epoch_block_wait: don't check TD_RUNNING
struct epoch_thread is not type safe (stack allocated) and thus cannot be dereferenced from another CPU Reported by: novel@
This commit is contained in:
parent
456a4ad51e
commit
9fec45d8e5
@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
static MALLOC_DEFINE(M_EPOCH, "epoch", "epoch based reclamation");
|
static MALLOC_DEFINE(M_EPOCH, "epoch", "epoch based reclamation");
|
||||||
|
|
||||||
/* arbitrary --- needs benchmarking */
|
/* arbitrary --- needs benchmarking */
|
||||||
#define MAX_ADAPTIVE_SPIN 1000
|
#define MAX_ADAPTIVE_SPIN 100
|
||||||
#define MAX_EPOCHS 64
|
#define MAX_EPOCHS 64
|
||||||
|
|
||||||
CTASSERT(sizeof(ck_epoch_entry_t) == sizeof(struct epoch_context));
|
CTASSERT(sizeof(ck_epoch_entry_t) == sizeof(struct epoch_context));
|
||||||
@ -240,24 +240,38 @@ epoch_block_handler_preempt(struct ck_epoch *global __unused, ck_epoch_record_t
|
|||||||
locksheld = td->td_locks;
|
locksheld = td->td_locks;
|
||||||
spincount = 0;
|
spincount = 0;
|
||||||
counter_u64_add(block_count, 1);
|
counter_u64_add(block_count, 1);
|
||||||
|
/*
|
||||||
|
* We lost a race and there's no longer any threads
|
||||||
|
* on the CPU in an epoch section.
|
||||||
|
*/
|
||||||
|
if (TAILQ_EMPTY(&record->er_tdlist))
|
||||||
|
return;
|
||||||
|
|
||||||
if (record->er_cpuid != curcpu) {
|
if (record->er_cpuid != curcpu) {
|
||||||
/*
|
/*
|
||||||
* If the head of the list is running, we can wait for it
|
* If the head of the list is running, we can wait for it
|
||||||
* to remove itself from the list and thus save us the
|
* to remove itself from the list and thus save us the
|
||||||
* overhead of a migration
|
* overhead of a migration
|
||||||
*/
|
*/
|
||||||
if ((tdwait = TAILQ_FIRST(&record->er_tdlist)) != NULL &&
|
gen = record->er_gen;
|
||||||
TD_IS_RUNNING(tdwait->et_td)) {
|
thread_unlock(td);
|
||||||
gen = record->er_gen;
|
/*
|
||||||
thread_unlock(td);
|
* We can't actually check if the waiting thread is running
|
||||||
do {
|
* so we simply poll for it to exit before giving up and
|
||||||
cpu_spinwait();
|
* migrating.
|
||||||
} while (tdwait == TAILQ_FIRST(&record->er_tdlist) &&
|
*/
|
||||||
gen == record->er_gen && TD_IS_RUNNING(tdwait->et_td) &&
|
do {
|
||||||
spincount++ < MAX_ADAPTIVE_SPIN);
|
cpu_spinwait();
|
||||||
thread_lock(td);
|
} while (!TAILQ_EMPTY(&record->er_tdlist) &&
|
||||||
|
gen == record->er_gen &&
|
||||||
|
spincount++ < MAX_ADAPTIVE_SPIN);
|
||||||
|
thread_lock(td);
|
||||||
|
/*
|
||||||
|
* If the generation has changed we can poll again
|
||||||
|
* otherwise we need to migrate.
|
||||||
|
*/
|
||||||
|
if (gen != record->er_gen)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Being on the same CPU as that of the record on which
|
* Being on the same CPU as that of the record on which
|
||||||
* we need to wait allows us access to the thread
|
* we need to wait allows us access to the thread
|
||||||
|
Loading…
Reference in New Issue
Block a user