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

📄 dpm.c

📁 Linux 2.4 内核下动态电源管理(Dynamic Power Management)的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * destroy an operating point * Assumes dpm_sem is held and the opt is no longer needed *anywhere* *****************************************************************************/voiddestroy_opt(struct dpm_opt *opt){	list_del(&opt->list);	kfree(opt->name);	kfree(opt);}/***************************************************************************** * create a named class of operating points (to be used to map to an operating * state) *****************************************************************************/intdpm_create_class(const char *name, char **op_names, unsigned nops){	int i;	struct dpm_class *cls;	trace("in dpm_create_class for \"%s\"\n", name);	dpm_lock();	/* ensure class is not empty */	if (nops == 0) {		dpm_unlock();		return -EINVAL;	}	/* ensure name is unique */	list_find(cls, name, dpm_classes, struct dpm_class);	if (cls) {		dpm_unlock();		return -EEXIST;	}	/* get memory for class */	cls = (struct dpm_class *) kmalloc(sizeof (struct dpm_class), GFP_KERNEL);	if (!cls) {		dpm_unlock();		return -ENOMEM;	}	trace("%s @ 0x%08lx\n", name, (unsigned long)cls);	memset(cls, 0, sizeof (struct dpm_class));	/* get memory for array of pointers to operating points */	cls->ops =	    (struct dpm_opt **) kmalloc(nops * sizeof (struct dpm_opt *),					GFP_KERNEL);	if (!cls->ops) {		kfree(cls);		dpm_unlock();		return -ENOMEM;	}	/* get memory for class name */	cls->name = (char *) kmalloc(strlen(name) + 1, GFP_KERNEL);	if (!cls->name) {		kfree(cls->ops);		kfree(cls);		dpm_unlock();		return -ENOMEM;	}	/* find named op points and put their pointers in the class */	for (i = 0; i < nops; ++i) {		struct dpm_opt *opt;		list_find(opt, op_names[i], dpm_opts, struct dpm_opt);		if (!opt) {			kfree(cls->name);			kfree(cls->ops);			kfree(cls);			dpm_unlock();			return -ENOENT;		}		cls->ops[i] = opt;	}	strcpy(cls->name, name);	cls->nops = nops;	cls->opt = cls->ops[0];	/* add class to our list */	list_add(&cls->list, &dpm_classes);	dpm_unlock();	return 0;}/***************************************************************************** * destroy a class * Assumes dpm_sem is held and the class is no longer needed *anywhere* *****************************************************************************/voiddestroy_class(struct dpm_class *cls){	list_del(&cls->list);	kfree(cls->ops);	kfree(cls->name);	kfree(cls);}/********* * Fill out pointer with all classes for a policy */intdpm_get_classes_in_policy(char *name, char **class_names){        int i;        struct dpm_policy  *policy;        list_find(policy, name, dpm_policies, struct dpm_policy);        if (policy == NULL) {                return -EEXIST;        }        for(i = 0; i < DPM_STATES; i++) {                class_names[i] = policy->classes[i]->name;        }        return 0;}/********* * Fill out pointer with all currently installed policies */intdpm_get_all_policies(char **policies){        int i = 0;	struct list_head  * p;	list_for_each(p, &dpm_policies) {		policies[i++] = ((struct dpm_policy *) 				 list_entry(p, struct dpm_policy, list))->name;	}	return i;}/***************************************************************************** * create power policy *****************************************************************************/intdpm_create_policy(const char *name, char **class_names){	int i;	struct dpm_policy *policy;	trace("in dpm_install_policy for \"%s\" policy\n", name);	dpm_lock();	/* ensure unique name */	list_find(policy, name, dpm_policies, struct dpm_policy);	if (policy) {		dpm_unlock();		return -EEXIST;	}	/* get memory for policy */	policy =	    (struct dpm_policy *) kmalloc(sizeof (struct dpm_policy),					  GFP_KERNEL);	if (!policy) {		dpm_unlock();		return -ENOMEM;	}	trace("%s @ 0x%08lx\n", name, (unsigned long)policy);	memset(policy, 0, sizeof (struct dpm_policy));	/* get memory for policy name */	policy->name = (char *) kmalloc(strlen(name) + 1, GFP_KERNEL);	if (!policy->name) {		kfree(policy);		dpm_unlock();		return -ENOMEM;	}	/* initialize the policy */	for (i = 0; i < DPM_STATES; ++i) {		if (!class_names[i]) {			kfree(policy->name);			kfree(policy);			dpm_unlock();			return -EINVAL;		}		list_find(policy->classes[i],class_names[i],				dpm_classes, struct dpm_class);		if(!policy->classes[i]) {			kfree(policy->name);			kfree(policy);			dpm_unlock();			return -ENOENT;		}	}	strcpy(policy->name, name);	/* add policy to our list */	list_add(&policy->list, &dpm_policies);	trace("installed \"%s\" policy\n", name);	dpm_unlock();	return 0;}/***************************************************************************** * destroy a power policy * Assumes dpm_sem is held and the policy is no longer needed *anywhere* *****************************************************************************/voiddestroy_policy(struct dpm_policy *policy){	list_del(&policy->list);	kfree(policy->name);	kfree(policy);}/***************************************************************************** * uninstall power policy *****************************************************************************/intdpm_destroy_policy(const char *name){	struct dpm_policy *policy;	trace("processing destroy request for \"%s\"\n", name);	dpm_lock();	/* find the named policy */	list_find(policy, name, dpm_policies, struct dpm_policy);	if (!policy) {		dpm_unlock();		return -ENOENT;	}	/* can't uninstall active policy */	if (policy == dpm_active_policy) {		dpm_unlock();		return -EBUSY;	}	/* remove the policy */	destroy_policy(policy);	dpm_unlock();	trace("destroyed \"%s\" policy\n", name);	return 0;}/* * set active power policy */intdpm_set_policy(const char *name){	int i, j;	struct dpm_policy *new_p;	struct dpm_class *cls;	trace("in dpm_set_policy for \"%s\" policy\n", name);	dpm_lock();	list_find(new_p, name, dpm_policies, struct dpm_policy);	if (!new_p) {		dpm_trace(DPM_TRACE_SET_POLICY, name, -ENOENT);		dpm_unlock();		return -ENOENT;	/* invalid name */	}	if (new_p == dpm_active_policy) {		dpm_trace(DPM_TRACE_SET_POLICY, name, 0);		trace("\"%s\" policy already activated\n", name);		dpm_unlock();		return 0;	}	/* find best unconstrained operating point for each operating state */	for (i = 0; i < DPM_STATES; ++i) {		cls = new_p->classes[i];		cls->opt = 0;		for (j = 0; j < cls->nops; ++j) {			if (!cls->ops[j]->constrained) {				cls->opt = cls->ops[j];				break;			}		}		if (!cls->opt) {			dpm_trace(DPM_TRACE_SET_POLICY, name, -EPERM);			dpm_unlock();			return -EPERM;		}	}#ifdef CONFIG_DPM_STATS	if (dpm_active_policy)		dpm_update_stats(&new_p->stats, &dpm_active_policy->stats);	else {		new_p->stats.start_time = dpm_md_time();		new_p->stats.end_time = 0;		new_p->stats.count++;	}#endif	dpm_active_policy = new_p;	dpm_enabled = 1;	/* Start the policy synchronously */	mb();	dpm_trace(DPM_TRACE_SET_POLICY, name, 0);	dpm_set_opt_sync();	dpm_unlock();	return 0;}/***************************************************************************** * set a task state *****************************************************************************/intdpm_set_task_state(pid_t pid, dpm_state_t task_state){	struct task_struct *p;	if (task_state == -(DPM_TASK_STATE_LIMIT + 1)) 		task_state = DPM_NO_STATE;	else if (abs(task_state) > DPM_TASK_STATE_LIMIT) {		dpm_trace(DPM_TRACE_SET_TASK_STATE, pid, task_state, -EINVAL);		return -EINVAL;	} else 		task_state += DPM_TASK_STATE;	read_lock(&tasklist_lock);	if (pid == 0)		p = current;	else		p = find_task_by_pid(pid);	if (!p) {		read_unlock(&tasklist_lock);		dpm_trace(DPM_TRACE_SET_TASK_STATE, pid, task_state, -ENOENT);		return -ENOENT;	}	p->dpm_state = task_state;	read_unlock(&tasklist_lock);	dpm_trace(DPM_TRACE_SET_TASK_STATE, pid, task_state, 0);	if (pid == 0)		dpm_set_os(p->dpm_state);	return 0;}/***************************************************************************** * set a raw op state *****************************************************************************/intdpm_set_op_state(const char *name){	int op_state;	for (op_state = 0; op_state < DPM_STATES; op_state++)		if (strcmp(dpm_state_names[op_state], name) == 0) {			dpm_set_os(op_state);			return 0;		}	return -ENOENT;}/***************************************************************************** * get a task state *****************************************************************************/intdpm_get_task_state(pid_t pid, dpm_state_t * task_state){	struct task_struct *p;	read_lock(&tasklist_lock);	if (pid == 0)		p = current;	else		p = find_task_by_pid(pid);	if (!p) {		read_unlock(&tasklist_lock);		return -ENOENT;	}	if (p->dpm_state == DPM_NO_STATE)		*task_state = -(DPM_TASK_STATE_LIMIT + 1);	else		*task_state = p->dpm_state - DPM_TASK_STATE;	read_unlock(&tasklist_lock);	return 0;}/***************************************************************************** * terminate the DPM *****************************************************************************/intdpm_terminate(void){	trace("in dpm_terminate\n");	if (!dpm_initialized)		return 0;	dpm_lock();	dpm_initialized = 0;	dpm_enabled = 0;	dpm_active_opt = NULL;	/* destroy all entities */	while (!list_empty(&dpm_policies))		destroy_policy(list_entry			       (dpm_policies.next, struct dpm_policy, list));	while (!list_empty(&dpm_classes))		destroy_class(list_entry(dpm_classes.next, struct dpm_class,					 list));	while (!list_empty(&dpm_opts))		destroy_opt(list_entry(dpm_opts.next, struct dpm_opt, list));	mb();	dpm_unlock();	trace("DPM is now terminated\n");	return 0;}EXPORT_SYMBOL(dpm_init);EXPORT_SYMBOL(dpm_terminate);EXPORT_SYMBOL(dpm_disable);EXPORT_SYMBOL(dpm_enable);EXPORT_SYMBOL(dpm_create_opt);EXPORT_SYMBOL(dpm_create_class);EXPORT_SYMBOL(dpm_create_policy);EXPORT_SYMBOL(dpm_destroy_policy);EXPORT_SYMBOL(dpm_set_policy);/* ?? Needed in kernel mode ?? EXPORT_SYMBOL(dpm_get_policy);*/EXPORT_SYMBOL(dpm_set_task_state);EXPORT_SYMBOL(dpm_get_task_state);extern void *sys_call_table[];/* until we get a permanent syscall number */#ifdef __NR_SYSCALL_BASEstatic int sys_dpm_nr = __NR_sys_dpm - __NR_SYSCALL_BASE;#elsestatic int sys_dpm_nr = __NR_sys_dpm;#endif/**************************************************************************** * install dynamic power policy support ****************************************************************************/intdpm_init_module(void){	extern asmlinkage long sys_ni_syscall(void);	/* ensure syscall slot is available */	if (sys_call_table[sys_dpm_nr] != sys_ni_syscall) {		printk("DPM syscall already taken, system call #%d disabled.\n",		       sys_dpm_nr);		sys_call_table[sys_dpm_nr] = sys_ni_syscall;	} else {		/* install our syscall */		sys_call_table[sys_dpm_nr] = sys_dpm;	}#ifdef CONFIG_PROC_FS	{		void dpm_proc_init(void);		dpm_proc_init();	}#endif	dpm_md_init();	trace("DPM is now installed\n");	return 0;}/**************************************************************************** * remove dynamic power policy support ****************************************************************************/voiddpm_exit_module(void){	/* disable power management policy system */	dpm_terminate();	dpm_md_cleanup();	/* uninstall our syscall */	sys_call_table[sys_dpm_nr] = sys_call_table[0];#ifdef CONFIG_PROC_FS	{		void dpm_proc_cleanup(void);		dpm_proc_cleanup();	}#endif	trace("DPM module is now unloaded\n");}/**************************************************************************** * LTT ****************************************************************************/#ifdef CONFIG_TRACEvoiddpm_ltt_trace_init(){	int	k;	for (k = 0; k < DPM_STATES; k++) {		TRACE_DEFINE_NAME(TRACE_EV_DEFINE_NAME_DPM_STATE,					k, 0, dpm_state_names[k]);	}}#endif#ifdef MODULEmodule_init(dpm_init_module);module_exit(dpm_exit_module);#else__initcall(dpm_init_module);#endif/* * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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