예제 #1
0
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);
}
예제 #2
0
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);
}