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

📄 manager.c

📁 一个Windows下的Linux专用虚拟机
💻 C
字号:
/* * This source code is a part of coLinux source package. * * Dan Aloni <da-x@colinux.org>, 2003-2004 (c) * * The code is licensed under the GPL. See the COPYING file at * the root directory. */#include <colinux/common/libc.h>#include <colinux/os/kernel/alloc.h>#include <colinux/os/kernel/monitor.h>#include <colinux/os/kernel/manager.h>#include <colinux/os/kernel/misc.h>#include <colinux/os/kernel/mutex.h>#include <colinux/arch/mmu.h>#include "manager.h"#include "monitor.h"#include "pages.h"#include "reversedpfns.h"co_manager_t *co_global_manager = NULL;static void set_hostmem_usage_limit(co_manager_t *manager){	if (manager->hostmem_amount >= 256 * 0x100000) {		/* more than 256MB */		/* use_limit = host - 64mb */		manager->hostmem_usage_limit = manager->hostmem_amount - 64 * 0x100000;	} else {		/* less then 256MB */		/* use_limit = host * (3/4) */		manager->hostmem_usage_limit = ((manager->hostmem_amount/0x100000)*3/4) * 0x100000;	}	co_debug("machine RAM use limit: %ld MB" , manager->hostmem_amount/0x100000);}co_rc_t co_manager_load(co_manager_t *manager){	co_rc_t rc;	co_memset(manager, 0, sizeof(*manager));		co_debug("loaded to host kernel");	co_list_init(&manager->opens);	co_list_init(&manager->monitors);	rc = co_os_mutex_create(&manager->lock);	if (!CO_OK(rc))		return rc;	rc = co_os_physical_memory_pages(&manager->hostmem_pages);	if (!CO_OK(rc))		goto out_err_mutex;	if (manager->hostmem_pages > 0x100000) {		co_debug_error("error, machines with more than 4GB are not currently supported");		rc = CO_RC(ERROR);		goto out_err_mutex;	}	co_debug("machine has %ld MB of RAM", manager->hostmem_pages >> 8);	manager->hostmem_amount = manager->hostmem_pages << CO_ARCH_PAGE_SHIFT;	set_hostmem_usage_limit(manager);	rc = co_debug_init(&manager->debug);	if (!CO_OK(rc))		goto out_err_mutex;	manager->state = CO_MANAGER_STATE_INITIALIZED_DEBUG;	rc = co_manager_arch_init(manager, &manager->archdep);	if (!CO_OK(rc))		goto out_err_debug;	manager->state = CO_MANAGER_STATE_INITIALIZED_ARCH;	rc = co_os_manager_init(manager, &manager->osdep);	if (!CO_OK(rc))		goto out_err_arch;	manager->state = CO_MANAGER_STATE_INITIALIZED_OSDEP;	rc = co_manager_alloc_reversed_pfns(manager);	if (!CO_OK(rc))		goto out_err_os;	manager->state = CO_MANAGER_STATE_INITIALIZED;	return rc;/* error path */out_err_os:	co_os_manager_free(manager->osdep);	out_err_arch:	co_manager_arch_free(manager->archdep);out_err_debug:	co_debug_free(&manager->debug);out_err_mutex:	co_os_mutex_destroy(manager->lock);	manager->state = CO_MANAGER_STATE_NOT_INITIALIZED;	return rc;}void co_manager_unload(co_manager_t *manager){	co_debug("unloaded from host kernel");	if (manager->state >= CO_MANAGER_STATE_INITIALIZED) {		co_manager_free_reversed_pfns(manager);		co_os_mutex_destroy(manager->lock);	}	if (manager->state >= CO_MANAGER_STATE_INITIALIZED_OSDEP)		co_os_manager_free(manager->osdep);	if (manager->state >= CO_MANAGER_STATE_INITIALIZED_ARCH)		co_manager_arch_free(manager->archdep);	if (manager->state >= CO_MANAGER_STATE_INITIALIZED_DEBUG)		co_debug_free(&manager->debug);	manager->state = CO_MANAGER_STATE_NOT_INITIALIZED;}co_rc_t co_manager_send(co_manager_t *manager, co_manager_open_desc_t opened, co_message_t *message){	bool_t ret;	co_rc_t rc = CO_RC_OK;	co_os_mutex_acquire(opened->lock);	ret = co_os_manager_userspace_try_send_direct(manager, opened, message);	if (!ret)		rc = co_message_dup_to_queue(message, &opened->out_queue);	co_os_mutex_release(opened->lock);	return rc;}co_rc_t co_manager_send_eof(co_manager_t *manager, co_manager_open_desc_t opened){	opened->active = PFALSE;		return co_os_manager_userspace_eof(manager, opened);}co_rc_t co_manager_open(co_manager_t *manager, co_manager_open_desc_t *opened_out){	co_manager_open_desc_t opened;	co_rc_t rc;	opened = co_os_malloc(sizeof(*opened));	if (!opened)		return CO_RC(OUT_OF_MEMORY);	co_memset(opened, 0, sizeof(*opened));		rc = co_os_mutex_create(&opened->lock);	if (!CO_OK(rc))		return rc;	rc = co_os_manager_userspace_open(opened);	if (!CO_OK(rc)) {		co_os_mutex_destroy(opened->lock);		co_os_free(opened);		return rc;	}	opened->monitor = NULL;	opened->debug_section = NULL;	opened->ref_count = 1;	opened->active = PTRUE;	co_queue_init(&opened->out_queue);	co_os_mutex_acquire(manager->lock);	co_list_add_head(&opened->node, &manager->opens);	manager->num_opens++;	co_os_mutex_release(manager->lock);	*opened_out = opened;	return CO_RC(OK);}static co_rc_t co_manager_close_(co_manager_t *manager, co_manager_open_desc_t opened){	co_os_manager_userspace_close(opened);	if (opened->monitor != NULL) {		co_monitor_t *mon = opened->monitor;		opened->monitor = NULL;		co_monitor_refdown(mon, PFALSE, opened->monitor_owner);	}	if (opened->debug_section != NULL) {		co_debug_fold(&manager->debug, opened->debug_section);		opened->debug_section = NULL;	}	co_os_mutex_acquire(manager->lock);	co_list_del(&opened->node);	manager->num_opens--;	co_os_mutex_release(manager->lock);	co_os_mutex_destroy(opened->lock);	co_queue_flush(&opened->out_queue);	co_os_free(opened);	return CO_RC(OK);}/* must be called only when manager->lock is locked */co_rc_t co_manager_open_ref(co_manager_open_desc_t opened){	co_rc_t rc = CO_RC(OK);	co_os_mutex_acquire(opened->lock);	if (opened->ref_count == 0)		rc = CO_RC(ERROR);	else		opened->ref_count++;	co_os_mutex_release(opened->lock);	return rc;}co_rc_t co_manager_close(co_manager_t *manager, co_manager_open_desc_t opened){	bool_t close;	co_os_mutex_acquire(opened->lock);	opened->ref_count--;	close = (opened->ref_count == 0);	co_os_mutex_release(opened->lock);	if (close) {		return co_manager_close_(manager, opened);	}	return CO_RC(OK);}co_rc_t co_manager_open_desc_deactive_and_close(co_manager_t *manager, co_manager_open_desc_t opened){	co_rc_t rc;	opened->active = PFALSE;	if (opened->monitor != NULL) {		co_monitor_t *mon = opened->monitor;		int index;		co_os_mutex_acquire(mon->connected_modules_write_lock);		for (index=0; index < CO_MONITOR_MODULES_COUNT; index++) {			if (mon->connected_modules[index] != opened)				continue;						mon->connected_modules[index] = NULL;			co_manager_close(manager, opened);		}		co_os_mutex_release(mon->connected_modules_write_lock);	}		rc = co_manager_close(manager, opened);		return rc;}co_rc_t co_manager_ioctl(co_manager_t *manager, unsigned long ioctl, 			 void *io_buffer, unsigned long in_size,			 unsigned long out_size, unsigned long *return_size,			 co_manager_open_desc_t opened){	co_rc_t rc = CO_RC_OK;	co_monitor_t *cmon = NULL;	*return_size = 0;	switch (ioctl) {	case CO_MANAGER_IOCTL_STATUS: {		co_manager_ioctl_status_t *params;		params = (typeof(params))(io_buffer);		params->state = manager->state;		params->monitors_count = manager->monitors_count;		params->periphery_api_version = CO_LINUX_PERIPHERY_API_VERSION;		params->linux_api_version = CO_LINUX_API_VERSION;		*return_size = sizeof(*params);		return CO_RC(OK);	}	case CO_MANAGER_IOCTL_INFO: {		co_manager_ioctl_info_t *params;		params = (typeof(params))(io_buffer);		params->hostmem_usage_limit = manager->hostmem_usage_limit;		params->hostmem_used = manager->hostmem_used;		*return_size = sizeof(*params);		return CO_RC(OK);	}	case CO_MANAGER_IOCTL_DEBUG: {		co_debug_write_vector_t vec;		vec.vec_size = 0;		vec.size = in_size;		vec.ptr = io_buffer;				co_debug_write_log(&manager->debug, &opened->debug_section, &vec, 1);		return CO_RC(OK);	}	case CO_MANAGER_IOCTL_DEBUG_READER: {		co_manager_ioctl_debug_reader_t *params;		params = (typeof(params))(io_buffer);		params->rc = co_debug_read(&manager->debug, params->user_buffer, 					   params->user_buffer_size, &params->filled);		*return_size = sizeof(*params);		return CO_RC(OK);	}	case CO_MANAGER_IOCTL_DEBUG_LEVELS: {		co_manager_ioctl_debug_levels_t *params;		params = (typeof(params))(io_buffer);		if (params->modify) {			co_global_debug_levels = params->levels;		} else {			params->levels = co_global_debug_levels;		}		*return_size = sizeof(*params);		return CO_RC(OK);	}	default:		break;	}	if (manager->state < CO_MANAGER_STATE_INITIALIZED) {		return CO_RC_ERROR;	}	switch (ioctl) {	case CO_MANAGER_IOCTL_CREATE: {				co_manager_ioctl_create_t *params = (typeof(params))(io_buffer);		if (opened->monitor)			return CO_RC(ERROR);					rc = co_monitor_create(manager, params, &cmon);		if (CO_OK(rc)) {			opened->monitor = cmon;			opened->monitor_owner = PTRUE;		}		params->rc = rc;		*return_size = sizeof(*params);		break;	}	case CO_MANAGER_IOCTL_MONITOR_LIST: {		co_manager_ioctl_monitor_list_t *params = (typeof(params))(io_buffer);		co_monitor_t *monitor = NULL;		co_rc_t rc = CO_RC(OK);		int i = 0;		co_os_mutex_acquire(manager->lock);		co_list_each_entry(monitor, &manager->monitors, node) {			if (i >= CO_MAX_MONITORS) {				/* We don't enforce a limit on create, so just				 * break from the loop and return the first ones				 */				break;			}			params->ids[i++] = monitor->id;		}		co_os_mutex_release(manager->lock);		params->count = i;		params->rc = rc;		*return_size = sizeof(*params);		break;	}	case CO_MANAGER_IOCTL_ATTACH: {		co_manager_ioctl_attach_t *params = (typeof(params))(io_buffer);		co_monitor_t *monitor = NULL;		co_rc_t rc = CO_RC(ERROR);		co_os_mutex_acquire(manager->lock);		co_list_each_entry(monitor, &manager->monitors, node) {			if (monitor->id == params->id) {				monitor->refcount++;				opened->monitor = monitor;				rc = CO_RC(OK);				break;			}		}		co_os_mutex_release(manager->lock);		if (!CO_OK(rc)) {			opened->monitor = NULL;		}		if (opened->monitor) {			int index;			co_module_t module;			co_manager_open_desc_t old_opened;			cmon = opened->monitor;			co_os_mutex_acquire(cmon->connected_modules_write_lock);			for (index=0; index < params->num_modules; index++) {				module = params->modules[index];				old_opened = cmon->connected_modules[module];				if (old_opened)					co_manager_close(manager, old_opened);				cmon->connected_modules[module] = opened;				opened->ref_count++;						}			co_os_mutex_release(cmon->connected_modules_write_lock);		}		*return_size = sizeof(*params);		params->rc = rc;		break;	}	case CO_MANAGER_IOCTL_MONITOR: {		co_manager_ioctl_monitor_t *params = (typeof(params))(io_buffer);		*return_size = sizeof(*params);		if (in_size < sizeof(*params)) {			co_debug_error("monitor ioctl too small! (%ld < %d)", in_size, sizeof(*params));			params->rc = CO_RC(MONITOR_NOT_LOADED);			break;		}				if (!opened->monitor) {			params->rc = CO_RC(MONITOR_NOT_LOADED);			break;		}				in_size -= sizeof(*params);		params->rc = co_monitor_ioctl(opened->monitor, params, in_size, 					      out_size, return_size, opened);		break;	}	default:		return CO_RC(ERROR);	}	return CO_RC(OK);}

⌨️ 快捷键说明

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