diff options
author | Jason Evans <je@fb.com> | 2012-04-24 04:14:26 (GMT) |
---|---|---|
committer | Jason Evans <je@fb.com> | 2012-04-24 04:14:26 (GMT) |
commit | 577dd84660351c727a62db99b308e35d9da224a1 (patch) | |
tree | 87dc96c6431084470714203005c55d4e0e12dad9 /src/quarantine.c | |
parent | 87667a86a072ed5127343cc7698c3144cac37e05 (diff) | |
download | jemalloc-577dd84660351c727a62db99b308e35d9da224a1.zip jemalloc-577dd84660351c727a62db99b308e35d9da224a1.tar.gz jemalloc-577dd84660351c727a62db99b308e35d9da224a1.tar.bz2 |
Handle quarantine resurrection during thread exit.
Handle quarantine resurrection during thread exit in much the same way
as tcache resurrection is handled.
Diffstat (limited to 'src/quarantine.c')
-rw-r--r-- | src/quarantine.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/src/quarantine.c b/src/quarantine.c index 5fb6c39..26ec589 100644 --- a/src/quarantine.c +++ b/src/quarantine.c @@ -1,5 +1,13 @@ #include "jemalloc/internal/jemalloc_internal.h" +/* + * quarantine pointers close to NULL are used to encode state information that + * is used for cleaning up during thread shutdown. + */ +#define QUARANTINE_STATE_REINCARNATED ((quarantine_t *)(uintptr_t)1) +#define QUARANTINE_STATE_PURGATORY ((quarantine_t *)(uintptr_t)2) +#define QUARANTINE_STATE_MAX QUARANTINE_STATE_PURGATORY + /******************************************************************************/ /* Data. */ @@ -105,10 +113,25 @@ quarantine(void *ptr) assert(opt_quarantine); quarantine = *quarantine_tsd_get(); - if (quarantine == NULL && (quarantine = - quarantine_init(LG_MAXOBJS_INIT)) == NULL) { - idalloc(ptr); - return; + if ((uintptr_t)quarantine <= (uintptr_t)QUARANTINE_STATE_MAX) { + if (quarantine == NULL) { + if ((quarantine = quarantine_init(LG_MAXOBJS_INIT)) == + NULL) { + idalloc(ptr); + return; + } + } else { + if (quarantine == QUARANTINE_STATE_PURGATORY) { + /* + * Make a note that quarantine() was called + * after quarantine_cleanup() was called. + */ + quarantine = QUARANTINE_STATE_REINCARNATED; + quarantine_tsd_set(&quarantine); + } + idalloc(ptr); + return; + } } /* * Drain one or more objects if the quarantine size limit would be @@ -144,9 +167,26 @@ quarantine_cleanup(void *arg) { quarantine_t *quarantine = *(quarantine_t **)arg; - if (quarantine != NULL) { + if (quarantine == QUARANTINE_STATE_REINCARNATED) { + /* + * Another destructor deallocated memory after this destructor + * was called. Reset quarantine to QUARANTINE_STATE_PURGATORY + * in order to receive another callback. + */ + quarantine = QUARANTINE_STATE_PURGATORY; + quarantine_tsd_set(&quarantine); + } else if (quarantine == QUARANTINE_STATE_PURGATORY) { + /* + * The previous time this destructor was called, we set the key + * to QUARANTINE_STATE_PURGATORY so that other destructors + * wouldn't cause re-creation of the quarantine. This time, do + * nothing, so that the destructor will not be called again. + */ + } else if (quarantine != NULL) { quarantine_drain(quarantine, 0); idalloc(quarantine); + quarantine = QUARANTINE_STATE_PURGATORY; + quarantine_tsd_set(&quarantine); } } |