6
/*The structure of gai_nbhdl_t is (this is our internal handle)*/
9
unsigned int ihdl_index:8;
10
unsigned int ga_nbtag:24;
14
/*Each element in the armci handle linked list is of type ga_armcihdl_t*/
15
typedef struct struct_armcihdl_t{
17
struct struct_armcihdl_t *next;
18
struct struct_armcihdl_t *previous;
24
/*We create an array of type ga_nbhdl_array_t. Each of the elements in this
25
array is the head of the armcihandle linked list that is associated with
29
ga_armcihdl_t *ahandle;
35
/*fills up the armci_hdl_t entries in ga_armcihdl_t */
36
static armci_hdl_t hdl_array[NUM_HDLS];
39
/*index of the following array goes into ihdl_index. while waiting for a
40
*non-bloking ga call, we first check if
41
*(list_element_array[inbhandle->ihdl_index].ga_nbtag == inbhandle->ga_nbtag)
42
*if it is, then we complete all the armci handles in the linked list this
45
static ga_nbhdl_array_t ga_ihdl_array[NUM_HDLS];
48
/*this is the array of linked list elements. */
49
static ga_armcihdl_t list_element_array[NUM_HDLS] = {
50
{&(hdl_array[0]), NULL,NULL,0, -1 },{&(hdl_array[1]), NULL,NULL, 1,-1 },
51
{&(hdl_array[2]), NULL,NULL,2, -1 },{&(hdl_array[3]), NULL,NULL, 3,-1 },
52
{&(hdl_array[4]), NULL,NULL,4, -1 },{&(hdl_array[5]), NULL,NULL, 5,-1 },
53
{&(hdl_array[6]), NULL,NULL,6, -1 },{&(hdl_array[7]), NULL,NULL, 7,-1 },
54
{&(hdl_array[8]), NULL,NULL,8, -1 },{&(hdl_array[9]), NULL,NULL, 9,-1 },
55
{&(hdl_array[10]),NULL,NULL,10,-1 },{&(hdl_array[11]),NULL,NULL,11,-1 },
56
{&(hdl_array[12]),NULL,NULL,12,-1 },{&(hdl_array[13]),NULL,NULL,13,-1 },
57
{&(hdl_array[14]),NULL,NULL,14,-1 },{&(hdl_array[15]),NULL,NULL,15,-1 },
58
{&(hdl_array[16]),NULL,NULL,16,-1 },{&(hdl_array[17]),NULL,NULL,17,-1 },
59
{&(hdl_array[18]),NULL,NULL,18,-1 },{&(hdl_array[19]),NULL,NULL,19,-1 }};
66
static int nextIHAelement=-1; /*oldest ga_ihdl_array element*/
67
static int nextLEAelement=-1; /*oldest list_element_array element*/
68
static int ihdl_array_avail[NUM_HDLS]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
69
static int list_ele_avail[NUM_HDLS]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
71
/*\ a unique tag everytime
73
static unsigned int ga_nb_tag;
74
unsigned int get_next_tag(){
75
return((++ga_nb_tag));
78
/*\ the only way to complete a list element!
79
* does the basic list operation: remove element, update previous and next
80
* links of the previous and next elements in the linked list
81
* prev==null => this was the element pointed by the head(ie, first element).
83
static void clear_list_element(int index){
84
ga_armcihdl_t *listele,*prev,*next;
86
printf("\n%d:clearing handle %d\n",GAme,index);fflush(stdout);
88
listele = &(list_element_array[index]);
90
/*first wait for the armci handle */
91
ARMCI_Wait(listele->handle);
93
/*set prev and next links of my prev element and my next element*/
94
prev=listele->previous;
99
ga_ihdl_array[listele->ga_hdlarr_index].ahandle=next;
101
next->previous = prev;
103
/*since one element from the linked list is completed, update the count*/
104
ga_ihdl_array[listele->ga_hdlarr_index].count--;
106
/*reset the prev and next pointers and initialize the handle*/
108
listele->previous=NULL;
109
ARMCI_INIT_HANDLE(listele->handle);
110
list_ele_avail[index]=1;
114
/*\ Get the next available list element from the list element array, if
115
* nothing is available, free element with index nextLEAelement
117
ga_armcihdl_t* get_armcihdl(){
119
ga_armcihdl_t *ret_handle;
121
/*first see if an element from the list_ele_arr is already available */
122
for(i=0;i<NUM_HDLS;i++)
123
if(list_ele_avail[i]){
125
ARMCI_INIT_HANDLE(list_element_array[i].handle);
127
printf("\n%d:found a free handle %d\n",GAme,i);fflush(stdout);
129
return(&(list_element_array[i]));
132
/*nothing is available so best element to clear is nextLEAelement(LRU)*/
133
if(nextLEAelement==-1)
136
printf("\n%d:have to clear handle %d\n",GAme,nextLEAelement);
139
clear_list_element(nextLEAelement);
140
list_ele_avail[nextLEAelement]=0;
142
ret_handle=&(list_element_array[nextLEAelement]);
144
/*update the LRU element index */
145
nextLEAelement = (nextLEAelement+1)%NUM_HDLS;
149
/*\ Input is the index to the ga_ihdl_array that has the head of the list.
150
* This function waits for all the elements in the list.
152
static void free_armci_handle_list(int elementtofree){
153
ga_armcihdl_t *first = ga_ihdl_array[elementtofree].ahandle,*next;
154
/*call clear_list_element for every element in the list*/
157
clear_list_element(first->index);
161
/*reset the head of the list for reuse*/
162
ga_ihdl_array[elementtofree].count=0;
163
ga_ihdl_array[elementtofree].ga_nbtag=0;
164
ga_ihdl_array[elementtofree].ahandle=NULL;
165
ihdl_array_avail[elementtofree]=1;
169
/*\ Add the armci handle list element to the end of the list.
171
static void add_armcihdl_to_list(ga_armcihdl_t *listelement, int headindex){
172
ga_armcihdl_t *first=ga_ihdl_array[headindex].ahandle;
174
ga_ihdl_array[headindex].count++;
175
listelement->ga_hdlarr_index = headindex;
176
if(ga_ihdl_array[headindex].ahandle==NULL){
177
ga_ihdl_array[headindex].ahandle=listelement;
178
listelement->previous= NULL;
181
while(first->next!=NULL){
184
first->next=listelement;
185
listelement->previous=first;
189
/*\ Complete the list of armci handles associated with a particular GA request.
190
* specific=-1 means free the next available one. other values complete the
191
* armci handle list pointed to by head at that "specific" element.
193
static int get_GAnbhdl_element(int specific){
195
if(specific!=-1)elementtofree=specific;
197
for(i=0;i<NUM_HDLS;i++)
198
if(ihdl_array_avail[i]){
199
ihdl_array_avail[i]=0;
202
if(nextIHAelement==-1)
204
elementtofree=nextIHAelement;
205
nextIHAelement = (elementtofree+1)%NUM_HDLS;
207
free_armci_handle_list(elementtofree);
208
return(elementtofree);
212
/*\ called from ga_put/get before a call to every non-blocking armci request.
214
armci_hdl_t* get_armci_nbhandle(Integer *nbhandle){
215
gai_nbhdl_t *inbhandle = (gai_nbhdl_t *)nbhandle;
216
ga_armcihdl_t *ret_handle;
217
if(inbhandle->ihdl_index == (NUM_HDLS+1)){
218
inbhandle->ihdl_index = get_GAnbhdl_element(-1);
219
inbhandle->ga_nbtag = get_next_tag();
220
ga_ihdl_array[(inbhandle->ihdl_index)].ga_nbtag=inbhandle->ga_nbtag;
222
ret_handle = get_armcihdl();
223
add_armcihdl_to_list(ret_handle,inbhandle->ihdl_index);
224
return(ret_handle->handle);
227
/*\ the wait routine which is called inside nga_nbwait and ga_nbwait
229
int nga_wait_internal(Integer *nbhandle){
230
gai_nbhdl_t *inbhandle = (gai_nbhdl_t *)nbhandle;
232
if(inbhandle->ihdl_index==(NUM_HDLS+1))retval=0;
233
else if(inbhandle->ga_nbtag !=ga_ihdl_array[inbhandle->ihdl_index].ga_nbtag)
236
free_armci_handle_list(inbhandle->ihdl_index);
242
static int test_list_element(int index){
243
ga_armcihdl_t *listele,*prev,*next;
245
printf("\n%d:clearing handle %d\n",GAme,index);fflush(stdout);
247
listele = &(list_element_array[index]);
249
return (ARMCI_Test(listele->handle));
252
static int test_armci_handle_list(int elementtofree){
253
ga_armcihdl_t *first = ga_ihdl_array[elementtofree].ahandle,*next;
255
/*call clear_list_element for every element in the list*/
258
if (test_list_element(first->index) == 0) {
267
/*\ the test routine which is called inside nga_nbtest
269
int nga_test_internal(Integer *nbhandle){
270
gai_nbhdl_t *inbhandle = (gai_nbhdl_t *)nbhandle;
272
if(inbhandle->ihdl_index==(NUM_HDLS+1))retval=0;
273
else if(inbhandle->ga_nbtag !=ga_ihdl_array[inbhandle->ihdl_index].ga_nbtag)
276
return (test_armci_handle_list(inbhandle->ihdl_index));
281
/*\ unlike in ARMCI, user doesnt have to initialize handle in GA.
282
* it is done by the get/put call instead.
284
void ga_init_nbhandle(Integer *nbhandle)
286
gai_nbhdl_t *inbhandle = (gai_nbhdl_t *)nbhandle;
287
inbhandle->ihdl_index=(NUM_HDLS+1);