Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gp_wsync.c,v 1.4 2002/02/21 22:24:52 giles Exp $ */
18
/* MS Windows (Win32) thread / semaphore / monitor implementation */
19
/* original multi-threading code by John Desrosiers */
20
#include "malloc_.h"
21
#include "gserror.h"
22
#include "gserrors.h"
23
#include "gpsync.h"
24
#include "windows_.h"
25
#include <process.h>
26
 
27
/* ------- Synchronization primitives -------- */
28
 
29
/* Semaphore supports wait/signal semantics */
30
 
31
typedef struct win32_semaphore_s {
32
    HANDLE handle;		/* returned from CreateSemaphore */
33
} win32_semaphore;
34
 
35
uint
36
gp_semaphore_sizeof(void)
37
{
38
    return sizeof(win32_semaphore);
39
}
40
 
41
int	/* if sema <> 0 rets -ve error, 0 ok; if sema == 0, 0 movable, 1 fixed */
42
gp_semaphore_open(
43
		  gp_semaphore * sema	/* create semaphore here */
44
)
45
{
46
    win32_semaphore *const winSema = (win32_semaphore *)sema;
47
 
48
    if (winSema) {
49
	winSema->handle = CreateSemaphore(NULL, 0, max_int, NULL);
50
	return
51
	    (winSema->handle != NULL ? 0 :
52
	     gs_note_error(gs_error_unknownerror));
53
    } else
54
	return 0;		/* Win32 semaphores handles may be moved */
55
}
56
 
57
int
58
gp_semaphore_close(
59
		   gp_semaphore * sema	/* semaphore to affect */
60
)
61
{
62
    win32_semaphore *const winSema = (win32_semaphore *)sema;
63
 
64
    if (winSema->handle != NULL)
65
	CloseHandle(winSema->handle);
66
    winSema->handle = NULL;
67
    return 0;
68
}
69
 
70
int				/* rets 0 ok, -ve error */
71
gp_semaphore_wait(
72
		  gp_semaphore * sema	/* semaphore to affect */
73
)
74
{
75
    win32_semaphore *const winSema = (win32_semaphore *)sema;
76
 
77
    return
78
	(WaitForSingleObject(winSema->handle, INFINITE) == WAIT_OBJECT_0
79
	 ? 0 : gs_error_unknownerror);
80
}
81
 
82
int				/* rets 0 ok, -ve error */
83
gp_semaphore_signal(
84
		    gp_semaphore * sema	/* semaphore to affect */
85
)
86
{
87
    win32_semaphore *const winSema = (win32_semaphore *)sema;
88
 
89
    return
90
	(ReleaseSemaphore(winSema->handle, 1, NULL) ? 0 :
91
	 gs_error_unknownerror);
92
}
93
 
94
 
95
/* Monitor supports enter/leave semantics */
96
 
97
typedef struct win32_monitor_s {
98
    CRITICAL_SECTION lock;	/* critical section lock */
99
} win32_monitor;
100
 
101
uint
102
gp_monitor_sizeof(void)
103
{
104
    return sizeof(win32_monitor);
105
}
106
 
107
int	/* if sema <> 0 rets -ve error, 0 ok; if sema == 0, 0 movable, 1 fixed */
108
gp_monitor_open(
109
		gp_monitor * mon	/* create monitor here */
110
)
111
{
112
    win32_monitor *const winMon = (win32_monitor *)mon;
113
 
114
    if (mon) {
115
	InitializeCriticalSection(&winMon->lock);	/* returns no status */
116
	return 0;
117
    } else
118
	return 1;		/* Win32 critical sections mutsn't be moved */
119
}
120
 
121
int
122
gp_monitor_close(
123
		 gp_monitor * mon	/* monitor to affect */
124
)
125
{
126
    win32_monitor *const winMon = (win32_monitor *)mon;
127
 
128
    DeleteCriticalSection(&winMon->lock);	/* rets no status */
129
    return 0;
130
}
131
 
132
int				/* rets 0 ok, -ve error */
133
gp_monitor_enter(
134
		 gp_monitor * mon	/* monitor to affect */
135
)
136
{
137
    win32_monitor *const winMon = (win32_monitor *)mon;
138
 
139
    EnterCriticalSection(&winMon->lock);	/* rets no status */
140
    return 0;
141
}
142
 
143
int				/* rets 0 ok, -ve error */
144
gp_monitor_leave(
145
		 gp_monitor * mon	/* monitor to affect */
146
)
147
{
148
    win32_monitor *const winMon = (win32_monitor *)mon;
149
 
150
    LeaveCriticalSection(&winMon->lock);	/* rets no status */
151
    return 0;
152
}
153
 
154
/* --------- Thread primitives ---------- */
155
 
156
typedef struct gp_thread_creation_closure_s {
157
    gp_thread_creation_callback_t function;	/* function to start */
158
    void *data;			/* magic data to pass to thread */
159
} gp_thread_creation_closure;
160
 
161
/* Origin of new threads started by gp_create_thread */
162
private void
163
gp_thread_begin_wrapper(
164
			void *thread_data	/* gp_thread_creation_closure passed as magic data */
165
)
166
{
167
    gp_thread_creation_closure closure;
168
 
169
    closure = *(gp_thread_creation_closure *)thread_data;
170
    free(thread_data);
171
    (*closure.function)(closure.data);
172
    _endthread();
173
}
174
 
175
/* Call a function on a brand new thread */
176
int				/* 0 ok, -ve error */
177
gp_create_thread(
178
		 gp_thread_creation_callback_t function,	/* function to start */
179
		 void *data	/* magic data to pass to thread fn */
180
)
181
{
182
    /* Create the magic closure that thread_wrapper gets passed */
183
    gp_thread_creation_closure *closure =
184
	(gp_thread_creation_closure *)malloc(sizeof(*closure));
185
 
186
    if (!closure)
187
	return gs_error_VMerror;
188
    closure->function = function;
189
    closure->data = data;
190
 
191
    /*
192
     * Start thread_wrapper.  The Watcom _beginthread returns (int)(-1) if
193
     * the call fails.  The Microsoft _beginthread returns -1 (according to
194
     * the doc, even though the return type is "unsigned long" !!!) if the
195
     * call fails; we aren't sure what the Borland _beginthread returns.
196
     * The hack with ~ avoids a source code commitment as to whether the
197
     * return type is [u]int or [u]long.
198
     *
199
     * BEGIN_THREAD is a macro (defined in windows_.h) because _beginthread
200
     * takes different arguments in Watcom C.
201
     */
202
    if (~BEGIN_THREAD(gp_thread_begin_wrapper, 0, closure) != 0)
203
	return 0;
204
    return_error(gs_error_unknownerror);
205
}
206