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 |