On 18/03/2016 17:18, Alex Bennée wrote: > + > + /* Protected by tb_lock. */
Only writes are protected by tb_lock. Read happen outside the lock. Reads are not quite thread safe yet, because of tb_flush. In order to fix that, there's either the async_safe_run() mechanism from Fred or preferrably the code generation buffer could be moved under RCU. Because tb_flush is really rare, my suggestion is simply to allocate two code generation buffers and do something like static int which_buffer_is_in_use_bit_mask = 1; ... /* in tb_flush */ assert (which_buffer_is_in_use_bit_mask != 3); if (which_buffer_is_in_use_bit_mask == 1) { which_buffer_is_in_use_bit_mask |= 2; call_rcu(function doing which_buffer_is_in_use_bit_mask &= ~1); point TCG to second buffer } else if (which_buffer_is_in_use_bit_mask == 2) { which_buffer_is_in_use_bit_mask |= 1; call_rcu(function doing which_buffer_is_in_use_bit_mask &= ~2); point TCG to first buffer } Basically, we just assert that call_rcu makes at least one pass between two tb_flushes. All this is also a prerequisite for patch 1. Paolo > struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; > +