Added SILC Thread Queue API
[silc.git] / lib / silcutil / os2 / silcos2thread.c
1 /*
2
3   silcos2thread.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2002 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* I used Apache's APR code as a reference here. */
20 /* $Id$ */
21
22 #include "silc.h"
23
24 /* XXX This leaks memory. Perhaps the SilcThread API should be changed
25    since the silc_thread_self() causes that BeOS and OS/2 is hard to
26    do to support this SilcThread API */
27
28 #ifdef SILC_THREADS
29
30 /* Thread structure for OS/2 */
31 typedef struct {
32   unsigned long thread;
33   SilcThreadStart start_func;
34   void *context;
35   SilcBool waitable;
36 } *SilcOs2Thread;
37
38 /* Actual routine that is called by OS/2 when the thread is created.
39    We will call the start_func from here. When this returns the thread
40    is destroyed. */
41
42 static void silc_thread_os2_start(void *context)
43 {
44   SilcOs2Thread thread = (SilcOs2Thread)context;
45   silc_thread_exit((*thread->start_func)(thread->context));
46 }
47
48 #endif
49
50 SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
51                               SilcBool waitable)
52 {
53 #ifdef SILC_THREADS
54   int ret;
55   SilcOs2Thread thread = silc_calloc(1, sizeof(*thread));
56   if (!thread)
57     return NULL;
58
59   thread->start_func = start_func;
60   thread->context = context;
61   thread->waitable = waitable;
62
63   /* Create the thread, and run it */
64   thread->thread = _beginthread(silc_thread_os2_start, NULL, 65536, thread);
65   if (thread->thread < 0) {
66     SILC_LOG_ERROR(("Could not create new thread"));
67     silc_free(thread);
68     return NULL;
69   }
70
71   return (SilcThread)thread->thread;
72 #else
73   /* Call thread callback immediately */
74   (*start_func)(context);
75   return NULL;
76 #endif
77 }
78
79 void silc_thread_exit(void *exit_value)
80 {
81 #ifdef SILC_THREADS
82   _endthread();
83 #endif
84 }
85
86 SilcThread silc_thread_self(void)
87 {
88 #ifdef SILC_THREADS
89   PIB *pib;
90   TIB *tib;
91   DosGetInfoBlocks(&tib, &pib);
92   return (SilcThread)tib->tib_ptib2->tib2_ultid;
93 #else
94   return NULL;
95 #endif
96 }
97
98 SilcBool silc_thread_wait(SilcThread thread, void **exit_value)
99 {
100 #ifdef SILC_THREADS
101
102   if (DosWaitThread((unsigned long)thread, DCWW_WAIT) !=
103       ERROR_INVALID_THREADID) {
104     if (exit_value)
105       *exit_value = NULL;
106     return TRUE;
107   }
108
109   return FALSE;
110 #else
111   return FALSE;
112 #endif
113 }