123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- #include <errno.h>
- #include <sched.h>
- #include <time.h>
- #include "pthread.h"
- #include "internals.h"
- #include "spinlock.h"
- #include "restart.h"
- void internal_function __pthread_lock(struct _pthread_fastlock * lock,
- pthread_descr self)
- {
- long oldstatus, newstatus;
- int spurious_wakeup_count = 0;
- do {
- oldstatus = lock->__status;
- if (oldstatus == 0) {
- newstatus = 1;
- } else {
- if (self == NULL)
- self = thread_self();
- newstatus = (long) self;
- }
- if (self != NULL) {
- ASSERT(self->p_nextlock == NULL);
- THREAD_SETMEM(self, p_nextlock, (pthread_descr) oldstatus);
- }
- } while(! compare_and_swap(&lock->__status, oldstatus, newstatus,
- &lock->__spinlock));
-
- if (oldstatus != 0) {
- for (;;) {
- suspend(self);
- if (self->p_nextlock != NULL) {
-
- spurious_wakeup_count++;
- continue;
- }
- break;
- }
- }
-
- while (spurious_wakeup_count--)
- restart(self);
- }
- void internal_function __pthread_unlock(struct _pthread_fastlock * lock)
- {
- long oldstatus;
- pthread_descr thr, * ptr, * maxptr;
- int maxprio;
- again:
- oldstatus = lock->__status;
- if (oldstatus == 0 || oldstatus == 1) {
-
- if (! compare_and_swap(&lock->__status, oldstatus, 0, &lock->__spinlock))
- goto again;
- return;
- }
-
- ptr = (pthread_descr *) &lock->__status;
- thr = (pthread_descr) oldstatus;
- maxprio = 0;
- maxptr = ptr;
- while (thr != (pthread_descr) 1) {
- if (thr->p_priority >= maxprio) {
- maxptr = ptr;
- maxprio = thr->p_priority;
- }
- ptr = &(thr->p_nextlock);
- thr = *ptr;
- }
-
- if (maxptr == (pthread_descr *) &lock->__status) {
-
- thr = (pthread_descr) oldstatus;
- if (! compare_and_swap(&lock->__status,
- oldstatus, (long)(thr->p_nextlock),
- &lock->__spinlock))
- goto again;
- } else {
-
- thr = *maxptr;
- *maxptr = thr->p_nextlock;
- }
-
- thr->p_nextlock = NULL;
- restart(thr);
- }
- #ifdef TEST_FOR_COMPARE_AND_SWAP
- int __pthread_has_cas = 0;
- #endif
- #if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP
- static void __pthread_acquire(int * spinlock);
- int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
- int * spinlock)
- {
- int res;
- if (testandset(spinlock)) __pthread_acquire(spinlock);
- if (*ptr == oldval) {
- *ptr = newval; res = 1;
- } else {
- res = 0;
- }
- *spinlock = 0;
- return res;
- }
- static void __pthread_acquire(int * spinlock)
- {
- int cnt = 0;
- struct timespec tm;
- while (testandset(spinlock)) {
- if (cnt < MAX_SPIN_COUNT) {
- sched_yield();
- cnt++;
- } else {
- tm.tv_sec = 0;
- tm.tv_nsec = SPIN_SLEEP_DURATION;
- nanosleep(&tm, NULL);
- cnt = 0;
- }
- }
- }
- #endif
|