Source File th/thread.c

    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  |