vm_offset_t kalloc_canblock( vm_size_t size, boolean_t canblock) { register int zindex; register vm_size_t allocsize; /* * If size is too large for a zone, then use kmem_alloc. * (We use kmem_alloc instead of kmem_alloc_wired so that * krealloc can use kmem_realloc.) */ if (size >= kalloc_max_prerounded) { vm_offset_t addr; /* kmem_alloc could block so we return if noblock */ if (!canblock) { return(0); } if (kmem_alloc(kalloc_map, &addr, size) != KERN_SUCCESS) addr = 0; if (addr) { kalloc_large_inuse++; kalloc_large_total += size; if (kalloc_large_total > kalloc_large_max) kalloc_large_max = kalloc_large_total; } return(addr); } /* compute the size of the block that we will actually allocate */ allocsize = KALLOC_MINSIZE; zindex = first_k_zone; while (allocsize < size) { allocsize <<= 1; zindex++; } /* allocate from the appropriate zone */ assert(allocsize < kalloc_max); return(zalloc_canblock(k_zone[zindex], canblock)); }
void * kalloc_canblock( vm_size_t size, boolean_t canblock) { zone_t z; if (size < MAX_SIZE_ZDLUT) z = get_zone_dlut(size); else if (size < kalloc_max_prerounded) z = get_zone_search(size, k_zindex_start); else { /* * If size is too large for a zone, then use kmem_alloc. * (We use kmem_alloc instead of kmem_alloc_kobject so that * krealloc can use kmem_realloc.) */ vm_map_t alloc_map; void *addr; /* kmem_alloc could block so we return if noblock */ if (!canblock) { return(NULL); } if (size >= kalloc_kernmap_size) alloc_map = kernel_map; else alloc_map = kalloc_map; if (kmem_alloc(alloc_map, (vm_offset_t *)&addr, size) != KERN_SUCCESS) { if (alloc_map != kernel_map) { if (kmem_alloc(kernel_map, (vm_offset_t *)&addr, size) != KERN_SUCCESS) addr = NULL; } else addr = NULL; } if (addr != NULL) { kalloc_spin_lock(); /* * Thread-safe version of the workaround for 4740071 * (a double FREE()) */ if (size > kalloc_largest_allocated) kalloc_largest_allocated = size; kalloc_large_inuse++; kalloc_large_total += size; kalloc_large_sum += size; if (kalloc_large_total > kalloc_large_max) kalloc_large_max = kalloc_large_total; kalloc_unlock(); KALLOC_ZINFO_SALLOC(size); } return(addr); } #ifdef KALLOC_DEBUG if (size > z->elem_size) panic("%s: z %p (%s) but requested size %lu", __func__, z, z->zone_name, (unsigned long)size); #endif assert(size <= z->elem_size); return (zalloc_canblock(z, canblock)); }