osMemory.c 10.3 KB
Newer Older
wafwerar's avatar
wafwerar 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#define ALLOW_FORBID_FUNC
wafwerar's avatar
wafwerar 已提交
17 18 19
#ifdef _TD_DARWIN_64
#include <malloc/malloc.h>
#else
wafwerar's avatar
wafwerar 已提交
20
#include <malloc.h>
wafwerar's avatar
wafwerar 已提交
21
#endif
wafwerar's avatar
wafwerar 已提交
22 23
#include "os.h"

wafwerar's avatar
wafwerar 已提交
24
#if defined(USE_TD_MEMORY) || defined(USE_ADDR2LINE)
wafwerar's avatar
wafwerar 已提交
25

L
Liu Jicong 已提交
26
#define TD_MEMORY_SYMBOL ('T' << 24 | 'A' << 16 | 'O' << 8 | 'S')
wafwerar's avatar
wafwerar 已提交
27

28
#define TD_MEMORY_STACK_TRACE_DEPTH 10
wafwerar's avatar
wafwerar 已提交
29

30 31
typedef struct TdMemoryInfo *TdMemoryInfoPtr;

H
Haojun Liao 已提交
32
typedef struct TdMemoryInfo {
wafwerar's avatar
wafwerar 已提交
33
  int32_t symbol;
H
Haojun Liao 已提交
34
  int32_t memorySize;
L
Liu Jicong 已提交
35
  void   *stackTrace[TD_MEMORY_STACK_TRACE_DEPTH];  // gdb: disassemble /m 0xXXX
36 37 38
  // TdMemoryInfoPtr pNext;
  // TdMemoryInfoPtr pPrev;
} TdMemoryInfo;
wafwerar's avatar
wafwerar 已提交
39

40
// static TdMemoryInfoPtr GlobalMemoryPtr = NULL;
wafwerar's avatar
wafwerar 已提交
41

wafwerar's avatar
wafwerar 已提交
42
#ifdef WINDOWS
L
Liu Jicong 已提交
43
#define tstrdup(str) _strdup(str)
wafwerar's avatar
wafwerar 已提交
44 45 46 47 48 49 50 51 52 53 54

int32_t taosBackTrace(void **buffer, int32_t size) {
  int32_t frame = 0;
  return frame;
}

#ifdef USE_ADDR2LINE
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")

void taosPrintBackTrace() {
H
Hongze Cheng 已提交
55 56 57 58 59 60 61 62
#define MAX_STACK_FRAMES 20

  void *pStack[MAX_STACK_FRAMES];

  HANDLE process = GetCurrentProcess();
  SymInitialize(process, NULL, TRUE);
  WORD frames = CaptureStackBackTrace(1, MAX_STACK_FRAMES, pStack, NULL);

wafwerar's avatar
wafwerar 已提交
63
  char buf_tmp[1024];
H
Hongze Cheng 已提交
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
  for (WORD i = 0; i < frames; ++i) {
    DWORD64 address = (DWORD64)(pStack[i]);

    DWORD64      displacementSym = 0;
    char         buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;

    DWORD           displacementLine = 0;
    IMAGEHLP_LINE64 line;
    // SymSetOptions(SYMOPT_LOAD_LINES);
    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);

    if (SymFromAddr(process, address, &displacementSym, pSymbol) &&
        SymGetLineFromAddr64(process, address, &displacementLine, &line)) {
      snprintf(buf_tmp, sizeof(buf_tmp), "BackTrace %08" PRId64 " %s:%d %s\n", taosGetSelfPthreadId(), line.FileName,
               line.LineNumber, pSymbol->Name);
    } else {
      snprintf(buf_tmp, sizeof(buf_tmp), "BackTrace error: %d\n", GetLastError());
    }
    write(1, buf_tmp, strlen(buf_tmp));
  }
wafwerar's avatar
wafwerar 已提交
87 88
}
#endif
wafwerar's avatar
wafwerar 已提交
89
#else
90
#define tstrdup(str) strdup(str)
wafwerar's avatar
wafwerar 已提交
91

L
Liu Jicong 已提交
92
#include <execinfo.h>
wafwerar's avatar
wafwerar 已提交
93

wafwerar's avatar
wafwerar 已提交
94
#define STACKCALL __attribute__((regparm(1), noinline))
95
void **STACKCALL taosGetEbp(void) {
wafwerar's avatar
wafwerar 已提交
96 97 98 99 100 101 102
  void **ebp = NULL;
  __asm__ __volatile__("mov %%rbp, %0;\n\t"
                       : "=m"(ebp)  /* output */
                       :            /* input */
                       : "memory"); /* not affect register */
  return (void **)(*ebp);
}
wafwerar's avatar
wafwerar 已提交
103

wafwerar's avatar
wafwerar 已提交
104 105
int32_t taosBackTrace(void **buffer, int32_t size) {
  int32_t frame = 0;
L
Liu Jicong 已提交
106 107 108
  void  **ebp;
  void  **ret = NULL;
  size_t  func_frame_distance = 0;
wafwerar's avatar
wafwerar 已提交
109
  if (buffer != NULL && size > 0) {
110
    ebp = taosGetEbp();
wafwerar's avatar
wafwerar 已提交
111
    func_frame_distance = (size_t)*ebp - (size_t)ebp;
wafwerar's avatar
wafwerar 已提交
112 113 114 115 116
    while (ebp && frame < size && (func_frame_distance < (1ULL << 24))  // assume function ebp more than 16M
           && (func_frame_distance > 0)) {
      ret = ebp + 1;
      buffer[frame++] = *ret;
      ebp = (void **)(*ebp);
wafwerar's avatar
wafwerar 已提交
117
      func_frame_distance = (size_t)*ebp - (size_t)ebp;
wafwerar's avatar
wafwerar 已提交
118 119 120 121
    }
  }
  return frame;
}
wafwerar's avatar
wafwerar 已提交
122

123 124 125 126 127
// char **taosBackTraceSymbols(int32_t *size) {
//   void  *buffer[20] = {NULL};
//   *size = taosBackTrace(buffer, 20);
//   return backtrace_symbols(buffer, *size);
// }
wafwerar's avatar
wafwerar 已提交
128

wafwerar's avatar
wafwerar 已提交
129 130 131
#ifdef USE_ADDR2LINE

#include "dwarf.h"
H
Hongze Cheng 已提交
132 133
#include "libdwarf.h"
#include "osThread.h"
wafwerar's avatar
wafwerar 已提交
134 135 136

#define DW_PR_DUu "llu"

H
Hongze Cheng 已提交
137 138 139 140 141 142
typedef struct lookup_table {
  Dwarf_Line         *table;
  Dwarf_Line_Context *ctxts;
  int                 cnt;
  Dwarf_Addr          low;
  Dwarf_Addr          high;
wafwerar's avatar
wafwerar 已提交
143 144
} lookup_tableT;

H
Hongze Cheng 已提交
145
extern int  create_lookup_table(Dwarf_Debug dbg, lookup_tableT *lookup_table);
wafwerar's avatar
wafwerar 已提交
146 147
extern void delete_lookup_table(lookup_tableT *lookup_table);

H
Hongze Cheng 已提交
148 149 150
size_t              addr = 0;
lookup_tableT       lookup_table;
Dwarf_Debug         tDbg;
wafwerar's avatar
wafwerar 已提交
151 152 153
static TdThreadOnce traceThreadInit = PTHREAD_ONCE_INIT;

void endTrace() {
wafwerar's avatar
wafwerar 已提交
154 155
  TdThreadOnce tmp = PTHREAD_ONCE_INIT;
  if (memcmp(&traceThreadInit, &tmp, sizeof(TdThreadOnce)) != 0) {
wafwerar's avatar
wafwerar 已提交
156 157
    delete_lookup_table(&lookup_table);
    dwarf_finish(tDbg);
wafwerar's avatar
wafwerar 已提交
158
  }
wafwerar's avatar
wafwerar 已提交
159 160
}
void startTrace() {
H
Hongze Cheng 已提交
161
  int       ret;
wafwerar's avatar
wafwerar 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
  Dwarf_Ptr errarg = 0;

  FILE *fp = fopen("/proc/self/maps", "r");
  fscanf(fp, "%lx-", &addr);
  fclose(fp);

  ret = dwarf_init_path("/proc/self/exe", NULL, 0, DW_GROUPNUMBER_ANY, NULL, errarg, &tDbg, NULL);
  if (ret == DW_DLV_NO_ENTRY) {
    printf("Unable to open file");
    return;
  }

  ret = create_lookup_table(tDbg, &lookup_table);
  if (ret != DW_DLV_OK) {
    printf("Unable to create lookup table");
    return;
  }
  atexit(endTrace);
}
static void print_line(Dwarf_Debug dbg, Dwarf_Line line, Dwarf_Addr pc) {
H
Hongze Cheng 已提交
182
  char          *linesrc = "??";
wafwerar's avatar
wafwerar 已提交
183
  Dwarf_Unsigned lineno = 0;
wafwerar's avatar
wafwerar 已提交
184

wafwerar's avatar
wafwerar 已提交
185 186 187 188
  if (line) {
    dwarf_linesrc(line, &linesrc, NULL);
    dwarf_lineno(line, &lineno, NULL);
  }
189
  printf("BackTrace %08" PRId64 " %s:%" DW_PR_DUu "\n", taosGetSelfPthreadId(), linesrc, lineno);
wafwerar's avatar
wafwerar 已提交
190
  if (line) dwarf_dealloc(dbg, linesrc, DW_DLA_STRING);
wafwerar's avatar
wafwerar 已提交
191 192
}
void taosPrintBackTrace() {
H
Hongze Cheng 已提交
193 194
  int        size = 20;
  void     **buffer[20];
wafwerar's avatar
wafwerar 已提交
195
  Dwarf_Addr pc;
H
Hongze Cheng 已提交
196 197 198 199
  int32_t    frame = 0;
  void     **ebp;
  void     **ret = NULL;
  size_t     func_frame_distance = 0;
wafwerar's avatar
wafwerar 已提交
200 201 202 203

  taosThreadOnce(&traceThreadInit, startTrace);

  if (buffer != NULL && size > 0) {
H
Hongze Cheng 已提交
204
    ebp = taosGetEbp();
wafwerar's avatar
wafwerar 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
    func_frame_distance = (size_t)*ebp - (size_t)ebp;
    while (ebp && frame < size && (func_frame_distance < (1ULL << 24)) && (func_frame_distance > 0)) {
      ret = ebp + 1;
      buffer[frame++] = *ret;
      ebp = (void **)(*ebp);
      func_frame_distance = (size_t)*ebp - (size_t)ebp;
    }
    for (size_t i = 0; i < frame; i++) {
      pc = (size_t)buffer[i] - addr;
      if (pc > 0) {
        if (pc >= lookup_table.low && pc < lookup_table.high) {
          Dwarf_Line line = lookup_table.table[pc - lookup_table.low];
          if (line) print_line(tDbg, line, pc);
        }
      }
    }
  }
}
#endif
#endif
#endif

#ifndef USE_ADDR2LINE
void taosPrintBackTrace() { return; }
wafwerar's avatar
wafwerar 已提交
229 230
#endif

D
dapan1121 已提交
231
int32_t taosMemoryDbgInit() {
232
#if defined(LINUX) && !defined(_ALPINE)
D
dapan1121 已提交
233 234 235
  int ret = mallopt(M_MMAP_THRESHOLD, 0);
  if (0 == ret) {
    return TAOS_SYSTEM_ERROR(errno);
236
  }
D
dapan1121 已提交
237 238

  return 0;
239
#else
D
dapan1121 已提交
240 241 242 243 244
  return TSDB_CODE_FAILED;
#endif
}

int32_t taosMemoryDbgInitRestore() {
245
#if defined(LINUX) && !defined(_ALPINE)
D
dapan1121 已提交
246 247 248
  int ret = mallopt(M_MMAP_THRESHOLD, 128 * 1024);
  if (0 == ret) {
    return TAOS_SYSTEM_ERROR(errno);
249
  }
D
dapan1121 已提交
250 251

  return 0;
252
#else
D
dapan1121 已提交
253 254 255 256
  return TSDB_CODE_FAILED;
#endif
}

wafwerar's avatar
wafwerar 已提交
257
void *taosMemoryMalloc(int64_t size) {
wafwerar's avatar
wafwerar 已提交
258
#ifdef USE_TD_MEMORY
wafwerar's avatar
wafwerar 已提交
259
  void *tmp = malloc(size + sizeof(TdMemoryInfo));
wafwerar's avatar
wafwerar 已提交
260 261 262 263 264
  if (tmp == NULL) return NULL;

  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)tmp;
  pTdMemoryInfo->memorySize = size;
  pTdMemoryInfo->symbol = TD_MEMORY_SYMBOL;
L
Liu Jicong 已提交
265
  taosBackTrace(pTdMemoryInfo->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
wafwerar's avatar
wafwerar 已提交
266

L
Liu Jicong 已提交
267
  return (char *)tmp + sizeof(TdMemoryInfo);
wafwerar's avatar
wafwerar 已提交
268 269 270
#else
  return malloc(size);
#endif
wafwerar's avatar
wafwerar 已提交
271 272
}

wafwerar's avatar
wafwerar 已提交
273
void *taosMemoryCalloc(int64_t num, int64_t size) {
wafwerar's avatar
wafwerar 已提交
274
#ifdef USE_TD_MEMORY
wafwerar's avatar
wafwerar 已提交
275
  int32_t memorySize = num * size;
L
Liu Jicong 已提交
276
  char   *tmp = calloc(memorySize + sizeof(TdMemoryInfo), 1);
wafwerar's avatar
wafwerar 已提交
277 278 279 280 281
  if (tmp == NULL) return NULL;

  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)tmp;
  pTdMemoryInfo->memorySize = memorySize;
  pTdMemoryInfo->symbol = TD_MEMORY_SYMBOL;
L
Liu Jicong 已提交
282
  taosBackTrace(pTdMemoryInfo->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
wafwerar's avatar
wafwerar 已提交
283

L
Liu Jicong 已提交
284
  return (char *)tmp + sizeof(TdMemoryInfo);
wafwerar's avatar
wafwerar 已提交
285 286 287
#else
  return calloc(num, size);
#endif
wafwerar's avatar
wafwerar 已提交
288 289
}

wafwerar's avatar
wafwerar 已提交
290
void *taosMemoryRealloc(void *ptr, int64_t size) {
wafwerar's avatar
wafwerar 已提交
291
#ifdef USE_TD_MEMORY
wafwerar's avatar
wafwerar 已提交
292
  if (ptr == NULL) return taosMemoryMalloc(size);
L
Liu Jicong 已提交
293 294

  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
X
xinsheng Ren 已提交
295 296 297 298
  ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL);
  if (tpTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
+      return NULL;
+ }
wafwerar's avatar
wafwerar 已提交
299 300 301 302 303 304

  TdMemoryInfo tdMemoryInfo;
  memcpy(&tdMemoryInfo, pTdMemoryInfo, sizeof(TdMemoryInfo));

  void *tmp = realloc(pTdMemoryInfo, size + sizeof(TdMemoryInfo));
  if (tmp == NULL) return NULL;
L
Liu Jicong 已提交
305

wafwerar's avatar
wafwerar 已提交
306 307 308
  memcpy(tmp, &tdMemoryInfo, sizeof(TdMemoryInfo));
  ((TdMemoryInfoPtr)tmp)->memorySize = size;

L
Liu Jicong 已提交
309
  return (char *)tmp + sizeof(TdMemoryInfo);
wafwerar's avatar
wafwerar 已提交
310 311 312
#else
  return realloc(ptr, size);
#endif
wafwerar's avatar
wafwerar 已提交
313 314
}

315
void *taosStrdup(const char *ptr) {
316 317
#ifdef USE_TD_MEMORY
  if (ptr == NULL) return NULL;
L
Liu Jicong 已提交
318 319

  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
X
xinsheng Ren 已提交
320 321
  ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL);
  if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
322 323
   return NULL;
 }
wafwerar's avatar
wafwerar 已提交
324
  void *tmp = tstrdup(pTdMemoryInfo);
325
  if (tmp == NULL) return NULL;
L
Liu Jicong 已提交
326

327
  memcpy(tmp, pTdMemoryInfo, sizeof(TdMemoryInfo));
L
Liu Jicong 已提交
328
  taosBackTrace(((TdMemoryInfoPtr)tmp)->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
329

L
Liu Jicong 已提交
330
  return (char *)tmp + sizeof(TdMemoryInfo);
331
#else
wafwerar's avatar
wafwerar 已提交
332
  return tstrdup(ptr);
333 334 335
#endif
}

wafwerar's avatar
wafwerar 已提交
336
void taosMemoryFree(void *ptr) {
D
dapan1121 已提交
337
  if (NULL == ptr) return;
wafwerar's avatar
wafwerar 已提交
338
#ifdef USE_TD_MEMORY
L
Liu Jicong 已提交
339 340
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
  if (pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL) {
wafwerar's avatar
wafwerar 已提交
341 342
    pTdMemoryInfo->memorySize = 0;
    // memset(pTdMemoryInfo, 0, sizeof(TdMemoryInfo));
wafwerar's avatar
wafwerar 已提交
343 344
    free(pTdMemoryInfo);
  } else {
wafwerar's avatar
wafwerar 已提交
345
    free(ptr);
wafwerar's avatar
wafwerar 已提交
346
  }
wafwerar's avatar
wafwerar 已提交
347
#else
wafwerar's avatar
wafwerar 已提交
348
  return free(ptr);
wafwerar's avatar
wafwerar 已提交
349
#endif
wafwerar's avatar
wafwerar 已提交
350 351
}

wafwerar's avatar
wafwerar 已提交
352
int64_t taosMemorySize(void *ptr) {
wafwerar's avatar
wafwerar 已提交
353
  if (ptr == NULL) return 0;
wafwerar's avatar
wafwerar 已提交
354 355

#ifdef USE_TD_MEMORY
L
Liu Jicong 已提交
356
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
X
xinsheng Ren 已提交
357 358 359 360
  ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL);
  if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
+   return NULL;
+ }
wafwerar's avatar
wafwerar 已提交
361 362

  return pTdMemoryInfo->memorySize;
wafwerar's avatar
wafwerar 已提交
363 364 365
#else
#ifdef WINDOWS
  return _msize(ptr);
wafwerar's avatar
wafwerar 已提交
366 367
#elif defined(_TD_DARWIN_64)
  return malloc_size(ptr);
wafwerar's avatar
wafwerar 已提交
368 369 370
#else
  return malloc_usable_size(ptr);
#endif
wafwerar's avatar
wafwerar 已提交
371
#endif
L
Liu Jicong 已提交
372
}
G
gccgdb1234 已提交
373 374

void taosMemoryTrim(int32_t size) {
sangshuduo's avatar
sangshuduo 已提交
375
#if defined(WINDOWS) || defined(DARWIN) || defined(_ALPINE)
dengyihao's avatar
dengyihao 已提交
376 377 378 379 380
  // do nothing
  return;
#else
  malloc_trim(size);
#endif
G
gccgdb1234 已提交
381
}
382 383 384

void* taosMemoryMallocAlign(uint32_t alignment, int64_t size) {
#ifdef USE_TD_MEMORY
X
xinsheng Ren 已提交
385
  ASSERT(0);
386
#else
387
#if defined(LINUX)
388 389
  void* p = memalign(alignment, size);
  return p;
390 391 392
#else
  return taosMemoryMalloc(size);
#endif
393 394
#endif
}