Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
finit.c
Go to the documentation of this file.
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines