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