diff options
Diffstat (limited to 'firmware/kernel/include')
-rw-r--r-- | firmware/kernel/include/kernel.h | 1 | ||||
-rw-r--r-- | firmware/kernel/include/mutex.h | 20 | ||||
-rw-r--r-- | firmware/kernel/include/queue.h | 2 | ||||
-rw-r--r-- | firmware/kernel/include/thread.h | 81 |
4 files changed, 64 insertions, 40 deletions
diff --git a/firmware/kernel/include/kernel.h b/firmware/kernel/include/kernel.h index fafff25ce4..d2ffffcda9 100644 --- a/firmware/kernel/include/kernel.h +++ b/firmware/kernel/include/kernel.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "system.h" | 26 | #include "system.h" |
27 | #include "queue.h" | 27 | #include "queue.h" |
28 | #include "mutex.h" | 28 | #include "mutex.h" |
29 | #include "mrsw_lock.h" | ||
29 | #include "tick.h" | 30 | #include "tick.h" |
30 | 31 | ||
31 | #ifdef INCLUDE_TIMEOUT_API | 32 | #ifdef INCLUDE_TIMEOUT_API |
diff --git a/firmware/kernel/include/mutex.h b/firmware/kernel/include/mutex.h index bcf5701bd9..02b85f331f 100644 --- a/firmware/kernel/include/mutex.h +++ b/firmware/kernel/include/mutex.h | |||
@@ -28,20 +28,14 @@ | |||
28 | 28 | ||
29 | struct mutex | 29 | struct mutex |
30 | { | 30 | { |
31 | struct thread_entry *queue; /* waiter list */ | 31 | struct thread_entry *queue; /* waiter list */ |
32 | int recursion; /* lock owner recursion count */ | 32 | int recursion; /* lock owner recursion count */ |
33 | struct blocker blocker; /* priority inheritance info | ||
34 | for waiters and owner*/ | ||
35 | IF_COP( struct corelock cl; ) /* multiprocessor sync */ | ||
33 | #ifdef HAVE_PRIORITY_SCHEDULING | 36 | #ifdef HAVE_PRIORITY_SCHEDULING |
34 | struct blocker blocker; /* priority inheritance info | 37 | bool no_preempt; |
35 | for waiters */ | ||
36 | bool no_preempt; /* don't allow higher-priority thread | ||
37 | to be scheduled even if woken */ | ||
38 | #else | ||
39 | struct thread_entry *thread; /* Indicates owner thread - an owner | ||
40 | implies a locked state - same goes | ||
41 | for priority scheduling | ||
42 | (in blocker struct for that) */ | ||
43 | #endif | 38 | #endif |
44 | IF_COP( struct corelock cl; ) /* multiprocessor sync */ | ||
45 | }; | 39 | }; |
46 | 40 | ||
47 | extern void mutex_init(struct mutex *m); | 41 | extern void mutex_init(struct mutex *m); |
@@ -56,7 +50,7 @@ static inline void mutex_set_preempt(struct mutex *m, bool preempt) | |||
56 | #else | 50 | #else |
57 | /* Deprecated but needed for now - firmware/drivers/ata_mmc.c */ | 51 | /* Deprecated but needed for now - firmware/drivers/ata_mmc.c */ |
58 | static inline bool mutex_test(const struct mutex *m) | 52 | static inline bool mutex_test(const struct mutex *m) |
59 | { return m->thread != NULL; } | 53 | { return m->blocker.thread != NULL; } |
60 | #endif /* HAVE_PRIORITY_SCHEDULING */ | 54 | #endif /* HAVE_PRIORITY_SCHEDULING */ |
61 | 55 | ||
62 | #endif /* MUTEX_H */ | 56 | #endif /* MUTEX_H */ |
diff --git a/firmware/kernel/include/queue.h b/firmware/kernel/include/queue.h index 1b404f8297..3f24598d5b 100644 --- a/firmware/kernel/include/queue.h +++ b/firmware/kernel/include/queue.h | |||
@@ -143,6 +143,8 @@ extern bool queue_peek(struct event_queue *q, struct queue_event *ev); | |||
143 | #define QPEEK_FILTER_COUNT_MASK (0xffu) /* 0x00=1 filter, 0xff=256 filters */ | 143 | #define QPEEK_FILTER_COUNT_MASK (0xffu) /* 0x00=1 filter, 0xff=256 filters */ |
144 | #define QPEEK_FILTER_HEAD_ONLY (1u << 8) /* Ignored if no filters */ | 144 | #define QPEEK_FILTER_HEAD_ONLY (1u << 8) /* Ignored if no filters */ |
145 | #define QPEEK_REMOVE_EVENTS (1u << 9) /* Remove or discard events */ | 145 | #define QPEEK_REMOVE_EVENTS (1u << 9) /* Remove or discard events */ |
146 | #define QPEEK_FILTER1(a) QPEEK_FILTER2((a), (a)) | ||
147 | #define QPEEK_FILTER2(a, b) (&(const long [2]){ (a), (b) }) | ||
146 | extern bool queue_peek_ex(struct event_queue *q, | 148 | extern bool queue_peek_ex(struct event_queue *q, |
147 | struct queue_event *ev, | 149 | struct queue_event *ev, |
148 | unsigned int flags, | 150 | unsigned int flags, |
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 | |||
85 | BITARRAY_TYPE_DECLARE(threadbit_t, threadbit, MAXTHREADS) | ||
86 | BITARRAY_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 */ |
138 | struct blocker | 143 | struct 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) */ | 155 | struct blocker_splay |
150 | struct 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) */ | ||
155 | struct thread_entry * | ||
156 | wakeup_priority_protocol_release(struct thread_entry *thread); | ||
157 | 167 | ||
168 | /* Quick-disinherit of priority elevation. Must be a running thread. */ | ||
169 | void priority_disinherit(struct thread_entry *thread, struct blocker *bl); | ||
158 | 170 | ||
159 | struct priority_distribution | 171 | struct 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) */ |
339 | void sleep_thread(int ticks); | 352 | void 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) */ |
341 | void block_thread(struct thread_entry *current); | 354 | void 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 */ | ||
344 | void 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. */ |
353 | unsigned int thread_queue_wake(struct thread_entry **list); | 363 | unsigned 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 */ |
356 | unsigned int wakeup_thread(struct thread_entry **list); | 367 | enum wakeup_thread_protocol |
368 | { | ||
369 | WAKEUP_DEFAULT, | ||
370 | WAKEUP_TRANSFER, | ||
371 | WAKEUP_RELEASE, | ||
372 | WAKEUP_TRANSFER_MULTI, | ||
373 | }; | ||
374 | |||
375 | unsigned 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 | |||
359 | int thread_set_priority(unsigned int thread_id, int priority); | 382 | int thread_set_priority(unsigned int thread_id, int priority); |
360 | int thread_get_priority(unsigned int thread_id); | 383 | int 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 |
363 | void thread_set_io_priority(unsigned int thread_id, int io_priority); | 390 | void thread_set_io_priority(unsigned int thread_id, int io_priority); |
364 | int thread_get_io_priority(unsigned int thread_id); | 391 | int thread_get_io_priority(unsigned int thread_id); |