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