mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Make function call tracing lockless
This commit is contained in:
parent
9877c04fac
commit
694a0da990
2 changed files with 37 additions and 50 deletions
|
@ -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");
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue