mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
86 lines
2 KiB
PHP
86 lines
2 KiB
PHP
// clang-format off
|
|
|
|
/* ----------------------- Operations on smallbins ----------------------- */
|
|
|
|
/*
|
|
Various forms of linking and unlinking are defined as macros. Even
|
|
the ones for trees, which are very long but have very short typical
|
|
paths. This is ugly but reduces reliance on inlining support of
|
|
compilers.
|
|
*/
|
|
|
|
/* Link a free chunk into a smallbin */
|
|
#define insert_small_chunk(M, P, S) {\
|
|
bindex_t I = small_index(S);\
|
|
mchunkptr B = smallbin_at(M, I);\
|
|
mchunkptr F = B;\
|
|
assert(S >= MIN_CHUNK_SIZE);\
|
|
if (!smallmap_is_marked(M, I))\
|
|
mark_smallmap(M, I);\
|
|
else if (RTCHECK(ok_address(M, B->fd)))\
|
|
F = B->fd;\
|
|
else {\
|
|
CORRUPTION_ERROR_ACTION(M);\
|
|
}\
|
|
B->fd = P;\
|
|
F->bk = P;\
|
|
P->fd = F;\
|
|
P->bk = B;\
|
|
}
|
|
|
|
/* Unlink a chunk from a smallbin */
|
|
#define unlink_small_chunk(M, P, S) {\
|
|
mchunkptr F = P->fd;\
|
|
mchunkptr B = P->bk;\
|
|
bindex_t I = small_index(S);\
|
|
assert(P != B);\
|
|
assert(P != F);\
|
|
assert(chunksize(P) == small_index2size(I));\
|
|
if (RTCHECK(F == smallbin_at(M,I) || (ok_address(M, F) && F->bk == P))) { \
|
|
if (B == F) {\
|
|
clear_smallmap(M, I);\
|
|
}\
|
|
else if (RTCHECK(B == smallbin_at(M,I) ||\
|
|
(ok_address(M, B) && B->fd == P))) {\
|
|
F->bk = B;\
|
|
B->fd = F;\
|
|
}\
|
|
else {\
|
|
CORRUPTION_ERROR_ACTION(M);\
|
|
}\
|
|
}\
|
|
else {\
|
|
CORRUPTION_ERROR_ACTION(M);\
|
|
}\
|
|
}
|
|
|
|
/* Unlink the first chunk from a smallbin */
|
|
#define unlink_first_small_chunk(M, B, P, I) {\
|
|
mchunkptr F = P->fd;\
|
|
assert(P != B);\
|
|
assert(P != F);\
|
|
assert(chunksize(P) == small_index2size(I));\
|
|
if (B == F) {\
|
|
clear_smallmap(M, I);\
|
|
}\
|
|
else if (RTCHECK(ok_address(M, F) && F->bk == P)) {\
|
|
F->bk = B;\
|
|
B->fd = F;\
|
|
}\
|
|
else {\
|
|
CORRUPTION_ERROR_ACTION(M);\
|
|
}\
|
|
}
|
|
|
|
/* Replace dv node, binning the old one */
|
|
/* Used only when dvsize known to be small */
|
|
#define replace_dv(M, P, S) {\
|
|
size_t DVS = M->dvsize;\
|
|
assert(is_small(DVS));\
|
|
if (DVS != 0) {\
|
|
mchunkptr DV = M->dv;\
|
|
insert_small_chunk(M, DV, DVS);\
|
|
}\
|
|
M->dvsize = S;\
|
|
M->dv = P;\
|
|
}
|