Logo Search packages:      
Sourcecode: qfits version File versions  Download package

void* qfits_memory_malloc ( size_t  size,
const char *  filename,
int  lineno 
)

Allocate memory.

Parameters:
size Size (in bytes) to allocate.
filename Name of the file where the alloc took place.
lineno Line number in the file.
Returns:
1 newly allocated pointer.
This function is a replacement call for malloc. It should never be called directly but through a macro instead, as:

  qfits_memory_malloc(size, __FILE__, __LINE__)

Definition at line 239 of file qfits_memory.c.

Referenced by qfits_memory_calloc(), qfits_memory_realloc(), and qfits_memory_strdup().

{
    void    *   ptr ;
    char    *   fname ;
    int         swapfileid ;
    int         swapfd ;
    char        wbuf[MEMPAGESZ] ;
    int         nbufs ;
    int         memtype ;
    int         i ;
    int         pos ;
#ifdef __linux__
    int         p ;
#endif

    /* If QFITS_MEMORY_MODE is 0 or 1, do not use the qfits_memory model  */
    if (QFITS_MEMORY_MODE == 0) return malloc(size);
    else if (QFITS_MEMORY_MODE == 1) {
        ptr = malloc(size);
        if (ptr == NULL) exit(1) ;
        else return ptr ;
    }
    
    /* Initialize table if needed */
    if (qfits_memory_initialized==0) {
        qfits_memory_init() ;
        qfits_memory_initialized++ ;
    }

    /* Protect the call */
    if (size==0) {
        qfits_mem_debug(
            fprintf(stderr, "qfits_mem: malloc called with 0 size - %s (%d)\n",
                    filename, lineno);
        );
        return NULL ;
    }

    /* Try to allocate in memory */
#ifdef __linux__
    /* Linux does not honor the RLIMIT_DATA limit.
     * The only way to limit the amount of memory taken by
     * a process is to set RLIMIT_AS, which unfortunately also
     * limits down the maximal amount of memory addressable with
     * mmap() calls, making on-the-fly swap space creation useless
     * in this module. To avoid this, the RLIMIT_DATA value
     * is honored here with this test.
     */
    ptr = NULL ;
    if (qfits_memory_table.rlimit_data<1) {
        /* No limit set on RLIMIT_DATA: proceed with malloc */
        ptr = malloc(size);
    } else if (qfits_memory_table.alloc_total+size <= 
            (size_t)qfits_memory_table.rlimit_data) {
        /* Next allocation will still be within limits: proceed */
        ptr = malloc(size);
    }
#else
    ptr = malloc(size);
#endif
    if (ptr==NULL) {
        /* No more RAM available: try to allocate private swap */
        qfits_mem_debug(
            fprintf(stderr, "qfits_mem: hit a NULL pointer -- swapping\n");
        );

        /* Create swap file with rights: rw-rw-rw- */
        swapfileid = ++ qfits_memory_table.file_reg ;
        fname = qfits_memory_tmpfilename(swapfileid);
        swapfd = open(fname, O_RDWR | O_CREAT);
        if (swapfd==-1) {
            fprintf(stderr, "qfits_mem: cannot create swap file\n");
            exit(-1);
        }
        fchmod(swapfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);

        /* Compute number of passes to insert buffer */
        nbufs = size / MEMPAGESZ ;
        if (size % MEMPAGESZ != 0) nbufs ++ ;

        /* Dump empty buffers into file */
        memset(wbuf, 0, MEMPAGESZ);
        for (i=0 ; i<nbufs ; i++) {
            if (write(swapfd, wbuf, MEMPAGESZ)==-1) {
                perror("write");
                fprintf(stderr,
                        "qfits_mem: fatal error: cannot create swapfile\n");
                close(swapfd);
                remove(fname);
                exit(-1);
            }
        }

        /* mmap() the swap file */
        ptr = (void*)mmap(0,
                          nbufs * MEMPAGESZ,
                          PROT_READ | PROT_WRITE,
                          MAP_PRIVATE,
                          swapfd,
                          0);
        if ((char*)ptr == (char*)-1) {
            perror("mmap");
            fprintf(stderr,
                    "qfits_mem: fatal error: mmap failed for swap file\n");
            close(swapfd);
            remove(fname);
            exit(-1);
        }

        qfits_mem_debug(
            fprintf(stderr, "qfits_mem: swap [%s] created for %ld bytes\n", 
                fname, (long)size);
        );

        memtype = MEMTYPE_SWAP ;
        qfits_memory_table.alloc_swap += size ;
        qfits_memory_table.nswapfiles ++ ;
    } else {
        /* Memory allocation succeeded */
#ifdef __linux__
        /*
         * On Linux, the returned pointer might not be honored later.
         * To make sure the returned memory is actually usable, it has to
         * be touched. The following will touch one byte every 'pagesize'
         * bytes to make sure all blocks are visited and properly allocated
         * by the OS.
         */
        qfits_mem_debug(
            fprintf(stderr, "qfits_mem: touching memory (Linux)\n");
        );
        for (p=0 ; p<(int)size ; p+=qfits_memory_table.pagesize) 
            ((char*)ptr)[p] = 0;
#endif
        swapfd = -1 ;
        swapfileid = -1 ;
        memtype = MEMTYPE_RAM ;
        qfits_memory_table.alloc_ram   += size ;
    }
    
    /* Print out message in debug mode */
    qfits_mem_debug(
        fprintf(stderr, "qfits_mem: %p alloc(%ld) in %s (%d)\n",
            ptr, (long)size, filename, lineno) ;
    );

    /* Add cell into general table */
    pos = qfits_memory_addcell(  ptr,
                            size,
                            filename,
                            lineno,
                            memtype,
                            swapfileid,
                            swapfd,
                            NULL);
    /* Adjust size */
    qfits_memory_table.alloc_total += size ;
    /* Remember biggest allocated block */
    if (qfits_memory_table.alloc_total > qfits_memory_table.alloc_max)
        qfits_memory_table.alloc_max = qfits_memory_table.alloc_total ;

    /* Insert memory stamp */
    return (void*)ptr ;
}


Generated by  Doxygen 1.6.0   Back to index