# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID d3279720963294702936ecb45d49cd4db8b5caaf
# Parent c055d76ec55922d75de300bff74dc413319a0d43
Add missing renamed files. Oops.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r c055d76ec559 -r d32797209632 xen/common/timer.c
--- /dev/null Thu Jan 12 22:39:14 2006
+++ b/xen/common/timer.c Thu Jan 12 23:16:07 2006
@@ -0,0 +1,288 @@
+/******************************************************************************
+ * timer.c
+ *
+ * Copyright (c) 2002-2003 Rolf Neugebauer
+ * Copyright (c) 2002-2005 K A Fraser
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/types.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+#include <xen/lib.h>
+#include <xen/smp.h>
+#include <xen/perfc.h>
+#include <xen/time.h>
+#include <xen/softirq.h>
+#include <xen/timer.h>
+#include <xen/keyhandler.h>
+#include <asm/system.h>
+#include <asm/desc.h>
+
+/*
+ * We pull handlers off the timer list this far in future,
+ * rather than reprogramming the time hardware.
+ */
+#define TIMER_SLOP (50*1000) /* ns */
+
+struct timers {
+ spinlock_t lock;
+ struct timer **heap;
+} __cacheline_aligned;
+
+struct timers timers[NR_CPUS];
+
+extern int reprogram_timer(s_time_t timeout);
+
+/****************************************************************************
+ * HEAP OPERATIONS.
+ */
+
+#define GET_HEAP_SIZE(_h) ((int)(((u16 *)(_h))[0]))
+#define SET_HEAP_SIZE(_h,_v) (((u16 *)(_h))[0] = (u16)(_v))
+
+#define GET_HEAP_LIMIT(_h) ((int)(((u16 *)(_h))[1]))
+#define SET_HEAP_LIMIT(_h,_v) (((u16 *)(_h))[1] = (u16)(_v))
+
+/* Sink down element @pos of @heap. */
+static void down_heap(struct timer **heap, int pos)
+{
+ int sz = GET_HEAP_SIZE(heap), nxt;
+ struct timer *t = heap[pos];
+
+ while ( (nxt = (pos << 1)) <= sz )
+ {
+ if ( ((nxt+1) <= sz) && (heap[nxt+1]->expires < heap[nxt]->expires) )
+ nxt++;
+ if ( heap[nxt]->expires > t->expires )
+ break;
+ heap[pos] = heap[nxt];
+ heap[pos]->heap_offset = pos;
+ pos = nxt;
+ }
+
+ heap[pos] = t;
+ t->heap_offset = pos;
+}
+
+/* Float element @pos up @heap. */
+static void up_heap(struct timer **heap, int pos)
+{
+ struct timer *t = heap[pos];
+
+ while ( (pos > 1) && (t->expires < heap[pos>>1]->expires) )
+ {
+ heap[pos] = heap[pos>>1];
+ heap[pos]->heap_offset = pos;
+ pos >>= 1;
+ }
+
+ heap[pos] = t;
+ t->heap_offset = pos;
+}
+
+
+/* Delete @t from @heap. Return TRUE if new top of heap. */
+static int remove_entry(struct timer **heap, struct timer *t)
+{
+ int sz = GET_HEAP_SIZE(heap);
+ int pos = t->heap_offset;
+
+ t->heap_offset = 0;
+
+ if ( unlikely(pos == sz) )
+ {
+ SET_HEAP_SIZE(heap, sz-1);
+ goto out;
+ }
+
+ heap[pos] = heap[sz];
+ heap[pos]->heap_offset = pos;
+
+ SET_HEAP_SIZE(heap, --sz);
+
+ if ( (pos > 1) && (heap[pos]->expires < heap[pos>>1]->expires) )
+ up_heap(heap, pos);
+ else
+ down_heap(heap, pos);
+
+ out:
+ return (pos == 1);
+}
+
+
+/* Add new entry @t to @heap. Return TRUE if new top of heap. */
+static int add_entry(struct timer ***pheap, struct timer *t)
+{
+ struct timer **heap = *pheap;
+ int sz = GET_HEAP_SIZE(heap);
+
+ /* Copy the heap if it is full. */
+ if ( unlikely(sz == GET_HEAP_LIMIT(heap)) )
+ {
+ /* old_limit == (2^n)-1; new_limit == (2^(n+4))-1 */
+ int old_limit = GET_HEAP_LIMIT(heap);
+ int new_limit = ((old_limit + 1) << 4) - 1;
+ heap = xmalloc_array(struct timer *, new_limit + 1);
+ BUG_ON(heap == NULL);
+ memcpy(heap, *pheap, (old_limit + 1) * sizeof(*heap));
+ SET_HEAP_LIMIT(heap, new_limit);
+ if ( old_limit != 0 )
+ xfree(*pheap);
+ *pheap = heap;
+ }
+
+ SET_HEAP_SIZE(heap, ++sz);
+ heap[sz] = t;
+ t->heap_offset = sz;
+ up_heap(heap, sz);
+ return (t->heap_offset == 1);
+}
+
+
+/****************************************************************************
+ * TIMER OPERATIONS.
+ */
+
+static inline void __add_timer(struct timer *timer)
+{
+ int cpu = timer->cpu;
+ if ( add_entry(&timers[cpu].heap, timer) )
+ cpu_raise_softirq(cpu, TIMER_SOFTIRQ);
+}
+
+
+static inline void __stop_timer(struct timer *timer)
+{
+ int cpu = timer->cpu;
+ if ( remove_entry(timers[cpu].heap, timer) )
+ cpu_raise_softirq(cpu, TIMER_SOFTIRQ);
+}
+
+
+void set_timer(struct timer *timer, s_time_t expires)
+{
+ int cpu = timer->cpu;
+ unsigned long flags;
+
+ spin_lock_irqsave(&timers[cpu].lock, flags);
+ ASSERT(timer != NULL);
+ if ( active_timer(timer) )
+ __stop_timer(timer);
+ timer->expires = expires;
+ __add_timer(timer);
+ spin_unlock_irqrestore(&timers[cpu].lock, flags);
+}
+
+
+void stop_timer(struct timer *timer)
+{
+ int cpu = timer->cpu;
+ unsigned long flags;
+
+ spin_lock_irqsave(&timers[cpu].lock, flags);
+ ASSERT(timer != NULL);
+ if ( active_timer(timer) )
+ __stop_timer(timer);
+ spin_unlock_irqrestore(&timers[cpu].lock, flags);
+}
+
+
+static void timer_softirq_action(void)
+{
+ int cpu = smp_processor_id();
+ struct timer *t, **heap;
+ s_time_t now;
+ void (*fn)(void *);
+ void *data;
+
+ spin_lock_irq(&timers[cpu].lock);
+
+ do {
+ heap = timers[cpu].heap;
+ now = NOW();
+
+ while ( (GET_HEAP_SIZE(heap) != 0) &&
+ ((t = heap[1])->expires < (now + TIMER_SLOP)) )
+ {
+ remove_entry(heap, t);
+
+ fn = t->function;
+ data = t->data;
+
+ if ( fn != NULL )
+ {
+ spin_unlock_irq(&timers[cpu].lock);
+ (*fn)(data);
+ spin_lock_irq(&timers[cpu].lock);
+ }
+
+ /* Heap may have grown while the lock was released. */
+ heap = timers[cpu].heap;
+ }
+ }
+ while ( !reprogram_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) );
+
+ spin_unlock_irq(&timers[cpu].lock);
+}
+
+
+static void dump_timerq(unsigned char key)
+{
+ struct timer *t;
+ unsigned long flags;
+ s_time_t now = NOW();
+ int i, j;
+
+ printk("Dumping timer queues: NOW=0x%08X%08X\n",
+ (u32)(now>>32), (u32)now);
+
+ for_each_online_cpu( i )
+ {
+ printk("CPU[%02d] ", i);
+ spin_lock_irqsave(&timers[i].lock, flags);
+ for ( j = 1; j <= GET_HEAP_SIZE(timers[i].heap); j++ )
+ {
+ t = timers[i].heap[j];
+ printk (" %d : %p ex=0x%08X%08X %p\n",
+ j, t, (u32)(t->expires>>32), (u32)t->expires, t->data);
+ }
+ spin_unlock_irqrestore(&timers[i].lock, flags);
+ printk("\n");
+ }
+}
+
+
+void __init timer_init(void)
+{
+ static struct timer *dummy_heap;
+ int i;
+
+ open_softirq(TIMER_SOFTIRQ, timer_softirq_action);
+
+ /*
+ * All CPUs initially share an empty dummy heap. Only those CPUs that
+ * are brought online will be dynamically allocated their own heap.
+ */
+ SET_HEAP_SIZE(&dummy_heap, 0);
+ SET_HEAP_LIMIT(&dummy_heap, 0);
+
+ for ( i = 0; i < NR_CPUS; i++ )
+ {
+ spin_lock_init(&timers[i].lock);
+ timers[i].heap = &dummy_heap;
+ }
+
+ register_keyhandler('a', dump_timerq, "dump timer queues");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r c055d76ec559 -r d32797209632 xen/include/xen/timer.h
--- /dev/null Thu Jan 12 22:39:14 2006
+++ b/xen/include/xen/timer.h Thu Jan 12 23:16:07 2006
@@ -0,0 +1,81 @@
+/******************************************************************************
+ * timer.h
+ *
+ * Copyright (c) 2002-2003 Rolf Neugebauer
+ * Copyright (c) 2002-2005 K A Fraser
+ */
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+#include <xen/spinlock.h>
+#include <xen/time.h>
+#include <xen/string.h>
+
+struct timer {
+ /* System time expiry value (nanoseconds since boot). */
+ s_time_t expires;
+ /* CPU on which this timer will be installed and executed. */
+ unsigned int cpu;
+ /* On expiry, '(*function)(data)' will be executed in softirq context. */
+ void (*function)(void *);
+ void *data;
+ /* Timer-heap offset. */
+ unsigned int heap_offset;
+};
+
+/*
+ * All functions below can be called for any CPU from any CPU in any context.
+ */
+
+/* Returns TRUE if the given timer is on a timer list. */
+static __inline__ int active_timer(struct timer *timer)
+{
+ return (timer->heap_offset != 0);
+}
+
+/*
+ * It initialises the static fields of the timer structure.
+ * It can be called multiple times to reinitialise a single (inactive) timer.
+ */
+static __inline__ void init_timer(
+ struct timer *timer,
+ void (*function)(void *),
+ void *data,
+ unsigned int cpu)
+{
+ memset(timer, 0, sizeof(*timer));
+ timer->function = function;
+ timer->data = data;
+ timer->cpu = cpu;
+}
+
+/*
+ * Set the expiry time and activate a timer (which must previously have been
+ * initialised by init_timer).
+ */
+extern void set_timer(struct timer *timer, s_time_t expires);
+
+/*
+ * Deactivate a timer (which must previously have been initialised by
+ * init_timer). This function has no effect if the timer is not currently
+ * active.
+ */
+extern void stop_timer(struct timer *timer);
+
+/*
+ * Initialisation. Must be called before any other timer function.
+ */
+extern void timer_init(void);
+
+#endif /* _TIMER_H_ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|