shm_mem.c 6.0 KB

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