Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2007, 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: Oliver Schmidt <ol.sc@web.de> 00032 * 00033 * $Id: mtarch.c,v 1.2 2007/04/03 18:37:15 oliverschmidt Exp $ 00034 */ 00035 00036 #if defined(_WIN32) || defined(__CYGWIN__) 00037 00038 #define WIN32_LEAN_AND_MEAN 00039 #include <windows.h> 00040 00041 static void *main_fiber; 00042 00043 #elif defined(__linux) || defined(__APPLE__) 00044 00045 #ifdef __APPLE__ 00046 /* Avoid deprecated error on Darwin */ 00047 #define _XOPEN_SOURCE 00048 #endif 00049 00050 #include <stdlib.h> 00051 #include <signal.h> 00052 #include <ucontext.h> 00053 00054 struct mtarch_t { 00055 char stack[4096]; 00056 ucontext_t context; 00057 }; 00058 00059 static ucontext_t main_context; 00060 static ucontext_t *running_context; 00061 00062 #endif /* _WIN32 || __CYGWIN__ || __linux */ 00063 00064 #include "mtarch.h" 00065 00066 /*--------------------------------------------------------------------------*/ 00067 void 00068 mtarch_init(void) 00069 { 00070 #if defined(_WIN32) || defined(__CYGWIN__) 00071 00072 main_fiber = ConvertThreadToFiber(NULL); 00073 00074 #endif /* _WIN32 || __CYGWIN__ */ 00075 } 00076 /*--------------------------------------------------------------------------*/ 00077 void 00078 mtarch_remove(void) 00079 { 00080 #if defined(_WIN32) || defined(__CYGWIN__) 00081 00082 ConvertFiberToThread(); 00083 00084 #endif /* _WIN32 || __CYGWIN__ */ 00085 } 00086 /*--------------------------------------------------------------------------*/ 00087 void 00088 mtarch_start(struct mtarch_thread *thread, 00089 void (* function)(void *data), 00090 void *data) 00091 { 00092 #if defined(_WIN32) || defined(__CYGWIN__) 00093 00094 thread->mt_thread = CreateFiber(0, (LPFIBER_START_ROUTINE)function, data); 00095 00096 #elif defined(__linux) 00097 00098 thread->mt_thread = malloc(sizeof(struct mtarch_t)); 00099 00100 getcontext(&((struct mtarch_t *)thread->mt_thread)->context); 00101 00102 ((struct mtarch_t *)thread->mt_thread)->context.uc_link = NULL; 00103 ((struct mtarch_t *)thread->mt_thread)->context.uc_stack.ss_sp = 00104 ((struct mtarch_t *)thread->mt_thread)->stack; 00105 ((struct mtarch_t *)thread->mt_thread)->context.uc_stack.ss_size = 00106 sizeof(((struct mtarch_t *)thread->mt_thread)->stack); 00107 00108 /* Some notes: 00109 - If a CPU needs stronger alignment for the stack than malloc() 00110 guarantees (like i.e. IA64) then makecontext() is supposed to 00111 add that alignment internally. 00112 - According to POSIX the arguments to function() are of type int 00113 and there are in fact 64-bit implementations which support only 00114 32 bits per argument meaning that a pointer argument has to be 00115 splitted into two arguments. 00116 - Most implementations interpret context.uc_stack.ss_sp on entry 00117 as the lowest stack address even if the CPU stack actually grows 00118 downwards. Although this means that ss_sp does NOT represent the 00119 CPU stack pointer this behaviour makes perfectly sense as it is 00120 the only way to stay independent from the CPU architecture. But 00121 Solaris prior to release 10 interprets ss_sp as highest stack 00122 address thus requiring special handling. */ 00123 makecontext(&((struct mtarch_t *)thread->mt_thread)->context, 00124 (void (*)(void))function, 1, data); 00125 00126 #endif /* _WIN32 || __CYGWIN__ || __linux */ 00127 } 00128 /*--------------------------------------------------------------------------*/ 00129 void 00130 mtarch_yield(void) 00131 { 00132 #if defined(_WIN32) || defined(__CYGWIN__) 00133 00134 SwitchToFiber(main_fiber); 00135 00136 #elif defined(__linux) 00137 00138 swapcontext(running_context, &main_context); 00139 00140 #endif /* _WIN32 || __CYGWIN__ || __linux */ 00141 } 00142 /*--------------------------------------------------------------------------*/ 00143 void 00144 mtarch_exec(struct mtarch_thread *thread) 00145 { 00146 #if defined(_WIN32) || defined(__CYGWIN__) 00147 00148 SwitchToFiber(thread->mt_thread); 00149 00150 #elif defined(__linux) 00151 00152 running_context = &((struct mtarch_t *)thread->mt_thread)->context; 00153 swapcontext(&main_context, running_context); 00154 running_context = NULL; 00155 00156 #endif /* _WIN32 || __CYGWIN__ || __linux */ 00157 } 00158 /*--------------------------------------------------------------------------*/ 00159 void 00160 mtarch_stop(struct mtarch_thread *thread) 00161 { 00162 #if defined(_WIN32) || defined(__CYGWIN__) 00163 00164 DeleteFiber(thread->mt_thread); 00165 00166 #elif defined(linux) || defined(__linux) 00167 00168 free(thread->mt_thread); 00169 00170 #endif /* _WIN32 || __CYGWIN__ || __linux */ 00171 } 00172 /*--------------------------------------------------------------------------*/ 00173 void 00174 mtarch_pstart(void) 00175 { 00176 } 00177 /*--------------------------------------------------------------------------*/ 00178 void 00179 mtarch_pstop(void) 00180 { 00181 } 00182 /*--------------------------------------------------------------------------*/