1/* 2 * Copyright (c) 2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_APACHE_LICENSE_HEADER_START@ 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * @APPLE_APACHE_LICENSE_HEADER_END@ 19 */ 20#include <stdio.h> 21#include <stdlib.h> 22#include <assert.h> 23#include <malloc/malloc.h> 24#include <auto_zone.h> 25 26struct BlockRecorderContext { 27 size_t blocks_in_use; 28 size_t size_in_use; 29 malloc_zone_t *zone; 30}; 31typedef struct BlockRecorderContext BlockRecorderContext; 32 33static void blockRecorder(task_t task, void *context, unsigned type, vm_range_t *ranges, unsigned count) { 34 BlockRecorderContext *blockContext = context; 35 while (count--) { 36 blockContext->blocks_in_use++; 37 // <rdar://problem/4574925> scalable malloc shouldn't count the zone as part of the allocated block space. 38 if (ranges->address != (vm_address_t)blockContext->zone) blockContext->size_in_use += ranges->size; 39 ++ranges; 40 } 41} 42 43void test_introspection(malloc_zone_t *zone, boolean_t exact) { 44 static void* pointers[1000]; 45 BlockRecorderContext context = { 0, 0, zone }; 46 malloc_statistics_t stats; 47 size_t i; 48 49 // allocate 1000 randomly sized blocks. 50 for (i = 0; i < 1000; ++i) { 51 size_t random_size = (random() & 0x1FFFF); 52 pointers[i] = malloc_zone_malloc(zone, random_size); 53 } 54 55 // deallocate a random number of the blocks. 56 for (i = 0; i < 1000; ++i) { 57 if (random() & 0x1) { 58 malloc_zone_free(zone, pointers[i]); 59 pointers[i] = NULL; 60 } 61 } 62 63 // validate that these agree with the values returned by the enumeration APIs. 64 zone->introspect->enumerator(mach_task_self(), &context, MALLOC_PTR_IN_USE_RANGE_TYPE, (vm_address_t)zone, NULL, blockRecorder); 65 malloc_zone_statistics(zone, &stats); 66 if (exact) { 67 assert(stats.blocks_in_use == context.blocks_in_use); 68 assert(stats.size_in_use == context.size_in_use); 69 } else { 70 // the malloc default zone enumerators don't currently match the statistics. 71 assert(stats.blocks_in_use >= context.blocks_in_use); 72 assert(stats.size_in_use >= context.size_in_use); 73 } 74} 75 76int main() { 77 test_introspection(auto_zone_create("auto zone"), true); 78 test_introspection(malloc_default_zone(), false); 79 test_introspection(malloc_create_zone(8192, 0), false); 80 return 0; 81} 82