/* Put pins back to a pinbox. Usually called via lf_alloc_put_pins() or lf_hash_put_pins(). DESCRIPTION empty the purgatory (XXX deadlock warning below!), push LF_PINS structure to a stack */ void _lf_pinbox_put_pins(LF_PINS *pins) { LF_PINBOX *pinbox= pins->pinbox; uint32 top_ver, nr; nr= pins->link; #ifndef DBUG_OFF { /* This thread should not hold any pin. */ int i; for (i= 0; i < LF_PINBOX_PINS; i++) DBUG_ASSERT(pins->pin[i] == 0); } #endif /* DBUG_OFF */ /* XXX this will deadlock if other threads will wait for the caller to do something after _lf_pinbox_put_pins(), and they would have pinned addresses that the caller wants to free. Thus: only free pins when all work is done and nobody can wait for you!!! */ while (pins->purgatory_count) { _lf_pinbox_real_free(pins); if (pins->purgatory_count) { my_atomic_rwlock_wrunlock(&pins->pinbox->pinarray.lock); pthread_yield(); my_atomic_rwlock_wrlock(&pins->pinbox->pinarray.lock); } } top_ver= pinbox->pinstack_top_ver; do { pins->link= top_ver % LF_PINBOX_MAX_PINS; } while (!my_atomic_cas32((int32 volatile*) &pinbox->pinstack_top_ver, (int32*) &top_ver, top_ver-pins->link+nr+LF_PINBOX_MAX_PINS)); return; }
/* Free an object allocated via pinbox allocator DESCRIPTION add an object to purgatory. if necessary, call _lf_pinbox_real_free() to actually free something. */ void _lf_pinbox_free(LF_PINS *pins, void *addr) { add_to_purgatory(pins, addr); if (pins->purgatory_count % LF_PURGATORY_SIZE) _lf_pinbox_real_free(pins); }