Contiki 3.x
mtarch.c
1 /*
2  * Copyright (c) 2007, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * Author: Oliver Schmidt <ol.sc@web.de>
32  *
33  */
34 
35 #include "sys/mt.h"
36 
37 #ifndef MTARCH_STACKSIZE
38 #define MTARCH_STACKSIZE 4096
39 #endif /* MTARCH_STACKSIZE */
40 
41 #if defined(_WIN32) || defined(__CYGWIN__)
42 
43 #define WIN32_LEAN_AND_MEAN
44 #include <windows.h>
45 
46 static void *main_fiber;
47 
48 #elif defined(__linux) || defined(__APPLE__)
49 
50 #ifdef __APPLE__
51 /* Avoid deprecated error on Darwin */
52 #define _XOPEN_SOURCE
53 #endif
54 
55 #include <stdlib.h>
56 #include <signal.h>
57 #include <ucontext.h>
58 
59 struct mtarch_t {
60  char stack[MTARCH_STACKSIZE];
61  ucontext_t context;
62 };
63 
64 static ucontext_t main_context;
65 static ucontext_t *running_context;
66 
67 #endif /* _WIN32 || __CYGWIN__ || __linux */
68 
69 /*--------------------------------------------------------------------------*/
70 void
72 {
73 #if defined(_WIN32) || defined(__CYGWIN__)
74 
75  main_fiber = ConvertThreadToFiber(NULL);
76 
77 #endif /* _WIN32 || __CYGWIN__ */
78 }
79 /*--------------------------------------------------------------------------*/
80 void
82 {
83 #if defined(_WIN32) || defined(__CYGWIN__)
84 
85  ConvertFiberToThread();
86 
87 #endif /* _WIN32 || __CYGWIN__ */
88 }
89 /*--------------------------------------------------------------------------*/
90 void
91 mtarch_start(struct mtarch_thread *thread,
92  void (* function)(void *data),
93  void *data)
94 {
95 #if defined(_WIN32) || defined(__CYGWIN__)
96 
97  thread->mt_thread = CreateFiber(0, (LPFIBER_START_ROUTINE)function, data);
98 
99 #elif defined(__linux)
100 
101  thread->mt_thread = malloc(sizeof(struct mtarch_t));
102 
103  getcontext(&((struct mtarch_t *)thread->mt_thread)->context);
104 
105  ((struct mtarch_t *)thread->mt_thread)->context.uc_link = NULL;
106  ((struct mtarch_t *)thread->mt_thread)->context.uc_stack.ss_sp =
107  ((struct mtarch_t *)thread->mt_thread)->stack;
108  ((struct mtarch_t *)thread->mt_thread)->context.uc_stack.ss_size =
109  sizeof(((struct mtarch_t *)thread->mt_thread)->stack);
110 
111  /* Some notes:
112  - If a CPU needs stronger alignment for the stack than malloc()
113  guarantees (like i.e. IA64) then makecontext() is supposed to
114  add that alignment internally.
115  - According to POSIX the arguments to function() are of type int
116  and there are in fact 64-bit implementations which support only
117  32 bits per argument meaning that a pointer argument has to be
118  splitted into two arguments.
119  - Most implementations interpret context.uc_stack.ss_sp on entry
120  as the lowest stack address even if the CPU stack actually grows
121  downwards. Although this means that ss_sp does NOT represent the
122  CPU stack pointer this behaviour makes perfectly sense as it is
123  the only way to stay independent from the CPU architecture. But
124  Solaris prior to release 10 interprets ss_sp as highest stack
125  address thus requiring special handling. */
126  makecontext(&((struct mtarch_t *)thread->mt_thread)->context,
127  (void (*)(void))function, 1, data);
128 
129 #endif /* _WIN32 || __CYGWIN__ || __linux */
130 }
131 /*--------------------------------------------------------------------------*/
132 void
134 {
135 #if defined(_WIN32) || defined(__CYGWIN__)
136 
137  SwitchToFiber(main_fiber);
138 
139 #elif defined(__linux)
140 
141  swapcontext(running_context, &main_context);
142 
143 #endif /* _WIN32 || __CYGWIN__ || __linux */
144 }
145 /*--------------------------------------------------------------------------*/
146 void
147 mtarch_exec(struct mtarch_thread *thread)
148 {
149 #if defined(_WIN32) || defined(__CYGWIN__)
150 
151  SwitchToFiber(thread->mt_thread);
152 
153 #elif defined(__linux)
154 
155  running_context = &((struct mtarch_t *)thread->mt_thread)->context;
156  swapcontext(&main_context, running_context);
157  running_context = NULL;
158 
159 #endif /* _WIN32 || __CYGWIN__ || __linux */
160 }
161 /*--------------------------------------------------------------------------*/
162 void
163 mtarch_stop(struct mtarch_thread *thread)
164 {
165 #if defined(_WIN32) || defined(__CYGWIN__)
166 
167  DeleteFiber(thread->mt_thread);
168 
169 #elif defined(linux) || defined(__linux)
170 
171  free(thread->mt_thread);
172 
173 #endif /* _WIN32 || __CYGWIN__ || __linux */
174 }
175 /*--------------------------------------------------------------------------*/
176 void
177 mtarch_pstart(void)
178 {
179 }
180 /*--------------------------------------------------------------------------*/
181 void
182 mtarch_pstop(void)
183 {
184 }
185 /*--------------------------------------------------------------------------*/
void mtarch_init(void)
Initialize the architecture specific support functions for the multi-thread library.
Definition: mtarch.c:49
void mtarch_yield(void)
Yield the processor.
Definition: mtarch.c:89
Header file for the preemptive multitasking library for Contiki.
void mtarch_remove(void)
Uninstall library and clean up.
Definition: mtarch.c:54
void mtarch_start(struct mtarch_thread *thread, void(*function)(void *data), void *data)
Setup the stack frame for a thread that is being started.
Definition: mtarch.c:59
#define NULL
The null pointer.
void mtarch_exec(struct mtarch_thread *thread)
Start executing a thread.
Definition: mtarch.c:95
void mtarch_stop(struct mtarch_thread *thread)
Clean up the stack of a thread.
Definition: mtarch.c:110
Copyright (c) 2014, Analog Devices, Inc.
Definition: mtarch.h:42