18e743bcdSJeenu Viswambharan /* 2*f8d2a0e5SBoyan Karatotev * Copyright (c) 2017-2024, 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 ... */ 13c2ad38ceSVarun Wadekar #define __pubsub_start_sym(event) __pubsub_##event##_start 14c2ad38ceSVarun Wadekar #define __pubsub_end_sym(event) __pubsub_##event##_end 15da04341eSChris Kay #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 */ 22c2ad38ceSVarun Wadekar #if defined(USE_ARM_LINK) 23c2ad38ceSVarun Wadekar #define REGISTER_PUBSUB_EVENT(event) \ 24c2ad38ceSVarun Wadekar __pubsub_start_sym(event) +0 FIXED \ 25c2ad38ceSVarun Wadekar { \ 26c2ad38ceSVarun Wadekar *(__pubsub_section(event)) \ 27c2ad38ceSVarun Wadekar } \ 28c2ad38ceSVarun Wadekar __pubsub_end_sym(event) +0 FIXED EMPTY 0 \ 29c2ad38ceSVarun Wadekar { \ 30c2ad38ceSVarun Wadekar /* placeholder */ \ 31c2ad38ceSVarun Wadekar } 32c2ad38ceSVarun 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) = . 37c2ad38ceSVarun 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 49c2ad38ceSVarun Wadekar #if defined(USE_ARM_LINK) 50c2ad38ceSVarun Wadekar #define __pubsub_start_sym(event) Load$$__pubsub_##event##_start$$Base 51c2ad38ceSVarun Wadekar #define __pubsub_end_sym(event) Load$$__pubsub_##event##_end$$Base 52c2ad38ceSVarun Wadekar #else 53c2ad38ceSVarun Wadekar #define __pubsub_start_sym(event) __pubsub_##event##_start 54c2ad38ceSVarun Wadekar #define __pubsub_end_sym(event) __pubsub_##event##_end 55c2ad38ceSVarun Wadekar #endif 56c2ad38ceSVarun Wadekar 57da04341eSChris Kay #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 7073308618SAntonio Nino Diaz * 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); \ 76*f8d2a0e5SBoyan Karatotev pubsub_cb_t __cb_func_##func##event __used __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