shrub/noun/trace.c

464 lines
9.3 KiB
C
Raw Normal View History

/* g/t.c -
2014-09-05 23:55:16 +04:00
**
2015-02-20 02:22:51 +03:00
** This file is in the public domain.
2014-09-05 23:55:16 +04:00
*/
#include "all.h"
2014-12-01 03:06:08 +03:00
#include <pthread.h>
2014-09-05 23:55:16 +04:00
static c3_o _ct_lop_o;
2014-11-06 03:20:01 +03:00
/* u3t_push(): push on trace stack.
2014-09-05 23:55:16 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_push(u3_noun mon)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3R->bug.tax = u3nc(mon, u3R->bug.tax);
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3t_mean(): push `[%mean roc]` on trace stack.
2014-09-05 23:55:16 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_mean(u3_noun roc)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3R->bug.tax = u3nc(u3nc(c3__mean, roc), u3R->bug.tax);
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3t_drop(): drop from meaning stack.
2014-09-05 23:55:16 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_drop(void)
2014-09-05 23:55:16 +04:00
{
2014-11-05 04:18:47 +03:00
c3_assert(_(u3du(u3R->bug.tax)));
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun tax = u3R->bug.tax;
2014-09-05 23:55:16 +04:00
2014-09-06 00:13:24 +04:00
u3R->bug.tax = u3k(u3t(tax));
u3z(tax);
2014-09-05 23:55:16 +04:00
}
}
2014-10-03 23:51:27 +04:00
extern void
u3_lo_tank(c3_l tab_l, u3_noun tac);
2014-11-06 03:20:01 +03:00
/* u3t_slog(): print directly.
2014-09-05 23:55:16 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_slog(u3_noun hod)
2014-09-05 23:55:16 +04:00
{
2015-02-20 02:22:51 +03:00
#ifdef GHETTO
static int old;
2015-02-20 02:22:51 +03:00
static struct timeval b4, f2, d0;
c3_w ms_w;
2015-02-20 02:22:51 +03:00
if ( old ) {
gettimeofday(&f2, 0);
2015-02-20 02:22:51 +03:00
timersub(&f2, &b4, &d0);
ms_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000);
if (ms_w > 10) {
printf("%6d.%02dms ", ms_w, (int) (d0.tv_usec % 1000) / 10);
gettimeofday(&b4, 0);
}
else {
printf(" ");
}
2015-02-20 02:22:51 +03:00
}
else gettimeofday(&b4, 0);
2015-02-20 02:22:51 +03:00
old = 1;
#endif
if ( (0 != u3A->roc) && (c3y == u3du(hod)) ) {
2014-10-03 23:51:27 +04:00
u3_noun pri = u3h(hod);
switch ( pri ) {
case 3: printf(">>> "); break;
case 2: printf(">> "); break;
case 1: printf("> "); break;
}
u3_lo_tank(0, u3k(u3t(hod)));
}
2014-09-06 00:13:24 +04:00
u3z(hod);
2014-09-05 23:55:16 +04:00
}
2014-09-27 04:27:35 +04:00
2014-11-06 03:20:01 +03:00
/* u3t_heck(): profile point.
2014-09-27 04:27:35 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_heck(u3_atom cog)
2014-09-27 04:27:35 +04:00
{
#if 0
u3R->pro.cel_d++;
#else
2017-12-07 03:33:24 +03:00
c3_w len_w = u3r_met(3, cog);
c3_c* str_c = alloca(1 + len_w);
u3r_bytes(0, len_w, (c3_y *)str_c, cog);
str_c[len_w] = 0;
2014-11-29 05:19:11 +03:00
// Profile sampling, because it allocates on the home road,
// only works on when we're not at home.
//
if ( &(u3H->rod_u) != u3R ) {
u3a_road* rod_u;
2016-02-23 22:45:28 +03:00
2014-11-29 05:19:11 +03:00
rod_u = u3R;
u3R = &(u3H->rod_u);
{
if ( 0 == u3R->pro.day ) {
u3R->pro.day = u3v_do("doss", 0);
}
2017-12-07 03:33:24 +03:00
u3R->pro.day = u3dc("pi-heck", u3i_string(str_c), u3R->pro.day);
2014-11-29 05:19:11 +03:00
}
u3R = rod_u;
}
#endif
2014-11-29 05:19:11 +03:00
}
#if 0
static void
_ct_sane(u3_noun lab)
{
if ( u3_nul != lab ) {
c3_assert(c3y == u3du(lab));
c3_assert(c3y == u3ud(u3h(lab)));
_ct_sane(u3t(lab));
}
}
#endif
2014-12-01 03:06:08 +03:00
#if 1
2014-11-29 05:19:11 +03:00
/* _t_samp_process(): process raw sample data from live road.
*/
static u3_noun
_t_samp_process(u3_road* rod_u)
{
u3_noun pef = u3_nul; // (list (pair path (map path ,@ud)))
u3_noun muf = u3_nul; // (map path ,@ud)
c3_w len_w = 0;
// Accumulate a label/map stack which collapses recursive segments.
//
while ( rod_u ) {
u3_noun don = rod_u->pro.don;
while ( u3_nul != don ) {
// Get surface allocated label
//
// u3_noun lab = u3nc(u3i_string("foobar"), 0);
u3_noun laj = u3h(don),
lab = u3a_take(laj);
u3a_wash(laj);
2014-11-29 05:19:11 +03:00
// Add the label to the traced label stack, trimming recursion.
//
{
u3_noun old;
if ( u3_none == (old = u3kdb_get(u3k(muf), u3k(lab))) ) {
muf = u3kdb_put(muf, u3k(lab), len_w);
pef = u3nc(u3nc(lab, u3k(muf)), pef);
len_w += 1;
}
else {
u3_assure(u3a_is_cat(old));
2014-09-27 04:27:35 +04:00
2014-11-29 05:19:11 +03:00
u3z(muf);
while ( len_w > (old + 1) ) {
u3_noun t_pef = u3k(u3t(pef));
len_w -= 1;
u3z(pef);
pef = t_pef;
}
muf = u3k(u3t(u3h(pef)));
2014-11-30 13:06:41 +03:00
u3z(lab);
2014-11-29 05:19:11 +03:00
}
}
don = u3t(don);
}
rod_u = u3tn(u3_road, rod_u->par_p);
2014-11-29 05:19:11 +03:00
}
2014-12-01 03:06:08 +03:00
u3z(muf);
2014-11-29 05:19:11 +03:00
// Lose the maps and save a pure label stack in original order.
//
{
u3_noun pal = u3_nul;
while ( u3_nul != pef ) {
u3_noun h_pef = u3h(pef);
u3_noun t_pef = u3k(u3t(pef));
pal = u3nc(u3k(u3h(h_pef)), pal);
u3z(pef);
pef = t_pef;
}
2014-11-30 13:06:41 +03:00
// fprintf(stderr, "sample: stack length %d\r\n", u3kb_lent(u3k(pal)));
2014-11-29 05:19:11 +03:00
return pal;
}
2014-09-27 04:27:35 +04:00
}
2014-12-01 03:06:08 +03:00
#endif
2014-09-27 04:27:35 +04:00
2014-11-06 03:20:01 +03:00
/* u3t_samp(): sample.
2014-09-27 04:27:35 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_samp(void)
2014-09-27 04:27:35 +04:00
{
if ( c3y == _ct_lop_o ) {
// _ct_lop_o here is a mutex for modifying pro.don. we
// do not want to sample in the middle of doing that, as
// it can cause memory errors.
return;
}
2014-12-03 03:26:30 +03:00
u3C.wag_w &= ~u3o_debug_cpu;
2015-05-15 03:39:27 +03:00
static int home = 0;
static int away = 0;
2014-11-29 05:19:11 +03:00
// Profile sampling, because it allocates on the home road,
// only works on when we're not at home.
//
if ( &(u3H->rod_u) != u3R ) {
2015-05-15 03:39:27 +03:00
home++;
2014-12-03 00:53:35 +03:00
c3_l mot_l;
2014-11-29 05:19:11 +03:00
u3a_road* rod_u;
2014-12-03 00:53:35 +03:00
if ( _(u3T.mal_o) ) {
mot_l = c3_s3('m','a','l');
}
2015-01-15 22:10:29 +03:00
else if ( _(u3T.coy_o) ) {
mot_l = c3_s3('c','o','y');
}
else if ( _(u3T.euq_o) ) {
mot_l = c3_s3('e','u','q');
}
2014-12-03 00:53:35 +03:00
else if ( _(u3T.far_o) ) {
mot_l = c3_s3('f','a','r');
}
else if ( _(u3T.noc_o) ) {
c3_assert(!_(u3T.glu_o));
mot_l = c3_s3('n','o','c');
}
else if ( _(u3T.glu_o) ) {
mot_l = c3_s3('g','l','u');
}
else {
mot_l = c3_s3('f','u','n');
}
2014-11-29 05:19:11 +03:00
rod_u = u3R;
u3R = &(u3H->rod_u);
{
u3_noun lab = _t_samp_process(rod_u);
2014-12-01 03:06:08 +03:00
2014-11-29 05:19:11 +03:00
c3_assert(u3R == &u3H->rod_u);
if ( 0 == u3R->pro.day ) {
2018-09-28 02:42:43 +03:00
/* bunt a +doss
*/
u3R->pro.day = u3nt(u3nq(0, 0, 0, u3nq(0, 0, 0, 0)), 0, 0);
2014-11-29 05:19:11 +03:00
}
2014-12-03 00:53:35 +03:00
u3R->pro.day = u3dt("pi-noon", mot_l, lab, u3R->pro.day);
2014-11-29 05:19:11 +03:00
}
u3R = rod_u;
}
2015-05-15 03:39:27 +03:00
else {
away++;
// fprintf(stderr,"home: %06d away: %06d\r\n", home, away);
}
2014-12-03 03:26:30 +03:00
u3C.wag_w |= u3o_debug_cpu;
2014-09-27 04:27:35 +04:00
}
2014-11-29 05:19:11 +03:00
/* u3t_come(): push on profile stack; return yes if active push. RETAIN.
2014-09-27 04:27:35 +04:00
*/
2014-11-29 05:19:11 +03:00
c3_o
u3t_come(u3_noun lab)
2014-09-27 04:27:35 +04:00
{
2018-03-30 21:49:18 +03:00
if ( (u3_nul == u3R->pro.don) || !_(u3r_sing(lab, u3h(u3R->pro.don))) ) {
u3a_gain(lab);
_ct_lop_o = c3y;
u3R->pro.don = u3nc(lab, u3R->pro.don);
_ct_lop_o = c3n;
2014-11-29 05:19:11 +03:00
return c3y;
}
else return c3n;
2014-09-27 04:27:35 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3t_flee(): pop off profile stack.
2014-09-27 04:27:35 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_flee(void)
2014-09-27 04:27:35 +04:00
{
_ct_lop_o = c3y;
u3_noun don = u3R->pro.don;
u3R->pro.don = u3k(u3t(don));
_ct_lop_o = c3n;
u3z(don);
2014-09-27 04:27:35 +04:00
}
extern FILE*
u3_term_io_hija(void);
extern void
u3_term_io_loja(int x);
extern void
u3_term_tape(u3_noun tep);
extern void
u3_term_wall(u3_noun wol);
/* u3t_print_steps: print step counter.
*/
void
u3t_print_steps(c3_c* cap_c, c3_d sep_d)
{
FILE* fil_f = u3_term_io_hija();
c3_w gib_w = (sep_d / 1000000000ULL);
c3_w mib_w = (sep_d % 1000000000ULL) / 1000000ULL;
c3_w kib_w = (sep_d % 1000000ULL) / 1000ULL;
c3_w bib_w = (sep_d % 1000ULL);
if ( sep_d ) {
if ( gib_w ) {
fprintf(fil_f, "%s: G/%d.%03d.%03d.%03d\r\n",
cap_c, gib_w, mib_w, kib_w, bib_w);
}
else if ( mib_w ) {
fprintf(fil_f, "%s: M/%d.%03d.%03d\r\n", cap_c, mib_w, kib_w, bib_w);
}
else if ( kib_w ) {
fprintf(fil_f, "%s: K/%d.%03d\r\n", cap_c, kib_w, bib_w);
}
else if ( bib_w ) {
fprintf(fil_f, "%s: %d\r\n", cap_c, bib_w);
}
}
u3_term_io_loja(0);
}
2014-11-06 03:20:01 +03:00
/* u3t_damp(): print and clear profile data.
2014-09-27 04:27:35 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_damp(void)
2014-09-27 04:27:35 +04:00
{
fprintf(stderr, "\r\n");
2014-09-27 22:37:04 +04:00
if ( 0 != u3R->pro.day ) {
2014-11-06 06:10:22 +03:00
u3_noun wol = u3do("pi-tell", u3R->pro.day);
u3_term_wall(wol);
2014-09-27 04:27:35 +04:00
2018-09-28 02:42:43 +03:00
/* bunt a +doss
*/
u3R->pro.day = u3nt(u3nq(0, 0, 0, u3nq(0, 0, 0, 0)), 0, 0);
2014-09-27 22:37:04 +04:00
}
u3t_print_steps("nocks", u3R->pro.nox_d);
u3t_print_steps("cells", u3R->pro.cel_d);
u3R->pro.nox_d = 0;
u3R->pro.cel_d = 0;
2014-09-27 04:27:35 +04:00
}
/* _ct_sigaction(): profile sigaction callback.
*/
2014-11-30 13:06:41 +03:00
void _ct_sigaction(c3_i x_i)
{
// fprintf(stderr, "itimer!\r\n"); abort();
u3t_samp();
}
2014-09-27 04:27:35 +04:00
2014-12-03 03:26:30 +03:00
/* u3t_init(): initialize tracing layer.
*/
void
u3t_init(void)
{
u3T.noc_o = c3n;
u3T.glu_o = c3n;
u3T.mal_o = c3n;
u3T.far_o = c3n;
2015-01-15 22:10:29 +03:00
u3T.coy_o = c3n;
u3T.euq_o = c3n;
2014-12-03 03:26:30 +03:00
}
2014-11-06 03:20:01 +03:00
/* u3t_boot(): turn sampling on.
2014-09-27 04:27:35 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_boot(void)
2014-09-27 04:27:35 +04:00
{
2014-12-03 03:26:30 +03:00
if ( u3C.wag_w & u3o_debug_cpu ) {
_ct_lop_o = c3n;
2018-11-12 23:20:32 +03:00
#if defined(U3_OS_osx) || defined(U3_OS_linux)
// Register _ct_sigaction to be called on `SIGPROF`.
2015-05-14 02:48:29 +03:00
{
2018-11-12 23:20:32 +03:00
struct sigaction sig_s = {0};
2015-05-14 02:48:29 +03:00
sig_s.sa_handler = _ct_sigaction;
sigemptyset(&(sig_s.sa_mask));
sigaction(SIGPROF, &sig_s, 0);
2018-11-12 23:20:32 +03:00
}
2015-05-14 02:48:29 +03:00
2018-11-12 23:20:32 +03:00
// Unblock `SIGPROF` for this thread (we will block it again when `u3t_boff` is called).
{
sigset_t set;
2015-05-14 02:48:29 +03:00
sigemptyset(&set);
sigaddset(&set, SIGPROF);
if ( 0 != pthread_sigmask(SIG_UNBLOCK, &set, NULL) ) {
perror("pthread_sigmask");
}
2018-11-12 23:20:32 +03:00
}
2015-05-14 02:48:29 +03:00
2018-11-12 23:20:32 +03:00
// Ask for SIGPROF to be sent every 10ms.
{
struct itimerval itm_v = {0};
2015-05-14 02:48:29 +03:00
itm_v.it_interval.tv_usec = 10000;
itm_v.it_value = itm_v.it_interval;
setitimer(ITIMER_PROF, &itm_v, 0);
}
2014-12-03 22:17:32 +03:00
#elif defined(U3_OS_bsd)
2018-11-12 23:20:32 +03:00
# error "Profiling isn't yet supported on BSD"
2014-12-03 22:17:32 +03:00
#else
# error "port: profiling"
#endif
2014-11-29 05:19:11 +03:00
}
2014-09-27 04:27:35 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3t_boff(): turn profile sampling off.
2014-09-27 04:27:35 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3t_boff(void)
2014-09-27 04:27:35 +04:00
{
2014-11-29 05:19:11 +03:00
if ( u3C.wag_w & u3o_debug_cpu ) {
2018-11-12 23:20:32 +03:00
#if defined(U3_OS_osx) || defined(U3_OS_linux)
// Mask SIGPROF signals in this thread (and this is the only
// thread that unblocked them).
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGPROF);
if ( 0 != pthread_sigmask(SIG_BLOCK, &set, NULL) ) {
perror("pthread_sigmask");
}
2014-11-30 13:06:41 +03:00
}
2014-09-27 04:27:35 +04:00
2018-11-12 23:20:32 +03:00
// Disable the SIGPROF timer.
{
struct itimerval itm_v = {0};
setitimer(ITIMER_PROF, &itm_v, 0);
}
2014-09-27 04:27:35 +04:00
2018-11-12 23:20:32 +03:00
// Ignore SIGPROF signals.
{
struct sigaction sig_s = {0};
sigemptyset(&(sig_s.sa_mask));
sig_s.sa_handler = SIG_IGN;
sigaction(SIGPROF, &sig_s, 0);
}
2014-12-03 22:17:32 +03:00
#elif defined(U3_OS_bsd)
2018-11-12 23:20:32 +03:00
# error "Profiling isn't yet supported on BSD"
2014-12-03 22:17:32 +03:00
#else
# error "port: profiling"
#endif
2014-11-29 05:19:11 +03:00
}
2014-09-27 04:27:35 +04:00
}