Modified GPU Manager so that quiescence will not be detected in situations
[charm.git] / src / arch / cuda / hybridAPI / wrqueue.cu
1 /*
2  * wrqueue.cu
3  *
4  * by Lukasz Wesolowski
5  * 04.12.2008
6  *
7  * a simple FIFO queue for GPU work requests
8  *
9  */
10
11 #include "ck.h"
12 #include "cuda-hybrid-api.h"
13 #include "wrqueue.h"
14 #include "stdio.h"
15
16 #ifdef GPU_WRQ_VERBOSE
17 extern int CmiMyPe();
18 #endif
19
20 void initWRqueue(workRequestQueue **qptr) {
21
22   (*qptr) = (workRequestQueue*) malloc(sizeof(workRequestQueue));  
23
24   (*qptr)->head = 0; 
25   (*qptr)->tail = -1;
26   (*qptr)->size = 0; 
27   (*qptr)->capacity = QUEUE_SIZE_INIT; 
28   (*qptr)->requests = (workRequest *) 
29     malloc(QUEUE_SIZE_INIT * sizeof(workRequest)); 
30
31 }
32
33 void enqueue(workRequestQueue *q, workRequest *wr) {
34   if (q->size == q->capacity) {
35     workRequest *newArray; 
36     int newSize; 
37     int tailendIndex;/* the starting index for the second part of the array */
38
39     /* queue is out of space: create a new queue that is a factor
40        QUEUE_EXPANSION_FACTOR larger */
41
42     newSize = q->capacity * QUEUE_EXPANSION_FACTOR;
43     newArray = (workRequest *) malloc(newSize * sizeof(workRequest));
44
45     /* copy requests to the new array */
46     memcpy(newArray, &q->requests[q->head], 
47            (q->capacity - q->head) * sizeof(workRequest));
48
49     /* if head index is not 0, there are additional work requests to
50        be copied from the beginning of the array */
51     if (q->head != 0) {
52       tailendIndex = q->capacity - q->head; 
53       memcpy(&newArray[tailendIndex], q->requests, 
54              q->head * sizeof(workRequest)); 
55     }
56
57     /* free the old queue's memory */
58     
59     free(q->requests); 
60
61     /* update bookkeeping variables in the expanded queue */
62     q->tail = q->size - 1; 
63     q->capacity *= QUEUE_EXPANSION_FACTOR;
64     q->head = 0;
65     
66     /* reassign the pointer to the new queue */
67     q->requests = newArray;
68   }
69
70   q->tail++; 
71   if (q->tail == q->capacity) {
72     q->tail = 0; 
73   }
74
75   memcpy(&q->requests[q->tail], wr, sizeof(workRequest));
76
77   q->requests[q->tail].state = QUEUED; 
78
79   q->size++; 
80
81   CpvAccess(_qd)->create();
82
83 #ifdef GPU_WRQ_VERBOSE
84   printf("(%d) ENQ size: %d\n", CmiMyPe(), q->size);
85 #endif
86 }
87
88 void setWRCallback(workRequest *wr, void *cb) {
89     wr->callbackFn = cb;
90 }
91
92 void dequeue(workRequestQueue *q) {
93   q->head++; 
94   if (q->head == q->capacity) {
95     q->head = 0; 
96   }
97   q->size--; 
98 #ifdef GPU_WRQ_VERBOSE
99   printf("(%d) DEQ size: %d\n", CmiMyPe(), q->size);
100 #endif
101
102   CpvAccess(_qd)->process();
103
104 }
105
106 int deleteWRqueue(workRequestQueue *q) {
107   if (q->size != 0) {
108     return -1; 
109   }
110   else {
111     free(q->requests); 
112     return 0; 
113   }
114 }
115
116 workRequest * firstElement(workRequestQueue *q) {
117   if (q->size == 0) {
118     return NULL; 
119   }
120   else {
121     return &q->requests[q->head]; 
122   }
123 }
124
125 workRequest * secondElement(workRequestQueue *q) {
126   if (q->size < 2) {
127     return NULL; 
128   }
129   else {
130     if (q->head == (q->capacity-1)) {
131       return &q->requests[0];
132     }
133     else {
134       return &q->requests[q->head+1]; 
135     }
136   }
137 }
138
139 workRequest * thirdElement(workRequestQueue *q) {
140   if (q->size < 3) {
141     return NULL; 
142   }
143   else {
144     int wrIndex = q->head+2;
145
146     if (wrIndex >= q->capacity) {
147       wrIndex -= q->capacity; 
148     }
149
150     return &q->requests[wrIndex]; 
151   }
152 }
153
154 int isEmpty(workRequestQueue *q) {
155   if (q->size == 0) {
156     return 1; 
157   }
158   else {
159     return 0; 
160   }
161 }