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 <assert.h> 34 #include <cdefs.h> 35 #include <stddef.h> 36 37 #include <arch_helpers.h> 38 39 #define __pubsub_section(event) __section("__pubsub_" #event) 40 41 /* 42 * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols 43 * exported by the linker required for the other pubsub macros to work. 44 */ 45 #define REGISTER_PUBSUB_EVENT(event) \ 46 extern pubsub_cb_t __pubsub_start_sym(event)[]; \ 47 extern pubsub_cb_t __pubsub_end_sym(event)[] 48 49 /* 50 * Have the function func called back when the specified event happens. This 51 * macro places the function address into the pubsub section, which is picked up 52 * and invoked by the invoke_pubsubs() function via. the PUBLISH_EVENT* macros. 53 * 54 * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. 55 */ 56 #define SUBSCRIBE_TO_EVENT(event, func) \ 57 extern pubsub_cb_t __cb_func_##func##event __pubsub_section(event); \ 58 pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = (func) 59 60 /* 61 * Iterate over subscribed handlers for a defined event. 'event' is the name of 62 * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'. 63 */ 64 #define for_each_subscriber(event, subscriber) \ 65 for (subscriber = __pubsub_start_sym(event); \ 66 subscriber < __pubsub_end_sym(event); \ 67 subscriber++) 68 69 /* 70 * Publish a defined event supplying an argument. All subscribed handlers are 71 * invoked, but the return value of handlers are ignored for now. 72 */ 73 #define PUBLISH_EVENT_ARG(event, arg) \ 74 do { \ 75 pubsub_cb_t *subscriber; \ 76 for_each_subscriber(event, subscriber) { \ 77 (*subscriber)(arg); \ 78 } \ 79 } while (0) 80 81 /* Publish a defined event with NULL argument */ 82 #define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL) 83 84 /* Subscriber callback type */ 85 typedef void* (*pubsub_cb_t)(const void *arg); 86 87 #endif /* __LINKER__ */ 88 #endif /* PUBSUB_H */ 89