ck_epoch: Remove redundant e + 2 observation.

This inefficiency was introduced in the overhaul of
the ck_epoch API.

Synchronize is executed with respect to e. At e + 1,
references can only exist to objects logically deleted
at e or e + 1. At e + 2, however, references can only exist to
objects logically deleted at e + 1 and e + 2. In the case that a
thread observes an out of date epoch value, an increment to the
global epoch would fail as the active bit is ordered with respect
to the memory barrier in synchronize. In the case that a protected
section begins after the memory barrier, then it is guaranteed
to not acquire the hazardous reference.

This does not change granularity of deferral lists, however.
There is still a requirement of 3 deferral lists on the fast path
(4 in ck_epoch for fast path purposes) as at any moment, any given
deferral list for value e can contain references to objects with
active references from both e and e - 1.
ck_pring
Samy Al Bahra 11 years ago
parent b17706f967
commit c4849aeaae

@ -337,7 +337,7 @@ ck_epoch_synchronize(struct ck_epoch *global, struct ck_epoch_record *record)
* we are at a grace period.
*/
if (active == false)
goto leave;
break;
/*
* Increment current epoch. CAS semantics are used to eliminate
@ -364,34 +364,10 @@ reload:
* generation. We can actually avoid an addtional scan step
* at this point.
*/
goto leave;
}
}
/*
* At this point, we are at e + 2. If all threads have observed
* this epoch value, then no threads are at e + 1 and no references
* could exist to the snapshot of e observed at the time this
* function was called.
*/
while (cr = ck_epoch_scan(global, cr, delta, &active), cr != NULL) {
ck_pr_stall();
/*
* If the epoch value was changed from underneath us then
* our epoch must have been observed at some point.
*
* If all threads have gone inactive, we are also at a grace
* period as any reads succeeding this call to synchronize
* will imply a full memory barrier (logically deleted objects
* will not be visible).
*/
epoch = ck_pr_load_uint(&global->epoch);
if ((epoch != delta) | (active == false))
break;
}
}
leave:
record->epoch = delta;
return;
}

Loading…
Cancel
Save