On Tue, Dec 01, 2020 at 10:46:00AM -0300, Martin Pieuchot wrote:
> On 01/12/20(Tue) 21:47, Jonathan Matthew wrote:
> > On Tue, Dec 01, 2020 at 10:31:43AM +0100, Claudio Jeker wrote:
> > > On Mon, Nov 30, 2020 at 07:10:47PM -0300, Martin Pieuchot wrote:
> > > > Every multi-threaded process keeps a list of threads in `ps_threads'.
> > > > This list is iterated in interrupt and process context which makes it
> > > > complicated to protect it with a rwlock.
> > > > 
> > > > One of the places where such iteration is done is inside the tsleep(9)
> > > > routines, directly in single_thread_check() or via CURSIG().  In order
> > > > to take this code path out of the KERNEL_LOCK(), claudio@ proposed to
> > > > use SMR_TAILQ.  This has the advantage of not introducing lock
> > > > dependencies and allow us to address every iteration one-by-one.
> > > > 
> > > > Diff below is a first step into this direction, it replaces the existing
> > > > TAILQ_* macros by the locked version of SMR_TAILQ*.  This is mostly 
> > > > lifted
> > > > from claudio@'s diff and should not introduce any side effect.
> > > > 
> > > > ok?
> > > > 
> > > > diff --git sys/uvm/uvm_glue.c sys/uvm/uvm_glue.c
> > > > index 390307c4c81..40a10e4c1c5 100644
> > > > --- sys/uvm/uvm_glue.c
> > > > +++ sys/uvm/uvm_glue.c
> > > > @@ -369,7 +369,7 @@ uvm_swapout_threads(void)
> > > >                  * the smallest p_slptime
> > > >                  */
> > > >                 slpp = NULL;
> > > > -               TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) {
> > > > +               SMR_TAILQ_FOREACH_LOCKED(p, &pr->ps_threads, 
> > > > p_thr_link) {
> > > >                         switch (p->p_stat) {
> > > >                         case SRUN:
> > > >                         case SONPROC:
> > > > 
> > > 
> > > Why did you not include the smr_call() to safely free struct proc in this
> > > diff?
> 
> So we can discuss it separately,  I'm happy to do it now :)
> 
> > I was wondering about this too.  Freeing the struct proc is already delayed
> > by some amount since it happens in the reaper or in the parent process, does
> > it make sense to combine that with the SMR wait?
> 
> exit1() for a multi-threaded process does the following:
> 
>       atomic_setbits_int(&p->p_flag, P_WEXIT);
> 
>       single_thread_check(p, 0);  // directly or via single_thread_set()
> 
>       SMR_TAILQ_REMOVE_LOCKED(&pr->ps_threads, p, p_thr_link);
> 
> 
> Note that exit1() can't be called in parallel.
> 
> If exit1() is called with EXIT_NORMAL, the current thread will start by
> setting `ps_single' then iterate over `ps_thread'.  This is done before
> updating `ps_thread' so there's no race in that case.
> 
> If exit1() is called with EXIT_THREAD, the current thread might end up
> removing itself from `ps_thread' while another one is iterating over it.
> Since we're currently concerned about the iteration in single_thread_set()
> notice that `P_WEXIT' is checked first.  So if my understanding is correct
> is should be enough to do the following:
> 
>       SMR_TAILQ_REMOVE_LOCKED(&pr->ps_threads, p, p_thr_link);
>       smr_barrier();
> 
> That would delays exit1() a bit but doesn't involve callback which is
> IMHO simpler.
> 
> Did I miss anything?

Did you run a make build with that smr_barrier() in it and checked that it
does not cause a slow down? I am sceptical, smr_barrier() is a very slow
construct which introduces large delays and should be avoided whenever
possible.

-- 
:wq Claudio

Reply via email to