From cb71b2fca60f9197a2fe3a477c8221aaa217c4a8 Mon Sep 17 00:00:00 2001 From: fros4943 Date: Fri, 29 Sep 2006 14:32:15 +0000 Subject: [PATCH] added support for busy-waits in simulated contiki processes (the entire process_run()-loop is inside a Contiki multi-thread) --- platform/cooja/Makefile.cooja | 17 +- platform/cooja/sys/cooja_mt.c | 107 +++++++++++ platform/cooja/sys/cooja_mt.h | 252 ++++++++++++++++++++++++++ platform/cooja/sys/cooja_mtarch.c | 124 +++++++++++++ platform/cooja/sys/cooja_mtarch.h | 53 ++++++ tools/cooja/config/code_main_template | 34 +++- 6 files changed, 570 insertions(+), 17 deletions(-) create mode 100644 platform/cooja/sys/cooja_mt.c create mode 100644 platform/cooja/sys/cooja_mt.h create mode 100644 platform/cooja/sys/cooja_mtarch.c create mode 100644 platform/cooja/sys/cooja_mtarch.h diff --git a/platform/cooja/Makefile.cooja b/platform/cooja/Makefile.cooja index 18e35b5bc..0a3d46957 100644 --- a/platform/cooja/Makefile.cooja +++ b/platform/cooja/Makefile.cooja @@ -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 ## @@ -27,21 +27,16 @@ MAINFILE = $(OUTPUT_DIR)/$(TYPEID).co COOJA = $(CONTIKI)/platform/$(TARGET) 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 \ - pir-sensor.c radio-arch.c rs232.c vib-sensor.c simEnvChange.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 \ clock.c log.c -CORE_FILES = random.c sensors.c leds.c serial.c mt.c mtarch.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 +CORE_FILES = random.c sensors.c leds.c serial.c CONTIKI_TARGET_SOURCEFILES = \ -$(COOJALIB) $(COOJAINTFS) $(CORE_FILES) $(PROJECT_SOURCEFILES) +$(COOJA_BASE) $(COOJA_INTFS) $(CORE_FILES) $(PROJECT_SOURCEFILES) CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) diff --git a/platform/cooja/sys/cooja_mt.c b/platform/cooja/sys/cooja_mt.c new file mode 100644 index 000000000..2d6e7cf5c --- /dev/null +++ b/platform/cooja/sys/cooja_mt.c @@ -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 + * + * $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 + */ + +#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(); +} diff --git a/platform/cooja/sys/cooja_mt.h b/platform/cooja/sys/cooja_mt.h new file mode 100644 index 000000000..177684791 --- /dev/null +++ b/platform/cooja/sys/cooja_mt.h @@ -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 + * + * $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 + */ +#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__ */ diff --git a/platform/cooja/sys/cooja_mtarch.c b/platform/cooja/sys/cooja_mtarch.c new file mode 100644 index 000000000..13eed0bbf --- /dev/null +++ b/platform/cooja/sys/cooja_mtarch.c @@ -0,0 +1,124 @@ +/* + * This file is ripped from x86/mtarch.c of the Contiki Multi-threading library. + * Fredrik Osterlind + */ + +#include +#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; +} +/*--------------------------------------------------------------------------*/ diff --git a/platform/cooja/sys/cooja_mtarch.h b/platform/cooja/sys/cooja_mtarch.h new file mode 100644 index 000000000..5e6cbca93 --- /dev/null +++ b/platform/cooja/sys/cooja_mtarch.h @@ -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 + */ +#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__ */ + diff --git a/tools/cooja/config/code_main_template b/tools/cooja/config/code_main_template index f3ceb8051..30a9c1ab8 100644 --- a/tools/cooja/config/code_main_template +++ b/tools/cooja/config/code_main_template @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * 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 "dev/radio-arch.h" #include "sys/etimer.h" +#include "sys/cooja_mt.h" /* Declare all initialization processes */ [PROCESS_DEFINITIONS] @@ -101,6 +102,26 @@ static struct uip_fw_netif simNetworkIF = */ 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; /*---------------------------------------------------------------------------*/ @@ -134,6 +155,9 @@ Java_se_sics_cooja_corecomm_[CLASS_NAME]_init(JNIEnv *env, jobject obj) /* Start user applications */ 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 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); - -// return (ret); } /*---------------------------------------------------------------------------*/ /** @@ -212,8 +233,9 @@ Java_se_sics_cooja_corecomm_[CLASS_NAME]_tick(JNIEnv *env, jobject obj) simEtimerPending = 0; } - /* Execute the contiki code (save process_run return value for state decisions) */ - simProcessRunValue = process_run(); + /* Let Contiki execute one or a part of the process_run()-function via the thread. + This call stores the process_run() return value */ + cooja_mt_exec(&process_run_thread); /* Let all simulation interfaces act before returning to java */ doActionsAfterTick();