pw_sync_baremetal: Add simple mutex implementation
Adds a dummy mutex implementation for baremetal configurations.
The provided implementation makes a single attempt to acquire the
lock and asserts if it is unavailable. It does not perform interrupt
masking or disable global interrupts, so this implementation does
not support simultaneous multi-threaded environments including IRQs,
and is only meant to prevent data corruption.
Change-Id: Id122f890a37822c3b752b810e0e687f19f8c9dbd
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/45721
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Prashanth Swaminathan <prashanthsw@google.com>
Reviewed-by: Ewout van Bekkum <ewout@google.com>
diff --git a/pw_sync_baremetal/BUILD b/pw_sync_baremetal/BUILD
index 69821e1..f3eeb51 100644
--- a/pw_sync_baremetal/BUILD
+++ b/pw_sync_baremetal/BUILD
@@ -46,3 +46,28 @@
"//pw_sync:yield_core",
],
)
+
+pw_cc_library(
+ name = "mutex_headers",
+ hdrs = [
+ "public/pw_sync_baremetal/mutex_inline.h",
+ "public/pw_sync_baremetal/mutex_native.h",
+ "public_overrides/pw_sync_backend/mutex_inline.h",
+ "public_overrides/pw_sync_backend/mutex_native.h",
+ ],
+ includes = [
+ "public",
+ "public_overrides",
+ ],
+ target_compatible_with = ["@platforms//os:none"],
+)
+
+pw_cc_library(
+ name = "mutex",
+ target_compatible_with = ["@platforms//os:none"],
+ deps = [
+ ":mutex_headers",
+ "//pw_assert",
+ "//pw_sync:mutex_facade",
+ ],
+)
diff --git a/pw_sync_baremetal/BUILD.gn b/pw_sync_baremetal/BUILD.gn
index 881e807..e862556 100644
--- a/pw_sync_baremetal/BUILD.gn
+++ b/pw_sync_baremetal/BUILD.gn
@@ -33,7 +33,8 @@
# asserts if it is unavailable. It does not perform interrupt masking or disable
# global interrupts, so this implementation does not support simultaneous
# multi-threaded environments including IRQs, and is only meant to prevent
-# data corruption.
+# data corruption. This implementation is not yet set up to support hardware
+# multi-threading (SMP, SMT, etc).
pw_source_set("interrupt_spin_lock") {
public_configs = [
":public_include_path",
@@ -52,6 +53,27 @@
]
}
+# This target provides the backend for pw::sync::Mutex.
+# The provided implementation makes a single attempt to acquire the lock and
+# asserts if it is unavailable. This implementation is not yet set up to support
+# hardware multi-threading (SMP, SMT, etc).
+pw_source_set("mutex") {
+ public_configs = [
+ ":public_include_path",
+ ":backend_config",
+ ]
+ public = [
+ "public/pw_sync_baremetal/mutex_inline.h",
+ "public/pw_sync_baremetal/mutex_native.h",
+ "public_overrides/pw_sync_backend/mutex_inline.h",
+ "public_overrides/pw_sync_backend/mutex_native.h",
+ ]
+ public_deps = [
+ "$dir_pw_assert",
+ "$dir_pw_sync:mutex.facade",
+ ]
+}
+
pw_doc_group("docs") {
sources = [ "docs.rst" ]
}
diff --git a/pw_sync_baremetal/docs.rst b/pw_sync_baremetal/docs.rst
index 1fbd99e..5984332 100644
--- a/pw_sync_baremetal/docs.rst
+++ b/pw_sync_baremetal/docs.rst
@@ -4,8 +4,25 @@
pw_sync_baremetal
-----------------
This is a set of backends for pw_sync that works on baremetal targets. It is not
-ready for use, and is under construction. The provided implementation makes a
-single attempt to acquire the lock and asserts if it is unavailable. It does not
-perform interrupt masking or disable global interrupts, so this implementation
-does not support simultaneous multi-threaded environments including IRQs, and is
-only meant to prevent data corruption.
+ready for use, and is under construction.
+
+.. note::
+ All constructs in this baremetal backend do not support hardware multi-threading
+ (SMP, SMT, etc).
+
+.. warning::
+ It does not perform interrupt masking or disable global interrupts. This is not
+ safe to use yet!
+
+-------------------------------------
+pw_sync_baremetal's InterruptSpinLock
+-------------------------------------
+The interrupt spin-lock implementation makes a single attempt to acquire the lock
+and asserts if it is unavailable. It does not perform interrupt masking or disable global
+interrupts.
+
+-------------------------
+pw_sync_baremetal's Mutex
+-------------------------
+The mutex implementation makes a single attempt to acquire the lock and asserts if
+it is unavailable.
diff --git a/pw_sync_baremetal/public/pw_sync_baremetal/mutex_inline.h b/pw_sync_baremetal/public/pw_sync_baremetal/mutex_inline.h
new file mode 100644
index 0000000..70a10c2
--- /dev/null
+++ b/pw_sync_baremetal/public/pw_sync_baremetal/mutex_inline.h
@@ -0,0 +1,38 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include "pw_assert/assert.h"
+#include "pw_sync/mutex.h"
+
+namespace pw::sync {
+
+inline Mutex::Mutex() : native_type_() {}
+
+inline Mutex::~Mutex() {}
+
+inline void Mutex::lock() { PW_ASSERT(try_lock()); }
+
+inline bool Mutex::try_lock() {
+ return !native_type_.test_and_set(std::memory_order_acquire);
+}
+
+inline void Mutex::unlock() {
+ PW_ASSERT(native_type_.test_and_set(std::memory_order_acquire));
+ native_type_.clear(std::memory_order_release);
+}
+
+inline Mutex::native_handle_type Mutex::native_handle() { return native_type_; }
+
+} // namespace pw::sync
diff --git a/pw_sync_baremetal/public/pw_sync_baremetal/mutex_native.h b/pw_sync_baremetal/public/pw_sync_baremetal/mutex_native.h
new file mode 100644
index 0000000..f5d6e13
--- /dev/null
+++ b/pw_sync_baremetal/public/pw_sync_baremetal/mutex_native.h
@@ -0,0 +1,23 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include <atomic>
+
+namespace pw::sync::backend {
+
+using NativeMutex = std::atomic_flag;
+using NativeMutexHandle = std::atomic_flag&;
+
+} // namespace pw::sync::backend
diff --git a/pw_sync_baremetal/public_overrides/pw_sync_backend/mutex_inline.h b/pw_sync_baremetal/public_overrides/pw_sync_backend/mutex_inline.h
new file mode 100644
index 0000000..f55dcc2
--- /dev/null
+++ b/pw_sync_baremetal/public_overrides/pw_sync_backend/mutex_inline.h
@@ -0,0 +1,16 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include "pw_sync_baremetal/mutex_inline.h"
diff --git a/pw_sync_baremetal/public_overrides/pw_sync_backend/mutex_native.h b/pw_sync_baremetal/public_overrides/pw_sync_backend/mutex_native.h
new file mode 100644
index 0000000..9d6b9e0
--- /dev/null
+++ b/pw_sync_baremetal/public_overrides/pw_sync_backend/mutex_native.h
@@ -0,0 +1,16 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include "pw_sync_baremetal/mutex_native.h"
diff --git a/targets/arduino/target_toolchains.gni b/targets/arduino/target_toolchains.gni
index cba6db8..e0b5907 100644
--- a/targets/arduino/target_toolchains.gni
+++ b/targets/arduino/target_toolchains.gni
@@ -46,6 +46,7 @@
pw_log_BACKEND = dir_pw_log_basic
pw_sync_INTERRUPT_SPIN_LOCK_BACKEND =
"$dir_pw_sync_baremetal:interrupt_spin_lock"
+ pw_sync_MUTEX_BACKEND = "$dir_pw_sync_baremetal:mutex"
pw_sys_io_BACKEND = dir_pw_sys_io_arduino
pw_rpc_system_server_BACKEND =
"$dir_pigweed/targets/arduino:system_rpc_server"
diff --git a/targets/lm3s6965evb_qemu/target_toolchains.gni b/targets/lm3s6965evb_qemu/target_toolchains.gni
index b0138af..c52deb2 100644
--- a/targets/lm3s6965evb_qemu/target_toolchains.gni
+++ b/targets/lm3s6965evb_qemu/target_toolchains.gni
@@ -42,6 +42,7 @@
pw_sys_io_BACKEND = dir_pw_sys_io_baremetal_lm3s6965evb
pw_sync_INTERRUPT_SPIN_LOCK_BACKEND =
"$dir_pw_sync_baremetal:interrupt_spin_lock"
+ pw_sync_MUTEX_BACKEND = "$dir_pw_sync_baremetal:mutex"
# pw_cpu_exception_armv7m tests do not work as expected in QEMU. It does not
# appear the divide-by-zero traps as expected when enabled, which prevents the
diff --git a/targets/stm32f429i_disc1/target_toolchains.gni b/targets/stm32f429i_disc1/target_toolchains.gni
index d20dba0..353476f 100644
--- a/targets/stm32f429i_disc1/target_toolchains.gni
+++ b/targets/stm32f429i_disc1/target_toolchains.gni
@@ -52,6 +52,7 @@
"$dir_pw_cpu_exception_cortex_m:support_armv7m"
pw_sync_INTERRUPT_SPIN_LOCK_BACKEND =
"$dir_pw_sync_baremetal:interrupt_spin_lock"
+ pw_sync_MUTEX_BACKEND = "$dir_pw_sync_baremetal:mutex"
pw_log_BACKEND = dir_pw_log_basic
pw_sys_io_BACKEND = dir_pw_sys_io_baremetal_stm32f429
pw_rpc_system_server_BACKEND =