/[lwip]/contrib/ports/win32/sys_arch.c
ViewVC logotype

Contents of /contrib/ports/win32/sys_arch.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (show annotations) (download)
Fri Jun 27 18:38:27 2008 UTC (15 years, 5 months ago) by goldsimon
Branch: MAIN
Changes since 1.7: +7 -7 lines
File MIME type: text/plain
Added new stats-defines for sys.

1 /*
2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25 * OF SUCH DAMAGE.
26 *
27 * This file is part of the lwIP TCP/IP stack.
28 *
29 * Author: Adam Dunkels <adam@sics.se>
30 * Simon Goldschmidt
31 *
32 */
33
34 #include <stdlib.h>
35 #include <stdio.h> /* sprintf() for task names */
36
37 #include <windows.h>
38 #include <time.h>
39
40 #include <lwip/opt.h>
41 #include <lwip/stats.h>
42 #include <lwip/debug.h>
43 #include <lwip/sys.h>
44
45 /* These functions are used from NO_SYS also, for precise timer triggering */
46 LARGE_INTEGER freq, sys_start_time;
47
48 void sys_init_timing()
49 {
50 QueryPerformanceFrequency(&freq);
51 QueryPerformanceCounter(&sys_start_time);
52 }
53
54 static LONGLONG sys_get_ms_longlong()
55 {
56 LONGLONG ret;
57 LARGE_INTEGER now;
58 QueryPerformanceCounter(&now);
59 ret = now.QuadPart-sys_start_time.QuadPart;
60 return (u32_t)(((ret)*1000)/freq.QuadPart);
61 }
62
63 u32_t sys_now()
64 {
65 return sys_get_ms_longlong();
66 }
67
68 #if !NO_SYS
69
70 #define MAX_QUEUE_ENTRIES 100
71
72 struct threadlist {
73 struct sys_timeouts timeouts;
74 DWORD id;
75 struct threadlist *next;
76 };
77
78 struct lwip_mbox {
79 HANDLE sem;
80 void* q_mem[MAX_QUEUE_ENTRIES];
81 u32_t head, tail;
82 };
83
84 struct threadlist *lwip_win32_threads = NULL;
85 CRITICAL_SECTION critSec;
86
87 void InitSysArchProtect()
88 {
89 InitializeCriticalSection(&critSec);
90 }
91 u32_t sys_arch_protect()
92 {
93 EnterCriticalSection(&critSec);
94 return 0;
95 }
96 void sys_arch_unprotect(u32_t pval)
97 {
98 LWIP_UNUSED_ARG(pval);
99 LeaveCriticalSection(&critSec);
100 }
101 void do_sleep(int ms)
102 {
103 Sleep(ms);
104 }
105
106 void sys_init(void)
107 {
108 sys_init_timing();
109 InitSysArchProtect();
110 }
111
112 sys_sem_t sys_sem_new(u8_t count)
113 {
114 HANDLE new_sem = NULL;
115 new_sem = CreateSemaphore(0, count, 100000, 0);
116 LWIP_ASSERT("Error creating semaphore", new_sem != NULL);
117 if(new_sem != NULL) {
118 #if LWIP_STATS
119 SYS_STATS_INC(sem.used);
120 LWIP_ASSERT("sys_sem_new() counter overflow", lwip_stats.sys.sem.used != 0 );
121 if (lwip_stats.sys.sem.used > lwip_stats.sys.sem.max) {
122 lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
123 }
124 #endif /* LWIP_STATS */
125 return new_sem;
126 }
127
128 /* failed to allocate memory... */
129 #if LWIP_STATS
130 SYS_STATS_INC(sem.err);
131 #endif /* LWIP_STATS */
132 return SYS_SEM_NULL;
133 }
134
135 void sys_sem_free(sys_sem_t sem)
136 {
137 /* parameter check */
138 LWIP_ASSERT("sem != NULL", sem != NULL);
139 LWIP_ASSERT("sem != INVALID_HANDLE_VALUE", sem != INVALID_HANDLE_VALUE);
140 CloseHandle(sem);
141
142 #if LWIP_STATS
143 SYS_STATS_DEC(sem.used);
144 LWIP_ASSERT("sys_sem_free() closed more than created", lwip_stats.sys.sem.used != (u16_t)-1);
145 #endif /* LWIP_STATS */
146 }
147
148 u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
149 {
150 DWORD ret;
151 LONGLONG starttime, endtime;
152 LWIP_ASSERT("sem != NULL", sem != NULL);
153 LWIP_ASSERT("sem != INVALID_HANDLE_VALUE", sem != INVALID_HANDLE_VALUE);
154 if(!timeout)
155 {
156 /* wait infinite */
157 starttime = sys_get_ms_longlong();
158 ret = WaitForSingleObject(sem, INFINITE);
159 LWIP_ASSERT("Error waiting for mutex", ret == WAIT_OBJECT_0);
160 endtime = sys_get_ms_longlong();
161 /* return the time we waited for the sem */
162 return (u32_t)(endtime - starttime);
163 }
164 else
165 {
166 int ret;
167 starttime = sys_get_ms_longlong();
168 ret = WaitForSingleObject(sem, timeout);
169 LWIP_ASSERT("Error waiting for mutex", (ret == WAIT_OBJECT_0) || (ret == WAIT_TIMEOUT));
170 if(ret == WAIT_OBJECT_0)
171 {
172 endtime = sys_get_ms_longlong();
173 /* return the time we waited for the sem */
174 return (u32_t)(endtime - starttime);
175 }
176 else
177 {
178 /* timeout */
179 return SYS_ARCH_TIMEOUT;
180 }
181 }
182 }
183
184 void sys_sem_signal(sys_sem_t sem)
185 {
186 DWORD ret;
187 LWIP_ASSERT("sem != NULL", sem != NULL);
188 LWIP_ASSERT("sem != INVALID_HANDLE_VALUE", sem != INVALID_HANDLE_VALUE);
189 ret = ReleaseSemaphore(sem, 1, NULL);
190 LWIP_ASSERT("Error releasing mutex", ret != 0);
191 }
192
193 struct sys_timeouts *sys_arch_timeouts(void)
194 {
195 struct sys_timeouts *ret = NULL;
196 struct threadlist *t, *new_thread;
197 DWORD threadID;
198 SYS_ARCH_DECL_PROTECT(lev);
199
200 threadID = GetCurrentThreadId();
201 SYS_ARCH_PROTECT(lev);
202 for(t = lwip_win32_threads; t != NULL; t = t->next)
203 {
204 if(t->id == threadID)
205 {
206 ret = &(t->timeouts);
207 SYS_ARCH_UNPROTECT(lev);
208 return ret;
209 }
210 }
211 new_thread = (struct threadlist*)malloc(sizeof(struct threadlist));
212 LWIP_ASSERT("new_thread != NULL", new_thread != NULL);
213 if(new_thread != NULL) {
214 OutputDebugString("First call to sys_arch_timeouts for thread");
215 new_thread->next = lwip_win32_threads;
216 lwip_win32_threads = new_thread;
217 new_thread->id = threadID;
218 new_thread->timeouts.next = NULL;
219 ret = &(new_thread->timeouts);
220 SYS_ARCH_UNPROTECT(lev);
221 return ret;
222 }
223 SYS_ARCH_UNPROTECT(lev);
224 LWIP_ASSERT("should not come here", 0);
225 return 0;
226 }
227
228 sys_thread_t sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
229 {
230 struct threadlist *new_thread;
231 HANDLE h;
232 SYS_ARCH_DECL_PROTECT(lev);
233
234 LWIP_UNUSED_ARG(name);
235 LWIP_UNUSED_ARG(stacksize);
236 LWIP_UNUSED_ARG(prio);
237
238 new_thread = (struct threadlist*)malloc(sizeof(struct threadlist));
239 LWIP_ASSERT("new_thread != NULL", new_thread != NULL);
240 if(new_thread != NULL) {
241 SYS_ARCH_PROTECT(lev);
242 new_thread->next = lwip_win32_threads;
243 lwip_win32_threads = new_thread;
244 new_thread->timeouts.next = NULL;
245
246 h = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)function, arg, 0, &(new_thread->id));
247 LWIP_ASSERT("h != 0", h != 0);
248 LWIP_ASSERT("h != -1", h != INVALID_HANDLE_VALUE);
249
250 SYS_ARCH_UNPROTECT(lev);
251 return new_thread->id;
252 }
253 return 0;
254 }
255
256 sys_mbox_t sys_mbox_new(int size)
257 {
258 struct lwip_mbox *new_mbox;
259
260 LWIP_UNUSED_ARG(size);
261
262 new_mbox = (struct lwip_mbox*)malloc(sizeof(struct lwip_mbox));
263 LWIP_ASSERT("new_mbox != NULL", new_mbox != NULL);
264 if(new_mbox == NULL) {
265 #if LWIP_STATS
266 SYS_STATS_INC(mbox.err);
267 #endif /* LWIP_STATS */
268 return SYS_SEM_NULL;
269 }
270 new_mbox->sem = CreateSemaphore(0, 0, MAX_QUEUE_ENTRIES, 0);
271 LWIP_ASSERT("Error creating semaphore", new_mbox->sem != NULL);
272 if(new_mbox->sem == NULL) {
273 #if LWIP_STATS
274 SYS_STATS_INC(mbox.err);
275 #endif /* LWIP_STATS */
276 free(new_mbox);
277 new_mbox = NULL;
278 return SYS_SEM_NULL;
279 }
280 memset(&new_mbox->q_mem, 0, sizeof(u32_t)*MAX_QUEUE_ENTRIES);
281 new_mbox->head = 0;
282 new_mbox->tail = 0;
283 #if LWIP_STATS
284 SYS_STATS_INC(mbox.used);
285 LWIP_ASSERT("sys_mbox_new() counter overflow", lwip_stats.sys.mbox.used != 0 );
286 if (lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max) {
287 lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
288 }
289 #endif /* LWIP_STATS */
290 return new_mbox;
291 }
292
293 void sys_mbox_free(sys_mbox_t mbox)
294 {
295 /* parameter check */
296 LWIP_ASSERT("sys_mbox_free ", mbox != SYS_MBOX_NULL );
297 LWIP_ASSERT("mbox->sem != NULL", mbox->sem != NULL);
298 LWIP_ASSERT("mbox->sem != INVALID_HANDLE_VALUE", mbox->sem != INVALID_HANDLE_VALUE);
299
300 CloseHandle(mbox->sem);
301 free(mbox);
302
303 #if LWIP_STATS
304 SYS_STATS_DEC(mbox.used);
305 LWIP_ASSERT( "sys_mbox_free() ", lwip_stats.sys.mbox.used!= (u16_t)-1 );
306 #endif /* LWIP_STATS */
307 }
308
309 void sys_mbox_post(sys_mbox_t q, void *msg)
310 {
311 DWORD ret;
312 SYS_ARCH_DECL_PROTECT(lev);
313
314 /* parameter check */
315 LWIP_ASSERT("sys_mbox_free ", q != SYS_MBOX_NULL );
316 LWIP_ASSERT("q->sem != NULL", q->sem != NULL);
317 LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE);
318
319 SYS_ARCH_PROTECT(lev);
320 q->q_mem[q->head] = msg;
321 (q->head)++;
322 if (q->head >= MAX_QUEUE_ENTRIES) {
323 q->head = 0;
324 }
325 LWIP_ASSERT("mbox is full!", q->head != q->tail);
326 ret = ReleaseSemaphore(q->sem, 1, 0);
327 LWIP_ASSERT("Error releasing sem", ret != 0);
328
329 SYS_ARCH_UNPROTECT(lev);
330 }
331
332 err_t sys_mbox_trypost(sys_mbox_t q, void *msg)
333 {
334 u32_t new_head;
335 DWORD ret;
336 SYS_ARCH_DECL_PROTECT(lev);
337
338 /* parameter check */
339 LWIP_ASSERT("sys_mbox_free ", q != SYS_MBOX_NULL );
340 LWIP_ASSERT("q->sem != NULL", q->sem != NULL);
341 LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE);
342
343 SYS_ARCH_PROTECT(lev);
344
345 new_head = q->head + 1;
346 if (new_head >= MAX_QUEUE_ENTRIES) {
347 new_head = 0;
348 }
349 if (new_head == q->tail) {
350 SYS_ARCH_UNPROTECT(lev);
351 return ERR_MEM;
352 }
353
354 q->q_mem[q->head] = msg;
355 q->head = new_head;
356 LWIP_ASSERT("mbox is full!", q->head != q->tail);
357 ret = ReleaseSemaphore(q->sem, 1, 0);
358 LWIP_ASSERT("Error releasing sem", ret != 0);
359
360 SYS_ARCH_UNPROTECT(lev);
361 return ERR_OK;
362 }
363
364 u32_t sys_arch_mbox_fetch(sys_mbox_t q, void **msg, u32_t timeout)
365 {
366 DWORD ret;
367 LONGLONG starttime, endtime;
368 SYS_ARCH_DECL_PROTECT(lev);
369
370 /* parameter check */
371 LWIP_ASSERT("sys_mbox_free ", q != SYS_MBOX_NULL );
372 LWIP_ASSERT("q->sem != NULL", q->sem != NULL);
373 LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE);
374
375 if (timeout == 0) {
376 timeout = INFINITE;
377 }
378 starttime = sys_get_ms_longlong();
379 if ((ret = WaitForSingleObject(q->sem, timeout)) == WAIT_OBJECT_0) {
380 SYS_ARCH_PROTECT(lev);
381 if(msg != NULL) {
382 *msg = q->q_mem[q->tail];
383 }
384
385 (q->tail)++;
386 if (q->tail >= MAX_QUEUE_ENTRIES) {
387 q->tail = 0;
388 }
389 SYS_ARCH_UNPROTECT(lev);
390 endtime = sys_get_ms_longlong();
391 return (u32_t)(endtime - starttime);
392 }
393 else
394 {
395 LWIP_ASSERT("Error waiting for sem", ret == WAIT_TIMEOUT);
396 if(msg != NULL) {
397 *msg = NULL;
398 }
399
400 return SYS_ARCH_TIMEOUT;
401 }
402 }
403
404 u32_t sys_arch_mbox_tryfetch(sys_mbox_t q, void **msg)
405 {
406 DWORD ret;
407 SYS_ARCH_DECL_PROTECT(lev);
408
409 /* parameter check */
410 LWIP_ASSERT("sys_mbox_free ", q != SYS_MBOX_NULL );
411 LWIP_ASSERT("q->sem != NULL", q->sem != NULL);
412 LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE);
413
414 if ((ret = WaitForSingleObject(q->sem, 0)) == WAIT_OBJECT_0) {
415 SYS_ARCH_PROTECT(lev);
416 if(msg != NULL) {
417 *msg = q->q_mem[q->tail];
418 }
419
420 (q->tail)++;
421 if (q->tail >= MAX_QUEUE_ENTRIES) {
422 q->tail = 0;
423 }
424 SYS_ARCH_UNPROTECT(lev);
425 return 0;
426 }
427 else
428 {
429 LWIP_ASSERT("Error waiting for sem", ret == WAIT_TIMEOUT);
430 if(msg != NULL) {
431 *msg = NULL;
432 }
433
434 return SYS_ARCH_TIMEOUT;
435 }
436 }
437 #endif /* !NO_SYS */

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26