STATICFNDEF void times_usec(ext_tms *curr) { int res; struct rusage usage; struct timespec elp_time; res = getrusage(RUSAGE_SELF, &usage); if (res == -1) MPROF_RTS_ERROR((VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("getrusage"), CALLFROM, errno)); curr->tms_utime = (usage.ru_utime.tv_sec * (gtm_uint64_t)1000000) + usage.ru_utime.tv_usec; curr->tms_stime = (usage.ru_stime.tv_sec * (gtm_uint64_t)1000000) + usage.ru_stime.tv_usec; /* also start recording the elapsed time */ while (TRUE) { res = clock_gettime(use_realtime_flag ? CLOCK_REALTIME : CLOCK_MONOTONIC, &elp_time); if (res == -1) { if ((EINVAL == errno) && !use_realtime_flag) { use_realtime_flag = TRUE; continue; } else MPROF_RTS_ERROR((VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("clock_gettime"), CALLFROM, errno)); } break; } curr->tms_etime = (elp_time.tv_sec * (gtm_uint64_t)1000000) + (elp_time.tv_nsec / 1000); return; }
STATICFNDEF void times_usec(ext_tms *curr) { int res; struct rusage usage; struct timespec elp_time; res = getrusage(RUSAGE_SELF, &usage); if (-1 == res) MPROF_RTS_ERROR((CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("getrusage"), CALLFROM, errno)); # ifdef __osf__ /* On Tru64 getrusage sometimes fails to increment the seconds value when the microseconds wrap around at 1M. If we detect * this, we make a second call to getrusage if so. A more complete check would be to also verify whether the new seconds * value is less than the previous one, but we anyway have an assert in UPDATE_TIME that would catch that, and our testing * on Tru64 has not shown that type of faulty behavior. */ if (((usage.ru_utime.tv_sec == last_usage.ru_utime.tv_sec) && (usage.ru_utime.tv_usec < last_usage.ru_utime.tv_usec)) || ((usage.ru_stime.tv_sec == last_usage.ru_stime.tv_sec) && (usage.ru_stime.tv_usec < last_usage.ru_stime.tv_usec))) { DEBUG_ONLY(last_usage = usage); res = getrusage(RUSAGE_SELF, &usage); if (-1 == res) MPROF_RTS_ERROR((CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("getrusage"), CALLFROM, errno)); /* In debug also ensure that a subsequent call to getrusage restored the seconds value. */ assert((usage.ru_utime.tv_sec > last_usage.ru_utime.tv_sec) || (usage.ru_stime.tv_sec > last_usage.ru_stime.tv_sec)); } last_usage = usage; # endif curr->tms_utime = (usage.ru_utime.tv_sec * (gtm_uint64_t)1000000) + usage.ru_utime.tv_usec; curr->tms_stime = (usage.ru_stime.tv_sec * (gtm_uint64_t)1000000) + usage.ru_stime.tv_usec; /* Also start recording the elapsed time. */ while (TRUE) { res = clock_gettime(use_realtime_flag ? CLOCK_REALTIME : CLOCK_MONOTONIC, &elp_time); if (res == -1) { if ((EINVAL == errno) && !use_realtime_flag) { use_realtime_flag = TRUE; continue; } else MPROF_RTS_ERROR((CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("clock_gettime"), CALLFROM, errno)); } break; } curr->tms_etime = (elp_time.tv_sec * (gtm_uint64_t)1000000) + (elp_time.tv_nsec / 1000); return; }
STATICFNDEF void get_cputime (ext_tms *curr) { int4 cpu_time_used; int status; int jpi_code = JPI$_CPUTIM; if ((status = lib$getjpi(&jpi_code, &process_id, 0, &cpu_time_used, 0, 0)) != SS$_NORMAL) MPROF_RTS_ERROR((CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("LIB$GETJPI"), CALLFROM, status)); curr->tms_utime = cpu_time_used; curr->tms_stime = 0; return; }
STATICFNDEF void child_times_usec(void) { int res; struct rusage usage; res = getrusage(RUSAGE_CHILDREN, &usage); if (res == -1) MPROF_RTS_ERROR((CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("getrusage"), CALLFROM, errno)); child_user = (usage.ru_utime.tv_sec * (gtm_uint64_t)1000000) + usage.ru_utime.tv_usec; child_system = (usage.ru_stime.tv_sec * (gtm_uint64_t)1000000) + usage.ru_stime.tv_usec; return; }
/* Enables tracing and ensures that all critical structures are initialized */ void turn_tracing_on(mval *gvn, boolean_t from_env, boolean_t save_gbl) { ext_tms curr; trace_entry tmp_trc_tbl_entry; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; mdb_ch_set = !from_env; /* if tracing is on explicitly, or if it is implicit with saving */ if (save_gbl || !from_env) { if (is_tracing_on) { gtm_putmsg(VARLSTCNT(1) ERR_TRACINGON); return; } if ((0 == gvn->str.len) || ('^' != gvn->str.addr[0])) MPROF_RTS_ERROR((VARLSTCNT(4) ERR_NOTGBL, 2, gvn->str.len, gvn->str.addr)); } /* the following should only be a one-time operation */ if (!TREF(mprof_ptr)) { TREF(mprof_ptr) = (mprof_wrapper *)malloc(SIZEOF(mprof_wrapper)); memset(TREF(mprof_ptr), 0, SIZEOF(mprof_wrapper)); } /* only need to have the gvn if we are going to save the data */ if (save_gbl && (0 < gvn->str.len)) { parse_gvn(gvn); (TREF(mprof_ptr))->gbl_to_fill = *gvn; (TREF(mprof_ptr))->gbl_to_fill.str.addr = (char *)malloc(gvn->str.len); /* len was already set up */ memcpy((TREF(mprof_ptr))->gbl_to_fill.str.addr, gvn->str.addr, gvn->str.len); } /* preallocate some space */ if (!(TREF(mprof_ptr))->pcavailbase) { (TREF(mprof_ptr))->pcavailbase = (char **)malloc(PROFCALLOC_DSBLKSIZE); *(TREF(mprof_ptr))->pcavailbase = 0; } (TREF(mprof_ptr))->pcavailptr = (TREF(mprof_ptr))->pcavailbase; (TREF(mprof_ptr))->pcavail = PROFCALLOC_DSBLKSIZE - OFFSET_LEN; memset((TREF(mprof_ptr))->pcavailptr + 1, 0, (TREF(mprof_ptr))->pcavail); curr = (TREF(mprof_ptr))->tprev; TIMES(&curr); UNIX_ONLY(child_times_usec();)