aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-03-11 08:16:51 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-04-23 11:14:09 +0000
commit057e390dadaf942bb2bfb66a2c3d68f79ff6506a (patch)
tree59cc66901f98a6bd7c36ed81730b196f4385475b
parent6d608fc5ab9c6c8eedc85d739b4e58b21c16d19d (diff)
Stop arming realtime posix process timers on suspend or terminate
(cherry picked from commit 4d27d8d2f3b8ae4ef3efc86b220c7ff2dbdbac5a)
-rw-r--r--sys/kern/kern_time.c48
-rw-r--r--sys/sys/timers.h1
2 files changed, 40 insertions, 9 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 3010ee326105..d3b19111b0f3 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -895,6 +895,8 @@ void
itimer_proc_continue(struct proc *p)
{
struct timeval ctv;
+ struct itimer *it;
+ int id;
PROC_LOCK_ASSERT(p, MA_OWNED);
@@ -906,6 +908,23 @@ itimer_proc_continue(struct proc *p)
else
realitexpire_reset_callout(p, NULL);
}
+
+ if (p->p_itimers != NULL) {
+ for (id = 3; id < TIMER_MAX; id++) {
+ it = p->p_itimers->its_timers[id];
+ if (it == NULL)
+ continue;
+ if ((it->it_flags & ITF_PSTOPPED) != 0) {
+ ITIMER_LOCK(it);
+ if ((it->it_flags & ITF_PSTOPPED) != 0) {
+ it->it_flags &= ~ITF_PSTOPPED;
+ if ((it->it_flags & ITF_DELETING) == 0)
+ realtimer_expire(it);
+ }
+ ITIMER_UNLOCK(it);
+ }
+ }
+ }
}
/*
@@ -1651,6 +1670,7 @@ realtimer_expire(void *arg)
struct timespec cts, ts;
struct timeval tv;
struct itimer *it;
+ struct proc *p;
uint64_t interval, now, overruns, value;
it = (struct itimer *)arg;
@@ -1689,10 +1709,15 @@ realtimer_expire(void *arg)
timespecclear(&it->it_time.it_value);
}
if (timespecisset(&it->it_time.it_value)) {
- timespecsub(&it->it_time.it_value, &cts, &ts);
- TIMESPEC_TO_TIMEVAL(&tv, &ts);
- callout_reset(&it->it_callout, tvtohz(&tv),
- realtimer_expire, it);
+ p = it->it_proc;
+ if (P_SHOULDSTOP(p) || P_KILLED(p)) {
+ it->it_flags |= ITF_PSTOPPED;
+ } else {
+ timespecsub(&it->it_time.it_value, &cts, &ts);
+ TIMESPEC_TO_TIMEVAL(&tv, &ts);
+ callout_reset(&it->it_callout, tvtohz(&tv),
+ realtimer_expire, it);
+ }
}
itimer_enter(it);
ITIMER_UNLOCK(it);
@@ -1700,11 +1725,16 @@ realtimer_expire(void *arg)
ITIMER_LOCK(it);
itimer_leave(it);
} else if (timespecisset(&it->it_time.it_value)) {
- ts = it->it_time.it_value;
- timespecsub(&ts, &cts, &ts);
- TIMESPEC_TO_TIMEVAL(&tv, &ts);
- callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire,
- it);
+ p = it->it_proc;
+ if (P_SHOULDSTOP(p) || P_KILLED(p)) {
+ it->it_flags |= ITF_PSTOPPED;
+ } else {
+ ts = it->it_time.it_value;
+ timespecsub(&ts, &cts, &ts);
+ TIMESPEC_TO_TIMEVAL(&tv, &ts);
+ callout_reset(&it->it_callout, tvtohz(&tv),
+ realtimer_expire, it);
+ }
}
}
diff --git a/sys/sys/timers.h b/sys/sys/timers.h
index aa1912149452..5d6f0c95afa2 100644
--- a/sys/sys/timers.h
+++ b/sys/sys/timers.h
@@ -82,6 +82,7 @@ struct itimer {
#define ITF_DELETING 0x01
#define ITF_WANTED 0x02
+#define ITF_PSTOPPED 0x04
#define ITCF_ONWORKLIST 0x01