Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf callchain: Refactor callchain option parsing

record_opts__parse_callchain is shared by builtin-record and
builtin-trace, it is declared in callchain.h. Move the declaration to
callchain.c for consistency with the header. In other cases make the
option callback a small static stub that then calls into callchain.c.

Make the no argument '-g' callchain option just a short-cut for
'--call-graph fp' so that there is consistency in how the arguments
are handled. This requires the const char* string to be strdup-ed in
__parse_callchain_report_opt. For consistency also make
parse_callchain_record use strdup and remove some unnecessary
casts. Also, be more explicit about the '-g' behavior if there is a
.perfconfig file setting.

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
c006753c 443556be

+104 -80
+15 -50
tools/perf/builtin-record.c
··· 2975 2975 return status; 2976 2976 } 2977 2977 2978 - static void callchain_debug(struct callchain_param *callchain) 2979 - { 2980 - static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 2981 - 2982 - pr_debug("callchain: type %s\n", str[callchain->record_mode]); 2983 - 2984 - if (callchain->record_mode == CALLCHAIN_DWARF) 2985 - pr_debug("callchain: stack dump size %d\n", 2986 - callchain->dump_size); 2987 - } 2988 - 2989 - int record_opts__parse_callchain(struct record_opts *record, 2990 - struct callchain_param *callchain, 2991 - const char *arg, bool unset) 2992 - { 2993 - int ret; 2994 - callchain->enabled = !unset; 2995 - 2996 - /* --no-call-graph */ 2997 - if (unset) { 2998 - callchain->record_mode = CALLCHAIN_NONE; 2999 - pr_debug("callchain: disabled\n"); 3000 - return 0; 3001 - } 3002 - 3003 - ret = parse_callchain_record_opt(arg, callchain); 3004 - if (!ret) { 3005 - /* Enable data address sampling for DWARF unwind. */ 3006 - if (callchain->record_mode == CALLCHAIN_DWARF && 3007 - !record->record_data_mmap_set) 3008 - record->record_data_mmap = true; 3009 - callchain_debug(callchain); 3010 - } 3011 - 3012 - return ret; 3013 - } 3014 - 3015 - int record_parse_callchain_opt(const struct option *opt, 2978 + static int record_parse_callchain_opt(const struct option *opt, 3016 2979 const char *arg, 3017 2980 int unset) 3018 2981 { 3019 2982 return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 3020 2983 } 3021 2984 3022 - int record_callchain_opt(const struct option *opt, 3023 - const char *arg __maybe_unused, 3024 - int unset __maybe_unused) 2985 + static int record_callchain_opt(const struct option *opt, 2986 + const char *arg __maybe_unused, 2987 + int unset) 3025 2988 { 3026 - struct callchain_param *callchain = opt->value; 2989 + /* 2990 + * The -g option only sets the callchain if not already configured by 2991 + * .perfconfig. It does, however, enable it. 2992 + */ 2993 + if (callchain_param.record_mode != CALLCHAIN_NONE) { 2994 + callchain_param.enabled = true; 2995 + return 0; 2996 + } 3027 2997 3028 - callchain->enabled = true; 3029 - 3030 - if (callchain->record_mode == CALLCHAIN_NONE) 3031 - callchain->record_mode = CALLCHAIN_FP; 3032 - 3033 - callchain_debug(callchain); 3034 - return 0; 2998 + return record_opts__parse_callchain(opt->value, &callchain_param, "fp", unset); 3035 2999 } 3000 + 3036 3001 3037 3002 static int perf_record_config(const char *var, const char *value, void *cb) 3038 3003 { ··· 3490 3525 OPT_CALLBACK(0, "mmap-flush", &record.opts, "number", 3491 3526 "Minimal number of bytes that is extracted from mmap data pages (default: 1)", 3492 3527 record__mmap_flush_parse), 3493 - OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 3528 + OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 3494 3529 NULL, "enables call-graph recording" , 3495 3530 &record_callchain_opt), 3496 3531 OPT_CALLBACK(0, "call-graph", &record.opts,
+18 -7
tools/perf/builtin-top.c
··· 1387 1387 } 1388 1388 1389 1389 static int 1390 - callchain_opt(const struct option *opt, const char *arg, int unset) 1391 - { 1392 - symbol_conf.use_callchain = true; 1393 - return record_callchain_opt(opt, arg, unset); 1394 - } 1395 - 1396 - static int 1397 1390 parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1398 1391 { 1399 1392 struct callchain_param *callchain = opt->value; ··· 1405 1412 1406 1413 return parse_callchain_top_opt(arg); 1407 1414 } 1415 + 1416 + static int 1417 + callchain_opt(const struct option *opt, const char *arg __maybe_unused, int unset) 1418 + { 1419 + struct callchain_param *callchain = opt->value; 1420 + 1421 + /* 1422 + * The -g option only sets the callchain if not already configured by 1423 + * .perfconfig. It does, however, enable it. 1424 + */ 1425 + if (callchain->record_mode != CALLCHAIN_NONE) { 1426 + callchain->enabled = true; 1427 + return 0; 1428 + } 1429 + 1430 + return parse_callchain_opt(opt, "fp", unset); 1431 + } 1432 + 1408 1433 1409 1434 static int perf_top_config(const char *var, const char *value, void *cb __maybe_unused) 1410 1435 {
+8 -1
tools/perf/builtin-trace.c
··· 5300 5300 return 0; 5301 5301 } 5302 5302 5303 + static int trace_parse_callchain_opt(const struct option *opt, 5304 + const char *arg, 5305 + int unset) 5306 + { 5307 + return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 5308 + } 5309 + 5303 5310 static int trace__config(const char *var, const char *value, void *arg) 5304 5311 { 5305 5312 struct trace *trace = arg; ··· 5454 5447 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"), 5455 5448 OPT_CALLBACK(0, "call-graph", &trace.opts, 5456 5449 "record_mode[,record_size]", record_callchain_help, 5457 - &record_parse_callchain_opt), 5450 + &trace_parse_callchain_opt), 5458 5451 OPT_BOOLEAN(0, "libtraceevent_print", &trace.libtraceevent_print, 5459 5452 "Use libtraceevent to print the tracepoint arguments."), 5460 5453 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
+60 -13
tools/perf/util/callchain.c
··· 30 30 #include "map.h" 31 31 #include "callchain.h" 32 32 #include "branch.h" 33 + #include "record.h" 33 34 #include "symbol.h" 34 35 #include "thread.h" 35 36 #include "util.h" ··· 171 170 static int 172 171 __parse_callchain_report_opt(const char *arg, bool allow_record_opt) 173 172 { 174 - char *tok; 173 + char *tok, *arg_copy; 175 174 char *endptr, *saveptr = NULL; 176 175 bool minpcnt_set = false; 177 176 bool record_opt_set = false; ··· 183 182 if (!arg) 184 183 return 0; 185 184 186 - while ((tok = strtok_r((char *)arg, ",", &saveptr)) != NULL) { 185 + arg_copy = strdup(arg); 186 + if (!arg_copy) 187 + return -ENOMEM; 188 + 189 + tok = strtok_r(arg_copy, ",", &saveptr); 190 + while (tok) { 187 191 if (!strncmp(tok, "none", strlen(tok))) { 188 192 callchain_param.mode = CHAIN_NONE; 189 193 callchain_param.enabled = false; 190 194 symbol_conf.use_callchain = false; 191 - return 0; 195 + goto out; 192 196 } 193 197 194 198 if (!parse_callchain_mode(tok) || ··· 220 214 unsigned long size = 0; 221 215 222 216 if (get_stack_size(tok, &size) < 0) 223 - return -1; 217 + goto err_out; 224 218 callchain_param.dump_size = size; 225 219 try_stack_size = false; 226 220 } else if (!minpcnt_set) { 227 221 /* try to get the min percent */ 228 222 callchain_param.min_percent = strtod(tok, &endptr); 229 223 if (tok == endptr) 230 - return -1; 224 + goto err_out; 231 225 minpcnt_set = true; 232 226 } else { 233 227 /* try print limit at last */ 234 228 callchain_param.print_limit = strtoul(tok, &endptr, 0); 235 229 if (tok == endptr) 236 - return -1; 230 + goto err_out; 237 231 } 238 232 next: 239 - arg = NULL; 233 + tok = strtok_r(NULL, ",", &saveptr); 240 234 } 241 235 242 236 if (callchain_register_param(&callchain_param) < 0) { 243 237 pr_err("Can't register callchain params\n"); 244 - return -1; 238 + goto err_out; 245 239 } 240 + out: 241 + free(arg_copy); 246 242 return 0; 243 + err_out: 244 + free(arg_copy); 245 + return -1; 247 246 } 248 247 249 248 int parse_callchain_report_opt(const char *arg) ··· 268 257 int ret = -1; 269 258 270 259 /* We need buffer that we know we can write to. */ 271 - buf = malloc(strlen(arg) + 1); 260 + buf = strdup(arg); 272 261 if (!buf) 273 262 return -ENOMEM; 274 263 275 - strcpy(buf, arg); 276 - 277 - tok = strtok_r((char *)buf, ",", &saveptr); 278 - name = tok ? : (char *)buf; 264 + tok = strtok_r(buf, ",", &saveptr); 265 + name = tok ? : buf; 279 266 280 267 do { 281 268 /* Framepointer style */ ··· 332 323 if (param->defer && param->record_mode != CALLCHAIN_FP) { 333 324 pr_err("callchain: deferred callchain only works with FP\n"); 334 325 return -EINVAL; 326 + } 327 + 328 + return ret; 329 + } 330 + 331 + static void callchain_debug(const struct callchain_param *callchain) 332 + { 333 + static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 334 + 335 + pr_debug("callchain: type %s\n", str[callchain->record_mode]); 336 + 337 + if (callchain->record_mode == CALLCHAIN_DWARF) 338 + pr_debug("callchain: stack dump size %d\n", 339 + callchain->dump_size); 340 + } 341 + 342 + int record_opts__parse_callchain(struct record_opts *record, 343 + struct callchain_param *callchain, 344 + const char *arg, bool unset) 345 + { 346 + int ret; 347 + 348 + callchain->enabled = !unset; 349 + 350 + /* --no-call-graph */ 351 + if (unset) { 352 + callchain->record_mode = CALLCHAIN_NONE; 353 + pr_debug("callchain: disabled\n"); 354 + return 0; 355 + } 356 + 357 + ret = parse_callchain_record_opt(arg, callchain); 358 + if (!ret) { 359 + /* Enable data address sampling for DWARF unwind. */ 360 + if (callchain->record_mode == CALLCHAIN_DWARF && 361 + !record->record_data_mmap_set) 362 + record->record_data_mmap = true; 363 + callchain_debug(callchain); 335 364 } 336 365 337 366 return ret;
+3 -9
tools/perf/util/callchain.h
··· 9 9 10 10 struct addr_location; 11 11 struct evsel; 12 + struct hist_entry; 13 + struct hists; 12 14 struct ip_callchain; 13 15 struct map; 14 16 struct perf_sample; 17 + struct record_opts; 15 18 struct thread; 16 - struct hists; 17 19 18 20 #define HELP_PAD "\t\t\t\t" 19 21 ··· 238 236 239 237 int callchain_cursor__copy(struct callchain_cursor *dst, 240 238 struct callchain_cursor *src); 241 - 242 - struct option; 243 - struct hist_entry; 244 - 245 - int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 246 - int record_callchain_opt(const struct option *opt, const char *arg, int unset); 247 - 248 - struct record_opts; 249 239 250 240 int record_opts__parse_callchain(struct record_opts *record, 251 241 struct callchain_param *callchain,