Why is there e_drain_sx and e_drain_mtx?

Hans Petter Selasky hps at selasky.org
Tue Dec 29 11:07:28 UTC 2020


On 12/29/20 11:49 AM, Sebastian Huber wrote:
> Hello,
> 
> in the epoch based reclamation implementation we have
> 
> struct epoch {
>          struct ck_epoch e_epoch __aligned(EPOCH_ALIGN);
>          epoch_record_t e_pcpu_record;
>          int     e_in_use;
>          int     e_flags;
>          struct sx e_drain_sx;
>          struct mtx e_drain_mtx;
>          volatile int e_drain_count;
>          const char *e_name;
> };
> 
> The e_drain_sx and e_drain_mtx are only used in
> 
> void
> epoch_drain_callbacks(epoch_t epoch)
> {
> ...
>      DROP_GIANT();
> 
>      sx_xlock(&epoch->e_drain_sx);
>      mtx_lock(&epoch->e_drain_mtx);
> 
> ...
> 
>      mtx_unlock(&epoch->e_drain_mtx);
>      sx_xunlock(&epoch->e_drain_sx);
> 
>      PICKUP_GIANT();
> }
> 
> Why is there a combination of a shared/exclusive lock and a mutex used 
> like this? Why is a single mutex insufficient?
> 

Hi Sebastian,

The sx_xlock() is there because the operation may sleep and mutexes must 
be dropped when sleeping. We only allow one drain at a time.

The mtx_lock() is there to make the operation atomic with regards to the 
msleep/wakeup sequence. Search for the use of e_drain_mtx . Else the 
msleep and wakeup calls may miss eachother.

How is the porting going otherwise? Do you see any performance 
improvements using EPOCH?

--HPS


More information about the freebsd-hackers mailing list