From: Daniel P. <d.p...@gm...> - 2005-04-13 21:38:33
|
Hi, Here we have a patch that brings the possibility to statically assign a=20 given task (application) to a dpm task-state. If we want mozilla to run in task state "task-2" we make like this: #echo -n "assign mozilla task-2" > /sys/dpm/task_assignment So, whenever mozilla becomes a task it will go to "task-2" task state. if we issue: #cat /sys/dpm/task_assignment=20 We have: #DPM task assignment - [ mozilla] [task-2]. And all other assigned applications. This enables the possibility of assign applications to certain tasks states= =20 in boot scripts. It makes dpm usage easier from the user point of view. This patch should be applied over: 2.6.11 (www.kernel.org <http://www.kernel.org>) patch-2.6.11-omap1 (www.muru.com <http://www.muru.com>) dpm-2.6.11.patch (http://sourceforge.net/projects/dynamicpower/) dpm-2.6.10-omap.patch (http://sourceforge.net/projects/dynamicpower/) It was tested in OMAP Innovator1510.=20 Tests and comments are very welcome. Daniel Petrini -------------------------- 10LE - Linux Nokia Institute of Tecnology - INdT Manaus - Brazil ------------------------------------------------------------------- diff -uprN linux-2.6.11-vanilla-dpm-2611-orig/drivers/dpm/dpm.c=20 linux-2.6.11-vanilla-dpm-2611/drivers/dpm/dpm.c --- linux-2.6.11-vanilla-dpm-2611-orig/drivers/dpm/dpm.c 2005-04-13 08:36: 28.000000000 -0400 +++ linux-2.6.11-vanilla-dpm-2611/drivers/dpm/dpm.c 2005-04-13 16:06: 21.000000000 -0400 @@ -175,6 +175,9 @@ LIST_HEAD(dpm_policies); LIST_HEAD(dpm_classes); LIST_HEAD(dpm_opts); +/* currently installed task assignments*/ +LIST_HEAD(dpm_task_assignments); + DECLARE_MUTEX(_dpm_lock); spinlock_t dpm_policy_lock =3D SPIN_LOCK_UNLOCKED; @@ -498,6 +501,47 @@ dpm_set_os(dpm_state_t new_state) EXPORT_SYMBOL(dpm_set_os); /**************************************************************************= *** + * verify task assignment + *=20 + * Function to verify to which task-state a starting task will be assigned= . +=20 ***************************************************************************= */ +int +dpm_verify_task_assignment(struct task_struct *task) +{ + struct list_head *p; + int task_state; +=20 + if (dpm_lock_interruptible()) + return -ERESTARTSYS; + + /* Searches this task cmdline at /sys/dpm/task_assignment entry */ +=20 + /* Assign it or default case not found */ + list_for_each(p, &dpm_task_assignments)=20 + /* If the newly created process name matches task assignm. ..*/ + if (strcmp(task->comm, ((struct dpm_task_assignment *)=20 + list_entry(p, struct dpm_task_assignment, list))->name) =3D=3D 0)=20 + /* Retrieve the task state of that process */ + for (task_state =3D DPM_TASK_STATE - DPM_TASK_STATE_LIMIT; + task_state <=3D DPM_TASK_STATE + DPM_TASK_STATE_LIMIT;=20 + task_state++) +=20 + if (strcmp(dpm_state_names[task_state],((struct dpm_task_assignment*) + list_entry(p, struct dpm_task_assignment, list))->state_name ) =3D=3D 0){ + task->dpm_state =3D task_state; + return 0; + } +=20 + /* Not listed - default behavior */ + task->dpm_state =3D DPM_TASK_STATE; + + dpm_unlock(); + + return 0; +} +EXPORT_SYMBOL(dpm_verify_task_assignment); + +/*************************************************************************= **** * initialize the DPM ***************************************************************************= **/ int @@ -1003,6 +1047,79 @@ dpm_set_op_state(const char *name) return -ENOENT; } +/*************************************************************************= **** + * Creation and destruction of task assignment data +=20 ***************************************************************************= **/ +int +_dpm_create_task_assignment(const char *app_name, const char *task_state, + struct dpm_task_assignment **p) +{ + struct dpm_task_assignment *tsk_ast; + + /* get the memory for it */ + if (!=20 + (tsk_ast =3D (struct dpm_task_assignment *) kmalloc=20 + (sizeof(struct dpm_task_assignment), GFP_KERNEL))) { + return -ENOMEM; + } + + memset(tsk_ast, 0, sizeof(struct dpm_task_assignment)); + + /* Allocate and store the strings*/ + if (!(tsk_ast->name =3D + (char *) kmalloc(strlen(app_name) + 1, GFP_KERNEL ))) { + kfree(tsk_ast); + return -ENOMEM; + } + strcpy (tsk_ast->name, app_name); + + if (!(tsk_ast->state_name =3D (char *) kmalloc(strlen(task_state) + 1, + GFP_KERNEL ))) { + kfree(tsk_ast); + return -ENOMEM; + } + strcpy(tsk_ast->state_name, task_state); + + INIT_LIST_HEAD(&tsk_ast->list); + *p =3D tsk_ast; + + return 0; +} + +int=20 +dpm_create_task_assignment(const char *app_name, const char *task_state) +{ + struct dpm_task_assignment * tsk_ast; + int ret; + + dpm_lock(); +=20 + /* ensure unique application name entry */ + list_find(tsk_ast, app_name, dpm_task_assignments,=20 + struct dpm_task_assignment); + if (tsk_ast) { + dpm_unlock(); + return -EEXIST; + } +=20 + /* create the assignment */ + ret =3D _dpm_create_task_assignment(app_name, task_state, &tsk_ast); + + if (!ret) + list_add(&tsk_ast->list, &dpm_task_assignments); + + dpm_unlock(); + return ret; +} + +void +destroy_task_assignment(struct dpm_task_assignment *tsk_ast) +{ + list_del(&tsk_ast->list); + kfree(tsk_ast->name); + kfree(tsk_ast->state_name); + kfree(tsk_ast); +} /**************************************************************************= *** * terminate the DPM @@ -1033,8 +1150,11 @@ dynamicpower_terminate(void) while (!list_empty(&dpm_classes)) destroy_class(list_entry(dpm_classes.next, struct dpm_class, list)); - - + while (!list_empty(&dpm_task_assignments)) + destroy_task_assignment(list_entry(dpm_task_assignments.next, + struct dpm_task_assignment, list)); +=20 +=20 mb(); dpm_unlock(); diff -uprN linux-2.6.11-vanilla-dpm-2611-orig/drivers/dpm/dpm-ui.c=20 linux-2.6.11-vanilla-dpm-2611/drivers/dpm/dpm-ui.c --- linux-2.6.11-vanilla-dpm-2611-orig/drivers/dpm/dpm-ui.c 2005-04-13=20 08:36:28.000000000 -0400 +++ linux-2.6.11-vanilla-dpm-2611/drivers/dpm/dpm-ui.c 2005-04-13 16:07: 44.000000000 -0400 @@ -120,8 +120,88 @@ static ssize_t dpm_control_store(struct=20 dpm_attr(control,dpm_control); +/* + * Reads task-assignment + */ + +static ssize_t dpm_task_assignment_show(struct subsystem * subsys, char *= =20 buf) +{ + ssize_t len =3D 0; + struct list_head *p; + + if (dpm_lock_interruptible()) + return -ERESTARTSYS; + + if (!dpm_enabled) { + len +=3D sprintf(buf, "DPM disabled\n"); + } else { +=20 + list_for_each(p, &dpm_task_assignments) { + printk("DPM task assignment - [%10s] [%6s].\n", + ((struct dpm_task_assignment *)=20 + list_entry(p, struct dpm_task_assignment, list))->name, + ((struct dpm_task_assignment *) + list_entry(p, struct dpm_task_assignment, list))->state_name ); + } +=20 + } + + dpm_unlock(); + return len; +} + +/*************************************************************************= **** + * Treats sys entries and stores properly. writing in=20 /sys/dpm/task_assignment + * Receives something like "assign mozilla task-2" +=20 ***************************************************************************= **/ +static ssize_t dpm_task_assignment_store(struct subsystem * subsys,=20 + const char * buf, size_t n) +{ + int error =3D 0; + char *tbuf =3D NULL; + char *token[MAXTOKENS]; + int ntoks =3D tokenizer(&tbuf, buf, n, (char **) &token, MAXTOKENS); + int task_state; + int valid_input =3D 0; +=20 + if (ntoks <=3D 0) { + error =3D ntoks; + goto out; + } + + if (strcmp(token[0],"assign") =3D=3D 0) { + + /* Consistency check */ + for (task_state =3D DPM_TASK_STATE - DPM_TASK_STATE_LIMIT; + task_state <=3D DPM_TASK_STATE + DPM_TASK_STATE_LIMIT;=20 + task_state++) + if (strcmp(dpm_state_names[task_state], token[2]) =3D=3D 0) { + printk ("Associate [%10s] <-> [%6s]\n", token[1], token[2]); + error =3D dpm_create_task_assignment(token[1], token[2]); + valid_input =3D 1; + }=20 + if (!valid_input) { + printk ("DPM - Invalid input\n"); + error =3D -EINVAL; + goto out; + } +=20 +=20 + } else + error =3D -EINVAL; + + out: + if (tbuf) + kfree(tbuf); + return error ? error : n; +=20 +} + +dpm_attr(task_assignment,dpm_task_assignment); + static struct attribute * g[] =3D { &dpm_control_attr.attr, + &dpm_task_assignment_attr.attr,=20 NULL, }; diff -uprN linux-2.6.11-vanilla-dpm-2611-orig/fs/exec.c=20 linux-2.6.11-vanilla-dpm-2611/fs/exec.c --- linux-2.6.11-vanilla-dpm-2611-orig/fs/exec.c 2005-04-13 08:36: 28.000000000 -0400 +++ linux-2.6.11-vanilla-dpm-2611/fs/exec.c 2005-04-13 16:08:23.000000000-0= 400 @@ -48,6 +48,7 @@ #include <linux/syscalls.h> #include <linux/rmap.h> #include <linux/acct.h> +#include <linux/dpm.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -1194,6 +1195,9 @@ int do_execve(char * filename, acct_update_integrals(); update_mem_hiwater(); kfree(bprm); + + dpm_verify_task_assignment(current); +=20 return retval; } diff -uprN linux-2.6.11-vanilla-dpm-2611-orig/include/linux/dpm.h=20 linux-2.6.11-vanilla-dpm-2611/include/linux/dpm.h --- linux-2.6.11-vanilla-dpm-2611-orig/include/linux/dpm.h 2005-04-13 08:36= : 29.000000000 -0400 +++ linux-2.6.11-vanilla-dpm-2611/include/linux/dpm.h 2005-04-13 16:08: 08.000000000 -0400 @@ -166,6 +166,14 @@ struct dpm_policy { struct dpm_stats stats; /* statistics */ }; +/* Internal representation of the application and task-states relation*/ +struct dpm_task_assignment { + char *name; /* User space app*/ + char *state_name; /* DPM state name */ + struct list_head list; /* Store assignements */ +}; + + /* * internal use utility functions for use by DPM */ @@ -277,6 +285,9 @@ extern void dpm_sysfs_destroy_op(struct=20 extern int proc_pid_dpm_read(struct task_struct*,char*); +/* Task assignment */ +int dpm_verify_task_assignment(struct task_struct *task); +int dpm_create_task_assignment(const char *app_name, const char=20 *task_state); /* * global data for power management system @@ -286,6 +297,9 @@ extern int proc_pid_dpm_read(struct task extern struct list_head dpm_policies; extern struct list_head dpm_classes; extern struct list_head dpm_opts; + +extern struct list_head dpm_task_assignments; + extern struct semaphore dpm_policy_sem; extern spinlock_t dpm_policy_lock; |