osMemory.c 9.8 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
L
Liu Jicong 已提交
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

wafwerar's avatar
wafwerar 已提交
231
void *taosMemoryMalloc(int64_t size) {
wafwerar's avatar
wafwerar 已提交
232
#ifdef USE_TD_MEMORY
wafwerar's avatar
wafwerar 已提交
233
  void *tmp = malloc(size + sizeof(TdMemoryInfo));
wafwerar's avatar
wafwerar 已提交
234 235 236 237 238
  if (tmp == NULL) return NULL;

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

L
Liu Jicong 已提交
241
  return (char *)tmp + sizeof(TdMemoryInfo);
wafwerar's avatar
wafwerar 已提交
242 243 244
#else
  return malloc(size);
#endif
wafwerar's avatar
wafwerar 已提交
245 246
}

wafwerar's avatar
wafwerar 已提交
247
void *taosMemoryCalloc(int64_t num, int64_t size) {
wafwerar's avatar
wafwerar 已提交
248
#ifdef USE_TD_MEMORY
wafwerar's avatar
wafwerar 已提交
249
  int32_t memorySize = num * size;
L
Liu Jicong 已提交
250
  char   *tmp = calloc(memorySize + sizeof(TdMemoryInfo), 1);
wafwerar's avatar
wafwerar 已提交
251 252 253 254 255
  if (tmp == NULL) return NULL;

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

L
Liu Jicong 已提交
258
  return (char *)tmp + sizeof(TdMemoryInfo);
wafwerar's avatar
wafwerar 已提交
259 260 261
#else
  return calloc(num, size);
#endif
wafwerar's avatar
wafwerar 已提交
262 263
}

wafwerar's avatar
wafwerar 已提交
264
void *taosMemoryRealloc(void *ptr, int64_t size) {
wafwerar's avatar
wafwerar 已提交
265
#ifdef USE_TD_MEMORY
wafwerar's avatar
wafwerar 已提交
266
  if (ptr == NULL) return taosMemoryMalloc(size);
L
Liu Jicong 已提交
267 268

  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
X
xinsheng Ren 已提交
269 270 271 272
  ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL);
  if (tpTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
+      return NULL;
+ }
wafwerar's avatar
wafwerar 已提交
273 274 275 276 277 278

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

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

wafwerar's avatar
wafwerar 已提交
280 281 282
  memcpy(tmp, &tdMemoryInfo, sizeof(TdMemoryInfo));
  ((TdMemoryInfoPtr)tmp)->memorySize = size;

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

wafwerar's avatar
wafwerar 已提交
289
void *taosMemoryStrDup(const char *ptr) {
290 291
#ifdef USE_TD_MEMORY
  if (ptr == NULL) return NULL;
L
Liu Jicong 已提交
292 293

  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
X
xinsheng Ren 已提交
294 295 296 297
  ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL);
  if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
+   return NULL;
+ }
wafwerar's avatar
wafwerar 已提交
298
  void *tmp = tstrdup(pTdMemoryInfo);
299
  if (tmp == NULL) return NULL;
L
Liu Jicong 已提交
300

301
  memcpy(tmp, pTdMemoryInfo, sizeof(TdMemoryInfo));
L
Liu Jicong 已提交
302
  taosBackTrace(((TdMemoryInfoPtr)tmp)->stackTrace, TD_MEMORY_STACK_TRACE_DEPTH);
303

L
Liu Jicong 已提交
304
  return (char *)tmp + sizeof(TdMemoryInfo);
305
#else
wafwerar's avatar
wafwerar 已提交
306
  return tstrdup(ptr);
307 308 309
#endif
}

wafwerar's avatar
wafwerar 已提交
310
void taosMemoryFree(void *ptr) {
D
dapan1121 已提交
311
  if (NULL == ptr) return;
wafwerar's avatar
wafwerar 已提交
312
#ifdef USE_TD_MEMORY
L
Liu Jicong 已提交
313 314
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
  if (pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL) {
wafwerar's avatar
wafwerar 已提交
315 316
    pTdMemoryInfo->memorySize = 0;
    // memset(pTdMemoryInfo, 0, sizeof(TdMemoryInfo));
wafwerar's avatar
wafwerar 已提交
317 318
    free(pTdMemoryInfo);
  } else {
wafwerar's avatar
wafwerar 已提交
319
    free(ptr);
wafwerar's avatar
wafwerar 已提交
320
  }
wafwerar's avatar
wafwerar 已提交
321
#else
wafwerar's avatar
wafwerar 已提交
322
  return free(ptr);
wafwerar's avatar
wafwerar 已提交
323
#endif
wafwerar's avatar
wafwerar 已提交
324 325
}

wafwerar's avatar
wafwerar 已提交
326
int64_t taosMemorySize(void *ptr) {
wafwerar's avatar
wafwerar 已提交
327
  if (ptr == NULL) return 0;
wafwerar's avatar
wafwerar 已提交
328 329

#ifdef USE_TD_MEMORY
L
Liu Jicong 已提交
330
  TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo));
X
xinsheng Ren 已提交
331 332 333 334
  ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL);
  if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) {
+   return NULL;
+ }
wafwerar's avatar
wafwerar 已提交
335 336

  return pTdMemoryInfo->memorySize;
wafwerar's avatar
wafwerar 已提交
337 338 339
#else
#ifdef WINDOWS
  return _msize(ptr);
wafwerar's avatar
wafwerar 已提交
340 341
#elif defined(_TD_DARWIN_64)
  return malloc_size(ptr);
wafwerar's avatar
wafwerar 已提交
342 343 344
#else
  return malloc_usable_size(ptr);
#endif
wafwerar's avatar
wafwerar 已提交
345
#endif
L
Liu Jicong 已提交
346
}
G
gccgdb1234 已提交
347 348

void taosMemoryTrim(int32_t size) {
dengyihao's avatar
dengyihao 已提交
349 350 351 352 353 354
#if defined(WINDOWS) || defined(DARWIN)
  // do nothing
  return;
#else
  malloc_trim(size);
#endif
G
gccgdb1234 已提交
355
}
356 357 358

void* taosMemoryMallocAlign(uint32_t alignment, int64_t size) {
#ifdef USE_TD_MEMORY
X
xinsheng Ren 已提交
359
  ASSERT(0);
360
#else
361
#if defined(LINUX)
362 363
  void* p = memalign(alignment, size);
  return p;
364 365 366
#else
  return taosMemoryMalloc(size);
#endif
367 368
#endif
}