Home | History | Annotate | Download | only in el3_runtime
      1 /*
      2  * Copyright (c) 2017, 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 #define SUBSCRIBE_TO_EVENT(event, func) \
     54 	pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = func
     55 
     56 /*
     57  * Iterate over subscribed handlers for a defined event. 'event' is the name of
     58  * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'.
     59  */
     60 #define for_each_subscriber(event, subscriber) \
     61 	for (subscriber = __pubsub_start_sym(event); \
     62 			subscriber < __pubsub_end_sym(event); \
     63 			subscriber++)
     64 
     65 /*
     66  * Publish a defined event supplying an argument. All subscribed handlers are
     67  * invoked, but the return value of handlers are ignored for now.
     68  */
     69 #define PUBLISH_EVENT_ARG(event, arg) \
     70 	do { \
     71 		pubsub_cb_t *subscriber; \
     72 		for_each_subscriber(event, subscriber) { \
     73 			(*subscriber)(arg); \
     74 		} \
     75 	} while (0)
     76 
     77 /* Publish a defined event with NULL argument */
     78 #define PUBLISH_EVENT(event)	PUBLISH_EVENT_ARG(event, NULL)
     79 
     80 /* Subscriber callback type */
     81 typedef void* (*pubsub_cb_t)(const void *arg);
     82 
     83 #endif	/* __LINKER__ */
     84 #endif	/* __PUBSUB_H__ */
     85