xref: /nrf52832-nimble/rt-thread/examples/libc/ex5.c (revision 104654410c56c573564690304ae786df310c91fc)
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