perf-hooks.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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)(desc->hook_ctx);
  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, \
  39. .p_hook_func = &__perf_hook_func_##name, \
  40. .hook_ctx = NULL};
  41. #include "perf-hooks-list.h"
  42. #undef PERF_HOOK
  43. #define PERF_HOOK(name) \
  44. &__perf_hook_desc_##name,
  45. static struct perf_hook_desc *perf_hooks[] = {
  46. #include "perf-hooks-list.h"
  47. };
  48. #undef PERF_HOOK
  49. int perf_hooks__set_hook(const char *hook_name,
  50. perf_hook_func_t hook_func,
  51. void *hook_ctx)
  52. {
  53. unsigned int i;
  54. for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
  55. if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
  56. continue;
  57. if (*(perf_hooks[i]->p_hook_func))
  58. pr_warning("Overwrite existing hook: %s\n", hook_name);
  59. *(perf_hooks[i]->p_hook_func) = hook_func;
  60. perf_hooks[i]->hook_ctx = hook_ctx;
  61. return 0;
  62. }
  63. return -ENOENT;
  64. }
  65. perf_hook_func_t perf_hooks__get_hook(const char *hook_name)
  66. {
  67. unsigned int i;
  68. for (i = 0; i < ARRAY_SIZE(perf_hooks); i++) {
  69. if (strcmp(hook_name, perf_hooks[i]->hook_name) != 0)
  70. continue;
  71. return *(perf_hooks[i]->p_hook_func);
  72. }
  73. return ERR_PTR(-ENOENT);
  74. }