summaryrefslogtreecommitdiff
path: root/firmware/kernel/pthread/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/kernel/pthread/thread.c')
-rw-r--r--firmware/kernel/pthread/thread.c81
1 files changed, 15 insertions, 66 deletions
diff --git a/firmware/kernel/pthread/thread.c b/firmware/kernel/pthread/thread.c
index 354a946..71cbd1d 100644
--- a/firmware/kernel/pthread/thread.c
+++ b/firmware/kernel/pthread/thread.c
@@ -3,8 +3,8 @@
#include <errno.h>
#include <pthread.h>
#include "/usr/include/semaphore.h"
+#include "thread-internal.h"
#include "kernel.h"
-#include "thread.h"
#define NSEC_PER_SEC 1000000000L
static inline void timespec_add_ns(struct timespec *a, uint64_t ns)
@@ -25,11 +25,6 @@ struct thread_init_data {
__thread struct thread_entry *_current;
-struct thread_entry* thread_self_entry(void)
-{
- return _current;
-}
-
unsigned int thread_self(void)
{
return (unsigned) pthread_self();
@@ -70,12 +65,10 @@ static void *trampoline(void *arg)
if (data->start_frozen)
{
struct corelock thaw_lock;
- struct thread_entry *queue = NULL;
corelock_init(&thaw_lock);
corelock_lock(&thaw_lock);
_current->lock = &thaw_lock;
- _current->bqp = &queue;
sem_post(&data->init_sem);
block_thread_switch(_current, _current->lock);
_current->lock = NULL;
@@ -97,7 +90,7 @@ void thread_thaw(unsigned int thread_id)
if (e->lock)
{
corelock_lock(e->lock);
- wakeup_thread(e->bqp);
+ wakeup_thread(e);
corelock_unlock(e->lock);
}
/* else: no lock. must be running already */
@@ -135,7 +128,7 @@ unsigned int create_thread(void (*function)(void),
data->entry = entry;
pthread_cond_init(&entry->cond, NULL);
entry->runnable = true;
- entry->l = (struct thread_list) { NULL, NULL };
+
sem_init(&data->init_sem, 0, 0);
if (pthread_create(&retval, NULL, trampoline, data) < 0)
@@ -153,58 +146,19 @@ unsigned int create_thread(void (*function)(void),
return retval;
}
-static void add_to_list_l(struct thread_entry **list,
- struct thread_entry *thread)
-{
- if (*list == NULL)
- {
- /* Insert into unoccupied list */
- thread->l.next = thread;
- thread->l.prev = thread;
- *list = thread;
- }
- else
- {
- /* Insert last */
- thread->l.next = *list;
- thread->l.prev = (*list)->l.prev;
- thread->l.prev->l.next = thread;
- (*list)->l.prev = thread;
- }
-}
-
-static void remove_from_list_l(struct thread_entry **list,
- struct thread_entry *thread)
-{
- if (thread == thread->l.next)
- {
- /* The only item */
- *list = NULL;
- return;
- }
-
- if (thread == *list)
- {
- /* List becomes next item */
- *list = thread->l.next;
- }
-
- /* Fix links to jump over the removed entry. */
- thread->l.prev->l.next = thread->l.next;
- thread->l.next->l.prev = thread->l.prev;
-}
-
/* for block_thread(), _w_tmp() and wakeup_thread() t->lock must point
* to a corelock instance, and this corelock must be held by the caller */
void block_thread_switch(struct thread_entry *t, struct corelock *cl)
{
t->runnable = false;
- add_to_list_l(t->bqp, t);
+ if (wait_queue_ptr(t))
+ wait_queue_register(t);
while(!t->runnable)
pthread_cond_wait(&t->cond, &cl->mutex);
}
-void block_thread_switch_w_tmo(struct thread_entry *t, int timeout, struct corelock *cl)
+void block_thread_switch_w_tmo(struct thread_entry *t, int timeout,
+ struct corelock *cl)
{
int err = 0;
struct timespec ts;
@@ -213,30 +167,25 @@ void block_thread_switch_w_tmo(struct thread_entry *t, int timeout, struct corel
timespec_add_ns(&ts, timeout * (NSEC_PER_SEC/HZ));
t->runnable = false;
- add_to_list_l(t->bqp, t);
+ wait_queue_register(t->wqp, t);
while(!t->runnable && !err)
err = pthread_cond_timedwait(&t->cond, &cl->mutex, &ts);
if (err == ETIMEDOUT)
{ /* the thread timed out and was not explicitely woken up.
* we need to do this now to mark it runnable again */
- remove_from_list_l(t->bqp, t);
t->runnable = true;
- if (t->wakeup_ext_cb)
- t->wakeup_ext_cb(t);
+ /* NOTE: objects do their own removal upon timer expiration */
}
}
-unsigned int wakeup_thread(struct thread_entry **list)
+unsigned int wakeup_thread(struct thread_entry *t)
{
- struct thread_entry *t = *list;
- if (t)
- {
- remove_from_list_l(list, t);
- t->runnable = true;
- pthread_cond_signal(&t->cond);
- }
- return THREAD_NONE;
+ if (t->wqp)
+ wait_queue_remove(t);
+ t->runnable = true;
+ pthread_cond_signal(&t->cond);
+ return THREAD_OK;
}