Parent directory

synchronization_util.h

2529 bytes
 1// Copyright 2022 Stefan Kerkmann
 2// SPDX-License-Identifier: GPL-2.0-or-later
 3
 4#pragma once
 5
 6#if defined(PLATFORM_SUPPORTS_SYNCHRONIZATION)
 7#    if defined(SPLIT_KEYBOARD)
 8void split_shared_memory_lock(void);
 9void split_shared_memory_unlock(void);
10#    endif
11#else
12#    if defined(SPLIT_KEYBOARD)
13inline void split_shared_memory_lock(void){};
14inline void split_shared_memory_unlock(void){};
15#    endif
16#endif
17
18/* GCCs cleanup attribute expects a function with one parameter, which is a
19 * pointer to a type compatible with the variable. As we don't want to expose
20 * the platforms internal mutex type this workaround with auto generated adapter
21 * function is defined */
22#define QMK_DECLARE_AUTOUNLOCK_HELPERS(prefix)                              \
23    inline unsigned prefix##_autounlock_lock_helper(void) {                 \
24        prefix##_lock();                                                    \
25        return 0;                                                           \
26    }                                                                       \
27                                                                            \
28    inline void prefix##_autounlock_unlock_helper(unsigned* unused_guard) { \
29        prefix##_unlock();                                                  \
30    }
31
32/* Generate an out-of-line implementation in case the inline functions defined
33 * by the above macro don't actually get inlined. */
34#define QMK_IMPLEMENT_AUTOUNLOCK_HELPERS(prefix)                  \
35    extern inline unsigned prefix##_autounlock_lock_helper(void); \
36    extern inline void     prefix##_autounlock_unlock_helper(unsigned* unused_guard);
37
38/* Convinience macro the automatically generate the correct RAII-style
39 * lock_autounlock function macro */
40#define QMK_DECLARE_AUTOUNLOCK_CALL(prefix) unsigned prefix##_guard __attribute__((unused, cleanup(prefix##_autounlock_unlock_helper))) = prefix##_autounlock_lock_helper
41
42#if defined(SPLIT_KEYBOARD)
43QMK_DECLARE_AUTOUNLOCK_HELPERS(split_shared_memory)
44
45/**
46 * @brief Acquire exclusive access to the split keyboard shared memory, by
47 * calling the platforms `split_shared_memory_lock()` function. The lock is
48 * automatically released by calling the platforms `split_shared_memory_unlock()`
49 * function. This happens when the block where
50 * `split_shared_memory_lock_autounlock()` is called in goes out of scope i.e.
51 * when the enclosing function returns.
52 */
53#    define split_shared_memory_lock_autounlock QMK_DECLARE_AUTOUNLOCK_CALL(split_shared_memory)
54#endif