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