mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
f7780de24b
Cosmopolitan now supports mremap(), which is only supported on Linux and NetBSD. First, it allows memory mappings to be relocated without copying them; this can dramatically speed up data structures like std::vector if the array size grows larger than 256kb. The mremap() system call is also 10x faster than munmap() when shrinking large memory mappings. There's now two functions, getpagesize() and getgransize() which help to write portable code that uses mmap(MAP_FIXED). Alternative sysconf() may be called with our new _SC_GRANSIZE. The madvise() system call now has a better wrapper with improved documentation.
78 lines
2.7 KiB
C++
78 lines
2.7 KiB
C++
|
|
/* ----------------------- Direct-mmapping chunks ----------------------- */
|
|
|
|
/*
|
|
Directly mmapped chunks are set up with an offset to the start of
|
|
the mmapped region stored in the prev_foot field of the chunk. This
|
|
allows reconstruction of the required argument to MUNMAP when freed,
|
|
and also allows adjustment of the returned chunk to meet alignment
|
|
requirements (especially in memalign).
|
|
*/
|
|
|
|
/* Malloc using mmap */
|
|
static void* mmap_alloc(mstate m, size_t nb) {
|
|
size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
|
|
if (m->footprint_limit != 0) {
|
|
size_t fp = m->footprint + mmsize;
|
|
if (fp <= m->footprint || fp > m->footprint_limit)
|
|
return 0;
|
|
}
|
|
if (mmsize > nb) { /* Check for wrap around 0 */
|
|
char* mm = (char*)(dlmalloc_requires_more_vespene_gas(mmsize));
|
|
if (mm != CMFAIL) {
|
|
size_t offset = align_offset(chunk2mem(mm));
|
|
size_t psize = mmsize - offset - MMAP_FOOT_PAD;
|
|
mchunkptr p = (mchunkptr)(mm + offset);
|
|
p->prev_foot = offset;
|
|
p->head = psize;
|
|
mark_inuse_foot(m, p, psize);
|
|
chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
|
|
chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
|
|
|
|
if (m->least_addr == 0 || mm < m->least_addr)
|
|
m->least_addr = mm;
|
|
if ((m->footprint += mmsize) > m->max_footprint)
|
|
m->max_footprint = m->footprint;
|
|
assert(is_aligned(chunk2mem(p)));
|
|
check_mmapped_chunk(m, p);
|
|
return chunk2mem(p);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Realloc using mmap */
|
|
static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb, int flags) {
|
|
size_t oldsize = chunksize(oldp);
|
|
(void)flags; /* placate people compiling -Wunused */
|
|
if (is_small(nb)) /* Can't shrink mmap regions below small size */
|
|
return 0;
|
|
/* Keep old chunk if big enough but not too big */
|
|
if (oldsize >= nb + SIZE_T_SIZE &&
|
|
(oldsize - nb) <= (mparams.granularity << 1))
|
|
return oldp;
|
|
else {
|
|
size_t offset = oldp->prev_foot;
|
|
size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD;
|
|
size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
|
|
char* cp = (char*)CALL_MREMAP((char*)oldp - offset,
|
|
oldmmsize, newmmsize, flags);
|
|
if (cp != MAP_FAILED) {
|
|
mchunkptr newp = (mchunkptr)(cp + offset);
|
|
size_t psize = newmmsize - offset - MMAP_FOOT_PAD;
|
|
newp->head = psize;
|
|
mark_inuse_foot(m, newp, psize);
|
|
chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
|
|
chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
|
|
|
|
if (cp < m->least_addr)
|
|
m->least_addr = cp;
|
|
if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint)
|
|
m->max_footprint = m->footprint;
|
|
check_mmapped_chunk(m, newp);
|
|
return newp;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|