/* * category: [core for memory] * apply status: * edit status: * build status: * description: debug_trace would be invoked by stm, but stm is not used anywhere... * */ #ifndef __MEMUTIL_H__ #define __MEMUTIL_H__ #pragma once #include "config.h" #ifdef _WIN32 #define _CRTDBG_MAP_ALLOC #include #include #include //for struct timeval #else //TODO: remove #else macro. //because error C2039 would occur: “int8_t”: is not the member of “`global namespace'” #include #endif #ifdef __cplusplus extern "C" { #endif #include #include #include #include #ifdef _WIN32 static __inline void prefetch(void* p) { _asm { //NTA(non-temporal data with respect to all cache levels) prefetch data into non-temporal cache structure and //into a location close to the processor, minimizing cache pollution. prefetchnta p } } #else //rw, locality: 1(w), 0(r), temporal locality(0-3, 3 is default) #define prefetch(x) __builtin_prefetch(x, 0) #endif #define INT64_GET_HIGH_PART(x) (*((int*)(&(x)) + 1)) #define INT64_GET_LOW_PART(x) (*(int*)&(x)) static __inline int int64_get_high_part(__int64 x) { return INT64_GET_HIGH_PART(x); } static __inline int int64_get_low_part(__int64 x) { return INT64_GET_LOW_PART(x); } struct __i8_helper { union { __int64 i; struct { int l; int h; }; }; }; static __inline __int64 int64_make(int low_part, int high_part) { struct __i8_helper t; t.l = low_part; t.h = high_part; return t.i; } #define offset_of(type, member) \ (((char*)(&((type*)0)->member)) - (char*)0) #define container_of(ptr, type, member) \ ((type*)((char*)(ptr) - offset_of(type, member))) #define field_size(type, member) \ sizeof(((type*)0)->member) #define array_size(x) \ (sizeof(x)/sizeof((x)[0])) #define FLAG_BIT(f) f##_BIT /* for compatility at different platform [3/31/2020 Gifur] */ #ifndef PARAM_SIZE_DEFINED #define PARAM_SIZE_DEFINED #ifdef _WIN32 typedef int param_size_t; #else #if (defined(__x86_64__) || defined(__aarch64__)) typedef intptr_t param_size_t; #elif defined(__i386__) typedef int param_size_t; #else typedef intptr_t param_size_t; #endif #endif //_WIN32 #endif // !PARAM_SIZE_DEFINED #ifdef DEBUD_MEM_TRACE #include "memtrace.h" #define ZALLOC(size) zalloc(size) #define ZCALLOC(num, size) czalloc(num, size) #define MALLOC_T(type) (type*)malloc(sizeof(type)) #define ZALLOC_T(type) (type*)zalloc(sizeof(type)) #define CALLOC_T(num, type) (type*)calloc(num, sizeof(type)) #define REALLOC realloc #define FREE(x) do {free(x); x = NULL;} while(0) #define STRDUP(str) strdup(str) #else /** DEBUD_MEM_TRACE*/ #if 0 static __inline void* zalloc(size_t size) { void* buf = malloc(size); if (buf) { memset(buf, 0, size); } return buf; } static __inline void* zcalloc(size_t num, size_t size) { void* buf = calloc(num, size); if (buf) { memset(buf, 0, num * size); } return buf; } #define ZALLOC(size) zalloc(size) #define ZCALLOC(num, size) czalloc(num, size) #define MALLOC_T(type) (type*)malloc(sizeof(type)) #define ZALLOC_T(type) (type*)zalloc(sizeof(type)) #define CALLOC_T(num, type) (type*)calloc(num, sizeof(type)) #define REALLOC realloc #define FREE(x) do {free(x); x = NULL;} while(0) #define STRDUP(str) _strdup(str) #else #define ZALLOC(size) toolkit_zalloc(size) #define ZCALLOC(num, size) toolkit_calloc(num, size) #define MALLOC_T(type) (type*)toolkit_malloc(sizeof(type)) #define ZALLOC_T(type) (type*)toolkit_zalloc(sizeof(type)) #define CALLOC_T(num, type) (type*)toolkit_calloc(num, sizeof(type)) #define REALLOC toolkit_realloc #define FREE(x) do {toolkit_free(x); x = NULL;} while(0) #define STRDUP(str) toolkit_strdup(str) #endif #endif /** DEBUD_MEM_TRACE*/ #define SAFE_INVOKE_0(lpfn) if(lpfn) lpfn() #define SAFE_INVOKE_1(lpfn, param1) if(lpfn) lpfn(param1) #define SAFE_INVOKE_2(lpfn, param1, param2) if(lpfn) lpfn(param1, param2) #define SAFE_INVOKE_3(lpfn, param1, param2, param3) if(lpfn) lpfn(param1, param2, param3) #define SAFE_INVOKE_4(lpfn, param1, param2, param3, param4) if(lpfn) lpfn(param1, param2, param3, param4) #define SAFE_INVOKE_5(lpfn, param1, param2, param3, param4, param5) if(lpfn) lpfn(param1, param2, param3, param4, param5) #define SAFE_INVOKE_6(lpfn, param1, param2, param3, param4, param5, param6) if(lpfn) lpfn(param1, param2, param3, param4, param5, param6) #define SAFE_INVOKE_7(lpfn, param1, param2, param3, param4, param5, param6, param7) if(lpfn) lpfn(param1, param2, param3, param4, param5, param6, param7) #define SAFE_INVOKE_8(lpfn, param1, param2, param3, param4, param5, param6, param7, param8) if(lpfn) lpfn(param1, param2, param3, param4, param5, param6, param7, param8) #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) #define INIT_COUNTER(name, x) enum { name = __LINE__ + x } #define DEF_COUNTER(name) (__LINE__ - name) /** * resize buffer with data preserved * @param old pointer to old buffer * @param elemsize element size * @param oldcnt the old element count * @param newcnt the new element count * @return return new buffer, if failed, original buffer is returned, if success old buffer will be freed */ TOOLKIT_API void *buffer_resize(void* old, int elemsize, int oldcnt, int newcnt); TOOLKIT_API void *shm_buffer_resize(void* old, int elemsize, int oldcnt, int newcnt); /** * check expand */ TOOLKIT_API int array_check_expand(void **old, int elemsize, int cnt, int *capacity); TOOLKIT_API int shm_array_check_expand(void **old, int elemsize, int cnt, int *capacity); typedef struct toolkit_allocator_t tk_allocator_t; typedef void* (*toolkit_malloc_func)(size_t size); typedef void* (*toolkit_realloc_func)(void* ptr, size_t size); typedef void* (*toolkit_calloc_func)(size_t count, size_t size); typedef void (*toolkit_free_func)(void* ptr); TOOLKIT_API int toolkit_replace_allocator(toolkit_malloc_func malloc_func, toolkit_realloc_func realloc_func, toolkit_calloc_func calloc_func, toolkit_free_func free_func); TOOLKIT_API void* toolkit_malloc(size_t size); TOOLKIT_API void* toolkit_calloc(size_t num, size_t size); TOOLKIT_API void* toolkit_realloc(void* ptr, size_t size); TOOLKIT_API void toolkit_free(void *p); TOOLKIT_API void *toolkit_zalloc(size_t size); TOOLKIT_API void *toolkit_zcalloc(size_t num, size_t size); TOOLKIT_API char *toolkit_strdup(const char *s); TOOLKIT_API char* toolkit_strndup(const char* s, size_t n); TOOLKIT_API wchar_t *toolkit_wcsdup(const wchar_t *s); #if !defined(_DEBUG) || !defined(DEBUG) #define ASSERT_RETURN(cond, ret) \ if (!(cond)) \ return ret; #else #define ASSERT_RETURN(cond, ret) assert(cond); #endif TOOLKIT_API void debug_trace(const char *fmt, ...); #if defined(_DEBUG) || defined(DEBUG) #define DEBUG_TRACE(fmt, ...) debug_trace(fmt, __VA_ARGS__); #else #define DEBUG_TRACE(fmt, ...) #endif /*defined(_DEBUG) || defined(DEBUG)*/ #if defined(_WIN32) && ( defined(_DEBUG) || defined(DEBUG)) #define LEAK_TRACE_SNAPSHOT_BEGIN() _CrtMemState s1, s2, s3; \ do { \ _CrtMemCheckpoint(&s1); \ } while (false) #define LEAK_TRACE_SNAPSHOT_END() \ do { \ _CrtMemCheckpoint(&s2); \ if (_CrtMemDifference(&s3, &s1, &s2)) \ _CrtMemDumpStatistics(&s3); \ } while (false) #else #define LEAK_TRACE_SNAPSHOT_BEGIN() ((void)0) #define LEAK_TRACE_SNAPSHOT_END() ((void)0) #endif //#if defined(_WIN32) && ( defined(_DEBUG) || defined(DEBUG)) /* * -1: x < y * 1: x > y * 0: x == y */ static __inline int timeval_cmp(struct timeval *x, struct timeval *y) { if (x->tv_sec < y->tv_sec) { return -1; } else if (x->tv_sec > y->tv_sec) { return 1; } else { if (x->tv_usec < y->tv_usec) { return -1; } else if (x->tv_usec > y->tv_usec) { return 1; } else { return 0; } } } static __inline void timeval_diff(struct timeval *x, struct timeval *y, struct timeval *out) { out->tv_sec = x->tv_sec - y->tv_sec; out->tv_usec = x->tv_usec - y->tv_usec; if (out->tv_usec < 0) { out->tv_sec --; out->tv_usec = 1000000 + out->tv_usec; } } static __inline void timeval_add_sec(struct timeval *tm, unsigned int sec) { tm->tv_sec += sec; } static __inline void timeval_add_msec(struct timeval *tm, unsigned int msec) { tm->tv_sec += msec / 1000; msec = msec % 1000; tm->tv_usec += msec*1000; if (tm->tv_usec > 1000000) { tm->tv_usec -= 1000000; tm->tv_sec++; } } // return msec of x - y static __inline int timeval_sub(struct timeval *x, struct timeval *y) { return (x->tv_sec - y->tv_sec) * 1000 + (1000000 + x->tv_usec - y->tv_usec)/1000 - 1000; } #ifdef __cplusplus } // extern "C" { #endif #endif //__MEMUTIL_H__