On Sun, Aug 23, 2015 at 18:24:55 -0700, Paolo Bonzini wrote: > On 23/08/2015 17:24, Emilio G. Cota wrote: > > This is similar in intent to the async_safe_work mechanism. The main > > differences are: > > > > - Work is run on a single CPU thread *after* all others are put to sleep > > > > - Sleeping threads are woken up by the worker thread upon completing its job > > > > - A flag as been added to tcg_ctx so that only one thread can schedule > > work at a time. The flag is checked every time tb_lock is acquired. > > > > - Handles the possibility of CPU threads being created after the existing > > CPUs are put to sleep. This is easily triggered with many threads on > > a many-core host in usermode. > > > > - Works for both softmmu and usermode > > > > Signed-off-by: Emilio G. Cota <c...@braap.org> > > I think this is a duplicate of the existing run_on_cpu code. If needed > in user-mode emulation, it should be extracted out of cpus.c.
They're similar, yes. > Also I think it is dangerous (prone to deadlocks) to wait for other CPUs > with synchronize_cpu and condvar. The key to avoid deadlocks is not to hold any locks that might be acquired within an RCU read critical section when calling synchronize_rcu(). The condvars are for the sleeping threads so that they can be woken up; sleepers don't call synchronize_rcu(). > I would much rather prefer to _halt_ > the CPUs if there is pending work, and keep it halted like this: > > static inline bool cpu_has_work(CPUState *cpu) > { > CPUClass *cc = CPU_GET_CLASS(cpu); > > + if (tcg_ctx.tb_ctx.tcg_has_work) { > + return false; > + } > g_assert(cc->has_work); > return cc->has_work(cpu); > } > > You can then run flush_queued_work from linux-user/main.c (and > bsd-user/main.c) when cpu_exec returns EXCP_HALTED. OK. Will try something like this. Emilio