1*61c4878aSAndroid Build Coastguard Worker.. _seed-0128: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker================================= 4*61c4878aSAndroid Build Coastguard Worker0128: Abstracting Thread Creation 5*61c4878aSAndroid Build Coastguard Worker================================= 6*61c4878aSAndroid Build Coastguard Worker.. seed:: 7*61c4878aSAndroid Build Coastguard Worker :number: 128 8*61c4878aSAndroid Build Coastguard Worker :name: Abstracting Thread Creation 9*61c4878aSAndroid Build Coastguard Worker :status: Accepted 10*61c4878aSAndroid Build Coastguard Worker :proposal_date: 2024-04-25 11*61c4878aSAndroid Build Coastguard Worker :cl: 206670 12*61c4878aSAndroid Build Coastguard Worker :authors: Wyatt Hepler 13*61c4878aSAndroid Build Coastguard Worker :facilitator: Taylor Cramer 14*61c4878aSAndroid Build Coastguard Worker 15*61c4878aSAndroid Build Coastguard Worker------- 16*61c4878aSAndroid Build Coastguard WorkerSummary 17*61c4878aSAndroid Build Coastguard Worker------- 18*61c4878aSAndroid Build Coastguard WorkerThis SEED proposes supporting cross-platform thread creation with ``pw_thread``. 19*61c4878aSAndroid Build Coastguard WorkerIt introduces APIs for creating a thread without referring to the specific OS / 20*61c4878aSAndroid Build Coastguard Worker``pw_thread`` backend. This dramatically simplifies thread creation for the 21*61c4878aSAndroid Build Coastguard Worker:ref:`vast majority <seed-0128-thread-config-survey>` of production use cases. 22*61c4878aSAndroid Build Coastguard WorkerIt does so without sacrificing configurability or limiting users in any way. 23*61c4878aSAndroid Build Coastguard Worker 24*61c4878aSAndroid Build Coastguard WorkerKey new features 25*61c4878aSAndroid Build Coastguard Worker================ 26*61c4878aSAndroid Build Coastguard Worker- ``pw::ThreadAttrs`` describes cross-platform thread attributes: 27*61c4878aSAndroid Build Coastguard Worker 28*61c4878aSAndroid Build Coastguard Worker - Thread name. 29*61c4878aSAndroid Build Coastguard Worker - Stack size. 30*61c4878aSAndroid Build Coastguard Worker - ``pw::ThreadPriority`` to represent a thread's priority. 31*61c4878aSAndroid Build Coastguard Worker 32*61c4878aSAndroid Build Coastguard Worker- ``pw::ThreadContext`` represents the resources required to run one thread. 33*61c4878aSAndroid Build Coastguard Worker- ``pw::Thread`` can be started from ``ThreadAttrs`` and ``ThreadContext``. 34*61c4878aSAndroid Build Coastguard Worker- Additions to the ``pw_thread`` facade to support the new functionality. 35*61c4878aSAndroid Build Coastguard Worker 36*61c4878aSAndroid Build Coastguard Workerpw_thread API overview 37*61c4878aSAndroid Build Coastguard Worker====================== 38*61c4878aSAndroid Build Coastguard WorkerWith these changes, the key pw_thread features are as follows: 39*61c4878aSAndroid Build Coastguard Worker 40*61c4878aSAndroid Build Coastguard Worker.. topic:: Thread creation API 41*61c4878aSAndroid Build Coastguard Worker 42*61c4878aSAndroid Build Coastguard Worker Key Types 43*61c4878aSAndroid Build Coastguard Worker 44*61c4878aSAndroid Build Coastguard Worker - ``pw::Thread`` -- Thread handle. The thread might be unstarted, running, or 45*61c4878aSAndroid Build Coastguard Worker completed. 46*61c4878aSAndroid Build Coastguard Worker - ``pw::thread::Options`` -- Base class for platform-specific thread options. 47*61c4878aSAndroid Build Coastguard Worker priority. 48*61c4878aSAndroid Build Coastguard Worker - ``pw::ThreadAttrs`` -- Generic thread attributes: name, size, priority. 49*61c4878aSAndroid Build Coastguard Worker may include stack. 50*61c4878aSAndroid Build Coastguard Worker - ``pw::ThreadPriority`` -- Generic thread priority, with relative modifiers. 51*61c4878aSAndroid Build Coastguard Worker - ``pw::ThreadContext`` -- Generic thread resources. Depending on backend, 52*61c4878aSAndroid Build Coastguard Worker - ``pw::ThreadStack`` -- Optionally specify a thread stack separately from 53*61c4878aSAndroid Build Coastguard Worker the context. 54*61c4878aSAndroid Build Coastguard Worker 55*61c4878aSAndroid Build Coastguard Worker Key methods 56*61c4878aSAndroid Build Coastguard Worker 57*61c4878aSAndroid Build Coastguard Worker - ``pw::Thread`` -- Constructor, ``join()``. 58*61c4878aSAndroid Build Coastguard Worker - ``pw::ThreadAttrs`` -- ``set_name(name)``, ``set_priority(priority)``, 59*61c4878aSAndroid Build Coastguard Worker ``set_stack_size_bytes(bytes)``. 60*61c4878aSAndroid Build Coastguard Worker - ``pw::ThreadPriority`` -- ``Low()``, ``Medium()``, ``High()``, 61*61c4878aSAndroid Build Coastguard Worker ``NextHigher()``, ``NextLower()``, etc. 62*61c4878aSAndroid Build Coastguard Worker 63*61c4878aSAndroid Build Coastguard WorkerExample 64*61c4878aSAndroid Build Coastguard Worker======= 65*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 66*61c4878aSAndroid Build Coastguard Worker 67*61c4878aSAndroid Build Coastguard Worker // "example_project/threads.h" 68*61c4878aSAndroid Build Coastguard Worker 69*61c4878aSAndroid Build Coastguard Worker // Define thread attributes for the main thread. 70*61c4878aSAndroid Build Coastguard Worker constexpr pw::ThreadAttrs kMainThread = pw::ThreadAttrs() 71*61c4878aSAndroid Build Coastguard Worker .set_name("app") 72*61c4878aSAndroid Build Coastguard Worker .set_priority(pw::ThreadPriority::Medium()), 73*61c4878aSAndroid Build Coastguard Worker .set_stack_size_bytes(MY_PROJECT_MAIN_STACK_SIZE_BYTES); 74*61c4878aSAndroid Build Coastguard Worker 75*61c4878aSAndroid Build Coastguard Worker // Define attributes for another thread, based on kMainThread. 76*61c4878aSAndroid Build Coastguard Worker constexpr pw::ThreadAttrs kLogThread = pw::ThreadAttrs(kMainThread) 77*61c4878aSAndroid Build Coastguard Worker .set_name("logging") 78*61c4878aSAndroid Build Coastguard Worker .set_priority_next_lower(); 79*61c4878aSAndroid Build Coastguard Worker 80*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 81*61c4878aSAndroid Build Coastguard Worker 82*61c4878aSAndroid Build Coastguard Worker // "example_project/main.cc" 83*61c4878aSAndroid Build Coastguard Worker 84*61c4878aSAndroid Build Coastguard Worker #include "example_project/threads.h" 85*61c4878aSAndroid Build Coastguard Worker 86*61c4878aSAndroid Build Coastguard Worker // Declare a thread context that can be used to start a thread. 87*61c4878aSAndroid Build Coastguard Worker pw::ThreadContext<MY_PROJECT_APP_STACK_SIZE_BYTES> app_thread_context; 88*61c4878aSAndroid Build Coastguard Worker 89*61c4878aSAndroid Build Coastguard Worker // Declare thread contexts associated with specific ThreadAttrs. 90*61c4878aSAndroid Build Coastguard Worker pw::ThreadContext<kMainThread> main_thread_context; 91*61c4878aSAndroid Build Coastguard Worker pw::ThreadContext<kLogThread> log_thread_context; 92*61c4878aSAndroid Build Coastguard Worker 93*61c4878aSAndroid Build Coastguard Worker // Thread handle for a non-detached thread. 94*61c4878aSAndroid Build Coastguard Worker pw::Thread app_thread; 95*61c4878aSAndroid Build Coastguard Worker 96*61c4878aSAndroid Build Coastguard Worker void StartThreads() { 97*61c4878aSAndroid Build Coastguard Worker // Start the main and logging threads. 98*61c4878aSAndroid Build Coastguard Worker pw::Thread(main_thread_context, MainThreadBody).detach(); 99*61c4878aSAndroid Build Coastguard Worker pw::Thread(log_thread_context, LoggingThreadBody).detach(); 100*61c4878aSAndroid Build Coastguard Worker 101*61c4878aSAndroid Build Coastguard Worker // Start an app thread that uses the app_thread_context. Since the stack size 102*61c4878aSAndroid Build Coastguard Worker // is not specified, the full stack provided by app_thread_context is used. 103*61c4878aSAndroid Build Coastguard Worker app_thread = pw::Thread( 104*61c4878aSAndroid Build Coastguard Worker app_thread_context, pw::ThreadAttrs().set_name("app 1"), AppThreadBody1); 105*61c4878aSAndroid Build Coastguard Worker } 106*61c4878aSAndroid Build Coastguard Worker 107*61c4878aSAndroid Build Coastguard Worker void MainThreadBody() { 108*61c4878aSAndroid Build Coastguard Worker // Join the "app 1" thread and reuse the app_thread_context for a new thread. 109*61c4878aSAndroid Build Coastguard Worker app_thread.join(); 110*61c4878aSAndroid Build Coastguard Worker app_thread = pw::Thread( 111*61c4878aSAndroid Build Coastguard Worker app_thread_context, pw::ThreadAttrs().set_name("app 2"), AppThreadBody2); 112*61c4878aSAndroid Build Coastguard Worker ... 113*61c4878aSAndroid Build Coastguard Worker } 114*61c4878aSAndroid Build Coastguard Worker 115*61c4878aSAndroid Build Coastguard Worker---------- 116*61c4878aSAndroid Build Coastguard WorkerMotivation 117*61c4878aSAndroid Build Coastguard Worker---------- 118*61c4878aSAndroid Build Coastguard WorkerPigweed's ``pw_thread`` module does not support cross-platform thread creation. 119*61c4878aSAndroid Build Coastguard WorkerInstead, threads must be created by instantiating a 120*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::thread::Options` specific to the thread backend. For example, to 121*61c4878aSAndroid Build Coastguard Workercreate a FreeRTOS thread, one must instantiate a 122*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::thread::freertos::Options` and configure it with a 123*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::thread::freertos::Context` 124*61c4878aSAndroid Build Coastguard Worker 125*61c4878aSAndroid Build Coastguard WorkerCross-platform thread creation was intentionally avoided in the ``pw_thread`` 126*61c4878aSAndroid Build Coastguard WorkerAPI. It is not possible to specify thread attributes in a truly generic, 127*61c4878aSAndroid Build Coastguard Workerportable way. Every OS/RTOS exposes a different set of thread parameters, and 128*61c4878aSAndroid Build Coastguard Workersettings for one platform may behave completely differently or not exist on 129*61c4878aSAndroid Build Coastguard Workeranother. 130*61c4878aSAndroid Build Coastguard Worker 131*61c4878aSAndroid Build Coastguard WorkerCross-platform thread creation may not be possible to do perfectly, but avoiding 132*61c4878aSAndroid Build Coastguard Workerit has significant downsides. 133*61c4878aSAndroid Build Coastguard Worker 134*61c4878aSAndroid Build Coastguard Worker- The current APIs optimize for control at the expense of usability. Thread 135*61c4878aSAndroid Build Coastguard Worker creation is complex. 136*61c4878aSAndroid Build Coastguard Worker- Developers always have to deal with the full complexity of thread creation, 137*61c4878aSAndroid Build Coastguard Worker even for simple cases or when just getting started. 138*61c4878aSAndroid Build Coastguard Worker- Users must learn a slightly different API for each RTOS. The full ``Thread`` 139*61c4878aSAndroid Build Coastguard Worker API cannot be documented in one place. 140*61c4878aSAndroid Build Coastguard Worker- Cross-platform code that creates threads must call functions that return 141*61c4878aSAndroid Build Coastguard Worker ``pw::thread::Options``. Each platform implements the functions as needed. 142*61c4878aSAndroid Build Coastguard Worker This requires exposing threads in the public API. Libraries such as 143*61c4878aSAndroid Build Coastguard Worker :ref:`module-pw_system` cannot add internal threads without breaking their 144*61c4878aSAndroid Build Coastguard Worker users. 145*61c4878aSAndroid Build Coastguard Worker- Code for creating ``pw::thread::Options`` must be duplicated for each 146*61c4878aSAndroid Build Coastguard Worker platform. 147*61c4878aSAndroid Build Coastguard Worker- Projects avoid writing cross-platform code and tests due to the complexity of 148*61c4878aSAndroid Build Coastguard Worker thread creation. 149*61c4878aSAndroid Build Coastguard Worker 150*61c4878aSAndroid Build Coastguard Worker``pw_system`` and threads 151*61c4878aSAndroid Build Coastguard Worker========================= 152*61c4878aSAndroid Build Coastguard WorkerCurrently, running :ref:`module-pw_system` requires writing custom low-level 153*61c4878aSAndroid Build Coastguard Workercode that is aware of both ``pw_system`` and the RTOS it is running on 154*61c4878aSAndroid Build Coastguard Worker(see e.g. `boot.cc 155*61c4878aSAndroid Build Coastguard Worker<https://cs.opensource.google/pigweed/pigweed/+/4d23123c37a33638b2f1ce611423e74d385623ff:targets/stm32f429i_disc1_stm32cube/boot.cc;l=133>`_ 156*61c4878aSAndroid Build Coastguard Workerand `target_hooks.cc 157*61c4878aSAndroid Build Coastguard Worker<https://cs.opensource.google/pigweed/pigweed/+/4d23123c37a33638b2f1ce611423e74d385623ff:pw_system/zephyr_target_hooks.cc>`_). 158*61c4878aSAndroid Build Coastguard WorkerEnabling cross-platform thread creation would make it easier to use 159*61c4878aSAndroid Build Coastguard Worker``pw_system``. The code for running ``pw_system`` on any target would be the 160*61c4878aSAndroid Build Coastguard Workersame: a single function call in ``main``. The user would no longer have to 161*61c4878aSAndroid Build Coastguard Workerallocate stacks or create :cpp:class:`pw::thread::Options` for ``pw_system`` 162*61c4878aSAndroid Build Coastguard Workerthreads; this could be managed by ``pw_system`` itself and configured with 163*61c4878aSAndroid Build Coastguard Workergeneric ``pw_system`` options if needed. 164*61c4878aSAndroid Build Coastguard Worker 165*61c4878aSAndroid Build Coastguard WorkerCross-platform thread creation also makes it easier for ``pw_system`` users to 166*61c4878aSAndroid Build Coastguard Workerwrite their own code. Setting up a thread takes just two lines of code and no 167*61c4878aSAndroid Build Coastguard Workerinteractions with RTOS-specific APIs. A ``pw_system`` application created this 168*61c4878aSAndroid Build Coastguard Workerway can run on any platform out of the box. 169*61c4878aSAndroid Build Coastguard Worker 170*61c4878aSAndroid Build Coastguard Worker--------------------- 171*61c4878aSAndroid Build Coastguard WorkerProblem investigation 172*61c4878aSAndroid Build Coastguard Worker--------------------- 173*61c4878aSAndroid Build Coastguard WorkerVarious cross-platform threading APIs exist today. 174*61c4878aSAndroid Build Coastguard Worker 175*61c4878aSAndroid Build Coastguard WorkerC++ Standard Library 176*61c4878aSAndroid Build Coastguard Worker==================== 177*61c4878aSAndroid Build Coastguard WorkerThe C++ Standard Library currently provides a limited cross-platform thread 178*61c4878aSAndroid Build Coastguard Workercreation API in ``<thread>``. No thread attributes are exposed; threads are 179*61c4878aSAndroid Build Coastguard Workercreated with platform defaults. 180*61c4878aSAndroid Build Coastguard Worker 181*61c4878aSAndroid Build Coastguard WorkerAn effort is underway to standardize some thread attributes, giving users more 182*61c4878aSAndroid Build Coastguard Workercontrol over threads while maintaining portability. See `P2019 -- Thread 183*61c4878aSAndroid Build Coastguard Workerattributes 184*61c4878aSAndroid Build Coastguard Worker<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2019r6.pdf>`_ for 185*61c4878aSAndroid Build Coastguard Workerdetails. The latest proposal exposes the thread name and stack size. Some 186*61c4878aSAndroid Build Coastguard Workeralternatives have also been proposed (`P3072 187*61c4878aSAndroid Build Coastguard Worker<https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3072r2.html>`_). 188*61c4878aSAndroid Build Coastguard Worker 189*61c4878aSAndroid Build Coastguard WorkerPOSIX 190*61c4878aSAndroid Build Coastguard Worker===== 191*61c4878aSAndroid Build Coastguard WorkerPOSIX is a portable operating system API. The POSIX thread creation function 192*61c4878aSAndroid Build Coastguard Worker``pthread_create`` takes a pointer to a ``pthread_attr_t`` struct. This struct 193*61c4878aSAndroid Build Coastguard Workermay a support a wide variety thread options that are configured with functions 194*61c4878aSAndroid Build Coastguard Workersuch as ``pthread_attr_setstacksize``, ``pthread_attr_setschedpolicy``, and 195*61c4878aSAndroid Build Coastguard Workerothers. A thread's name can be set with ``pthread_setname_np``. See `man 196*61c4878aSAndroid Build Coastguard Workerpthreads <https://man7.org/linux/man-pages/man7/pthreads.7.html>`_ for details. 197*61c4878aSAndroid Build Coastguard Worker 198*61c4878aSAndroid Build Coastguard WorkerCMSIS-RTOS 199*61c4878aSAndroid Build Coastguard Worker========== 200*61c4878aSAndroid Build Coastguard WorkerThe `CMSIS-RTOS2 API 201*61c4878aSAndroid Build Coastguard Worker<https://www.keil.com/pack/doc/CMSIS/RTOS2/html/index.html>`_ provides a generic 202*61c4878aSAndroid Build Coastguard WorkerRTOS interface intended for use with Arm Cortex devices. CMSIS-RTOS2 is 203*61c4878aSAndroid Build Coastguard Workerimplemented by several operating systems, including FreeRTOS and Arm's own Keil 204*61c4878aSAndroid Build Coastguard WorkerRTX5. 205*61c4878aSAndroid Build Coastguard Worker 206*61c4878aSAndroid Build Coastguard WorkerCMSIS-RTOS2 provides a comprehensive set of thread attributes in its 207*61c4878aSAndroid Build Coastguard Worker`osThreadAttr_t 208*61c4878aSAndroid Build Coastguard Worker<https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__ThreadMgmt.html#structosThreadAttr__t>`_ 209*61c4878aSAndroid Build Coastguard Workerstruct. It also provides functions for initializing and controlling the 210*61c4878aSAndroid Build Coastguard Workerscheduler, such as `osKernelStart 211*61c4878aSAndroid Build Coastguard Worker<https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__KernelCtrl.html#ga9ae2cc00f0d89d7b6a307bba942b5221>`_. 212*61c4878aSAndroid Build Coastguard Worker 213*61c4878aSAndroid Build Coastguard Worker-------- 214*61c4878aSAndroid Build Coastguard WorkerProposal 215*61c4878aSAndroid Build Coastguard Worker-------- 216*61c4878aSAndroid Build Coastguard WorkerThe new cross-platform API does not replace the existing backend-specific thread 217*61c4878aSAndroid Build Coastguard Workercreation APIs. The new API supports most production use cases, but does not 218*61c4878aSAndroid Build Coastguard Workerexpose the full capabilities and configuration of all supported RTOSes. It is 219*61c4878aSAndroid Build Coastguard Workerintended to be easy to adopt, while providing a frictionless pathway to the 220*61c4878aSAndroid Build Coastguard Workercurrent, fully configurable APIs if needed. 221*61c4878aSAndroid Build Coastguard Worker 222*61c4878aSAndroid Build Coastguard WorkerWith this proposal, per-target thread creation is simply a matter of setting 223*61c4878aSAndroid Build Coastguard Workervariables differently for each target. This removes the need for duplicated code 224*61c4878aSAndroid Build Coastguard Workerfor creating platform-specific thread contexts and ``pw::thread::Options``. 225*61c4878aSAndroid Build Coastguard Worker 226*61c4878aSAndroid Build Coastguard WorkerGeneric thread attributes 227*61c4878aSAndroid Build Coastguard Worker========================= 228*61c4878aSAndroid Build Coastguard WorkerThis SEED introduces a limited set of cross-platform thread attributes. These 229*61c4878aSAndroid Build Coastguard Workergeneric attributes map to a platform-specific :cpp:class:`pw::thread::Options`. 230*61c4878aSAndroid Build Coastguard Worker 231*61c4878aSAndroid Build Coastguard WorkerThere are three thread attributes: 232*61c4878aSAndroid Build Coastguard Worker 233*61c4878aSAndroid Build Coastguard Worker- Name 234*61c4878aSAndroid Build Coastguard Worker- Stack size 235*61c4878aSAndroid Build Coastguard Worker- Priority 236*61c4878aSAndroid Build Coastguard Worker 237*61c4878aSAndroid Build Coastguard WorkerOther attributes may be added in the future, such as dynamic or static 238*61c4878aSAndroid Build Coastguard Workerresource allocation. 239*61c4878aSAndroid Build Coastguard Worker 240*61c4878aSAndroid Build Coastguard WorkerThread attributes are provided only as hints to the backend. Backends should 241*61c4878aSAndroid Build Coastguard Workerrespect thread attributes, if possible, but may ignore or adapt them depending 242*61c4878aSAndroid Build Coastguard Workeron the OS's capabilities. Backends cannot fail to create thread because of how 243*61c4878aSAndroid Build Coastguard Workerthread attributes are set, but users may check the backend's capabilities, such 244*61c4878aSAndroid Build Coastguard Workeras whether thread priorities are supported, as needed. 245*61c4878aSAndroid Build Coastguard Worker 246*61c4878aSAndroid Build Coastguard WorkerExamples of acceptable adaptations to thread attributes. 247*61c4878aSAndroid Build Coastguard Worker 248*61c4878aSAndroid Build Coastguard Worker- Ignore the thread name and stack size because the underlying API does not 249*61c4878aSAndroid Build Coastguard Worker support specifying them (e.g. C++'s ``<thread>``). 250*61c4878aSAndroid Build Coastguard Worker- Silently truncate a thread name because the underlying RTOS only supports 251*61c4878aSAndroid Build Coastguard Worker shorter names. 252*61c4878aSAndroid Build Coastguard Worker- Round up to the minimum required stack size from a smaller requested stack 253*61c4878aSAndroid Build Coastguard Worker size. 254*61c4878aSAndroid Build Coastguard Worker- Add a fixed amount to a requested stack size to account for RTOS overhead. 255*61c4878aSAndroid Build Coastguard Worker- Dynamically allocate the thread stack if it is above a certain size; 256*61c4878aSAndroid Build Coastguard Worker statically allocate it otherwise. 257*61c4878aSAndroid Build Coastguard Worker 258*61c4878aSAndroid Build Coastguard Worker.. _seed-0128-thread-config-survey: 259*61c4878aSAndroid Build Coastguard Worker 260*61c4878aSAndroid Build Coastguard WorkerWhy these thread attributes? 261*61c4878aSAndroid Build Coastguard Worker---------------------------- 262*61c4878aSAndroid Build Coastguard WorkerA survey of thread creation with Pigweed across a few large, production projects 263*61c4878aSAndroid Build Coastguard Workerfound that 99% of their thread configurations can be exactly represented with 264*61c4878aSAndroid Build Coastguard Workerthread name, priority, stack size. The only exception was a single RTOS feature 265*61c4878aSAndroid Build Coastguard Workerused in a few threads in one project. 266*61c4878aSAndroid Build Coastguard Worker 267*61c4878aSAndroid Build Coastguard WorkerThe proof is in the pudding: ``pw_thread`` users almost never need low-level, 268*61c4878aSAndroid Build Coastguard WorkerRTOS-specific threading features. Abstracting these three thread attributes 269*61c4878aSAndroid Build Coastguard Workerdramatically simplifies thread creation, resulting in more portable, 270*61c4878aSAndroid Build Coastguard Workereasier-to-test code. In the rare cases when more control is needed, the existing 271*61c4878aSAndroid Build Coastguard Workernon-portable ``pw_thread`` API is ready to use. 272*61c4878aSAndroid Build Coastguard Worker 273*61c4878aSAndroid Build Coastguard WorkerOS / RTOS support for thread attributes 274*61c4878aSAndroid Build Coastguard Worker--------------------------------------- 275*61c4878aSAndroid Build Coastguard WorkerMost OS APIs support the proposed thread attributes. 276*61c4878aSAndroid Build Coastguard Worker 277*61c4878aSAndroid Build Coastguard Worker.. list-table:: 278*61c4878aSAndroid Build Coastguard Worker :header-rows: 1 279*61c4878aSAndroid Build Coastguard Worker 280*61c4878aSAndroid Build Coastguard Worker * - OS / API 281*61c4878aSAndroid Build Coastguard Worker - function 282*61c4878aSAndroid Build Coastguard Worker - name 283*61c4878aSAndroid Build Coastguard Worker - stack size 284*61c4878aSAndroid Build Coastguard Worker - priority type 285*61c4878aSAndroid Build Coastguard Worker - priority levels 286*61c4878aSAndroid Build Coastguard Worker * - C++ ``<thread>`` 287*61c4878aSAndroid Build Coastguard Worker - `std::thread <https://en.cppreference.com/w/cpp/thread/thread/thread>`_ 288*61c4878aSAndroid Build Coastguard Worker - none 289*61c4878aSAndroid Build Coastguard Worker - none 290*61c4878aSAndroid Build Coastguard Worker - none 291*61c4878aSAndroid Build Coastguard Worker - none 292*61c4878aSAndroid Build Coastguard Worker * - POSIX 293*61c4878aSAndroid Build Coastguard Worker - `pthread_create 294*61c4878aSAndroid Build Coastguard Worker <https://man7.org/linux/man-pages/man3/pthread_create.3.html>`_ 295*61c4878aSAndroid Build Coastguard Worker - `C string 296*61c4878aSAndroid Build Coastguard Worker <https://man7.org/linux/man-pages/man3/pthread_setname_np.3.html>`_ 297*61c4878aSAndroid Build Coastguard Worker - `bytes 298*61c4878aSAndroid Build Coastguard Worker <https://man7.org/linux/man-pages/man3/pthread_attr_setstacksize.3.html>`_ 299*61c4878aSAndroid Build Coastguard Worker - `pthread_attr_setschedparam <https://man7.org/linux/man-pages/man3/pthread_attr_setschedparam.3.html>`_ 300*61c4878aSAndroid Build Coastguard Worker - `at least 32 301*61c4878aSAndroid Build Coastguard Worker <https://man7.org/linux/man-pages/man2/sched_get_priority_max.2.html>`_ 302*61c4878aSAndroid Build Coastguard Worker * - `CMSIS-RTOS2 / Keil RTX5 <https://arm-software.github.io/CMSIS_6/latest/RTOS2/group__CMSIS__RTOS__ThreadMgmt.html>`_ 303*61c4878aSAndroid Build Coastguard Worker - `osThreadNew <https://arm-software.github.io/CMSIS_6/latest/RTOS2/group__CMSIS__RTOS__ThreadMgmt.html#ga48d68b8666d99d28fa646ee1d2182b8f>`_ 304*61c4878aSAndroid Build Coastguard Worker - `C string 305*61c4878aSAndroid Build Coastguard Worker <https://arm-software.github.io/CMSIS_6/latest/RTOS2/group__CMSIS__RTOS__ThreadMgmt.html#structosThreadAttr__t>`__ 306*61c4878aSAndroid Build Coastguard Worker - bytes 307*61c4878aSAndroid Build Coastguard Worker - `osPriority_t 308*61c4878aSAndroid Build Coastguard Worker <https://arm-software.github.io/CMSIS_6/latest/RTOS2/group__CMSIS__RTOS__ThreadMgmt.html#gad4e3e0971b41f2d17584a8c6837342ec>`_ 309*61c4878aSAndroid Build Coastguard Worker - 56 310*61c4878aSAndroid Build Coastguard Worker * - `embOS <https://www.segger.com/downloads/embos/UM01001>`_ 311*61c4878aSAndroid Build Coastguard Worker - ``OS_TASK_Create()`` 312*61c4878aSAndroid Build Coastguard Worker - | C string 313*61c4878aSAndroid Build Coastguard Worker | uses pointer 314*61c4878aSAndroid Build Coastguard Worker - bytes 315*61c4878aSAndroid Build Coastguard Worker - ``unsigned int`` 316*61c4878aSAndroid Build Coastguard Worker - 2³²-2 317*61c4878aSAndroid Build Coastguard Worker * - `FreeRTOS <https://www.freertos.org>`_ 318*61c4878aSAndroid Build Coastguard Worker - `xTaskCreateStatic <https://www.freertos.org/xTaskCreateStatic.html>`_ 319*61c4878aSAndroid Build Coastguard Worker - | C string 320*61c4878aSAndroid Build Coastguard Worker | copies `configMAX_TASK_NAME_LEN <https://www.freertos.org/a00110.html#configMAX_TASK_NAME_LEN>`_ 321*61c4878aSAndroid Build Coastguard Worker - words 322*61c4878aSAndroid Build Coastguard Worker - `unsigned int <https://www.freertos.org/RTOS-task-priority.html>`_ 323*61c4878aSAndroid Build Coastguard Worker - | `configMAX_PRIORITIES <https://www.freertos.org/a00110.html#configMAX_PRIORITIES>`_ 324*61c4878aSAndroid Build Coastguard Worker | `≤32 in some configs <https://www.freertos.org/a00110.html#configUSE_PORT_OPTIMISED_TASK_SELECTION>`_ 325*61c4878aSAndroid Build Coastguard Worker * - `NuttX <https://nuttx.apache.org/docs/latest/index.html>`_ 326*61c4878aSAndroid Build Coastguard Worker - | `task_create <https://nuttx.apache.org/docs/latest/reference/user/01_task_control.html#c.task_create>`_ 327*61c4878aSAndroid Build Coastguard Worker | (also POSIX APIs) 328*61c4878aSAndroid Build Coastguard Worker - C string 329*61c4878aSAndroid Build Coastguard Worker - bytes 330*61c4878aSAndroid Build Coastguard Worker - ``int`` 331*61c4878aSAndroid Build Coastguard Worker - `256 <https://github.com/apache/nuttx/blob/0ed714bba4280f98f35cb0df1f9d668099604f97/include/sys/types.h#L81>`_ 332*61c4878aSAndroid Build Coastguard Worker * - `ThreadX <https://github.com/eclipse-threadx/rtos-docs>`_ 333*61c4878aSAndroid Build Coastguard Worker - `tx_thread_create 334*61c4878aSAndroid Build Coastguard Worker <https://github.com/eclipse-threadx/rtos-docs/blob/80bd9fe9a33fa79257c75629be1b4438b84db7bc/rtos-docs/threadx/chapter4.md#tx_thread_create>`_ 335*61c4878aSAndroid Build Coastguard Worker - `C string 336*61c4878aSAndroid Build Coastguard Worker <https://github.com/eclipse-threadx/rtos-docs/blob/80bd9fe9a33fa79257c75629be1b4438b84db7bc/rtos-docs/threadx/chapter4.md#example-54>`__ 337*61c4878aSAndroid Build Coastguard Worker - bytes 338*61c4878aSAndroid Build Coastguard Worker - ``unsigned int`` (``TX_MAX_PRIORITIES - 1``)–0 (0 highest) 339*61c4878aSAndroid Build Coastguard Worker - `multiple of 32 340*61c4878aSAndroid Build Coastguard Worker <https://github.com/eclipse-threadx/threadx/blob/80bd9fe9a33fa79257c75629be1b4438b84db7bc/common/inc/tx_api.h#L2143>`_ 341*61c4878aSAndroid Build Coastguard Worker * - ``pw::ThreadContext`` 342*61c4878aSAndroid Build Coastguard Worker - :cpp:type:`pw::Thread` 343*61c4878aSAndroid Build Coastguard Worker - C string 344*61c4878aSAndroid Build Coastguard Worker - bytes 345*61c4878aSAndroid Build Coastguard Worker - custom class 346*61c4878aSAndroid Build Coastguard Worker - same as underying OS 347*61c4878aSAndroid Build Coastguard Worker 348*61c4878aSAndroid Build Coastguard WorkerCreating threads 349*61c4878aSAndroid Build Coastguard Worker================ 350*61c4878aSAndroid Build Coastguard WorkerThe APIs proposed in this SEED streamline thread creation for common use cases, 351*61c4878aSAndroid Build Coastguard Workerwhile allowing for full configuration when necessary. 352*61c4878aSAndroid Build Coastguard Worker 353*61c4878aSAndroid Build Coastguard WorkerGenerally, projects should start with the minimum complexity required and 354*61c4878aSAndroid Build Coastguard Workerincrease the complexity only if more control is needed. Threads defined in 355*61c4878aSAndroid Build Coastguard Workerupstream Pigweed should start with some configurability to avoid friction in 356*61c4878aSAndroid Build Coastguard Workerdownstream projects. 357*61c4878aSAndroid Build Coastguard Worker 358*61c4878aSAndroid Build Coastguard WorkerDynamic threads: "just give me a thread" 359*61c4878aSAndroid Build Coastguard Worker---------------------------------------- 360*61c4878aSAndroid Build Coastguard WorkerFor simple cases, Pigweed will offer a new static ``pw::Thread::Start`` 361*61c4878aSAndroid Build Coastguard Workerfunction. 362*61c4878aSAndroid Build Coastguard Worker 363*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 364*61c4878aSAndroid Build Coastguard Worker 365*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread.h" 366*61c4878aSAndroid Build Coastguard Worker 367*61c4878aSAndroid Build Coastguard Worker void CreateThreads() { 368*61c4878aSAndroid Build Coastguard Worker pw::Thread::Start([] { /* thread body */ ).detach(); 369*61c4878aSAndroid Build Coastguard Worker } 370*61c4878aSAndroid Build Coastguard Worker 371*61c4878aSAndroid Build Coastguard Worker.. admonition:: When should I use ``pw::Thread::Start``? 372*61c4878aSAndroid Build Coastguard Worker 373*61c4878aSAndroid Build Coastguard Worker - Experimenting 374*61c4878aSAndroid Build Coastguard Worker - Prototyping 375*61c4878aSAndroid Build Coastguard Worker 376*61c4878aSAndroid Build Coastguard WorkerDeclare a default thread 377*61c4878aSAndroid Build Coastguard Worker------------------------ 378*61c4878aSAndroid Build Coastguard WorkerCreate a thread with ``DefaultThreadContext`` and default attributes. The 379*61c4878aSAndroid Build Coastguard Worker``pw_thread`` backend starts a thread with a default name, stack size, and 380*61c4878aSAndroid Build Coastguard Workerpriority. 381*61c4878aSAndroid Build Coastguard Worker 382*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 383*61c4878aSAndroid Build Coastguard Worker 384*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread.h" 385*61c4878aSAndroid Build Coastguard Worker 386*61c4878aSAndroid Build Coastguard Worker pw::DefaultThreadContext context; 387*61c4878aSAndroid Build Coastguard Worker 388*61c4878aSAndroid Build Coastguard Worker void CreateThreads() { 389*61c4878aSAndroid Build Coastguard Worker pw::Thread(context, pw::ThreadAttrs(), [] { /* thread body */ }).detach(); 390*61c4878aSAndroid Build Coastguard Worker } 391*61c4878aSAndroid Build Coastguard Worker 392*61c4878aSAndroid Build Coastguard Worker.. admonition:: When should I use default thread contexts? 393*61c4878aSAndroid Build Coastguard Worker 394*61c4878aSAndroid Build Coastguard Worker - Experimenting 395*61c4878aSAndroid Build Coastguard Worker - Prototyping 396*61c4878aSAndroid Build Coastguard Worker - Testing 397*61c4878aSAndroid Build Coastguard Worker - Getting started 398*61c4878aSAndroid Build Coastguard Worker 399*61c4878aSAndroid Build Coastguard WorkerConfigurable thread attributes 400*61c4878aSAndroid Build Coastguard Worker------------------------------ 401*61c4878aSAndroid Build Coastguard WorkerDefine a ``pw::ThreadAttrs`` and use it to create threads with 402*61c4878aSAndroid Build Coastguard Worker``pw::ThreadContext<>``. Attributes are configured as needed using the project's 403*61c4878aSAndroid Build Coastguard Workerconfiguration pattern. 404*61c4878aSAndroid Build Coastguard Worker 405*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 406*61c4878aSAndroid Build Coastguard Worker 407*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread.h" 408*61c4878aSAndroid Build Coastguard Worker #include "project/config.h" 409*61c4878aSAndroid Build Coastguard Worker 410*61c4878aSAndroid Build Coastguard Worker constexpr auto kMyThread = pw::ThreadAttrs() 411*61c4878aSAndroid Build Coastguard Worker .set_name("my thread") 412*61c4878aSAndroid Build Coastguard Worker .set_priority(MY_THREAD_PRIORITY) 413*61c4878aSAndroid Build Coastguard Worker .set_stack_size_bytes(kMyThreadStackSizeBytes); 414*61c4878aSAndroid Build Coastguard Worker 415*61c4878aSAndroid Build Coastguard Worker pw::ThreadContext<kMyThread> my_thread_context; 416*61c4878aSAndroid Build Coastguard Worker 417*61c4878aSAndroid Build Coastguard Worker pw::Thread other_thread; 418*61c4878aSAndroid Build Coastguard Worker pw::ThreadContext<kOtherThreadStackSizeBytes> other_thread_context; 419*61c4878aSAndroid Build Coastguard Worker 420*61c4878aSAndroid Build Coastguard Worker void StartThreads() { 421*61c4878aSAndroid Build Coastguard Worker pw::Thread(my_thread_context, [] { /* thread body */ }).detach(); 422*61c4878aSAndroid Build Coastguard Worker 423*61c4878aSAndroid Build Coastguard Worker other_thread = pw::Thread(other_thread_context, 424*61c4878aSAndroid Build Coastguard Worker pw::ThreadAttrs().set_name("other"), 425*61c4878aSAndroid Build Coastguard Worker OtherThreadBody); 426*61c4878aSAndroid Build Coastguard Worker } 427*61c4878aSAndroid Build Coastguard Worker 428*61c4878aSAndroid Build Coastguard WorkerExample configuration header: 429*61c4878aSAndroid Build Coastguard Worker 430*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 431*61c4878aSAndroid Build Coastguard Worker 432*61c4878aSAndroid Build Coastguard Worker // "project/config.h" 433*61c4878aSAndroid Build Coastguard Worker 434*61c4878aSAndroid Build Coastguard Worker // Configurable thread priority. Can be changed by defining 435*61c4878aSAndroid Build Coastguard Worker // MY_THREAD_PRIORITY in the build system. 436*61c4878aSAndroid Build Coastguard Worker #ifndef MY_THREAD_PRIORITY 437*61c4878aSAndroid Build Coastguard Worker #define MY_THREAD_PRIORITY pw::ThreadPriority::High() 438*61c4878aSAndroid Build Coastguard Worker #endif // MY_THREAD_PRIORITY 439*61c4878aSAndroid Build Coastguard Worker 440*61c4878aSAndroid Build Coastguard Worker // Configuration may be based on the target platform. 441*61c4878aSAndroid Build Coastguard Worker #if BUILDING_FOR_PLATFORM_A 442*61c4878aSAndroid Build Coastguard Worker inline constexpr size_t kMyThreadStackSizeBytes = 2048; 443*61c4878aSAndroid Build Coastguard Worker inline constexpr size_t kOtherThreadStackSizeBytes = 1024; 444*61c4878aSAndroid Build Coastguard Worker #else 445*61c4878aSAndroid Build Coastguard Worker inline constexpr size_t kMyThreadStackSizeBytes = 1536; 446*61c4878aSAndroid Build Coastguard Worker inline constexpr size_t kOtherThreadStackSizeBytes = 512; 447*61c4878aSAndroid Build Coastguard Worker #endif // BUILDING_FOR_PLATFORM_A 448*61c4878aSAndroid Build Coastguard Worker 449*61c4878aSAndroid Build Coastguard Worker.. admonition:: When should I use configurable thread attributes? 450*61c4878aSAndroid Build Coastguard Worker 451*61c4878aSAndroid Build Coastguard Worker - Pigweed upstream development 452*61c4878aSAndroid Build Coastguard Worker - Production project development 453*61c4878aSAndroid Build Coastguard Worker 454*61c4878aSAndroid Build Coastguard WorkerPlatform-specific thread creation 455*61c4878aSAndroid Build Coastguard Worker--------------------------------- 456*61c4878aSAndroid Build Coastguard WorkerIn the rare case that platform-specific thread configuration is required, 457*61c4878aSAndroid Build Coastguard Workerprovide a function that returns ``NativeOptions`` or ``const Options&`` and use 458*61c4878aSAndroid Build Coastguard Workerit to create a thread. The function may be a facade, so each target can 459*61c4878aSAndroid Build Coastguard Workerimplement it differently. Projects may provide a default implementation of the 460*61c4878aSAndroid Build Coastguard Workerfunction that uses ``pw::ThreadAttrs``. 461*61c4878aSAndroid Build Coastguard Worker 462*61c4878aSAndroid Build Coastguard WorkerThis approach is equivalent to the original non-portable ``pw_thread`` creation 463*61c4878aSAndroid Build Coastguard Workerpattern, optionally with a ``pw::ThreadAttrs``-based default implementation of 464*61c4878aSAndroid Build Coastguard Workerthe function. This approach is only necessary for threads that specifically 465*61c4878aSAndroid Build Coastguard Workerrequire non-portable features. Other threads should continue to use 466*61c4878aSAndroid Build Coastguard Worker``pw::ThreadAttrs``. 467*61c4878aSAndroid Build Coastguard Worker 468*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 469*61c4878aSAndroid Build Coastguard Worker 470*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/thread.h" 471*61c4878aSAndroid Build Coastguard Worker #include "project/config.h" 472*61c4878aSAndroid Build Coastguard Worker 473*61c4878aSAndroid Build Coastguard Worker // This function returns a `pw::thread::Options` for creating a thread. 474*61c4878aSAndroid Build Coastguard Worker pw::thread::NativeOptions GetThreadOptions(); 475*61c4878aSAndroid Build Coastguard Worker 476*61c4878aSAndroid Build Coastguard Worker // Optionally, provide a default implementation of `GetThreadOptions()` that 477*61c4878aSAndroid Build Coastguard Worker // uses `pw::ThreadAttrs`. 478*61c4878aSAndroid Build Coastguard Worker #if !PROJECT_CFG_THREAD_CUSTOM_OPTIONS 479*61c4878aSAndroid Build Coastguard Worker 480*61c4878aSAndroid Build Coastguard Worker pw::thread::NativeOptions GetThreadOptions() { 481*61c4878aSAndroid Build Coastguard Worker static constinit pw::ThreadContext<project::cfg::kThreadStackSizeHintBytes> context; 482*61c4878aSAndroid Build Coastguard Worker return pw::thread::GetNativeOptions( 483*61c4878aSAndroid Build Coastguard Worker context, pw::ThreadAttrs().set_name("thread name")); 484*61c4878aSAndroid Build Coastguard Worker } 485*61c4878aSAndroid Build Coastguard Worker 486*61c4878aSAndroid Build Coastguard Worker #endif // !PROJECT_CFG_THREAD_CUSTOM_OPTIONS 487*61c4878aSAndroid Build Coastguard Worker 488*61c4878aSAndroid Build Coastguard Worker // Call `GetThreadOptions()` to create a thread. 489*61c4878aSAndroid Build Coastguard Worker void CreateThreads() { 490*61c4878aSAndroid Build Coastguard Worker pw::Thread(GetThreadOptions(), [] { /* thread body */ }).detach(); 491*61c4878aSAndroid Build Coastguard Worker } 492*61c4878aSAndroid Build Coastguard Worker 493*61c4878aSAndroid Build Coastguard WorkerExample configuration header: 494*61c4878aSAndroid Build Coastguard Worker 495*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 496*61c4878aSAndroid Build Coastguard Worker 497*61c4878aSAndroid Build Coastguard Worker // project/config.h 498*61c4878aSAndroid Build Coastguard Worker 499*61c4878aSAndroid Build Coastguard Worker // Set to 1 to implement `GetThreadOptions()` and provide fully custom 500*61c4878aSAndroid Build Coastguard Worker // `pw::thread::Options` for the platform. 501*61c4878aSAndroid Build Coastguard Worker #ifndef PROJECT_CFG_THREAD_CUSTOM_OPTIONS 502*61c4878aSAndroid Build Coastguard Worker #define PROJECT_CFG_THREAD_CUSTOM_OPTIONS 0 503*61c4878aSAndroid Build Coastguard Worker #endif // PROJECT_CFG_THREAD_CUSTOM_OPTIONS 504*61c4878aSAndroid Build Coastguard Worker 505*61c4878aSAndroid Build Coastguard Worker // Stack size setting for the default thread options. 506*61c4878aSAndroid Build Coastguard Worker #ifndef PROJECT_CFG_THREAD_STACKS_SIZE_HINT 507*61c4878aSAndroid Build Coastguard Worker #define PROJECT_CFG_THREAD_STACKS_SIZE_HINT 2048 508*61c4878aSAndroid Build Coastguard Worker #endif // PROJECT_CFG_THREAD_STACKS_SIZE_HINT 509*61c4878aSAndroid Build Coastguard Worker 510*61c4878aSAndroid Build Coastguard Worker namespace project::cfg { 511*61c4878aSAndroid Build Coastguard Worker 512*61c4878aSAndroid Build Coastguard Worker inline constexpr size_t kThreadStackSizeHintBytes = PROJECT_CFG_THREAD_STACKS_SIZE_HINT; 513*61c4878aSAndroid Build Coastguard Worker 514*61c4878aSAndroid Build Coastguard Worker } // namespace project::cfg 515*61c4878aSAndroid Build Coastguard Worker 516*61c4878aSAndroid Build Coastguard WorkerThis approach is not recommended as a starting point. It adds complexity that is 517*61c4878aSAndroid Build Coastguard Workerunlikely to be necessary. Most projects should start with configurable 518*61c4878aSAndroid Build Coastguard Worker``ThreadAttrs`` and add switch to platform-specific thread configuration only 519*61c4878aSAndroid Build Coastguard Workerfor threads that need it. 520*61c4878aSAndroid Build Coastguard Worker 521*61c4878aSAndroid Build Coastguard Worker.. admonition:: When should I use platform-specific thread creation? 522*61c4878aSAndroid Build Coastguard Worker 523*61c4878aSAndroid Build Coastguard Worker - Pigweed upstream development, if a downstream user specifically requires 524*61c4878aSAndroid Build Coastguard Worker platform-specific thread features for a thread defined by Pigweed. 525*61c4878aSAndroid Build Coastguard Worker - Production project development that requires platform-specific thread 526*61c4878aSAndroid Build Coastguard Worker features. 527*61c4878aSAndroid Build Coastguard Worker 528*61c4878aSAndroid Build Coastguard WorkerC++ implementation details 529*61c4878aSAndroid Build Coastguard Worker========================== 530*61c4878aSAndroid Build Coastguard Worker 531*61c4878aSAndroid Build Coastguard WorkerFacade additions 532*61c4878aSAndroid Build Coastguard Worker----------------- 533*61c4878aSAndroid Build Coastguard WorkerThis proposal adds a few items to the ``pw_thread`` facade: 534*61c4878aSAndroid Build Coastguard Worker 535*61c4878aSAndroid Build Coastguard Worker- Aliases for the native context types wrapped by ``pw::ThreadContext``. 536*61c4878aSAndroid Build Coastguard Worker- Information about the range of supported thread priorities used by 537*61c4878aSAndroid Build Coastguard Worker ``pw::ThreadPriority``. 538*61c4878aSAndroid Build Coastguard Worker- Alias for the native ``pw::thread::Options`` type. 539*61c4878aSAndroid Build Coastguard Worker- Function that maps ``pw::ThreadContext`` and ``pw::ThreadAttrs`` to native 540*61c4878aSAndroid Build Coastguard Worker ``pw::thread::Options``. 541*61c4878aSAndroid Build Coastguard Worker 542*61c4878aSAndroid Build Coastguard WorkerThese features are used by ``pw_thread`` classes, not end users. 543*61c4878aSAndroid Build Coastguard Worker 544*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 545*61c4878aSAndroid Build Coastguard Worker 546*61c4878aSAndroid Build Coastguard Worker // pw_thread_backend/thread_native.h 547*61c4878aSAndroid Build Coastguard Worker 548*61c4878aSAndroid Build Coastguard Worker namespace pw::thread::backend { 549*61c4878aSAndroid Build Coastguard Worker 550*61c4878aSAndroid Build Coastguard Worker // Native, non-templated context (resources). 551*61c4878aSAndroid Build Coastguard Worker using NativeContext = /* implementation-defined */; 552*61c4878aSAndroid Build Coastguard Worker 553*61c4878aSAndroid Build Coastguard Worker // Thread context with a stack size hint. Must derive from or be the same 554*61c4878aSAndroid Build Coastguard Worker // type as `NativeContext`. Must be default constructible. 555*61c4878aSAndroid Build Coastguard Worker template <size_t kStackSizeHintBytes> 556*61c4878aSAndroid Build Coastguard Worker using NativeContextWithStack = /* implementation-defined */; 557*61c4878aSAndroid Build Coastguard Worker 558*61c4878aSAndroid Build Coastguard Worker // Stack size to use when unspecified; 0 for platforms that do not support 559*61c4878aSAndroid Build Coastguard Worker // defining the stack size. 560*61c4878aSAndroid Build Coastguard Worker inline constexpr size_t kDefaultStackSizeBytes = /* implementation-defined */; 561*61c4878aSAndroid Build Coastguard Worker 562*61c4878aSAndroid Build Coastguard Worker // Define the range of thread priority values. These values may represent a 563*61c4878aSAndroid Build Coastguard Worker // subset of priorities supported by the OS. The `kHighestPriority` may be 564*61c4878aSAndroid Build Coastguard Worker // numerically higher or lower than `kLowestPriority`, depending on the OS. 565*61c4878aSAndroid Build Coastguard Worker // Backends that do not support priorities must set `kLowestPriority` and 566*61c4878aSAndroid Build Coastguard Worker // `kHighestPriority` to the same value, and should use `int` for 567*61c4878aSAndroid Build Coastguard Worker // `NativePriority`. 568*61c4878aSAndroid Build Coastguard Worker using NativePriority = /* implementation-defined */; 569*61c4878aSAndroid Build Coastguard Worker inline constexpr NativePriority kLowestPriority = /* implementation-defined */; 570*61c4878aSAndroid Build Coastguard Worker inline constexpr NativePriority kHighestPriority = /* implementation-defined */; 571*61c4878aSAndroid Build Coastguard Worker 572*61c4878aSAndroid Build Coastguard Worker // Native options class derived from pw::thread::Options. 573*61c4878aSAndroid Build Coastguard Worker using NativeOptions = /* implementation-defined */; 574*61c4878aSAndroid Build Coastguard Worker 575*61c4878aSAndroid Build Coastguard Worker // Converts cross-platform ThreadAttrs to NativeOptions. May be defined 576*61c4878aSAndroid Build Coastguard Worker // in ``pw_thread_backend/thread_inline.h`` or in a .cc file. 577*61c4878aSAndroid Build Coastguard Worker NativeOptions GetNativeOptions(NativeContext& context, 578*61c4878aSAndroid Build Coastguard Worker const ThreadAttrs& attributes); 579*61c4878aSAndroid Build Coastguard Worker 580*61c4878aSAndroid Build Coastguard Worker } // namespace pw::thread::backend 581*61c4878aSAndroid Build Coastguard Worker 582*61c4878aSAndroid Build Coastguard Worker``pw_thread_stl`` example implementation: 583*61c4878aSAndroid Build Coastguard Worker 584*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 585*61c4878aSAndroid Build Coastguard Worker 586*61c4878aSAndroid Build Coastguard Worker namespace pw::thread::backend { 587*61c4878aSAndroid Build Coastguard Worker 588*61c4878aSAndroid Build Coastguard Worker using NativeContext = pw::thread::stl::Context; 589*61c4878aSAndroid Build Coastguard Worker 590*61c4878aSAndroid Build Coastguard Worker // Ignore the stack size since it's not supported. 591*61c4878aSAndroid Build Coastguard Worker template <size_t> 592*61c4878aSAndroid Build Coastguard Worker using NativeContextWithStack = pw::thread::stl::Context; 593*61c4878aSAndroid Build Coastguard Worker 594*61c4878aSAndroid Build Coastguard Worker inline constexpr size_t kDefaultStackSizeBytes = 0; 595*61c4878aSAndroid Build Coastguard Worker 596*61c4878aSAndroid Build Coastguard Worker using NativePriority = int; 597*61c4878aSAndroid Build Coastguard Worker inline constexpr NativePriority kLowestPriority = 0; 598*61c4878aSAndroid Build Coastguard Worker inline constexpr NativePriority kHighestPriority = 0; 599*61c4878aSAndroid Build Coastguard Worker 600*61c4878aSAndroid Build Coastguard Worker using NativeOptions = pw::thread::stl::Options; 601*61c4878aSAndroid Build Coastguard Worker 602*61c4878aSAndroid Build Coastguard Worker inline NativeOptions GetNativeOptions(NativeContext&, const ThreadAttrs&) { 603*61c4878aSAndroid Build Coastguard Worker return pw::thread::stl::Options(); 604*61c4878aSAndroid Build Coastguard Worker } 605*61c4878aSAndroid Build Coastguard Worker 606*61c4878aSAndroid Build Coastguard Worker } // namespace pw::thread::backend 607*61c4878aSAndroid Build Coastguard Worker 608*61c4878aSAndroid Build Coastguard Worker``pw_thread_freertos`` example implementation: 609*61c4878aSAndroid Build Coastguard Worker 610*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 611*61c4878aSAndroid Build Coastguard Worker 612*61c4878aSAndroid Build Coastguard Worker namespace pw::thread::backend { 613*61c4878aSAndroid Build Coastguard Worker 614*61c4878aSAndroid Build Coastguard Worker using NativeContext = pw::thread::freertos::StaticContext; 615*61c4878aSAndroid Build Coastguard Worker 616*61c4878aSAndroid Build Coastguard Worker // Convert bytes to words, rounding up. 617*61c4878aSAndroid Build Coastguard Worker template <size_t kStackSizeBytes> 618*61c4878aSAndroid Build Coastguard Worker using NativeContextWithStack = pw::thread::stl::StaticContextWithStack< 619*61c4878aSAndroid Build Coastguard Worker (kStackSizeBytes + sizeof(StackType_t) - 1) / sizeof(StackType_t)>; 620*61c4878aSAndroid Build Coastguard Worker 621*61c4878aSAndroid Build Coastguard Worker inline constexpr size_t kDefaultStackSizeBytes = 622*61c4878aSAndroid Build Coastguard Worker pw::thread::freertos::config::kDefaultStackSizeWords; 623*61c4878aSAndroid Build Coastguard Worker 624*61c4878aSAndroid Build Coastguard Worker using NativePriority = UBaseType_t; 625*61c4878aSAndroid Build Coastguard Worker inline constexpr NativePriority kLowestPriority = tskIDLE_PRIORITY; 626*61c4878aSAndroid Build Coastguard Worker inline constexpr NativePriority kHighestPriority = configMAX_PRIORITIES - 1; 627*61c4878aSAndroid Build Coastguard Worker 628*61c4878aSAndroid Build Coastguard Worker using NativeOptions = pw::thread::freertos::Options; 629*61c4878aSAndroid Build Coastguard Worker 630*61c4878aSAndroid Build Coastguard Worker inline NativeOptions GetNativeOptions(NativeContext& context, 631*61c4878aSAndroid Build Coastguard Worker const ThreadAttrs& attrs) { 632*61c4878aSAndroid Build Coastguard Worker return pw::thread::freertos::Options() 633*61c4878aSAndroid Build Coastguard Worker .set_static_context(context), 634*61c4878aSAndroid Build Coastguard Worker .set_name(attrs.name()) 635*61c4878aSAndroid Build Coastguard Worker .set_priority(attrs.priority().native()) 636*61c4878aSAndroid Build Coastguard Worker } 637*61c4878aSAndroid Build Coastguard Worker 638*61c4878aSAndroid Build Coastguard Worker } // namespace pw::thread::backend 639*61c4878aSAndroid Build Coastguard Worker 640*61c4878aSAndroid Build Coastguard Worker``ThreadPriority`` 641*61c4878aSAndroid Build Coastguard Worker------------------ 642*61c4878aSAndroid Build Coastguard WorkerDifferent OS APIs define priorities very differently. Some support a few 643*61c4878aSAndroid Build Coastguard Workerpriority levels, others support the full range of a ``uint32_t``. For some, 0 is 644*61c4878aSAndroid Build Coastguard Workerthe lowest priority and for others it is the highest. And changing the OS's 645*61c4878aSAndroid Build Coastguard Workerscheduling policy might changes how threads are scheduled without changing their 646*61c4878aSAndroid Build Coastguard Workerpriorities. 647*61c4878aSAndroid Build Coastguard Worker 648*61c4878aSAndroid Build Coastguard Worker``pw::ThreadPriority`` represents thread priority precisely but abstractly. It 649*61c4878aSAndroid Build Coastguard Workersupports the following: 650*61c4878aSAndroid Build Coastguard Worker 651*61c4878aSAndroid Build Coastguard Worker- Represent the full range of priorities supported by the underlying OS. 652*61c4878aSAndroid Build Coastguard Worker- Set priorities in absolute terms that map to OS priority ranges in a 653*61c4878aSAndroid Build Coastguard Worker reasonable way. 654*61c4878aSAndroid Build Coastguard Worker- Set priorities relative to one another. 655*61c4878aSAndroid Build Coastguard Worker- Check that priorities are actually higher or lower than one another on a given 656*61c4878aSAndroid Build Coastguard Worker platform at compile time. 657*61c4878aSAndroid Build Coastguard Worker- Check if the backend supports thread priorities at all. 658*61c4878aSAndroid Build Coastguard Worker 659*61c4878aSAndroid Build Coastguard WorkerMany projects will be able to define a single priority set for all platforms. 660*61c4878aSAndroid Build Coastguard WorkerThe priorities may translate differently to each platforms, but this may not 661*61c4878aSAndroid Build Coastguard Workermatter. If a single set of priorities does not work for all platforms, 662*61c4878aSAndroid Build Coastguard Workerpriorities can be configured per platform, like other attributes. 663*61c4878aSAndroid Build Coastguard Worker 664*61c4878aSAndroid Build Coastguard WorkerHere is a high-level overview of the class: 665*61c4878aSAndroid Build Coastguard Worker 666*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 667*61c4878aSAndroid Build Coastguard Worker 668*61c4878aSAndroid Build Coastguard Worker namespace pw { 669*61c4878aSAndroid Build Coastguard Worker 670*61c4878aSAndroid Build Coastguard Worker class ThreadPriority { 671*61c4878aSAndroid Build Coastguard Worker public: 672*61c4878aSAndroid Build Coastguard Worker // True if the backend supports different priority levels. 673*61c4878aSAndroid Build Coastguard Worker static constexpr bool IsSupported(); 674*61c4878aSAndroid Build Coastguard Worker 675*61c4878aSAndroid Build Coastguard Worker // Named priorities. These priority levels span the backend's supported 676*61c4878aSAndroid Build Coastguard Worker // priority range. 677*61c4878aSAndroid Build Coastguard Worker // 678*61c4878aSAndroid Build Coastguard Worker // The optional `kPlus` template parameter returns a priority the specified 679*61c4878aSAndroid Build Coastguard Worker // number of levels higher than the named priority, but never exceeding the 680*61c4878aSAndroid Build Coastguard Worker // priority of the next named level, if supported by the backend. 681*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority VeryLow<unsigned kPlus = 0>(); 682*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority Low<unsigned kPlus = 0>(); 683*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority MediumLow<unsigned kPlus = 0>(); 684*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority Medium<unsigned kPlus = 0>(); 685*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority MediumHigh<unsigned kPlus = 0>(); 686*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority High<unsigned kPlus = 0>(); 687*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority VeryHigh<unsigned kPlus = 0>(); 688*61c4878aSAndroid Build Coastguard Worker 689*61c4878aSAndroid Build Coastguard Worker // Refers to the lowest or highest priority supported by the OS. 690*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority Lowest<unsigned kPlus = 0>(); 691*61c4878aSAndroid Build Coastguard Worker static constexpr ThreadPriority Highest(); 692*61c4878aSAndroid Build Coastguard Worker 693*61c4878aSAndroid Build Coastguard Worker // Returns the ThreadPriority with next distinct higher or lower value. If 694*61c4878aSAndroid Build Coastguard Worker // the priority is already the highest/lowest, returns the same value. 695*61c4878aSAndroid Build Coastguard Worker constexpr ThreadPriority NextLower(); 696*61c4878aSAndroid Build Coastguard Worker constexpr ThreadPriority NextHigher(); 697*61c4878aSAndroid Build Coastguard Worker 698*61c4878aSAndroid Build Coastguard Worker // Returns the ThreadPriority with next distinct higher or lower value. 699*61c4878aSAndroid Build Coastguard Worker // Asserts that the priority is not already the highest/lowest. 700*61c4878aSAndroid Build Coastguard Worker constexpr ThreadPriority NextLowerChecked(); 701*61c4878aSAndroid Build Coastguard Worker constexpr ThreadPriority NextHigherChecked(); 702*61c4878aSAndroid Build Coastguard Worker 703*61c4878aSAndroid Build Coastguard Worker // ThreadPriority supports comparison. This makes it possible, for example, 704*61c4878aSAndroid Build Coastguard Worker // to static_assert that one priority is higher than another in the 705*61c4878aSAndroid Build Coastguard Worker // backend. 706*61c4878aSAndroid Build Coastguard Worker constexpr bool operator==(const ThreadPriority&); 707*61c4878aSAndroid Build Coastguard Worker ... 708*61c4878aSAndroid Build Coastguard Worker 709*61c4878aSAndroid Build Coastguard Worker // Access the native thread priority type. These functions may be helpful 710*61c4878aSAndroid Build Coastguard Worker // when ThreadPriority is configured separately for each platform. 711*61c4878aSAndroid Build Coastguard Worker using native_type = backend::NativeThreadPriority; 712*61c4878aSAndroid Build Coastguard Worker 713*61c4878aSAndroid Build Coastguard Worker static constexpr FromNative(native_type native_priority); 714*61c4878aSAndroid Build Coastguard Worker 715*61c4878aSAndroid Build Coastguard Worker native_type native() const; 716*61c4878aSAndroid Build Coastguard Worker }; 717*61c4878aSAndroid Build Coastguard Worker 718*61c4878aSAndroid Build Coastguard Worker } // namespace pw 719*61c4878aSAndroid Build Coastguard Worker 720*61c4878aSAndroid Build Coastguard WorkerExample uses: 721*61c4878aSAndroid Build Coastguard Worker 722*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 723*61c4878aSAndroid Build Coastguard Worker 724*61c4878aSAndroid Build Coastguard Worker // Named priorities are spread over the backend's supported priority range. 725*61c4878aSAndroid Build Coastguard Worker constexpr pw::ThreadPriority kThreadOne = ThreadPriority::Low(); 726*61c4878aSAndroid Build Coastguard Worker constexpr pw::ThreadPriority kThreadTwo = ThreadPriority::Medium(); 727*61c4878aSAndroid Build Coastguard Worker 728*61c4878aSAndroid Build Coastguard Worker // Define a priority one higher than Medium, but never equal to or greater 729*61c4878aSAndroid Build Coastguard Worker // than the next named priority, MediumHigh, if possible in the given 730*61c4878aSAndroid Build Coastguard Worker // backend. 731*61c4878aSAndroid Build Coastguard Worker constexpr pw::ThreadPriority kThreadThree = ThreadPriority::Medium<1>(); 732*61c4878aSAndroid Build Coastguard Worker 733*61c4878aSAndroid Build Coastguard Worker // Set the priority exactly one backend priority level higher than 734*61c4878aSAndroid Build Coastguard Worker // kThreadThree, if supported by the backend. 735*61c4878aSAndroid Build Coastguard Worker constexpr pw::ThreadPriority kThreadFour = kThreadThree.NextHigher(); 736*61c4878aSAndroid Build Coastguard Worker 737*61c4878aSAndroid Build Coastguard Worker static_assert(!ThreadPriority::IsSupported() || kThreadThree < kThreadFour); 738*61c4878aSAndroid Build Coastguard Worker 739*61c4878aSAndroid Build Coastguard Worker.. tip:: 740*61c4878aSAndroid Build Coastguard Worker 741*61c4878aSAndroid Build Coastguard Worker It is recommended that projects pick a starting priority level (e.g. 742*61c4878aSAndroid Build Coastguard Worker ``ThreadPriority::Lowest().NextHigher()``) and define all priorities relative 743*61c4878aSAndroid Build Coastguard Worker to it. 744*61c4878aSAndroid Build Coastguard Worker 745*61c4878aSAndroid Build Coastguard WorkerMapping OS priorities to named priorities 746*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 747*61c4878aSAndroid Build Coastguard WorkerIf thread priorities are not supported, all named priorities are the same level. 748*61c4878aSAndroid Build Coastguard Worker 749*61c4878aSAndroid Build Coastguard WorkerIf fewer than 7 levels are supported by the backend, some named levels map to 750*61c4878aSAndroid Build Coastguard Workerthe same OS priority. For example, if there are only 3 priority levels 751*61c4878aSAndroid Build Coastguard Workersupported, then ``VeryLow == Low``, ``MediumLow == Medium == MediumHigh``, and 752*61c4878aSAndroid Build Coastguard Worker``High == VeryHigh``. 753*61c4878aSAndroid Build Coastguard Worker 754*61c4878aSAndroid Build Coastguard WorkerFor backends that support 7 or more priority levels, each named priority level 755*61c4878aSAndroid Build Coastguard Workeris guaranteed to map to a unique OS priority. 756*61c4878aSAndroid Build Coastguard Worker 757*61c4878aSAndroid Build Coastguard Worker``ThreadAttrs`` 758*61c4878aSAndroid Build Coastguard Worker--------------- 759*61c4878aSAndroid Build Coastguard WorkerThe ``ThreadAttrs`` class represents generic thread attributes. It is a 760*61c4878aSAndroid Build Coastguard Workercross-platform version of :cpp:class:`pw::thread::Options`. 761*61c4878aSAndroid Build Coastguard Worker 762*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 763*61c4878aSAndroid Build Coastguard Worker 764*61c4878aSAndroid Build Coastguard Worker namespace pw { 765*61c4878aSAndroid Build Coastguard Worker 766*61c4878aSAndroid Build Coastguard Worker // Generic thread attributes. 767*61c4878aSAndroid Build Coastguard Worker class ThreadAttrs { 768*61c4878aSAndroid Build Coastguard Worker public: 769*61c4878aSAndroid Build Coastguard Worker // Initializes ThreadAttrs to their backend-defined defaults. 770*61c4878aSAndroid Build Coastguard Worker constexpr ThreadAttrs(); 771*61c4878aSAndroid Build Coastguard Worker 772*61c4878aSAndroid Build Coastguard Worker // ThreadAttrs can be copied to share properties between threads. 773*61c4878aSAndroid Build Coastguard Worker constexpr ThreadAttrs(const ThreadAttrs&) = default; 774*61c4878aSAndroid Build Coastguard Worker constexpr ThreadAttrs& operator=(const ThreadAttrs&) = default; 775*61c4878aSAndroid Build Coastguard Worker 776*61c4878aSAndroid Build Coastguard Worker // Name hint as a null-terminated string; never null. 777*61c4878aSAndroid Build Coastguard Worker constexpr const char* name() const; 778*61c4878aSAndroid Build Coastguard Worker constexpr ThreadAttrs& set_name(const char* name); 779*61c4878aSAndroid Build Coastguard Worker 780*61c4878aSAndroid Build Coastguard Worker constexpr Priority priority() const; 781*61c4878aSAndroid Build Coastguard Worker constexpr ThreadAttrs& set_priority(Priority priority); 782*61c4878aSAndroid Build Coastguard Worker 783*61c4878aSAndroid Build Coastguard Worker // Increment or decrement the priority to set task priorities relative to 784*61c4878aSAndroid Build Coastguard Worker // one another. 785*61c4878aSAndroid Build Coastguard Worker constexpr ThreadAttrs& set_priority_next_higher(); 786*61c4878aSAndroid Build Coastguard Worker constexpr ThreadAttrs& set_priority_next_lower(); 787*61c4878aSAndroid Build Coastguard Worker 788*61c4878aSAndroid Build Coastguard Worker constexpr size_t stack_size_bytes() const; 789*61c4878aSAndroid Build Coastguard Worker constexpr ThreadAttrs& set_stack_size_bytes(size_t stack_size_bytes); 790*61c4878aSAndroid Build Coastguard Worker }; 791*61c4878aSAndroid Build Coastguard Worker 792*61c4878aSAndroid Build Coastguard Worker } // namespace pw 793*61c4878aSAndroid Build Coastguard Worker 794*61c4878aSAndroid Build Coastguard Worker``ThreadAttrs`` may be defined at runtime or as ``constexpr`` constants. 795*61c4878aSAndroid Build Coastguard WorkerProjects may find it helpful to define ``ThreadAttrs`` in a centralized 796*61c4878aSAndroid Build Coastguard Workerlocation. 797*61c4878aSAndroid Build Coastguard Worker 798*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 799*61c4878aSAndroid Build Coastguard Worker 800*61c4878aSAndroid Build Coastguard Worker #include "pw_thread/attrs.h" 801*61c4878aSAndroid Build Coastguard Worker #include "my_project/config.h" 802*61c4878aSAndroid Build Coastguard Worker 803*61c4878aSAndroid Build Coastguard Worker namespace my_project { 804*61c4878aSAndroid Build Coastguard Worker 805*61c4878aSAndroid Build Coastguard Worker // Global list of thread attributes. 806*61c4878aSAndroid Build Coastguard Worker 807*61c4878aSAndroid Build Coastguard Worker inline constexpr auto kThreadOne = pw::ThreadAttrs() 808*61c4878aSAndroid Build Coastguard Worker .set_name("thread one") 809*61c4878aSAndroid Build Coastguard Worker .set_stack_size_bytes(1024) 810*61c4878aSAndroid Build Coastguard Worker .set_priority(pw::ThreadPriority::Medium()); 811*61c4878aSAndroid Build Coastguard Worker 812*61c4878aSAndroid Build Coastguard Worker inline constexpr auto kThreadTwo = pw::ThreadAttrs(kThreadOne) 813*61c4878aSAndroid Build Coastguard Worker .set_name("thread two"); 814*61c4878aSAndroid Build Coastguard Worker 815*61c4878aSAndroid Build Coastguard Worker inline constexpr auto kImportantThread = pw::ThreadAttrs() 816*61c4878aSAndroid Build Coastguard Worker .set_name("important!") 817*61c4878aSAndroid Build Coastguard Worker .set_stack_size_bytes(IMPORTANT_THREAD_STACK_SIZE_BYTES) 818*61c4878aSAndroid Build Coastguard Worker .set_priority(IMPORTANT_THREAD_PRIORITY); 819*61c4878aSAndroid Build Coastguard Worker 820*61c4878aSAndroid Build Coastguard Worker inline constexpr auto kLessImportantThread = pw::ThreadAttrs() 821*61c4878aSAndroid Build Coastguard Worker .set_name("also important!") 822*61c4878aSAndroid Build Coastguard Worker .set_stack_size_bytes(IMPORTANT_THREAD_STACK_SIZE_BYTES) 823*61c4878aSAndroid Build Coastguard Worker .set_priority(kImportantThread.priority().NextLower()); 824*61c4878aSAndroid Build Coastguard Worker 825*61c4878aSAndroid Build Coastguard Worker static_assert( 826*61c4878aSAndroid Build Coastguard Worker !pw::ThreadPriority::IsSupported() || 827*61c4878aSAndroid Build Coastguard Worker kImportantThread.priority() > kLessImportantThread.priority(), 828*61c4878aSAndroid Build Coastguard Worker "If the platform supports priorities, ImportantThread must be higher " 829*61c4878aSAndroid Build Coastguard Worker "priority than LessImportantThread"); 830*61c4878aSAndroid Build Coastguard Worker 831*61c4878aSAndroid Build Coastguard Worker } // namespace my_project 832*61c4878aSAndroid Build Coastguard Worker 833*61c4878aSAndroid Build Coastguard Worker``ThreadContext`` 834*61c4878aSAndroid Build Coastguard Worker----------------- 835*61c4878aSAndroid Build Coastguard Worker``pw::ThreadContext`` represents the resources required to run one thread. 836*61c4878aSAndroid Build Coastguard WorkerThis may include platform-specific handles, a statically allocated thread 837*61c4878aSAndroid Build Coastguard Workercontrol block (TCB), or the thread's stack. If platforms do not require manual 838*61c4878aSAndroid Build Coastguard Workerallocation for threads, ``pw::ThreadContext`` may be empty. 839*61c4878aSAndroid Build Coastguard Worker 840*61c4878aSAndroid Build Coastguard Worker``ThreadContext`` is a generic wrapper around a backend-defined object. It 841*61c4878aSAndroid Build Coastguard Workerprevents unintentional access of backend-specific features on the native object. 842*61c4878aSAndroid Build Coastguard Worker 843*61c4878aSAndroid Build Coastguard Worker``ThreadContext`` objects may be reused if their associated thread has been 844*61c4878aSAndroid Build Coastguard Workerjoined. 845*61c4878aSAndroid Build Coastguard Worker 846*61c4878aSAndroid Build Coastguard Worker``ThreadContext`` takes a few forms: 847*61c4878aSAndroid Build Coastguard Worker 848*61c4878aSAndroid Build Coastguard Worker- ``ThreadContext<kStackSizeHintBytes>`` -- Context with internally allocated 849*61c4878aSAndroid Build Coastguard Worker thread stack. 850*61c4878aSAndroid Build Coastguard Worker- ``ThreadContext<kThreadAttrs>`` -- Context associated with a set of 851*61c4878aSAndroid Build Coastguard Worker ``ThreadAttrs``. Uses internally or externally allocated stack based on the 852*61c4878aSAndroid Build Coastguard Worker ``ThreadAttrs``. 853*61c4878aSAndroid Build Coastguard Worker- ``ThreadContext<>`` -- Context with a runtime-provided ``ThreadStack``. 854*61c4878aSAndroid Build Coastguard Worker 855*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 856*61c4878aSAndroid Build Coastguard Worker 857*61c4878aSAndroid Build Coastguard Worker namespace pw { 858*61c4878aSAndroid Build Coastguard Worker 859*61c4878aSAndroid Build Coastguard Worker // Represents the resources required for one thread. May include OS data 860*61c4878aSAndroid Build Coastguard Worker // structures, the thread stack, or be empty, depending on the platform. 861*61c4878aSAndroid Build Coastguard Worker // 862*61c4878aSAndroid Build Coastguard Worker // ThreadContext may be reused or deleted if the associated thread is 863*61c4878aSAndroid Build Coastguard Worker // joined. 864*61c4878aSAndroid Build Coastguard Worker template <auto> 865*61c4878aSAndroid Build Coastguard Worker class ThreadContext; 866*61c4878aSAndroid Build Coastguard Worker 867*61c4878aSAndroid Build Coastguard Worker // ThreadContext with integrated stack. 868*61c4878aSAndroid Build Coastguard Worker template <size_t kStackSizeHintBytes, 869*61c4878aSAndroid Build Coastguard Worker size_t kAlignmentBytes = alignof(std::max_align_t)> 870*61c4878aSAndroid Build Coastguard Worker class ThreadContext { 871*61c4878aSAndroid Build Coastguard Worker public: 872*61c4878aSAndroid Build Coastguard Worker constexpr ThreadContext() = default; 873*61c4878aSAndroid Build Coastguard Worker 874*61c4878aSAndroid Build Coastguard Worker private: 875*61c4878aSAndroid Build Coastguard Worker backend::NativeContextWithStack<kStackSizeHintBytes, kAlignmentBytes> native_context_; 876*61c4878aSAndroid Build Coastguard Worker }; 877*61c4878aSAndroid Build Coastguard Worker 878*61c4878aSAndroid Build Coastguard Worker // Alias for ThreadContext with the backend's default stack size. 879*61c4878aSAndroid Build Coastguard Worker using DefaultThreadContext = ThreadContext<backend::kDefaultStackSizeBytes>; 880*61c4878aSAndroid Build Coastguard Worker 881*61c4878aSAndroid Build Coastguard Worker // Declares a ThreadContext that is associated with a specific set of thread 882*61c4878aSAndroid Build Coastguard Worker // attributes. Internally allocates the stack if the stack size hint is set. 883*61c4878aSAndroid Build Coastguard Worker // The ThreadContext may be reused if the associated thread is joined, but 884*61c4878aSAndroid Build Coastguard Worker // all threads use the same ThreadAttrs. 885*61c4878aSAndroid Build Coastguard Worker template <const ThreadAttrs& kAttributes> 886*61c4878aSAndroid Build Coastguard Worker class ThreadContext { 887*61c4878aSAndroid Build Coastguard Worker private: 888*61c4878aSAndroid Build Coastguard Worker ThreadContext<kAttributes.stack_size_bytes()> context_; 889*61c4878aSAndroid Build Coastguard Worker }; 890*61c4878aSAndroid Build Coastguard Worker 891*61c4878aSAndroid Build Coastguard Worker } // namespace pw 892*61c4878aSAndroid Build Coastguard Worker 893*61c4878aSAndroid Build Coastguard Worker #include "pw_thread_backend/thread_inline.h" 894*61c4878aSAndroid Build Coastguard Worker 895*61c4878aSAndroid Build Coastguard Worker``ThreadStack`` 896*61c4878aSAndroid Build Coastguard Worker--------------- 897*61c4878aSAndroid Build Coastguard WorkerRepresents a thread stack of the specified size. The object may be empty if the 898*61c4878aSAndroid Build Coastguard Workerbackends dynamically allocate stacks. 899*61c4878aSAndroid Build Coastguard Worker 900*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 901*61c4878aSAndroid Build Coastguard Worker 902*61c4878aSAndroid Build Coastguard Worker namespace pw { 903*61c4878aSAndroid Build Coastguard Worker 904*61c4878aSAndroid Build Coastguard Worker template <size_t kStackSizeBytes> 905*61c4878aSAndroid Build Coastguard Worker class ThreadStack { 906*61c4878aSAndroid Build Coastguard Worker private: 907*61c4878aSAndroid Build Coastguard Worker backend::NativeThreadStack<kStackSizeBytes> native_stack_; 908*61c4878aSAndroid Build Coastguard Worker }; 909*61c4878aSAndroid Build Coastguard Worker 910*61c4878aSAndroid Build Coastguard Worker } // namespace pw 911*61c4878aSAndroid Build Coastguard Worker 912*61c4878aSAndroid Build Coastguard Worker``ThreadStack`` may specified separately from the ``ThreadContext`` if users 913*61c4878aSAndroid Build Coastguard Workerhave need to declare stacks in different sections or want to keep them separate 914*61c4878aSAndroid Build Coastguard Workerfrom other items in the ``ThreadContext``. The ``ThreadStack`` is set on the 915*61c4878aSAndroid Build Coastguard Worker``ThreadAttrs`` instead of the stack size: 916*61c4878aSAndroid Build Coastguard Worker 917*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 918*61c4878aSAndroid Build Coastguard Worker 919*61c4878aSAndroid Build Coastguard Worker STACK_SECTION alignas(256) constinit ThreadStack<kAppStackSizeBytes> kMainStack; 920*61c4878aSAndroid Build Coastguard Worker 921*61c4878aSAndroid Build Coastguard Worker constexpr pw::ThreadAttrs kMainThread = pw::ThreadAttrs() 922*61c4878aSAndroid Build Coastguard Worker .set_name("MainThread") 923*61c4878aSAndroid Build Coastguard Worker .set_stack(kMainStack) 924*61c4878aSAndroid Build Coastguard Worker .set_priority(kMainPriority); 925*61c4878aSAndroid Build Coastguard Worker 926*61c4878aSAndroid Build Coastguard Worker ThreadContext<kMainThread> kMainThreadContext; 927*61c4878aSAndroid Build Coastguard Worker 928*61c4878aSAndroid Build Coastguard Worker void RunThread() { 929*61c4878aSAndroid Build Coastguard Worker pw::Thread(kMainThreadContext, [] { /* thread body */ }).detach(); 930*61c4878aSAndroid Build Coastguard Worker } 931*61c4878aSAndroid Build Coastguard Worker 932*61c4878aSAndroid Build Coastguard Worker``ThreadContext`` objects that are not associated with a ``ThreadAttrs`` work 933*61c4878aSAndroid Build Coastguard Workersimilarly: 934*61c4878aSAndroid Build Coastguard Worker 935*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 936*61c4878aSAndroid Build Coastguard Worker 937*61c4878aSAndroid Build Coastguard Worker STACK_SECTION alignas(256) constinit ThreadStack<kAppStackSizeBytes> kAppStack; 938*61c4878aSAndroid Build Coastguard Worker 939*61c4878aSAndroid Build Coastguard Worker ThreadContext<> kAppThreadContext; 940*61c4878aSAndroid Build Coastguard Worker 941*61c4878aSAndroid Build Coastguard Worker void RunThreads() { 942*61c4878aSAndroid Build Coastguard Worker pw::Thread thread(kAppThreadContext, 943*61c4878aSAndroid Build Coastguard Worker pw::ThreadAttrs().set_stack(kAppStack).set_name("T1"), 944*61c4878aSAndroid Build Coastguard Worker [] { /* thread body */ }); 945*61c4878aSAndroid Build Coastguard Worker thread.join() 946*61c4878aSAndroid Build Coastguard Worker 947*61c4878aSAndroid Build Coastguard Worker pw::Thread thread(kAppThreadContext, 948*61c4878aSAndroid Build Coastguard Worker pw::ThreadAttrs().set_stack(kAppStack).set_name("T2"), 949*61c4878aSAndroid Build Coastguard Worker [] { /* thread body */ }); 950*61c4878aSAndroid Build Coastguard Worker thread.join(); 951*61c4878aSAndroid Build Coastguard Worker } 952*61c4878aSAndroid Build Coastguard Worker 953*61c4878aSAndroid Build Coastguard WorkerThe ``STACK_SECTION`` macro would be provided by a config header: 954*61c4878aSAndroid Build Coastguard Worker 955*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 956*61c4878aSAndroid Build Coastguard Worker 957*61c4878aSAndroid Build Coastguard Worker #if BUILDING_FOR_DEVICE_A 958*61c4878aSAndroid Build Coastguard Worker #define STACK_SECTION PW_PLACE_IN_SECTION(".thread_stacks") 959*61c4878aSAndroid Build Coastguard Worker #else // building for device B 960*61c4878aSAndroid Build Coastguard Worker #define STACK_SECTION // section doesn't matter 961*61c4878aSAndroid Build Coastguard Worker #endif // BUILDING_FOR_DEVICE_A 962*61c4878aSAndroid Build Coastguard Worker 963*61c4878aSAndroid Build Coastguard Worker``Thread`` additions 964*61c4878aSAndroid Build Coastguard Worker-------------------- 965*61c4878aSAndroid Build Coastguard Worker``pw::Thread`` will accept ``ThreadContext`` and ``ThreadAttrs``. 966*61c4878aSAndroid Build Coastguard Worker 967*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 968*61c4878aSAndroid Build Coastguard Worker 969*61c4878aSAndroid Build Coastguard Worker class Thread { 970*61c4878aSAndroid Build Coastguard Worker // Existing constructor. 971*61c4878aSAndroid Build Coastguard Worker Thread(const Options& options, Function<void()>&& entry) 972*61c4878aSAndroid Build Coastguard Worker 973*61c4878aSAndroid Build Coastguard Worker // Creates a thread with a ThreadContext associated with a ThreadAttrs. 974*61c4878aSAndroid Build Coastguard Worker template <const ThreadAttrs& kAttributes> 975*61c4878aSAndroid Build Coastguard Worker Thread(ThreadContext<kAttributes>& context, Function<void()>&& entry); 976*61c4878aSAndroid Build Coastguard Worker 977*61c4878aSAndroid Build Coastguard Worker // Creates a thread from attributes passed in a template parameter. 978*61c4878aSAndroid Build Coastguard Worker template <const ThreadAttrs& kAttributes, size_t kStackSizeHintBytes> 979*61c4878aSAndroid Build Coastguard Worker Thread(ThreadContext<kStackSizeHintBytes>& context, 980*61c4878aSAndroid Build Coastguard Worker Function<void()>&& entry); 981*61c4878aSAndroid Build Coastguard Worker 982*61c4878aSAndroid Build Coastguard Worker // Creates a thread from context and attributes. Performs a runtime check 983*61c4878aSAndroid Build Coastguard Worker // that the ThreadContext's stack is large enough, which can be avoided by 984*61c4878aSAndroid Build Coastguard Worker // using one of the other constructors. 985*61c4878aSAndroid Build Coastguard Worker template <size_t kStackSizeHintBytes> 986*61c4878aSAndroid Build Coastguard Worker Thread(ThreadContext<kStackSizeHintBytes>& context, 987*61c4878aSAndroid Build Coastguard Worker const ThreadAttrs& attributes, 988*61c4878aSAndroid Build Coastguard Worker Function<void()>&& entry); 989*61c4878aSAndroid Build Coastguard Worker 990*61c4878aSAndroid Build Coastguard Worker // Creates a thread with the provided context and attributes. The 991*61c4878aSAndroid Build Coastguard Worker // attributes have a ThreadStack set. 992*61c4878aSAndroid Build Coastguard Worker Thread(ThreadContext<>& context, 993*61c4878aSAndroid Build Coastguard Worker const ThreadAttrs& attributes, 994*61c4878aSAndroid Build Coastguard Worker Function<void()>&& entry); 995*61c4878aSAndroid Build Coastguard Worker 996*61c4878aSAndroid Build Coastguard WorkerDynamic thread creation function 997*61c4878aSAndroid Build Coastguard Worker-------------------------------- 998*61c4878aSAndroid Build Coastguard WorkerThe ``pw::Thread::Start`` function starts a thread as simply as possible. It 999*61c4878aSAndroid Build Coastguard Workerstarts returns a ``pw::Thread`` that runs a user-provided function. Users may 1000*61c4878aSAndroid Build Coastguard Workeroptionally provide ``pw::ThreadAttrs``. 1001*61c4878aSAndroid Build Coastguard Worker 1002*61c4878aSAndroid Build Coastguard Worker``pw::Thread::Start`` is implemented with a new, separate facade. The backend 1003*61c4878aSAndroid Build Coastguard Workermay statically or dynamically allocate resources. A default backend that 1004*61c4878aSAndroid Build Coastguard Workerstatically allocates resources for a fixed number of threads will be provided in 1005*61c4878aSAndroid Build Coastguard Workerupstream Pigweed. 1006*61c4878aSAndroid Build Coastguard Worker 1007*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 1008*61c4878aSAndroid Build Coastguard Worker 1009*61c4878aSAndroid Build Coastguard Worker namespace pw { 1010*61c4878aSAndroid Build Coastguard Worker 1011*61c4878aSAndroid Build Coastguard Worker class Thread { 1012*61c4878aSAndroid Build Coastguard Worker ... 1013*61c4878aSAndroid Build Coastguard Worker 1014*61c4878aSAndroid Build Coastguard Worker // Starts running the thread_body in a separate thread. The thread is 1015*61c4878aSAndroid Build Coastguard Worker // allocated and managed by the backend. 1016*61c4878aSAndroid Build Coastguard Worker template <typename Function, typename... Args> 1017*61c4878aSAndroid Build Coastguard Worker static Thread Start(Function&& thread_body, Args&&... args); 1018*61c4878aSAndroid Build Coastguard Worker 1019*61c4878aSAndroid Build Coastguard Worker template <typename Function, typename... Args> 1020*61c4878aSAndroid Build Coastguard Worker static Thread Start(const pw::ThreadAttrs& attributes, Function&& thread_body, Args&&... args); 1021*61c4878aSAndroid Build Coastguard Worker }; 1022*61c4878aSAndroid Build Coastguard Worker 1023*61c4878aSAndroid Build Coastguard Worker } // namespace pw 1024