Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
60
canlock(Lock *lk)
61
{
62
	return !tas(&lk->key);
63
}
64
 
65
void
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
102
unlock(Lock *lk)
103
{
104
	assert(lk->key);
105
	lk->key = 0;
106
}
107
 
108
#endif
109
 
110
void
111
ilock(Lock *lk)
112
{
113
	lock(lk);
114
}
115
 
116
void
117
iunlock(Lock *lk)
118
{
119
	unlock(lk);
120
}