xref: /aosp_15_r20/external/pigweed/pw_system/threads.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_system/config.h"
16 #include "pw_thread/thread.h"
17 
18 // For now, pw_system:async only supports FreeRTOS or standard library threads.
19 //
20 // This file will be rewritten once the SEED-0128 generic thread creation APIs
21 // are available. Details of the threads owned by pw_system should be an
22 // internal implementation detail. If configuration is necessary, it can be
23 // exposed through regular config options, rather than requiring users to
24 // implement functions.
25 
26 #if __has_include("FreeRTOS.h")
27 
28 #include "FreeRTOS.h"
29 #include "pw_thread_freertos/options.h"
30 #include "task.h"
31 
32 namespace pw::system {
33 namespace {
34 
ToWords(size_t bytes)35 constexpr size_t ToWords(size_t bytes) {
36   return (bytes + sizeof(StackType_t) - 1) / sizeof(StackType_t);
37 }
38 
39 }  // namespace
40 
StartScheduler()41 [[noreturn]] void StartScheduler() {
42   vTaskStartScheduler();
43   PW_UNREACHABLE;
44 }
45 
46 // Low to high priorities.
47 enum class ThreadPriority : UBaseType_t {
48   kDispatcher = tskIDLE_PRIORITY + 1,
49   // TODO(amontanez): These should ideally be at different priority levels, but
50   // there's synchronization issues when they are.
51   kWorkQueue = kDispatcher,
52   kLog = kDispatcher,
53   kRpc = kDispatcher,
54   kTransfer = kDispatcher,
55   kNumPriorities,
56 };
57 
58 static_assert(static_cast<UBaseType_t>(ThreadPriority::kNumPriorities) <=
59               configMAX_PRIORITIES);
60 
LogThreadOptions()61 const thread::Options& LogThreadOptions() {
62   static thread::freertos::StaticContextWithStack<ToWords(
63       kLogThreadStackSizeBytes)>
64       context;
65   static constexpr auto options =
66       pw::thread::freertos::Options()
67           .set_name("LogThread")
68           .set_static_context(context)
69           .set_priority(static_cast<UBaseType_t>(ThreadPriority::kLog));
70   return options;
71 }
72 
RpcThreadOptions()73 const thread::Options& RpcThreadOptions() {
74   static thread::freertos::StaticContextWithStack<ToWords(
75       kRpcThreadStackSizeBytes)>
76       context;
77   static constexpr auto options =
78       pw::thread::freertos::Options()
79           .set_name("RpcThread")
80           .set_static_context(context)
81           .set_priority(static_cast<UBaseType_t>(ThreadPriority::kRpc));
82   return options;
83 }
84 
TransferThreadOptions()85 const thread::Options& TransferThreadOptions() {
86   static thread::freertos::StaticContextWithStack<ToWords(
87       kTransferThreadStackSizeBytes)>
88       context;
89   static constexpr auto options =
90       pw::thread::freertos::Options()
91           .set_name("TransferThread")
92           .set_static_context(context)
93           .set_priority(static_cast<UBaseType_t>(ThreadPriority::kTransfer));
94   return options;
95 }
96 
DispatcherThreadOptions()97 const thread::Options& DispatcherThreadOptions() {
98   static thread::freertos::StaticContextWithStack<ToWords(
99       kDispatcherThreadStackSizeBytes)>
100       context;
101   static constexpr auto options =
102       pw::thread::freertos::Options()
103           .set_name("DispatcherThread")
104           .set_static_context(context)
105           .set_priority(static_cast<UBaseType_t>(ThreadPriority::kDispatcher));
106   return options;
107 }
108 
WorkQueueThreadOptions()109 const thread::Options& WorkQueueThreadOptions() {
110   static thread::freertos::StaticContextWithStack<ToWords(
111       kWorkQueueThreadStackSizeBytes)>
112       context;
113   static constexpr auto options =
114       pw::thread::freertos::Options()
115           .set_name("WorkQueueThread")
116           .set_static_context(context)
117           .set_priority(static_cast<UBaseType_t>(ThreadPriority::kWorkQueue));
118   return options;
119 }
120 
121 }  // namespace pw::system
122 
123 #else  // STL
124 
125 #include <chrono>
126 #include <thread>
127 
128 #include "pw_thread_stl/options.h"
129 
130 namespace pw::system {
131 namespace {
132 
133 thread::stl::Options stl_thread_options;
134 
135 }  // namespace
136 
StartScheduler()137 [[noreturn]] void StartScheduler() {
138   while (true) {
139     std::this_thread::sleep_for(std::chrono::system_clock::duration::max());
140   }
141 }
142 
LogThreadOptions()143 const thread::Options& LogThreadOptions() { return stl_thread_options; }
144 
RpcThreadOptions()145 const thread::Options& RpcThreadOptions() { return stl_thread_options; }
146 
TransferThreadOptions()147 const thread::Options& TransferThreadOptions() { return stl_thread_options; }
148 
DispatcherThreadOptions()149 const thread::Options& DispatcherThreadOptions() { return stl_thread_options; }
150 
WorkQueueThreadOptions()151 const thread::Options& WorkQueueThreadOptions() { return stl_thread_options; }
152 
153 }  // namespace pw::system
154 
155 #endif  // __has_include("FreeRTOS.h")
156