static uintptr_t iopa_alloc(vm_size_t bytes, uint32_t balign) { static const uint64_t align_masks[] = { 0xFFFFFFFFFFFFFFFF, 0xAAAAAAAAAAAAAAAA, 0x8888888888888888, 0x8080808080808080, 0x8000800080008000, 0x8000000080000000, 0x8000000000000000, }; io_pagealloc_t * pa; uintptr_t addr = 0; uint32_t count; uint64_t align; if (!bytes) bytes = 1; count = (bytes + kIOPageAllocChunkBytes - 1) / kIOPageAllocChunkBytes; align = align_masks[log2up((balign + kIOPageAllocChunkBytes - 1) / kIOPageAllocChunkBytes)]; IOSimpleLockLock(gIOPageAllocLock); pa = (typeof(pa)) queue_first(&gIOPageAllocList); while (!queue_end(&gIOPageAllocList, &pa->link)) { addr = iopa_allocinpage(pa, count, align); if (addr) { gIOPageAllocBytes += bytes; break; } pa = (typeof(pa)) queue_next(&pa->link); } IOSimpleLockUnlock(gIOPageAllocLock); if (!addr) { pa = iopa_allocpage(); if (pa) { addr = iopa_allocinpage(pa, count, align); IOSimpleLockLock(gIOPageAllocLock); if (pa->avail) enqueue_head(&gIOPageAllocList, &pa->link); gIOPageAllocCount++; if (addr) gIOPageAllocBytes += bytes; IOSimpleLockUnlock(gIOPageAllocLock); } } if (addr) { assert((addr & ((1 << log2up(balign)) - 1)) == 0); IOStatisticsAlloc(kIOStatisticsMallocAligned, bytes); #if IOALLOCDEBUG debug_iomalloc_size += bytes; #endif } return (addr); }
BGBGC_Chunk *BGBGC_NewBlock(int size, int exec) { int size2; BGBGC_Chunk *head; void *p; int i; size2=size+(sizeof(BGBGC_Chunk)*2)+4095+(size>>BGBGC_MAPSHIFT); size2=1<<log2up(size2); if(size2<(1<<BGBGC_CHKSIZE))size2=1<<BGBGC_CHKSIZE; #ifdef linux if(exec) { #ifdef __x86_64__ head=(BGBGC_Chunk *)mmap(NULL, size2, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); #else head=(BGBGC_Chunk *)mmap(NULL, size2, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); #endif }else { head=(BGBGC_Chunk *)mmap(NULL, size2, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); } #else #ifdef WIN32 if(exec) { head=VirtualAlloc(NULL, size2, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); }else { head=VirtualAlloc(NULL, size2, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); } if(!head)return(NULL); memset(head, 0, size2); #else // head=sbrk(size2); head=malloc(size2); if(!head)return(NULL); memset(head, 0, size2); #endif #endif if(!head)return(NULL); head->next=bgbgc_initchain; head->size=size2; bgbgc_initchain=head; head->magic=BGBGC_MAGIC; if(exec)head->magic=BGBGC_XMAGIC; i=size2>>BGBGC_MAPSHIFT; head->map=((byte *)head)+(size2-i); head->data=(byte *)head; i=size2>>BGBGC_CELLSHIFT; head->cells=i-(i>>BGBGC_MAPSHIFT); for(i=0; i<((sizeof(BGBGC_Chunk)+BGBGC_CELLPAD)>>BGBGC_CELLSHIFT); i++) BGBGC_ChunkSetEnt(head, i, 3); // printf("BGBGC_NewBlock(%d): %p\n", size2, head); bgbgc_total_cells+=head->cells; i=bgbgc_nchunk++; if(i>=1024) { *(int *)-1=-1; } bgbgc_chunktab[i]=head; return(head); }