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 =