1 /* Support for thread stuff.
2 *
3 * JC & KM 9/5/94
4 * Modified:
5 * 28/11/94 JC
6 * - return(0) missing from tidy_thread_info()
7 * 4/8/99 RP JC
8 * - reorganised for POSIX
9 * 28/3/11
10 * - moved to vips_ namespace
11 */
12
13 /*
14
15 This file is part of VIPS.
16
17 VIPS is free software; you can redistribute it and/or modify
18 it under the terms of the GNU Lesser General Public License as published by
19 the Free Software Foundation; either version 2 of the License, or
20 (at your option) any later version.
21
22 This program is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU Lesser General Public License for more details.
26
27 You should have received a copy of the GNU Lesser General Public License
28 along with this program; if not, write to the Free Software
29 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 02110-1301 USA
31
32 */
33
34 /*
35
36 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
37
38 */
39
40 /*
41 #define DEBUG_IO
42 */
43
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif /*HAVE_CONFIG_H*/
47 #include <vips/intl.h>
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <signal.h>
52 #include <errno.h>
53
54 #include <vips/vips.h>
55 #include <vips/thread.h>
56
57 void
vips_semaphore_init(VipsSemaphore * s,int v,char * name)58 vips_semaphore_init( VipsSemaphore *s, int v, char *name )
59 {
60 s->v = v;
61 s->name = name;
62 s->mutex = vips_g_mutex_new();
63 s->cond = vips_g_cond_new();
64 }
65
66 void
vips_semaphore_destroy(VipsSemaphore * s)67 vips_semaphore_destroy( VipsSemaphore *s )
68 {
69 VIPS_FREEF( vips_g_mutex_free, s->mutex );
70 VIPS_FREEF( vips_g_cond_free, s->cond );
71 }
72
73 /* Add n to the semaphore and signal any threads that are blocked waiting
74 * a change.
75 */
76 int
vips_semaphore_upn(VipsSemaphore * s,int n)77 vips_semaphore_upn( VipsSemaphore *s, int n )
78 {
79 int value_after_op;
80
81 g_mutex_lock( s->mutex );
82 s->v += n;
83 value_after_op = s->v;
84
85 /* If we are only incrementing by one, we only need to wake a single
86 * thread. If we are incrementing by a lot, we must wake all threads.
87 */
88 if( n == 1 )
89 g_cond_signal( s->cond );
90 else
91 g_cond_broadcast( s->cond );
92 g_mutex_unlock( s->mutex );
93
94 #ifdef DEBUG_IO
95 printf( "vips_semaphore_upn(\"%s\",%d) = %d\n",
96 s->name, n, value_after_op );
97 if( value_after_op > 1 )
98 vips_error( "vips_semaphore_upn", "up over 1!" );
99 #endif /*DEBUG_IO*/
100
101 return( value_after_op );
102 }
103
104 /* Increment the semaphore.
105 */
106 int
vips_semaphore_up(VipsSemaphore * s)107 vips_semaphore_up( VipsSemaphore *s )
108 {
109 return( vips_semaphore_upn( s, 1 ) );
110 }
111
112 /* Wait for sem>n, then subtract n.
113 */
114 int
vips_semaphore_downn(VipsSemaphore * s,int n)115 vips_semaphore_downn( VipsSemaphore *s, int n )
116 {
117 int value_after_op;
118
119 VIPS_GATE_START( "vips_semaphore_downn: wait" );
120
121 g_mutex_lock( s->mutex );
122
123 while( s->v < n )
124 g_cond_wait( s->cond, s->mutex );
125 s->v -= n;
126 value_after_op = s->v;
127
128 g_mutex_unlock( s->mutex );
129
130 #ifdef DEBUG_IO
131 printf( "vips_semaphore_downn(\"%s\",%d): %d\n",
132 s->name, n, value_after_op );
133 #endif /*DEBUG_IO*/
134
135 VIPS_GATE_STOP( "vips_semaphore_downn: wait" );
136
137 return( value_after_op );
138 }
139
140 /* Wait for sem > 0, then decrement.
141 */
142 int
vips_semaphore_down(VipsSemaphore * s)143 vips_semaphore_down( VipsSemaphore *s )
144 {
145 return( vips_semaphore_downn( s, 1 ) );
146 }
147