summaryrefslogtreecommitdiff
path: root/platforms/synchronization_util.h
diff options
context:
space:
mode:
authorStefan Kerkmann <karlk90@pm.me>2022-06-21 00:24:53 +0200
committerGitHub <noreply@github.com>2022-06-21 08:24:53 +1000
commit2703ecc9e98819ab4d13bdb6da6e0d02ee840d86 (patch)
treea6ffe98a5dea71199255f23e612e469fa3bda3c0 /platforms/synchronization_util.h
parent62eaec52e0b6aadfea629e7457d1d7d8647e840c (diff)
[BUG] Fix deadlocks on disconnected secondary half (#17423)
Diffstat (limited to 'platforms/synchronization_util.h')
-rw-r--r--platforms/synchronization_util.h30
1 files changed, 30 insertions, 0 deletions
diff --git a/platforms/synchronization_util.h b/platforms/synchronization_util.h
index 3730f271db..81ce074cac 100644
--- a/platforms/synchronization_util.h
+++ b/platforms/synchronization_util.h
@@ -12,3 +12,33 @@ void split_shared_memory_unlock(void);
inline void split_shared_memory_lock(void){};
inline void split_shared_memory_unlock(void){};
#endif
+
+/* GCCs cleanup attribute expects a function with one parameter, which is a
+ * pointer to a type compatible with the variable. As we don't want to expose
+ * the platforms internal mutex type this workaround with auto generated adapter
+ * function is defined */
+#define QMK_DECLARE_AUTOUNLOCK_HELPERS(prefix) \
+ inline unsigned prefix##_autounlock_lock_helper(void) { \
+ prefix##_lock(); \
+ return 0; \
+ } \
+ \
+ inline void prefix##_autounlock_unlock_helper(unsigned* unused_guard) { \
+ prefix##_unlock(); \
+ }
+
+/* Convinience macro the automatically generate the correct RAII-style
+ * lock_autounlock function macro */
+#define QMK_DECLARE_AUTOUNLOCK_CALL(prefix) unsigned prefix##_guard __attribute__((unused, cleanup(prefix##_autounlock_unlock_helper))) = prefix##_autounlock_lock_helper
+
+QMK_DECLARE_AUTOUNLOCK_HELPERS(split_shared_memory)
+
+/**
+ * @brief Acquire exclusive access to the split keyboard shared memory, by
+ * calling the platforms `split_shared_memory_lock()` function. The lock is
+ * automatically released by calling the platforms `split_shared_memory_unlock()`
+ * function. This happens when the block where
+ * `split_shared_memory_lock_autounlock()` is called in goes out of scope i.e.
+ * when the enclosing function returns.
+ */
+#define split_shared_memory_lock_autounlock QMK_DECLARE_AUTOUNLOCK_CALL(split_shared_memory)