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 |