* realloc: change the size of a memory block */
| 942 | * realloc: change the size of a memory block |
| 943 | */ |
| 944 | void * |
| 945 | realloc(void *addr, size_t size, struct malloc_type *mtp, int flags) |
| 946 | { |
| 947 | uma_zone_t zone; |
| 948 | uma_slab_t slab; |
| 949 | unsigned long alloc; |
| 950 | void *newaddr; |
| 951 | |
| 952 | KASSERT(mtp->ks_version == M_VERSION, |
| 953 | ("realloc: bad malloc type version")); |
| 954 | KASSERT(curthread->td_critnest == 0 || SCHEDULER_STOPPED(), |
| 955 | ("realloc: called with spinlock or critical section held")); |
| 956 | |
| 957 | /* realloc(NULL, ...) is equivalent to malloc(...) */ |
| 958 | if (addr == NULL) |
| 959 | return (malloc(size, mtp, flags)); |
| 960 | |
| 961 | /* |
| 962 | * XXX: Should report free of old memory and alloc of new memory to |
| 963 | * per-CPU stats. |
| 964 | */ |
| 965 | |
| 966 | #ifdef DEBUG_MEMGUARD |
| 967 | if (is_memguard_addr(addr)) |
| 968 | return (memguard_realloc(addr, size, mtp, flags)); |
| 969 | #endif |
| 970 | |
| 971 | #ifdef DEBUG_REDZONE |
| 972 | slab = NULL; |
| 973 | zone = NULL; |
| 974 | alloc = redzone_get_size(addr); |
| 975 | #else |
| 976 | vtozoneslab((vm_offset_t)addr & (~UMA_SLAB_MASK), &zone, &slab); |
| 977 | |
| 978 | /* Sanity check */ |
| 979 | KASSERT(slab != NULL, |
| 980 | ("realloc: address %p out of range", (void *)addr)); |
| 981 | |
| 982 | /* Get the size of the original block */ |
| 983 | if (!malloc_large_slab(slab)) |
| 984 | alloc = zone->uz_size; |
| 985 | else |
| 986 | alloc = malloc_large_size(slab); |
| 987 | |
| 988 | /* Reuse the original block if appropriate */ |
| 989 | if (size <= alloc |
| 990 | && (size > (alloc >> REALLOC_FRACTION) || alloc == MINALLOCSIZE)) |
| 991 | return (addr); |
| 992 | #endif /* !DEBUG_REDZONE */ |
| 993 | |
| 994 | /* Allocate a new, bigger (or smaller) block */ |
| 995 | if ((newaddr = malloc(size, mtp, flags)) == NULL) |
| 996 | return (NULL); |
| 997 | |
| 998 | /* Copy over original contents */ |
| 999 | bcopy(addr, newaddr, min(size, alloc)); |
| 1000 | free(addr, mtp); |
| 1001 | return (newaddr); |