if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0);
}
+#ifndef __wasilibc_unmodified_upstream
+static void *map_base_deferred_free;
+
+static void process_map_base_deferred_free()
+{
+ /* called with __tl_lock held */
+ free(map_base_deferred_free);
+ map_base_deferred_free = NULL;
+}
+#endif
+
#ifdef __wasilibc_unmodified_upstream
_Noreturn void __pthread_exit(void *result)
#else
}
#else
if (state==DT_DETACHED && self->map_base) {
- free(self->map_base);
+ /* As we use malloc/free which is considerably more complex
+ * than mmap/munmap to call and can even require a valid
+ * thread context, it's difficult to implement __unmapself.
+ *
+ * Here we take an alternative approach which simply defers
+ * the deallocation. An obvious downside of this approach is
+ * that it keeps the stack longer. (possibly forever.)
+ * To avoid wasting too much memory, we only defer a single
+ * item at most. */
+ process_map_base_deferred_free();
+ map_base_deferred_free = self->map_base;
// Can't use `exit()` here, because it is too high level
return;
}
if (map == MAP_FAILED) goto fail;
}
#else
+ /* Process the deferred free request if any before
+ * allocationg a new one. Hopefully it enables a reuse of the memory.
+ *
+ * Note: We can't perform a simple "handoff" becasue allocation
+ * sizes might be different. (eg. the stack size might differ) */
+ __tl_lock();
+ process_map_base_deferred_free();
+ __tl_unlock();
map = malloc(size);
if (!map) goto fail;
#endif