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