blob: cbd8ecc057aa166b88e93eb17c3f33dbe4093b12 [file] [log] [blame]
Jeenu Viswambharane3f22002017-09-22 08:32:10 +01001/*
Chris Kay33bfc5e2023-02-14 11:30:04 +00002 * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
Jeenu Viswambharane3f22002017-09-22 08:32:10 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Antonio Nino Diaz5eb88372018-11-08 10:20:19 +00007#ifndef PUBSUB_H
8#define PUBSUB_H
Jeenu Viswambharane3f22002017-09-22 08:32:10 +01009
Jeenu Viswambharane3f22002017-09-22 08:32:10 +010010#ifdef __LINKER__
11
12/* For the linker ... */
Varun Wadekar4d034c52019-01-11 14:47:48 -080013#define __pubsub_start_sym(event) __pubsub_##event##_start
14#define __pubsub_end_sym(event) __pubsub_##event##_end
Chris Kay33bfc5e2023-02-14 11:30:04 +000015#define __pubsub_section(event) .__pubsub_##event
Jeenu Viswambharane3f22002017-09-22 08:32:10 +010016
17/*
18 * REGISTER_PUBSUB_EVENT has a different definition between linker and compiler
19 * contexts. In linker context, this collects pubsub sections for each event,
20 * placing guard symbols around each.
21 */
Varun Wadekar4d034c52019-01-11 14:47:48 -080022#if defined(USE_ARM_LINK)
23#define REGISTER_PUBSUB_EVENT(event) \
24 __pubsub_start_sym(event) +0 FIXED \
25 { \
26 *(__pubsub_section(event)) \
27 } \
28 __pubsub_end_sym(event) +0 FIXED EMPTY 0 \
29 { \
30 /* placeholder */ \
31 }
32#else
Jeenu Viswambharane3f22002017-09-22 08:32:10 +010033#define REGISTER_PUBSUB_EVENT(event) \
34 __pubsub_start_sym(event) = .; \
35 KEEP(*(__pubsub_section(event))); \
36 __pubsub_end_sym(event) = .
Varun Wadekar4d034c52019-01-11 14:47:48 -080037#endif
Jeenu Viswambharane3f22002017-09-22 08:32:10 +010038
39#else /* __LINKER__ */
40
41/* For the compiler ... */
42
Jeenu Viswambharane3f22002017-09-22 08:32:10 +010043#include <assert.h>
44#include <cdefs.h>
45#include <stddef.h>
46
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000047#include <arch_helpers.h>
48
Varun Wadekar4d034c52019-01-11 14:47:48 -080049#if defined(USE_ARM_LINK)
50#define __pubsub_start_sym(event) Load$$__pubsub_##event##_start$$Base
51#define __pubsub_end_sym(event) Load$$__pubsub_##event##_end$$Base
52#else
53#define __pubsub_start_sym(event) __pubsub_##event##_start
54#define __pubsub_end_sym(event) __pubsub_##event##_end
55#endif
56
Chris Kay33bfc5e2023-02-14 11:30:04 +000057#define __pubsub_section(event) __section(".__pubsub_" #event)
Jeenu Viswambharane3f22002017-09-22 08:32:10 +010058
59/*
60 * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols
61 * exported by the linker required for the other pubsub macros to work.
62 */
63#define REGISTER_PUBSUB_EVENT(event) \
64 extern pubsub_cb_t __pubsub_start_sym(event)[]; \
65 extern pubsub_cb_t __pubsub_end_sym(event)[]
66
67/*
68 * Have the function func called back when the specified event happens. This
69 * macro places the function address into the pubsub section, which is picked up
Antonio Nino Diaz56b68ad2019-02-28 13:35:21 +000070 * and invoked by the invoke_pubsubs() function via the PUBLISH_EVENT* macros.
Roberto Vargas05712702018-02-12 12:36:17 +000071 *
72 * The extern declaration is there to satisfy MISRA C-2012 rule 8.4.
Jeenu Viswambharane3f22002017-09-22 08:32:10 +010073 */
74#define SUBSCRIBE_TO_EVENT(event, func) \
Roberto Vargas05712702018-02-12 12:36:17 +000075 extern pubsub_cb_t __cb_func_##func##event __pubsub_section(event); \
76 pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = (func)
Jeenu Viswambharane3f22002017-09-22 08:32:10 +010077
78/*
79 * Iterate over subscribed handlers for a defined event. 'event' is the name of
80 * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'.
81 */
82#define for_each_subscriber(event, subscriber) \
83 for (subscriber = __pubsub_start_sym(event); \
84 subscriber < __pubsub_end_sym(event); \
85 subscriber++)
86
87/*
88 * Publish a defined event supplying an argument. All subscribed handlers are
89 * invoked, but the return value of handlers are ignored for now.
90 */
91#define PUBLISH_EVENT_ARG(event, arg) \
92 do { \
93 pubsub_cb_t *subscriber; \
94 for_each_subscriber(event, subscriber) { \
95 (*subscriber)(arg); \
96 } \
97 } while (0)
98
99/* Publish a defined event with NULL argument */
100#define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL)
101
102/* Subscriber callback type */
103typedef void* (*pubsub_cb_t)(const void *arg);
104
105#endif /* __LINKER__ */
Antonio Nino Diaz5eb88372018-11-08 10:20:19 +0000106#endif /* PUBSUB_H */