pthread_mutex.c 4.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include <rtthread.h>
#include "pthread.h"

#define  MUTEXATTR_SHARED_MASK 0x0010
#define  MUTEXATTR_TYPE_MASK   0x000f

const pthread_mutexattr_t pthread_default_mutexattr = PTHREAD_PROCESS_PRIVATE;

int pthread_mutexattr_init(pthread_mutexattr_t *attr)
{
	if (attr)
	{
		*attr = pthread_default_mutexattr;
		return 0;
	}

	return EINVAL;
}
19
RTM_EXPORT(pthread_mutexattr_init);
20 21 22 23 24 25 26 27 28 29 30

int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
{
	if (attr)
	{
	 	*attr = -1;
		return 0;
	}

	return EINVAL;
}
31
RTM_EXPORT(pthread_mutexattr_destroy);
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
{
	if (attr && type)
	{
        int  atype = (*attr & MUTEXATTR_TYPE_MASK);

		if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK)
		{
			*type = atype;
			return 0;
		}
	}

	return EINVAL;
}
48
RTM_EXPORT(pthread_mutexattr_gettype);
49 50 51 52 53 54 55 56 57 58 59 60

int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
{
    if (attr && type >= PTHREAD_MUTEX_NORMAL &&
                type <= PTHREAD_MUTEX_ERRORCHECK )
	{
        *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type;
        return 0;
    }

    return EINVAL;
}
61
RTM_EXPORT(pthread_mutexattr_settype);
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int  pshared)
{
    if (!attr) return EINVAL;

    switch (pshared)
	{
    case PTHREAD_PROCESS_PRIVATE:
        *attr &= ~MUTEXATTR_SHARED_MASK;
        return 0;

    case PTHREAD_PROCESS_SHARED:
        *attr |= MUTEXATTR_SHARED_MASK;
        return 0;
    }

    return EINVAL;
}
80
RTM_EXPORT(pthread_mutexattr_setpshared);
81 82 83 84 85 86 87 88 89

int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared)
{
    if (!attr || !pshared) return EINVAL;

    *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED
                                               : PTHREAD_PROCESS_PRIVATE;
    return 0;
}
90
RTM_EXPORT(pthread_mutexattr_getpshared);
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
{
	rt_err_t result;
	char name[RT_NAME_MAX];
	static rt_uint16_t pthread_mutex_number = 0;

	if (!mutex) return EINVAL;

	/* build mutex name */
	rt_snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++);
	if (attr == RT_NULL) mutex->attr = pthread_default_mutexattr;
	else mutex->attr = *attr;

	/* init mutex lock */
	result = rt_mutex_init(&(mutex->lock), name, RT_IPC_FLAG_FIFO);
	if (result != RT_EOK) return EINVAL;

	/* detach the object from system object container */
	rt_object_detach(&(mutex->lock.parent.parent));

	return 0;
}
114
RTM_EXPORT(pthread_mutex_init);
115 116 117 118 119 120 121 122 123 124 125 126 127

int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
	if (!mutex || mutex->attr == -1) return EINVAL;

	/* it's busy */
	if (mutex->lock.owner != RT_NULL) return EBUSY;

	rt_memset(mutex, 0, sizeof(pthread_mutex_t));
	mutex->attr = -1;

	return 0;
}
128
RTM_EXPORT(pthread_mutex_destroy);
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

int pthread_mutex_lock(pthread_mutex_t *mutex)
{
	int mtype;
	rt_err_t result;

	if (!mutex) return EINVAL;

	if (mutex->attr == -1)
	{
		/* init mutex */
		pthread_mutex_init(mutex, RT_NULL);
	}

	mtype = mutex->attr & MUTEXATTR_TYPE_MASK;
	rt_enter_critical();
	if (mutex->lock.owner == rt_thread_self() && mtype != PTHREAD_MUTEX_RECURSIVE)
	{
		rt_exit_critical();
		return EDEADLK;
	}
	rt_exit_critical();

	result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER);
	if (result == RT_EOK) return 0;

	return EINVAL;
}
157
RTM_EXPORT(pthread_mutex_lock);
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183

int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
	rt_err_t result;

	if (!mutex) return EINVAL;
	if (mutex->attr == -1)
	{
		/* init mutex */
		pthread_mutex_init(mutex, RT_NULL);
	}

	if (mutex->lock.owner != rt_thread_self())
	{
		int mtype;
		mtype = mutex->attr & MUTEXATTR_TYPE_MASK;

		/* error check, return EPERM */
		if (mtype == PTHREAD_MUTEX_ERRORCHECK) return EPERM;

		/* no thread waiting on this mutex */
		if (mutex->lock.owner == RT_NULL) return 0;
	}

	result = rt_mutex_release(&(mutex->lock));
	if (result == RT_EOK) return 0;
184 185
	
	return EINVAL;
186
}
187
RTM_EXPORT(pthread_mutex_unlock);
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

int pthread_mutex_trylock(pthread_mutex_t *mutex)
{
	rt_err_t result;

	if (!mutex) return EINVAL;
	if (mutex->attr == -1)
	{
		/* init mutex */
		pthread_mutex_init(mutex, RT_NULL);
	}

	result = rt_mutex_take(&(mutex->lock), 0);
	if (result == RT_EOK) return 0;

	return EBUSY;
}
205
RTM_EXPORT(pthread_mutex_trylock);
206