1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved. 2 // 3 // SPDX-License-Identifier: BSD-3-Clause 4 5 // Wait for or raise events. 6 // 7 // These macros may apply architecture-specific optimisations to improve the 8 // efficiency of inter-CPU signalling by polling shared variables. 9 // 10 // These are the default definitions, which provide adequate memory barriers 11 // but otherwise just busy-wait. This header should only be included by the 12 // architecture-specific asm/event.h, which can optionally define the 13 // asm_event_wait() macro to an operation that may sleep, and also define the 14 // other operations if necessary. 15 16 // Load a polled variable before a possible asm_event_wait(). 17 // 18 // This load must be an acquire operation on the specified variable. 19 // 20 // To be safe on platforms that sleep in asm_event_wait(), the return value of 21 // this macro _must_ be used in an expression that determines whether to 22 // call asm_event_wait(). 23 #if !defined(asm_event_load_before_wait) 24 #define asm_event_load_before_wait(p) \ 25 atomic_load_explicit(p, memory_order_acquire) 26 #endif 27 28 // As above, but for a named bitfield type. 29 // 30 // This is needed to hide pointer casts that would otherwise be unsafe on 31 // platforms where asm_event_load_before_wait() needs type-specific inline asm, 32 // such as ARMv8. 33 #if !defined(asm_event_load_bf_before_wait) 34 #define asm_event_load_bf_before_wait(name, p) asm_event_load_before_wait(p) 35 #endif 36 37 // Poll after checking the result of asm_event_load_before_wait(). 38 // 39 // Polling may place the calling CPU in a low-power halt state until the 40 // value read by asm_event_load_before_wait() is updated by either a remote CPU, 41 // or a local interrupt handler that interrupts the poll. The polled variable 42 // must be updated by either calling asm_event_store_and_wake(), or with some 43 // other store operation followed by a call to asm_event_wake_updated(). 44 // 45 // Updates performed by remote CPUs in any other way, or performed by the local 46 // CPU other than in an interrupt handler that preempts the poll, are not 47 // guaranteed to wake a sleeping poll. 48 // 49 // Polling must be safe from races; that is, asm_event_wait() must return if 50 // an update inter-thread happens after asm_event_load_before_wait(), regardless 51 // of whether the update inter-thread happens after asm_event_wait() is called. 52 // 53 // Polling is not required to sleep until the polled value is updated; 54 // it may wake early or not sleep at all. If the CPU does not support this 55 // operation and will never sleep, ASM_EVENT_WAIT_IS_NOOP is defined to be 56 // nonzero. 57 #if !defined(asm_event_wait) 58 #define ASM_EVENT_WAIT_IS_NOOP 1 59 #define asm_event_wait(p) ((void)0) 60 #else 61 #define ASM_EVENT_WAIT_IS_NOOP 0 62 #endif 63 64 // Store an event variable and wake CPUs waiting on it. 65 // 66 // This store must be a release operation on the specified variable. 67 #if !defined(asm_event_store_and_wake) 68 #define asm_event_store_and_wake(p, v) \ 69 atomic_store_explicit((p), (v), memory_order_release) 70 #endif 71 72 // Wake CPUs waiting on one or more variables that have been updated with direct 73 // atomic_*() calls rather than by calling asm_event_store_and_wake(). 74 // 75 // Any direct updates must either be release operations, or else followed by 76 // a release fence, prior to executing this operation. 77 // 78 // This may be more expensive than asm_event_store_and_wake(), especially for a 79 // single store. 80 #if !defined(asm_event_wake_updated) 81 #define asm_event_wake_updated() (void)0 82 #endif 83