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 |