mem: initial doxygen documentation for MM, small whitespace changes
[sip-router] / mem / shm_mem.c
1 /*
2
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of sip-router, a free SIP server.
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20
21 /*
22  * History:
23  * --------
24  *  2003-03-12  split shm_mem_init in shm_getmem & shm_mem_init_mallocs
25  *               (andrei)
26  *  2004-07-27  ANON mmap support, needed on darwin (andrei)
27  *  2004-09-19  shm_mem_destroy: destroy first the lock & then unmap (andrei)
28  *  2007-06-10   support for sfm_malloc & shm_malloc_destroy() (andrei)
29  */
30
31 /**
32  * \file
33  * \brief  Shared memory functions
34  * \ingroup mem
35  */
36
37
38 #ifdef SHM_MEM
39
40 #include <stdlib.h>
41
42 #include "shm_mem.h"
43 #include "../config.h"
44 #include "../globals.h"
45 #include "memdbg.h"
46
47 #ifdef  SHM_MMAP
48
49 #include <unistd.h>
50 #include <sys/mman.h>
51 #include <sys/types.h> /*open*/
52 #include <sys/stat.h>
53 #include <fcntl.h>
54
55 #endif
56
57 #define _ROUND2TYPE(s, type) \
58         (((s)+(sizeof(type)-1))&(~(sizeof(type)-1)))
59 #define _ROUND_LONG(s) _ROUND2TYPE(s, long)
60
61
62 #ifndef SHM_MMAP
63 static int shm_shmid=-1; /*shared memory id*/
64 #endif
65
66 #ifndef SHM_SAFE_MALLOC
67 gen_lock_t* mem_lock=0;
68 #endif
69
70 static void* shm_mempool=(void*)-1;
71 #ifdef LL_MALLOC
72         struct sfm_block* shm_block;
73 #elif SF_MALLOC
74         struct sfm_block* shm_block;
75 #elif F_MALLOC
76         struct fm_block* shm_block;
77 #elif DL_MALLOC
78         mspace shm_block;
79 #else
80         struct qm_block* shm_block;
81 #endif
82
83
84 inline static void* sh_realloc(void* p, unsigned int size)
85 {
86         void *r;
87         shm_lock(); 
88         shm_free_unsafe(p);
89         r=shm_malloc_unsafe(size);
90         shm_unlock();
91         return r;
92 }
93
94 /* look at a buffer if there is perhaps enough space for the new size
95    (It is beneficial to do so because vq_malloc is pretty stateful
96     and if we ask for a new buffer size, we can still make it happy
97     with current buffer); if so, we return current buffer again;
98     otherwise, we free it, allocate a new one and return it; no
99     guarantee for buffer content; if allocation fails, we return
100     NULL
101 */
102
103 #ifdef DBG_QM_MALLOC
104 void* _shm_resize( void* p, unsigned int s, const char* file, const char* func,
105                                                         int line)
106 #else
107 void* _shm_resize( void* p , unsigned int s)
108 #endif
109 {
110         if (p==0) {
111                 DBG("WARNING:vqm_resize: resize(0) called\n");
112                 return shm_malloc( s );
113         }
114         return sh_realloc( p, s ); 
115 }
116
117
118
119
120
121 int shm_getmem()
122 {
123
124 #ifdef SHM_MMAP
125 #ifndef USE_ANON_MMAP
126         int fd;
127 #endif
128 #else
129         struct shmid_ds shm_info;
130 #endif
131
132 #ifdef SHM_MMAP
133         if (shm_mempool && (shm_mempool!=(void*)-1)){
134 #else
135         if ((shm_shmid!=-1)||(shm_mempool!=(void*)-1)){
136 #endif
137                 LOG(L_CRIT, "BUG: shm_mem_init: shm already initialized\n");
138                 return -1;
139         }
140         
141 #ifdef SHM_MMAP
142 #ifdef USE_ANON_MMAP
143         shm_mempool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE,
144                                          MAP_ANON|MAP_SHARED, -1 ,0);
145 #else
146         fd=open("/dev/zero", O_RDWR);
147         if (fd==-1){
148                 LOG(L_CRIT, "ERROR: shm_mem_init: could not open /dev/zero: %s\n",
149                                 strerror(errno));
150                 return -1;
151         }
152         shm_mempool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
153         /* close /dev/zero */
154         close(fd);
155 #endif /* USE_ANON_MMAP */
156 #else
157         
158         shm_shmid=shmget(IPC_PRIVATE, /* SHM_MEM_SIZE */ shm_mem_size , 0700);
159         if (shm_shmid==-1){
160                 LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate shared memory"
161                                 " segment: %s\n", strerror(errno));
162                 return -1;
163         }
164         shm_mempool=shmat(shm_shmid, 0, 0);
165 #endif
166         if (shm_mempool==(void*)-1){
167                 LOG(L_CRIT, "ERROR: shm_mem_init: could not attach shared memory"
168                                 " segment: %s\n", strerror(errno));
169                 /* destroy segment*/
170                 shm_mem_destroy();
171                 return -1;
172         }
173         return 0;
174 }
175
176
177
178 int shm_mem_init_mallocs(void* mempool, unsigned long pool_size)
179 {
180         /* init it for malloc*/
181         shm_block=shm_malloc_init(mempool, pool_size);
182         if (shm_block==0){
183                 LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize shared"
184                                 " malloc\n");
185                 shm_mem_destroy();
186                 return -1;
187         }
188 #ifndef SHM_SAFE_MALLOC
189         mem_lock=shm_malloc_unsafe(sizeof(gen_lock_t)); /* skip lock_alloc, 
190                                                                                                            race cond*/
191         if (mem_lock==0){
192                 LOG(L_CRIT, "ERROR: shm_mem_init: could not allocate lock\n");
193                 shm_mem_destroy();
194                 return -1;
195         }
196         if (lock_init(mem_lock)==0){
197                 LOG(L_CRIT, "ERROR: shm_mem_init: could not initialize lock\n");
198                 shm_mem_destroy();
199                 return -1;
200         }
201 #endif  /*SHM SAFE_MALLOC */
202         
203         DBG("shm_mem_init: success\n");
204         
205         return 0;
206 }
207
208
209 int shm_mem_init(int force_alloc)
210 {
211         int ret;
212         long sz;
213         long* p;
214         long* end;
215         
216         ret=shm_getmem();
217         if (ret<0) return ret;
218         if (force_alloc){
219                 sz=sysconf(_SC_PAGESIZE);
220                 DBG("shm_mem_init: %ld bytes/page\n", sz);
221                 if ((sz<sizeof(*p)) || (_ROUND_LONG(sz)!=sz)){
222                         LOG(L_WARN, "shm_mem_init: invalid page size %ld, using 4096\n",
223                                         sz);
224                         sz=4096; /* invalid page size, use 4096 */
225                 }
226                 end=shm_mempool+shm_mem_size-sizeof(*p);
227                 /* touch one word in every page */
228                 for(p=(long*)_ROUND_LONG((long)shm_mempool); p<=end;
229                                                                                 p=(long*)((char*)p+sz))
230                         *p=0; 
231         }
232         return shm_mem_init_mallocs(shm_mempool, shm_mem_size);
233 }
234
235
236 void shm_mem_destroy()
237 {
238 #ifndef SHM_MMAP
239         struct shmid_ds shm_info;
240 #endif
241         
242         DBG("shm_mem_destroy\n");
243 #ifndef SHM_SAFE_MALLOC
244         if (mem_lock){
245                 DBG("destroying the shared memory lock\n");
246                 lock_destroy(mem_lock); /* we don't need to dealloc it*/
247         }
248 #endif  /*SHM SAFE_MALLOC */
249         if (shm_block){
250                 shm_malloc_destroy(shm_block);
251                 shm_block=0;
252         }
253         if (shm_mempool && (shm_mempool!=(void*)-1)) {
254 #ifdef SHM_MMAP
255                 munmap(shm_mempool, /* SHM_MEM_SIZE */ shm_mem_size );
256 #else
257                 shmdt(shm_mempool);
258 #endif
259                 shm_mempool=(void*)-1;
260         }
261 #ifndef SHM_MMAP
262         if (shm_shmid!=-1) {
263                 shmctl(shm_shmid, IPC_RMID, &shm_info);
264                 shm_shmid=-1;
265         }
266 #endif
267 }
268
269
270 #endif