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