1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/core/thread.c

194 lines
4.5 KiB
C
Raw Normal View History

/**
* thread functions
*
* Copyright (C) 2013 Freie Universität Berlin
*
* This file subject to the terms and conditions of the GNU Lesser 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"
inline int thread_getpid() {
2010-10-28 11:22:57 +02:00
return active_thread->pid;
}
int thread_getlastpid() {
extern int last_pid;
return last_pid;
}
unsigned int thread_getstatus(int pid) {
2010-10-28 11:22:57 +02:00
if (sched_threads[pid]==NULL)
return STATUS_NOT_FOUND;
2010-10-28 11:22:57 +02:00
return sched_threads[pid]->status;
}
void thread_sleep() {
if ( inISR()) return;
dINT();
sched_set_status((tcb_t*)active_thread, STATUS_SLEEPING);
eINT();
2010-10-28 11:22:57 +02:00
thread_yield();
}
int thread_wakeup(int pid) {
DEBUG("thread_wakeup: Trying to wakeup PID %i...\n", pid);
int isr = inISR();
if (! isr) {
DEBUG("thread_wakeup: Not in interrupt.\n");
dINT();
}
2010-10-28 11:22:57 +02:00
int result = sched_threads[pid]->status;
if (result == STATUS_SLEEPING) {
DEBUG("thread_wakeup: Thread is sleeping.\n");
sched_set_status((tcb_t*)sched_threads[pid], STATUS_RUNNING);
if (!isr) {
eINT();
2010-10-28 11:22:57 +02:00
thread_yield();
} else {
2010-10-28 11:22:57 +02:00
sched_context_switch_request = 1;
}
return 1;
} else {
DEBUG("thread_wakeup: Thread is not sleeping!\n");
if (!isr) eINT();
return STATUS_NOT_FOUND;
}
}
2010-10-28 11:22:57 +02:00
int thread_measure_stack_usage(char* stack) {
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;
}
int thread_create(char *stack, int stacksize, char priority, int flags, void (*function) (void), const char* name)
{
/* allocate our thread control block at the top of our stackspace */
int total_stacksize = stacksize;
stacksize -= sizeof(tcb_t);
2010-11-09 17:01:52 +01:00
/* align tcb address on 32bit boundary */
unsigned int tcb_address = (unsigned int) stack + stacksize;
if ( tcb_address & 1 ) {
tcb_address--;
stacksize--;
}
if ( tcb_address & 2 ) {
tcb_address-=2;
stacksize-=2;
}
tcb_t *cb = (tcb_t*) tcb_address;
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;
break;
}
pid++;
}
if (pid == MAXTHREADS) {
DEBUG("thread_create(): too many threads!\n");
if (! inISR()) {
eINT();
}
return -EOVERFLOW;
}
2013-03-06 01:08:15 +01:00
cb->sp = thread_stack_init(function,stack,stacksize);
cb->stack_start = stack;
cb->stack_size = total_stacksize;
cb->priority = priority;
cb->status = 0;
2010-11-26 14:21:48 +01:00
cb->rq_entry.data = (unsigned int) cb;
cb->rq_entry.next = NULL;
cb->rq_entry.prev = NULL;
cb->name = name;
cb->wait_data = NULL;
2010-11-26 14:21:48 +01:00
cb->msg_waiters.data = 0;
cb->msg_waiters.priority = 0;
cb->msg_waiters.next = NULL;
2010-11-26 14:21:48 +01:00
cib_init(&(cb->msg_queue),0);
2010-11-26 15:02:15 +01:00
cb->msg_array = NULL;
num_tasks++;
DEBUG("Created thread %s. PID: %u. Priority: %u.\n", name, cb->pid, priority);
if (flags & CREATE_SLEEPING) {
sched_set_status(cb, STATUS_SLEEPING);
} else {
sched_set_status(cb, STATUS_PENDING);
if (!(flags & CREATE_WOUT_YIELD)) {
if (! inISR()) {
eINT();
2010-10-28 11:22:57 +02:00
thread_yield();
} else {
2010-10-28 11:22:57 +02:00
sched_context_switch_request = 1;
}
}
}
2010-10-28 11:22:57 +02:00
if (!inISR() && active_thread!=NULL) {
eINT();
}
return pid;
}