summaryrefslogtreecommitdiffstats
path: root/lib/libkse/thread/thr_mutex.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libkse/thread/thr_mutex.c')
-rw-r--r--lib/libkse/thread/thr_mutex.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/lib/libkse/thread/thr_mutex.c b/lib/libkse/thread/thr_mutex.c
index a402d4b..b2a06f2 100644
--- a/lib/libkse/thread/thr_mutex.c
+++ b/lib/libkse/thread/thr_mutex.c
@@ -94,7 +94,8 @@ _mutex_reinit(pthread_mutex_t * mutex)
TAILQ_INIT(&(*mutex)->m_queue);
(*mutex)->m_owner = NULL;
(*mutex)->m_data.m_count = 0;
- (*mutex)->m_flags = MUTEX_FLAGS_INITED;
+ (*mutex)->m_flags &= MUTEX_FLAGS_PRIVATE;
+ (*mutex)->m_flags |= MUTEX_FLAGS_INITED;
(*mutex)->m_refcount = 0;
(*mutex)->m_prio = 0;
(*mutex)->m_saved_prio = 0;
@@ -428,6 +429,9 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
_MUTEX_INIT_LINK(*mutex);
}
+ /* Reset the interrupted flag: */
+ _thread_run->interrupted = 0;
+
/* Process according to mutex type: */
switch ((*mutex)->m_protocol) {
/* Default POSIX mutex: */
@@ -602,6 +606,13 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
break;
}
+ /*
+ * Check to see if this thread was interrupted and
+ * is still in the mutex queue of waiting threads:
+ */
+ if (_thread_run->interrupted != 0)
+ mutex_queue_remove(*mutex, _thread_run);
+
/* Unlock the mutex structure: */
_SPINUNLOCK(&(*mutex)->lock);
@@ -610,6 +621,11 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
* necessary:
*/
_thread_kern_sig_undefer();
+
+ if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
+ _thread_exit_cleanup();
+ pthread_exit(PTHREAD_CANCELED);
+ }
}
/* Return the completion status: */
@@ -1314,6 +1330,18 @@ mutex_rescan_owned (pthread_t pthread, pthread_mutex_t mutex)
}
}
+void
+_mutex_unlock_private(pthread_t pthread)
+{
+ struct pthread_mutex *m, *m_next;
+
+ for (m = TAILQ_FIRST(&pthread->mutexq); m != NULL; m = m_next) {
+ m_next = TAILQ_NEXT(m, m_qe);
+ if ((m->m_flags & MUTEX_FLAGS_PRIVATE) != 0)
+ pthread_mutex_unlock(&m);
+ }
+}
+
/*
* Dequeue a waiting thread from the head of a mutex queue in descending
* priority order.
@@ -1323,8 +1351,17 @@ mutex_queue_deq(pthread_mutex_t mutex)
{
pthread_t pthread;
- if ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL)
+ while ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL) {
TAILQ_REMOVE(&mutex->m_queue, pthread, qe);
+ pthread->flags &= ~PTHREAD_FLAGS_IN_MUTEXQ;
+
+ /*
+ * Only exit the loop if the thread hasn't been
+ * cancelled.
+ */
+ if (pthread->interrupted == 0)
+ break;
+ }
return(pthread);
}
@@ -1335,7 +1372,10 @@ mutex_queue_deq(pthread_mutex_t mutex)
static inline void
mutex_queue_remove(pthread_mutex_t mutex, pthread_t pthread)
{
- TAILQ_REMOVE(&mutex->m_queue, pthread, qe);
+ if ((pthread->flags & PTHREAD_FLAGS_IN_MUTEXQ) != 0) {
+ TAILQ_REMOVE(&mutex->m_queue, pthread, qe);
+ pthread->flags &= ~PTHREAD_FLAGS_IN_MUTEXQ;
+ }
}
/*
@@ -1359,6 +1399,7 @@ mutex_queue_enq(pthread_mutex_t mutex, pthread_t pthread)
tid = TAILQ_NEXT(tid, qe);
TAILQ_INSERT_BEFORE(tid, pthread, qe);
}
+ pthread->flags |= PTHREAD_FLAGS_IN_MUTEXQ;
}
#endif
OpenPOWER on IntegriCloud