mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-26 06:34:20 +08:00
On Linux, a worker thread that exits without having made any object it allocated reachable from another thread gives back all of its memory: the pages it carved, including ProgramLifetime instances and other objects it never freed, and the system blocks it still holds. The memory goes back once no other worker thread is running, so that returning it does not slow the workers that are still running. A worker carves past each slice's frontier while the arena's free lists and returned regions are set aside, takes from those free lists only once a slice has no bump room left, and records the system blocks it allocates. Messages and intern tables that share published graphs by pointer, and the process-wide key arrays of typed records, mark the thread as sharing; so does a remote free of one of its blocks. A worker that did not share parks with its arena claimed and its discard queued: returning pages makes the kernel interrupt every running thread of the process to flush its TLB, and glibc's trim locks the arenas other threads allocate from. The last worker to park starts one helper that returns each queued worker's pages, frees its system blocks, and restores its arena to its state at the claim, with the free blocks the worker took free again. A thread that finds every arena claimed runs the queued discards itself. A worker that shared keeps its memory as before. SCR_SA_DISCARD=0 keeps every worker's memory; SCR_SA_DISCARD=poison makes the discarded pages inaccessible instead, for tests.