Files
QNX/lib/c/alloc/core.c
2025-08-20 19:02:58 +08:00

219 lines
4.9 KiB
C

/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
/*-
* core: interface to system mmap,munmap,etc...
*
* Some OS versions don't support munmap, so core keeps around bits that
* don't make it back. There are other versions which have buggy munmaps
* that only work on the same range as the mmap which allocated it.
* These are handled by the upper layer.
*
* Compiling with the "TESTING" flag sets allows you to select the behaviour
*
* of unmap based on the environment variable MUNMAP_WORKS:
* = 0 simulate munmap always failing.
* = 1 use underlying munmap
* = * pretend munumap works, but don't invoke it (ie. leak).
*
*/
#include <assert.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include "malloc-lib.h"
typedef struct core_blk {
unsigned sz;
struct core_blk *next;
struct core_blk *prev;
} core_blk_t;
#define DEFAULT_MAX_ARENA 12
static core_blk_t *core_cache_list=NULL;
unsigned __core_cache_max_num=DEFAULT_MAX_ARENA;
unsigned __core_cache_max_sz=0;
static unsigned core_cache_size=0;
static unsigned core_cache_num=0;
#define CORE_CACHE_ENQ(__addr, __size, __status, __force) \
{ \
core_blk_t *cblk = (core_blk_t *)__addr; \
cblk->sz = __size; \
cblk->prev = NULL; \
if (!(__force) && \
( ((__core_cache_max_sz == 0) && (__core_cache_max_num == 0)) || \
((__core_cache_max_sz) && \
((core_cache_size + __size) > __core_cache_max_sz)) ||\
((__core_cache_max_num) && \
(core_cache_num >= __core_cache_max_num)) \
)) { \
__status = 1; /* not cached */ \
} \
else { \
if (core_cache_list == NULL) { \
core_cache_list = cblk; \
cblk->next = NULL; \
} \
else {\
cblk->next = core_cache_list; \
core_cache_list->prev = cblk; \
core_cache_list = cblk; \
} \
core_cache_size +=__size; \
core_cache_num++; \
__status = 0; /* cached */ \
_malloc_stats.m_freemem += __size; \
} \
}
#define CORE_CACHE_DEQ(__addr, __size, __fixed, __rsize) \
{ \
core_blk_t *cblk=NULL; \
core_blk_t *temp; \
temp = core_cache_list; \
while (temp) { \
if ((__size == 0) || \
((!__fixed) && (temp->sz >= __size)) || \
(temp->sz == __size) \
) { \
cblk = temp; \
core_cache_num--; \
core_cache_size -= temp->sz; \
if (temp == core_cache_list) { \
core_cache_list = temp->next; \
if (core_cache_list != NULL) \
core_cache_list->prev = NULL; \
} \
else { \
temp->prev->next = temp->next; \
if (temp->next != NULL) { \
temp->next->prev = temp->prev; \
} \
} \
break; \
} \
temp = temp->next; \
} \
if (cblk != NULL) { \
__addr = cblk; \
*__rsize = cblk->sz; \
_malloc_stats.m_freemem -= cblk->sz; \
} \
else { \
__addr = NULL; \
} \
}
#ifndef TESTING
#define getmem __getmem
#define putmem __putmem
#else
static int works = -1;
static char *
getmem(unsigned nbytes)
{
return __getmem(nbytes);
}
static int
putmem(char *cp, unsigned nbytes)
{
if (works == -1) {
char *p = getenv("MUNMAP_WORKS");
works = p?strtol(p,0,0):0;
}
switch (works) {
case 0:
return -1;
case 1:
return munmap(cp,nbytes);
default:
return 0;
}
}
#endif
void __core_cache_adjust()
{
void *addr;
int rsize;
while ((core_cache_num > __core_cache_max_num) ||
(core_cache_size > __core_cache_max_sz)) {
CORE_CACHE_DEQ(addr, 0, 0, &rsize);
putmem(addr, rsize);
_malloc_stats.m_corefrees++;
}
}
void __core_prealloc_cache(unsigned size)
{
void *addr;
unsigned sz;
int status;
sz = _amblksiz;
while (core_cache_size < size) {
addr = getmem(sz);
if (addr == (void *)-1) {
return;
}
CORE_CACHE_ENQ(addr, sz, status, 1);
_malloc_stats.m_heapsize += sz;
_malloc_stats.m_coreallocs++;
}
return;
}
char *
morecore(unsigned nbytes, int fixed, int *rsize)
{
char *z;
void *addr=NULL;
CORE_CACHE_DEQ(addr, nbytes, fixed, rsize);
if (addr == NULL) {
z = getmem(nbytes);
_malloc_stats.m_heapsize += nbytes;
_malloc_stats.m_coreallocs++;
*rsize = nbytes;
}
else
z = (char *)addr;
return z;
}
int
donecore(void *cp, unsigned nbytes)
{
int status=0;
CORE_CACHE_ENQ(cp, nbytes, status, 0);
if (status) { // not cached
putmem(cp, nbytes);
_malloc_stats.m_heapsize -= nbytes;
_malloc_stats.m_corefrees++;
}
return 0;
}
__SRCVERSION("core.c $Rev: 153052 $");