xref: /illumos-gate/usr/src/uts/common/syscall/lwpsys.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/sysmacros.h>
33 #include <sys/systm.h>
34 #include <sys/prsystm.h>
35 #include <sys/cred.h>
36 #include <sys/errno.h>
37 #include <sys/proc.h>
38 #include <sys/signal.h>
39 #include <sys/kmem.h>
40 #include <sys/unistd.h>
41 #include <sys/cmn_err.h>
42 #include <sys/schedctl.h>
43 #include <sys/debug.h>
44 #include <sys/contract/process_impl.h>
45 
46 kthread_t *
47 idtot(proc_t *p, id_t lwpid)
48 {
49 	lwpdir_t *ldp;
50 
51 	if ((ldp = lwp_hash_lookup(p, lwpid)) != NULL)
52 		return (ldp->ld_entry->le_thread);
53 	return (NULL);
54 }
55 
56 /*
57  * Stop an lwp of the current process
58  */
59 int
60 syslwp_suspend(id_t lwpid)
61 {
62 	kthread_t *t;
63 	int error;
64 	proc_t *p = ttoproc(curthread);
65 
66 	mutex_enter(&p->p_lock);
67 	if ((t = idtot(p, lwpid)) == NULL)
68 		error = ESRCH;
69 	else
70 		error = lwp_suspend(t);
71 	mutex_exit(&p->p_lock);
72 	if (error)
73 		return (set_errno(error));
74 	return (0);
75 }
76 
77 int
78 syslwp_continue(id_t lwpid)
79 {
80 	kthread_t *t;
81 	proc_t *p = ttoproc(curthread);
82 
83 	mutex_enter(&p->p_lock);
84 	if ((t = idtot(p, lwpid)) == NULL) {
85 		mutex_exit(&p->p_lock);
86 		return (set_errno(ESRCH));
87 	}
88 	lwp_continue(t);
89 	mutex_exit(&p->p_lock);
90 	return (0);
91 }
92 
93 int
94 lwp_kill(id_t lwpid, int sig)
95 {
96 	sigqueue_t *sqp;
97 	kthread_t *t;
98 	proc_t *p = ttoproc(curthread);
99 
100 	if (sig < 0 || sig >= NSIG)
101 		return (set_errno(EINVAL));
102 	if (sig != 0)
103 		sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
104 	mutex_enter(&p->p_lock);
105 	if ((t = idtot(p, lwpid)) == NULL) {
106 		mutex_exit(&p->p_lock);
107 		if (sig != 0)
108 			kmem_free(sqp, sizeof (sigqueue_t));
109 		return (set_errno(ESRCH));
110 	}
111 	if (sig == 0) {
112 		mutex_exit(&p->p_lock);
113 		return (0);
114 	}
115 	sqp->sq_info.si_signo = sig;
116 	sqp->sq_info.si_code = SI_LWP;
117 	sqp->sq_info.si_pid = p->p_pid;
118 	sqp->sq_info.si_ctid = PRCTID(p);
119 	sqp->sq_info.si_zoneid = getzoneid();
120 	sqp->sq_info.si_uid = crgetruid(CRED());
121 	sigaddqa(p, t, sqp);
122 	mutex_exit(&p->p_lock);
123 	return (0);
124 }
125 
126 /*
127  * This is the specification of lwp_wait() from the _lwp_wait(2) manual page:
128  *
129  * The lwp_wait() function blocks the current lwp until the lwp specified
130  * by 'lwpid' terminates.  If the specified lwp terminated prior to the call
131  * to lwp_wait(), then lwp_wait() returns immediately.  If 'lwpid' is zero,
132  * then lwp_wait() waits for any undetached lwp in the current process.
133  * If 'lwpid' is not zero, then it must specify an undetached lwp in the
134  * current process.  If 'departed' is not NULL, then it points to a location
135  * where the id of the exited lwp is stored.
136  *
137  * When an lwp exits and there are one or more lwps in the process waiting
138  * for this specific lwp to exit, then one of the waiting lwps is unblocked
139  * and it returns from lwp_wait() successfully.  Any other lwps waiting for
140  * this same lwp to exit are also unblocked, however, they return from
141  * lwp_wait() with the error ESRCH.  If there are no lwps in the process
142  * waiting for this specific lwp to exit but there are one or more lwps
143  * waiting for any lwp to exit, then one of the waiting lwps is unblocked
144  * and it returns from lwp_wait() successfully.
145  *
146  * If an lwp is waiting for any lwp to exit, it blocks until an undetached
147  * lwp for which no other lwp is waiting terminates, at which time it returns
148  * successfully, or until all other lwps in the process are either daemon
149  * lwps or lwps waiting in lwp_wait(), in which case it returns EDEADLK.
150  */
151 int
152 lwp_wait(id_t lwpid, id_t *departed)
153 {
154 	proc_t *p = ttoproc(curthread);
155 	int error = 0;
156 	int daemon = (curthread->t_proc_flag & TP_DAEMON)? 1 : 0;
157 	lwpent_t *target_lep;
158 	lwpdir_t *ldp;
159 	lwpent_t *lep;
160 
161 	/*
162 	 * lwp_wait() is not supported for the /proc agent lwp.
163 	 */
164 	if (curthread == p->p_agenttp)
165 		return (set_errno(ENOTSUP));
166 
167 	mutex_enter(&p->p_lock);
168 	prbarrier(p);
169 
170 	curthread->t_waitfor = lwpid;
171 	p->p_lwpwait++;
172 	p->p_lwpdwait += daemon;
173 
174 	if (lwpid != 0) {
175 		if ((ldp = lwp_hash_lookup(p, lwpid)) == NULL)
176 			target_lep = NULL;
177 		else {
178 			target_lep = ldp->ld_entry;
179 			target_lep->le_waiters++;
180 			target_lep->le_dwaiters += daemon;
181 		}
182 	}
183 
184 	while (error == 0) {
185 		kthread_t *t;
186 		id_t tid;
187 		int i;
188 
189 		if (lwpid != 0) {
190 			/*
191 			 * Look for a specific zombie lwp.
192 			 */
193 			if (target_lep == NULL)
194 				error = ESRCH;
195 			else if ((t = target_lep->le_thread) != NULL) {
196 				if (!(t->t_proc_flag & TP_TWAIT))
197 					error = EINVAL;
198 			} else {
199 				/*
200 				 * We found the zombie we are waiting for.
201 				 */
202 				ASSERT(p->p_zombcnt > 0);
203 				p->p_zombcnt--;
204 				p->p_lwpwait--;
205 				p->p_lwpdwait -= daemon;
206 				curthread->t_waitfor = -1;
207 				lwp_hash_out(p, lwpid);
208 				mutex_exit(&p->p_lock);
209 				if (departed != NULL &&
210 				    copyout(&lwpid, departed, sizeof (id_t)))
211 					return (set_errno(EFAULT));
212 				return (0);
213 			}
214 		} else {
215 			/*
216 			 * Look for any zombie lwp.
217 			 */
218 			int some_non_daemon_will_return = 0;
219 
220 			/* for each entry in the lwp directory... */
221 			ldp = p->p_lwpdir;
222 			for (i = 0; i < p->p_lwpdir_sz; i++, ldp++) {
223 
224 				if ((lep = ldp->ld_entry) == NULL ||
225 				    lep->le_thread != NULL)
226 					continue;
227 
228 				/*
229 				 * We found a zombie lwp.  If there is some
230 				 * other thread waiting specifically for the
231 				 * zombie we just found, then defer to the other
232 				 * waiting thread and continue searching for
233 				 * another zombie.  Also check to see if there
234 				 * is some non-daemon thread sleeping here in
235 				 * lwp_wait() that will succeed and return when
236 				 * we drop p->p_lock.  This is tested below.
237 				 */
238 				tid = lep->le_lwpid;
239 				if (lep->le_waiters != 0) {
240 					if (lep->le_waiters - lep->le_dwaiters)
241 						some_non_daemon_will_return = 1;
242 					continue;
243 				}
244 
245 				/*
246 				 * We found a zombie that no one else
247 				 * is specifically waiting for.
248 				 */
249 				ASSERT(p->p_zombcnt > 0);
250 				p->p_zombcnt--;
251 				p->p_lwpwait--;
252 				p->p_lwpdwait -= daemon;
253 				curthread->t_waitfor = -1;
254 				lwp_hash_out(p, tid);
255 				mutex_exit(&p->p_lock);
256 				if (departed != NULL &&
257 				    copyout(&tid, departed, sizeof (id_t)))
258 					return (set_errno(EFAULT));
259 				return (0);
260 			}
261 
262 			/*
263 			 * We are waiting for anyone.  If all non-daemon lwps
264 			 * are waiting here, and if we determined above that
265 			 * no non-daemon lwp will return, we have deadlock.
266 			 */
267 			if (!some_non_daemon_will_return &&
268 			    p->p_lwpcnt == p->p_lwpdaemon +
269 			    (p->p_lwpwait - p->p_lwpdwait))
270 				error = EDEADLK;
271 		}
272 
273 		if (error == 0 && lwpid != 0) {
274 			/*
275 			 * We are waiting for a specific non-zombie lwp.
276 			 * Fail if there is a deadlock loop.
277 			 */
278 			for (;;) {
279 				if (t == curthread) {
280 					error = EDEADLK;
281 					break;
282 				}
283 				/* who is he waiting for? */
284 				if ((tid = t->t_waitfor) == -1)
285 					break;
286 				if (tid == 0) {
287 					/*
288 					 * The lwp we are waiting for is
289 					 * waiting for anyone (transitively).
290 					 * If there are no zombies right now
291 					 * and if we would have deadlock due
292 					 * to all non-daemon lwps waiting here,
293 					 * wake up the lwp that is waiting for
294 					 * anyone so it can return EDEADLK.
295 					 */
296 					if (p->p_zombcnt == 0 &&
297 					    p->p_lwpcnt == p->p_lwpdaemon +
298 					    p->p_lwpwait - p->p_lwpdwait)
299 						cv_broadcast(&p->p_lwpexit);
300 					break;
301 				}
302 				if ((ldp = lwp_hash_lookup(p, tid)) == NULL ||
303 				    (t = ldp->ld_entry->le_thread) == NULL)
304 					break;
305 			}
306 		}
307 
308 		if (error)
309 			break;
310 
311 		/*
312 		 * Wait for some lwp to terminate.
313 		 */
314 		if (!cv_wait_sig(&p->p_lwpexit, &p->p_lock))
315 			error = EINTR;
316 		prbarrier(p);
317 
318 		if (lwpid != 0) {
319 			if ((ldp = lwp_hash_lookup(p, lwpid)) == NULL)
320 				target_lep = NULL;
321 			else
322 				target_lep = ldp->ld_entry;
323 		}
324 	}
325 
326 	if (lwpid != 0 && target_lep != NULL) {
327 		target_lep->le_waiters--;
328 		target_lep->le_dwaiters -= daemon;
329 	}
330 	p->p_lwpwait--;
331 	p->p_lwpdwait -= daemon;
332 	curthread->t_waitfor = -1;
333 	mutex_exit(&p->p_lock);
334 	return (set_errno(error));
335 }
336 
337 int
338 lwp_detach(id_t lwpid)
339 {
340 	kthread_t *t;
341 	proc_t *p = ttoproc(curthread);
342 	lwpdir_t *ldp;
343 	int error = 0;
344 
345 	mutex_enter(&p->p_lock);
346 	prbarrier(p);
347 	if ((ldp = lwp_hash_lookup(p, lwpid)) == NULL)
348 		error = ESRCH;
349 	else if ((t = ldp->ld_entry->le_thread) != NULL) {
350 		if (!(t->t_proc_flag & TP_TWAIT))
351 			error = EINVAL;
352 		else {
353 			t->t_proc_flag &= ~TP_TWAIT;
354 			cv_broadcast(&p->p_lwpexit);
355 		}
356 	} else {
357 		ASSERT(p->p_zombcnt > 0);
358 		p->p_zombcnt--;
359 		lwp_hash_out(p, lwpid);
360 	}
361 	mutex_exit(&p->p_lock);
362 
363 	if (error)
364 		return (set_errno(error));
365 	return (0);
366 }
367 
368 /*
369  * Unpark the specified lwp.
370  */
371 static int
372 lwp_unpark(id_t lwpid)
373 {
374 	proc_t *p = ttoproc(curthread);
375 	kthread_t *t;
376 	int error = 0;
377 
378 	mutex_enter(&p->p_lock);
379 	if ((t = idtot(p, lwpid)) == NULL)
380 		error = ESRCH;
381 	else {
382 		mutex_enter(&t->t_delay_lock);
383 		t->t_unpark = 1;
384 		cv_signal(&t->t_delay_cv);
385 		mutex_exit(&t->t_delay_lock);
386 	}
387 	mutex_exit(&p->p_lock);
388 	return (error);
389 }
390 
391 /*
392  * Cancel a previous unpark for the specified lwp.
393  *
394  * This interface exists ONLY to support older versions of libthread, which
395  * called lwp_unpark(self) to force calls to lwp_park(self) to return
396  * immediately.  These older libthreads required a mechanism to cancel the
397  * lwp_unpark(self).
398  *
399  * libc does not call this interface.  Instead, the sc_park flag in the
400  * schedctl page is cleared to force calls to lwp_park() to return
401  * immediately.
402  */
403 static int
404 lwp_unpark_cancel(id_t lwpid)
405 {
406 	proc_t *p = ttoproc(curthread);
407 	kthread_t *t;
408 	int error = 0;
409 
410 	mutex_enter(&p->p_lock);
411 	if ((t = idtot(p, lwpid)) == NULL) {
412 		error = ESRCH;
413 	} else {
414 		mutex_enter(&t->t_delay_lock);
415 		t->t_unpark = 0;
416 		mutex_exit(&t->t_delay_lock);
417 	}
418 	mutex_exit(&p->p_lock);
419 	return (error);
420 }
421 
422 /*
423  * Sleep until we are set running by lwp_unpark() or until we are
424  * interrupted by a signal or until we exhaust our timeout.
425  * timeoutp is an in/out parameter.  On entry, it contains the relative
426  * time until timeout.  On exit, we copyout the residual time left to it.
427  */
428 static int
429 lwp_park(timespec_t *timeoutp, id_t lwpid)
430 {
431 	timespec_t rqtime;
432 	timespec_t rmtime;
433 	timespec_t now;
434 	timespec_t *rqtp = NULL;
435 	kthread_t *t = curthread;
436 	int timecheck = 0;
437 	int error = 0;
438 	model_t datamodel = ttoproc(t)->p_model;
439 
440 	if (lwpid != 0)		/* unpark the other lwp, if any */
441 		(void) lwp_unpark(lwpid);
442 
443 	if (timeoutp) {
444 		timecheck = timechanged;
445 		gethrestime(&now);
446 		if (datamodel == DATAMODEL_NATIVE) {
447 			if (copyin(timeoutp, &rqtime, sizeof (timespec_t))) {
448 				error = EFAULT;
449 				goto out;
450 			}
451 		} else {
452 			timespec32_t timeout32;
453 
454 			if (copyin(timeoutp, &timeout32, sizeof (timeout32))) {
455 				error = EFAULT;
456 				goto out;
457 			}
458 			TIMESPEC32_TO_TIMESPEC(&rqtime, &timeout32)
459 		}
460 
461 		if (itimerspecfix(&rqtime)) {
462 			error = EINVAL;
463 			goto out;
464 		}
465 		/*
466 		 * Convert the timespec value into absolute time.
467 		 */
468 		timespecadd(&rqtime, &now);
469 		rqtp = &rqtime;
470 	}
471 
472 	(void) new_mstate(t, LMS_USER_LOCK);
473 
474 	mutex_enter(&t->t_delay_lock);
475 	if (!schedctl_is_park())
476 		error = EINTR;
477 	while (error == 0 && t->t_unpark == 0) {
478 		switch (cv_waituntil_sig(&t->t_delay_cv,
479 		    &t->t_delay_lock, rqtp, timecheck)) {
480 		case 0:
481 			error = EINTR;
482 			break;
483 		case -1:
484 			error = ETIME;
485 			break;
486 		}
487 	}
488 	t->t_unpark = 0;
489 	mutex_exit(&t->t_delay_lock);
490 
491 	if (timeoutp != NULL) {
492 		rmtime.tv_sec = rmtime.tv_nsec = 0;
493 		if (error != ETIME) {
494 			gethrestime(&now);
495 			if ((now.tv_sec < rqtime.tv_sec) ||
496 			    ((now.tv_sec == rqtime.tv_sec) &&
497 			    (now.tv_nsec < rqtime.tv_nsec))) {
498 				rmtime = rqtime;
499 				timespecsub(&rmtime, &now);
500 			}
501 		}
502 		if (datamodel == DATAMODEL_NATIVE) {
503 			if (copyout(&rmtime, timeoutp, sizeof (rmtime)))
504 				error = EFAULT;
505 		} else {
506 			timespec32_t rmtime32;
507 
508 			TIMESPEC_TO_TIMESPEC32(&rmtime32, &rmtime);
509 			if (copyout(&rmtime32, timeoutp, sizeof (rmtime32)))
510 				error = EFAULT;
511 		}
512 	}
513 out:
514 	schedctl_unpark();
515 	if (t->t_mstate == LMS_USER_LOCK)
516 		(void) new_mstate(t, LMS_SYSTEM);
517 	return (error);
518 }
519 
520 #define	MAXLWPIDS	1024
521 
522 /*
523  * Unpark all of the specified lwps.
524  * Do it in chunks of MAXLWPIDS to avoid allocating too much memory.
525  */
526 static int
527 lwp_unpark_all(id_t *lwpidp, int nids)
528 {
529 	proc_t *p = ttoproc(curthread);
530 	kthread_t *t;
531 	int error = 0;
532 	id_t *lwpid;
533 	size_t lwpidsz;
534 	int n;
535 	int i;
536 
537 	if (nids <= 0)
538 		return (EINVAL);
539 
540 	lwpidsz = MIN(nids, MAXLWPIDS) * sizeof (id_t);
541 	lwpid = kmem_alloc(lwpidsz, KM_SLEEP);
542 	while (nids > 0) {
543 		n = MIN(nids, MAXLWPIDS);
544 		if (copyin(lwpidp, lwpid, n * sizeof (id_t))) {
545 			error = EFAULT;
546 			break;
547 		}
548 		mutex_enter(&p->p_lock);
549 		for (i = 0; i < n; i++) {
550 			if ((t = idtot(p, lwpid[i])) == NULL)
551 				error = ESRCH;
552 			else {
553 				mutex_enter(&t->t_delay_lock);
554 				t->t_unpark = 1;
555 				cv_signal(&t->t_delay_cv);
556 				mutex_exit(&t->t_delay_lock);
557 			}
558 		}
559 		mutex_exit(&p->p_lock);
560 		lwpidp += n;
561 		nids -= n;
562 	}
563 	kmem_free(lwpid, lwpidsz);
564 	return (error);
565 }
566 
567 /*
568  * SYS_lwp_park() system call.
569  */
570 int
571 syslwp_park(int which, uintptr_t arg1, uintptr_t arg2)
572 {
573 	int error;
574 
575 	switch (which) {
576 	case 0:
577 		error = lwp_park((timespec_t *)arg1, (id_t)arg2);
578 		break;
579 	case 1:
580 		error = lwp_unpark((id_t)arg1);
581 		break;
582 	case 2:
583 		error = lwp_unpark_all((id_t *)arg1, (int)arg2);
584 		break;
585 	case 3:
586 		/*
587 		 * This subcode is not used by libc.  It exists ONLY to
588 		 * support older versions of libthread which do not use
589 		 * the sc_park flag in the schedctl page.
590 		 *
591 		 * These versions of libthread need to be modifed or emulated
592 		 * to change calls to syslwp_park(1, tid, 0) to
593 		 * syslwp_park(3, tid).
594 		 */
595 		error = lwp_unpark_cancel((id_t)arg1);
596 		break;
597 	case 4:
598 		/*
599 		 * This subcode is not used by libc.  It exists ONLY to
600 		 * support older versions of libthread which do not use
601 		 * the sc_park flag in the schedctl page.
602 		 *
603 		 * These versions of libthread need to be modified or emulated
604 		 * to change calls to syslwp_park(0, ts, tid) to
605 		 * syslwp_park(4, ts, tid).
606 		 */
607 		schedctl_set_park();
608 		error = lwp_park((timespec_t *)arg1, (id_t)arg2);
609 		break;
610 	default:
611 		error = EINVAL;
612 		break;
613 	}
614 
615 	if (error)
616 		return (set_errno(error));
617 	return (0);
618 }
619