Topic : Multi-Threaded Programming
Author : LUPG
Page : << Previous 8  Next >>
Go to page :


still cannot be invoked at the same time by seperate threads. The second thread will be blocked on the mutex until the first thread finishes the function call. You might call for using seperate mutexes for unrelated functions, but usually you've no idea how the library really works and thus cannot know which functions access the same set of resources. More then that, even if you do know that, a new version of the library might behave differently, forcing you to modify your whole locking system.

As you can see, non-MT-safe libraries need special attention, so it is best to find MT-safe libraries with a similar functionality, if possible.




Using A Threads-Aware Debugger

One last thing to note - when debugging a multi-threaded application, one needs to use a debugger that "sees" the threads in the program. Most up-to-date debuggers that come with commercial development environments are thread-aware. As for Linux, gdb as is shiped with most (all?) distributions seems to be not thread-aware. There is a project, called 'SmartGDB', that added thread support to gdb, as well as a graphical user interface (which is almost a must when debugging multi-threaded applications). However, it may be used to debug only multi-threaded applications that use the various user-level thread libraries. Debugging LinuxThreads with SmartGDB requires applying some kernel patches, that are currently available only for Linux kernels from the 2.1.X series. More information about this tool may be found at http://hegel.ittc.ukans.edu/projects/smartgdb/. There is also some information about availability of patches to the 2.0.32 kernel and gdb 4.17. This information may be found on the LinuxThreads homepage (http://pauillac.inria.fr/~xleroy/linuxthreads/).




Side-Notes

water-marks algorithm

An algorithm used mostly when handling buffers or queues: start filling in the queue. If its size exceeds a threshold, known as the high water-mark, stop filling the queue (or start emptying it faster). Keep this state until the size of the queue becomes lower then another threshold, known as the low water-mark. At this point, resume the operation of filling the queue (or return the emptying speed to the original speed).




pthread_create.c


#include <stdio.h>       /* standard I/O routines                 */
#include <pthread.h>     /* pthread functions and data structures */

/* function to be executed by the new thread */
void*
do_loop(void* data)
{
    int i;   /* counter, to print numbers */
    int j;   /* counter, for delay        */
    int me = *((int*)data);     /* thread identifying number */

    for (i=0; i<10; i++) {
 for (j=0; j<500000; j++) /* delay loop */
     ;
        printf("'%d' - Got '%d'\n", me, i);
    }

    /* exit the thread */
    pthread_exit(NULL);
}

/* like any C program, program's execution begins in main */
int
main(int argc, char* argv[])
{
    int        thr_id;         /* thread ID for the newly created thread */
    pthread_t  p_thread;       /* thread's structure                     */
    int        a         = 1;  /* thread 1 identifying number            */
    int        b         = 2;  /* thread 2 identifying number            */

    /* create a new thread that will execute 'do_loop()' */
    thr_id = pthread_create(&p_thread, NULL, do_loop, (void*)&a);
    /* run 'do_loop()' in the main thread as well */
    do_loop((void*)&b);
    
    /* NOT REACHED */
    return 0;
}





employee-with-mutex.c


#include <stdio.h>       /* standard I/O routines                 */
#include <pthread.h>     /* pthread functions and data structures */

#define NUM_EMPLOYEES 2                   /* size of each array.    */

/* global mutex for our program. assignment initializes it */
pthread_mutex_t a_mutex = PTHREAD_MUTEX_INITIALIZER;

struct employee {
    int number;
    int id;
    char first_name[20];
    char last_name[30];
    char department[30];
    int room_number;
};

/* global variable - our employees array, with 2 employees */
struct employee employees[] = {
    { 1, 12345678, "danny", "cohen", "Accounting", 101},
    { 2, 87654321, "moshe", "levy", "Programmers", 202}
};

/* global variable - employee of the day. */
struct employee employee_of_the_day;

/* function to copy one employee struct into another */
void
copy_employee(struct employee* from, struct employee* to)
{
    int rc; /* contain mutex lock/unlock results */

    /* lock the mutex, to assure exclusive access to 'a' and 'b'. */
    rc = pthread_mutex_lock(&a_mutex);

    to->number = from->number;
    to->id = from->id;
    strcpy(to->first_name, from->first_name);
    strcpy(to->last_name, from->last_name);
    strcpy(to->department, from->department);
    to->room_number = from->room_number;

    /* unlock mutex */
    rc = pthread_mutex_unlock(&a_mutex);
}

/* function to be executed by the variable setting threads thread */
void*
do_loop(void* data)
{
    int my_num = *((int*)data);   /* thread identifying number         */

    while (1) {
        /* set employee of the day to be the one with number 'my_num'. */
 copy_employee(&employees[my_num-1], &employee_of_the_day);
    }
}

/* like any C program, program's execution begins in main */
int
main(int argc, char* argv[])
{
    int        i;              /* loop counter                          */
    int        thr_id1;        /* thread ID for the first new thread    */
    int        thr_id2;        /* thread ID for the second new thread   */
    pthread_t  p_thread1;      /* first thread's structure              */
    pthread_t  p_thread2;      /* second thread's structure             */
    int        num1      = 1;  /* thread 1 employee number              */
    int        num2      = 2;  /* thread 2 employee number              */
    struct employee eotd;      /* local copy of 'employee of the day'.  */
    struct employee* worker;   /* pointer to currently checked employee */

    /* initialize employee of the day to first 1. */
    copy_employee(&employees[0], &employee_of_the_day);

    /* create a new thread that will execute 'do_loop()' with '1'       */
    thr_id1 = pthread_create(&p_thread1, NULL, do_loop, (void*)&num1);
    /* create a second thread that will execute 'do_loop()' with '2'    */
    thr_id2 = pthread_create(&p_thread2, NULL, do_loop, (void*)&num2);

    /* run a loop that verifies integrity of 'employee of the day' many */
    /* many many times.....                                             */
    for (i=0; i<60000; i++) {
        /* save contents of 'employee of the day' to local 'worker'.    */
        copy_employee(&employee_of_the_day, &eotd);
 worker = &employees[eotd.number-1];

  


Page : << Previous 8  Next >>