static void get_tname(ph_thread_t *me, char *buf, uint32_t size) { uint64_t tid; if (me) { ph_snprintf(buf, size, "%s/%d", me->name, me->tid); return; } #if defined(__linux__) tid = syscall(SYS_gettid); #elif defined(__MACH__) pthread_threadid_np(pthread_self(), &tid); #elif defined(__sun__) tid = _lwp_self(); #else tid = (uint64_t)(intptr_t)self; #endif #if defined(__linux__) || defined(__MACH__) if (pthread_getname_np(pthread_self(), buf, size) == 0) { int len = strlen(buf); if (len > 0) { ph_snprintf(buf + len, size - len, "/%" PRIu64, tid); return; } } #endif ph_snprintf(buf, size, "lwp/%" PRIu64, tid); }
static void error_set(ph_var_err_t *error, const lex_t *lex, const char *msg, ...) { va_list ap; char msg_text[PH_VAR_ERROR_TEXT_LENGTH]; char msg_with_context[PH_VAR_ERROR_TEXT_LENGTH]; int line = -1, col = -1; size_t pos = 0; const char *result = msg_text; uint32_t len; // Don't change it if it is already set if (!error || error->text[0]) { return; } va_start(ap, msg); ph_vsnprintf(msg_text, sizeof(msg_text), msg, ap); va_end(ap); line = lex->stream.line; col = lex->stream.column; pos = lex->stream.position; len = ph_string_len(&lex->saved_text); // If the first byte is NUL, just pretend it has no length, // otherwise we end up with weird error messages if (len && lex->saved_text.buf[0] == 0) { len = 0; } if (len) { if (len <= 20) { ph_snprintf(msg_with_context, sizeof(msg_with_context), "%s near '`Ps%p'", msg_text, (void*)&lex->saved_text); result = msg_with_context; } } else { if (lex->stream.state == STREAM_STATE_ERROR) { /* No context for UTF-8 decoding errors */ result = msg_text; } else { ph_snprintf(msg_with_context, sizeof(msg_with_context), "%s near end of file", msg_text); result = msg_with_context; } } error->line = line; error->column = col; error->position = pos; ph_snprintf(error->text, sizeof(error->text), "%s", result); }
// Query memory stats static void cmd_memory(ph_sock_t *sock) { ph_mem_stats_t stats[1]; ph_memtype_t base = PH_MEMTYPE_FIRST; char name[29]; ph_stm_printf(sock->stream, "%28s %9s %9s %9s %9s %9s\r\n", "WHAT", "BYTES", "OOM", "ALLOCS", "FREES", "REALLOC" ); while (1) { int n, i; n = ph_mem_stat_range(base, base + (sizeof(stats) / sizeof(stats[0])), stats); for (i = 0; i < n; i++) { ph_snprintf(name, sizeof(name), "%s/%s", stats[i].def->facility, stats[i].def->name); ph_stm_printf(sock->stream, "%28s " "%9"PRIu64" " "%9"PRIu64" " "%9"PRIu64" " "%9"PRIu64" " "%9"PRIu64" " "\r\n", name, stats[i].bytes, stats[i].oom, stats[i].allocs, stats[i].frees, stats[i].reallocs); } if ((uint32_t)n < sizeof(stats) / sizeof(stats[0])) { break; } base += n; } }
// Query all counters except for memory counters. static void cmd_counters(ph_sock_t *sock) { #define NUM_SLOTS 64 #define NUM_COUNTERS 2048 struct counter_name_val counter_data[NUM_COUNTERS]; int64_t view_slots[NUM_SLOTS]; const char *view_names[NUM_SLOTS]; ph_counter_scope_iterator_t iter; uint32_t num_slots, i; uint32_t n_counters = 0; uint32_t longest_name = 0; char name[69]; // Collect all counter data; it is returned in an undefined order. // For the sake of testing we want to order it, so we collect the data // and then sort it ph_counter_scope_iterator_init(&iter); ph_counter_scope_t *iter_scope; while ((iter_scope = ph_counter_scope_iterator_next(&iter)) != NULL) { uint32_t slen; if (strncmp(ph_counter_scope_get_name(iter_scope), "memory/", 7) == 0) { ph_counter_scope_delref(iter_scope); continue; } slen = strlen(ph_counter_scope_get_name(iter_scope)); num_slots = ph_counter_scope_get_view(iter_scope, NUM_SLOTS, view_slots, view_names); for (i = 0; i < num_slots; i++) { uint32_t l = strlen(view_names[i]); longest_name = MAX(longest_name, l + slen + 1); counter_data[n_counters].scope_name = ph_counter_scope_get_name(iter_scope); counter_data[n_counters].name = view_names[i]; counter_data[n_counters].val = view_slots[i]; n_counters++; if (n_counters >= NUM_COUNTERS) { break; } } ph_counter_scope_delref(iter_scope); if (n_counters >= NUM_COUNTERS) { break; } } qsort(counter_data, n_counters, sizeof(struct counter_name_val), compare_counter_name_val); for (i = 0; i < n_counters; i++) { ph_snprintf(name, sizeof(name), "%s/%s", counter_data[i].scope_name, counter_data[i].name); ph_stm_printf(sock->stream, "%*s %16" PRIi64"\r\n", longest_name, name, counter_data[i].val); } if (n_counters >= NUM_COUNTERS) { ph_stm_printf(sock->stream, "WARNING: too many counters to sort, output truncated\r\n"); } }