| 1 | /* |
| 2 | * This Source Code Form is subject to the terms of the Mozilla Public |
| 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 5 | * |
| 6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. |
| 7 | */ |
| 8 | |
| 9 | /* This file should not be included in any file outside of this directory */ |
| 10 | |
| 11 | #ifndef LIBGDK |
| 12 | #error this file should not be included outside its source directory |
| 13 | #endif |
| 14 | |
| 15 | /* persist hash heaps for persistent BATs */ |
| 16 | #define PERSISTENTHASH 1 |
| 17 | |
| 18 | /* persist order index heaps for persistent BATs */ |
| 19 | #define PERSISTENTIDX 1 |
| 20 | |
| 21 | #include "gdk_system_private.h" |
| 22 | |
| 23 | enum heaptype { |
| 24 | offheap, |
| 25 | varheap, |
| 26 | hashheap, |
| 27 | imprintsheap, |
| 28 | orderidxheap |
| 29 | }; |
| 30 | |
| 31 | #ifdef GDKLIBRARY_OLDDATE |
| 32 | __hidden int cvtdate(int n) |
| 33 | __attribute__((__visibility__("hidden" ))); |
| 34 | #endif |
| 35 | |
| 36 | __hidden gdk_return ATOMheap(int id, Heap *hp, size_t cap) |
| 37 | __attribute__((__warn_unused_result__)) |
| 38 | __attribute__((__visibility__("hidden" ))); |
| 39 | __hidden bool ATOMisdescendant(int id, int parentid) |
| 40 | __attribute__((__visibility__("hidden" ))); |
| 41 | __hidden int ATOMunknown_find(const char *nme) |
| 42 | __attribute__((__warn_unused_result__)) |
| 43 | __attribute__((__visibility__("hidden" ))); |
| 44 | __hidden str ATOMunknown_name(int a) |
| 45 | __attribute__((__visibility__("hidden" ))); |
| 46 | __hidden void ATOMunknown_clean(void) |
| 47 | __attribute__((__visibility__("hidden" ))); |
| 48 | __hidden bool BATcheckhash(BAT *b) |
| 49 | __attribute__((__visibility__("hidden" ))); |
| 50 | __hidden bool BATcheckimprints(BAT *b) |
| 51 | __attribute__((__visibility__("hidden" ))); |
| 52 | __hidden gdk_return BATcheckmodes(BAT *b, bool persistent) |
| 53 | __attribute__((__warn_unused_result__)) |
| 54 | __attribute__((__visibility__("hidden" ))); |
| 55 | __hidden BAT *BATcreatedesc(oid hseq, int tt, bool heapnames, role_t role) |
| 56 | __attribute__((__visibility__("hidden" ))); |
| 57 | __hidden void BATdelete(BAT *b) |
| 58 | __attribute__((__visibility__("hidden" ))); |
| 59 | __hidden void BATdestroy(BAT *b) |
| 60 | __attribute__((__visibility__("hidden" ))); |
| 61 | __hidden void BATfree(BAT *b) |
| 62 | __attribute__((__visibility__("hidden" ))); |
| 63 | __hidden PROPrec *BATgetprop(BAT *b, enum prop_t idx) |
| 64 | __attribute__((__visibility__("hidden" ))); |
| 65 | __hidden PROPrec * BATgetprop_nolock(BAT *b, enum prop_t idx) |
| 66 | __attribute__((__visibility__("hidden" ))); |
| 67 | __hidden gdk_return BATgroup_internal(BAT **groups, BAT **extents, BAT **histo, BAT *b, BAT *s, BAT *g, BAT *e, BAT *h, bool subsorted) |
| 68 | __attribute__((__warn_unused_result__)) |
| 69 | __attribute__((__visibility__("hidden" ))); |
| 70 | __hidden Hash *BAThash_impl(BAT *b, BAT *s, const char *ext) |
| 71 | __attribute__((__visibility__("hidden" ))); |
| 72 | __hidden void BATinit_idents(BAT *bn) |
| 73 | __attribute__((__visibility__("hidden" ))); |
| 74 | __hidden BAT *BATload_intern(bat bid, bool lock) |
| 75 | __attribute__((__visibility__("hidden" ))); |
| 76 | __hidden gdk_return BATmaterialize(BAT *b) |
| 77 | __attribute__((__warn_unused_result__)) |
| 78 | __attribute__((__visibility__("hidden" ))); |
| 79 | __hidden void BATrmprop(BAT *b, enum prop_t idx) |
| 80 | __attribute__((__visibility__("hidden" ))); |
| 81 | __hidden void BATsetdims(BAT *b) |
| 82 | __attribute__((__visibility__("hidden" ))); |
| 83 | __hidden void BATsetprop(BAT *b, enum prop_t idx, int type, const void *v) |
| 84 | __attribute__((__visibility__("hidden" ))); |
| 85 | __hidden void BATsetprop_nolock(BAT *b, enum prop_t idx, int type, const void *v) |
| 86 | __attribute__((__visibility__("hidden" ))); |
| 87 | __hidden gdk_return BBPcacheit(BAT *bn, bool lock) |
| 88 | __attribute__((__warn_unused_result__)) |
| 89 | __attribute__((__visibility__("hidden" ))); |
| 90 | void BBPdump(void) /* never called: for debugging only */ |
| 91 | __attribute__((__cold__)); |
| 92 | __hidden void BBPexit(void) |
| 93 | __attribute__((__visibility__("hidden" ))); |
| 94 | __hidden BAT *BBPgetdesc(bat i) |
| 95 | __attribute__((__visibility__("hidden" ))); |
| 96 | __hidden gdk_return BBPinit(void) |
| 97 | __attribute__((__visibility__("hidden" ))); |
| 98 | __hidden bat BBPinsert(BAT *bn) |
| 99 | __attribute__((__warn_unused_result__)) |
| 100 | __attribute__((__visibility__("hidden" ))); |
| 101 | __hidden int BBPselectfarm(role_t role, int type, enum heaptype hptype) |
| 102 | __attribute__((__visibility__("hidden" ))); |
| 103 | __hidden void BBPunshare(bat b) |
| 104 | __attribute__((__visibility__("hidden" ))); |
| 105 | __hidden BUN binsearch(const oid *restrict indir, oid offset, int type, const void *restrict vals, const char * restrict vars, int width, BUN lo, BUN hi, const void *restrict v, int ordering, int last) |
| 106 | __attribute__((__visibility__("hidden" ))); |
| 107 | __hidden BUN binsearch_bte(const oid *restrict indir, oid offset, const bte *restrict vals, BUN lo, BUN hi, bte v, int ordering, int last) |
| 108 | __attribute__((__visibility__("hidden" ))); |
| 109 | __hidden BUN binsearch_sht(const oid *restrict indir, oid offset, const sht *restrict vals, BUN lo, BUN hi, sht v, int ordering, int last) |
| 110 | __attribute__((__visibility__("hidden" ))); |
| 111 | __hidden BUN binsearch_int(const oid *restrict indir, oid offset, const int *restrict vals, BUN lo, BUN hi, int v, int ordering, int last) |
| 112 | __attribute__((__visibility__("hidden" ))); |
| 113 | __hidden BUN binsearch_lng(const oid *restrict indir, oid offset, const lng *restrict vals, BUN lo, BUN hi, lng v, int ordering, int last) |
| 114 | __attribute__((__visibility__("hidden" ))); |
| 115 | #ifdef HAVE_HGE |
| 116 | __hidden BUN binsearch_hge(const oid *restrict indir, oid offset, const hge *restrict vals, BUN lo, BUN hi, hge v, int ordering, int last) |
| 117 | __attribute__((__visibility__("hidden" ))); |
| 118 | #endif |
| 119 | __hidden BUN binsearch_flt(const oid *restrict indir, oid offset, const flt *restrict vals, BUN lo, BUN hi, flt v, int ordering, int last) |
| 120 | __attribute__((__visibility__("hidden" ))); |
| 121 | __hidden BUN binsearch_dbl(const oid *restrict indir, oid offset, const dbl *restrict vals, BUN lo, BUN hi, dbl v, int ordering, int last) |
| 122 | __attribute__((__visibility__("hidden" ))); |
| 123 | __hidden gdk_return BUNreplace(BAT *b, oid left, const void *right, bool force) |
| 124 | __attribute__((__warn_unused_result__)) |
| 125 | __attribute__((__visibility__("hidden" ))); |
| 126 | __hidden Heap *createOIDXheap(BAT *b, bool stable) |
| 127 | __attribute__((__visibility__("hidden" ))); |
| 128 | __hidden void gdk_bbp_reset(void) |
| 129 | __attribute__((__visibility__("hidden" ))); |
| 130 | __hidden gdk_return GDKextend(const char *fn, size_t size) |
| 131 | __attribute__((__warn_unused_result__)) |
| 132 | __attribute__((__visibility__("hidden" ))); |
| 133 | __hidden gdk_return GDKextendf(int fd, size_t size, const char *fn) |
| 134 | __attribute__((__warn_unused_result__)) |
| 135 | __attribute__((__visibility__("hidden" ))); |
| 136 | __hidden int GDKfdlocate(int farmid, const char *nme, const char *mode, const char *ext) |
| 137 | __attribute__((__visibility__("hidden" ))); |
| 138 | __hidden FILE *GDKfilelocate(int farmid, const char *nme, const char *mode, const char *ext) |
| 139 | __attribute__((__visibility__("hidden" ))); |
| 140 | __hidden FILE *GDKfileopen(int farmid, const char *dir, const char *name, const char *extension, const char *mode) |
| 141 | __attribute__((__visibility__("hidden" ))); |
| 142 | __hidden char *GDKload(int farmid, const char *nme, const char *ext, size_t size, size_t *maxsize, storage_t mode) |
| 143 | __attribute__((__visibility__("hidden" ))); |
| 144 | __hidden void GDKlog(_In_z_ _Printf_format_string_ FILE * fl, const char *format, ...) |
| 145 | __attribute__((__format__(__printf__, 2, 3))) |
| 146 | __attribute__((__visibility__("hidden" ))); |
| 147 | __hidden gdk_return GDKmove(int farmid, const char *dir1, const char *nme1, const char *ext1, const char *dir2, const char *nme2, const char *ext2) |
| 148 | __attribute__((__warn_unused_result__)) |
| 149 | __attribute__((__visibility__("hidden" ))); |
| 150 | __hidden void *GDKmremap(const char *path, int mode, void *old_address, size_t old_size, size_t *new_size) |
| 151 | __attribute__((__visibility__("hidden" ))); |
| 152 | __hidden gdk_return GDKmunmap(void *addr, size_t len) |
| 153 | __attribute__((__warn_unused_result__)) |
| 154 | __attribute__((__visibility__("hidden" ))); |
| 155 | __hidden gdk_return GDKremovedir(int farmid, const char *nme) |
| 156 | __attribute__((__warn_unused_result__)) |
| 157 | __attribute__((__visibility__("hidden" ))); |
| 158 | __hidden gdk_return GDKsave(int farmid, const char *nme, const char *ext, void *buf, size_t size, storage_t mode, bool dosync) |
| 159 | __attribute__((__warn_unused_result__)) |
| 160 | __attribute__((__visibility__("hidden" ))); |
| 161 | __hidden gdk_return GDKssort_rev(void *restrict h, void *restrict t, const void *restrict base, size_t n, int hs, int ts, int tpe) |
| 162 | __attribute__((__warn_unused_result__)) |
| 163 | __attribute__((__visibility__("hidden" ))); |
| 164 | __hidden gdk_return GDKssort(void *restrict h, void *restrict t, const void *restrict base, size_t n, int hs, int ts, int tpe) |
| 165 | __attribute__((__warn_unused_result__)) |
| 166 | __attribute__((__visibility__("hidden" ))); |
| 167 | __hidden gdk_return GDKunlink(int farmid, const char *dir, const char *nme, const char *extension) |
| 168 | __attribute__((__visibility__("hidden" ))); |
| 169 | #ifdef NATIVE_WIN32 |
| 170 | __hidden void GDKwinerror(_In_z_ _Printf_format_string_ const char *format, ...) |
| 171 | __attribute__((__format__(__printf__, 1, 2))) |
| 172 | __attribute__((__visibility__("hidden" ))); |
| 173 | #endif |
| 174 | __hidden void HASHfree(BAT *b) |
| 175 | __attribute__((__visibility__("hidden" ))); |
| 176 | __hidden bool HASHgonebad(BAT *b, const void *v) |
| 177 | __attribute__((__visibility__("hidden" ))); |
| 178 | __hidden BUN HASHmask(BUN cnt) |
| 179 | __attribute__((__visibility__("hidden" ))); |
| 180 | __hidden gdk_return HASHnew(Hash *h, int tpe, BUN size, BUN mask, BUN count) |
| 181 | __attribute__((__visibility__("hidden" ))); |
| 182 | __hidden gdk_return HEAPalloc(Heap *h, size_t nitems, size_t itemsize) |
| 183 | __attribute__((__warn_unused_result__)) |
| 184 | __attribute__((__visibility__("hidden" ))); |
| 185 | __hidden gdk_return HEAPcopy(Heap *dst, Heap *src) |
| 186 | __attribute__((__warn_unused_result__)) |
| 187 | __attribute__((__visibility__("hidden" ))); |
| 188 | __hidden gdk_return HEAPdelete(Heap *h, const char *o, const char *ext) |
| 189 | __attribute__((__visibility__("hidden" ))); |
| 190 | __hidden void HEAPfree(Heap *h, bool remove) |
| 191 | __attribute__((__visibility__("hidden" ))); |
| 192 | __hidden gdk_return HEAPload(Heap *h, const char *nme, const char *ext, bool trunc) |
| 193 | __attribute__((__warn_unused_result__)) |
| 194 | __attribute__((__visibility__("hidden" ))); |
| 195 | __hidden void HEAP_recover(Heap *, const var_t *, BUN) |
| 196 | __attribute__((__visibility__("hidden" ))); |
| 197 | __hidden gdk_return HEAPsave(Heap *h, const char *nme, const char *ext) |
| 198 | __attribute__((__warn_unused_result__)) |
| 199 | __attribute__((__visibility__("hidden" ))); |
| 200 | __hidden gdk_return HEAPshrink(Heap *h, size_t size) |
| 201 | __attribute__((__warn_unused_result__)) |
| 202 | __attribute__((__visibility__("hidden" ))); |
| 203 | __hidden int HEAPwarm(Heap *h) |
| 204 | __attribute__((__visibility__("hidden" ))); |
| 205 | __hidden void IMPSfree(BAT *b) |
| 206 | __attribute__((__visibility__("hidden" ))); |
| 207 | __hidden int IMPSgetbin(int tpe, bte bits, const char *restrict bins, const void *restrict v) |
| 208 | __attribute__((__visibility__("hidden" ))); |
| 209 | #ifndef NDEBUG |
| 210 | void IMPSprint(BAT *b) /* never called: for debugging only */ |
| 211 | __attribute__((__cold__)); |
| 212 | #endif |
| 213 | __hidden void MT_init_posix(void) |
| 214 | __attribute__((__visibility__("hidden" ))); |
| 215 | __hidden void *MT_mremap(const char *path, int mode, void *old_address, size_t old_size, size_t *new_size) |
| 216 | __attribute__((__visibility__("hidden" ))); |
| 217 | __hidden int MT_msync(void *p, size_t len) |
| 218 | __attribute__((__visibility__("hidden" ))); |
| 219 | __hidden void OIDXfree(BAT *b) |
| 220 | __attribute__((__visibility__("hidden" ))); |
| 221 | __hidden void persistOIDX(BAT *b) |
| 222 | __attribute__((__visibility__("hidden" ))); |
| 223 | __hidden void PROPdestroy(BAT *b) |
| 224 | __attribute__((__visibility__("hidden" ))); |
| 225 | __hidden gdk_return rangejoin(BAT *r1, BAT *r2, BAT *l, BAT *rl, BAT *rh, struct canditer *lci, struct canditer *rci, bool li, bool hi, bool anti, bool symmetric, BUN maxsize) |
| 226 | __attribute__((__warn_unused_result__)) |
| 227 | __attribute__((__visibility__("hidden" ))); |
| 228 | __hidden void strCleanHash(Heap *hp, bool rebuild) |
| 229 | __attribute__((__visibility__("hidden" ))); |
| 230 | __hidden int strCmp(const char *l, const char *r) |
| 231 | __attribute__((__visibility__("hidden" ))); |
| 232 | __hidden int strCmpNoNil(const unsigned char *l, const unsigned char *r) |
| 233 | __attribute__((__visibility__("hidden" ))); |
| 234 | __hidden void strHeap(Heap *d, size_t cap) |
| 235 | __attribute__((__visibility__("hidden" ))); |
| 236 | __hidden var_t strLocate(Heap *h, const char *v) |
| 237 | __attribute__((__visibility__("hidden" ))); |
| 238 | __hidden var_t strPut(Heap *h, var_t *dst, const char *v) |
| 239 | __attribute__((__visibility__("hidden" ))); |
| 240 | __hidden str strRead(str a, stream *s, size_t cnt) |
| 241 | __attribute__((__visibility__("hidden" ))); |
| 242 | __hidden ssize_t strToStr(char **restrict dst, size_t *restrict len, const char *restrict src, bool external) |
| 243 | __attribute__((__visibility__("hidden" ))); |
| 244 | __hidden gdk_return strWrite(const char *a, stream *s, size_t cnt) |
| 245 | __attribute__((__visibility__("hidden" ))); |
| 246 | __hidden gdk_return unshare_string_heap(BAT *b) |
| 247 | __attribute__((__warn_unused_result__)) |
| 248 | __attribute__((__visibility__("hidden" ))); |
| 249 | __hidden void VIEWdestroy(BAT *b) |
| 250 | __attribute__((__visibility__("hidden" ))); |
| 251 | __hidden gdk_return VIEWreset(BAT *b) |
| 252 | __attribute__((__warn_unused_result__)) |
| 253 | __attribute__((__visibility__("hidden" ))); |
| 254 | __hidden BAT *virtualize(BAT *bn) |
| 255 | __attribute__((__visibility__("hidden" ))); |
| 256 | |
| 257 | /* some macros to help print info about BATs when using ALGODEBUG */ |
| 258 | #define ALGOBATFMT "%s#" BUNFMT "@" OIDFMT "[%s]%s%s%s%s%s%s%s%s%s" |
| 259 | #define ALGOBATPAR(b) BATgetId(b), \ |
| 260 | BATcount(b), \ |
| 261 | b->hseqbase, \ |
| 262 | ATOMname(b->ttype), \ |
| 263 | !b->batTransient ? "P" : isVIEW(b) ? "V" : "T", \ |
| 264 | BATtdense(b) ? "D" : b->ttype == TYPE_void && b->tvheap ? "X" :"", \ |
| 265 | b->tsorted ? "S" : "", \ |
| 266 | b->trevsorted ? "R" : "", \ |
| 267 | b->tkey ? "K" : "", \ |
| 268 | b->tnonil ? "N" : "", \ |
| 269 | b->thash ? "H" : "", \ |
| 270 | b->torderidx ? "O" : "", \ |
| 271 | b->timprints ? "I" : b->theap.parentid && BBP_cache(b->theap.parentid)->timprints ? "(I)" : "" |
| 272 | /* use ALGOOPTBAT* when BAT is optional (can be NULL) */ |
| 273 | #define ALGOOPTBATFMT "%s%s" BUNFMT "%s" OIDFMT "%s%s%s%s%s%s%s%s%s%s%s%s" |
| 274 | #define ALGOOPTBATPAR(b) \ |
| 275 | b ? BATgetId(b) : "", \ |
| 276 | b ? "#" : "", \ |
| 277 | b ? BATcount(b) : 0, \ |
| 278 | b ? "@" : "", \ |
| 279 | b ? b->hseqbase : 0, \ |
| 280 | b ? "[" : "", \ |
| 281 | b ? ATOMname(b->ttype) : "", \ |
| 282 | b ? "]" : "", \ |
| 283 | b ? !b->batTransient ? "P" : isVIEW(b) ? "V" : "T" : "", \ |
| 284 | b && BATtdense(b) ? "D" : b && b->ttype == TYPE_void && b->tvheap ? "X" :"", \ |
| 285 | b && b->tsorted ? "S" : "", \ |
| 286 | b && b->trevsorted ? "R" : "", \ |
| 287 | b && b->tkey ? "K" : "", \ |
| 288 | b && b->tnonil ? "N" : "", \ |
| 289 | b && b->thash ? "H" : "", \ |
| 290 | b && b->torderidx ? "O" : "", \ |
| 291 | b ? b->timprints ? "I" : b->theap.parentid && BBP_cache(b->theap.parentid)->timprints ? "(I)" : "" : "" |
| 292 | |
| 293 | #define BBP_BATMASK (128 * SIZEOF_SIZE_T - 1) |
| 294 | #define BBP_THREADMASK 63 |
| 295 | |
| 296 | struct PROPrec { |
| 297 | enum prop_t id; |
| 298 | ValRecord v; |
| 299 | struct PROPrec *next; /* simple chain of properties */ |
| 300 | }; |
| 301 | |
| 302 | struct Imprints { |
| 303 | bte bits; /* how many bits in imprints */ |
| 304 | Heap imprints; |
| 305 | void *bins; /* pointer into imprints heap (bins borders) */ |
| 306 | BUN *stats; /* pointer into imprints heap (stats per bin) */ |
| 307 | void *imps; /* pointer into imprints heap (bit vectors) */ |
| 308 | void *dict; /* pointer into imprints heap (dictionary) */ |
| 309 | BUN impcnt; /* counter for imprints */ |
| 310 | BUN dictcnt; /* counter for cache dictionary */ |
| 311 | }; |
| 312 | |
| 313 | typedef struct { |
| 314 | MT_Lock swap; |
| 315 | } batlock_t; |
| 316 | |
| 317 | typedef struct { |
| 318 | MT_Lock cache; |
| 319 | MT_Lock trim; |
| 320 | bat free; |
| 321 | } bbplock_t; |
| 322 | |
| 323 | typedef char long_str[IDLENGTH]; /* standard GDK static string */ |
| 324 | |
| 325 | #define MAXFARMS 32 |
| 326 | |
| 327 | extern struct BBPfarm_t { |
| 328 | unsigned int roles; /* bitmask of allowed roles */ |
| 329 | const char *dirname; /* farm directory */ |
| 330 | FILE *lock_file; |
| 331 | } BBPfarms[MAXFARMS]; |
| 332 | |
| 333 | extern batlock_t GDKbatLock[BBP_BATMASK + 1]; |
| 334 | extern bbplock_t GDKbbpLock[BBP_THREADMASK + 1]; |
| 335 | extern size_t GDK_mmap_minsize_persistent; /* size after which we use memory mapped files for persistent heaps */ |
| 336 | extern size_t GDK_mmap_minsize_transient; /* size after which we use memory mapped files for transient heaps */ |
| 337 | extern size_t GDK_mmap_pagesize; /* mmap granularity */ |
| 338 | extern MT_Lock GDKnameLock; |
| 339 | extern MT_Lock GDKthreadLock; |
| 340 | extern MT_Lock GDKtmLock; |
| 341 | |
| 342 | #define BATcheck(tst, msg, err) \ |
| 343 | do { \ |
| 344 | if ((tst) == NULL) { \ |
| 345 | if (strchr((msg), ':')) \ |
| 346 | GDKerror("%s.\n", (msg)); \ |
| 347 | else \ |
| 348 | GDKerror("%s: BAT required.\n", (msg)); \ |
| 349 | return (err); \ |
| 350 | } \ |
| 351 | } while (0) |
| 352 | #define ERRORcheck(tst, msg, err) \ |
| 353 | do { \ |
| 354 | if (tst) { \ |
| 355 | GDKerror(msg); \ |
| 356 | return (err); \ |
| 357 | } \ |
| 358 | } while (0) |
| 359 | |
| 360 | #define GDKswapLock(x) GDKbatLock[(x)&BBP_BATMASK].swap |
| 361 | #if SIZEOF_SIZE_T == 8 |
| 362 | #define threadmask(y) ((int) ((mix_int((unsigned int) y) ^ mix_int((unsigned int) (y >> 32))) & BBP_THREADMASK)) |
| 363 | #else |
| 364 | #define threadmask(y) ((int) (mix_int(y) & BBP_THREADMASK)) |
| 365 | #endif |
| 366 | #define GDKtrimLock(y) GDKbbpLock[y].trim |
| 367 | #define GDKcacheLock(y) GDKbbpLock[y].cache |
| 368 | #define BBP_free(y) GDKbbpLock[y].free |
| 369 | |
| 370 | /* extra space in front of strings in string heaps when hashash is set |
| 371 | * if at least (2*SIZEOF_BUN), also store length (heaps are then |
| 372 | * incompatible) */ |
| 373 | #define ((SIZEOF_BUN + GDK_VARALIGN - 1) & ~(GDK_VARALIGN - 1)) |
| 374 | |
| 375 | #if !defined(NDEBUG) && !defined(STATIC_CODE_ANALYSIS) |
| 376 | /* see comment in gdk.h */ |
| 377 | #ifdef __GNUC__ |
| 378 | #define GDKmunmap(p, l) \ |
| 379 | ({ void *_ptr = (p); \ |
| 380 | size_t _len = (l); \ |
| 381 | gdk_return _res = GDKmunmap(_ptr, _len); \ |
| 382 | ALLOCDEBUG \ |
| 383 | fprintf(stderr, \ |
| 384 | "#GDKmunmap(%p,%zu) -> %u" \ |
| 385 | " %s[%s:%d]\n", \ |
| 386 | _ptr, _len, _res, \ |
| 387 | __func__, __FILE__, __LINE__); \ |
| 388 | _res; \ |
| 389 | }) |
| 390 | #define GDKmremap(p, m, oa, os, ns) \ |
| 391 | ({ \ |
| 392 | const char *_path = (p); \ |
| 393 | int _mode = (m); \ |
| 394 | void *_oa = (oa); \ |
| 395 | size_t _os = (os); \ |
| 396 | size_t *_ns = (ns); \ |
| 397 | size_t _ons = *_ns; \ |
| 398 | void *_res = GDKmremap(_path, _mode, _oa, _os, _ns); \ |
| 399 | ALLOCDEBUG \ |
| 400 | fprintf(stderr, \ |
| 401 | "#GDKmremap(%s,0x%x,%p,%zu,%zu > %zu) -> %p" \ |
| 402 | " %s[%s:%d]\n", \ |
| 403 | _path ? _path : "NULL", (unsigned) _mode, \ |
| 404 | _oa, _os, _ons, *_ns, \ |
| 405 | _res, \ |
| 406 | __func__, __FILE__, __LINE__); \ |
| 407 | _res; \ |
| 408 | }) |
| 409 | #else |
| 410 | static inline gdk_return |
| 411 | GDKmunmap_debug(void *ptr, size_t len, const char *filename, int lineno) |
| 412 | { |
| 413 | gdk_return res = GDKmunmap(ptr, len); |
| 414 | ALLOCDEBUG fprintf(stderr, |
| 415 | "#GDKmunmap(%p,%zu) -> %d [%s:%d]\n" , |
| 416 | ptr, len, (int) res, filename, lineno); |
| 417 | return res; |
| 418 | } |
| 419 | #define GDKmunmap(p, l) GDKmunmap_debug((p), (l), __FILE__, __LINE__) |
| 420 | static inline void * |
| 421 | GDKmremap_debug(const char *path, int mode, void *old_address, size_t old_size, size_t *new_size, const char *filename, int lineno) |
| 422 | { |
| 423 | size_t orig_new_size = *new_size; |
| 424 | void *res = GDKmremap(path, mode, old_address, old_size, new_size); |
| 425 | ALLOCDEBUG |
| 426 | fprintf(stderr, |
| 427 | "#GDKmremap(%s,0x%x,%p,%zu,%zu > %zu) -> %p" |
| 428 | " [%s:%d]\n" , |
| 429 | path ? path : "NULL" , mode, |
| 430 | old_address, old_size, orig_new_size, *new_size, |
| 431 | res, |
| 432 | filename, lineno); |
| 433 | return res; |
| 434 | } |
| 435 | #define GDKmremap(p, m, oa, os, ns) GDKmremap_debug(p, m, oa, os, ns, __FILE__, __LINE__) |
| 436 | |
| 437 | #endif |
| 438 | #endif |
| 439 | |