diff options
Diffstat (limited to 'src/opt.c')
-rw-r--r-- | src/opt.c | 133 |
1 files changed, 58 insertions, 75 deletions
@@ -102,39 +102,20 @@ enum pred_type { PRED_TYPES, }; -/** Get the name of a predicate type. */ -static const char *pred_type_name(enum pred_type type) { - switch (type) { - case READABLE_PRED: - return "-readable"; - case WRITABLE_PRED: - return "-writable"; - case EXECUTABLE_PRED: - return "-executable"; - case ACL_PRED: - return "-acl"; - case CAPABLE_PRED: - return "-capable"; - case EMPTY_PRED: - return "-empty"; - case HIDDEN_PRED: - return "-hidden"; - case NOGROUP_PRED: - return "-nogroup"; - case NOUSER_PRED: - return "-nouser"; - case SPARSE_PRED: - return "-sparse"; - case XATTR_PRED: - return "-xattr"; - - case PRED_TYPES: - break; - } - - bfs_bug("Unknown predicate %d", (int)type); - return "???"; -} +/** Predicate type names. */ +static const char *const pred_names[] = { + [READABLE_PRED] = "-readable", + [WRITABLE_PRED] = "-writable", + [EXECUTABLE_PRED] = "-executable", + [ACL_PRED] = "-acl", + [CAPABLE_PRED] = "-capable", + [EMPTY_PRED] = "-empty", + [HIDDEN_PRED] = "-hidden", + [NOGROUP_PRED] = "-nogroup", + [NOUSER_PRED] = "-nouser", + [SPARSE_PRED] = "-sparse", + [XATTR_PRED] = "-xattr", +}; /** * A contrained integer range. @@ -242,29 +223,15 @@ enum range_type { RANGE_TYPES, }; -/** Get the name of a range type. */ -static const char *range_type_name(enum range_type type) { - switch (type) { - case DEPTH_RANGE: - return "-depth"; - case GID_RANGE: - return "-gid"; - case INUM_RANGE: - return "-inum"; - case LINKS_RANGE: - return "-links"; - case SIZE_RANGE: - return "-size"; - case UID_RANGE: - return "-uid"; - - case RANGE_TYPES: - break; - } - - bfs_bug("Unknown range %d", (int)type); - return "???"; -} +/** Range type names. */ +static const char *const range_names[] = { + [DEPTH_RANGE] = "-depth", + [GID_RANGE] = "-gid", + [INUM_RANGE] = "-inum", + [LINKS_RANGE] = "-links", + [SIZE_RANGE] = "-size", + [UID_RANGE] = "-uid", +}; /** * The data flow analysis domain. @@ -333,27 +300,27 @@ static void df_init_top(struct df_domain *value) { /** Check for the top element. */ static bool df_is_top(const struct df_domain *value) { - for (int i = 0; i < PRED_TYPES; ++i) { - if (value->preds[i] != PRED_TOP) { - return false; - } - } + for (int i = 0; i < PRED_TYPES; ++i) { + if (value->preds[i] != PRED_TOP) { + return false; + } + } - for (int i = 0; i < RANGE_TYPES; ++i) { - if (!range_is_top(&value->ranges[i])) { - return false; - } - } + for (int i = 0; i < RANGE_TYPES; ++i) { + if (!range_is_top(&value->ranges[i])) { + return false; + } + } - if (value->types != ~0U) { - return false; - } + if (value->types != ~0U) { + return false; + } - if (value->xtypes != ~0U) { - return false; - } + if (value->xtypes != ~0U) { + return false; + } - return true; + return true; } /** Compute the union of two fact sets. */ @@ -503,7 +470,7 @@ typedef bool dump_fn(struct bfs_opt *opt, const char *format, ...); /** Print a df_pred. */ static void pred_dump(dump_fn *dump, struct bfs_opt *opt, const struct df_domain *value, enum pred_type type) { - dump(opt, "${blu}%s${rs}: ", pred_type_name(type)); + dump(opt, "${blu}%s${rs}: ", pred_names[type]); FILE *file = opt->ctx->cerr->file; switch (value->preds[type]) { @@ -524,7 +491,7 @@ static void pred_dump(dump_fn *dump, struct bfs_opt *opt, const struct df_domain /** Print a df_range. */ static void range_dump(dump_fn *dump, struct bfs_opt *opt, const struct df_domain *value, enum range_type type) { - dump(opt, "${blu}%s${rs}: ", range_type_name(type)); + dump(opt, "${blu}%s${rs}: ", range_names[type]); FILE *file = opt->ctx->cerr->file; const struct df_range *range = &value->ranges[type]; @@ -2221,6 +2188,11 @@ static float estimate_stat_odds(struct bfs_ctx *ctx) { return 1.0 - nostat_odds; } +/** Matches -(exec|ok) ... \; */ +static bool single_exec(const struct bfs_expr *expr) { + return expr->eval_fn == eval_exec && !(expr->exec->flags & BFS_EXEC_MULTI); +} + int bfs_optimize(struct bfs_ctx *ctx) { bfs_ctx_dump(ctx, DEBUG_OPT); @@ -2299,6 +2271,17 @@ int bfs_optimize(struct bfs_ctx *ctx) { opt_leave(&opt, "eager stat cost: ${ylw}%g${rs}\n", eager_cost); } +#ifndef POSIX_SPAWN_SETRLIMIT + // If bfs_spawn_setrlimit() would force us to use fork() over + // posix_spawn(), the extra cost may outweigh the benefit of a + // higher RLIMIT_NOFILE + float single_exec_odds = estimate_odds(ctx->expr, single_exec); + if (single_exec_odds >= 0.5) { + opt_enter(&opt, "single ${blu}-exec${rs} odds: ${ylw}%g${rs}\n", single_exec_odds); + ctx->raise_nofile = false; + opt_leave(&opt, "not raising RLIMIT_NOFILE\n"); + } +#endif } opt_leave(&opt, NULL); |