a7ece8f7e5e61598370683c19166b77f6dde6c67
[sip-router] / mem / shm_mem.c
1 /* $Id$
2  *
3  * Shared memory functions
4  */
5
6 #ifdef SHM_MEM
7
8 #include <stdlib.h>
9
10 #include "shm_mem.h"
11 #include "../config.h"
12 #include "../globals.h"
13
14 #ifdef  SHM_MMAP
15
16 #include <unistd.h>
17 #include <sys/mman.h>
18 #include <sys/types.h> /*open*/
19 #include <sys/stat.h>
20 #include <fcntl.h>
21
22 #endif
23
24 #ifdef FAST_LOCK
25 #include "../fastlock.h"
26 #endif
27
28
29
30
31 /* define semun */
32 #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
33         /* union semun is defined by including <sys/sem.h> */
34 #else
35 #ifndef __FreeBSD__
36         /* according to X/OPEN we have to define it ourselves */
37         union semun {
38                 int val;                    /* value for SETVAL */
39                 struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
40                 unsigned short int *array;  /* array for GETALL, SETALL */
41                 struct seminfo *__buf;      /* buffer for IPC_INFO */
42         };
43 #endif
44 #endif
45
46
47
48 #ifndef SHM_MMAP
49 static int shm_shmid=-1; /*shared memory id*/
50 #endif
51
52 #ifdef FAST_LOCK
53 fl_lock_t* mem_lock=0;
54 #else
55 int shm_semid=-1; /*semaphore id*/
56 #endif
57
58 static void* shm_mempool=(void*)-1;
59 #ifdef VQ_MALLOC
60         struct vqm_block* shm_block;
61 #elif F_MALLOC
62         struct fm_block* shm_block;
63 #else
64         struct qm_block* shm_block;
65 #endif
66
67
68 inline static void* sh_realloc(void* p, unsigned int size)
69 {
70         void *r;
71         shm_lock(); 
72         shm_free_unsafe(p);
73         r=shm_malloc_unsafe(size);
74         shm_unlock();
75         return r;
76 }
77
78 /* look at a buffer if there is perhaps enough space for the new size
79    (It is benefitial to do so because vq_malloc is pretty stateful
80     and if we ask for a new buffer size, we can still make it happy
81     with current buffer); if so, we return current buffer again;
82     otherwise, we free it, allocate a new one and return it; no
83     guarantee for buffer content; if allocation fails, we return
84     NULL
85 */
86
87 #ifdef DBG_QM_MALLOC
88 void* _shm_resize( void* p, unsigned int s, char* file, char* func, unsigned int line)
89 #else
90 void* _shm_resize( void* p , unsigned int s)
91 #endif
92 {
93 #ifdef VQ_MALLOC
94         struct vqm_frag *f;
95 #endif
96         if (p==0) {
97                 DBG("WARNING:vqm_resize: resize(0) called\n");
98                 return shm_malloc( s );
99         }
100 #       ifdef DBG_QM_MALLOC
101 #       ifdef VQ_MALLOC
102         f=(struct  vqm_frag*) ((char*)p-sizeof(struct vqm_frag));
103         DBG("_shm_resize(%p, %d), called from %s: %s(%d)\n",  
104                 p, s, file, func, line);
105         VQM_DEBUG_FRAG(shm_block, f);
106         if (p>(void *)shm_block->core_end || p<(void*)shm_block->init_core){
107                 LOG(L_CRIT, "BUG: vqm_free: bad pointer %p (out of memory block!) - "
108                                 "aborting\n", p);
109                 abort();
110         }
111 #endif
112 #       endif
113         return sh_realloc( p, s ); 
114 }
115
116 #ifdef _OBSOLETED
117 #ifdef DBG_QM_MALLOC
118 void* _shm_resize( void* p, unsigned int s, char* file, char* func, unsigned int line)
119 #else
120 void* _shm_resize( void* p , unsigned int s)
121 #endif
122 {
123         
124 #ifdef VQ_MALLOC
125         struct vqm_frag *f;
126 #else
127         #ifdef __SUNPRO_C
128                 /*no warning support on Sun cc */
129         #else
130                 #ifdef _NO_NO_NO
131                         #warning shm_resize performs suboptimally without VQ_MALLOC!
132                 #endif
133         #endif
134 #endif
135
136         if (p==0) {
137                 DBG("WARNING:vqm_resize: resize(0) called\n");
138                 return shm_malloc( s );
139         }
140
141 #       ifdef VQ_MALLOC
142         f=(struct  vqm_frag*) ((char*)p-sizeof(struct vqm_frag));
143 #       ifdef DBG_QM_MALLOC
144         DBG("_shm_resize(%p, %d), called from %s: %s(%d)\n",  
145                 p, s, file, func, line);
146         VQM_DEBUG_FRAG(shm_block, f);
147         if (p>(void *)shm_block->core_end || p<(void*)shm_block->init_core){
148                 LOG(L_CRIT, "BUG: vqm_free: bad pointer %p (out of memory block!) - "
149                                 "aborting\n", p);
150                 abort();
151         }
152 #       endif
153         if (s <= f->size-VQM_OVERHEAD) {
154 #               ifdef DBG_QM_MALLOC
155                 DBG("DEBUG: happy guy -- you reused a memory fragment!\n");
156 #               endif
157                 return p;
158         };
159 #endif
160         /* we can't make the request happy with current size */
161         return sh_realloc( p, s ); 
162 }
163 #endif
164
165
166
167 int shm_mem_init()
168 {
169
170 #ifndef FAST_LOCK
171         union semun su;
172         int ret;
173 #endif
174 #ifdef SHM_MMAP
175         int fd;
176 #else
177         struct shmid_ds shm_info;
178 #endif
179
180 #ifdef SHM_MMAP
181         if (shm_mempool && (shm_mempool!=(void*)-1)){
182 #else
183         if ((shm_shmid!=-1)||(shm_semid!=-1)||(shm_mempool!=(void*)-1)){
184 #endif
185                 LOG(L_CRIT, "BUG: shm_mem_init: shm already initialized\n");
186                 return -1;
187         }
188         
189 #ifdef SHM_MMAP
190         fd=open("/dev/zero", O_RDWR);
191         if (fd==-1){
192                 LOG(L_CRIT, "ERROR: shm_mem_init: could not open /dev/zero: %s\n",
193                                 strerror(errno));
194                 return -1;
195         }
196         shm_mempool=mmap(0, /* SHM_MEM_SIZE */ shm_mem_size, PROT_READ|PROT_WRITE, MAP_SHARED,
197                                                 fd ,0);
198         /* close /dev/zero */
199         close(fd);
200 #else
201         
202         shm_shmid=shmget(IPC_PRIVATE, /* SHM_MEM_SIZE */ shm_mem_size , 0700);
203         if (shm_shmid==-1){
204                 LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate shared memory"
205                                 " segment: %s\n", strerror(errno));
206                 return -1;
207         }
208         shm_mempool=shmat(shm_shmid, 0, 0);
209 #endif
210         if (shm_mempool==(void*)-1){
211                 LOG(L_CRIT, "ERROR: shm_mem_init: could not attach shared memory"
212                                 " segment: %s\n", strerror(errno));
213                 /* destroy segment*/
214                 shm_mem_destroy();
215                 return -1;
216         }
217
218 #ifndef FAST_LOCK
219         /* alloc a semaphore (for malloc)*/
220         shm_semid=semget(IPC_PRIVATE, 1, 0700);
221         if (shm_semid==-1){
222                 LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate semaphore: %s\n",
223                                 strerror(errno));
224                 shm_mem_destroy();
225                 return -1;
226         }
227         /* set its value to 1 (mutex)*/
228         su.val=1;
229         ret=semctl(shm_semid, 0, SETVAL, su);
230         if (ret==-1){
231                 LOG(L_CRIT, "ERROR: shm_mem_init: could not set initial semaphore"
232                                 " value: %s\n", strerror(errno));
233                 shm_mem_destroy();
234                 return -1;
235         }
236 #endif
237         /* init it for malloc*/
238 #       ifdef VQ_MALLOC
239                 shm_block=vqm_malloc_init(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size );
240         #elif defined F_MALLOC
241                 shm_block=fm_malloc_init(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size );
242 #       else
243                 shm_block=qm_malloc_init(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size );
244 #       endif
245         if (shm_block==0){
246                 LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize shared"
247                                 " malloc\n");
248                 shm_mem_destroy();
249                 return -1;
250         }
251 #ifdef FAST_LOCK
252         mem_lock=shm_malloc_unsafe(sizeof(fl_lock_t));
253         init_lock(*mem_lock);
254 #endif
255         
256         DBG("shm_mem_init: success\n");
257         
258         return 0;
259 }
260
261
262
263 void shm_mem_destroy()
264 {
265 #ifndef SHM_MMAP
266         struct shmid_ds shm_info;
267 #endif
268 #ifndef FAST_LOCK
269         union semun zero_un;
270 #endif
271         
272         DBG("shm_mem_destroy\n");
273         if (shm_mempool && (shm_mempool!=(void*)-1)) {
274 #ifdef SHM_MMAP
275                 munmap(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size );
276 #else
277                 shmdt(shm_mempool);
278 #endif
279                 shm_mempool=(void*)-1;
280         }
281 #ifndef SHM_MMAP
282         if (shm_shmid!=-1) {
283                 shmctl(shm_shmid, IPC_RMID, &shm_info);
284                 shm_shmid=-1;
285         }
286 #endif
287 #ifndef FAST_LOCK
288         if (shm_semid!=-1) {
289                 zero_un.val=0;
290                 semctl(shm_semid, 0, IPC_RMID, zero_un);
291                 shm_semid=-1;
292         }
293 #endif
294 }
295
296
297 #endif