summaryrefslogtreecommitdiff
path: root/firmware/kernel/thread-internal.h
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2014-08-08 01:39:29 -0400
committerMichael Sevakis <jethead71@rockbox.org>2014-08-08 01:59:59 -0400
commit981d028c09d10ed867f2f955f58d60b753c64f29 (patch)
tree0dab835a14c5cb3e740be4e46be93c42aec76bc5 /firmware/kernel/thread-internal.h
parent53d9f2e6a7564e487bdac87f6e28c662e8407458 (diff)
downloadrockbox-981d028c09d10ed867f2f955f58d60b753c64f29.zip
rockbox-981d028c09d10ed867f2f955f58d60b753c64f29.tar.gz
rockbox-981d028c09d10ed867f2f955f58d60b753c64f29.tar.bz2
rockbox-981d028c09d10ed867f2f955f58d60b753c64f29.tar.xz
Do some kernel cleanup
* Seal away private thread and kernel definitions and declarations into the internal headers in order to better hide internal structure. * Add a thread-common.c file that keeps shared functions together. List functions aren't messed with since that's about to be changed to different ones. * It is necessary to modify some ARM/PP stuff since GCC was complaining about constant pool distance and I would rather not force dump it. Just bl the cache calls in the startup and exit code and let it use veneers if it must. * Clean up redundant #includes in relevant areas and reorganize them. * Expunge useless and dangerous stuff like remove_thread(). Change-Id: I6e22932fad61a9fac30fd1363c071074ee7ab382
Diffstat (limited to 'firmware/kernel/thread-internal.h')
-rw-r--r--firmware/kernel/thread-internal.h237
1 files changed, 86 insertions, 151 deletions
diff --git a/firmware/kernel/thread-internal.h b/firmware/kernel/thread-internal.h
index c2acdfb..894bd1f 100644
--- a/firmware/kernel/thread-internal.h
+++ b/firmware/kernel/thread-internal.h
@@ -18,15 +18,13 @@
* KIND, either express or implied.
*
****************************************************************************/
+#ifndef THREAD_INTERNAL_H
+#define THREAD_INTERNAL_H
-#ifndef THREAD_H
-#define THREAD_H
-
-#include "config.h"
-#include <inttypes.h>
-#include <stddef.h>
-#include <stdbool.h>
-#include "gcc_extensions.h"
+#include "thread.h"
+#include <stdio.h>
+#include "panic.h"
+#include "debug.h"
/*
* We need more stack when we run under a host
@@ -48,23 +46,6 @@ struct regs
#include "asm/thread.h"
#endif /* HAVE_SDL_THREADS */
-#ifdef CPU_PP
-#ifdef HAVE_CORELOCK_OBJECT
-/* No reliable atomic instruction available - use Peterson's algorithm */
-struct corelock
-{
- volatile unsigned char myl[NUM_CORES];
- volatile unsigned char turn;
-} __attribute__((packed));
-
-/* Too big to inline everywhere */
-void corelock_init(struct corelock *cl);
-void corelock_lock(struct corelock *cl);
-int corelock_try_lock(struct corelock *cl);
-void corelock_unlock(struct corelock *cl);
-#endif /* HAVE_CORELOCK_OBJECT */
-#endif /* CPU_PP */
-
/* NOTE: The use of the word "queue" may also refer to a linked list of
threads being maintained that are normally dealt with in FIFO order
and not necessarily kernel event_queue */
@@ -84,58 +65,43 @@ enum
TIMEOUT_STATE_FIRST = STATE_SLEEPING,
};
-#if NUM_CORES > 1
-/* Pointer value for name field to indicate thread is being killed. Using
- * an alternate STATE_* won't work since that would interfere with operation
- * while the thread is still running. */
-#define THREAD_DESTRUCT ((const char *)~(intptr_t)0)
-#endif
+#ifdef HAVE_PRIORITY_SCHEDULING
-/* Link information for lists thread is in */
-struct thread_entry; /* forward */
-struct thread_list
+/* Quick-disinherit of priority elevation. Must be a running thread. */
+void priority_disinherit(struct thread_entry *thread, struct blocker *bl);
+
+struct priority_distribution
{
- struct thread_entry *prev; /* Previous thread in a list */
- struct thread_entry *next; /* Next thread in a list */
+ uint8_t hist[NUM_PRIORITIES]; /* Histogram: Frequency for each priority */
+ priobit_t mask; /* Bitmask of hist entries that are not zero */
};
-#ifndef HAVE_CORELOCK_OBJECT
-/* No atomic corelock op needed or just none defined */
-#define corelock_init(cl)
-#define corelock_lock(cl)
-#define corelock_try_lock(cl)
-#define corelock_unlock(cl)
-#endif /* HAVE_CORELOCK_OBJECT */
+#endif /* HAVE_PRIORITY_SCHEDULING */
-#ifdef HAVE_PRIORITY_SCHEDULING
-struct blocker
+#ifdef HAVE_CORELOCK_OBJECT
+/* Operations to be performed just before stopping a thread and starting
+ a new one if specified before calling switch_thread */
+enum
{
- struct thread_entry * volatile thread; /* thread blocking other threads
- (aka. object owner) */
- int priority; /* highest priority waiter */
- struct thread_entry * (*wakeup_protocol)(struct thread_entry *thread);
+ TBOP_CLEAR = 0, /* No operation to do */
+ TBOP_UNLOCK_CORELOCK, /* Unlock a corelock variable */
+ TBOP_SWITCH_CORE, /* Call the core switch preparation routine */
};
-/* Choices of wakeup protocol */
-
-/* For transfer of object ownership by one thread to another thread by
- * the owning thread itself (mutexes) */
-struct thread_entry *
- wakeup_priority_protocol_transfer(struct thread_entry *thread);
-
-/* For release by owner where ownership doesn't change - other threads,
- * interrupts, timeouts, etc. (mutex timeout, queues) */
-struct thread_entry *
- wakeup_priority_protocol_release(struct thread_entry *thread);
-
-
-struct priority_distribution
+struct thread_blk_ops
{
- uint8_t hist[NUM_PRIORITIES]; /* Histogram: Frequency for each priority */
- uint32_t mask; /* Bitmask of hist entries that are not zero */
+ struct corelock *cl_p; /* pointer to corelock */
+ unsigned char flags; /* TBOP_* flags */
};
+#endif /* NUM_CORES > 1 */
-#endif /* HAVE_PRIORITY_SCHEDULING */
+/* Link information for lists thread is in */
+struct thread_entry; /* forward */
+struct thread_list
+{
+ struct thread_entry *prev; /* Previous thread in a list */
+ struct thread_entry *next; /* Next thread in a list */
+};
/* Information kept in each thread slot
* members are arranged according to size - largest first - in order
@@ -183,6 +149,8 @@ struct thread_entry
volatile intptr_t retval; /* Return value from a blocked operation/
misc. use */
#endif
+ uint32_t id; /* Current slot id */
+ int __errno; /* Thread error number (errno tls) */
#ifdef HAVE_PRIORITY_SCHEDULING
/* Priority summary of owned objects that support inheritance */
struct blocker *blocker; /* Pointer to blocker when this thread is blocked
@@ -198,7 +166,6 @@ struct thread_entry
unsigned char priority; /* Scheduled priority (higher of base or
all threads blocked by this one) */
#endif
- uint16_t id; /* Current slot id */
unsigned short stack_size; /* Size of stack in bytes */
unsigned char state; /* Thread slot state (STATE_*) */
#ifdef HAVE_SCHEDULER_BOOSTCTRL
@@ -209,30 +176,6 @@ struct thread_entry
#endif
};
-/*** Macros for internal use ***/
-/* Thread ID, 16 bits = |VVVVVVVV|SSSSSSSS| */
-#define THREAD_ID_VERSION_SHIFT 8
-#define THREAD_ID_VERSION_MASK 0xff00
-#define THREAD_ID_SLOT_MASK 0x00ff
-#define THREAD_ID_INIT(n) ((1u << THREAD_ID_VERSION_SHIFT) | (n))
-
-#ifdef HAVE_CORELOCK_OBJECT
-/* Operations to be performed just before stopping a thread and starting
- a new one if specified before calling switch_thread */
-enum
-{
- TBOP_CLEAR = 0, /* No operation to do */
- TBOP_UNLOCK_CORELOCK, /* Unlock a corelock variable */
- TBOP_SWITCH_CORE, /* Call the core switch preparation routine */
-};
-
-struct thread_blk_ops
-{
- struct corelock *cl_p; /* pointer to corelock */
- unsigned char flags; /* TBOP_* flags */
-};
-#endif /* NUM_CORES > 1 */
-
/* Information kept for each core
* Members are arranged for the same reason as in thread_entry
*/
@@ -256,61 +199,45 @@ struct core_entry
#endif /* NUM_CORES */
};
-#ifdef HAVE_PRIORITY_SCHEDULING
-#define IF_PRIO(...) __VA_ARGS__
-#define IFN_PRIO(...)
-#else
-#define IF_PRIO(...)
-#define IFN_PRIO(...) __VA_ARGS__
-#endif
-
-void core_idle(void);
-void core_wake(IF_COP_VOID(unsigned int core));
-
-/* Initialize the scheduler */
-void init_threads(void) INIT_ATTR;
+/* Thread ID, 32 bits = |VVVVVVVV|VVVVVVVV|VVVVVVVV|SSSSSSSS| */
+#define THREAD_ID_VERSION_SHIFT 8
+#define THREAD_ID_VERSION_MASK 0xffffff00
+#define THREAD_ID_SLOT_MASK 0x000000ff
+#define THREAD_ID_INIT(n) ((1u << THREAD_ID_VERSION_SHIFT) | (n))
+#define THREAD_ID_SLOT(id) ((id) & THREAD_ID_SLOT_MASK)
-/* Allocate a thread in the scheduler */
-#define CREATE_THREAD_FROZEN 0x00000001 /* Thread is frozen at create time */
-unsigned int create_thread(void (*function)(void),
- void* stack, size_t stack_size,
- unsigned flags, const char *name
- IF_PRIO(, int priority)
- IF_COP(, unsigned int core));
+/* Thread locking */
+#if NUM_CORES > 1
+#define LOCK_THREAD(thread) \
+ ({ corelock_lock(&(thread)->slot_cl); })
+#define TRY_LOCK_THREAD(thread) \
+ ({ corelock_try_lock(&(thread)->slot_cl); })
+#define UNLOCK_THREAD(thread) \
+ ({ corelock_unlock(&(thread)->slot_cl); })
+#define UNLOCK_THREAD_AT_TASK_SWITCH(thread) \
+ ({ unsigned int _core = (thread)->core; \
+ cores[_core].blk_ops.flags |= TBOP_UNLOCK_CORELOCK; \
+ cores[_core].blk_ops.cl_p = &(thread)->slot_cl; })
+#else /* NUM_CORES == 1*/
+#define LOCK_THREAD(thread) \
+ ({ (void)(thread); })
+#define TRY_LOCK_THREAD(thread) \
+ ({ (void)(thread); })
+#define UNLOCK_THREAD(thread) \
+ ({ (void)(thread); })
+#define UNLOCK_THREAD_AT_TASK_SWITCH(thread) \
+ ({ (void)(thread); })
+#endif /* NUM_CORES */
-/* Set and clear the CPU frequency boost flag for the calling thread */
-#ifdef HAVE_SCHEDULER_BOOSTCTRL
-void trigger_cpu_boost(void);
-void cancel_cpu_boost(void);
-#else
-#define trigger_cpu_boost() do { } while(0)
-#define cancel_cpu_boost() do { } while(0)
-#endif
-/* Return thread entry from id */
-struct thread_entry *thread_id_entry(unsigned int thread_id);
-/* Make a frozed thread runnable (when started with CREATE_THREAD_FROZEN).
- * Has no effect on a thread not frozen. */
-void thread_thaw(unsigned int thread_id);
-/* Wait for a thread to exit */
-void thread_wait(unsigned int thread_id);
-/* Exit the current thread */
-void thread_exit(void) NORETURN_ATTR;
-#if defined(DEBUG) || defined(ROCKBOX_HAS_LOGF)
-#define ALLOW_REMOVE_THREAD
-/* Remove a thread from the scheduler */
-void remove_thread(unsigned int thread_id);
-#endif
+#define DEADBEEF ((uintptr_t)0xdeadbeefdeadbeefull)
/* Switch to next runnable thread */
void switch_thread(void);
/* Blocks a thread for at least the specified number of ticks (0 = wait until
* next tick) */
void sleep_thread(int ticks);
-/* Indefinitely blocks the current thread on a thread queue */
-void block_thread(struct thread_entry *current);
-/* Blocks the current thread on a thread queue until explicitely woken or
- * the timeout is reached */
-void block_thread_w_tmo(struct thread_entry *current, int timeout);
+/* Blocks the current thread on a thread queue (< 0 == infinite) */
+void block_thread(struct thread_entry *current, int timeout);
/* Return bit flags for thread wakeup */
#define THREAD_NONE 0x0 /* No thread woken up (exclusive) */
@@ -322,12 +249,25 @@ void block_thread_w_tmo(struct thread_entry *current, int timeout);
unsigned int thread_queue_wake(struct thread_entry **list);
/* Wakeup a thread at the head of a list */
-unsigned int wakeup_thread(struct thread_entry **list);
+enum wakeup_thread_protocol
+{
+ WAKEUP_DEFAULT,
+ WAKEUP_TRANSFER,
+ WAKEUP_RELEASE,
+ WAKEUP_TRANSFER_MULTI,
+};
+
+unsigned int wakeup_thread_(struct thread_entry **list
+ IF_PRIO(, enum wakeup_thread_protocol proto));
#ifdef HAVE_PRIORITY_SCHEDULING
-int thread_set_priority(unsigned int thread_id, int priority);
-int thread_get_priority(unsigned int thread_id);
+#define wakeup_thread(list, proto) \
+ wakeup_thread_((list), (proto))
+#else /* !HAVE_PRIORITY_SCHEDULING */
+#define wakeup_thread(list, proto...) \
+ wakeup_thread_((list));
#endif /* HAVE_PRIORITY_SCHEDULING */
+
#ifdef HAVE_IO_PRIORITY
void thread_set_io_priority(unsigned int thread_id, int io_priority);
int thread_get_io_priority(unsigned int thread_id);
@@ -339,19 +279,14 @@ unsigned int switch_core(unsigned int new_core);
/* Return the id of the calling thread. */
unsigned int thread_self(void);
-/* Return the thread_entry for the calling thread.
- * INTERNAL: Intended for use by kernel and not for programs. */
+/* Return the thread_entry for the calling thread */
struct thread_entry* thread_self_entry(void);
-/* Debugging info - only! */
-int thread_stack_usage(const struct thread_entry *thread);
-#if NUM_CORES > 1
-int idle_stack_usage(unsigned int core);
-#endif
-void thread_get_name(char *buffer, int size,
- struct thread_entry *thread);
+/* Return thread entry from id */
+struct thread_entry *thread_id_entry(unsigned int thread_id);
+
#ifdef RB_PROFILE
void profile_thread(void);
#endif
-#endif /* THREAD_H */
+#endif /* THREAD_INTERNAL_H */