This source file includes following definitions.
- tsleep
- sleep_setup
- sleep_finish
- sleep_setup_timeout
- sleep_finish_timeout
- sleep_setup_signal
- sleep_finish_signal
- endtsleep
- unsleep
- wakeup_n
- wakeup
- sys_sched_yield
- sys_thrsleep
- sys_thrwakeup
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 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/kernel.h>
44 #include <sys/buf.h>
45 #include <sys/signalvar.h>
46 #include <sys/resourcevar.h>
47 #include <uvm/uvm_extern.h>
48 #include <sys/sched.h>
49 #include <sys/timeout.h>
50 #include <sys/mount.h>
51 #include <sys/syscallargs.h>
52 #include <sys/pool.h>
53
54 #include <machine/spinlock.h>
55
56 #ifdef KTRACE
57 #include <sys/ktrace.h>
58 #endif
59
60 void updatepri(struct proc *);
61 void endtsleep(void *);
62
63
64
65
66
67
68 #define TABLESIZE 128
69 #define LOOKUP(x) (((long)(x) >> 8) & (TABLESIZE - 1))
70 struct slpque {
71 struct proc *sq_head;
72 struct proc **sq_tailp;
73 } slpque[TABLESIZE];
74
75
76
77
78
79
80
81
82
83
84 int safepri;
85
86
87
88
89
90
91
92
93
94
95
96
97 int
98 tsleep(void *ident, int priority, const char *wmesg, int timo)
99 {
100 struct sleep_state sls;
101 int error, error1;
102
103 if (cold || panicstr) {
104 int s;
105
106
107
108
109
110
111 s = splhigh();
112 splx(safepri);
113 splx(s);
114 return (0);
115 }
116
117 sleep_setup(&sls, ident, priority, wmesg);
118 sleep_setup_timeout(&sls, timo);
119 sleep_setup_signal(&sls, priority);
120
121 sleep_finish(&sls, 1);
122 error1 = sleep_finish_timeout(&sls);
123 error = sleep_finish_signal(&sls);
124
125
126 if (error == 0 && error1 != 0)
127 error = error1;
128
129 return (error);
130 }
131
132 void
133 sleep_setup(struct sleep_state *sls, void *ident, int prio, const char *wmesg)
134 {
135 struct proc *p = curproc;
136 struct slpque *qp;
137
138 #ifdef DIAGNOSTIC
139 if (ident == NULL)
140 panic("tsleep: no ident");
141 if (p->p_stat != SONPROC)
142 panic("tsleep: not SONPROC");
143 if (p->p_back != NULL)
144 panic("tsleep: p_back not NULL");
145 #endif
146
147 #ifdef KTRACE
148 if (KTRPOINT(p, KTR_CSW))
149 ktrcsw(p, 1, 0);
150 #endif
151
152 sls->sls_catch = 0;
153 sls->sls_do_sleep = 1;
154 sls->sls_sig = 1;
155
156 SCHED_LOCK(sls->sls_s);
157
158 p->p_wchan = ident;
159 p->p_wmesg = wmesg;
160 p->p_slptime = 0;
161 p->p_priority = prio & PRIMASK;
162 qp = &slpque[LOOKUP(ident)];
163 if (qp->sq_head == 0)
164 qp->sq_head = p;
165 else
166 *qp->sq_tailp = p;
167 *(qp->sq_tailp = &p->p_forw) = NULL;
168 }
169
170 void
171 sleep_finish(struct sleep_state *sls, int do_sleep)
172 {
173 struct proc *p = curproc;
174
175 if (sls->sls_do_sleep && do_sleep) {
176 p->p_stat = SSLEEP;
177 p->p_stats->p_ru.ru_nvcsw++;
178 SCHED_ASSERT_LOCKED();
179 mi_switch();
180 } else if (!do_sleep) {
181 unsleep(p);
182 #ifdef DIAGNOSTIC
183 if (p->p_stat != SONPROC)
184 panic("sleep_finish !SONPROC");
185 #endif
186 }
187
188 p->p_cpu->ci_schedstate.spc_curpriority = p->p_usrpri;
189 SCHED_UNLOCK(sls->sls_s);
190
191
192
193
194
195 atomic_clearbits_int(&p->p_flag, P_SINTR);
196
197 #ifdef KTRACE
198 if (KTRPOINT(p, KTR_CSW))
199 ktrcsw(p, 0, 0);
200 #endif
201 }
202
203 void
204 sleep_setup_timeout(struct sleep_state *sls, int timo)
205 {
206 if (timo)
207 timeout_add(&curproc->p_sleep_to, timo);
208 }
209
210 int
211 sleep_finish_timeout(struct sleep_state *sls)
212 {
213 struct proc *p = curproc;
214
215 if (p->p_flag & P_TIMEOUT) {
216 atomic_clearbits_int(&p->p_flag, P_TIMEOUT);
217 return (EWOULDBLOCK);
218 } else if (timeout_pending(&p->p_sleep_to)) {
219 timeout_del(&p->p_sleep_to);
220 }
221
222 return (0);
223 }
224
225 void
226 sleep_setup_signal(struct sleep_state *sls, int prio)
227 {
228 struct proc *p = curproc;
229
230 if ((sls->sls_catch = (prio & PCATCH)) == 0)
231 return;
232
233
234
235
236
237
238
239
240
241
242 atomic_setbits_int(&p->p_flag, P_SINTR);
243 if ((sls->sls_sig = CURSIG(p)) != 0) {
244 if (p->p_wchan)
245 unsleep(p);
246 p->p_stat = SONPROC;
247 sls->sls_do_sleep = 0;
248 } else if (p->p_wchan == 0) {
249 sls->sls_catch = 0;
250 sls->sls_do_sleep = 0;
251 }
252 }
253
254 int
255 sleep_finish_signal(struct sleep_state *sls)
256 {
257 struct proc *p = curproc;
258
259 if (sls->sls_catch != 0) {
260 if (sls->sls_sig != 0 || (sls->sls_sig = CURSIG(p)) != 0) {
261 if (p->p_sigacts->ps_sigintr & sigmask(sls->sls_sig))
262 return (EINTR);
263 return (ERESTART);
264 }
265 }
266
267 return (0);
268 }
269
270
271
272
273
274
275
276 void
277 endtsleep(void *arg)
278 {
279 struct proc *p = arg;
280 int s;
281
282 SCHED_LOCK(s);
283 if (p->p_wchan) {
284 if (p->p_stat == SSLEEP)
285 setrunnable(p);
286 else
287 unsleep(p);
288 atomic_setbits_int(&p->p_flag, P_TIMEOUT);
289 }
290 SCHED_UNLOCK(s);
291 }
292
293
294
295
296 void
297 unsleep(struct proc *p)
298 {
299 struct slpque *qp;
300 struct proc **hp;
301
302 if (p->p_wchan) {
303 hp = &(qp = &slpque[LOOKUP(p->p_wchan)])->sq_head;
304 while (*hp != p)
305 hp = &(*hp)->p_forw;
306 *hp = p->p_forw;
307 if (qp->sq_tailp == &p->p_forw)
308 qp->sq_tailp = hp;
309 p->p_wchan = 0;
310 }
311 }
312
313
314
315
316 void
317 wakeup_n(void *ident, int n)
318 {
319 struct slpque *qp;
320 struct proc *p, **q;
321 int s;
322
323 SCHED_LOCK(s);
324 qp = &slpque[LOOKUP(ident)];
325 restart:
326 for (q = &qp->sq_head; (p = *q) != NULL; ) {
327 #ifdef DIAGNOSTIC
328 if (p->p_back)
329 panic("wakeup: p_back not NULL");
330 if (p->p_stat != SSLEEP && p->p_stat != SSTOP)
331 panic("wakeup: p_stat is %d", (int)p->p_stat);
332 #endif
333 if (p->p_wchan == ident) {
334 --n;
335 p->p_wchan = 0;
336 *q = p->p_forw;
337 if (qp->sq_tailp == &p->p_forw)
338 qp->sq_tailp = q;
339 if (p->p_stat == SSLEEP) {
340
341 if (p->p_slptime > 1)
342 updatepri(p);
343 p->p_slptime = 0;
344 p->p_stat = SRUN;
345
346
347
348
349
350
351
352
353
354
355 setrunqueue(p);
356 KASSERT(p->p_cpu != NULL);
357 need_resched(p->p_cpu);
358
359
360 if (n != 0)
361 goto restart;
362 else
363 break;
364 }
365 } else
366 q = &p->p_forw;
367 }
368 SCHED_UNLOCK(s);
369 }
370
371
372
373
374 void
375 wakeup(void *chan)
376 {
377 wakeup_n(chan, -1);
378 }
379
380 int
381 sys_sched_yield(struct proc *p, void *v, register_t *retval)
382 {
383 yield();
384 return (0);
385 }
386
387 #ifdef RTHREADS
388
389 int
390 sys_thrsleep(struct proc *p, void *v, register_t *revtal)
391 {
392 struct sys_thrsleep_args *uap = v;
393 long ident = (long)SCARG(uap, ident);
394 int timo = SCARG(uap, timeout);
395 _spinlock_lock_t *lock = SCARG(uap, lock);
396 _spinlock_lock_t unlocked = _SPINLOCK_UNLOCKED;
397 int error;
398
399 p->p_thrslpid = ident;
400
401 if (lock)
402 copyout(&unlocked, lock, sizeof(unlocked));
403 if (hz > 1000)
404 timo = timo * (hz / 1000);
405 else
406 timo = timo / (1000 / hz);
407 if (timo < 0)
408 timo = 0;
409 error = tsleep(&p->p_thrslpid, PUSER | PCATCH, "thrsleep", timo);
410
411 if (error == ERESTART)
412 error = EINTR;
413
414 return (error);
415
416 }
417
418 int
419 sys_thrwakeup(struct proc *p, void *v, register_t *retval)
420 {
421 struct sys_thrwakeup_args *uap = v;
422 long ident = (long)SCARG(uap, ident);
423 int n = SCARG(uap, n);
424 struct proc *q;
425 int found = 0;
426
427 TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
428 if (q->p_thrslpid == ident) {
429 wakeup(&q->p_thrslpid);
430 q->p_thrslpid = 0;
431 if (++found == n)
432 return (0);
433 }
434 }
435 if (!found)
436 return (ESRCH);
437
438 return (0);
439 }
440 #endif