Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
map_datapool_.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 ** NAME
00039 **      map_datapool.c - mmap executable's datapool section to file
00040 **
00041 ** C SYNOPSIS
00042 **      int map_datapool_(const char* datapoolname, char* dpaddress, int* dplength )
00043 **      
00044 ** FORTRAN SYNOPSIS
00045 **      integer*4 map_datapool(datapool, dpaddress, dplength)
00046 **      character*n datapool    ! n is the number of characters in string
00047 **      character*(*) dpaddress
00048 **      integer*4 dplength
00049 **      
00050 **      
00051 ** DESCRIPTION
00052 **      map_datapool will use mmap to map the specified datapool
00053 **      for sharing the data 
00054 **
00055 **      map_datapool is called from the .init section of each datapool DSO
00056 **
00057 ** SEE ALSO
00058 **      ld(2), mmap(2)
00059 */
00060 
00061 #include <fcntl.h>
00062 #include <sys/mman.h>
00063 #include <stdio.h>
00064 #include <limits.h>
00065 #include <sys/types.h>
00066 #include <unistd.h>
00067 #include <alloca.h>
00068  
00069 #define MAX_DP  100
00070 static int *count_ptr[MAX_DP];
00071 static char fn_save[MAX_DP][PATH_MAX];
00072 static int ndp = 0;
00073 
00074 static    char *cpath;
00075 static struct flock flk;
00076 static  int ltype;
00077 extern int errno;
00078 
00079 int DEBUG_MAP_LOCALDATA = 0;            /* Set this to 1 to debug local data */
00080 
00081 /*
00082 ** Fortran interface for f77_map_datapool_.
00083 ** The following arguments are used:
00084 ** dpname       = name of the datapool
00085 ** dp_address   = address of the first datapool item (not counting the filler)
00086 ** dp_length    = length of the datapool
00087 */
00088 void
00089 f77_map_datapool_(const char* dpname, char *dp_address, int dp_length)
00090 {
00091     int length;
00092     char *getenv(), *dp_dir;
00093     int plen;
00094     int fd;
00095     int pagesize = sysconf(_SC_PAGESIZE);
00096     int plength, poff, nusers;
00097    
00098     length = strlen(dpname);
00099     if (dp_dir = getenv("DATAPOOL_DIR")) {
00100         plen = strlen(dp_dir);
00101         cpath = (char*)alloca(plen + length + 2);
00102         strcpy( cpath, dp_dir );
00103         if (dp_dir[plen-1] != '/') cpath[plen++] = '/';
00104     }
00105     else {
00106         cpath = (char*) alloca(length + 10);
00107         strcpy( cpath, "/usr/tmp/" );
00108         plen = 9;
00109     }
00110     *(cpath+plen++) = 'D';
00111     *(cpath+plen++) = 'P';
00112     *(cpath+plen++) = '_';
00113     strncpy(cpath+plen, dpname, length + 1);
00114     cpath[plen+length] = '\0';
00115     strcpy(fn_save[ndp], cpath);
00116 
00117     dp_address -= sizeof( int );        /* make sure there is space for the user count */
00118     poff = (long)dp_address % pagesize;
00119     dp_address -= poff;         /* adjust for page offset */
00120     plength = dp_length + poff + sizeof( int );
00121 
00122     if ((fd = open(cpath, O_RDWR | O_CREAT, 0666)) == -1)
00123     {
00124         fprintf(stderr,
00125                 "map_localdata_: cannot open file %s for mmap\n", cpath );
00126         abort();
00127     }
00128 
00129     if (DEBUG_MAP_LOCALDATA)
00130         printf("mmap address = %x  , length = %d\n", dp_address, plength );
00131     if (mmap(dp_address, plength, PROT_READ | PROT_WRITE,
00132             MAP_AUTOGROW | MAP_SHARED | MAP_FIXED,
00133             fd, 0) == (caddr_t) -1)
00134     {
00135         fprintf(stderr,
00136                     "map_datapool: trouble sharing %s at address %X\n",
00137                     cpath, dp_address);
00138         perror("map_datapool (mmap)");
00139         fflush(stderr);
00140         close(fd);
00141         abort();
00142     }
00143     else
00144     {
00145         if (DEBUG_MAP_LOCALDATA)
00146         {
00147             fprintf(stderr, "map_datapool: sharing file %s at address %X\n",
00148                     cpath, dp_address);
00149             fflush(stderr);
00150         }
00151     }
00152 
00153     count_ptr[ndp] = (int *) dp_address;
00154 
00155     while ((nusers = _test_and_set( count_ptr[ ndp ], -1 )) < 0)
00156         ;
00157     *count_ptr[ ndp++ ] = ++nusers;
00158 }
00159 
00160 /*
00161 ** Fortran interface for f77_map_datapool_pad_.
00162 ** The following arguments are used:
00163 ** dpname       = name of the datapool
00164 ** dp_address   = address of the first datapool item (not counting the filler)
00165 ** dp_length    = length of the datapool
00166 ** pagesize     = page size specified by the user
00167 */
00168 void
00169 f77_map_datapool_pad_(const char* dpname, char *dp_address, int dp_length,
00170 int pagesize)
00171 {
00172     int length;
00173     char *getenv(), *dp_dir;
00174     int plen;
00175     int fd;
00176     int plength, poff, nusers;
00177    
00178     length = strlen(dpname);
00179     if (dp_dir = getenv("DATAPOOL_DIR")) {
00180         plen = strlen(dp_dir);
00181         cpath = (char*)alloca(plen + length + 2);
00182         strcpy( cpath, dp_dir );
00183         if (dp_dir[plen-1] != '/') cpath[plen++] = '/';
00184     }
00185     else {
00186         cpath = (char*) alloca(length + 10);
00187         strcpy( cpath, "/usr/tmp/" );
00188         plen = 9;
00189     }
00190     *(cpath+plen++) = 'D';
00191     *(cpath+plen++) = 'P';
00192     *(cpath+plen++) = '_';
00193     strncpy(cpath+plen, dpname, length + 1);
00194     cpath[plen+length] = '\0';
00195     strcpy(fn_save[ndp], cpath);
00196 
00197     dp_address -= sizeof( int );        /* make sure there is space for the user count */
00198     poff = (long)dp_address % pagesize;
00199     dp_address -= poff;         /* adjust for page offset */
00200     plength = dp_length + poff + sizeof( int );
00201 
00202     if ((fd = open(cpath, O_RDWR | O_CREAT, 0666)) == -1)
00203     {
00204         fprintf(stderr,
00205                 "map_localdata_: cannot open file %s for mmap\n", cpath );
00206         abort();
00207     }
00208 
00209     if (DEBUG_MAP_LOCALDATA)
00210         printf("mmap address = %x  , length = %d\n", dp_address, plength );
00211     if (mmap(dp_address, plength, PROT_READ | PROT_WRITE,
00212             MAP_AUTOGROW | MAP_SHARED | MAP_FIXED,
00213             fd, 0) == (caddr_t) -1)
00214     {
00215         fprintf(stderr,
00216                     "map_datapool: trouble sharing %s at address %X\n",
00217                     cpath, dp_address);
00218         perror("map_datapool (mmap)");
00219         fflush(stderr);
00220         close(fd);
00221         abort();
00222     }
00223     else
00224     {
00225         if (DEBUG_MAP_LOCALDATA)
00226         {
00227             fprintf(stderr, "map_datapool: sharing file %s at address %X\n",
00228                     cpath, dp_address);
00229             fflush(stderr);
00230         }
00231     }
00232 
00233     count_ptr[ndp] = (int *) dp_address;
00234 
00235     while ((nusers = _test_and_set( count_ptr[ ndp ], -1 )) < 0)
00236         ;
00237     *count_ptr[ ndp++ ] = ++nusers;
00238 }
00239 
00240 
00241 void
00242 f77_unmap_datapool_()
00243 {
00244     /* This function determines whether the mmap file in /usr/tmp/DP_name
00245     should be removed or not by examining the number of users currently
00246     accessing the file denoted in file /usr/tmp/DP_name.users.  If it
00247     is the last person accessing the file then it will clean up that
00248     /usr/tmp/DP_name* files.  Although the unmapping might not have
00249     the exact one-to-one correspondence to the mapping that does not
00250     really matter since at the end of the processes, ALL datapools that
00251     have been mapped will be unmapped and which one gets unmapped first
00252     does not matter.
00253     */
00254     int nusers;
00255 
00256     ndp--;
00257     while ((nusers = _test_and_set( count_ptr[ ndp ], -1 )) < 0)
00258         ;
00259     *count_ptr[ ndp ] = --nusers;
00260     
00261     /* no more users delete this file */
00262     if (!nusers) {
00263         unlink( fn_save[ndp] );
00264     }
00265 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines