summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Xu <davidxu@FreeBSD.org>2005-10-23 04:12:26 +0000
committerDavid Xu <davidxu@FreeBSD.org>2005-10-23 04:12:26 +0000
commit5da49fcb8a52cb119d97d64aa185d85226cac472 (patch)
tree7383ee16c42480a0bcfe4b153dbc59ff08633709
parent575c4eadf68ecda15af1a6f8aba1c378e072728e (diff)
Notes
-rw-r--r--sys/kern/kern_sig.c70
-rw-r--r--sys/sys/signalvar.h13
2 files changed, 70 insertions, 13 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index f1b90c520b18..169e2c7a1525 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -97,8 +97,6 @@ static int kern_sigtimedwait(struct thread *, sigset_t,
ksiginfo_t *, struct timespec *);
static int do_tdsignal(struct thread *, int, ksiginfo_t *, sigtarget_t);
static void sigqueue_start(void);
-static ksiginfo_t * ksiginfo_alloc(void);
-static void ksiginfo_free(ksiginfo_t *);
static int psignal_common(struct proc *p, int sig, ksiginfo_t *ksi);
static uma_zone_t ksiginfo_zone = NULL;
@@ -215,20 +213,30 @@ sigqueue_start(void)
uma_prealloc(ksiginfo_zone, preallocate_siginfo);
}
-static ksiginfo_t *
+ksiginfo_t *
ksiginfo_alloc(void)
{
if (ksiginfo_zone != NULL)
- return ((ksiginfo_t *)uma_zalloc(ksiginfo_zone, M_NOWAIT));
+ return ((ksiginfo_t *)uma_zalloc(ksiginfo_zone, M_NOWAIT | M_ZERO));
return (NULL);
}
-static void
+void
ksiginfo_free(ksiginfo_t *ksi)
{
uma_zfree(ksiginfo_zone, ksi);
}
+static __inline int
+ksiginfo_tryfree(ksiginfo_t *ksi)
+{
+ if (!(ksi->ksi_flags & KSI_EXT)) {
+ uma_zfree(ksiginfo_zone, ksi);
+ return (1);
+ }
+ return (0);
+}
+
void
sigqueue_init(sigqueue_t *list, struct proc *p)
{
@@ -253,7 +261,6 @@ sigqueue_get(sigqueue_t *sq, int signo, ksiginfo_t *si)
KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited"));
- ksiginfo_init(si);
if (!SIGISMEMBER(sq->sq_signals, signo))
return (0);
@@ -262,9 +269,9 @@ sigqueue_get(sigqueue_t *sq, int signo, ksiginfo_t *si)
if (ksi->ksi_signo == signo) {
if (count == 0) {
TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link);
+ ksi->ksi_sigq = NULL;
ksiginfo_copy(ksi, si);
- ksiginfo_free(ksi);
- if (p != NULL)
+ if (ksiginfo_tryfree(ksi) && p != NULL)
p->p_pendingcnt--;
}
count++;
@@ -277,6 +284,31 @@ sigqueue_get(sigqueue_t *sq, int signo, ksiginfo_t *si)
return (signo);
}
+void
+sigqueue_take(ksiginfo_t *ksi)
+{
+ struct ksiginfo *kp;
+ struct proc *p;
+ sigqueue_t *sq;
+
+ if ((sq = ksi->ksi_sigq) == NULL)
+ return;
+
+ p = sq->sq_proc;
+ TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link);
+ ksi->ksi_sigq = NULL;
+ if (!(ksi->ksi_flags & KSI_EXT) && p != NULL)
+ p->p_pendingcnt--;
+
+ for (kp = TAILQ_FIRST(&sq->sq_list); kp != NULL;
+ kp = TAILQ_NEXT(kp, ksi_link)) {
+ if (kp->ksi_signo == ksi->ksi_signo)
+ break;
+ }
+ if (kp == NULL)
+ SIGDELSET(sq->sq_signals, ksi->ksi_signo);
+}
+
int
sigqueue_add(sigqueue_t *sq, int signo, ksiginfo_t *si)
{
@@ -289,6 +321,13 @@ sigqueue_add(sigqueue_t *sq, int signo, ksiginfo_t *si)
if (signo == SIGKILL || signo == SIGSTOP || si == NULL)
goto out_set_bit;
+ /* directly insert the ksi, don't copy it */
+ if (si->ksi_flags & KSI_INS) {
+ TAILQ_INSERT_TAIL(&sq->sq_list, si, ksi_link);
+ si->ksi_sigq = sq;
+ goto out_set_bit;
+ }
+
if (__predict_false(ksiginfo_zone == NULL))
goto out_set_bit;
@@ -304,6 +343,7 @@ sigqueue_add(sigqueue_t *sq, int signo, ksiginfo_t *si)
ksiginfo_copy(si, ksi);
ksi->ksi_signo = signo;
TAILQ_INSERT_TAIL(&sq->sq_list, ksi, ksi_link);
+ ksi->ksi_sigq = sq;
}
if ((si->ksi_flags & KSI_TRAP) != 0) {
@@ -327,10 +367,13 @@ sigqueue_flush(sigqueue_t *sq)
KASSERT(sq->sq_flags & SQ_INIT, ("sigqueue not inited"));
+ if (p != NULL)
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
while ((ksi = TAILQ_FIRST(&sq->sq_list)) != NULL) {
TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link);
- ksiginfo_free(ksi);
- if (p != NULL)
+ ksi->ksi_sigq = NULL;
+ if (ksiginfo_tryfree(ksi) && p != NULL)
p->p_pendingcnt--;
}
@@ -372,6 +415,7 @@ sigqueue_move_set(sigqueue_t *src, sigqueue_t *dst, sigset_t *setp)
if (p1 != NULL)
p1->p_pendingcnt--;
TAILQ_INSERT_TAIL(&dst->sq_list, ksi, ksi_link);
+ ksi->ksi_sigq = dst;
if (p2 != NULL)
p2->p_pendingcnt++;
}
@@ -410,8 +454,8 @@ sigqueue_delete_set(sigqueue_t *sq, sigset_t *set)
next = TAILQ_NEXT(ksi, ksi_link);
if (SIGISMEMBER(*set, ksi->ksi_signo)) {
TAILQ_REMOVE(&sq->sq_list, ksi, ksi_link);
- ksiginfo_free(ksi);
- if (p != NULL)
+ ksi->ksi_sigq = NULL;
+ if (ksiginfo_tryfree(ksi) && p != NULL)
p->p_pendingcnt--;
}
}
@@ -1205,6 +1249,7 @@ out:
if (sig) {
sig_t action;
+ ksiginfo_init(ksi);
sigqueue_get(&td->td_sigqueue, sig, ksi);
ksi->ksi_signo = sig;
error = 0;
@@ -2622,6 +2667,7 @@ postsig(sig)
PROC_LOCK_ASSERT(p, MA_OWNED);
ps = p->p_sigacts;
mtx_assert(&ps->ps_mtx, MA_OWNED);
+ ksiginfo_init(&ksi);
sigqueue_get(&td->td_sigqueue, sig, &ksi);
ksi.ksi_signo = sig;
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 395930167941..124ff970301d 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -203,6 +203,7 @@ typedef struct ksiginfo {
TAILQ_ENTRY(ksiginfo) ksi_link;
siginfo_t ksi_info;
int ksi_flags;
+ struct sigqueue *ksi_sigq;
} ksiginfo_t;
#define ksi_signo ksi_info.si_signo
@@ -215,9 +216,16 @@ typedef struct ksiginfo {
#define ksi_value ksi_info.si_value
#define ksi_band ksi_info.si_band
#define ksi_trapno ksi_info.si_trapno
+#define ksi_overrun ksi_info.si_overrun
+#define ksi_timerid ksi_info.si_timerid
/* bits for ksi_flags */
#define KSI_TRAP 0x01 /* Generated by trap. */
+#define KSI_EXT 0x02 /* Externally managed ksi. */
+#define KSI_INS 0x04 /* Directly insert ksi, not the copy */
+#define KSI_COPYMASK KSI_TRAP
+
+#define KSI_ONQ(ksi) ((ksi)->ksi_sigq != NULL)
typedef struct sigqueue {
sigset_t sq_signals;
@@ -276,7 +284,7 @@ static __inline void
ksiginfo_copy(ksiginfo_t *src, ksiginfo_t *dst)
{
(dst)->ksi_info = src->ksi_info;
- (dst)->ksi_flags = src->ksi_flags;
+ (dst)->ksi_flags = (src->ksi_flags & KSI_COPYMASK);
}
struct pgrp;
@@ -323,6 +331,8 @@ int tdsignal(struct thread *td, int sig, ksiginfo_t *ksi,
sigtarget_t target);
void trapsignal(struct thread *td, ksiginfo_t *);
int ptracestop(struct thread *td, int sig);
+ksiginfo_t * ksiginfo_alloc(void);
+void ksiginfo_free(ksiginfo_t *);
void sigqueue_init(struct sigqueue *queue, struct proc *p);
void sigqueue_flush(struct sigqueue *queue);
void sigqueue_delete_proc(struct proc *p, int sig);
@@ -335,6 +345,7 @@ void sigqueue_collect_set(struct sigqueue *queue, sigset_t *set);
void sigqueue_move(struct sigqueue *, struct sigqueue *, int sig);
void sigqueue_delete_set_proc(struct proc *, sigset_t *);
void sigqueue_delete_stopmask_proc(struct proc *);
+void sigqueue_take(ksiginfo_t *ksi);
/*
* Machine-dependent functions: