1 /* The classic producer-consumer example. 2 Illustrates mutexes and conditions. 3 All integers between 0 and 9999 should be printed exactly twice, 4 once to the right of the arrow and once to the left. */ 5 6 #include <stdio.h> 7 #include "pthread.h" 8 9 #define BUFFER_SIZE 16 10 11 /* Circular buffer of integers. */ 12 13 struct prodcons { 14 int buffer[BUFFER_SIZE]; /* the actual data */ 15 pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */ 16 int readpos, writepos; /* positions for reading and writing */ 17 pthread_cond_t notempty; /* signaled when buffer is not empty */ 18 pthread_cond_t notfull; /* signaled when buffer is not full */ 19 }; 20 21 /* Initialize a buffer */ 22 23 static void init(struct prodcons * b) 24 { 25 pthread_mutex_init(&b->lock, NULL); 26 pthread_cond_init(&b->notempty, NULL); 27 pthread_cond_init(&b->notfull, NULL); 28 b->readpos = 0; 29 b->writepos = 0; 30 } 31 32 /* Store an integer in the buffer */ 33 static void put(struct prodcons * b, int data) 34 { 35 pthread_mutex_lock(&b->lock); 36 /* Wait until buffer is not full */ 37 while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) { 38 pthread_cond_wait(&b->notfull, &b->lock); 39 /* pthread_cond_wait reacquired b->lock before returning */ 40 } 41 /* Write the data and advance write pointer */ 42 b->buffer[b->writepos] = data; 43 b->writepos++; 44 if (b->writepos >= BUFFER_SIZE) b->writepos = 0; 45 /* Signal that the buffer is now not empty */ 46 pthread_cond_signal(&b->notempty); 47 pthread_mutex_unlock(&b->lock); 48 } 49 50 /* Read and remove an integer from the buffer */ 51 52 static int get(struct prodcons * b) 53 { 54 int data; 55 pthread_mutex_lock(&b->lock); 56 /* Wait until buffer is not empty */ 57 while (b->writepos == b->readpos) { 58 pthread_cond_wait(&b->notempty, &b->lock); 59 } 60 /* Read the data and advance read pointer */ 61 data = b->buffer[b->readpos]; 62 b->readpos++; 63 if (b->readpos >= BUFFER_SIZE) b->readpos = 0; 64 /* Signal that the buffer is now not full */ 65 pthread_cond_signal(&b->notfull); 66 pthread_mutex_unlock(&b->lock); 67 return data; 68 } 69 70 /* A test program: one thread inserts integers from 1 to 10000, 71 the other reads them and prints them. */ 72 73 #define OVER (-1) 74 75 struct prodcons buffer; 76 77 static void * producer(void * data) 78 { 79 int n; 80 for (n = 0; n < 10000; n++) { 81 printf("%d --->\n", n); 82 put(&buffer, n); 83 } 84 put(&buffer, OVER); 85 return NULL; 86 } 87 88 static void * consumer(void * data) 89 { 90 int d; 91 while (1) { 92 d = get(&buffer); 93 if (d == OVER) break; 94 printf("---> %d\n", d); 95 } 96 return NULL; 97 } 98 99 int libc_ex2(void) 100 { 101 pthread_t th_a, th_b; 102 void * retval; 103 104 init(&buffer); 105 /* Create the threads */ 106 pthread_create(&th_a, NULL, producer, 0); 107 pthread_create(&th_b, NULL, consumer, 0); 108 /* Wait until producer and consumer finish. */ 109 pthread_join(th_a, &retval); 110 pthread_join(th_b, &retval); 111 return 0; 112 } 113 #include <finsh.h> 114 FINSH_FUNCTION_EXPORT(libc_ex2, example 2 for libc); 115