pubsub.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #ifndef PUBSUB_H
  7. #define PUBSUB_H
  8. #ifdef __LINKER__
  9. /* For the linker ... */
  10. #define __pubsub_start_sym(event) __pubsub_##event##_start
  11. #define __pubsub_end_sym(event) __pubsub_##event##_end
  12. #define __pubsub_section(event) .__pubsub_##event
  13. /*
  14. * REGISTER_PUBSUB_EVENT has a different definition between linker and compiler
  15. * contexts. In linker context, this collects pubsub sections for each event,
  16. * placing guard symbols around each.
  17. */
  18. #if defined(USE_ARM_LINK)
  19. #define REGISTER_PUBSUB_EVENT(event) \
  20. __pubsub_start_sym(event) +0 FIXED \
  21. { \
  22. *(__pubsub_section(event)) \
  23. } \
  24. __pubsub_end_sym(event) +0 FIXED EMPTY 0 \
  25. { \
  26. /* placeholder */ \
  27. }
  28. #else
  29. #define REGISTER_PUBSUB_EVENT(event) \
  30. __pubsub_start_sym(event) = .; \
  31. KEEP(*(__pubsub_section(event))); \
  32. __pubsub_end_sym(event) = .
  33. #endif
  34. #else /* __LINKER__ */
  35. /* For the compiler ... */
  36. #include <assert.h>
  37. #include <cdefs.h>
  38. #include <stddef.h>
  39. #include <arch_helpers.h>
  40. #if defined(USE_ARM_LINK)
  41. #define __pubsub_start_sym(event) Load$$__pubsub_##event##_start$$Base
  42. #define __pubsub_end_sym(event) Load$$__pubsub_##event##_end$$Base
  43. #else
  44. #define __pubsub_start_sym(event) __pubsub_##event##_start
  45. #define __pubsub_end_sym(event) __pubsub_##event##_end
  46. #endif
  47. #define __pubsub_section(event) __section(".__pubsub_" #event)
  48. /*
  49. * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols
  50. * exported by the linker required for the other pubsub macros to work.
  51. */
  52. #define REGISTER_PUBSUB_EVENT(event) \
  53. extern pubsub_cb_t __pubsub_start_sym(event)[]; \
  54. extern pubsub_cb_t __pubsub_end_sym(event)[]
  55. /*
  56. * Have the function func called back when the specified event happens. This
  57. * macro places the function address into the pubsub section, which is picked up
  58. * and invoked by the invoke_pubsubs() function via the PUBLISH_EVENT* macros.
  59. *
  60. * The extern declaration is there to satisfy MISRA C-2012 rule 8.4.
  61. */
  62. #define SUBSCRIBE_TO_EVENT(event, func) \
  63. extern pubsub_cb_t __cb_func_##func##event __pubsub_section(event); \
  64. pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = (func)
  65. /*
  66. * Iterate over subscribed handlers for a defined event. 'event' is the name of
  67. * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'.
  68. */
  69. #define for_each_subscriber(event, subscriber) \
  70. for (subscriber = __pubsub_start_sym(event); \
  71. subscriber < __pubsub_end_sym(event); \
  72. subscriber++)
  73. /*
  74. * Publish a defined event supplying an argument. All subscribed handlers are
  75. * invoked, but the return value of handlers are ignored for now.
  76. */
  77. #define PUBLISH_EVENT_ARG(event, arg) \
  78. do { \
  79. pubsub_cb_t *subscriber; \
  80. for_each_subscriber(event, subscriber) { \
  81. (*subscriber)(arg); \
  82. } \
  83. } while (0)
  84. /* Publish a defined event with NULL argument */
  85. #define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL)
  86. /* Subscriber callback type */
  87. typedef void* (*pubsub_cb_t)(const void *arg);
  88. #endif /* __LINKER__ */
  89. #endif /* PUBSUB_H */