| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 | /* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date           Author       Notes * 2010-10-26     Bernard      the first version */#include <rtthread.h>#include "pthread.h"#define  MUTEXATTR_SHARED_MASK 0x0010#define  MUTEXATTR_TYPE_MASK   0x000fconst 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;}RTM_EXPORT(pthread_mutexattr_init);int pthread_mutexattr_destroy(pthread_mutexattr_t *attr){    if (attr)    {        *attr = -1;        return 0;    }    return EINVAL;}RTM_EXPORT(pthread_mutexattr_destroy);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;}RTM_EXPORT(pthread_mutexattr_gettype);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;}RTM_EXPORT(pthread_mutexattr_settype);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;}RTM_EXPORT(pthread_mutexattr_setpshared);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;}RTM_EXPORT(pthread_mutexattr_getpshared);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));    mutex->lock.parent.parent.type = RT_Object_Class_Mutex;    return 0;}RTM_EXPORT(pthread_mutex_init);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;}RTM_EXPORT(pthread_mutex_destroy);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;}RTM_EXPORT(pthread_mutex_lock);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;        return EINVAL;}RTM_EXPORT(pthread_mutex_unlock);int pthread_mutex_trylock(pthread_mutex_t *mutex){    rt_err_t result;    int mtype;    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), 0);    if (result == RT_EOK) return 0;    return EBUSY;}RTM_EXPORT(pthread_mutex_trylock);
 |