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