1    | /***************************************
2    |   $Revision: 1.26 $
3    | 
4    |   Example code: A thread.
5    | 
6    |   Status: NOT REVUED, NOT TESTED
7    | 
8    |  Authors:       Chris Ottrey
9    | 		Joao Damas
10   | 
11   |   +html+ <DL COMPACT>
12   |   +html+ <DT>Online References:
13   |   +html+ <DD><UL>
14   |   +html+ </UL>
15   |   +html+ </DL>
16   |  
17   |   ******************/ /******************
18   |   Modification History:
19   |         ottrey (02/03/1999) Created.
20   |         ottrey (08/03/1999) Modified.
21   |         ottrey (17/06/1999) Stripped down.
22   |         joao   (22/06/1999) Redid thread startup
23   |   ******************/ /******************
24   |   Copyright (c) 1999                              RIPE NCC
25   |  
26   |   All Rights Reserved
27   |   
28   |   Permission to use, copy, modify, and distribute this software and its
29   |   documentation for any purpose and without fee is hereby granted,
30   |   provided that the above copyright notice appear in all copies and that
31   |   both that copyright notice and this permission notice appear in
32   |   supporting documentation, and that the name of the author not be
33   |   used in advertising or publicity pertaining to distribution of the
34   |   software without specific, written prior permission.
35   |   
36   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
37   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
38   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
39   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
40   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
41   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42   |   ***************************************/
43   | #include <pthread.h>       /* Posix thread library */
44   | #include <stdio.h>
45   | #include <strings.h>
46   | 
47   | #include "thread.h"
48   | /* #include "socket.h"
49   | #include "protocol_whois.h"
50   | #include "protocol_config.h"
51   | #include "protocol_mirror.h"
52   | #include "constants.h"
53   | #include "server.h"
54   | */
55   | #include "memwrap.h"
56   | 
57   | 
58   | /*+ String sizes +*/
59   | #define STR_S   63
60   | #define STR_M   255
61   | #define STR_L   1023
62   | #define STR_XL  4095
63   | #define STR_XXL 16383
64   | 
65   | //typedef struct th_args {
66   | //	void *function;
67   | //	int sock;
68   | //} th_args;
69   | 
70   | /*************************************************
71   | *                                                *
72   | *     Readers Writes Locks that favor READERS    *
73   | *                                                *
74   | *************************************************/
75   | /* TH_acquire_read_lock() */
76   | /*++++++++++++++++++++++++++++++++++++++
77   | 
78   |   Aquire a readers lock.
79   | 
80   |   rw_lock_t *prw_lock Readers writers lock.
81   | 
82   |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
83   |   More:
84   |   +html+ <PRE>
85   |   Author:
86   |         ottrey
87   |   +html+ </PRE>
88   |   ++++++++++++++++++++++++++++++++++++++*/
89   | void TH_acquire_read_lock(rw_lock_t *prw_lock) { 
90   |   pthread_mutex_lock(&prw_lock->rw_mutex);
91   | 
92   |   while (prw_lock->rw_count < 0) {
93   |     pthread_cond_wait(&prw_lock->rw_cond, &prw_lock->rw_mutex);
94   |   }
95   | 
96   |   ++prw_lock->rw_count;
97   |   pthread_mutex_unlock(&prw_lock->rw_mutex);
98   | 
99   | } /* TH_acquire_read_lock() */
100  | 
101  | /* TH_release_read_lock() */
102  | /*++++++++++++++++++++++++++++++++++++++
103  | 
104  |   Release a readers lock.
105  | 
106  |   rw_lock_t *prw_lock Readers writers lock.
107  | 
108  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
109  |   More:
110  |   +html+ <PRE>
111  |   Author:
112  |         ottrey
113  |   +html+ </PRE>
114  |   ++++++++++++++++++++++++++++++++++++++*/
115  | void TH_release_read_lock(rw_lock_t *prw_lock) { 
116  |   pthread_mutex_lock(&prw_lock->rw_mutex);
117  | 
118  |   --prw_lock->rw_count;
119  | 
120  |   if (!prw_lock->rw_count) {
121  |     pthread_cond_signal(&prw_lock->rw_cond);
122  |   }
123  | 
124  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
125  | 
126  | } /* TH_release_read_lock() */
127  | 
128  | /* TH_acquire_write_lock() */
129  | /*++++++++++++++++++++++++++++++++++++++
130  | 
131  |   Aquire a writers lock.
132  | 
133  |   rw_lock_t *prw_lock Readers writers lock.
134  | 
135  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
136  |   More:
137  |   +html+ <PRE>
138  |   Author:
139  |         ottrey
140  |   +html+ </PRE>
141  |   ++++++++++++++++++++++++++++++++++++++*/
142  | void TH_acquire_write_lock(rw_lock_t *prw_lock) { 
143  |   pthread_mutex_lock(&prw_lock->rw_mutex);
144  | 
145  |   while (prw_lock->rw_count != 0) {
146  |     pthread_cond_wait(&prw_lock->rw_cond, &prw_lock->rw_mutex);
147  |   }
148  | 
149  |   prw_lock->rw_count = -1;
150  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
151  | 
152  | } /* TH_acquire_write_lock() */
153  | 
154  | /* TH_release_write_lock() */
155  | /*++++++++++++++++++++++++++++++++++++++
156  | 
157  |   Release a writers lock.
158  | 
159  |   rw_lock_t *prw_lock Readers writers lock.
160  | 
161  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
162  |   More:
163  |   +html+ <PRE>
164  |   Author:
165  |         ottrey
166  |   +html+ </PRE>
167  |   ++++++++++++++++++++++++++++++++++++++*/
168  | void TH_release_write_lock(rw_lock_t *prw_lock) { 
169  |   pthread_mutex_lock(&prw_lock->rw_mutex);
170  |   prw_lock->rw_count = 0;
171  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
172  |   pthread_cond_broadcast(&prw_lock->rw_cond);
173  | 
174  | } /* TH_release_write_lock() */
175  | 
176  | /* TH_init_read_write_lock() */
177  | /*++++++++++++++++++++++++++++++++++++++
178  | 
179  |   Initialize a readers/writers lock.
180  | 
181  |   rw_lock_t *prw_lock Readers writers lock.
182  | 
183  |   Side effect: the lock is set to open(?)
184  | 
185  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
186  |   More:
187  |   +html+ <PRE>
188  |   Author:
189  |         ottrey
190  |   +html+ </PRE>
191  |   ++++++++++++++++++++++++++++++++++++++*/
192  | void TH_init_read_write_lock(rw_lock_t *prw_lock) { 
193  |   pthread_mutex_init(&prw_lock->rw_mutex, NULL);
194  |   pthread_cond_init(&prw_lock->rw_cond, NULL);
195  |   pthread_cond_init(&prw_lock->w_cond, NULL);
196  |   prw_lock->rw_count = 0;
197  |   prw_lock->w_count = 1; /* just in case one uses wrong interface */
198  | 
199  | } /* TH_init_read_write_lock() */
200  | 
201  | /*************************************************
202  | *                                                *
203  | *     Readers Writes Locks that favor WRITERS    *
204  | *                                                *
205  | *************************************************/
206  | /* TH_acquire_read_lockw() */
207  | /*++++++++++++++++++++++++++++++++++++++
208  | 
209  |   Aquire a readers lock.
210  | 
211  |   rw_lock_t *prw_lock Readers writers lock.
212  | 
213  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
214  |   More:
215  |   +html+ <PRE>
216  |   Author:
217  |         ottrey
218  |   +html+ </PRE>
219  |   ++++++++++++++++++++++++++++++++++++++*/
220  | void TH_acquire_read_lockw(rw_lock_t *prw_lock) { 
221  |   pthread_mutex_lock(&prw_lock->rw_mutex);
222  | 
223  |   while (prw_lock->w_count != 0) {
224  |     pthread_cond_wait(&prw_lock->w_cond, &prw_lock->rw_mutex);
225  |   }
226  | 
227  |   ++prw_lock->rw_count;
228  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
229  | 
230  | } /* TH_acquire_read_lockw() */
231  | 
232  | /* TH_release_read_lockw() */
233  | /*++++++++++++++++++++++++++++++++++++++
234  | 
235  |   Release a readers lock.
236  | 
237  |   rw_lock_t *prw_lock Readers writers lock.
238  | 
239  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
240  |   More:
241  |   +html+ <PRE>
242  |   Author:
243  |         ottrey
244  |   +html+ </PRE>
245  |   ++++++++++++++++++++++++++++++++++++++*/
246  | void TH_release_read_lockw(rw_lock_t *prw_lock) { 
247  |   pthread_mutex_lock(&prw_lock->rw_mutex);
248  | 
249  |   --prw_lock->rw_count;
250  | 
251  |   if (!prw_lock->rw_count) {
252  |     pthread_cond_signal(&prw_lock->rw_cond);
253  |   }
254  | 
255  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
256  | 
257  | } /* TH_release_read_lockw() */
258  | 
259  | /* TH_acquire_write_lockw() */
260  | /*++++++++++++++++++++++++++++++++++++++
261  | 
262  |   Aquire a writers lock.
263  | 
264  |   rw_lock_t *prw_lock Readers writers lock.
265  | 
266  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
267  |   More:
268  |   +html+ <PRE>
269  |   Author:
270  |         ottrey
271  |   +html+ </PRE>
272  |   ++++++++++++++++++++++++++++++++++++++*/
273  | void TH_acquire_write_lockw(rw_lock_t *prw_lock) { 
274  |   pthread_mutex_lock(&prw_lock->rw_mutex);
275  | 
276  |  /* check for writers */
277  |   while (prw_lock->w_count != 0) {
278  |     pthread_cond_wait(&prw_lock->w_cond, &prw_lock->rw_mutex);
279  |   }
280  | 
281  |   prw_lock->w_count = 1;
282  |  
283  |  /* wait until all readers are gone */
284  |   while (prw_lock->rw_count != 0) {
285  |     pthread_cond_wait(&prw_lock->rw_cond, &prw_lock->rw_mutex);
286  |   }
287  |  
288  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
289  | 
290  | } /* TH_acquire_write_lockw() */
291  | 
292  | /* TH_release_write_lockw() */
293  | /*++++++++++++++++++++++++++++++++++++++
294  | 
295  |   Release a writers lock.
296  | 
297  |   rw_lock_t *prw_lock Readers writers lock.
298  | 
299  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
300  |   More:
301  |   +html+ <PRE>
302  |   Author:
303  |         ottrey
304  |   +html+ </PRE>
305  |   ++++++++++++++++++++++++++++++++++++++*/
306  | void TH_release_write_lockw(rw_lock_t *prw_lock) { 
307  |   pthread_mutex_lock(&prw_lock->rw_mutex);
308  |   prw_lock->w_count = 0;
309  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
310  |   pthread_cond_broadcast(&prw_lock->w_cond);
311  | 
312  | } /* TH_release_write_lockw() */
313  | 
314  | /* TH_init_read_write_lockw() */
315  | /*++++++++++++++++++++++++++++++++++++++
316  | 
317  |   Initialize a readers/writers lock.
318  | 
319  |   rw_lock_t *prw_lock Readers writers lock.
320  | 
321  |   Side effect: the lock is set to open(?)
322  | 
323  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
324  |   More:
325  |   +html+ <PRE>
326  |   Author:
327  |         ottrey
328  |   +html+ </PRE>
329  |   ++++++++++++++++++++++++++++++++++++++*/
330  | void TH_init_read_write_lockw(rw_lock_t *prw_lock) { 
331  |   pthread_mutex_init(&prw_lock->rw_mutex, NULL);
332  |   pthread_cond_init(&prw_lock->rw_cond, NULL);
333  |   pthread_cond_init(&prw_lock->w_cond, NULL);
334  |   prw_lock->rw_count = 0;
335  |   prw_lock->w_count = 0;
336  | 
337  | } /* TH_init_read_write_lockw() */
338  | 
339  | 
340  | 
341  | /*************************************************
342  | *                                                *
343  | *     Other functions                            *
344  | *                                                *
345  | *************************************************/
346  | 
347  | 
348  | int TH_get_id(void) {
349  | 
350  |   return (int)pthread_self();
351  | 
352  | } /* TH_get_id() */
353  | 
354  | /* TH_to_string() */
355  | char *TH_to_string(void) {
356  |   char *thread_info;
357  |   char tmp[STR_L];
358  |   char thread_info_buffer[STR_XL];
359  | 
360  |   strcpy(thread_info_buffer, "Thread = { ");
361  | 
362  |   sprintf(tmp, "[pthread_self] = \"%d\" ", pthread_self());
363  |   strcat(thread_info_buffer, tmp);
364  |   
365  |   /*
366  |   thread_name = (char *)pthread_getspecific(Name);
367  | 
368  |   if (thread_name == NULL ) {
369  |     sprintf(tmp, "[Name] = \"%s\" ", "didn't work!");
370  |   }
371  |   else {
372  |     sprintf(tmp, "[Name] = \"%s\" ", thread_name);
373  |   }
374  |   strcat(thread_info_buffer, tmp);
375  |   */
376  |   
377  |   strcat(thread_info_buffer, "}");
378  |   
379  |   dieif( wr_malloc((void **)&thread_info, 
380  | 		   strlen(thread_info_buffer)+1) != UT_OK);  
381  | 
382  |   strcpy(thread_info, thread_info_buffer);
383  | 
384  |   return thread_info;
385  | } /* TH_to_string() */
386  | 
387  | 
388  | /*++++++++++++++++++++++++++++++++++++++
389  | 
390  |   This is the routine that creates a thread. 
391  | 
392  |    More:
393  |   +html+ <PRE>
394  |   Author:
395  |         ottrey
396  | 	joao
397  | 	andrei
398  |   +html+ </PRE>
399  |   ++++++++++++++++++++++++++++++++++++++*/
400  | pthread_t TH_create(void *do_function(void *), void *arguments ) {
401  |   pthread_t tid;
402  |   pthread_attr_t attr;
403  |   size_t ssize;
404  |   int ret;
405  | 
406  |     /* Start a new thread. */
407  |     pthread_attr_init(&attr);     /* initialize attr with default attributes */
408  |     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
409  | 
410  | #if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
411  |     defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
412  |     /*********
413  |       For SCO, we need to increase the stack size, because the default is
414  |       exceedingly small.  This also works on FreeBSD.  In Solaris, the
415  |       stack size is 0, which is interpreted as the default, meaning 1
416  |       Mbyte for 32-bit processes or 2 Mbyte for 64-bit processes.
417  |       However, trying to *set* the stack size to 0 results in an error.
418  |       Therefore, we don't want to set the size to 0.  Probably not a good
419  |       idea in any event.  :) Linux doesn't support this function (as of
420  |       the 2.4.2 kernel).
421  | 
422  |       Note: see also modules/sk/cd_watchdog.c
423  |      *********/
424  |     dieif(pthread_attr_getstacksize(&attr, &ssize) != 0);
425  |     if (ssize > 0) {
426  |         dieif(pthread_attr_setstacksize(&attr, ssize * 4) != 0);
427  |     }
428  | #endif
429  | 
430  |     ret = pthread_create(&tid, &attr, do_function, arguments);
431  |     if( ret !=0 ) die;
432  |     pthread_attr_destroy(&attr);
433  | 
434  |     return tid;
435  | 
436  | } /* TH_run() */
437  | 
438  | 
439  |