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