⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memmgr.c copy

📁 ati driver
💻 C COPY
📖 第 1 页 / 共 2 页
字号:
	bool get_discarded_list;	bool make_locked;		uint alloc_id;	uint user_alloc_id;	uint offset;	int discarded_list;} vmem_io_alloc;status_t vmem_ioctl_alloc( vmem_pool *pool, vmem_dev_info *dev, vmem_io_alloc *buffer ){	unsigned int client_id = buffer->client_id;	vmem_client *client;	vmem_entry *alloc;	status_t result = B_OK;	retry:	ACQUIRE_BEN( pool->lock );		client = vmem_check_client_id( pool, buffer->client_id, dev );	if( client == NULL ) {		result = B_BAD_VALUE;		goto exit;	}			result = vmem_server_alloc( pool, client, buffer->size, &alloc );		if( result == B_BUSY ) {		RELEASE_BEN( pool->lock );		goto retry;	}		if( buffer->make_locked )		alloc->alloc_user->prev = vmem_entry_LOCKED;		if( buffer->get_discarded_list &&		(result == B_NO_MEMORY || result == B_OK) ) 	{		buffer->discarded_list = client->discarded_list;		client->discarded_list = INT_MAX;	}		if( result != B_OK )		goto exit;			buffer->alloc_id = alloc->id;	buffer->user_alloc_id = alloc->alloc_user - client->allocs;	buffer->offset = alloc->pos << pool->block_shift;	exit:	RELEASE_BEN( pool->lock );	return result;}typedef struct vmem_io_free {	uint client_id;	uint alloc_id;	bool get_discarded_list;		int discarded_list;} vmem_io_free;status_t vmem_ioctl_free( vmem_pool *pool, vmem_dev_info *dev, vmem_io_free *buffer ){	uint client_id = buffer->client_id;	uint alloc_id = buffer->alloc_id;	vmem_client *client;	vmem_entry *alloc;	status_t result = B_OK;	ACQUIRE_BEN( pool->lock );	client = vmem_check_client_id( pool, buffer->client_id, dev );	if( client == NULL ) {		result = B_BAD_VALUE;		goto exit;	}				if( alloc_id > pool->max_allocs ) {		SHOW_ERROR( 1, "alloc_id=%d is invalid", alloc_id );		result = B_BAD_VALUE;		goto exit;	}		alloc = &pool->allocs[alloc_id];	if( alloc->client != client ) {		SHOW_ERROR( 1, "alloc_id %d doesn't belong to client %d",			alloc_id, client );		result = B_BAD_VALUE;		goto exit;	}	result = vmem_server_free( pool, client, alloc );		if( buffer->get_discarded_list && result == B_OK ) {		buffer->discarded_list = client->discarded_list;		client->discarded_list = INT_MAX;	}	exit:	RELEASE_BEN( pool->lock );	return result;}static status_t vmem_client_create( vmem_pool *pool, const char *name, int max_allocs, vmem_client **res_client ){	int client_id;	vmem_client *client;	int i;	free_entry *client_free_list = (free_entry *)pool->clients;	status_t result = B_NO_MEMORY;		client_id = pool->unused_clients - client_free_list;		if( client_id == 0 ) {		SHOW_ERROR0( 0, "Out of client ids" );		goto err1;	}		client = malloc( sizeof( *client ));	if( client == NULL )		goto err2;	client->id = client_id;		max_allocs = min( max_allocs, 3 );			client->max_allocs = max_allocs;		client->alloc_area_id = create_area( name, (void **)&client->user, B_ANY_ADDRESS, 		sizeof( vmem_user ) + max_allocs * sizeof( vmem_entry_user ),		B_NO_LOCK, 0 );			if( client->alloc_area_id  < 0 ) {		result = client->alloc_area_id;		goto err3;	}			client->allocs = (vmem_entry_user *)((int)client->user + sizeof( vmem_user *));		for( i = 0; i < max_allocs - 1; ++i ) 		client->allocs[i].next = i + 1;			client->allocs[max_allocs - 1].next = INT_MAX;	client->unused_list = 0;		client->discarded_list = INT_MAX;		pool->unused_clients = client_free_list[client_id].next;	pool->clients[client_id] = client;		*res_client = client;		return B_OK;	err3:	free( client );err2:err1:	return result;}typedef struct vmem_io_create {	area_id alloc_area_id;	uint client_id;} vmem_io_create;status_t vmem_ioctl_create( vmem_pool *pool, vmem_dev_info *dev, const char *name, vmem_io_create *buffer ){	status_t result;	vmem_client *client;		ACQUIRE_BEN( pool->lock );	result = vmem_client_create( pool, name, pool->max_allocs, &client );	if( result != B_OK )		goto exit;	client->prev = NULL;	client->next = dev->clients;	if( dev->clients )		dev->clients->prev = client;	dev->clients = client;		buffer->client_id = client->id;	buffer->alloc_area_id = client->alloc_area_id;exit:		RELEASE_BEN( pool->lock );	return result;}static void vmem_server_free_client( vmem_pool *pool, vmem_client *client ){	vmem_entry *alloc;		for( alloc = pool->first; alloc; alloc = alloc->next ) {		if( alloc->client == client ) {			vmem_server_discard( pool, alloc );			vmem_server_merge_allocs( pool, alloc, true );		}	}}static void vmem_client_destroy( vmem_pool *pool, vmem_client *client ){	free_entry *client_free_list = (free_entry *)pool->clients;		vmem_server_free_client( pool, client );	client_free_list[client->id].next = pool->unused_clients;	pool->unused_clients = &client_free_list[client->id];		delete_area( client->alloc_area_id );	free( client );}typedef struct vmem_io_destroy {	uint client_id;} vmem_io_destroy;status_t vmem_ioctl_destroy( vmem_pool *pool, vmem_dev_info *dev, vmem_io_destroy *buffer ){	uint client_id = buffer->client_id;	status_t result;	vmem_client *client;	ACQUIRE_BEN( pool->lock );		client = vmem_check_client_id( pool, buffer->client_id, dev );	if( client == NULL ) {		result = B_BAD_VALUE;		goto exit;	}			if( client->prev )		client->prev->next = client->next;	else		dev->clients = client->next;			if( client->next )		client->next->prev = client->prev;			vmem_client_destroy( pool, client );		result = B_OK;	exit:	RELEASE_BEN( pool->lock );	return result;}void vmem_client_destroy_all( vmem_pool *pool, vmem_dev_info *dev ){	vmem_client *client, *next;		for( client = dev->clients; client; client = next ) {		next = client->next;				vmem_client_destroy( pool, client );	}}vmem_pool *vmem_server_create( const char *name, int size, int block_size, int max_allocs, int max_clients ){	vmem_pool *pool;	vmem_entry *first;	int i;	uint j;	free_entry *clients_free_list;		pool = malloc( sizeof( *pool ));	if( pool == NULL )		goto err1;			INIT_BEN( name, pool->lock );	if( pool->lock.sem < 0 ) 		goto err2;	pool->max_clients = max_clients;	pool->clients = malloc( sizeof( vmem_client * ) * max_clients );	if( pool->clients == NULL )		goto err3;			memset( pool->clients, 0, sizeof( vmem_client * ) * max_clients );	clients_free_list = (free_entry *)pool->clients;	// client_id 0 is unused (we use it as "end-of-freelist" )	for( i = 1; i < max_clients - 1; ++i ) 		clients_free_list[i].next = &clients_free_list[i+1];	clients_free_list[max_clients - 1].next = &clients_free_list[0];	pool->unused_clients = &clients_free_list[1];			pool->block_shift = minBits( block_size );	pool->block_size = 1 << pool->block_shift;		pool->num_blocks = size >> pool->block_shift;		max_allocs = max( max_allocs, 3 );	pool->max_allocs = max_allocs;		pool->allocs = malloc( sizeof( vmem_entry ) * max_allocs ); 	if( pool->allocs == NULL )		goto err4;	memset( pool->allocs, 0, sizeof( vmem_entry ) * max_allocs );		for( j = 0; j < pool->max_allocs; ++i ) 		pool->allocs[j].id = j;	first = &pool->allocs[0];	first->next = NULL;	first->prev = NULL;	first->pos = 0;	first->num_blocks = pool->num_blocks;	first->alloc_user = &pool->alloc_dummy;	first->client = NULL;		pool->first = first;		// dummy must look like an allocated, non-locked range	// (this way find_vmem_block does not distinguish between 	//  empty and allocated, non-locked range)	pool->alloc_dummy.prev = 0;		for( j = 1; j < pool->max_allocs - 1; ++i ) 		pool->allocs[j].next = &pool->allocs[j+1];	pool->allocs[pool->max_allocs - 1].next = NULL;	pool->unused_list = &pool->allocs[1];	return pool;	err4:	free( pool->clients );err3:	DELETE_BEN( pool->lock );err2:	free( pool );err1:	return NULL;}void vmem_server_destroy( vmem_pool *pool ){	free( pool->allocs );	free( pool->clients );	DELETE_BEN( pool->lock );	free( pool );}static vmem_client *vmem_check_client_id( vmem_pool *pool, uint client_id, vmem_dev_info *dev ){	vmem_client *client;		if( client_id > pool->max_clients ) {		SHOW_ERROR( 1, "client_id=%d is invalid (out of range)", client_id );		return NULL;	}		client = pool->clients[client_id];		if( (vmem_client **)client <= &pool->clients[0] || 		(vmem_client **)client >= &pool->clients[pool->max_clients] )	{		SHOW_ERROR( 1, "client_id=%d is invalid (id is marked as being unused)", client_id );		return NULL;	}			if( client->dev != dev ) {		SHOW_ERROR( 1, "client_id=%d doesn't belong to device handle", client_id );		return NULL;	}		return client;}void vmem_entry( vmem_user *pool, size_t size, int make_locked,	vmem_user **alloc, void *addr, uint *alloc_id, uint *discarded_list ){	mem_io_alloc buffer;	buffer->client_id = pool->client_id;	buffer->size = size;	buffer->get_discarded_list = discarded_list != NULL;	buffer->make_locked = make_locked;			result = pool->ioctl( pool->dev, pool->first_ioctl, buffer, sizeof( buffer ));		if( result != B_OK )		return result;		*alloc_id = buffer->alloc_id;	*alloc = &pool->allocs[user_alloc_id];	*addr = pool->base_address + offset;		if( discarded_list )		*discarded_list = buffer.discarded_list;	return B_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -