Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/gs/src/gp_psync.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1999, 2000 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_psync.c,v 1.4 2002/02/21 22:24:52 giles Exp $ */
18
/* POSIX pthreads threads / semaphore / monitor implementation */
19
#include "std.h"
20
#include "malloc_.h"
21
#include <pthread.h>
22
#include "gserror.h"
23
#include "gserrors.h"
24
#include "gpsync.h"
25
 
26
/*
27
 * Thanks to Larry Jones <larry.jones@sdrc.com> for this revision of
28
 * Aladdin's original code into a form that depends only on POSIX APIs.
29
 */
30
 
31
/*
32
 * Some old versions of the pthreads library define
33
 * pthread_attr_setdetachstate as taking a Boolean rather than an enum.
34
 * Compensate for this here.
35
 */
36
#ifndef PTHREAD_CREATE_DETACHED
37
#  define PTHREAD_CREATE_DETACHED 1
38
#endif
39
 
40
/* ------- Synchronization primitives -------- */
41
 
42
/* Semaphore supports wait/signal semantics */
43
 
44
typedef struct pt_semaphore_t {
45
    int count;
46
    pthread_mutex_t mutex;
47
    pthread_cond_t cond;
48
} pt_semaphore_t;
49
 
50
uint
51
gp_semaphore_sizeof(void)
52
{
53
    return sizeof(pt_semaphore_t);
54
}
55
 
56
/*
57
 * This procedure should really check errno and return something
58
 * more informative....
59
 */
60
#define SEM_ERROR_CODE(scode)\
61
  (scode != 0 ? gs_note_error(gs_error_ioerror) : 0)
62
 
63
int
64
gp_semaphore_open(gp_semaphore * sema)
65
{
66
    pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
67
    int scode;
68
 
69
    if (!sema)
70
	return -1;		/* semaphores are not movable */
71
    sem->count = 0;
72
    scode = pthread_mutex_init(&sem->mutex, NULL);
73
    if (scode == 0)
74
	scode = pthread_cond_init(&sem->cond, NULL);
75
    return SEM_ERROR_CODE(scode);
76
}
77
 
78
int
79
gp_semaphore_close(gp_semaphore * sema)
80
{
81
    pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
82
    int scode, scode2;
83
 
84
    scode = pthread_cond_destroy(&sem->cond);
85
    scode2 = pthread_mutex_destroy(&sem->mutex);
86
    if (scode == 0)
87
	scode = scode2;
88
    return SEM_ERROR_CODE(scode);
89
}
90
 
91
int
92
gp_semaphore_wait(gp_semaphore * sema)
93
{
94
    pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
95
    int scode, scode2;
96
 
97
    scode = pthread_mutex_lock(&sem->mutex);
98
    if (scode != 0)
99
	return SEM_ERROR_CODE(scode);
100
    while (sem->count == 0) {
101
        scode = pthread_cond_wait(&sem->cond, &sem->mutex);
102
        if (scode != 0)
103
	    break;
104
    }
105
    if (scode == 0)
106
	--sem->count;
107
    scode2 = pthread_mutex_unlock(&sem->mutex);
108
    if (scode == 0)
109
	scode = scode2;
110
    return SEM_ERROR_CODE(scode);
111
}
112
 
113
int
114
gp_semaphore_signal(gp_semaphore * sema)
115
{
116
    pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
117
    int scode, scode2;
118
 
119
    scode = pthread_mutex_lock(&sem->mutex);
120
    if (scode != 0)
121
	return SEM_ERROR_CODE(scode);
122
    if (sem->count++ == 0)
123
	scode = pthread_cond_signal(&sem->cond);
124
    scode2 = pthread_mutex_unlock(&sem->mutex);
125
    if (scode == 0)
126
	scode = scode2;
127
    return SEM_ERROR_CODE(scode);
128
}
129
 
130
 
131
/* Monitor supports enter/leave semantics */
132
 
133
uint
134
gp_monitor_sizeof(void)
135
{
136
    return sizeof(pthread_mutex_t);
137
}
138
 
139
int
140
gp_monitor_open(gp_monitor * mona)
141
{
142
    pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
143
    int scode;
144
 
145
    if (!mona)
146
	return -1;		/* monitors are not movable */
147
    scode = pthread_mutex_init(mon, NULL);
148
    return SEM_ERROR_CODE(scode);
149
}
150
 
151
int
152
gp_monitor_close(gp_monitor * mona)
153
{
154
    pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
155
    int scode;
156
 
157
    scode = pthread_mutex_destroy(mon);
158
    return SEM_ERROR_CODE(scode);
159
}
160
 
161
int
162
gp_monitor_enter(gp_monitor * mona)
163
{
164
    pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
165
    int scode;
166
 
167
    scode = pthread_mutex_lock(mon);
168
    return SEM_ERROR_CODE(scode);
169
}
170
 
171
int
172
gp_monitor_leave(gp_monitor * mona)
173
{
174
    pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
175
    int scode;
176
 
177
    scode = pthread_mutex_unlock(mon);
178
    return SEM_ERROR_CODE(scode);
179
}
180
 
181
 
182
/* --------- Thread primitives ---------- */
183
 
184
/*
185
 * In order to deal with the type mismatch between our thread API, where
186
 * the starting procedure returns void, and the API defined by pthreads,
187
 * where the procedure returns void *, we need to create a wrapper
188
 * closure.
189
 */
190
typedef struct gp_thread_creation_closure_s {
191
    gp_thread_creation_callback_t proc;  /* actual start procedure */
192
    void *proc_data;			/* closure data for proc */
193
} gp_thread_creation_closure_t;
194
 
195
/* Wrapper procedure called to start the new thread. */
196
private void *
197
gp_thread_begin_wrapper(void *thread_data /* gp_thread_creation_closure_t * */)
198
{
199
    gp_thread_creation_closure_t closure;
200
 
201
    closure = *(gp_thread_creation_closure_t *)thread_data;
202
    free(thread_data);
203
    DISCARD(closure.proc(closure.proc_data));
204
    return NULL;		/* return value is ignored */
205
}
206
 
207
int
208
gp_create_thread(gp_thread_creation_callback_t proc, void *proc_data)
209
{
210
    gp_thread_creation_closure_t *closure =
211
	(gp_thread_creation_closure_t *)malloc(sizeof(*closure));
212
    pthread_t ignore_thread;
213
    pthread_attr_t attr;
214
    int code;
215
 
216
    if (!closure)
217
	return_error(gs_error_VMerror);
218
    closure->proc = proc;
219
    closure->proc_data = proc_data;
220
    pthread_attr_init(&attr);
221
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
222
    code = pthread_create(&ignore_thread, &attr, gp_thread_begin_wrapper,
223
			  closure);
224
    if (code) {
225
	free(closure);
226
	return_error(gs_error_ioerror);
227
    }
228
    return 0;
229
}