From owner-freebsd-arch@FreeBSD.ORG Sat Nov 22 17:06:06 2014 Return-Path: Delivered-To: freebsd-arch@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 37441CCA; Sat, 22 Nov 2014 17:06:06 +0000 (UTC) Received: from kib.kiev.ua (kib.kiev.ua [IPv6:2001:470:d5e7:1::1]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9DE25948; Sat, 22 Nov 2014 17:06:04 +0000 (UTC) Received: from tom.home (kostik@localhost [127.0.0.1]) by kib.kiev.ua (8.14.9/8.14.9) with ESMTP id sAMH5u2K065665 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sat, 22 Nov 2014 19:05:56 +0200 (EET) (envelope-from kostikbel@gmail.com) DKIM-Filter: OpenDKIM Filter v2.9.2 kib.kiev.ua sAMH5u2K065665 Received: (from kostik@localhost) by tom.home (8.14.9/8.14.9/Submit) id sAMH5uuD065664; Sat, 22 Nov 2014 19:05:56 +0200 (EET) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: tom.home: kostik set sender to kostikbel@gmail.com using -f Date: Sat, 22 Nov 2014 19:05:56 +0200 From: Konstantin Belousov To: Andriy Gapon Subject: Re: suspending threads before devices Message-ID: <20141122170556.GY17068@kib.kiev.ua> References: <201203202037.q2KKbNfK037014@svn.freebsd.org> <201411181721.56505.jhb@freebsd.org> <87FFDA99-ADDC-4F56-A3E8-56CCAA544542@bsdimp.com> <1580793.3ynJAbfVom@ralph.baldwin.cx> <20141120142806.GJ17068@kib.kiev.ua> <546F37A3.8090506@FreeBSD.org> <20141121160629.GO17068@kib.kiev.ua> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20141121160629.GO17068@kib.kiev.ua> User-Agent: Mutt/1.5.23 (2014-03-12) X-Spam-Status: No, score=-2.0 required=5.0 tests=ALL_TRUSTED,BAYES_00, DKIM_ADSP_CUSTOM_MED,FREEMAIL_FROM,NML_ADSP_CUSTOM_MED autolearn=no autolearn_force=no version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on tom.home Cc: Jung-uk Kim , "freebsd-arch@freebsd.org" X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 22 Nov 2014 17:06:06 -0000 On Fri, Nov 21, 2014 at 06:06:29PM +0200, Konstantin Belousov wrote: > Below is the current version of the patch. I still have to write the > code to sync local filesystems, I decided to utilize syncer shutdown mode for this. It seems to be easy and does what we need. An interesting corner case are the pagedaemon and vmdaemon. Both of them could generate more writes to the filesystems even after all userspace is stopped and the sync flushed everything. It is more probable for pagedaemon. Might be, it would need a suspend/resume methods in future. Note that bufdaemon does not need suspend, since all dirty buffers are handled by syncer. diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 7ae7d4e..19c33b6 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -289,7 +289,7 @@ kern_execve(td, args, mac_p) args->endp - args->begin_envv); if (p->p_flag & P_HADTHREADS) { PROC_LOCK(p); - if (thread_single(SINGLE_BOUNDARY)) { + if (thread_single(p, SINGLE_BOUNDARY)) { PROC_UNLOCK(p); exec_free_args(args); return (ERESTART); /* Try again later. */ @@ -308,9 +308,9 @@ kern_execve(td, args, mac_p) * force other threads to suicide. */ if (error == 0) - thread_single(SINGLE_EXIT); + thread_single(p, SINGLE_EXIT); else - thread_single_end(); + thread_single_end(p, SINGLE_BOUNDARY); PROC_UNLOCK(p); } if ((td->td_pflags & TDP_EXECVMSPC) != 0) { diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 1e4c095..b58e830 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -206,7 +206,7 @@ exit1(struct thread *td, int rv) * re-check all suspension request, the thread should * either be suspended there or exit. */ - if (!thread_single(SINGLE_EXIT)) + if (!thread_single(p, SINGLE_EXIT)) break; /* diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 62f43ba..80d7f82 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -317,7 +317,7 @@ fork_norfproc(struct thread *td, int flags) if (((p1->p_flag & (P_HADTHREADS|P_SYSTEM)) == P_HADTHREADS) && (flags & (RFCFDG | RFFDG))) { PROC_LOCK(p1); - if (thread_single(SINGLE_BOUNDARY)) { + if (thread_single(p1, SINGLE_BOUNDARY)) { PROC_UNLOCK(p1); return (ERESTART); } @@ -348,7 +348,7 @@ fail: if (((p1->p_flag & (P_HADTHREADS|P_SYSTEM)) == P_HADTHREADS) && (flags & (RFCFDG | RFFDG))) { PROC_LOCK(p1); - thread_single_end(); + thread_single_end(p1, SINGLE_BOUNDARY); PROC_UNLOCK(p1); } return (error); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 495139f..1a11655 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2893,3 +2893,128 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_OSREL, osrel, CTLFLAG_RW | static SYSCTL_NODE(_kern_proc, KERN_PROC_SIGTRAMP, sigtramp, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_sigtramp, "Process signal trampoline location"); + +void +stop_all_proc(void) +{ + struct proc *cp, *p; + int r; + bool restart, seen_stopped, stopped_some; + + cp = curproc; + /* + * stop_all_proc() assumes that all process which have + * usermode must be stopped, except current process, for + * obvious reasons. Since other threads in the process + * establishing global stop could unstop something, disable + * calls from multithreaded processes as precaution. The + * service must not be user-callable anyway. + */ + KASSERT((cp->p_flag & P_HADTHREADS) == 0 || + (cp->p_flag & P_KTHREAD) != 0, ("mt stop_all_proc")); + +allproc_loop: + sx_xlock(&allproc_lock); + seen_stopped = stopped_some = restart = false; + LIST_REMOVE(cp, p_list); + LIST_INSERT_HEAD(&allproc, cp, p_list); + for (;;) { + p = LIST_NEXT(cp, p_list); + if (p == NULL) + break; + LIST_REMOVE(cp, p_list); + LIST_INSERT_AFTER(p, cp, p_list); + PROC_LOCK(p); + if ((p->p_flag & (P_KTHREAD | P_SYSTEM | + P_TOTAL_STOP)) != 0) { + PROC_UNLOCK(p); + continue; + } + if (P_SHOULDSTOP(p)) { + /* + * Stopped processes are only tolerated when + * there are no other processes which might + * continue them. + */ + seen_stopped = true; + PROC_UNLOCK(p); + continue; + } + _PHOLD(p); + sx_xunlock(&allproc_lock); + r = thread_single(p, SINGLE_ALLPROC); + if (r != 0) + restart = true; + else + stopped_some = true; + _PRELE(p); + PROC_UNLOCK(p); + sx_xlock(&allproc_lock); + } + sx_xunlock(&allproc_lock); + if (restart || (seen_stopped && stopped_some)) { + kern_yield(PRI_USER); + goto allproc_loop; + } +} + +void +resume_all_proc(void) +{ + struct proc *cp, *p; + + cp = curproc; + sx_xlock(&allproc_lock); + LIST_REMOVE(cp, p_list); + LIST_INSERT_HEAD(&allproc, cp, p_list); + for (;;) { + p = LIST_NEXT(cp, p_list); + if (p == NULL) + break; + LIST_REMOVE(cp, p_list); + LIST_INSERT_AFTER(p, cp, p_list); + PROC_LOCK(p); + if ((p->p_flag & P_TOTAL_STOP) != 0) { + sx_xunlock(&allproc_lock); + _PHOLD(p); + thread_single_end(p, SINGLE_ALLPROC); + _PRELE(p); + PROC_UNLOCK(p); + sx_xlock(&allproc_lock); + } else { + PROC_UNLOCK(p); + } + } + sx_xunlock(&allproc_lock); +} + +#define TOTAL_STOP_DEBUG 1 +#ifdef TOTAL_STOP_DEBUG +volatile static int ap_resume; +#include + +static int +sysctl_debug_stop_all_proc(SYSCTL_HANDLER_ARGS) +{ + int error, val; + + val = 0; + ap_resume = 0; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + if (val != 0) { + stop_all_proc(); + syncer_suspend(); + while (ap_resume == 0) + ; + syncer_resume(); + resume_all_proc(); + } + return (0); +} + +SYSCTL_PROC(_debug, OID_AUTO, stop_all_proc, CTLTYPE_INT | CTLFLAG_RW | + CTLFLAG_MPSAFE, (void *)&ap_resume, 0, sysctl_debug_stop_all_proc, "I", + ""); +#endif diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5cdc2ce..97245fb 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2471,7 +2471,7 @@ ptracestop(struct thread *td, int sig) cv_broadcast(&p->p_dbgwait); } stopme: - thread_suspend_switch(td); + thread_suspend_switch(td, p); if (p->p_xthread == td) p->p_xthread = NULL; if (!(p->p_flag & P_TRACED)) @@ -2730,7 +2730,7 @@ issignal(struct thread *td) p->p_xstat = sig; PROC_SLOCK(p); sig_suspend_threads(td, p, 0); - thread_suspend_switch(td); + thread_suspend_switch(td, p); PROC_SUNLOCK(p); mtx_lock(&ps->ps_mtx); break; @@ -2919,7 +2919,7 @@ sigexit(td, sig) * XXX If another thread attempts to single-thread before us * (e.g. via fork()), we won't get a dump at all. */ - if ((sigprop(sig) & SA_CORE) && (thread_single(SINGLE_NO_EXIT) == 0)) { + if ((sigprop(sig) & SA_CORE) && thread_single(p, SINGLE_NO_EXIT) == 0) { p->p_sig = sig; /* * Log signals which would cause core dumps diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index ec084ed..d10e1f3 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$"); SDT_PROVIDER_DECLARE(proc); SDT_PROBE_DEFINE(proc, , , lwp__exit); - /* * thread related storage. */ @@ -446,7 +445,7 @@ thread_exit(void) if (p->p_numthreads == p->p_suspcount) { thread_lock(p->p_singlethread); wakeup_swapper = thread_unsuspend_one( - p->p_singlethread); + p->p_singlethread, p); thread_unlock(p->p_singlethread); if (wakeup_swapper) kick_proc0(); @@ -575,13 +574,54 @@ calc_remaining(struct proc *p, int mode) remaining = p->p_numthreads; else if (mode == SINGLE_BOUNDARY) remaining = p->p_numthreads - p->p_boundary_count; - else if (mode == SINGLE_NO_EXIT) + else if (mode == SINGLE_NO_EXIT || mode == SINGLE_ALLPROC) remaining = p->p_numthreads - p->p_suspcount; else panic("calc_remaining: wrong mode %d", mode); return (remaining); } +static int +remain_for_mode(int mode) +{ + + return (mode == SINGLE_ALLPROC ? 0 : 1); +} + +static int +weed_inhib(int mode, struct thread *td2, struct proc *p) +{ + int wakeup_swapper; + + PROC_LOCK_ASSERT(p, MA_OWNED); + PROC_SLOCK_ASSERT(p, MA_OWNED); + THREAD_LOCK_ASSERT(td2, MA_OWNED); + + wakeup_swapper = 0; + switch (mode) { + case SINGLE_EXIT: + if (TD_IS_SUSPENDED(td2)) + wakeup_swapper |= thread_unsuspend_one(td2, p); + if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) + wakeup_swapper |= sleepq_abort(td2, EINTR); + break; + case SINGLE_BOUNDARY: + if (TD_IS_SUSPENDED(td2) && (td2->td_flags & TDF_BOUNDARY) == 0) + wakeup_swapper |= thread_unsuspend_one(td2, p); + if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) + wakeup_swapper |= sleepq_abort(td2, ERESTART); + break; + case SINGLE_ALLPROC: + case SINGLE_NO_EXIT: + if (TD_IS_SUSPENDED(td2) && (td2->td_flags & TDF_BOUNDARY) == 0) + wakeup_swapper |= thread_unsuspend_one(td2, p); + if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) + wakeup_swapper |= sleepq_abort(td2, ERESTART); + break; + } + return (wakeup_swapper); +} + /* * Enforce single-threading. * @@ -596,19 +636,29 @@ calc_remaining(struct proc *p, int mode) * any sleeping threads that are interruptable. (PCATCH). */ int -thread_single(int mode) +thread_single(struct proc *p, int mode) { struct thread *td; struct thread *td2; - struct proc *p; int remaining, wakeup_swapper; td = curthread; - p = td->td_proc; + KASSERT(mode == SINGLE_EXIT || mode == SINGLE_BOUNDARY || + mode == SINGLE_ALLPROC || mode == SINGLE_NO_EXIT, + ("invalid mode %d", mode)); + /* + * If allowing non-ALLPROC singlethreading for non-curproc + * callers, calc_remaining() and remain_for_mode() should be + * adjusted to also account for td->td_proc != p. For now + * this is not implemented because it is not used. + */ + KASSERT((mode == SINGLE_ALLPROC && td->td_proc != p) || + (mode != SINGLE_ALLPROC && td->td_proc == p), + ("mode %d proc %p curproc %p", mode, p, td->td_proc)); mtx_assert(&Giant, MA_NOTOWNED); PROC_LOCK_ASSERT(p, MA_OWNED); - if ((p->p_flag & P_HADTHREADS) == 0) + if ((p->p_flag & P_HADTHREADS) == 0 && mode != SINGLE_ALLPROC) return (0); /* Is someone already single threading? */ @@ -625,11 +675,13 @@ thread_single(int mode) else p->p_flag &= ~P_SINGLE_BOUNDARY; } + if (mode == SINGLE_ALLPROC) + p->p_flag |= P_TOTAL_STOP; p->p_flag |= P_STOPPED_SINGLE; PROC_SLOCK(p); p->p_singlethread = td; remaining = calc_remaining(p, mode); - while (remaining != 1) { + while (remaining != remain_for_mode(mode)) { if (P_SHOULDSTOP(p) != P_STOPPED_SINGLE) goto stopme; wakeup_swapper = 0; @@ -638,41 +690,8 @@ thread_single(int mode) continue; thread_lock(td2); td2->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK; - if (TD_IS_INHIBITED(td2)) { - switch (mode) { - case SINGLE_EXIT: - if (TD_IS_SUSPENDED(td2)) - wakeup_swapper |= - thread_unsuspend_one(td2); - if (TD_ON_SLEEPQ(td2) && - (td2->td_flags & TDF_SINTR)) - wakeup_swapper |= - sleepq_abort(td2, EINTR); - break; - case SINGLE_BOUNDARY: - if (TD_IS_SUSPENDED(td2) && - !(td2->td_flags & TDF_BOUNDARY)) - wakeup_swapper |= - thread_unsuspend_one(td2); - if (TD_ON_SLEEPQ(td2) && - (td2->td_flags & TDF_SINTR)) - wakeup_swapper |= - sleepq_abort(td2, ERESTART); - break; - case SINGLE_NO_EXIT: - if (TD_IS_SUSPENDED(td2) && - !(td2->td_flags & TDF_BOUNDARY)) - wakeup_swapper |= - thread_unsuspend_one(td2); - if (TD_ON_SLEEPQ(td2) && - (td2->td_flags & TDF_SINTR)) - wakeup_swapper |= - sleepq_abort(td2, ERESTART); - break; - default: - break; - } - } + if (TD_IS_INHIBITED(td2)) + wakeup_swapper |= weed_inhib(mode, td2, p); #ifdef SMP else if (TD_IS_RUNNING(td2) && td != td2) { forward_signal(td2); @@ -687,7 +706,7 @@ thread_single(int mode) /* * Maybe we suspended some threads.. was it enough? */ - if (remaining == 1) + if (remaining == remain_for_mode(mode)) break; stopme: @@ -695,7 +714,7 @@ stopme: * Wake us up when everyone else has suspended. * In the mean time we suspend as well. */ - thread_suspend_switch(td); + thread_suspend_switch(td, p); remaining = calc_remaining(p, mode); } if (mode == SINGLE_EXIT) { @@ -821,7 +840,7 @@ thread_suspend_check(int return_instead) if (p->p_numthreads == p->p_suspcount + 1) { thread_lock(p->p_singlethread); wakeup_swapper = - thread_unsuspend_one(p->p_singlethread); + thread_unsuspend_one(p->p_singlethread, p); thread_unlock(p->p_singlethread); if (wakeup_swapper) kick_proc0(); @@ -854,11 +873,9 @@ thread_suspend_check(int return_instead) } void -thread_suspend_switch(struct thread *td) +thread_suspend_switch(struct thread *td, struct proc *p) { - struct proc *p; - p = td->td_proc; KASSERT(!TD_IS_SUSPENDED(td), ("already suspended")); PROC_LOCK_ASSERT(p, MA_OWNED); PROC_SLOCK_ASSERT(p, MA_OWNED); @@ -866,8 +883,10 @@ thread_suspend_switch(struct thread *td) * We implement thread_suspend_one in stages here to avoid * dropping the proc lock while the thread lock is owned. */ - thread_stopped(p); - p->p_suspcount++; + if (p == td->td_proc) { + thread_stopped(p); + p->p_suspcount++; + } PROC_UNLOCK(p); thread_lock(td); td->td_flags &= ~TDF_NEEDSUSPCHK; @@ -897,15 +916,16 @@ thread_suspend_one(struct thread *td) } int -thread_unsuspend_one(struct thread *td) +thread_unsuspend_one(struct thread *td, struct proc *p) { - struct proc *p = td->td_proc; - PROC_SLOCK_ASSERT(p, MA_OWNED); THREAD_LOCK_ASSERT(td, MA_OWNED); KASSERT(TD_IS_SUSPENDED(td), ("Thread not suspended")); TD_CLR_SUSPENDED(td); - p->p_suspcount--; + if (td->td_proc == p) { + PROC_SLOCK_ASSERT(p, MA_OWNED); + p->p_suspcount--; + } return (setrunnable(td)); } @@ -925,7 +945,7 @@ thread_unsuspend(struct proc *p) FOREACH_THREAD_IN_PROC(p, td) { thread_lock(td); if (TD_IS_SUSPENDED(td)) { - wakeup_swapper |= thread_unsuspend_one(td); + wakeup_swapper |= thread_unsuspend_one(td, p); } thread_unlock(td); } @@ -936,9 +956,12 @@ thread_unsuspend(struct proc *p) * threading request. Now we've downgraded to single-threaded, * let it continue. */ - thread_lock(p->p_singlethread); - wakeup_swapper = thread_unsuspend_one(p->p_singlethread); - thread_unlock(p->p_singlethread); + if (p->p_singlethread->td_proc == p) { + thread_lock(p->p_singlethread); + wakeup_swapper = thread_unsuspend_one( + p->p_singlethread, p); + thread_unlock(p->p_singlethread); + } } if (wakeup_swapper) kick_proc0(); @@ -948,16 +971,20 @@ thread_unsuspend(struct proc *p) * End the single threading mode.. */ void -thread_single_end(void) +thread_single_end(struct proc *p, int mode) { struct thread *td; - struct proc *p; int wakeup_swapper; - td = curthread; - p = td->td_proc; + KASSERT(mode == SINGLE_EXIT || mode == SINGLE_BOUNDARY || + mode == SINGLE_ALLPROC || mode == SINGLE_NO_EXIT, + ("invalid mode %d", mode)); PROC_LOCK_ASSERT(p, MA_OWNED); - p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT | P_SINGLE_BOUNDARY); + KASSERT((mode == SINGLE_ALLPROC && (p->p_flag & P_TOTAL_STOP) != 0) || + (mode != SINGLE_ALLPROC && (p->p_flag & P_TOTAL_STOP) == 0), + ("mode %d does not match P_TOTAL_STOP", mode)); + p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT | P_SINGLE_BOUNDARY | + P_TOTAL_STOP); PROC_SLOCK(p); p->p_singlethread = NULL; wakeup_swapper = 0; @@ -967,11 +994,11 @@ thread_single_end(void) * on the process. The single threader must be allowed * to continue however as this is a bad place to stop. */ - if ((p->p_numthreads != 1) && (!P_SHOULDSTOP(p))) { + if (p->p_numthreads != remain_for_mode(mode) && !P_SHOULDSTOP(p)) { FOREACH_THREAD_IN_PROC(p, td) { thread_lock(td); if (TD_IS_SUSPENDED(td)) { - wakeup_swapper |= thread_unsuspend_one(td); + wakeup_swapper |= thread_unsuspend_one(td, p); } thread_unlock(td); } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 345aad6..b4dde06 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1773,6 +1773,8 @@ sync_vnode(struct synclist *slp, struct bufobj **bo, struct thread *td) return (0); } +static int first_printf = 1; + /* * System filesystem synchronizer daemon. */ @@ -1791,7 +1793,6 @@ sched_sync(void) last_work_seen = 0; syncer_final_iter = 0; - first_printf = 1; syncer_state = SYNCER_RUNNING; starttime = time_uptime; td->td_pflags |= TDP_NORUNNINGBUF; @@ -1955,6 +1956,25 @@ syncer_shutdown(void *arg, int howto) kproc_shutdown(arg, howto); } +void +syncer_suspend(void) +{ + + syncer_shutdown(updateproc, 0); +} + +void +syncer_resume(void) +{ + + mtx_lock(&sync_mtx); + first_printf = 1; + syncer_state = SYNCER_RUNNING; + mtx_unlock(&sync_mtx); + cv_broadcast(&sync_wakeup); + kproc_resume(updateproc); +} + /* * Reassign a buffer from one vnode to another. * Used to assign file specific control information diff --git a/sys/sys/mount.h b/sys/sys/mount.h index c4e1145..07b9c7a 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -917,6 +917,9 @@ vfs_uninit_t vfs_stduninit; vfs_extattrctl_t vfs_stdextattrctl; vfs_sysctl_t vfs_stdsysctl; +void syncer_suspend(void); +void syncer_resume(void); + #else /* !_KERNEL */ #include diff --git a/sys/sys/proc.h b/sys/sys/proc.h index fac0915..2163543 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -635,7 +635,7 @@ struct proc { #define P_SINGLE_BOUNDARY 0x400000 /* Threads should suspend at user boundary. */ #define P_HWPMC 0x800000 /* Process is using HWPMCs */ #define P_JAILED 0x1000000 /* Process is in jail. */ -#define P_UNUSED1 0x2000000 +#define P_TOTAL_STOP 0x2000000 /* Stopped in proc_stop_total. */ #define P_INEXEC 0x4000000 /* Process is in execve(). */ #define P_STATCHILD 0x8000000 /* Child process stopped or exited. */ #define P_INMEM 0x10000000 /* Loaded into memory. */ @@ -696,6 +696,7 @@ struct proc { #define SINGLE_NO_EXIT 0 #define SINGLE_EXIT 1 #define SINGLE_BOUNDARY 2 +#define SINGLE_ALLPROC 3 #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_PARGS); @@ -945,22 +946,25 @@ void thread_exit(void) __dead2; void thread_free(struct thread *td); void thread_link(struct thread *td, struct proc *p); void thread_reap(void); -int thread_single(int how); -void thread_single_end(void); +int thread_single(struct proc *p, int how); +void thread_single_end(struct proc *p, int how); void thread_stash(struct thread *td); void thread_stopped(struct proc *p); void childproc_stopped(struct proc *child, int reason); void childproc_continued(struct proc *child); void childproc_exited(struct proc *child); int thread_suspend_check(int how); -void thread_suspend_switch(struct thread *); +void thread_suspend_switch(struct thread *, struct proc *p); void thread_suspend_one(struct thread *td); void thread_unlink(struct thread *td); void thread_unsuspend(struct proc *p); -int thread_unsuspend_one(struct thread *td); +int thread_unsuspend_one(struct thread *td, struct proc *p); void thread_wait(struct proc *p); struct thread *thread_find(struct proc *p, lwpid_t tid); +void stop_all_proc(void); +void resume_all_proc(void); + static __inline int curthread_pflags_set(int flags) {