mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-07-06 19:38:41 +03:00
add support for sub-processes (to supportpython/cpython#113717)
This commit is contained in:
parent
f87a4c15b2
commit
d9aa19a763
7 changed files with 119 additions and 44 deletions
|
@ -288,8 +288,16 @@ mi_decl_export bool mi_manage_os_memory_ex(void* start, size_t size, bool is_co
|
|||
mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t arena_id);
|
||||
#endif
|
||||
|
||||
|
||||
// Experimental: allow sub-processes whose memory segments stay separated (and no reclamation between them)
|
||||
// Used for example for separate interpreter's in one process.
|
||||
typedef void* mi_subproc_id_t;
|
||||
mi_decl_export mi_subproc_id_t mi_subproc_new(void);
|
||||
mi_decl_export void mi_subproc_delete(mi_subproc_id_t subproc);
|
||||
mi_decl_export void mi_subproc_add_current_thread(mi_subproc_id_t subproc); // this should be called right after a thread is created (and no allocation has taken place yet)
|
||||
|
||||
// deprecated
|
||||
mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
|
||||
mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
|
|
|
@ -130,14 +130,17 @@ void _mi_arena_unsafe_destroy_all(mi_stats_t* stats);
|
|||
|
||||
bool _mi_arena_segment_clear_abandoned(mi_segment_t* segment);
|
||||
void _mi_arena_segment_mark_abandoned(mi_segment_t* segment);
|
||||
size_t _mi_arena_segment_abandoned_count(void);
|
||||
|
||||
typedef struct mi_arena_field_cursor_s { // abstract
|
||||
void* _mi_arena_meta_zalloc(size_t size, mi_memid_t* memid);
|
||||
void _mi_arena_meta_free(void* p, mi_memid_t memid, size_t size);
|
||||
|
||||
typedef struct mi_arena_field_cursor_s { // abstract struct
|
||||
mi_arena_id_t start;
|
||||
int count;
|
||||
size_t bitmap_idx;
|
||||
mi_subproc_t* subproc;
|
||||
} mi_arena_field_cursor_t;
|
||||
void _mi_arena_field_cursor_init(mi_heap_t* heap, mi_arena_field_cursor_t* current);
|
||||
void _mi_arena_field_cursor_init(mi_heap_t* heap, mi_subproc_t* subproc, mi_arena_field_cursor_t* current);
|
||||
mi_segment_t* _mi_arena_segment_clear_abandoned_next(mi_arena_field_cursor_t* previous);
|
||||
|
||||
// "segment-map.c"
|
||||
|
|
|
@ -307,7 +307,7 @@ typedef struct mi_page_s {
|
|||
mi_block_t* local_free; // list of deferred free blocks by this thread (migrates to `free`)
|
||||
uint16_t used; // number of blocks in use (including blocks in `thread_free`)
|
||||
uint8_t block_size_shift; // if not zero, then `(1 << block_size_shift) == block_size` (only used for fast path in `free.c:_mi_page_ptr_unalign`)
|
||||
uint8_t heap_tag; // tag of the owning heap, used for separated heaps by object type
|
||||
uint8_t heap_tag; // tag of the owning heap, used to separate heaps by object type
|
||||
// padding
|
||||
size_t block_size; // size available in each block (always `>0`)
|
||||
uint8_t* page_start; // start of the page area containing the blocks
|
||||
|
@ -387,6 +387,7 @@ typedef struct mi_memid_s {
|
|||
// ---------------------------------------------------------------
|
||||
// Segments contain mimalloc pages
|
||||
// ---------------------------------------------------------------
|
||||
typedef struct mi_subproc_s mi_subproc_t;
|
||||
|
||||
// Segments are large allocated memory blocks (2MiB on 64 bit) from the OS.
|
||||
// Inside segments we allocated fixed size _pages_ that contain blocks.
|
||||
|
@ -409,6 +410,7 @@ typedef struct mi_segment_s {
|
|||
size_t capacity; // count of available pages (`#free + used`)
|
||||
size_t segment_info_size;// space we are using from the first page for segment meta-data and possible guard pages.
|
||||
uintptr_t cookie; // verify addresses in secure mode: `_mi_ptr_cookie(segment) == segment->cookie`
|
||||
mi_subproc_t* subproc; // segment belongs to sub process
|
||||
|
||||
// layout like this to optimize access in `mi_free`
|
||||
_Atomic(mi_threadid_t) thread_id; // unique id of the thread owning this segment
|
||||
|
@ -600,10 +602,23 @@ void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount);
|
|||
#define mi_heap_stat_decrease(heap,stat,amount) mi_stat_decrease( (heap)->tld->stats.stat, amount)
|
||||
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Sub processes do not reclaim or visit segments
|
||||
// from other sub processes
|
||||
// ------------------------------------------------------
|
||||
|
||||
struct mi_subproc_s {
|
||||
_Atomic(size_t) abandoned_count; // count of abandoned segments for this sup-process
|
||||
mi_memid_t memid; // provenance
|
||||
};
|
||||
|
||||
mi_subproc_t* mi_subproc_from_id(mi_subproc_id_t subproc_id);
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Thread Local data
|
||||
// ------------------------------------------------------
|
||||
|
||||
// Milliseconds as in `int64_t` to avoid overflows
|
||||
typedef int64_t mi_msecs_t;
|
||||
|
||||
// Queue of segments
|
||||
|
@ -628,8 +643,9 @@ typedef struct mi_segments_tld_s {
|
|||
size_t current_size; // current size of all segments
|
||||
size_t peak_size; // peak size of all segments
|
||||
size_t reclaim_count;// number of reclaimed (abandoned) segments
|
||||
mi_subproc_t* subproc; // sub-process this thread belongs to.
|
||||
mi_stats_t* stats; // points to tld stats
|
||||
mi_os_tld_t* os; // points to os stats
|
||||
mi_os_tld_t* os; // points to os tld
|
||||
} mi_segments_tld_t;
|
||||
|
||||
// Thread local data
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue