aboutsummaryrefslogtreecommitdiff
path: root/src/libthread/proctab.ch
blob: d51543f991482d954b167ec681c8ac0a24264a38 (plain)
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
/*
 * Proc structure hash table indexed by proctabid() (usually getpid()).
 * No lock is necessary for lookups (important when called from signal
 * handlers).
 * 
 * To be included from other files (e.g., Linux-clone.c).
 */

#define T ((void*)-1)

enum
{
	PTABHASH = 1031,
};

static Lock ptablock;
static Proc *proctab[PTABHASH];
static Proc *theproc;
static int multi;

void
_threadmultiproc(void)
{
	if(multi == 0){
		multi = 1;
		_threadsetproc(theproc);
	}
}

void
_threadsetproc(Proc *p)
{
	int i, h;
	Proc **t;

	if(!multi){
		theproc = p;
		return;
	}
	lock(&ptablock);
	p->procid = procid();
	h = p->procid%PTABHASH;
	for(i=0; i<PTABHASH; i++){
		t = &proctab[(h+i)%PTABHASH];
		if(*t==nil || *t==T){
			*t = p;
			break;
		}
	}
	unlock(&ptablock);
	if(i == PTABHASH)
		sysfatal("too many procs - proctab is full");
}

static Proc**
_threadfindproc(int id)
{
	int i, h;
	Proc **t;

	if(!multi)
		return &theproc;

	h = id%PTABHASH;
	for(i=0; i<PTABHASH; i++){
		t = &proctab[(h+i)%PTABHASH];
		if(*t != nil && *t != T && (*t)->procid == id){
			unlock(&ptablock);
			return t;
		}
	}
	return nil;
}

Proc*
_threadgetproc(void)
{
	Proc **t;

	t = _threadfindproc(procid());
	if(t == nil)
		return nil;
	return *t;
}

Proc*
_threaddelproc(void)
{
	Proc **t, *p;

	t = _threadfindproc(procid());
	if(t == nil)
		return nil;
	p = *t;
	*t = T;
	return p;
}