#ifndef __NANOV2_ZONE_H
#define __NANOV2_ZONE_H
#if CONFIG_NANOZONE
#pragma mark -
#pragma mark Address Structure
#if TARGET_OS_OSX || TARGET_OS_SIMULATOR || TARGET_OS_DRIVERKIT
#define NANOV2_REGION_BITS 15
#define NANOV2_ARENA_BITS 3
#define NANOV2_BLOCK_BITS 12
#define NANOV2_OFFSET_BITS 14
#else // TARGET_OS_OSX || TARGET_OS_SIMULATOR || TARGET_OS_DRIVERKIT
#define NANOV2_REGION_BITS 0
#define NANOV2_ARENA_BITS 3
#define NANOV2_BLOCK_BITS 12
#define NANOV2_OFFSET_BITS 14
#endif // TARGET_OS_OSX || TARGET_OS_SIMULATOR || TARGET_OS_DRIVERKIT
#if NANOV2_REGION_BITS > 0
#define NANOV2_MULTIPLE_REGIONS 1
#else // NANOV2_REGION_BITS > 0
#define NANOV2_MULTIPLE_REGIONS 0
#endif // NANOV2_REGION_BITS > 0
#define NANOV2_BLOCK_SIZE (1 << NANOV2_OFFSET_BITS)
#define NANOV2_ARENA_SIZE (64 * 1024 * 1024)
#define NANOV2_REGION_SIZE (512 * 1024 * 1024)
#define NANOV2_BLOCKS_PER_ARENA (NANOV2_ARENA_SIZE/NANOV2_BLOCK_SIZE)
#define NANOV2_ARENAS_PER_REGION (NANOV2_REGION_SIZE/NANOV2_ARENA_SIZE)
#define NANOV2_MAX_SLOTS_PER_BLOCK (NANOV2_BLOCK_SIZE/NANO_REGIME_QUANTA_SIZE)
#if NANOV2_MULTIPLE_REGIONS
#define NANOV2_MAX_REGION_NUMBER ((1 << NANOV2_REGION_BITS) - 1)
#else // NANOV2_MULTIPLE_REGIONS
#define NANOV2_MAX_REGION_NUMBER 0
#endif // NANOV2_MULTIPLE_REGIONS
#if defined(__BIG_ENDIAN__)
struct nanov2_addr_s {
uintptr_t nano_signature : NANOZONE_SIGNATURE_BITS;
#if NANOV2_MULTIPLE_REGIONS
uintptr_t nano_region: NANOV2_REGION_BITS;
#endif // NANOV2_MULTIPLE_REGIONS
uintptr_t nano_arena : NANOV2_ARENA_BITS;
uintptr_t nano_block : NANOV2_BLOCK_BITS;
uintptr_t nano_offset : NANOV2_OFFSET_BITS;
};
MALLOC_STATIC_ASSERT(sizeof(struct nanov2_addr_s) == sizeof(uintptr_t),
"Wrong size for nanov2_addr_s");
#else // defined(__BIG_ENDIAN__)
struct nanov2_addr_s {
uintptr_t nano_offset : NANOV2_OFFSET_BITS;
uintptr_t nano_block : NANOV2_BLOCK_BITS;
uintptr_t nano_arena : NANOV2_ARENA_BITS;
#if NANOV2_MULTIPLE_REGIONS
uintptr_t nano_region: NANOV2_REGION_BITS;
#endif // NANOV2_MULTIPLE_REGIONS
uintptr_t nano_signature : NANOZONE_SIGNATURE_BITS;
};
MALLOC_STATIC_ASSERT(sizeof(struct nanov2_addr_s) == sizeof(uintptr_t),
"Wrong size for nanov2_addr_s");
#endif // defined(__BIG_ENDIAN__)
typedef union {
void *addr;
struct nanov2_addr_s fields;
} nanov2_addr_t;
typedef unsigned nanov2_size_class_t;
#pragma mark -
#pragma mark Block Definitions
typedef struct {
unsigned char content[NANOV2_BLOCK_SIZE];
} nanov2_block_t;
MALLOC_STATIC_ASSERT(sizeof(nanov2_block_t) == NANOV2_BLOCK_SIZE,
"nanov2_block_t must be the same size as a block");
#pragma mark -
#pragma mark Arena and Block Definitions
typedef struct {
nanov2_block_t blocks[NANOV2_BLOCKS_PER_ARENA];
} nanov2_arena_t;
MALLOC_STATIC_ASSERT(sizeof(nanov2_arena_t) == NANOV2_BLOCK_SIZE * NANOV2_BLOCKS_PER_ARENA,
"nanov2_arena_t must be the same size as its blocks");
typedef struct {
uint32_t next_slot : 11; uint32_t free_count : 10; uint32_t gen_count : 10; uint32_t in_use : 1; } nanov2_block_meta_t;
MALLOC_STATIC_ASSERT(sizeof(nanov2_block_meta_t) == sizeof(uint32_t),
"Incorrect size for nanov2_block_meta_t");
#define SLOT_NULL 0 // Slot has never been used.
#define SLOT_BUMP 0x7fb // Marks the end of the free list
#define SLOT_FULL 0x7fc // Slot is full (no free slots)
#define SLOT_CAN_MADVISE 0x7fd // Block can be madvised (and in_use == 0)
#define SLOT_MADVISING 0x7fe // Block is being madvised. Do not touch
#define SLOT_MADVISED 0x7ff // Block has been madvised.
typedef union {
nanov2_block_meta_t meta;
uint32_t bits;
} nanov2_block_meta_view_t;
typedef struct {
nanov2_block_meta_t arena_block_meta[NANOV2_BLOCKS_PER_ARENA];
} nanov2_arena_metablock_t;
MALLOC_STATIC_ASSERT(sizeof(nanov2_arena_metablock_t) == NANOV2_BLOCK_SIZE,
"nanov2_arena_metablock_t must be the same size as a block");
typedef struct {
uint64_t double_free_guard;
uint16_t next_slot;
} nanov2_free_slot_t;
MALLOC_STATIC_ASSERT(
sizeof(nanov2_free_slot_t) <= NANO_REGIME_QUANTA_SIZE,
"nanov2_free_slot_t too large");
typedef unsigned nanov2_block_index_t;
typedef unsigned nanov2_meta_index_t;
#pragma mark -
#pragma mark Region Definitions
typedef struct {
nanov2_arena_t arenas[NANOV2_ARENAS_PER_REGION];
} nanov2_region_t;
typedef struct {
uint16_t next_region_offset; uint16_t unused;
} nanov2_region_linkage_t;
MALLOC_STATIC_ASSERT(
sizeof (nanov2_block_meta_t) == sizeof(nanov2_region_linkage_t),
"nanov2_block_meta_t must be the same size as nanov2_region_linkage_t");
#pragma mark -
#pragma mark Statistics
typedef struct {
uint64_t total_allocations;
uint64_t total_frees;
uint64_t madvised_blocks; uint64_t madvise_races; } nanov2_size_class_statistics;
typedef struct {
unsigned allocated_regions;
unsigned region_address_clashes;
nanov2_size_class_statistics size_class_statistics[NANO_SIZE_CLASSES];
} nanov2_statistics_t;
#pragma mark -
#pragma mark Zone Definitions
#define MAX_CURRENT_BLOCKS 64
#define MAX_CURRENT_BLOCKS_MASK (MAX_CURRENT_BLOCKS - 1)
MALLOC_STATIC_ASSERT(MAX_CURRENT_BLOCKS > 1 &&
!(MAX_CURRENT_BLOCKS & MAX_CURRENT_BLOCKS_MASK),
"MAX_CURRENT_BLOCKS must be a power of 2");
typedef struct nanozonev2_s {
malloc_zone_t basic_zone;
uint8_t pad[PAGE_MAX_SIZE - sizeof(malloc_zone_t)];
nanov2_block_meta_t *current_block[NANO_SIZE_CLASSES][MAX_CURRENT_BLOCKS];
_malloc_lock_s current_block_lock[NANO_SIZE_CLASSES][MAX_CURRENT_BLOCKS];
_malloc_lock_s delegate_allocations_lock;
uint16_t delegate_allocations;
unsigned debug_flags;
uint64_t aslr_cookie;
uint64_t aslr_cookie_aligned;
uintptr_t slot_freelist_cookie;
malloc_zone_t *helper_zone;
_malloc_lock_s blocks_lock;
_malloc_lock_s regions_lock;
nanov2_region_t *first_region_base;
nanov2_region_t *current_region_base;
nanov2_arena_t *current_region_next_arena;
void *current_region_limit;
_malloc_lock_s madvise_lock;
nanov2_statistics_t statistics;
} nanozonev2_t;
#define NANOZONEV2_ZONE_PAGED_SIZE mach_vm_round_page(sizeof(nanozonev2_t))
#pragma mark -
#pragma mark Address Manipulation
#define NANOV2_BLOCK_ADDRESS_MASK ~((1ULL << (NANOV2_OFFSET_BITS)) - 1)
#define NANOV2_ARENA_ADDRESS_MASK \
~((1ULL << (NANOV2_BLOCK_BITS + NANOV2_OFFSET_BITS)) - 1)
#define NANOV2_REGION_ADDRESS_MASK \
~((1ULL << (NANOV2_ARENA_BITS + NANOV2_BLOCK_BITS + NANOV2_OFFSET_BITS)) - 1)
#endif // CONFIG_NANOZONE
#endif // __NANOV2_ZONE_H