18e743bcdSJeenu Viswambharan /* 2*c2ad38ceSVarun Wadekar * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. 38e743bcdSJeenu Viswambharan * 48e743bcdSJeenu Viswambharan * SPDX-License-Identifier: BSD-3-Clause 58e743bcdSJeenu Viswambharan */ 68e743bcdSJeenu Viswambharan 7c3cf06f1SAntonio Nino Diaz #ifndef PUBSUB_H 8c3cf06f1SAntonio Nino Diaz #define PUBSUB_H 98e743bcdSJeenu Viswambharan 108e743bcdSJeenu Viswambharan #ifdef __LINKER__ 118e743bcdSJeenu Viswambharan 128e743bcdSJeenu Viswambharan /* For the linker ... */ 13*c2ad38ceSVarun Wadekar #define __pubsub_start_sym(event) __pubsub_##event##_start 14*c2ad38ceSVarun Wadekar #define __pubsub_end_sym(event) __pubsub_##event##_end 158e743bcdSJeenu Viswambharan #define __pubsub_section(event) __pubsub_##event 168e743bcdSJeenu Viswambharan 178e743bcdSJeenu Viswambharan /* 188e743bcdSJeenu Viswambharan * REGISTER_PUBSUB_EVENT has a different definition between linker and compiler 198e743bcdSJeenu Viswambharan * contexts. In linker context, this collects pubsub sections for each event, 208e743bcdSJeenu Viswambharan * placing guard symbols around each. 218e743bcdSJeenu Viswambharan */ 22*c2ad38ceSVarun Wadekar #if defined(USE_ARM_LINK) 23*c2ad38ceSVarun Wadekar #define REGISTER_PUBSUB_EVENT(event) \ 24*c2ad38ceSVarun Wadekar __pubsub_start_sym(event) +0 FIXED \ 25*c2ad38ceSVarun Wadekar { \ 26*c2ad38ceSVarun Wadekar *(__pubsub_section(event)) \ 27*c2ad38ceSVarun Wadekar } \ 28*c2ad38ceSVarun Wadekar __pubsub_end_sym(event) +0 FIXED EMPTY 0 \ 29*c2ad38ceSVarun Wadekar { \ 30*c2ad38ceSVarun Wadekar /* placeholder */ \ 31*c2ad38ceSVarun Wadekar } 32*c2ad38ceSVarun Wadekar #else 338e743bcdSJeenu Viswambharan #define REGISTER_PUBSUB_EVENT(event) \ 348e743bcdSJeenu Viswambharan __pubsub_start_sym(event) = .; \ 358e743bcdSJeenu Viswambharan KEEP(*(__pubsub_section(event))); \ 368e743bcdSJeenu Viswambharan __pubsub_end_sym(event) = . 37*c2ad38ceSVarun Wadekar #endif 388e743bcdSJeenu Viswambharan 398e743bcdSJeenu Viswambharan #else /* __LINKER__ */ 408e743bcdSJeenu Viswambharan 418e743bcdSJeenu Viswambharan /* For the compiler ... */ 428e743bcdSJeenu Viswambharan 438e743bcdSJeenu Viswambharan #include <assert.h> 448e743bcdSJeenu Viswambharan #include <cdefs.h> 458e743bcdSJeenu Viswambharan #include <stddef.h> 468e743bcdSJeenu Viswambharan 4709d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 4809d40e0eSAntonio Nino Diaz 49*c2ad38ceSVarun Wadekar #if defined(USE_ARM_LINK) 50*c2ad38ceSVarun Wadekar #define __pubsub_start_sym(event) Load$$__pubsub_##event##_start$$Base 51*c2ad38ceSVarun Wadekar #define __pubsub_end_sym(event) Load$$__pubsub_##event##_end$$Base 52*c2ad38ceSVarun Wadekar #else 53*c2ad38ceSVarun Wadekar #define __pubsub_start_sym(event) __pubsub_##event##_start 54*c2ad38ceSVarun Wadekar #define __pubsub_end_sym(event) __pubsub_##event##_end 55*c2ad38ceSVarun Wadekar #endif 56*c2ad38ceSVarun Wadekar 578e743bcdSJeenu Viswambharan #define __pubsub_section(event) __section("__pubsub_" #event) 588e743bcdSJeenu Viswambharan 598e743bcdSJeenu Viswambharan /* 608e743bcdSJeenu Viswambharan * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols 618e743bcdSJeenu Viswambharan * exported by the linker required for the other pubsub macros to work. 628e743bcdSJeenu Viswambharan */ 638e743bcdSJeenu Viswambharan #define REGISTER_PUBSUB_EVENT(event) \ 648e743bcdSJeenu Viswambharan extern pubsub_cb_t __pubsub_start_sym(event)[]; \ 658e743bcdSJeenu Viswambharan extern pubsub_cb_t __pubsub_end_sym(event)[] 668e743bcdSJeenu Viswambharan 678e743bcdSJeenu Viswambharan /* 688e743bcdSJeenu Viswambharan * Have the function func called back when the specified event happens. This 698e743bcdSJeenu Viswambharan * macro places the function address into the pubsub section, which is picked up 708e743bcdSJeenu Viswambharan * and invoked by the invoke_pubsubs() function via. the PUBLISH_EVENT* macros. 717fabe1a8SRoberto Vargas * 727fabe1a8SRoberto Vargas * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. 738e743bcdSJeenu Viswambharan */ 748e743bcdSJeenu Viswambharan #define SUBSCRIBE_TO_EVENT(event, func) \ 757fabe1a8SRoberto Vargas extern pubsub_cb_t __cb_func_##func##event __pubsub_section(event); \ 767fabe1a8SRoberto Vargas pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = (func) 778e743bcdSJeenu Viswambharan 788e743bcdSJeenu Viswambharan /* 798e743bcdSJeenu Viswambharan * Iterate over subscribed handlers for a defined event. 'event' is the name of 808e743bcdSJeenu Viswambharan * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'. 818e743bcdSJeenu Viswambharan */ 828e743bcdSJeenu Viswambharan #define for_each_subscriber(event, subscriber) \ 838e743bcdSJeenu Viswambharan for (subscriber = __pubsub_start_sym(event); \ 848e743bcdSJeenu Viswambharan subscriber < __pubsub_end_sym(event); \ 858e743bcdSJeenu Viswambharan subscriber++) 868e743bcdSJeenu Viswambharan 878e743bcdSJeenu Viswambharan /* 888e743bcdSJeenu Viswambharan * Publish a defined event supplying an argument. All subscribed handlers are 898e743bcdSJeenu Viswambharan * invoked, but the return value of handlers are ignored for now. 908e743bcdSJeenu Viswambharan */ 918e743bcdSJeenu Viswambharan #define PUBLISH_EVENT_ARG(event, arg) \ 928e743bcdSJeenu Viswambharan do { \ 938e743bcdSJeenu Viswambharan pubsub_cb_t *subscriber; \ 948e743bcdSJeenu Viswambharan for_each_subscriber(event, subscriber) { \ 958e743bcdSJeenu Viswambharan (*subscriber)(arg); \ 968e743bcdSJeenu Viswambharan } \ 978e743bcdSJeenu Viswambharan } while (0) 988e743bcdSJeenu Viswambharan 998e743bcdSJeenu Viswambharan /* Publish a defined event with NULL argument */ 1008e743bcdSJeenu Viswambharan #define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL) 1018e743bcdSJeenu Viswambharan 1028e743bcdSJeenu Viswambharan /* Subscriber callback type */ 1038e743bcdSJeenu Viswambharan typedef void* (*pubsub_cb_t)(const void *arg); 1048e743bcdSJeenu Viswambharan 1058e743bcdSJeenu Viswambharan #endif /* __LINKER__ */ 106c3cf06f1SAntonio Nino Diaz #endif /* PUBSUB_H */ 107