Thread: HELP! Multiple threads access to global variables

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    5

    HELP! Multiple threads access to global variables

    I'm trying to solve the producer consumer problem for multiple producers and consumers using a multi slot buffer.

    I am using a mutex to ensure mutual exclusion when the producer and consumers are accessing the buffers, and a conditional variable to block when the buffer is full or empty.

    The globals are buffer, which is an array of struct 'data' and buffercount, which is an int to keep track of the size of buffer.

    However, I cannot access the variables and my threads stall. This can be seen because though in the producer thread, i create the data and get into the function writeData, which writes the data to the buffer, I cannot print the values of count or write to the buffer in that function, it just stops.

    Below is my code:

    Code:
    #include <pthread.h>
    #include <semaphore.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    typedef struct{
    int x,y,z;
    }data;
    
    volatile data buffer[20];
    volatile int count;
    pthread_mutex_t m;
    pthread_cond_t qu_empty_cond = PTHREAD_COND_INITIALIZER;
    pthread_cond_t qu_full_cond = PTHREAD_COND_INITIALIZER;
    
    
    
    void produce();
    void consume();
    void createData(data*);
    void writeBuffer(data);
    void readBuffer(data*);
    void waitRandom();
    void shiftBuffer();
    
    
    int main (){
    pthread_t p, c;
    count = 0;
    
    if(pthread_mutex_init(&m, NULL)){
            printf("mutex creation failed\n");
            return 1;
    }
    else printf("mutex creation sucess\n");
    
    if(pthread_create (&p,NULL,(void *) &produce,NULL)){
            printf("producer creation failed\n");
            return 1;
    }
    
    if (pthread_create (&c,NULL,(void *) &consume,NULL)){
            printf("consumer creation failed\n");
            return 1;
    }
    
    return 0;
    }
    
    void produce(void){
    printf("producer creation success count\n");
    while(1){
            data a;
            createData(&a);
            printf("PRODUCE: checking for mutual exclusion\n");
            pthread_mutex_lock(&m);
            printf("have mutual exclusion to produce\n");
            //if 20 block
    
            /*while(count>=20){
                    printf("stuck \n");
                    pthread_cond_wait(&qu_full_cond, &m);
                    }*/
            writeBuffer(a);
            //increment
            count++;
            if(count=1)
    pthread_cond_signal(&qu_empty_cond);
            pthread_mutex_unlock(&m);
            printf("lost mutual exclusion to produce\n");
            waitRandom();
            }
    }
    
    void consume(void){
    printf("consumer creation success \n");
    while(1){
            data a;
            printf("CONSUME: checking for mutual exclusion\n");
            pthread_mutex_lock(&m);
            printf("have mutual exclusion to consume\n");
            //if 0 block
            while(count<=0){
                    printf("stuck\n");
                    waitRandom();
                    pthread_cond_wait(&qu_empty_cond, &m);
                    }
            readBuffer(&a);
            shiftBuffer();
            count--;
            //if 19 release
            if(count=19)
                    pthread_cond_signal(&qu_full_cond);
            pthread_mutex_unlock(&m);
            printf("lost mutual exclusion to consume\n");
            waitRandom();
            }
    }
    
    
    
    void createData(data* a){
            printf("creating data\n");
            a->x=1;
            a->y=2;
            a->z=3;
    }
    
    void writeBuffer(data a){
            printf("inthefunction1111\n");
            printf("writing to buffer slot %d, new size of buffer is %d\n", count, count+1);
            buffer[count] = a;
            printf("%d      %d      %d",buffer[count].x,buffer[count].y,buffer[count].z);
    }
    
    void readBuffer(data* a){
            printf("reading buffer slot 0 \n");
            a->x = buffer[0].x;
            a->y = buffer[0].y;
            a->z = buffer[0].z;
    }
    
    void shiftBuffer(void){
            int i;
            printf("deleting buffer slot 0 \n");
            for(i=0;i<count;i++)
                    buffer[i]=buffer[i+1];
    }
    
    void waitRandom(void){
            srand ( time(NULL) );
            sleep(rand()%2000 + 1000 );
    }
    Last edited by thilar; 10-29-2012 at 03:16 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Do NOT ignore the return values from function!
    pthread_mutex_lock

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  4. #4
    Registered User
    Join Date
    Oct 2012
    Posts
    5
    Sorry for the double post, I thought both forums seemed like good bets to find someone who could help. Stahta01 I'll make the changes your suggested and keep you posted.

  5. #5
    Registered User
    Join Date
    Oct 2012
    Posts
    5
    I added lines to check the return argument of the mutex lock. I also added unistd.h for the sleep call and fixed the if statements to block for full and empty buffers with == instead of just =. however I am still having the same problems.....

    below is the code

    Code:
    #include <pthread.h>
    #include <semaphore.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <unistd.h>
    
    typedef struct{
    int x,y,z;
    }data;
    
    volatile data buffer[20];
    volatile int count;
    pthread_mutex_t m;
    pthread_cond_t qu_empty_cond = PTHREAD_COND_INITIALIZER;
    pthread_cond_t qu_full_cond = PTHREAD_COND_INITIALIZER;
    
    
    
    void produce();
    void consume();
    void createData(data*);
    void writeBuffer(data);
    void readBuffer(data*);
    void waitRandom();
    void shiftBuffer();
    
    
    int main (){
    pthread_t p, c;
    count = 0;
    
    if(pthread_mutex_init(&m, NULL)){
            printf("mutex creation failed\n");
            return 1;
    }
    else printf("mutex creation sucess\n");
    
    if(pthread_create (&p,NULL,(void *) &produce,NULL)){
            printf("producer creation failed\n");
            return 1;
    }
    
    if (pthread_create (&c,NULL,(void *) &consume,NULL)){
            printf("consumer creation failed\n");
            return 1;
    }
    
    return 0;
    }
    
    void produce(void){
    printf("producer creation success count\n");
    while(1){
            data a;
            createData(&a);
            printf("PRODUCE: checking for mutual exclusion\n");
            if(pthread_mutex_lock(&m))
                    printf("MUTEX lock in PRODUCER failed, blocking until MUTEX is available \n");
            else
            printf("have mutual exclusion to produce\n");
            //if 20 block
            /*while(count>=20){
                    printf("stuck \n");
                    pthread_cond_wait(&qu_full_cond, &m);
                    }*/
            writeBuffer(a);
            //increment
            count++;
            if(count==1)
                    pthread_cond_signal(&qu_empty_cond);
            pthread_mutex_unlock(&m);
            printf("lost mutual exclusion to produce\n");
            waitRandom();
            }
    }
    
    void consume(void){
    printf("consumer creation success \n");
    while(1){
            data a;
            printf("CONSUME: checking for mutual exclusion\n");
            if(pthread_mutex_lock(&m))
                    printf("MUTEX lock in CONSUMER failed, blocking until MUTEX is available \n");
            else
                    printf("have mutual exclusion to consume\n");
            //if 0 block
            while(count<=0){
                    printf("stuck\n");
                    waitRandom();
                    pthread_cond_wait(&qu_empty_cond, &m);
                    }
            readBuffer(&a);
            shiftBuffer();
            count--;
            //if 19 release
            if(count==19)
                    pthread_cond_signal(&qu_full_cond);
            pthread_mutex_unlock(&m);
            printf("lost mutual exclusion to consume\n");
            waitRandom();
            }
    }
    
    
    
    void createData(data* a){
            printf("creating data\n");
            a->x=1;
            a->y=2;
            a->z=3;
    }
    
    void writeBuffer(data a){
            printf("inthefunction1111\n");
            printf("writing to buffer slot %d, new size of buffer is %d\n", count, count+1);
            buffer[count] = a;
            printf("%d      %d      %d",buffer[count].x,buffer[count].y,buffer[count].z);
    }
    
    void readBuffer(data* a){
            printf("reading buffer slot 0 \n");
            a->x = buffer[0].x;
            a->y = buffer[0].y;
            a->z = buffer[0].z;
    }
    
    void shiftBuffer(void){
            int i;
            printf("deleting buffer slot 0 \n");
            for(i=0;i<count;i++)
                    buffer[i]=buffer[i+1];
    }
    
    void waitRandom(void){
            srand ( time(NULL) );
            sleep(rand()%2000 + 1000 );
    }

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    I suggest re-reading the directions; I see no where it says that pthread_mutex_lock calls does blocking.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  7. #7
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by stahta01 View Post
    I suggest re-reading the directions; I see no where it says that pthread_mutex_lock calls does blocking.

    Tim S.
    From the link you posted:
    The mutex object referenced by mutex is locked by calling pthread_mutex_lock(). If the mutex is already locked, the calling thread blocks until the mutex becomes available.
    Of course, if there's an error it returns a non-zero value and errno contains the error number, and it obviously doesn't block in that case. The code as posted doesn't properly handle that case.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by stahta01 View Post
    I suggest re-reading the directions; I see no where it says that pthread_mutex_lock calls does blocking.

    Tim S.
    Blocking is the whole point of a mutex.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Registered User
    Join Date
    Oct 2012
    Posts
    5
    Yes, I fairly sure the mutex works. The problem is accessing the global variables count and buffer. Specifically in the function writeBuffer, called by the first producer, the printf"in the function11111" is printed, yet the following line one 116 "printf("writing to buffer slot %d, new size of buffer is %d\n", count, count+1);" IS NOT

  10. #10
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    These lines,
    Quote Originally Posted by thilar View Post
    Code:
            if(pthread_mutex_lock(&m))
                    printf("MUTEX lock in PRODUCER failed, blocking until MUTEX is available \n");
    Code:
            if(pthread_mutex_lock(&m))
                    printf("MUTEX lock in CONSUMER failed, blocking until MUTEX is available \n");
    do not do what the print statements say.

    pthread_mutex_lock() returns 0 if it was successful, EINVAL (defined in errno.h) if the mutex was not properly initialized, or EDEADLK if you have a deadlock.

    When pthread_mutex_lock() returns nonzero, you have a bug in your program. Either the mutex is uninitialized, or you have a deadlock: some other thread already holding this mutex, while waiting on another mutex this thread already has locked. The proper thing to do when this happens is to end the thread by returning from the thread function.

    Your code, however, lies to the user if an errors occurs. It claims to block, while in reality, the code just forges on!

    The fact that pthread_mutex_lock() will block only means that the function may take an indefinitely long time for it to return. It does not mean that it does some kind of magic afterwards, as your print statements imply.

  11. #11
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by thilar View Post
    the printf"in the function11111" is printed, yet the following line one 116 "printf("writing to buffer slot %d, new size of buffer is %d\n", count, count+1);" IS NOT
    You have a printf without a trailing newline there. In that case, the C library is especially greedy in caching the output. So, it will only be output when the next printf occurs.

    Make sure all your lines end with a newline, and add fflush(stdout); to the points you need to make everything sent to standard output is actually output, instead of just sitting cached somewhere waiting for the next output command.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Global Access to Global Class without so many pointers
    By parad0x13 in forum C++ Programming
    Replies: 1
    Last Post: 11-11-2009, 02:48 PM
  2. static global & global variables
    By aqeel in forum C Programming
    Replies: 1
    Last Post: 09-25-2009, 12:32 PM
  3. Replies: 5
    Last Post: 08-06-2008, 09:59 AM
  4. a point of threads to create multiple threads
    By v3dant in forum C Programming
    Replies: 3
    Last Post: 10-06-2004, 09:48 AM
  5. Threads and global variables
    By Spark in forum C Programming
    Replies: 8
    Last Post: 05-29-2002, 02:08 PM