~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to src/gp_psync.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2001-2006 Artifex Software, Inc.
2
 
   All Rights Reserved.
3
 
  
4
 
   This software is provided AS-IS with no warranty, either express or
5
 
   implied.
6
 
 
7
 
   This software is distributed under license and may not be copied, modified
8
 
   or distributed except as expressly authorized under the terms of that
9
 
   license.  Refer to licensing information at http://www.artifex.com/
10
 
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11
 
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12
 
*/
13
 
 
14
 
/* $Id: gp_psync.c 8715 2008-05-08 19:10:40Z ray $ */
15
 
/* POSIX pthreads threads / semaphore / monitor implementation */
16
 
#include "std.h"
17
 
#include "malloc_.h"
18
 
#include <pthread.h>
19
 
#include "gserror.h"
20
 
#include "gserrors.h"
21
 
#include "gpsync.h"
22
 
 
23
 
/*
24
 
 * Thanks to Larry Jones <larry.jones@sdrc.com> for this revision of
25
 
 * Aladdin's original code into a form that depends only on POSIX APIs.
26
 
 */
27
 
 
28
 
/*
29
 
 * Some old versions of the pthreads library define
30
 
 * pthread_attr_setdetachstate as taking a Boolean rather than an enum.
31
 
 * Compensate for this here.
32
 
 */
33
 
#ifndef PTHREAD_CREATE_DETACHED
34
 
#  define PTHREAD_CREATE_DETACHED 1
35
 
#endif
36
 
 
37
 
/* ------- Synchronization primitives -------- */
38
 
 
39
 
/* Semaphore supports wait/signal semantics */
40
 
 
41
 
typedef struct pt_semaphore_t {
42
 
    int count;
43
 
    pthread_mutex_t mutex;
44
 
    pthread_cond_t cond;
45
 
} pt_semaphore_t;
46
 
 
47
 
uint
48
 
gp_semaphore_sizeof(void)
49
 
{
50
 
    return sizeof(pt_semaphore_t);
51
 
}
52
 
 
53
 
/*
54
 
 * This procedure should really check errno and return something
55
 
 * more informative....
56
 
 */
57
 
#define SEM_ERROR_CODE(scode)\
58
 
  (scode != 0 ? gs_note_error(gs_error_ioerror) : 0)
59
 
 
60
 
int
61
 
gp_semaphore_open(gp_semaphore * sema)
62
 
{
63
 
    pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
64
 
    int scode;
65
 
 
66
 
    if (!sema)
67
 
        return -1;              /* semaphores are not movable */
68
 
    sem->count = 0;
69
 
    scode = pthread_mutex_init(&sem->mutex, NULL);
70
 
    if (scode == 0)
71
 
        scode = pthread_cond_init(&sem->cond, NULL);
72
 
    return SEM_ERROR_CODE(scode);
73
 
}
74
 
 
75
 
int
76
 
gp_semaphore_close(gp_semaphore * sema)
77
 
{
78
 
    pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
79
 
    int scode, scode2;
80
 
 
81
 
    scode = pthread_cond_destroy(&sem->cond);
82
 
    scode2 = pthread_mutex_destroy(&sem->mutex);
83
 
    if (scode == 0)
84
 
        scode = scode2;
85
 
    return SEM_ERROR_CODE(scode);
86
 
}
87
 
 
88
 
int
89
 
gp_semaphore_wait(gp_semaphore * sema)
90
 
{
91
 
    pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
92
 
    int scode, scode2;
93
 
 
94
 
    scode = pthread_mutex_lock(&sem->mutex);
95
 
    if (scode != 0)
96
 
        return SEM_ERROR_CODE(scode);
97
 
    while (sem->count == 0) {
98
 
        scode = pthread_cond_wait(&sem->cond, &sem->mutex);
99
 
        if (scode != 0)
100
 
            break;
101
 
    }
102
 
    if (scode == 0)
103
 
        --sem->count;
104
 
    scode2 = pthread_mutex_unlock(&sem->mutex);
105
 
    if (scode == 0)
106
 
        scode = scode2;
107
 
    return SEM_ERROR_CODE(scode);
108
 
}
109
 
 
110
 
int
111
 
gp_semaphore_signal(gp_semaphore * sema)
112
 
{
113
 
    pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
114
 
    int scode, scode2;
115
 
 
116
 
    scode = pthread_mutex_lock(&sem->mutex);
117
 
    if (scode != 0)
118
 
        return SEM_ERROR_CODE(scode);
119
 
    if (sem->count++ == 0)
120
 
        scode = pthread_cond_signal(&sem->cond);
121
 
    scode2 = pthread_mutex_unlock(&sem->mutex);
122
 
    if (scode == 0)
123
 
        scode = scode2;
124
 
    return SEM_ERROR_CODE(scode);
125
 
}
126
 
 
127
 
 
128
 
/* Monitor supports enter/leave semantics */
129
 
 
130
 
/*
131
 
 * We need PTHREAD_MUTEX_RECURSIVE behavior, but this isn't totally portable
132
 
 * so we implement it in a more portable fashion, keeping track of the
133
 
 * owner thread using 'pthread_self()'
134
 
 */
135
 
typedef struct gp_pthread_recursive_s {
136
 
    pthread_mutex_t mutex;      /* actual mutex */
137
 
    pthread_t   self_id;        /* owner */
138
 
} gp_pthread_recursive_t;
139
 
 
140
 
uint
141
 
gp_monitor_sizeof(void)
142
 
{
143
 
    return sizeof(gp_pthread_recursive_t);
144
 
}
145
 
 
146
 
int
147
 
gp_monitor_open(gp_monitor * mona)
148
 
{
149
 
    pthread_mutex_t * const mon = &((gp_pthread_recursive_t *)mona)->mutex;
150
 
    int scode;
151
 
 
152
 
    if (!mona)
153
 
        return -1;              /* monitors are not movable */
154
 
    ((gp_pthread_recursive_t *)mona)->self_id = 0;      /* Not valid unless mutex is locked */
155
 
    scode = pthread_mutex_init(mon, NULL);
156
 
    return SEM_ERROR_CODE(scode);
157
 
}
158
 
 
159
 
int
160
 
gp_monitor_close(gp_monitor * mona)
161
 
{
162
 
    pthread_mutex_t * const mon = &((gp_pthread_recursive_t *)mona)->mutex;
163
 
    int scode;
164
 
 
165
 
    scode = pthread_mutex_destroy(mon);
166
 
    return SEM_ERROR_CODE(scode);
167
 
}
168
 
 
169
 
int
170
 
gp_monitor_enter(gp_monitor * mona)
171
 
{
172
 
    pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
173
 
    int scode;
174
 
 
175
 
    if ((scode = pthread_mutex_trylock(mon)) == 0) {
176
 
        ((gp_pthread_recursive_t *)mona)->self_id = pthread_self();
177
 
        return SEM_ERROR_CODE(scode);
178
 
    } else {
179
 
        if (pthread_equal(pthread_self(),((gp_pthread_recursive_t *)mona)->self_id))
180
 
            return 0;
181
 
        else {
182
 
            /* we were not the owner, wait */
183
 
            scode = pthread_mutex_lock(mon);
184
 
            ((gp_pthread_recursive_t *)mona)->self_id = pthread_self();
185
 
            return SEM_ERROR_CODE(scode);
186
 
        }
187
 
    }
188
 
}
189
 
 
190
 
int
191
 
gp_monitor_leave(gp_monitor * mona)
192
 
{
193
 
    pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
194
 
    int scode;
195
 
 
196
 
    scode = pthread_mutex_unlock(mon);
197
 
    ((gp_pthread_recursive_t *)mona)->self_id = 0;      /* Not valid unless mutex is locked */
198
 
    return SEM_ERROR_CODE(scode);
199
 
}
200
 
 
201
 
 
202
 
/* --------- Thread primitives ---------- */
203
 
 
204
 
/*
205
 
 * In order to deal with the type mismatch between our thread API, where
206
 
 * the starting procedure returns void, and the API defined by pthreads,
207
 
 * where the procedure returns void *, we need to create a wrapper
208
 
 * closure.
209
 
 */
210
 
typedef struct gp_thread_creation_closure_s {
211
 
    gp_thread_creation_callback_t proc;  /* actual start procedure */
212
 
    void *proc_data;                    /* closure data for proc */
213
 
} gp_thread_creation_closure_t;
214
 
 
215
 
/* Wrapper procedure called to start the new thread. */
216
 
static void *
217
 
gp_thread_begin_wrapper(void *thread_data /* gp_thread_creation_closure_t * */)
218
 
{
219
 
    gp_thread_creation_closure_t closure;
220
 
 
221
 
    closure = *(gp_thread_creation_closure_t *)thread_data;
222
 
    free(thread_data);
223
 
    DISCARD(closure.proc(closure.proc_data));
224
 
    return NULL;                /* return value is ignored */
225
 
}
226
 
 
227
 
int
228
 
gp_create_thread(gp_thread_creation_callback_t proc, void *proc_data)
229
 
{
230
 
    gp_thread_creation_closure_t *closure =
231
 
        (gp_thread_creation_closure_t *)malloc(sizeof(*closure));
232
 
    pthread_t ignore_thread;
233
 
    pthread_attr_t attr;
234
 
    int code;
235
 
 
236
 
    if (!closure)
237
 
        return_error(gs_error_VMerror);
238
 
    closure->proc = proc;
239
 
    closure->proc_data = proc_data;
240
 
    pthread_attr_init(&attr);
241
 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
242
 
    code = pthread_create(&ignore_thread, &attr, gp_thread_begin_wrapper,
243
 
                          closure);
244
 
    if (code) {
245
 
        free(closure);
246
 
        return_error(gs_error_ioerror);
247
 
    }
248
 
    return 0;
249
 
}