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