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 @@ -2322,7 +2322,7 @@ thread_unsuspend(p); PROC_SUNLOCK(p); sigqueue_delete(sigqueue, sig); - goto out; + goto out_cont; } if (action == SIG_CATCH) { /* @@ -2337,7 +2337,7 @@ */ thread_unsuspend(p); PROC_SUNLOCK(p); - goto out; + goto out_cont; } if (prop & SIGPROP_STOP) { @@ -2422,6 +2422,8 @@ PROC_SLOCK(p); thread_unsuspend(p); PROC_SUNLOCK(p); +out_cont: + itimer_proc_continue(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_continue(struct proc *p) +{ + struct timeval ctv; + + PROC_LOCK_ASSERT(p, MA_OWNED); + + if ((p->p_flag2 & P2_ITSTOPPED) != 0) { + 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,7 @@ p->p_flag &= ~(P_STOPPED_TRACE | P_STOPPED_SIG | P_WAITED); thread_unsuspend(p); PROC_SUNLOCK(p); + itimer_proc_continue(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 @@ -825,6 +825,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 */ @@ -1091,6 +1092,7 @@ struct trapframe *); void fork_return(struct thread *, struct trapframe *); int inferior(struct proc *p); +void itimer_proc_continue(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);