~kris/9p

9hist

ref: 2f9960b6a2a96ce115350b9b954cab1915edfd22 9hist/port/taslock.c -rw-r--r-- 1.8 KiB
2f9960b6 — David du Colombier Plan 9 from Bell Labs 1996-05-22 30 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"

void
lockloop(Lock *l, ulong pc)
{
	print("lock loop key 0x%lux pc 0x%lux held by pc 0x%lux proc %d\n",
		l->key, pc, l->pc, l->pid);
	dumpaproc(up);
}

#define LOCKLOOP 100000000	/* to detect a lock loop */
#define SPINLOOP 10000000	/* to keep tas's off the bus */

void
lock(Lock *l)
{
	int i, pri, spins;
	ulong pc, pid;

	pc = getcallerpc(l);
	if(up){
		pid = up->pid;
		pri = up->priority;
	} else {
		pid = 0;
		pri = 0;
	}

	/* quick try, it might work */
	if(tas(&l->key) == 0){
		l->pc = pc;
		l->pid = pid;
		l->pri = pri;
		return;
	}

	spins = 0;
	for(;;){
		i = 0;
		while(l->key)
			if(i++ > SPINLOOP){
				/* look for lock loops */
				if(spins++ > LOCKLOOP/SPINLOOP){
					spins = 0;
					lockloop(l, pc);
				}

				/* possible priority inversion, try switching priority */
				if(up && up->state == Running)
				if(getstatus()&IE) {
print("priority inversion\n");
					up->lockpri = l->pri;
					sched();
				}
			}

		if(tas(&l->key) == 0){
			l->pc = pc;
			l->pid = pid;
			l->pri = pri;
			up->lockpri = 0;
			return;
		}
	}
}

void
ilock(Lock *l)
{
	ulong x;
	ulong pc, pid;

	pc = getcallerpc(l);
	pid = up ? up->pid : 0;

	x = splhi();
	if(tas(&l->key) == 0){
		l->sr = x;
		l->pc = pc;
		l->pid = pid;
		l->pri = 0;
		return;
	}

	for(;;){
		while(l->key)
			;
		if(tas(&l->key) == 0){
			l->sr = x;
			l->pc = pc;
			l->pid = pid;
			l->pri = 0;
			return;
		}
	}
}

int
canlock(Lock *l)
{
	if(tas(&l->key))
		return 0;

	l->pc = getcallerpc(l);
	if(up){
		l->pid = up->pid;
		l->pri = up->priority;
	} else {
		l->pid = 0;
		l->pri = 0;
	}
	return 1;
}

void
unlock(Lock *l)
{
	l->key = 0;
	l->pc = 0;
	l->pri = 0;
}

void
iunlock(Lock *l)
{
	ulong sr;

	sr = l->sr;
	l->key = 0;
	l->pc = 0;
	l->pri = 0;
	splx(sr);
}