1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_sync: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker======= 4*61c4878aSAndroid Build Coastguard Workerpw_sync 5*61c4878aSAndroid Build Coastguard Worker======= 6*61c4878aSAndroid Build Coastguard WorkerThe ``pw_sync`` module contains utilities for synchronizing between threads 7*61c4878aSAndroid Build Coastguard Workerand/or interrupts through signaling primitives and critical section lock 8*61c4878aSAndroid Build Coastguard Workerprimitives. 9*61c4878aSAndroid Build Coastguard Worker 10*61c4878aSAndroid Build Coastguard Worker.. Warning:: 11*61c4878aSAndroid Build Coastguard Worker 12*61c4878aSAndroid Build Coastguard Worker This module is still under construction, the API is not yet stable. 13*61c4878aSAndroid Build Coastguard Worker 14*61c4878aSAndroid Build Coastguard Worker.. Note:: 15*61c4878aSAndroid Build Coastguard Worker 16*61c4878aSAndroid Build Coastguard Worker The objects in this module do not have an Init() style public API which is 17*61c4878aSAndroid Build Coastguard Worker common in many RTOS C APIs. Instead, they rely on being able to invoke the 18*61c4878aSAndroid Build Coastguard Worker native initialization APIs for synchronization primitives during C++ 19*61c4878aSAndroid Build Coastguard Worker construction. 20*61c4878aSAndroid Build Coastguard Worker 21*61c4878aSAndroid Build Coastguard Worker In order to support global statically constructed synchronization without 22*61c4878aSAndroid Build Coastguard Worker constexpr constructors, the user and/or backend **MUST** ensure that any 23*61c4878aSAndroid Build Coastguard Worker initialization required in your environment is done prior to the creation 24*61c4878aSAndroid Build Coastguard Worker and/or initialization of the native synchronization primitives 25*61c4878aSAndroid Build Coastguard Worker (e.g. kernel initialization). 26*61c4878aSAndroid Build Coastguard Worker 27*61c4878aSAndroid Build Coastguard Worker-------------------------------- 28*61c4878aSAndroid Build Coastguard WorkerCritical Section Lock Primitives 29*61c4878aSAndroid Build Coastguard Worker-------------------------------- 30*61c4878aSAndroid Build Coastguard WorkerThe critical section lock primitives provided by this module comply with 31*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_, 32*61c4878aSAndroid Build Coastguard Worker`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_, and where 33*61c4878aSAndroid Build Coastguard Workerrelevant 34*61c4878aSAndroid Build Coastguard Worker`TimedLockable <https://en.cppreference.com/w/cpp/named_req/TimedLockable>`_ C++ 35*61c4878aSAndroid Build Coastguard Workernamed requirements. This means that they are compatible with existing helpers in 36*61c4878aSAndroid Build Coastguard Workerthe STL's ``<mutex>`` thread support library. For example `std::lock_guard 37*61c4878aSAndroid Build Coastguard Worker<https://en.cppreference.com/w/cpp/thread/lock_guard>`_ and `std::unique_lock 38*61c4878aSAndroid Build Coastguard Worker<https://en.cppreference.com/w/cpp/thread/unique_lock>`_ can be directly used. 39*61c4878aSAndroid Build Coastguard Worker 40*61c4878aSAndroid Build Coastguard WorkerMutex 41*61c4878aSAndroid Build Coastguard Worker===== 42*61c4878aSAndroid Build Coastguard WorkerThe Mutex is a synchronization primitive that can be used to protect shared data 43*61c4878aSAndroid Build Coastguard Workerfrom being simultaneously accessed by multiple threads. It offers exclusive, 44*61c4878aSAndroid Build Coastguard Workernon-recursive ownership semantics where priority inheritance is used to solve 45*61c4878aSAndroid Build Coastguard Workerthe classic priority-inversion problem. 46*61c4878aSAndroid Build Coastguard Worker 47*61c4878aSAndroid Build Coastguard WorkerThe Mutex's API is C++11 STL 48*61c4878aSAndroid Build Coastguard Worker`std::mutex <https://en.cppreference.com/w/cpp/thread/mutex>`_ like, 49*61c4878aSAndroid Build Coastguard Workermeaning it is a 50*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_ 51*61c4878aSAndroid Build Coastguard Workerand `Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_. 52*61c4878aSAndroid Build Coastguard Worker 53*61c4878aSAndroid Build Coastguard Worker.. list-table:: 54*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 55*61c4878aSAndroid Build Coastguard Worker 56*61c4878aSAndroid Build Coastguard Worker * - Supported on 57*61c4878aSAndroid Build Coastguard Worker - Backend module 58*61c4878aSAndroid Build Coastguard Worker * - FreeRTOS 59*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_freertos` 60*61c4878aSAndroid Build Coastguard Worker * - ThreadX 61*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_threadx` 62*61c4878aSAndroid Build Coastguard Worker * - embOS 63*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_embos` 64*61c4878aSAndroid Build Coastguard Worker * - STL 65*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_stl` 66*61c4878aSAndroid Build Coastguard Worker * - Baremetal 67*61c4878aSAndroid Build Coastguard Worker - Planned 68*61c4878aSAndroid Build Coastguard Worker * - Zephyr 69*61c4878aSAndroid Build Coastguard Worker - Planned 70*61c4878aSAndroid Build Coastguard Worker * - CMSIS-RTOS API v2 & RTX5 71*61c4878aSAndroid Build Coastguard Worker - Planned 72*61c4878aSAndroid Build Coastguard Worker 73*61c4878aSAndroid Build Coastguard WorkerC++ 74*61c4878aSAndroid Build Coastguard Worker--- 75*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::Mutex 76*61c4878aSAndroid Build Coastguard Worker :members: 77*61c4878aSAndroid Build Coastguard Worker 78*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::Mutex 79*61c4878aSAndroid Build Coastguard Worker 80*61c4878aSAndroid Build Coastguard Worker.. list-table:: 81*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 82*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 83*61c4878aSAndroid Build Coastguard Worker 84*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 85*61c4878aSAndroid Build Coastguard Worker - Thread 86*61c4878aSAndroid Build Coastguard Worker - Interrupt 87*61c4878aSAndroid Build Coastguard Worker - NMI 88*61c4878aSAndroid Build Coastguard Worker * - :cpp:class:`pw::sync::Mutex::Mutex` 89*61c4878aSAndroid Build Coastguard Worker - ✔ 90*61c4878aSAndroid Build Coastguard Worker - 91*61c4878aSAndroid Build Coastguard Worker - 92*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::Mutex::~Mutex` 93*61c4878aSAndroid Build Coastguard Worker - ✔ 94*61c4878aSAndroid Build Coastguard Worker - 95*61c4878aSAndroid Build Coastguard Worker - 96*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`lock` 97*61c4878aSAndroid Build Coastguard Worker - ✔ 98*61c4878aSAndroid Build Coastguard Worker - 99*61c4878aSAndroid Build Coastguard Worker - 100*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_lock` 101*61c4878aSAndroid Build Coastguard Worker - ✔ 102*61c4878aSAndroid Build Coastguard Worker - 103*61c4878aSAndroid Build Coastguard Worker - 104*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`unlock` 105*61c4878aSAndroid Build Coastguard Worker - ✔ 106*61c4878aSAndroid Build Coastguard Worker - 107*61c4878aSAndroid Build Coastguard Worker - 108*61c4878aSAndroid Build Coastguard Worker 109*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 110*61c4878aSAndroid Build Coastguard Worker 111*61c4878aSAndroid Build Coastguard Worker 112*61c4878aSAndroid Build Coastguard WorkerExamples in C++ 113*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^ 114*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 115*61c4878aSAndroid Build Coastguard Worker 116*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/mutex.h" 117*61c4878aSAndroid Build Coastguard Worker 118*61c4878aSAndroid Build Coastguard Worker pw::sync::Mutex mutex; 119*61c4878aSAndroid Build Coastguard Worker 120*61c4878aSAndroid Build Coastguard Worker void ThreadSafeCriticalSection() { 121*61c4878aSAndroid Build Coastguard Worker mutex.lock(); 122*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 123*61c4878aSAndroid Build Coastguard Worker mutex.unlock(); 124*61c4878aSAndroid Build Coastguard Worker } 125*61c4878aSAndroid Build Coastguard Worker 126*61c4878aSAndroid Build Coastguard Worker 127*61c4878aSAndroid Build Coastguard WorkerAlternatively you can use C++'s RAII helpers to ensure you always unlock. 128*61c4878aSAndroid Build Coastguard Worker 129*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 130*61c4878aSAndroid Build Coastguard Worker 131*61c4878aSAndroid Build Coastguard Worker #include <mutex> 132*61c4878aSAndroid Build Coastguard Worker 133*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/mutex.h" 134*61c4878aSAndroid Build Coastguard Worker 135*61c4878aSAndroid Build Coastguard Worker pw::sync::Mutex mutex; 136*61c4878aSAndroid Build Coastguard Worker 137*61c4878aSAndroid Build Coastguard Worker void ThreadSafeCriticalSection() { 138*61c4878aSAndroid Build Coastguard Worker std::lock_guard lock(mutex); 139*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 140*61c4878aSAndroid Build Coastguard Worker } 141*61c4878aSAndroid Build Coastguard Worker 142*61c4878aSAndroid Build Coastguard WorkerC 143*61c4878aSAndroid Build Coastguard Worker- 144*61c4878aSAndroid Build Coastguard WorkerThe Mutex must be created in C++, however it can be passed into C using the 145*61c4878aSAndroid Build Coastguard Worker``pw_sync_Mutex`` opaque struct alias. 146*61c4878aSAndroid Build Coastguard Worker 147*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_Mutex_Lock 148*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_Mutex_TryLock 149*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_Mutex_Unlock 150*61c4878aSAndroid Build Coastguard Worker 151*61c4878aSAndroid Build Coastguard Worker.. list-table:: 152*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 153*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 154*61c4878aSAndroid Build Coastguard Worker 155*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 156*61c4878aSAndroid Build Coastguard Worker - Thread 157*61c4878aSAndroid Build Coastguard Worker - Interrupt 158*61c4878aSAndroid Build Coastguard Worker - NMI 159*61c4878aSAndroid Build Coastguard Worker * - ``void pw_sync_Mutex_Lock`` 160*61c4878aSAndroid Build Coastguard Worker - ✔ 161*61c4878aSAndroid Build Coastguard Worker - 162*61c4878aSAndroid Build Coastguard Worker - 163*61c4878aSAndroid Build Coastguard Worker * - ``bool pw_sync_Mutex_TryLock`` 164*61c4878aSAndroid Build Coastguard Worker - ✔ 165*61c4878aSAndroid Build Coastguard Worker - 166*61c4878aSAndroid Build Coastguard Worker - 167*61c4878aSAndroid Build Coastguard Worker * - ``void pw_sync_Mutex_Unlock`` 168*61c4878aSAndroid Build Coastguard Worker - ✔ 169*61c4878aSAndroid Build Coastguard Worker - 170*61c4878aSAndroid Build Coastguard Worker - 171*61c4878aSAndroid Build Coastguard Worker 172*61c4878aSAndroid Build Coastguard WorkerExample in C 173*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^ 174*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 175*61c4878aSAndroid Build Coastguard Worker 176*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/mutex.h" 177*61c4878aSAndroid Build Coastguard Worker 178*61c4878aSAndroid Build Coastguard Worker pw::sync::Mutex mutex; 179*61c4878aSAndroid Build Coastguard Worker 180*61c4878aSAndroid Build Coastguard Worker extern pw_sync_Mutex mutex; // This can only be created in C++. 181*61c4878aSAndroid Build Coastguard Worker 182*61c4878aSAndroid Build Coastguard Worker void ThreadSafeCriticalSection(void) { 183*61c4878aSAndroid Build Coastguard Worker pw_sync_Mutex_Lock(&mutex); 184*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 185*61c4878aSAndroid Build Coastguard Worker pw_sync_Mutex_Unlock(&mutex); 186*61c4878aSAndroid Build Coastguard Worker } 187*61c4878aSAndroid Build Coastguard Worker 188*61c4878aSAndroid Build Coastguard WorkerTimedMutex 189*61c4878aSAndroid Build Coastguard Worker========== 190*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync 191*61c4878aSAndroid Build Coastguard Worker 192*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`TimedMutex` is an extension of the Mutex which offers timeout 193*61c4878aSAndroid Build Coastguard Workerand deadline based semantics. 194*61c4878aSAndroid Build Coastguard Worker 195*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`TimedMutex`'s API is C++11 STL 196*61c4878aSAndroid Build Coastguard Worker`std::timed_mutex <https://en.cppreference.com/w/cpp/thread/timed_mutex>`_ like, 197*61c4878aSAndroid Build Coastguard Workermeaning it is a 198*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_, 199*61c4878aSAndroid Build Coastguard Worker`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_, and 200*61c4878aSAndroid Build Coastguard Worker`TimedLockable <https://en.cppreference.com/w/cpp/named_req/TimedLockable>`_. 201*61c4878aSAndroid Build Coastguard Worker 202*61c4878aSAndroid Build Coastguard WorkerNote that the :cpp:class:`TimedMutex` is a derived :cpp:class:`Mutex` class, 203*61c4878aSAndroid Build Coastguard Workermeaning that a :cpp:class:`TimedMutex` can be used by someone who needs the 204*61c4878aSAndroid Build Coastguard Workerbasic :cpp:class:`Mutex`. This is in contrast to the C++ STL's 205*61c4878aSAndroid Build Coastguard Worker`std::timed_mutex <https://en.cppreference.com/w/cpp/thread/timed_mutex>`_. 206*61c4878aSAndroid Build Coastguard Worker 207*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 208*61c4878aSAndroid Build Coastguard Worker 209*61c4878aSAndroid Build Coastguard Worker.. list-table:: 210*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 211*61c4878aSAndroid Build Coastguard Worker 212*61c4878aSAndroid Build Coastguard Worker * - Supported on 213*61c4878aSAndroid Build Coastguard Worker - Backend module 214*61c4878aSAndroid Build Coastguard Worker * - FreeRTOS 215*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_freertos` 216*61c4878aSAndroid Build Coastguard Worker * - ThreadX 217*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_threadx` 218*61c4878aSAndroid Build Coastguard Worker * - embOS 219*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_embos` 220*61c4878aSAndroid Build Coastguard Worker * - STL 221*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_stl` 222*61c4878aSAndroid Build Coastguard Worker * - Zephyr 223*61c4878aSAndroid Build Coastguard Worker - Planned 224*61c4878aSAndroid Build Coastguard Worker * - CMSIS-RTOS API v2 & RTX5 225*61c4878aSAndroid Build Coastguard Worker - Planned 226*61c4878aSAndroid Build Coastguard Worker 227*61c4878aSAndroid Build Coastguard WorkerC++ 228*61c4878aSAndroid Build Coastguard Worker--- 229*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::TimedMutex 230*61c4878aSAndroid Build Coastguard Worker :members: 231*61c4878aSAndroid Build Coastguard Worker 232*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::TimedMutex 233*61c4878aSAndroid Build Coastguard Worker 234*61c4878aSAndroid Build Coastguard Worker.. list-table:: 235*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 236*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 237*61c4878aSAndroid Build Coastguard Worker 238*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 239*61c4878aSAndroid Build Coastguard Worker - Thread 240*61c4878aSAndroid Build Coastguard Worker - Interrupt 241*61c4878aSAndroid Build Coastguard Worker - NMI 242*61c4878aSAndroid Build Coastguard Worker * - :cpp:class:`pw::sync::TimedMutex::TimedMutex` 243*61c4878aSAndroid Build Coastguard Worker - ✔ 244*61c4878aSAndroid Build Coastguard Worker - 245*61c4878aSAndroid Build Coastguard Worker - 246*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::TimedMutex::~TimedMutex` 247*61c4878aSAndroid Build Coastguard Worker - ✔ 248*61c4878aSAndroid Build Coastguard Worker - 249*61c4878aSAndroid Build Coastguard Worker - 250*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::Mutex::lock` 251*61c4878aSAndroid Build Coastguard Worker - ✔ 252*61c4878aSAndroid Build Coastguard Worker - 253*61c4878aSAndroid Build Coastguard Worker - 254*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::Mutex::try_lock` 255*61c4878aSAndroid Build Coastguard Worker - ✔ 256*61c4878aSAndroid Build Coastguard Worker - 257*61c4878aSAndroid Build Coastguard Worker - 258*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_lock_for` 259*61c4878aSAndroid Build Coastguard Worker - ✔ 260*61c4878aSAndroid Build Coastguard Worker - 261*61c4878aSAndroid Build Coastguard Worker - 262*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_lock_until` 263*61c4878aSAndroid Build Coastguard Worker - ✔ 264*61c4878aSAndroid Build Coastguard Worker - 265*61c4878aSAndroid Build Coastguard Worker - 266*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::Mutex::unlock` 267*61c4878aSAndroid Build Coastguard Worker - ✔ 268*61c4878aSAndroid Build Coastguard Worker - 269*61c4878aSAndroid Build Coastguard Worker - 270*61c4878aSAndroid Build Coastguard Worker 271*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 272*61c4878aSAndroid Build Coastguard Worker 273*61c4878aSAndroid Build Coastguard Worker 274*61c4878aSAndroid Build Coastguard WorkerExamples in C++ 275*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^ 276*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 277*61c4878aSAndroid Build Coastguard Worker 278*61c4878aSAndroid Build Coastguard Worker #include "pw_chrono/system_clock.h" 279*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/timed_mutex.h" 280*61c4878aSAndroid Build Coastguard Worker 281*61c4878aSAndroid Build Coastguard Worker pw::sync::TimedMutex mutex; 282*61c4878aSAndroid Build Coastguard Worker 283*61c4878aSAndroid Build Coastguard Worker bool ThreadSafeCriticalSectionWithTimeout( 284*61c4878aSAndroid Build Coastguard Worker const SystemClock::duration timeout) { 285*61c4878aSAndroid Build Coastguard Worker if (!mutex.try_lock_for(timeout)) { 286*61c4878aSAndroid Build Coastguard Worker return false; 287*61c4878aSAndroid Build Coastguard Worker } 288*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 289*61c4878aSAndroid Build Coastguard Worker mutex.unlock(); 290*61c4878aSAndroid Build Coastguard Worker return true; 291*61c4878aSAndroid Build Coastguard Worker } 292*61c4878aSAndroid Build Coastguard Worker 293*61c4878aSAndroid Build Coastguard WorkerAlternatively you can use C++'s RAII helpers to ensure you always unlock. 294*61c4878aSAndroid Build Coastguard Worker 295*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 296*61c4878aSAndroid Build Coastguard Worker 297*61c4878aSAndroid Build Coastguard Worker #include <mutex> 298*61c4878aSAndroid Build Coastguard Worker 299*61c4878aSAndroid Build Coastguard Worker #include "pw_chrono/system_clock.h" 300*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/timed_mutex.h" 301*61c4878aSAndroid Build Coastguard Worker 302*61c4878aSAndroid Build Coastguard Worker pw::sync::TimedMutex mutex; 303*61c4878aSAndroid Build Coastguard Worker 304*61c4878aSAndroid Build Coastguard Worker bool ThreadSafeCriticalSectionWithTimeout( 305*61c4878aSAndroid Build Coastguard Worker const SystemClock::duration timeout) { 306*61c4878aSAndroid Build Coastguard Worker std::unique_lock lock(mutex, std::defer_lock); 307*61c4878aSAndroid Build Coastguard Worker if (!lock.try_lock_for(timeout)) { 308*61c4878aSAndroid Build Coastguard Worker return false; 309*61c4878aSAndroid Build Coastguard Worker } 310*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 311*61c4878aSAndroid Build Coastguard Worker return true; 312*61c4878aSAndroid Build Coastguard Worker } 313*61c4878aSAndroid Build Coastguard Worker 314*61c4878aSAndroid Build Coastguard WorkerC 315*61c4878aSAndroid Build Coastguard Worker- 316*61c4878aSAndroid Build Coastguard WorkerThe TimedMutex must be created in C++, however it can be passed into C using the 317*61c4878aSAndroid Build Coastguard Worker``pw_sync_TimedMutex`` opaque struct alias. 318*61c4878aSAndroid Build Coastguard Worker 319*61c4878aSAndroid Build Coastguard Worker.. doxygenfile:: timed_mutex.h 320*61c4878aSAndroid Build Coastguard Worker :sections: func 321*61c4878aSAndroid Build Coastguard Worker 322*61c4878aSAndroid Build Coastguard Worker.. list-table:: 323*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 324*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 325*61c4878aSAndroid Build Coastguard Worker 326*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 327*61c4878aSAndroid Build Coastguard Worker - Thread 328*61c4878aSAndroid Build Coastguard Worker - Interrupt 329*61c4878aSAndroid Build Coastguard Worker - NMI 330*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw_sync_TimedMutex_Lock` 331*61c4878aSAndroid Build Coastguard Worker - ✔ 332*61c4878aSAndroid Build Coastguard Worker - 333*61c4878aSAndroid Build Coastguard Worker - 334*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw_sync_TimedMutex_TryLock` 335*61c4878aSAndroid Build Coastguard Worker - ✔ 336*61c4878aSAndroid Build Coastguard Worker - 337*61c4878aSAndroid Build Coastguard Worker - 338*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw_sync_TimedMutex_TryLockFor` 339*61c4878aSAndroid Build Coastguard Worker - ✔ 340*61c4878aSAndroid Build Coastguard Worker - 341*61c4878aSAndroid Build Coastguard Worker - 342*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw_sync_TimedMutex_TryLockUntil` 343*61c4878aSAndroid Build Coastguard Worker - ✔ 344*61c4878aSAndroid Build Coastguard Worker - 345*61c4878aSAndroid Build Coastguard Worker - 346*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw_sync_TimedMutex_Unlock` 347*61c4878aSAndroid Build Coastguard Worker - ✔ 348*61c4878aSAndroid Build Coastguard Worker - 349*61c4878aSAndroid Build Coastguard Worker - 350*61c4878aSAndroid Build Coastguard Worker 351*61c4878aSAndroid Build Coastguard WorkerExample in C 352*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^ 353*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 354*61c4878aSAndroid Build Coastguard Worker 355*61c4878aSAndroid Build Coastguard Worker #include "pw_chrono/system_clock.h" 356*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/timed_mutex.h" 357*61c4878aSAndroid Build Coastguard Worker 358*61c4878aSAndroid Build Coastguard Worker pw::sync::TimedMutex mutex; 359*61c4878aSAndroid Build Coastguard Worker 360*61c4878aSAndroid Build Coastguard Worker extern pw_sync_TimedMutex mutex; // This can only be created in C++. 361*61c4878aSAndroid Build Coastguard Worker 362*61c4878aSAndroid Build Coastguard Worker bool ThreadSafeCriticalSectionWithTimeout( 363*61c4878aSAndroid Build Coastguard Worker const pw_chrono_SystemClock_Duration timeout) { 364*61c4878aSAndroid Build Coastguard Worker if (!pw_sync_TimedMutex_TryLockFor(&mutex, timeout)) { 365*61c4878aSAndroid Build Coastguard Worker return false; 366*61c4878aSAndroid Build Coastguard Worker } 367*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 368*61c4878aSAndroid Build Coastguard Worker pw_sync_TimedMutex_Unlock(&mutex); 369*61c4878aSAndroid Build Coastguard Worker return true; 370*61c4878aSAndroid Build Coastguard Worker } 371*61c4878aSAndroid Build Coastguard Worker 372*61c4878aSAndroid Build Coastguard WorkerRecursiveMutex 373*61c4878aSAndroid Build Coastguard Worker============== 374*61c4878aSAndroid Build Coastguard Worker``pw_sync`` provides ``pw::sync::RecursiveMutex``, a recursive mutex 375*61c4878aSAndroid Build Coastguard Workerimplementation. At this time, this facade can only be used internally by 376*61c4878aSAndroid Build Coastguard WorkerPigweed. 377*61c4878aSAndroid Build Coastguard Worker 378*61c4878aSAndroid Build Coastguard WorkerInterruptSpinLock 379*61c4878aSAndroid Build Coastguard Worker================= 380*61c4878aSAndroid Build Coastguard WorkerThe InterruptSpinLock is a synchronization primitive that can be used to protect 381*61c4878aSAndroid Build Coastguard Workershared data from being simultaneously accessed by multiple threads and/or 382*61c4878aSAndroid Build Coastguard Workerinterrupts as a targeted global lock, with the exception of Non-Maskable 383*61c4878aSAndroid Build Coastguard WorkerInterrupts (NMIs). It offers exclusive, non-recursive ownership semantics where 384*61c4878aSAndroid Build Coastguard WorkerIRQs up to a backend defined level of "NMIs" will be masked to solve 385*61c4878aSAndroid Build Coastguard Workerpriority-inversion. 386*61c4878aSAndroid Build Coastguard Worker 387*61c4878aSAndroid Build Coastguard WorkerThis InterruptSpinLock relies on built-in local interrupt masking to make it 388*61c4878aSAndroid Build Coastguard Workerinterrupt safe without requiring the caller to separately mask and unmask 389*61c4878aSAndroid Build Coastguard Workerinterrupts when using this primitive. 390*61c4878aSAndroid Build Coastguard Worker 391*61c4878aSAndroid Build Coastguard WorkerUnlike global interrupt locks, this also works safely and efficiently on SMP 392*61c4878aSAndroid Build Coastguard Workersystems. On systems which are not SMP, spinning is not required but some state 393*61c4878aSAndroid Build Coastguard Workermay still be used to detect recursion. 394*61c4878aSAndroid Build Coastguard Worker 395*61c4878aSAndroid Build Coastguard WorkerThe InterruptSpinLock is a 396*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_ 397*61c4878aSAndroid Build Coastguard Workerand 398*61c4878aSAndroid Build Coastguard Worker`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_. 399*61c4878aSAndroid Build Coastguard Worker 400*61c4878aSAndroid Build Coastguard Worker.. list-table:: 401*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 402*61c4878aSAndroid Build Coastguard Worker 403*61c4878aSAndroid Build Coastguard Worker * - Supported on 404*61c4878aSAndroid Build Coastguard Worker - Backend module 405*61c4878aSAndroid Build Coastguard Worker * - FreeRTOS 406*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_freertos` 407*61c4878aSAndroid Build Coastguard Worker * - ThreadX 408*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_threadx` 409*61c4878aSAndroid Build Coastguard Worker * - embOS 410*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_embos` 411*61c4878aSAndroid Build Coastguard Worker * - STL 412*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_stl` 413*61c4878aSAndroid Build Coastguard Worker * - Baremetal 414*61c4878aSAndroid Build Coastguard Worker - Planned, not ready for use 415*61c4878aSAndroid Build Coastguard Worker * - Zephyr 416*61c4878aSAndroid Build Coastguard Worker - Planned 417*61c4878aSAndroid Build Coastguard Worker * - CMSIS-RTOS API v2 & RTX5 418*61c4878aSAndroid Build Coastguard Worker - Planned 419*61c4878aSAndroid Build Coastguard Worker 420*61c4878aSAndroid Build Coastguard WorkerC++ 421*61c4878aSAndroid Build Coastguard Worker--- 422*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::InterruptSpinLock 423*61c4878aSAndroid Build Coastguard Worker :members: 424*61c4878aSAndroid Build Coastguard Worker 425*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::InterruptSpinLock 426*61c4878aSAndroid Build Coastguard Worker 427*61c4878aSAndroid Build Coastguard Worker.. list-table:: 428*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 429*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 430*61c4878aSAndroid Build Coastguard Worker 431*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 432*61c4878aSAndroid Build Coastguard Worker - Thread 433*61c4878aSAndroid Build Coastguard Worker - Interrupt 434*61c4878aSAndroid Build Coastguard Worker - NMI 435*61c4878aSAndroid Build Coastguard Worker * - :cpp:class:`pw::sync::InterruptSpinLock::InterruptSpinLock` 436*61c4878aSAndroid Build Coastguard Worker - ✔ 437*61c4878aSAndroid Build Coastguard Worker - ✔ 438*61c4878aSAndroid Build Coastguard Worker - 439*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::InterruptSpinLock::~InterruptSpinLock` 440*61c4878aSAndroid Build Coastguard Worker - ✔ 441*61c4878aSAndroid Build Coastguard Worker - ✔ 442*61c4878aSAndroid Build Coastguard Worker - 443*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`lock` 444*61c4878aSAndroid Build Coastguard Worker - ✔ 445*61c4878aSAndroid Build Coastguard Worker - ✔ 446*61c4878aSAndroid Build Coastguard Worker - 447*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_lock` 448*61c4878aSAndroid Build Coastguard Worker - ✔ 449*61c4878aSAndroid Build Coastguard Worker - ✔ 450*61c4878aSAndroid Build Coastguard Worker - 451*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`unlock` 452*61c4878aSAndroid Build Coastguard Worker - ✔ 453*61c4878aSAndroid Build Coastguard Worker - ✔ 454*61c4878aSAndroid Build Coastguard Worker - 455*61c4878aSAndroid Build Coastguard Worker 456*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 457*61c4878aSAndroid Build Coastguard Worker 458*61c4878aSAndroid Build Coastguard WorkerExamples in C++ 459*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^ 460*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 461*61c4878aSAndroid Build Coastguard Worker 462*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/interrupt_spin_lock.h" 463*61c4878aSAndroid Build Coastguard Worker 464*61c4878aSAndroid Build Coastguard Worker pw::sync::InterruptSpinLock interrupt_spin_lock; 465*61c4878aSAndroid Build Coastguard Worker 466*61c4878aSAndroid Build Coastguard Worker void InterruptSafeCriticalSection() { 467*61c4878aSAndroid Build Coastguard Worker interrupt_spin_lock.lock(); 468*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 469*61c4878aSAndroid Build Coastguard Worker interrupt_spin_lock.unlock(); 470*61c4878aSAndroid Build Coastguard Worker } 471*61c4878aSAndroid Build Coastguard Worker 472*61c4878aSAndroid Build Coastguard Worker 473*61c4878aSAndroid Build Coastguard WorkerAlternatively you can use C++'s RAII helpers to ensure you always unlock. 474*61c4878aSAndroid Build Coastguard Worker 475*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 476*61c4878aSAndroid Build Coastguard Worker 477*61c4878aSAndroid Build Coastguard Worker #include <mutex> 478*61c4878aSAndroid Build Coastguard Worker 479*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/interrupt_spin_lock.h" 480*61c4878aSAndroid Build Coastguard Worker 481*61c4878aSAndroid Build Coastguard Worker pw::sync::InterruptSpinLock interrupt_spin_lock; 482*61c4878aSAndroid Build Coastguard Worker 483*61c4878aSAndroid Build Coastguard Worker void InterruptSafeCriticalSection() { 484*61c4878aSAndroid Build Coastguard Worker std::lock_guard lock(interrupt_spin_lock); 485*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 486*61c4878aSAndroid Build Coastguard Worker } 487*61c4878aSAndroid Build Coastguard Worker 488*61c4878aSAndroid Build Coastguard Worker 489*61c4878aSAndroid Build Coastguard WorkerC 490*61c4878aSAndroid Build Coastguard Worker- 491*61c4878aSAndroid Build Coastguard WorkerThe InterruptSpinLock must be created in C++, however it can be passed into C using the 492*61c4878aSAndroid Build Coastguard Worker``pw_sync_InterruptSpinLock`` opaque struct alias. 493*61c4878aSAndroid Build Coastguard Worker 494*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_InterruptSpinLock_Lock 495*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_InterruptSpinLock_TryLock 496*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_InterruptSpinLock_Unlock 497*61c4878aSAndroid Build Coastguard Worker 498*61c4878aSAndroid Build Coastguard Worker.. list-table:: 499*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 500*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 501*61c4878aSAndroid Build Coastguard Worker 502*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 503*61c4878aSAndroid Build Coastguard Worker - Thread 504*61c4878aSAndroid Build Coastguard Worker - Interrupt 505*61c4878aSAndroid Build Coastguard Worker - NMI 506*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw_sync_InterruptSpinLock_Lock` 507*61c4878aSAndroid Build Coastguard Worker - ✔ 508*61c4878aSAndroid Build Coastguard Worker - ✔ 509*61c4878aSAndroid Build Coastguard Worker - 510*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw_sync_InterruptSpinLock_TryLock` 511*61c4878aSAndroid Build Coastguard Worker - ✔ 512*61c4878aSAndroid Build Coastguard Worker - ✔ 513*61c4878aSAndroid Build Coastguard Worker - 514*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw_sync_InterruptSpinLock_Unlock` 515*61c4878aSAndroid Build Coastguard Worker - ✔ 516*61c4878aSAndroid Build Coastguard Worker - ✔ 517*61c4878aSAndroid Build Coastguard Worker - 518*61c4878aSAndroid Build Coastguard Worker 519*61c4878aSAndroid Build Coastguard WorkerExample in C 520*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^ 521*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 522*61c4878aSAndroid Build Coastguard Worker 523*61c4878aSAndroid Build Coastguard Worker #include "pw_chrono/system_clock.h" 524*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/interrupt_spin_lock.h" 525*61c4878aSAndroid Build Coastguard Worker 526*61c4878aSAndroid Build Coastguard Worker pw::sync::InterruptSpinLock interrupt_spin_lock; 527*61c4878aSAndroid Build Coastguard Worker 528*61c4878aSAndroid Build Coastguard Worker extern pw_sync_InterruptSpinLock interrupt_spin_lock; // This can only be created in C++. 529*61c4878aSAndroid Build Coastguard Worker 530*61c4878aSAndroid Build Coastguard Worker void InterruptSafeCriticalSection(void) { 531*61c4878aSAndroid Build Coastguard Worker pw_sync_InterruptSpinLock_Lock(&interrupt_spin_lock); 532*61c4878aSAndroid Build Coastguard Worker NotThreadSafeCriticalSection(); 533*61c4878aSAndroid Build Coastguard Worker pw_sync_InterruptSpinLock_Unlock(&interrupt_spin_lock); 534*61c4878aSAndroid Build Coastguard Worker } 535*61c4878aSAndroid Build Coastguard Worker 536*61c4878aSAndroid Build Coastguard WorkerThread Safety Lock Annotations 537*61c4878aSAndroid Build Coastguard Worker============================== 538*61c4878aSAndroid Build Coastguard WorkerPigweed's critical section lock primitives support Clang's thread safety 539*61c4878aSAndroid Build Coastguard Workeranalysis extension for C++. The analysis is completely static at compile-time. 540*61c4878aSAndroid Build Coastguard WorkerThis is only supported when building with Clang. The annotations are no-ops when 541*61c4878aSAndroid Build Coastguard Workerusing different compilers. 542*61c4878aSAndroid Build Coastguard Worker 543*61c4878aSAndroid Build Coastguard WorkerPigweed provides the ``pw_sync/lock_annotations.h`` header file with macro 544*61c4878aSAndroid Build Coastguard Workerdefinitions to allow developers to document the locking policies of 545*61c4878aSAndroid Build Coastguard Workermulti-threaded code. The annotations can also help program analysis tools to 546*61c4878aSAndroid Build Coastguard Workeridentify potential thread safety issues. 547*61c4878aSAndroid Build Coastguard Worker 548*61c4878aSAndroid Build Coastguard WorkerMore information on Clang's thread safety analysis system can be found 549*61c4878aSAndroid Build Coastguard Worker`here <https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_. 550*61c4878aSAndroid Build Coastguard Worker 551*61c4878aSAndroid Build Coastguard WorkerEnabling Clang's Analysis 552*61c4878aSAndroid Build Coastguard Worker------------------------- 553*61c4878aSAndroid Build Coastguard WorkerIn order to enable the analysis, Clang requires that the ``-Wthread-safety`` 554*61c4878aSAndroid Build Coastguard Workercompilation flag be used. In addition, if any STL components like 555*61c4878aSAndroid Build Coastguard Worker``std::lock_guard`` are used, the STL's built in annotations have to be manually 556*61c4878aSAndroid Build Coastguard Workerenabled, typically by setting the ``_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS`` 557*61c4878aSAndroid Build Coastguard Workermacro. 558*61c4878aSAndroid Build Coastguard Worker 559*61c4878aSAndroid Build Coastguard WorkerIf using GN, the ``pw_build:clang_thread_safety_warnings`` config is provided 560*61c4878aSAndroid Build Coastguard Workerto do this for you, when added to your clang toolchain definition's default 561*61c4878aSAndroid Build Coastguard Workerconfigs. 562*61c4878aSAndroid Build Coastguard Worker 563*61c4878aSAndroid Build Coastguard WorkerWhy use lock annotations? 564*61c4878aSAndroid Build Coastguard Worker------------------------- 565*61c4878aSAndroid Build Coastguard WorkerLock annotations can help warn you about potential race conditions in your code 566*61c4878aSAndroid Build Coastguard Workerwhen using locks: you have to remember to grab lock(s) before entering a 567*61c4878aSAndroid Build Coastguard Workercritical section, yuou have to remember to unlock it when you leave, and you 568*61c4878aSAndroid Build Coastguard Workerhave to avoid deadlocks. 569*61c4878aSAndroid Build Coastguard Worker 570*61c4878aSAndroid Build Coastguard WorkerClang's lock annotations let you inform the compiler and anyone reading your 571*61c4878aSAndroid Build Coastguard Workercode which variables are guarded by which locks, which locks should or cannot be 572*61c4878aSAndroid Build Coastguard Workerheld when calling which function, which order locks should be acquired in, etc. 573*61c4878aSAndroid Build Coastguard Worker 574*61c4878aSAndroid Build Coastguard WorkerUsing Lock Annotations 575*61c4878aSAndroid Build Coastguard Worker---------------------- 576*61c4878aSAndroid Build Coastguard WorkerWhen referring to locks in the arguments of the attributes, you should 577*61c4878aSAndroid Build Coastguard Workeruse variable names or more complex expressions (e.g. ``my_object->lock_``) 578*61c4878aSAndroid Build Coastguard Workerthat evaluate to a concrete lock object whenever possible. If the lock 579*61c4878aSAndroid Build Coastguard Workeryou want to refer to is not in scope, you may use a member pointer 580*61c4878aSAndroid Build Coastguard Worker(e.g. ``&MyClass::lock_``) to refer to a lock in some (unknown) object. 581*61c4878aSAndroid Build Coastguard Worker 582*61c4878aSAndroid Build Coastguard WorkerAnnotating Lock Usage 583*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^ 584*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_GUARDED_BY 585*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_PT_GUARDED_BY 586*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_ACQUIRED_AFTER 587*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_ACQUIRED_BEFORE 588*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_EXCLUSIVE_LOCKS_REQUIRED 589*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_SHARED_LOCKS_REQUIRED 590*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOCKS_EXCLUDED 591*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOCK_RETURNED 592*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOCKABLE 593*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_SCOPED_LOCKABLE 594*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_EXCLUSIVE_LOCK_FUNCTION 595*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_SHARED_LOCK_FUNCTION 596*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_UNLOCK_FUNCTION 597*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_EXCLUSIVE_TRYLOCK_FUNCTION 598*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_SHARED_TRYLOCK_FUNCTION 599*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_ASSERT_EXCLUSIVE_LOCK 600*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_ASSERT_SHARED_LOCK 601*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_NO_LOCK_SAFETY_ANALYSIS 602*61c4878aSAndroid Build Coastguard Worker 603*61c4878aSAndroid Build Coastguard WorkerAnnotating Lock Objects 604*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^ 605*61c4878aSAndroid Build Coastguard WorkerIn order of lock usage annotation to work, the lock objects themselves need to 606*61c4878aSAndroid Build Coastguard Workerbe annotated as well. In case you are providing your own lock or psuedo-lock 607*61c4878aSAndroid Build Coastguard Workerobject, you can use the macros in this section to annotate it. 608*61c4878aSAndroid Build Coastguard Worker 609*61c4878aSAndroid Build Coastguard WorkerAs an example we've annotated a Lock and a RAII ScopedLocker object for you, see 610*61c4878aSAndroid Build Coastguard Workerthe macro documentation after for more details: 611*61c4878aSAndroid Build Coastguard Worker 612*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 613*61c4878aSAndroid Build Coastguard Worker 614*61c4878aSAndroid Build Coastguard Worker class PW_LOCKABLE("Lock") Lock { 615*61c4878aSAndroid Build Coastguard Worker public: 616*61c4878aSAndroid Build Coastguard Worker void Lock() PW_EXCLUSIVE_LOCK_FUNCTION(); 617*61c4878aSAndroid Build Coastguard Worker 618*61c4878aSAndroid Build Coastguard Worker void ReaderLock() PW_SHARED_LOCK_FUNCTION(); 619*61c4878aSAndroid Build Coastguard Worker 620*61c4878aSAndroid Build Coastguard Worker void Unlock() PW_UNLOCK_FUNCTION(); 621*61c4878aSAndroid Build Coastguard Worker 622*61c4878aSAndroid Build Coastguard Worker void ReaderUnlock() PW_SHARED_TRYLOCK_FUNCTION(); 623*61c4878aSAndroid Build Coastguard Worker 624*61c4878aSAndroid Build Coastguard Worker bool TryLock() PW_EXCLUSIVE_TRYLOCK_FUNCTION(true); 625*61c4878aSAndroid Build Coastguard Worker 626*61c4878aSAndroid Build Coastguard Worker bool ReaderTryLock() PW_SHARED_TRYLOCK_FUNCTION(true); 627*61c4878aSAndroid Build Coastguard Worker 628*61c4878aSAndroid Build Coastguard Worker void AssertHeld() PW_ASSERT_EXCLUSIVE_LOCK(); 629*61c4878aSAndroid Build Coastguard Worker 630*61c4878aSAndroid Build Coastguard Worker void AssertReaderHeld() PW_ASSERT_SHARED_LOCK(); 631*61c4878aSAndroid Build Coastguard Worker }; 632*61c4878aSAndroid Build Coastguard Worker 633*61c4878aSAndroid Build Coastguard Worker 634*61c4878aSAndroid Build Coastguard Worker // Tag types for selecting a constructor. 635*61c4878aSAndroid Build Coastguard Worker struct adopt_lock_t {} inline constexpr adopt_lock = {}; 636*61c4878aSAndroid Build Coastguard Worker struct defer_lock_t {} inline constexpr defer_lock = {}; 637*61c4878aSAndroid Build Coastguard Worker struct shared_lock_t {} inline constexpr shared_lock = {}; 638*61c4878aSAndroid Build Coastguard Worker 639*61c4878aSAndroid Build Coastguard Worker class PW_SCOPED_LOCKABLE ScopedLocker { 640*61c4878aSAndroid Build Coastguard Worker // Acquire lock, implicitly acquire *this and associate it with lock. 641*61c4878aSAndroid Build Coastguard Worker ScopedLocker(Lock *lock) PW_EXCLUSIVE_LOCK_FUNCTION(lock) 642*61c4878aSAndroid Build Coastguard Worker : lock_(lock), locked(true) { 643*61c4878aSAndroid Build Coastguard Worker lock->Lock(); 644*61c4878aSAndroid Build Coastguard Worker } 645*61c4878aSAndroid Build Coastguard Worker 646*61c4878aSAndroid Build Coastguard Worker // Assume lock is held, implicitly acquire *this and associate it with lock. 647*61c4878aSAndroid Build Coastguard Worker ScopedLocker(Lock *lock, adopt_lock_t) PW_EXCLUSIVE_LOCKS_REQUIRED(lock) 648*61c4878aSAndroid Build Coastguard Worker : lock_(lock), locked(true) {} 649*61c4878aSAndroid Build Coastguard Worker 650*61c4878aSAndroid Build Coastguard Worker // Acquire lock in shared mode, implicitly acquire *this and associate it 651*61c4878aSAndroid Build Coastguard Worker // with lock. 652*61c4878aSAndroid Build Coastguard Worker ScopedLocker(Lock *lock, shared_lock_t) PW_SHARED_LOCK_FUNCTION(lock) 653*61c4878aSAndroid Build Coastguard Worker : lock_(lock), locked(true) { 654*61c4878aSAndroid Build Coastguard Worker lock->ReaderLock(); 655*61c4878aSAndroid Build Coastguard Worker } 656*61c4878aSAndroid Build Coastguard Worker 657*61c4878aSAndroid Build Coastguard Worker // Assume lock is held in shared mode, implicitly acquire *this and associate 658*61c4878aSAndroid Build Coastguard Worker // it with lock. 659*61c4878aSAndroid Build Coastguard Worker ScopedLocker(Lock *lock, adopt_lock_t, shared_lock_t) 660*61c4878aSAndroid Build Coastguard Worker PW_SHARED_LOCKS_REQUIRED(lock) : lock_(lock), locked(true) {} 661*61c4878aSAndroid Build Coastguard Worker 662*61c4878aSAndroid Build Coastguard Worker // Assume lock is not held, implicitly acquire *this and associate it with 663*61c4878aSAndroid Build Coastguard Worker // lock. 664*61c4878aSAndroid Build Coastguard Worker ScopedLocker(Lock *lock, defer_lock_t) PW_LOCKS_EXCLUDED(lock) 665*61c4878aSAndroid Build Coastguard Worker : lock_(lock), locked(false) {} 666*61c4878aSAndroid Build Coastguard Worker 667*61c4878aSAndroid Build Coastguard Worker // Release *this and all associated locks, if they are still held. 668*61c4878aSAndroid Build Coastguard Worker // There is no warning if the scope was already unlocked before. 669*61c4878aSAndroid Build Coastguard Worker ~ScopedLocker() PW_UNLOCK_FUNCTION() { 670*61c4878aSAndroid Build Coastguard Worker if (locked) 671*61c4878aSAndroid Build Coastguard Worker lock_->GenericUnlock(); 672*61c4878aSAndroid Build Coastguard Worker } 673*61c4878aSAndroid Build Coastguard Worker 674*61c4878aSAndroid Build Coastguard Worker // Acquire all associated locks exclusively. 675*61c4878aSAndroid Build Coastguard Worker void Lock() PW_EXCLUSIVE_LOCK_FUNCTION() { 676*61c4878aSAndroid Build Coastguard Worker lock_->Lock(); 677*61c4878aSAndroid Build Coastguard Worker locked = true; 678*61c4878aSAndroid Build Coastguard Worker } 679*61c4878aSAndroid Build Coastguard Worker 680*61c4878aSAndroid Build Coastguard Worker // Try to acquire all associated locks exclusively. 681*61c4878aSAndroid Build Coastguard Worker bool TryLock() PW_EXCLUSIVE_TRYLOCK_FUNCTION(true) { 682*61c4878aSAndroid Build Coastguard Worker return locked = lock_->TryLock(); 683*61c4878aSAndroid Build Coastguard Worker } 684*61c4878aSAndroid Build Coastguard Worker 685*61c4878aSAndroid Build Coastguard Worker // Acquire all associated locks in shared mode. 686*61c4878aSAndroid Build Coastguard Worker void ReaderLock() PW_SHARED_LOCK_FUNCTION() { 687*61c4878aSAndroid Build Coastguard Worker lock_->ReaderLock(); 688*61c4878aSAndroid Build Coastguard Worker locked = true; 689*61c4878aSAndroid Build Coastguard Worker } 690*61c4878aSAndroid Build Coastguard Worker 691*61c4878aSAndroid Build Coastguard Worker // Try to acquire all associated locks in shared mode. 692*61c4878aSAndroid Build Coastguard Worker bool ReaderTryLock() PW_SHARED_TRYLOCK_FUNCTION(true) { 693*61c4878aSAndroid Build Coastguard Worker return locked = lock_->ReaderTryLock(); 694*61c4878aSAndroid Build Coastguard Worker } 695*61c4878aSAndroid Build Coastguard Worker 696*61c4878aSAndroid Build Coastguard Worker // Release all associated locks. Warn on double unlock. 697*61c4878aSAndroid Build Coastguard Worker void Unlock() PW_UNLOCK_FUNCTION() { 698*61c4878aSAndroid Build Coastguard Worker lock_->Unlock(); 699*61c4878aSAndroid Build Coastguard Worker locked = false; 700*61c4878aSAndroid Build Coastguard Worker } 701*61c4878aSAndroid Build Coastguard Worker 702*61c4878aSAndroid Build Coastguard Worker // Release all associated locks. Warn on double unlock. 703*61c4878aSAndroid Build Coastguard Worker void ReaderUnlock() PW_UNLOCK_FUNCTION() { 704*61c4878aSAndroid Build Coastguard Worker lock_->ReaderUnlock(); 705*61c4878aSAndroid Build Coastguard Worker locked = false; 706*61c4878aSAndroid Build Coastguard Worker } 707*61c4878aSAndroid Build Coastguard Worker 708*61c4878aSAndroid Build Coastguard Worker private: 709*61c4878aSAndroid Build Coastguard Worker Lock* lock_; 710*61c4878aSAndroid Build Coastguard Worker bool locked_; 711*61c4878aSAndroid Build Coastguard Worker }; 712*61c4878aSAndroid Build Coastguard Worker 713*61c4878aSAndroid Build Coastguard Worker----------------------------- 714*61c4878aSAndroid Build Coastguard WorkerCritical Section Lock Helpers 715*61c4878aSAndroid Build Coastguard Worker----------------------------- 716*61c4878aSAndroid Build Coastguard Worker 717*61c4878aSAndroid Build Coastguard WorkerVirtual Lock Interfaces 718*61c4878aSAndroid Build Coastguard Worker======================= 719*61c4878aSAndroid Build Coastguard WorkerVirtual lock interfaces can be useful when lock selection cannot be templated. 720*61c4878aSAndroid Build Coastguard Worker 721*61c4878aSAndroid Build Coastguard WorkerWhy use virtual locks? 722*61c4878aSAndroid Build Coastguard Worker---------------------- 723*61c4878aSAndroid Build Coastguard WorkerVirtual locks enable depending on locks without templating implementation code 724*61c4878aSAndroid Build Coastguard Workeron the type, while retaining flexibility with respect to the concrete lock type. 725*61c4878aSAndroid Build Coastguard WorkerPigweed tries to avoid pushing policy on to users, and virtual locks are one way 726*61c4878aSAndroid Build Coastguard Workerto accomplish that without templating everything. 727*61c4878aSAndroid Build Coastguard Worker 728*61c4878aSAndroid Build Coastguard WorkerA case when virtual locks are useful is when the concrete lock type changes at 729*61c4878aSAndroid Build Coastguard Workerrun time. For example, access to flash may be protected at run time by an 730*61c4878aSAndroid Build Coastguard Workerinternal mutex, however at crash time we may want to switch to a no-op lock. A 731*61c4878aSAndroid Build Coastguard Workervirtual lock interface could be used here to minimize the code-size cost that 732*61c4878aSAndroid Build Coastguard Workerwould occur otherwise if the flash driver were templated. 733*61c4878aSAndroid Build Coastguard Worker 734*61c4878aSAndroid Build Coastguard WorkerVirtualBasicLockable 735*61c4878aSAndroid Build Coastguard Worker-------------------- 736*61c4878aSAndroid Build Coastguard WorkerThe ``VirtualBasicLockable`` interface meets the 737*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_ C++ 738*61c4878aSAndroid Build Coastguard Workernamed requirement. Our critical section lock primitives offer optional virtual 739*61c4878aSAndroid Build Coastguard Workerversions, including: 740*61c4878aSAndroid Build Coastguard Worker 741*61c4878aSAndroid Build Coastguard Worker* :cpp:func:`pw::sync::VirtualMutex` 742*61c4878aSAndroid Build Coastguard Worker* :cpp:func:`pw::sync::VirtualTimedMutex` 743*61c4878aSAndroid Build Coastguard Worker* :cpp:func:`pw::sync::VirtualInterruptSpinLock` 744*61c4878aSAndroid Build Coastguard Worker 745*61c4878aSAndroid Build Coastguard Worker.. _module-pw_sync-genericbasiclockable: 746*61c4878aSAndroid Build Coastguard Worker 747*61c4878aSAndroid Build Coastguard WorkerGenericBasicLockable 748*61c4878aSAndroid Build Coastguard Worker-------------------- 749*61c4878aSAndroid Build Coastguard Worker``GenericBasicLockable`` is a helper construct that can be used to declare 750*61c4878aSAndroid Build Coastguard Workervirtual versions of a critical section lock primitive that meets the 751*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_ 752*61c4878aSAndroid Build Coastguard WorkerC++ named requirement. For example, given a ``Mutex`` type with ``lock()`` and 753*61c4878aSAndroid Build Coastguard Worker``unlock()`` methods, a ``VirtualMutex`` type that derives from 754*61c4878aSAndroid Build Coastguard Worker``VirtualBasicLockable`` can be declared as follows: 755*61c4878aSAndroid Build Coastguard Worker 756*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 757*61c4878aSAndroid Build Coastguard Worker 758*61c4878aSAndroid Build Coastguard Worker class VirtualMutex : public GenericBasicLockable<Mutex> {}; 759*61c4878aSAndroid Build Coastguard Worker 760*61c4878aSAndroid Build Coastguard WorkerBorrowable 761*61c4878aSAndroid Build Coastguard Worker========== 762*61c4878aSAndroid Build Coastguard Worker``Borrowable`` is a helper construct that enables callers to borrow an object 763*61c4878aSAndroid Build Coastguard Workerwhich is guarded by a lock, enabling a containerized style of external locking. 764*61c4878aSAndroid Build Coastguard Worker 765*61c4878aSAndroid Build Coastguard WorkerUsers who need access to the guarded object can ask to acquire a 766*61c4878aSAndroid Build Coastguard Worker``BorrowedPointer`` which permits access while the lock is held. 767*61c4878aSAndroid Build Coastguard Worker 768*61c4878aSAndroid Build Coastguard WorkerThis class is compatible with locks which comply with 769*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_, 770*61c4878aSAndroid Build Coastguard Worker`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_, and 771*61c4878aSAndroid Build Coastguard Worker`TimedLockable <https://en.cppreference.com/w/cpp/named_req/TimedLockable>`_ 772*61c4878aSAndroid Build Coastguard WorkerC++ named requirements. 773*61c4878aSAndroid Build Coastguard Worker 774*61c4878aSAndroid Build Coastguard WorkerBy default the selected lock type is a ``pw::sync::VirtualBasicLockable``. If 775*61c4878aSAndroid Build Coastguard Workerthis virtual interface is used, the templated lock parameter can be skipped. 776*61c4878aSAndroid Build Coastguard Worker 777*61c4878aSAndroid Build Coastguard WorkerExternal vs Internal locking 778*61c4878aSAndroid Build Coastguard Worker---------------------------- 779*61c4878aSAndroid Build Coastguard WorkerBefore we explain why Borrowable is useful, it's important to understand the 780*61c4878aSAndroid Build Coastguard Workertrade-offs when deciding on using internal and/or external locking. 781*61c4878aSAndroid Build Coastguard Worker 782*61c4878aSAndroid Build Coastguard WorkerInternal locking is when the lock is hidden from the caller entirely and is used 783*61c4878aSAndroid Build Coastguard Workerinternally to the API. For example: 784*61c4878aSAndroid Build Coastguard Worker 785*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 786*61c4878aSAndroid Build Coastguard Worker 787*61c4878aSAndroid Build Coastguard Worker class BankAccount { 788*61c4878aSAndroid Build Coastguard Worker public: 789*61c4878aSAndroid Build Coastguard Worker void Deposit(int amount) { 790*61c4878aSAndroid Build Coastguard Worker std::lock_guard lock(mutex_); 791*61c4878aSAndroid Build Coastguard Worker balance_ += amount; 792*61c4878aSAndroid Build Coastguard Worker } 793*61c4878aSAndroid Build Coastguard Worker 794*61c4878aSAndroid Build Coastguard Worker void Withdraw(int amount) { 795*61c4878aSAndroid Build Coastguard Worker std::lock_guard lock(mutex_); 796*61c4878aSAndroid Build Coastguard Worker balance_ -= amount; 797*61c4878aSAndroid Build Coastguard Worker } 798*61c4878aSAndroid Build Coastguard Worker 799*61c4878aSAndroid Build Coastguard Worker void Balance() const { 800*61c4878aSAndroid Build Coastguard Worker std::lock_guard lock(mutex_); 801*61c4878aSAndroid Build Coastguard Worker return balance_; 802*61c4878aSAndroid Build Coastguard Worker } 803*61c4878aSAndroid Build Coastguard Worker 804*61c4878aSAndroid Build Coastguard Worker private: 805*61c4878aSAndroid Build Coastguard Worker int balance_ PW_GUARDED_BY(mutex_); 806*61c4878aSAndroid Build Coastguard Worker pw::sync::Mutex mutex_; 807*61c4878aSAndroid Build Coastguard Worker }; 808*61c4878aSAndroid Build Coastguard Worker 809*61c4878aSAndroid Build Coastguard WorkerInternal locking guarantees that any concurrent calls to its public member 810*61c4878aSAndroid Build Coastguard Workerfunctions don't corrupt an instance of that class. This is typically ensured by 811*61c4878aSAndroid Build Coastguard Workerhaving each member function acquire a lock on the object upon entry. This way, 812*61c4878aSAndroid Build Coastguard Workerfor any instance, there can only be one member function call active at any 813*61c4878aSAndroid Build Coastguard Workermoment, serializing the operations. 814*61c4878aSAndroid Build Coastguard Worker 815*61c4878aSAndroid Build Coastguard WorkerOne common issue that pops up is that member functions may have to call other 816*61c4878aSAndroid Build Coastguard Workermember functions which also require locks. This typically results in a 817*61c4878aSAndroid Build Coastguard Workerduplication of the public API into an internal mirror where the lock is already 818*61c4878aSAndroid Build Coastguard Workerheld. This along with having to modify every thread-safe public member function 819*61c4878aSAndroid Build Coastguard Workermay results in an increased code size. 820*61c4878aSAndroid Build Coastguard Worker 821*61c4878aSAndroid Build Coastguard WorkerHowever, with the per-method locking approach, it is not possible to perform a 822*61c4878aSAndroid Build Coastguard Workermulti-method thread-safe transaction. For example, what if we only wanted to 823*61c4878aSAndroid Build Coastguard Workerwithdraw money if the balance was high enough? With the current API there would 824*61c4878aSAndroid Build Coastguard Workerbe a risk that money is withdrawn after we've checked the balance. 825*61c4878aSAndroid Build Coastguard Worker 826*61c4878aSAndroid Build Coastguard WorkerThis is usually why external locking is used. This is when the lock is exposed 827*61c4878aSAndroid Build Coastguard Workerto the caller and may be used externally to the public API. External locking 828*61c4878aSAndroid Build Coastguard Workercan take may forms which may even include mixing internal and external locking. 829*61c4878aSAndroid Build Coastguard WorkerIn its most simplistic form it is an external lock used along side each 830*61c4878aSAndroid Build Coastguard Workerinstance, e.g.: 831*61c4878aSAndroid Build Coastguard Worker 832*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 833*61c4878aSAndroid Build Coastguard Worker 834*61c4878aSAndroid Build Coastguard Worker class BankAccount { 835*61c4878aSAndroid Build Coastguard Worker public: 836*61c4878aSAndroid Build Coastguard Worker void Deposit(int amount) { 837*61c4878aSAndroid Build Coastguard Worker balance_ += amount; 838*61c4878aSAndroid Build Coastguard Worker } 839*61c4878aSAndroid Build Coastguard Worker 840*61c4878aSAndroid Build Coastguard Worker void Withdraw(int amount) { 841*61c4878aSAndroid Build Coastguard Worker balance_ -= amount; 842*61c4878aSAndroid Build Coastguard Worker } 843*61c4878aSAndroid Build Coastguard Worker 844*61c4878aSAndroid Build Coastguard Worker void Balance() const { 845*61c4878aSAndroid Build Coastguard Worker return balance_; 846*61c4878aSAndroid Build Coastguard Worker } 847*61c4878aSAndroid Build Coastguard Worker 848*61c4878aSAndroid Build Coastguard Worker private: 849*61c4878aSAndroid Build Coastguard Worker int balance_; 850*61c4878aSAndroid Build Coastguard Worker }; 851*61c4878aSAndroid Build Coastguard Worker 852*61c4878aSAndroid Build Coastguard Worker pw::sync::Mutex bobs_account_mutex; 853*61c4878aSAndroid Build Coastguard Worker BankAccount bobs_account PW_GUARDED_BY(bobs_account_mutex); 854*61c4878aSAndroid Build Coastguard Worker 855*61c4878aSAndroid Build Coastguard WorkerThe lock is acquired before the bank account is used for a transaction. In 856*61c4878aSAndroid Build Coastguard Workeraddition, we do not have to modify every public function and its trivial to 857*61c4878aSAndroid Build Coastguard Workercall other public member functions from a public member function. However, as 858*61c4878aSAndroid Build Coastguard Workeryou can imagine instantiating and passing around the instances and their locks 859*61c4878aSAndroid Build Coastguard Workercan become error prone. 860*61c4878aSAndroid Build Coastguard Worker 861*61c4878aSAndroid Build Coastguard WorkerThis is why ``Borrowable`` exists. 862*61c4878aSAndroid Build Coastguard Worker 863*61c4878aSAndroid Build Coastguard WorkerWhy use Borrowable? 864*61c4878aSAndroid Build Coastguard Worker------------------- 865*61c4878aSAndroid Build Coastguard Worker``Borrowable`` offers code-size efficient way to enable external locking that is 866*61c4878aSAndroid Build Coastguard Workereasy and safe to use. It is effectively a container which holds references to a 867*61c4878aSAndroid Build Coastguard Workerprotected instance and its lock which provides RAII-style access. 868*61c4878aSAndroid Build Coastguard Worker 869*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 870*61c4878aSAndroid Build Coastguard Worker 871*61c4878aSAndroid Build Coastguard Worker pw::sync::Mutex bobs_account_mutex; 872*61c4878aSAndroid Build Coastguard Worker BankAccount bobs_account PW_GUARDED_BY(bobs_account_mutex); 873*61c4878aSAndroid Build Coastguard Worker pw::sync::Borrowable<BankAccount, pw::sync::Mutex> bobs_acount( 874*61c4878aSAndroid Build Coastguard Worker bobs_account, bobs_account_mutex); 875*61c4878aSAndroid Build Coastguard Worker 876*61c4878aSAndroid Build Coastguard WorkerThis construct is useful when sharing objects or data which are transactional in 877*61c4878aSAndroid Build Coastguard Workernature where making individual operations threadsafe is insufficient. See the 878*61c4878aSAndroid Build Coastguard Workersection on internal vs external locking tradeoffs above. 879*61c4878aSAndroid Build Coastguard Worker 880*61c4878aSAndroid Build Coastguard WorkerIt can also offer a code-size and stack-usage efficient way to separate timeout 881*61c4878aSAndroid Build Coastguard Workerconstraints between the acquiring of the shared object and timeouts used for the 882*61c4878aSAndroid Build Coastguard Workershared object's API. For example, imagine you have an I2c bus which is used by 883*61c4878aSAndroid Build Coastguard Workerseveral threads and you'd like to specify an ACK timeout of 50ms. It'd be ideal 884*61c4878aSAndroid Build Coastguard Workerif the duration it takes to gain exclusive access to the I2c bus does not eat 885*61c4878aSAndroid Build Coastguard Workerinto the ACK timeout you'd like to use for the transaction. Borrowable can help 886*61c4878aSAndroid Build Coastguard Workeryou do exactly this if you provide access to the I2c bus through a 887*61c4878aSAndroid Build Coastguard Worker``Borrowable``. 888*61c4878aSAndroid Build Coastguard Worker 889*61c4878aSAndroid Build Coastguard Worker.. note:: 890*61c4878aSAndroid Build Coastguard Worker 891*61c4878aSAndroid Build Coastguard Worker ``Borrowable`` has semantics similar to a pointer and should be passed by 892*61c4878aSAndroid Build Coastguard Worker value. Furthermore, a ``Borrowable<U>`` can be assigned to a 893*61c4878aSAndroid Build Coastguard Worker ``Borrowable<T>`` if ``U`` is a subclass of ``T``. 894*61c4878aSAndroid Build Coastguard Worker 895*61c4878aSAndroid Build Coastguard WorkerC++ 896*61c4878aSAndroid Build Coastguard Worker--- 897*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::BorrowedPointer 898*61c4878aSAndroid Build Coastguard Worker :members: 899*61c4878aSAndroid Build Coastguard Worker 900*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::Borrowable 901*61c4878aSAndroid Build Coastguard Worker :members: 902*61c4878aSAndroid Build Coastguard Worker 903*61c4878aSAndroid Build Coastguard WorkerExample in C++ 904*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^ 905*61c4878aSAndroid Build Coastguard Worker 906*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 907*61c4878aSAndroid Build Coastguard Worker 908*61c4878aSAndroid Build Coastguard Worker #include <chrono> 909*61c4878aSAndroid Build Coastguard Worker 910*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/span.h" 911*61c4878aSAndroid Build Coastguard Worker #include "pw_i2c/initiator.h" 912*61c4878aSAndroid Build Coastguard Worker #include "pw_status/try.h" 913*61c4878aSAndroid Build Coastguard Worker #include "pw_status/result.h" 914*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/borrow.h" 915*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/mutex.h" 916*61c4878aSAndroid Build Coastguard Worker 917*61c4878aSAndroid Build Coastguard Worker class ExampleI2c : public pw::i2c::Initiator; 918*61c4878aSAndroid Build Coastguard Worker 919*61c4878aSAndroid Build Coastguard Worker pw::sync::VirtualMutex i2c_mutex; 920*61c4878aSAndroid Build Coastguard Worker ExampleI2c i2c; 921*61c4878aSAndroid Build Coastguard Worker pw::sync::Borrowable<ExampleI2c> borrowable_i2c(i2c, i2c_mutex); 922*61c4878aSAndroid Build Coastguard Worker 923*61c4878aSAndroid Build Coastguard Worker pw::Result<ConstByteSpan> ReadI2cData(ByteSpan buffer) { 924*61c4878aSAndroid Build Coastguard Worker // Block indefinitely waiting to borrow the i2c bus. 925*61c4878aSAndroid Build Coastguard Worker pw::sync::BorrowedPointer<ExampleI2c> borrowed_i2c = 926*61c4878aSAndroid Build Coastguard Worker borrowable_i2c.acquire(); 927*61c4878aSAndroid Build Coastguard Worker 928*61c4878aSAndroid Build Coastguard Worker // Execute a sequence of transactions to get the needed data. 929*61c4878aSAndroid Build Coastguard Worker PW_TRY(borrowed_i2c->WriteFor(kFirstWrite, std::chrono::milliseconds(50))); 930*61c4878aSAndroid Build Coastguard Worker PW_TRY(borrowed_i2c->WriteReadFor(kSecondWrite, buffer, 931*61c4878aSAndroid Build Coastguard Worker std::chrono::milliseconds(10))); 932*61c4878aSAndroid Build Coastguard Worker 933*61c4878aSAndroid Build Coastguard Worker // Borrowed i2c pointer is returned when the scope exits. 934*61c4878aSAndroid Build Coastguard Worker return buffer; 935*61c4878aSAndroid Build Coastguard Worker } 936*61c4878aSAndroid Build Coastguard Worker 937*61c4878aSAndroid Build Coastguard WorkerInlineBorrowable 938*61c4878aSAndroid Build Coastguard Worker================= 939*61c4878aSAndroid Build Coastguard Worker``InlineBorrowable`` is a helper to simplify the common use case where an object 940*61c4878aSAndroid Build Coastguard Workeris wrapped in a ``Borrowable`` for its entire lifetime. The InlineBorrowable 941*61c4878aSAndroid Build Coastguard Workerowns the guarded object and the lock object. 942*61c4878aSAndroid Build Coastguard Worker 943*61c4878aSAndroid Build Coastguard WorkerInlineBorrowable has a separate parameter for the concrete lock type 944*61c4878aSAndroid Build Coastguard Workerthat is instantiated and a (possibly virtual) lock interface type that is 945*61c4878aSAndroid Build Coastguard Workerreferenced by users of the guarded object. The default lock is 946*61c4878aSAndroid Build Coastguard Worker``pw::sync::VirtualMutex`` and the default lock interface is 947*61c4878aSAndroid Build Coastguard Worker``pw::sync::VirtualBasicLockable``. 948*61c4878aSAndroid Build Coastguard Worker 949*61c4878aSAndroid Build Coastguard WorkerAn InlineBorrowable is a Borrowable with the same guarded object and lock 950*61c4878aSAndroid Build Coastguard Workerinterface types, and it can be passed directly to APIs that expect a Borrowable 951*61c4878aSAndroid Build Coastguard Workerreference. 952*61c4878aSAndroid Build Coastguard Worker 953*61c4878aSAndroid Build Coastguard WorkerWhy use InlineBorrowable? 954*61c4878aSAndroid Build Coastguard Worker------------------------- 955*61c4878aSAndroid Build Coastguard WorkerIt is a safer and simpler way to guard an object for its entire lifetime. The 956*61c4878aSAndroid Build Coastguard Workerunguarded object is never exposed and doesn't need to be stored in a separate 957*61c4878aSAndroid Build Coastguard Workervariable or data member. The guarded object and its lock are guaranteed to have 958*61c4878aSAndroid Build Coastguard Workerthe same lifetime, and the lock cannot be re-used for any other purpose. 959*61c4878aSAndroid Build Coastguard Worker 960*61c4878aSAndroid Build Coastguard WorkerConstructing objects in-place 961*61c4878aSAndroid Build Coastguard Worker----------------------------- 962*61c4878aSAndroid Build Coastguard WorkerThe guarded object and its lock are constructed in-place by the 963*61c4878aSAndroid Build Coastguard WorkerInlineBorrowable, and any constructor parameters required by the object or 964*61c4878aSAndroid Build Coastguard Workerits lock must be passed through the InlineBorrowable constructor. There are 965*61c4878aSAndroid Build Coastguard Workerseveral ways to do this: 966*61c4878aSAndroid Build Coastguard Worker 967*61c4878aSAndroid Build Coastguard Worker* Pass the parameters for the guarded object inline to the constructor. This is 968*61c4878aSAndroid Build Coastguard Worker the recommended way to construct the object when the lock does not require any 969*61c4878aSAndroid Build Coastguard Worker constructor parameters. Use the ``std::in_place`` marker to invoke the inline 970*61c4878aSAndroid Build Coastguard Worker constructor. 971*61c4878aSAndroid Build Coastguard Worker 972*61c4878aSAndroid Build Coastguard Worker .. code-block:: cpp 973*61c4878aSAndroid Build Coastguard Worker 974*61c4878aSAndroid Build Coastguard Worker InlineBorrowable<Foo> foo(std::in_place, foo_arg1, foo_arg2); 975*61c4878aSAndroid Build Coastguard Worker InlineBorrowable<std::array<int, 2>> foo_array(std::in_place, 1, 2); 976*61c4878aSAndroid Build Coastguard Worker 977*61c4878aSAndroid Build Coastguard Worker* Pass the parameters inside tuples: 978*61c4878aSAndroid Build Coastguard Worker 979*61c4878aSAndroid Build Coastguard Worker .. code-block:: cpp 980*61c4878aSAndroid Build Coastguard Worker 981*61c4878aSAndroid Build Coastguard Worker InlineBorrowable<Foo> foo(std::forward_as_tuple(foo_arg1, foo_arg2)); 982*61c4878aSAndroid Build Coastguard Worker 983*61c4878aSAndroid Build Coastguard Worker InlineBorrowable<Foo, MyLock> foo_lock( 984*61c4878aSAndroid Build Coastguard Worker std::forward_as_tuple(foo_arg1, foo_arg2), 985*61c4878aSAndroid Build Coastguard Worker std::forward_as_tuple(lock_arg1, lock_arg2)); 986*61c4878aSAndroid Build Coastguard Worker 987*61c4878aSAndroid Build Coastguard Worker .. note:: This approach only supports list initialization starting with C++20. 988*61c4878aSAndroid Build Coastguard Worker 989*61c4878aSAndroid Build Coastguard Worker* Use callables to construct the guarded object and lock object: 990*61c4878aSAndroid Build Coastguard Worker 991*61c4878aSAndroid Build Coastguard Worker .. code-block:: cpp 992*61c4878aSAndroid Build Coastguard Worker 993*61c4878aSAndroid Build Coastguard Worker InlineBorrowable<Foo> foo([&]{ return Foo{foo_arg1, foo_arg2}; }); 994*61c4878aSAndroid Build Coastguard Worker 995*61c4878aSAndroid Build Coastguard Worker InlineBorrowable<Foo, MyLock> foo_lock( 996*61c4878aSAndroid Build Coastguard Worker [&]{ return Foo{foo_arg1, foo_arg2}; } 997*61c4878aSAndroid Build Coastguard Worker [&]{ return MyLock{lock_arg1, lock_arg2}; } 998*61c4878aSAndroid Build Coastguard Worker 999*61c4878aSAndroid Build Coastguard Worker .. note:: It is possible to construct and return objects that are not copyable 1000*61c4878aSAndroid Build Coastguard Worker or movable, thanks to mandatory copy ellision (return value optimization). 1001*61c4878aSAndroid Build Coastguard Worker 1002*61c4878aSAndroid Build Coastguard WorkerC++ 1003*61c4878aSAndroid Build Coastguard Worker--- 1004*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::InlineBorrowable 1005*61c4878aSAndroid Build Coastguard Worker :members: 1006*61c4878aSAndroid Build Coastguard Worker 1007*61c4878aSAndroid Build Coastguard WorkerExample in C++ 1008*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^ 1009*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 1010*61c4878aSAndroid Build Coastguard Worker 1011*61c4878aSAndroid Build Coastguard Worker #include <utility> 1012*61c4878aSAndroid Build Coastguard Worker 1013*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/span.h" 1014*61c4878aSAndroid Build Coastguard Worker #include "pw_i2c/initiator.h" 1015*61c4878aSAndroid Build Coastguard Worker #include "pw_status/result.h" 1016*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/inline_borrowable.h" 1017*61c4878aSAndroid Build Coastguard Worker 1018*61c4878aSAndroid Build Coastguard Worker struct I2cOptions; 1019*61c4878aSAndroid Build Coastguard Worker 1020*61c4878aSAndroid Build Coastguard Worker class ExampleI2c : public pw::i2c::Initiator { 1021*61c4878aSAndroid Build Coastguard Worker public: 1022*61c4878aSAndroid Build Coastguard Worker ExampleI2c(int bus_id, I2cOptions options); 1023*61c4878aSAndroid Build Coastguard Worker // ... 1024*61c4878aSAndroid Build Coastguard Worker }; 1025*61c4878aSAndroid Build Coastguard Worker 1026*61c4878aSAndroid Build Coastguard Worker int kBusId; 1027*61c4878aSAndroid Build Coastguard Worker I2cOptions opts; 1028*61c4878aSAndroid Build Coastguard Worker 1029*61c4878aSAndroid Build Coastguard Worker pw::sync::InlineBorrowable<ExampleI2c> i2c(std::in_place, kBusId, opts); 1030*61c4878aSAndroid Build Coastguard Worker 1031*61c4878aSAndroid Build Coastguard Worker pw::Result<ConstByteSpan> ReadI2cData( 1032*61c4878aSAndroid Build Coastguard Worker pw::sync::Borrowable<pw::i2c::Initiator> initiator, 1033*61c4878aSAndroid Build Coastguard Worker ByteSpan buffer); 1034*61c4878aSAndroid Build Coastguard Worker 1035*61c4878aSAndroid Build Coastguard Worker pw::Result<ConstByteSpan> ReadData(ByteSpan buffer) { 1036*61c4878aSAndroid Build Coastguard Worker return ReadI2cData(i2c, buffer); 1037*61c4878aSAndroid Build Coastguard Worker } 1038*61c4878aSAndroid Build Coastguard Worker 1039*61c4878aSAndroid Build Coastguard Worker-------------------- 1040*61c4878aSAndroid Build Coastguard WorkerSignaling Primitives 1041*61c4878aSAndroid Build Coastguard Worker-------------------- 1042*61c4878aSAndroid Build Coastguard WorkerNative signaling primitives tend to vary more compared to critial section locks 1043*61c4878aSAndroid Build Coastguard Workeracross different platforms. For example, although common signaling primtives 1044*61c4878aSAndroid Build Coastguard Workerlike semaphores are in most if not all RTOSes and even POSIX, it was not in the 1045*61c4878aSAndroid Build Coastguard WorkerSTL before C++20. Likewise many C++ developers are surprised that conditional 1046*61c4878aSAndroid Build Coastguard Workervariables tend to not be natively supported on RTOSes. Although you can usually 1047*61c4878aSAndroid Build Coastguard Workerbuild any signaling primitive based on other native signaling primitives, this 1048*61c4878aSAndroid Build Coastguard Workermay come with non-trivial added overhead in ROM, RAM, and execution efficiency. 1049*61c4878aSAndroid Build Coastguard Worker 1050*61c4878aSAndroid Build Coastguard WorkerFor this reason, Pigweed intends to provide some simpler signaling primitives 1051*61c4878aSAndroid Build Coastguard Workerwhich exist to solve a narrow programming need but can be implemented as 1052*61c4878aSAndroid Build Coastguard Workerefficiently as possible for the platform that it is used on. 1053*61c4878aSAndroid Build Coastguard Worker 1054*61c4878aSAndroid Build Coastguard WorkerThis simpler but highly portable class of signaling primitives is intended to 1055*61c4878aSAndroid Build Coastguard Workerensure that a portability efficiency tradeoff does not have to be made up front. 1056*61c4878aSAndroid Build Coastguard WorkerToday this is class of simpler signaling primitives is limited to the 1057*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::ThreadNotification` and 1058*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::TimedThreadNotification`. 1059*61c4878aSAndroid Build Coastguard Worker 1060*61c4878aSAndroid Build Coastguard WorkerThreadNotification 1061*61c4878aSAndroid Build Coastguard Worker================== 1062*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync 1063*61c4878aSAndroid Build Coastguard Worker 1064*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`ThreadNotification` is a synchronization primitive that can be used to 1065*61c4878aSAndroid Build Coastguard Workerpermit a SINGLE thread to block and consume a latching, saturating 1066*61c4878aSAndroid Build Coastguard Workernotification from multiple notifiers. 1067*61c4878aSAndroid Build Coastguard Worker 1068*61c4878aSAndroid Build Coastguard Worker.. Note:: 1069*61c4878aSAndroid Build Coastguard Worker Although only a single thread can block on a :cpp:class:`ThreadNotification` 1070*61c4878aSAndroid Build Coastguard Worker at a time, many instances may be used by a single thread just like binary 1071*61c4878aSAndroid Build Coastguard Worker semaphores. This is in contrast to some native RTOS APIs, such as direct 1072*61c4878aSAndroid Build Coastguard Worker task notifications, which re-use the same state within a thread's context. 1073*61c4878aSAndroid Build Coastguard Worker 1074*61c4878aSAndroid Build Coastguard Worker.. Warning:: 1075*61c4878aSAndroid Build Coastguard Worker This is a single consumer/waiter, multiple producer/notifier API! 1076*61c4878aSAndroid Build Coastguard Worker The acquire APIs must only be invoked by a single consuming thread. As a 1077*61c4878aSAndroid Build Coastguard Worker result, having multiple threads receiving notifications via the acquire API 1078*61c4878aSAndroid Build Coastguard Worker is unsupported. 1079*61c4878aSAndroid Build Coastguard Worker 1080*61c4878aSAndroid Build Coastguard WorkerThis is effectively a subset of the :cpp:class:`BinarySemaphore` API, except 1081*61c4878aSAndroid Build Coastguard Workerthat only a single thread can be notified and block at a time. 1082*61c4878aSAndroid Build Coastguard Worker 1083*61c4878aSAndroid Build Coastguard WorkerThe single consumer aspect of the API permits the use of a smaller and/or 1084*61c4878aSAndroid Build Coastguard Workerfaster native APIs such as direct thread signaling. This should be 1085*61c4878aSAndroid Build Coastguard Workerbacked by the most efficient native primitive for a target, regardless of 1086*61c4878aSAndroid Build Coastguard Workerwhether that is a semaphore, event flag group, condition variable, or something 1087*61c4878aSAndroid Build Coastguard Workerelse. 1088*61c4878aSAndroid Build Coastguard Worker 1089*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`ThreadNotification` is initialized to being empty (latch is not 1090*61c4878aSAndroid Build Coastguard Workerset). 1091*61c4878aSAndroid Build Coastguard Worker 1092*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 1093*61c4878aSAndroid Build Coastguard Worker 1094*61c4878aSAndroid Build Coastguard WorkerGeneric BinarySemaphore-based Backend 1095*61c4878aSAndroid Build Coastguard Worker------------------------------------- 1096*61c4878aSAndroid Build Coastguard WorkerThis module provides a generic backend for 1097*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::ThreadNotification` via 1098*61c4878aSAndroid Build Coastguard Worker``pw_sync:binary_semaphore_thread_notification`` which uses a 1099*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::BinarySemaphore` as the backing primitive. See 1100*61c4878aSAndroid Build Coastguard Worker:ref:`BinarySemaphore <module-pw_sync-binary-semaphore>` for backend 1101*61c4878aSAndroid Build Coastguard Workeravailability. 1102*61c4878aSAndroid Build Coastguard Worker 1103*61c4878aSAndroid Build Coastguard WorkerOptimized Backend 1104*61c4878aSAndroid Build Coastguard Worker----------------- 1105*61c4878aSAndroid Build Coastguard Worker.. list-table:: 1106*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 1107*61c4878aSAndroid Build Coastguard Worker 1108*61c4878aSAndroid Build Coastguard Worker * - Supported on 1109*61c4878aSAndroid Build Coastguard Worker - Optimized backend module 1110*61c4878aSAndroid Build Coastguard Worker * - FreeRTOS 1111*61c4878aSAndroid Build Coastguard Worker - ``pw_sync_freertos:thread_notification`` 1112*61c4878aSAndroid Build Coastguard Worker * - ThreadX 1113*61c4878aSAndroid Build Coastguard Worker - Not possible, use ``pw_sync:binary_semaphore_thread_notification`` 1114*61c4878aSAndroid Build Coastguard Worker * - embOS 1115*61c4878aSAndroid Build Coastguard Worker - Not needed, use ``pw_sync:binary_semaphore_thread_notification`` 1116*61c4878aSAndroid Build Coastguard Worker * - STL 1117*61c4878aSAndroid Build Coastguard Worker - Not planned, use ``pw_sync:binary_semaphore_thread_notification`` 1118*61c4878aSAndroid Build Coastguard Worker * - Baremetal 1119*61c4878aSAndroid Build Coastguard Worker - Planned 1120*61c4878aSAndroid Build Coastguard Worker * - Zephyr 1121*61c4878aSAndroid Build Coastguard Worker - Planned 1122*61c4878aSAndroid Build Coastguard Worker * - CMSIS-RTOS API v2 & RTX5 1123*61c4878aSAndroid Build Coastguard Worker - Planned 1124*61c4878aSAndroid Build Coastguard Worker 1125*61c4878aSAndroid Build Coastguard WorkerC++ 1126*61c4878aSAndroid Build Coastguard Worker--- 1127*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::ThreadNotification 1128*61c4878aSAndroid Build Coastguard Worker :members: 1129*61c4878aSAndroid Build Coastguard Worker 1130*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::ThreadNotification 1131*61c4878aSAndroid Build Coastguard Worker 1132*61c4878aSAndroid Build Coastguard Worker.. list-table:: 1133*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 1134*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 1135*61c4878aSAndroid Build Coastguard Worker 1136*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 1137*61c4878aSAndroid Build Coastguard Worker - Thread 1138*61c4878aSAndroid Build Coastguard Worker - Interrupt 1139*61c4878aSAndroid Build Coastguard Worker - NMI 1140*61c4878aSAndroid Build Coastguard Worker * - :cpp:class:`pw::sync::ThreadNotification::ThreadNotification` 1141*61c4878aSAndroid Build Coastguard Worker - ✔ 1142*61c4878aSAndroid Build Coastguard Worker - 1143*61c4878aSAndroid Build Coastguard Worker - 1144*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::ThreadNotification::~ThreadNotification` 1145*61c4878aSAndroid Build Coastguard Worker - ✔ 1146*61c4878aSAndroid Build Coastguard Worker - 1147*61c4878aSAndroid Build Coastguard Worker - 1148*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`acquire` 1149*61c4878aSAndroid Build Coastguard Worker - ✔ 1150*61c4878aSAndroid Build Coastguard Worker - 1151*61c4878aSAndroid Build Coastguard Worker - 1152*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire` 1153*61c4878aSAndroid Build Coastguard Worker - ✔ 1154*61c4878aSAndroid Build Coastguard Worker - 1155*61c4878aSAndroid Build Coastguard Worker - 1156*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`release` 1157*61c4878aSAndroid Build Coastguard Worker - ✔ 1158*61c4878aSAndroid Build Coastguard Worker - ✔ 1159*61c4878aSAndroid Build Coastguard Worker - 1160*61c4878aSAndroid Build Coastguard Worker 1161*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 1162*61c4878aSAndroid Build Coastguard Worker 1163*61c4878aSAndroid Build Coastguard Worker 1164*61c4878aSAndroid Build Coastguard WorkerExamples in C++ 1165*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^ 1166*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 1167*61c4878aSAndroid Build Coastguard Worker 1168*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/thread_notification.h" 1169*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread_core.h" 1170*61c4878aSAndroid Build Coastguard Worker 1171*61c4878aSAndroid Build Coastguard Worker class FooHandler() : public pw::thread::ThreadCore { 1172*61c4878aSAndroid Build Coastguard Worker // Public API invoked by other threads and/or interrupts. 1173*61c4878aSAndroid Build Coastguard Worker void NewFooAvailable() { 1174*61c4878aSAndroid Build Coastguard Worker new_foo_notification_.release(); 1175*61c4878aSAndroid Build Coastguard Worker } 1176*61c4878aSAndroid Build Coastguard Worker 1177*61c4878aSAndroid Build Coastguard Worker private: 1178*61c4878aSAndroid Build Coastguard Worker pw::sync::ThreadNotification new_foo_notification_; 1179*61c4878aSAndroid Build Coastguard Worker 1180*61c4878aSAndroid Build Coastguard Worker // Thread function. 1181*61c4878aSAndroid Build Coastguard Worker void Run() override { 1182*61c4878aSAndroid Build Coastguard Worker while (true) { 1183*61c4878aSAndroid Build Coastguard Worker new_foo_notification_.acquire(); 1184*61c4878aSAndroid Build Coastguard Worker HandleFoo(); 1185*61c4878aSAndroid Build Coastguard Worker } 1186*61c4878aSAndroid Build Coastguard Worker } 1187*61c4878aSAndroid Build Coastguard Worker 1188*61c4878aSAndroid Build Coastguard Worker void HandleFoo(); 1189*61c4878aSAndroid Build Coastguard Worker } 1190*61c4878aSAndroid Build Coastguard Worker 1191*61c4878aSAndroid Build Coastguard WorkerTimedThreadNotification 1192*61c4878aSAndroid Build Coastguard Worker======================= 1193*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`TimedThreadNotification` is an extension of the 1194*61c4878aSAndroid Build Coastguard Worker:cpp:class:`ThreadNotification` which offers timeout and deadline based 1195*61c4878aSAndroid Build Coastguard Workersemantics. 1196*61c4878aSAndroid Build Coastguard Worker 1197*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`TimedThreadNotification` is initialized to being empty (latch is 1198*61c4878aSAndroid Build Coastguard Workernot set). 1199*61c4878aSAndroid Build Coastguard Worker 1200*61c4878aSAndroid Build Coastguard Worker.. Warning:: 1201*61c4878aSAndroid Build Coastguard Worker This is a single consumer/waiter, multiple producer/notifier API! The 1202*61c4878aSAndroid Build Coastguard Worker acquire APIs must only be invoked by a single consuming thread. As a result, 1203*61c4878aSAndroid Build Coastguard Worker having multiple threads receiving notifications via the acquire API is 1204*61c4878aSAndroid Build Coastguard Worker unsupported. 1205*61c4878aSAndroid Build Coastguard Worker 1206*61c4878aSAndroid Build Coastguard WorkerGeneric BinarySemaphore-based Backend 1207*61c4878aSAndroid Build Coastguard Worker------------------------------------- 1208*61c4878aSAndroid Build Coastguard WorkerThis module provides a generic backend for 1209*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::TimedThreadNotification` via 1210*61c4878aSAndroid Build Coastguard Worker``pw_sync:binary_semaphore_timed_thread_notification`` which uses a 1211*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::BinarySemaphore` as the backing primitive. See 1212*61c4878aSAndroid Build Coastguard Worker:ref:`BinarySemaphore <module-pw_sync-binary-semaphore>` for backend 1213*61c4878aSAndroid Build Coastguard Workeravailability. 1214*61c4878aSAndroid Build Coastguard Worker 1215*61c4878aSAndroid Build Coastguard WorkerOptimized Backend 1216*61c4878aSAndroid Build Coastguard Worker----------------- 1217*61c4878aSAndroid Build Coastguard Worker.. list-table:: 1218*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 1219*61c4878aSAndroid Build Coastguard Worker 1220*61c4878aSAndroid Build Coastguard Worker * - Supported on 1221*61c4878aSAndroid Build Coastguard Worker - Backend module 1222*61c4878aSAndroid Build Coastguard Worker * - FreeRTOS 1223*61c4878aSAndroid Build Coastguard Worker - ``pw_sync_freertos:timed_thread_notification`` 1224*61c4878aSAndroid Build Coastguard Worker * - ThreadX 1225*61c4878aSAndroid Build Coastguard Worker - Not possible, use ``pw_sync:binary_semaphore_timed_thread_notification`` 1226*61c4878aSAndroid Build Coastguard Worker * - embOS 1227*61c4878aSAndroid Build Coastguard Worker - Not needed, use ``pw_sync:binary_semaphore_timed_thread_notification`` 1228*61c4878aSAndroid Build Coastguard Worker * - STL 1229*61c4878aSAndroid Build Coastguard Worker - Not planned, use ``pw_sync:binary_semaphore_timed_thread_notification`` 1230*61c4878aSAndroid Build Coastguard Worker * - Zephyr 1231*61c4878aSAndroid Build Coastguard Worker - Planned 1232*61c4878aSAndroid Build Coastguard Worker * - CMSIS-RTOS API v2 & RTX5 1233*61c4878aSAndroid Build Coastguard Worker - Planned 1234*61c4878aSAndroid Build Coastguard Worker 1235*61c4878aSAndroid Build Coastguard WorkerC++ 1236*61c4878aSAndroid Build Coastguard Worker--- 1237*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::TimedThreadNotification 1238*61c4878aSAndroid Build Coastguard Worker :members: 1239*61c4878aSAndroid Build Coastguard Worker 1240*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::TimedThreadNotification 1241*61c4878aSAndroid Build Coastguard Worker 1242*61c4878aSAndroid Build Coastguard Worker.. list-table:: 1243*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 1244*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 1245*61c4878aSAndroid Build Coastguard Worker 1246*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 1247*61c4878aSAndroid Build Coastguard Worker - Thread 1248*61c4878aSAndroid Build Coastguard Worker - Interrupt 1249*61c4878aSAndroid Build Coastguard Worker - NMI 1250*61c4878aSAndroid Build Coastguard Worker * - :cpp:class:`pw::sync::TimedThreadNotification::TimedThreadNotification` 1251*61c4878aSAndroid Build Coastguard Worker - ✔ 1252*61c4878aSAndroid Build Coastguard Worker - 1253*61c4878aSAndroid Build Coastguard Worker - 1254*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::TimedThreadNotification::~TimedThreadNotification` 1255*61c4878aSAndroid Build Coastguard Worker - ✔ 1256*61c4878aSAndroid Build Coastguard Worker - 1257*61c4878aSAndroid Build Coastguard Worker - 1258*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`acquire` 1259*61c4878aSAndroid Build Coastguard Worker - ✔ 1260*61c4878aSAndroid Build Coastguard Worker - 1261*61c4878aSAndroid Build Coastguard Worker - 1262*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire` 1263*61c4878aSAndroid Build Coastguard Worker - ✔ 1264*61c4878aSAndroid Build Coastguard Worker - 1265*61c4878aSAndroid Build Coastguard Worker - 1266*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire_for` 1267*61c4878aSAndroid Build Coastguard Worker - ✔ 1268*61c4878aSAndroid Build Coastguard Worker - 1269*61c4878aSAndroid Build Coastguard Worker - 1270*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire_until` 1271*61c4878aSAndroid Build Coastguard Worker - ✔ 1272*61c4878aSAndroid Build Coastguard Worker - 1273*61c4878aSAndroid Build Coastguard Worker - 1274*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`release` 1275*61c4878aSAndroid Build Coastguard Worker - ✔ 1276*61c4878aSAndroid Build Coastguard Worker - ✔ 1277*61c4878aSAndroid Build Coastguard Worker - 1278*61c4878aSAndroid Build Coastguard Worker 1279*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 1280*61c4878aSAndroid Build Coastguard Worker 1281*61c4878aSAndroid Build Coastguard WorkerExamples in C++ 1282*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^ 1283*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 1284*61c4878aSAndroid Build Coastguard Worker 1285*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/timed_thread_notification.h" 1286*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread_core.h" 1287*61c4878aSAndroid Build Coastguard Worker 1288*61c4878aSAndroid Build Coastguard Worker class FooHandler() : public pw::thread::ThreadCore { 1289*61c4878aSAndroid Build Coastguard Worker // Public API invoked by other threads and/or interrupts. 1290*61c4878aSAndroid Build Coastguard Worker void NewFooAvailable() { 1291*61c4878aSAndroid Build Coastguard Worker new_foo_notification_.release(); 1292*61c4878aSAndroid Build Coastguard Worker } 1293*61c4878aSAndroid Build Coastguard Worker 1294*61c4878aSAndroid Build Coastguard Worker private: 1295*61c4878aSAndroid Build Coastguard Worker pw::sync::TimedThreadNotification new_foo_notification_; 1296*61c4878aSAndroid Build Coastguard Worker 1297*61c4878aSAndroid Build Coastguard Worker // Thread function. 1298*61c4878aSAndroid Build Coastguard Worker void Run() override { 1299*61c4878aSAndroid Build Coastguard Worker while (true) { 1300*61c4878aSAndroid Build Coastguard Worker if (new_foo_notification_.try_acquire_for(kNotificationTimeout)) { 1301*61c4878aSAndroid Build Coastguard Worker HandleFoo(); 1302*61c4878aSAndroid Build Coastguard Worker } 1303*61c4878aSAndroid Build Coastguard Worker DoOtherStuff(); 1304*61c4878aSAndroid Build Coastguard Worker } 1305*61c4878aSAndroid Build Coastguard Worker } 1306*61c4878aSAndroid Build Coastguard Worker 1307*61c4878aSAndroid Build Coastguard Worker void HandleFoo(); 1308*61c4878aSAndroid Build Coastguard Worker void DoOtherStuff(); 1309*61c4878aSAndroid Build Coastguard Worker } 1310*61c4878aSAndroid Build Coastguard Worker 1311*61c4878aSAndroid Build Coastguard WorkerCountingSemaphore 1312*61c4878aSAndroid Build Coastguard Worker================= 1313*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync 1314*61c4878aSAndroid Build Coastguard Worker 1315*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`CountingSemaphore` is a synchronization primitive that can be 1316*61c4878aSAndroid Build Coastguard Workerused for counting events and/or resource management where receiver(s) can block 1317*61c4878aSAndroid Build Coastguard Workeron acquire until notifier(s) signal by invoking release. 1318*61c4878aSAndroid Build Coastguard Worker 1319*61c4878aSAndroid Build Coastguard WorkerNote that unlike :cpp:class:`Mutex`, priority inheritance is not used by 1320*61c4878aSAndroid Build Coastguard Workersemaphores meaning semaphores are subject to unbounded priority inversions. Due 1321*61c4878aSAndroid Build Coastguard Workerto this, Pigweed does not recommend semaphores for mutual exclusion. 1322*61c4878aSAndroid Build Coastguard Worker 1323*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`CountingSemaphore` is initialized to being empty or having no 1324*61c4878aSAndroid Build Coastguard Workertokens. 1325*61c4878aSAndroid Build Coastguard Worker 1326*61c4878aSAndroid Build Coastguard WorkerThe entire API is thread safe, but only a subset is interrupt safe. 1327*61c4878aSAndroid Build Coastguard Worker 1328*61c4878aSAndroid Build Coastguard Worker.. Note:: 1329*61c4878aSAndroid Build Coastguard Worker If there is only a single consuming thread, use a 1330*61c4878aSAndroid Build Coastguard Worker :cpp:class:`ThreadNotification` instead which can be much more efficient on 1331*61c4878aSAndroid Build Coastguard Worker some RTOSes such as FreeRTOS. 1332*61c4878aSAndroid Build Coastguard Worker 1333*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 1334*61c4878aSAndroid Build Coastguard Worker 1335*61c4878aSAndroid Build Coastguard Worker.. Warning:: 1336*61c4878aSAndroid Build Coastguard Worker Releasing multiple tokens is often not natively supported, meaning you may 1337*61c4878aSAndroid Build Coastguard Worker end up invoking the native kernel API many times, i.e. once per token you 1338*61c4878aSAndroid Build Coastguard Worker are releasing! 1339*61c4878aSAndroid Build Coastguard Worker 1340*61c4878aSAndroid Build Coastguard Worker.. list-table:: 1341*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 1342*61c4878aSAndroid Build Coastguard Worker 1343*61c4878aSAndroid Build Coastguard Worker * - Supported on 1344*61c4878aSAndroid Build Coastguard Worker - Backend module 1345*61c4878aSAndroid Build Coastguard Worker * - FreeRTOS 1346*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_freertos` 1347*61c4878aSAndroid Build Coastguard Worker * - ThreadX 1348*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_threadx` 1349*61c4878aSAndroid Build Coastguard Worker * - embOS 1350*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_embos` 1351*61c4878aSAndroid Build Coastguard Worker * - STL 1352*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_stl` 1353*61c4878aSAndroid Build Coastguard Worker * - Zephyr 1354*61c4878aSAndroid Build Coastguard Worker - Planned 1355*61c4878aSAndroid Build Coastguard Worker * - CMSIS-RTOS API v2 & RTX5 1356*61c4878aSAndroid Build Coastguard Worker - Planned 1357*61c4878aSAndroid Build Coastguard Worker 1358*61c4878aSAndroid Build Coastguard WorkerC++ 1359*61c4878aSAndroid Build Coastguard Worker--- 1360*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::CountingSemaphore 1361*61c4878aSAndroid Build Coastguard Worker :members: 1362*61c4878aSAndroid Build Coastguard Worker 1363*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::CountingSemaphore 1364*61c4878aSAndroid Build Coastguard Worker 1365*61c4878aSAndroid Build Coastguard Worker.. list-table:: 1366*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 1367*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 1368*61c4878aSAndroid Build Coastguard Worker 1369*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 1370*61c4878aSAndroid Build Coastguard Worker - Thread 1371*61c4878aSAndroid Build Coastguard Worker - Interrupt 1372*61c4878aSAndroid Build Coastguard Worker - NMI 1373*61c4878aSAndroid Build Coastguard Worker * - :cpp:class:`pw::sync::CountingSemaphore::CountingSemaphore` 1374*61c4878aSAndroid Build Coastguard Worker - ✔ 1375*61c4878aSAndroid Build Coastguard Worker - 1376*61c4878aSAndroid Build Coastguard Worker - 1377*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::CountingSemaphore::~CountingSemaphore` 1378*61c4878aSAndroid Build Coastguard Worker - ✔ 1379*61c4878aSAndroid Build Coastguard Worker - 1380*61c4878aSAndroid Build Coastguard Worker - 1381*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`acquire` 1382*61c4878aSAndroid Build Coastguard Worker - ✔ 1383*61c4878aSAndroid Build Coastguard Worker - 1384*61c4878aSAndroid Build Coastguard Worker - 1385*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire` 1386*61c4878aSAndroid Build Coastguard Worker - ✔ 1387*61c4878aSAndroid Build Coastguard Worker - ✔ 1388*61c4878aSAndroid Build Coastguard Worker - 1389*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire_for` 1390*61c4878aSAndroid Build Coastguard Worker - ✔ 1391*61c4878aSAndroid Build Coastguard Worker - 1392*61c4878aSAndroid Build Coastguard Worker - 1393*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire_until` 1394*61c4878aSAndroid Build Coastguard Worker - ✔ 1395*61c4878aSAndroid Build Coastguard Worker - 1396*61c4878aSAndroid Build Coastguard Worker - 1397*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`release` 1398*61c4878aSAndroid Build Coastguard Worker - ✔ 1399*61c4878aSAndroid Build Coastguard Worker - ✔ 1400*61c4878aSAndroid Build Coastguard Worker - 1401*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`max` 1402*61c4878aSAndroid Build Coastguard Worker - ✔ 1403*61c4878aSAndroid Build Coastguard Worker - ✔ 1404*61c4878aSAndroid Build Coastguard Worker - ✔ 1405*61c4878aSAndroid Build Coastguard Worker 1406*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 1407*61c4878aSAndroid Build Coastguard Worker 1408*61c4878aSAndroid Build Coastguard WorkerExamples in C++ 1409*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^ 1410*61c4878aSAndroid Build Coastguard WorkerAs an example, a counting sempahore can be useful to run periodic tasks at 1411*61c4878aSAndroid Build Coastguard Workerfrequencies near or higher than the system clock tick rate in a way which lets 1412*61c4878aSAndroid Build Coastguard Workeryou detect whether you ever fall behind. 1413*61c4878aSAndroid Build Coastguard Worker 1414*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 1415*61c4878aSAndroid Build Coastguard Worker 1416*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/counting_semaphore.h" 1417*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread_core.h" 1418*61c4878aSAndroid Build Coastguard Worker 1419*61c4878aSAndroid Build Coastguard Worker class PeriodicWorker() : public pw::thread::ThreadCore { 1420*61c4878aSAndroid Build Coastguard Worker // Public API invoked by a higher frequency timer interrupt. 1421*61c4878aSAndroid Build Coastguard Worker void TimeToExecute() { 1422*61c4878aSAndroid Build Coastguard Worker periodic_run_semaphore_.release(); 1423*61c4878aSAndroid Build Coastguard Worker } 1424*61c4878aSAndroid Build Coastguard Worker 1425*61c4878aSAndroid Build Coastguard Worker private: 1426*61c4878aSAndroid Build Coastguard Worker pw::sync::CountingSemaphore periodic_run_semaphore_; 1427*61c4878aSAndroid Build Coastguard Worker 1428*61c4878aSAndroid Build Coastguard Worker // Thread function. 1429*61c4878aSAndroid Build Coastguard Worker void Run() override { 1430*61c4878aSAndroid Build Coastguard Worker while (true) { 1431*61c4878aSAndroid Build Coastguard Worker size_t behind_by_n_cycles = 0; 1432*61c4878aSAndroid Build Coastguard Worker periodic_run_semaphore_.acquire(); // Wait to run until it's time. 1433*61c4878aSAndroid Build Coastguard Worker while (periodic_run_semaphore_.try_acquire()) { 1434*61c4878aSAndroid Build Coastguard Worker ++behind_by_n_cycles; 1435*61c4878aSAndroid Build Coastguard Worker } 1436*61c4878aSAndroid Build Coastguard Worker if (behind_by_n_cycles > 0) { 1437*61c4878aSAndroid Build Coastguard Worker PW_LOG_WARNING("Not keeping up, behind by %d cycles", 1438*61c4878aSAndroid Build Coastguard Worker behind_by_n_cycles); 1439*61c4878aSAndroid Build Coastguard Worker } 1440*61c4878aSAndroid Build Coastguard Worker DoPeriodicWork(); 1441*61c4878aSAndroid Build Coastguard Worker } 1442*61c4878aSAndroid Build Coastguard Worker } 1443*61c4878aSAndroid Build Coastguard Worker 1444*61c4878aSAndroid Build Coastguard Worker void DoPeriodicWork(); 1445*61c4878aSAndroid Build Coastguard Worker } 1446*61c4878aSAndroid Build Coastguard Worker 1447*61c4878aSAndroid Build Coastguard Worker.. _module-pw_sync-binary-semaphore: 1448*61c4878aSAndroid Build Coastguard Worker 1449*61c4878aSAndroid Build Coastguard WorkerBinarySemaphore 1450*61c4878aSAndroid Build Coastguard Worker=============== 1451*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync 1452*61c4878aSAndroid Build Coastguard Worker 1453*61c4878aSAndroid Build Coastguard Worker:cpp:class:`BinarySemaphore` is a specialization of CountingSemaphore with an 1454*61c4878aSAndroid Build Coastguard Workerarbitrary token limit of 1. Note that that ``max()`` is >= 1, meaning it may be 1455*61c4878aSAndroid Build Coastguard Workerreleased up to ``max()`` times but only acquired once for those N releases. 1456*61c4878aSAndroid Build Coastguard Worker 1457*61c4878aSAndroid Build Coastguard WorkerImplementations of :cpp:class:`BinarySemaphore` are typically more 1458*61c4878aSAndroid Build Coastguard Workerefficient than the default implementation of :cpp:class:`CountingSemaphore`. 1459*61c4878aSAndroid Build Coastguard Worker 1460*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`BinarySemaphore` is initialized to being empty or having no 1461*61c4878aSAndroid Build Coastguard Workertokens. 1462*61c4878aSAndroid Build Coastguard Worker 1463*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 1464*61c4878aSAndroid Build Coastguard Worker 1465*61c4878aSAndroid Build Coastguard WorkerThe entire API is thread safe, but only a subset is interrupt safe. 1466*61c4878aSAndroid Build Coastguard Worker 1467*61c4878aSAndroid Build Coastguard Worker.. Note:: 1468*61c4878aSAndroid Build Coastguard Worker If there is only a single consuming thread, use a 1469*61c4878aSAndroid Build Coastguard Worker :cpp:class:`ThreadNotification` instead which can be much more efficient on 1470*61c4878aSAndroid Build Coastguard Worker some RTOSes such as FreeRTOS. 1471*61c4878aSAndroid Build Coastguard Worker 1472*61c4878aSAndroid Build Coastguard Worker.. list-table:: 1473*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 1474*61c4878aSAndroid Build Coastguard Worker 1475*61c4878aSAndroid Build Coastguard Worker * - Supported on 1476*61c4878aSAndroid Build Coastguard Worker - Backend module 1477*61c4878aSAndroid Build Coastguard Worker * - FreeRTOS 1478*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_freertos` 1479*61c4878aSAndroid Build Coastguard Worker * - ThreadX 1480*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_threadx` 1481*61c4878aSAndroid Build Coastguard Worker * - embOS 1482*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_embos` 1483*61c4878aSAndroid Build Coastguard Worker * - STL 1484*61c4878aSAndroid Build Coastguard Worker - :ref:`module-pw_sync_stl` 1485*61c4878aSAndroid Build Coastguard Worker * - Zephyr 1486*61c4878aSAndroid Build Coastguard Worker - Planned 1487*61c4878aSAndroid Build Coastguard Worker * - CMSIS-RTOS API v2 & RTX5 1488*61c4878aSAndroid Build Coastguard Worker - Planned 1489*61c4878aSAndroid Build Coastguard Worker 1490*61c4878aSAndroid Build Coastguard WorkerC++ 1491*61c4878aSAndroid Build Coastguard Worker--- 1492*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::BinarySemaphore 1493*61c4878aSAndroid Build Coastguard Worker :members: 1494*61c4878aSAndroid Build Coastguard Worker 1495*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::BinarySemaphore 1496*61c4878aSAndroid Build Coastguard Worker 1497*61c4878aSAndroid Build Coastguard Worker.. list-table:: 1498*61c4878aSAndroid Build Coastguard Worker :widths: 70 10 10 10 1499*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 1500*61c4878aSAndroid Build Coastguard Worker 1501*61c4878aSAndroid Build Coastguard Worker * - Safe to use in context 1502*61c4878aSAndroid Build Coastguard Worker - Thread 1503*61c4878aSAndroid Build Coastguard Worker - Interrupt 1504*61c4878aSAndroid Build Coastguard Worker - NMI 1505*61c4878aSAndroid Build Coastguard Worker * - :cpp:class:`pw::sync::BinarySemaphore::BinarySemaphore` 1506*61c4878aSAndroid Build Coastguard Worker - ✔ 1507*61c4878aSAndroid Build Coastguard Worker - 1508*61c4878aSAndroid Build Coastguard Worker - 1509*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`pw::sync::BinarySemaphore::~BinarySemaphore` 1510*61c4878aSAndroid Build Coastguard Worker - ✔ 1511*61c4878aSAndroid Build Coastguard Worker - 1512*61c4878aSAndroid Build Coastguard Worker - 1513*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`acquire` 1514*61c4878aSAndroid Build Coastguard Worker - ✔ 1515*61c4878aSAndroid Build Coastguard Worker - 1516*61c4878aSAndroid Build Coastguard Worker - 1517*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire` 1518*61c4878aSAndroid Build Coastguard Worker - ✔ 1519*61c4878aSAndroid Build Coastguard Worker - ✔ 1520*61c4878aSAndroid Build Coastguard Worker - 1521*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire_for` 1522*61c4878aSAndroid Build Coastguard Worker - ✔ 1523*61c4878aSAndroid Build Coastguard Worker - 1524*61c4878aSAndroid Build Coastguard Worker - 1525*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`try_acquire_until` 1526*61c4878aSAndroid Build Coastguard Worker - ✔ 1527*61c4878aSAndroid Build Coastguard Worker - 1528*61c4878aSAndroid Build Coastguard Worker - 1529*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`release` 1530*61c4878aSAndroid Build Coastguard Worker - ✔ 1531*61c4878aSAndroid Build Coastguard Worker - ✔ 1532*61c4878aSAndroid Build Coastguard Worker - 1533*61c4878aSAndroid Build Coastguard Worker * - :cpp:func:`max` 1534*61c4878aSAndroid Build Coastguard Worker - ✔ 1535*61c4878aSAndroid Build Coastguard Worker - ✔ 1536*61c4878aSAndroid Build Coastguard Worker - ✔ 1537*61c4878aSAndroid Build Coastguard Worker 1538*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop:: 1539*61c4878aSAndroid Build Coastguard Worker 1540*61c4878aSAndroid Build Coastguard WorkerExamples in C++ 1541*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^ 1542*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 1543*61c4878aSAndroid Build Coastguard Worker 1544*61c4878aSAndroid Build Coastguard Worker #include "pw_sync/binary_semaphore.h" 1545*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread_core.h" 1546*61c4878aSAndroid Build Coastguard Worker 1547*61c4878aSAndroid Build Coastguard Worker class FooHandler() : public pw::thread::ThreadCore { 1548*61c4878aSAndroid Build Coastguard Worker // Public API invoked by other threads and/or interrupts. 1549*61c4878aSAndroid Build Coastguard Worker void NewFooAvailable() { 1550*61c4878aSAndroid Build Coastguard Worker new_foo_semaphore_.release(); 1551*61c4878aSAndroid Build Coastguard Worker } 1552*61c4878aSAndroid Build Coastguard Worker 1553*61c4878aSAndroid Build Coastguard Worker private: 1554*61c4878aSAndroid Build Coastguard Worker pw::sync::BinarySemaphore new_foo_semaphore_; 1555*61c4878aSAndroid Build Coastguard Worker 1556*61c4878aSAndroid Build Coastguard Worker // Thread function. 1557*61c4878aSAndroid Build Coastguard Worker void Run() override { 1558*61c4878aSAndroid Build Coastguard Worker while (true) { 1559*61c4878aSAndroid Build Coastguard Worker if (new_foo_semaphore_.try_acquire_for(kNotificationTimeout)) { 1560*61c4878aSAndroid Build Coastguard Worker HandleFoo(); 1561*61c4878aSAndroid Build Coastguard Worker } 1562*61c4878aSAndroid Build Coastguard Worker DoOtherStuff(); 1563*61c4878aSAndroid Build Coastguard Worker } 1564*61c4878aSAndroid Build Coastguard Worker } 1565*61c4878aSAndroid Build Coastguard Worker 1566*61c4878aSAndroid Build Coastguard Worker void HandleFoo(); 1567*61c4878aSAndroid Build Coastguard Worker void DoOtherStuff(); 1568*61c4878aSAndroid Build Coastguard Worker } 1569*61c4878aSAndroid Build Coastguard Worker 1570*61c4878aSAndroid Build Coastguard Worker.. _module-pw_sync-condition-variables: 1571*61c4878aSAndroid Build Coastguard Worker 1572*61c4878aSAndroid Build Coastguard WorkerCondition Variables 1573*61c4878aSAndroid Build Coastguard Worker===================== 1574*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::ConditionVariable` provides a condition variable 1575*61c4878aSAndroid Build Coastguard Workerimplementation that provides semantics and an API very similar to 1576*61c4878aSAndroid Build Coastguard Worker`std::condition_variable 1577*61c4878aSAndroid Build Coastguard Worker<https://en.cppreference.com/w/cpp/thread/condition_variable>`_ in the C++ 1578*61c4878aSAndroid Build Coastguard WorkerStandard Library. 1579*61c4878aSAndroid Build Coastguard Worker 1580*61c4878aSAndroid Build Coastguard Worker.. warning:: 1581*61c4878aSAndroid Build Coastguard Worker Condition variables are not a good abstraction for embedded due to spurious 1582*61c4878aSAndroid Build Coastguard Worker wakeups. As a result, the only ``pw_sync`` backend provided by Pigweed that 1583*61c4878aSAndroid Build Coastguard Worker supports condition variables is :ref:`module-pw_sync_stl`. Consider using 1584*61c4878aSAndroid Build Coastguard Worker a ``ThreadNotification`` instead, as these do not cause spurious wakeups and 1585*61c4878aSAndroid Build Coastguard Worker can be used in an interrupt context. 1586*61c4878aSAndroid Build Coastguard Worker 1587*61c4878aSAndroid Build Coastguard WorkerLimitations 1588*61c4878aSAndroid Build Coastguard Worker----------- 1589*61c4878aSAndroid Build Coastguard WorkerAs a blocking operation, condition variables should not be waited on in an 1590*61c4878aSAndroid Build Coastguard Workerinterrupt context. Less intuitively, condition variables should not be notified 1591*61c4878aSAndroid Build Coastguard Workerin an interrupt context. Notifying a condition variable involves checking the 1592*61c4878aSAndroid Build Coastguard Workercorresponding condition to decide whether to resume waiting threads. This check 1593*61c4878aSAndroid Build Coastguard Workercan happen either on the signaling thread or the waiting thread: 1594*61c4878aSAndroid Build Coastguard Worker 1595*61c4878aSAndroid Build Coastguard Worker- If the signaling thread checks the condition, it needs to exclusively access 1596*61c4878aSAndroid Build Coastguard Worker the waiters and their associated conditions. Access to this list must be 1597*61c4878aSAndroid Build Coastguard Worker synchronized with calls to wait on the variable. Additional state checked by 1598*61c4878aSAndroid Build Coastguard Worker the conditions may also need to be synchronized. As a result, checking the 1599*61c4878aSAndroid Build Coastguard Worker conditions on the signaling thread may involve blocking and is not suitable 1600*61c4878aSAndroid Build Coastguard Worker for a interrupt context. 1601*61c4878aSAndroid Build Coastguard Worker- If the waiting threads check their conditions, access to the list of waiters 1602*61c4878aSAndroid Build Coastguard Worker still needs to be synchronized. Additionally, a thread may find that its 1603*61c4878aSAndroid Build Coastguard Worker condition is not satisfied, and that it needs to resume waiting. Waking 1604*61c4878aSAndroid Build Coastguard Worker threads only to resume waiting is costly in terms of both power and 1605*61c4878aSAndroid Build Coastguard Worker performance. 1606*61c4878aSAndroid Build Coastguard Worker 1607*61c4878aSAndroid Build Coastguard WorkerThe second approach leads to spurious wakeups in a thread context as well. The 1608*61c4878aSAndroid Build Coastguard Workerfirst approach may also have spurious wakeups if the condition changes between 1609*61c4878aSAndroid Build Coastguard Workersignaling the waiter and the waiter reacquiring its lock. 1610*61c4878aSAndroid Build Coastguard Worker 1611*61c4878aSAndroid Build Coastguard Worker.. toctree:: 1612*61c4878aSAndroid Build Coastguard Worker :hidden: 1613*61c4878aSAndroid Build Coastguard Worker :maxdepth: 1 1614*61c4878aSAndroid Build Coastguard Worker 1615*61c4878aSAndroid Build Coastguard Worker Backends <backends> 1616