Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001, Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2.1 of the GNU Lesser General Public License 00007 as published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU Lesser General Public 00021 License along with this program; if not, write the Free Software 00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 00023 USA. 00024 00025 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00026 Mountain View, CA 94043, or: 00027 00028 http://www.sgi.com 00029 00030 For further information regarding this notice, see: 00031 00032 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00033 00034 */ 00035 00036 00037 00038 #pragma ident "@(#) libf/fio/finit.c 92.4 11/16/99 15:43:33" 00039 00040 /* 00041 * This module contains Fortran initialization routines. There 00042 * are three times Fortran initialization routines are called: 00043 * 00044 * 1) Called at first I/O 00045 * _initialize_e_fortran_io() 00046 * _initialize_i_fortran_io() 00047 * 2) Called from $START(). 00048 * _finit() on PVP and MPP systems 00049 * _F90_INIT() on Sparc systems 00050 * _initialize_e_fortran_io() on all systems 00051 * 3) Called from Fortran main program prologue code. 00052 * f$init() on PVP and MPP systems 00053 * 00054 * Note that _initialize_e_fortran_io() is called in startup/prologue 00055 * code and at first I/O. This is because on Sparc systems we might 00056 * have a C main program which calls Fortran subroutines and the 00057 * startup/prologue initializations would be bypassed. 00058 */ 00059 00060 #ifdef _UNICOS 00061 #include <infoblk.h> 00062 #include <sys/category.h> 00063 #endif 00064 #if defined(_LITTLE_ENDIAN) 00065 #include <stdlib.h> 00066 #include <cray/portdefs.h> 00067 #else /* little endian */ 00068 #include <signal.h> 00069 #include <stdio.h> 00070 #include <stdlib.h> 00071 #include <string.h> 00072 #include <unistd.h> 00073 #include <sys/stat.h> 00074 #include <cray/mtlock.h> 00075 #if defined(_CRAYMPP) && defined(SA_SIGINFO) 00076 #define GOT_SIGINFO 00077 #include <siginfo.h> 00078 #endif 00079 #include "fio.h" 00080 #endif /* little endian */ 00081 00082 #ifdef _UNICOS 00083 #pragma _CRI soft _lwrite_setup 00084 #elif !defined(_LITTLE_ENDIAN) 00085 #pragma weak _lwrite_setup 00086 #endif 00087 extern void _lwrite_setup(void); /* List-directed write setup routine */ 00088 00089 #ifdef _UNICOS 00090 #pragma _CRI soft _wf_setup 00091 #elif !defined(_LITTLE_ENDIAN) 00092 #pragma weak _wf_setup 00093 #endif 00094 extern void _wf_setup(void); /* Formatted write setup routine */ 00095 extern void _fcleanup(void); /* I/O cleanup routine */ 00096 #ifdef __mips 00097 extern void _fortclean(void); /* flush stdio under lock */ 00098 #endif 00099 00100 /* Forward and external references */ 00101 00102 #ifdef GOT_SIGINFO 00103 static void _f_sig(int, siginfo_t *, void *); 00104 #else 00105 static void _f_sig(int); 00106 #endif 00107 extern void _aborthandle(void); /* Cleanup routine */ 00108 #ifdef _CRAYMPP 00109 /* _f_stopsig is referenced in libc/gen/exit.c */ 00110 void _f_stopsig(int); 00111 extern void _abortcatch(int); 00112 #endif 00113 00114 #ifdef _CRAY1 00115 #pragma _CRI soft $WBUFLN, $RBUFLN 00116 extern int $WBUFLN, $RBUFLN; 00117 _f_int $RFDCOM[1]; 00118 _f_int $WFDCOM[1]; 00119 #endif /* _CRAY1 */ 00120 00121 #ifndef _ABSOFT 00122 extern char *sys_siglist[]; /* Array of signal messages */ 00123 #endif 00124 00125 extern int __fdctrace_enable; /* FDC trace flag */ 00126 00127 short _fortran_io_is_init; /* set to 1 by _initialize_fortran_io() */ 00128 short _e_fortran_io_is_init; /* set to 1 by _initialize_e_fortran_io() */ 00129 short _i_fortran_io_is_init; /* set to 1 by _initialize_i_fortran_io() */ 00130 short _f_abort; /* set to 1 by _f_sig() signal handler */ 00131 00132 #ifdef _CRAYMPP 00133 /* These variables and defines are used for handling stopall */ 00134 volatile int _infio; 00135 volatile int _needtostop; 00136 extern int G@INTIO; 00137 #endif 00138 00139 /* 00140 * _initialize_fortran_io 00141 * 00142 * Called the first time any external or internal Fortran unit is 00143 * connected or used. 00144 */ 00145 void 00146 _initialize_fortran_io(void) 00147 { 00148 _fortran_io_is_init = 1; 00149 00150 /* Set up the precision used for list-directed floating point output */ 00151 00152 if (LOADED(_lwrite_setup)) 00153 _lwrite_setup(); 00154 00155 /* Set up formatted write behavior */ 00156 00157 if (LOADED(_wf_setup)) 00158 _wf_setup(); 00159 00160 #ifdef _CRAY1 00161 /* 00162 * $RBUFLN and $WBUFLN were external symbols controlling the 00163 * length of the read and write formatted line buffers, 00164 * respectively. The user could increase the maximum allowable 00165 * formatted record size by increasing the value of these 00166 * symbols at load time with segldr. Now, we simulate that 00167 * behavior by increasing _f_rcsz if these symbols are defined 00168 * and larger than _f_rcsz. For historic reasons, this is done 00169 * only on the CX/CEA. 00170 * 00171 * The $RFDCOM and $WFDCOM common blocks used to contain the 00172 * line buffer. We keep an existing 1-word block so that users 00173 * can change it and still get a similar caution message. 00174 * 00175 * This crud can be deprecated someday since we now allow RECL 00176 * on sequential files, which can accomplish the same thing. 00177 */ 00178 00179 if (LOADED_DATA(&$RBUFLN)) 00180 if (_VALUE($RBUFLN) > _f_rcsz) 00181 _f_rcsz = _VALUE($RBUFLN); 00182 00183 if (LOADED_DATA(&$WBUFLN)) 00184 if (_VALUE($WBUFLN) > _f_rcsz) 00185 _f_rcsz = _VALUE($WBUFLN); 00186 #endif /* _CRAY1 */ 00187 00188 return; 00189 } 00190 00191 /* 00192 * _initialize_e_fortran_io 00193 * 00194 * Called the first time any external Fortran unit is connected. 00195 * 00196 * Assumes that _openlock is locked to prevent multiple concurrent calls. 00197 */ 00198 void 00199 _initialize_e_fortran_io(void) 00200 { 00201 _e_fortran_io_is_init = 1; 00202 00203 if (! _fortran_io_is_init) 00204 _initialize_fortran_io(); 00205 00206 /* Register for cleanup routine at exit and abort time */ 00207 00208 (void) atexit(_fcleanup); 00209 #ifdef __mips 00210 (void) __ateachexit(_fortclean); 00211 #endif 00212 #ifdef _UNICOS 00213 (void) atabort(_fcleanup); 00214 #endif /* _UNICOS */ 00215 00216 /* Conditionally set FFIO tracing */ 00217 00218 #ifdef DEBUG 00219 if (__fdctrace_enable < 0) { 00220 char *estr; 00221 00222 estr = getenv("FDCTRACE"); 00223 00224 __fdctrace_enable = (estr == NULL) ? 0 : atol(estr); 00225 } 00226 #endif /* DEBUG */ 00227 00228 return; 00229 } 00230 00231 /* 00232 * _initialize_i_fortran_io 00233 * 00234 * Called the first time any internal Fortran unit is accessed. 00235 */ 00236 void 00237 _initialize_i_fortran_io(void) 00238 { 00239 _i_fortran_io_is_init = 1; 00240 00241 if (! _fortran_io_is_init) 00242 _initialize_fortran_io(); 00243 00244 return; 00245 } 00246 00247 #ifdef _UNICOS 00248 00249 /* 00250 * _finit 00251 * 00252 * Fortran library initialization routine; called by $START(). 00253 */ 00254 void 00255 _finit(void) 00256 { 00257 /* 00258 * Call _initialize_e_fortran_io here to ensure that atexit(_fcleanup) 00259 * is called before any user atexit() call is made. 00260 */ 00261 _initialize_e_fortran_io(); 00262 return; 00263 } 00264 00265 /* 00266 * f$init 00267 * 00268 * Called by the prologue in PVP and MPP Fortran main programs. 00269 * It is here that we do the funny signal catching which ensures that 00270 * a traceback is printed when some specific signals are received. 00271 */ 00272 void 00273 f$init(void) 00274 { 00275 register short catchem; 00276 char *trace; 00277 00278 catchem = 1; 00279 00280 /* 00281 * If "TRACEBK" == 0 or "TRACEBK2" != 0 then don't do traceback. 00282 */ 00283 00284 if (((trace = getenv("TRACEBK")) && atol(trace) == 0) || 00285 ((trace = getenv("TRACEBK2")) && atol(trace) != 0)) 00286 catchem = 0; 00287 #ifdef _CRAYMPP 00288 /* 00289 * Always register for SIGBUFIO; this is used by STOP and 00290 * globalexit() to get all PEs to clean up and exit. 00291 */ 00292 if (_num_pes() > 1) { 00293 struct sigaction act, oact; 00294 00295 act.sa_handler = _f_stopsig; 00296 act.sa_mask = 0; 00297 act.sa_flags = SA_RESETHAND | SA_CLEARPEND ; 00298 00299 (void) sigaction(SIGBUFIO, &act, &oact); 00300 00301 if (oact.sa_handler != SIG_DFL && 00302 oact.sa_handler != _f_stopsig) 00303 (void) sigaction(SIGBUFIO, &oact, 0); 00304 } 00305 #endif 00306 if (catchem) { 00307 #ifndef SIGSMCE 00308 #define SIGSMCE 38 00309 #endif 00310 #ifndef SIGAPTEAM 00311 #define SIGAPTEAM 39 00312 #endif 00313 unsigned long mask; 00314 struct sigaction act, oact; 00315 register int sig; 00316 00317 mask = (SIG_DMPDFL | sigmask(SIGHUP) | 00318 sigmask(SIGINT) | sigmask(SIGTERM) | 00319 sigmask(SIGCPULIM) | sigmask(SIGPIPE) | 00320 sigmask(SIGSMCE)) | sigmask(SIGAPTEAM) 00321 & ~SIG_CANTMASK; 00322 #ifdef GOT_SIGINFO 00323 act.sa_sigaction = _f_sig; 00324 #else 00325 act.sa_handler = _f_sig; 00326 #endif 00327 act.sa_mask = 0; 00328 act.sa_flags = SA_RESETHAND | SA_NODEFER | SA_CLEARPEND; 00329 #ifdef GOT_SIGINFO 00330 act.sa_flags |= SA_SIGINFO; 00331 #endif 00332 00333 for (sig = 1; mask != 0; sig++, mask >>= 1) 00334 if (mask & 01) { 00335 (void) sigaction(sig, &act, &oact); 00336 #ifdef _CRAYMPP 00337 if (oact.sa_handler != SIG_DFL && 00338 oact.sa_handler != _abortcatch) 00339 #else 00340 if (oact.sa_handler != SIG_DFL) 00341 #endif 00342 (void) sigaction(sig, &oact, 0); 00343 } 00344 } 00345 00346 #ifdef _CRAYMPP 00347 _barrier(); /* let all PEs catch up */ 00348 #endif 00349 00350 return; 00351 } 00352 00353 #endif /* _UNICOS */ 00354 00355 /* 00356 * _f_sig() is the Fortran run-time signal handler. 00357 */ 00358 00359 #if defined(_UNICOS) && !(defined(GOT_SIGINFO) || defined(_CRAYMPP)) 00360 00361 static short _f_gotsig = 0; /* In _f_sig() flag word */ 00362 static long _f_siglock = 0; /* Lock word for _f_sig() */ 00363 00364 static void 00365 _f_sig(int sig) 00366 { 00367 sigset_t set; 00368 00369 (void) sigoff(); /* Turn signals off */ 00370 00371 _semclr(2); /* Clear TSKLK for lock calls */ 00372 00373 MEM_LOCK(&_f_siglock); /* Protect global data update */ 00374 00375 if (_f_gotsig == 0) { /* If no one has been here yet */ 00376 00377 _f_gotsig = 1; /* Close the door */ 00378 _f_abort = 1; /* Indicate abnormal abort */ 00379 00380 MEM_UNLOCK(&_f_siglock); 00381 00382 (void) sigon(); 00383 (void) fflush(stdout); 00384 (void) fflush(stderr); /* Just in case */ 00385 00386 if (sig > 0 && sig < NSIG) { 00387 (void) write(fileno(stderr), sys_siglist[sig], 00388 strlen(sys_siglist[sig])); 00389 (void) write(fileno(stderr), "\n", 1); 00390 } 00391 00392 (void) sigtrbk(stderr); 00393 00394 _aborthandle(); /* Do cleanup routines */ 00395 00396 } 00397 else { /* Someone is already in */ 00398 00399 MEM_UNLOCK(&_f_siglock); 00400 00401 (void) sigon(); 00402 } 00403 00404 set = sigmask(sig); /* Block signal */ 00405 00406 (void) sigprocmask(SIG_BLOCK, &set, NULL); 00407 (void) killm(C_PROC, 0, sig); /* Resend signal */ 00408 00409 return; 00410 } 00411 00412 #elif defined(_CRAYMPP) 00413 00414 static DECL_LOCK(_f_siglock) /* MPP: Lock word for _f_sig() */ 00415 00416 void 00417 _f_stopsig(int sig) 00418 { 00419 /* Set G@INTIO so we do not retry any call that failed with EINTR */ 00420 00421 G@INTIO = 1; 00422 00423 if (_infio) { 00424 /* We are in some i/o statement */ 00425 /* Wait till we are finished to call _fcleanup */ 00426 /* The STMT_BEGIN macro sets _infio and STMT_END */ 00427 /* clears it. STMT_END checks to see if _needtostop */ 00428 /* is set - if so, it calls this routine */ 00429 struct sigaction act, oact; 00430 00431 _needtostop = 1; 00432 act.sa_handler = _f_stopsig; 00433 act.sa_mask = 0; 00434 act.sa_flags = SA_RESETHAND | SA_CLEARPEND ; 00435 00436 (void) sigaction(SIGBUFIO, &act, &oact); 00437 return; 00438 } 00439 00440 _fcleanup(); /* all PEs cleanup and exit */ 00441 00442 exit(0); 00443 } 00444 00445 #ifdef GOT_SIGINFO 00446 static void 00447 _f_sig(int sig, siginfo_t *sip, void *ctx) 00448 #else 00449 static void 00450 _f_sig(int sig) 00451 #endif 00452 { 00453 sigset_t set; 00454 register long locked; 00455 register long start; 00456 register long wait; 00457 char buf[50]; 00458 00459 (void) sigoff(); 00460 00461 locked = _shmem_test_lock(&_f_siglock); 00462 _f_abort = 1; /* Indicate abnormal abort */ 00463 00464 if (!locked) { 00465 /* 00466 * The first PE in _f_sig prints out the signal, 00467 * does a traceback, and runs cleanup routines 00468 */ 00469 (void) sigon(); 00470 (void) fflush(stdout); 00471 (void) fflush(stderr); 00472 #ifdef GOT_SIGINFO 00473 psiginfo(sip, "SIGNAL"); 00474 #else 00475 if (sig > 0 && sig < NSIG) { 00476 (void) strncpy(buf, sys_siglist[sig], sizeof(buf) - 1); 00477 (void) strcat(buf, "\n"); 00478 (void) write(fileno(stderr), buf, strlen(buf)); 00479 } 00480 #endif 00481 (void) sigtrbk(stderr); 00482 _aborthandle(); 00483 } else { 00484 /* 00485 * subsequent PEs in _f_sig call cleanup routines, 00486 * synchronize on a barrier (UNICOS-MAX only), 00487 * then call _localexit(). 00488 */ 00489 (void) sigon(); 00490 _aborthandle(); 00491 #ifdef _UNICOS_MAX 00492 _barrier(); 00493 #endif 00494 _localexit(EXIT_FAILURE); 00495 } 00496 /* 00497 * Under UNICOS-MAX, the first PE in _f_sig() blocks the 00498 * signal, then re-sends the signal, waits for awhile 00499 * to see if the other PEs have cleaned up, then returns 00500 * from the signal handler to kill the application 00501 * 00502 * Under UNICOS/mk, we block the signal and re-send it, 00503 * then exit the signal handler. The kernel will restore 00504 * the registers to the point-of-interrupt and restore 00505 * the old signal mask (which has the signal unmasked). 00506 * The calling PE will die with the signal; this will 00507 * cause a SIGAPTEAM to be sent to all other PEs, which 00508 * will bring them into this routine to clean up and exit. 00509 */ 00510 set = sigmask(sig); 00511 00512 (void) sigprocmask(SIG_BLOCK, &set, NULL); 00513 (void) killm(C_PROC, 0, sig); 00514 00515 #ifdef _UNICOS_MAX 00516 _set_barrier(); 00517 start = _rtc(); 00518 wait = start + CLK_TCK; 00519 00520 while (_rtc() >= start && _rtc() < wait) { 00521 if (_test_barrier()) 00522 break; 00523 } 00524 #endif 00525 00526 return; 00527 } 00528 #endif /* _CRAYMPP */ 00529 00530 #ifdef _SOLARIS 00531 /* 00532 * _F90_INIT(): 00533 * 00534 * The Fortran 90 library initialization routine for Sparc. 00535 * It is called by the CRI startup code on Sparc for f90 programs. 00536 */ 00537 00538 void 00539 _F90_INIT() 00540 { 00541 00542 /* 00543 * We call _initialize_e_fortran_io here to ensure that atexit(_fcleanup) 00544 * is called before any user atexit() call is made. 00545 */ 00546 _initialize_e_fortran_io(); 00547 00548 return; 00549 } 00550 00551 #endif /* _SOLARIS */