lkml.org 
[lkml]   [2007]   [Aug]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH/RFC 3/4]Introduce "account modifiers" mechanism
    [PATCH 3/3] introduce "account modifiers" mechanism in the kernel allowing a
    module to modify the collected accounting for a given task. This implementation
    is based on the "preempt_notifier". "account_system_time()" and
    "account_user_time()" can call functions registered by a module to modify the
    cputime value.

    Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
    --
    ------------- Laurent.Vivier@bull.net --------------
    "Software is hard" - Donald Knuth
    Index: kvm/include/linux/sched.h
    ===================================================================
    --- kvm.orig/include/linux/sched.h 2007-08-16 15:23:27.000000000 +0200
    +++ kvm/include/linux/sched.h 2007-08-16 15:23:41.000000000 +0200
    @@ -955,6 +955,10 @@
    /* list of struct preempt_notifier: */
    struct hlist_head preempt_notifiers;
    #endif
    +#ifdef CONFIG_ACCOUNT_MODIFIERS
    + /* list of struct account_modifiers: */
    + struct hlist_head account_modifiers;
    +#endif

    unsigned short ioprio;
    #ifdef CONFIG_BLK_DEV_IO_TRACE
    @@ -1873,6 +1877,31 @@
    }
    #endif

    +#ifdef CONFIG_ACCOUNT_MODIFIERS
    +struct account_modifier;
    +struct account_ops {
    + cputime_t (*user_time)(struct account_modifier *,
    + struct task_struct *, cputime_t );
    + cputime_t (*system_time)(struct account_modifier *,
    + struct task_struct *, int, cputime_t);
    +};
    +
    +struct account_modifier {
    + struct hlist_node link;
    + struct account_ops *ops;
    +};
    +
    +void account_modifier_register(struct account_modifier *modifier);
    +void account_modifier_unregister(struct account_modifier *modifier);
    +
    +static inline void account_modifier_init(struct account_modifier *modifier,
    + struct account_ops *ops)
    +{
    + INIT_HLIST_NODE(&modifier->link);
    + modifier->ops = ops;
    +}
    +#endif
    +
    #endif /* __KERNEL__ */

    #endif
    Index: kvm/kernel/sched.c
    ===================================================================
    --- kvm.orig/kernel/sched.c 2007-08-16 15:15:33.000000000 +0200
    +++ kvm/kernel/sched.c 2007-08-16 15:23:28.000000000 +0200
    @@ -1593,6 +1593,9 @@
    #ifdef CONFIG_PREEMPT_NOTIFIERS
    INIT_HLIST_HEAD(&p->preempt_notifiers);
    #endif
    +#ifdef CONFIG_ACCOUNT_MODIFIERS
    + INIT_HLIST_HEAD(&p->account_modifiers);
    +#endif

    /*
    * We mark the process as running here, but have not actually
    @@ -1731,6 +1734,62 @@
    }

    #endif
    +#ifdef CONFIG_ACCOUNT_MODIFIERS
    +
    +void account_modifier_register(struct account_modifier *modifier)
    +{
    + hlist_add_head(&modifier->link, &current->account_modifiers);
    +}
    +EXPORT_SYMBOL_GPL(account_modifier_register);
    +
    +void account_modifier_unregister(struct account_modifier *modifier)
    +{
    + hlist_del(&modifier->link);
    +}
    +EXPORT_SYMBOL_GPL(account_modifier_unregister);
    +
    +static cputime_t fire_user_time_account_modifiers(struct task_struct *curr,
    + cputime_t cputime)
    +{
    + struct account_modifier *modifier;
    + struct hlist_node *node;
    +
    + hlist_for_each_entry(modifier, node, &curr->account_modifiers, link)
    + if (modifier->ops->user_time)
    + cputime = modifier->ops->user_time(modifier,
    + curr, cputime);
    + return cputime;
    +}
    +
    +static cputime_t fire_system_time_account_modifiers(struct task_struct *curr,
    + int hardirq_offset,
    + cputime_t cputime)
    +{
    + struct account_modifier *modifier;
    + struct hlist_node *node;
    +
    + hlist_for_each_entry(modifier, node, &curr->account_modifiers, link)
    + if (modifier->ops->system_time)
    + cputime = modifier->ops->system_time(modifier,
    + curr, hardirq_offset, cputime);
    + return cputime;
    +}
    +
    +#else
    +
    +static inline cputime_t fire_user_time_account_modifiers(struct task_struct *curr, cputime_t cputime)
    +{
    + return cputime;
    +}
    +
    +static inline cputime_t fire_system_time_account_modifiers(struct task_struct *curr,
    + int hardirq_offset,
    + cputime_t cputime)
    +{
    + return cputime;
    +}
    +
    +#endif

    /**
    * prepare_task_switch - prepare to switch tasks
    @@ -3223,6 +3282,8 @@
    struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
    cputime64_t tmp;

    + cputime = fire_user_time_account_modifiers(p, cputime);
    +
    p->utime = cputime_add(p->utime, cputime);

    /* Add user time to cpustat. */
    @@ -3246,6 +3307,8 @@
    struct rq *rq = this_rq();
    cputime64_t tmp;

    + cputime = fire_system_time_account_modifiers(p,hardirq_offset, cputime);
    +
    p->stime = cputime_add(p->stime, cputime);

    /* Add system time to cpustat. */
    @@ -6522,6 +6585,9 @@
    #ifdef CONFIG_PREEMPT_NOTIFIERS
    INIT_HLIST_HEAD(&init_task.preempt_notifiers);
    #endif
    +#ifdef CONFIG_ACCOUNT_MODIFIERS
    + INIT_HLIST_HEAD(&init_task.account_modifiers);
    +#endif

    #ifdef CONFIG_SMP
    nr_cpu_ids = highest_cpu + 1;
    \
     
     \ /
      Last update: 2007-08-16 18:01    [W:3.967 / U:0.452 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site