Annotation of qemu/roms/ipxe/src/interface/linux/linux_umalloc.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2010 Piotr JaroszyƄski <[email protected]>
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or
                      5:  * modify it under the terms of the GNU General Public License as
                      6:  * published by the Free Software Foundation; either version 2 of the
                      7:  * License, or any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful, but
                     10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     12:  * General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * along with this program; if not, write to the Free Software
                     16:  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
                     17:  */
                     18: 
                     19: FILE_LICENCE(GPL2_OR_LATER);
                     20: 
                     21: #include <valgrind/memcheck.h>
                     22: 
                     23: /** @file
                     24:  *
                     25:  * iPXE user memory allocation API for linux
                     26:  *
                     27:  */
                     28: 
                     29: #include <assert.h>
                     30: #include <ipxe/umalloc.h>
                     31: 
                     32: #include <linux_api.h>
                     33: 
                     34: /** Special address returned for empty allocations */
                     35: #define NOWHERE ((void *)-1)
                     36: 
                     37: /** Poison to make the metadata more unique */
                     38: #define POISON 0xa5a5a5a5
                     39: #define min(a,b) (((a)<(b))?(a):(b))
                     40: 
                     41: /** Metadata stored at the beginning of all allocations */
                     42: struct metadata
                     43: {
                     44:        unsigned poison;
                     45:        size_t size;
                     46: };
                     47: 
                     48: #define SIZE_MD (sizeof(struct metadata))
                     49: 
                     50: /** Simple realloc which passes most of the work to mmap(), mremap() and munmap() */
                     51: static void * linux_realloc(void *ptr, size_t size)
                     52: {
                     53:        struct metadata md = {0, 0};
                     54:        struct metadata * mdptr = NULL;
                     55: 
                     56:        DBG2("linux_realloc(%p, %zd)\n", ptr, size);
                     57: 
                     58:        /* Check whether we have a valid pointer */
                     59:        if (ptr != NULL && ptr != NOWHERE) {
                     60:                mdptr = ptr - SIZE_MD;
                     61:                VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD);
                     62:                md = *mdptr;
                     63:                VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD);
                     64: 
                     65:                /* Check for poison in the metadata */
                     66:                if (md.poison != POISON) {
                     67:                        DBG("linux_realloc bad poison: 0x%x (expected 0x%x)\n", md.poison, POISON);
                     68:                        return NULL;
                     69:                }
                     70:        } else {
                     71:                /* Handle NOWHERE as NULL */
                     72:                ptr = NULL;
                     73:        }
                     74: 
                     75:        /*
                     76:         * At this point, ptr is either NULL or pointing to a region allocated by us.
                     77:         * In the latter case mdptr is pointing to a valid metadata, otherwise it is NULL.
                     78:         */
                     79: 
                     80:        /* Handle deallocation or allocation of size 0 */
                     81:        if (size == 0) {
                     82:                if (mdptr) {
                     83:                        if (linux_munmap(mdptr, md.size))
                     84:                                DBG("linux_realloc munmap failed: %s\n", linux_strerror(linux_errno));
                     85:                        VALGRIND_FREELIKE_BLOCK(ptr, sizeof(*mdptr));
                     86:                }
                     87:                return NOWHERE;
                     88:        }
                     89: 
                     90:        if (ptr) {
                     91:                char *vbits = NULL;
                     92: 
                     93:                if (RUNNING_ON_VALGRIND > 0)
                     94:                        vbits = linux_realloc(NULL, min(size, md.size));
                     95: 
                     96: /* prevent an unused variable warning when building w/o valgrind support */
                     97: #ifndef NVALGRIND
                     98:                VALGRIND_GET_VBITS(ptr, vbits, min(size, md.size));
                     99: #endif
                    100: 
                    101:                VALGRIND_FREELIKE_BLOCK(ptr, SIZE_MD);
                    102: 
                    103:                mdptr = linux_mremap(mdptr, md.size + SIZE_MD, size + SIZE_MD, MREMAP_MAYMOVE);
                    104:                if (mdptr == MAP_FAILED) {
                    105:                        DBG("linux_realloc mremap failed: %s\n", linux_strerror(linux_errno));
                    106:                        return NULL;
                    107:                }
                    108:                ptr = ((void *)mdptr) + SIZE_MD;
                    109: 
                    110:                VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0);
                    111: /* prevent an unused variable warning when building w/o valgrind support */
                    112: #ifndef NVALGRIND
                    113:                VALGRIND_SET_VBITS(ptr, vbits, min(size, md.size));
                    114: #endif
                    115: 
                    116:                if (RUNNING_ON_VALGRIND > 0)
                    117:                        linux_realloc(vbits, 0);
                    118:        } else {
                    119:                mdptr = linux_mmap(NULL, size + SIZE_MD, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
                    120:                if (mdptr == MAP_FAILED) {
                    121:                        DBG("linux_realloc mmap failed: %s\n", linux_strerror(linux_errno));
                    122:                        return NULL;
                    123:                }
                    124:                ptr = ((void *)mdptr) + SIZE_MD;
                    125:                VALGRIND_MALLOCLIKE_BLOCK(ptr, size, SIZE_MD, 0);
                    126:        }
                    127: 
                    128:        /* Update the metadata */
                    129:        VALGRIND_MAKE_MEM_DEFINED(mdptr, SIZE_MD);
                    130:        mdptr->poison = POISON;
                    131:        mdptr->size = size;
                    132:        VALGRIND_MAKE_MEM_NOACCESS(mdptr, SIZE_MD);
                    133:        // VALGRIND_MALLOCLIKE_BLOCK ignores redzones currently, make our own
                    134:        VALGRIND_MAKE_MEM_NOACCESS(ptr + size, SIZE_MD);
                    135: 
                    136:        return ptr;
                    137: }
                    138: 
                    139: /**
                    140:  * Reallocate external memory
                    141:  *
                    142:  * @v old_ptr          Memory previously allocated by umalloc(), or UNULL
                    143:  * @v new_size         Requested size
                    144:  * @ret new_ptr                Allocated memory, or UNULL
                    145:  *
                    146:  * Calling realloc() with a new size of zero is a valid way to free a
                    147:  * memory block.
                    148:  */
                    149: static userptr_t linux_urealloc(userptr_t old_ptr, size_t new_size)
                    150: {
                    151:        return (userptr_t)linux_realloc((void *)old_ptr, new_size);
                    152: }
                    153: 
                    154: PROVIDE_UMALLOC(linux, urealloc, linux_urealloc);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.