Annotation of qemu/roms/ipxe/src/interface/linux/linux_umalloc.c, revision 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.