BRL-CAD
malloc.c
Go to the documentation of this file.
1 /* M A L L O C . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 #include <stdlib.h>
24 #include <string.h>
25 #ifdef HAVE_SYS_IPC_H
26 # include <sys/ipc.h>
27 #endif
28 #ifdef HAVE_SYS_SHM_H
29 # include <sys/shm.h>
30 #endif
31 #include "errno.h"
32 #include "bio.h"
33 
34 #include "bu/debug.h"
35 #include "bu/list.h"
36 #include "bu/log.h"
37 #include "bu/malloc.h"
38 #include "bu/parallel.h"
39 
40 /**
41  * this controls whether to semaphore protect malloc calls
42  *
43  * FIXME: we really don't need to do this any more, especially if
44  * compiling against glibc+pthreads. Windows, however, needs might
45  * need some build flag encouragement.
46  */
47 #define MALLOC_NOT_MP_SAFE 1
48 
49 
50 /**
51  * used by the memory allocation routines going through alloc() to
52  * indicate whether allocated memory should be zero'd.
53  */
54 typedef enum {
57 } alloc_t;
58 
59 
60 #define MDB_MAGIC 0x12348969
61 struct memdebug {
62  uint32_t magic; /* corruption can be everywhere */
63  void *mdb_addr;
64  const char *mdb_str;
65  size_t mdb_len;
66 };
67 static struct memdebug *bu_memdebug = (struct memdebug *)NULL;
68 static struct memdebug *bu_memdebug_lowat = (struct memdebug *)NULL;
69 static size_t bu_memdebug_len = 0;
70 #define MEMDEBUG_NULL ((struct memdebug *)0)
71 
72 struct memqdebug {
73  struct bu_list q;
74  struct memdebug m;
75 };
76 
77 
78 static struct bu_list *bu_memq = BU_LIST_NULL;
79 static struct bu_list bu_memqhd = BU_LIST_INIT_ZERO;
80 #define MEMQDEBUG_NULL ((struct memqdebug *)0)
81 
82 /* non-published globals */
83 extern const char bu_vls_message[];
84 extern const char bu_strdup_message[];
85 
86 
87 /**
88  * Add another entry to the memory debug table
89  */
90 HIDDEN void
91 memdebug_add(void *ptr, size_t cnt, const char *str)
92 {
93  register struct memdebug *mp = NULL;
94 
95 top:
97 
98  if (LIKELY(bu_memdebug != NULL)) {
99  mp = &bu_memdebug[bu_memdebug_len-1];
100  if (bu_memdebug_lowat > bu_memdebug
101  && bu_memdebug_lowat < mp)
102  {
103  mp = bu_memdebug_lowat;
104  } else {
105  bu_memdebug_lowat = mp;
106  }
107  }
108 
109 again:
110  if (LIKELY(bu_memdebug != NULL)) {
111  for (; mp >= bu_memdebug; mp--) {
112  /* Search for an empty slot */
113  if (mp->mdb_len > 0) continue;
114  mp->magic = MDB_MAGIC;
115  mp->mdb_addr = ptr;
116  mp->mdb_len = cnt;
117  mp->mdb_str = str;
118  bu_memdebug_lowat = mp-1;
120  return;
121  }
122  /* Didn't find a slot. If started in middle, go again */
123  mp = &bu_memdebug[bu_memdebug_len-1];
124  if (bu_memdebug_lowat != mp) {
125  bu_memdebug_lowat = mp;
126  goto again;
127  }
128  }
129 
130  /* Need to make more slots */
131  if (bu_memdebug_len <= 0) {
132  bu_memdebug_len = 5120-2;
133  bu_memdebug = (struct memdebug *)calloc(
134  bu_memdebug_len, sizeof(struct memdebug));
135  if (bu_memdebug == (struct memdebug *)0)
136  bu_bomb("memdebug_add() malloc failure\n");
137  } else {
138  size_t old_len = bu_memdebug_len;
139  bu_memdebug_len *= 16;
140  bu_memdebug = (struct memdebug *)realloc((char *)bu_memdebug, sizeof(struct memdebug) * bu_memdebug_len);
141  if (bu_memdebug == (struct memdebug *)0)
142  bu_bomb("memdebug_add() malloc failure\n");
143  memset((char *)&bu_memdebug[old_len], 0,
144  (bu_memdebug_len-old_len) * sizeof(struct memdebug));
145  }
147 
148  goto top;
149 }
150 
151 
152 /**
153  * Check an entry against the memory debug table, based upon its address.
154  */
155 HIDDEN struct memdebug *
156 memdebug_check(register void *ptr, const char *str)
157 {
158  register struct memdebug *mp = &bu_memdebug[bu_memdebug_len-1];
159  register uint32_t *ip;
160 
161  if (bu_memdebug == (struct memdebug *)0) {
163  fprintf(stderr, "memdebug_check(%p, %s) no memdebug table yet\n",
164  ptr, str);
166  return MEMDEBUG_NULL;
167  }
168  for (; mp >= bu_memdebug; mp--) {
169  if (!mp->magic) continue;
170  if (mp->magic != MDB_MAGIC) bu_bomb("memdebug_check() malloc tracing table corrupted!\n");
171  if (mp->mdb_len == 0) continue;
172  if (mp->mdb_addr != ptr) continue;
173  ip = (uint32_t *)((char *)ptr+mp->mdb_len-sizeof(uint32_t));
174  if (*ip != MDB_MAGIC) {
176  fprintf(stderr, "ERROR memdebug_check(%p, %s) %s, barrier word corrupted!\nbarrier at %p was=x%lx s/b=x%x, len=%llu\n",
177  ptr, str, mp->mdb_str,
178  (void *)ip, (unsigned long)*ip, MDB_MAGIC, (unsigned long long)mp->mdb_len);
180  bu_bomb("memdebug_check() memory corruption\n");
181  }
182  return mp; /* OK */
183  }
184  return MEMDEBUG_NULL;
185 }
186 
187 
188 extern int bu_bomb_failsafe_init(void);
189 
190 /**
191  * This routine only returns on successful allocation. We promise
192  * never to return a NULL pointer; caller doesn't have to check.
193  *
194  * Requesting allocation of zero bytes is considered a irrecoverable
195  * mistake in order to fulfill the non-NULL promise.
196  *
197  * Failure results in bu_bomb() being called.
198  *
199  * type is 0 for malloc, 1 for calloc
200  */
201 HIDDEN void *
202 alloc(alloc_t type, size_t cnt, size_t sz, const char *str)
203 {
204  void *ptr = 0;
205  register size_t size = sz;
206  const size_t MINSIZE = sizeof(uint32_t) > sizeof(intptr_t) ? sizeof(uint32_t) : sizeof(intptr_t);
207 
208  static int failsafe_init = 0;
209 
210  const char *nul = "(null)";
211  if (!str)
212  str = nul;
213 
214  /* bu_bomb hook to recover from memory problems */
215  if (UNLIKELY(!failsafe_init)) {
216  failsafe_init = bu_bomb_failsafe_init();
217  }
218 
219  if (UNLIKELY(cnt == 0 || sz == 0)) {
220  fprintf(stderr, "ERROR: alloc size=0 (cnt=%llu, sz=%llu) %s\n",
221  (unsigned long long)cnt, (unsigned long long)sz, str);
222  bu_bomb("ERROR: bu_malloc(0)\n");
223  }
224 
225  /* minimum allocation size, always big enough to stash a pointer.
226  * that said, if you're anywhere near this size, you're probably
227  * doing something wrong.
228  */
229  if (UNLIKELY(size < MINSIZE)) {
230  size = MINSIZE;
231  }
232 
233  /* if we're debugging, we need a slightly larger allocation size
234  * for debug tracking.
235  */
237  /* Pad, plus full uint32_t for magic number */
238  size = (size + 2*sizeof(uint32_t) - 1) & (~(sizeof(uint32_t) - 1));
239  } else if (UNLIKELY(bu_debug&BU_DEBUG_MEM_QCHECK)) {
240  size = (size + 2*sizeof(struct memqdebug) - 1) & (~(sizeof(struct memqdebug) - 1));
241  }
242 
243 #if defined(MALLOC_NOT_MP_SAFE)
245 #endif
246 
247 /* align allocations to what address multiple */
248 #define ALIGN 8
249 
250  switch (type) {
251  case MALLOC:
252 #ifdef HAVE_POSIX_MEMALIGN
253  if (posix_memalign(&ptr, ALIGN, cnt*size))
254  ptr = NULL;
255 #else
256  ptr = malloc(cnt*size);
257 #endif
258  break;
259  case CALLOC:
260 #ifdef HAVE_POSIX_MEMALIGN
261  if (posix_memalign(&ptr, ALIGN, cnt*size))
262  ptr = NULL;
263  else
264  memset(ptr, 0, cnt*size);
265 #else
266  ptr = calloc(cnt, size);
267 #endif
268  break;
269  default:
270  bu_bomb("ERROR: alloc with unknown type\n");
271  }
272 
273  if (UNLIKELY(ptr==NULL || bu_debug&BU_DEBUG_MEM_LOG)) {
274  fprintf(stderr, "NULL malloc(%llu) %s\n", (unsigned long long)(cnt*size), str);
275  }
276 
277 #if defined(MALLOC_NOT_MP_SAFE)
279 #endif
280 
281  if (UNLIKELY(ptr==(char *)0)) {
282  fprintf(stderr, "bu_malloc: Insufficient memory available\n");
283  bu_bomb("bu_malloc: malloc failure");
284  }
285  if (UNLIKELY(bu_debug&BU_DEBUG_MEM_CHECK)) {
286  memdebug_add(ptr, cnt*size, str);
287 
288  /* Install a barrier word at the end of the dynamic arena */
289  /* Correct location depends on 'cnt*size' being rounded up, above */
290 
291  *((uint32_t *)(((char *)ptr) + (cnt*size) - sizeof(uint32_t))) = MDB_MAGIC;
292  } else if (UNLIKELY(bu_debug&BU_DEBUG_MEM_QCHECK)) {
293  struct memqdebug *mp = (struct memqdebug *)ptr;
294  ptr = (void *)(((struct memqdebug *)ptr)+1);
295  mp->m.magic = MDB_MAGIC;
296  mp->m.mdb_addr = ptr;
297  mp->m.mdb_len = cnt*size;
298  mp->m.mdb_str = str;
300  if (bu_memq == BU_LIST_NULL) {
301  bu_memq = &bu_memqhd;
302  BU_LIST_INIT(bu_memq);
303  }
304  BU_LIST_APPEND(bu_memq, &(mp->q));
305  BU_LIST_MAGIC_SET(&(mp->q), MDB_MAGIC);
307  }
308  bu_n_malloc++;
309  return ptr;
310 }
311 
312 
313 void *
314 bu_malloc(size_t size, const char *str)
315 {
316  return alloc(MALLOC, 1, size, str);
317 }
318 
319 
320 void *
321 bu_calloc(size_t nelem, size_t elsize, const char *str)
322 {
323  return alloc(CALLOC, nelem, elsize, str);
324 }
325 
326 
327 void
328 bu_free(void *ptr, const char *str)
329 {
330  const char *nul = "(null)";
331  if (!str)
332  str = nul;
333 
335  fprintf(stderr, "%p free %s\n", ptr, str);
336  }
337 
338  if (UNLIKELY(ptr == (char *)0 || ptr == (char *)(-1L))) {
339  fprintf(stderr, "%p free ERROR %s\n", ptr, str);
340  return;
341  }
343  struct memdebug *mp;
344  mp = memdebug_check(ptr, str);
345  if (UNLIKELY(mp == MEMDEBUG_NULL)) {
346  fprintf(stderr, "ERROR bu_free(%p, %s) pointer bad, or not allocated with bu_malloc! Ignored.\n", ptr, str);
347  } else {
348  mp->mdb_len = 0; /* successful delete */
349  }
350  } else if (UNLIKELY(bu_debug&BU_DEBUG_MEM_QCHECK)) {
351  struct memqdebug *mp = ((struct memqdebug *)ptr)-1;
352  if (UNLIKELY(!BU_LIST_MAGIC_EQUAL(&(mp->q), MDB_MAGIC))) {
353  fprintf(stderr, "ERROR bu_free(%p, %s) pointer bad, or not allocated with bu_malloc! Ignored.\n", ptr, str);
354  } else {
355  ptr = (void *)mp;
357  BU_LIST_DEQUEUE(&(mp->q));
359  }
360  }
361 
362 #if defined(MALLOC_NOT_MP_SAFE)
364 #endif
365 
366  /* Here we wipe out the first four bytes before the actual free()
367  * as a basic memory safeguard. This should wipe out any magic
368  * number in structures and provide a distinct memory signature if
369  * the address happens to be accessed via some other pointer or
370  * the program crashes. While we're not guaranteed anything after
371  * free(), some implementations leave the zapped value intact.
372  */
373  *((uint32_t *)ptr) = 0xFFFFFFFF; /* zappo! */
374 
375  free(ptr);
376 #if defined(MALLOC_NOT_MP_SAFE)
378 #endif
379 }
380 
381 
382 void *
383 bu_realloc(register void *ptr, size_t siz, const char *str)
384 {
385  struct memdebug *mp=NULL;
386  void *original_ptr;
387  const size_t MINSIZE = sizeof(uint32_t) > sizeof(intptr_t) ? sizeof(uint32_t) : sizeof(intptr_t);
388 
389  /* If bu_realloc receives a NULL pointer and zero size then bomb
390  * because the behavior of realloc is undefined for these inputs.
391  */
392  if (UNLIKELY(ptr == NULL && siz == 0)) {
393  bu_bomb("bu_realloc(): invalid input, NULL pointer and zero size\n");
394  }
395 
396  /* If bu_realloc receives a NULL pointer and non-zero size then
397  * allocate new memory.
398  */
399  if (UNLIKELY(ptr == NULL && siz > 0)) {
400  return bu_malloc(siz, str);
401  }
402 
403  /* If bu_realloc receives a non-NULL pointer and zero size then
404  * free the memory. Instead of returning NULL, though, the
405  * standard says we can return a small allocation suitable for
406  * passing to bu_free(). Do that so we can maintain our LIBBU
407  * guarantee of worry-free memory management.
408  */
409  if (UNLIKELY(ptr != NULL && siz == 0)) {
410  bu_free(ptr, str);
411  return bu_malloc(MINSIZE, str);
412  }
413 
414  /* If the new allocation size is smaller than the minimum size
415  * to store a pointer then set the size to this minimum size.
416  * This is necessary so that the function bu_free can place a
417  * value in the memory before it is freed. The size allocated
418  * needs to be large enough to hold this value.
419  */
420  if (UNLIKELY(siz < MINSIZE)) {
421  siz = MINSIZE;
422  }
423 
425  mp = memdebug_check(ptr, str);
426  if (UNLIKELY(mp == MEMDEBUG_NULL)) {
427  fprintf(stderr, "%p realloc%6d %s ** barrier check failure\n",
428  ptr, (int)siz, str);
429  }
430  /* Pad, plus full uint32_t for magic number */
431  siz = (siz+2*sizeof(uint32_t)-1)&(~(sizeof(uint32_t)-1));
432  } else if (UNLIKELY(bu_debug&BU_DEBUG_MEM_QCHECK)) {
433  struct memqdebug *mqp = ((struct memqdebug *)ptr)-1;
434 
435  siz = (siz + 2*sizeof(struct memqdebug) - 1)
436  &(~(sizeof(struct memqdebug)-1));
437 
438  if (UNLIKELY(!BU_LIST_MAGIC_EQUAL(&(mqp->q), MDB_MAGIC))) {
439  fprintf(stderr, "ERROR bu_realloc(%p, %s) pointer bad, "
440  "or not allocated with bu_malloc! Ignored.\n",
441  ptr, str);
442  /*
443  * Since we're ignoring this, at least return the pointer
444  * that was passed in. Standard says behavior is
445  * undefined when reallocating memory not allocated with
446  * the matching allocation routines (i.e., bu_malloc() or
447  * bu_calloc() in our situation), so we are fair game to
448  * just return the pointer we were given.
449  */
450  return ptr;
451  }
452  ptr = (void *)mqp;
453  BU_LIST_DEQUEUE(&(mqp->q));
454  }
455 
456  original_ptr = ptr;
457 
458 #if defined(MALLOC_NOT_MP_SAFE)
460 #endif
461  ptr = realloc(ptr, siz);
462 #if defined(MALLOC_NOT_MP_SAFE)
464 #endif
465 
466  /* If realloc returns NULL then it failed to allocate the
467  * requested memory and we need to bomb.
468  */
469  if (UNLIKELY(!ptr)) {
470  fprintf(stderr, "bu_realloc(): unable to allocate requested memory of size %ld, %s\n", (long int)siz, str);
471  bu_bomb("bu_realloc(): unable to allocate requested memory.\n");
472  }
473 
474  if (UNLIKELY(ptr==(char *)0 || bu_debug&BU_DEBUG_MEM_LOG)) {
475  if (ptr == original_ptr) {
476  fprintf(stderr, "%p realloc%6d %s [grew in place]\n",
477  ptr, (int)siz, str);
478  } else {
479  fprintf(stderr, "%p realloc%6d %s [moved from %p]\n",
480  ptr, (int)siz, str, original_ptr);
481  }
482  }
483 
484  if (UNLIKELY(bu_debug&BU_DEBUG_MEM_CHECK && ptr)) {
485  /* Even if ptr didn't change, need to update siz & barrier */
487  mp->mdb_addr = ptr;
488  mp->mdb_len = siz;
489 
490  /* Install a barrier word at the new end of the dynamic
491  * arena. Correct location depends on 'siz' being rounded up,
492  * above.
493  */
494  *((uint32_t *)(((char *)ptr)+siz-sizeof(uint32_t))) = MDB_MAGIC;
496  } else if (UNLIKELY(bu_debug&BU_DEBUG_MEM_QCHECK && ptr)) {
497  struct memqdebug *mqp;
499  mqp = (struct memqdebug *)ptr;
500  ptr = (void *)(((struct memqdebug *)ptr)+1);
501  mqp->m.magic = MDB_MAGIC;
502  mqp->m.mdb_addr = ptr;
503  mqp->m.mdb_len = siz;
504  mqp->m.mdb_str = str;
505  BU_ASSERT(bu_memq != BU_LIST_NULL);
506  BU_LIST_APPEND(bu_memq, &(mqp->q));
507  BU_LIST_MAGIC_SET(&(mqp->q), MDB_MAGIC);
509  }
510  bu_n_realloc++;
511  return ptr;
512 }
513 
514 
515 void
516 bu_prmem(const char *str)
517 {
518  register struct memdebug *mp;
519  register struct memqdebug *mqp;
520  register uint32_t *ip;
521  register size_t count = 0;
522 
523  fprintf(stderr, "\nbu_prmem(): dynamic memory use (%s)\n", str);
525  fprintf(stderr, "\tMemory debugging is now OFF\n");
526  }
527  fprintf(stderr, " Address Length Purpose\n");
528  if (bu_memdebug_len > 0) {
529  mp = &bu_memdebug[bu_memdebug_len-1];
530  for (; mp >= bu_memdebug; mp--) {
531  if (!mp->magic) continue;
532  if (mp->magic != MDB_MAGIC) bu_bomb("memdebug_check() malloc tracing table corrupted!\n");
533  if (mp->mdb_len == 0) continue;
534 
535  count++;
536  ip = (uint32_t *)(((char *)mp->mdb_addr)+mp->mdb_len-sizeof(uint32_t));
537  if (mp->mdb_str == bu_strdup_message) {
538  fprintf(stderr, "%p %llu bu_strdup: \"%s\"\n",
539  mp->mdb_addr, (unsigned long long)mp->mdb_len,
540  ((char *)mp->mdb_addr));
541  } else if (mp->mdb_str == bu_vls_message) {
542  fprintf(stderr, "%p %llu bu_vls: \"%s\"\n",
543  mp->mdb_addr, (unsigned long long)mp->mdb_len,
544  ((char *)mp->mdb_addr));
545  } else {
546  fprintf(stderr, "%p %llu %s\n",
547  mp->mdb_addr, (unsigned long long)mp->mdb_len,
548  mp->mdb_str);
549  }
550  if (*ip != MDB_MAGIC) {
551  fprintf(stderr, "\tCorrupted end marker was=x%lx\ts/b=x%x\n",
552  (unsigned long)*ip, MDB_MAGIC);
553  }
554  }
555  }
556 
557 
558  if (bu_memq != BU_LIST_NULL) {
559  fprintf(stderr, "memdebug queue\n Address Length Purpose\n");
560  BU_LIST_EACH(bu_memq, mqp, struct memqdebug) {
561  if (!BU_LIST_MAGIC_EQUAL(&(mqp->q), MDB_MAGIC)
562  || !BU_LIST_MAGIC_EQUAL(&(mqp->m), MDB_MAGIC))
563  bu_bomb("bu_prmem() malloc tracing queue corrupted!\n");
564  if (mqp->m.mdb_str == bu_strdup_message) {
565  fprintf(stderr, "%p %llu bu_strdup: \"%s\"\n",
566  mqp->m.mdb_addr, (unsigned long long)mqp->m.mdb_len,
567  ((char *)mqp->m.mdb_addr));
568  } else if (mqp->m.mdb_str == bu_vls_message) {
569  fprintf(stderr, "%p %llu bu_vls: \"%s\"\n",
570  mqp->m.mdb_addr, (unsigned long long)mqp->m.mdb_len,
571  ((char *)mqp->m.mdb_addr));
572  } else {
573  fprintf(stderr, "%p %llu %s\n",
574  mqp->m.mdb_addr, (unsigned long long)mqp->m.mdb_len,
575  mqp->m.mdb_str);
576  }
577  }
578  }
579 
580  fprintf(stderr, "%lu allocation entries\n", (unsigned long)count);
581 }
582 
583 
584 int
585 bu_malloc_len_roundup(register int nbytes)
586 {
587 #if !defined(HAVE_CALTECH_MALLOC)
588  return nbytes;
589 #else
590  static int pagesz;
591  register int n;
592  register int amt;
593 
594  if (pagesz == 0)
595  pagesz = getpagesize();
596 
597 #define OVERHEAD (4*sizeof(unsigned char) + \
598  2*sizeof(unsigned short) + \
599  sizeof(unsigned int))
600  n = pagesz - OVERHEAD;
601  if (nbytes <= n)
602  return n;
603  amt = pagesz;
604 
605  while (nbytes > amt + n) {
606  amt <<= 1;
607  }
608  return amt-OVERHEAD-sizeof(int);
609 #endif
610 }
611 
612 
613 void
614 bu_ck_malloc_ptr(void *ptr, const char *str)
615 {
616  register struct memdebug *mp = &bu_memdebug[bu_memdebug_len-1];
617  register uint32_t *ip;
618 
619 
620  if (UNLIKELY(ptr == (char *)NULL)) {
621  fprintf(stderr, "bu_ck_malloc_ptr(%p, %s) null pointer\n\n", ptr, str);
622  bu_bomb("Goodbye");
623  }
624 
626  if (bu_memdebug == (struct memdebug *)0) {
627  fprintf(stderr, "bu_ck_malloc_ptr(%p, %s) no memdebug table yet\n",
628  ptr, str);
629  /* warning only -- the program is just getting started */
630  return;
631  }
632 
633  for (; mp >= bu_memdebug; mp--) {
634  if (!mp->magic) continue;
635  if (mp->magic != MDB_MAGIC) bu_bomb("bu_ck_malloc_ptr() malloc tracing table corrupted!\n");
636  if (mp->mdb_len == 0 || mp->mdb_addr != ptr) continue;
637 
638  /* Found the relevant entry */
639  ip = (uint32_t *)(((char *)ptr)+mp->mdb_len-sizeof(uint32_t));
640  if (*ip != MDB_MAGIC) {
641  fprintf(stderr, "ERROR bu_ck_malloc_ptr(%p, %s) barrier word corrupted! was=x%lx s/b=x%x\n",
642  ptr, str, (unsigned long)*ip, MDB_MAGIC);
643  bu_bomb("bu_ck_malloc_ptr\n");
644  }
645  return; /* OK */
646  }
647  fprintf(stderr, "WARNING: bu_ck_malloc_ptr(%p, %s)\
648  pointer not in table of allocated memory.\n", ptr, str);
649  } else if (UNLIKELY(bu_debug&BU_DEBUG_MEM_QCHECK)) {
650  struct memqdebug *mqp = (struct memqdebug *)ptr;
651  if (UNLIKELY(!BU_LIST_MAGIC_EQUAL(&(mqp->q), MDB_MAGIC) || mqp->m.magic != MDB_MAGIC)) {
652  fprintf(stderr, "WARNING: bu_ck_malloc_ptr(%p, %s)"
653  " memory corrupted.\n", ptr, str);
654  }
655  }
656 }
657 
658 
659 int
661 {
662  register struct memdebug *mp = &bu_memdebug[bu_memdebug_len-1];
663  register uint32_t *ip;
664 
665  if (UNLIKELY(bu_memdebug == (struct memdebug *)0)) {
666  fprintf(stderr, "bu_mem_barriercheck() no memdebug table yet\n");
667  return 0;
668  }
670  for (; mp >= bu_memdebug; mp--) {
671  if (!mp->magic) continue;
672  if (mp->magic != MDB_MAGIC) {
674  fprintf(stderr, " mp->magic = x%lx, s/b=x%x\n", (unsigned long)(mp->magic), MDB_MAGIC);
675  bu_bomb("bu_mem_barriercheck() malloc tracing table corrupted!\n");
676  }
677  if (mp->mdb_len == 0) continue;
678  ip = (uint32_t *)(((char *)mp->mdb_addr)+mp->mdb_len-sizeof(uint32_t));
679  if (*ip != MDB_MAGIC) {
681  fprintf(stderr, "ERROR bu_mem_barriercheck(%p, len=%llu) barrier word corrupted!\n\tbarrier at %p was=x%lx s/b=x%x %s\n",
682  mp->mdb_addr, (unsigned long long)mp->mdb_len,
683  (void *)ip, (unsigned long)*ip, MDB_MAGIC, mp->mdb_str);
684  return -1; /* FAIL */
685  }
686  }
688  return 0; /* OK */
689 }
690 
691 int
692 bu_shmget(int *shmid, char **shared_memory, int key, size_t size)
693 {
694  int ret = 1;
695 #ifdef HAVE_SYS_SHM_H
696  int shmsize;
697  long psize = sysconf(_SC_PAGESIZE);
698  int flags = IPC_CREAT|0666;
699 
700  ret = 0;
701  errno = 0;
702 
703  /*
704  make more portable
705  shmsize = (size + getpagesize()-1) & ~(getpagesize()-1);
706  */
707  shmsize = (size + psize - 1) & ~(psize - 1);
708 
709  /* First try to attach to an existing one */
710  if (((*shmid) = shmget(key, shmsize, 0)) < 0) {
711  /* No existing one, create a new one */
712  if (((*shmid) = shmget(key, shmsize, flags)) < 0) {
713  printf("bu_shmget failed, errno=%d\n", errno);
714  return 1;
715  }
716  ret = -1;
717  }
718 
719  /* WWW this is unnecessary in this version? */
720  /* Open the segment Read/Write */
721  /* This gets mapped to a high address on some platforms, so no problem. */
722  if (((*shared_memory) = (char *)shmat((*shmid), 0, 0)) == (char *)(-1L)) {
723  printf("errno=%d\n", errno);
724  return 1;
725  }
726 
727 #endif
728  return ret;
729 }
730 
731 
732 /*
733  * Local Variables:
734  * mode: C
735  * tab-width: 8
736  * indent-tabs-mode: t
737  * c-file-style: "stroustrup"
738  * End:
739  * ex: shiftwidth=4 tabstop=8
740  */
struct memdebug m
Definition: malloc.c:74
Definition: list.h:118
#define BU_DEBUG_MEM_CHECK
Definition: debug.h:54
#define MEMDEBUG_NULL
Definition: malloc.c:70
#define LIKELY(expression)
Definition: common.h:261
void * bu_realloc(register void *ptr, size_t siz, const char *str)
Definition: malloc.c:383
void bu_prmem(const char *str)
Definition: malloc.c:516
int bu_malloc_len_roundup(register int nbytes)
Definition: malloc.c:585
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
#define BU_LIST_INIT_ZERO
Definition: list.h:167
#define BU_LIST_MAGIC_SET(_l, _magic)
Definition: list.h:129
const char bu_vls_message[]
Definition: globals.c:57
Header file for the BRL-CAD common definitions.
#define BU_LIST_APPEND(old, new)
Definition: list.h:197
#define BU_ASSERT(_equation)
Definition: defines.h:216
#define HIDDEN
Definition: common.h:86
alloc_t
Definition: malloc.c:54
void * bu_malloc(size_t size, const char *str)
Definition: malloc.c:314
HIDDEN void * alloc(alloc_t type, size_t cnt, size_t sz, const char *str)
Definition: malloc.c:202
void * mdb_addr
Definition: malloc.c:63
void * memset(void *s, int c, size_t n)
void * bu_calloc(size_t nelem, size_t elsize, const char *str)
Definition: malloc.c:321
#define ALIGN
Definition: malloc.c:56
#define BU_DEBUG_MEM_QCHECK
Definition: debug.h:59
size_t mdb_len
Definition: malloc.c:65
static void top()
#define BU_DEBUG_MEM_LOG
Definition: debug.h:55
uint32_t magic
Definition: malloc.c:62
#define BU_SEM_MALLOC
Definition: parallel.h:183
long bu_n_realloc
Definition: globals.c:50
void bu_ck_malloc_ptr(void *ptr, const char *str)
Definition: malloc.c:614
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
struct bu_list q
Definition: malloc.c:73
int bu_mem_barriercheck(void)
Definition: malloc.c:660
int bu_debug
Definition: globals.c:87
#define BU_LIST_INIT(_hp)
Definition: list.h:148
#define MDB_MAGIC
Definition: malloc.c:60
#define BU_LIST_EACH(hp, p, type)
Definition: list.h:343
HIDDEN void memdebug_add(void *ptr, size_t cnt, const char *str)
Definition: malloc.c:91
Definition: malloc.c:55
const char * mdb_str
Definition: malloc.c:64
int bu_shmget(int *shmid, char **shared_memory, int key, size_t size)
Definition: malloc.c:692
#define BU_LIST_NULL
Definition: list.h:124
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
#define BU_LIST_DEQUEUE(cur)
Definition: list.h:209
#define BU_LIST_MAGIC_EQUAL(_l, _magic)
Definition: list.h:135
long bu_n_malloc
Definition: globals.c:42
HIDDEN struct memdebug * memdebug_check(register void *ptr, const char *str)
Definition: malloc.c:156
void bu_bomb(const char *str) _BU_ATTR_NORETURN
Definition: bomb.c:91
const char bu_strdup_message[]
Definition: globals.c:64
int bu_bomb_failsafe_init(void)
Definition: bomb.c:71
#define UNLIKELY(expression)
Definition: common.h:282