1 /*
2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include "stdioInterf.h"
19 #include "fioMacros.h"
20
21 #define DEFENTS (512)
22
23 /* allocate channel structure */
24
25 struct chdr *
__fort_allchn(struct chdr * cp,int dents,int sents,int cpus)26 __fort_allchn(struct chdr *cp, int dents, int sents, int cpus)
27 {
28 struct chdr *c;
29 struct chdr *ct;
30
31 /* allocate new channel, ents, and cpu structures */
32
33 c = (chdr *)__fort_calloc(sizeof(chdr) +
34 (sizeof(struct ents) * (dents + sents)) +
35 (sizeof(struct ccpu) * cpus),
36 1);
37 c->sp = (struct ents *)((char *)c + sizeof(chdr));
38 c->sn = sents;
39 c->rp =
40 (struct ents *)((char *)c + sizeof(chdr) + (sizeof(struct ents) * sents));
41 c->rn = dents;
42 c->cp = (struct ccpu *)((char *)c + sizeof(chdr) +
43 (sizeof(struct ents) * (sents + dents)));
44 c->cn = cpus;
45 c->flags = CHDR_1INT | CHDR_1DBL;
46
47 /* chain structure into list */
48
49 if (cp != (struct chdr *)0) {
50 ct = cp;
51 while (ct->next != (struct chdr *)0) {
52 ct = ct->next;
53 }
54 ct->next = c;
55 }
56
57 return (c);
58 }
59
60 /* free a list of channels */
61
62 void
__fort_frechn(struct chdr * c)63 __fort_frechn(struct chdr *c)
64 {
65 struct chdr *d;
66 int n;
67
68 while (c != (struct chdr *)0) {
69 for (n = 0; n < c->sn; n++) {
70 if (c->sp[n].beg != (struct ent *)0) {
71 __fort_free((char *)c->sp[n].beg);
72 }
73 }
74 for (n = 0; n < c->rn; n++) {
75 if (c->rp[n].beg != (struct ent *)0) {
76 __fort_free((char *)c->rp[n].beg);
77 }
78 }
79 for (n = 0; n < c->cn; n++) {
80 if (c->cp[n].opt != (void *)0) {
81 __fort_free((char *)c->cp[n].opt);
82 }
83 }
84 d = c->next;
85 __fort_free(c);
86 c = d;
87 }
88 }
89
90 /* reset channels */
91
92 void
__fort_rstchn(struct chdr * c)93 __fort_rstchn(struct chdr *c)
94 {
95 int n;
96
97 while (c != (struct chdr *)0) {
98 for (n = 0; n < c->sn; n++) {
99 c->sp[n].avl = c->sp[n].beg;
100 }
101 for (n = 0; n < c->rn; n++) {
102 c->rp[n].avl = c->rp[n].beg;
103 }
104 c = c->next;
105 }
106 }
107
108 /* send data */
109
__fort_sendl(struct chdr * c,int indx,void * adr,long cnt,long str,int typ,long ilen)110 void __fort_sendl(struct chdr *c, /* channels */
111 int indx, /* indx to send to */
112 void *adr, /* adr of first data item */
113 long cnt, /* number of data items */
114 long str, /* stride between data items */
115 int typ, /* data type (see pghpft.h) */
116 long ilen) /* data item length */
117 {
118 register struct ents *s;
119 register int n;
120
121 #ifdef DEBUG
122 if (indx >= c->sn) {
123 __fort_abort("__fort_send: index >= cpu count\n");
124 }
125 #endif
126 s = &(c->sp[indx]);
127 if (s->avl == s->end) {
128 n = s->end - s->beg;
129 if (s->beg == (struct ent *)0) {
130 s->beg = (struct ent *)__fort_malloc((n + DEFENTS) * sizeof(struct ent));
131 } else {
132 s->beg = (struct ent *)__fort_realloc(s->beg,
133 (n + DEFENTS) * sizeof(struct ent));
134 }
135 s->end = s->beg + n + DEFENTS;
136 s->avl = s->beg + n;
137 }
138 s->avl->adr = adr;
139 s->avl->cnt = cnt;
140 s->avl->str = str;
141 s->avl->typ = typ;
142 s->avl->ilen = ilen;
143 s->avl->len = cnt * ilen;
144 if (c->flags & (CHDR_1INT | CHDR_1DBL)) {
145 if (cnt != 1) {
146 c->flags &= ~(CHDR_1INT | CHDR_1DBL);
147 } else {
148 if (ilen != sizeof(int)) {
149 c->flags &= ~CHDR_1INT;
150 }
151 if (ilen != sizeof(double)) {
152 c->flags &= ~CHDR_1DBL;
153 }
154 }
155 }
156 s->avl++;
157 }
158
159 /* recv data */
160
__fort_recvl(struct chdr * c,int indx,void * adr,long cnt,long str,int typ,long ilen)161 void __fort_recvl(struct chdr *c, /* channels */
162 int indx, /* indx to receive from */
163 void *adr, /* adr of first data item */
164 long cnt, /* number of data items */
165 long str, /* stride between data items */
166 int typ, /* data type (see pghpft.h) */
167 long ilen) /* data item length */
168 {
169 register struct ents *r;
170 register int n;
171
172 #ifdef DEBUG
173 if (indx >= c->rn) {
174 __fort_abort("__fort_recv: index >= cpu count\n");
175 }
176 #endif
177 r = &(c->rp[indx]);
178 if (r->avl == r->end) {
179 n = r->end - r->beg;
180 if (r->beg == (struct ent *)0) {
181 r->beg = (struct ent *)__fort_malloc((n + DEFENTS) * sizeof(struct ent));
182 } else {
183 r->beg = (struct ent *)__fort_realloc(r->beg,
184 (n + DEFENTS) * sizeof(struct ent));
185 }
186 r->end = r->beg + n + DEFENTS;
187 r->avl = r->beg + n;
188 }
189 r->avl->adr = adr;
190 r->avl->cnt = cnt;
191 r->avl->str = str;
192 r->avl->typ = typ;
193 r->avl->ilen = ilen;
194 r->avl->len = cnt * ilen;
195 if (c->flags & (CHDR_1INT | CHDR_1DBL)) {
196 if (cnt != 1) {
197 c->flags &= ~(CHDR_1INT | CHDR_1DBL);
198 } else {
199 if (ilen != sizeof(int)) {
200 c->flags &= ~CHDR_1INT;
201 }
202 if (ilen != sizeof(double)) {
203 c->flags &= ~CHDR_1DBL;
204 }
205 }
206 }
207 r->avl++;
208 }
209
210 /* chain channels together */
211
__fort_chain_em_up(struct chdr * list,struct chdr * c)212 struct chdr *__fort_chain_em_up(struct chdr *list, /* current and new head */
213 struct chdr *c) /* new tail */
214 {
215 struct chdr *ct;
216
217 if (list == (struct chdr *)0) {
218 return (c);
219 }
220 ct = list;
221 while (ct->next != (struct chdr *)0) {
222 ct = ct->next;
223 }
224 ct->next = c;
225 return (list);
226 }
227
228 /* change data addresses and type in list of channels */
229
__fort_adjbase(struct chdr * c,char * bases,char * baser,int typ,long ilen)230 void __fort_adjbase(struct chdr *c, /* list of channels */
231 char *bases, /* send base address */
232 char *baser, /* recv base address */
233 int typ, /* data type */
234 long ilen) /* data item length */
235 {
236 struct ent *p;
237 int n;
238 long l;
239
240 while (c != (struct chdr *)0) {
241 if (~c->flags & CHDR_BASE) {
242 __fort_abort("__fort_adjbase: setbase not called");
243 }
244 c->flags &= ~(CHDR_1INT | CHDR_1DBL);
245 if ((c->bases != bases) || (c->typ != typ) || (c->ilen != ilen)) {
246 if (c->ilen == ilen) {
247 for (n = 0; n < c->sn; n++) {
248 p = c->sp[n].beg;
249 while (p < c->sp[n].avl) {
250 l = p->adr - c->bases;
251 p->adr = l + bases;
252 #ifdef DEBUG
253 if (c->typ != p->typ)
254 __fort_abort("__fort_adjbase: inconsistent send data types");
255 #endif
256 p->typ = typ;
257 p++;
258 }
259 }
260 } else {
261 for (n = 0; n < c->sn; n++) {
262 p = c->sp[n].beg;
263 while (p < c->sp[n].avl) {
264 l = p->adr - c->bases;
265 l /= c->ilen;
266 l *= ilen;
267 p->adr = l + bases;
268 #ifdef DEBUG
269 if (c->typ != p->typ)
270 __fort_abort("__fort_adjbase: inconsistent send data types");
271 #endif
272 p->typ = typ;
273 p->ilen = ilen;
274 p->len = p->cnt * ilen;
275 p++;
276 }
277 }
278 }
279 c->bases = bases;
280 }
281 if ((c->baser != baser) || (c->typ != typ) || (c->ilen != ilen)) {
282 if (c->ilen == ilen) {
283 for (n = 0; n < c->rn; n++) {
284 p = c->rp[n].beg;
285 while (p < c->rp[n].avl) {
286 l = p->adr - c->baser;
287 p->adr = l + baser;
288 #ifdef DEBUG
289 if (c->typ != p->typ)
290 __fort_abort("__fort_adjbase: inconsistent recv data types");
291 #endif
292 p->typ = typ;
293 p++;
294 }
295 }
296 } else {
297 for (n = 0; n < c->rn; n++) {
298 p = c->rp[n].beg;
299 while (p < c->rp[n].avl) {
300 l = p->adr - c->baser;
301 l /= c->ilen;
302 l *= ilen;
303 p->adr = l + baser;
304 #ifdef DEBUG
305 if (c->typ != p->typ)
306 __fort_abort("__fort_adjbase: inconsistent recv data types");
307 #endif
308 p->typ = typ;
309 p->ilen = ilen;
310 p->len = p->cnt * ilen;
311 p++;
312 }
313 }
314 }
315 c->baser = baser;
316 }
317 c->typ = typ;
318 c->ilen = ilen;
319 c = c->next;
320 }
321 }
322
323 /* set bases addresses and data type (called once after __fort_chn_xxx) */
324
__fort_setbase(chdr * c,char * bases,char * baser,int typ,long ilen)325 void __fort_setbase(chdr *c, /* list of channels */
326 char *bases, /* send base address */
327 char *baser, /* recv base address */
328 int typ, /* data type */
329 long ilen) /* data item length */
330 {
331
332 while (c != (struct chdr *)0) {
333 c->flags |= CHDR_BASE;
334 c->bases = bases;
335 c->baser = baser;
336 c->typ = typ;
337 c->ilen = ilen;
338 c = c->next;
339 }
340 }
341
342 /*
343 * keep track of the global buffer
344 *
345 * this routine should ONLY be used by routines called by __fort_doit and
346 * then only very carefully.
347 */
348
349 #define GBUFA 4096 /* global buffer size alignment */
350
351 static int gbufz;
352 static char *gbuf;
353
354 char *
__fort_getgbuf(long len)355 __fort_getgbuf(long len)
356 {
357 if (len <= gbufz) {
358 return (gbuf);
359 }
360 if (gbuf != (char *)0) {
361 __fort_gfree(gbuf);
362 }
363 len = (len + GBUFA - 1) & ~(GBUFA - 1);
364 gbuf = __fort_gmalloc(len);
365 gbufz = len;
366 return (gbuf);
367 }
368
369 /* prune unsed entries and do special optimizations */
370
371 #define MINSHIFT 1024 /* smaller send values may be send */
372
373 void
__fort_chn_prune(struct chdr * c)374 __fort_chn_prune(struct chdr *c)
375 {
376 struct ccpu *cp;
377 struct ccpu ccpu;
378 int n;
379 int m;
380
381 while (c != (struct chdr *)0) {
382
383 /* prune unused entries */
384
385 m = 0;
386 for (n = 0; n < c->cn; n++) {
387 if (n != m) {
388 c->cp[m] = c->cp[n];
389 }
390 if (((c->cp[n].sp != (struct ents *)0) &&
391 (c->cp[n].sp->avl > c->cp[n].sp->beg)) ||
392 ((c->cp[n].rp != (struct ents *)0) &&
393 (c->cp[n].rp->avl > c->cp[n].rp->beg))) {
394 m++;
395 }
396 }
397 c->cn = m;
398
399 c = c->next;
400 }
401 }
402