Reducing filter stack size to allow for lesser thread stack size

This commit is contained in:
Maria Matejka 2021-08-25 22:20:48 +02:00
parent ceef6de459
commit 2c13759136
6 changed files with 48 additions and 30 deletions

View file

@ -35,6 +35,7 @@ struct config {
u32 proto_default_debug; /* Default protocol debug mask */ u32 proto_default_debug; /* Default protocol debug mask */
u32 proto_default_mrtdump; /* Default protocol mrtdump mask */ u32 proto_default_mrtdump; /* Default protocol mrtdump mask */
u32 channel_default_debug; /* Default channel debug mask */ u32 channel_default_debug; /* Default channel debug mask */
u16 filter_vstk, filter_estk; /* Filter stack depth */
struct timeformat tf_route; /* Time format for 'show route' */ struct timeformat tf_route; /* Time format for 'show route' */
struct timeformat tf_proto; /* Time format for 'show protocol' */ struct timeformat tf_proto; /* Time format for 'show protocol' */
struct timeformat tf_log; /* Time format for the logfile */ struct timeformat tf_log; /* Time format for the logfile */

View file

@ -288,7 +288,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH, PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
EMPTY, EMPTY,
FILTER, WHERE, EVAL, ATTRIBUTE, FILTER, WHERE, EVAL, ATTRIBUTE,
BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT) BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT, STACKS)
%nonassoc THEN %nonassoc THEN
%nonassoc ELSE %nonassoc ELSE
@ -312,6 +312,12 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
CF_GRAMMAR CF_GRAMMAR
conf: FILTER STACKS expr expr ';' {
new_config->filter_vstk = $3;
new_config->filter_estk = $4;
}
;
conf: filter_def ; conf: filter_def ;
filter_def: filter_def:
FILTER symbol { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); } FILTER symbol { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); }

View file

@ -195,6 +195,7 @@ FID_INTERPRET_BODY()')
# that was needed in the former implementation. # that was needed in the former implementation.
m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_INTERPRET_BODY()') m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_INTERPRET_BODY()')
m4_define(LINEX_, `do { m4_define(LINEX_, `do {
if (fstk->ecnt + 1 >= fstk->elen) runtime("Filter execution stack overflow");
fstk->estk[fstk->ecnt].pos = 0; fstk->estk[fstk->ecnt].pos = 0;
fstk->estk[fstk->ecnt].line = $1; fstk->estk[fstk->ecnt].line = $1;
fstk->estk[fstk->ecnt].ventry = fstk->vcnt; fstk->estk[fstk->ecnt].ventry = fstk->vcnt;
@ -232,7 +233,7 @@ FID_INTERPRET_BODY()')
# state the result and put it to the right place. # state the result and put it to the right place.
m4_define(RESULT, `RESULT_TYPE([[$1]]) RESULT_([[$1]],[[$2]],[[$3]])') m4_define(RESULT, `RESULT_TYPE([[$1]]) RESULT_([[$1]],[[$2]],[[$3]])')
m4_define(RESULT_, `RESULT_VAL([[ (struct f_val) { .type = $1, .val.$2 = $3 } ]])') m4_define(RESULT_, `RESULT_VAL([[ (struct f_val) { .type = $1, .val.$2 = $3 } ]])')
m4_define(RESULT_VAL, `FID_HIC(, [[do { res = $1; fstk->vcnt++; } while (0)]], m4_define(RESULT_VAL, `FID_HIC(, [[do { res = $1; f_vcnt_check_overflow(1); fstk->vcnt++; } while (0)]],
[[return fi_constant(what, $1)]])') [[return fi_constant(what, $1)]])')
m4_define(RESULT_VOID, `RESULT_VAL([[ (struct f_val) { .type = T_VOID } ]])') m4_define(RESULT_VOID, `RESULT_VAL([[ (struct f_val) { .type = T_VOID } ]])')

View file

@ -1003,6 +1003,7 @@
curline.vbase = curline.ventry; curline.vbase = curline.ventry;
/* Storage for local variables */ /* Storage for local variables */
f_vcnt_check_overflow(sym->function->vars);
memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars); memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars);
fstk->vcnt += sym->function->vars; fstk->vcnt += sym->function->vars;
} }

View file

@ -50,30 +50,28 @@ enum f_exception {
FE_RETURN = 0x1, FE_RETURN = 0x1,
}; };
struct filter_exec_stack {
struct filter_stack { const struct f_line *line; /* The line that is being executed */
/* Value stack for execution */ uint pos; /* Instruction index in the line */
#define F_VAL_STACK_MAX 4096 uint ventry; /* Value stack depth on entry */
uint vcnt; /* Current value stack size; 0 for empty */ uint vbase; /* Where to index variable positions from */
uint ecnt; /* Current execute stack size; 0 for empty */ enum f_exception emask; /* Exception mask */
struct f_val vstk[F_VAL_STACK_MAX]; /* The stack itself */
/* Instruction stack for execution */
#define F_EXEC_STACK_MAX 4096
struct {
const struct f_line *line; /* The line that is being executed */
uint pos; /* Instruction index in the line */
uint ventry; /* Value stack depth on entry */
uint vbase; /* Where to index variable positions from */
enum f_exception emask; /* Exception mask */
} estk[F_EXEC_STACK_MAX];
}; };
/* Internal filter state, to be allocated on stack when executing filters */ /* Internal filter state, to be allocated on stack when executing filters */
struct filter_state { struct filter_state {
/* Stacks needed for execution */ /* Stacks needed for execution */
struct filter_stack *stack; struct filter_stack {
/* Current filter stack depth */
/* Value stack */
uint vcnt, vlen;
struct f_val *vstk;
/* Instruction stack for execution */
uint ecnt, elen;
struct filter_exec_stack *estk;
} stack;
/* The route we are processing. This may be NULL to indicate no route available. */ /* The route we are processing. This may be NULL to indicate no route available. */
struct rte **rte; struct rte **rte;
@ -95,10 +93,13 @@ struct filter_state {
}; };
_Thread_local static struct filter_state filter_state; _Thread_local static struct filter_state filter_state;
_Thread_local static struct filter_stack filter_stack;
void (*bt_assert_hook)(int result, const struct f_line_item *assert); void (*bt_assert_hook)(int result, const struct f_line_item *assert);
#define _f_stack_init(fs, px, def) ((fs).stack.px##stk = alloca(sizeof(*(fs).stack.px##stk) * ((fs).stack.px##len = (config && config->filter_##px##stk) ? config->filter_##px##stk : (def))))
#define f_stack_init(fs) ( _f_stack_init(fs, v, 128), _f_stack_init(fs, e, 128) )
static inline void f_cache_eattrs(struct filter_state *fs) static inline void f_cache_eattrs(struct filter_state *fs)
{ {
fs->eattrs = &((*fs->rte)->attrs->eattrs); fs->eattrs = &((*fs->rte)->attrs->eattrs);
@ -163,15 +164,17 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
ASSERT(line->args == 0); ASSERT(line->args == 0);
/* Initialize the filter stack */ /* Initialize the filter stack */
struct filter_stack *fstk = fs->stack; struct filter_stack *fstk = &fs->stack;
fstk->vcnt = line->vars; fstk->vcnt = line->vars;
memset(fstk->vstk, 0, sizeof(struct f_val) * line->vars); memset(fstk->vstk, 0, sizeof(struct f_val) * line->vars);
/* The same as with the value stack. Not resetting the stack for performance reasons. */ /* The same as with the value stack. Not resetting the stack for performance reasons. */
fstk->ecnt = 1; fstk->ecnt = 1;
fstk->estk[0].line = line; fstk->estk[0] = (struct filter_exec_stack) {
fstk->estk[0].pos = 0; .line = line,
.pos = 0,
};
#define curline fstk->estk[fstk->ecnt-1] #define curline fstk->estk[fstk->ecnt-1]
@ -191,6 +194,8 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
#define v2 vv(1) #define v2 vv(1)
#define v3 vv(2) #define v3 vv(2)
#define f_vcnt_check_overflow(n) do { if (fstk->vcnt + n >= fstk->vlen) runtime("Filter execution stack overflow"); } while (0)
#define runtime(fmt, ...) do { \ #define runtime(fmt, ...) do { \
if (!(fs->flags & FF_SILENT)) \ if (!(fs->flags & FF_SILENT)) \
log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \ log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
@ -276,12 +281,13 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i
/* Initialize the filter state */ /* Initialize the filter state */
filter_state = (struct filter_state) { filter_state = (struct filter_state) {
.stack = &filter_stack,
.rte = rte, .rte = rte,
.pool = tmp_pool, .pool = tmp_pool,
.flags = flags, .flags = flags,
}; };
f_stack_init(filter_state);
LOG_BUFFER_INIT(filter_state.buf); LOG_BUFFER_INIT(filter_state.buf);
/* Run the interpreter itself */ /* Run the interpreter itself */
@ -340,11 +346,12 @@ enum filter_return
f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool) f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool)
{ {
filter_state = (struct filter_state) { filter_state = (struct filter_state) {
.stack = &filter_stack,
.rte = rte, .rte = rte,
.pool = tmp_pool, .pool = tmp_pool,
}; };
f_stack_init(filter_state);
LOG_BUFFER_INIT(filter_state.buf); LOG_BUFFER_INIT(filter_state.buf);
ASSERT(!((*rte)->flags & REF_COW)); ASSERT(!((*rte)->flags & REF_COW));
@ -363,10 +370,11 @@ enum filter_return
f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres) f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres)
{ {
filter_state = (struct filter_state) { filter_state = (struct filter_state) {
.stack = &filter_stack,
.pool = tmp_pool, .pool = tmp_pool,
}; };
f_stack_init(filter_state);
LOG_BUFFER_INIT(filter_state.buf); LOG_BUFFER_INIT(filter_state.buf);
enum filter_return fret = interpret(&filter_state, expr, pres); enum filter_return fret = interpret(&filter_state, expr, pres);
@ -383,10 +391,11 @@ f_eval_int(const struct f_line *expr)
{ {
/* Called independently in parse-time to eval expressions */ /* Called independently in parse-time to eval expressions */
filter_state = (struct filter_state) { filter_state = (struct filter_state) {
.stack = &filter_stack,
.pool = cfg_mem, .pool = cfg_mem,
}; };
f_stack_init(filter_state);
struct f_val val; struct f_val val;
LOG_BUFFER_INIT(filter_state.buf); LOG_BUFFER_INIT(filter_state.buf);

View file

@ -240,7 +240,7 @@ bt_log_result(int result, u64 time, const char *fmt, va_list argptr)
printf("%s\n", result_str); printf("%s\n", result_str);
if (do_die && !result) if (do_die && !result)
abort(); exit(1);
} }
static u64 static u64