~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to erts/emulator/sys/win32/sys_threads.c

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* ``The contents of this file are subject to the Erlang Public License,
2
 
 * Version 1.1, (the "License"); you may not use this file except in
3
 
 * compliance with the License. You should have received a copy of the
4
 
 * Erlang Public License along with this software. If not, it can be
5
 
 * retrieved via the world wide web at http://www.erlang.org/.
6
 
 * 
7
 
 * Software distributed under the License is distributed on an "AS IS"
8
 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
 
 * the License for the specific language governing rights and limitations
10
 
 * under the License.
11
 
 * 
12
 
 * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
 
 * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
 
 * AB. All Rights Reserved.''
15
 
 * 
16
 
 *     $Id$
17
 
 *
18
 
 */
19
 
 
20
 
#include <windows.h>
21
 
#include <process.h>
22
 
 
23
 
#ifdef HAVE_CONFIG_H
24
 
#  include "config.h"
25
 
#endif
26
 
#include <stdio.h>
27
 
#include <stdlib.h>
28
 
#include <string.h>
29
 
 
30
 
#include "sys.h"
31
 
#include "erl_alloc.h"
32
 
#include "erl_driver.h"
33
 
#define ERL_THREADS_EMU_INTERNAL__
34
 
#include "erl_threads.h"
35
 
 
36
 
static DWORD tl_wait_ix;
37
 
typedef struct _erts_wait_t {
38
 
    HANDLE event;
39
 
    struct _erts_wait_t *next;
40
 
    struct _erts_wait_t *prev;
41
 
    int in_list;
42
 
} _erts_wait_t;
43
 
 
44
 
typedef struct _erts_cond_t {
45
 
    CRITICAL_SECTION cs;
46
 
    struct _erts_wait_t *waiters;
47
 
} _erts_cond_t;
48
 
 
49
 
static _erts_wait_t main_thread_wait;
50
 
 
51
 
static CRITICAL_SECTION sys_mutex[ERTS_MAX_SYS_MUTEX];
52
 
 
53
 
erts_mutex_t erts_mutex_create()
54
 
{
55
 
    CRITICAL_SECTION* mp = (CRITICAL_SECTION*)
56
 
        erts_alloc_fnf(ERTS_ALC_T_MUTEX, sizeof(CRITICAL_SECTION));
57
 
    if (mp != NULL)
58
 
        InitializeCriticalSection(mp);
59
 
    return (erts_mutex_t) mp;
60
 
}
61
 
 
62
 
erts_mutex_t erts_mutex_sys(int mno)
63
 
{   
64
 
    CRITICAL_SECTION* mp; 
65
 
    if (mno >= ERTS_MAX_SYS_MUTEX || mno < 0)
66
 
        return NULL;
67
 
    mp = &sys_mutex[mno];
68
 
    InitializeCriticalSection(mp);
69
 
    return (erts_mutex_t) mp;
70
 
 
71
 
}
72
 
 
73
 
int erts_atfork_sys(void (*prepare)(void),
74
 
                    void (*parent)(void),
75
 
                    void (*child)(void))
76
 
{
77
 
    return 0;
78
 
}
79
 
 
80
 
int erts_mutex_set_default_atfork(erts_mutex_t mtx)
81
 
{
82
 
    return 0;
83
 
}
84
 
 
85
 
int erts_mutex_unset_default_atfork(erts_mutex_t mtx)
86
 
{
87
 
    return 0;
88
 
}
89
 
 
90
 
int erts_mutex_destroy(erts_mutex_t mtx)
91
 
{
92
 
    if (mtx != NULL) {
93
 
        DeleteCriticalSection((CRITICAL_SECTION*)mtx);
94
 
        erts_free(ERTS_ALC_T_MUTEX, mtx);
95
 
        return 0;
96
 
    }
97
 
    return -1;
98
 
}
99
 
 
100
 
int erts_mutex_lock (erts_mutex_t mtx)
101
 
{
102
 
    EnterCriticalSection((CRITICAL_SECTION*) mtx);
103
 
    return 0;
104
 
}
105
 
 
106
 
int erts_mutex_unlock (erts_mutex_t mtx)
107
 
{
108
 
    LeaveCriticalSection((CRITICAL_SECTION*) mtx);
109
 
    return 0;
110
 
}
111
 
 
112
 
erts_cond_t erts_cond_create()
113
 
{
114
 
    _erts_cond_t* cvp = (_erts_cond_t*)
115
 
        erts_alloc_fnf(ERTS_ALC_T_COND_VAR, sizeof(_erts_cond_t));
116
 
    InitializeCriticalSection(&cvp->cs);
117
 
    cvp->waiters = NULL;
118
 
    return (erts_cond_t) cvp;
119
 
}
120
 
 
121
 
int erts_cond_destroy(erts_cond_t cv)
122
 
{
123
 
    _erts_cond_t* cvp = (_erts_cond_t*) cv;
124
 
    if (cvp != NULL) {
125
 
        DeleteCriticalSection(&cvp->cs);
126
 
        erts_free(ERTS_ALC_T_COND_VAR, cvp);
127
 
        return 0;
128
 
    }
129
 
    return -1;
130
 
}
131
 
 
132
 
int erts_cond_signal(erts_cond_t cv)
133
 
{
134
 
    _erts_cond_t* cvp = (_erts_cond_t*) cv;
135
 
    EnterCriticalSection(&cvp->cs);
136
 
    if (cvp->waiters) {
137
 
        SetEvent(cvp->waiters->event);
138
 
        cvp->waiters->in_list = 0;
139
 
        cvp->waiters = cvp->waiters->next;
140
 
        if (cvp->waiters)
141
 
            cvp->waiters->prev = NULL;
142
 
    }
143
 
    LeaveCriticalSection(&cvp->cs);
144
 
    return 0;
145
 
}
146
 
 
147
 
int erts_cond_broadcast (erts_cond_t cv)
148
 
{
149
 
    struct _erts_wait_t *wp;
150
 
    _erts_cond_t* cvp = (_erts_cond_t*) cv;
151
 
 
152
 
    /* signal every event in waiting queue */
153
 
    EnterCriticalSection(&cvp->cs);
154
 
    for (wp = cvp->waiters; wp; wp = wp->next) {
155
 
        wp->in_list = 0;
156
 
        SetEvent(wp->event);
157
 
    }
158
 
    cvp->waiters = NULL;
159
 
    LeaveCriticalSection(&cvp->cs);
160
 
    return 0;
161
 
}
162
 
 
163
 
int erts_cond_wait(erts_cond_t cv, erts_mutex_t mtx)
164
 
{
165
 
    return erts_cond_timedwait(cv, mtx, INFINITE);
166
 
}
167
 
 
168
 
int erts_cond_timedwait(erts_cond_t cv, erts_mutex_t mtx, long time)
169
 
{
170
 
    _erts_cond_t* cvp = (_erts_cond_t*) cv;
171
 
    _erts_wait_t *wp;
172
 
    DWORD code;
173
 
 
174
 
    EnterCriticalSection(&cvp->cs);
175
 
 
176
 
    wp = (_erts_wait_t *) TlsGetValue(tl_wait_ix);
177
 
    ASSERT(wp);
178
 
 
179
 
    wp->prev = NULL;
180
 
    wp->next = cvp->waiters;
181
 
    if (wp->next)
182
 
        wp->next->prev = wp;
183
 
    wp->in_list = 1;
184
 
    cvp->waiters = wp;
185
 
    LeaveCriticalSection(&cvp->cs);
186
 
 
187
 
    /* wait for event to signal */
188
 
    LeaveCriticalSection((CRITICAL_SECTION*) mtx);
189
 
    code = WaitForSingleObject(wp->event, time);
190
 
    EnterCriticalSection((CRITICAL_SECTION*)mtx);
191
 
 
192
 
    if (code != WAIT_OBJECT_0) {
193
 
        EnterCriticalSection(&cvp->cs);
194
 
        if (wp->in_list) {
195
 
            /* remove from wait list */
196
 
            if (wp->prev)
197
 
                wp->prev->next = wp->next;
198
 
            else
199
 
                cvp->waiters = wp->next;
200
 
            if (wp->next)
201
 
                wp->next->prev = wp->prev;
202
 
            wp->in_list = 0;
203
 
        }
204
 
        LeaveCriticalSection(&cvp->cs);
205
 
    }
206
 
    /* else: we was removed from the list by a signal or broadcast */
207
 
 
208
 
    /* resume processing */
209
 
    return code != WAIT_OBJECT_0;
210
 
}
211
 
 
212
 
typedef struct {
213
 
    void* arg;
214
 
    void* (*func)(void*);
215
 
    _erts_wait_t *pwait;
216
 
    int res;
217
 
} thread_data__;
218
 
 
219
 
static unsigned thread_wrapper(void* args)
220
 
{
221
 
    void* (*func)(void*);
222
 
    void *arg;
223
 
    _erts_wait_t wait;
224
 
    _erts_wait_t *pwait;
225
 
 
226
 
    func  = ((thread_data__ *) args)->func;
227
 
    arg   = ((thread_data__ *) args)->arg;
228
 
    pwait = ((thread_data__ *) args)->pwait;
229
 
 
230
 
    wait.event = CreateEvent(NULL, FALSE, FALSE, NULL);
231
 
    wait.in_list = 0;
232
 
    if (!wait.event || !TlsSetValue(tl_wait_ix, (LPVOID) &wait)) {
233
 
        if (wait.event)
234
 
            CloseHandle(wait.event);
235
 
        ((thread_data__ *) args)->res = -1;
236
 
        SetEvent(pwait->event);
237
 
        _endthreadex((unsigned) 1);
238
 
        return (unsigned) 1;
239
 
    }
240
 
 
241
 
    ASSERT(&wait == (_erts_wait_t *) TlsGetValue(tl_wait_ix));
242
 
    ((thread_data__ *) args)->res = 0;
243
 
    SetEvent(pwait->event);
244
 
 
245
 
    (void) /* FIXME: Implement propagation of threads result */
246
 
        (*func)(arg);
247
 
 
248
 
    CloseHandle(wait.event);
249
 
    _endthreadex(0);
250
 
 
251
 
    return 0;
252
 
}
253
 
 
254
 
 
255
 
int erts_thread_create(erts_thread_t* tpp, 
256
 
                      void* (*func)(void*),
257
 
                      void* arg,
258
 
                      int detached)
259
 
{
260
 
    thread_data__ td;
261
 
    HANDLE h;
262
 
    DWORD code;
263
 
    DWORD ID;
264
 
 
265
 
    td.func = func;
266
 
    td.arg = arg;
267
 
    td.res = -1;
268
 
    td.pwait = (_erts_wait_t *) TlsGetValue(tl_wait_ix);
269
 
    ASSERT(td.pwait);
270
 
 
271
 
    h = (HANDLE) _beginthreadex(NULL,
272
 
                                0,
273
 
                                (LPTHREAD_START_ROUTINE) thread_wrapper, 
274
 
                                (LPVOID) &td,
275
 
                                0,
276
 
                                &ID);
277
 
    if (h == INVALID_HANDLE_VALUE)
278
 
        return -1;
279
 
    code = WaitForSingleObject(td.pwait->event, INFINITE);
280
 
    if (detached)
281
 
        CloseHandle(h);
282
 
    *tpp = (erts_thread_t)h;
283
 
    if (code != WAIT_OBJECT_0) {
284
 
        ASSERT(0);
285
 
        return -1;
286
 
    }
287
 
    return td.res;
288
 
}
289
 
 
290
 
erts_thread_t erts_thread_self()
291
 
{
292
 
    return GetCurrentThread();
293
 
}
294
 
 
295
 
void erts_thread_exit(void* val)
296
 
{
297
 
    _erts_wait_t *wp = (_erts_wait_t *) TlsGetValue(tl_wait_ix);
298
 
    CloseHandle(wp->event);
299
 
    /* FIXME: Implement propagation of threads result */
300
 
    _endthreadex(0);
301
 
}
302
 
 
303
 
int erts_thread_join(erts_thread_t tp, void** vp)
304
 
{
305
 
    /* FIXME: Implement propagation of threads result */
306
 
    DWORD code;
307
 
    code = WaitForSingleObject((HANDLE)tp, INFINITE); /* FIX ERRORS */
308
 
    CloseHandle(tp);
309
 
    return code != WAIT_OBJECT_0;
310
 
}
311
 
 
312
 
int erts_thread_kill(erts_thread_t tp)
313
 
{
314
 
    return -1;
315
 
}
316
 
 
317
 
void __noreturn erl_exit(int n, char*, ...);
318
 
 
319
 
void
320
 
erts_sys_threads_init(void)
321
 
{
322
 
    /* NOTE: erts_sys_threads_init() is called before allocators are
323
 
     * initialized; therefore, it's not allowed to call erts_alloc()
324
 
     * (and friends) from here.
325
 
     */
326
 
 
327
 
    tl_wait_ix = TlsAlloc();
328
 
    if (tl_wait_ix == -1)
329
 
        erl_exit(1, "Failed to allocate thread local wait index\n");
330
 
    if (!TlsSetValue(tl_wait_ix, (LPVOID) &main_thread_wait))
331
 
        erl_exit(1, "Failed to set main thread wait object\n");
332
 
    main_thread_wait.event = CreateEvent(NULL, FALSE, FALSE, NULL);
333
 
    main_thread_wait.in_list = 0;
334
 
    if (!main_thread_wait.event)
335
 
        erl_exit(1, "Failed to create main thread wait event\n");
336
 
 
337
 
    ASSERT(&main_thread_wait == (_erts_wait_t *) TlsGetValue(tl_wait_ix));
338
 
}
339