PERFORCE change 67675 for review
David Xu
davidxu at FreeBSD.org
Sat Dec 25 05:08:21 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=67675
Change 67675 by davidxu at 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);
More information about the p4-projects
mailing list