1 | /*************************************** 2 | $Revision: 1.30 $ 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(SCO) 390 | /********* 391 | For SCO, we need to increase the stack size, because the default is 392 | exceedingly small. 393 | 394 | Note: see also modules/sk/cd_watchdog.c 395 | *********/ 396 | dieif(pthread_attr_getstacksize(&attr, &ssize) != 0); 397 | if (ssize > 0) { 398 | dieif(pthread_attr_setstacksize(&attr, ssize * 4) != 0); 399 | } 400 | #endif 401 | 402 | ret = pthread_create(&tid, &attr, do_function, arguments); 403 | if( ret !=0 ) die; 404 | pthread_attr_destroy(&attr); 405 | 406 | return tid; 407 | 408 | } /* TH_run() */ 409 | 410 | 411 |