SURFEX v8.1
General documentation of Surfex
fnecsx.c
Go to the documentation of this file.
1 /* fnecsx.c */
2 
3 /*
4 
5  This source file contains reverse-engineered functions that are called
6  when ALLOCATE & DEALLOCATE are issued in Fortran90 codes on NEC SX.
7 
8  This facilitates memory monitoring and allocations in a similar way
9  as we can do on IBM (see also getcurheap.c) and
10  provides unified interface to Dr.Hook with memory tracing/profiling.
11 
12  To have any effect, compile with sxcc :
13 
14  -DINTERCEPT_ALLOC
15  -DNECSX
16 
17 
18  Author: Sami Saarinen, ECMWF, 02-Feb-2007
19 
20 */
21 
22 #include "intercept_alloc.h"
23 
24 #if defined(INTERCEPT_ALLOC)
25 #if defined(NECSX)
26 
27 #include "raise.h"
28 #include <stdlib.h>
29 
30 typedef long long int ll_t;
31 typedef unsigned long long int u_ll_t;
32 
33 /* Maximum no of dimensions allowed in any given Fortran90 array */
34 
35 #define FNECSX_MAXDIM 7
36 
37 /*
38 typedef struct {
39  ll_t lo;
40  ll_t hi;
41  ll_t stride;
42 } dim_t ;
43 */
44 
45 #define FNECSX_NKEYS 3
46 #define FNECSX_KEY_LO 0
47 #define FNECSX_KEY_HI 1
48 #define FNECSX_KEY_ST 2
49 
50 typedef struct {
51  u_ll_t *p;
52  int status;
53  int ndims;
54  ll_t s[FNECSX_MAXDIM][FNECSX_NKEYS];
55 } desc_t;
56 
57 #if 0
58 /* Logical, f.ex.: if (ALLOCATED(allocatable_array)) ... */
59 extern ll_t fy_sallocd(desc_t *d);
60 #endif
61 
62 /* For sxf90 -dw i.e. 4-byte int for istat in [DE]ALLOCATE(..., stat=istat) is required */
63 extern void f_alloc(ll_t arg1, desc_t *d, int *stat, ll_t elsize);
64 extern void f_deallc(ll_t arg1, desc_t *d, int *stat);
65 
66 /* For sxf90 -ew i.e. 8-byte int for istat in [DE]ALLOCATE(..., stat=istat) is required */
67 extern void f_allocl(ll_t arg1, desc_t *d, ll_t *stat, ll_t elsize);
68 extern void f_deallcl(ll_t arg1, desc_t *d, ll_t *stat);
69 
70 int EC_malloc_will_abort = 0; /* affects getcurheap.c when memory allocation fails in EC_malloc() */
71 
72 extern void necsx_trbk_fl_(const char *msg, const char *filename, int *lineno,
73  int msglen, int filenamelen); /* from ../utilities/gentrbk.F90 */
74 #define ERROR_MSG(msg) { \
75  int lineno = __LINE__; necsx_trbk_fl_(msg, __FILE__, &lineno, strlen(msg), sizeof(__FILE__)-1); }
76 
77 #else
78 #undef INTERCEPT_ALLOC
79 #endif
80 #endif /* defined(INTERCEPT_ALLOC) */
81 
82 #if !defined(INTERCEPT_ALLOC)
83 
84 /* Other than NEC SX machines or when -DINTERCEPT_ALLOC was NOT supplied */
85 
86 void ec_envredo_() { }
87 
88 #else /* is indeed defined(INTERCEPT_ALLOC) */
89 
90 /* NEC SX with -DINTERCEPT_ALLOC */
91 
92 static int ec_prtdesc = -1;
93 static int ec_initheap = 0;
94 static unsigned int ec_initval4 = 0;
95 static u_ll_t ec_initval8 = 0;
96 static int ec_malloc = 1;
97 
98 static
99 void init4(unsigned int p4[], ll_t n)
100 {
101  u_ll_t tmp = ec_initval4;
102  ll_t j;
103  for (j=0; j<n; j++) p4[j] = tmp;
104 }
105 
106 static
107 void init8(u_ll_t p8[], ll_t n)
108 {
109  u_ll_t tmp = ec_initval8;
110  ll_t j;
111  for (j=0; j<n; j++) p8[j] = tmp;
112 }
113 
114 static
115 void envinit()
116 {
117  char *env;
118 
119  /* Print array descriptor info */
120  env = getenv("EC_PRTDESC");
121  if (env) {
122  ec_prtdesc = atoi(env);
123  if (ec_prtdesc != 0) ec_prtdesc = 1;
124  }
125  else {
126  ec_prtdesc = 0;
127  }
128 
129  /* Simulating the effect of "-init heap={zero|nan|0xXXXX}" */
130  env = getenv("EC_INITHEAP");
131  if (env) {
132  int len = strlen(env);
133  if (strcasecmp(env,"zero") == 0 || strcasecmp(env,"0") == 0) {
134  ec_initheap = 1; /* 1-byte long */
135  if (ec_prtdesc) fprintf(stderr,"EC_INITHEAP='%s' => ec_initheap = %d\n",env,ec_initheap);
136  }
137  else if (strcasecmp(env,"nan") == 0) {
138  ec_initheap = 4; /* 4-bytes long */
139  ec_initval4 = 0x7fffffff;
140  if (ec_prtdesc) fprintf(stderr,"EC_INITHEAP='%s' => ec_initheap = %d : value = 0x%x (%u,%d)\n",
142  }
143  else if (len >= 2 && env[0] == '0' && (env[1] == 'x' || env[1] == 'X')) {
144  if (len <= 10) { /* 0x12345678 */
145  ec_initheap = 4;
146  sscanf(env,"0x%x",&ec_initval4);
147  if (ec_prtdesc) fprintf(stderr,"EC_INITHEAP='%s' => ec_initheap = %d : value = 0x%x (%u,%d)\n",
149  }
150  else if (len > 10 && len <= 18) { /* 0x1234567890abcdef */
151  ec_initheap = 8;
152  sscanf(env,"0x%llx",&ec_initval8);
153  if (ec_prtdesc) fprintf(stderr,"EC_INITHEAP='%s' => ec_initheap = %d : value = 0x%llx (%llu,%lld)\n",
155  }
156  else {
157  ec_initheap = 0;
158  }
159  }
160  else {
161  ec_initheap = 0;
162  }
163  }
164  else {
165  ec_initheap = 0;
166  }
167 
168  /* Use EC_malloc/EC_calloc/EC_free (default) or malloc/calloc/free */
169  env = getenv("EC_MALLOC");
170  if (env) {
171  ec_malloc = atoi(env);
172  if (ec_malloc != 0) ec_malloc = 1;
173  }
174  else {
175  ec_malloc = 1;
176  }
177 }
178 
179 void ec_envredo_() { envinit(); };
180 
181 static
182 void prtdesc(ll_t arg1, FILE *fp, const char *s, const desc_t *d,
183  const int *stat, ll_t elsize_in)
184 {
185  if (ec_prtdesc == -1) {
186  envinit();
187  if (ec_prtdesc == 0) return;
188  }
189  if (fp && s && d) {
190  int j;
191  int ndims = d->ndims;
192  ll_t elsize = d->s[0][FNECSX_KEY_ST];
193  ll_t ntot = 1;
194  ll_t total_bytes;
195  ll_t nsave[FNECSX_MAXDIM];
196 #pragma cdir altcode,loopcnt=FNECSX_MAXDIM
197  for (j=0; j<ndims; j++) {
198  ll_t n = d->s[j][FNECSX_KEY_HI] - d->s[j][FNECSX_KEY_LO] + 1;
199  ntot *= n;
200  nsave[j] = n;
201  }
202  if (((ntot/2)*2) != ntot) ntot++; /* mod(ntot,2) not 0 i.e. ntot is odd --> add 1 */
203  total_bytes = ntot * elsize + 1;
204  fprintf(fp, "=== %s : desc = 0x%llx [%lld] : arg1 = %lld, stat (addr) = 0x%llx\n",s,d,d,arg1,stat);
205  fprintf(fp,"p = 0x%llx [%lld] : status = %d, ndims = %d, elsize's = (%lld, %lld), total = %lld\n",
206  d->p, d->p, d->status, ndims, elsize, elsize_in, total_bytes);
207  for (j=0; j<ndims; j++) {
208  ll_t n = nsave[j];
209  fprintf(fp,"[dim#%d] : lo = %lld, hi = %lld (n=%lld), stride = %lld\n",
210  j+1, d->s[j][FNECSX_KEY_LO], d->s[j][FNECSX_KEY_HI], n,
211  d->s[j][FNECSX_KEY_ST]);
212  }
213  if (d->p) {
214  u_ll_t dummy = d->p[-1];
215  u_ll_t adjsize = d->p[-2];
216  u_ll_t keyptr = d->p[-3];
217  fprintf(fp,"\tdummy = %llu\n",dummy);
218  fprintf(fp,"\tadjsize (bytes) = %llu\n",adjsize);
219  fprintf(fp,"\tDr.Hook keyptr = 0x%llx [%llu]\n",keyptr,keyptr);
220  }
221  }
222 }
223 
224 #if 0
225 ll_t fy_sallocd(desc_t *d)
226 {
227  if (ec_prtdesc) prtdesc(-1, stderr, "fy_sallocd", d, NULL, -1);
228  return (d && d->p && (d->status == 3 || d->status == 1)) ? 1 : 0;
229 }
230 #endif
231 
232 void f_alloc(ll_t arg1, desc_t *d, int *stat, ll_t elsize)
233 {
234  const int istat_offset = 193;
235  int istat = 0;
236  const char *errmsg[2] = {
237  "Value of allocate-object must not be currently allocated array in ALLOCATE.", /* 193 */
238  "Could not allocate in ALLOCATE." /* 194 */
239  };
240  if (stat && stat == (int *)0x1) stat = NULL;
241  if (ec_prtdesc) prtdesc(arg1, stderr, "f_alloc>", d, stat, elsize);
242  if (d && (arg1 == 3 || arg1 == 2)) {
243  /* arg1 == 3 : ALLOCATABLE array --> d->status becomes = 3
244  arg1 == 2 : POINTER array --> d->status becomes = 1 */
245  int j;
246  int ndims = d->ndims;
247  u_ll_t *p = NULL;
248  void *vptr = NULL;
249  ll_t ntot = 1;
250  ll_t total_bytes;
251  ll_t nsave[FNECSX_MAXDIM];
252 #pragma cdir altcode,loopcnt=FNECSX_MAXDIM
253  for (j=0; j<ndims; j++) {
254  ll_t n = d->s[j][FNECSX_KEY_HI] - d->s[j][FNECSX_KEY_LO] + 1;
255  ntot *= n;
256  nsave[j] = n;
257  }
258  if (((ntot/2)*2) != ntot) ntot++; /* mod(ntot,2) not 0 i.e. ntot is odd --> add 1 */
259  total_bytes = ntot * elsize + 1;
260  if (ec_initheap == 1) {
261  /* EC_INITHEAP=zero */
262  if (ec_malloc) {
263  vptr = EC_calloc(total_bytes,1);
264  }
265  else {
266  vptr = calloc(total_bytes,1);
267  }
268  }
269  else {
270  if (ec_malloc) {
271  vptr = EC_malloc(total_bytes);
272  }
273  else {
274  vptr = malloc(total_bytes);
275  }
276  if (ec_initheap != 0) {
277  if (ec_initheap == 4) {
278  /* EC_INITHEAP=nan or max an 8 digit hexadecimal number */
279  ll_t n = total_bytes/4;
280  init4(vptr, n);
281  }
282  else if (ec_initheap == 8) {
283  /* EC_INITHEAP=nan or a 9-16 digit hexadecimal number */
284  ll_t n = total_bytes/8;
285  init8(vptr, n);
286  }
287  } /* if (ec_initheap) */
288  }
289  p = vptr;
290  if (p) {
291  d->p = p;
292  d->status = (arg1 == 3) ? 3 : 1;
293  d->s[0][FNECSX_KEY_ST] = elsize;
294  if (ndims > 1) {
295 #pragma cdir altcode,loopcnt=FNECSX_MAXDIM
296  for (j=1; j<ndims; j++) {
297  d->s[j][FNECSX_KEY_ST] = nsave[j] * d->s[j-1][FNECSX_KEY_ST];
298  }
299  } /* if (ndims > 1) */
300  }
301  else {
302  istat = 194;
303  }
304  }
305  else {
306  istat = 193;
307  }
308  if (ec_prtdesc) prtdesc(arg1, stderr, "f_alloc<", d, stat, elsize);
309  if (istat != 0 && !stat) {
310  const char *msg = errmsg[istat-istat_offset];
311  fprintf(stderr,"***Error#%d: %s\n",istat,msg);
312  prtdesc(arg1, stderr, "f_alloc", d, stat, elsize);
313  ERROR_MSG(msg);
314  RAISE(SIGABRT);
315  _exit(1); /* Just in case, but shouldn't end up here at all */
316  }
317  if (stat) *stat = istat;
318 }
319 
320 
321 void f_allocl(ll_t arg1, desc_t *d, ll_t *stat, ll_t elsize)
322 {
323  int istat = 0;
324  if (stat && stat == (ll_t *)0x1) stat = NULL;
325  f_alloc(arg1, d, stat ? &istat : NULL, elsize);
326  if (stat) *stat = istat;
327 }
328 
329 
330 void f_deallc(ll_t arg1, desc_t *d, int *stat)
331 {
332  const int istat_offset = 195;
333  int istat = 0;
334  const char *errmsg[2] = {
335  "Value of allocate-object must not be disassociated pointer/not allocated array in DEALLOCATE.", /* 195 */
336  "Illegal value of allocate-object in DEALLOCATE." /* 196 */
337  };
338  if (stat && stat == (int *)0x1) stat = NULL;
339  if (ec_prtdesc) prtdesc(arg1, stderr, "f_deallc>", d, stat, -1);
340  if (d && ((arg1 | d->status) == 3)) {
341  int j;
342  int ndims = d->ndims;
343  u_ll_t *p = d->p;
344  if (p) {
345  if (ec_malloc) {
346  EC_free(p);
347  }
348  else {
349  free(p);
350  }
351  d->p = NULL;
352  d->status = 0;
353 #pragma cdir altcode,loopcnt=FNECSX_MAXDIM
354  for (j=0; j<ndims; j++) {
355  d->s[j][FNECSX_KEY_ST] = 0;
356  }
357  }
358  else {
359  istat = 196;
360  }
361  }
362  else {
363  istat = 195;
364  }
365  if (ec_prtdesc) prtdesc(arg1, stderr, "f_deallc<", d, stat, -1);
366  if (istat != 0 && !stat) {
367  const char *msg = errmsg[istat-istat_offset];
368  fprintf(stderr,"***Error#%d: %s\n",istat,msg);
369  prtdesc(arg1, stderr, "f_deallc", d, stat, -1);
370  ERROR_MSG(msg);
371  RAISE(SIGABRT);
372  _exit(1); /* Just in case, but shouldn't end up here at all */
373  }
374  if (stat) *stat = istat;
375 }
376 
377 
378 void f_deallcl(ll_t arg1, desc_t *d, ll_t *stat)
379 {
380  int istat = 0;
381  if (stat && stat == (ll_t *)0x1) stat = NULL;
382  f_deallc(arg1, d, stat ? &istat : NULL);
383  if (stat) *stat = istat;
384 }
385 
386 #endif /* #if !defined(INTERCEPT_ALLOC) ... #else ... */
387 
388 void ec_envredo() { ec_envredo_(); }
void necsx_trbk_fl_(const char *msg, const char *filename, int *lineno, int msglen, int filenamelen)
static void init8(u_ll_t p8[], ll_t n)
Definition: fnecsx.c:107
void f_alloc(ll_t arg1, desc_t *d, int *stat, ll_t elsize)
Definition: fnecsx.c:232
void f_deallcl(ll_t arg1, desc_t *d, ll_t *stat)
Definition: fnecsx.c:378
static void prtdesc(ll_t arg1, FILE *fp, const char *s, const desc_t *d, const int *stat, ll_t elsize_in)
Definition: fnecsx.c:182
unsigned long long int u_ll_t
Definition: privpub.h:295
long long int ll_t
Definition: privpub.h:293
FILE * fp
Definition: opfla_perfmon.c:24
static int ec_initheap
Definition: fnecsx.c:93
void f_deallc(ll_t arg1, desc_t *d, int *stat)
Definition: fnecsx.c:330
int EC_malloc_will_abort
Definition: fnecsx.c:70
ERROR in n
Definition: ecsort_shared.h:90
ll_t fy_sallocd(desc_t *d)
Definition: fnecsx.c:225
long long int ll_t
Definition: fnecsx.c:30
void f_allocl(ll_t arg1, desc_t *d, ll_t *stat, ll_t elsize)
Definition: fnecsx.c:321
void ec_envredo()
Definition: fnecsx.c:388
static void init4(unsigned int p4[], ll_t n)
Definition: fnecsx.c:99
void * EC_calloc(long long int nelem, long long int elsize)
Definition: getcurheap.c:490
static int ec_prtdesc
Definition: fnecsx.c:92
static int ec_malloc
Definition: fnecsx.c:96
void EC_free(void *p)
Definition: getcurheap.c:315
void * EC_malloc(long long int size)
Definition: getcurheap.c:366
unsigned long long int u_ll_t
Definition: fnecsx.c:31
static void envinit()
Definition: fnecsx.c:115
void ec_envredo_()
Definition: fnecsx.c:86
static u_ll_t ec_initval8
Definition: fnecsx.c:95
static unsigned int ec_initval4
Definition: fnecsx.c:94