/* * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #ifndef __PUBSUB_H__ #define __PUBSUB_H__ #define __pubsub_start_sym(event) __pubsub_##event##_start #define __pubsub_end_sym(event) __pubsub_##event##_end #ifdef __LINKER__ /* For the linker ... */ #define __pubsub_section(event) __pubsub_##event /* * REGISTER_PUBSUB_EVENT has a different definition between linker and compiler * contexts. In linker context, this collects pubsub sections for each event, * placing guard symbols around each. */ #define REGISTER_PUBSUB_EVENT(event) \ __pubsub_start_sym(event) = .; \ KEEP(*(__pubsub_section(event))); \ __pubsub_end_sym(event) = . #else /* __LINKER__ */ /* For the compiler ... */ #include <arch_helpers.h> #include <assert.h> #include <cdefs.h> #include <stddef.h> #define __pubsub_section(event) __section("__pubsub_" #event) /* * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols * exported by the linker required for the other pubsub macros to work. */ #define REGISTER_PUBSUB_EVENT(event) \ extern pubsub_cb_t __pubsub_start_sym(event)[]; \ extern pubsub_cb_t __pubsub_end_sym(event)[] /* * Have the function func called back when the specified event happens. This * macro places the function address into the pubsub section, which is picked up * and invoked by the invoke_pubsubs() function via. the PUBLISH_EVENT* macros. */ #define SUBSCRIBE_TO_EVENT(event, func) \ pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = func /* * Iterate over subscribed handlers for a defined event. 'event' is the name of * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'. */ #define for_each_subscriber(event, subscriber) \ for (subscriber = __pubsub_start_sym(event); \ subscriber < __pubsub_end_sym(event); \ subscriber++) /* * Publish a defined event supplying an argument. All subscribed handlers are * invoked, but the return value of handlers are ignored for now. */ #define PUBLISH_EVENT_ARG(event, arg) \ do { \ pubsub_cb_t *subscriber; \ for_each_subscriber(event, subscriber) { \ (*subscriber)(arg); \ } \ } while (0) /* Publish a defined event with NULL argument */ #define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL) /* Subscriber callback type */ typedef void* (*pubsub_cb_t)(const void *arg); #endif /* __LINKER__ */ #endif /* __PUBSUB_H__ */