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