1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/mm.h>
23#include <linux/slab.h>
24#include <linux/init.h>
25#include <linux/bootmem.h>
26
27#define PIDHASH_SIZE 4096
28#define pid_hashfn(nr) ((nr >> 8) ^ nr) & (PIDHASH_SIZE - 1)
29static struct list_head pid_hash[PIDTYPE_MAX][PIDHASH_SIZE];
30
31int pid_max = PID_MAX_DEFAULT;
32int last_pid;
33
34#define RESERVED_PIDS 300
35
36#define PIDMAP_ENTRIES (PID_MAX_LIMIT/PAGE_SIZE/8)
37#define BITS_PER_PAGE (PAGE_SIZE*8)
38#define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1)
39
40
41
42
43
44
45
46typedef struct pidmap {
47 atomic_t nr_free;
48 void *page;
49} pidmap_t;
50
51static pidmap_t pidmap_array[PIDMAP_ENTRIES] =
52 { [ 0 ... PIDMAP_ENTRIES-1 ] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } };
53
54static pidmap_t *map_limit = pidmap_array + PIDMAP_ENTRIES;
55
56inline void free_pidmap(int pid)
57{
58 pidmap_t *map = pidmap_array + pid / BITS_PER_PAGE;
59 int offset = pid & BITS_PER_PAGE_MASK;
60
61 clear_bit(offset, map->page);
62 atomic_inc(&map->nr_free);
63}
64
65
66
67
68
69static inline pidmap_t *next_free_map(pidmap_t *map, int *max_steps)
70{
71 while (--*max_steps) {
72 if (++map == map_limit)
73 map = pidmap_array;
74 if (unlikely(!map->page)) {
75 unsigned long page = get_zeroed_page(GFP_KERNEL);
76
77
78
79
80 if (cmpxchg(&map->page, NULL, (void *) page))
81 free_page(page);
82 if (!map->page)
83 break;
84 }
85 if (atomic_read(&map->nr_free))
86 return map;
87 }
88 return NULL;
89}
90
91int alloc_pidmap(void)
92{
93 int pid, offset, max_steps = PIDMAP_ENTRIES + 1;
94 pidmap_t *map;
95
96 pid = last_pid + 1;
97 if (pid >= pid_max)
98 pid = RESERVED_PIDS;
99
100 offset = pid & BITS_PER_PAGE_MASK;
101 map = pidmap_array + pid / BITS_PER_PAGE;
102
103 if (likely(map->page && !test_and_set_bit(offset, map->page))) {
104
105
106
107
108
109return_pid:
110 atomic_dec(&map->nr_free);
111 last_pid = pid;
112 return pid;
113 }
114
115 if (!offset || !atomic_read(&map->nr_free)) {
116next_map:
117 map = next_free_map(map, &max_steps);
118 if (!map)
119 goto failure;
120 offset = 0;
121 }
122
123
124
125scan_more:
126 offset = find_next_zero_bit(map->page, BITS_PER_PAGE, offset);
127 if (offset == BITS_PER_PAGE)
128 goto next_map;
129 if (test_and_set_bit(offset, map->page))
130 goto scan_more;
131
132
133 pid = (map - pidmap_array) * BITS_PER_PAGE + offset;
134 goto return_pid;
135
136failure:
137 return -1;
138}
139
140inline struct pid *find_pid(enum pid_type type, int nr)
141{
142 struct list_head *elem, *bucket = &pid_hash[type][pid_hashfn(nr)];
143 struct pid *pid;
144
145 list_for_each_noprefetch(elem, bucket) {
146 pid = list_entry(elem, struct pid, hash_chain);
147 if (pid->nr == nr)
148 return pid;
149 }
150 return NULL;
151}
152
153int attach_pid(task_t *task, enum pid_type type, int nr)
154{
155 struct pid *pid = find_pid(type, nr);
156
157 if (pid)
158 atomic_inc(&pid->count);
159 else {
160 pid = &task->pids[type].pid;
161 pid->nr = nr;
162 atomic_set(&pid->count, 1);
163 INIT_LIST_HEAD(&pid->task_list);
164 pid->task = task;
165 get_task_struct(task);
166 list_add(&pid->hash_chain, &pid_hash[type][pid_hashfn(nr)]);
167 }
168 list_add(&task->pids[type].pid_chain, &pid->task_list);
169 task->pids[type].pidptr = pid;
170
171 return 0;
172}
173
174void detach_pid(task_t *task, enum pid_type type)
175{
176 struct pid_link *link = task->pids + type;
177 struct pid *pid = link->pidptr;
178 int nr;
179
180 list_del(&link->pid_chain);
181 if (!atomic_dec_and_test(&pid->count))
182 return;
183
184 nr = pid->nr;
185 list_del(&pid->hash_chain);
186 put_task_struct(pid->task);
187
188 for (type = 0; type < PIDTYPE_MAX; ++type)
189 if (find_pid(type, nr))
190 return;
191 free_pidmap(nr);
192}
193
194extern task_t *find_task_by_pid(int nr)
195{
196 struct pid *pid = find_pid(PIDTYPE_PID, nr);
197
198 if (!pid)
199 return NULL;
200 return pid_task(pid->task_list.next, PIDTYPE_PID);
201}
202
203void __init pidhash_init(void)
204{
205 int i, j;
206
207
208
209
210 pidmap_array->page = (void *)get_zeroed_page(GFP_KERNEL);
211 set_bit(0, pidmap_array->page);
212 atomic_dec(&pidmap_array->nr_free);
213
214 for (i = 0; i < PIDTYPE_MAX; i++) {
215 for (j = 0; j < PIDHASH_SIZE; j++)
216 INIT_LIST_HEAD(&pid_hash[i][j]);
217 attach_pid(current, i, 0);
218 }
219}
220