Deleted Added
full compact
thr_mutex.c (129482) thr_mutex.c (129484)
1/*
2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
1/*
2 * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/lib/libthr/thread/thr_mutex.c 129482 2004-05-20 11:55:04Z mtm $
32 * $FreeBSD: head/lib/libthr/thread/thr_mutex.c 129484 2004-05-20 12:06:16Z mtm $
33 */
34#include <stdlib.h>
35#include <errno.h>
36#include <string.h>
37#include <sys/param.h>
38#include <sys/queue.h>
39#include <pthread.h>
40#include <time.h>

--- 188 unchanged lines hidden (view full) ---

229 * Acquires a mutex for the current thread. The caller must
230 * lock the mutex before calling this function.
231 */
232static void
233acquire_mutex(struct pthread_mutex *mtx, struct pthread *ptd)
234{
235 mtx->m_owner = ptd;
236 _MUTEX_ASSERT_NOT_OWNED(mtx);
33 */
34#include <stdlib.h>
35#include <errno.h>
36#include <string.h>
37#include <sys/param.h>
38#include <sys/queue.h>
39#include <pthread.h>
40#include <time.h>

--- 188 unchanged lines hidden (view full) ---

229 * Acquires a mutex for the current thread. The caller must
230 * lock the mutex before calling this function.
231 */
232static void
233acquire_mutex(struct pthread_mutex *mtx, struct pthread *ptd)
234{
235 mtx->m_owner = ptd;
236 _MUTEX_ASSERT_NOT_OWNED(mtx);
237 _thread_critical_enter(ptd);
237 PTHREAD_LOCK(ptd);
238 TAILQ_INSERT_TAIL(&ptd->mutexq, mtx, m_qe);
238 TAILQ_INSERT_TAIL(&ptd->mutexq, mtx, m_qe);
239 _thread_critical_exit(ptd);
239 PTHREAD_UNLOCK(ptd);
240}
241
242/*
243 * Releases a mutex from the current thread. The owner must
244 * lock the mutex. The next thread on the queue will be returned
245 * locked by the current thread. The caller must take care to
246 * unlock it.
247 */

--- 8 unchanged lines hidden (view full) ---

256
257 /*
258 * Deque next thread waiting for this mutex and attach
259 * the mutex to it. The thread will already be locked.
260 */
261 if ((ptd = mutex_queue_deq(mtx)) != NULL) {
262 TAILQ_INSERT_TAIL(&ptd->mutexq, mtx, m_qe);
263 ptd->data.mutex = NULL;
240}
241
242/*
243 * Releases a mutex from the current thread. The owner must
244 * lock the mutex. The next thread on the queue will be returned
245 * locked by the current thread. The caller must take care to
246 * unlock it.
247 */

--- 8 unchanged lines hidden (view full) ---

256
257 /*
258 * Deque next thread waiting for this mutex and attach
259 * the mutex to it. The thread will already be locked.
260 */
261 if ((ptd = mutex_queue_deq(mtx)) != NULL) {
262 TAILQ_INSERT_TAIL(&ptd->mutexq, mtx, m_qe);
263 ptd->data.mutex = NULL;
264 PTHREAD_NEW_STATE(ptd, PS_RUNNING);
264 PTHREAD_WAKE(ptd);
265 }
266 mtx->m_owner = ptd;
267}
268
269int
270__pthread_mutex_trylock(pthread_mutex_t *mutex)
271{
272 int ret = 0;

--- 107 unchanged lines hidden (view full) ---

380 }
381
382 if ((*mutex)->m_type == PTHREAD_MUTEX_RECURSIVE)
383 (*mutex)->m_data.m_count++;
384
385 /*
386 * The mutex is now owned by curthread.
387 */
265 }
266 mtx->m_owner = ptd;
267}
268
269int
270__pthread_mutex_trylock(pthread_mutex_t *mutex)
271{
272 int ret = 0;

--- 107 unchanged lines hidden (view full) ---

380 }
381
382 if ((*mutex)->m_type == PTHREAD_MUTEX_RECURSIVE)
383 (*mutex)->m_data.m_count++;
384
385 /*
386 * The mutex is now owned by curthread.
387 */
388 _thread_critical_enter(curthread);
388 PTHREAD_LOCK(curthread);
389
390 /*
391 * The mutex's priority may have changed while waiting for it.
392 */
393 if ((*mutex)->m_protocol == PTHREAD_PRIO_PROTECT &&
394 curthread->active_priority > (*mutex)->m_prio) {
395 mutex_attach_to_next_pthread(*mutex);
396 if ((*mutex)->m_owner != NULL)
389
390 /*
391 * The mutex's priority may have changed while waiting for it.
392 */
393 if ((*mutex)->m_protocol == PTHREAD_PRIO_PROTECT &&
394 curthread->active_priority > (*mutex)->m_prio) {
395 mutex_attach_to_next_pthread(*mutex);
396 if ((*mutex)->m_owner != NULL)
397 _thread_critical_exit((*mutex)->m_owner);
398 _thread_critical_exit(curthread);
397 PTHREAD_UNLOCK((*mutex)->m_owner);
398 PTHREAD_UNLOCK(curthread);
399 _SPINUNLOCK(&(*mutex)->lock);
400 return (EINVAL);
401 }
402
403 switch ((*mutex)->m_protocol) {
404 case PTHREAD_PRIO_INHERIT:
405 curthread->prio_inherit_count++;
406 break;

--- 5 unchanged lines hidden (view full) ---

412 curthread->inherited_priority = (*mutex)->m_prio;
413 curthread->active_priority = (*mutex)->m_prio;
414 }
415 break;
416 default:
417 /* Nothing */
418 break;
419 }
399 _SPINUNLOCK(&(*mutex)->lock);
400 return (EINVAL);
401 }
402
403 switch ((*mutex)->m_protocol) {
404 case PTHREAD_PRIO_INHERIT:
405 curthread->prio_inherit_count++;
406 break;

--- 5 unchanged lines hidden (view full) ---

412 curthread->inherited_priority = (*mutex)->m_prio;
413 curthread->active_priority = (*mutex)->m_prio;
414 }
415 break;
416 default:
417 /* Nothing */
418 break;
419 }
420 _thread_critical_exit(curthread);
420 PTHREAD_UNLOCK(curthread);
421out:
422 _SPINUNLOCK(&(*mutex)->lock);
423 return (error);
424}
425
426/*
427 * Caller must lock thread.
428 */

--- 18 unchanged lines hidden (view full) ---

447 * XXX LOR with respect to tempMtx and ptd.
448 * Order should be: 1. mutex
449 * 2. pthread
450 */
451 _SPINLOCK(&tempMtx->lock);
452
453 tempTd = TAILQ_FIRST(&tempMtx->m_queue);
454 if (tempTd != NULL) {
421out:
422 _SPINUNLOCK(&(*mutex)->lock);
423 return (error);
424}
425
426/*
427 * Caller must lock thread.
428 */

--- 18 unchanged lines hidden (view full) ---

447 * XXX LOR with respect to tempMtx and ptd.
448 * Order should be: 1. mutex
449 * 2. pthread
450 */
451 _SPINLOCK(&tempMtx->lock);
452
453 tempTd = TAILQ_FIRST(&tempMtx->m_queue);
454 if (tempTd != NULL) {
455 UMTX_LOCK(&tempTd->lock);
455 PTHREAD_LOCK(tempTd);
456 if (tempTd->active_priority > ptd->active_priority) {
457 ptd->inherited_priority =
458 tempTd->active_priority;
459 ptd->active_priority =
460 tempTd->active_priority;
461 }
456 if (tempTd->active_priority > ptd->active_priority) {
457 ptd->inherited_priority =
458 tempTd->active_priority;
459 ptd->active_priority =
460 tempTd->active_priority;
461 }
462 UMTX_UNLOCK(&tempTd->lock);
462 PTHREAD_UNLOCK(tempTd);
463 }
464 _SPINUNLOCK(&tempMtx->lock);
465 }
466}
467
468/*
469 * Caller must lock thread.
470 */

--- 165 unchanged lines hidden (view full) ---

636
637 case PTHREAD_MUTEX_NORMAL:
638 /*
639 * What SS2 define as a 'normal' mutex. Intentionally
640 * deadlock on attempts to get a lock you already own.
641 */
642 if (noblock)
643 return (EBUSY);
463 }
464 _SPINUNLOCK(&tempMtx->lock);
465 }
466}
467
468/*
469 * Caller must lock thread.
470 */

--- 165 unchanged lines hidden (view full) ---

636
637 case PTHREAD_MUTEX_NORMAL:
638 /*
639 * What SS2 define as a 'normal' mutex. Intentionally
640 * deadlock on attempts to get a lock you already own.
641 */
642 if (noblock)
643 return (EBUSY);
644 PTHREAD_SET_STATE(curthread, PS_DEADLOCK);
644 curthread->isdeadlocked = 1;
645 _SPINUNLOCK(&(mutex)->lock);
646 _thread_suspend(curthread, NULL);
647 PANIC("Shouldn't resume here?\n");
648 break;
649
650 default:
651 /* Do Nothing */
652 break;

--- 25 unchanged lines hidden (view full) ---

678 return (0);
679 }
680 }
681
682 /*
683 * Release the mutex from this thread and attach it to
684 * the next thread in the queue, if there is one waiting.
685 */
645 _SPINUNLOCK(&(mutex)->lock);
646 _thread_suspend(curthread, NULL);
647 PANIC("Shouldn't resume here?\n");
648 break;
649
650 default:
651 /* Do Nothing */
652 break;

--- 25 unchanged lines hidden (view full) ---

678 return (0);
679 }
680 }
681
682 /*
683 * Release the mutex from this thread and attach it to
684 * the next thread in the queue, if there is one waiting.
685 */
686 _thread_critical_enter(curthread);
686 PTHREAD_LOCK(curthread);
687 mutex_attach_to_next_pthread(*mutex);
688 if ((*mutex)->m_owner != NULL)
687 mutex_attach_to_next_pthread(*mutex);
688 if ((*mutex)->m_owner != NULL)
689 _thread_critical_exit((*mutex)->m_owner);
689 PTHREAD_UNLOCK((*mutex)->m_owner);
690 if (add_reference != 0) {
691 /* Increment the reference count: */
692 (*mutex)->m_refcount++;
693 }
694 _SPINUNLOCK(&(*mutex)->lock);
695
696 /*
697 * Fix priority of the thread that just released the mutex.

--- 14 unchanged lines hidden (view full) ---

712 restore_prio_protection(curthread);
713 if (curthread->prio_inherit_count > 0)
714 restore_prio_inheritance(curthread);
715 break;
716 default:
717 /* Nothing */
718 break;
719 }
690 if (add_reference != 0) {
691 /* Increment the reference count: */
692 (*mutex)->m_refcount++;
693 }
694 _SPINUNLOCK(&(*mutex)->lock);
695
696 /*
697 * Fix priority of the thread that just released the mutex.

--- 14 unchanged lines hidden (view full) ---

712 restore_prio_protection(curthread);
713 if (curthread->prio_inherit_count > 0)
714 restore_prio_inheritance(curthread);
715 break;
716 default:
717 /* Nothing */
718 break;
719 }
720 _thread_critical_exit(curthread);
720 PTHREAD_UNLOCK(curthread);
721 return (0);
722}
723
724void
725_mutex_unlock_private(pthread_t pthread)
726{
727 struct pthread_mutex *m, *m_next;
728

--- 25 unchanged lines hidden (view full) ---

754 * priority order. This funtion will return with the thread locked.
755 */
756static inline pthread_t
757mutex_queue_deq(pthread_mutex_t mutex)
758{
759 pthread_t pthread;
760
761 while ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL) {
721 return (0);
722}
723
724void
725_mutex_unlock_private(pthread_t pthread)
726{
727 struct pthread_mutex *m, *m_next;
728

--- 25 unchanged lines hidden (view full) ---

754 * priority order. This funtion will return with the thread locked.
755 */
756static inline pthread_t
757mutex_queue_deq(pthread_mutex_t mutex)
758{
759 pthread_t pthread;
760
761 while ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL) {
762 _thread_critical_enter(pthread);
762 PTHREAD_LOCK(pthread);
763 TAILQ_REMOVE(&mutex->m_queue, pthread, sqe);
764 pthread->flags &= ~PTHREAD_FLAGS_IN_MUTEXQ;
765
766 /*
767 * Only exit the loop if the thread hasn't been
763 TAILQ_REMOVE(&mutex->m_queue, pthread, sqe);
764 pthread->flags &= ~PTHREAD_FLAGS_IN_MUTEXQ;
765
766 /*
767 * Only exit the loop if the thread hasn't been
768 * cancelled.
768 * asynchronously cancelled.
769 */
769 */
770 if (((pthread->cancelflags & PTHREAD_CANCELLING) == 0 ||
771 (pthread->cancelflags & PTHREAD_CANCEL_DISABLE) != 0 ||
772 ((pthread->cancelflags & PTHREAD_CANCELLING) != 0 &&
773 (pthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) == 0)) &&
774 pthread->state == PS_MUTEX_WAIT)
775 break;
770 if (pthread->cancelmode == M_ASYNC &&
771 pthread->cancellation != CS_NULL)
772 continue;
776 else
773 else
777 _thread_critical_exit(pthread);
774 break;
778 }
775 }
779
780 return (pthread);
781}
782
783/*
784 * Remove a waiting thread from a mutex queue in descending priority order.
785 */
786static inline void
787mutex_queue_remove(pthread_mutex_t mutex, pthread_t pthread)

--- 31 unchanged lines hidden (view full) ---

819 else {
820 tid = TAILQ_FIRST(&mutex->m_queue);
821 while (pthread->active_priority <= tid->active_priority)
822 tid = TAILQ_NEXT(tid, sqe);
823 TAILQ_INSERT_BEFORE(tid, pthread, sqe);
824 }
825 if (mutex->m_protocol == PTHREAD_PRIO_INHERIT &&
826 pthread == TAILQ_FIRST(&mutex->m_queue)) {
776 return (pthread);
777}
778
779/*
780 * Remove a waiting thread from a mutex queue in descending priority order.
781 */
782static inline void
783mutex_queue_remove(pthread_mutex_t mutex, pthread_t pthread)

--- 31 unchanged lines hidden (view full) ---

815 else {
816 tid = TAILQ_FIRST(&mutex->m_queue);
817 while (pthread->active_priority <= tid->active_priority)
818 tid = TAILQ_NEXT(tid, sqe);
819 TAILQ_INSERT_BEFORE(tid, pthread, sqe);
820 }
821 if (mutex->m_protocol == PTHREAD_PRIO_INHERIT &&
822 pthread == TAILQ_FIRST(&mutex->m_queue)) {
827 UMTX_LOCK(&mutex->m_owner->lock);
823 PTHREAD_LOCK(mutex->m_owner);
828 if (pthread->active_priority >
829 mutex->m_owner->active_priority) {
830 mutex->m_owner->inherited_priority =
831 pthread->active_priority;
832 mutex->m_owner->active_priority =
833 pthread->active_priority;
834 }
824 if (pthread->active_priority >
825 mutex->m_owner->active_priority) {
826 mutex->m_owner->inherited_priority =
827 pthread->active_priority;
828 mutex->m_owner->active_priority =
829 pthread->active_priority;
830 }
835 UMTX_UNLOCK(&mutex->m_owner->lock);
831 PTHREAD_UNLOCK(mutex->m_owner);
836 }
837 pthread->flags |= PTHREAD_FLAGS_IN_MUTEXQ;
838}
839
840/*
841 * Caller must lock mutex and pthread.
842 */
843void
844readjust_priorities(struct pthread *pthread, struct pthread_mutex *mtx)
845{
832 }
833 pthread->flags |= PTHREAD_FLAGS_IN_MUTEXQ;
834}
835
836/*
837 * Caller must lock mutex and pthread.
838 */
839void
840readjust_priorities(struct pthread *pthread, struct pthread_mutex *mtx)
841{
846 if (pthread->state == PS_MUTEX_WAIT) {
842 if ((pthread->flags & PTHREAD_FLAGS_IN_MUTEXQ) != 0) {
847 mutex_queue_remove(mtx, pthread);
848 mutex_queue_enq(mtx, pthread);
843 mutex_queue_remove(mtx, pthread);
844 mutex_queue_enq(mtx, pthread);
849 UMTX_LOCK(&mtx->m_owner->lock);
845 PTHREAD_LOCK(mtx->m_owner);
850 adjust_prio_inheritance(mtx->m_owner);
851 if (mtx->m_owner->prio_protect_count > 0)
852 adjust_prio_protection(mtx->m_owner);
846 adjust_prio_inheritance(mtx->m_owner);
847 if (mtx->m_owner->prio_protect_count > 0)
848 adjust_prio_protection(mtx->m_owner);
853 UMTX_UNLOCK(&mtx->m_owner->lock);
849 PTHREAD_UNLOCK(mtx->m_owner);
854 }
855 if (pthread->prio_inherit_count > 0)
856 adjust_prio_inheritance(pthread);
857 if (pthread->prio_protect_count > 0)
858 adjust_prio_protection(pthread);
859}
860
861/*

--- 16 unchanged lines hidden (view full) ---

878 }
879
880 /*
881 * Put this thread on the mutex's list of waiting threads.
882 * The lock on the thread ensures atomic (as far as other
883 * threads are concerned) setting of the thread state with
884 * it's status on the mutex queue.
885 */
850 }
851 if (pthread->prio_inherit_count > 0)
852 adjust_prio_inheritance(pthread);
853 if (pthread->prio_protect_count > 0)
854 adjust_prio_protection(pthread);
855}
856
857/*

--- 16 unchanged lines hidden (view full) ---

874 }
875
876 /*
877 * Put this thread on the mutex's list of waiting threads.
878 * The lock on the thread ensures atomic (as far as other
879 * threads are concerned) setting of the thread state with
880 * it's status on the mutex queue.
881 */
886 _thread_critical_enter(curthread);
882 PTHREAD_LOCK(curthread);
887 mutex_queue_enq(mutexp, curthread);
888 do {
883 mutex_queue_enq(mutexp, curthread);
884 do {
889 if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0 &&
890 (curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0 &&
891 (curthread->cancelflags & PTHREAD_CANCELLING) != 0) {
885 if (curthread->cancelmode == M_ASYNC &&
886 curthread->cancellation != CS_NULL) {
892 mutex_queue_remove(mutexp, curthread);
887 mutex_queue_remove(mutexp, curthread);
893 _thread_critical_exit(curthread);
888 PTHREAD_UNLOCK(curthread);
894 _SPINUNLOCK(&mutexp->lock);
895 pthread_testcancel();
896 }
889 _SPINUNLOCK(&mutexp->lock);
890 pthread_testcancel();
891 }
897 PTHREAD_SET_STATE(curthread, PS_MUTEX_WAIT);
898 curthread->data.mutex = mutexp;
892 curthread->data.mutex = mutexp;
899 _thread_critical_exit(curthread);
893 PTHREAD_UNLOCK(curthread);
900 _SPINUNLOCK(&mutexp->lock);
901 error = _thread_suspend(curthread, abstime);
902 if (error != 0 && error != ETIMEDOUT && error != EINTR)
903 PANIC("Cannot suspend on mutex.");
904 _SPINLOCK(&mutexp->lock);
894 _SPINUNLOCK(&mutexp->lock);
895 error = _thread_suspend(curthread, abstime);
896 if (error != 0 && error != ETIMEDOUT && error != EINTR)
897 PANIC("Cannot suspend on mutex.");
898 _SPINLOCK(&mutexp->lock);
905 _thread_critical_enter(curthread);
899 PTHREAD_LOCK(curthread);
906 if (error == ETIMEDOUT) {
907 /*
908 * Between the timeout and when the mutex was
909 * locked the previous owner may have released
910 * the mutex to this thread. Or not.
911 */
900 if (error == ETIMEDOUT) {
901 /*
902 * Between the timeout and when the mutex was
903 * locked the previous owner may have released
904 * the mutex to this thread. Or not.
905 */
912 if (mutexp->m_owner == curthread) {
906 if (mutexp->m_owner == curthread)
913 error = 0;
907 error = 0;
914 } else {
908 else
915 _mutex_lock_backout(curthread);
909 _mutex_lock_backout(curthread);
916 curthread->state = PS_RUNNING;
917 error = ETIMEDOUT;
918 }
919 }
920 } while ((curthread->flags & PTHREAD_FLAGS_IN_MUTEXQ) != 0);
910 }
911 } while ((curthread->flags & PTHREAD_FLAGS_IN_MUTEXQ) != 0);
921 _thread_critical_exit(curthread);
912 PTHREAD_UNLOCK(curthread);
922 return (error);
923}
913 return (error);
914}