fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / s390 / kernel / vtime.c
index 63cdfec..21baaf5 100644 (file)
@@ -7,7 +7,6 @@
  *    Author(s): Jan Glauber <jan.glauber@de.ibm.com>
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
 #include <linux/notifier.h>
 #include <linux/kernel_stat.h>
 #include <linux/rcupdate.h>
+#include <linux/posix-timers.h>
 
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
+#include <asm/irq_regs.h>
 
-#define VTIMER_MAGIC (TIMER_MAGIC + 1)
 static ext_int_info_t ext_int_info_timer;
 DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
@@ -32,7 +32,7 @@ DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
  * Update process times based on virtual cpu times stored by entry.S
  * to the lowcore fields user_timer, system_timer & steal_clock.
  */
-void account_user_vtime(struct task_struct *tsk)
+void account_tick_vtime(struct task_struct *tsk)
 {
        cputime_t cputime;
        __u64 timer, clock;
@@ -69,6 +69,32 @@ void account_user_vtime(struct task_struct *tsk)
        if (rcu_pending(smp_processor_id()))
                rcu_check_callbacks(smp_processor_id(), rcu_user_flag);
        scheduler_tick();
+       run_posix_cpu_timers(tsk);
+}
+
+/*
+ * Update process times based on virtual cpu times stored by entry.S
+ * to the lowcore fields user_timer, system_timer & steal_clock.
+ */
+void account_vtime(struct task_struct *tsk)
+{
+       cputime_t cputime;
+       __u64 timer;
+
+       timer = S390_lowcore.last_update_timer;
+       asm volatile ("  STPT %0"    /* Store current cpu timer value */
+                     : "=m" (S390_lowcore.last_update_timer) );
+       S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
+
+       cputime = S390_lowcore.user_timer >> 12;
+       S390_lowcore.user_timer -= cputime << 12;
+       S390_lowcore.steal_clock -= cputime << 12;
+       account_user_time(tsk, cputime);
+
+       cputime =  S390_lowcore.system_timer >> 12;
+       S390_lowcore.system_timer -= cputime << 12;
+       S390_lowcore.steal_clock -= cputime << 12;
+       account_system_time(tsk, 0, cputime);
 }
 
 /*
@@ -120,12 +146,17 @@ static void start_cpu_timer(void)
        struct vtimer_queue *vt_list;
 
        vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
-       set_vtimer(vt_list->idle);
+
+       /* CPU timer interrupt is pending, don't reprogramm it */
+       if (vt_list->idle & 1LL<<63)
+               return;
+
+       if (!list_empty(&vt_list->list))
+               set_vtimer(vt_list->idle);
 }
 
 static void stop_cpu_timer(void)
 {
-       __u64 done;
        struct vtimer_queue *vt_list;
 
        vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
@@ -136,21 +167,17 @@ static void stop_cpu_timer(void)
                goto fire;
        }
 
-       /* store progress */
-       asm volatile ("STPT %0" : "=m" (done));
+       /* store the actual expire value */
+       asm volatile ("STPT %0" : "=m" (vt_list->idle));
 
        /*
-        * If done is negative we do not stop the CPU timer
-        * because we will get instantly an interrupt that
-        * will start the CPU timer again.
+        * If the CPU timer is negative we don't reprogramm
+        * it because we will get instantly an interrupt.
         */
-       if (done & 1LL<<63)
+       if (vt_list->idle & 1LL<<63)
                return;
-       else
-               vt_list->offset += vt_list->to_expire - done;
 
-       /* save the actual expire value */
-       vt_list->idle = done;
+       vt_list->offset += vt_list->to_expire - vt_list->idle;
 
        /*
         * We cannot halt the CPU timer, we just write a value that
@@ -182,11 +209,11 @@ static void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
  * Do the callback functions of expired vtimer events.
  * Called from within the interrupt handler.
  */
-static void do_callbacks(struct list_head *cb_list, struct pt_regs *regs)
+static void do_callbacks(struct list_head *cb_list)
 {
        struct vtimer_queue *vt_list;
        struct vtimer_list *event, *tmp;
-       void (*fn)(unsigned long, struct pt_regs*);
+       void (*fn)(unsigned long);
        unsigned long data;
 
        if (list_empty(cb_list))
@@ -197,7 +224,7 @@ static void do_callbacks(struct list_head *cb_list, struct pt_regs *regs)
        list_for_each_entry_safe(event, tmp, cb_list, entry) {
                fn = event->function;
                data = event->data;
-               fn(data, regs);
+               fn(data);
 
                if (!event->interval)
                        /* delete one shot timer */
@@ -215,7 +242,7 @@ static void do_callbacks(struct list_head *cb_list, struct pt_regs *regs)
 /*
  * Handler for the virtual CPU timer.
  */
-static void do_cpu_timer_interrupt(struct pt_regs *regs, __u16 error_code)
+static void do_cpu_timer_interrupt(__u16 error_code)
 {
        int cpu;
        __u64 next, delta;
@@ -248,7 +275,7 @@ static void do_cpu_timer_interrupt(struct pt_regs *regs, __u16 error_code)
                list_move_tail(&event->entry, &cb_list);
        }
        spin_unlock(&vt_list->lock);
-       do_callbacks(&cb_list, regs);
+       do_callbacks(&cb_list);
 
        /* next event is first in list */
        spin_lock(&vt_list->lock);
@@ -274,20 +301,12 @@ static void do_cpu_timer_interrupt(struct pt_regs *regs, __u16 error_code)
 
 void init_virt_timer(struct vtimer_list *timer)
 {
-       timer->magic = VTIMER_MAGIC;
        timer->function = NULL;
        INIT_LIST_HEAD(&timer->entry);
        spin_lock_init(&timer->lock);
 }
 EXPORT_SYMBOL(init_virt_timer);
 
-static inline int check_vtimer(struct vtimer_list *timer)
-{
-       if (timer->magic != VTIMER_MAGIC)
-               return -EINVAL;
-       return 0;
-}
-
 static inline int vtimer_pending(struct vtimer_list *timer)
 {
        return (!list_empty(&timer->entry));
@@ -337,13 +356,13 @@ static void internal_add_vtimer(struct vtimer_list *timer)
 
        set_vtimer(event->expires);
        spin_unlock_irqrestore(&vt_list->lock, flags);
-       /* release CPU aquired in prepare_vtimer or mod_virt_timer() */
+       /* release CPU acquired in prepare_vtimer or mod_virt_timer() */
        put_cpu();
 }
 
 static inline int prepare_vtimer(struct vtimer_list *timer)
 {
-       if (check_vtimer(timer) || !timer->function) {
+       if (!timer->function) {
                printk("add_virt_timer: uninitialized timer\n");
                return -EINVAL;
        }
@@ -411,7 +430,7 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
        unsigned long flags;
        int cpu;
 
-       if (check_vtimer(timer) || !timer->function) {
+       if (!timer->function) {
                printk("mod_virt_timer: uninitialized timer\n");
                return  -EINVAL;
        }
@@ -478,11 +497,6 @@ int del_virt_timer(struct vtimer_list *timer)
        unsigned long flags;
        struct vtimer_queue *vt_list;
 
-       if (check_vtimer(timer)) {
-               printk("del_virt_timer: timer not initialized\n");
-               return -EINVAL;
-       }
-
        /* check if timer is pending */
        if (!vtimer_pending(timer))
                return 0;