o Refine kse_thr_interrupt to allow it to handle different commands.

o Remove TDF_NOSIGPOST.
o Add a member td_waitset to proc structure, it will be used for sigwait.

Tested by: deischen
This commit is contained in:
David Xu 2003-07-17 22:45:33 +00:00
parent e76bad968c
commit dd7da9aa28
10 changed files with 140 additions and 136 deletions

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: src/sys/kern/syscalls.master,v 1.150 2003/06/04 03:49:31 rwatson Exp
* created from FreeBSD: src/sys/kern/syscalls.master,v 1.151 2003/06/28 08:29:05 davidxu Exp
*/
#include "opt_compat.h"

View File

@ -384,7 +384,8 @@ proc_linkup(struct proc *p, struct ksegrp *kg,
/*
struct kse_thr_interrupt_args {
struct kse_thr_mailbox * tmbx;
int sig;
int cmd;
long data;
};
*/
int
@ -392,47 +393,63 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
{
struct proc *p;
struct thread *td2;
int sig = uap->sig;
p = td->td_proc;
if (!(p->p_flag & P_SA) || (uap->tmbx == NULL) ||
(sig < -2) || (sig > _SIG_MAXSIG))
if (!(p->p_flag & P_SA))
return (EINVAL);
PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
FOREACH_THREAD_IN_PROC(p, td2) {
if (td2->td_mailbox == uap->tmbx)
break;
}
if (td2 == NULL) {
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
return (ESRCH);
}
if (sig > 0) {
td2->td_flags &= ~TDF_INTERRUPT;
mtx_unlock_spin(&sched_lock);
tdsignal(td2, sig, SIGTARGET_TD);
} else if (sig == 0) {
mtx_unlock_spin(&sched_lock);
} else {
td2->td_flags |= TDF_INTERRUPT | TDF_ASTPENDING;
if (TD_CAN_UNBIND(td2))
td2->td_upcall->ku_flags |= KUF_DOUPCALL;
if (sig == -1)
td2->td_intrval = EINTR;
else if (sig == -2)
td2->td_intrval = ERESTART;
if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR)) {
if (td2->td_flags & TDF_CVWAITQ)
cv_abort(td2);
else
abortsleep(td2);
switch (uap->cmd) {
case KSE_INTR_SENDSIG:
if (uap->data < 0 || uap->data > _SIG_MAXSIG)
return (EINVAL);
case KSE_INTR_INTERRUPT:
case KSE_INTR_RESTART:
PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
FOREACH_THREAD_IN_PROC(p, td2) {
if (td2->td_mailbox == uap->tmbx)
break;
}
mtx_unlock_spin(&sched_lock);
if (td2 == NULL) {
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
return (ESRCH);
}
if (uap->cmd == KSE_INTR_SENDSIG) {
if (uap->data > 0) {
td2->td_flags &= ~TDF_INTERRUPT;
mtx_unlock_spin(&sched_lock);
tdsignal(td2, (int)uap->data, SIGTARGET_TD);
} else {
mtx_unlock_spin(&sched_lock);
}
} else {
td2->td_flags |= TDF_INTERRUPT | TDF_ASTPENDING;
if (TD_CAN_UNBIND(td2))
td2->td_upcall->ku_flags |= KUF_DOUPCALL;
if (uap->cmd == KSE_INTR_INTERRUPT)
td2->td_intrval = EINTR;
else
td2->td_intrval = ERESTART;
if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR)) {
if (td2->td_flags & TDF_CVWAITQ)
cv_abort(td2);
else
abortsleep(td2);
}
mtx_unlock_spin(&sched_lock);
}
PROC_UNLOCK(p);
break;
case KSE_INTR_SIGEXIT:
if (uap->data < 1 || uap->data > _SIG_MAXSIG)
return (EINVAL);
PROC_LOCK(p);
sigexit(td, (int)uap->data);
break;
default:
return (EINVAL);
}
PROC_UNLOCK(p);
return (0);
}
@ -991,7 +1008,7 @@ thread_free(struct thread *td)
* The list is anchored in the ksegrp structure.
*/
int
thread_export_context(struct thread *td)
thread_export_context(struct thread *td, int willexit)
{
struct proc *p;
struct ksegrp *kg;
@ -1023,17 +1040,19 @@ thread_export_context(struct thread *td)
* For sync signal, it is only possible when the signal is not
* caught by userland or process is being debugged.
*/
PROC_LOCK(p);
if (td->td_flags & TDF_NEEDSIGCHK) {
mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_NEEDSIGCHK;
mtx_unlock_spin(&sched_lock);
PROC_LOCK(p);
mtx_lock(&p->p_sigacts->ps_mtx);
while ((sig = cursig(td)) != 0)
postsig(sig);
mtx_unlock(&p->p_sigacts->ps_mtx);
PROC_UNLOCK(p);
}
if (willexit)
SIGFILLSET(td->td_sigmask);
PROC_UNLOCK(p);
/* Get address in latest mbox of list pointer */
addr = (void *)(&td->td_mailbox->tm_next);
@ -1067,11 +1086,7 @@ thread_export_context(struct thread *td)
bad:
PROC_LOCK(p);
psignal(p, SIGSEGV);
PROC_UNLOCK(p);
/* The mailbox is bad, don't use it */
td->td_mailbox = NULL;
td->td_usticks = 0;
sigexit(td, SIGILL);
return (error);
}
@ -1665,15 +1680,7 @@ thread_userret(struct thread *td, struct trapframe *frame)
return (0);
}
mtx_unlock_spin(&sched_lock);
error = thread_export_context(td);
if (error) {
/*
* Failing to do the KSE operation just defaults
* back to synchonous operation, so just return from
* the syscall.
*/
goto out;
}
thread_export_context(td, 0);
/*
* There is something to report, and we own an upcall
* strucuture, we can go to userland.
@ -1681,22 +1688,14 @@ thread_userret(struct thread *td, struct trapframe *frame)
*/
td->td_pflags |= TDP_UPCALLING;
} else if (td->td_mailbox && (ku == NULL)) {
/*
* Because we are exiting, SIGKILL and SIGSTOP shouldn't
* be posted to us anymore, otherwise they will be lost.
*/
mtx_lock_spin(&sched_lock);
td->td_flags |= TDF_NOSIGPOST;
mtx_unlock_spin(&sched_lock);
error = thread_export_context(td);
/* possibly upcall with error? */
thread_export_context(td, 1);
PROC_LOCK(p);
/*
* There are upcall threads waiting for
* work to do, wake one of them up.
* XXXKSE Maybe wake all of them up.
*/
if (!error && kg->kg_upsleeps)
if (kg->kg_upsleeps)
wakeup_one(&kg->kg_completed);
mtx_lock_spin(&sched_lock);
thread_stopped(p);

View File

@ -384,7 +384,8 @@ proc_linkup(struct proc *p, struct ksegrp *kg,
/*
struct kse_thr_interrupt_args {
struct kse_thr_mailbox * tmbx;
int sig;
int cmd;
long data;
};
*/
int
@ -392,47 +393,63 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
{
struct proc *p;
struct thread *td2;
int sig = uap->sig;
p = td->td_proc;
if (!(p->p_flag & P_SA) || (uap->tmbx == NULL) ||
(sig < -2) || (sig > _SIG_MAXSIG))
if (!(p->p_flag & P_SA))
return (EINVAL);
PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
FOREACH_THREAD_IN_PROC(p, td2) {
if (td2->td_mailbox == uap->tmbx)
break;
}
if (td2 == NULL) {
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
return (ESRCH);
}
if (sig > 0) {
td2->td_flags &= ~TDF_INTERRUPT;
mtx_unlock_spin(&sched_lock);
tdsignal(td2, sig, SIGTARGET_TD);
} else if (sig == 0) {
mtx_unlock_spin(&sched_lock);
} else {
td2->td_flags |= TDF_INTERRUPT | TDF_ASTPENDING;
if (TD_CAN_UNBIND(td2))
td2->td_upcall->ku_flags |= KUF_DOUPCALL;
if (sig == -1)
td2->td_intrval = EINTR;
else if (sig == -2)
td2->td_intrval = ERESTART;
if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR)) {
if (td2->td_flags & TDF_CVWAITQ)
cv_abort(td2);
else
abortsleep(td2);
switch (uap->cmd) {
case KSE_INTR_SENDSIG:
if (uap->data < 0 || uap->data > _SIG_MAXSIG)
return (EINVAL);
case KSE_INTR_INTERRUPT:
case KSE_INTR_RESTART:
PROC_LOCK(p);
mtx_lock_spin(&sched_lock);
FOREACH_THREAD_IN_PROC(p, td2) {
if (td2->td_mailbox == uap->tmbx)
break;
}
mtx_unlock_spin(&sched_lock);
if (td2 == NULL) {
mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(p);
return (ESRCH);
}
if (uap->cmd == KSE_INTR_SENDSIG) {
if (uap->data > 0) {
td2->td_flags &= ~TDF_INTERRUPT;
mtx_unlock_spin(&sched_lock);
tdsignal(td2, (int)uap->data, SIGTARGET_TD);
} else {
mtx_unlock_spin(&sched_lock);
}
} else {
td2->td_flags |= TDF_INTERRUPT | TDF_ASTPENDING;
if (TD_CAN_UNBIND(td2))
td2->td_upcall->ku_flags |= KUF_DOUPCALL;
if (uap->cmd == KSE_INTR_INTERRUPT)
td2->td_intrval = EINTR;
else
td2->td_intrval = ERESTART;
if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR)) {
if (td2->td_flags & TDF_CVWAITQ)
cv_abort(td2);
else
abortsleep(td2);
}
mtx_unlock_spin(&sched_lock);
}
PROC_UNLOCK(p);
break;
case KSE_INTR_SIGEXIT:
if (uap->data < 1 || uap->data > _SIG_MAXSIG)
return (EINVAL);
PROC_LOCK(p);
sigexit(td, (int)uap->data);
break;
default:
return (EINVAL);
}
PROC_UNLOCK(p);
return (0);
}
@ -991,7 +1008,7 @@ thread_free(struct thread *td)
* The list is anchored in the ksegrp structure.
*/
int
thread_export_context(struct thread *td)
thread_export_context(struct thread *td, int willexit)
{
struct proc *p;
struct ksegrp *kg;
@ -1023,17 +1040,19 @@ thread_export_context(struct thread *td)
* For sync signal, it is only possible when the signal is not
* caught by userland or process is being debugged.
*/
PROC_LOCK(p);
if (td->td_flags & TDF_NEEDSIGCHK) {
mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_NEEDSIGCHK;
mtx_unlock_spin(&sched_lock);
PROC_LOCK(p);
mtx_lock(&p->p_sigacts->ps_mtx);
while ((sig = cursig(td)) != 0)
postsig(sig);
mtx_unlock(&p->p_sigacts->ps_mtx);
PROC_UNLOCK(p);
}
if (willexit)
SIGFILLSET(td->td_sigmask);
PROC_UNLOCK(p);
/* Get address in latest mbox of list pointer */
addr = (void *)(&td->td_mailbox->tm_next);
@ -1067,11 +1086,7 @@ thread_export_context(struct thread *td)
bad:
PROC_LOCK(p);
psignal(p, SIGSEGV);
PROC_UNLOCK(p);
/* The mailbox is bad, don't use it */
td->td_mailbox = NULL;
td->td_usticks = 0;
sigexit(td, SIGILL);
return (error);
}
@ -1665,15 +1680,7 @@ thread_userret(struct thread *td, struct trapframe *frame)
return (0);
}
mtx_unlock_spin(&sched_lock);
error = thread_export_context(td);
if (error) {
/*
* Failing to do the KSE operation just defaults
* back to synchonous operation, so just return from
* the syscall.
*/
goto out;
}
thread_export_context(td, 0);
/*
* There is something to report, and we own an upcall
* strucuture, we can go to userland.
@ -1681,22 +1688,14 @@ thread_userret(struct thread *td, struct trapframe *frame)
*/
td->td_pflags |= TDP_UPCALLING;
} else if (td->td_mailbox && (ku == NULL)) {
/*
* Because we are exiting, SIGKILL and SIGSTOP shouldn't
* be posted to us anymore, otherwise they will be lost.
*/
mtx_lock_spin(&sched_lock);
td->td_flags |= TDF_NOSIGPOST;
mtx_unlock_spin(&sched_lock);
error = thread_export_context(td);
/* possibly upcall with error? */
thread_export_context(td, 1);
PROC_LOCK(p);
/*
* There are upcall threads waiting for
* work to do, wake one of them up.
* XXXKSE Maybe wake all of them up.
*/
if (!error && kg->kg_upsleeps)
if (kg->kg_upsleeps)
wakeup_one(&kg->kg_completed);
mtx_lock_spin(&sched_lock);
thread_stopped(p);

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: src/sys/kern/syscalls.master,v 1.150 2003/06/04 03:49:31 rwatson Exp
* created from FreeBSD: src/sys/kern/syscalls.master,v 1.151 2003/06/28 08:29:05 davidxu Exp
*/
const char *syscallnames[] = {

View File

@ -556,7 +556,7 @@
380 MSTD BSD { int kse_wakeup(struct kse_mailbox *mbx); }
381 STD BSD { int kse_create(struct kse_mailbox *mbx, \
int newgroup); }
382 MSTD BSD { int kse_thr_interrupt(struct kse_thr_mailbox *tmbx, int sig); }
382 MSTD BSD { int kse_thr_interrupt(struct kse_thr_mailbox *tmbx, int cmd, long data); }
383 MSTD BSD { int kse_release(struct timespec *timeout); }
384 MSTD BSD { int __mac_get_proc(struct mac *mac_p); }
385 MSTD BSD { int __mac_set_proc(struct mac *mac_p); }

View File

@ -94,11 +94,16 @@ struct kse_mailbox {
#define KMF_BOUND 0x08
#define KMF_WAITSIGEVENT 0x10
#define KSE_INTR_INTERRUPT 0x01
#define KSE_INTR_RESTART 0x02
#define KSE_INTR_SENDSIG 0x03
#define KSE_INTR_SIGEXIT 0x04
#ifndef _KERNEL
int kse_create(struct kse_mailbox *, int);
int kse_exit(void);
int kse_release(struct timespec *);
int kse_thr_interrupt(struct kse_thr_mailbox *, int);
int kse_thr_interrupt(struct kse_thr_mailbox *, int, long);
int kse_wakeup(struct kse_mailbox *);
#endif /* !_KERNEL */

View File

@ -298,6 +298,7 @@ struct thread {
sigset_t td_oldsigmask; /* (k) Saved mask from pre sigpause. */
sigset_t td_sigmask; /* (c) Current signal mask. */
sigset_t td_siglist; /* (c) Sigs arrived, not delivered. */
sigset_t *td_waitset; /* (c) Wait set for sigwait */
TAILQ_ENTRY(thread) td_umtx; /* (c?) Link for when we're blocked. */
#define td_endzero td_base_pri
@ -341,7 +342,6 @@ struct thread {
#define TDF_SELECT 0x000040 /* Selecting; wakeup/waiting danger. */
#define TDF_CVWAITQ 0x000080 /* Thread is on a cv_waitq (not slpq). */
#define TDF_ONSLEEPQ 0x000200 /* On the sleep queue. */
#define TDF_NOSIGPOST 0x000400 /* Thread doesn't want signals */
#define TDF_ASTPENDING 0x000800 /* Thread has some asynchronous events. */
#define TDF_TIMOFAIL 0x001000 /* Timeout from sleep after we were awake. */
#define TDF_INTERRUPT 0x002000 /* Thread is marked as interrupted. */
@ -903,7 +903,7 @@ void ksegrp_unlink(struct ksegrp *kg);
void thread_signal_add(struct thread *td, int sig);
struct thread *thread_alloc(void);
void thread_exit(void) __dead2;
int thread_export_context(struct thread *td);
int thread_export_context(struct thread *td, int willexit);
void thread_free(struct thread *td);
void thread_link(struct thread *td, struct ksegrp *kg);
void thread_reap(void);

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: src/sys/kern/syscalls.master,v 1.150 2003/06/04 03:49:31 rwatson Exp
* created from FreeBSD: src/sys/kern/syscalls.master,v 1.151 2003/06/28 08:29:05 davidxu Exp
*/
#define SYS_syscall 0

View File

@ -1,7 +1,7 @@
# FreeBSD system call names.
# DO NOT EDIT-- this file is automatically generated.
# $FreeBSD$
# created from FreeBSD: src/sys/kern/syscalls.master,v 1.150 2003/06/04 03:49:31 rwatson Exp
# created from FreeBSD: src/sys/kern/syscalls.master,v 1.151 2003/06/28 08:29:05 davidxu Exp
MIASM = \
syscall.o \
exit.o \

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: src/sys/kern/syscalls.master,v 1.150 2003/06/04 03:49:31 rwatson Exp
* created from FreeBSD: src/sys/kern/syscalls.master,v 1.151 2003/06/28 08:29:05 davidxu Exp
*/
#ifndef _SYS_SYSPROTO_H_
@ -1072,7 +1072,8 @@ struct kse_create_args {
};
struct kse_thr_interrupt_args {
char tmbx_l_[PADL_(struct kse_thr_mailbox *)]; struct kse_thr_mailbox * tmbx; char tmbx_r_[PADR_(struct kse_thr_mailbox *)];
char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
char data_l_[PADL_(long)]; long data; char data_r_[PADR_(long)];
};
struct kse_release_args {
char timeout_l_[PADL_(struct timespec *)]; struct timespec * timeout; char timeout_r_[PADR_(struct timespec *)];