Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 1 | /* |
Varun Wadekar | 4d034c5 | 2019-01-11 14:47:48 -0800 | [diff] [blame] | 2 | * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
Antonio Nino Diaz | 5eb8837 | 2018-11-08 10:20:19 +0000 | [diff] [blame] | 7 | #ifndef PUBSUB_H |
| 8 | #define PUBSUB_H |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 9 | |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 10 | #ifdef __LINKER__ |
| 11 | |
| 12 | /* For the linker ... */ |
Varun Wadekar | 4d034c5 | 2019-01-11 14:47:48 -0800 | [diff] [blame] | 13 | #define __pubsub_start_sym(event) __pubsub_##event##_start |
| 14 | #define __pubsub_end_sym(event) __pubsub_##event##_end |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 15 | #define __pubsub_section(event) __pubsub_##event |
| 16 | |
| 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 Wadekar | 4d034c5 | 2019-01-11 14:47:48 -0800 | [diff] [blame] | 22 | #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 Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 33 | #define REGISTER_PUBSUB_EVENT(event) \ |
| 34 | __pubsub_start_sym(event) = .; \ |
| 35 | KEEP(*(__pubsub_section(event))); \ |
| 36 | __pubsub_end_sym(event) = . |
Varun Wadekar | 4d034c5 | 2019-01-11 14:47:48 -0800 | [diff] [blame] | 37 | #endif |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 38 | |
| 39 | #else /* __LINKER__ */ |
| 40 | |
| 41 | /* For the compiler ... */ |
| 42 | |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 43 | #include <assert.h> |
| 44 | #include <cdefs.h> |
| 45 | #include <stddef.h> |
| 46 | |
Antonio Nino Diaz | e0f9063 | 2018-12-14 00:18:21 +0000 | [diff] [blame] | 47 | #include <arch_helpers.h> |
| 48 | |
Varun Wadekar | 4d034c5 | 2019-01-11 14:47:48 -0800 | [diff] [blame] | 49 | #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 | |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 57 | #define __pubsub_section(event) __section("__pubsub_" #event) |
| 58 | |
| 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 Diaz | 56b68ad | 2019-02-28 13:35:21 +0000 | [diff] [blame] | 70 | * and invoked by the invoke_pubsubs() function via the PUBLISH_EVENT* macros. |
Roberto Vargas | 0571270 | 2018-02-12 12:36:17 +0000 | [diff] [blame] | 71 | * |
| 72 | * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 73 | */ |
| 74 | #define SUBSCRIBE_TO_EVENT(event, func) \ |
Roberto Vargas | 0571270 | 2018-02-12 12:36:17 +0000 | [diff] [blame] | 75 | extern pubsub_cb_t __cb_func_##func##event __pubsub_section(event); \ |
| 76 | pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = (func) |
Jeenu Viswambharan | e3f2200 | 2017-09-22 08:32:10 +0100 | [diff] [blame] | 77 | |
| 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 */ |
| 103 | typedef void* (*pubsub_cb_t)(const void *arg); |
| 104 | |
| 105 | #endif /* __LINKER__ */ |
Antonio Nino Diaz | 5eb8837 | 2018-11-08 10:20:19 +0000 | [diff] [blame] | 106 | #endif /* PUBSUB_H */ |