You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
10 KiB
358 lines
10 KiB
2 years ago
|
/*
|
||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||
|
*
|
||
|
* Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V.
|
||
|
*/
|
||
|
|
||
|
#ifndef _GDK_UTILS_H_
|
||
|
#define _GDK_UTILS_H_
|
||
|
|
||
|
#include <setjmp.h>
|
||
|
|
||
|
gdk_export const char *GDKgetenv(const char *name);
|
||
|
|
||
|
gdk_export bool GDKgetenv_istext(const char *name, const char* text);
|
||
|
gdk_export bool GDKgetenv_isyes(const char *name);
|
||
|
gdk_export bool GDKgetenv_istrue(const char *name);
|
||
|
|
||
|
gdk_export int GDKgetenv_int(const char *name, int def);
|
||
|
|
||
|
gdk_export gdk_return GDKsetenv(const char *name, const char *value);
|
||
|
gdk_export gdk_return GDKcopyenv(BAT **key, BAT **val, bool writable);
|
||
|
|
||
|
/*
|
||
|
* @+ Memory management
|
||
|
* Memory management in GDK mostly relies on the facilities offered by
|
||
|
* the underlying OS. The below routines monitor the available memory
|
||
|
* resources which consist of physical swap space and logical vm
|
||
|
* space. There are three kinds of memory, that affect these two
|
||
|
* resources in different ways:
|
||
|
*
|
||
|
* - memory mapping
|
||
|
* which ask for a logical region of virtual memory space. In
|
||
|
* principle, no physical memory is needed to keep the system afloat
|
||
|
* here, as the memory mapped file is swapped onto a disk object
|
||
|
* that already exists.
|
||
|
*
|
||
|
* Actually, there are two kings of memory mapping used in GDK,
|
||
|
* namely read-only direct mapped and writable copy-on write. For
|
||
|
* the dirty pages, the latter actually also consumes physical
|
||
|
* memory resources, but that is ignored here for simplicity.
|
||
|
*
|
||
|
* - anonymous virtual memory
|
||
|
* This is virtual memory that is mapped on the swap file. Hence,
|
||
|
* this consumes both logical VM space resources and physical memory
|
||
|
* space.
|
||
|
*
|
||
|
* - malloced memory
|
||
|
* comes from the heap and directly consumes physical memory
|
||
|
* resources.
|
||
|
*
|
||
|
* The malloc routine checks the memory consumption every 1000 calls,
|
||
|
* or for calls larger that 50000 bytes. Consequently, at least every
|
||
|
* 50MB increase, alloc memory is checked. The VM calls always check
|
||
|
* the memory consumption.
|
||
|
*/
|
||
|
/* default setting to administer everything */
|
||
|
#define GDK_MEM_NULLALLOWED
|
||
|
|
||
|
#if SIZEOF_VOID_P==8
|
||
|
#define GDK_VM_MAXSIZE LL_CONSTANT(4398046511104) /* :-) a 64-bit OS: 4TB */
|
||
|
#else
|
||
|
#define GDK_VM_MAXSIZE LL_CONSTANT(1610612736) /* :-| a 32-bit OS: 1.5GB */
|
||
|
#endif
|
||
|
/* virtual memory defines */
|
||
|
gdk_export size_t _MT_npages;
|
||
|
gdk_export size_t _MT_pagesize;
|
||
|
|
||
|
#define MT_pagesize() _MT_pagesize
|
||
|
#define MT_npages() _MT_npages
|
||
|
|
||
|
gdk_export size_t GDK_mem_maxsize; /* max allowed size of committed memory */
|
||
|
gdk_export size_t GDK_vm_maxsize; /* max allowed size of reserved vm */
|
||
|
|
||
|
gdk_export void *GDKmmap(const char *path, int mode, size_t len)
|
||
|
__attribute__((__warn_unused_result__));
|
||
|
gdk_export gdk_return GDKmunmap(void *addr, size_t len);
|
||
|
|
||
|
gdk_export size_t GDKmem_cursize(void); /* RAM/swapmem that MonetDB has claimed from OS */
|
||
|
gdk_export size_t GDKvm_cursize(void); /* current MonetDB VM address space usage */
|
||
|
|
||
|
gdk_export void *GDKmalloc(size_t size)
|
||
|
__attribute__((__malloc__))
|
||
|
__attribute__((__alloc_size__(1)))
|
||
|
__attribute__((__warn_unused_result__));
|
||
|
gdk_export void *GDKzalloc(size_t size)
|
||
|
__attribute__((__malloc__))
|
||
|
__attribute__((__alloc_size__(1)))
|
||
|
__attribute__((__warn_unused_result__));
|
||
|
gdk_export void *GDKrealloc(void *pold, size_t size)
|
||
|
__attribute__((__alloc_size__(2)))
|
||
|
__attribute__((__warn_unused_result__));
|
||
|
gdk_export void GDKfree(void *blk);
|
||
|
gdk_export str GDKstrdup(const char *s)
|
||
|
__attribute__((__malloc__))
|
||
|
__attribute__((__warn_unused_result__));
|
||
|
gdk_export str GDKstrndup(const char *s, size_t n)
|
||
|
__attribute__((__malloc__))
|
||
|
__attribute__((__warn_unused_result__));
|
||
|
gdk_export size_t GDKmallocated(const void *s);
|
||
|
|
||
|
gdk_export void MT_init(void); /* init the package. */
|
||
|
struct opt;
|
||
|
gdk_export gdk_return GDKinit(struct opt *set, int setlen, bool embedded);
|
||
|
|
||
|
/* used for testing only */
|
||
|
gdk_export void GDKsetmallocsuccesscount(lng count);
|
||
|
|
||
|
/*
|
||
|
* Upon closing the session, all persistent BATs should be saved and
|
||
|
* the transient BATs should be removed. The buffer pool manager
|
||
|
* takes care of this.
|
||
|
*/
|
||
|
gdk_export void GDKexit(int status);
|
||
|
gdk_export bool GDKexiting(void);
|
||
|
|
||
|
gdk_export void GDKprepareExit(void);
|
||
|
gdk_export void GDKreset(int status);
|
||
|
/* global version number */
|
||
|
gdk_export const char *GDKversion(void)
|
||
|
__attribute__((__const__));
|
||
|
/* ABI version of GDK library */
|
||
|
gdk_export const char *GDKlibversion(void)
|
||
|
__attribute__((__const__));
|
||
|
|
||
|
// these are used in embedded mode to jump out of GDKfatal
|
||
|
gdk_export jmp_buf GDKfataljump;
|
||
|
gdk_export str GDKfatalmsg;
|
||
|
gdk_export bit GDKfataljumpenable;
|
||
|
|
||
|
/* Timers
|
||
|
* The following relative timers are available for inspection.
|
||
|
* Note that they may consume recognizable overhead.
|
||
|
*
|
||
|
*/
|
||
|
gdk_export lng GDKusec(void);
|
||
|
gdk_export int GDKms(void);
|
||
|
|
||
|
|
||
|
#if !defined(NDEBUG) && !defined(__COVERITY__)
|
||
|
/* In debugging mode, replace GDKmalloc and other functions with a
|
||
|
* version that optionally prints calling information.
|
||
|
*
|
||
|
* We have two versions of this code: one using a GNU C extension, and
|
||
|
* one using traditional C. The GNU C version also prints the name of
|
||
|
* the calling function.
|
||
|
*/
|
||
|
#ifdef __GNUC__
|
||
|
#define GDKmalloc(s) \
|
||
|
({ \
|
||
|
size_t _size = (s); \
|
||
|
void *_res = GDKmalloc(_size); \
|
||
|
TRC_DEBUG(ALLOC, "GDKmalloc(%zu) -> %p\n", \
|
||
|
_size, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define GDKzalloc(s) \
|
||
|
({ \
|
||
|
size_t _size = (s); \
|
||
|
void *_res = GDKzalloc(_size); \
|
||
|
TRC_DEBUG(ALLOC, "GDKzalloc(%zu) -> %p\n", \
|
||
|
_size, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define GDKrealloc(p, s) \
|
||
|
({ \
|
||
|
void *_ptr = (p); \
|
||
|
size_t _size = (s); \
|
||
|
char _buf[12]; \
|
||
|
snprintf(_buf, sizeof(_buf), "%p", _ptr); \
|
||
|
void *_res = GDKrealloc(_ptr, _size); \
|
||
|
TRC_DEBUG(ALLOC, "GDKrealloc(%s,%zu) -> %p\n", \
|
||
|
_buf, _size, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define GDKfree(p) \
|
||
|
({ \
|
||
|
void *_ptr = (p); \
|
||
|
if (_ptr) \
|
||
|
TRC_DEBUG(ALLOC, "GDKfree(%p)\n", _ptr); \
|
||
|
GDKfree(_ptr); \
|
||
|
})
|
||
|
#define GDKstrdup(s) \
|
||
|
({ \
|
||
|
const char *_str = (s); \
|
||
|
void *_res = GDKstrdup(_str); \
|
||
|
TRC_DEBUG(ALLOC, "GDKstrdup(len=%zu) -> %p\n", \
|
||
|
_str ? strlen(_str) : 0, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define GDKstrndup(s, n) \
|
||
|
({ \
|
||
|
const char *_str = (s); \
|
||
|
size_t _n = (n); \
|
||
|
void *_res = GDKstrndup(_str, _n); \
|
||
|
TRC_DEBUG(ALLOC, "GDKstrndup(len=%zu) -> %p\n", \
|
||
|
_n, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define GDKmmap(p, m, l) \
|
||
|
({ \
|
||
|
const char *_path = (p); \
|
||
|
int _mode = (m); \
|
||
|
size_t _len = (l); \
|
||
|
void *_res = GDKmmap(_path, _mode, _len); \
|
||
|
TRC_DEBUG(ALLOC, "GDKmmap(%s,0x%x,%zu) -> %p\n", \
|
||
|
_path ? _path : "NULL", \
|
||
|
(unsigned) _mode, _len, \
|
||
|
_res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define GDKmunmap(p, l) \
|
||
|
({ void *_ptr = (p); \
|
||
|
size_t _len = (l); \
|
||
|
gdk_return _res = GDKmunmap(_ptr, _len); \
|
||
|
TRC_DEBUG(ALLOC, \
|
||
|
"GDKmunmap(%p,%zu) -> %u\n", \
|
||
|
_ptr, _len, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define malloc(s) \
|
||
|
({ \
|
||
|
size_t _size = (s); \
|
||
|
void *_res = malloc(_size); \
|
||
|
TRC_DEBUG(ALLOC, "malloc(%zu) -> %p\n", \
|
||
|
_size, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define calloc(n, s) \
|
||
|
({ \
|
||
|
size_t _nmemb = (n); \
|
||
|
size_t _size = (s); \
|
||
|
void *_res = calloc(_nmemb,_size); \
|
||
|
TRC_DEBUG(ALLOC, "calloc(%zu,%zu) -> %p\n", \
|
||
|
_nmemb, _size, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define realloc(p, s) \
|
||
|
({ \
|
||
|
void *_ptr = (p); \
|
||
|
size_t _size = (s); \
|
||
|
char _buf[12]; \
|
||
|
snprintf(_buf, sizeof(_buf), "%p", _ptr); \
|
||
|
void *_res = realloc(_ptr, _size); \
|
||
|
TRC_DEBUG(ALLOC, "realloc(%s,%zu) -> %p\n", \
|
||
|
_buf, _size, _res); \
|
||
|
_res; \
|
||
|
})
|
||
|
#define free(p) \
|
||
|
({ \
|
||
|
void *_ptr = (p); \
|
||
|
TRC_DEBUG(ALLOC, "free(%p)\n", _ptr); \
|
||
|
free(_ptr); \
|
||
|
})
|
||
|
#else
|
||
|
static inline void *
|
||
|
GDKmalloc_debug(size_t size)
|
||
|
{
|
||
|
void *res = GDKmalloc(size);
|
||
|
TRC_DEBUG(ALLOC, "GDKmalloc(%zu) -> %p\n", size, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define GDKmalloc(s) GDKmalloc_debug((s))
|
||
|
static inline void *
|
||
|
GDKzalloc_debug(size_t size)
|
||
|
{
|
||
|
void *res = GDKzalloc(size);
|
||
|
TRC_DEBUG(ALLOC, "GDKzalloc(%zu) -> %p\n", size, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define GDKzalloc(s) GDKzalloc_debug((s))
|
||
|
static inline void *
|
||
|
GDKrealloc_debug(void *ptr, size_t size)
|
||
|
{
|
||
|
void *res = GDKrealloc(ptr, size);
|
||
|
TRC_DEBUG(ALLOC, "GDKrealloc(%p,%zu) -> %p\n", ptr, size, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define GDKrealloc(p, s) GDKrealloc_debug((p), (s))
|
||
|
static inline void
|
||
|
GDKfree_debug(void *ptr)
|
||
|
{
|
||
|
TRC_DEBUG(ALLOC, "GDKfree(%p)\n", ptr);
|
||
|
GDKfree(ptr);
|
||
|
}
|
||
|
#define GDKfree(p) GDKfree_debug((p))
|
||
|
static inline char *
|
||
|
GDKstrdup_debug(const char *str)
|
||
|
{
|
||
|
void *res = GDKstrdup(str);
|
||
|
TRC_DEBUG(ALLOC, "GDKstrdup(len=%zu) -> %p\n",
|
||
|
str ? strlen(str) : 0, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define GDKstrdup(s) GDKstrdup_debug((s))
|
||
|
static inline char *
|
||
|
GDKstrndup_debug(const char *str, size_t n)
|
||
|
{
|
||
|
void *res = GDKstrndup(str, n);
|
||
|
TRC_DEBUG(ALLOC, "GDKstrndup(len=%zu) -> %p\n", n, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define GDKstrndup(s, n) GDKstrndup_debug((s), (n))
|
||
|
static inline void *
|
||
|
GDKmmap_debug(const char *path, int mode, size_t len)
|
||
|
{
|
||
|
void *res = GDKmmap(path, mode, len);
|
||
|
TRC_DEBUG(ALLOC, "GDKmmap(%s,0x%x,%zu) -> %p\n",
|
||
|
path ? path : "NULL", (unsigned) mode, len, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define GDKmmap(p, m, l) GDKmmap_debug((p), (m), (l))
|
||
|
static inline gdk_return
|
||
|
GDKmunmap_debug(void *ptr, size_t len)
|
||
|
{
|
||
|
gdk_return res = GDKmunmap(ptr, len);
|
||
|
TRC_DEBUG(ALLOC, "GDKmunmap(%p,%zu) -> %d\n",
|
||
|
ptr, len, (int) res);
|
||
|
return res;
|
||
|
}
|
||
|
#define GDKmunmap(p, l) GDKmunmap_debug((p), (l))
|
||
|
static inline void *
|
||
|
malloc_debug(size_t size)
|
||
|
{
|
||
|
void *res = malloc(size);
|
||
|
TRC_DEBUG(ALLOC, "malloc(%zu) -> %p\n", size, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define malloc(s) malloc_debug((s))
|
||
|
static inline void *
|
||
|
calloc_debug(size_t nmemb, size_t size)
|
||
|
{
|
||
|
void *res = calloc(nmemb, size);
|
||
|
TRC_DEBUG(ALLOC, "calloc(%zu,%zu) -> %p\n", nmemb, size, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define calloc(n, s) calloc_debug((n), (s))
|
||
|
static inline void *
|
||
|
realloc_debug(void *ptr, size_t size)
|
||
|
{
|
||
|
void *res = realloc(ptr, size);
|
||
|
TRC_DEBUG(ALLOC, "realloc(%p,%zu) -> %p \n", ptr, size, res);
|
||
|
return res;
|
||
|
}
|
||
|
#define realloc(p, s) realloc_debug((p), (s))
|
||
|
static inline void
|
||
|
free_debug(void *ptr)
|
||
|
{
|
||
|
TRC_DEBUG(ALLOC, "free(%p)\n", ptr);
|
||
|
free(ptr);
|
||
|
}
|
||
|
#define free(p) free_debug((p))
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#endif /* _GDK_UTILS_H_ */
|