diff options
Diffstat (limited to 'components/pthreads/pthread_mutex.c')
| -rw-r--r-- | components/pthreads/pthread_mutex.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/components/pthreads/pthread_mutex.c b/components/pthreads/pthread_mutex.c new file mode 100644 index 0000000000..4e244cee9e --- /dev/null +++ b/components/pthreads/pthread_mutex.c @@ -0,0 +1,193 @@ +#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;
+}
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
+{
+ if (attr)
+ {
+ *attr = -1;
+ return 0;
+ }
+
+ return EINVAL;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
|
