xref: /aosp_15_r20/external/pigweed/seed/0128.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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