modules/th/thread.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- log_print
- TH_acquire_read_lock
- TH_release_read_lock
- TH_acquire_write_lock
- TH_release_write_lock
- TH_init_read_write_lock
- TH_get_id
- TH_to_string
- TH_do_whois
- TH_do_config
- main_thread
- TH_run
/***************************************
$Revision: 1.6 $
Example code: A thread.
Status: NOT REVUED, NOT TESTED
Authors: Chris Ottrey
Joao Damas
+html+ <DL COMPACT>
+html+ <DT>Online References:
+html+ <DD><UL>
+html+ </UL>
+html+ </DL>
******************/ /******************
Modification History:
ottrey (02/03/1999) Created.
ottrey (08/03/1999) Modified.
ottrey (17/06/1999) Stripped down.
joao (22/06/1999) Redid thread startup
******************/ /******************
Copyright (c) 1999 RIPE NCC
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of the author not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
***************************************/
#include "thread.h"
#include <stdio.h>
#include "protocol_config.h"
#include "constants.h"
/*+ String sizes +*/
#define STR_S 63
#define STR_M 255
#define STR_L 1023
#define STR_XL 4095
#define STR_XXL 16383
/*+ Mutex lock. Used for synchronizing changes. +*/
pthread_mutex_t Whois_thread_count_lock;
pthread_mutex_t Config_thread_count_lock;
pthread_mutex_t Mirror_thread_count_lock;
/*+ The number of threads. +*/
int Whois_thread_count;
int Config_thread_count;
int Mirror_thread_count;
typedef struct th_args {
void * function;
int sock;
} th_args;
static void log_print(const char *arg) {
/* [<][>][^][v][top][bottom][index][help] */
FILE *logf;
char *str;
if (CO_get_thread_logging() == 1) {
if (strcmp(CO_get_thread_logfile(), "stdout") == 0) {
printf(arg);
}
else {
logf = fopen(CO_get_thread_logfile(), "a");
fprintf(logf, arg);
fclose(logf);
}
}
} /* log_print() */
/* TH_acquire_read_lock() */
/*++++++++++++++++++++++++++++++++++++++
Aquire a readers lock.
rw_lock_t *prw_lock Readers writers lock.
Reference: "Multithreaded Programming Techniques - Prasad p.192"
More:
+html+ <PRE>
Author:
ottrey
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
void TH_acquire_read_lock(rw_lock_t *prw_lock) {
/* [<][>][^][v][top][bottom][index][help] */
pthread_mutex_lock(&prw_lock->rw_mutex);
while (prw_lock->rw_count < 0) {
pthread_cond_wait(&prw_lock->rw_cond, &prw_lock->rw_mutex);
}
++prw_lock->rw_count;
pthread_mutex_unlock(&prw_lock->rw_mutex);
} /* TH_acquire_read_lock() */
/* TH_release_read_lock() */
/*++++++++++++++++++++++++++++++++++++++
Release a readers lock.
rw_lock_t *prw_lock Readers writers lock.
Reference: "Multithreaded Programming Techniques - Prasad p.192"
More:
+html+ <PRE>
Author:
ottrey
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
void TH_release_read_lock(rw_lock_t *prw_lock) {
/* [<][>][^][v][top][bottom][index][help] */
pthread_mutex_lock(&prw_lock->rw_mutex);
--prw_lock->rw_count;
if (!prw_lock->rw_count) {
pthread_cond_signal(&prw_lock->rw_cond);
}
pthread_mutex_unlock(&prw_lock->rw_mutex);
} /* TH_release_read_lock() */
/* TH_acquire_write_lock() */
/*++++++++++++++++++++++++++++++++++++++
Aquire a writers lock.
rw_lock_t *prw_lock Readers writers lock.
Reference: "Multithreaded Programming Techniques - Prasad p.192"
More:
+html+ <PRE>
Author:
ottrey
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
void TH_acquire_write_lock(rw_lock_t *prw_lock) {
/* [<][>][^][v][top][bottom][index][help] */
pthread_mutex_lock(&prw_lock->rw_mutex);
while (prw_lock->rw_count != 0) {
pthread_cond_wait(&prw_lock->rw_cond, &prw_lock->rw_mutex);
}
prw_lock->rw_count = -1;
pthread_mutex_unlock(&prw_lock->rw_mutex);
} /* TH_acquire_write_lock() */
/* TH_release_write_lock() */
/*++++++++++++++++++++++++++++++++++++++
Release a writers lock.
rw_lock_t *prw_lock Readers writers lock.
Reference: "Multithreaded Programming Techniques - Prasad p.192"
More:
+html+ <PRE>
Author:
ottrey
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
void TH_release_write_lock(rw_lock_t *prw_lock) {
/* [<][>][^][v][top][bottom][index][help] */
pthread_mutex_lock(&prw_lock->rw_mutex);
prw_lock->rw_count = 0;
pthread_mutex_unlock(&prw_lock->rw_mutex);
pthread_cond_broadcast(&prw_lock->rw_cond);
} /* TH_release_write_lock() */
/* TH_init_read_write_lock() */
/*++++++++++++++++++++++++++++++++++++++
Initialize a readers/writers lock.
rw_lock_t *prw_lock Readers writers lock.
Reference: "Multithreaded Programming Techniques - Prasad p.192"
More:
+html+ <PRE>
Author:
ottrey
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
void TH_init_read_write_lock(rw_lock_t *prw_lock) {
/* [<][>][^][v][top][bottom][index][help] */
mutex_init(&prw_lock->rw_mutex, NULL);
cond_init(&prw_lock->rw_cond, NULL);
prw_lock->rw_count = 0;
} /* TH_init_read_write_lock() */
int TH_get_id(void) {
/* [<][>][^][v][top][bottom][index][help] */
return (int)pthread_self();
} /* TH_get_id() */
/* TH_to_string() */
char *TH_to_string(void) {
/* [<][>][^][v][top][bottom][index][help] */
char *thread_info;
char tmp[STR_L];
char thread_info_buffer[STR_XL];
char *thread_name;
strcpy(thread_info_buffer, "Thread = { ");
sprintf(tmp, "[pthread_self] = \"%d\" ", pthread_self());
strcat(thread_info_buffer, tmp);
/*
thread_name = (char *)pthread_getspecific(Name);
if (thread_name == NULL ) {
sprintf(tmp, "[Name] = \"%s\" ", "didn't work!");
}
else {
sprintf(tmp, "[Name] = \"%s\" ", thread_name);
}
strcat(thread_info_buffer, tmp);
*/
strcat(thread_info_buffer, "}");
thread_info = (char *)calloc(1, strlen(thread_info_buffer)+1);
strcpy(thread_info, thread_info_buffer);
return thread_info;
} /* TH_to_string() */
/* TH_do_whois() */
/*++++++++++++++++++++++++++++++++++++++
Handle whois connections.
void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
More:
+html+ <PRE>
Author:
joao
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
void TH_do_whois(void *arg) {
/* [<][>][^][v][top][bottom][index][help] */
int sock = (int)arg;
char print_buf[STR_M];
sprintf(print_buf, "Whois: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
/* Use a mutex to update the global whois thread counter. */
pthread_mutex_lock(&Whois_thread_count_lock);
Whois_thread_count++;
sprintf(print_buf, "Whois_thread_count++=%d\n", Whois_thread_count); log_print(print_buf); strcpy(print_buf, "");
pthread_mutex_unlock(&Whois_thread_count_lock);
PW_interact(sock);
/* Use a mutex to update the global whois thread counter. */
pthread_mutex_lock(&Whois_thread_count_lock);
Whois_thread_count--;
sprintf(print_buf, "Whois_thread_count--=%d\n", Whois_thread_count); log_print(print_buf); strcpy(print_buf, "");
pthread_mutex_unlock(&Whois_thread_count_lock);
pthread_exit((void *)0);
} /* TH_do_whois() */
/* TH_do_config() */
/*++++++++++++++++++++++++++++++++++++++
Handle config connections.
void *arg The socket to connect to. (It has to be passed in this way for this
thread routine.)
More:
+html+ <PRE>
Author:
joao
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
void TH_do_config(void *arg) {
/* [<][>][^][v][top][bottom][index][help] */
int sock = (int)arg;
char print_buf[STR_M];
sprintf(print_buf, "Config: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
/*
printf("Hi there, there is nothing to configure yet\nBye..... :-)\n");
fflush(NULL);
SK_close(sock);
*/
PC_interact(sock);
pthread_exit((void *)0);
} /* TH_do_config() */
/* main_thread() */
/*++++++++++++++++++++++++++++++++++++++
Waits for an incoming connection on the and spawns a new thread to handle it.
void *arg Pointer to a struct containing the socket to talk to the client and
the function to call depending on the incoming connection.
More:
+html+ <PRE>
Author:
ottrey
joao
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
static void *main_thread(void *arg) {
/* [<][>][^][v][top][bottom][index][help] */
th_args *args = (th_args *)arg;
pthread_t tid;
pthread_attr_t attr;
int connected_socket;
while(1) {
connected_socket = SK_accept_connection(args->sock);
/* Start a new thread. */
pthread_attr_init(&attr); /* initialize attr with default attributes */
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, (void *(*)(void *))(args->function), (void *)connected_socket);
}
} /* main_thread() */
/* TH_run() */
/*++++++++++++++++++++++++++++++++++++++
This is the routine that creates the main threads.
int sock The socket to connect to.
void * do_function The function to call for each type of service
More:
+html+ <PRE>
Author:
ottrey
joao
+html+ </PRE>
++++++++++++++++++++++++++++++++++++++*/
void TH_run(int sock, void *do_function) {
/* [<][>][^][v][top][bottom][index][help] */
th_args *args;
pthread_t tid;
pthread_attr_t attr;
char print_buf[STR_M];
int connected_socket;
args = (th_args *)calloc(1,sizeof(th_args));
args->function=do_function;
args->sock=sock;
/* pthread_mutex_init(&Whois_thread_count_lock,NULL); */
if ( CO_get_max_threads() == 0 ) {
sprintf(print_buf, "Running with no threads\n"); log_print(print_buf); strcpy(print_buf, "");
connected_socket = SK_accept_connection(sock);
PW_interact(connected_socket);
}
else {
/* Start a new thread. */
pthread_attr_init(&attr); /* initialize attr with default attributes */
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, main_thread, (void *)args);
}
} /* TH_run() */