Dawn Framework 1.0
Universal data acquisition framework for embedded systems
thread.cxx
1// dawn/src/common/thread.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/common/thread.hxx"
7
8#include <cerrno>
9#include <cstring>
10#include <sched.h>
11
12#include "dawn/debug.hxx"
13
14using namespace dawn;
15
17{
18 if (thCreated)
19 {
20 thQuit = true;
21 (void)joinThread();
22 }
23
24 thQuitDone = true;
25}
26
27int CThreadedObject::joinThread()
28{
29 int ret;
30
31 if (!thCreated)
32 {
33 return OK;
34 }
35
36 ret = pthread_join(th, nullptr);
37 if (ret != 0)
38 {
39 DAWNERR("Failed to join worker thread (%d)\n", ret);
40 return -ret;
41 }
42
43 thCreated = false;
44 std::memset(&th, 0, sizeof(th));
45 return OK;
46}
47
48int CThreadedObject::buildThreadAttr(pthread_attr_t &attr, bool &needsDestroy) const
49{
50 struct sched_param param;
51 int maxPrio;
52 int minPrio;
53 int policy;
54 int priority;
55 int ret;
56
57 needsDestroy = false;
58
59 if (threadConfig.priority < THREAD_PRIORITY_DEFAULT)
60 {
61 DAWNERR("Invalid worker thread priority %d\n", threadConfig.priority);
62 return -EINVAL;
63 }
64
65 if (threadConfig.scheduler < THREAD_SCHEDULER_DEFAULT)
66 {
67 DAWNERR("Invalid worker thread scheduler %d\n", threadConfig.scheduler);
68 return -EINVAL;
69 }
70
71 ret = pthread_attr_init(&attr);
72 if (ret != 0)
73 {
74 DAWNERR("Failed to initialize worker thread attributes (%d)\n", ret);
75 return -ret;
76 }
77
78 needsDestroy = true;
79
80 if (threadConfig.stackSize > 0)
81 {
82 ret = pthread_attr_setstacksize(&attr, threadConfig.stackSize);
83 if (ret != 0)
84 {
85 DAWNERR(
86 "Failed to set worker thread stack size to %zu (%d)\n", threadConfig.stackSize, ret);
87 return -ret;
88 }
89 }
90
91 if (threadConfig.priority == THREAD_PRIORITY_DEFAULT &&
92 threadConfig.scheduler == THREAD_SCHEDULER_DEFAULT)
93 {
94 return OK;
95 }
96
97 ret = pthread_getschedparam(pthread_self(), &policy, &param);
98 if (ret != 0)
99 {
100 DAWNERR("Failed to read creator thread scheduler (%d)\n", ret);
101 return -ret;
102 }
103
104 if (threadConfig.scheduler != THREAD_SCHEDULER_DEFAULT)
105 {
106 policy = threadConfig.scheduler;
107 }
108
109 minPrio = sched_get_priority_min(policy);
110 maxPrio = sched_get_priority_max(policy);
111 if (minPrio < 0 || maxPrio < 0)
112 {
113 int err;
114
115 err = errno != 0 ? errno : EINVAL;
116 DAWNERR("Failed to query priority range for scheduler %d\n", policy);
117 return -err;
118 }
119
120 priority = param.sched_priority;
121 if (threadConfig.priority != THREAD_PRIORITY_DEFAULT)
122 {
123 priority = threadConfig.priority;
124 }
125 else if (priority < minPrio || priority > maxPrio)
126 {
127 priority = minPrio;
128 }
129
130 if (priority < minPrio || priority > maxPrio)
131 {
132 DAWNERR("Worker thread priority %d is outside scheduler %d range [%d, %d]\n",
133 priority,
134 policy,
135 minPrio,
136 maxPrio);
137 return -EINVAL;
138 }
139
140 param.sched_priority = priority;
141
142 ret = pthread_attr_setschedpolicy(&attr, policy);
143 if (ret != 0)
144 {
145 DAWNERR("Failed to set worker thread scheduler %d (%d)\n", policy, ret);
146 return -ret;
147 }
148
149 ret = pthread_attr_setschedparam(&attr, &param);
150 if (ret != 0)
151 {
152 DAWNERR("Failed to set worker thread priority %d (%d)\n", priority, ret);
153 return -ret;
154 }
155
156 ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
157 if (ret != 0)
158 {
159 DAWNERR("Failed to enable explicit worker thread scheduling (%d)\n", ret);
160 return -ret;
161 }
162
163 return OK;
164}
165
167{
168 pthread_attr_t attr;
169 bool needsDestroy;
170 int ret;
171
172 if (thCreated)
173 {
174 if (!thQuitDone)
175 {
176 DAWNERR("Thread already running\n");
177 return -EBUSY;
178 }
179
180 ret = joinThread();
181 if (ret != OK)
182 {
183 return ret;
184 }
185 }
186
187 if (!threadFunc)
188 {
189 DAWNERR("Thread function not set before calling threadStart()\n");
190 return -EINVAL;
191 }
192
193 thQuit = false;
194 thQuitDone = false;
195
196 ret = buildThreadAttr(attr, needsDestroy);
197 if (ret != OK)
198 {
199 if (needsDestroy)
200 {
201 int destroyRet;
202
203 destroyRet = pthread_attr_destroy(&attr);
204 if (destroyRet != 0)
205 {
206 DAWNERR("Failed to destroy worker thread attributes (%d)\n", destroyRet);
207 }
208 }
209
210 thQuit = true;
211 thQuitDone = true;
212 return ret;
213 }
214
215 ret = pthread_create(&th, needsDestroy ? &attr : nullptr, &CThreadedObject::threadEntry, this);
216
217 if (needsDestroy)
218 {
219 int destroyRet;
220
221 destroyRet = pthread_attr_destroy(&attr);
222 if (destroyRet != 0)
223 {
224 DAWNERR("Failed to destroy worker thread attributes (%d)\n", destroyRet);
225 }
226 }
227
228 if (ret != 0)
229 {
230 DAWNERR("Failed to create worker thread (%d)\n", ret);
231 thQuit = true;
232 thQuitDone = true;
233 return -ret;
234 }
235
236 thCreated = true;
237 return OK;
238}
239
241{
242 int ret;
243
244 thQuit = true;
245
246 ret = joinThread();
247 if (ret != OK)
248 {
249 return ret;
250 }
251
252 thQuitDone = true;
253 return OK;
254}
255
257{
258 return !thQuitDone;
259}
260
261void CThreadedObject::threadWrapper()
262{
263 if (threadFunc)
264 {
265 threadFunc();
266 }
267
268 thQuitDone = true;
269}
270
271void *CThreadedObject::threadEntry(void *arg)
272{
273 CThreadedObject *self;
274
275 self = static_cast<CThreadedObject *>(arg);
276 if (self != nullptr)
277 {
278 self->threadWrapper();
279 }
280
281 return nullptr;
282}
Portable thread owner abstraction for Dawn components.
Definition thread.hxx:32
bool isRunning() const
Check if the worker thread is running.
Definition thread.cxx:256
int threadStop()
Stop the worker thread.
Definition thread.cxx:240
virtual ~CThreadedObject()
Destructor - cleans up thread resources.
Definition thread.cxx:16
static int THREAD_SCHEDULER_DEFAULT
Default scheduler behavior.
Definition thread.hxx:48
int threadStart()
Start the worker thread.
Definition thread.cxx:166
static int THREAD_PRIORITY_DEFAULT
Default thread priority behavior.
Definition thread.hxx:40
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
int priority
Requested thread priority (0 = creator default).
Definition thread.hxx:57
size_t stackSize
Requested stack size in bytes (0 = OS default).
Definition thread.hxx:56
int scheduler
Requested scheduler policy (-1 = creator default).
Definition thread.hxx:58