mtarch.c

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

Generated on Mon Apr 11 14:23:34 2011 for Contiki 2.5 by  doxygen 1.6.1