added support for busy-waits in simulated contiki processes

(the entire process_run()-loop is inside a Contiki multi-thread)
This commit is contained in:
fros4943 2006-09-29 14:32:15 +00:00
parent c033cf5810
commit cb71b2fca6
6 changed files with 570 additions and 17 deletions

View file

@ -1,4 +1,4 @@
# $Id: Makefile.cooja,v 1.4 2006/09/29 12:48:48 fros4943 Exp $ # $Id: Makefile.cooja,v 1.5 2006/09/29 14:33:31 fros4943 Exp $
## The COOJA Simulator Contiki platform Makefile ## The COOJA Simulator Contiki platform Makefile
## ##
@ -27,21 +27,16 @@ MAINFILE = $(OUTPUT_DIR)/$(TYPEID).co
COOJA = $(CONTIKI)/platform/$(TARGET) COOJA = $(CONTIKI)/platform/$(TARGET)
CONTIKI_TARGET_DIRS = . dev lib sys CONTIKI_TARGET_DIRS = . dev lib sys
COOJALIB = simEnvChange.c irq.c COOJA_BASE = simEnvChange.c irq.c cooja_mt.c cooja_mtarch.c
COOJAINTFS = beep.c button-sensor.c ip.c leds-arch.c moteid.c \ COOJA_INTFS = beep.c button-sensor.c ip.c leds-arch.c moteid.c \
pir-sensor.c radio-arch.c rs232.c vib-sensor.c simEnvChange.c \ pir-sensor.c radio-arch.c rs232.c vib-sensor.c \
clock.c log.c clock.c log.c
CORE_FILES = random.c sensors.c leds.c serial.c mt.c mtarch.c CORE_FILES = random.c sensors.c leds.c serial.c
#COOJA_SYS = $(patsubst $(COOJA)/sys/%.c,%.c,$(wildcard $(COOJA)/sys/*.c))
#COOJA_DEV = $(patsubst $(COOJA)/dev/%.c,%.c,$(wildcard $(COOJA)/dev/*.c))
#COOJA_LIB = $(patsubst $(COOJA)/lib/%.c,%.c,$(wildcard $(COOJA)/lib/*.c))
#COOJA_LIB = simEnvChange.c
CONTIKI_TARGET_SOURCEFILES = \ CONTIKI_TARGET_SOURCEFILES = \
$(COOJALIB) $(COOJAINTFS) $(CORE_FILES) $(PROJECT_SOURCEFILES) $(COOJA_BASE) $(COOJA_INTFS) $(CORE_FILES) $(PROJECT_SOURCEFILES)
CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)

View file

@ -0,0 +1,107 @@
/*
* Copyright (c) 2004, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: cooja_mt.c,v 1.1 2006/09/29 14:32:38 fros4943 Exp $
*/
/*
* This file is ripped from mt.c of the Contiki Multi-threading library.
* Fredrik Osterlind <fros@sics.se>
*/
#include "contiki.h"
#include "sys/cooja_mt.h"
#include "sys/cc.h"
#define MT_STATE_READY 1
#define MT_STATE_RUNNING 2
#define MT_STATE_WAITING 3
#define MT_STATE_PEEK 4
#define MT_STATE_EXITED 5
static struct cooja_mt_thread *current;
/*--------------------------------------------------------------------------*/
void
cooja_mt_init(void)
{
cooja_mtarch_init();
}
/*--------------------------------------------------------------------------*/
void
cooja_mt_remove(void)
{
cooja_mtarch_remove();
}
/*--------------------------------------------------------------------------*/
void
cooja_mt_start(struct cooja_mt_thread *thread, void (* function)(void *), void *data)
{
/* Call the architecture dependant function to set up the processor
stack with the correct parameters. */
cooja_mtarch_start(&thread->thread, function, data);
thread->state = MT_STATE_READY;
}
/*--------------------------------------------------------------------------*/
void
cooja_mt_exec(struct cooja_mt_thread *thread)
{
if(thread->state == MT_STATE_READY ||
thread->state == MT_STATE_PEEK) {
thread->state = MT_STATE_RUNNING;
current = thread;
/* Switch context to the thread. The function call will not return
until the the thread has yielded, or is preempted. */
/*printf("swtis\n");*/
cooja_mtarch_exec(&thread->thread);
}
}
/*--------------------------------------------------------------------------*/
void
cooja_mt_exit(void)
{
current->state = MT_STATE_EXITED;
current = NULL;
cooja_mtarch_yield();
}
/*--------------------------------------------------------------------------*/
void
cooja_mt_yield(void)
{
current->state = MT_STATE_READY;
current = NULL;
/* This function is called from the running thread, and we call the
switch function in order to switch the thread to the main Contiki
program instead. For us, the switch function will not return
until the next time we are scheduled to run. */
cooja_mtarch_yield();
}

View file

@ -0,0 +1,252 @@
/*
* Copyright (c) 2004, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: cooja_mt.h,v 1.1 2006/09/29 14:32:38 fros4943 Exp $
*/
/*
* This file is ripped from mt.h of the Contiki Multi-threading library.
* Fredrik Osterlind <fros@sics.se>
*/
#ifndef __COOJA_MT_H__
#define __COOJA_MT_H__
#include "contiki.h"
/**
* An opaque structure that is used for holding the state of a thread.
*
* The structure should be defined in the "mtarch.h" file. This
* structure typically holds the entire stack for the thread.
*/
struct cooja_mtarch_thread;
/**
* Initialize the architecture specific support functions for the
* multi-thread library.
*
* This function is implemented by the architecture specific functions
* for the multi-thread library and is called by the mt_init()
* function as part of the initialization of the library. The
* mtarch_init() function can be used for, e.g., starting preemtion
* timers or other architecture specific mechanisms required for the
* operation of the library.
*/
void cooja_mtarch_init(void);
/**
* Uninstall library and clean up.
*
*/
void cooja_mtarch_remove(void);
/**
* Setup the stack frame for a thread that is being started.
*
* This function is called by the mt_start() function in order to set
* up the architecture specific stack of the thread to be started.
*
* \param thread A pointer to a struct mtarch_thread for the thread to
* be started.
*
* \param function A pointer to the function that the thread will
* start executing the first time it is scheduled to run.
*
* \param data A pointer to the argument that the function should be
* passed.
*/
void cooja_mtarch_start(struct cooja_mtarch_thread *thread,
void (* function)(void *data),
void *data);
/**
* Yield the processor.
*
* This function is called by the mt_yield() function, which is called
* from the running thread in order to give up the processor.
*
*/
void cooja_mtarch_yield(void);
/**
* Start executing a thread.
*
* This function is called from mt_exec() and the purpose of the
* function is to start execution of the thread. The function should
* switch in the stack of the thread, and does not return until the
* thread has explicitly yielded (using mt_yield()) or until it is
* preempted.
*
*/
void cooja_mtarch_exec(struct cooja_mtarch_thread *thread);
/** @} */
#include "cooja_mtarch.h"
struct cooja_mt_thread {
int state;
process_event_t *evptr;
process_data_t *dataptr;
struct cooja_mtarch_thread thread;
};
/**
* No error.
*
* \hideinitializer
*/
#define MT_OK 1
/**
* Initializes the multithreading library.
*
*/
void cooja_mt_init(void);
/**
* Uninstalls library and cleans up.
*
*/
void cooja_mt_remove(void);
/**
* Starts a multithreading thread.
*
* \param thread Pointer to an mt_thread struct that must have been
* previously allocated by the caller.
*
* \param function A pointer to the entry function of the thread that is
* to be set up.
*
* \param data A pointer that will be passed to the entry function.
*
*/
void cooja_mt_start(struct cooja_mt_thread *thread, void (* function)(void *), void *data);
/**
* Execute parts of a thread.
*
* This function is called by a Contiki process and runs a
* thread. The function does not return until the thread has yielded,
* or is preempted.
*
* \note The thread must first be initialized with the mt_init() function.
*
* \param thread A pointer to a struct mt_thread block that must be
* allocated by the caller.
*
*/
void cooja_mt_exec(struct cooja_mt_thread *thread);
/**
* Post an event to a thread.
*
* This function posts an event to a thread. The thread will be
* scheduled if the thread currently is waiting for the posted event
* number. If the thread is not waiting for the event, this function
* does nothing.
*
* \note The thread must first be initialized with the mt_init() function.
*
* \param thread A pointer to a struct mt_thread block that must be
* allocated by the caller.
*
* \param s The event that is posted to the thread.
*
* \param data An opaque pointer to a user specified structure
* containing additonal information, or NULL if no additional
* information is needed.
*/
/*void mt_exec_event(struct mt_thread *thread, process_event_t s,
process_data_t data);*/
/**
* Voluntarily give up the processor.
*
* This function is called by a running thread in order to give up
* control of the CPU.
*
*/
void cooja_mt_yield(void);
/**
* Post an event to another process.
*
* This function is called by a running thread and will emit a signal
* to another Contiki process. This will cause the currently executing
* thread to yield.
*
* \param p The process receiving the signal, or PROCESS_BROADCAST
* for a broadcast event.
*
* \param ev The event to be posted.
*
* \param data A pointer to a message that is to be delivered together
* with the signal.
*
*/
/*void mt_post(struct process *p, process_event_t ev, process_data_t data);*/
/**
* Block and wait for an event to occur.
*
* This function can be called by a running thread in order to block
* and wait for an event. The function returns when an event has
* occured. The event number and the associated data are placed in the
* variables pointed to by the function arguments.
*
* \param ev A pointer to a process_event_t variable. The variable
* will be filled with the number event that woke the thread.
*
* \param data A pointer to a process_data_t variable. The variable
* will be filled with the data associated with the event that woke
* the thread.
*
*/
/*void mt_wait(process_event_t *ev, process_data_t *data);*/
/**
* Exit a thread.
*
* This function is called from within an executing thread in order to
* exit the thread. The function never returns.
*
*/
void cooja_mt_exit(void);
/** @} */
/** @} */
#endif /* __MT_H__ */

View file

@ -0,0 +1,124 @@
/*
* This file is ripped from x86/mtarch.c of the Contiki Multi-threading library.
* Fredrik Osterlind <fros@sics.se>
*/
#include <stdio.h>
#include "sys/cooja_mt.h"
struct frame {
unsigned long flags;
unsigned long ebp;
unsigned long edi;
unsigned long esi;
unsigned long edx;
unsigned long ecx;
unsigned long ebx;
unsigned long eax;
unsigned long retaddr;
unsigned long retaddr2;
unsigned long data;
};
/*--------------------------------------------------------------------------*/
void
cooja_mtarch_init(void)
{
}
/*--------------------------------------------------------------------------*/
void
cooja_mtarch_start(struct cooja_mtarch_thread *t,
void (*function)(void *), void *data)
{
struct frame *f = (struct frame *)&t->stack[COOJA_MTARCH_STACKSIZE - sizeof(struct frame)/4];
int i;
for(i = 0; i < COOJA_MTARCH_STACKSIZE; ++i) {
t->stack[i] = i;
}
memset(f, 0, sizeof(struct frame));
f->retaddr = (unsigned long)function;
f->data = (unsigned long)data;
t->sp = (unsigned long)&f->flags;
f->ebp = (unsigned long)&f->eax;
}
/*--------------------------------------------------------------------------*/
static unsigned long cooja_spsave, cooja_sptmp;
static struct cooja_mtarch_thread *cooja_running_thread;
static void
cooja_sw(void)
{
asm("pushl %eax");
asm("pushl %ebx");
asm("pushl %ecx");
asm("pushl %edx");
asm("pushl %esi");
asm("pushl %edi");
asm("pushl %ebp");
// asm("pushl %ebp"); /* XXX: should push FPU flags here. */
asm("movl %esp, cooja_spsave");
cooja_sptmp = cooja_running_thread->sp;
cooja_running_thread->sp = cooja_spsave;
asm("movl cooja_sptmp, %esp");
// asm("popl %ebp"); /* XXX: should pop FPU flags here. */
asm("popl %ebp");
asm("popl %edi");
asm("popl %esi");
asm("popl %edx");
asm("popl %ecx");
asm("popl %ebx");
asm("popl %eax");
}
/*--------------------------------------------------------------------------*/
void
cooja_mtarch_exec(struct cooja_mtarch_thread *t)
{
cooja_running_thread = t;
cooja_sw();
cooja_running_thread = NULL;
}
/*--------------------------------------------------------------------------*/
void
cooja_mtarch_remove(void)
{
}
/*--------------------------------------------------------------------------*/
void
cooja_mtarch_yield(void)
{
cooja_sw();
}
/*--------------------------------------------------------------------------*/
void
cooja_mtarch_pstop(void)
{
}
/*--------------------------------------------------------------------------*/
void
cooja_mtarch_pstart(void)
{
}
/*--------------------------------------------------------------------------*/
int
cooja_mtarch_stack_usage(struct cooja_mt_thread *t)
{
int i;
for(i = 0; i < COOJA_MTARCH_STACKSIZE; ++i) {
if(t->thread.stack[i] != i) {
return COOJA_MTARCH_STACKSIZE - i;
}
}
return -1;
}
/*--------------------------------------------------------------------------*/

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* This file is ripped from x86/mtarch.h of the Contiki Multi-threading library.
* Fredrik Osterlind <fros@sics.se>
*/
#ifndef __COOJA_MTARCH_H__
#define __COOJA_MTARCH_H__
#ifndef COOJA_MTARCH_STACKSIZE
#define COOJA_MTARCH_STACKSIZE 1024
#endif /* COOJA_MTARCH_STACKSIZE */
struct cooja_mtarch_thread {
/* Note: stack must be aligned on 4-byte boundary. */
unsigned long stack[COOJA_MTARCH_STACKSIZE];
unsigned long sp;
};
struct cooja_mt_thread;
int cooja_mtarch_stack_usage(struct cooja_mt_thread *t);
#endif /* __COOJA_MTARCH_H__ */

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: code_main_template,v 1.3 2006/09/06 10:37:08 fros4943 Exp $ * $Id: code_main_template,v 1.4 2006/09/29 14:32:15 fros4943 Exp $
*/ */
/** /**
@ -71,6 +71,7 @@
#include "net/uip.h" #include "net/uip.h"
#include "dev/radio-arch.h" #include "dev/radio-arch.h"
#include "sys/etimer.h" #include "sys/etimer.h"
#include "sys/cooja_mt.h"
/* Declare all initialization processes */ /* Declare all initialization processes */
[PROCESS_DEFINITIONS] [PROCESS_DEFINITIONS]
@ -101,6 +102,26 @@ static struct uip_fw_netif simNetworkIF =
*/ */
int referenceVar; int referenceVar;
/*
* process_run() infinite loop.
* Is yielded at least once per function call.
*/
static struct cooja_mt_thread process_run_thread;
static void
start_process_run_loop(void *data)
{
while(1)
{
/* Always pretend we have processes left while inside process_run() */
simProcessRunValue = 1;
simProcessRunValue = process_run();
/* Yield thread when one process_run has completed */
cooja_mt_yield();
}
}
extern unsigned long _end; extern unsigned long _end;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -134,6 +155,9 @@ Java_se_sics_cooja_corecomm_[CLASS_NAME]_init(JNIEnv *env, jobject obj)
/* Start user applications */ /* Start user applications */
autostart_start((struct process **) autostart_processes); autostart_start((struct process **) autostart_processes);
/* Prepare thread that will do the process_run()-loop */
cooja_mt_start(&process_run_thread, &start_process_run_loop, NULL);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
@ -153,10 +177,7 @@ Java_se_sics_cooja_corecomm_[CLASS_NAME]_init(JNIEnv *env, jobject obj)
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_se_sics_cooja_corecomm_[CLASS_NAME]_getMemory(JNIEnv *env, jobject obj, jint start, jint length, jbyteArray mem_arr) Java_se_sics_cooja_corecomm_[CLASS_NAME]_getMemory(JNIEnv *env, jobject obj, jint start, jint length, jbyteArray mem_arr)
{ {
// jbyteArray ret=(*env)->NewByteArray(env, length);
(*env)->SetByteArrayRegion(env, mem_arr, 0, (size_t) length, (jbyte *) start); (*env)->SetByteArrayRegion(env, mem_arr, 0, (size_t) length, (jbyte *) start);
// return (ret);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
@ -212,8 +233,9 @@ Java_se_sics_cooja_corecomm_[CLASS_NAME]_tick(JNIEnv *env, jobject obj)
simEtimerPending = 0; simEtimerPending = 0;
} }
/* Execute the contiki code (save process_run return value for state decisions) */ /* Let Contiki execute one or a part of the process_run()-function via the thread.
simProcessRunValue = process_run(); This call stores the process_run() return value */
cooja_mt_exec(&process_run_thread);
/* Let all simulation interfaces act before returning to java */ /* Let all simulation interfaces act before returning to java */
doActionsAfterTick(); doActionsAfterTick();