Thread: struct type, requires a pointer (needpointer)

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    8

    Thumbs up struct type, requires a pointer (needpointer)

    Hello C programmers! I'm a novice programmer about to graduate as long as I can complete this assignment by 10:00 AM tomorrow.

    The assignment is a solution to the producer-consumer problem using a bounded buffer and multiple processes (as opposed to threads, which I had to do in an earlier assignment). Unfortunately for me, the assignments in this class are written in C, a language I don't fully understand as much as my peers (my University started teaching beginning programming classes in C the semester after I was finished with them, I learned in Java).

    Anyway, to the problem. The program is to take in a file using stdin, and use multiple processes to rearrange the lines of the file based on the line number at the beginning of each line (they are currently out of order).

    The producer takes each line, and creates a struct "item" which has an int id and a char[] str. It then places the item in the bounded buffer for the consumer to use. I will include the code for each module of the program, but the errors all seem to come from producer.c, where my curItem to which I try and assign values from the file keeps coming up with a needpointer error.

    Also, I haven't yet successfully compiled it, so I'm not sure if the output will be what I want, so if you can catch any other errors and let me know that would be greatly appreciated.

    producer.c
    Code:
    #include "assign5.h"
    
    
    /* Global variables for producer.c */
       pid_t prodid;      /* Producer Process Id */
       void *shmptr;      /* pointer to shared memory returned by shmget() */
       shr_mem_t *sp;     /* pointer to shared memory structure */
       int shmid;         /* shared memory ID number */
       sem_t *MUTEXptr;   /* pointer to the MUTEX semaphore */
       sem_t *EMPTYptr;   /* pointer to the EMPTY semaphore */
       sem_t *FULLptr;    /* pointer to the FULL semaphore  */
    
    
    /*******************************************************************/
    /* Function to cleanup before exiting                              */
    /*******************************************************************/
    void cleanup_on_exit()
    {
    /* Only detach shared memory.  Parent will remove it from system */ 
    /* Don't worry about semaphores.  Parent will delete them */
    
       shmdt(shmptr);	
    
    }
    
    
    /**************************************************************************/
    /* Function to be invoked by the OS if CTRL-C is pressed during execution */
    /**************************************************************************/
    void ctrl_c(int signum)
    {
       perror("producer: You have pressed CTRL_C\n");
       cleanup_on_exit();  /* Perform cleanup operations before exiting */
       exit(0);
    }
    
    
    /**************************************************************************/
    /* Function to produce one item in the buffer                             */
    /**************************************************************************/
    void produce_item(struct item *item)
    {
    
       sem_wait(EMPTYptr);                 /* wait for a full buffer */
       sem_wait(MUTEXptr);                 /* wait for the mutex lock */
    
       sp->buff[sp->in].id = item->id;     /* put item id into buffer */
       sp->buff[sp->in].str = item->str;   /* .... Place associated string into buffer item istring .... */
       printf("Producer: Produced %10d at buffer[%d]\n", item->id, sp->in);
       sp->in = (sp->in + 1) % BUFFSIZE;   /* increment buffer index */
    
       sem_post(MUTEXptr);                 /* release the mutex lock */
       sem_post(FULLptr);                  /* signal a full buffer slot */
    }
    
    /**************************************************************************/
    /* Main producer routine                                                  */
    /**************************************************************************/
    int main(int argc, char *argv[])
    {
       int n;             /* local variable for produced item */
       key_t shm_key;               /* key for shared memory segment */	
       char *procName = argv[0];    /* name of this process */
       
       /* local variables for reading in lines and putting into item structure */
       int c, charIndex, numIndex, lineId;
       char curStr[80], idStr[4];
       struct item * curItem;
        
    /* Setup system environment */
       signal(SIGINT, ctrl_c);      /* specify routine to handle CTRL-C */
       setbuf(stdout, NULL);        /* turn off buffering of stdout */
       setbuf(stderr, NULL);        /* turn off buffering of stderr */
    
    /* Use ftok() to get value for the key to identify the shared memory segment */
       shm_key = ftok(KEYPATH, KEYPROJ);
    
    /* Get the ID of the existing shared memory segment */
       shmid = shmget(shm_key, size_of(sp), S_IWUSR);
       if (shmid == -1) {
          perror("shmget failed in producer");
          exit(1);
          }
    
    /* Attach the shared memory segment */
       shmptr = shmat(shmid, NULL, 0);
       if (shmptr == (void *)-1) {
          perror("shmat failed in producer");
          exit(1);
          }
    
    /* Cast shared memory pointer to structure type */
       sp = (shr_mem_t *)shmptr;
    
    /* Get pointers to the semaphores created by the parent */
       MUTEXptr = sem_open(sp->MUTEXname, 0, 0, 0);
       EMPTYptr = sem_open(sp->EMPTYname, 0, 0, 0);
       FULLptr = sem_open(sp->FULLname, 0, 0, 0);
    
    /* Read data and produce items until EOF */
       charIndex = 0;
       while ( (c=getchar()) != EOF ) { /* read lines of data fron stdin */
          /* ... read new data item (id and string) from stdin ... */
          if( c != '\n' && c != '\r' ){
    	  
    		curStr[charIndex++] = c;
    	  
    	  }else{ /* hit the newline */
    	  
    	    /* end the string */
    		curStr[charIndex] = '\0';
    		
    		/* get first four chars and put in idStr */
    	    for(charIndex = 0, numIndex = 0; charIndex < 4; charIndex++){ 
    			
    			/* skip white spaces */
    			if( !isspace( curStr[charIndex] ) ){ idStr[numIndex++] = curStr[charIndex]; }
    			
    		}
    		idStr[numIndex] = '\0';
    		
    		/* convert idStr to int */
    		lineId = atoi(idStr);
    		
    		/* get rid of id from curStr */
    		for(charIndex = 0; curStr[charIndex + 4] != '\0'; charIndex++){
    		
    			curStr[charIndex] = curStr[charIndex + 4];
    		
    		}
    		curStr[charIndex] = '\0';
    	  
    	    /* assign id and string to new item */
    		curItem->id = lineId;
    		curItem->str = curStr;
    	  
            /* validate item id values for correctness */
    	    if(curItem->id >= MAX_STRINGS){
    	  
    		  printf("***ERR*** Producer ignoring item with id=%d", item->id);
    	  
    	    }else{
    		  produce_item(curItem); /* add item to buffer */
    	    }
    		
    	  }
    	
    	}
    
    /* At EOF ... */
    	curItem->id = SENTINEL;
    	curItem->str = '\0';
    /* Add a sentinal item in Buffer to signal end of data input */
        produce_item(curItem ); /* produce a sentinel value after EOF */
    
    /* Write a termination message */
        sem_wait(MUTEXptr);       /* protect printf as a critical section */
        printf("%s exiting.....\n", procName);
        sem_post(MUTEXptr);
    
    /* Clean up and exit */
       cleanup_on_exit();
       exit(0);
    }
    parent.c
    Code:
    #include "assign5.h"
    
    
    /* Global variables for parent.c */
       int shmid, i;          /* the shared memory segment ID number */
       void *shmptr;       /* the pointer to shared memory returned by shmget() */
       char MUTEXid[32];   /* the unique generated name for the MUTEX semaphore */
       char EMPTYid[32];   /* the unique generated name for the EMPTY semaphore */
       char FULLid[32];    /* the unique generated name for the FULL semaphore  */
    
    
    /*******************************************************************/
    /* Function to cleanup shared memory and semaphores before exiting */
    /*******************************************************************/
    void cleanup_on_exit()
    {
       shmdt(shmptr);                   /* detach the shared memory */
       shmctl(shmid, IPC_RMID, NULL);                  /* delete the shared memory segment */
       sem_unlink(MUTEXid);            /* delete the MUTEX semaphore */
       sem_unlink(EMPTYid);            /* delete the EMPTY semaphore */
       sem_unlink(FULLid);             /* delete the FULL sempahore */
    }
    
    
    /**************************************************************************/
    /* Function to be invoked by the OS if CTRL-C is pressed during execution */
    /**************************************************************************/
    void ctrl_c(int signum)
    {
       printf("Parent: You have pressed CTRL-C\n");
       cleanup_on_exit();
       exit(0);
    }
    
    
    /**************************************************************************/
    /* Main program function                                                  */
    /**************************************************************************/
    int main(int argc, char *argv[]) {
    
    /* Local variable declarations */
       key_t shm_key;     /* key for shared memory segment */
       shr_mem_t *sp;     /* pointer to shared memory structure */
       int pid;           /* process ID number */
    
    /* Setup system environment */
       signal(SIGINT, ctrl_c);    /* specify routine to handle CTRL-C */
       setbuf(stdout, NULL);      /* turn off buffering of stdout */
       setbuf(stderr, NULL);      /* turn off buffering of stderr */
    
    /* Generate unique sempaphore names and initialize the semaphores */
       pid = getpid();   /* get process id for semaphore names */
       sprintf(MUTEXid,"semmutex%d", pid);   /* generate MUTEX semaphore name */
       sprintf(EMPTYid,"semempty%d", pid);   /* generate EMPTY semaphore name */
       sprintf(FULLid,"semfull%d", pid);     /* generate FULL semaphore name  */
    
       /* Why set the permissions to 660? Is this a good choice? */
       sem_open(MUTEXid, O_CREAT, 0660, 1);         /* init the MUTEX semaphore */
       sem_open(EMPTYid, O_CREAT, 0660, BUFFSIZE);  /* init the EMPTY semaphore */
       sem_open(FULLid, O_CREAT, 0660, 0);          /* init the FULL semaphore  */
    
    /* Use ftok() to get a value for a key to identify a shared memory segment */
       shm_key = ftok(KEYPATH, KEYPROJ);
    
    /* Create the shared memory segment */
       shmid = shmget(shm_key, size_of(sp), S_IRUSR | S_IWUSR);
       if (shmid == -1) {
          perror("shmget failed in parent");
          exit(1);
          }
    
    /* Attach shared memory segment to the parent process */
       shmptr = shmat(shmid, NULL, 0);
       if (shmptr == (void *)-1) {
          perror("shmat failed in parent");
          cleanup_on_exit();      /* clean up before exiting */
          exit(1);
          }
    
    /* Cast the returned pointer to the structure type */
       sp = (shr_mem_t *)shmptr;
    
    /* Initialize shared memory fields */
       sp->debug = 0;  /* Turn debug flag off */
       sp->in = 0;     /* index of next empty slot */
       sp->out = 0;    /* index of next full slot  */
       strcpy(sp->MUTEXname, MUTEXid);    /* MUTEX semaphore name */
       strcpy(sp->EMPTYname, EMPTYid);    /* EMPTY semaphore name */
       strcpy(sp->FULLname, FULLid);      /* FULL semaphore name  */
       /* Initialize string array to be empty.  WHY?  */
       for (i=0; i<MAX_STRINGS; i++) sp->strarray[i][0] = '\0';  /* null string */
    
    /* Fork the producer and consumer processes */
       printf("Creating the producer and consumer processes...\n");
    
       if (fork() == 0) {  /* in producer process */
          /* Replace this program with producer program */
          if (execl("producer", "Producer", NULL) == -1) {
             perror("execl failed for producer");
             cleanup_on_exit();   /* clean up before exiting */
             exit(3);
             }
           }
    
       if (fork() == 0) {  /* in consumer process */
          /* Replace this program with the consumer program */
          if (execl("consumer", "Consumer", NULL) == -1) {
             perror("execl failed for consumer");
             cleanup_on_exit();  /* clean up before exiting */
             exit(3);
             }
          }
    
    /* Wait for producer and consumer processes to finish */
        /* Is there something else you should check here ?  If so, what is it? */
        /* How would this change if you had multiple consumers ?  */
        wait(NULL);
        wait(NULL);
    
    /* Print termination message, clean up, and exit */
       /* ... completed processing - print out contents of string array ... */
       for (i = 0; (strarray[i][0] != '\0') && ( i < MAX_STRINGS ); i++){
    	
    		printf("%s\n", strarray[i]);
    	
    	}
    
       printf("Parent process exiting.\n");
       cleanup_on_exit();      /*Remove shared memory and semaphores */
       return(0);
    }
    consumer.c
    Code:
    #include "assign5.h"
    
    
    /* Global variables for consumer.c  */
       pid_t consid;      /* Consumer Process Id */
       void *shmptr;      /* pointer to shared memory returned by shmget() */
    
    
    /*******************************************************************/
    /* Function to cleanup before exiting                              */
    /*******************************************************************/
    void cleanup_on_exit()
    {
    /* Only detach shared memory.  Parent will remove it from system */
    /* Don't worry about semaphores.  Parent will delete them */
    
       shmdt(shmptr);
    
    }
    
    
    /**************************************************************************/
    /* Function to be invoked by the OS if CTRL-C is pressed during execution */
    /**************************************************************************/
    void ctrl_c(int signum)
    {
       perror("consumer: You have pressed CTRL_C\n");
       cleanup_on_exit();  /* Perform cleanup operations before exiting */
       exit(0);
    }
    
    
    /**************************************************************************/
    /* Main Consumer Routine                                                  */
    /**************************************************************************/
    int main(int argc, char *argv[])
    {
       int n;             /* local variable for consumed item */
       int shmid;         /* shared memory ID number */
       key_t shm_key;     /* key for shared memory segment */
       shr_mem_t *sp;     /* pointer to shared memory structure */
       sem_t *MUTEXptr;   /* pointer to the MUTEX semaphore */
       sem_t *EMPTYptr;   /* pointer to the EMPTY semaphore */
       sem_t *FULLptr;    /* pointer to the FULL semaphore  */
       char *procName = argv[0];  /* name of this process */
    
       signal(SIGINT, ctrl_c);
       setbuf(stdout, NULL);
       setbuf(stderr, NULL);
    
    /* Use ftok() to get value for the key to identify the shared memory segment */
       shm_key = ftok(KEYPATH, KEYPROJ);
    
    /* Get the ID of the existing shared memory segment */
       shmid = shmget(shm_key, size_of(sp), S_IRUSR);	
       if (shmid == -1) {
          perror("shmget failed in consumer");
          exit(1);
          }
    
    /* Attach the shared memory segment */
       shmptr = shmat(shmid, NULL, 0);
       if(shmptr == (void *)-1) {
          perror("shmat failed in consumer");
          exit(1);
          }
    
    /* Cast shared memory pointer to structure type */
       sp = (shr_mem_t *)shmptr;
    
    /* Get pointers to the semaphores created by the parent */
       MUTEXptr = sem_open(sp->MUTEXname, 0, 0, 0);
       EMPTYptr = sem_open(sp->EMPTYname, 0, 0, 0);
       FULLptr = sem_open(sp->FULLname, 0, 0, 0);	
    
    /* Consume items until the SENTINEL is found */
       do {
          sem_wait(FULLptr);                    /* wait for a full buffer */
          sem_wait(MUTEXptr);                   /* wait for the mutex lock */
    
          n = sp->buff[sp->out].id;             /* get item id from buffer */
          /* Note that an item has been consumed and add PID to msg */
          printf("   %s: Consumed %10d at buffer[%d]\n", procName, n, sp->out);
    
          if (n != SENTINEL) {
             /* .... place item string into string array .... */
             sp->out = (sp->out + 1) % BUFFSIZE;   /* increment buffer index */
             }
    
          sem_post(MUTEXptr);                   /* release the mutex lock */
          sem_post(EMPTYptr);                   /* signal an empty buffer slot */
    
          } while(n != SENTINEL);
    
    /* Write a termination message */
        sem_wait(MUTEXptr);      /* protect printf as a critical section */
        printf("   %s exiting....\n", procName);
        sem_post(MUTEXptr);
    
    /* Clean up and exit */
       cleanup_on_exit();
       exit(0);
    }
    assign5.h
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <semaphore.h>
    #include <errno.h>
    #include <memory.h>
    #include <ctype.h>
    
    #define NUM_CONSUMERS 1
    #define BUFFSIZE 14
    #define MAX_STRINGS 110
    #define SENTINEL -999999999  /* sentinel value for consumer process */
    
    /* Bounded Buffer item structure */
    struct item{
       int  id;  /* string index value */
       char str[80];  /* string value */
       };
    
    /* Structure for the shared memory region */
    typedef struct{
       int    debug;           /* debug flag */
       int    in;              /* index of next empty slot */    
       int    out;             /* index of next full slot  */
       char   MUTEXname[32];   /* name of the MUTEX semaphore */
       char   EMPTYname[32];   /* name of the EMPTY semaphore */
       char   FULLname[32];    /* name of the FULL semaphore  */
       struct item buff[BUFFSIZE];  /* circular buffer for producer/consumer items*/
       char   strarray[MAX_STRINGS][80]; /* shared array of strings for consumers */
    } shr_mem_t;
    
    /* Values for obtaining a shmid key via ftok() */
    #define KEYPATH "."
    #define KEYPROJ 4520
    as5.data (input file)
    Code:
    107	Wow, you wasted an entire section on that? Yep, I can't stress enough how 
      63	    * X-to-Y model. The mapping between LWPs and Threads.
      22	We will dive into the world of threads with some a little bit of "theory"
      23	first.  We will examine thread synchronization primitives and then a tutorial
      56	Before we can dive into the details of how threads are supported, we need to
      30  ####################################################################
      39  ####################################################################
       3                    The Beginning of the End
     110  $$$$$$$$$$$$$$$$$$The End of the Beginning$$$$$$$$$$$$$$$$$$$$$$$$$$
      47  ####################################################################
      55  ####################################################################
      76	Linux uses the one-to-one model. Each thread is mapped to a single LWP. Why
      72	Solaris uses the many-to-many model. CPUs are mapped to any number of LWPs
      69	    * Unbound threads have process contention scope, in other words, these
      87	thread type for the job.
      17	However, times have changed and many papers have been written on
     102	    Yes, threads are great... for the right tasks! Don't waste your time
      90	    * Thread-safe means that the program protects shared data, possibly
      77	is this approach favored in Linux over the many-to-many model? Linux LWPs are
      91	      through the use of mutual exclusion
      40	Now that we have pictures of dancing needles in our heads, lets move onto
      29	    Isn't that something you put through an eye of a sewing needle?  Yes.
      54	different technique to support threads.
      50	not support threads. Fortunately most modern Operating Systems support 
      53	few, support multithreaded programs. However, each Operating System uses a 
      62	      also sometimes referred to as kernel threads.
      18	multithreading.  Some advocate the use of threads, while others do not. With
      74	for slices of CPU time.
      81	"processes" scheduled which are in the same thread family as the currently
      92	    * Reentrant code means that a program can have more than one thread
      12	a program on a uniprocessor machine in most cases does not yield enough
     104	event-based programming is the better route, or just plain, sequential, and 
       1	      Multithreaded Programming :: Improving Performance through Threads
      45	blown processes, but are smaller portions of the process running concurrently
      82	running process.
     108	important picking the right tool for the job is.
      15	Parallelizing our thoughts does not come naturally nor is it an easy task.
      37	doing other useful work even if the other needle took 4 hours to sew on a 
       5	sequential or serialized?  Simply put, code is executed one instruction after
      86	either one. Each scenario demands a thorough analysis to select the right
      11	dominance of uniprocessing machines available to programmers. Multithreading 
      32	    Think of sewing needles as the CPUs (or LWPs) and the threads in a 
      60	     number of LWPs is usually greater than the number of CPUs in the system.
      97	      subset of Concurrency. Parallelism implies simultaneous running of code
       6	the next in a monolithic fashion, with no regard to the many possible
      35	both needles at the same time. Taking this analogy a little further, if one 
      85	your multithreaded program. There is no general rule when it comes to using
      41	something more concrete. A thread is a sequence of instructions that can be
      99	      that many tasks can run in any order and possibly in parallel.
      34	take longer to finish the job than if you split the thread into two and used 
      59	    * Lightweight Process (LWP) can be thought of as a virtual CPU where the
      78	really lightweight and thus LWP creation is not as expensive as it is in
      61	      Thread libraries communicate with LWPs to schedule threads. LWPs are
     101	Part IV :: Threads Rule!
      10	Why is it that most programs are sequential? One guess could be the relative
      98	     (which is impossible on uniprocessor machines) while Concurrency implies
      27	                       What is a thread?
     111$$$$                       What is a process?
      42	executed in parallel with other threads [wikipedia.com]. They are not
      46	(or in parallel). Hence, the term lightweight is used.
      80	multiprocess in Linux is that the scheduler (2.4) gives a 1 point boost to
      19	the increasing popularity of Symmetric-Multiprocessing machines, programming
      48	Part II :: Operating System Support
      89	Part III :: Other Terms
       8	degraded if the program performs a blocking call.
      28	Part I :: Definition
      24	on how to use POSIX pthreads. Finally, we will finish off with thread
      36	needle had to sew on a button (blocking I/O), the other needle could continue 
      13	performance gains to merit days, weeks, or months worth of work to thread
      52	Solaris, FreeBSD, Linux, AIX, HP-UX, IRIX, and Windows NT, just to name a 
      57	get familiarized with a few terms.
      51	threads, either with their own thread library or through POSIX pthreads. Sun 
      31	How does it relate to programming then?
      44	recursive definition but it makes sense. Threads of a program are not full-
      84	Moreover, creating bound or unbound threads can greatly impact performance of
      64	    * Contention Scope is how threads compete for system resources (e.g.
      67	      threads contend with other processes on the entire system (and thus are
      93	      executing concurrently
      96	    * Concurrency vs. Parallelism - They are not the same! Parallelism is a
       4	    Most code written today is sequential. What do we mean by the term 
      20	multithreaded code is a skill worth learning.
     105	no-frills code can do the job just right.
      49	    You cannot expect a multithreaded program to run on a kernel that does 
      95	      (e.g. can be called from a signal handler)
      68	      scheduled by the kernel)
      38	single button.  If you only used one needle, you would be ~4 hours behind!
      43	processes, but rather lightweight threads of execution. This seems like a
      66	    * Bound threads have system-wide contention scope, in other words, these
       7	resources available to the program. Overall performance can be serverely
      94	    * Async-safe means that a function is reentrant while handling a signal
      33	program as the fiber. If you had two needles but only one thread, it would 
      73	which are then mapped to any number of threads. The kernel schedules the LWPs
      70	      threads are scheduled by the library onto available LWPs
     103	multithreading a program that isn't worth multithreading. Sometimes 
      14	code.  Another guess is that most of us think in a sequential manner.
      79	Solaris. Another bonus to make your program multithreaded rather than
      25	performance and a brief overview of multiprocess programming.
     100	
     106	
      16	
      21	
      26	
       2	   (http://vergil.chemistry.gatech.edu/resources/programming/threads.htm)
       3	
      30	
      39	
      47	
      55	
      58	
      65	      scheduling)
      71	
      75	
      83	
      88	
       9
    desired output:
    Code:
    Creating the producer and consumer processes...
    Producer[1106700]: Produced        107 at buffer[0]
    Producer[1106700]: Produced         63 at buffer[1]
    Producer[1106700]: Produced         22 at buffer[2]
       Consumer[1104366]: Consumed        107 at buffer[0]
    Producer[1106700]: Produced         23 at buffer[3]
       Consumer[1104366]: Consumed         63 at buffer[1]
    Producer[1106700]: Produced         56 at buffer[4]
       Consumer[1104366]: Consumed         22 at buffer[2]
    Producer[1106700]: Produced         30 at buffer[5]
       Consumer[1104366]: Consumed         23 at buffer[3]
    Producer[1106700]: Produced         39 at buffer[6]
       Consumer[1104366]: Consumed         56 at buffer[4]
    Producer[1106700]: Produced          3 at buffer[7]
    ***ERR*** Producer ignoring new item with id=110
       Consumer[1104366]: Consumed         30 at buffer[5]
    Producer[1106700]: Produced         47 at buffer[8]
       Consumer[1104366]: Consumed         39 at buffer[6]
    Producer[1106700]: Produced         55 at buffer[9]
       Consumer[1104366]: Consumed          3 at buffer[7]
    Producer[1106700]: Produced         76 at buffer[0]
       Consumer[1104366]: Consumed         47 at buffer[8]
    Producer[1106700]: Produced         72 at buffer[1]
       Consumer[1104366]: Consumed         55 at buffer[9]
    Producer[1106700]: Produced         69 at buffer[2]
       Consumer[1104366]: Consumed         76 at buffer[0]
    Producer[1106700]: Produced         87 at buffer[3]
       Consumer[1104366]: Consumed         72 at buffer[1]
    Producer[1106700]: Produced         17 at buffer[4]
       Consumer[1104366]: Consumed         69 at buffer[2]
    Producer[1106700]: Produced        102 at buffer[5]
       Consumer[1104366]: Consumed         87 at buffer[3]
    Producer[1106700]: Produced         90 at buffer[6]
       Consumer[1104366]: Consumed         17 at buffer[4]
    Producer[1106700]: Produced         77 at buffer[7]
       Consumer[1104366]: Consumed        102 at buffer[5]
    Producer[1106700]: Produced         91 at buffer[8]
       Consumer[1104366]: Consumed         90 at buffer[6]
    Producer[1106700]: Produced         40 at buffer[9]
       Consumer[1104366]: Consumed         77 at buffer[7]
    Producer[1106700]: Produced         29 at buffer[0]
       Consumer[1104366]: Consumed         91 at buffer[8]
    Producer[1106700]: Produced         54 at buffer[1]
       Consumer[1104366]: Consumed         40 at buffer[9]
    Producer[1106700]: Produced         50 at buffer[2]
       Consumer[1104366]: Consumed         29 at buffer[0]
    Producer[1106700]: Produced         53 at buffer[3]
       Consumer[1104366]: Consumed         54 at buffer[1]
    Producer[1106700]: Produced         62 at buffer[4]
       Consumer[1104366]: Consumed         50 at buffer[2]
    Producer[1106700]: Produced         18 at buffer[5]
       Consumer[1104366]: Consumed         53 at buffer[3]
    Producer[1106700]: Produced         74 at buffer[6]
       Consumer[1104366]: Consumed         62 at buffer[4]
    Producer[1106700]: Produced         81 at buffer[7]
       Consumer[1104366]: Consumed         18 at buffer[5]
    Producer[1106700]: Produced         92 at buffer[8]
       Consumer[1104366]: Consumed         74 at buffer[6]
    Producer[1106700]: Produced         12 at buffer[9]
       Consumer[1104366]: Consumed         81 at buffer[7]
    Producer[1106700]: Produced        104 at buffer[0]
       Consumer[1104366]: Consumed         92 at buffer[8]
    Producer[1106700]: Produced          1 at buffer[1]
       Consumer[1104366]: Consumed         12 at buffer[9]
    Producer[1106700]: Produced         45 at buffer[2]
       Consumer[1104366]: Consumed        104 at buffer[0]
    Producer[1106700]: Produced         82 at buffer[3]
       Consumer[1104366]: Consumed          1 at buffer[1]
    Producer[1106700]: Produced        108 at buffer[4]
       Consumer[1104366]: Consumed         45 at buffer[2]
    Producer[1106700]: Produced         15 at buffer[5]
       Consumer[1104366]: Consumed         82 at buffer[3]
    Producer[1106700]: Produced         37 at buffer[6]
       Consumer[1104366]: Consumed        108 at buffer[4]
    Producer[1106700]: Produced          5 at buffer[7]
       Consumer[1104366]: Consumed         15 at buffer[5]
    Producer[1106700]: Produced         86 at buffer[8]
       Consumer[1104366]: Consumed         37 at buffer[6]
    Producer[1106700]: Produced         11 at buffer[9]
       Consumer[1104366]: Consumed          5 at buffer[7]
    Producer[1106700]: Produced         32 at buffer[0]
       Consumer[1104366]: Consumed         86 at buffer[8]
    Producer[1106700]: Produced         60 at buffer[1]
       Consumer[1104366]: Consumed         11 at buffer[9]
    Producer[1106700]: Produced         97 at buffer[2]
       Consumer[1104366]: Consumed         32 at buffer[0]
    Producer[1106700]: Produced          6 at buffer[3]
       Consumer[1104366]: Consumed         60 at buffer[1]
    Producer[1106700]: Produced         35 at buffer[4]
       Consumer[1104366]: Consumed         97 at buffer[2]
    Producer[1106700]: Produced         85 at buffer[5]
       Consumer[1104366]: Consumed          6 at buffer[3]
    Producer[1106700]: Produced         41 at buffer[6]
       Consumer[1104366]: Consumed         35 at buffer[4]
    Producer[1106700]: Produced         99 at buffer[7]
       Consumer[1104366]: Consumed         85 at buffer[5]
    Producer[1106700]: Produced         34 at buffer[8]
       Consumer[1104366]: Consumed         41 at buffer[6]
    Producer[1106700]: Produced         59 at buffer[9]
       Consumer[1104366]: Consumed         99 at buffer[7]
    Producer[1106700]: Produced         78 at buffer[0]
       Consumer[1104366]: Consumed         34 at buffer[8]
    Producer[1106700]: Produced         61 at buffer[1]
       Consumer[1104366]: Consumed         59 at buffer[9]
    Producer[1106700]: Produced        101 at buffer[2]
       Consumer[1104366]: Consumed         78 at buffer[0]
    Producer[1106700]: Produced         10 at buffer[3]
       Consumer[1104366]: Consumed         61 at buffer[1]
    Producer[1106700]: Produced         98 at buffer[4]
       Consumer[1104366]: Consumed        101 at buffer[2]
    Producer[1106700]: Produced         27 at buffer[5]
    ***ERR*** Producer ignoring new item with id=111
       Consumer[1104366]: Consumed         10 at buffer[3]
    Producer[1106700]: Produced         42 at buffer[6]
       Consumer[1104366]: Consumed         98 at buffer[4]
    Producer[1106700]: Produced         46 at buffer[7]
       Consumer[1104366]: Consumed         27 at buffer[5]
    Producer[1106700]: Produced         80 at buffer[8]
       Consumer[1104366]: Consumed         42 at buffer[6]
    Producer[1106700]: Produced         19 at buffer[9]
       Consumer[1104366]: Consumed         46 at buffer[7]
    Producer[1106700]: Produced         48 at buffer[0]
       Consumer[1104366]: Consumed         80 at buffer[8]
    Producer[1106700]: Produced         89 at buffer[1]
       Consumer[1104366]: Consumed         19 at buffer[9]
    Producer[1106700]: Produced          8 at buffer[2]
       Consumer[1104366]: Consumed         48 at buffer[0]
    Producer[1106700]: Produced         28 at buffer[3]
       Consumer[1104366]: Consumed         89 at buffer[1]
    Producer[1106700]: Produced         24 at buffer[4]
       Consumer[1104366]: Consumed          8 at buffer[2]
    Producer[1106700]: Produced         36 at buffer[5]
       Consumer[1104366]: Consumed         28 at buffer[3]
    Producer[1106700]: Produced         13 at buffer[6]
       Consumer[1104366]: Consumed         24 at buffer[4]
    Producer[1106700]: Produced         52 at buffer[7]
       Consumer[1104366]: Consumed         36 at buffer[5]
    Producer[1106700]: Produced         57 at buffer[8]
       Consumer[1104366]: Consumed         13 at buffer[6]
    Producer[1106700]: Produced         51 at buffer[9]
       Consumer[1104366]: Consumed         52 at buffer[7]
    Producer[1106700]: Produced         31 at buffer[0]
       Consumer[1104366]: Consumed         57 at buffer[8]
    Producer[1106700]: Produced         44 at buffer[1]
       Consumer[1104366]: Consumed         51 at buffer[9]
    Producer[1106700]: Produced         84 at buffer[2]
       Consumer[1104366]: Consumed         31 at buffer[0]
    Producer[1106700]: Produced         64 at buffer[3]
       Consumer[1104366]: Consumed         44 at buffer[1]
    Producer[1106700]: Produced         67 at buffer[4]
       Consumer[1104366]: Consumed         84 at buffer[2]
    Producer[1106700]: Produced         93 at buffer[5]
       Consumer[1104366]: Consumed         64 at buffer[3]
    Producer[1106700]: Produced         96 at buffer[6]
       Consumer[1104366]: Consumed         67 at buffer[4]
    Producer[1106700]: Produced          4 at buffer[7]
       Consumer[1104366]: Consumed         93 at buffer[5]
    Producer[1106700]: Produced         20 at buffer[8]
       Consumer[1104366]: Consumed         96 at buffer[6]
    Producer[1106700]: Produced        105 at buffer[9]
       Consumer[1104366]: Consumed          4 at buffer[7]
    Producer[1106700]: Produced         49 at buffer[0]
       Consumer[1104366]: Consumed         20 at buffer[8]
    Producer[1106700]: Produced         95 at buffer[1]
       Consumer[1104366]: Consumed        105 at buffer[9]
    Producer[1106700]: Produced         68 at buffer[2]
       Consumer[1104366]: Consumed         49 at buffer[0]
    Producer[1106700]: Produced         38 at buffer[3]
       Consumer[1104366]: Consumed         95 at buffer[1]
    Producer[1106700]: Produced         43 at buffer[4]
       Consumer[1104366]: Consumed         68 at buffer[2]
    Producer[1106700]: Produced         66 at buffer[5]
       Consumer[1104366]: Consumed         38 at buffer[3]
    Producer[1106700]: Produced          7 at buffer[6]
       Consumer[1104366]: Consumed         43 at buffer[4]
    Producer[1106700]: Produced         94 at buffer[7]
       Consumer[1104366]: Consumed         66 at buffer[5]
    Producer[1106700]: Produced         33 at buffer[8]
       Consumer[1104366]: Consumed          7 at buffer[6]
    Producer[1106700]: Produced         73 at buffer[9]
       Consumer[1104366]: Consumed         94 at buffer[7]
    Producer[1106700]: Produced         70 at buffer[0]
       Consumer[1104366]: Consumed         33 at buffer[8]
    Producer[1106700]: Produced        103 at buffer[1]
       Consumer[1104366]: Consumed         73 at buffer[9]
    Producer[1106700]: Produced         14 at buffer[2]
       Consumer[1104366]: Consumed         70 at buffer[0]
    Producer[1106700]: Produced         79 at buffer[3]
       Consumer[1104366]: Consumed        103 at buffer[1]
    Producer[1106700]: Produced         25 at buffer[4]
       Consumer[1104366]: Consumed         14 at buffer[2]
    Producer[1106700]: Produced        100 at buffer[5]
       Consumer[1104366]: Consumed         79 at buffer[3]
    Producer[1106700]: Produced        106 at buffer[6]
       Consumer[1104366]: Consumed         25 at buffer[4]
    Producer[1106700]: Produced         16 at buffer[7]
       Consumer[1104366]: Consumed        100 at buffer[5]
    Producer[1106700]: Produced         21 at buffer[8]
       Consumer[1104366]: Consumed        106 at buffer[6]
    Producer[1106700]: Produced         26 at buffer[9]
       Consumer[1104366]: Consumed         16 at buffer[7]
    Producer[1106700]: Produced          2 at buffer[0]
       Consumer[1104366]: Consumed         21 at buffer[8]
    Producer[1106700]: Produced          3 at buffer[1]
       Consumer[1104366]: Consumed         26 at buffer[9]
    Producer[1106700]: Produced         30 at buffer[2]
       Consumer[1104366]: Consumed          2 at buffer[0]
    Producer[1106700]: Produced         39 at buffer[3]
       Consumer[1104366]: Consumed          3 at buffer[1]
    Producer[1106700]: Produced         47 at buffer[4]
       Consumer[1104366]: Consumed         30 at buffer[2]
    Producer[1106700]: Produced         55 at buffer[5]
       Consumer[1104366]: Consumed         39 at buffer[3]
    Producer[1106700]: Produced         58 at buffer[6]
       Consumer[1104366]: Consumed         47 at buffer[4]
    Producer[1106700]: Produced         65 at buffer[7]
       Consumer[1104366]: Consumed         55 at buffer[5]
    Producer[1106700]: Produced         71 at buffer[8]
       Consumer[1104366]: Consumed         58 at buffer[6]
    Producer[1106700]: Produced         75 at buffer[9]
       Consumer[1104366]: Consumed         65 at buffer[7]
    Producer[1106700]: Produced         83 at buffer[0]
       Consumer[1104366]: Consumed         71 at buffer[8]
    Producer[1106700]: Produced         88 at buffer[1]
       Consumer[1104366]: Consumed         75 at buffer[9]
    Producer[1106700]: Produced          9 at buffer[2]
       Consumer[1104366]: Consumed         83 at buffer[0]
    Producer[1106700]: Produced -999999999 at buffer[3]
       Consumer[1104366]: Consumed         88 at buffer[1]
    Producer[1106700]: exiting.....
       Consumer[1104366]: Consumed          9 at buffer[2]
       Consumer[1104366]: Consumed -999999999 at buffer[3]
       Consumer[1104366] exiting....
    	      Multithreaded Programming :: Improving Performance through Threads
    	   (http://vergil.chemistry.gatech.edu/resources/programming/threads.htm)
    	
    	    Most code written today is sequential. What do we mean by the term 
    	sequential or serialized?  Simply put, code is executed one instruction after
    	the next in a monolithic fashion, with no regard to the many possible
    	resources available to the program. Overall performance can be serverely
    	degraded if the program performs a blocking call.
    	
    	Why is it that most programs are sequential? One guess could be the relative
    	dominance of uniprocessing machines available to programmers. Multithreading 
    	a program on a uniprocessor machine in most cases does not yield enough
    	performance gains to merit days, weeks, or months worth of work to thread
    	code.  Another guess is that most of us think in a sequential manner.
    	Parallelizing our thoughts does not come naturally nor is it an easy task.
    	
    	However, times have changed and many papers have been written on
    	multithreading.  Some advocate the use of threads, while others do not. With
    	the increasing popularity of Symmetric-Multiprocessing machines, programming
    	multithreaded code is a skill worth learning.
    	
    	We will dive into the world of threads with some a little bit of "theory"
    	first.  We will examine thread synchronization primitives and then a tutorial
    	on how to use POSIX pthreads. Finally, we will finish off with thread
    	performance and a brief overview of multiprocess programming.
    	
    	                       What is a thread?
    	Part I :: Definition
    	    Isn't that something you put through an eye of a sewing needle?  Yes.
    	
    	How does it relate to programming then?
    	    Think of sewing needles as the CPUs (or LWPs) and the threads in a 
    	program as the fiber. If you had two needles but only one thread, it would 
    	take longer to finish the job than if you split the thread into two and used 
    	both needles at the same time. Taking this analogy a little further, if one 
    	needle had to sew on a button (blocking I/O), the other needle could continue 
    	doing other useful work even if the other needle took 4 hours to sew on a 
    	single button.  If you only used one needle, you would be ~4 hours behind!
    	
    	Now that we have pictures of dancing needles in our heads, lets move onto
    	something more concrete. A thread is a sequence of instructions that can be
    	executed in parallel with other threads [wikipedia.com]. They are not
    	processes, but rather lightweight threads of execution. This seems like a
    	recursive definition but it makes sense. Threads of a program are not full-
    	blown processes, but are smaller portions of the process running concurrently
    	(or in parallel). Hence, the term lightweight is used.
    	
    	Part II :: Operating System Support
    	    You cannot expect a multithreaded program to run on a kernel that does 
    	not support threads. Fortunately most modern Operating Systems support 
    	threads, either with their own thread library or through POSIX pthreads. Sun 
    	Solaris, FreeBSD, Linux, AIX, HP-UX, IRIX, and Windows NT, just to name a 
    	few, support multithreaded programs. However, each Operating System uses a 
    	different technique to support threads.
    	
    	Before we can dive into the details of how threads are supported, we need to
    	get familiarized with a few terms.
    	
    	    * Lightweight Process (LWP) can be thought of as a virtual CPU where the
    	     number of LWPs is usually greater than the number of CPUs in the system.
    	      Thread libraries communicate with LWPs to schedule threads. LWPs are
    	      also sometimes referred to as kernel threads.
    	    * X-to-Y model. The mapping between LWPs and Threads.
    	    * Contention Scope is how threads compete for system resources (e.g.
    	      scheduling)
    	    * Bound threads have system-wide contention scope, in other words, these
    	      threads contend with other processes on the entire system (and thus are
    	      scheduled by the kernel)
    	    * Unbound threads have process contention scope, in other words, these
    	      threads are scheduled by the library onto available LWPs
    	
    	Solaris uses the many-to-many model. CPUs are mapped to any number of LWPs
    	which are then mapped to any number of threads. The kernel schedules the LWPs
    	for slices of CPU time.
    	
    	Linux uses the one-to-one model. Each thread is mapped to a single LWP. Why
    	is this approach favored in Linux over the many-to-many model? Linux LWPs are
    	really lightweight and thus LWP creation is not as expensive as it is in
    	Solaris. Another bonus to make your program multithreaded rather than
    	multiprocess in Linux is that the scheduler (2.4) gives a 1 point boost to
    	"processes" scheduled which are in the same thread family as the currently
    	running process.
    	
    	Moreover, creating bound or unbound threads can greatly impact performance of
    	your multithreaded program. There is no general rule when it comes to using
    	either one. Each scenario demands a thorough analysis to select the right
    	thread type for the job.
    	
    	Part III :: Other Terms
    	    * Thread-safe means that the program protects shared data, possibly
    	      through the use of mutual exclusion
    	    * Reentrant code means that a program can have more than one thread
    	      executing concurrently
    	    * Async-safe means that a function is reentrant while handling a signal
    	      (e.g. can be called from a signal handler)
    	    * Concurrency vs. Parallelism - They are not the same! Parallelism is a
    	      subset of Concurrency. Parallelism implies simultaneous running of code
    	     (which is impossible on uniprocessor machines) while Concurrency implies
    	      that many tasks can run in any order and possibly in parallel.
    	
    	Part IV :: Threads Rule!
    	    Yes, threads are great... for the right tasks! Don't waste your time
    	multithreading a program that isn't worth multithreading. Sometimes 
    	event-based programming is the better route, or just plain, sequential, and 
    	no-frills code can do the job just right.
    	
    	Wow, you wasted an entire section on that? Yep, I can't stress enough how 
    	important picking the right tool for the job is.
    
    Parent process exiting.

  2. #2
    Registered User
    Join Date
    Apr 2011
    Posts
    8

    Makefile

    I forgot to also include the Makefile, which may be helpful for anyone trying to be helpful

    Code:
    #
    # Macros to make sure we use the system's C compiler and options to
    # create a source listing and additional link libraries.
    CC = cc
    OPTS = -source_listing -lrt
    
    # Default action is to create three processing modules.
    #all:   producer consumer parent # alternate means to build the code
    
    all:    producer consumer parent
            @- echo "Initiate building of Producer/Consumer code"
            @- $(MAKE) producer
            @- $(MAKE) consumer
            @- $(MAKE) parent
    
    # Create the producer module.
    producer: producer.c assign5.h
            @- echo "Build the Producer code"
            $(CC) producer.c $(OPTS) -o producer
    
    # Create the consumer module.
            @- echo "Build the Consumer code"
    consumer: consumer.c assign5.h
            $(CC) consumer.c $(OPTS) -o consumer
    
    # Create the parent (main) module.
            @- echo "Build the Parent (main) code"
    parent: parent.c assign5.h
            $(CC) parent.c $(OPTS) -o parent
    
    # Clean up a directory after a build.
    clean:
            @- echo "Cleanup directory after a build"
            @- rm -f parent.lis producer.lis consumer.lis
            @  rm -i parent producer consumer
    
    # End of Makefile

  3. #3
    Registered User
    Join Date
    Dec 2011
    Posts
    1
    Hey,

    I'm in your same class. Have you had any luck with replies on other threads possibly? This one looks pretty dead.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 17
    Last Post: 03-06-2008, 02:32 PM
  2. Replies: 4
    Last Post: 08-27-2007, 11:51 PM
  3. struct "dereferencing pointer to incomplete type"
    By modec in forum C Programming
    Replies: 8
    Last Post: 04-14-2005, 03:39 PM
  4. "subscript requires array or pointer type"?
    By Nutka in forum C Programming
    Replies: 12
    Last Post: 12-06-2002, 05:51 PM
  5. Replies: 4
    Last Post: 11-09-2002, 01:16 PM

Tags for this Thread