Make function call tracing lockless

This commit is contained in:
Justine Tunney 2022-07-11 08:04:58 -07:00
parent 9877c04fac
commit 694a0da990
2 changed files with 37 additions and 50 deletions

View file

@ -20,14 +20,14 @@
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/cmpxchg.h" #include "libc/intrin/cmpxchg.h"
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/intrin/lockcmpxchg.h"
#include "libc/intrin/nopl.h" #include "libc/intrin/nopl.h"
#include "libc/intrin/pthread.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/nexgen32e/gettls.h"
#include "libc/nexgen32e/stackframe.h" #include "libc/nexgen32e/stackframe.h"
#include "libc/nexgen32e/threaded.h" #include "libc/runtime/internal.h"
#include "libc/runtime/stack.h" #include "libc/runtime/stack.h"
#include "libc/runtime/symbols.internal.h" #include "libc/runtime/symbols.internal.h"
#include "libc/thread/thread.h"
#define MAX_NESTING 512 #define MAX_NESTING 512
@ -41,25 +41,7 @@
void ftrace_hook(void); void ftrace_hook(void);
static struct Ftrace { static int g_stackdigs;
int skew;
int stackdigs;
int64_t lastaddr;
pthread_mutex_t lock;
volatile bool noreentry;
} g_ftrace;
static void __ftrace_lock(void) {
if (__threaded) {
pthread_mutex_lock(&g_ftrace.lock);
}
}
static void __ftrace_unlock(void) {
if (__threaded) {
pthread_mutex_unlock(&g_ftrace.lock);
}
}
static privileged inline int GetNestingLevelImpl(struct StackFrame *frame) { static privileged inline int GetNestingLevelImpl(struct StackFrame *frame) {
int nesting = -2; int nesting = -2;
@ -70,11 +52,12 @@ static privileged inline int GetNestingLevelImpl(struct StackFrame *frame) {
return MAX(0, nesting); return MAX(0, nesting);
} }
static privileged inline int GetNestingLevel(struct StackFrame *frame) { static privileged inline int GetNestingLevel(struct FtraceTls *ft,
struct StackFrame *sf) {
int nesting; int nesting;
nesting = GetNestingLevelImpl(frame); nesting = GetNestingLevelImpl(sf);
if (nesting < g_ftrace.skew) g_ftrace.skew = nesting; if (nesting < ft->skew) ft->skew = nesting;
nesting -= g_ftrace.skew; nesting -= ft->skew;
return MIN(MAX_NESTING, nesting); return MIN(MAX_NESTING, nesting);
} }
@ -87,31 +70,30 @@ static privileged inline int GetNestingLevel(struct StackFrame *frame) {
*/ */
privileged void ftracer(void) { privileged void ftracer(void) {
long stackuse; long stackuse;
struct StackFrame *frame; struct FtraceTls *ft;
__ftrace_lock(); struct StackFrame *sf;
if (_cmpxchg(&g_ftrace.noreentry, false, true)) { ft = (struct FtraceTls *)(__get_tls_inline() + 0x08);
frame = __builtin_frame_address(0); if (_cmpxchg(&ft->once, false, true)) {
frame = frame->next; ft->lastaddr = -1;
if (frame->addr != g_ftrace.lastaddr) { ft->skew = GetNestingLevelImpl(__builtin_frame_address(0));
stackuse = GetStackAddr() + GetStackSize() - (intptr_t)frame; }
kprintf("%rFUN %6P %'13T %'*ld %*s%t\n", g_ftrace.stackdigs, stackuse, if (_cmpxchg(&ft->noreentry, false, true)) {
GetNestingLevel(frame) * 2, "", frame->addr); sf = __builtin_frame_address(0);
g_ftrace.lastaddr = frame->addr; sf = sf->next;
} if (sf->addr != ft->lastaddr) {
g_ftrace.noreentry = false; stackuse = GetStackAddr() + GetStackSize() - (intptr_t)sf;
kprintf("%rFUN %6P %'13T %'*ld %*s%t\n", g_stackdigs, stackuse,
GetNestingLevel(ft, sf) * 2, "", sf->addr);
ft->lastaddr = sf->addr;
}
ft->noreentry = false;
} }
__ftrace_unlock();
} }
textstartup int ftrace_install(void) { textstartup int ftrace_install(void) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&g_ftrace.lock, &attr);
if (GetSymbolTable()) { if (GetSymbolTable()) {
g_ftrace.lastaddr = -1; __enable_tls();
g_ftrace.stackdigs = LengthInt64Thousands(GetStackSize()); g_stackdigs = LengthInt64Thousands(GetStackSize());
g_ftrace.skew = GetNestingLevelImpl(__builtin_frame_address(0));
return __hook(ftrace_hook, GetSymbolTable()); return __hook(ftrace_hook, GetSymbolTable());
} else { } else {
kprintf("error: --ftrace failed to open symbol table\n"); kprintf("error: --ftrace failed to open symbol table\n");

View file

@ -17,12 +17,17 @@ enum cthread_state {
cthread_detached = 4, cthread_detached = 4,
}; };
struct FtraceTls { /* 16 */
bool once; /* 0 */
bool noreentry; /* 1 */
int skew; /* 4 */
int64_t lastaddr; /* 8 */
};
struct cthread_descriptor_t { struct cthread_descriptor_t {
struct cthread_descriptor_t *self; /* 0x00 */ struct cthread_descriptor_t *self; /* 0x00 */
void *(*func)(void *); /* 0x08 */ struct FtraceTls ftrace; /* 0x08 */
int32_t __pad0; /* 0x10 */ int64_t __pad0; /* 0x10 */
int32_t state; /* 0x14 */
void *arg; /* 0x18 */
int64_t __pad1; /* 0x20 */ int64_t __pad1; /* 0x20 */
int64_t __pad2; /* 0x28 */ int64_t __pad2; /* 0x28 */
struct cthread_descriptor_t *self2; /* 0x30 */ struct cthread_descriptor_t *self2; /* 0x30 */