1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
/**
* Copyright 1981-2007 ECMWF
*
* Licensed under the GNU Lesser General Public License which
* incorporates the terms and conditions of version 3 of the GNU
* General Public License.
* See LICENSE and gpl-3.0.txt for details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "sharedmemory.h"
#include "fortdefs.h"
int sharedMemoryCharacteristics( int, int , float , int * , int * , key_t * );
void createSharedMemoryCoefficients( fortint , fortint , fortreal , fortint , key_t , int );
int debugSet = 0;
static char * debugLevel;
fortint SMREAD(
fortreal ** fortranArrayPointer, /* to be attached to shared memory */
fortint * Type, /* SP2LL, SP2QG, .. */
fortint * Truncation, /* spectral truncation */
fortreal * Grid) /* grid spacing or gaussian number */
/*
// Callable from Fortran.
//
*/
/*
C
C---->
C**** SMREAD
C
C Purpose
C -------
C
C This routine gets interpolation coefficients in a shared memory array.
C
C
C Interface
C ---------
C
C ISIZE = SMREAD(KARRAY,KTYPE,KTRUNC,GRID)
C
C
C Input parameters
C ----------------
C
C KTYPE - Type of spectral to grid transformation (SP2LL, SP2QG, ..)
C KTRUNC - Spectral truncation (eg 511 for T511)
C GRID - longitude grid spacing (for lat/long) or gaussian number
C
C
C Output parameters
C -----------------
C
C KARRAY - Pointer to a shared memory array of REALs
C
C Function returns the size (in values) of the shared memory array
C
C
C Common block usage
C ------------------
C
C None.
C
C
C Method
C ------
C
C Looks for coefficients in shared memory.
C Waits on semaphore for coefficients to become available.
C
C
C Externals
C ---------
C
C sharedMemoryCharacteristics - to get key and size for shared memory
C createSharedMemoryCoefficients - creates coefficients if necessary
C
C
C Reference
C ---------
C
C None.
C
C
C Comments
C --------
C
C Environment variable SHARED_DEBUG can be set (1, 2, ..) to give
C diagnostic printout.
C
C
C Author
C ------
C
C J.D.Chambers ECMWF January 2002
C
C
C Modifications
C -------------
C
C None.
C
C----<
C
*/
{
int type = (int) *Type;
int truncation = (int) *Truncation;
float grid = (float) *Grid;
key_t memoryKey;
int size, shmflg, shmid;
char * shmaddr;
int status, i;
fortint numberOfValues = 0;
char mode[] = "00666";
int value, semaphoreId, numlat, returnCode;
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} semvalues;
fortint Numlat;
struct sembuf bufs[1];
/*
// See if DEBUG switched on.
*/
if( ! debugSet ) {
debugLevel = getenv("SHARED_DEBUG");
if( debugLevel == NULL )
debugSet = DEBUGOFF; /* off */
else {
int loop;
for( loop = 0; loop < strlen(debugLevel) ; loop++ ) {
if( ! isdigit(debugLevel[loop]) ) {
printf("Invalid number string in SHARED_DEBUG: %s\n", debugLevel);
printf("SHARED_DEBUG must comprise only digits [0-9].\n");
debugSet = DEBUGOFF;
}
}
debugSet = DEBUGOFF + atoi( debugLevel );
}
if( DEBUG ) printf("SHARED_DEBUG: debug switched on\n");
}
/*
// Get key and size for shared memory (whole globe)
*/
if( DEBUG ) {
printf("SMREAD: type = %d\n",type);
printf("SMREAD: truncation = %d\n",truncation);
printf("SMREAD: grid = %f\n",grid);
}
status = sharedMemoryCharacteristics( type,
truncation,
grid,
&numlat,
&size,
&memoryKey);
if( status ) {
if( DEBUG ) printf("SMREAD: sharedMemoryCharacteristics call failed\n");
return (fortint) 0;
}
Numlat = numlat;
/*
// Wait for the shared memory array to become available
*/
if( DEBUG ) printf("SMREAD: call createSharedMemoryCoefficients with numlat = %d\n", numlat);
createSharedMemoryCoefficients(*Type,*Truncation,*Grid,Numlat,memoryKey,size);
bufs[0].sem_num = 0;
bufs[0].sem_op = -READY_TO_READ;
bufs[0].sem_flg = 0;
semaphoreId = (int) memoryKey;
if( DEBUG )
printf("SMREAD: wait for shared memory semaphore id %0x\n", semaphoreId);
status = semop(semaphoreId,bufs,1);
/*
// Locate shared segment
*/
if( DEBUG ) printf("SMREAD: locate shared memory\n");
shmflg = 0666;
shmid = shmget( memoryKey, (size_t)size, shmflg);
if ( shmid < 0 ) {
perror("shmget error");
return (fortint) 0;
}
/*
// Attach the shared segment to the array pointer
*/
if( DEBUG ) printf("SMREAD: attach shared memory to array\n");
shmaddr = (char *) NULL;
shmflg = 0;
*fortranArrayPointer = (fortreal *) shmat( shmid, shmaddr, shmflg);
if ( *fortranArrayPointer == (fortreal *) -1 ) {
perror("shmat error");
return (fortint) 0;
}
/*
// Set semaphore value to make memory readable for other readers
*/
if( DEBUG ) printf("SMREAD: set semaphore to make memory readable\n");
semvalues.val = READY_TO_READ;
value = semctl((int)semaphoreId, (int)0, (int)SETVAL,semvalues);
/*
// Return the size (in values) of the shared segment
*/
numberOfValues = (fortint) size/sizeof(fortreal);
if( DEBUG )
printf("SMREAD: number of values in shared memory = %d\n", numberOfValues);
return numberOfValues;
}
|