18e743bcdSJeenu Viswambharan /* 27fabe1a8SRoberto Vargas * Copyright (c) 2017-2018, 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 #define __pubsub_start_sym(event) __pubsub_##event##_start 118e743bcdSJeenu Viswambharan #define __pubsub_end_sym(event) __pubsub_##event##_end 128e743bcdSJeenu Viswambharan 138e743bcdSJeenu Viswambharan #ifdef __LINKER__ 148e743bcdSJeenu Viswambharan 158e743bcdSJeenu Viswambharan /* For the linker ... */ 168e743bcdSJeenu Viswambharan 178e743bcdSJeenu Viswambharan #define __pubsub_section(event) __pubsub_##event 188e743bcdSJeenu Viswambharan 198e743bcdSJeenu Viswambharan /* 208e743bcdSJeenu Viswambharan * REGISTER_PUBSUB_EVENT has a different definition between linker and compiler 218e743bcdSJeenu Viswambharan * contexts. In linker context, this collects pubsub sections for each event, 228e743bcdSJeenu Viswambharan * placing guard symbols around each. 238e743bcdSJeenu Viswambharan */ 248e743bcdSJeenu Viswambharan #define REGISTER_PUBSUB_EVENT(event) \ 258e743bcdSJeenu Viswambharan __pubsub_start_sym(event) = .; \ 268e743bcdSJeenu Viswambharan KEEP(*(__pubsub_section(event))); \ 278e743bcdSJeenu Viswambharan __pubsub_end_sym(event) = . 288e743bcdSJeenu Viswambharan 298e743bcdSJeenu Viswambharan #else /* __LINKER__ */ 308e743bcdSJeenu Viswambharan 318e743bcdSJeenu Viswambharan /* For the compiler ... */ 328e743bcdSJeenu Viswambharan 338e743bcdSJeenu Viswambharan #include <assert.h> 348e743bcdSJeenu Viswambharan #include <cdefs.h> 358e743bcdSJeenu Viswambharan #include <stddef.h> 368e743bcdSJeenu Viswambharan 37*09d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 38*09d40e0eSAntonio Nino Diaz 398e743bcdSJeenu Viswambharan #define __pubsub_section(event) __section("__pubsub_" #event) 408e743bcdSJeenu Viswambharan 418e743bcdSJeenu Viswambharan /* 428e743bcdSJeenu Viswambharan * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols 438e743bcdSJeenu Viswambharan * exported by the linker required for the other pubsub macros to work. 448e743bcdSJeenu Viswambharan */ 458e743bcdSJeenu Viswambharan #define REGISTER_PUBSUB_EVENT(event) \ 468e743bcdSJeenu Viswambharan extern pubsub_cb_t __pubsub_start_sym(event)[]; \ 478e743bcdSJeenu Viswambharan extern pubsub_cb_t __pubsub_end_sym(event)[] 488e743bcdSJeenu Viswambharan 498e743bcdSJeenu Viswambharan /* 508e743bcdSJeenu Viswambharan * Have the function func called back when the specified event happens. This 518e743bcdSJeenu Viswambharan * macro places the function address into the pubsub section, which is picked up 528e743bcdSJeenu Viswambharan * and invoked by the invoke_pubsubs() function via. the PUBLISH_EVENT* macros. 537fabe1a8SRoberto Vargas * 547fabe1a8SRoberto Vargas * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. 558e743bcdSJeenu Viswambharan */ 568e743bcdSJeenu Viswambharan #define SUBSCRIBE_TO_EVENT(event, func) \ 577fabe1a8SRoberto Vargas extern pubsub_cb_t __cb_func_##func##event __pubsub_section(event); \ 587fabe1a8SRoberto Vargas pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = (func) 598e743bcdSJeenu Viswambharan 608e743bcdSJeenu Viswambharan /* 618e743bcdSJeenu Viswambharan * Iterate over subscribed handlers for a defined event. 'event' is the name of 628e743bcdSJeenu Viswambharan * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'. 638e743bcdSJeenu Viswambharan */ 648e743bcdSJeenu Viswambharan #define for_each_subscriber(event, subscriber) \ 658e743bcdSJeenu Viswambharan for (subscriber = __pubsub_start_sym(event); \ 668e743bcdSJeenu Viswambharan subscriber < __pubsub_end_sym(event); \ 678e743bcdSJeenu Viswambharan subscriber++) 688e743bcdSJeenu Viswambharan 698e743bcdSJeenu Viswambharan /* 708e743bcdSJeenu Viswambharan * Publish a defined event supplying an argument. All subscribed handlers are 718e743bcdSJeenu Viswambharan * invoked, but the return value of handlers are ignored for now. 728e743bcdSJeenu Viswambharan */ 738e743bcdSJeenu Viswambharan #define PUBLISH_EVENT_ARG(event, arg) \ 748e743bcdSJeenu Viswambharan do { \ 758e743bcdSJeenu Viswambharan pubsub_cb_t *subscriber; \ 768e743bcdSJeenu Viswambharan for_each_subscriber(event, subscriber) { \ 778e743bcdSJeenu Viswambharan (*subscriber)(arg); \ 788e743bcdSJeenu Viswambharan } \ 798e743bcdSJeenu Viswambharan } while (0) 808e743bcdSJeenu Viswambharan 818e743bcdSJeenu Viswambharan /* Publish a defined event with NULL argument */ 828e743bcdSJeenu Viswambharan #define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL) 838e743bcdSJeenu Viswambharan 848e743bcdSJeenu Viswambharan /* Subscriber callback type */ 858e743bcdSJeenu Viswambharan typedef void* (*pubsub_cb_t)(const void *arg); 868e743bcdSJeenu Viswambharan 878e743bcdSJeenu Viswambharan #endif /* __LINKER__ */ 88c3cf06f1SAntonio Nino Diaz #endif /* PUBSUB_H */ 89