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