print.c
1 /*
2  shm-arena shared memory arena
3  Copyright (C) 2006-2008 Lance Arsenault (LGPL v3)
4 
5 
6  This file is part of shm-arena.
7 
8  shm-arena is free software; you can redistribute it and/or modify
9  it under the terms of the GNU Lesser General Public License as
10  published by the Free Software Foundation; either version 3 of the
11  License, or (at your option) any later version.
12 
13  shm-arena is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this program. If not, see
20  <http://www.gnu.org/licenses/>.
21 */
22 
26 #include "config.h"
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <sys/mman.h>
36 #include <pthread.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 
40 #include <pthread.h>
41 #include "spew.h"
42 #include "assert.h"
43 #include "debug_lock.h"
44 #include "shm_arena.h"
45 #include "arena.h"
46 #include "arena_lock.h"
47 #include "avl.h"
48 
62 {
63  int ret = 0;
64  int i;
65  int err;
66  struct mapping_header * map_header;
67  struct seg_header *seg;
68 
69  arena = get_arena_and_autolock(arena, 1, &err IF_SPEW(, __func__));
70  if(!arena)
71  {
72  errno = err;
73  return -1;
74  }
75 
76  if(arena->header->magic != ARENA_MAGIC)
77  {
78  printf("Bad magic number 0x%X != 0x%X\n",
79  arena->header->magic, ARENA_MAGIC);
80  errno = EINVAL;
81  goto print_error;
82  }
83 
84  /* Make sure that we have the current number of memory mappings for
85  * this arena file, by comparing the local and arena file
86  * change_count. */
87  pthread_mutex_lock(&arena->mapping_mutex);
88  if(arena->change_count != arena->header->change_count)
89  {
90  if(_shm_arena_sync_mappings(IF_SPEW(__func__,) arena))
91  {
92  SPEW_SYS_ERR(_WARN, ret, "%s() failed", __func__);
93  pthread_mutex_unlock(&arena->mapping_mutex);
94  goto print_error;
95  }
96  }
97  pthread_mutex_unlock(&arena->mapping_mutex);
98 
99 
100  seg = (struct seg_header *)
101  (arena->mapping[0].start +
102  (CHUNKS(sizeof(struct arena_header)) + CHUNKS(sizeof(struct mapping_header))));
103 
104  for(i=0; i<arena->num_mappings;)
105  {
106 
107  map_header = get_mapping_header(arena, i);
108 
109  while((uintptr_t)seg <
110  (((uintptr_t)(arena->mapping[i].start)) + map_header->length_used*CHUNK))
111  {
112  struct seg_footer *footer;
113  footer = get_seg_footer(seg);
114 
115  if(!(footer->flags & IS_FREE))
116  printf("%zu %s\n", seg->user_length, get_seg_name(seg));
117 
118 
119 
120  if(seg->length == 0)
121  {
122  printf("***ERROR***** seg->length = 0\n");
123  break;
124  }
125  else if((uintptr_t) (seg->length*CHUNK) >
126  (((uintptr_t)(map_header->length_used*CHUNK)) -
127  ((uintptr_t)(seg))-((uintptr_t)(arena->mapping[i].start))))
128  {
129  printf("***ERROR***** seg->length = "OFFSET_FORMAT
130  " CHUNKS IS TOO LARGE for this mapping\n", seg->length);
131  break;
132  }
133 
134  /* Goto the next segment. */
135  seg = (struct seg_header *)(((uint8_t *) seg) + seg->length*CHUNK);
136  }
137 
138  i++;
139 
140  if(i<arena->num_mappings)
141  {
142  map_header = get_mapping_header(arena, i);
143  seg = (struct seg_header *)(arena->mapping[i].start +
144  CHUNKS(sizeof(struct mapping_header)));
145  }
146  }
147 
148  err = arena_autounlock(arena IF_SPEW(, __func__));
149 
150  ASSERT(err == 0);
151  if(err)
152  {
153  SPEW(_WARN, "We're screwed");
154  errno = err;
155  /* don't give the user false hope. */
156  ret = -1;
157  }
158 
159  return ret;
160 
161  print_error:
162 
163  err = arena_autounlock(arena IF_SPEW(, __func__));
164 
165  ASSERT(err == 0);
166  if(err)
167  {
168  SPEW(_WARN, "We're screwed");
169  errno = err;
170  /* don't give the user false hope. */
171  ret = -1;
172  }
173 
174  return -1;
175 }
176 
177 
191 {
192  int ret = 0;
193  int i;
194  int err;
195  struct mapping_header * map_header;
196  struct seg_header *seg;
197  size_t pagesize;
198 
199  arena = get_arena_and_autolock(arena, 1, &err IF_SPEW(, __func__));
200  if(!arena)
201  {
202  errno = err;
203  return -1;
204  }
205 
206  pagesize = getpagesize();
207  if(arena->header->magic != ARENA_MAGIC)
208  {
209  printf("Bad magic number 0x%X != 0x%X\n",
210  arena->header->magic, ARENA_MAGIC);
211  errno = EINVAL;
212  goto print_error;
213  }
214 
215  /* Make sure that we have the current number of memory mappings for
216  * this arena file, by comparing the local and arena file
217  * change_count. */
218  pthread_mutex_lock(&arena->mapping_mutex);
219  if(arena->change_count != arena->header->change_count)
220  {
221  if(_shm_arena_sync_mappings(IF_SPEW(__func__,) arena))
222  {
223  SPEW_SYS_ERR(_WARN, ret, "%s() failed", __func__);
224  pthread_mutex_unlock(&arena->mapping_mutex);
225  goto print_error;
226  }
227  }
228  pthread_mutex_unlock(&arena->mapping_mutex);
229 
230 
231  printf("-------------------------------------------------------------\n");
232 
233  printf("pagesize = %zu bytes CHUNK = %zu bytes\n\n",
234  pagesize, CHUNK);
235 
236  printf(" " MAPNUM_FORMAT " mapping(s)\n", arena->num_mappings);
237 
238  printf("--------------------------------------------------------------------\n"
239  "-------------- MAPPING 0 at %p -------------------------\n"
240  "--------------------------------------------------------------------\n"
241  " struct arena_header size= %zu bytes = %zu CHUNKS\n",
242  arena->header,
243  sizeof(struct arena_header), CHUNKS(sizeof(struct arena_header))/CHUNK);
244 
245  map_header = get_mapping_header(arena, 0);
246  printf(" ----------------------------------------------------------\n"
247  " struct mapping_header size= %zu CHUNK(s) = %zu bytes \n"
248  " -------------------------------------------------------\n"
249  " map_length = "OFFSET_FORMAT" CHUNKS = %zu bytes = %zu pages\n"
250  " length_used = "OFFSET_FORMAT" CHUNKS = %zu bytes\n"
251  " -------------------------------------------------------\n",
252  CHUNKS(sizeof(struct mapping_header))/CHUNK, sizeof(struct mapping_header),
253  map_header->map_length, map_header->map_length*CHUNK,
254  map_header->map_length*CHUNK/pagesize,
255  map_header->length_used, map_header->length_used*CHUNK);
256 
257  printf(" magic = 0x%X ", arena->header->magic);
258 
259 #define SHOW_FLAG(x,f) (((x)&(f))?("|" #f):"")
260 
261  printf(" flags = 0");
262 
263  /* define a MACRO so that we may add and print lots of flags */
264 #define SHOW_FLAG(x,f) (((x)&(f))?("|" #f):"")
265  printf("%s ",
266  SHOW_FLAG(arena->header->flags, SHM_WITH_SHM_OPEN)
267  );
268 #undef SHOW_FLAG
269 
270  printf("num_mappings = "MAPNUM_FORMAT"\n\n", arena->header->num_mappings);
271 
272 
273  printf(" free_mapnum = "MAPNUM_FORMAT"\r",
274  arena->header->free_mapnum);
275  printf(" alloc_mapnum = "MAPNUM_FORMAT"\n", arena->header->alloc_mapnum);
276 
277 
278  printf(" free_offset = "OFFSET_FORMAT" CHUNKS\r",
279  arena->header->free_offset);
280  printf(" alloc_offset = "OFFSET_FORMAT" CHUNKS\n",
281  arena->header->alloc_offset);
282 
283 
284 
285  seg = (struct seg_header *)
286  (arena->mapping[0].start +
287  (CHUNKS(sizeof(struct arena_header)) + CHUNKS(sizeof(struct mapping_header))));
288 
289  for(i=0; i<arena->num_mappings;)
290  {
291 
292  /* The next mapping header is in the mapping before */
293  map_header = get_mapping_header(arena, i+1);
294 
295  printf(" ------------------------------------------------------------\n"
296  " details for next mapping (mapping %d)\n"
297  " struct mapping_header size= %zu bytes = %zu CHUNK(S)\n"
298  " ------------------------------------------------------------\n"
299  " map_length = "OFFSET_FORMAT" CHUNKS = %zu bytes = %zu pages\n"
300  " length_used = "OFFSET_FORMAT" CHUNKS = %zu bytes\n"
301  " ------------------------------------------------------------\n",
302  i+1,
303  sizeof(struct mapping_header),
304  CHUNKS(sizeof(struct mapping_header))/CHUNK,
305  map_header->map_length, map_header->map_length*CHUNK,
306  map_header->map_length*CHUNK/pagesize,
307  map_header->length_used, map_header->length_used*CHUNK);
308 
309  map_header = get_mapping_header(arena, i);
310 
311  while((uintptr_t)seg <
312  (uintptr_t)(arena->mapping[i].start + map_header->length_used*CHUNK))
313  {
314  struct seg_footer *footer;
315  footer = get_seg_footer(seg);
316 
317  printf(" -----------------------------------------------------------\n");
318 
319  if(!(footer->flags & IS_FREE))
320  printf(" \"%s\"", get_seg_name(seg));
321  else
322  printf(" free");
323 
324  printf(" segment at %p %s read-write lock\n"
325  " %"PRIuPTR" CHUNKS from mapping %d start\n"
326  " right_mapnum = "MAPNUM_FORMAT"\r"
327  " left_mapnum = "MAPNUM_FORMAT"\n"
328  " right_offset = "OFFSET_FORMAT" CHUNKS\r"
329  " left_offset = "OFFSET_FORMAT" CHUNKS\n"
330 
331  " length = "OFFSET_FORMAT" CHUNKS = %zu bytes\n"
332  " user_length = %zu bytes %s %zu CHUNK(S)\n"
333  " height = "HEIGHT_FORMAT"\n",
334  seg, (footer->flags & WITH_RWLOCK)?"with":"without",
335  (((uintptr_t) seg) - ((uintptr_t) arena->mapping[i].start))/CHUNK,
336  i,
337  seg->right_mapnum, seg->left_mapnum,
338  seg->right_offset, seg->left_offset,
339  seg->length, seg->length*CHUNK,
340  seg->user_length,
341  (seg->user_length != (seg->user_length/CHUNK)*CHUNK)?"uses":"=",
342  CHUNKS(seg->user_length)/CHUNK,
343  seg->height);
344 
345  if(footer->length != seg->length)
346  printf("***ERROR****THE FOOTER length ("OFFSET_FORMAT" CHUNKS) does not match "
347  "the HEADER length\n", footer->length);
348 
349  printf(" -----------------------------------------------------------\n");
350 
351  if(seg->length == 0)
352  {
353  printf("***ERROR***** seg->length = 0\n");
354  break;
355  }
356  else if((uintptr_t) (seg->length*CHUNK) >
357  (((uintptr_t)(map_header->length_used*CHUNK)) -
358  ((uintptr_t)(seg))-((uintptr_t)(arena->mapping[i].start))))
359  {
360  printf("***ERROR***** seg->length = "OFFSET_FORMAT
361  " CHUNKS IS TOO LARGE for this mapping\n", seg->length);
362  break;
363  }
364 
365  /* Goto the next segment. */
366  seg = (struct seg_header *)(((uint8_t *) seg) + seg->length*CHUNK);
367  }
368 
369  i++;
370 
371  if(i<arena->num_mappings)
372  {
373  printf("--------------------------------------------------------------------\n"
374  "-------------- MAPPING %d at %p -------------------------\n"
375  "--------------------------------------------------------------------\n",
376  i, arena->mapping[i].start);
377  map_header = get_mapping_header(arena, i);
378  seg = (struct seg_header *)(arena->mapping[i].start +
379  CHUNKS(sizeof(struct mapping_header)));
380  }
381  }
382  printf("--------------------------------------------------------------------\n");
383 
384 
385 
386  err = arena_autounlock(arena IF_SPEW(, __func__));
387 
388  ASSERT(err == 0);
389  if(err)
390  {
391  SPEW(_WARN, "We're screwed");
392  errno = err;
393  /* don't give the user false hope. */
394  ret = -1;
395  }
396 
397  return ret;
398 
399  print_error:
400 
401  err = arena_autounlock(arena IF_SPEW(, __func__));
402 
403  ASSERT(err == 0);
404  if(err)
405  {
406  SPEW(_WARN, "We're screwed");
407  errno = err;
408  /* don't give the user false hope. */
409  ret = -1;
410  }
411 
412  return -1;
413 }
414 
415 
416 static
417 void print_alloc_node(shm_arena_t arena, mapnum_t mapnum,
418  offset_t offset)
419 {
420  struct seg_header *seg;
421  char *name;
422  seg = get_seg_header(arena, mapnum, offset);
423 
424  ASSERT(seg);
425 
426  name = get_seg_name(seg);
427 
428  printf( " -> n"MAPNUM_FORMAT"x"OFFSET_FORMAT";\n",
429  mapnum, offset);
430  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT
431  " [label=\"%s\\ns=%zu\\nh="HEIGHT_FORMAT"\"];\n",
432  mapnum, offset, name, seg->user_length, seg->height);
433 
434  if(seg->left_offset)
435  {
436  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT,
437  mapnum, offset);
438  print_alloc_node(arena, seg->left_mapnum, seg->left_offset);
439  }
440  else if(seg->right_offset)
441  {
442  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT
443  " -> l"MAPNUM_FORMAT"x"OFFSET_FORMAT" [style=dotted,arrowhead=dot];\n",
444  mapnum, offset, mapnum, offset);
445  printf( " l"MAPNUM_FORMAT"x"OFFSET_FORMAT" [label=\"\",color=white];\n",
446  mapnum, offset);
447  }
448 
449  if(seg->right_offset)
450  {
451  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT,
452  mapnum, offset);
453  print_alloc_node(arena, seg->right_mapnum, seg->right_offset);
454  }
455  else if(seg->left_offset)
456  {
457  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT
458  " -> r"MAPNUM_FORMAT"x"OFFSET_FORMAT" [style=dotted,arrowhead=dot];\n",
459  mapnum, offset, mapnum, offset);
460  printf( " r"MAPNUM_FORMAT"x"OFFSET_FORMAT" [label=\"\",color=white];\n",
461  mapnum, offset);
462  }
463 }
464 
465 
466 static
467 void print_free_node(shm_arena_t arena, mapnum_t mapnum,
468  offset_t offset)
469 {
470  struct seg_header *seg;
471  seg = get_seg_header(arena, mapnum, offset);
472 
473  ASSERT(seg);
474 
475 
476  printf( " -> n"MAPNUM_FORMAT"x"OFFSET_FORMAT";\n",
477  mapnum, offset);
478  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT
479  " [label=\"m="MAPNUM_FORMAT"\\ns="OFFSET_FORMAT"\\nof="
480  OFFSET_FORMAT"\\nh="HEIGHT_FORMAT"\"];\n",
481  mapnum, offset, mapnum, seg->length, offset, seg->height);
482 
483  if(seg->left_offset)
484  {
485  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT,
486  mapnum, offset);
487  print_free_node(arena, seg->left_mapnum, seg->left_offset);
488  }
489  else if(seg->right_offset)
490  {
491  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT
492  " -> l"MAPNUM_FORMAT"x"OFFSET_FORMAT" [style=dotted,arrowhead=dot];\n",
493  mapnum, offset, mapnum, offset);
494  printf( " l"MAPNUM_FORMAT"x"OFFSET_FORMAT" [label=\"\",color=white];\n",
495  mapnum, offset);
496  }
497 
498  if(seg->right_offset)
499  {
500  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT,
501  mapnum, offset);
502  print_free_node(arena, seg->right_mapnum, seg->right_offset);
503  }
504  else if(seg->left_offset)
505  {
506  printf( " n"MAPNUM_FORMAT"x"OFFSET_FORMAT
507  " -> r"MAPNUM_FORMAT"x"OFFSET_FORMAT" [style=dotted,arrowhead=dot];\n",
508  mapnum, offset, mapnum, offset);
509  printf( " r"MAPNUM_FORMAT"x"OFFSET_FORMAT" [label=\"\",color=white];\n",
510  mapnum, offset);
511  }
512 }
513 
514 
536 {
537  int ret = 0;
538  int err;
539 
540  arena = get_arena_and_autolock(arena, 1, &err IF_SPEW(, __func__));
541  if(!arena)
542  {
543  errno = err;
544  return -1;
545  }
546 
547  if(arena->header->magic != ARENA_MAGIC)
548  {
549  errno = EINVAL;
550  SPEW_SYS_ERR(_WARN, ret, "Bad magic number 0x%X != 0x%X\n",
551  arena->header->magic, ARENA_MAGIC);
552  goto print_error;
553  }
554 
555  /* Make sure that we have the current number of memory mappings for
556  * this arena file, by comparing the local and arena file
557  * change_count. */
558  pthread_mutex_lock(&arena->mapping_mutex);
559  if(arena->change_count != arena->header->change_count)
560  {
561  if(_shm_arena_sync_mappings(IF_SPEW(__func__,) arena))
562  {
563  SPEW_SYS_ERR(_WARN, ret, "%s() failed", __func__);
564  pthread_mutex_unlock(&arena->mapping_mutex);
565  goto print_error;
566  }
567  }
568  pthread_mutex_unlock(&arena->mapping_mutex);
569 
570  printf("digraph G {\n\n");
571  printf("bgcolor =\"transparent\";\n");
572  printf(" node [style=filled,color=\"0.7 0.3 10\"]\n");
573 
574  printf("\"allocated\\nsegments\"");
575 
576  if(arena->header->alloc_offset)
577  {
578  print_alloc_node(arena, arena->header->alloc_mapnum,
579  arena->header->alloc_offset);
580  }
581  else
582  {
583  printf(";\n");
584  }
585 
586  printf("\n\n node [color=\"0.4 0.8 10\"]\n");
587 
588  printf("\n \"free\\nsegments\"");
589 
590  if(arena->header->free_offset)
591  {
592  print_free_node(arena, arena->header->free_mapnum,
593  arena->header->free_offset);
594  }
595  else
596  {
597  printf(";\n");
598  }
599 
600  printf("\n}\n");
601 
602  err = arena_autounlock(arena IF_SPEW(, __func__));
603 
604  ASSERT(err == 0);
605  if(err)
606  {
607  SPEW(_WARN, "We're screwed");
608  errno = err;
609  /* don't give the user false hope. */
610  return -1;
611  }
612 
613  return 0;
614 
615  print_error:
616 
617  err = arena_autounlock(arena IF_SPEW(, __func__));
618 
619  ASSERT(err == 0);
620  if(err)
621  {
622  SPEW(_WARN, "We're screwed");
623  errno = err;
624  /* don't give the user false hope. */
625  }
626 
627  return -1;
628 }
629 
630 
639 int shm_arena_check(shm_arena_t arena)
640 {
641  int ret = 0;
642  int i, err;
643 
644  arena = get_arena_and_autolock(arena, 1, &err IF_SPEW(, __func__));
645  if(!arena)
646  {
647  errno = err;
648  return -1;
649  }
650 
651  if(arena->header->magic != ARENA_MAGIC)
652  {
653  errno = EINVAL;
654  SPEW_SYS_ERR(_WARN, ret, "Bad magic number 0x%X != 0x%X\n",
655  arena->header->magic, ARENA_MAGIC);
656  goto print_error;
657  }
658 
659  /* Make sure that we have the current number of memory mappings for
660  * this arena file, by comparing the local and arena file
661  * change_count. */
662  pthread_mutex_lock(&arena->mapping_mutex);
663  if(arena->change_count != arena->header->change_count)
664  {
665  if(_shm_arena_sync_mappings(IF_SPEW(__func__,) arena))
666  {
667  SPEW_SYS_ERR(_WARN, ret, "%s() failed", __func__);
668  pthread_mutex_unlock(&arena->mapping_mutex);
669  goto print_error;
670  }
671  }
672  pthread_mutex_unlock(&arena->mapping_mutex);
673 
674  for(i=0;i<arena->num_mappings;i++)
675  {
676  struct seg_header *seg;
677  struct mapping_header * map_header;
678 
679  map_header = get_mapping_header(arena, i);
680  seg = (struct seg_header *)
681  (arena->mapping[i].start +
682  (CHUNKS(sizeof(struct mapping_header)) +
683  ((i==0)?CHUNKS(sizeof(struct arena_header)):0)));
684 
685  while((uintptr_t)seg <
686  (uintptr_t)(arena->mapping[i].start +
687  map_header->length_used*CHUNK))
688  {
689  struct seg_footer *f;
690  int diff;
691 
692  f = get_seg_footer(seg);
693 
694  if(f->flags & IS_FREE)
695  {
696  if(seg != _shm_check_free_segment(arena, i,
697  get_offset(arena, seg, i)))
698  {
699  ret = 1;
700  printf("did not find free segment in AVL tree\n");
701  printf("mapping=%d offset="OFFSET_FORMAT" CHUNKS\n",
702  i, get_offset(arena, seg, i));
703  }
704  }
705  else
706  {
707  mapnum_t mapnum;;
708  if(seg != find_segment(arena, get_seg_name(seg), &mapnum))
709  {
710  ret = 1;
711  printf("did not find allocated segment \"%s\" in AVL tree\n",
712  get_seg_name(seg));
713  printf("mapping=%d offset="OFFSET_FORMAT" CHUNKS\n",
714  i, get_offset(arena, seg, i));
715  }
716  }
717 
718  if(seg->length == 0)
719  {
720  printf("***ERROR***** seg->length = 0\n");
721  ret = 1;
722  }
723  else if((uintptr_t) (seg->length*CHUNK) >
724  (((uintptr_t)(map_header->length_used*CHUNK)) -
725  ((uintptr_t)(seg))-((uintptr_t)(arena->mapping[i].start))))
726  {
727  printf("***ERROR***** seg->length = "OFFSET_FORMAT
728  " CHUNKS IS TOO LARGE for this mapping\n", seg->length);
729  ret = 1;
730  }
731 
732  diff = difference(arena, seg);
733 
734  if(diff > 1 || diff < -1)
735  {
736  ret = 1;
737  printf("%s segment \"%s\" is not balanced: diff=%d "
738  "%s child is higher\n",
739  (f->flags & IS_FREE)?"free":"allocated",
740  (f->flags & IS_FREE)?"":get_seg_name(seg),
741  diff, (diff>0)?"left":"right");
742  printf("mapping=%d offset="OFFSET_FORMAT" CHUNKS\n",
743  i, get_offset(arena, seg, i));
744  }
745 
746  /* Goto the next segment. */
747  seg = (struct seg_header *)(((uint8_t *) seg) + seg->length*CHUNK);
748  }
749  }
750 
751  print_error:
752 
753  err = arena_autounlock(arena IF_SPEW(, __func__));
754 
755  ASSERT(err == 0);
756  if(err)
757  {
758  SPEW(_WARN, "We're screwed");
759  errno = err;
760  /* don't give the user false hope. */
761  ret = -1;
762  }
763 
764  return ret;
765 }
struct arena_header * header
Definition: arena.h:446
uint32_t flags
Definition: arena.h:367
struct shm_mapping * mapping
Definition: arena.h:454
offset_t free_offset
Definition: arena.h:394
int num_mappings
Definition: arena.h:459
pthread_mutex_t mapping_mutex
Definition: arena.h:468
mapnum_t num_mappings
Definition: arena.h:387
mapnum_t right_mapnum
Definition: arena.h:142
offset_t right_offset
Definition: arena.h:147
offset_t length_used
Definition: arena.h:352
mapnum_t left_mapnum
Definition: arena.h:142
uint32_t change_count
Definition: arena.h:464
mapnum_t alloc_mapnum
Definition: arena.h:392
offset_t map_length
Definition: arena.h:345
offset_t length
Definition: arena.h:153
int shm_arena_print_list(shm_arena_t arena)
Definition: print.c:61
offset_t left_offset
Definition: arena.h:147
mapnum_t free_mapnum
Definition: arena.h:390
uint32_t change_count
Definition: arena.h:383
uint32_t magic
Definition: arena.h:364
size_t user_length
Definition: arena.h:156
#define SHM_WITH_SHM_OPEN
shm_arena_create() flag to use shm_open()
Definition: shm_arena.h:123
offset_t alloc_offset
Definition: arena.h:396
uint8_t * start
Definition: arena.h:405
height_t height
Definition: arena.h:150
int shm_arena_print_dot(shm_arena_t arena)
print debug information about a shared memory arena object in this case a dot file that can be made i...
Definition: print.c:535
int shm_arena_print(shm_arena_t arena)
print the cotents of a shared memory arena file to stdout
Definition: print.c:190

Shared Memory Arena version RC-0.0.25