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