memutil.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * category: [core for memory]
  3. * apply status:
  4. * edit status:
  5. * build status:
  6. * description: debug_trace would be invoked by stm, but stm is not used anywhere...
  7. *
  8. */
  9. #ifndef __MEMUTIL_H__
  10. #define __MEMUTIL_H__
  11. #pragma once
  12. #include "config.h"
  13. #ifdef _WIN32
  14. #define _CRTDBG_MAP_ALLOC
  15. #include <stdlib.h>
  16. #include <crtdbg.h>
  17. #include <WinSock2.h> //for struct timeval
  18. #else
  19. //TODO: remove #else macro.
  20. //because error C2039 would occur: “int8_t”: is not the member of “`global namespace'”
  21. #include <winpr/wtypes.h>
  22. #endif
  23. #ifdef __cplusplus
  24. extern "C" {
  25. #endif
  26. #include <errno.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <malloc.h>
  30. #ifdef _WIN32
  31. static __inline void prefetch(void* p)
  32. {
  33. _asm
  34. {
  35. //NTA(non-temporal data with respect to all cache levels) prefetch data into non-temporal cache structure and
  36. //into a location close to the processor, minimizing cache pollution.
  37. prefetchnta p
  38. }
  39. }
  40. #else
  41. //rw, locality: 1(w), 0(r), temporal locality(0-3, 3 is default)
  42. #define prefetch(x) __builtin_prefetch(x, 0)
  43. #endif
  44. #define INT64_GET_HIGH_PART(x) (*((int*)(&(x)) + 1))
  45. #define INT64_GET_LOW_PART(x) (*(int*)&(x))
  46. static __inline int int64_get_high_part(__int64 x)
  47. {
  48. return INT64_GET_HIGH_PART(x);
  49. }
  50. static __inline int int64_get_low_part(__int64 x)
  51. {
  52. return INT64_GET_LOW_PART(x);
  53. }
  54. struct __i8_helper {
  55. union {
  56. __int64 i;
  57. struct {
  58. int l;
  59. int h;
  60. };
  61. };
  62. };
  63. static __inline __int64 int64_make(int low_part, int high_part)
  64. {
  65. struct __i8_helper t;
  66. t.l = low_part;
  67. t.h = high_part;
  68. return t.i;
  69. }
  70. #define offset_of(type, member) \
  71. (((char*)(&((type*)0)->member)) - (char*)0)
  72. #define container_of(ptr, type, member) \
  73. ((type*)((char*)(ptr) - offset_of(type, member)))
  74. #define field_size(type, member) \
  75. sizeof(((type*)0)->member)
  76. #define array_size(x) \
  77. (sizeof(x)/sizeof((x)[0]))
  78. #define FLAG_BIT(f) f##_BIT
  79. /* for compatility at different platform [3/31/2020 Gifur] */
  80. #ifndef PARAM_SIZE_DEFINED
  81. #define PARAM_SIZE_DEFINED
  82. #ifdef _WIN32
  83. typedef int param_size_t;
  84. #else
  85. #if (defined(__x86_64__) || defined(__aarch64__))
  86. typedef intptr_t param_size_t;
  87. #elif defined(__i386__)
  88. typedef int param_size_t;
  89. #else
  90. typedef intptr_t param_size_t;
  91. #endif
  92. #endif //_WIN32
  93. #endif // !PARAM_SIZE_DEFINED
  94. #ifdef DEBUD_MEM_TRACE
  95. #include "memtrace.h"
  96. #define ZALLOC(size) zalloc(size)
  97. #define ZCALLOC(num, size) czalloc(num, size)
  98. #define MALLOC_T(type) (type*)malloc(sizeof(type))
  99. #define ZALLOC_T(type) (type*)zalloc(sizeof(type))
  100. #define CALLOC_T(num, type) (type*)calloc(num, sizeof(type))
  101. #define REALLOC realloc
  102. #define FREE(x) do {free(x); x = NULL;} while(0)
  103. #define STRDUP(str) strdup(str)
  104. #else /** DEBUD_MEM_TRACE*/
  105. #if 0
  106. static __inline void* zalloc(size_t size)
  107. {
  108. void* buf = malloc(size);
  109. if (buf) {
  110. memset(buf, 0, size);
  111. }
  112. return buf;
  113. }
  114. static __inline void* zcalloc(size_t num, size_t size)
  115. {
  116. void* buf = calloc(num, size);
  117. if (buf) {
  118. memset(buf, 0, num * size);
  119. }
  120. return buf;
  121. }
  122. #define ZALLOC(size) zalloc(size)
  123. #define ZCALLOC(num, size) czalloc(num, size)
  124. #define MALLOC_T(type) (type*)malloc(sizeof(type))
  125. #define ZALLOC_T(type) (type*)zalloc(sizeof(type))
  126. #define CALLOC_T(num, type) (type*)calloc(num, sizeof(type))
  127. #define REALLOC realloc
  128. #define FREE(x) do {free(x); x = NULL;} while(0)
  129. #define STRDUP(str) _strdup(str)
  130. #else
  131. #define ZALLOC(size) toolkit_zalloc(size)
  132. #define ZCALLOC(num, size) toolkit_calloc(num, size)
  133. #define MALLOC_T(type) (type*)toolkit_malloc(sizeof(type))
  134. #define ZALLOC_T(type) (type*)toolkit_zalloc(sizeof(type))
  135. #define CALLOC_T(num, type) (type*)toolkit_calloc(num, sizeof(type))
  136. #define REALLOC toolkit_realloc
  137. #define FREE(x) do {toolkit_free(x); x = NULL;} while(0)
  138. #define STRDUP(str) toolkit_strdup(str)
  139. #endif
  140. #endif /** DEBUD_MEM_TRACE*/
  141. #define SAFE_INVOKE_0(lpfn) if(lpfn) lpfn()
  142. #define SAFE_INVOKE_1(lpfn, param1) if(lpfn) lpfn(param1)
  143. #define SAFE_INVOKE_2(lpfn, param1, param2) if(lpfn) lpfn(param1, param2)
  144. #define SAFE_INVOKE_3(lpfn, param1, param2, param3) if(lpfn) lpfn(param1, param2, param3)
  145. #define SAFE_INVOKE_4(lpfn, param1, param2, param3, param4) if(lpfn) lpfn(param1, param2, param3, param4)
  146. #define SAFE_INVOKE_5(lpfn, param1, param2, param3, param4, param5) if(lpfn) lpfn(param1, param2, param3, param4, param5)
  147. #define SAFE_INVOKE_6(lpfn, param1, param2, param3, param4, param5, param6) if(lpfn) lpfn(param1, param2, param3, param4, param5, param6)
  148. #define SAFE_INVOKE_7(lpfn, param1, param2, param3, param4, param5, param6, param7) if(lpfn) lpfn(param1, param2, param3, param4, param5, param6, param7)
  149. #define SAFE_INVOKE_8(lpfn, param1, param2, param3, param4, param5, param6, param7, param8) if(lpfn) lpfn(param1, param2, param3, param4, param5, param6, param7, param8)
  150. #define SAFE_INVOKE_9(lpfn, param1, param2, param3, param4, param5, param6, param7, param8, param9) if(lpfn) lpfn(param1, param2, param3, param4, param5, param6, param7, param8, param9)
  151. #define INIT_COUNTER(name, x) enum { name = __LINE__ + x }
  152. #define DEF_COUNTER(name) (__LINE__ - name)
  153. /**
  154. * resize buffer with data preserved
  155. * @param old pointer to old buffer
  156. * @param elemsize element size
  157. * @param oldcnt the old element count
  158. * @param newcnt the new element count
  159. * @return return new buffer, if failed, original buffer is returned, if success old buffer will be freed
  160. */
  161. TOOLKIT_API void *buffer_resize(void* old, int elemsize, int oldcnt, int newcnt);
  162. TOOLKIT_API void *shm_buffer_resize(void* old, int elemsize, int oldcnt, int newcnt);
  163. /**
  164. * check expand
  165. */
  166. TOOLKIT_API int array_check_expand(void **old, int elemsize, int cnt, int *capacity);
  167. TOOLKIT_API int shm_array_check_expand(void **old, int elemsize, int cnt, int *capacity);
  168. typedef struct toolkit_allocator_t tk_allocator_t;
  169. typedef void* (*toolkit_malloc_func)(size_t size);
  170. typedef void* (*toolkit_realloc_func)(void* ptr, size_t size);
  171. typedef void* (*toolkit_calloc_func)(size_t count, size_t size);
  172. typedef void (*toolkit_free_func)(void* ptr);
  173. TOOLKIT_API int toolkit_replace_allocator(toolkit_malloc_func malloc_func,
  174. toolkit_realloc_func realloc_func,
  175. toolkit_calloc_func calloc_func,
  176. toolkit_free_func free_func);
  177. TOOLKIT_API void* toolkit_malloc(size_t size);
  178. TOOLKIT_API void* toolkit_calloc(size_t num, size_t size);
  179. TOOLKIT_API void* toolkit_realloc(void* ptr, size_t size);
  180. TOOLKIT_API void toolkit_free(void *p);
  181. TOOLKIT_API void *toolkit_zalloc(size_t size);
  182. TOOLKIT_API void *toolkit_zcalloc(size_t num, size_t size);
  183. TOOLKIT_API char *toolkit_strdup(const char *s);
  184. TOOLKIT_API char* toolkit_strndup(const char* s, size_t n);
  185. TOOLKIT_API wchar_t *toolkit_wcsdup(const wchar_t *s);
  186. #if !defined(_DEBUG) || !defined(DEBUG)
  187. #define ASSERT_RETURN(cond, ret) \
  188. if (!(cond)) \
  189. return ret;
  190. #else
  191. #define ASSERT_RETURN(cond, ret) assert(cond);
  192. #endif
  193. TOOLKIT_API void debug_trace(const char *fmt, ...);
  194. #if defined(_DEBUG) || defined(DEBUG)
  195. #define DEBUG_TRACE(fmt, ...) debug_trace(fmt, __VA_ARGS__);
  196. #else
  197. #define DEBUG_TRACE(fmt, ...)
  198. #endif /*defined(_DEBUG) || defined(DEBUG)*/
  199. #if defined(_WIN32) && ( defined(_DEBUG) || defined(DEBUG))
  200. #define LEAK_TRACE_SNAPSHOT_BEGIN() _CrtMemState s1, s2, s3; \
  201. do { \
  202. _CrtMemCheckpoint(&s1); \
  203. } while (false)
  204. #define LEAK_TRACE_SNAPSHOT_END() \
  205. do { \
  206. _CrtMemCheckpoint(&s2); \
  207. if (_CrtMemDifference(&s3, &s1, &s2)) \
  208. _CrtMemDumpStatistics(&s3); \
  209. } while (false)
  210. #else
  211. #define LEAK_TRACE_SNAPSHOT_BEGIN() ((void)0)
  212. #define LEAK_TRACE_SNAPSHOT_END() ((void)0)
  213. #endif //#if defined(_WIN32) && ( defined(_DEBUG) || defined(DEBUG))
  214. /*
  215. * -1: x < y
  216. * 1: x > y
  217. * 0: x == y
  218. */
  219. static __inline int timeval_cmp(struct timeval *x, struct timeval *y)
  220. {
  221. if (x->tv_sec < y->tv_sec) {
  222. return -1;
  223. } else if (x->tv_sec > y->tv_sec) {
  224. return 1;
  225. } else {
  226. if (x->tv_usec < y->tv_usec) {
  227. return -1;
  228. } else if (x->tv_usec > y->tv_usec) {
  229. return 1;
  230. } else {
  231. return 0;
  232. }
  233. }
  234. }
  235. static __inline void timeval_diff(struct timeval *x, struct timeval *y, struct timeval *out)
  236. {
  237. out->tv_sec = x->tv_sec - y->tv_sec;
  238. out->tv_usec = x->tv_usec - y->tv_usec;
  239. if (out->tv_usec < 0) {
  240. out->tv_sec --;
  241. out->tv_usec = 1000000 + out->tv_usec;
  242. }
  243. }
  244. static __inline void timeval_add_sec(struct timeval *tm, unsigned int sec)
  245. {
  246. tm->tv_sec += sec;
  247. }
  248. static __inline void timeval_add_msec(struct timeval *tm, unsigned int msec)
  249. {
  250. tm->tv_sec += msec / 1000;
  251. msec = msec % 1000;
  252. tm->tv_usec += msec*1000;
  253. if (tm->tv_usec > 1000000) {
  254. tm->tv_usec -= 1000000;
  255. tm->tv_sec++;
  256. }
  257. }
  258. // return msec of x - y
  259. static __inline int timeval_sub(struct timeval *x, struct timeval *y)
  260. {
  261. return (x->tv_sec - y->tv_sec) * 1000 + (1000000 + x->tv_usec - y->tv_usec)/1000 - 1000;
  262. }
  263. #ifdef __cplusplus
  264. } // extern "C" {
  265. #endif
  266. #endif //__MEMUTIL_H__