Date: Sat, 25 Dec 2004 13:08:19 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 67675 for review Message-ID: <200412251308.iBPD8Jgu036515@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=67675 Change 67675 by davidxu@davidxu_tiger on 2004/12/25 13:08:08 Refine simple mutex type locking code. The simple mutex has already ability to be shared among processes, but because pthread_mutex_t was defined as a pointer, current it can not be shared by processes. Affected files ... .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_mutex.c#5 edit Differences ... ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_mutex.c#5 (text+ko) ==== @@ -66,7 +66,6 @@ #define THR_IN_MUTEXQ(thr) (((thr)->sflags & THR_FLAGS_IN_SYNCQ) != 0) #define MUTEX_DESTROY(m) do { \ - _UMTX_DESTROY(&(m)->m_lock); \ free(m); \ } while (0) @@ -103,7 +102,7 @@ int -_pthread_mutex_init(pthread_mutex_t *mutex, +__pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr) { struct pthread_mutex *pmutex; @@ -151,7 +150,7 @@ malloc(sizeof(struct pthread_mutex))) == NULL) { ret = ENOMEM; } else { - _UMTX_INIT(&pmutex->m_lock); + umtx_init(&pmutex->m_lock); /* Set the mutex flags: */ pmutex->m_flags = flags; @@ -201,10 +200,26 @@ return (ret); } +int +_pthread_mutex_init(pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutex_attr) +{ + struct pthread_mutex_attr mattr, *mattrp; + + if ((mutex_attr == NULL) || (*mutex_attr == NULL)) + return (__pthread_mutex_init(mutex, &static_mattr)); + else { + mattr = **mutex_attr; + mattr.m_flags |= MUTEX_FLAGS_PRIVATE; + mattrp = &mattr; + return (__pthread_mutex_init(mutex, &mattrp)); + } +} + void _thr_mutex_reinit(pthread_mutex_t *mutex) { - _UMTX_REINIT(&(*mutex)->m_lock); + umtx_init(&(*mutex)->m_lock); TAILQ_INIT(&(*mutex)->m_queue); MUTEX_INIT_LINK(*mutex); (*mutex)->m_owner = NULL; @@ -217,6 +232,7 @@ int _pthread_mutex_destroy(pthread_mutex_t *mutex) { + struct pthread *curthread = _get_curthread(); pthread_mutex_t m; int ret = 0; @@ -224,11 +240,22 @@ ret = EINVAL; else { /* - * Check to see if this mutex is in use: + * Try to lock the mutex structure, we only need to + * try once, if failed, the mutex is in used. + */ + ret = umtx_trylock(&(*mutex)->m_lock, curthread->tid); + if (ret) + return (ret); + + /* + * Check mutex other fields to see if this mutex is + * in use. Mostly for prority mutex types, or there + * are condition variables referencing it. */ if (((*mutex)->m_owner != NULL) || (TAILQ_FIRST(&(*mutex)->m_queue) != NULL) || ((*mutex)->m_refcount != 0)) { + umtx_unlock(&(*mutex)->m_lock, curthread->tid); ret = EBUSY; } else { /* @@ -238,6 +265,9 @@ m = *mutex; *mutex = NULL; + /* Unlock the mutex structure: */ + umtx_unlock(&m->m_lock, curthread->tid); + /* * Free the memory allocated for the mutex * structure: @@ -276,7 +306,7 @@ THR_LOCK_ACQUIRE(thread, &_mutex_static_lock); if (*mutex == NULL) - ret = pthread_mutex_init(mutex, &static_mattr); + ret = _pthread_mutex_init(mutex, &static_mattr); else ret = 0; @@ -291,15 +321,17 @@ int ret = 0; THR_ASSERT((mutex != NULL) && (*mutex != NULL), - "Uninitialized mutex in pthread_mutex_trylock_basic"); + "Uninitialized mutex in pthread_mutex_trylock"); + /* Short cut for simple mutex. */ if ((*mutex)->m_protocol == PTHREAD_PRIO_NONE) { ret = umtx_trylock(&(*mutex)->m_lock, curthread->tid); if (ret == 0) { (*mutex)->m_owner = curthread; /* - * XXX there should be a separated list for owned mutex, - * separated it from priority mutex list + * XXX there should be a separated list for + * owned mutex, separated it from priority + * mutex list */ #if 0 /* Add to the list of owned mutexes: */ @@ -307,14 +339,15 @@ TAILQ_INSERT_TAIL(&curthread->mutexq, (*mutex), m_qe); #endif - } else if ((*mutex)->m_owner == curthread) + } else if (umtx_owner(&(*mutex)->m_lock) == curthread->tid) { ret = mutex_self_trylock(curthread, *mutex); - else - ret = EBUSY; + } /* else {} */ return (ret); } + /* Code for priority mutex */ + /* Lock the mutex structure: */ THR_LOCK_ACQUIRE(curthread, &(*mutex)->m_lock); @@ -462,14 +495,17 @@ THR_ASSERT((m != NULL) && (*m != NULL), "Uninitialized mutex in mutex_lock_common"); + /* Short cut for simple mutex. */ + if ((*m)->m_protocol == PTHREAD_PRIO_NONE) { /* Default POSIX mutex: */ ret = umtx_trylock(&(*m)->m_lock, curthread->tid); if (ret == 0) { (*m)->m_owner = curthread; /* - * XXX there should be a separated list for owned mutex, - * separated it from priority mutex list + * XXX there should be a separated list for + * owned mutex, separated it from priority + * mutex list */ #if 0 /* Add to the list of owned mutexes: */ @@ -477,18 +513,21 @@ TAILQ_INSERT_TAIL(&curthread->mutexq, (*m), m_qe); #endif - } else if ((*m)->m_owner == curthread && - !((*m)->m_type == PTHREAD_MUTEX_NORMAL && - abstime != NULL)) { + } else if (umtx_owner(&(*m)->m_lock) == curthread->tid && + (*m)->m_type != PTHREAD_MUTEX_NORMAL) { ret = mutex_self_lock(curthread, *m); } else { - if (abstime != NULL) { - ret = umtx_timedlock(&(*m)->m_lock, curthread->tid, - (struct timespec *)abstime); + if (abstime == NULL) { + ret = UMTX_LOCK(&(*m)->m_lock, curthread->tid); + } else { + ret = umtx_timedlock(&(*m)->m_lock, + curthread->tid, abstime); + /* + * Timed out wait is not restarted if + * it was interrupted, not worth to do it. + */ if (ret == EAGAIN || ret == EINTR) ret = ETIMEDOUT; - } else { - ret = _UMTX_LOCK(&(*m)->m_lock, curthread->tid); } if (ret == 0) { (*m)->m_owner = curthread; @@ -503,6 +542,8 @@ return (ret); } + /* Code for priority mutex */ + if (abstime != NULL && (abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) return (EINVAL); @@ -884,7 +925,7 @@ static inline int mutex_self_trylock(struct pthread *curthread, pthread_mutex_t m) { - int ret = 0; + int ret; switch (m->m_type) { /* case PTHREAD_MUTEX_DEFAULT: */ @@ -896,6 +937,7 @@ case PTHREAD_MUTEX_RECURSIVE: /* Increment the lock count: */ m->m_count++; + ret = 0; break; default: @@ -909,7 +951,7 @@ static inline int mutex_self_lock(struct pthread *curthread, pthread_mutex_t m) { - int ret = 0; + int ret; switch (m->m_type) { /* case PTHREAD_MUTEX_DEFAULT: */ @@ -935,6 +977,7 @@ /* Schedule the next thread: */ _thr_sched_switch_unlocked(curthread); + ret = 0; break; case PTHREAD_MUTEX_RECURSIVE: @@ -960,15 +1003,19 @@ if (m == NULL || *m == NULL) ret = EINVAL; else { + /* Short cut for simple mutex. */ + if ((*m)->m_protocol == PTHREAD_PRIO_NONE) { /* * Check if the running thread is not the owner of the * mutex: */ - if ((*m)->m_owner != curthread) + if (__predict_false(umtx_owner(&(*m)->m_lock) != + curthread->tid)) { ret = EPERM; - else if (((*m)->m_type == PTHREAD_MUTEX_RECURSIVE) && - ((*m)->m_count > 0)) { + } else if (__predict_false( + (*m)->m_type == PTHREAD_MUTEX_RECURSIVE && + (*m)->m_count > 0)) { /* Decrement the count: */ (*m)->m_count--; if (add_reference) @@ -996,15 +1043,15 @@ (*m)->m_refcount++; /* * Hand off the mutex to the next waiting - * thread: + * thread, XXX ignore return value. */ - ret = umtx_unlock(&(*m)->m_lock, - curthread->tid); - /* XXX decrease refcount if failed ? */ + umtx_unlock(&(*m)->m_lock, curthread->tid); } return (ret); } + /* Code for priority mutex */ + /* Lock the mutex structure: */ THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412251308.iBPD8Jgu036515>