-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfc_queue.c
More file actions
247 lines (197 loc) · 6.1 KB
/
Copy pathfc_queue.c
File metadata and controls
247 lines (197 loc) · 6.1 KB
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#include <stdio.h>
#include <stdlib.h>
#include "timers_lib.h"
struct node_t{
int value;//TODO: maybe change this
struct node_t * next;
};
struct queue_t{
struct node_t * Head;
struct node_t * Tail;
int lock;
};
struct pub_record{ //TODO: pad?? to avoid false sharing.
long long int temp;
int pending; //1 = waiting for op
long long int temp2;
int op; // operation 1= enqueue , 0= dequeue
long long int temp3;
int val;
long long int temp4;
int response; //1 means reposponse is here!
long long int temp5;
};
int ERROR_VALUE=54;
long long int glob_counter=0;
long long int count_enqs=0;
long long int count_deqs=0;
void lock_queue (struct queue_t * Q){
while (1){
if (!Q->lock){
if(!__sync_lock_test_and_set(&(Q->lock),1)) break;
}
}
}
void unlock_queue(struct queue_t * Q){
Q->lock = 0;
}
void initialize(struct queue_t * Q,struct pub_record * pub,int n){//TODO: init count?
int i;
struct node_t * node = (struct node_t *) malloc(sizeof(struct node_t));
node->next = NULL;
Q->Head = node; //TODO: check this
Q->Tail = node;
Q->lock = 0;
for(i=0; i <n ;i++){
pub[i].pending = 0;
pub[i].response =0;
}
}
void enqueue(struct queue_t * Q, int val){
int store = 0;
struct node_t * node = (struct node_t *) malloc(sizeof(struct node_t));
node->value = val;
node->next = NULL;
//while(__sync_lock_test_and_set(&Q->lock,1));
//#pragma omp critical
//struct node_t * tail = Q->Tail;
//tail->next =node;
Q->Tail->next=node;
Q->Tail = node;
//__sync_lock_test_and_set(&Q->lock,0);
}
int dequeue(struct queue_t * Q, int * val){
struct node_t * node = Q->Head;
struct node_t * next = node->next;
//struct node_t * tail = Q->Tail;
if(next == NULL) return 0;
else{
*val = next->value;
Q->Head =next;
}
free(node);
return 1;
}
int try_access(struct queue_t * Q,struct pub_record * pub,int operation, int val,int n){
int tid= omp_get_thread_num();
int i,res,count;
//1
pub[tid].op = operation;
pub[tid].val = val;
pub[tid].pending=1;
while (1){
if(Q->lock){
count=0;
while((!pub[tid].response)&&(count<10000000)) count++; //check periodicaly for lock
if(pub[tid].response ==1){
pub[tid].response=0;
return (pub[tid].val);
}
}
else{
if(__sync_lock_test_and_set(&(Q->lock),1)) continue;// must spin backto response
else{
glob_counter++;
for(i=0 ;i<n; i++){
if(pub[i].pending){
if (pub[i].op ==1) {count_enqs++; enqueue(Q,pub[i].val);}
else if(pub[i].op==0){
count_deqs++;
res=dequeue(Q,&pub[i].val);
if(!res)
pub[i].val = ERROR_VALUE;
}
else printf("wtf!! %d \n",pub[i].op);
pub[i].pending = 0;
pub[i].response = 1;
}
}
int temp_val=pub[tid].val;
pub[tid].response=0;
Q->lock=0;
return temp_val;
}
}
}
}
void printqueue(struct queue_t * Q){
struct node_t * curr ;
struct node_t * next ;
curr = Q->Head;
next = Q->Head->next;
while (curr != Q->Tail){
printf("%d ",curr->value);
curr = next;
next = curr ->next;
}
printf("%d ",curr->value);
printf("\n");
}
int main(int argc, char *argv[]){
int res,val,i,j,num_threads,count,result;
num_threads=atoi(argv[1]);
count =atoi(argv[2]);
struct queue_t * Q = (struct queue_t *) malloc(sizeof(struct queue_t));
struct pub_record pub[num_threads];
//Q->Head = NULL;
//Q->Tail = NULL;
initialize(Q,pub,num_threads);
/*result = try_access(Q,pub,1,5,num_threads);
result = try_access(Q,pub,1,7,num_threads);
result = try_access(Q,pub,0,5,num_threads);
printf("asdadsa %d\n",result);
result = try_access(Q,pub,1,12,num_threads);
printqueue(Q);
*/
/*enqueue(Q,5);
enqueue(Q,7);
enqueue(Q,4);
//res = dequeue(Q,&val);
//if (res) printf("Dequeued %d \n",val);
enqueue(Q,1);
printqueue(Q)*/
timer_tt * timer = timer_init();
timer_start(timer);
#pragma omp parallel for num_threads(num_threads) shared(Q,pub) private(res,val,i,j)
for(i=0;i<num_threads;i++){
for(j=0; j<count/num_threads;j++){
try_access(Q,pub,1,i,num_threads);
res=try_access(Q,pub,0,9,num_threads);
if(res==ERROR_VALUE) printf("%d\n",res);
}
}
timer_stop(timer);
double timer_val = timer_report_sec(timer);
printf("num_threads %d enq-deqs total %d\n",num_threads,count);
printf("thread number %d total time %lf\n",omp_get_thread_num(),timer_val);
printf("glob counter %ld \n",glob_counter);
timer_tt * timer2=timer_init();
timer_start(timer2);
int k=0;
for(k=0;k<glob_counter;k++){
for(i=0;i<num_threads;i++)
res=pub[i].pending;
}
timer_stop(timer2);
printf("total delay %lf\n",timer_report_sec(timer2));
printqueue(Q);
printf("total enqs %ld\n",count_enqs);
printf("total deqs %ld\n",count_deqs);
//------------------------------------------------------
/*double thread_time;
timer_tt * timer;
#pragma omp parallel for num_threads(num_threads) shared(Q) private(timer,j,i,thread_time)
for(i=0;i<num_threads;i++){
timer = timer_init();
timer_start(timer);
lock_queue(Q);
for( j=0; j<100;j++)
printf("thread %d in critical \n",omp_get_thread_num());
unlock_queue(Q);
timer_stop(timer);
thread_time = timer_report_sec(timer);
printf("thread %d time %lf\n",omp_get_thread_num(),thread_time);
}
*/
return 1;
}