xref: /plan9/sys/src/cmd/gs/src/gxsync.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1998 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: gxsync.c,v 1.4 2002/02/21 22:24:53 giles Exp $ */
18 /* Interface to platform-based synchronization primitives */
19 
20 /* Initial version 2/1/98 by John Desrosiers (soho@crl.com) */
21 
22 #include "memory_.h"
23 #include "gx.h"
24 #include "gserrors.h"
25 #include "gsmemory.h"
26 #include "gxsync.h"
27 
28 /* This module abstracts the platform-specific synchronization primitives. */
29 /* Since these routines will see heavy use, performance is important. */
30 
31 
32 /* ----- Semaphore interface ----- */
33 /* These have the usual queued, counting semaphore semantics: at init time, */
34 /* the event count is set to 0 ('wait' will wait until 1st signal). */
35 
36 /* Allocate & initialize a semaphore */
37 gx_semaphore_t *		/* returns a new semaphore, 0 if error */
gx_semaphore_alloc(gs_memory_t * memory)38 gx_semaphore_alloc(
39 		      gs_memory_t * memory	/* memory allocator to use */
40 )
41 {
42     gx_semaphore_t *sema;
43 
44     /* sizeof decl'd sema struct, minus semaphore placeholder's size, + actual semaphore size */
45     unsigned semaSizeof
46     = sizeof(*sema) - sizeof(sema->native) + gp_semaphore_sizeof();
47 
48     if (gp_semaphore_open(0) == 0)	/* see if gp_semaphores are movable */
49 	/* movable */
50 	sema = (gx_semaphore_t *) gs_alloc_bytes(memory, semaSizeof,
51 						 "gx_semaphore (create)");
52     else
53 	/* unmovable */
54 	sema = (gx_semaphore_t *) gs_alloc_bytes_immovable(memory, semaSizeof,
55 						   "gx_semaphore (create)");
56     if (sema == 0)
57 	return 0;
58 
59     /* Make sema remember which allocator was used to allocate it */
60     sema->memory = memory;
61 
62     if (gp_semaphore_open(&sema->native) < 0) {
63 	gs_free_object(memory, sema, "gx_semaphore (alloc)");
64 	return 0;
65     }
66     return sema;
67 }
68 
69 /* Deinit & free a semaphore */
70 void
gx_semaphore_free(gx_semaphore_t * sema)71 gx_semaphore_free(
72 		     gx_semaphore_t * sema	/* semaphore to delete */
73 )
74 {
75     if (sema) {
76 	gp_semaphore_close(&sema->native);
77 	gs_free_object(sema->memory, sema, "gx_semaphore (free)");
78     }
79 }
80 
81 /* Macros defined in gxsync.h, but redefined here so compiler chex consistency */
82 #define gx_semaphore_wait(sema)  gp_semaphore_wait(&(sema)->native)
83 #define gx_semaphore_signal(sema)  gp_semaphore_signal(&(sema)->native)
84 
85 
86 /* ----- Monitor interface ----- */
87 /* These have the usual monitor semantics: at init time, */
88 /* the event count is set to 1 (1st 'enter' succeeds immediately). */
89 
90 /* Allocate & Init a monitor */
91 gx_monitor_t *			/* returns a new monitor, 0 if error */
gx_monitor_alloc(gs_memory_t * memory)92 gx_monitor_alloc(
93 		    gs_memory_t * memory	/* memory allocator to use */
94 )
95 {
96     gx_monitor_t *mon;
97 
98     /* sizeof decl'd mon struct, minus monitor placeholder's size, + actual monitor size */
99     unsigned monSizeof
100     = sizeof(*mon) - sizeof(mon->native) + gp_monitor_sizeof();
101 
102     if (gp_monitor_open(0) == 0)	/* see if gp_monitors are movable */
103 	/* movable */
104 	mon = (gx_monitor_t *) gs_alloc_bytes(memory, monSizeof,
105 					      "gx_monitor (create)");
106     else
107 	/* unmovable */
108 	mon = (gx_monitor_t *) gs_alloc_bytes_immovable(memory, monSizeof,
109 						     "gx_monitor (create)");
110     if (mon == 0)
111 	return 0;
112 
113     /* Make monitor remember which allocator was used to allocate it */
114     mon->memory = memory;
115 
116     if (gp_monitor_open(&mon->native) < 0) {
117 	gs_free_object(memory, mon, "gx_monitor (alloc)");
118 	return 0;
119     }
120     return mon;
121 }
122 
123 /* Dnit & free a monitor */
124 void
gx_monitor_free(gx_monitor_t * mon)125 gx_monitor_free(
126 		   gx_monitor_t * mon	/* monitor to delete */
127 )
128 {
129     if (mon) {
130 	gp_monitor_close(&mon->native);
131 	gs_free_object(mon->memory, mon, "gx_monitor (free)");
132     }
133 }
134 
135 /* Macros defined in gxsync.h, but redefined here so compiler chex consistency */
136 #define gx_monitor_enter(sema)  gp_monitor_enter(&(sema)->native)
137 #define gx_monitor_leave(sema)  gp_monitor_leave(&(sema)->native)
138