Alien-Judy
view release on metacpan or search on metacpan
src/judy-1.0.5/test/malloc-pre2.8a.c view on Meta::CPAN
long as the value is meaningful), and returns 1 if successful else
0. SVID/XPG/ANSI defines four standard param numbers for mallopt,
normally defined in malloc.h. Only one of these (M_MXFAST) is used
in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply,
so setting them has no effect. But this malloc also supports four
other options in mallopt. See below for details. Briefly, supported
parameters are as follows (listed defaults are for "typical"
configurations).
Symbol param # default allowed param values
M_MXFAST 1 64 0-64 (0 disables fastbins)
M_TRIM_THRESHOLD -1 256*1024 any (-1U disables trimming)
M_TOP_PAD -2 0 any
M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support)
M_MMAP_MAX -4 65536 any (0 disables use of mmap)
*/
int public_mALLOPt(int, int);
/*
mallinfo()
Returns (by copy) a struct containing various summary statistics:
arena: current total non-mmapped bytes allocated from system
ordblks: the number of free chunks
smblks: the number of fastbin blocks (i.e., small chunks that
have been freed but not use resused or consolidated)
hblks: current number of mmapped regions
hblkhd: total bytes held in mmapped regions
usmblks: the maximum total allocated space. This will be greater
than current total if trimming has occurred.
fsmblks: total bytes held in fastbin blocks
uordblks: current total allocated space (normal or mmapped)
fordblks: total free space
keepcost: the maximum number of bytes that could ideally be released
back to system via malloc_trim. ("ideally" means that
it ignores page restrictions etc.)
Because these fields are ints, but internal bookkeeping may
be kept as longs, the reported values may wrap around zero and
thus be inaccurate.
*/
struct mallinfo public_mALLINFo(void);
/*
independent_calloc(size_t n_elements, size_t element_size, Void_t* chunks[]);
independent_calloc is similar to calloc, but instead of returning a
single cleared space, it returns an array of pointers to n_elements
independent elements that can hold contents of size elem_size, each
of which starts out cleared, and can be independently freed,
realloc'ed etc. The elements are guaranteed to be adjacently
allocated (this is not guaranteed to occur with multiple callocs or
mallocs), which may also improve cache locality in some
applications.
The "chunks" argument is optional (i.e., may be null, which is
probably the most typical usage). If it is null, the returned array
is itself dynamically allocated and should also be freed when it is
no longer needed. Otherwise, the chunks array must be of at least
n_elements in length. It is filled in with the pointers to the
chunks.
In either case, independent_calloc returns this pointer array, or
null if the allocation failed. If n_elements is zero and "chunks"
is null, it returns a chunk representing an array with zero elements
(which should be freed if not wanted).
Each element must be individually freed when it is no longer
needed. If you'd like to instead be able to free all at once, you
should instead use regular calloc and assign pointers into this
space to represent elements. (In this case though, you cannot
independently free elements.)
independent_calloc simplifies and speeds up implementations of many
kinds of pools. It may also be useful when constructing large data
structures that initially have a fixed number of fixed-sized nodes,
but the number is not known at compile time, and some of the nodes
may later need to be freed. For example:
struct Node { int item; struct Node* next; };
struct Node* build_list() {
struct Node** pool;
int n = read_number_of_nodes_needed();
if (n <= 0) return 0;
pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);
if (pool == 0) die();
// organize into a linked list...
struct Node* first = pool[0];
for (i = 0; i < n-1; ++i)
pool[i]->next = pool[i+1];
free(pool); // Can now free the array (or not, if it is needed later)
return first;
}
*/
Void_t** public_iCALLOc(size_t, size_t, Void_t**);
/*
independent_comalloc(size_t n_elements, size_t sizes[], Void_t* chunks[]);
independent_comalloc allocates, all at once, a set of n_elements
chunks with sizes indicated in the "sizes" array. It returns
an array of pointers to these elements, each of which can be
independently freed, realloc'ed etc. The elements are guaranteed to
be adjacently allocated (this is not guaranteed to occur with
multiple callocs or mallocs), which may also improve cache locality
in some applications.
The "chunks" argument is optional (i.e., may be null). If it is null
the returned array is itself dynamically allocated and should also
be freed when it is no longer needed. Otherwise, the chunks array
must be of at least n_elements in length. It is filled in with the
pointers to the chunks.
In either case, independent_comalloc returns this pointer array, or
null if the allocation failed. If n_elements is zero and chunks is
null, it returns a chunk representing an array with zero elements
(which should be freed if not wanted).
Each element must be individually freed when it is no longer
needed. If you'd like to instead be able to free all at once, you
should instead use a single regular malloc, and assign pointers at
particular offsets in the aggregate space. (In this case though, you
cannot independently free elements.)
independent_comallac differs from independent_calloc in that each
element may have a different size, and also that it does not
automatically clear elements.
independent_comalloc can be used to speed up allocation in cases
where several structs or objects must always be allocated at the
same time. For example:
struct Head { ... }
struct Foot { ... }
void send_message(char* msg) {
int msglen = strlen(msg);
size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };
void* chunks[3];
if (independent_comalloc(3, sizes, chunks) == 0)
die();
struct Head* head = (struct Head*)(chunks[0]);
char* body = (char*)(chunks[1]);
struct Foot* foot = (struct Foot*)(chunks[2]);
// ...
}
In general though, independent_comalloc is worth using only for
larger values of n_elements. For small values, you probably won't
detect enough difference from series of malloc calls to bother.
Overuse of independent_comalloc can increase overall memory usage,
since it cannot reuse existing noncontiguous small chunks that
might be available for some of the elements.
*/
Void_t** public_iCOMALLOc(size_t, size_t*, Void_t**);
/*
pvalloc(size_t n);
Equivalent to valloc(minimum-page-that-holds(n)), that is,
round up n to nearest pagesize.
*/
Void_t* public_pVALLOc(size_t);
/*
cfree(Void_t* p);
Equivalent to free(p).
cfree is needed/defined on some systems that pair it with calloc,
for odd historical reasons (such as: cfree is used in example
src/judy-1.0.5/test/malloc-pre2.8a.c view on Meta::CPAN
}
/*
------------------------------ cfree ------------------------------
*/
void cFREe(Void_t *mem) {
fREe(mem);
}
/*
------------------------- independent_calloc -------------------------
*/
Void_t** iCALLOc(size_t n_elements, size_t elem_size, Void_t* chunks[]) {
size_t sz = elem_size; /* serves as 1-element array */
/* opts arg of 3 means all elements are same size, and should be cleared */
return iALLOc(n_elements, &sz, 3, chunks);
}
/*
------------------------- independent_comalloc -------------------------
*/
Void_t** iCOMALLOc(size_t n_elements, size_t sizes[], Void_t* chunks[]) {
return iALLOc(n_elements, sizes, 0, chunks);
}
/*
------------------------------ ialloc ------------------------------
ialloc provides common support for independent_X routines, handling all of
the combinations that can result.
The opts arg has:
bit 0 set if all elements are same size (using sizes[0])
bit 1 set if elements should be zeroed
*/
static Void_t** iALLOc(size_t n_elements,
size_t* sizes,
int opts,
Void_t* chunks[]) {
mstate av = get_malloc_state();
INTERNAL_SIZE_T element_size; /* chunksize of each element, if all same */
INTERNAL_SIZE_T contents_size; /* total size of elements */
INTERNAL_SIZE_T array_size; /* request size of pointer array */
Void_t* mem; /* malloced aggregate space */
mchunkptr p; /* corresponding chunk */
CHUNK_SIZE_T remainder_size; /* remaining bytes while splitting */
Void_t** marray; /* either "chunks" or malloced ptr array */
mchunkptr array_chunk; /* chunk for malloced ptr array */
unsigned int mprops; /* to disable mmap */
CHUNK_SIZE_T size;
size_t i;
ensure_initialization(av);
/* compute array length, if needed */
if (chunks != 0) {
if (n_elements == 0)
return chunks; /* nothing to do */
marray = chunks;
array_size = 0;
}
else {
/* if empty req, must still return chunk representing empty array */
if (n_elements == 0)
return (Void_t**) mALLOc(0);
marray = 0;
array_size = request2size(n_elements * (sizeof(Void_t*)));
}
/* compute total element size */
if (opts & 0x1) { /* all-same-size */
element_size = request2size(*sizes);
contents_size = n_elements * element_size;
}
else { /* add up all the sizes */
element_size = 0;
contents_size = 0;
for (i = 0; i != n_elements; ++i)
contents_size += request2size(sizes[i]);
}
/* subtract out alignment bytes from total to minimize overallocation */
size = contents_size + array_size - MALLOC_ALIGN_MASK;
/*
Allocate the aggregate chunk.
But first disable mmap so malloc won't use it, since
we would not be able to later free/realloc space internal
to a segregated mmap region.
*/
mprops = av->sysctl; /* disable mmap */
disable_mmap(av);
mem = mALLOc(size);
av->sysctl = mprops; /* reset mmap */
if (mem == 0)
return 0;
p = mem2chunk(mem);
assert(!chunk_is_mmapped(p));
remainder_size = chunksize(p);
if (opts & 0x2) { /* optionally clear the elements */
MALLOC_ZERO(mem, remainder_size - SIZE_SZ - array_size);
}
/* If not provided, allocate the pointer array as final part of chunk */
if (marray == 0) {
array_chunk = chunk_at_offset(p, contents_size);
marray = (Void_t**) (chunk2mem(array_chunk));
set_head(array_chunk, (remainder_size - contents_size) | PREV_INUSE);
remainder_size = contents_size;
}
( run in 0.548 second using v1.01-cache-2.11-cpan-13bb782fe5a )