1 #include <u.h> 2 #include <libc.h> 3 4 #ifdef PTHREAD 5 6 static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; 7 8 static void lockinit(Lock * lk)9lockinit(Lock *lk) 10 { 11 pthread_mutexattr_t attr; 12 13 pthread_mutex_lock(&initmutex); 14 if(lk->init == 0){ 15 pthread_mutexattr_init(&attr); 16 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); 17 pthread_mutex_init(&lk->mutex, &attr); 18 pthread_mutexattr_destroy(&attr); 19 lk->init = 1; 20 } 21 pthread_mutex_unlock(&initmutex); 22 } 23 24 void lock(Lock * lk)25lock(Lock *lk) 26 { 27 if(!lk->init) 28 lockinit(lk); 29 if(pthread_mutex_lock(&lk->mutex) != 0) 30 abort(); 31 } 32 33 int canlock(Lock * lk)34canlock(Lock *lk) 35 { 36 int r; 37 38 if(!lk->init) 39 lockinit(lk); 40 r = pthread_mutex_trylock(&lk->mutex); 41 if(r == 0) 42 return 1; 43 if(r == EBUSY) 44 return 0; 45 abort(); 46 } 47 48 void unlock(Lock * lk)49unlock(Lock *lk) 50 { 51 if(pthread_mutex_unlock(&lk->mutex) != 0) 52 abort(); 53 } 54 55 #else 56 57 /* old, non-pthread systems */ 58 59 int canlock(Lock * lk)60canlock(Lock *lk) 61 { 62 return !tas(&lk->key); 63 } 64 65 void lock(Lock * lk)66lock(Lock *lk) 67 { 68 int i; 69 70 /* easy case */ 71 if(canlock(lk)) 72 return; 73 74 /* for multi processor machines */ 75 for(i=0; i<100; i++) 76 if(canlock(lk)) 77 return; 78 79 for(i=0; i<100; i++) { 80 osyield(); 81 if(canlock(lk)) 82 return; 83 } 84 85 /* looking bad - make sure it is not a priority problem */ 86 for(i=0; i<12; i++) { 87 osmsleep(1<<i); 88 if(canlock(lk)) 89 return; 90 } 91 92 /* we are in trouble */ 93 for(;;) { 94 if(canlock(lk)) 95 return; 96 iprint("lock loop %ld: val=%d &lock=%ux pc=%p\n", getpid(), lk->key, lk, getcallerpc(&lk)); 97 osmsleep(1000); 98 } 99 } 100 101 void unlock(Lock * lk)102unlock(Lock *lk) 103 { 104 assert(lk->key); 105 lk->key = 0; 106 } 107 108 #endif 109 110 void ilock(Lock * lk)111ilock(Lock *lk) 112 { 113 lock(lk); 114 } 115 116 void iunlock(Lock * lk)117iunlock(Lock *lk) 118 { 119 unlock(lk); 120 } 121