modules/ims_qos: added patch for flow-description bug when request originates from...
[sip-router] / mem / shm.c
1 /*
2  * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.com)
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 #include <stdlib.h>
20
21 #include "../config.h"
22 #include "../globals.h"
23 #include "memdbg.h"
24 #include "shm.h"
25
26 #ifdef  SHM_MMAP
27
28 #include <unistd.h>
29 #include <sys/mman.h>
30 #include <sys/types.h> /*open*/
31 #include <sys/stat.h>
32 #include <fcntl.h>
33
34 #endif
35
36 #include "memcore.h"
37
38 #define _ROUND2TYPE(s, type) \
39         (((s)+(sizeof(type)-1))&(~(sizeof(type)-1)))
40 #define _ROUND_LONG(s) _ROUND2TYPE(s, long)
41
42
43 void shm_core_destroy(void);
44
45 #ifndef SHM_MMAP
46 static int _shm_core_shmid = -1; /*shared memory id*/
47 #endif
48
49 gen_lock_t* _shm_lock=0;
50
51 static void* _shm_core_pool = (void*)-1;
52
53 sr_shm_api_t _shm_root = {0};
54
55 /**
56  *
57  */
58 int shm_getmem(void)
59 {
60
61 #ifdef SHM_MMAP
62 #ifndef USE_ANON_MMAP
63         int fd;
64 #endif
65 #else
66         struct shmid_ds shm_info;
67 #endif
68
69 #ifdef SHM_MMAP
70         if (_shm_core_pool && (_shm_core_pool!=(void*)-1)){
71 #else
72         if ((_shm_core_shmid!=-1)||(_shm_core_pool!=(void*)-1)){
73 #endif
74                 LOG(L_CRIT, "shm already initialized\n");
75                 return -1;
76         }
77         
78 #ifdef SHM_MMAP
79 #ifdef USE_ANON_MMAP
80         _shm_core_pool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE,
81                                          MAP_ANON|MAP_SHARED, -1 ,0);
82 #else
83         fd=open("/dev/zero", O_RDWR);
84         if (fd==-1){
85                 LOG(L_CRIT, "could not open /dev/zero: %s\n",
86                                 strerror(errno));
87                 return -1;
88         }
89         _shm_core_pool=mmap(0, shm_mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd ,0);
90         /* close /dev/zero */
91         close(fd);
92 #endif /* USE_ANON_MMAP */
93 #else
94         
95         _shm_core_shmid=shmget(IPC_PRIVATE, shm_mem_size , 0700);
96         if (_shm_core_shmid==-1){
97                 LOG(L_CRIT, "could not allocate shared memory"
98                                 " segment: %s\n", strerror(errno));
99                 return -1;
100         }
101         _shm_core_pool=shmat(_shm_core_shmid, 0, 0);
102 #endif
103         if (_shm_core_pool==(void*)-1){
104                 LOG(L_CRIT, "could not attach shared memory"
105                                 " segment: %s\n", strerror(errno));
106                 /* destroy segment*/
107                 shm_core_destroy();
108                 return -1;
109         }
110         return 0;
111 }
112
113 /**
114  *
115  */
116 void* shm_core_get_pool(void)
117 {
118         int ret;
119         long sz;
120         long* p;
121         long* end;
122         
123         ret=shm_getmem();
124         if (ret<0)
125                 return NULL;
126
127         if (shm_force_alloc){
128                 sz=sysconf(_SC_PAGESIZE);
129                 DBG("%ld bytes/page\n", sz);
130                 if ((sz<sizeof(*p)) || (_ROUND_LONG(sz)!=sz)){
131                         LOG(L_WARN, "invalid page size %ld, using 4096\n",
132                                         sz);
133                         sz=4096; /* invalid page size, use 4096 */
134                 }
135                 end=_shm_core_pool+shm_mem_size-sizeof(*p);
136                 /* touch one word in every page */
137                 for(p=(long*)_ROUND_LONG((long)_shm_core_pool); p<=end;
138                                                                                 p=(long*)((char*)p+sz))
139                         *p=0; 
140         }
141         return _shm_core_pool;
142 }
143
144 /**
145  * init the core lock
146  */
147 int shm_core_lock_init(void)
148 {
149         if (_shm_lock) {
150                 LM_DBG("shared memory lock initialized\n");
151                 return 0;
152         }
153         _shm_lock=shm_malloc_unsafe(sizeof(gen_lock_t)); /* skip lock_alloc, 
154                                                                                                            race cond*/
155         if (_shm_lock==0){
156                 LOG(L_CRIT, "could not allocate lock\n");
157                 shm_core_destroy();
158                 return -1;
159         }
160         if (lock_init(_shm_lock)==0){
161                 LOG(L_CRIT, "could not initialize lock\n");
162                 shm_core_destroy();
163                 return -1;
164         }
165         return 0;
166 }
167
168 /**
169  *
170  */
171 void shm_core_lock_destroy(void)
172 {
173         if (_shm_lock){
174                 DBG("destroying the shared memory lock\n");
175                 lock_destroy(_shm_lock); /* we don't need to dealloc it*/
176         }
177 }
178
179 /**
180  *
181  */
182 void shm_core_destroy(void)
183 {
184 #ifndef SHM_MMAP
185         struct shmid_ds shm_info;
186 #endif
187         
188         if (_shm_core_pool && (_shm_core_pool!=(void*)-1)) {
189 #ifdef SHM_MMAP
190                 munmap(_shm_core_pool, /* SHM_MEM_SIZE */ shm_mem_size );
191 #else
192                 shmdt(_shm_core_pool);
193 #endif
194                 _shm_core_pool=(void*)-1;
195         }
196 #ifndef SHM_MMAP
197         if (shm_shmid!=-1) {
198                 shmctl(shm_shmid, IPC_RMID, &shm_info);
199                 shm_shmid=-1;
200         }
201 #endif
202 }
203
204 /**
205  *
206  */
207 int shm_init_api(sr_shm_api_t *ap)
208 {
209         memset(&_shm_root, 0, sizeof(sr_shm_api_t));
210         _shm_root.mname          = ap->mname;
211         _shm_root.mem_pool       = ap->mem_pool;
212         _shm_root.mem_block      = ap->mem_block;
213         _shm_root.xmalloc        = ap->xmalloc;
214         _shm_root.xmalloc_unsafe = ap->xmalloc_unsafe;
215         _shm_root.xfree          = ap->xfree;
216         _shm_root.xfree_unsafe   = ap->xfree_unsafe;
217         _shm_root.xrealloc       = ap->xrealloc;
218         _shm_root.xresize        = ap->xresize;
219         _shm_root.xstatus        = ap->xstatus;
220         _shm_root.xinfo          = ap->xinfo;
221         _shm_root.xavailable     = ap->xavailable;
222         _shm_root.xsums          = ap->xsums;
223         _shm_root.xdestroy       = ap->xdestroy;
224         _shm_root.xmodstats      = ap->xmodstats;
225         _shm_root.xfmodstats     = ap->xfmodstats;
226         return 0;
227
228 }
229
230 /**
231  *
232  */
233 int shm_init_manager(char *name)
234 {
235         if(strcmp(name, "fm")==0
236                         || strcmp(name, "f_malloc")==0
237                         || strcmp(name, "fmalloc")==0) {
238                 /*fast malloc*/
239                 return fm_malloc_init_shm_manager();
240         } else if(strcmp(name, "qm")==0
241                         || strcmp(name, "q_malloc")==0
242                         || strcmp(name, "qmalloc")==0) {
243                 /*quick malloc*/
244                 return qm_malloc_init_shm_manager();
245         } else if(strcmp(name, "tlsf")==0
246                         || strcmp(name, "tlsf_malloc")==0) {
247                 /*tlsf malloc*/
248                 return tlsf_malloc_init_shm_manager();
249         } else if(strcmp(name, "sm")==0) {
250                 /*system malloc*/
251         } else {
252                 /*custom malloc - module*/
253         }
254         return -1;
255 }
256
257 /**
258  *
259  */
260 void shm_destroy_manager(void)
261 {
262         shm_core_lock_destroy();
263         if(_shm_root.xdestroy) {
264                 _shm_root.xdestroy();
265                 LM_DBG("destroying memory manager: %s\n",
266                                 (_shm_root.mname)?_shm_root.mname:"unknown");
267         }
268         shm_core_destroy();
269 }
270
271 /**
272  *
273  */
274 void shm_print_manager(void)
275 {
276         LM_DBG("shm - using memory manager: %s\n",
277                         (_pkg_root.mname)?_pkg_root.mname:"unknown");
278 }