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 |