Source File modules/th/thread.c

    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  |