1    | /***************************************
2    |   $Revision: 1.29 $
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,2000,2001,2002               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   | 
44   | #include "rip.h"
45   | 
46   | #include <pthread.h>       /* Posix thread library */
47   | #include <stdio.h>
48   | #include <strings.h>
49   | 
50   | //typedef struct th_args {
51   | //	void *function;
52   | //	int sock;
53   | //} th_args;
54   | 
55   | /*************************************************
56   | *                                                *
57   | *     Readers Writes Locks that favor READERS    *
58   | *                                                *
59   | *************************************************/
60   | /* TH_acquire_read_lock() */
61   | /*++++++++++++++++++++++++++++++++++++++
62   | 
63   |   Aquire a readers lock.
64   | 
65   |   rw_lock_t *prw_lock Readers writers lock.
66   | 
67   |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
68   |   More:
69   |   +html+ <PRE>
70   |   Author:
71   |         ottrey
72   |   +html+ </PRE>
73   |   ++++++++++++++++++++++++++++++++++++++*/
74   | void TH_acquire_read_lock(rw_lock_t *prw_lock) { 
75   |   pthread_mutex_lock(&prw_lock->rw_mutex);
76   | 
77   |   while (prw_lock->rw_count < 0) {
78   |     pthread_cond_wait(&prw_lock->rw_cond, &prw_lock->rw_mutex);
79   |   }
80   | 
81   |   ++prw_lock->rw_count;
82   |   pthread_mutex_unlock(&prw_lock->rw_mutex);
83   | 
84   | } /* TH_acquire_read_lock() */
85   | 
86   | /* TH_release_read_lock() */
87   | /*++++++++++++++++++++++++++++++++++++++
88   | 
89   |   Release a readers lock.
90   | 
91   |   rw_lock_t *prw_lock Readers writers lock.
92   | 
93   |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
94   |   More:
95   |   +html+ <PRE>
96   |   Author:
97   |         ottrey
98   |   +html+ </PRE>
99   |   ++++++++++++++++++++++++++++++++++++++*/
100  | void TH_release_read_lock(rw_lock_t *prw_lock) { 
101  |   pthread_mutex_lock(&prw_lock->rw_mutex);
102  | 
103  |   --prw_lock->rw_count;
104  | 
105  |   if (!prw_lock->rw_count) {
106  |     pthread_cond_signal(&prw_lock->rw_cond);
107  |   }
108  | 
109  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
110  | 
111  | } /* TH_release_read_lock() */
112  | 
113  | /* TH_acquire_write_lock() */
114  | /*++++++++++++++++++++++++++++++++++++++
115  | 
116  |   Aquire a writers lock.
117  | 
118  |   rw_lock_t *prw_lock Readers writers lock.
119  | 
120  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
121  |   More:
122  |   +html+ <PRE>
123  |   Author:
124  |         ottrey
125  |   +html+ </PRE>
126  |   ++++++++++++++++++++++++++++++++++++++*/
127  | void TH_acquire_write_lock(rw_lock_t *prw_lock) { 
128  |   pthread_mutex_lock(&prw_lock->rw_mutex);
129  | 
130  |   while (prw_lock->rw_count != 0) {
131  |     pthread_cond_wait(&prw_lock->rw_cond, &prw_lock->rw_mutex);
132  |   }
133  | 
134  |   prw_lock->rw_count = -1;
135  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
136  | 
137  | } /* TH_acquire_write_lock() */
138  | 
139  | /* TH_release_write_lock() */
140  | /*++++++++++++++++++++++++++++++++++++++
141  | 
142  |   Release a writers lock.
143  | 
144  |   rw_lock_t *prw_lock Readers writers lock.
145  | 
146  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
147  |   More:
148  |   +html+ <PRE>
149  |   Author:
150  |         ottrey
151  |   +html+ </PRE>
152  |   ++++++++++++++++++++++++++++++++++++++*/
153  | void TH_release_write_lock(rw_lock_t *prw_lock) { 
154  |   pthread_mutex_lock(&prw_lock->rw_mutex);
155  |   prw_lock->rw_count = 0;
156  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
157  |   pthread_cond_broadcast(&prw_lock->rw_cond);
158  | 
159  | } /* TH_release_write_lock() */
160  | 
161  | /* TH_init_read_write_lock() */
162  | /*++++++++++++++++++++++++++++++++++++++
163  | 
164  |   Initialize a readers/writers lock.
165  | 
166  |   rw_lock_t *prw_lock Readers writers lock.
167  | 
168  |   Side effect: the lock is set to open(?)
169  | 
170  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
171  |   More:
172  |   +html+ <PRE>
173  |   Author:
174  |         ottrey
175  |   +html+ </PRE>
176  |   ++++++++++++++++++++++++++++++++++++++*/
177  | void TH_init_read_write_lock(rw_lock_t *prw_lock) { 
178  |   pthread_mutex_init(&prw_lock->rw_mutex, NULL);
179  |   pthread_cond_init(&prw_lock->rw_cond, NULL);
180  |   pthread_cond_init(&prw_lock->w_cond, NULL);
181  |   prw_lock->rw_count = 0;
182  |   prw_lock->w_count = 1; /* just in case one uses wrong interface */
183  | 
184  | } /* TH_init_read_write_lock() */
185  | 
186  | /*************************************************
187  | *                                                *
188  | *     Readers Writes Locks that favor WRITERS    *
189  | *                                                *
190  | *************************************************/
191  | /* TH_acquire_read_lockw() */
192  | /*++++++++++++++++++++++++++++++++++++++
193  | 
194  |   Aquire a readers lock.
195  | 
196  |   rw_lock_t *prw_lock Readers writers lock.
197  | 
198  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
199  |   More:
200  |   +html+ <PRE>
201  |   Author:
202  |         ottrey
203  |   +html+ </PRE>
204  |   ++++++++++++++++++++++++++++++++++++++*/
205  | void TH_acquire_read_lockw(rw_lock_t *prw_lock) { 
206  |   pthread_mutex_lock(&prw_lock->rw_mutex);
207  | 
208  |   while (prw_lock->w_count != 0) {
209  |     pthread_cond_wait(&prw_lock->w_cond, &prw_lock->rw_mutex);
210  |   }
211  | 
212  |   ++prw_lock->rw_count;
213  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
214  | 
215  | } /* TH_acquire_read_lockw() */
216  | 
217  | /* TH_release_read_lockw() */
218  | /*++++++++++++++++++++++++++++++++++++++
219  | 
220  |   Release a readers lock.
221  | 
222  |   rw_lock_t *prw_lock Readers writers lock.
223  | 
224  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
225  |   More:
226  |   +html+ <PRE>
227  |   Author:
228  |         ottrey
229  |   +html+ </PRE>
230  |   ++++++++++++++++++++++++++++++++++++++*/
231  | void TH_release_read_lockw(rw_lock_t *prw_lock) { 
232  |   pthread_mutex_lock(&prw_lock->rw_mutex);
233  | 
234  |   --prw_lock->rw_count;
235  | 
236  |   if (!prw_lock->rw_count) {
237  |     pthread_cond_signal(&prw_lock->rw_cond);
238  |   }
239  | 
240  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
241  | 
242  | } /* TH_release_read_lockw() */
243  | 
244  | /* TH_acquire_write_lockw() */
245  | /*++++++++++++++++++++++++++++++++++++++
246  | 
247  |   Aquire a writers lock.
248  | 
249  |   rw_lock_t *prw_lock Readers writers lock.
250  | 
251  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
252  |   More:
253  |   +html+ <PRE>
254  |   Author:
255  |         ottrey
256  |   +html+ </PRE>
257  |   ++++++++++++++++++++++++++++++++++++++*/
258  | void TH_acquire_write_lockw(rw_lock_t *prw_lock) { 
259  |   pthread_mutex_lock(&prw_lock->rw_mutex);
260  | 
261  |  /* check for writers */
262  |   while (prw_lock->w_count != 0) {
263  |     pthread_cond_wait(&prw_lock->w_cond, &prw_lock->rw_mutex);
264  |   }
265  | 
266  |   prw_lock->w_count = 1;
267  |  
268  |  /* wait until all readers are gone */
269  |   while (prw_lock->rw_count != 0) {
270  |     pthread_cond_wait(&prw_lock->rw_cond, &prw_lock->rw_mutex);
271  |   }
272  |  
273  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
274  | 
275  | } /* TH_acquire_write_lockw() */
276  | 
277  | /* TH_release_write_lockw() */
278  | /*++++++++++++++++++++++++++++++++++++++
279  | 
280  |   Release a writers lock.
281  | 
282  |   rw_lock_t *prw_lock Readers writers lock.
283  | 
284  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
285  |   More:
286  |   +html+ <PRE>
287  |   Author:
288  |         ottrey
289  |   +html+ </PRE>
290  |   ++++++++++++++++++++++++++++++++++++++*/
291  | void TH_release_write_lockw(rw_lock_t *prw_lock) { 
292  |   pthread_mutex_lock(&prw_lock->rw_mutex);
293  |   prw_lock->w_count = 0;
294  |   pthread_mutex_unlock(&prw_lock->rw_mutex);
295  |   pthread_cond_broadcast(&prw_lock->w_cond);
296  | 
297  | } /* TH_release_write_lockw() */
298  | 
299  | /* TH_init_read_write_lockw() */
300  | /*++++++++++++++++++++++++++++++++++++++
301  | 
302  |   Initialize a readers/writers lock.
303  | 
304  |   rw_lock_t *prw_lock Readers writers lock.
305  | 
306  |   Side effect: the lock is set to open(?)
307  | 
308  |   Reference: "Multithreaded Programming Techniques - Prasad p.192"
309  |   More:
310  |   +html+ <PRE>
311  |   Author:
312  |         ottrey
313  |   +html+ </PRE>
314  |   ++++++++++++++++++++++++++++++++++++++*/
315  | void TH_init_read_write_lockw(rw_lock_t *prw_lock) { 
316  |   pthread_mutex_init(&prw_lock->rw_mutex, NULL);
317  |   pthread_cond_init(&prw_lock->rw_cond, NULL);
318  |   pthread_cond_init(&prw_lock->w_cond, NULL);
319  |   prw_lock->rw_count = 0;
320  |   prw_lock->w_count = 0;
321  | 
322  | } /* TH_init_read_write_lockw() */
323  | 
324  | 
325  | 
326  | /*************************************************
327  | *                                                *
328  | *     Other functions                            *
329  | *                                                *
330  | *************************************************/
331  | 
332  | 
333  | int TH_get_id(void) {
334  | 
335  |   return (int)pthread_self();
336  | 
337  | } /* TH_get_id() */
338  | 
339  | /* TH_to_string() */
340  | char *TH_to_string(void) {
341  |   char tmp[STR_L];
342  |   char thread_info_buffer[STR_XL];
343  | 
344  |   strcpy(thread_info_buffer, "Thread = { ");
345  | 
346  |   sprintf(tmp, "[pthread_self] = \"%lu\" ", (long unsigned)pthread_self());
347  |   strcat(thread_info_buffer, tmp);
348  |   
349  |   /*
350  |   thread_name = (char *)pthread_getspecific(Name);
351  | 
352  |   if (thread_name == NULL ) {
353  |     sprintf(tmp, "[Name] = \"%s\" ", "didn't work!");
354  |   }
355  |   else {
356  |     sprintf(tmp, "[Name] = \"%s\" ", thread_name);
357  |   }
358  |   strcat(thread_info_buffer, tmp);
359  |   */
360  |   
361  |   strcat(thread_info_buffer, "}");
362  |   
363  |   return UT_strdup(thread_info_buffer);
364  | } /* TH_to_string() */
365  | 
366  | 
367  | /*++++++++++++++++++++++++++++++++++++++
368  | 
369  |   This is the routine that creates a thread. 
370  | 
371  |    More:
372  |   +html+ <PRE>
373  |   Author:
374  |         ottrey
375  | 	joao
376  | 	andrei
377  |   +html+ </PRE>
378  |   ++++++++++++++++++++++++++++++++++++++*/
379  | pthread_t TH_create(void *do_function(void *), void *arguments ) {
380  |   pthread_t tid;
381  |   pthread_attr_t attr;
382  |   size_t ssize;
383  |   int ret;
384  | 
385  |     /* Start a new thread. */
386  |     pthread_attr_init(&attr);     /* initialize attr with default attributes */
387  |     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
388  | 
389  | #if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
390  |     defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
391  |     /*********
392  |       For SCO, we need to increase the stack size, because the default is
393  |       exceedingly small.  This also works on FreeBSD.  In Solaris, the
394  |       stack size is 0, which is interpreted as the default, meaning 1
395  |       Mbyte for 32-bit processes or 2 Mbyte for 64-bit processes.
396  |       However, trying to *set* the stack size to 0 results in an error.
397  |       Therefore, we don't want to set the size to 0.  Probably not a good
398  |       idea in any event.  :) Linux doesn't support this function (as of
399  |       the 2.4.2 kernel).
400  | 
401  |       Note: see also modules/sk/cd_watchdog.c
402  |      *********/
403  |     dieif(pthread_attr_getstacksize(&attr, &ssize) != 0);
404  |     if (ssize > 0) {
405  |         dieif(pthread_attr_setstacksize(&attr, ssize * 4) != 0);
406  |     }
407  | #endif
408  | 
409  |     ret = pthread_create(&tid, &attr, do_function, arguments);
410  |     if( ret !=0 ) die;
411  |     pthread_attr_destroy(&attr);
412  | 
413  |     return tid;
414  | 
415  | } /* TH_run() */
416  | 
417  | 
418  |