博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android pthread mutex 实现分析
阅读量:2456 次
发布时间:2019-05-11

本文共 30584 字,大约阅读时间需要 101 分钟。

在Android ICS中,pthead库对应的路径为:

Android\bionic\libc\bionic\pthread.c

Android\bionic\libc\bionic\pthread-atfork.c

Android\bionic\libc\bionic\pthread-rwlocks.c

Android\bionic\libc\bionic\pthread-timers.c

Android\bionic\libc\bionic\pthread_internal.h

Android\bionic\libc\include\pthread.h

其中mutex在pthread.c中,相关的API有:

[cpp]
  1. //pthread mutexattr 操作   
  2. int pthread_mutexattr_init(pthread_mutexattr_t *attr);  
  3. int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);  
  4.   
  5. int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);  
  6. int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);  
  7.   
  8. int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int  pshared);  
  9. int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared);  
  10.   
  11.   
  12.   
  13.   
  14. //pthread mutex 操作   
  15. int pthread_mutex_init(pthread_mutex_t *mutex,  
  16.                        const pthread_mutexattr_t *attr);  
  17. int pthread_mutex_destroy(pthread_mutex_t *mutex);  
  18.   
  19. int pthread_mutex_lock(pthread_mutex_t *mutex);  
  20. int pthread_mutex_unlock(pthread_mutex_t *mutex);  
  21. int pthread_mutex_trylock(pthread_mutex_t *mutex);  
  22. int pthread_mutex_timedlock(pthread_mutex_t *mutex, struct timespec*  ts);  
//pthread mutexattr 操作int pthread_mutexattr_init(pthread_mutexattr_t *attr);int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type);int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int  pshared);int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared);//pthread mutex 操作int pthread_mutex_init(pthread_mutex_t *mutex,                       const pthread_mutexattr_t *attr);int pthread_mutex_destroy(pthread_mutex_t *mutex);int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_timedlock(pthread_mutex_t *mutex, struct timespec*  ts);

pthread_mutex_t对应一个结构体,包含一个int字段

typedef struct{    int volatile value;} pthread_mutex_t;

int字段分为5个部分,

/*

a mutex is implemented as a 32-bit integer holding the following fields

 * * bits:     name     description

* 31-16     tid      owner thread's kernel id (recursive and errorcheck only)

 * 15-14     type     mutex type

* 13           shared   process-shared flag

* 12-2       counter  counter of recursive mutexes

* 1-0         state    lock state (0, 1 or 2)

*/

定义了一些macro来获得各个部分,其中mutex的type分为3类,有Normal, Recursive, Errorcheck,Recursize允许递归,Errorcheck会检测当前的状态。

[cpp]
  1. #define  MUTEX_OWNER(m)  (((m)->value >> 16) & 0xffff)   
  2. #define  MUTEX_COUNTER(m) (((m)->value >> 2) & 0xfff)   
  3.   
  4. #define  MUTEX_TYPE_MASK       0xc000   
  5. #define  MUTEX_TYPE_NORMAL     0x0000   
  6. #define  MUTEX_TYPE_RECURSIVE  0x4000   
  7. #define  MUTEX_TYPE_ERRORCHECK 0x8000   
  8.   
  9. #define  MUTEX_COUNTER_SHIFT  2   
  10. #define  MUTEX_COUNTER_MASK   0x1ffc   
  11. #define  MUTEX_SHARED_MASK    0x2000   
  12.   
  13. enum {  
  14.     PTHREAD_MUTEX_NORMAL = 0,  
  15.     PTHREAD_MUTEX_RECURSIVE = 1,  
  16.     PTHREAD_MUTEX_ERRORCHECK = 2,  
  17.   
  18.     PTHREAD_MUTEX_ERRORCHECK_NP = PTHREAD_MUTEX_ERRORCHECK,  
  19.     PTHREAD_MUTEX_RECURSIVE_NP  = PTHREAD_MUTEX_RECURSIVE,  
  20.   
  21.     PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL  
  22. };  
#define  MUTEX_OWNER(m)  (((m)->value >> 16) & 0xffff)#define  MUTEX_COUNTER(m) (((m)->value >> 2) & 0xfff)#define  MUTEX_TYPE_MASK       0xc000#define  MUTEX_TYPE_NORMAL     0x0000#define  MUTEX_TYPE_RECURSIVE  0x4000#define  MUTEX_TYPE_ERRORCHECK 0x8000#define  MUTEX_COUNTER_SHIFT  2#define  MUTEX_COUNTER_MASK   0x1ffc#define  MUTEX_SHARED_MASK    0x2000enum {    PTHREAD_MUTEX_NORMAL = 0,    PTHREAD_MUTEX_RECURSIVE = 1,    PTHREAD_MUTEX_ERRORCHECK = 2,    PTHREAD_MUTEX_ERRORCHECK_NP = PTHREAD_MUTEX_ERRORCHECK,    PTHREAD_MUTEX_RECURSIVE_NP  = PTHREAD_MUTEX_RECURSIVE,    PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL};

1 Mutex属性

pthread_mutexattr_t用来描述mutex的属性,

typedef long pthread_mutexattr_t;

属性包含了mutex的type,以及sharedflag。对应于mutex_t

 * 15-14     type     mutex type

 * 13           shared   process-shared flag

/* a mutex attribute holds the following fields

 *
 * bits:     name       description
 * 0-3       type       type of mutex
 * 4         shared     process-shared flag
 */
#define  MUTEXATTR_TYPE_MASK   0x000f
#define  MUTEXATTR_SHARED_MASK 0x0010

#define PTHREAD_PROCESS_PRIVATE  0
#define PTHREAD_PROCESS_SHARED   1

1.1 init和destory

init将type设置为Default,也就是Normal(0)也就是,type=Normal, shared  为Private

[cpp]
  1. int pthread_mutex_init(pthread_mutex_t *mutex,  
  2.                        const pthread_mutexattr_t *attr)  
  3. {  
  4.     int value = 0;  
  5.   
  6.     if (mutex == NULL)  
  7.         return EINVAL;  
  8.   
  9.     if (__likely(attr == NULL)) {  
  10.         mutex->value = MUTEX_TYPE_NORMAL;  
  11.         return 0;  
  12.     }  
  13.   
  14.     if ((*attr & MUTEXATTR_SHARED_MASK) != 0)  
  15.         value |= MUTEX_SHARED_MASK;  
  16.   
  17.     switch (*attr & MUTEXATTR_TYPE_MASK) {  
  18.     case PTHREAD_MUTEX_NORMAL:  
  19.         value |= MUTEX_TYPE_NORMAL;  
  20.         break;  
  21.     case PTHREAD_MUTEX_RECURSIVE:  
  22.         value |= MUTEX_TYPE_RECURSIVE;  
  23.         break;  
  24.     case PTHREAD_MUTEX_ERRORCHECK:  
  25.         value |= MUTEX_TYPE_ERRORCHECK;  
  26.         break;  
  27.     default:  
  28.         return EINVAL;  
  29.     }  
  30.   
  31.     mutex->value = value;  
  32.     return 0;  
  33. }  
  34. //destory将attr置为-1   
  35. int pthread_mutex_destroy(pthread_mutex_t *mutex)  
  36. {  
  37.     int ret;  
  38.   
  39.     /* use trylock to ensure that the mutex value is 
  40.      * valid and is not already locked. */  
  41.     ret = pthread_mutex_trylock(mutex);  
  42.     if (ret != 0)  
  43.         return ret;  
  44.   
  45.     mutex->value = 0xdead10cc;  
  46.     return 0;  
  47. }  
int pthread_mutex_init(pthread_mutex_t *mutex,                       const pthread_mutexattr_t *attr){    int value = 0;    if (mutex == NULL)        return EINVAL;    if (__likely(attr == NULL)) {        mutex->value = MUTEX_TYPE_NORMAL;        return 0;    }    if ((*attr & MUTEXATTR_SHARED_MASK) != 0)        value |= MUTEX_SHARED_MASK;    switch (*attr & MUTEXATTR_TYPE_MASK) {    case PTHREAD_MUTEX_NORMAL:        value |= MUTEX_TYPE_NORMAL;        break;    case PTHREAD_MUTEX_RECURSIVE:        value |= MUTEX_TYPE_RECURSIVE;        break;    case PTHREAD_MUTEX_ERRORCHECK:        value |= MUTEX_TYPE_ERRORCHECK;        break;    default:        return EINVAL;    }    mutex->value = value;    return 0;}//destory将attr置为-1int pthread_mutex_destroy(pthread_mutex_t *mutex){    int ret;    /* use trylock to ensure that the mutex value is     * valid and is not already locked. */    ret = pthread_mutex_trylock(mutex);    if (ret != 0)        return ret;    mutex->value = 0xdead10cc;    return 0;}

1.2 settype 和gettype

对pthread_mutexattr_t的type字段进行取值和赋值

[cpp]
  1.  int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)  
  2. {  
  3.     if (attr) {  
  4.         int  atype = (*attr & MUTEXATTR_TYPE_MASK);  
  5.   
  6.          if (atype >= PTHREAD_MUTEX_NORMAL &&  
  7.              atype <= PTHREAD_MUTEX_ERRORCHECK) {  
  8.             *type = atype;  
  9.             return 0;  
  10.         }  
  11.     }  
  12.     return EINVAL;  
  13. }  
  14.   
  15. int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)  
  16. {  
  17.     if (attr && type >= PTHREAD_MUTEX_NORMAL &&  
  18.                 type <= PTHREAD_MUTEX_ERRORCHECK ) {  
  19.         *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type;  
  20.         return 0;  
  21.     }  
  22.     return EINVAL;  
  23.   
  24. }  
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type){    if (attr) {        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;}

1.3 setpshared和getpshared

[cpp]
  1. int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int  pshared)  
  2. {  
  3.     if (!attr)  
  4.         return EINVAL;  
  5.   
  6.     switch (pshared) {  
  7.     case PTHREAD_PROCESS_PRIVATE:  
  8.         *attr &= ~MUTEXATTR_SHARED_MASK;  
  9.         return 0;  
  10.   
  11.     case PTHREAD_PROCESS_SHARED:  
  12.         /* our current implementation of pthread actually supports shared 
  13.          * mutexes but won't cleanup if a process dies with the mutex held. 
  14.          * Nevertheless, it's better than nothing. Shared mutexes are used 
  15.          * by surfaceflinger and audioflinger. 
  16.          */  
  17.         *attr |= MUTEXATTR_SHARED_MASK;  
  18.         return 0;  
  19.     }  
  20.     return EINVAL;  
  21. }  
  22.   
  23. int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared)  
  24. {  
  25.     if (!attr || !pshared)  
  26.         return EINVAL;  
  27.   
  28.     *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED  
  29.                                                : PTHREAD_PROCESS_PRIVATE;  
  30.     return 0;  
  31. }  
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:        /* our current implementation of pthread actually supports shared         * mutexes but won't cleanup if a process dies with the mutex held.         * Nevertheless, it's better than nothing. Shared mutexes are used         * by surfaceflinger and audioflinger.         */        *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;}

2 Mutex实现

2.1 Mutex init和 destory

如果attr==NULL,则采用默认属性, type =normal, shared = private,

否则,感觉属性的type和shared进行设置

[cpp]
  1. int pthread_mutex_init(pthread_mutex_t *mutex,  
  2.                        const pthread_mutexattr_t *attr)  
  3. {  
  4.     int value = 0;  
  5.   
  6.     if (mutex == NULL)  
  7.         return EINVAL;  
  8.   
  9.     if (__likely(attr == NULL)) {  
  10.         mutex->value = MUTEX_TYPE_NORMAL;  
  11.         return 0;  
  12.     }  
  13.   
  14.     if ((*attr & MUTEXATTR_SHARED_MASK) != 0)  
  15.         value |= MUTEX_SHARED_MASK;  
  16.   
  17.     switch (*attr & MUTEXATTR_TYPE_MASK) {  
  18.     case PTHREAD_MUTEX_NORMAL:  
  19.         value |= MUTEX_TYPE_NORMAL;  
  20.         break;  
  21.     case PTHREAD_MUTEX_RECURSIVE:  
  22.         value |= MUTEX_TYPE_RECURSIVE;  
  23.         break;  
  24.     case PTHREAD_MUTEX_ERRORCHECK:  
  25.         value |= MUTEX_TYPE_ERRORCHECK;  
  26.         break;  
  27.     default:  
  28.         return EINVAL;  
  29.     }  
  30.   
  31.     mutex->value = value;  
  32.     return 0;  
  33. }  
  34. 如果mutex当前不被lock,则设置value为0xdead10cc  
  35. int pthread_mutex_destroy(pthread_mutex_t *mutex)  
  36. {  
  37.     int ret;  
  38.   
  39.     /* use trylock to ensure that the mutex value is 
  40.      * valid and is not already locked. */  
  41.     ret = pthread_mutex_trylock(mutex);  
  42.     if (ret != 0)  
  43.         return ret;  
  44.   
  45.     mutex->value = 0xdead10cc;  
  46.     return 0;  
  47. }  
int pthread_mutex_init(pthread_mutex_t *mutex,                       const pthread_mutexattr_t *attr){    int value = 0;    if (mutex == NULL)        return EINVAL;    if (__likely(attr == NULL)) {        mutex->value = MUTEX_TYPE_NORMAL;        return 0;    }    if ((*attr & MUTEXATTR_SHARED_MASK) != 0)        value |= MUTEX_SHARED_MASK;    switch (*attr & MUTEXATTR_TYPE_MASK) {    case PTHREAD_MUTEX_NORMAL:        value |= MUTEX_TYPE_NORMAL;        break;    case PTHREAD_MUTEX_RECURSIVE:        value |= MUTEX_TYPE_RECURSIVE;        break;    case PTHREAD_MUTEX_ERRORCHECK:        value |= MUTEX_TYPE_ERRORCHECK;        break;    default:        return EINVAL;    }    mutex->value = value;    return 0;}如果mutex当前不被lock,则设置value为0xdead10ccint pthread_mutex_destroy(pthread_mutex_t *mutex){    int ret;    /* use trylock to ensure that the mutex value is     * valid and is not already locked. */    ret = pthread_mutex_trylock(mutex);    if (ret != 0)        return ret;    mutex->value = 0xdead10cc;    return 0;}

2.2 lock, unlock, trylock, timedlock

[cpp]
  1. int pthread_mutex_lock(pthread_mutex_t *mutex)  
  2. {  
  3.     int mtype, tid, new_lock_type, shared;  
  4.   
  5.     if (__unlikely(mutex == NULL))  
  6.         return EINVAL;  
  7.   
  8.     mtype = (mutex->value & MUTEX_TYPE_MASK);  
  9.     shared = (mutex->value & MUTEX_SHARED_MASK);  
  10.   
  11.     /* Handle normal case first */  
  12.    if ( __likely(mtype == MUTEX_TYPE_NORMAL) ) {
    //type为normal,   
  13.         _normal_lock(mutex);  
  14.         return 0;  
  15.     }  
  16.   
  17.     /* Do we already own this recursive or error-check mutex ? */  
  18.     tid = __get_thread()->kernel_id;  
  19.    if ( tid == MUTEX_OWNER(mutex) )//已经持有mutex,递归的情况   
  20.     {  
  21.         int  oldv, counter;  
  22.   
  23.         if (mtype == MUTEX_TYPE_ERRORCHECK) {  
  24.             /* trying to re-lock a mutex we already acquired */  
  25.             return EDEADLK;  
  26.         }  
  27.         /* 
  28.          * We own the mutex, but other threads are able to change 
  29.          * the contents (e.g. promoting it to "contended"), so we 
  30.          * need to hold the global lock. 
  31.          */  
  32.     _recursive_lock();//更新counter   
  33.         oldv         = mutex->value;  
  34.         counter      = (oldv + (1 << MUTEX_COUNTER_SHIFT)) & MUTEX_COUNTER_MASK;  
  35.         mutex->value = (oldv & ~MUTEX_COUNTER_MASK) | counter;  
  36.         _recursive_unlock();  
  37.         return 0;  
  38.     }  
  39.   
  40.     /* We don't own the mutex, so try to get it. 
  41.      * 
  42.      * First, we try to change its state from 0 to 1, if this 
  43.      * doesn't work, try to change it to state 2. 
  44.      */  
  45.     new_lock_type = 1;  
  46.   
  47.     /* compute futex wait opcode and restore shared flag in mtype */  
  48.     mtype |= shared;  
  49.   
  50.     for (;;) {  
  51.         int  oldv;  
  52.   
  53.         _recursive_lock();  
  54.         oldv = mutex->value;  
  55.         if (oldv == mtype) { /* uncontended released lock => 1 or 2 */  
  56.             mutex->value = ((tid << 16) | mtype | new_lock_type);  
  57.         } else if ((oldv & 3) == 1) { /* locked state 1 => state 2 */  
  58.             oldv ^= 3;  
  59.             mutex->value = oldv;  
  60.         }  
  61.         _recursive_unlock();  
  62.   
  63.         if (oldv == mtype)  
  64.             break;  
  65.   
  66.         /* 
  67.          * The lock was held, possibly contended by others.  From 
  68.          * now on, if we manage to acquire the lock, we have to 
  69.          * assume that others are still contending for it so that 
  70.          * we'll wake them when we unlock it. 
  71.          */  
  72.         new_lock_type = 2;  
  73.   
  74.         __futex_wait_ex(&mutex->value, shared, oldv, NULL);  
  75.     }  
  76.     return 0;  
  77. }  
int pthread_mutex_lock(pthread_mutex_t *mutex){    int mtype, tid, new_lock_type, shared;    if (__unlikely(mutex == NULL))        return EINVAL;    mtype = (mutex->value & MUTEX_TYPE_MASK);    shared = (mutex->value & MUTEX_SHARED_MASK);    /* Handle normal case first */   if ( __likely(mtype == MUTEX_TYPE_NORMAL) ) {//type为normal,        _normal_lock(mutex);        return 0;    }    /* Do we already own this recursive or error-check mutex ? */    tid = __get_thread()->kernel_id;   if ( tid == MUTEX_OWNER(mutex) )//已经持有mutex,递归的情况    {        int  oldv, counter;        if (mtype == MUTEX_TYPE_ERRORCHECK) {            /* trying to re-lock a mutex we already acquired */            return EDEADLK;        }        /*         * We own the mutex, but other threads are able to change         * the contents (e.g. promoting it to "contended"), so we         * need to hold the global lock.         */    _recursive_lock();//更新counter        oldv         = mutex->value;        counter      = (oldv + (1 << MUTEX_COUNTER_SHIFT)) & MUTEX_COUNTER_MASK;        mutex->value = (oldv & ~MUTEX_COUNTER_MASK) | counter;        _recursive_unlock();        return 0;    }    /* We don't own the mutex, so try to get it.     *     * First, we try to change its state from 0 to 1, if this     * doesn't work, try to change it to state 2.     */    new_lock_type = 1;    /* compute futex wait opcode and restore shared flag in mtype */    mtype |= shared;    for (;;) {        int  oldv;        _recursive_lock();        oldv = mutex->value;        if (oldv == mtype) { /* uncontended released lock => 1 or 2 */            mutex->value = ((tid << 16) | mtype | new_lock_type);        } else if ((oldv & 3) == 1) { /* locked state 1 => state 2 */            oldv ^= 3;            mutex->value = oldv;        }        _recursive_unlock();        if (oldv == mtype)            break;        /*         * The lock was held, possibly contended by others.  From         * now on, if we manage to acquire the lock, we have to         * assume that others are still contending for it so that         * we'll wake them when we unlock it.         */        new_lock_type = 2;        __futex_wait_ex(&mutex->value, shared, oldv, NULL);    }    return 0;}

normal 的情况

[cpp]
  1. /* 
  2.  * Lock a non-recursive mutex. 
  3.  * 
  4.  * As noted above, there are three states: 
  5.  *   0 (unlocked, no contention) 
  6.  *   1 (locked, no contention) 
  7.  *   2 (locked, contention) 
  8.  * 
  9.  * Non-recursive mutexes don't use the thread-id or counter fields, and the 
  10.  * "type" value is zero, so the only bits that will be set are the ones in 
  11.  * the lock state field. 
  12.  */  
  13. static __inline__ void  
  14. _normal_lock(pthread_mutex_t*  mutex)  
  15. {  
  16.     /* We need to preserve the shared flag during operations */  
  17.     int  shared = mutex->value & MUTEX_SHARED_MASK;  
  18.     /* 
  19.      * The common case is an unlocked mutex, so we begin by trying to 
  20.      * change the lock's state from 0 to 1.  __atomic_cmpxchg() returns 0 
  21.      * if it made the swap successfully.  If the result is nonzero, this 
  22.      * lock is already held by another thread. 
  23.      */  
  24.       
  25.     if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value ) != 0) {  
  26.         /* 
  27.          * We want to go to sleep until the mutex is available, which 
  28.          * requires promoting it to state 2.  We need to swap in the new 
  29.          * state value and then wait until somebody wakes us up. 
  30.          * 
  31.          * __atomic_swap() returns the previous value.  We swap 2 in and 
  32.          * see if we got zero back; if so, we have acquired the lock.  If 
  33.          * not, another thread still holds the lock and we wait again. 
  34.          * 
  35.          * The second argument to the __futex_wait() call is compared 
  36.          * against the current value.  If it doesn't match, __futex_wait() 
  37.          * returns immediately (otherwise, it sleeps for a time specified 
  38.          * by the third argument; 0 means sleep forever).  This ensures 
  39.          * that the mutex is in state 2 when we go to sleep on it, which 
  40.          * guarantees a wake-up call. 
  41.          */  
  42.     while (__atomic_swap(shared|2, &mutex->value ) != (shared|0))//等待muex   
  43.             __futex_wait_ex(&mutex->value, shared, shared|2, 0);  
  44.     }  
  45.     ANDROID_MEMBAR_FULL();  
  46. }  
/* * Lock a non-recursive mutex. * * As noted above, there are three states: *   0 (unlocked, no contention) *   1 (locked, no contention) *   2 (locked, contention) * * Non-recursive mutexes don't use the thread-id or counter fields, and the * "type" value is zero, so the only bits that will be set are the ones in * the lock state field. */static __inline__ void_normal_lock(pthread_mutex_t*  mutex){    /* We need to preserve the shared flag during operations */    int  shared = mutex->value & MUTEX_SHARED_MASK;    /*     * The common case is an unlocked mutex, so we begin by trying to     * change the lock's state from 0 to 1.  __atomic_cmpxchg() returns 0     * if it made the swap successfully.  If the result is nonzero, this     * lock is already held by another thread.     */        if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value ) != 0) {        /*         * We want to go to sleep until the mutex is available, which         * requires promoting it to state 2.  We need to swap in the new         * state value and then wait until somebody wakes us up.         *         * __atomic_swap() returns the previous value.  We swap 2 in and         * see if we got zero back; if so, we have acquired the lock.  If         * not, another thread still holds the lock and we wait again.         *         * The second argument to the __futex_wait() call is compared         * against the current value.  If it doesn't match, __futex_wait()         * returns immediately (otherwise, it sleeps for a time specified         * by the third argument; 0 means sleep forever).  This ensures         * that the mutex is in state 2 when we go to sleep on it, which         * guarantees a wake-up call.         */    while (__atomic_swap(shared|2, &mutex->value ) != (shared|0))//等待muex            __futex_wait_ex(&mutex->value, shared, shared|2, 0);    }    ANDROID_MEMBAR_FULL();}

在recursive的情况下,需要使用mutex来包含counter,

[cpp]
  1. static pthread_mutex_t  __recursive_lock = PTHREAD_MUTEX_INITIALIZER;  
  2.   
  3. static void  
  4. _recursive_lock(void)  
  5. {  
  6.     _normal_lock(&__recursive_lock);  
  7. }  
  8.   
  9. static void  
  10. _recursive_unlock(void)  
  11. {  
  12.     _normal_unlock(&__recursive_lock );  
  13. }  
static pthread_mutex_t  __recursive_lock = PTHREAD_MUTEX_INITIALIZER;static void_recursive_lock(void){    _normal_lock(&__recursive_lock);}static void_recursive_unlock(void){    _normal_unlock(&__recursive_lock );}
unlock的情况

[cpp]
  1. int pthread_mutex_unlock(pthread_mutex_t *mutex)  
  2. {  
  3.     int mtype, tid, oldv, shared;  
  4.   
  5.     if (__unlikely(mutex == NULL))  
  6.         return EINVAL;  
  7.   
  8.     mtype  = (mutex->value & MUTEX_TYPE_MASK);  
  9.     shared = (mutex->value & MUTEX_SHARED_MASK);  
  10.   
  11.     /* Handle common case first */  
  12.     if (__likely(mtype == MUTEX_TYPE_NORMAL)) {
    //normal   
  13.         _normal_unlock(mutex);  
  14.         return 0;  
  15.     }  
  16.   
  17.     /* Do we already own this recursive or error-check mutex ? */  
  18.     tid = __get_thread()->kernel_id;  
  19.     if ( tid != MUTEX_OWNER(mutex) )//error check的情况,错误退出   
  20.         return EPERM;  
  21.   
  22.     /* We do, decrement counter or release the mutex if it is 0 */  
  23.     _recursive_lock();  
  24.     oldv = mutex->value;  
  25.     if (oldv & MUTEX_COUNTER_MASK) {  
  26.         mutex->value = oldv - (1 << MUTEX_COUNTER_SHIFT);  
  27.         oldv = 0;  
  28.     } else {  
  29.         mutex->value = shared | mtype;  
  30.     }  
  31.     _recursive_unlock();  
  32.   
  33.     /* Wake one waiting thread, if any */  
  34.    if ((oldv & 3) == 2) {  
  35.         __futex_wake_ex(&mutex->value, shared, 1);  
  36.     }  
  37.     return 0;  
  38. }  
  39.   
  40.   
  41. /* 
  42.  * Release a non-recursive mutex.  The caller is responsible for determining 
  43.  * that we are in fact the owner of this lock. 
  44.  */  
  45. static __inline__ void  
  46. _normal_unlock(pthread_mutex_t*  mutex)  
  47. {  
  48.     ANDROID_MEMBAR_FULL();  
  49.   
  50.     /* We need to preserve the shared flag during operations */  
  51.     int  shared = mutex->value & MUTEX_SHARED_MASK;  
  52.   
  53.     /* 
  54.      * The mutex state will be 1 or (rarely) 2.  We use an atomic decrement 
  55.      * to release the lock.  __atomic_dec() returns the previous value; 
  56.      * if it wasn't 1 we have to do some additional work. 
  57.      */  
  58.     if (__atomic_dec(&mutex->value) != (shared|1)) {  
  59.         /* 
  60.          * Start by releasing the lock.  The decrement changed it from 
  61.          * "contended lock" to "uncontended lock", which means we still 
  62.          * hold it, and anybody who tries to sneak in will push it back 
  63.          * to state 2. 
  64.          * 
  65.          * Once we set it to zero the lock is up for grabs.  We follow 
  66.          * this with a __futex_wake() to ensure that one of the waiting 
  67.          * threads has a chance to grab it. 
  68.          * 
  69.          * This doesn't cause a race with the swap/wait pair in 
  70.          * _normal_lock(), because the __futex_wait() call there will 
  71.          * return immediately if the mutex value isn't 2. 
  72.          */  
  73.         mutex->value = shared;  
  74.   
  75.         /* 
  76.          * Wake up one waiting thread.  We don't know which thread will be 
  77.          * woken or when it'll start executing -- futexes make no guarantees 
  78.          * here.  There may not even be a thread waiting. 
  79.          * 
  80.          * The newly-woken thread will replace the 0 we just set above 
  81.          * with 2, which means that when it eventually releases the mutex 
  82.          * it will also call FUTEX_WAKE.  This results in one extra wake 
  83.          * call whenever a lock is contended, but lets us avoid forgetting 
  84.          * anyone without requiring us to track the number of sleepers. 
  85.          * 
  86.          * It's possible for another thread to sneak in and grab the lock 
  87.          * between the zero assignment above and the wake call below.  If 
  88.          * the new thread is "slow" and holds the lock for a while, we'll 
  89.          * wake up a sleeper, which will swap in a 2 and then go back to 
  90.          * sleep since the lock is still held.  If the new thread is "fast", 
  91.          * running to completion before we call wake, the thread we 
  92.          * eventually wake will find an unlocked mutex and will execute. 
  93.          * Either way we have correct behavior and nobody is orphaned on 
  94.          * the wait queue. 
  95.          */  
  96.         __futex_wake_ex(&mutex->value, shared, 1);//唤醒等待的   
  97.     }  
  98. }  
  99.    
int pthread_mutex_unlock(pthread_mutex_t *mutex){    int mtype, tid, oldv, shared;    if (__unlikely(mutex == NULL))        return EINVAL;    mtype  = (mutex->value & MUTEX_TYPE_MASK);    shared = (mutex->value & MUTEX_SHARED_MASK);    /* Handle common case first */    if (__likely(mtype == MUTEX_TYPE_NORMAL)) {//normal        _normal_unlock(mutex);        return 0;    }    /* Do we already own this recursive or error-check mutex ? */    tid = __get_thread()->kernel_id;    if ( tid != MUTEX_OWNER(mutex) )//error check的情况,错误退出        return EPERM;    /* We do, decrement counter or release the mutex if it is 0 */    _recursive_lock();    oldv = mutex->value;    if (oldv & MUTEX_COUNTER_MASK) {        mutex->value = oldv - (1 << MUTEX_COUNTER_SHIFT);        oldv = 0;    } else {        mutex->value = shared | mtype;    }    _recursive_unlock();    /* Wake one waiting thread, if any */   if ((oldv & 3) == 2) {        __futex_wake_ex(&mutex->value, shared, 1);    }    return 0;}/* * Release a non-recursive mutex.  The caller is responsible for determining * that we are in fact the owner of this lock. */static __inline__ void_normal_unlock(pthread_mutex_t*  mutex){    ANDROID_MEMBAR_FULL();    /* We need to preserve the shared flag during operations */    int  shared = mutex->value & MUTEX_SHARED_MASK;    /*     * The mutex state will be 1 or (rarely) 2.  We use an atomic decrement     * to release the lock.  __atomic_dec() returns the previous value;     * if it wasn't 1 we have to do some additional work.     */    if (__atomic_dec(&mutex->value) != (shared|1)) {        /*         * Start by releasing the lock.  The decrement changed it from         * "contended lock" to "uncontended lock", which means we still         * hold it, and anybody who tries to sneak in will push it back         * to state 2.         *         * Once we set it to zero the lock is up for grabs.  We follow         * this with a __futex_wake() to ensure that one of the waiting         * threads has a chance to grab it.         *         * This doesn't cause a race with the swap/wait pair in         * _normal_lock(), because the __futex_wait() call there will         * return immediately if the mutex value isn't 2.         */        mutex->value = shared;        /*         * Wake up one waiting thread.  We don't know which thread will be         * woken or when it'll start executing -- futexes make no guarantees         * here.  There may not even be a thread waiting.         *         * The newly-woken thread will replace the 0 we just set above         * with 2, which means that when it eventually releases the mutex         * it will also call FUTEX_WAKE.  This results in one extra wake         * call whenever a lock is contended, but lets us avoid forgetting         * anyone without requiring us to track the number of sleepers.         *         * It's possible for another thread to sneak in and grab the lock         * between the zero assignment above and the wake call below.  If         * the new thread is "slow" and holds the lock for a while, we'll         * wake up a sleeper, which will swap in a 2 and then go back to         * sleep since the lock is still held.  If the new thread is "fast",         * running to completion before we call wake, the thread we         * eventually wake will find an unlocked mutex and will execute.         * Either way we have correct behavior and nobody is orphaned on         * the wait queue.         */        __futex_wake_ex(&mutex->value, shared, 1);//唤醒等待的    }} 

trylock

[cpp]
  1. int pthread_mutex_trylock(pthread_mutex_t *mutex)  
  2. {  
  3.     int mtype, tid, oldv, shared;  
  4.   
  5.     if (__unlikely(mutex == NULL))  
  6.         return EINVAL;  
  7.   
  8.     mtype  = (mutex->value & MUTEX_TYPE_MASK);  
  9.     shared = (mutex->value & MUTEX_SHARED_MASK);  
  10.   
  11.     /* Handle common case first */  
  12.     if ( __likely(mtype == MUTEX_TYPE_NORMAL) )  
  13.     {  
  14.         if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value) == 0) {  
  15.             ANDROID_MEMBAR_FULL();  
  16.             return 0;  
  17.         }  
  18.   
  19.         return EBUSY;  
  20.     }  
  21.   
  22.     /* Do we already own this recursive or error-check mutex ? */  
  23.     tid = __get_thread()->kernel_id;  
  24.     if ( tid == MUTEX_OWNER(mutex) )//当前thread已经持有mutex   
  25.     {  
  26.         int counter;  
  27.   
  28.         if (mtype == MUTEX_TYPE_ERRORCHECK) {  
  29.             /* already locked by ourselves */  
  30.             return EDEADLK;  
  31.         }  
  32.         //更新counter计数器   
  33.         _recursive_lock();  
  34.         oldv = mutex->value;  
  35.         counter = (oldv + (1 << MUTEX_COUNTER_SHIFT)) & MUTEX_COUNTER_MASK;  
  36.         mutex->value = (oldv & ~MUTEX_COUNTER_MASK) | counter;  
  37.         _recursive_unlock();  
  38.         return 0;  
  39.     }  
  40.   
  41.     /* Restore sharing bit in mtype */  
  42.     mtype |= shared;  
  43.   
  44.     /* Try to lock it, just once. */  
  45.     _recursive_lock();  
  46.     oldv = mutex->value;  
  47.     if (oldv == mtype)  /* uncontended released lock => state 1 */  
  48.         mutex->value = ((tid << 16) | mtype | 1);  
  49.     _recursive_unlock();  
  50.   
  51.     if (oldv != mtype)  
  52.         return EBUSY;  
  53.   
  54.     return 0;  
  55. }  
int pthread_mutex_trylock(pthread_mutex_t *mutex){    int mtype, tid, oldv, shared;    if (__unlikely(mutex == NULL))        return EINVAL;    mtype  = (mutex->value & MUTEX_TYPE_MASK);    shared = (mutex->value & MUTEX_SHARED_MASK);    /* Handle common case first */    if ( __likely(mtype == MUTEX_TYPE_NORMAL) )    {        if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value) == 0) {            ANDROID_MEMBAR_FULL();            return 0;        }        return EBUSY;    }    /* Do we already own this recursive or error-check mutex ? */    tid = __get_thread()->kernel_id;    if ( tid == MUTEX_OWNER(mutex) )//当前thread已经持有mutex    {        int counter;        if (mtype == MUTEX_TYPE_ERRORCHECK) {            /* already locked by ourselves */            return EDEADLK;        }        //更新counter计数器        _recursive_lock();        oldv = mutex->value;        counter = (oldv + (1 << MUTEX_COUNTER_SHIFT)) & MUTEX_COUNTER_MASK;        mutex->value = (oldv & ~MUTEX_COUNTER_MASK) | counter;        _recursive_unlock();        return 0;    }    /* Restore sharing bit in mtype */    mtype |= shared;    /* Try to lock it, just once. */    _recursive_lock();    oldv = mutex->value;    if (oldv == mtype)  /* uncontended released lock => state 1 */        mutex->value = ((tid << 16) | mtype | 1);    _recursive_unlock();    if (oldv != mtype)        return EBUSY;    return 0;}

timeout

[cpp]
  1. int pthread_mutex_lock_timeout_np(pthread_mutex_t *mutex, unsigned msecs)  
  2. {  
  3.     clockid_t        clock = CLOCK_MONOTONIC;  
  4.     struct timespec  abstime;  
  5.     struct timespec  ts;  
  6.     int              mtype, tid, oldv, new_lock_type, shared;  
  7.   
  8.     /* compute absolute expiration time */  
  9.     __timespec_to_relative_msec(&abstime, msecs, clock);  
  10.   
  11.     if (__unlikely(mutex == NULL))  
  12.         return EINVAL;  
  13.   
  14.     mtype  = (mutex->value & MUTEX_TYPE_MASK);  
  15.     shared = (mutex->value & MUTEX_SHARED_MASK);  
  16.   
  17.     /* Handle common case first */  
  18.     if ( __likely(mtype == MUTEX_TYPE_NORMAL) )//normal的情况   
  19.     {  
  20.         /* fast path for uncontended lock */  
  21.         if (__atomic_cmpxchg(shared|0, shared|1, &mutex->value) == 0) {  
  22.             ANDROID_MEMBAR_FULL();  
  23.             return 0;  
  24.         }  
  25.          //在while循环中等待,直到超时或者获得mutex   
  26.       /* loop while needed */  
  27.       while (__atomic_swap(shared|2, &mutex->value) != (shared|0)) {  
  28.             if (__timespec_to_absolute(&ts, &abstime, clock) < 0)  
  29.                 return EBUSY;  
  30.   
  31.             __futex_wait_ex(&mutex->value, shared, shared|2, &ts);  
  32.         }  
  33.         ANDROID_MEMBAR_FULL();  
  34.         return 0;  
  35.     }  
  36.   
  37.     /* Do we already own this recursive or error-check mutex ? */  
  38.     tid = __get_thread()->kernel_id;  
  39.     if ( tid == MUTEX_OWNER(mutex) )  
  40.     {  
  41.         int  oldv, counter;  
  42.   
  43.         if (mtype == MUTEX_TYPE_ERRORCHECK) {  
  44.             /* already locked by ourselves */  
  45.             return EDEADLK;  
  46.         }  
  47.   
  48.         _recursive_lock();  
  49.         oldv = mutex->value;  
  50.         counter = (oldv + (1 << MUTEX_COUNTER_SHIFT)) & MUTEX_COUNTER_MASK;  
  51.         mutex->value = (oldv & ~MUTEX_COUNTER_MASK) | counter;  
  52.         _recursive_unlock();  
  53.         return 0;  
  54.     }  
  55.   
  56.     /* We don't own the mutex, so try to get it. 
  57.      * 
  58.      * First, we try to change its state from 0 to 1, if this 
  59.      * doesn't work, try to change it to state 2. 
  60.      */  
  61.     new_lock_type = 1;  
  62.   
  63.     /* Compute wait op and restore sharing bit in mtype */  
  64.     mtype  |= shared;  
  65.   
  66.     //循环等待,直到超时   
  67.  for (;;) {  
  68.         int  oldv;  
  69.         struct timespec  ts;  
  70.   
  71.         _recursive_lock();  
  72.         oldv = mutex->value;  
  73.         if (oldv == mtype) { /* uncontended released lock => 1 or 2 */  
  74.             mutex->value = ((tid << 16) | mtype | new_lock_type);  
  75.         } else if ((oldv & 3) == 1) { /* locked state 1 => state 2 */  
  76.             oldv ^= 3;  
  77.             mutex->value = oldv;  
  78.         }  
  79.         _recursive_unlock();  
  80.   
  81.         if (oldv == mtype)  
  82.             break;  
  83.   
  84.         /* 
  85.          * The lock was held, possibly contended by others.  From 
  86.          * now on, if we manage to acquire the lock, we have to 
  87.          * assume that others are still contending for it so that 
  88.          * we'll wake them when we unlock it. 
  89.          */  
  90.         new_lock_type = 2;  
  91.        //超时退出   
  92.        if (__timespec_to_absolute(&ts, &abstime, clock) < 0)  
  93.             return EBUSY;  
  94.   
  95.         __futex_wait_ex(&mutex->value, shared, oldv, &ts);  
  96.     }  
  97.     return 0;  
  98. }  

转载地址:http://mashb.baihongyu.com/

你可能感兴趣的文章
程序如何检查堆栈溢出_通过使用堆栈检查平衡的括号(C ++程序)
查看>>
rip1 rip2_RIP的完整形式是什么?
查看>>
ruby 集合 分组_在Ruby中找到集合的长度
查看>>
sizeof函数_PHP sizeof()函数与示例
查看>>
python函数示例_abs()函数以及Python中的示例
查看>>
计算机图形学 顶点定义_在计算机图形学中定义一个圆
查看>>
斯威夫特山地车_斯威夫特| 打印“ Hello World”程序
查看>>
sql中len函数_在SQL中使用LEN(),ROUND()函数
查看>>
python二分法查找程序_Python程序查找标准偏差
查看>>
java bitset_Java BitSet size()方法与示例
查看>>
java reader_Java Reader skip()方法与示例
查看>>
java treemap_Java TreeMap get()方法与示例
查看>>
python 示例_带有示例的Python File tell()方法
查看>>
C ++中带有示例的nanl()函数
查看>>
CSS中的对象适合属性
查看>>
scala 数字阶乘_Scala程序查找数字的阶乘
查看>>
数据挖掘 数据增强_增强数据结构
查看>>
Java Dictionary put()方法与示例
查看>>
strictmath_Java StrictMath pow()方法与示例
查看>>
java treemap_Java TreeMap values()方法与示例
查看>>