Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement profiler for linux. #490

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion src/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
#include <hl.h>
#include <hlmodule.h>

#ifdef HL_LINUX
#include <signal.h>
#include <semaphore.h>
#include <unistd.h>
#endif

#define MAX_STACK_SIZE (8 << 20)
#define MAX_STACK_COUNT 2048

Expand Down Expand Up @@ -73,6 +79,25 @@ static struct {
profile_data *first_record;
} data = {0};

#ifdef HL_LINUX
static struct
{
sem_t msg2;
sem_t msg3;
sem_t msg4;
ucontext_t context;
} shared_context;

static void sigprof_handler(int sig, siginfo_t *info, void *ucontext)
{
ucontext_t *ctx = ucontext;
shared_context.context = *ctx;
sem_post(&shared_context.msg2);
sem_wait(&shared_context.msg3);
sem_post(&shared_context.msg4);
}
#endif

static void *get_thread_stackptr( thread_handle *t, void **eip ) {
#ifdef HL_WIN_DESKTOP
CONTEXT c;
Expand All @@ -85,6 +110,14 @@ static void *get_thread_stackptr( thread_handle *t, void **eip ) {
*eip = (void*)c.Eip;
return (void*)c.Esp;
# endif
#elif defined(HL_LINUX)
# ifdef HL_64
*eip = (void*)shared_context.context.uc_mcontext.gregs[REG_RIP];
return (void*)shared_context.context.uc_mcontext.gregs[REG_RSP];
# else
*eip = (void*)shared_context.context.uc_mcontext.gregs[REG_EIP];
return (void*)shared_context.context.uc_mcontext.gregs[REG_ESP];
# endif
#else
return NULL;
#endif
Expand All @@ -110,6 +143,14 @@ static bool pause_thread( thread_handle *t, bool b ) {
ResumeThread(t->h);
return true;
}
#elif defined(HL_LINUX)
if( b ) {
tgkill(getpid(), t->tid, SIGPROF);
return sem_wait(&shared_context.msg2) == 0;
} else {
sem_post(&shared_context.msg3);
return sem_wait(&shared_context.msg4) == 0;
}
#else
return false;
#endif
Expand Down Expand Up @@ -144,6 +185,10 @@ static void read_thread_data( thread_handle *t ) {
return;
}

#ifdef HL_LINUX
int count = hl_module_capture_stack_range(t->inf->stack_top, stack, data.stackOut, MAX_STACK_COUNT);
pause_thread(t, false);
#else
int size = (int)((unsigned char*)t->inf->stack_top - (unsigned char*)stack);
if( size > MAX_STACK_SIZE-32 ) size = MAX_STACK_SIZE-32;
memcpy(data.tmpMemory + 2,stack,size);
Expand All @@ -153,6 +198,7 @@ static void read_thread_data( thread_handle *t ) {
size += sizeof(void*) * 2;

int count = hl_module_capture_stack_range((char*)data.tmpMemory+size, (void**)data.tmpMemory, data.stackOut, MAX_STACK_COUNT);
#endif
int eventId = count | 0x80000000;
double time = hl_sys_time();
record_data(&time,sizeof(double));
Expand Down Expand Up @@ -211,7 +257,7 @@ static void hl_profile_loop( void *_ ) {
static void profile_event( int code, vbyte *data, int dataLen );

void hl_profile_setup( int sample_count ) {
# if defined(HL_THREADS) && defined(HL_WIN_DESKTOP)
# if defined(HL_THREADS) && (defined(HL_WIN_DESKTOP) || defined(HL_LINUX))
hl_setup_profiler(profile_event,hl_profile_end);
if( data.sample_count ) return;
if( sample_count < 0 ) {
Expand All @@ -220,6 +266,15 @@ void hl_profile_setup( int sample_count ) {
return;
}
data.sample_count = sample_count;
# ifdef HL_LINUX
sem_init(&shared_context.msg2, 0, 0);
sem_init(&shared_context.msg3, 0, 0);
sem_init(&shared_context.msg4, 0, 0);
struct sigaction action = {0};
action.sa_sigaction = sigprof_handler;
action.sa_flags = SA_SIGINFO;
sigaction(SIGPROF, &action, NULL);
# endif
hl_thread_start(hl_profile_loop,NULL,false);
# endif
}
Expand Down