Skip to content

Commit

Permalink
Add profile.c to src/ and build it.
Browse files Browse the repository at this point in the history
This keeps the Julia code in a package, until Windows support is ready.
  • Loading branch information
timholy committed Jul 24, 2013
1 parent 3d917e1 commit 159203b
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ override CXXFLAGS += $(JCXXFLAGS)

SRCS = \
jltypes gf ast builtins module codegen interpreter \
alloc dlload sys init task array dump toplevel jl_uv jlapi
alloc dlload sys init task array dump toplevel jl_uv jlapi profile

FLAGS = \
-D_GNU_SOURCE \
Expand Down
158 changes: 158 additions & 0 deletions src/profile.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#include <stdlib.h>
#include <stddef.h>

typedef ptrdiff_t ptrint_t;

This comment has been minimized.

Copy link
@blakejohnson

blakejohnson Jul 25, 2013

Contributor

You can drop this line now that the code is in base. It is already defined in support/dtypes.h

This comment has been minimized.

Copy link
@staticfloat

staticfloat Jul 25, 2013

Member

Nice catch, @blakejohnson. :) I believe I was the one that put this in here, to avoid having to link against possibly nonexistant internal julia headers when installing Profile.jl onto a binary-only distribution. But now, we can #include since we're in base. :)


extern size_t rec_backtrace(ptrint_t *bt_data, size_t maxsize);

static ptrint_t* bt_data_prof = NULL;
static size_t bt_size_max = 0;
static size_t bt_size_cur = 0;
static u_int64_t nsecprof;

//
// Timer section
//
#if defined(__WIN32__)
//Need timer implementation for windows
#else
#include <signal.h>
#if defined (__APPLE__) || defined(__FreeBSD___)
#include <sys/time.h>
struct itimerval timerprof;
int running;

// The handler function, called whenever the profiling timer elapses
static void sprofile_bt(int dummy)
{
// Get backtrace data
bt_size_cur += rec_backtrace(bt_data_prof+bt_size_cur, bt_size_max-bt_size_cur-1);
// Mark the end of this block with 0
bt_data_prof[bt_size_cur] = 0;
bt_size_cur++;
// Re-arm the timer
if (running && bt_size_cur < bt_size_max) {
timerprof.it_value.tv_usec = nsecprof/1000;
setitimer(ITIMER_REAL, &timerprof, 0);
signal(SIGALRM, sprofile_bt);
}
}

int sprofile_start_timer(void)
{
timerprof.it_interval.tv_sec = 0;
timerprof.it_interval.tv_usec = 0;
timerprof.it_value.tv_sec = 0;
timerprof.it_value.tv_usec = nsecprof/1000;
if (setitimer(ITIMER_REAL, &timerprof, 0) == -1)
return -3;

running = 1;
signal(SIGALRM, sprofile_bt);

return 0;
}

void sprofile_stop_timer(void)
{
running = 0;
}
#else
// Linux implementation. Linux can use the BSD timers, but this is
// the more careful approach.
#include <time.h>
#include <string.h> // for memset

static timer_t timerprof;
static struct itimerspec itsprof;

// The handler function, called whenever the profiling timer elapses
static void sprofile_bt(int signal, siginfo_t *si, void *uc)
{
if (si->si_value.sival_ptr == &timerprof && bt_size_cur < bt_size_max) {
// Get backtrace data
bt_size_cur += rec_backtrace(bt_data_prof+bt_size_cur, bt_size_max-bt_size_cur-1);
// Mark the end of this block with 0
bt_data_prof[bt_size_cur] = 0;
bt_size_cur++;
// Re-arm the timer
if (bt_size_cur < bt_size_max) {
itsprof.it_value.tv_nsec = nsecprof;
timer_settime(timerprof, 0, &itsprof, NULL);
}
}
}

int sprofile_start_timer(void)
{
struct sigevent sigprof;
struct sigaction sa;

// Establish the signal handler
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sprofile_bt;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGUSR1, &sa, NULL) == -1)
return -1;

// Establish the signal event
memset(&sigprof, 0, sizeof(struct sigevent));
sigprof.sigev_notify = SIGEV_SIGNAL;
sigprof.sigev_signo = SIGUSR1;
sigprof.sigev_value.sival_ptr = &timerprof;
if (timer_create(CLOCK_REALTIME, &sigprof, &timerprof) == -1)
return -2;

// Start the timer
itsprof.it_value.tv_sec = 0;
itsprof.it_interval.tv_sec = 0; // make it fire once
itsprof.it_interval.tv_nsec = 0;
itsprof.it_value.tv_nsec = nsecprof;
if (timer_settime(timerprof, 0, &itsprof, NULL) == -1)
return -3;

return 0;
}

void sprofile_stop_timer(void)
{
timer_delete(timerprof);
}
#endif
#endif

//
// Utility functions
//
int sprofile_init(size_t maxsize, u_int64_t delay_nsec)
{
bt_size_max = maxsize;
nsecprof = delay_nsec;
if (bt_data_prof != NULL)
free(bt_data_prof);
bt_data_prof = (ptrint_t*) malloc(maxsize*sizeof(ptrint_t));
if (bt_data_prof == NULL && maxsize > 0)
return -1;
return 0;
}

u_int8_t* sprofile_get_data(void)
{
return (u_int8_t*) bt_data_prof;
}

size_t sprofile_len_data(void)
{
return bt_size_cur;
}

size_t sprofile_maxlen_data(void)
{
return bt_size_max;
}

void sprofile_clear_data(void)
{
bt_size_cur = 0;
}

0 comments on commit 159203b

Please sign in to comment.