xref: /plan9/sys/src/cmd/unix/drawterm/libc/lock.c (revision 96cbc34f1b36a29efdcfd47b10e70703a690febc)
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)9 lockinit(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)25 lock(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)34 canlock(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)49 unlock(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)60 canlock(Lock *lk)
61 {
62 	return !tas(&lk->key);
63 }
64 
65 void
lock(Lock * lk)66 lock(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)102 unlock(Lock *lk)
103 {
104 	assert(lk->key);
105 	lk->key = 0;
106 }
107 
108 #endif
109 
110 void
ilock(Lock * lk)111 ilock(Lock *lk)
112 {
113 	lock(lk);
114 }
115 
116 void
iunlock(Lock * lk)117 iunlock(Lock *lk)
118 {
119 	unlock(lk);
120 }
121