perf-hooks.c 1.8 KB

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