ktap_state *kp_newthread(ktap_state *mainthread) { ktap_state *ks; ks = kp_percpu_data(KTAP_PERCPU_DATA_STATE); ks->stack = kp_percpu_data(KTAP_PERCPU_DATA_STACK); G(ks) = G(mainthread); ks->gclist = NULL; ktap_init_state(ks); return ks; }
static int kplib_backtrace(ktap_state *ks) { struct stack_trace trace; int skip = 10, max_entries = 10; int n = kp_arg_nr(ks); ktap_btrace *bt; if (n >= 1) { kp_arg_check(ks, 1, KTAP_TYPE_NUMBER); skip = nvalue(kp_arg(ks, 1)); } if (n >= 2) { kp_arg_check(ks, 2, KTAP_TYPE_NUMBER); max_entries = nvalue(kp_arg(ks, 2)); max_entries = min(max_entries, KTAP_MAX_STACK_ENTRIES); } bt = kp_percpu_data(ks, KTAP_PERCPU_DATA_BTRACE); trace.nr_entries = 0; trace.skip = skip; trace.max_entries = max_entries; trace.entries = (unsigned long *)(bt + 1); save_stack_trace(&trace); bt->nr_entries = trace.nr_entries; set_btrace(ks->top, bt); incr_top(ks); return 1; }
void kp_event_tostring(ktap_state *ks, struct trace_seq *seq) { struct ktap_event *e = ks->current_event; struct trace_iterator *iter; struct trace_event *ev; enum print_line_t ret = TRACE_TYPE_NO_CONSUME; /* Simulate the iterator */ /* * use temp percpu buffer as trace_iterator * we cannot use same temp buffer as printf. */ iter = kp_percpu_data(KTAP_PERCPU_DATA_BUFFER2); trace_seq_init(&iter->seq); iter->ent = e->entry; ev = &(e->call->event); if (ev) ret = ev->funcs->trace(iter, 0, ev); if (ret != TRACE_TYPE_NO_CONSUME) { struct trace_seq *s = &iter->seq; int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; s->buffer[len] = '\0'; trace_seq_puts(seq, s->buffer); } }
static int ktap_lib_backtrace(ktap_state *ks) { struct stack_trace trace; ktap_btrace *bt; bt = kp_percpu_data(KTAP_PERCPU_DATA_BTRACE); trace.nr_entries = 0; trace.skip = 10; trace.max_entries = KTAP_STACK_MAX_ENTRIES; trace.entries = &bt->entries[0]; save_stack_trace(&trace); bt->nr_entries = trace.nr_entries; setbtvalue(ks->top, bt); incr_top(ks); return 1; }
/* don't engage with tstring when printf, use buffer directly */ static int ktap_lib_printf(ktap_state *ks) { struct trace_seq *seq; preempt_disable_notrace(); seq = kp_percpu_data(KTAP_PERCPU_DATA_BUFFER); trace_seq_init(seq); if (kp_strfmt(ks, seq)) return 0; seq->buffer[seq->len] = '\0'; kp_transport_write(ks, seq->buffer, seq->len + 1); preempt_enable_notrace(); return 0; }
static void ktap_concat(ktap_state *ks, int start, int end) { int i, len = 0; StkId top = ks->ci->u.l.base; ktap_string *ts; char *ptr, *buffer; for (i = start; i <= end; i++) { if (!ttisstring(top + i)) { kp_error(ks, "cannot concat non-string\n"); setnilvalue(top + start); return; } len += rawtsvalue(top + i)->tsv.len; } if (len >= KTAP_PERCPU_BUFFER_SIZE) { kp_error(ks, "Error: too long string concatenation\n"); return; } preempt_disable_notrace(); buffer = kp_percpu_data(KTAP_PERCPU_DATA_BUFFER); ptr = buffer; for (i = start; i <= end; i++) { int len = rawtsvalue(top + i)->tsv.len; strncpy(ptr, svalue(top + i), len); ptr += len; } ts = kp_tstring_newlstr(ks, buffer, len); setsvalue(top + start, ts); preempt_enable_notrace(); }