1 /***************************************************************************/
2 /* This code is part of WWW grabber called pavuk */
3 /* Copyright (c) 1997 - 2001 Stefan Ondrejicka */
4 /* Distributed under GPL 2 or later */
5 /***************************************************************************/
6
7 #include "config.h"
8
9 #ifdef HAVE_MT
10 #include <stdio.h>
11 #include <sys/time.h>
12 #include <time.h>
13 #include "gui.h"
14 #include "mt.h"
15
16 pthread_key_t _mt_key_main_thread;
17
18 pthread_mutex_t _mt_urlstack_lock;
19 pthread_mutex_t _mt_urlhash_lock;
20 pthread_mutex_t _mt_filehash_lock;
21 pthread_mutex_t _mt_cookies_lock;
22 pthread_mutex_t _mt_authinfo_lock;
23 pthread_mutex_t _mt_getlfname_lock;
24 pthread_mutex_t _mt_dns_lock;
25 pthread_mutex_t _mt_log_lock;
26 pthread_mutex_t _mt_slog_lock;
27 pthread_mutex_t _mt_tlog_lock;
28 pthread_mutex_t _mt_dbase_lock;
29 pthread_mutex_t _mt_dcnt_lock;
30 pthread_mutex_t _mt_time_lock;
31 pthread_mutex_t _mt_ghbn_lock;
32 pthread_mutex_t _mt_output_lock;
33 pthread_mutex_t _mt_proxy_lock;
34 pthread_mutex_t _mt_dirr_lock;
35 pthread_mutex_t _mt_tcnt_lock;
36 pthread_mutex_t _mt_gtktree_lock;
37 pthread_mutex_t _mt_gtkstatus_lock;
38 pthread_mutex_t _mt_gtklog_lock;
39 pthread_mutex_t _mt_rejcnt_lock;
40 pthread_mutex_t _mt_failcnt_lock;
41 pthread_mutex_t _mt_gcfg_lock;
42 pthread_mutex_t _mt_nscache_lock;
43 pthread_mutex_t _mt_robots_lock;
44 pthread_mutex_t _mt_dumpurls_lock;
45 pthread_mutex_t _mt_taghash_lock;
46 pthread_mutex_t _mt_dumpfd_lock;
47 pthread_mutex_t _mt_inet_ntoa_lock;
48 pthread_mutex_t _mt_mozjs_lock;
49 pthread_mutex_t _mt_ssl_map_lock;
50
mt_init(void)51 void mt_init(void)
52 {
53 static int __h_errno;
54
55 pthread_mutex_init(&_mt_urlstack_lock, NULL);
56 pthread_mutex_init(&_mt_urlhash_lock, NULL);
57 pthread_mutex_init(&_mt_filehash_lock, NULL);
58 pthread_mutex_init(&_mt_cookies_lock, NULL);
59 pthread_mutex_init(&_mt_authinfo_lock, NULL);
60 pthread_mutex_init(&_mt_dns_lock, NULL);
61 pthread_mutex_init(&_mt_log_lock, NULL);
62 pthread_mutex_init(&_mt_slog_lock, NULL);
63 pthread_mutex_init(&_mt_tlog_lock, NULL);
64 pthread_mutex_init(&_mt_dcnt_lock, NULL);
65 pthread_mutex_init(&_mt_time_lock, NULL);
66 pthread_mutex_init(&_mt_ghbn_lock, NULL);
67 pthread_mutex_init(&_mt_getlfname_lock, NULL);
68 pthread_mutex_init(&_mt_output_lock, NULL);
69 pthread_mutex_init(&_mt_proxy_lock, NULL);
70 pthread_mutex_init(&_mt_dirr_lock, NULL);
71 pthread_mutex_init(&_mt_tcnt_lock, NULL);
72 pthread_mutex_init(&_mt_gtktree_lock, NULL);
73 pthread_mutex_init(&_mt_gtkstatus_lock, NULL);
74 pthread_mutex_init(&_mt_gtklog_lock, NULL);
75 pthread_mutex_init(&_mt_rejcnt_lock, NULL);
76 pthread_mutex_init(&_mt_failcnt_lock, NULL);
77 pthread_mutex_init(&_mt_gcfg_lock, NULL);
78 pthread_mutex_init(&_mt_nscache_lock, NULL);
79 pthread_mutex_init(&_mt_robots_lock, NULL);
80 pthread_mutex_init(&_mt_dumpurls_lock, NULL);
81 pthread_mutex_init(&_mt_taghash_lock, NULL);
82 pthread_mutex_init(&_mt_dumpfd_lock, NULL);
83 pthread_mutex_init(&_mt_inet_ntoa_lock, NULL);
84 pthread_mutex_init(&_mt_mozjs_lock, NULL);
85 pthread_mutex_init(&_mt_ssl_map_lock, NULL);
86
87 pthread_key_create(&cfg.currdoc_key, NULL);
88 pthread_key_create(&cfg.herrno_key, NULL);
89 pthread_key_create(&cfg.thrnr_key, NULL);
90 pthread_key_create(&cfg.privcfg_key, NULL);
91 pthread_key_create(&_mt_key_main_thread, NULL);
92
93 mt_semaphore_init(&cfg.nrunning_sem);
94 mt_semaphore_init(&cfg.urlstack_sem);
95
96 pthread_setspecific(cfg.herrno_key, &__h_errno);
97 pthread_setspecific(cfg.currdoc_key, NULL);
98 pthread_setspecific(cfg.thrnr_key, (void *) -1);
99 pthread_setspecific(cfg.privcfg_key, &cfg);
100 pthread_setspecific(_mt_key_main_thread, (void *) TRUE);
101
102 cfg.cfg_changed = 0L;
103
104 #ifdef GTK_FACE
105 g_thread_init(NULL);
106 #endif
107 }
108
mt_pthread_mutex_lock(pthread_mutex_t * mutex,char * id)109 int mt_pthread_mutex_lock(pthread_mutex_t * mutex, char *id)
110 {
111 int rv;
112
113 DEBUG_MTLOCK("Try lock(%ld) - %s\n", pthread_self(), id);
114 rv = pthread_mutex_lock(mutex);
115 DEBUG_MTLOCK("Locking(%ld) - %s\n", pthread_self(), id);
116
117 return rv;
118 }
119
mt_pthread_mutex_unlock(pthread_mutex_t * mutex,char * id)120 int mt_pthread_mutex_unlock(pthread_mutex_t * mutex, char *id)
121 {
122 DEBUG_MTLOCK("Unlocking(%ld) - %s\n", pthread_self(), id);
123 return pthread_mutex_unlock(mutex);
124 }
125
126 /********************************************************/
127 /* semaphore code based on Tom Wagner and Don Towsley's */
128 /* document "Getting Started With POSIX Threads" */
129 /********************************************************/
mt_semaphore_init(mt_semaphore * sem)130 int mt_semaphore_init(mt_semaphore * sem)
131 {
132 sem->v = 1;
133 if(pthread_mutex_init(&(sem->mutex), NULL))
134 {
135 xperror("mt_semaphore_init - mutex_init");
136 return -1;
137 }
138 if(pthread_cond_init(&(sem->cond), NULL))
139 {
140 xperror("mt_semaphore_init - cond_init");
141 return -1;
142 }
143 return 0;
144 }
145
mt_semaphore_destroy(mt_semaphore * sem)146 int mt_semaphore_destroy(mt_semaphore * sem)
147 {
148 if(pthread_mutex_destroy(&(sem->mutex)))
149 {
150 xperror("mt_semaphore_destroy - mutex_destroy");
151 return -1;
152 }
153 if(pthread_cond_destroy(&(sem->cond)))
154 {
155 xperror("mt_semaphore_destroy - cond_destroy");
156 return -1;
157 }
158 return 0;
159 }
160
mt_semaphore_up(mt_semaphore * sem)161 long mt_semaphore_up(mt_semaphore * sem)
162 {
163 long rv;
164
165 pthread_mutex_lock(&(sem->mutex));
166
167 sem->v++;
168 rv = sem->v;
169
170 pthread_mutex_unlock(&(sem->mutex));
171 pthread_cond_signal(&(sem->cond));
172 return rv;
173 }
174
mt_semaphore_down(mt_semaphore * sem)175 long mt_semaphore_down(mt_semaphore * sem)
176 {
177 long rv;
178
179 pthread_mutex_lock(&(sem->mutex));
180
181 while(sem->v <= 0)
182 {
183 pthread_cond_wait(&(sem->cond), &(sem->mutex));
184 }
185
186 sem->v--;
187 rv = sem->v;
188
189 pthread_mutex_unlock(&(sem->mutex));
190
191 return rv;
192 }
193
set_ts(struct timespec * ts,int msec)194 static void set_ts(struct timespec *ts, int msec)
195 {
196 #ifdef HAVE_PT_EXPIRATION_NP
197 {
198 struct timespec t;
199 t.tv_sec = msec / 1000;
200 t.tv_nsec = (msec % 1000) * 1000000;
201 pthread_get_expiration_np(&t, ts);
202 }
203 #else /* HAVE_PT_EXPIRATION_NP */
204
205 #ifdef HAVE_GETTIMEOFDAY
206 {
207 struct timeval t;
208 gettimeofday(&t, NULL);
209 ts->tv_sec = t.tv_sec;
210 ts->tv_nsec = t.tv_usec * 1000;
211 }
212 #else /* HAVE_GETTIMEOFDAY */
213 ts->tv_sec = time(NULL);
214 ts->tv_nsec = 0;
215 #endif /* HAVE_GETTIMEOFDAY */
216
217 ts->tv_sec += msec / 1000;
218 ts->tv_nsec += (msec % 1000) * 1000000;
219 ts->tv_sec += ts->tv_nsec / 1000000000;
220 ts->tv_nsec %= 1000000000;
221 #endif /* HAVE_PT_EXPIRATION_NP */
222 }
223
mt_semaphore_timed_down(mt_semaphore * sem,int msec)224 long mt_semaphore_timed_down(mt_semaphore * sem, int msec)
225 {
226 long rv;
227 struct timespec ts;
228 int errnum = 0;
229
230 pthread_mutex_lock(&(sem->mutex));
231
232 set_ts(&ts, msec);
233 while(sem->v <= 0)
234 {
235 errnum = pthread_cond_timedwait(&(sem->cond), &(sem->mutex), &ts);
236
237 if(errnum)
238 break;
239 }
240
241 if(!errnum)
242 {
243 sem->v--;
244 rv = sem->v;
245 }
246 else
247 rv = -1;
248
249 pthread_mutex_unlock(&(sem->mutex));
250
251 return rv;
252 }
253
mt_semaphore_timed_wait(mt_semaphore * sem,int msec)254 long mt_semaphore_timed_wait(mt_semaphore * sem, int msec)
255 {
256 long rv;
257 struct timespec ts;
258 int errnum = 0;
259
260 pthread_mutex_lock(&(sem->mutex));
261
262 set_ts(&ts, msec);
263 while(sem->v <= 0)
264 {
265 errnum = pthread_cond_timedwait(&(sem->cond), &(sem->mutex), &ts);
266
267 if(errnum)
268 break;
269 }
270
271 if(!errnum)
272 {
273 rv = sem->v;
274 }
275 else
276 rv = -1;
277
278 pthread_mutex_unlock(&(sem->mutex));
279
280 return rv;
281 }
282
mt_semaphore_decrement(mt_semaphore * sem)283 long mt_semaphore_decrement(mt_semaphore * sem)
284 {
285 long rv;
286
287 pthread_mutex_lock(&(sem->mutex));
288
289 sem->v--;
290 rv = sem->v;
291
292 pthread_mutex_unlock(&(sem->mutex));
293
294 return rv;
295 }
296 #endif
297