Statistics
| Branch: | Tag: | Revision:

amiro-os / kernel / patches / introduce-thread-hierarchy.patch @ 732a4657

History | View | Annotate | Download (51.975 KB)

1
diff --git a/os/rt/include/chschd.h b/os/rt/include/chschd.h
2
--- a/os/rt/include/chschd.h
3
+++ b/os/rt/include/chschd.h
4
@@ -176,6 +176,23 @@ struct ch_thread {
5
    * @brief   References to this thread.
6
    */
7
   trefs_t               refs;
8
+#endif
9
+#if (CH_CFG_USE_THREADHIERARCHY == TRUE) || defined(__DOXYGEN__)
10
+  /**
11
+   * @brief   Pointer to the parent thread.
12
+   * @note    NULL only for the main thread.
13
+   */
14
+  thread_t              *parent;
15
+  /**
16
+   * @brief   Pointer to the first child thread.
17
+   * @note    NULL if there are no child threads.
18
+   */
19
+  thread_t              *children;
20
+  /**
21
+   * @brief   Pointer to the next sibling thread.
22
+   * @brief   NULL if there are no more child threads.
23
+   */
24
+  thread_t              *sibling;
25
 #endif
26
   /**
27
    * @brief   Number of ticks remaining to this thread.
28
diff --git a/os/rt/include/chthreads.h b/os/rt/include/chthreads.h
29
--- a/os/rt/include/chthreads.h
30
+++ b/os/rt/include/chthreads.h
31
@@ -79,6 +79,12 @@ typedef struct {
32
    * @brief   Thread argument.
33
    */
34
   void              *arg;
35
+#if (CH_CFG_USE_THREADHIERARCHY) == TRUE || defined(__DOXYGEN__)
36
+  /**
37
+   * @brief   Pointer to the parent thread.
38
+   */
39
+  thread_t          *parent;
40
+#endif
41
 } thread_descriptor_t;
42
 
43
 /*===========================================================================*/
44
@@ -220,7 +226,11 @@ typedef struct {
45
 #ifdef __cplusplus
46
 extern "C" {
47
 #endif
48
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
49
+   thread_t *_thread_init(thread_t *tp, thread_t* parent, const char *name, tprio_t prio);
50
+#else
51
    thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio);
52
+#endif
53
 #if CH_DBG_FILL_THREADS == TRUE
54
   void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v);
55
 #endif
56
@@ -228,8 +238,13 @@ extern "C" {
57
   thread_t *chThdCreateSuspended(const thread_descriptor_t *tdp);
58
   thread_t *chThdCreateI(const thread_descriptor_t *tdp);
59
   thread_t *chThdCreate(const thread_descriptor_t *tdp);
60
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
61
+  thread_t *chThdCreateStatic(void *wsp, size_t size,
62
+                              tprio_t prio, tfunc_t pf, void *arg, thread_t *parent);
63
+#else
64
   thread_t *chThdCreateStatic(void *wsp, size_t size,
65
                               tprio_t prio, tfunc_t pf, void *arg);
66
+#endif
67
   thread_t *chThdStart(thread_t *tp);
68
 #if CH_CFG_USE_REGISTRY == TRUE
69
   thread_t *chThdAddRef(thread_t *tp);
70
diff --git a/os/rt/src/chsys.c b/os/rt/src/chsys.c
71
--- a/os/rt/src/chsys.c
72
+++ b/os/rt/src/chsys.c
73
@@ -126,14 +126,26 @@ void chSysInit(void) {
74
 #if CH_CFG_NO_IDLE_THREAD == FALSE
75
   /* Now this instructions flow becomes the main thread.*/
76
 #if CH_CFG_USE_REGISTRY == TRUE
77
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
78
+  currp = _thread_init(&ch.mainthread, NULL, (const char *)&ch_debug, NORMALPRIO);
79
+#else
80
   currp = _thread_init(&ch.mainthread, (const char *)&ch_debug, NORMALPRIO);
81
+#endif
82
+#else
83
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
84
+  currp = _thread_init(&ch.mainthread, NULL, "main", NORMALPRIO);
85
 #else
86
   currp = _thread_init(&ch.mainthread, "main", NORMALPRIO);
87
 #endif
88
+#endif
89
 #else
90
   /* Now this instructions flow becomes the idle thread.*/
91
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
92
+  currp = _thread_init(&ch.mainthread, NULL, "idle", IDLEPRIO);
93
+#else
94
   currp = _thread_init(&ch.mainthread, "idle", IDLEPRIO);
95
 #endif
96
+#endif
97
 
98
 #if CH_DBG_ENABLE_STACK_CHECK == TRUE
99
   {
100
@@ -172,6 +184,9 @@ void chSysInit(void) {
101
       THD_WORKING_AREA_END(ch_idle_thread_wa),
102
       IDLEPRIO,
103
       _idle_thread,
104
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
105
+      NULL,
106
+#endif
107
       NULL
108
     };
109
 
110
diff --git a/os/rt/src/chthreads.c b/os/rt/src/chthreads.c
111
--- a/os/rt/src/chthreads.c
112
+++ b/os/rt/src/chthreads.c
113
@@ -70,22 +70,67 @@
114
 /* Module local functions.                                                   */
115
 /*===========================================================================*/
116
 
117
+#if CH_CFG_USE_THREADHIERARCHY == TRUE || defined(__DOXYGEN__)
118
+/**
119
+ * @brief   Insert a thread to the list of children of another thread.
120
+ * @details If @p CH_CFG_THREADHIERARCHY_ORDERED is @p TRUE, children are ordered by their priorities (high to low).
121
+ *          Children with identical priority are ordered by 'age' (youngest first).
122
+ *
123
+ * @param[in] parent  Pointer to the parent thread (must not be NULL).
124
+ * @param[in] child   Pointer to the child thread (must not be NULL).
125
+ */
126
+inline void _thread_addChild(thread_t *parent, thread_t *child) {
127
+#if CH_CFG_THREADHIERARCHY_ORDERED == TRUE
128
+  thread_t *sibling = parent->children;
129
+  child->parent = parent;
130
+#if CH_CFG_USE_MUTEXES == TRUE
131
+  if (sibling == NULL || sibling->realprio <= child->realprio) {
132
+#else
133
+  if (sibling == NULL || sibling->prio <= child->prio) {
134
+#endif
135
+    child->sibling = sibling;
136
+    parent->children = child;
137
+  } else {
138
+#if CH_CFG_USE_MUTEXES == TRUE
139
+    while (sibling->sibling != NULL && sibling->sibling->realprio > child->realprio) {
140
+#else
141
+    while (sibling->sibling != NULL && sibling->sibling->prio > child->prio) {
142
+#endif
143
+      sibling = sibling->sibling;
144
+    }
145
+    child->sibling = sibling->sibling;
146
+    sibling->sibling = child;
147
+  }
148
+#else
149
+  child->parent = parent;
150
+  child->sibling = parent->children;
151
+  parent->children = child;
152
+#endif
153
+  return;
154
+}
155
+#endif
156
+
157
 /*===========================================================================*/
158
 /* Module exported functions.                                                */
159
 /*===========================================================================*/
160
 
161
+#if CH_CFG_USE_THREADHIERARCHY == TRUE || defined(__DOXYGEN__)
162
 /**
163
  * @brief   Initializes a thread structure.
164
  * @note    This is an internal functions, do not use it in application code.
165
  *
166
  * @param[in] tp        pointer to the thread
167
+ * @param[in] parent    pointer to the parent thread
168
  * @param[in] name      thread name
169
  * @param[in] prio      the priority level for the new thread
170
  * @return              The same thread pointer passed as parameter.
171
  *
172
  * @notapi
173
  */
174
+thread_t *_thread_init(thread_t *tp, thread_t *parent,  const char *name, tprio_t prio) {
175
+#else
176
 thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
177
+#endif
178
 
179
   tp->prio      = prio;
180
   tp->state     = CH_STATE_WTSTART;
181
@@ -110,6 +155,17 @@ thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
182
 #else
183
   (void)name;
184
 #endif
185
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
186
+  if (parent != NULL) {
187
+    _thread_addChild(parent, tp);
188
+  } else {
189
+    tp->parent = parent;
190
+    tp->sibling = NULL;
191
+  }
192
+  tp->children = NULL;
193
+#else
194
+  (void)parent;
195
+#endif
196
 #if CH_CFG_USE_WAITEXIT == TRUE
197
   list_init(&tp->waiting);
198
 #endif
199
@@ -190,7 +246,11 @@ thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp) {
200
   PORT_SETUP_CONTEXT(tp, tdp->wbase, tp, tdp->funcp, tdp->arg);
201
 
202
   /* The driver object is initialized but not started.*/
203
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
204
+  return _thread_init(tp, tdp->parent, tdp->name, tdp->prio);
205
+#else
206
   return _thread_init(tp, tdp->name, tdp->prio);
207
+#endif
208
 }
209
 
210
 /**
211
@@ -300,6 +360,7 @@ thread_t *chThdCreate(const thread_descriptor_t *tdp) {
212
   return tp;
213
 }
214
 
215
+#if CH_CFG_USE_THREADHIERARCHY == TRUE || defined(__DOXYGEN__)
216
 /**
217
  * @brief   Creates a new thread into a static memory area.
218
  * @post    The created thread has a reference counter set to one, it is
219
@@ -315,13 +376,20 @@ thread_t *chThdCreate(const thread_descriptor_t *tdp) {
220
  * @param[in] pf        the thread function
221
  * @param[in] arg       an argument passed to the thread function. It can be
222
  *                      @p NULL.
223
+ * @param[in] parent    pointer to a parent thread. Parameter only available if
224
+ *                      @p CH_CFG_USE_THREADHIERARCHY is @p TRUE. It can be
225
+ *                      @p NULL.
226
  * @return              The pointer to the @p thread_t structure allocated for
227
  *                      the thread into the working space area.
228
  *
229
  * @api
230
  */
231
+thread_t *chThdCreateStatic(void *wsp, size_t size,
232
+                            tprio_t prio, tfunc_t pf, void *arg, thread_t *parent) {
233
+#else
234
 thread_t *chThdCreateStatic(void *wsp, size_t size,
235
                             tprio_t prio, tfunc_t pf, void *arg) {
236
+#endif
237
   thread_t *tp;
238
 
239
   chDbgCheck((wsp != NULL) &&
240
@@ -358,7 +426,11 @@ thread_t *chThdCreateStatic(void *wsp, size_t size,
241
   /* Setting up the port-dependent part of the working area.*/
242
   PORT_SETUP_CONTEXT(tp, wsp, tp, pf, arg);
243
 
244
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
245
+  tp = _thread_init(tp, parent, "noname", prio);
246
+#else
247
   tp = _thread_init(tp, "noname", prio);
248
+#endif
249
 
250
   /* Starting the thread immediately.*/
251
   chSchWakeupS(tp, MSG_OK);
252
@@ -529,6 +601,30 @@ void chThdExitS(msg_t msg) {
253
 #endif
254
 #endif
255
 
256
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
257
+  thread_t *child;
258
+  /* Remove from parent's list of children. */
259
+  if (tp->parent != NULL) {
260
+    if (tp->parent->children == tp) {
261
+      tp->parent->children = tp->sibling;
262
+    } else {
263
+      child = tp->parent->children;
264
+      while (child->sibling != tp) {
265
+        child = child->sibling;
266
+      }
267
+      child->sibling = tp->sibling;
268
+    }
269
+    tp->parent = NULL;
270
+  }
271
+  tp->sibling = NULL;
272
+  /* Move any child threads to the main thread. */
273
+  while (tp->children != NULL) {
274
+    child = tp->children;
275
+    tp->children = child->sibling;
276
+    _thread_addChild(&ch.mainthread, child);
277
+  }
278
+#endif
279
+
280
   /* Going into final state.*/
281
   chSchGoSleepS(CH_STATE_FINAL);
282
 
283
@@ -610,6 +706,43 @@ tprio_t chThdSetPriority(tprio_t newprio) {
284
 #else
285
   oldprio = currp->prio;
286
   currp->prio = newprio;
287
+#endif
288
+#if (CH_CFG_USE_THREADHIERARCHY == TRUE) && (CH_CFG_THREADHIERARCHY_ORDERED == TRUE)
289
+  /* Reorder sibling list. */
290
+  if (currp->parent != NULL && newprio != oldprio) {
291
+    thread_t *sibling, *oldsibling;
292
+    if (newprio > oldprio) {
293
+      oldsibling = currp->sibling;
294
+      _thread_addChild(currp->parent, currp);
295
+      sibling = currp->sibling;
296
+      if (sibling != NULL) {
297
+        while (sibling->sibling != currp) {
298
+          sibling = sibling->sibling;
299
+        }
300
+        sibling->sibling = oldsibling;
301
+      }
302
+    } else /*if (newprio < oldprio)*/ {
303
+      sibling = currp->parent->children;
304