Home | History | Annotate | Download | only in syscall
      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	"@(#)lwpsys.c	1.42	07/06/04 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