-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconcurrency1.c
executable file
·170 lines (133 loc) · 2.8 KB
/
concurrency1.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* Concurrency 1: The Producer-Consumer Problem
* Group: 10-11
* CS444
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include "mt.h"
/* Buffer can hold up to 32 items */
#define BUFF_MAX 32
/* Item has a number for printing and a number for sleeping */
struct item {
int print_num;
int sleep_time;
};
/* Buffer, buffer count, and buffer mutex */
struct item buffer[BUFF_MAX];
int buff_count = 0;
pthread_mutex_t buff_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Functions for manipulating buffer */
void buff_push(struct item buff_item);
struct item buff_pop(void);
int buff_empty(void);
int buff_full(void);
void buff_lock(void);
void buff_unlock(void);
/* Consumer and producer functions */
void *consumer(void *arg);
void *producer(void *arg);
/* Functions for getting a random number */
int get_rand(void);
int get_rdrand(void);
int main(int argc, char **argv)
{
/* Seed Mersenne Twister */
unsigned long init[4] = {0x123, 0x234, 0x345, 0x456};
unsigned long length = 4;
init_by_array(init, length);
/* Number of threads specified by user */
int num_threads = atoi(argv[1]);
pthread_t con_threads[num_threads];
pthread_t prod_threads[num_threads];
while(1) {
/* Create threads */
int i;
for (i = 0; i < num_threads; i++) {
pthread_create(&(con_threads[i]), NULL, producer, NULL);
pthread_create(&(prod_threads[i]), NULL, consumer, NULL);
}
/* Join threads */
for (i = 0; i < num_threads; i++) {
pthread_join(prod_threads[i], NULL);
pthread_join(con_threads[i], NULL);
}
}
return 0;
}
void buff_push(struct item buff_item)
{
buffer[buff_count++] = buff_item;
}
struct item buff_pop(void)
{
return buffer[--buff_count];
}
int buff_empty(void)
{
return buff_count <= 0;
}
int buff_full(void)
{
return buff_count >= 32;
}
void buff_lock(void)
{
pthread_mutex_lock(&buff_mutex);
}
void buff_unlock(void)
{
pthread_mutex_unlock(&buff_mutex);
}
void *consumer(void *arg)
{
buff_lock();
if (buff_empty()) {
buff_unlock();
}
struct item buff_item = buff_pop();
sleep(buff_item.sleep_time);
printf("%d\n", buff_item.print_num);
fflush(stdout);
buff_unlock();
}
void *producer(void *arg)
{
struct item buff_item;
buff_lock();
if (buff_full()) {
buff_unlock();
}
sleep(get_rand() % 5 + 3);
buff_item.print_num = get_rand() % 1000;
buff_item.sleep_time = get_rand() % 8 + 2;
buff_push(buff_item);
buff_unlock();
}
int get_rand(void)
{
int rand_num;
unsigned int eax;
unsigned int ecx;
eax = 0x01;
__asm__ __volatile__(
"cpuid;"
: "=c"(ecx)
: "a"(eax)
);
if(ecx & 0x40000000)
rand_num = get_rdrand();
else
rand_num = genrand_int32();
return abs(rand_num);
}
int get_rdrand(void)
{
unsigned int rand_num;
__asm__ __volatile__(
"rdrand %0"
: "=r"(rand_num)
);
return rand_num;
}