One Level Up
Top Level
runtime/kp_str.c - ktap
Functions defined
Macros defined
Source code
- #include "../include/ktap_types.h"
- #include "kp_obj.h"
- #include "kp_str.h"
- #include "kp_mempool.h"
- #include <linux/ctype.h>
- #include <linux/module.h>
- #include <linux/kallsyms.h>
- #include "ktap.h"
- #include "kp_transport.h"
- #include "kp_vm.h"
- #include "kp_events.h"
- int kp_str_cmp(const ktap_str_t *ls, const ktap_str_t *rs)
- {
- const char *l = getstr(ls);
- size_t ll = ls->len;
- const char *r = getstr(rs);
- size_t lr = rs->len;
- for (;;) {
- int temp = strcmp(l, r);
- if (temp != 0)
- return temp;
- else {
-
-
- size_t len = strlen(l);
-
- if (len == lr)
- return (len == ll) ? 0 : 1;
- else if (len == ll)
- return -1;
-
- len++;
- l += len; ll -= len; r += len; lr -= len;
- }
- }
- }
- static __always_inline int str_fastcmp(const char *a, const char *b, int len)
- {
- int i = 0;
- kp_assert(len > 0);
- kp_assert((((uintptr_t)a + len - 1)&(PAGE_SIZE - 1)) <= PAGE_SIZE - 4);
- do {
- uint32_t v = *(uint32_t *)(a + i) ^ *(const uint32_t *)(b + i);
- if (v) {
- i -= len;
- #if KP_LE
- return (int32_t)i >= -3 ? (v << (32 + (i << 3))) : 1;
- #else
- return (int32_t)i >= -3 ? (v >> (32 + (i << 3))) : 1;
- #endif
- }
- i += 4;
- } while (i < len);
- return 0;
- }
- TODO
- #define STRING_HASHLIMIT 5
- static __always_inline unsigned int kp_str_hash(const char *str, size_t len)
- {
- unsigned int h = 201236 ^ len;
- size_t step = (len >> STRING_HASHLIMIT) + 1;
- size_t l1;
- for (l1 = len; l1 >= step; l1 -= step)
- h = h ^ ((h<<5) + (h>>2) + (u8)(str[l1 - 1]));
- return h;
- }
- int kp_str_resize(ktap_state_t *ks, int newmask)
- {
- ktap_global_state_t *g = G(ks);
- ktap_str_t **newhash;
- newhash = kp_zalloc(ks, (newmask + 1) * sizeof(ktap_str_t *));
- if (!newhash)
- return -ENOMEM;
- g->strmask = newmask;
- g->strhash = newhash;
- return 0;
- }
- ktap_str_t * kp_str_new(ktap_state_t *ks, const char *str, size_t len)
- {
- ktap_global_state_t *g = G(ks);
- ktap_str_t *s;
- ktap_obj_t *o;
- unsigned int h = kp_str_hash(str, len);
- unsigned long flags;
- if (len >= KP_MAX_STR)
- return NULL;
- local_irq_save(flags);
- arch_spin_lock(&g->str_lock);
- o = (ktap_obj_t *)g->strhash[h & g->strmask];
- if (likely((((uintptr_t)str+len-1) & (PAGE_SIZE-1)) <= PAGE_SIZE-4)) {
- while (o != NULL) {
- ktap_str_t *sx = (ktap_str_t *)o;
- if (sx->len == len &&
- !str_fastcmp(str, getstr(sx), len)) {
- arch_spin_unlock(&g->str_lock);
- local_irq_restore(flags);
- return sx;
- }
- o = gch(o)->nextgc;
- }
- } else {
- while (o != NULL) {
- ktap_str_t *sx = (ktap_str_t *)o;
- if (sx->len == len &&
- !memcmp(str, getstr(sx), len)) {
- arch_spin_unlock(&g->str_lock);
- local_irq_restore(flags);
- return sx;
- }
- o = gch(o)->nextgc;
- }
- }
-
- s = kp_mempool_alloc(ks, sizeof(ktap_str_t) + len + 1);
- if (unlikely(!s))
- goto out;
- s->gct = ~KTAP_TSTR;
- s->len = len;
- s->hash = h;
- s->reserved = 0;
- memcpy(s + 1, str, len);
- ((char *)(s + 1))[len] = '\0';
-
- h &= g->strmask;
- s->nextgc = (ktap_obj_t *)g->strhash[h];
- g->strhash[h] = s;
- if (g->strnum++ > KP_MAX_STRNUM) {
- kp_error(ks, "exceed max string number %d\n", KP_MAX_STRNUM);
- s = NULL;
- }
- out:
- arch_spin_unlock(&g->str_lock);
- local_irq_restore(flags);
- return s;
- }
- void kp_str_freeall(ktap_state_t *ks)
- {
-
- kp_free(ks, G(ks)->strhash);
- }
- #define uchar(c) ((unsigned char)(c))
- #define L_ESC '%'
- #define FLAGS "-+ #0"
- #define INTFRMLEN "ll"
- #define INTFRM_T long long
- #define MAX_FORMAT (sizeof(FLAGS) + sizeof(INTFRMLEN) + 10)
- static const char *scanformat(ktap_state_t *ks, const char *strfrmt, char *form)
- {
- const char *p = strfrmt;
- while (*p != '\0' && strchr(FLAGS, *p) != NULL)
- p++;
- if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) {
- kp_error(ks, "invalid format (repeated flags)\n");
- return NULL;
- }
- if (isdigit(uchar(*p)))
- p++;
- if (isdigit(uchar(*p)))
- p++;
- if (*p == '.') {
- p++;
- if (isdigit(uchar(*p)))
- p++;
- if (isdigit(uchar(*p)))
- p++;
- }
- if (isdigit(uchar(*p))) {
- kp_error(ks, "invalid format (width or precision too long)\n");
- return NULL;
- }
- *(form++) = '%';
- memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char));
- form += p - strfrmt + 1;
- *form = '\0';
- return p;
- }
- static void addlenmod(char *form, const char *lenmod)
- {
- size_t l = strlen(form);
- size_t lm = strlen(lenmod);
- char spec = form[l - 1];
- strcpy(form + l - 1, lenmod);
- form[l + lm - 1] = spec;
- form[l + lm] = '\0';
- }
- static void arg_error(ktap_state_t *ks, int narg, const char *extramsg)
- {
- kp_error(ks, "bad argument #%d: (%s)\n", narg, extramsg);
- }
- int kp_str_fmt(ktap_state_t *ks, struct trace_seq *seq)
- {
- int arg = 1;
- size_t sfl;
- ktap_val_t *arg_fmt = kp_arg(ks, 1);
- int argnum = kp_arg_nr(ks);
- const char *strfrmt, *strfrmt_end;
- strfrmt = svalue(arg_fmt);
- sfl = rawtsvalue(arg_fmt)->len;
- strfrmt_end = strfrmt + sfl;
- while (strfrmt < strfrmt_end) {
- if (*strfrmt != L_ESC)
- trace_seq_putc(seq, *strfrmt++);
- else if (*++strfrmt == L_ESC)
- trace_seq_putc(seq, *strfrmt++);
- else {
- char form[MAX_FORMAT];
- if (++arg > argnum) {
- arg_error(ks, arg, "no value");
- return -1;
- }
- strfrmt = scanformat(ks, strfrmt, form);
- switch (*strfrmt++) {
- case 'c':
- kp_arg_checknumber(ks, arg);
- trace_seq_printf(seq, form,
- nvalue(kp_arg(ks, arg)));
- break;
- case 'd': case 'i': {
- ktap_number n;
- INTFRM_T ni;
- kp_arg_checknumber(ks, arg);
- n = nvalue(kp_arg(ks, arg));
- ni = (INTFRM_T)n;
- addlenmod(form, INTFRMLEN);
- trace_seq_printf(seq, form, ni);
- break;
- }
- case 'p': {
- char str[KSYM_SYMBOL_LEN];
- kp_arg_checknumber(ks, arg);
- SPRINT_SYMBOL(str, nvalue(kp_arg(ks, arg)));
- _trace_seq_puts(seq, str);
- break;
- }
- case 'o': case 'u': case 'x': case 'X': {
- ktap_number n;
- unsigned INTFRM_T ni;
- kp_arg_checknumber(ks, arg);
- n = nvalue(kp_arg(ks, arg));
- ni = (unsigned INTFRM_T)n;
- addlenmod(form, INTFRMLEN);
- trace_seq_printf(seq, form, ni);
- break;
- }
- case 's': {
- ktap_val_t *v = kp_arg(ks, arg);
- const char *s;
- size_t l;
- if (is_nil(v)) {
- _trace_seq_puts(seq, "nil");
- return 0;
- }
- if (is_eventstr(v)) {
- const char *str = kp_event_tostr(ks);
- if (!str)
- return -1;
- _trace_seq_puts(seq,
- kp_event_tostr(ks));
- return 0;
- }
- kp_arg_checkstring(ks, arg);
- s = svalue(v);
- l = rawtsvalue(v)->len;
- if (!strchr(form, '.') && l >= 100) {
-
- _trace_seq_puts(seq, s);
- break;
- } else {
- trace_seq_printf(seq, form, s);
- break;
- }
- }
- default:
- kp_error(ks, "invalid option " KTAP_QL("%%%c")
- " to " KTAP_QL("format"),
- *(strfrmt - 1));
- return -1;
- }
- }
- }
- return 0;
- }
One Level Up
Top Level