sys_lwp.c revision 1.14 1 /* $NetBSD: sys_lwp.c,v 1.14 2007/03/14 23:07:27 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Nathan J. Williams, and Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Lightweight process (LWP) system calls. See kern_lwp.c for a description
41 * of LWPs.
42 */
43
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.14 2007/03/14 23:07:27 yamt Exp $");
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/pool.h>
50 #include <sys/proc.h>
51 #include <sys/types.h>
52 #include <sys/syscallargs.h>
53 #include <sys/kauth.h>
54 #include <sys/kmem.h>
55 #include <sys/sleepq.h>
56
57 #include <uvm/uvm_extern.h>
58
59 #define LWP_UNPARK_MAX 1024
60
61 syncobj_t lwp_park_sobj = {
62 SOBJ_SLEEPQ_SORTED,
63 sleepq_unsleep,
64 sleepq_changepri,
65 sleepq_lendpri,
66 syncobj_noowner,
67 };
68
69 sleeptab_t lwp_park_tab;
70
71 #ifdef LWP_COUNTERS
72 struct evcnt lwp_ev_park_early = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
73 NULL, "_lwp_park", "unparked early");
74 struct evcnt lwp_ev_park_raced = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
75 NULL, "_lwp_park", "raced");
76 struct evcnt lwp_ev_park_slowpath = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
77 NULL, "_lwp_park", "slowpath");
78 struct evcnt lwp_ev_park_miss = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
79 NULL, "_lwp_park", "not parked");
80 struct evcnt lwp_ev_park_bcast = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
81 NULL, "_lwp_park", "broadcast unpark");
82 struct evcnt lwp_ev_park_targ = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
83 NULL, "_lwp_park", "targeted unpark");
84 struct evcnt lwp_ev_park = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
85 NULL, "_lwp_park", "parked");
86
87 #define LWP_COUNT(ev, val) (ev).ev_count += (val) /* XXXSMP */
88 #else
89 #define LWP_COUNT(ev, val) /* nothing */
90 #endif
91
92 void
93 lwp_sys_init(void)
94 {
95 sleeptab_init(&lwp_park_tab);
96 #ifdef LWP_COUNTERS
97 evcnt_attach_static(&lwp_ev_park_early);
98 evcnt_attach_static(&lwp_ev_park_slowpath);
99 evcnt_attach_static(&lwp_ev_park_raced);
100 evcnt_attach_static(&lwp_ev_park_miss);
101 evcnt_attach_static(&lwp_ev_park_bcast);
102 evcnt_attach_static(&lwp_ev_park_targ);
103 evcnt_attach_static(&lwp_ev_park);
104 #endif
105 }
106
107 /* ARGSUSED */
108 int
109 sys__lwp_create(struct lwp *l, void *v, register_t *retval)
110 {
111 struct sys__lwp_create_args /* {
112 syscallarg(const ucontext_t *) ucp;
113 syscallarg(u_long) flags;
114 syscallarg(lwpid_t *) new_lwp;
115 } */ *uap = v;
116 struct proc *p = l->l_proc;
117 struct lwp *l2;
118 vaddr_t uaddr;
119 bool inmem;
120 ucontext_t *newuc;
121 int error, lid;
122
123 newuc = pool_get(&lwp_uc_pool, PR_WAITOK);
124
125 error = copyin(SCARG(uap, ucp), newuc, p->p_emul->e_ucsize);
126 if (error) {
127 pool_put(&lwp_uc_pool, newuc);
128 return error;
129 }
130
131 /* XXX check against resource limits */
132
133 inmem = uvm_uarea_alloc(&uaddr);
134 if (__predict_false(uaddr == 0)) {
135 pool_put(&lwp_uc_pool, newuc);
136 return ENOMEM;
137 }
138
139 newlwp(l, p, uaddr, inmem,
140 SCARG(uap, flags) & LWP_DETACHED,
141 NULL, 0, p->p_emul->e_startlwp, newuc, &l2);
142
143 /*
144 * Set the new LWP running, unless the caller has requested that
145 * it be created in suspended state. If the process is stopping,
146 * then the LWP is created stopped.
147 */
148 mutex_enter(&p->p_smutex);
149 lwp_lock(l2);
150 lid = l2->l_lid;
151 if ((SCARG(uap, flags) & LWP_SUSPENDED) == 0 &&
152 (l->l_flag & (LW_WREBOOT | LW_WSUSPEND | LW_WEXIT)) == 0) {
153 if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0)
154 l2->l_stat = LSSTOP;
155 else {
156 KASSERT(lwp_locked(l2, &sched_mutex));
157 p->p_nrlwps++;
158 l2->l_stat = LSRUN;
159 setrunqueue(l2);
160 }
161 } else
162 l2->l_stat = LSSUSPENDED;
163 lwp_unlock(l2);
164 mutex_exit(&p->p_smutex);
165
166 error = copyout(&lid, SCARG(uap, new_lwp), sizeof(lid));
167 if (error)
168 return error;
169
170 return 0;
171 }
172
173 int
174 sys__lwp_exit(struct lwp *l, void *v, register_t *retval)
175 {
176
177 lwp_exit(l);
178 return 0;
179 }
180
181 int
182 sys__lwp_self(struct lwp *l, void *v, register_t *retval)
183 {
184
185 *retval = l->l_lid;
186 return 0;
187 }
188
189 int
190 sys__lwp_getprivate(struct lwp *l, void *v, register_t *retval)
191 {
192
193 *retval = (uintptr_t)l->l_private;
194 return 0;
195 }
196
197 int
198 sys__lwp_setprivate(struct lwp *l, void *v, register_t *retval)
199 {
200 struct sys__lwp_setprivate_args /* {
201 syscallarg(void *) ptr;
202 } */ *uap = v;
203
204 l->l_private = SCARG(uap, ptr);
205 return 0;
206 }
207
208 int
209 sys__lwp_suspend(struct lwp *l, void *v, register_t *retval)
210 {
211 struct sys__lwp_suspend_args /* {
212 syscallarg(lwpid_t) target;
213 } */ *uap = v;
214 struct proc *p = l->l_proc;
215 struct lwp *t;
216 int error;
217
218 mutex_enter(&p->p_smutex);
219 if ((t = lwp_find(p, SCARG(uap, target))) == NULL) {
220 mutex_exit(&p->p_smutex);
221 return ESRCH;
222 }
223
224 /*
225 * Check for deadlock, which is only possible when we're suspending
226 * ourself. XXX There is a short race here, as p_nrlwps is only
227 * incremented when an LWP suspends itself on the kernel/user
228 * boundary. It's still possible to kill -9 the process so we
229 * don't bother checking further.
230 */
231 lwp_lock(t);
232 if ((t == l && p->p_nrlwps == 1) ||
233 (l->l_flag & (LW_WCORE | LW_WEXIT)) != 0) {
234 lwp_unlock(t);
235 mutex_exit(&p->p_smutex);
236 return EDEADLK;
237 }
238
239 /*
240 * Suspend the LWP. XXX If it's on a different CPU, we should wait
241 * for it to be preempted, where it will put itself to sleep.
242 *
243 * Suspension of the current LWP will happen on return to userspace.
244 */
245 error = lwp_suspend(l, t);
246 mutex_exit(&p->p_smutex);
247
248 return error;
249 }
250
251 int
252 sys__lwp_continue(struct lwp *l, void *v, register_t *retval)
253 {
254 struct sys__lwp_continue_args /* {
255 syscallarg(lwpid_t) target;
256 } */ *uap = v;
257 int error;
258 struct proc *p = l->l_proc;
259 struct lwp *t;
260
261 error = 0;
262
263 mutex_enter(&p->p_smutex);
264 if ((t = lwp_find(p, SCARG(uap, target))) == NULL) {
265 mutex_exit(&p->p_smutex);
266 return ESRCH;
267 }
268
269 lwp_lock(t);
270 lwp_continue(t);
271 mutex_exit(&p->p_smutex);
272
273 return error;
274 }
275
276 int
277 sys__lwp_wakeup(struct lwp *l, void *v, register_t *retval)
278 {
279 struct sys__lwp_wakeup_args /* {
280 syscallarg(lwpid_t) target;
281 } */ *uap = v;
282 struct lwp *t;
283 struct proc *p;
284 int error;
285
286 p = l->l_proc;
287 mutex_enter(&p->p_smutex);
288
289 if ((t = lwp_find(p, SCARG(uap, target))) == NULL) {
290 mutex_exit(&p->p_smutex);
291 return ESRCH;
292 }
293
294 lwp_lock(t);
295 t->l_flag |= LW_CANCELLED;
296
297 if (t->l_stat != LSSLEEP) {
298 error = ENODEV;
299 goto bad;
300 }
301
302 if ((t->l_flag & LW_SINTR) == 0) {
303 error = EBUSY;
304 goto bad;
305 }
306
307 /* Wake it up. setrunnable() will release the LWP lock. */
308 setrunnable(t);
309 mutex_exit(&p->p_smutex);
310 return 0;
311
312 bad:
313 lwp_unlock(t);
314 mutex_exit(&p->p_smutex);
315 return error;
316 }
317
318 int
319 sys__lwp_wait(struct lwp *l, void *v, register_t *retval)
320 {
321 struct sys__lwp_wait_args /* {
322 syscallarg(lwpid_t) wait_for;
323 syscallarg(lwpid_t *) departed;
324 } */ *uap = v;
325 struct proc *p = l->l_proc;
326 int error;
327 lwpid_t dep;
328
329 mutex_enter(&p->p_smutex);
330 error = lwp_wait1(l, SCARG(uap, wait_for), &dep, 0);
331 mutex_exit(&p->p_smutex);
332
333 if (error)
334 return error;
335
336 if (SCARG(uap, departed)) {
337 error = copyout(&dep, SCARG(uap, departed), sizeof(dep));
338 if (error)
339 return error;
340 }
341
342 return 0;
343 }
344
345 /* ARGSUSED */
346 int
347 sys__lwp_kill(struct lwp *l, void *v, register_t *retval)
348 {
349 struct sys__lwp_kill_args /* {
350 syscallarg(lwpid_t) target;
351 syscallarg(int) signo;
352 } */ *uap = v;
353 struct proc *p = l->l_proc;
354 struct lwp *t;
355 ksiginfo_t ksi;
356 int signo = SCARG(uap, signo);
357 int error = 0;
358
359 if ((u_int)signo >= NSIG)
360 return EINVAL;
361
362 KSI_INIT(&ksi);
363 ksi.ksi_signo = signo;
364 ksi.ksi_code = SI_USER;
365 ksi.ksi_pid = p->p_pid;
366 ksi.ksi_uid = kauth_cred_geteuid(l->l_cred);
367 ksi.ksi_lid = SCARG(uap, target);
368
369 mutex_enter(&proclist_mutex);
370 mutex_enter(&p->p_smutex);
371 if ((t = lwp_find(p, ksi.ksi_lid)) == NULL)
372 error = ESRCH;
373 else if (signo != 0)
374 kpsignal2(p, &ksi);
375 mutex_exit(&p->p_smutex);
376 mutex_exit(&proclist_mutex);
377
378 return error;
379 }
380
381 int
382 sys__lwp_detach(struct lwp *l, void *v, register_t *retval)
383 {
384 struct sys__lwp_detach_args /* {
385 syscallarg(lwpid_t) target;
386 } */ *uap = v;
387 struct proc *p;
388 struct lwp *t;
389 lwpid_t target;
390 int error;
391
392 target = SCARG(uap, target);
393 p = l->l_proc;
394
395 mutex_enter(&p->p_smutex);
396
397 if (l->l_lid == target)
398 t = l;
399 else {
400 /*
401 * We can't use lwp_find() here because the target might
402 * be a zombie.
403 */
404 LIST_FOREACH(t, &p->p_lwps, l_sibling)
405 if (t->l_lid == target)
406 break;
407 }
408
409 /*
410 * If the LWP is already detached, there's nothing to do.
411 * If it's a zombie, we need to clean up after it. LSZOMB
412 * is visible with the proc mutex held.
413 *
414 * After we have detached or released the LWP, kick any
415 * other LWPs that may be sitting in _lwp_wait(), waiting
416 * for the target LWP to exit.
417 */
418 if (t != NULL && t->l_stat != LSIDL) {
419 if ((t->l_prflag & LPR_DETACHED) == 0) {
420 p->p_ndlwps++;
421 t->l_prflag |= LPR_DETACHED;
422 if (t->l_stat == LSZOMB) {
423 cv_broadcast(&p->p_lwpcv);
424 lwp_free(t, 0, 0); /* releases proc mutex */
425 return 0;
426 }
427 error = 0;
428 } else
429 error = EINVAL;
430 } else
431 error = ESRCH;
432
433 cv_broadcast(&p->p_lwpcv);
434 mutex_exit(&p->p_smutex);
435
436 return error;
437 }
438
439 static inline wchan_t
440 lwp_park_wchan(struct proc *p, const void *hint)
441 {
442 return (wchan_t)((uintptr_t)p ^ (uintptr_t)hint);
443 }
444
445 /*
446 * 'park' an LWP waiting on a user-level synchronisation object. The LWP
447 * will remain parked until another LWP in the same process calls in and
448 * requests that it be unparked.
449 */
450 int
451 sys__lwp_park(struct lwp *l, void *v, register_t *retval)
452 {
453 struct sys__lwp_park_args /* {
454 syscallarg(const struct timespec *) ts;
455 syscallarg(ucontext_t *) uc;
456 syscallarg(const void *) hint;
457 } */ *uap = v;
458 const struct timespec *tsp;
459 struct timespec ts, tsx;
460 struct timeval tv;
461 sleepq_t *sq;
462 wchan_t wchan;
463 int timo, error;
464
465 /* Fix up the given timeout value. */
466 if ((tsp = SCARG(uap, ts)) != NULL) {
467 if ((error = copyin(tsp, &ts, sizeof(ts))) != 0)
468 return error;
469 getnanotime(&tsx);
470 timespecsub(&ts, &tsx, &ts);
471 tv.tv_sec = ts.tv_sec;
472 tv.tv_usec = ts.tv_nsec / 1000;
473 if (tv.tv_sec < 0 || (tv.tv_sec == 0 && tv.tv_usec < 0))
474 return ETIMEDOUT;
475 if ((error = itimerfix(&tv)) != 0)
476 return error;
477 timo = tvtohz(&tv);
478 } else
479 timo = 0;
480
481 /* Find and lock the sleep queue. */
482 wchan = lwp_park_wchan(l->l_proc, SCARG(uap, hint));
483 sq = sleeptab_lookup(&lwp_park_tab, wchan);
484
485 /*
486 * Before going the full route and blocking, check to see if an
487 * unpark op is pending.
488 */
489 sleepq_lwp_lock(l);
490 if ((l->l_flag & (LW_CANCELLED | LW_UNPARKED)) != 0) {
491 l->l_flag &= ~(LW_CANCELLED | LW_UNPARKED);
492 sleepq_lwp_unlock(l);
493 sleepq_unlock(sq);
494 LWP_COUNT(lwp_ev_park_early, 1);
495 return EALREADY;
496 }
497 #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
498 lwp_unlock_to(l, sq->sq_mutex);
499 #endif
500
501 /*
502 * For now we ignore the ucontext argument. In the future, we may
503 * put our stack up to be recycled. If it's binned, a trampoline
504 * function could call sleepq_unblock() on our behalf.
505 */
506 LWP_COUNT(lwp_ev_park, 1);
507 KERNEL_UNLOCK_ALL(l, &l->l_biglocks); /* XXX for compat32 */
508 sleepq_block(sq, sched_kpri(l), wchan, "parked", timo, 1,
509 &lwp_park_sobj);
510 error = sleepq_unblock(timo, 1);
511 switch (error) {
512 case EWOULDBLOCK:
513 error = ETIMEDOUT;
514 break;
515 case ERESTART:
516 error = EINTR;
517 break;
518 default:
519 /* nothing */
520 break;
521 }
522 return error;
523 }
524
525 int
526 sys__lwp_unpark(struct lwp *l, void *v, register_t *retval)
527 {
528 struct sys__lwp_unpark_args /* {
529 syscallarg(lwpid_t) target;
530 syscallarg(const void *) hint;
531 } */ *uap = v;
532 struct proc *p;
533 struct lwp *t;
534 sleepq_t *sq;
535 lwpid_t target;
536 wchan_t wchan;
537 int swapin;
538
539 p = l->l_proc;
540 target = SCARG(uap, target);
541
542 /*
543 * Easy case: search for the LWP on the sleep queue. If
544 * it's parked, remove it from the queue and set running.
545 */
546 wchan = lwp_park_wchan(p, SCARG(uap, hint));
547 sq = sleeptab_lookup(&lwp_park_tab, wchan);
548
549 TAILQ_FOREACH(t, &sq->sq_queue, l_sleepchain)
550 if (t->l_proc == p && t->l_lid == target)
551 break;
552
553 if (t == NULL) {
554 /*
555 * The LWP hasn't parked yet. Take the hit
556 * and mark the operation as pending.
557 */
558 LWP_COUNT(lwp_ev_park_slowpath, 1);
559 sleepq_unlock(sq);
560 mutex_enter(&p->p_smutex);
561 if ((t = lwp_find(p, target)) == NULL) {
562 mutex_exit(&p->p_smutex);
563 return ESRCH;
564 }
565 lwp_lock(t);
566 mutex_exit(&p->p_smutex);
567
568 if (t->l_sleepq == sq) {
569 /*
570 * We have raced, and the LWP is now parked.
571 * Wake it in the usual way.
572 */
573 KASSERT(t->l_syncobj == &lwp_park_sobj);
574 KASSERT(lwp_locked(t, sq->sq_mutex));
575 LWP_COUNT(lwp_ev_park_raced, 1);
576 } else {
577 /*
578 * It may not have parked yet, or is parked
579 * on a different user sync object. The
580 * latter is an application error.
581 */
582 t->l_flag |= LW_UNPARKED;
583 lwp_unlock(t);
584 return 0;
585 }
586 }
587
588 swapin = sleepq_remove(sq, t);
589 LWP_COUNT(lwp_ev_park_targ, 1);
590 sleepq_unlock(sq);
591 if (swapin)
592 uvm_kick_scheduler();
593 return 0;
594 }
595
596 int
597 sys__lwp_unpark_all(struct lwp *l, void *v, register_t *retval)
598 {
599 struct sys__lwp_unpark_all_args /* {
600 syscallarg(const lwpid_t *) targets;
601 syscallarg(size_t) ntargets;
602 syscallarg(const void *) hint;
603 } */ *uap = v;
604 struct proc *p;
605 struct lwp *t;
606 sleepq_t *sq;
607 wchan_t wchan;
608 lwpid_t targets[32], *tp, *tpp, *tmax, target;
609 int swapin, error;
610 u_int ntargets, unparked;
611 size_t sz;
612
613 p = l->l_proc;
614 ntargets = SCARG(uap, ntargets);
615
616 if (SCARG(uap, targets) == NULL) {
617 /*
618 * Let the caller know how much we are willing to do, and
619 * let it unpark the LWPs in blocks.
620 */
621 *retval = LWP_UNPARK_MAX;
622 return 0;
623 }
624 if (ntargets > LWP_UNPARK_MAX || ntargets == 0)
625 return EINVAL;
626
627 /*
628 * Copy in the target array. If it's a small number of LWPs, then
629 * place the numbers on the stack.
630 */
631 sz = sizeof(target) * ntargets;
632 if (sz <= sizeof(targets))
633 tp = targets;
634 else {
635 KERNEL_LOCK(1, l); /* XXXSMP */
636 tp = kmem_alloc(sz, KM_SLEEP);
637 KERNEL_UNLOCK_ONE(l); /* XXXSMP */
638 if (tp == NULL)
639 return ENOMEM;
640 }
641 error = copyin(SCARG(uap, targets), tp, sz);
642 if (error != 0) {
643 if (tp != targets) {
644 KERNEL_LOCK(1, l); /* XXXSMP */
645 kmem_free(tp, sz);
646 KERNEL_UNLOCK_ONE(l); /* XXXSMP */
647 }
648 return error;
649 }
650
651 unparked = 0;
652 swapin = 0;
653 wchan = lwp_park_wchan(p, SCARG(uap, hint));
654 sq = sleeptab_lookup(&lwp_park_tab, wchan);
655
656 for (tmax = tp + ntargets, tpp = tp; tpp < tmax; tpp++) {
657 target = *tpp;
658
659 /*
660 * Easy case: search for the LWP on the sleep queue. If
661 * it's parked, remove it from the queue and set running.
662 */
663 TAILQ_FOREACH(t, &sq->sq_queue, l_sleepchain)
664 if (t->l_proc == p && t->l_lid == target)
665 break;
666
667 if (t != NULL) {
668 swapin |= sleepq_remove(sq, t);
669 unparked++;
670 continue;
671 }
672
673 /*
674 * The LWP hasn't parked yet. Take the hit and
675 * mark the operation as pending.
676 */
677 LWP_COUNT(lwp_ev_park_slowpath, 1);
678 sleepq_unlock(sq);
679 mutex_enter(&p->p_smutex);
680 if ((t = lwp_find(p, target)) == NULL) {
681 mutex_exit(&p->p_smutex);
682 sleepq_lock(sq);
683 continue;
684 }
685 lwp_lock(t);
686 mutex_exit(&p->p_smutex);
687
688 if (t->l_sleepq == sq) {
689 /*
690 * We have raced, and the LWP is now parked.
691 * Wake it in the usual way.
692 */
693 KASSERT(t->l_syncobj == &lwp_park_sobj);
694 KASSERT(lwp_locked(t, sq->sq_mutex));
695 LWP_COUNT(lwp_ev_park_raced, 1);
696 swapin |= sleepq_remove(sq, t);
697 unparked++;
698 } else {
699 /*
700 * It may not have parked yet, or is parked
701 * on a different user sync object. The
702 * latter is an application error.
703 */
704 t->l_flag |= LW_UNPARKED;
705 lwp_unlock(t);
706 sleepq_lock(sq);
707 }
708 }
709
710 sleepq_unlock(sq);
711 if (tp != targets) {
712 KERNEL_LOCK(1, l); /* XXXSMP */
713 kmem_free(tp, sz);
714 KERNEL_UNLOCK_ONE(l); /* XXXSMP */
715 }
716 if (swapin)
717 uvm_kick_scheduler();
718 LWP_COUNT(lwp_ev_park_bcast, unparked);
719 LWP_COUNT(lwp_ev_park_miss, (ntargets - unparked));
720 /* XXXAD return unparked; */
721 return 0;
722 }
723