Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 1
#define _LOCK_EXTENSION
2
#include <stdlib.h>
3
#include <string.h>
4
#include "../plan9/sys9.h"
5
#include <lock.h>
6
 
7
enum
8
{
9
	Pagesize	= 4096,
10
	Semperpg	= Pagesize/(16*sizeof(unsigned int)),
11
	Lockaddr	= 0x60000000,
12
 
13
	POWER		= 0x320,
14
	MAGNUM		= 0x330,
15
	MAGNUMII	= 0x340,
16
	R4K		= 0x500,
17
};
18
 
19
static	int arch;
20
extern	int C_3ktas(int*);
21
extern	int C_4ktas(int*);
22
extern	int C_fcr0(void);
23
 
24
static void
25
lockinit(void)
26
{
27
	int n;
28
 
29
	if(arch != 0)
30
		return;	/* allow multiple calls */
31
	arch = C_fcr0();
32
	switch(arch) {
33
	case POWER:
34
		n = _SEGATTACH(0,  "lock", (void*)Lockaddr, Pagesize);
35
		if(n < 0) {
36
			arch = MAGNUM;
37
			break;
38
		}
39
		memset((void*)Lockaddr, 0, Pagesize);
40
		break;
41
	case MAGNUM:
42
	case MAGNUMII:
43
	case R4K:
44
		break;
45
	default:
46
		arch = R4K;
47
		break;
48
	}
49
 
50
}
51
 
52
void
53
lock(Lock *lk)
54
{
55
	int *hwsem;
56
	int hash;
57
 
58
retry:
59
	switch(arch) {
60
	case 0:
61
		lockinit();
62
		goto retry;
63
	case MAGNUM:
64
	case MAGNUMII:
65
		while(C_3ktas(&lk->val))
66
			_SLEEP(0);
67
		return;
68
	case R4K:
69
		for(;;){
70
			while(lk->val)
71
				;
72
			if(C_4ktas(&lk->val) == 0)
73
				return;
74
		}
75
		break;
76
	case POWER:
77
		/* Use low order lock bits to generate hash */
78
		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
79
		hwsem = (int*)Lockaddr+hash;
80
 
81
		for(;;) {
82
			if((*hwsem & 1) == 0) {
83
				if(lk->val)
84
					*hwsem = 0;
85
				else {
86
					lk->val = 1;
87
					*hwsem = 0;
88
					return;
89
				}
90
			}
91
			while(lk->val)
92
				;
93
		}
94
	}	
95
}
96
 
97
int
98
canlock(Lock *lk)
99
{
100
	int *hwsem;
101
	int hash;
102
 
103
retry:
104
	switch(arch) {
105
	case 0:
106
		lockinit();
107
		goto retry;
108
	case MAGNUM:
109
	case MAGNUMII:
110
		if(C_3ktas(&lk->val))
111
			return 0;
112
		return 1;
113
	case R4K:
114
		if(C_4ktas(&lk->val))
115
			return 0;
116
		return 1;
117
	case POWER:
118
		/* Use low order lock bits to generate hash */
119
		hash = ((int)lk/sizeof(int)) & (Semperpg-1);
120
		hwsem = (int*)Lockaddr+hash;
121
 
122
		if((*hwsem & 1) == 0) {
123
			if(lk->val)
124
				*hwsem = 0;
125
			else {
126
				lk->val = 1;
127
				*hwsem = 0;
128
				return 1;
129
			}
130
		}
131
		return 0;
132
	default:
133
		return 0;
134
	}	
135
}
136
 
137
void
138
unlock(Lock *lk)
139
{
140
	lk->val = 0;
141
}
142
 
143
int
144
tas(int *p)
145
{
146
	int *hwsem;
147
	int hash;
148
 
149
retry:
150
	switch(arch) {
151
	case 0:
152
		lockinit();
153
		goto retry;
154
	case MAGNUM:
155
	case MAGNUMII:
156
		return C_3ktas(p);
157
	case R4K:
158
		return C_4ktas(p);
159
	case POWER:
160
		/* Use low order lock bits to generate hash */
161
		hash = ((int)p/sizeof(int)) & (Semperpg-1);
162
		hwsem = (int*)Lockaddr+hash;
163
 
164
		if((*hwsem & 1) == 0) {
165
			if(*p)
166
				*hwsem = 0;
167
			else {
168
				*p = 1;
169
				*hwsem = 0;
170
				return 0;
171
			}
172
		}
173
		return 1;
174
	default:
175
		return 0;
176
	}	
177
}