• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 6785682079

07 Nov 2023 02:10PM UTC coverage: 88.251%. Remained the same
6785682079

push

github

fckxorg
Fix last commit.

Reported by PluMGMK.

(cherry-picked from commit 224129a8e)

The `_VMEVENTS` table, where the error handler for GC finalizers
is set, was not cleared from the stack after the initialization.
This commit adds stack cleanup.

Maxim Kokryashkin:
* added the description and the test for the problem

Part of tarantool/tarantool#9145

5341 of 5973 branches covered (0.0%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

10 existing lines in 2 files now uncovered.

20498 of 23306 relevant lines covered (87.95%)

2768772.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.22
/src/lj_sysprof.c
1
/*
2
** Implementation of sysprof - platform and Lua profiler.
3
*/
4

5
#define lj_sysprof_c
6
#define LUA_CORE
7

8
#include "lj_arch.h"
9
#include "lj_sysprof.h"
10

11
#if LJ_HASSYSPROF
12

13
#include "lj_obj.h"
14
#include "lj_debug.h"
15
#include "lj_dispatch.h"
16
#include "lj_frame.h"
17

18
#if LJ_HASJIT
19
#include "lj_jit.h"
20
#include "lj_trace.h"
21
#endif
22

23
#include "lj_wbuf.h"
24
#include "lj_profile_timer.h"
25
#include "lj_symtab.h"
26

27
#include <pthread.h>
28
#include <errno.h>
29
#include <execinfo.h>
30

31
/*
32
** Number of profiler frames we need to omit during stack
33
** unwinding.
34
**   +------------------------+
35
** 0 | default_backtrace_host |
36
**   +------------------------+
37
** 1 | stream_backtrace_host  |
38
**   +------------------------+
39
** 2 |  stream_{guest/host}   |
40
**   +------------------------+
41
** 3 |      stream_event      |
42
**   +------------------------+
43
** 4 | sysprof_record_sample  |
44
**   +------------------------+
45
** 5 | sysprof_signal_handler |
46
**   +------------------------+
47
*/
48
#define SYSPROF_HANDLER_STACK_DEPTH 6
49
#define SYSPROF_BACKTRACE_FRAME_MAX 512
50

51
/* Check that vmstate fits in 4 bits (see streaming format) */
52
#define vmstfit4(st) ((st & ~(uint32_t)((1 << 4) - 1)) == 0)
53

54
enum sysprof_state {
55
  /* Profiler is not running. */
56
  SPS_IDLE,
57
  /* Profiler is running. */
58
  SPS_PROFILE,
59
  /*
60
  ** Stopped in case of stopped or failed stream.
61
  ** Saved errno is set at luaM_sysprof_stop.
62
  */
63
  SPS_HALT
64
};
65

66
struct sysprof {
67
  global_State *g; /* Profiled VM. */
68
  pthread_t thread; /* Profiled thread. */
69
  volatile sig_atomic_t state; /* Internal state. */
70
  struct lj_wbuf out; /* Output accumulator. */
71
  struct luam_Sysprof_Counters counters; /* Profiling counters. */
72
  struct luam_Sysprof_Options opt; /* Profiling options. */
73
  luam_Sysprof_writer writer; /* Writer function for profile events. */
74
  luam_Sysprof_on_stop on_stop; /* Callback on profiling stopping. */
75
  luam_Sysprof_backtracer backtracer; /* Backtracing function for the host stack. */
76
  lj_profile_timer timer; /* Profiling timer. */
77
  int saved_errno; /* Saved errno when profiler failed. */
78
  uint32_t lib_adds; /* Number of libs loaded. Monotonic. */
79
};
80
/*
81
** XXX: Only one VM can be profiled at a time.
82
*/
83

84
static struct sysprof sysprof = {0};
85

86
/* --- Stream ------------------------------------------------------------- */
87

88
static const uint8_t ljp_header[] = {'l', 'j', 'p', LJP_FORMAT_VERSION,
89
                                      0x0, 0x0, 0x0};
90

91
static int stream_is_needed(struct sysprof *sp)
16✔
92
{
93
  return sp->opt.mode != LUAM_SYSPROF_DEFAULT;
16✔
94
}
95

96
static int is_unconfigured(struct sysprof *sp)
719✔
97
{
98
  return sp->backtracer == NULL || sp->on_stop == NULL || sp->writer == NULL;
241✔
99
}
100

101
static void stream_prologue(struct sysprof *sp)
2✔
102
{
103
  lj_symtab_dump(&sp->out, sp->g, &sp->lib_adds);
2✔
104
  lj_wbuf_addn(&sp->out, ljp_header, sizeof(ljp_header));
2✔
105
}
2✔
106

107
static void stream_epilogue(struct sysprof *sp)
2✔
108
{
109
  lj_wbuf_addbyte(&sp->out, LJP_EPILOGUE_BYTE);
2✔
110
}
111

112
static void stream_lfunc(struct lj_wbuf *buf, const GCfunc *func)
113
{
114
  lj_assertX(isluafunc(func), "bad lua function in sysprof stream");
115
  const GCproto *pt = funcproto(func);
116
  lj_assertX(pt != NULL, "bad lua function prototype in sysprof stream");
117
  lj_wbuf_addbyte(buf, LJP_FRAME_LFUNC);
118
  lj_wbuf_addu64(buf, (uintptr_t)pt);
119
  lj_wbuf_addu64(buf, (uint64_t)pt->firstline);
120
}
121

122
static void stream_cfunc(struct lj_wbuf *buf, const GCfunc *func)
2✔
123
{
124
  lj_assertX(iscfunc(func), "bad C function in sysprof stream");
2✔
125
  lj_wbuf_addbyte(buf, LJP_FRAME_CFUNC);
2✔
126
  lj_wbuf_addu64(buf, (uintptr_t)func->c.f);
2✔
127
}
2✔
128

129
static void stream_ffunc(struct lj_wbuf *buf, const GCfunc *func)
2✔
130
{
131
  lj_assertX(isffunc(func), "bad fast function in sysprof stream");
2✔
132
  lj_wbuf_addbyte(buf, LJP_FRAME_FFUNC);
2✔
133
  lj_wbuf_addu64(buf, func->c.ffid);
2✔
134
}
2✔
135

136
static void stream_frame_lua(struct lj_wbuf *buf, const cTValue *frame)
56✔
137
{
138
  const GCfunc *func = frame_func(frame);
56✔
139
  lj_assertX(func != NULL, "bad function in sysprof stream");
56✔
140
  if (isluafunc(func))
56✔
141
    stream_lfunc(buf, func);
52✔
142
  else if (isffunc(func))
4✔
143
    stream_ffunc(buf, func);
2✔
144
  else if (iscfunc(func))
2✔
145
    stream_cfunc(buf, func);
2✔
146
  else
147
    /* Unreachable. */
148
    lj_assertX(0, "bad function type in sysprof stream");
56✔
149
}
56✔
150

151
static void stream_backtrace_lua(struct sysprof *sp)
2✔
152
{
153
  global_State *g = sp->g;
2✔
154
  struct lj_wbuf *buf = &sp->out;
2✔
155
  cTValue *top_frame = NULL, *frame = NULL, *bot = NULL;
2✔
156
  lua_State *L = NULL;
2✔
157

158
  lj_assertX(g != NULL, "uninitialized global state in sysprof state");
2✔
159
  L = gco2th(gcref(g->cur_L));
2✔
160
  lj_assertG(L != NULL, "uninitialized Lua state in sysprof state");
2✔
161

162
  top_frame = g->top_frame - 1; //(1 + LJ_FR2)
2✔
163

164
  bot = tvref(L->stack) + LJ_FR2;
2✔
165
  /* Traverse frames backwards */
166
  for (frame = top_frame; frame > bot; frame = frame_prev(frame)) {
118✔
167
    if (frame_gc(frame) == obj2gco(L) || frame_isvarg(frame))
58✔
168
      continue;  /* Skip dummy frames. See lj_err_optype_call(). */
2✔
169
    stream_frame_lua(buf, frame);
56✔
170
  }
171

172
  lj_wbuf_addbyte(buf, LJP_FRAME_LUA_LAST);
2✔
173
}
2✔
174

175
static void *stream_frame_host(int frame_no, void *addr)
8✔
176
{
177
  struct sysprof *sp = &sysprof;
8✔
178
  /*
179
  ** We don't want the profiler stack to be streamed, as it will
180
  ** burden the profile with unnecessary information.
181
  */
182
  if (LJ_UNLIKELY(frame_no <= SYSPROF_HANDLER_STACK_DEPTH))
8✔
183
    return addr;
184
  else if (LJ_UNLIKELY(sp->opt.mode == LUAM_SYSPROF_LEAF &&
1✔
185
                         frame_no > SYSPROF_HANDLER_STACK_DEPTH))
186
    return NULL;
187

188
  lj_wbuf_addu64(&sp->out, (uintptr_t)addr);
1✔
189
  return addr;
1✔
190
}
191

192
static void default_backtrace_host(void *(writer)(int frame_no, void *addr))
2✔
193
{
194
  static void *backtrace_buf[SYSPROF_BACKTRACE_FRAME_MAX] = {};
2✔
195

196
  struct sysprof *sp = &sysprof;
2✔
197
  int max_depth = sp->opt.mode == LUAM_SYSPROF_LEAF
4✔
198
                  ? SYSPROF_HANDLER_STACK_DEPTH + 1
199
                  : SYSPROF_BACKTRACE_FRAME_MAX;
2✔
200
  const int depth = backtrace(backtrace_buf, max_depth);
2✔
201
  int level;
2✔
202

203
  lj_assertX(depth <= max_depth, "depth of C stack is too big");
2✔
204
  for (level = SYSPROF_HANDLER_STACK_DEPTH; level < depth; ++level) {
12✔
205
    if (!writer(level - SYSPROF_HANDLER_STACK_DEPTH + 1, backtrace_buf[level]))
8✔
206
      return;
207
  }
208
}
209

210
static void stream_backtrace_host(struct sysprof *sp)
2✔
211
{
212
  lj_assertX(sp->backtracer != NULL, "uninitialized sysprof backtracer");
2✔
213
  sp->backtracer(stream_frame_host);
2✔
214
  lj_wbuf_addu64(&sp->out, (uintptr_t)LJP_FRAME_HOST_LAST);
2✔
215
}
216

217
#if LJ_HASJIT
218
static void stream_trace(struct sysprof *sp, uint32_t vmstate)
×
219
{
220
  lj_wbuf_addbyte(&sp->out, (uint8_t)vmstate);
×
221
  struct lj_wbuf *out = &sp->out;
×
222
  uint32_t traceno = sp->g->vmstate;
×
223
  jit_State *J = G2J(sp->g);
×
224
  GCtrace *trace = traceref(J, traceno);
×
225

226
  GCproto *startpt = gco2pt(gcref(trace->startpt));
×
227

228
  lj_wbuf_addu64(out, traceno);
×
229
  lj_wbuf_addu64(out, (uintptr_t)startpt);
×
230
  lj_wbuf_addu64(out, startpt->firstline);
×
231
}
×
232
#endif
233

234
static void stream_guest(struct sysprof *sp, uint32_t vmstate)
2✔
235
{
236
  lj_wbuf_addbyte(&sp->out, (uint8_t)vmstate);
2✔
237
  stream_backtrace_lua(sp);
2✔
238
  stream_backtrace_host(sp);
2✔
239
}
2✔
240

UNCOV
241
static void stream_host(struct sysprof *sp, uint32_t vmstate)
×
242
{
UNCOV
243
  struct lua_State *L = gco2th(gcref(sp->g->cur_L));
×
UNCOV
244
  lj_symtab_dump_newc(&sp->lib_adds, &sp->out, LJP_SYMTAB_CFUNC_EVENT, L);
×
UNCOV
245
  lj_wbuf_addbyte(&sp->out, (uint8_t)vmstate);
×
UNCOV
246
  stream_backtrace_host(sp);
×
UNCOV
247
}
×
248

249
typedef void (*event_streamer)(struct sysprof *sp, uint32_t vmstate);
250

251
static event_streamer event_streamers[] = {
252
  /* XXX: order is important */
253
  stream_host,  /* LJ_VMST_INTERP */
254
  stream_guest, /* LJ_VMST_LFUNC */
255
  stream_guest, /* LJ_VMST_FFUNC */
256
  stream_guest, /* LJ_VMST_CFUNC */
257
  stream_host,  /* LJ_VMST_GC */
258
  stream_host,  /* LJ_VMST_EXIT */
259
  stream_host,  /* LJ_VMST_RECORD */
260
  stream_host,  /* LJ_VMST_OPT */
261
  stream_host,  /* LJ_VMST_ASM */
262
#if LJ_HASJIT
263
  stream_trace  /* LJ_VMST_TRACE */
264
#endif
265
};
266

267
static void stream_event(struct sysprof *sp, uint32_t vmstate)
268
{
269
  event_streamer stream = NULL;
270

271
  lj_assertX(vmstfit4(vmstate), "vmstate don't fit in 4 bits");
272
  stream = event_streamers[vmstate];
273
  lj_assertX(stream != NULL, "uninitialized sysprof stream");
274
  stream(sp, vmstate);
275
}
276

277
/* -- Signal handler ------------------------------------------------------ */
278

279
static void sysprof_record_sample(struct sysprof *sp, siginfo_t *info)
280
{
281
  global_State *g = sp->g;
282
  uint32_t _vmstate = ~(uint32_t)(g->vmstate);
283
  uint32_t vmstate = _vmstate < LJ_VMST_TRACE ? _vmstate : LJ_VMST_TRACE;
284

285
  lj_assertX(pthread_self() == sp->thread,
286
             "bad thread during sysprof record sample");
287

288
  /* Caveat: order of counters must match vmstate order in <lj_obj.h>. */
289
  ((uint64_t *)&sp->counters)[vmstate]++;
290

291
  sp->counters.samples++;
292

293
  if (!stream_is_needed(sp))
294
    return;
295

296
  stream_event(sp, vmstate);
297
  if (LJ_UNLIKELY(lj_wbuf_test_flag(&sp->out, STREAM_ERRIO|STREAM_STOP))) {
298
    sp->saved_errno = lj_wbuf_errno(&sp->out);
299
    lj_wbuf_terminate(&sp->out);
300
    sp->state = SPS_HALT;
301
  }
302
}
303

304
static void sysprof_signal_handler(int sig, siginfo_t *info, void *ctx)
3✔
305
{
306
  struct sysprof *sp = &sysprof;
3✔
307
  UNUSED(sig);
3✔
308
  UNUSED(ctx);
3✔
309

310
  switch (sp->state) {
3✔
311
    case SPS_PROFILE:
3✔
312
      sysprof_record_sample(sp, info);
3✔
313
      break;
3✔
314

315
    case SPS_IDLE:
316
    case SPS_HALT:
317
      /* noop */
318
      break;
319

320
    default:
321
      lj_assertX(0, "bad sysprof profiler state");
322
      break;
323
  }
324
}
3✔
325

326
/* -- Internal ------------------------------------------------------------ */
327

328
static int sysprof_validate(struct sysprof *sp,
13✔
329
                            const struct luam_Sysprof_Options *opt)
330
{
331
  switch (sp->state) {
13✔
332
    case SPS_IDLE:
11✔
333
      if (opt->mode > LUAM_SYSPROF_CALLGRAPH) {
11✔
334
        return PROFILE_ERRUSE;
335
      } else if (opt->mode != LUAM_SYSPROF_DEFAULT &&
10✔
336
                 (opt->buf == NULL || opt->len == 0 || is_unconfigured(sp))) {
3✔
337
        return PROFILE_ERRUSE;
338
      } else if (opt->interval == 0) {
9✔
339
        return PROFILE_ERRUSE;
1✔
340
      }
341
      break;
342

343
    case SPS_PROFILE:
344
    case SPS_HALT:
345
      return PROFILE_ERRRUN;
346

347
    default:
348
      lj_assertX(0, "bad sysprof profiler state");
349
      break;
350
  }
351

352
  return PROFILE_SUCCESS;
353
}
354

355
static int sysprof_init(struct sysprof *sp, lua_State *L,
356
                        const struct luam_Sysprof_Options *opt)
357
{
358
  const int status = sysprof_validate(sp, opt);
359
  if (PROFILE_SUCCESS != status)
360
    return status;
361

362
  /* Copy validated options to sysprof state. */
363
  memcpy(&sp->opt, opt, sizeof(sp->opt));
364

365
  /* Init general fields. */
366
  sp->g = G(L);
367
  sp->thread = pthread_self();
368

369
  /* Reset counters. */
370
  memset(&sp->counters, 0, sizeof(sp->counters));
371

372
  /* Reset saved errno. */
373
  sp->saved_errno = 0;
374

375
  if (stream_is_needed(sp))
376
    lj_wbuf_init(&sp->out, sp->writer, opt->ctx, opt->buf, opt->len);
377

378
  return PROFILE_SUCCESS;
379
}
380

381
/* -- Public profiling API ------------------------------------------------ */
382

383
int lj_sysprof_set_writer(luam_Sysprof_writer writer) {
239✔
384
  struct sysprof *sp = &sysprof;
239✔
385

386
  if (sp->state != SPS_IDLE || writer == NULL)
239✔
387
    return PROFILE_ERRUSE;
388

389
  sp->writer = writer;
239✔
390
  if (!is_unconfigured(sp)) {
239✔
391
    sp->state = SPS_IDLE;
×
392
  }
393
  return PROFILE_SUCCESS;
394
}
395

396
int lj_sysprof_set_on_stop(luam_Sysprof_on_stop on_stop) {
239✔
397
  struct sysprof *sp = &sysprof;
239✔
398

399
  if (sp->state != SPS_IDLE || on_stop == NULL)
239✔
400
    return PROFILE_ERRUSE;
401

402
  sp->on_stop = on_stop;
239✔
403
  if (!is_unconfigured(sp)) {
239✔
404
    sp->state = SPS_IDLE;
×
405
  }
406
  return PROFILE_SUCCESS;
407
}
408

409
int lj_sysprof_set_backtracer(luam_Sysprof_backtracer backtracer) {
239✔
410
  struct sysprof *sp = &sysprof;
239✔
411

412
  if (sp->state != SPS_IDLE)
239✔
413
    return PROFILE_ERRUSE;
414
  if (backtracer == NULL) {
239✔
415
    sp->backtracer = default_backtrace_host;
239✔
416
    /*
417
    ** XXX: `backtrace` is not signal-safe, according to man,
418
    ** because it is lazy loaded on the first call, which triggers
419
    ** allocations. We need to call `backtrace` before starting profiling
420
    ** to avoid lazy loading.
421
    */
422
    void *dummy = NULL;
239✔
423
    backtrace(&dummy, 1);
239✔
424
  }
425
  else {
426
    sp->backtracer = backtracer;
×
427
  }
428
  if (!is_unconfigured(sp)) {
239✔
429
    sp->state = SPS_IDLE;
239✔
430
  }
431
  return PROFILE_SUCCESS;
432
}
433

434
int lj_sysprof_start(lua_State *L, const struct luam_Sysprof_Options *opt)
13✔
435
{
436
  struct sysprof *sp = &sysprof;
13✔
437

438
  int status = sysprof_init(sp, L, opt);
13✔
439
  if (PROFILE_SUCCESS != status) {
13✔
440
    if (NULL != sp->on_stop) {
5✔
441
      /*
442
      ** Initialization may fail in case of unconfigured sysprof,
443
      ** so we cannot guarantee cleaning up resources in this case.
444
      */
445
      sp->on_stop(opt->ctx, opt->buf);
5✔
446
    }
447
    return status;
5✔
448
  }
449

450
  sp->state = SPS_PROFILE;
8✔
451

452
  if (stream_is_needed(sp)) {
8✔
453
    stream_prologue(sp);
2✔
454
    if (LJ_UNLIKELY(lj_wbuf_test_flag(&sp->out, STREAM_ERRIO|STREAM_STOP))) {
2✔
455
      /* on_stop call may change errno value. */
456
      const int saved_errno = lj_wbuf_errno(&sp->out);
×
457
      /* Ignore possible errors. mp->out.buf may be NULL here. */
458
      sp->on_stop(opt->ctx, sp->out.buf);
×
459
      lj_wbuf_terminate(&sp->out);
×
460
      sp->state = SPS_IDLE;
×
461
      errno = saved_errno;
×
462
      return PROFILE_ERRIO;
×
463
    }
464
  }
465

466
  sp->timer.opt.interval_msec = opt->interval;
8✔
467
  sp->timer.opt.handler = sysprof_signal_handler;
8✔
468
  lj_profile_timer_start(&sp->timer);
8✔
469

470
  return PROFILE_SUCCESS;
8✔
471
}
472

473
int lj_sysprof_stop(lua_State *L)
246✔
474
{
475
  struct sysprof *sp = &sysprof;
246✔
476
  global_State *g = sp->g;
246✔
477
  struct lj_wbuf *out = &sp->out;
246✔
478

479
  if (SPS_IDLE == sp->state)
246✔
480
    return PROFILE_ERRRUN;
481
  else if (G(L) != g)
8✔
482
    return PROFILE_ERRUSE;
483

484
  lj_profile_timer_stop(&sp->timer);
8✔
485

486
  if (SPS_HALT == sp->state) {
8✔
487
    errno = sp->saved_errno;
×
488
    sp->state = SPS_IDLE;
×
489
    /* wbuf was terminated when error occured. */
490
    return PROFILE_ERRIO;
×
491
  }
492

493
  sp->state = SPS_IDLE;
8✔
494

495
  if (stream_is_needed(sp)) {
8✔
496
    int cb_status = 0;
2✔
497

498
    stream_epilogue(sp);
2✔
499
    lj_wbuf_flush(out);
2✔
500

501
    cb_status = sp->on_stop(sp->opt.ctx, out->buf);
2✔
502
    if (LJ_UNLIKELY(lj_wbuf_test_flag(out, STREAM_ERRIO | STREAM_STOP)) ||
2✔
503
        cb_status != 0) {
504
      errno = lj_wbuf_errno(out);
×
505
      lj_wbuf_terminate(out);
×
506
      return PROFILE_ERRIO;
×
507
    }
508

509
    lj_wbuf_terminate(out);
2✔
510
  }
511

512
  return PROFILE_SUCCESS;
513
}
514

515
int lj_sysprof_report(struct luam_Sysprof_Counters *counters)
3✔
516
{
517
  const struct sysprof *sp = &sysprof;
3✔
518
  if (sp->state != SPS_IDLE)
3✔
519
    return PROFILE_ERRUSE;
520
  memcpy(counters, &sp->counters, sizeof(sp->counters));
3✔
521
  return PROFILE_SUCCESS;
3✔
522
}
523

524
void lj_sysprof_add_proto(const struct GCproto *pt)
55,806✔
525
{
526
  struct sysprof *sp = &sysprof;
55,806✔
527

528
  if (sp->state != SPS_PROFILE || sp->opt.mode == LUAM_SYSPROF_DEFAULT)
55,806✔
529
    return;
530

531
  /*
532
  ** XXX: Avoid sampling during the symtab extension. That shouldn't have any
533
  ** significant effect on profile precision, but if it does, it's better to
534
  ** implement an async-safe queue for the symtab events.
535
  */
536
  sp->state = SPS_IDLE;
×
537
  lj_wbuf_addbyte(&sp->out, LJP_SYMTAB_LFUNC_EVENT);
×
538
  lj_symtab_dump_proto(&sp->out, pt);
×
539
  sp->state = SPS_PROFILE;
×
540
}
541

542
#if LJ_HASJIT
543
void lj_sysprof_add_trace(const struct GCtrace *tr)
3,733✔
544
{
545
  struct sysprof *sp = &sysprof;
3,733✔
546

547
  if (sp->state != SPS_PROFILE || sp->opt.mode == LUAM_SYSPROF_DEFAULT)
3,733✔
548
    return;
549

550
  /* See the comment about the sysprof state above. */
551
  sp->state = SPS_IDLE;
×
552
  lj_wbuf_addbyte(&sp->out, LJP_SYMTAB_TRACE_EVENT);
×
553
  lj_symtab_dump_trace(&sp->out, tr);
×
554
  sp->state = SPS_PROFILE;
×
555
}
556
#endif /* LJ_HASJIT */
557

558
#else /* LJ_HASSYSPROF */
559

560
int lj_sysprof_set_writer(luam_Sysprof_writer writer) {
561
  UNUSED(writer);
562
  return PROFILE_ERRUSE;
563
}
564

565
int lj_sysprof_set_on_stop(luam_Sysprof_on_stop on_stop) {
566
  UNUSED(on_stop);
567
  return PROFILE_ERRUSE;
568
}
569

570
int lj_sysprof_set_backtracer(luam_Sysprof_backtracer backtracer) {
571
  UNUSED(backtracer);
572
  return PROFILE_ERRUSE;
573
}
574

575
int lj_sysprof_start(lua_State *L, const struct luam_Sysprof_Options *opt)
576
{
577
  UNUSED(L);
578
  return PROFILE_ERRUSE;
579
}
580

581
int lj_sysprof_stop(lua_State *L)
582
{
583
  UNUSED(L);
584
  return PROFILE_ERRUSE;
585
}
586

587
int lj_sysprof_report(struct luam_Sysprof_Counters *counters)
588
{
589
  UNUSED(counters);
590
  return PROFILE_ERRUSE;
591
}
592

593
void lj_sysprof_add_proto(const struct GCproto *pt)
594
{
595
  UNUSED(pt);
596
}
597

598
#if LJ_HASJIT
599
void lj_sysprof_add_trace(const struct GCtrace *tr)
600
{
601
  UNUSED(tr);
602
}
603
#endif /* LJ_HASJIT */
604

605
#endif /* LJ_HASSYSPROF */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc