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