1 #include "unpthread.h"
2
3 #define Pthread_mutex_lock(mptr) \
4 { int n; \
5 if ( (n = pthread_mutex_lock(mptr)) != 0) \
6 { errno = n; err_sys("pthread_mutex_lock error"); } \
7 }
8 #define Pthread_mutex_unlock(mptr) \
9 { int n; \
10 if ( (n = pthread_mutex_unlock(mptr)) != 0) \
11 { errno = n; err_sys("pthread_mutex_unlock error"); } \
12 }
13 #define Pthread_cond_wait(cptr,mptr) \
14 { int n; \
15 if ( (n = pthread_cond_wait(cptr,mptr)) != 0) \
16 { errno = n; err_sys("pthread_cond_wait error"); } \
17 }
18 #define Pthread_cond_signal(cptr) \
19 { int n; \
20 if ( (n = pthread_cond_signal(cptr)) != 0) \
21 { errno = n; err_sys("pthread_cond_signal error"); } \
22 }
23
24 #define NLOOP 50
25 #define BUFFSIZE 10
26
27 struct buf_t {
28 int b_buf[BUFFSIZE]; /* the buffer which contains integer items */
29 int b_nitems; /* #items currently in buffer */
30 int b_nextget;
31 int b_nextput;
32 pthread_mutex_t b_mutex;
33 pthread_cond_t b_cond_consumer; /* consumer waiting to get */
34 pthread_cond_t b_cond_producer; /* producer waiting to put */
35 } buf_t;
36
37 void *produce_loop(void *);
38 void *consume_loop(void *);
39
40 int
main(int argc,char ** argv)41 main(int argc, char **argv)
42 {
43 int n;
44 pthread_t tidA, tidB;
45
46 printf("main, addr(stack) = %x, addr(global) = %x, addr(func) = %x\n",
47 &n, &buf_t, &produce_loop);
48 if ( (n = pthread_create(&tidA, NULL, &produce_loop, NULL)) != 0)
49 errno = n, err_sys("pthread_create error for A");
50 if ( (n = pthread_create(&tidB, NULL, &consume_loop, NULL)) != 0)
51 errno = n, err_sys("pthread_create error for B");
52
53 /* wait for both threads to terminate */
54 if ( (n = pthread_join(tidA, NULL)) != 0)
55 errno = n, err_sys("pthread_join error for A");
56 if ( (n = pthread_join(tidB, NULL)) != 0)
57 errno = n, err_sys("pthread_join error for B");
58
59 exit(0);
60 }
61
62 void
produce(struct buf_t * bptr,int val)63 produce(struct buf_t *bptr, int val)
64 {
65 Pthread_mutex_lock(&bptr->b_mutex);
66 /* Wait if buffer is full */
67 while (bptr->b_nitems >= BUFFSIZE)
68 Pthread_cond_wait(&bptr->b_cond_producer, &bptr->b_mutex);
69
70 /* There is room, store the new value */
71 printf("produce %d\n", val);
72 bptr->b_buf[bptr->b_nextput] = val;
73 if (++bptr->b_nextput >= BUFFSIZE)
74 bptr->b_nextput = 0;
75 bptr->b_nitems++;
76
77 /* Signal consumer */
78 Pthread_cond_signal(&bptr->b_cond_consumer);
79 Pthread_mutex_unlock(&bptr->b_mutex);
80 }
81
82 int
consume(struct buf_t * bptr)83 consume(struct buf_t *bptr)
84 {
85 int val;
86
87 Pthread_mutex_lock(&bptr->b_mutex);
88 /* Wait if buffer is empty */
89 while (bptr->b_nitems <= 0)
90 Pthread_cond_wait(&bptr->b_cond_consumer, &bptr->b_mutex);
91
92 /* There is data, fetch the value */
93 val = bptr->b_buf[bptr->b_nextget];
94 printf("consume %d\n", val);
95 if (++bptr->b_nextget >= BUFFSIZE)
96 bptr->b_nextget = 0;
97 bptr->b_nitems--;
98
99 /* Signal producer; it might be waiting for space to store */
100 Pthread_cond_signal(&bptr->b_cond_producer);
101 Pthread_mutex_unlock(&bptr->b_mutex);
102
103 return(val);
104 }
105
106 void *
produce_loop(void * vptr)107 produce_loop(void *vptr)
108 {
109 int i;
110
111 printf("produce_loop thread, addr(stack) = %x\n", &i);
112 for (i = 0; i < NLOOP; i++) {
113 produce(&buf_t, i);
114 }
115
116 return(NULL);
117 }
118
119 void *
consume_loop(void * vptr)120 consume_loop(void *vptr)
121 {
122 int i, val;
123
124 printf("consume_loop thread, addr(stack) = %x\n", &i);
125 for (i = 0; i < NLOOP; i++) {
126 val = consume(&buf_t);
127 }
128
129 return(NULL);
130 }
131