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