Thread: Producer/Consumer W/ mutual exclusion

  1. #1
    Registered User
    Join Date
    Apr 2010
    Posts
    58

    Producer/Consumer W/ mutual exclusion

    Edit** new code in post 4
    Last edited by pantherman34; 05-04-2010 at 08:16 AM.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by pantherman34 View Post
    it compiles with no errors but i get a segmentation fault (core dumped) and have no idea why.
    Right now is the time in your life when it is good to learn to use gdb to debug a bit:

    getting a segfault using pointers

    Scroll down to post #7. This will take you about 2 minutes, then you will know WHY you get a seg fault -- or at least, you will know exactly where it happened. And you will be able to figure out WHY very easily forevermore!!!

    The other option is you can wait for me or someone else to copy paste your code, compile it, and run it in a debugger...but that seems a little silly, doesn't it?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Apr 2010
    Posts
    58
    that is very useful, thanks for the info. this is what it said

    Code:
    $ gdb ./a.exe
    GNU gdb 6.8.0.20080328-cvs (cygwin-special)
    Copyright (C) 2008 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "i686-pc-cygwin"...
    (gdb) run
    Starting program: /home/brandon/a.exe
    [New thread 4068.0xa10]
    [New thread 4068.0x794]
    USAGE:./main.out <INT> <INT> <INT>
          2 [main] a 4068 exception::handle: Exception: STATUS_ACCESS_VIOLATION
        369 [main] a 4068 open_stackdumpfile: Dumping stack trace to a.exe.stackdump
    
    
    Program received signal SIGSEGV, Segmentation fault.
    0x6110a694 in _strtol_r () from /usr/bin/cygwin1.dll
    (gdb) bt
    #0 0x6110a694 in _strtol_r () from /usr/bin/cygwin1.dll
    #1 0x7c859f5c in OutputDebugStringA ()
          from /cygdrive/c/WINDOWS/system32/kernel32.dll
    #2 0x40010006 in ?? ()
    #3 0x00000000 in ?? ()
    Last edited by pantherman34; 05-03-2010 at 06:18 PM.

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    This is where you want to use "bt" or "backtrace" as the next command -- that's in that post too

    Actually, I just compiled and ran your code here, I dunno if this might be a factor?
    Code:
    [root/media/sda6/root/C] gcc test.c -lpthread
    [root/media/sda6/root/C] ./a.out
    USAGE:./main.out <INT> <INT> <INT>
    Segmentation fault
    [root/media/sda6/root/C] ./a.out 1 2 3
    Exit the program
    I'm pretty sure it is the issue, since when I did the backtrace the fault is on line 144:
    Code:
       int mainSleepTime = atoi(argv[1]); /* Time in seconds for main to sleep */
    Here's a good gdb tutorial:

    RMS's gdb Tutorial

    To run in gdb with args, use:
    Code:
    (gdb) run 1 2 3
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    If the program is run with argc < 4, then argv[1] through argv[3] do not exist.

    Consider what that means for this code in main() if the program is run with less than 3 command line arguments.
    Code:
     if(argc != 4) {
          fprintf(stderr, "USAGE:./main.out <INT> <INT> <INT>\n");
       }
    
       int mainSleepTime = atoi(argv[1]); /* Time in seconds for main to sleep */
       int numProd = atoi(argv[2]); /* Number of producer threads */
       int numCons = atoi(argv[3]); /* Number of consumer threads */
    The simplest fix is probably to terminate the program if argc is not equal to 4.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User
    Join Date
    Apr 2010
    Posts
    58
    Ok. Here is new code, it was just easier to start over. I am not confused over the "idea" of this producer/consumer problem, but im still confused about threads and semaphores and stuff. this particular program had 4 threads that read or consume from a shared variable. It has 1 thread that writes or produces to that shared variable. All the thread loops need to loop indefinitly which im sure i havent done. and on each loop iteration it requirs 1 second on computation without access to the shared variable.

    And the data output i have in main needs to print report every second. My code has no errors, but it is exiting a 1. i definitely need some help! i tried my best to comment the code as to what is going on.

    Code:
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <semaphore.h>
    
    #define BUFF_SIZE   100	/* total number of slots */
    #define NP          1		/* total number of producers */
    #define NC          4		/* total number of consumers */
    #define NITERS      4		/* number of items produced/consumed */
    
    typedef struct {
        int buf[BUFF_SIZE];   /* shared var */
        int in;         	  /* buf[in%BUFF_SIZE] is the first empty slot */
        int out;        	  /* buf[out%BUFF_SIZE] is the first full slot */
        sem_t full;     	  /* keep track of the number of full spots */
        sem_t empty;    	  /* keep track of the number of empty spots */
        sem_t mutex;    	  /* enforce mutual exclusion to shared data */
    } sbuf_t;
    
    sbuf_t shared;
    
    /* function prototypes */
    void *Producer(void *arg);
    void *Consumer(void *arg);
    
    /* increments and decrements */
    int produced, consumed;
    
    int main()
    {
       /* producer/consumer threads */
        pthread_t idP, idC;
        
        /* loop control */
        int index;
        
        /* temp variables to comp the consumes and produces per hour */
        int temp1, temp2;
    
        /* keeps track of seconds */
        int j = 1;
    
        /* creates semaphores */
        sem_init(&shared.full, 0, 0);
        sem_init(&shared.empty, 0, BUFF_SIZE);
        sem_inti(&shared.mutex, 0, 1);
        
    
        /* creates producer thread */
        for (index = 0; index < NP; index++)
        {  
           /* Create 1 producer */
           pthread_create(&idP, NULL, Producer, (void*)index);
        }
    
        /* creates 4 consumer threads */
        for (index = 0; index < NC; index++)
        {
           pthread_create(&idC, NULL, Consumer, (void*)index);
        }
        
    
        while(1)
        {
           sleep(1);
           sem_wait(&shared.mutex);
           temp1 = (consumed * 3600) / j;
           temp2 = (produced * 3600) / j;
           printf("Statistics after %d seconds: ", j);
           sem_post(&shared.mutex);
           printf("So many consumed per hour: %d\n", temp1);
           printf("So many produced per hour: %d\n", temp2);
           printf("Ratio of consumed/produced per hour: %d", temp1 / temp2);
           j++;
        }
           
    
        sem_destroy(&shared.mutex); // destroy semaphore
        pthread_exit(NULL);
    }
    void *Producer(void *arg)
    {
        int data, index;
    
        index = (int)arg;
    
        printf("Thread %d in line to  produce\n", index);
    
        for (produced=0; produced < NITERS; produced++) {
    
            /* Produce item */
            data = produced;
            printf("[P%d] Producing %d ...\n", index, data); fflush(stdout);
    
           data=produce_item(shared.buf);
    
            /* If there are no empty slots, wait */
            sem_wait(&shared.empty);
            /* If another thread uses the buffer, wait */
            sem_wait(&shared.mutex);
            /* put new item in buffer */
            shared.buf[shared.in] = data;
            shared.in = (shared.in+1)%BUFF_SIZE;
            /* leave the critical region */
            sem_post(&shared.mutex);
            /* Increment the number of full slots */
            sem_post(&shared.full);
    
            /* Interleave  producer and consumer execution */
            if (produced % 2 == 1) sleep(1);
        }
        return NULL;
    }
    
    void *Consumer(void *arg)
    {
       int data, index;
    
        index = (int)arg;
    
        int consumed;
        printf("[C%d] Consuming %d ...\n", index, data); fflush(stdout);
    
        for (consumed=0; consumed < NITERS; consumed++) {
    
            data = consumed;
    
            /* If there are no full slots, wait */
            sem_wait(&shared.full);
            /* If another thread uses the buffer, wait */
            sem_wait(&shared.mutex);
            shared.buf[shared.out] = data;
            shared.out = (shared.out+1)%BUFF_SIZE;
            /* Release the buffer */
            sem_post(&shared.mutex);
            /* Increment the number of empty slots */
            sem_post(&shared.empty);
    
            /* Interleave  producer and consumer execution */
            if (consumed % 2 == 1) sleep(1);
        }
        return NULL;
    }

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> My code has no errors, ...
    >> sem_inti

    Producer/Consumer using mutexs C - CodeGuru Forums

    You seem to be in a hurry - when is it due?

    gg

  8. #8
    Registered User
    Join Date
    Apr 2010
    Posts
    58
    ha yea i caught that mistype in the debug, i thought it was just a warning. and no not in a hurry, just ready to get it finished!

  9. #9
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    http://www.csc.villanova.edu/~mdamian/threads/PC.htm

    >> but it is exiting a 1. i definitely need some help!
    So what exactly is the output you receive - and why it's not what you expected?

    gg

  10. #10
    Registered User
    Join Date
    Apr 2010
    Posts
    58
    Well actually, i have it working now, and it is giving expected results. the ratio isnt working though (dont know why, its very simple unless i have something wrong). it keeps giving me a ratio of 0. the ratio should be .75

    here is some up'd code
    Code:
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <semaphore.h>
    
    #define BUFF_SIZE   100	/* total number of slots */
    #define NP          2		/* total number of producers - 1*/
    #define NC          5		/* total number of consumers - 1 */
    #define NITERS      4		/* number of items produced/consumed */
    
    typedef struct {
        int buf[BUFF_SIZE];   /* shared var */
        int in;         	  /* buf[in%BUFF_SIZE] is the first empty slot */
        int out;        	  /* buf[out%BUFF_SIZE] is the first full slot */
        sem_t full;     	  /* keep track of the number of full spots */
        sem_t empty;    	  /* keep track of the number of empty spots */
        sem_t mutex;    	  /* enforce mutual exclusion to shared data */
    } sbuf_t;
    
    sbuf_t shared;
    
    /* function prototypes */
    void *Producer(void *arg);
    void *Consumer(void *arg);
    
    /* increments and decrements */
    int produced, consumed;
    
    int main()
    {
       /* producer/consumer threads */
        pthread_t idP, idC;
        
        /* loop control */
        int index;
        
        /* temp variables to comp the consumes and produces per hour */
        int temp1, temp2;
        int ratio = temp1 / temp2;
    
        /* keeps track of seconds */
        int j = 1;
    
        /* creates semaphores */
        sem_init(&shared.full, 0, 0);
        sem_init(&shared.empty, 0, BUFF_SIZE);
        sem_init(&shared.mutex, 0, 1);
        
    
        /* creates producer thread */
        for (index = 1; index < NP; index++)
        {  
           /* Create 1 producer */
           pthread_create(&idP, NULL, Producer, (void*)index);
        }
    
        /* creates 4 consumer threads */
        for (index = 1; index < NC; index++)
        {
           pthread_create(&idC, NULL, Consumer, (void*)index);
        }
        
    
        while(1)
        {
           sleep(1);
           sem_wait(&shared.mutex);
           temp1 = (consumed * 3600) / j;
           temp2 = (produced * 3600) / j;
           printf("\n\nStatistics after %d seconds: \n\n", j);
           sem_post(&shared.mutex);
           printf("So many consumed per hour: %d\n", temp1);
           printf("So many produced per hour: %d\n", temp2);
           printf("Ratio of consumed/produced per hour: %d\n", ratio);
           j++;
        }
    
        sem_destroy(&shared.mutex); // destroy semaphore
        pthread_exit(NULL);
    }
    void *Producer(void *arg)
    {
        int data, index;
    
        index = (int)arg;
    
        printf("Thread %d in line to  produce\n\n", index);
    
        for (produced=0; produced < NITERS; produced++) {
    
            /* Produce item */
            data = produced;
            printf("[P%d] Producing %d ...\n\n", index, data); fflush(stdout);
    
          // data=produce_item(shared.buf);
    
            /* If there are no empty slots, wait */
            sem_wait(&shared.empty);
            /* If another thread uses the buffer, wait */
            sem_wait(&shared.mutex);
            /* put new item in buffer */
            shared.buf[shared.in] = data;
            shared.in = (shared.in+1)%BUFF_SIZE;
            /* leave the critical region */
            sem_post(&shared.mutex);
            /* Increment the number of full slots */
            sem_post(&shared.full);
    
            /* Interleave  producer and consumer execution */
            if (produced % 2 == 1) sleep(1);
        }
        return NULL;
    }
    
    void *Consumer(void *arg)
    {
       int data, index;
    
        index = (int)arg;
    
        printf("[C%d] Consuming %d ...\n", index, data); fflush(stdout);
    
        for (consumed=0; consumed < NITERS; consumed++) {
    
            data = consumed;
    
            /* If there are no full slots, wait */
            sem_wait(&shared.full);
            /* If another thread uses the buffer, wait */
            sem_wait(&shared.mutex);
            shared.buf[shared.out] = data;
            shared.out = (shared.out+1)%BUFF_SIZE;
            /* Release the buffer */
            sem_post(&shared.mutex);
            /* Increment the number of empty slots */
            sem_post(&shared.empty);
    
            /* Interleave  producer and consumer execution */
            if (consumed % 2 == 1) sleep(1);
        }
        return NULL;
    }

  11. #11
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    First, you have unsynchronized access to "produced" and "consumed". Use local variables for the for loop and put the "total produced" and "total consumed" as members of sbuf_t - and only access them while mutex is held.

    You calculate temp1 and temp2 in the while loop, but not "ratio". You're also performing integer arithmetic (3/2 = 1).
    Change temp1, temp2, and ratio to float:
    Code:
    temp1 = (consumed * 3600.0f) / j;
    temp2 = (produced * 3600.0f) / j;
    ratio = temp1 / temp2;
    Then use %f instead of %d in printf.

    >> the ratio should be .75
    So for a given point in time, there should be 3 consumed for every 4 produced? Why is that?

    With 4 threads consuming and only 1 producing, production shouldn't out-pace consumption. So the ratio should pretty much stay at 1.

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Mutual Exclusion and Running a Single Copy [open,lockf,getpid]
    By hosseinyounesi in forum Linux Programming
    Replies: 11
    Last Post: 09-23-2009, 02:16 AM
  2. Replies: 4
    Last Post: 09-14-2008, 06:17 PM
  3. Mutual exclusion with threads
    By axr0284 in forum C++ Programming
    Replies: 10
    Last Post: 12-21-2005, 08:31 AM
  4. Mutual Exclusion Locks
    By sglass in forum C Programming
    Replies: 3
    Last Post: 03-21-2002, 01:31 PM
  5. Mutual linking
    By Mox in forum C++ Programming
    Replies: 2
    Last Post: 08-28-2001, 06:26 AM