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