xref: /arm-trusted-firmware/include/lib/el3_runtime/pubsub.h (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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