00001 /* 00002 * Copyright (c) 2004, Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * Author: Adam Dunkels <adam@sics.se> 00032 * 00033 * $Id: mt.c,v 1.1 2006/06/17 22:41:20 adamdunkels Exp $ 00034 */ 00035 00036 /** 00037 * \file 00038 * Implementation of the archtecture agnostic parts of the preemptive 00039 * multithreading library for Contiki. 00040 * 00041 * \author 00042 * Adam Dunkels <adam@sics.se> 00043 * 00044 */ 00045 00046 #include "contiki.h" 00047 #include "sys/mt.h" 00048 #include "sys/cc.h" 00049 00050 #define MT_STATE_READY 1 00051 #define MT_STATE_RUNNING 2 00052 #define MT_STATE_WAITING 3 00053 #define MT_STATE_PEEK 4 00054 #define MT_STATE_EXITED 5 00055 00056 static struct mt_thread *current; 00057 00058 /*--------------------------------------------------------------------------*/ 00059 void 00060 mt_init(void) 00061 { 00062 mtarch_init(); 00063 } 00064 /*--------------------------------------------------------------------------*/ 00065 void 00066 mt_remove(void) 00067 { 00068 mtarch_remove(); 00069 } 00070 /*--------------------------------------------------------------------------*/ 00071 void 00072 mt_start(struct mt_thread *thread, void (* function)(void *), void *data) 00073 { 00074 /* Call the architecture dependant function to set up the processor 00075 stack with the correct parameters. */ 00076 mtarch_start(&thread->thread, function, data); 00077 00078 thread->state = MT_STATE_READY; 00079 } 00080 /*--------------------------------------------------------------------------*/ 00081 void 00082 mt_exec(struct mt_thread *thread) 00083 { 00084 if(thread->state == MT_STATE_READY || 00085 thread->state == MT_STATE_PEEK) { 00086 thread->state = MT_STATE_RUNNING; 00087 current = thread; 00088 /* Switch context to the thread. The function call will not return 00089 until the the thread has yielded, or is preempted. */ 00090 /*printf("swtis\n");*/ 00091 mtarch_exec(&thread->thread); 00092 } 00093 } 00094 /*--------------------------------------------------------------------------*/ 00095 void 00096 mt_exit(void) 00097 { 00098 current->state = MT_STATE_EXITED; 00099 current = NULL; 00100 mtarch_yield(); 00101 } 00102 /*--------------------------------------------------------------------------*/ 00103 void 00104 mt_exec_event(struct mt_thread *thread, process_event_t ev, 00105 process_data_t data) 00106 { 00107 if(thread->state == MT_STATE_WAITING || 00108 thread->state == MT_STATE_PEEK) { 00109 *(thread->evptr) = ev; 00110 *(thread->dataptr) = data; 00111 thread->state = MT_STATE_RUNNING; 00112 current = thread; 00113 /* Switch context to the thread. The function call will not return 00114 until the the thread has yielded, or is preempted. */ 00115 mtarch_exec(&thread->thread); 00116 } 00117 } 00118 /*--------------------------------------------------------------------------*/ 00119 void 00120 mt_yield(void) 00121 { 00122 mtarch_pstop(); 00123 current->state = MT_STATE_READY; 00124 current = NULL; 00125 /* This function is called from the running thread, and we call the 00126 switch function in order to switch the thread to the main Contiki 00127 program instead. For us, the switch function will not return 00128 until the next time we are scheduled to run. */ 00129 mtarch_yield(); 00130 00131 } 00132 /*--------------------------------------------------------------------------*/ 00133 void 00134 mt_post(struct process *p, process_event_t ev, 00135 process_data_t data) 00136 { 00137 /* Turn off preemption to ensure mutual exclusion of kernel. */ 00138 mtarch_pstop(); 00139 00140 process_post(p, ev, data); 00141 00142 /* Turn preemption on again. */ 00143 mtarch_pstart(); 00144 } 00145 /*--------------------------------------------------------------------------*/ 00146 void 00147 mt_wait(process_event_t *ev, process_data_t *data) 00148 { 00149 mtarch_pstop(); 00150 current->evptr = ev; 00151 current->dataptr = data; 00152 current->state = MT_STATE_WAITING; 00153 current = NULL; 00154 mtarch_yield(); 00155 } 00156 /*--------------------------------------------------------------------------*/ 00157 void 00158 mt_peek(process_event_t *ev, process_data_t *data) 00159 { 00160 mtarch_pstop(); 00161 *ev = PROCESS_EVENT_NONE; 00162 current->evptr = ev; 00163 current->dataptr = data; 00164 current->state = MT_STATE_PEEK; 00165 current = NULL; 00166 mtarch_yield(); 00167 } 00168 /*--------------------------------------------------------------------------*/ 00169 void 00170 mtp_start(struct mt_process *t, 00171 void (* function)(void *), void *data) 00172 { 00173 mt_start(&t->t, function, data); 00174 process_start(t->p, function); 00175 } 00176 /*--------------------------------------------------------------------------*/ 00177 void 00178 mtp_exit(void) 00179 { 00180 mtarch_pstop(); 00181 mt_exit(); 00182 mt_remove(); 00183 } 00184 /*--------------------------------------------------------------------------*/ 00185 /*void 00186 mtp_eventhandler(ek_event_t ev, ek_data_t data) 00187 { 00188 struct mtp_thread *thread = (struct mtp_thread *)EK_PROC_STATE(EK_CURRENT()); 00189 00190 if(ev == EK_EVENT_REQUEST_EXIT) { 00191 ek_exit(); 00192 LOADER_UNLOAD(); 00193 00194 } else if(ev == EK_EVENT_INIT) { 00195 00196 ek_post(EK_PROC_ID(EK_CURRENT()), EK_EVENT_CONTINUE, NULL); 00197 00198 } else if(ev == EK_EVENT_CONTINUE) { 00199 00200 if(thread->t.state == MT_STATE_READY || 00201 thread->t.state == MT_STATE_PEEK) { 00202 mt_exec(&thread->t); 00203 if(thread->t.state == MT_STATE_EXITED) { 00204 ek_exit(); 00205 LOADER_UNLOAD(); 00206 } else { 00207 ek_post(EK_PROC_ID(EK_CURRENT()), EK_EVENT_CONTINUE, NULL); 00208 } 00209 } 00210 } else { 00211 mt_exec_event(&thread->t, ev, data); 00212 if(thread->t.state == MT_STATE_EXITED) { 00213 ek_exit(); 00214 LOADER_UNLOAD(); 00215 } else if(thread->t.state == MT_STATE_READY || 00216 thread->t.state == MT_STATE_PEEK) { 00217 ek_post(EK_PROC_ID(EK_CURRENT()), EK_EVENT_CONTINUE, NULL); 00218 } 00219 } 00220 }*/ 00221 /*--------------------------------------------------------------------------*/