1 /* 2 * Copyright (c) 2017, 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 #define SUBSCRIBE_TO_EVENT(event, func) \ 54 pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = func 55 56 /* 57 * Iterate over subscribed handlers for a defined event. 'event' is the name of 58 * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'. 59 */ 60 #define for_each_subscriber(event, subscriber) \ 61 for (subscriber = __pubsub_start_sym(event); \ 62 subscriber < __pubsub_end_sym(event); \ 63 subscriber++) 64 65 /* 66 * Publish a defined event supplying an argument. All subscribed handlers are 67 * invoked, but the return value of handlers are ignored for now. 68 */ 69 #define PUBLISH_EVENT_ARG(event, arg) \ 70 do { \ 71 pubsub_cb_t *subscriber; \ 72 for_each_subscriber(event, subscriber) { \ 73 (*subscriber)(arg); \ 74 } \ 75 } while (0) 76 77 /* Publish a defined event with NULL argument */ 78 #define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL) 79 80 /* Subscriber callback type */ 81 typedef void* (*pubsub_cb_t)(const void *arg); 82 83 #endif /* __LINKER__ */ 84 #endif /* __PUBSUB_H__ */ 85