xref: /plan9/sys/src/cmd/unix/drawterm/libc/lock.c (revision 96cbc34f1b36a29efdcfd47b10e70703a690febc)
18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
38ccd4a63SDavid du Colombier 
4*96cbc34fSDavid du Colombier #ifdef PTHREAD
5*96cbc34fSDavid du Colombier 
6*96cbc34fSDavid du Colombier static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
7*96cbc34fSDavid du Colombier 
8*96cbc34fSDavid du Colombier static void
lockinit(Lock * lk)9*96cbc34fSDavid du Colombier lockinit(Lock *lk)
10*96cbc34fSDavid du Colombier {
11*96cbc34fSDavid du Colombier 	pthread_mutexattr_t attr;
12*96cbc34fSDavid du Colombier 
13*96cbc34fSDavid du Colombier 	pthread_mutex_lock(&initmutex);
14*96cbc34fSDavid du Colombier 	if(lk->init == 0){
15*96cbc34fSDavid du Colombier 		pthread_mutexattr_init(&attr);
16*96cbc34fSDavid du Colombier 		pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
17*96cbc34fSDavid du Colombier 		pthread_mutex_init(&lk->mutex, &attr);
18*96cbc34fSDavid du Colombier 		pthread_mutexattr_destroy(&attr);
19*96cbc34fSDavid du Colombier 		lk->init = 1;
20*96cbc34fSDavid du Colombier 	}
21*96cbc34fSDavid du Colombier 	pthread_mutex_unlock(&initmutex);
22*96cbc34fSDavid du Colombier }
23*96cbc34fSDavid du Colombier 
24*96cbc34fSDavid du Colombier void
lock(Lock * lk)25*96cbc34fSDavid du Colombier lock(Lock *lk)
26*96cbc34fSDavid du Colombier {
27*96cbc34fSDavid du Colombier 	if(!lk->init)
28*96cbc34fSDavid du Colombier 		lockinit(lk);
29*96cbc34fSDavid du Colombier 	if(pthread_mutex_lock(&lk->mutex) != 0)
30*96cbc34fSDavid du Colombier 		abort();
31*96cbc34fSDavid du Colombier }
32*96cbc34fSDavid du Colombier 
33*96cbc34fSDavid du Colombier int
canlock(Lock * lk)34*96cbc34fSDavid du Colombier canlock(Lock *lk)
35*96cbc34fSDavid du Colombier {
36*96cbc34fSDavid du Colombier 	int r;
37*96cbc34fSDavid du Colombier 
38*96cbc34fSDavid du Colombier 	if(!lk->init)
39*96cbc34fSDavid du Colombier 		lockinit(lk);
40*96cbc34fSDavid du Colombier 	r = pthread_mutex_trylock(&lk->mutex);
41*96cbc34fSDavid du Colombier 	if(r == 0)
42*96cbc34fSDavid du Colombier 		return 1;
43*96cbc34fSDavid du Colombier 	if(r == EBUSY)
44*96cbc34fSDavid du Colombier 		return 0;
45*96cbc34fSDavid du Colombier 	abort();
46*96cbc34fSDavid du Colombier }
47*96cbc34fSDavid du Colombier 
48*96cbc34fSDavid du Colombier void
unlock(Lock * lk)49*96cbc34fSDavid du Colombier unlock(Lock *lk)
50*96cbc34fSDavid du Colombier {
51*96cbc34fSDavid du Colombier 	if(pthread_mutex_unlock(&lk->mutex) != 0)
52*96cbc34fSDavid du Colombier 		abort();
53*96cbc34fSDavid du Colombier }
54*96cbc34fSDavid du Colombier 
55*96cbc34fSDavid du Colombier #else
56*96cbc34fSDavid du Colombier 
57*96cbc34fSDavid du Colombier /* old, non-pthread systems */
58*96cbc34fSDavid du Colombier 
598ccd4a63SDavid du Colombier int
canlock(Lock * lk)608ccd4a63SDavid du Colombier canlock(Lock *lk)
618ccd4a63SDavid du Colombier {
628ccd4a63SDavid du Colombier 	return !tas(&lk->key);
638ccd4a63SDavid du Colombier }
648ccd4a63SDavid du Colombier 
658ccd4a63SDavid du Colombier void
lock(Lock * lk)668ccd4a63SDavid du Colombier lock(Lock *lk)
678ccd4a63SDavid du Colombier {
688ccd4a63SDavid du Colombier 	int i;
698ccd4a63SDavid du Colombier 
708ccd4a63SDavid du Colombier 	/* easy case */
718ccd4a63SDavid du Colombier 	if(canlock(lk))
728ccd4a63SDavid du Colombier 		return;
738ccd4a63SDavid du Colombier 
748ccd4a63SDavid du Colombier 	/* for multi processor machines */
758ccd4a63SDavid du Colombier 	for(i=0; i<100; i++)
768ccd4a63SDavid du Colombier 		if(canlock(lk))
778ccd4a63SDavid du Colombier 			return;
788ccd4a63SDavid du Colombier 
798ccd4a63SDavid du Colombier 	for(i=0; i<100; i++) {
808ccd4a63SDavid du Colombier 		osyield();
818ccd4a63SDavid du Colombier 		if(canlock(lk))
828ccd4a63SDavid du Colombier 			return;
838ccd4a63SDavid du Colombier 	}
848ccd4a63SDavid du Colombier 
858ccd4a63SDavid du Colombier 	/* looking bad - make sure it is not a priority problem */
868ccd4a63SDavid du Colombier 	for(i=0; i<12; i++) {
878ccd4a63SDavid du Colombier 		osmsleep(1<<i);
888ccd4a63SDavid du Colombier 		if(canlock(lk))
898ccd4a63SDavid du Colombier 			return;
908ccd4a63SDavid du Colombier 	}
918ccd4a63SDavid du Colombier 
928ccd4a63SDavid du Colombier 	/* we are in trouble */
938ccd4a63SDavid du Colombier 	for(;;) {
948ccd4a63SDavid du Colombier 		if(canlock(lk))
958ccd4a63SDavid du Colombier 			return;
96ec59a3ddSDavid du Colombier 		iprint("lock loop %ld: val=%d &lock=%ux pc=%p\n", getpid(), lk->key, lk, getcallerpc(&lk));
978ccd4a63SDavid du Colombier 		osmsleep(1000);
988ccd4a63SDavid du Colombier 	}
998ccd4a63SDavid du Colombier }
1008ccd4a63SDavid du Colombier 
1018ccd4a63SDavid du Colombier void
unlock(Lock * lk)1028ccd4a63SDavid du Colombier unlock(Lock *lk)
1038ccd4a63SDavid du Colombier {
1048ccd4a63SDavid du Colombier 	assert(lk->key);
1058ccd4a63SDavid du Colombier 	lk->key = 0;
1068ccd4a63SDavid du Colombier }
1078ccd4a63SDavid du Colombier 
108*96cbc34fSDavid du Colombier #endif
109*96cbc34fSDavid du Colombier 
1108ccd4a63SDavid du Colombier void
ilock(Lock * lk)1118ccd4a63SDavid du Colombier ilock(Lock *lk)
1128ccd4a63SDavid du Colombier {
1138ccd4a63SDavid du Colombier 	lock(lk);
1148ccd4a63SDavid du Colombier }
1158ccd4a63SDavid du Colombier 
1168ccd4a63SDavid du Colombier void
iunlock(Lock * lk)1178ccd4a63SDavid du Colombier iunlock(Lock *lk)
1188ccd4a63SDavid du Colombier {
1198ccd4a63SDavid du Colombier 	unlock(lk);
1208ccd4a63SDavid du Colombier }
121