Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133206958
D29106.id85258.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D29106.id85258.diff
View Options
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -524,6 +524,7 @@
callout_init_mtx(&p->p_itcallout, &p->p_mtx, 0);
callout_init_mtx(&p->p_limco, &p->p_mtx, 0);
callout_init(&td->td_slpcallout, 1);
+ TAILQ_INIT(&p->p_kqtim_stop);
/* Create credentials. */
newcred = crget();
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -676,28 +676,79 @@
struct kq_timer_cb_data {
struct callout c;
+ struct proc *p;
+ struct knote *kn;
+ int cpuid;
+ TAILQ_ENTRY(kq_timer_cb_data) link;
sbintime_t next; /* next timer event fires at */
sbintime_t to; /* precalculated timer period, 0 for abs */
};
+static void
+kqtimer_sched_callout(struct kq_timer_cb_data *kc)
+{
+ callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kc->kn,
+ kc->cpuid, C_ABSOLUTE);
+}
+
+void
+kqtimer_proc_continued(struct proc *p)
+{
+ struct kq_timer_cb_data *kc, *kc1;
+ struct bintime bt;
+ sbintime_t now;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ getboottimebin(&bt);
+ now = bttosbt(bt);
+
+ TAILQ_FOREACH_SAFE(kc, &p->p_kqtim_stop, link, kc1) {
+ TAILQ_REMOVE(&p->p_kqtim_stop, kc, link);
+ if (kc->next <= now)
+ filt_timerexpire(kc->kn);
+ else
+ kqtimer_sched_callout(kc);
+ }
+}
+
static void
filt_timerexpire(void *knx)
{
struct knote *kn;
struct kq_timer_cb_data *kc;
+ sbintime_t now;
kn = knx;
- kn->kn_data++;
- KNOTE_ACTIVATE(kn, 0); /* XXX - handle locking */
-
- if ((kn->kn_flags & EV_ONESHOT) != 0)
- return;
kc = kn->kn_ptr.p_v;
- if (kc->to == 0)
+
+ if ((kn->kn_flags & EV_ONESHOT) != 0 || kc->to == 0) {
+ kn->kn_data++;
+ KNOTE_ACTIVATE(kn, 0);
return;
- kc->next += kc->to;
- callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn,
- PCPU_GET(cpuid), C_ABSOLUTE);
+ }
+
+ for (now = sbinuptime(); kc->next <= now; kc->next += kc->to)
+ kn->kn_data++;
+ KNOTE_ACTIVATE(kn, 0); /* XXX - handle locking */
+
+ /*
+ * Initial check for stopped kc->p is racy. It is fine to
+ * miss the set of the stop flags, at worst we would schedule
+ * one more callout. On the other hand, it is not fine to not
+ * schedule when we we missed clearing of the flags, we
+ * recheck them under the lock and observe consistent state.
+ */
+ if (P_SHOULDSTOP(kc->p) || P_KILLED(kc->p)) {
+ PROC_LOCK(kc->p);
+ if (P_SHOULDSTOP(kc->p) || P_KILLED(kc->p)) {
+ TAILQ_INSERT_TAIL(&kc->p->p_kqtim_stop, kc, link);
+ PROC_UNLOCK(kc->p);
+ return;
+ }
+ PROC_UNLOCK(kc->p);
+ }
+ kqtimer_sched_callout(kc);
}
/*
@@ -753,6 +804,9 @@
kn->kn_flags |= EV_CLEAR; /* automatically set */
kn->kn_status &= ~KN_DETACHED; /* knlist_add clears it */
kn->kn_ptr.p_v = kc = malloc(sizeof(*kc), M_KQUEUE, M_WAITOK);
+ kc->kn = kn;
+ kc->p = curproc;
+ kc->cpuid = PCPU_GET(cpuid);
callout_init(&kc->c, 1);
filt_timerstart(kn, to);
@@ -772,8 +826,7 @@
kc->next = to + sbinuptime();
kc->to = to;
}
- callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn,
- PCPU_GET(cpuid), C_ABSOLUTE);
+ kqtimer_sched_callout(kc);
}
static void
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -598,6 +598,7 @@
LIST_INIT(&p2->p_orphans);
callout_init_mtx(&p2->p_itcallout, &p2->p_mtx, 0);
+ TAILQ_INIT(&p2->p_kqtim_stop);
/*
* This begins the section where we must prevent the parent
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2316,7 +2316,7 @@
thread_unsuspend(p);
PROC_SUNLOCK(p);
sigqueue_delete(sigqueue, sig);
- goto out;
+ goto out_cont;
}
if (action == SIG_CATCH) {
/*
@@ -2331,7 +2331,7 @@
*/
thread_unsuspend(p);
PROC_SUNLOCK(p);
- goto out;
+ goto out_cont;
}
if (prop & SIGPROP_STOP) {
@@ -2416,6 +2416,9 @@
PROC_SLOCK(p);
thread_unsuspend(p);
PROC_SUNLOCK(p);
+out_cont:
+ itimer_proc_continued(p);
+ kqtimer_proc_continued(p);
out:
/* If we jump here, proc slock should not be owned. */
PROC_SLOCK_ASSERT(p, MA_NOTOWNED);
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -881,6 +881,33 @@
return (0);
}
+static void
+realitexpire_reset_callout(struct proc *p, sbintime_t *isbtp)
+{
+ sbintime_t prec;
+
+ prec = isbtp == NULL ? tvtosbt(p->p_realtimer.it_interval) : *isbtp;
+ callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value),
+ prec >> tc_precexp, realitexpire, p, C_ABSOLUTE);
+}
+
+void
+itimer_proc_continued(struct proc *p)
+{
+ struct timeval ctv;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ if ((p->p_flag2 & P2_ITSTOPPED) == 0)
+ return;
+
+ p->p_flag2 &= ~P2_ITSTOPPED;
+ microuptime(&ctv);
+ if (timevalcmp(&p->p_realtimer.it_value, &ctv, >=))
+ realitexpire(p);
+ else
+ realitexpire_reset_callout(p, NULL);
+}
+
/*
* Real interval timer expired:
* send process whose timer expired an alarm signal.
@@ -908,6 +935,7 @@
wakeup(&p->p_itcallout);
return;
}
+
isbt = tvtosbt(p->p_realtimer.it_interval);
if (isbt >= sbt_timethreshold)
getmicrouptime(&ctv);
@@ -917,8 +945,14 @@
timevaladd(&p->p_realtimer.it_value,
&p->p_realtimer.it_interval);
} while (timevalcmp(&p->p_realtimer.it_value, &ctv, <=));
- callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value),
- isbt >> tc_precexp, realitexpire, p, C_ABSOLUTE);
+
+ if (P_SHOULDSTOP(p) || P_KILLED(p)) {
+ p->p_flag2 |= P2_ITSTOPPED;
+ return;
+ }
+
+ p->p_flag2 &= ~P2_ITSTOPPED;
+ realitexpire_reset_callout(p, &isbt);
}
/*
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1094,6 +1094,8 @@
p->p_flag &= ~(P_STOPPED_TRACE | P_STOPPED_SIG | P_WAITED);
thread_unsuspend(p);
PROC_SUNLOCK(p);
+ itimer_proc_continued(p);
+ kqtimer_proc_continued(p);
break;
case PT_WRITE_I:
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -183,6 +183,7 @@
struct kcov_info;
struct kdtrace_proc;
struct kdtrace_thread;
+struct kq_timer_cb_data;
struct mqueue_notifier;
struct p_sched;
struct proc;
@@ -727,6 +728,8 @@
*/
LIST_ENTRY(proc) p_orphan; /* (e) List of orphan processes. */
LIST_HEAD(, proc) p_orphans; /* (e) Pointer to list of orphans. */
+
+ TAILQ_HEAD(, kq_timer_cb_data) p_kqtim_stop; /* (c) */
};
#define p_session p_pgrp->pg_session
@@ -825,6 +828,7 @@
MAP_STACK */
#define P2_STKGAP_DISABLE_EXEC 0x00001000 /* Stack gap disabled
after exec */
+#define P2_ITSTOPPED 0x00002000
/* Flags protected by proctree_lock, kept in p_treeflags. */
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */
@@ -1090,6 +1094,8 @@
struct trapframe *);
void fork_return(struct thread *, struct trapframe *);
int inferior(struct proc *p);
+void itimer_proc_continued(struct proc *p);
+void kqtimer_proc_continued(struct proc *p);
void kern_proc_vmmap_resident(struct vm_map *map, struct vm_map_entry *entry,
int *resident_count, bool *super);
void kern_yield(int);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 24, 11:32 PM (4 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24149649
Default Alt Text
D29106.id85258.diff (7 KB)
Attached To
Mode
D29106: Stop posix realtime timer and kqueue EVFILT_TIMER timers around process stop and kill
Attached
Detach File
Event Timeline
Log In to Comment