typename allocator<T>::pointer allocator<T>::allocate(size_type n, void *const hint)
{
	const size_type nb = n * sizeof(T);
#	if DEBUG_SMA_TRACE_INTERFACE
	std::cout << "alloc " << nb << " bytes (n=" << n << ", hint=" << static_cast<void *>(hint) << ")" << std::endl;
#	endif
	assert(nb > 0);
	if (!(nb > 0)) {
		std::cerr << "cannot allocate a memory block of size " << nb << std::endl;
		goto badalloc;
	}
	if (nb > memfree->size()) {
		std::cerr << "triing to allocate a memory block of size " << nb << " bytes, "
			  << "but the managed memory has only a size of " << memfree->size() << " bytes." << std::endl;
		goto badalloc;
	}
	{//block
		auto mask = create_mask(nb, memfree->size());
		const size_type pos = find_free_memory(*memfree, mask);
		assert(0 <= pos && pos <= memfree->size());
		if (pos < memfree->size()) {
#			if DEBUG_SMA_TRACE_MEMALLOCATION
			std::cout << "reserved memory: " << mask.count() << " bytes -> "
				  << (memfree->count() - mask.count()) << " bytes free."
				  << std::endl;
#			endif
			*memfree = reserve_memory(*memfree, std::move(mask));
#			if DEBUG_SMA_TRACE_MEMALLOCATION
			print_free_memory();
#			endif
			return calc_pointer(memstart, pos);
		} else {
#			if DEBUG_SMA_TRACE_MEMALLOCATION
			std::cout << "not enough free memory to allocate " << nb << " bytes." << std::endl;
			print_free_memory();
#			endif
		}
	}
badalloc:
	/* not enough memory free */
	throw std::bad_alloc();
	return nullptr;
}
示例#2
0
static int
dom0_memory_reserve(uint32_t rsv_size)
{
	uint64_t pfn, vstart, vaddr;
	uint32_t i, num_block, size, allocated_size = 0;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
	dma_addr_t dma_handle;
#endif

	/* 2M as memory block */
	num_block = rsv_size / SIZE_PER_BLOCK;

	rsv_mm_info = vmalloc(sizeof(struct memblock_info) * num_block);
	if (!rsv_mm_info) {
		XEN_ERR("Unable to allocate device memory information\n");
		return -ENOMEM;
	}
	memset(rsv_mm_info, 0, sizeof(struct memblock_info) * num_block);

	/* try alloc size of 4M once */
	for (i = 0; i < num_block; i += 2) {
		vstart = (unsigned long)
			__get_free_pages(GFP_ATOMIC, MAX_NUM_ORDER);
		if (vstart == 0)
			break;

		dom0_dev.num_bigblock = i / 2 + 1;
		allocated_size =  SIZE_PER_BLOCK * (i + 2);

		/* size of 4M */
		size = DOM0_MEMBLOCK_SIZE * 2;

		vaddr = vstart;
		while (size > 0) {
			SetPageReserved(virt_to_page(vaddr));
			vaddr += PAGE_SIZE;
			size -= PAGE_SIZE;
		}

		pfn = virt_to_pfn(vstart);
		rsv_mm_info[i].pfn = pfn;
		rsv_mm_info[i].vir_addr = vstart;
		rsv_mm_info[i + 1].pfn =
				pfn + DOM0_MEMBLOCK_SIZE / PAGE_SIZE;
		rsv_mm_info[i + 1].vir_addr =
				vstart + DOM0_MEMBLOCK_SIZE;
	}

	/*if it failed to alloc 4M, and continue to alloc 2M once */
	for (; i < num_block; i++) {
		vstart = (unsigned long)
			__get_free_pages(GFP_ATOMIC, DOM0_CONTIG_NUM_ORDER);
		if (vstart == 0) {
			XEN_ERR("allocate memory fail.\n");
			dom0_memory_free(allocated_size);
			return -ENOMEM;
		}

		allocated_size += SIZE_PER_BLOCK;

		size = DOM0_MEMBLOCK_SIZE;
		vaddr = vstart;
		while (size > 0) {
			SetPageReserved(virt_to_page(vaddr));
			vaddr += PAGE_SIZE;
			size -= PAGE_SIZE;
		}
		pfn = virt_to_pfn(vstart);
		rsv_mm_info[i].pfn = pfn;
		rsv_mm_info[i].vir_addr = vstart;
	}

	sort_viraddr(rsv_mm_info, num_block);

	for (i = 0; i< num_block; i++) {

		/*
		 * This API is used to exchage MFN for getting a block of
		 * contiguous physical addresses, its maximum size is 2M.
		 */
	#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
		if (xen_create_contiguous_region(rsv_mm_info[i].vir_addr,
				DOM0_CONTIG_NUM_ORDER, 0) == 0) {
	#else
		if (xen_create_contiguous_region(rsv_mm_info[i].pfn * PAGE_SIZE,
				DOM0_CONTIG_NUM_ORDER, 0, &dma_handle) == 0) {
	#endif
			rsv_mm_info[i].exchange_flag = 1;
			rsv_mm_info[i].mfn =
				pfn_to_mfn(rsv_mm_info[i].pfn);
			rsv_mm_info[i].used = 0;
		} else {
			XEN_ERR("exchange memeory fail\n");
			rsv_mm_info[i].exchange_flag = 0;
			dom0_dev.fail_times++;
			if (dom0_dev.fail_times > MAX_EXCHANGE_FAIL_TIME) {
				dom0_memory_free(rsv_size);
				return  -EFAULT;
			}
		}
	}

	return 0;
}

static int
dom0_prepare_memsegs(struct memory_info *meminfo, struct dom0_mm_data *mm_data)
{
	uint32_t num_block;
	int idx;

	/* check if there is a free name buffer */
	memcpy(mm_data->name, meminfo->name, DOM0_NAME_MAX);
	mm_data->name[DOM0_NAME_MAX - 1] = '\0';
	idx = dom0_find_mempos();
	if (idx < 0)
		return -1;

	num_block = meminfo->size / SIZE_PER_BLOCK;
	/* find free memory and new memory segments*/
	find_free_memory(num_block, mm_data);
	find_memseg(num_block, mm_data);

	/* update private memory data */
	mm_data->refcnt++;
	mm_data->mem_size = meminfo->size;

	/* update global memory data */
	dom0_dev.mm_data[idx] = mm_data;
	dom0_dev.num_mem_ctx++;
	dom0_dev.used_memsize += mm_data->mem_size;

	return 0;
}