diff options
author | alfred <alfred@FreeBSD.org> | 1999-11-28 05:38:13 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 1999-11-28 05:38:13 +0000 |
commit | e7efcb5302ff3b4faef7cf619f51a4b4a509f09a (patch) | |
tree | 295e248e2503f8c817b16353f285d30439bf4bf4 /lib/libc_r/uthread/uthread_mutex.c | |
parent | dff67f0b84733be29e807fc281e817bc8639fd70 (diff) | |
download | FreeBSD-src-e7efcb5302ff3b4faef7cf619f51a4b4a509f09a.zip FreeBSD-src-e7efcb5302ff3b4faef7cf619f51a4b4a509f09a.tar.gz |
add pthread_cancel, obtained from OpenBSD.
eischen (Daniel Eischen) added wrappers to protect against cancled
threads orphaning internal resources.
the cancelability code is still a bit fuzzy but works for test
programs of my own, OpenBSD's and some examples from ORA's books.
add readdir_r to both libc and libc_r
add some 'const' attributes to function parameters
Reviewed by: eischen, jasone
Diffstat (limited to 'lib/libc_r/uthread/uthread_mutex.c')
-rw-r--r-- | lib/libc_r/uthread/uthread_mutex.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/lib/libc_r/uthread/uthread_mutex.c b/lib/libc_r/uthread/uthread_mutex.c index a402d4b..b2a06f2 100644 --- a/lib/libc_r/uthread/uthread_mutex.c +++ b/lib/libc_r/uthread/uthread_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 |