perf-hooks.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * perf_hooks.c
  4. *
  5. * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
  6. * Copyright (C) 2016 Huawei Inc.
  7. */
  8. #include <errno.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <setjmp.h>
  12. #include <linux/err.h>
  13. #include <linux/kernel.h>
  14. #include "util/debug.h"
  15. #include "util/perf-hooks.h"
  16. static sigjmp_buf jmpbuf;
  17. static const struct perf_hook_desc *current_perf_hook;
  18. void perf_hooks__invoke(const struct perf_hook_desc *desc)
  19. {
  20. if (!(desc && desc->p_hook_func && *desc->p_hook_func))
  21. return;
  22. if (sigsetjmp(jmpbuf, 1)) {
  23. pr_warning("Fatal error (SEGFAULT) in perf hook '%s'\n",
  24. desc->hook_name);
  25. *(current_perf_hook->p_hook_func) = NULL;
  26. } else {
  27. current_perf_hook = desc;
  28. (**desc->p_hook_func)(desc->hook_ctx);
  29. }
  30. current_perf_hook = NULL;
  31. }
  32. void perf_hooks__recover(void)
  33. {
  34. if (current_perf_hook)
  35. siglongjmp(jmpbuf, 1);
  36. }
  37. #define PERF_HOOK(name) \
  38. perf_hook_func_t __perf_hook_func_##name = NULL; \
  39. struct perf_hook_desc __perf_hook_desc_##name = \
  40. {.hook_name = #name, \
  41. .p_hook_func = &__perf_hook_func_##name, \
  42. .hook_ctx = NULL};
  43. #include "perf-hooks-list.h"
  44. #undef PERF_HOOK
  45. #define PERF_HOOK(name) \
  46. &__perf_hook_desc_##name,
  47. static struct perf_hook_desc *perf_hooks[] = {
  48. #include "perf-hooks-list.h"
  49. };
  50. #undef PERF_HOOK
  51. int perf_hooks__set_hook(const char *hook_name,
  52. perf_hook_func_t hook_func,
  53. void *hook_ctx)
  54. {
  55. unsigned int i;
  56. for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
  57. if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
  58. continue;
  59. if (*(perf_hooks[i]->p_hook_func))
  60. pr_warning("Overwrite existing hook: %s\n", hook_name);
  61. *(perf_hooks[i]->p_hook_func) = hook_func;
  62. perf_hooks[i]->hook_ctx = hook_ctx;
  63. return 0;
  64. }
  65. return -ENOENT;
  66. }
  67. perf_hook_func_t perf_hooks__get_hook(const char *hook_name)
  68. {
  69. unsigned int i;
  70. for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
  71. if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
  72. continue;
  73. return *(perf_hooks[i]->p_hook_func);
  74. }
  75. return ERR_PTR(-ENOENT);
  76. }