diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2021-03-11 08:16:51 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2021-04-23 11:14:09 +0000 |
| commit | 057e390dadaf942bb2bfb66a2c3d68f79ff6506a (patch) | |
| tree | 59cc66901f98a6bd7c36ed81730b196f4385475b | |
| parent | 6d608fc5ab9c6c8eedc85d739b4e58b21c16d19d (diff) | |
Stop arming realtime posix process timers on suspend or terminate
(cherry picked from commit 4d27d8d2f3b8ae4ef3efc86b220c7ff2dbdbac5a)
| -rw-r--r-- | sys/kern/kern_time.c | 48 | ||||
| -rw-r--r-- | sys/sys/timers.h | 1 |
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 |
