sync_mappings.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 
27 #include "config.h"
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <inttypes.h>
37 
38 #include <sys/mman.h>
39 #include <stdint.h>
40 
41 #include <pthread.h>
42 #include "spew.h"
43 #include "assert.h"
44 #include "debug_lock.h"
45 #include "shm_arena.h"
46 #include "arena.h"
47 #include "arena_lock.h"
48 #include "avl.h"
49 
50 
55 DLL_LOCAL
56 int _shm_arena_sync_mappings( IF_SPEW(const char *func,)
57  struct shm_arena *arena)
58 {
59  int i;
60  int mapping_changed = 0; /* bool: has a mapping changed size? */
61  struct mapping_header *map_header;
62  struct arena_header *header;
63  off_t offset = 0; /* offset into the arena file for each mapping */
64 
65  SPEW(_DEBUG, "%s(from func=\"%s\",,)", __func__, func);
66 
67  ASSERT(arena->header);
68 
69  header = arena->header;
70 
71  if(header->map_header.map_length < 1)
72  return SPEW_SYS_RET(1, _WARN,
73  "There are no mappings in the arena file");
74 
75  if(arena->num_mappings != header->num_mappings)
76  {
77  if(arena->num_mappings > header->num_mappings)
78  {
79  /* we have mappings that are no longer in the arena file */
80  int min;
81  min = arena->header->num_mappings;
82  for(i=arena->num_mappings-1; i>=min; i--)
83  {
84  if(munmap(arena->mapping[i].start,
85  arena->mapping[i].map_length))
86  return SPEW_SYS_RET(1, _WARN, "%s() failed: "
87  "munmap() failed: mapping %d", func, i);
88  (arena->num_mappings)--;
89  }
90  }
91  arena->mapping = (struct shm_mapping *)
92  realloc(arena->mapping,
93  arena->num_mappings*sizeof(struct shm_mapping));
94 
95  if(!(arena->mapping))
96  return SPEW_SYS_RET(1, _WARN, "%s() failed: realloc() failed",
97  func);
98 
99  /* Initialize any mappings that are being added. */
100  while(arena->num_mappings < header->num_mappings)
101  {
102  arena->mapping[arena->num_mappings].start = MAP_FAILED;
103  arena->mapping[arena->num_mappings].map_length = 0;
104  (arena->num_mappings)++;
105  }
106  }
107 
108  /* Any mappings could have changed so we must check them all. */
109 
110  /* check 1st (0) mapping */
111  if(arena->mapping[0].map_length != header->map_header.map_length)
112  {
113  if(munmap(arena->mapping[0].start,
114  arena->mapping[0].map_length*CHUNK))
115  return SPEW_SYS_RET(1, _WARN,
116  "%s() failed: mumap() failed: remapping %d",
117  func, 0);
118  arena->mapping[0].map_length = header->map_header.map_length;
119  arena->mapping[0].start =
120  mmap(arena->user_shm_address, arena->mapping[0].map_length*CHUNK,
121  PROT_READ|PROT_WRITE, MAP_SHARED, arena->fd, offset);
122  if(arena->mapping[0].start == MAP_FAILED)
123  return SPEW_SYS_RET(1, _WARN,
124  "%s() failed: mmap() failed: remapping %d",
125  func, 0);
126  if(arena->user_shm_address &&
127  arena->mapping[0].start != arena->user_shm_address)
128  return SPEW_SYS_RET(1, _WARN, "%s() failed: mmap() failed"
129  " with SHM_ADDRESS set: remapping %d",
130  func, 0);
131 
132  /* Once one mapping changes the offset into the file may change
133  * and so all the mappings are questionable. */
134  mapping_changed = 1;
135  }
136 
137  /* compute the offset to the next mapping */
138  offset = (arena->mapping[0].map_length)*CHUNK;
139 
140  /* check all other mappings */
141  map_header = get_mapping_header(arena, 1);
142 
143  for(i=1;i<header->num_mappings; i++)
144  {
145  /* Once one mapping changes the offset into the file may change
146  * and so all the mappings are questionable. */
147  if(arena->mapping[i].map_length != map_header->map_length
148  || mapping_changed)
149  {
150  void *map_start = NULL;
151 
152  if(munmap(arena->mapping[i].start,
153  arena->mapping[i].map_length*CHUNK))
154  return SPEW_SYS_RET(1, _WARN,
155  "%s() failed: mumap() failed: remapping %d",
156  func, i);
157 
158  arena->mapping[i].map_length = map_header->map_length;
159 
160  if(arena->user_shm_address)
161  map_start = (void*)(((uintptr_t) arena->mapping[i-1].start) +
162  arena->mapping[i-1].map_length*CHUNK);
163  arena->mapping[i].start =
164  mmap(map_start, arena->mapping[i].map_length*CHUNK,
165  PROT_READ|PROT_WRITE, MAP_SHARED, arena->fd, offset);
166  if(arena->mapping[i].start == MAP_FAILED)
167  return SPEW_SYS_RET(1, _WARN,
168  "%s() failed: mmap() failed:"
169  " remapping %d", func, i);
170  if(map_start && arena->mapping[i].start != map_start)
171  return SPEW_SYS_RET(1, _WARN,
172  "%s() failed: mmap() failed with SHM_ADDRESS set:"
173  " remapping %d", func, i);
174 
175  mapping_changed = 1;
176  }
177  /* go to the next mapping header */
178  map_header = get_mapping_header(arena, i);
179  /* compute the offset to the next mapping */
180  offset += (arena->mapping[i].map_length)*CHUNK;
181  }
182 
183  arena->num_mappings = header->num_mappings;
184  arena->change_count = header->change_count;
185 
186  return 0; /* no error */
187 }
struct arena_header * header
Definition: arena.h:446
struct shm_mapping * mapping
Definition: arena.h:454
int num_mappings
Definition: arena.h:459
mapnum_t num_mappings
Definition: arena.h:387
uint32_t change_count
Definition: arena.h:464
offset_t map_length
Definition: arena.h:345
void * user_shm_address
Definition: arena.h:484
struct mapping_header map_header
Definition: arena.h:374
offset_t map_length
Definition: arena.h:410
uint32_t change_count
Definition: arena.h:383
uint8_t * start
Definition: arena.h:405
int fd
Definition: arena.h:436

Shared Memory Arena version RC-0.0.25