Exemple #1
0
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;
}
Exemple #2
0
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;
}