modules/th/thread.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- TH_acquire_read_lock
- TH_release_read_lock
- TH_acquire_write_lock
- TH_release_write_lock
- TH_init_read_write_lock
- TH_acquire_read_lockw
- TH_release_read_lockw
- TH_acquire_write_lockw
- TH_release_write_lockw
- TH_init_read_write_lockw
- TH_get_id
- TH_to_string
- TH_create
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
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) {
/* [<][>][^][v][top][bottom][index][help] */
349
350 return (int)pthread_self();
351
352 } /* TH_get_id() */
353
354 /* TH_to_string() */
355 char *TH_to_string(void) {
/* [<][>][^][v][top][bottom][index][help] */
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 ) {
/* [<][>][^][v][top][bottom][index][help] */
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