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} |