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