static void * dat1Mmap( size_t nbytes, int prot, int flags, int fd, off_t offset, int *isreg, void **pntr, size_t *actbytes, int * status ) { void * mapped = NULL; int tries = 0; size_t pagesize = 0; void * where = NULL; off_t off = 0; *pntr = NULL; *isreg = 0; if (*status != SAI__OK) return NULL; /* We need to know the pagesize */ pagesize = sysconf( _SC_PAGESIZE ); *actbytes = nbytes; if (offset > 0) { /* Calculate the starting offset into the file and round this down to a */ /* multiple of the system page size. Calculate the number of bytes to map, */ /* allowing for this rounding. */ off = offset - ( offset % pagesize ); *actbytes += ( offset - off ); } while (!mapped) { *isreg = 0; tries++; if (*status != SAI__OK) goto CLEANUP; /* Get some anonymous memory - we always have to map read/write because we always have to copy data into this space. */ //printf("mmap(%p, %zu, %d, %d, %d, %zu -> %zu [%d])\n", where, *actbytes, prot, flags, fd, offset, off, pagesize); mapped = mmap( where, *actbytes, prot, flags, fd, off ); if (mapped == MAP_FAILED) { emsSyser( "MESSAGE", errno ); *status = DAT__FILMP; emsRep("datMap_2", "Error mapping some memory: ^MESSAGE", status ); mapped = NULL; *pntr = NULL; goto CLEANUP; } /* The pointer we register is the one that has been corrected for the shift we applied in the original request */ *pntr = mapped + (offset - off ); /* Must register with CNF so the pointer can be used by Fortran */ *isreg = cnfRegp( *pntr ); if (*isreg == -1) { /* Serious internal error */ *status = DAT__FILMP; emsRep("datMap_3", "Error registering a pointer for mapped data " " - internal CNF error", status ); goto CLEANUP; } else if (*isreg == 0) { /* Free the memory and try again */ if ( munmap( mapped, *actbytes ) != 0 ) { *status = DAT__FILMP; emsSyser( "MESSAGE", errno ); emsRep("datMap_4", "Error unmapping mapped memory following" " failed registration: ^MESSAGE", status); goto CLEANUP; } if (!where) where = mapped; where += pagesize; mapped = NULL; *pntr = NULL; } if (!mapped && tries > 100) { *status = DAT__FILMP; emsRepf("datMap_4b", "Failed to register mapped memory with CNF" " after %d attempts", status, tries ); goto CLEANUP; } } CLEANUP: return mapped; }
void *cnfRealloc( void * pntr, size_t size ) { /* *+ * Name: * cnfMalloc * Purpose: * Re-Allocate space that may be accessed from C and Fortran. * Invocation: * cpointer = cnfMalloc( size ); * Description: * This function allocates space in the same way as the standard C * remalloc() function, except that the pointer to the space * reallocated is automatically registered (using cnfRegp) for use * from both C and Fortran. This means that the returned pointer * may subsequently be converted into a Fortran pointer of type * F77_POINTER_TYPE (using cnfFptr), and back into a C pointer * (using cnfCptr). The contents of the space may therefore be * accessed from both languages. * Arguments: * void * pntr (Given) * Pointer to be re-allocated. Must have been malloced by cnfMalloc. * If new memory is allocated by this routine, this pointer will no * longer be valid. If the resize fails this pointer will still be valid. * This conforms to the standard ANSI C behaviour of realloc. * size_t size (Given) * The size of the required space. * Returned Value: * void *cnfRealloc * A registered pointer to the re-allocated space, or NULL if the * space could not be allocated. If NULL, "pntr" is not changed or freed. * Notes: * - The re-allocated space should be freed using cnfFree when no * longer required. *- */ int reg; /* Error status from pointer registration */ void * p; /* Temp pointer */ void * temp; /* Local copy of pointer from realloc */ /* Try to resize */ temp = starRealloc( pntr, size ); /* If a pointer to new memory was returned, then un-register the old */ /* pointer (if not NULL). */ if ( ( temp != pntr ) && ( pntr != NULL ) ) cnfUregp( pntr ); /* If a pointer to new memory was returned, attempt to register the new */ /* pointer (if not NULL). */ if ( ( temp != pntr ) && ( temp != NULL ) ) { reg = cnfRegp( temp ); /* If it could not be registered, then attempt to allocate some new memory */ /* with a registered pointer associated with it. */ if ( !reg ) { p = cnfMalloc( size ); /* If successful, transfer the data to the new (registered) memory and free */ /* the memory which could not be registered. */ if ( p ) { memcpy( p, temp, size ); starFree( temp ); temp = p; } else /* If no registered memory was available, free the unregistered memory and */ /* set the returned pointer to NULL. */ { starFree( temp ); temp = NULL; } } /* If an error occurred during pointer registration, free the unregistered */ /* memory and set the returned pointer to NULL. */ else if ( reg < 0 ) { starFree( temp ); temp = NULL; } } return temp; }