summaryrefslogtreecommitdiffstats
path: root/src/quarantine.c
diff options
context:
space:
mode:
authorJason Evans <je@fb.com>2012-04-24 04:14:26 (GMT)
committerJason Evans <je@fb.com>2012-04-24 04:14:26 (GMT)
commit577dd84660351c727a62db99b308e35d9da224a1 (patch)
tree87dc96c6431084470714203005c55d4e0e12dad9 /src/quarantine.c
parent87667a86a072ed5127343cc7698c3144cac37e05 (diff)
downloadjemalloc-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.c50
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);
}
}