Files
Arquivotheca.Solaris-2.5/uts/common/syscall/lwp_create.c
seta75D 7c4988eac0 Init
2021-10-11 19:38:01 -03:00

181 lines
4.4 KiB
C
Executable File

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* Copyright (c) 1994 Sun Microsystems, Inc. */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
#ident "@(#)lwp_create.c 1.9 95/09/27 SMI" /* from SVr4.0 1.78 */
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/syscall.h>
#include <sys/proc.h>
#include <sys/processor.h>
#include <sys/fault.h>
#include <sys/ucontext.h>
#include <sys/signal.h>
#include <sys/unistd.h>
#include <sys/cmn_err.h>
#include <sys/debug.h>
/*
* A process can create a special lwp, the "aslwp", to take signals sent
* asynchronously to this process. The "aslwp" (short for Asynchronous Signals'
* lwp) is like a daemon lwp within this process and it is the first recipient
* of any signal sent asynchronously to the containing process. The aslwp is
* created via a new, reserved flag (__LWP_ASLWP) to _lwp_create(2). Currently
* only an MT process, i.e. a process linked with -lthread, creates such an lwp.
* At user-level, "aslwp" is usually in a "sigwait()", waiting for all signals.
* The aslwp is set up by calling setup_aslwp() from syslwp_create().
*/
static void
setup_aslwp(kthread_t *t)
{
proc_t *p = ttoproc(t);
ASSERT(MUTEX_HELD(&p->p_lock));
ASSERT((p->p_flag & ASLWP) == 0 && p->p_aslwptp == NULL);
p->p_flag |= ASLWP;
p->p_aslwptp = t;
/*
* Since "aslwp"'s thread pointer has just been advertised above, it
* is impossible for it to have received any signals directed via
* sigtoproc(). They are all in p_sig and the sigqueue is all in
* p_sigqueue.
*/
ASSERT(sigisempty(&t->t_sig));
ASSERT(t->t_sigqueue == NULL);
t->t_sig = p->p_sig;
sigemptyset(&p->p_sig);
t->t_sigqueue = p->p_sigqueue;
p->p_sigqueue = NULL;
/*
* initialize binding state - might have been initialized
* inappropriately in "lwp_create()".
*/
t->t_bind_cpu = PBIND_NONE;
t->t_bound_cpu = 0;
}
/*
* This structure is used only for copying the arguments
* into the new LWP's arg area for the benefit of debuggers.
*/
struct lwp_createa {
ucontext_t *ucp;
int flags;
int *new_lwp;
};
/*
* Create a lwp.
*/
int
syslwp_create(ucontext_t *ucp, int flags, int *new_lwp)
{
klwp_id_t lwp;
proc_t *p = ttoproc(curthread);
kthread_t *t;
ucontext_t uc;
k_sigset_t sigmask;
int tid;
struct lwp_createa *ap;
extern void lwp_rtt();
if (copyin((caddr_t)ucp, (caddr_t)&uc, sizeof (ucontext_t)))
return (set_errno(EFAULT));
save_syscall_args(); /* save args for tracing first */
sigutok(&uc.uc_sigmask, &sigmask);
lwp = lwp_create(lwp_rtt, NULL, NULL, curproc, TS_STOPPED,
curthread->t_pri, sigmask, curthread->t_cid);
if (lwp == NULL)
return (set_errno(EAGAIN));
lwp_load(lwp, &uc);
t = lwptot(lwp);
/*
* copy new LWP's lwpid_t into the caller's specified buffer.
*/
if (new_lwp) {
if (copyout((char *)&t->t_tid, (char *)new_lwp, sizeof (int))) {
/*
* caller's buffer is not writable, return
* EFAULT, and terminate new LWP.
*/
mutex_enter(&p->p_lock);
t->t_proc_flag |= TP_EXITLWP;
t->t_sig_check = 1;
t->t_sysnum = 0;
lwp_continue(t);
mutex_exit(&p->p_lock);
return (set_errno(EFAULT));
}
}
mutex_enter(&p->p_lock);
/*
* Copy the syscall arguments to the new lwp's arg area
* for the benefit of debuggers.
*/
t->t_sysnum = SYS_lwp_create;
ap = (struct lwp_createa *)lwp->lwp_arg;
lwp->lwp_ap = (int *)ap;
ap->ucp = ucp;
ap->flags = flags;
ap->new_lwp = new_lwp;
/*
* If we are creating the aslwp, do some checks then set it up.
*/
if (flags & __LWP_ASLWP) {
if (p->p_flag & ASLWP) {
/*
* There is already an aslwp.
* Return EINVAL and terminate the new LWP.
*/
t->t_proc_flag |= TP_EXITLWP;
t->t_sig_check = 1;
t->t_sysnum = 0;
lwp_continue(t);
mutex_exit(&p->p_lock);
return (set_errno(EINVAL));
}
setup_aslwp(t);
}
if (!(flags & LWP_DETACHED))
t->t_proc_flag |= TP_TWAIT;
tid = (int)t->t_tid; /* for debugger */
if ((flags & LWP_SUSPENDED))
t->t_proc_flag |= TP_HOLDLWP; /* create suspended */
else
lwp_continue(t); /* start running */
mutex_exit(&p->p_lock);
return (tid);
}
/*
* Exit the calling lwp
*/
void
syslwp_exit()
{
proc_t *p = ttoproc(curthread);
mutex_enter(&p->p_lock);
lwp_exit();
/* NOTREACHED */
}