Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
fortunit.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/fortunit.c 92.1    06/22/99 11:11:33"
00039 
00040 #include <stdlib.h>
00041 #include <cray/nassert.h>
00042 #include "fio.h"
00043 
00044 /*
00045  *      _alloc_unit
00046  *
00047  *              Find an unopened unit for an external file.  If necessary, 
00048  *              allocate the unit and initialize it first, and add the unit 
00049  *              into the global unit table.  This function locks the unit 
00050  *              before returning.
00051  *
00052  *              This function assumes that _openlock is locked, that
00053  *              unum is a valid unit number/identfier, and that unit unum
00054  *              is not currently connected.             
00055  *
00056  *      Algorithm
00057  *
00058  *              The hash chain associated with "unum" is searched for
00059  *              any unconnected unit.   This unit is set up to contain
00060  *              the specified unit number before returning.   
00061  *
00062  *      Return value:
00063  *
00064  *              Pointer to the allocated unit on success.  NULL on error,
00065  *              with errno set to the specific error code.
00066  */
00067 
00068 unit *
00069 _alloc_unit(
00070         unum_t  unum,           /* unit number */
00071         int     private)        /* 1 if private, 0 if global unit */
00072 {
00073         register int    hval;
00074         register int    mytask;
00075         unit            *prcup;
00076         unit            *cup;
00077 
00078         if (! _e_fortran_io_is_init)
00079                 _initialize_e_fortran_io();
00080         
00081         hval    = UHASH(unum);
00082         prcup   = NULL;
00083         cup     = _fort_unit[hval].ulist;
00084         
00085 /*
00086  *      Skip all units which do not match the unit number sought.  Also
00087  *      skip any ulready-open units with the same unit number.  In that case
00088  *      we must be opening a task-private unit.
00089  */
00090         mytask  = private ? MYTASK : 0;
00091 
00092         while (cup != NULL) {
00093                 if (cup->uid == unum && 
00094                     cup->private == private && cup->utid == mytask)
00095                         break;
00096 
00097                 prcup   = cup;
00098                 cup     = cup->hashlink;
00099         }
00100         
00101 /*
00102  *      If a unit structure for the current unit number has not yet been
00103  *      allocated, then add one to the hash table.
00104  */
00105         if (cup == NULL) {
00106 
00107                 cup     = malloc(sizeof(unit));
00108 
00109                 if (cup == NULL) {
00110                         errno   = FENOMEMY;
00111                         return(NULL);
00112                 }
00113 
00114                 /*
00115                  * Initialize the unit, and then lock it before adding it to 
00116                  * the hash table to prevent losing the race with another task 
00117                  * for the lock.
00118                  *
00119                  * The FLSH_MEM call assures that the unit initialization
00120                  * reaches memory prior to the time the unit gets linked into
00121                  * the hash table.   This ensures that other tasks searching
00122                  * the unit hash table do not get a false match on this 
00123                  * unit.
00124                  */
00125 
00126                 cup->hashlink   = NULL;
00127                 cup->uid        = unum;
00128                 cup->private    = private;
00129                 cup->utid       = mytask;
00130                 INITIALIZE_LOCK(cup->uiolock);
00131                 _init_unit(cup);
00132 
00133                 MEM_LOCK(&cup->uiolock);
00134 
00135                 FLSH_MEM();
00136 
00137                 if (prcup == NULL)
00138                         _fort_unit[hval].ulist  = cup;
00139                 else
00140                         prcup->hashlink         = cup;
00141         }
00142         else {
00143                 /* We're in deep weeds if the unit is open. */
00144                 assert( ! OPEN_UPTR(cup));      
00145 
00146                 MEM_LOCK(&cup->uiolock);
00147 
00148                 _init_unit(cup);
00149         }
00150 
00151         return(cup);
00152 }
00153 
00154 /*
00155  *      _search_unit_list
00156  *
00157  *              Perform a linear search of the hash chain starting with
00158  *              the unit pointed to by ulist.
00159  */
00160 
00161 unit *
00162 _search_unit_list(unit *cup, unum_t unum)
00163 {
00164         while (cup != NULL) {
00165                 if (cup->uid == unum &&
00166                     (cup->private == 0 || cup->utid == MYTASK))
00167                         return(cup);
00168 
00169                 cup     = cup->hashlink;
00170         }
00171 
00172         return(cup);
00173 }
00174 
00175 /*
00176  *      _get_next_unit 
00177  *
00178  *              This function returns the next open unit in the unit table(s)
00179  *              after optionally locking the unit.  NULL is returned if there 
00180  *              are no more open units.
00181  *
00182  *              Note that if multiple tasks are active, and the caller of
00183  *              _get_next_unit wants to be assured of finding all currently
00184  *              open units at a given instant,   _openlock must be locked 
00185  *              prior to calling _get_next_unit().
00186  *
00187  *      Argument
00188  *
00189  *              prcup   Pointer to previous unit returned by _get_next_unit.
00190  *                      NULL indicates that _get_next_unit should return the
00191  *                      first open unit in the unit table.
00192  *
00193  *              iflock  !=0 iff units should be locked by _get_next_unit() 
00194  *                      before returning.
00195  *
00196  *              iftask  !=0 iff the search for the next unit should be 
00197  *                      restricted to units visible on the current task.
00198  *
00199  *      Return value:
00200  *              Pointer to the next connected unit.  If there are no more
00201  *              connected units, then NULL is returned.
00202  */
00203 
00204 unit *
00205 _get_next_unit(unit *prcup, int iflock, int iftask)
00206 {
00207         register int    hval;
00208         unit            *cup;
00209 
00210         if (prcup != NULL) {
00211                 cup     = prcup->hashlink;
00212                 hval    = UHASH(prcup->uid);
00213 
00214                 if (iflock)
00215                         _release_cup(prcup);    /* unlock previous unit */
00216         }
00217         else {
00218                 cup     = _fort_unit[0].ulist;
00219                 hval    = 0;
00220         }
00221 
00222         while (hval < HASH_SIZE) {
00223 
00224                 while (cup != NULL) {
00225                         if ( OPEN_UPTR(cup) &&  (iftask == 0 ||
00226                                 cup->private == 0 || cup->utid == MYTASK) ) {
00227 
00228                                 if (iflock) {
00229                                         MEM_LOCK(&cup->uiolock);
00230                                         if (cup->auxlockp != NULL)
00231                                                 MEM_LOCK(cup->auxlockp);
00232                                 }
00233                                 goto done;
00234                         }
00235 
00236                         cup     = cup->hashlink;
00237                 }
00238 
00239                 hval    = hval + 1;
00240 
00241                 if (hval < HASH_SIZE)
00242                         cup     = _fort_unit[hval].ulist;
00243         }
00244 
00245 done:
00246         return(cup);
00247 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines