summaryrefslogtreecommitdiff
path: root/firmware/kernel/include/thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/kernel/include/thread.h')
-rw-r--r--firmware/kernel/include/thread.h81
1 files changed, 54 insertions, 27 deletions
diff --git a/firmware/kernel/include/thread.h b/firmware/kernel/include/thread.h
index 8c13b462e6..f181f867cb 100644
--- a/firmware/kernel/include/thread.h
+++ b/firmware/kernel/include/thread.h
@@ -28,6 +28,7 @@
28#include <stdbool.h> 28#include <stdbool.h>
29#include "gcc_extensions.h" 29#include "gcc_extensions.h"
30#include "corelock.h" 30#include "corelock.h"
31#include "bitarray.h"
31 32
32/* Priority scheduling (when enabled with HAVE_PRIORITY_SCHEDULING) works 33/* Priority scheduling (when enabled with HAVE_PRIORITY_SCHEDULING) works
33 * by giving high priority threads more CPU time than lower priority threads 34 * by giving high priority threads more CPU time than lower priority threads
@@ -80,6 +81,10 @@
80#endif 81#endif
81 82
82#define MAXTHREADS (BASETHREADS+TARGET_EXTRA_THREADS) 83#define MAXTHREADS (BASETHREADS+TARGET_EXTRA_THREADS)
84
85BITARRAY_TYPE_DECLARE(threadbit_t, threadbit, MAXTHREADS)
86BITARRAY_TYPE_DECLARE(priobit_t, priobit, NUM_PRIORITIES)
87
83/* 88/*
84 * We need more stack when we run under a host 89 * We need more stack when we run under a host
85 * maybe more expensive C lib functions? 90 * maybe more expensive C lib functions?
@@ -134,32 +139,39 @@ struct thread_list
134 struct thread_entry *next; /* Next thread in a list */ 139 struct thread_entry *next; /* Next thread in a list */
135}; 140};
136 141
137#ifdef HAVE_PRIORITY_SCHEDULING 142/* Basic structure describing the owner of an object */
138struct blocker 143struct blocker
139{ 144{
140 struct thread_entry * volatile thread; /* thread blocking other threads 145 struct thread_entry * volatile thread; /* thread blocking other threads
141 (aka. object owner) */ 146 (aka. object owner) */
142 int priority; /* highest priority waiter */ 147#ifdef HAVE_PRIORITY_SCHEDULING
143 struct thread_entry * (*wakeup_protocol)(struct thread_entry *thread); 148 int priority; /* highest priority waiter */
149#endif
144}; 150};
145 151
146/* Choices of wakeup protocol */ 152/* If a thread has a blocker but the blocker's registered thread is NULL,
147 153 then it references this and the struct blocker pointer may be
148/* For transfer of object ownership by one thread to another thread by 154 reinterpreted as such. */
149 * the owning thread itself (mutexes) */ 155struct blocker_splay
150struct thread_entry * 156{
151 wakeup_priority_protocol_transfer(struct thread_entry *thread); 157 struct blocker blocker; /* blocker info (first!) */
158#ifdef HAVE_PRIORITY_SCHEDULING
159 threadbit_t mask; /* mask of nonzero tcounts */
160#if NUM_CORES > 1
161 struct corelock cl; /* mutual exclusion */
162#endif
163#endif /* HAVE_PRIORITY_SCHEDULING */
164};
152 165
153/* For release by owner where ownership doesn't change - other threads, 166#ifdef HAVE_PRIORITY_SCHEDULING
154 * interrupts, timeouts, etc. (mutex timeout, queues) */
155struct thread_entry *
156 wakeup_priority_protocol_release(struct thread_entry *thread);
157 167
168/* Quick-disinherit of priority elevation. Must be a running thread. */
169void priority_disinherit(struct thread_entry *thread, struct blocker *bl);
158 170
159struct priority_distribution 171struct priority_distribution
160{ 172{
161 uint8_t hist[NUM_PRIORITIES]; /* Histogram: Frequency for each priority */ 173 uint8_t hist[NUM_PRIORITIES]; /* Histogram: Frequency for each priority */
162 uint32_t mask; /* Bitmask of hist entries that are not zero */ 174 priobit_t mask; /* Bitmask of hist entries that are not zero */
163}; 175};
164 176
165#endif /* HAVE_PRIORITY_SCHEDULING */ 177#endif /* HAVE_PRIORITY_SCHEDULING */
@@ -210,6 +222,7 @@ struct thread_entry
210 volatile intptr_t retval; /* Return value from a blocked operation/ 222 volatile intptr_t retval; /* Return value from a blocked operation/
211 misc. use */ 223 misc. use */
212#endif 224#endif
225 uint32_t id; /* Current slot id */
213 int __errno; /* Thread error number (errno tls) */ 226 int __errno; /* Thread error number (errno tls) */
214#ifdef HAVE_PRIORITY_SCHEDULING 227#ifdef HAVE_PRIORITY_SCHEDULING
215 /* Priority summary of owned objects that support inheritance */ 228 /* Priority summary of owned objects that support inheritance */
@@ -226,7 +239,6 @@ struct thread_entry
226 unsigned char priority; /* Scheduled priority (higher of base or 239 unsigned char priority; /* Scheduled priority (higher of base or
227 all threads blocked by this one) */ 240 all threads blocked by this one) */
228#endif 241#endif
229 uint16_t id; /* Current slot id */
230 unsigned short stack_size; /* Size of stack in bytes */ 242 unsigned short stack_size; /* Size of stack in bytes */
231 unsigned char state; /* Thread slot state (STATE_*) */ 243 unsigned char state; /* Thread slot state (STATE_*) */
232#ifdef HAVE_SCHEDULER_BOOSTCTRL 244#ifdef HAVE_SCHEDULER_BOOSTCTRL
@@ -238,11 +250,12 @@ struct thread_entry
238}; 250};
239 251
240/*** Macros for internal use ***/ 252/*** Macros for internal use ***/
241/* Thread ID, 16 bits = |VVVVVVVV|SSSSSSSS| */ 253/* Thread ID, 32 bits = |VVVVVVVV|VVVVVVVV|VVVVVVVV|SSSSSSSS| */
242#define THREAD_ID_VERSION_SHIFT 8 254#define THREAD_ID_VERSION_SHIFT 8
243#define THREAD_ID_VERSION_MASK 0xff00 255#define THREAD_ID_VERSION_MASK 0xffffff00
244#define THREAD_ID_SLOT_MASK 0x00ff 256#define THREAD_ID_SLOT_MASK 0x000000ff
245#define THREAD_ID_INIT(n) ((1u << THREAD_ID_VERSION_SHIFT) | (n)) 257#define THREAD_ID_INIT(n) ((1u << THREAD_ID_VERSION_SHIFT) | (n))
258#define THREAD_ID_SLOT(id) ((id) & THREAD_ID_SLOT_MASK)
246 259
247#ifdef HAVE_CORELOCK_OBJECT 260#ifdef HAVE_CORELOCK_OBJECT
248/* Operations to be performed just before stopping a thread and starting 261/* Operations to be performed just before stopping a thread and starting
@@ -337,11 +350,8 @@ void switch_thread(void);
337/* Blocks a thread for at least the specified number of ticks (0 = wait until 350/* Blocks a thread for at least the specified number of ticks (0 = wait until
338 * next tick) */ 351 * next tick) */
339void sleep_thread(int ticks); 352void sleep_thread(int ticks);
340/* Indefinitely blocks the current thread on a thread queue */ 353/* Blocks the current thread on a thread queue (< 0 == infinite) */
341void block_thread(struct thread_entry *current); 354void block_thread(struct thread_entry *current, int timeout);
342/* Blocks the current thread on a thread queue until explicitely woken or
343 * the timeout is reached */
344void block_thread_w_tmo(struct thread_entry *current, int timeout);
345 355
346/* Return bit flags for thread wakeup */ 356/* Return bit flags for thread wakeup */
347#define THREAD_NONE 0x0 /* No thread woken up (exclusive) */ 357#define THREAD_NONE 0x0 /* No thread woken up (exclusive) */
@@ -350,15 +360,32 @@ void block_thread_w_tmo(struct thread_entry *current, int timeout);
350 higher priority than current were woken) */ 360 higher priority than current were woken) */
351 361
352/* A convenience function for waking an entire queue of threads. */ 362/* A convenience function for waking an entire queue of threads. */
353unsigned int thread_queue_wake(struct thread_entry **list); 363unsigned int thread_queue_wake(struct thread_entry **list,
364 volatile int *count);
354 365
355/* Wakeup a thread at the head of a list */ 366/* Wakeup a thread at the head of a list */
356unsigned int wakeup_thread(struct thread_entry **list); 367enum wakeup_thread_protocol
368{
369 WAKEUP_DEFAULT,
370 WAKEUP_TRANSFER,
371 WAKEUP_RELEASE,
372 WAKEUP_TRANSFER_MULTI,
373};
374
375unsigned int wakeup_thread_(struct thread_entry **list
376 IF_PRIO(, enum wakeup_thread_protocol proto));
357 377
358#ifdef HAVE_PRIORITY_SCHEDULING 378#ifdef HAVE_PRIORITY_SCHEDULING
379#define wakeup_thread(list, proto) \
380 wakeup_thread_((list), (proto))
381
359int thread_set_priority(unsigned int thread_id, int priority); 382int thread_set_priority(unsigned int thread_id, int priority);
360int thread_get_priority(unsigned int thread_id); 383int thread_get_priority(unsigned int thread_id);
384#else /* !HAVE_PRIORITY_SCHEDULING */
385#define wakeup_thread(list, proto...) \
386 wakeup_thread_((list));
361#endif /* HAVE_PRIORITY_SCHEDULING */ 387#endif /* HAVE_PRIORITY_SCHEDULING */
388
362#ifdef HAVE_IO_PRIORITY 389#ifdef HAVE_IO_PRIORITY
363void thread_set_io_priority(unsigned int thread_id, int io_priority); 390void thread_set_io_priority(unsigned int thread_id, int io_priority);
364int thread_get_io_priority(unsigned int thread_id); 391int thread_get_io_priority(unsigned int thread_id);