Revision 0a89baf2

View differences:

core/src/aos_system.c
818 818

  
819 819
#if (AMIROOS_CFG_SHELL_ENABLE == true)
820 820
  // start system shell thread
821
#if (CH_CFG_USE_THREADHIERARCHY == TRUE)
822
  aos.shell.thread = chThdCreateStatic(_shell_wa, sizeof(_shell_wa), AMIROOS_CFG_SHELL_THREADPRIO, aosShellThread, &aos.shell, &ch.mainthread);
823
#else
821 824
  aos.shell.thread = chThdCreateStatic(_shell_wa, sizeof(_shell_wa), AMIROOS_CFG_SHELL_THREADPRIO, aosShellThread, &aos.shell);
822 825
#endif
826
#endif
823 827

  
824 828
  return;
825 829
}
kernel/ChibiOS
1
Subproject commit 3a1b71ebdcf2687385f1b327feef0de7ccacb1f4
1
Subproject commit 67ad4a4ed58d91326e48555d3ca7f41ae0c16cb2
kernel/patches/introduce-thread-hierarchy.patch
1
diff --git a/os/rt/include/chschd.h b/os/rt/include/chschd.h
2
index 1d11d17..c71d8b4 100644
3
--- a/os/rt/include/chschd.h
4
+++ b/os/rt/include/chschd.h
5
@@ -177,6 +177,23 @@ struct ch_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
    */
29
diff --git a/os/rt/include/chthreads.h b/os/rt/include/chthreads.h
30
index 166d566..b767d74 100644
31
--- a/os/rt/include/chthreads.h
32
+++ b/os/rt/include/chthreads.h
33
@@ -79,6 +79,10 @@ typedef struct {
34
    * @brief   Thread argument.
35
    */
36
   void              *arg;
37
+  /**
38
+   * @brief   Pointer to the parent thread.
39
+   */
40
+  thread_t          *parent;
41
 } thread_descriptor_t;
42
 
43
 /*===========================================================================*/
44
@@ -220,7 +224,7 @@ typedef struct {
45
 #ifdef __cplusplus
46
 extern "C" {
47
 #endif
48
-   thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio);
49
+   thread_t *_thread_init(thread_t *tp, thread_t* parent, const char *name, tprio_t prio);
50
 #if CH_DBG_FILL_THREADS == TRUE
51
   void _thread_memfill(uint8_t *startp, uint8_t *endp, uint8_t v);
52
 #endif
53
@@ -228,8 +232,13 @@ extern "C" {
54
   thread_t *chThdCreateSuspended(const thread_descriptor_t *tdp);
55
   thread_t *chThdCreateI(const thread_descriptor_t *tdp);
56
   thread_t *chThdCreate(const thread_descriptor_t *tdp);
57
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
58
+  thread_t *chThdCreateStatic(void *wsp, size_t size,
59
+                              tprio_t prio, tfunc_t pf, void *arg, thread_t *parent);
60
+#else
61
   thread_t *chThdCreateStatic(void *wsp, size_t size,
62
                               tprio_t prio, tfunc_t pf, void *arg);
63
+#endif
64
   thread_t *chThdStart(thread_t *tp);
65
 #if CH_CFG_USE_REGISTRY == TRUE
66
   thread_t *chThdAddRef(thread_t *tp);
67
diff --git a/os/rt/src/chsys.c b/os/rt/src/chsys.c
68
index 346a8ba..c789d01 100644
69
--- a/os/rt/src/chsys.c
70
+++ b/os/rt/src/chsys.c
71
@@ -126,13 +126,13 @@ void chSysInit(void) {
72
 #if CH_CFG_NO_IDLE_THREAD == FALSE
73
   /* Now this instructions flow becomes the main thread.*/
74
 #if CH_CFG_USE_REGISTRY == TRUE
75
-  currp = _thread_init(&ch.mainthread, (const char *)&ch_debug, NORMALPRIO);
76
+  currp = _thread_init(&ch.mainthread, NULL, (const char *)&ch_debug, NORMALPRIO);
77
 #else
78
-  currp = _thread_init(&ch.mainthread, "main", NORMALPRIO);
79
+  currp = _thread_init(&ch.mainthread, NULL, "main", NORMALPRIO);
80
 #endif
81
 #else
82
   /* Now this instructions flow becomes the idle thread.*/
83
-  currp = _thread_init(&ch.mainthread, "idle", IDLEPRIO);
84
+  currp = _thread_init(&ch.mainthread, NULL, "idle", IDLEPRIO);
85
 #endif
86
 
87
 #if CH_DBG_ENABLE_STACK_CHECK == TRUE
88
@@ -172,6 +172,7 @@ void chSysInit(void) {
89
       THD_WORKING_AREA_END(ch_idle_thread_wa),
90
       IDLEPRIO,
91
       _idle_thread,
92
+      NULL,
93
       NULL
94
     };
95
 
96
diff --git a/os/rt/src/chthreads.c b/os/rt/src/chthreads.c
97
index 171c683..6bc0f78 100644
98
--- a/os/rt/src/chthreads.c
99
+++ b/os/rt/src/chthreads.c
100
@@ -70,6 +70,46 @@
101
 /* Module local functions.                                                   */
102
 /*===========================================================================*/
103
 
104
+#if CH_CFG_USE_THREADHIERARCHY == TRUE || defined(__DOXYGEN__)
105
+/**
106
+ * @brief   Insert a thread to the list of children of another thread.
107
+ * @details If @p CH_CFG_THREADHIERARCHY_ORDERED is @p TRUE, children are ordered by their priorities (high to low).
108
+ *          Children with identical priority are ordered by 'age' (youngest first).
109
+ *
110
+ * @param[in] parent  Pointer to the parent thread (must not be NULL).
111
+ * @param[in] child   Pointer to the child thread (must not be NULL).
112
+ */
113
+inline void _thread_addChild(thread_t *parent, thread_t *child) {
114
+#if CH_CFG_THREADHIERARCHY_ORDERED == TRUE
115
+  thread_t *sibling = parent->children;
116
+  child->parent = parent;
117
+#if CH_CFG_USE_MUTEXES == TRUE
118
+  if (sibling == NULL || sibling->realprio <= child->realprio) {
119
+#else
120
+  if (sibling == NULL || sibling->prio <= child->prio) {
121
+#endif
122
+    child->sibling = sibling;
123
+    parent->children = child;
124
+  } else {
125
+#if CH_CFG_USE_MUTEXES == TRUE
126
+    while (sibling->sibling != NULL && sibling->sibling->realprio > child->realprio) {
127
+#else
128
+    while (sibling->sibling != NULL && sibling->sibling->prio > child->prio) {
129
+#endif
130
+      sibling = sibling->sibling;
131
+    }
132
+    child->sibling = sibling->sibling;
133
+    sibling->sibling = child;
134
+  }
135
+#else
136
+  child->parent = parent;
137
+  child->sibling = parent->children;
138
+  parent->children = child;
139
+#endif
140
+  return;
141
+}
142
+#endif
143
+
144
 /*===========================================================================*/
145
 /* Module exported functions.                                                */
146
 /*===========================================================================*/
147
@@ -79,13 +119,14 @@
148
  * @note    This is an internal functions, do not use it in application code.
149
  *
150
  * @param[in] tp        pointer to the thread
151
+ * @param[in] parent    pointer to the parent thread
152
  * @param[in] name      thread name
153
  * @param[in] prio      the priority level for the new thread
154
  * @return              The same thread pointer passed as parameter.
155
  *
156
  * @notapi
157
  */
158
-thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
159
+thread_t *_thread_init(thread_t *tp, thread_t *parent,  const char *name, tprio_t prio) {
160
 
161
   tp->prio      = prio;
162
   tp->state     = CH_STATE_WTSTART;
163
@@ -110,6 +151,17 @@ thread_t *_thread_init(thread_t *tp, const char *name, tprio_t prio) {
164
 #else
165
   (void)name;
166
 #endif
167
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
168
+  if (parent != NULL) {
169
+    _thread_addChild(parent, tp);
170
+  } else {
171
+    tp->parent = parent;
172
+    tp->sibling = NULL;
173
+  }
174
+  tp->children = NULL;
175
+#else
176
+  (void)parent;
177
+#endif
178
 #if CH_CFG_USE_WAITEXIT == TRUE
179
   list_init(&tp->waiting);
180
 #endif
181
@@ -190,7 +242,7 @@ thread_t *chThdCreateSuspendedI(const thread_descriptor_t *tdp) {
182
   PORT_SETUP_CONTEXT(tp, tdp->wbase, tp, tdp->funcp, tdp->arg);
183
 
184
   /* The driver object is initialized but not started.*/
185
-  return _thread_init(tp, tdp->name, tdp->prio);
186
+  return _thread_init(tp, tdp->parent, tdp->name, tdp->prio);
187
 }
188
 
189
 /**
190
@@ -315,13 +367,21 @@ thread_t *chThdCreate(const thread_descriptor_t *tdp) {
191
  * @param[in] pf        the thread function
192
  * @param[in] arg       an argument passed to the thread function. It can be
193
  *                      @p NULL.
194
+ * @param[in] parent    pointer to a parent thread. Parameter only available if
195
+ *                      @p CH_CFG_USE_THREADHIERARCHY is @p TRUE. It can be
196
+ *                      @p NULL.
197
  * @return              The pointer to the @p thread_t structure allocated for
198
  *                      the thread into the working space area.
199
  *
200
  * @api
201
  */
202
+#if (CH_CFG_USE_THREADHIERARCHY == TRUE) || defined(__DOXYGEN__)
203
+thread_t *chThdCreateStatic(void *wsp, size_t size,
204
+                            tprio_t prio, tfunc_t pf, void *arg, thread_t *parent) {
205
+#else
206
 thread_t *chThdCreateStatic(void *wsp, size_t size,
207
                             tprio_t prio, tfunc_t pf, void *arg) {
208
+#endif
209
   thread_t *tp;
210
 
211
   chDbgCheck((wsp != NULL) &&
212
@@ -358,7 +418,11 @@ thread_t *chThdCreateStatic(void *wsp, size_t size,
213
   /* Setting up the port-dependent part of the working area.*/
214
   PORT_SETUP_CONTEXT(tp, wsp, tp, pf, arg);
215
 
216
-  tp = _thread_init(tp, "noname", prio);
217
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
218
+  tp = _thread_init(tp, parent, "noname", prio);
219
+#else
220
+  tp = _thread_init(tp, NULL, "noname", prio);
221
+#endif
222
 
223
   /* Starting the thread immediately.*/
224
   chSchWakeupS(tp, MSG_OK);
225
@@ -529,6 +593,30 @@ void chThdExitS(msg_t msg) {
226
 #endif
227
 #endif
228
 
229
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
230
+  thread_t *child;
231
+  /* Remove from parent's list of children. */
232
+  if (tp->parent != NULL) {
233
+    if (tp->parent->children == tp) {
234
+      tp->parent->children = tp->sibling;
235
+    } else {
236
+      child = tp->parent->children;
237
+      while (child->sibling != tp) {
238
+        child = child->sibling;
239
+      }
240
+      child->sibling = tp->sibling;
241
+    }
242
+    tp->parent = NULL;
243
+  }
244
+  tp->sibling = NULL;
245
+  /* Move any child threads to the main thread. */
246
+  while (tp->children != NULL) {
247
+    child = tp->children;
248
+    tp->children = child->sibling;
249
+    _thread_addChild(&ch.mainthread, child);
250
+  }
251
+#endif
252
+
253
   /* Going into final state.*/
254
   chSchGoSleepS(CH_STATE_FINAL);
255
 
256
@@ -611,6 +699,43 @@ tprio_t chThdSetPriority(tprio_t newprio) {
257
   oldprio = currp->prio;
258
   currp->prio = newprio;
259
 #endif
260
+#if (CH_CFG_USE_THREADHIERARCHY == TRUE) && (CH_CFG_THREADHIERARCHY_ORDERED == TRUE)
261
+  /* Reorder sibling list. */
262
+  if (currp->parent != NULL && newprio != oldprio) {
263
+    thread_t *sibling, *oldsibling;
264
+    if (newprio > oldprio) {
265
+      oldsibling = currp->sibling;
266
+      _thread_addChild(currp->parent, currp);
267
+      sibling = currp->sibling;
268
+      if (sibling != NULL) {
269
+        while (sibling->sibling != currp) {
270
+          sibling = sibling->sibling;
271
+        }
272
+        sibling->sibling = oldsibling;
273
+      }
274
+    } else /*if (newprio < oldprio)*/ {
275
+      sibling = currp->parent->children;
276
+      if (sibling == currp) {
277
+        currp->parent->children = currp->sibling;
278
+        _thread_addChild(currp->parent, currp);
279
+      } else {
280
+        while (sibling->sibling != currp) {
281
+          sibling = sibling->sibling;
282
+        }
283
+        sibling->sibling = currp->sibling;
284
+#if CH_CFG_USE_MUTEXES == TRUE
285
+        while (sibling->sibling != NULL && sibling->sibling->realprio > currp->realprio) {
286
+#else
287
+        while (sibling->sibling != NULL && sibling->sibling->prio > currp->prio) {
288
+#endif
289
+          sibling = sibling->sibling;
290
+        }
291
+        currp->sibling = sibling->sibling;
292
+        sibling->sibling = currp;
293
+      }
294
+    }
295
+  }
296
+#endif
297
   chSchRescheduleS();
298
   chSysUnlock();
299
 
300
diff --git a/test/rt/source/test/rt_test_root.c b/test/rt/source/test/rt_test_root.c
301
index e03d0f1..150d33d 100644
302
--- a/test/rt/source/test/rt_test_root.c
303
+++ b/test/rt/source/test/rt_test_root.c
304
@@ -106,6 +106,14 @@ void * ROMCONST wa[5] = {test_buffer + (WA_SIZE * 0),
305
                          test_buffer + (WA_SIZE * 3),
306
                          test_buffer + (WA_SIZE * 4)};
307
 
308
+thread_t *test_create_thread(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) {
309
+#if CH_CFG_USE_THREADHIERARCHY == TRUE
310
+  return chThdCreateStatic(wsp, size, prio, pf, arg, chThdGetSelfX());
311
+#else
312
+  return chThdCreateStatic(wsp, size, prio, pf, arg);
313
+#endif
314
+}
315
+
316
 /*
317
  * Sets a termination request in all the test-spawned threads.
318
  */
319
diff --git a/test/rt/source/test/rt_test_root.h b/test/rt/source/test/rt_test_root.h
320
index 6da777b..0cd40fc 100644
321
--- a/test/rt/source/test/rt_test_root.h
322
+++ b/test/rt/source/test/rt_test_root.h
323
@@ -88,6 +88,7 @@ extern thread_t *threads[MAX_THREADS];
324
 extern void * ROMCONST wa[5];
325
 
326
 void test_print_port_info(void);
327
+thread_t *test_create_thread(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg);
328
 void test_terminate_threads(void);
329
 void test_wait_threads(void);
330
 systime_t test_wait_tick(void);
331
diff --git a/test/rt/source/test/rt_test_sequence_001.c b/test/rt/source/test/rt_test_sequence_001.c
332
index 6f2b96f..f91c23f 100644
333
--- a/test/rt/source/test/rt_test_sequence_001.c
334
+++ b/test/rt/source/test/rt_test_sequence_001.c
335
@@ -193,6 +193,12 @@ static void rt_test_001_003_execute(void) {
336
     test_print("--- CH_CFG_USE_REGISTRY:                ");
337
     test_printn(CH_CFG_USE_REGISTRY);
338
     test_println("");
339
+    test_print("--- CH_CFG_USE_THREADHIERARCHY:         ");
340
+    test_printn(CH_CFG_USE_THREADHIERARCHY);
341
+    test_println("");
342
+    test_print("--- CH_CFG_THREADHIERARCHY_ORDERED:     ");
343
+    test_printn(CH_CFG_THREADHIERARCHY_ORDERED);
344
+    test_println("");
345
     test_print("--- CH_CFG_USE_WAITEXIT:                ");
346
     test_printn(CH_CFG_USE_WAITEXIT);
347
     test_println("");
348
@@ -207,7 +213,7 @@ static void rt_test_001_003_execute(void) {
349
     test_println("");
350
     test_print("--- CH_CFG_USE_MUTEXES_RECURS:          ");
351
     test_printn(CH_CFG_USE_MUTEXES_RECURSIVE);
352
-    test_println("");   
353
+    test_println("");
354
     test_print("--- CH_CFG_USE_CONDVARS:                ");
355
     test_printn(CH_CFG_USE_CONDVARS);
356
     test_println("");
357
diff --git a/test/rt/source/test/rt_test_sequence_003.c b/test/rt/source/test/rt_test_sequence_003.c
358
index 8598b12..f1ece71 100644
359
--- a/test/rt/source/test/rt_test_sequence_003.c
360
+++ b/test/rt/source/test/rt_test_sequence_003.c
361
@@ -46,6 +46,20 @@ static THD_FUNCTION(thread, p) {
362
   test_emit_token(*(char *)p);
363
 }
364
 
365
+#if (CH_CFG_USE_THREADHIERARCHY)
366
+static THD_FUNCTION(hierarchythread, p) {
367
+
368
+  do {
369
+    if (*(tprio_t *)p != chThdGetPriorityX()) {
370
+      chThdSetPriority(*(tprio_t *)p);
371
+    }
372
+    chThdSleepMilliseconds(10);
373
+  } while (!chThdShouldTerminateX());
374
+
375
+  chThdExit(MSG_OK);
376
+}
377
+#endif
378
+
379
 /****************************************************************************
380
  * Test cases.
381
  ****************************************************************************/
382
@@ -166,11 +180,11 @@ static void rt_test_003_002_execute(void) {
383
      sequence is tested.*/
384
   test_set_step(1);
385
   {
386
-    threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
387
-    threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
388
-    threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
389
-    threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
390
-    threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
391
+    threads[0] = test_create_thread(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
392
+    threads[1] = test_create_thread(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
393
+    threads[2] = test_create_thread(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
394
+    threads[3] = test_create_thread(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
395
+    threads[4] = test_create_thread(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
396
     test_wait_threads();
397
     test_assert_sequence("ABCDE", "invalid sequence");
398
   }
399
@@ -179,11 +193,11 @@ static void rt_test_003_002_execute(void) {
400
      sequence is tested.*/
401
   test_set_step(2);
402
   {
403
-    threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
404
-    threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
405
-    threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
406
-    threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
407
-    threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
408
+    threads[4] = test_create_thread(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
409
+    threads[3] = test_create_thread(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
410
+    threads[2] = test_create_thread(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
411
+    threads[1] = test_create_thread(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
412
+    threads[0] = test_create_thread(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
413
     test_wait_threads();
414
     test_assert_sequence("ABCDE", "invalid sequence");
415
   }
416
@@ -192,11 +206,11 @@ static void rt_test_003_002_execute(void) {
417
      sequence is tested.*/
418
   test_set_step(3);
419
   {
420
-    threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
421
-    threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
422
-    threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
423
-    threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
424
-    threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
425
+    threads[1] = test_create_thread(wa[1], WA_SIZE, chThdGetPriorityX()-4, thread, "D");
426
+    threads[0] = test_create_thread(wa[0], WA_SIZE, chThdGetPriorityX()-5, thread, "E");
427
+    threads[4] = test_create_thread(wa[4], WA_SIZE, chThdGetPriorityX()-1, thread, "A");
428
+    threads[3] = test_create_thread(wa[3], WA_SIZE, chThdGetPriorityX()-2, thread, "B");
429
+    threads[2] = test_create_thread(wa[2], WA_SIZE, chThdGetPriorityX()-3, thread, "C");
430
     test_wait_threads();
431
     test_assert_sequence("ABCDE", "invalid sequence");
432
   }
433
@@ -325,6 +339,405 @@ static const testcase_t rt_test_003_004 = {
434
 };
435
 #endif /* CH_CFG_USE_MUTEXES */
436