2010-09-22 15:10:42 +02:00
|
|
|
/**
|
|
|
|
* thread functions
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Freie Universität Berlin
|
|
|
|
*
|
|
|
|
* This file subject to the terms and conditions of the GNU General Public
|
|
|
|
* License. See the file LICENSE in the top level directory for more details.
|
|
|
|
*
|
|
|
|
* @ingroup kernel
|
|
|
|
* @{
|
|
|
|
* @file
|
|
|
|
* @author Kaspar Schleiser <kaspar.schleiser@fu-berlin.de>
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "thread.h"
|
|
|
|
#include "kernel.h"
|
|
|
|
|
|
|
|
//#define ENABLE_DEBUG
|
|
|
|
#include "debug.h"
|
|
|
|
#include "kernel_intern.h"
|
|
|
|
#include "bitarithm.h"
|
|
|
|
#include "hwtimer.h"
|
2010-10-28 11:22:57 +02:00
|
|
|
#include "sched.h"
|
2010-09-22 15:10:42 +02:00
|
|
|
|
|
|
|
inline int thread_getpid() {
|
2010-10-28 11:22:57 +02:00
|
|
|
return active_thread->pid;
|
2010-09-22 15:10:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int thread_getstatus(int pid) {
|
2010-10-28 11:22:57 +02:00
|
|
|
if (sched_threads[pid]==NULL)
|
2010-09-22 15:10:42 +02:00
|
|
|
return STATUS_NOT_FOUND;
|
2010-10-28 11:22:57 +02:00
|
|
|
return sched_threads[pid]->status;
|
2010-09-22 15:10:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void thread_sleep() {
|
|
|
|
if ( inISR()) return;
|
|
|
|
dINT();
|
2010-10-28 11:22:57 +02:00
|
|
|
sched_set_status((tcb*)active_thread, STATUS_SLEEPING);
|
|
|
|
thread_yield();
|
2010-09-22 15:10:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int thread_wakeup(int pid) {
|
2010-11-02 11:40:10 +01:00
|
|
|
DEBUG("thread_wakeup: Trying to wakeup PID %i...\n", pid);
|
2010-09-22 15:10:42 +02:00
|
|
|
int isr = inISR();
|
2010-11-02 11:40:10 +01:00
|
|
|
if (! isr) {
|
|
|
|
DEBUG("thread_wakeup: Not in interrupt.\n");
|
|
|
|
dINT();
|
|
|
|
}
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2010-10-28 11:22:57 +02:00
|
|
|
int result = sched_threads[pid]->status;
|
2010-09-22 15:10:42 +02:00
|
|
|
if (result == STATUS_SLEEPING) {
|
2010-11-02 11:40:10 +01:00
|
|
|
DEBUG("thread_wakeup: Thread is sleeping.\n");
|
2010-10-28 11:22:57 +02:00
|
|
|
sched_set_status((tcb*)sched_threads[pid], STATUS_RUNNING);
|
2010-09-22 15:10:42 +02:00
|
|
|
if (!isr) {
|
|
|
|
eINT();
|
2010-10-28 11:22:57 +02:00
|
|
|
thread_yield();
|
2010-09-22 15:10:42 +02:00
|
|
|
} else {
|
2010-10-28 11:22:57 +02:00
|
|
|
sched_context_switch_request = 1;
|
2010-09-22 15:10:42 +02:00
|
|
|
}
|
2010-11-04 16:21:39 +01:00
|
|
|
return 1;
|
2010-09-22 15:10:42 +02:00
|
|
|
} else {
|
2010-11-02 11:40:10 +01:00
|
|
|
DEBUG("thread_wakeup: Thread is not sleeping!\n");
|
2010-09-22 15:10:42 +02:00
|
|
|
if (!isr) eINT();
|
|
|
|
return STATUS_NOT_FOUND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-28 11:22:57 +02:00
|
|
|
int thread_measure_stack_usage(char* stack) {
|
2010-09-22 15:10:42 +02:00
|
|
|
unsigned int* stackp = (unsigned int*)stack;
|
|
|
|
/* assumption that the comparison fails before or after end of stack */
|
|
|
|
while( *stackp == (unsigned int)stackp )
|
|
|
|
stackp++;
|
|
|
|
|
|
|
|
int space = (unsigned int)stackp - (unsigned int)stack;
|
|
|
|
return space;
|
|
|
|
}
|
|
|
|
|
2010-11-04 16:47:24 +01:00
|
|
|
int thread_create(char *stack, int stacksize, char priority, int flags, void (*function) (void), const char* name)
|
2010-09-22 15:10:42 +02:00
|
|
|
{
|
2010-11-04 16:47:24 +01:00
|
|
|
/* allocate our thread control block at the top of our stackspace */
|
|
|
|
int total_stacksize = stacksize;
|
|
|
|
stacksize -= sizeof(tcb);
|
|
|
|
tcb *cb = (tcb*) (stack + stacksize);
|
2010-09-22 15:10:42 +02:00
|
|
|
|
|
|
|
if (priority >= SCHED_PRIO_LEVELS) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & CREATE_STACKTEST) {
|
|
|
|
/* assign each int of the stack the value of it's address */
|
|
|
|
unsigned int *stackmax = (unsigned int*) ((char*)stack + stacksize);
|
|
|
|
unsigned int* stackp = (unsigned int*)stack;
|
|
|
|
while(stackp < stackmax) {
|
|
|
|
*stackp = (unsigned int)stackp;
|
|
|
|
stackp++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* create stack guard */
|
|
|
|
*stack = (unsigned int)stack;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! inISR()) {
|
|
|
|
dINT();
|
|
|
|
}
|
|
|
|
|
|
|
|
int pid = 0;
|
|
|
|
while (pid < MAXTHREADS) {
|
2010-10-28 11:22:57 +02:00
|
|
|
if (sched_threads[pid] == NULL) {
|
|
|
|
sched_threads[pid] = cb;
|
2010-10-28 11:31:19 +02:00
|
|
|
cb->pid = pid;
|
2010-09-22 15:10:42 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
pid++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pid == MAXTHREADS) {
|
|
|
|
DEBUG("thread_create(): too many threads!\n");
|
|
|
|
|
|
|
|
if (! inISR()) {
|
|
|
|
eINT();
|
|
|
|
}
|
|
|
|
return -EOVERFLOW;
|
|
|
|
}
|
|
|
|
|
2010-10-28 11:22:57 +02:00
|
|
|
cb->sp = thread_stack_init(function,stack+stacksize);
|
2010-10-25 15:40:01 +02:00
|
|
|
cb->stack_start = stack;
|
2010-11-04 16:47:24 +01:00
|
|
|
cb->stack_size = total_stacksize;
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2010-10-25 15:40:01 +02:00
|
|
|
cb->priority = priority;
|
|
|
|
cb->status = 0;
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2010-10-25 15:40:01 +02:00
|
|
|
cb->name = name;
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2010-10-25 15:40:01 +02:00
|
|
|
cb->wait_data = NULL;
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2010-10-25 15:40:01 +02:00
|
|
|
cb->msg_queue.data = 0;
|
|
|
|
cb->msg_queue.priority = 0;
|
|
|
|
cb->msg_queue.next = NULL;
|
2010-09-22 15:10:42 +02:00
|
|
|
|
2010-10-25 15:40:01 +02:00
|
|
|
cb->rq_entry.data = (unsigned int) cb;
|
|
|
|
cb->rq_entry.next = NULL;
|
|
|
|
cb->rq_entry.prev = NULL;
|
2010-09-22 15:10:42 +02:00
|
|
|
|
|
|
|
num_tasks++;
|
|
|
|
|
2010-10-25 15:40:01 +02:00
|
|
|
DEBUG("Created thread %s. PID: %u. Priority: %u.\n", name, cb->pid, priority);
|
2010-09-22 15:10:42 +02:00
|
|
|
|
|
|
|
if (flags & CREATE_SLEEPING) {
|
2010-10-25 15:40:01 +02:00
|
|
|
sched_set_status(cb, STATUS_SLEEPING);
|
2010-09-22 15:10:42 +02:00
|
|
|
} else {
|
2010-10-25 15:40:01 +02:00
|
|
|
sched_set_status(cb, STATUS_PENDING);
|
2010-09-22 15:10:42 +02:00
|
|
|
if (!(flags & CREATE_WOUT_YIELD)) {
|
|
|
|
if (! inISR()) {
|
|
|
|
eINT();
|
2010-10-28 11:22:57 +02:00
|
|
|
thread_yield();
|
2010-09-22 15:10:42 +02:00
|
|
|
} else {
|
2010-10-28 11:22:57 +02:00
|
|
|
sched_context_switch_request = 1;
|
2010-09-22 15:10:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-28 11:22:57 +02:00
|
|
|
if (!inISR() && active_thread!=NULL) {
|
2010-09-22 15:10:42 +02:00
|
|
|
eINT();
|
|
|
|
}
|
|
|
|
|
|
|
|
return pid;
|
|
|
|
}
|
|
|
|
|