Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/mp_ring.c
Show First 20 Lines • Show All 321 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Enqueue n items and maybe drain the ring for some time. | * Enqueue n items and maybe drain the ring for some time. | ||||
* | * | ||||
* Returns an errno. | * Returns an errno. | ||||
*/ | */ | ||||
#ifdef NO_64BIT_ATOMICS | #ifdef NO_64BIT_ATOMICS | ||||
int | int | ||||
ifmp_ring_enqueue(struct ifmp_ring *r, void **items, int n, int budget) | ifmp_ring_enqueue(struct ifmp_ring *r, void **items, int n, int budget, int abdicate) | ||||
{ | { | ||||
union ring_state os, ns; | union ring_state os, ns; | ||||
uint16_t pidx_start, pidx_stop; | uint16_t pidx_start, pidx_stop; | ||||
int i; | int i; | ||||
MPASS(items != NULL); | MPASS(items != NULL); | ||||
MPASS(n > 0); | MPASS(n > 0); | ||||
Show All 36 Lines | ifmp_ring_enqueue(struct ifmp_ring *r, void **items, int n, int budget, int abdicate) | ||||
} while (i != pidx_stop); | } while (i != pidx_stop); | ||||
/* | /* | ||||
* Update the ring's pidx_tail. The release style atomic guarantees | * Update the ring's pidx_tail. The release style atomic guarantees | ||||
* that the items are visible to any thread that sees the updated pidx. | * that the items are visible to any thread that sees the updated pidx. | ||||
*/ | */ | ||||
os.state = ns.state = r->state; | os.state = ns.state = r->state; | ||||
ns.pidx_tail = pidx_stop; | ns.pidx_tail = pidx_stop; | ||||
if (abdicate) { | |||||
if (os.flags == IDLE) | |||||
ns.flags = ABDICATED; | |||||
} | |||||
else { | |||||
ns.flags = BUSY; | ns.flags = BUSY; | ||||
} | |||||
r->state = ns.state; | r->state = ns.state; | ||||
counter_u64_add(r->enqueues, n); | counter_u64_add(r->enqueues, n); | ||||
if (!abdicate) { | |||||
/* | /* | ||||
* Turn into a consumer if some other thread isn't active as a consumer | * Turn into a consumer if some other thread isn't active as a consumer | ||||
* already. | * already. | ||||
*/ | */ | ||||
if (os.flags != BUSY) | if (os.flags != BUSY) | ||||
drain_ring_locked(r, ns, os.flags, budget); | drain_ring_locked(r, ns, os.flags, budget); | ||||
} | |||||
mtx_unlock(&r->lock); | mtx_unlock(&r->lock); | ||||
return (0); | return (0); | ||||
} | } | ||||
#else | #else | ||||
int | int | ||||
ifmp_ring_enqueue(struct ifmp_ring *r, void **items, int n, int budget) | ifmp_ring_enqueue(struct ifmp_ring *r, void **items, int n, int budget, int abdicate) | ||||
{ | { | ||||
union ring_state os, ns; | union ring_state os, ns; | ||||
uint16_t pidx_start, pidx_stop; | uint16_t pidx_start, pidx_stop; | ||||
int i; | int i; | ||||
MPASS(items != NULL); | MPASS(items != NULL); | ||||
MPASS(n > 0); | MPASS(n > 0); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | ifmp_ring_enqueue(struct ifmp_ring *r, void **items, int n, int budget, int abdicate) | ||||
/* | /* | ||||
* Update the ring's pidx_tail. The release style atomic guarantees | * Update the ring's pidx_tail. The release style atomic guarantees | ||||
* that the items are visible to any thread that sees the updated pidx. | * that the items are visible to any thread that sees the updated pidx. | ||||
*/ | */ | ||||
do { | do { | ||||
os.state = ns.state = r->state; | os.state = ns.state = r->state; | ||||
ns.pidx_tail = pidx_stop; | ns.pidx_tail = pidx_stop; | ||||
if (abdicate) { | |||||
if (os.flags == IDLE) | if (os.flags == IDLE) | ||||
ns.flags = ABDICATED; | ns.flags = ABDICATED; | ||||
} | |||||
else { | |||||
ns.flags = BUSY; | |||||
} | |||||
} while (atomic_cmpset_rel_64(&r->state, os.state, ns.state) == 0); | } while (atomic_cmpset_rel_64(&r->state, os.state, ns.state) == 0); | ||||
critical_exit(); | critical_exit(); | ||||
counter_u64_add(r->enqueues, n); | counter_u64_add(r->enqueues, n); | ||||
if (!abdicate) { | |||||
/* | |||||
* Turn into a consumer if some other thread isn't active as a consumer | |||||
* already. | |||||
*/ | |||||
if (os.flags != BUSY) | |||||
drain_ring_lockless(r, ns, os.flags, budget); | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
#endif | #endif | ||||
void | void | ||||
ifmp_ring_check_drainage(struct ifmp_ring *r, int budget) | ifmp_ring_check_drainage(struct ifmp_ring *r, int budget) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 71 Lines • Show Last 20 Lines |