You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mem_pool.h 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*-
  2. * Copyright 2019 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * @file mem_pool.h
  18. * \brief Memory pools library.
  19. *
  20. * Memory pools library. Library is designed to implement efficient way to
  21. * store data in memory avoiding calling of many malloc/free. It has overhead
  22. * because of fact that objects live in pool for rather long time and are not freed
  23. * immediately after use, but if we know certainly when these objects can be used, we
  24. * can use pool for them
  25. */
  26. #ifndef RSPAMD_MEM_POOL_H
  27. #define RSPAMD_MEM_POOL_H
  28. #include "config.h"
  29. #if defined(HAVE_PTHREAD_PROCESS_SHARED) && !defined(DISABLE_PTHREAD_MUTEX)
  30. #include <pthread.h>
  31. #endif
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35. struct f_str_s;
  36. #ifdef __has_attribute
  37. # if __has_attribute(alloc_size)
  38. # define RSPAMD_ATTR_ALLOC_SIZE(pos) __attribute__((alloc_size(pos)))
  39. # else
  40. # define RSPAMD_ATTR_ALLOC_SIZE(pos)
  41. # endif
  42. # if __has_attribute(assume_aligned)
  43. # define RSPAMD_ATTR_ALLOC_ALIGN(al) __attribute__((assume_aligned(al)))
  44. # else
  45. # define RSPAMD_ATTR_ALLOC_ALIGN(al)
  46. # endif
  47. # if __has_attribute(returns_nonnull)
  48. # define RSPAMD_ATTR_RETURNS_NONNUL __attribute__((returns_nonnull))
  49. # else
  50. # define RSPAMD_ATTR_RETURNS_NONNUL
  51. # endif
  52. #else
  53. #define RSPAMD_ATTR_ALLOC_SIZE(pos)
  54. #define RSPAMD_ATTR_ALLOC_ALIGN(al)
  55. #define RSPAMD_ATTR_RETURNS_NONNUL
  56. #endif
  57. #define MEMPOOL_TAG_LEN 20
  58. #define MEMPOOL_UID_LEN 20
  59. /* All pointers are aligned as this variable */
  60. #define MIN_MEM_ALIGNMENT sizeof (guint64)
  61. /**
  62. * Destructor type definition
  63. */
  64. typedef void (*rspamd_mempool_destruct_t) (void *ptr);
  65. /**
  66. * Pool mutex structure
  67. */
  68. #if !defined(HAVE_PTHREAD_PROCESS_SHARED) || defined(DISABLE_PTHREAD_MUTEX)
  69. typedef struct memory_pool_mutex_s {
  70. gint lock;
  71. pid_t owner;
  72. guint spin;
  73. } rspamd_mempool_mutex_t;
  74. /**
  75. * Rwlock for locking shared memory regions
  76. */
  77. typedef struct memory_pool_rwlock_s {
  78. rspamd_mempool_mutex_t *__r_lock; /**< read mutex (private) */
  79. rspamd_mempool_mutex_t *__w_lock; /**< write mutex (private) */
  80. } rspamd_mempool_rwlock_t;
  81. #else
  82. typedef pthread_mutex_t rspamd_mempool_mutex_t;
  83. typedef pthread_rwlock_t rspamd_mempool_rwlock_t;
  84. #endif
  85. /**
  86. * Tag to use for logging purposes
  87. */
  88. struct rspamd_mempool_tag {
  89. gchar tagname[MEMPOOL_TAG_LEN]; /**< readable name */
  90. gchar uid[MEMPOOL_UID_LEN]; /**< unique id */
  91. };
  92. enum rspamd_mempool_flags {
  93. RSPAMD_MEMPOOL_DEBUG = (1u << 0u),
  94. };
  95. /**
  96. * Memory pool type
  97. */
  98. struct rspamd_mempool_entry_point;
  99. struct rspamd_mutex_s;
  100. struct rspamd_mempool_specific;
  101. typedef struct memory_pool_s {
  102. struct rspamd_mempool_specific *priv;
  103. struct rspamd_mempool_tag tag; /**< memory pool tag */
  104. } rspamd_mempool_t;
  105. /**
  106. * Statistics structure
  107. */
  108. typedef struct memory_pool_stat_s {
  109. guint pools_allocated; /**< total number of allocated pools */
  110. guint pools_freed; /**< number of freed pools */
  111. guint bytes_allocated; /**< bytes that are allocated with pool allocator */
  112. guint chunks_allocated; /**< number of chunks that are allocated */
  113. guint shared_chunks_allocated; /**< shared chunks allocated */
  114. guint chunks_freed; /**< chunks freed */
  115. guint oversized_chunks; /**< oversized chunks */
  116. guint fragmented_size; /**< fragmentation size */
  117. } rspamd_mempool_stat_t;
  118. /**
  119. * Allocate new memory poll
  120. * @param size size of pool's page
  121. * @return new memory pool object
  122. */
  123. rspamd_mempool_t *rspamd_mempool_new_ (gsize size, const gchar *tag, gint flags,
  124. const gchar *loc);
  125. #define rspamd_mempool_new(size, tag, flags) \
  126. rspamd_mempool_new_((size), (tag), (flags), G_STRLOC)
  127. /**
  128. * Get memory from pool
  129. * @param pool memory pool object
  130. * @param size bytes to allocate
  131. * @return pointer to allocated object
  132. */
  133. void *rspamd_mempool_alloc_ (rspamd_mempool_t *pool, gsize size, const gchar *loc)
  134. RSPAMD_ATTR_ALLOC_SIZE(2) RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT) RSPAMD_ATTR_RETURNS_NONNUL;
  135. #define rspamd_mempool_alloc(pool, size) \
  136. rspamd_mempool_alloc_((pool), (size), G_STRLOC)
  137. /**
  138. * Notify external memory usage for memory pool
  139. * @param pool
  140. * @param size
  141. * @param loc
  142. */
  143. void rspamd_mempool_notify_alloc_ (rspamd_mempool_t *pool, gsize size, const gchar *loc);
  144. #define rspamd_mempool_notify_alloc(pool, size) \
  145. rspamd_mempool_notify_alloc_((pool), (size), G_STRLOC)
  146. /**
  147. * Get memory and set it to zero
  148. * @param pool memory pool object
  149. * @param size bytes to allocate
  150. * @return pointer to allocated object
  151. */
  152. void *rspamd_mempool_alloc0_ (rspamd_mempool_t *pool, gsize size, const gchar *loc)
  153. RSPAMD_ATTR_ALLOC_SIZE(2) RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT) RSPAMD_ATTR_RETURNS_NONNUL;
  154. #define rspamd_mempool_alloc0(pool, size) \
  155. rspamd_mempool_alloc0_((pool), (size), G_STRLOC)
  156. /**
  157. * Make a copy of string in pool
  158. * @param pool memory pool object
  159. * @param src source string
  160. * @return pointer to newly created string that is copy of src
  161. */
  162. gchar *rspamd_mempool_strdup_ (rspamd_mempool_t *pool, const gchar *src, const gchar *loc)
  163. RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT);
  164. #define rspamd_mempool_strdup(pool, src) \
  165. rspamd_mempool_strdup_ ((pool), (src), G_STRLOC)
  166. /**
  167. * Make a copy of fixed string in pool as null terminated string
  168. * @param pool memory pool object
  169. * @param src source string
  170. * @return pointer to newly created string that is copy of src
  171. */
  172. gchar *rspamd_mempool_fstrdup_ (rspamd_mempool_t *pool,
  173. const struct f_str_s *src,
  174. const gchar *loc)
  175. RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT);
  176. #define rspamd_mempool_fstrdup(pool, src) \
  177. rspamd_mempool_fstrdup_ ((pool), (src), G_STRLOC)
  178. struct f_str_tok;
  179. /**
  180. * Make a copy of fixed string token in pool as null terminated string
  181. * @param pool memory pool object
  182. * @param src source string
  183. * @return pointer to newly created string that is copy of src
  184. */
  185. gchar *rspamd_mempool_ftokdup_ (rspamd_mempool_t *pool,
  186. const struct f_str_tok *src,
  187. const gchar *loc)
  188. RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT);
  189. #define rspamd_mempool_ftokdup(pool, src) \
  190. rspamd_mempool_ftokdup_ ((pool), (src), G_STRLOC)
  191. /**
  192. * Allocate piece of shared memory
  193. * @param pool memory pool object
  194. * @param size bytes to allocate
  195. */
  196. void *rspamd_mempool_alloc_shared_ (rspamd_mempool_t *pool, gsize size, const gchar *loc)
  197. RSPAMD_ATTR_ALLOC_SIZE(2) RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT) RSPAMD_ATTR_RETURNS_NONNUL;
  198. #define rspamd_mempool_alloc_shared(pool, size) \
  199. rspamd_mempool_alloc_shared_((pool), (size), G_STRLOC)
  200. void *rspamd_mempool_alloc0_shared_ (rspamd_mempool_t *pool, gsize size, const gchar *loc)
  201. RSPAMD_ATTR_ALLOC_SIZE(2) RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT) RSPAMD_ATTR_RETURNS_NONNUL;
  202. #define rspamd_mempool_alloc0_shared(pool, size) \
  203. rspamd_mempool_alloc0_shared_((pool), (size), G_STRLOC)
  204. /**
  205. * Add destructor callback to pool
  206. * @param pool memory pool object
  207. * @param func pointer to function-destructor
  208. * @param data pointer to data that would be passed to destructor
  209. */
  210. void rspamd_mempool_add_destructor_full (rspamd_mempool_t *pool,
  211. rspamd_mempool_destruct_t func,
  212. void *data,
  213. const gchar *function,
  214. const gchar *line);
  215. /* Macros for common usage */
  216. #define rspamd_mempool_add_destructor(pool, func, data) \
  217. rspamd_mempool_add_destructor_full (pool, func, data, G_STRFUNC, G_STRLOC)
  218. /**
  219. * Replace destructor callback to pool for specified pointer
  220. * @param pool memory pool object
  221. * @param func pointer to function-destructor
  222. * @param old_data pointer to old data
  223. * @param new_data pointer to data that would be passed to destructor
  224. */
  225. void rspamd_mempool_replace_destructor (rspamd_mempool_t *pool,
  226. rspamd_mempool_destruct_t func, void *old_data, void *new_data);
  227. /**
  228. * Calls all destructors associated with the specific memory pool without removing
  229. * of the pool itself
  230. * @param pool
  231. */
  232. void rspamd_mempool_destructors_enforce (rspamd_mempool_t *pool);
  233. /**
  234. * Delete pool, free all its chunks and call destructors chain
  235. * @param pool memory pool object
  236. */
  237. void rspamd_mempool_delete (rspamd_mempool_t *pool);
  238. /**
  239. * Get new mutex from pool (allocated in shared memory)
  240. * @param pool memory pool object
  241. * @return mutex object
  242. */
  243. rspamd_mempool_mutex_t *rspamd_mempool_get_mutex (rspamd_mempool_t *pool);
  244. /**
  245. * Lock mutex
  246. * @param mutex mutex to lock
  247. */
  248. void rspamd_mempool_lock_mutex (rspamd_mempool_mutex_t *mutex);
  249. /**
  250. * Unlock mutex
  251. * @param mutex mutex to unlock
  252. */
  253. void rspamd_mempool_unlock_mutex (rspamd_mempool_mutex_t *mutex);
  254. /**
  255. * Create new rwlock and place it in shared memory
  256. * @param pool memory pool object
  257. * @return rwlock object
  258. */
  259. rspamd_mempool_rwlock_t *rspamd_mempool_get_rwlock (rspamd_mempool_t *pool);
  260. /**
  261. * Acquire read lock
  262. * @param lock rwlock object
  263. */
  264. void rspamd_mempool_rlock_rwlock (rspamd_mempool_rwlock_t *lock);
  265. /**
  266. * Acquire write lock
  267. * @param lock rwlock object
  268. */
  269. void rspamd_mempool_wlock_rwlock (rspamd_mempool_rwlock_t *lock);
  270. /**
  271. * Release read lock
  272. * @param lock rwlock object
  273. */
  274. void rspamd_mempool_runlock_rwlock (rspamd_mempool_rwlock_t *lock);
  275. /**
  276. * Release write lock
  277. * @param lock rwlock object
  278. */
  279. void rspamd_mempool_wunlock_rwlock (rspamd_mempool_rwlock_t *lock);
  280. /**
  281. * Get pool allocator statistics
  282. * @param st stat pool struct
  283. */
  284. void rspamd_mempool_stat (rspamd_mempool_stat_t *st);
  285. /**
  286. * Reset memory pool stat
  287. */
  288. void rspamd_mempool_stat_reset (void);
  289. /**
  290. * Get optimal pool size based on page size for this system
  291. * @return size of memory page in system
  292. */
  293. #define rspamd_mempool_suggest_size() rspamd_mempool_suggest_size_(G_STRLOC)
  294. gsize rspamd_mempool_suggest_size_ (const char *loc);
  295. gsize rspamd_mempool_get_used_size (rspamd_mempool_t *pool);
  296. gsize rspamd_mempool_get_wasted_size (rspamd_mempool_t *pool);
  297. /**
  298. * Set memory pool variable
  299. * @param pool memory pool object
  300. * @param name name of variable
  301. * @param gpointer value value of variable
  302. * @param destructor pointer to function-destructor
  303. */
  304. void rspamd_mempool_set_variable (rspamd_mempool_t *pool,
  305. const gchar *name,
  306. gpointer value,
  307. rspamd_mempool_destruct_t destructor);
  308. /**
  309. * Get memory pool variable
  310. * @param pool memory pool object
  311. * @param name name of variable
  312. * @return NULL or pointer to variable data
  313. */
  314. gpointer rspamd_mempool_get_variable (rspamd_mempool_t *pool,
  315. const gchar *name);
  316. /**
  317. * Removes variable from memory pool
  318. * @param pool memory pool object
  319. * @param name name of variable
  320. */
  321. void rspamd_mempool_remove_variable (rspamd_mempool_t *pool,
  322. const gchar *name);
  323. /**
  324. * Prepend element to a list creating it in the memory pool
  325. * @param l
  326. * @param p
  327. * @return
  328. */
  329. GList *rspamd_mempool_glist_prepend (rspamd_mempool_t *pool,
  330. GList *l, gpointer p) G_GNUC_WARN_UNUSED_RESULT;
  331. /**
  332. * Append element to a list creating it in the memory pool
  333. * @param l
  334. * @param p
  335. * @return
  336. */
  337. GList *rspamd_mempool_glist_append (rspamd_mempool_t *pool,
  338. GList *l, gpointer p) G_GNUC_WARN_UNUSED_RESULT;
  339. #ifdef __cplusplus
  340. }
  341. #endif
  342. #endif