direct-io.hg
changeset 8579:d32797209632
Add missing renamed files. Oops.
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Fri Jan 13 00:16:07 2006 +0100 (2006-01-13) |
parents | c055d76ec559 |
children | cc2f35c83b4c |
files | xen/common/timer.c xen/include/xen/timer.h |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xen/common/timer.c Fri Jan 13 00:16:07 2006 +0100 1.3 @@ -0,0 +1,288 @@ 1.4 +/****************************************************************************** 1.5 + * timer.c 1.6 + * 1.7 + * Copyright (c) 2002-2003 Rolf Neugebauer 1.8 + * Copyright (c) 2002-2005 K A Fraser 1.9 + */ 1.10 + 1.11 +#include <xen/config.h> 1.12 +#include <xen/init.h> 1.13 +#include <xen/types.h> 1.14 +#include <xen/errno.h> 1.15 +#include <xen/sched.h> 1.16 +#include <xen/lib.h> 1.17 +#include <xen/smp.h> 1.18 +#include <xen/perfc.h> 1.19 +#include <xen/time.h> 1.20 +#include <xen/softirq.h> 1.21 +#include <xen/timer.h> 1.22 +#include <xen/keyhandler.h> 1.23 +#include <asm/system.h> 1.24 +#include <asm/desc.h> 1.25 + 1.26 +/* 1.27 + * We pull handlers off the timer list this far in future, 1.28 + * rather than reprogramming the time hardware. 1.29 + */ 1.30 +#define TIMER_SLOP (50*1000) /* ns */ 1.31 + 1.32 +struct timers { 1.33 + spinlock_t lock; 1.34 + struct timer **heap; 1.35 +} __cacheline_aligned; 1.36 + 1.37 +struct timers timers[NR_CPUS]; 1.38 + 1.39 +extern int reprogram_timer(s_time_t timeout); 1.40 + 1.41 +/**************************************************************************** 1.42 + * HEAP OPERATIONS. 1.43 + */ 1.44 + 1.45 +#define GET_HEAP_SIZE(_h) ((int)(((u16 *)(_h))[0])) 1.46 +#define SET_HEAP_SIZE(_h,_v) (((u16 *)(_h))[0] = (u16)(_v)) 1.47 + 1.48 +#define GET_HEAP_LIMIT(_h) ((int)(((u16 *)(_h))[1])) 1.49 +#define SET_HEAP_LIMIT(_h,_v) (((u16 *)(_h))[1] = (u16)(_v)) 1.50 + 1.51 +/* Sink down element @pos of @heap. */ 1.52 +static void down_heap(struct timer **heap, int pos) 1.53 +{ 1.54 + int sz = GET_HEAP_SIZE(heap), nxt; 1.55 + struct timer *t = heap[pos]; 1.56 + 1.57 + while ( (nxt = (pos << 1)) <= sz ) 1.58 + { 1.59 + if ( ((nxt+1) <= sz) && (heap[nxt+1]->expires < heap[nxt]->expires) ) 1.60 + nxt++; 1.61 + if ( heap[nxt]->expires > t->expires ) 1.62 + break; 1.63 + heap[pos] = heap[nxt]; 1.64 + heap[pos]->heap_offset = pos; 1.65 + pos = nxt; 1.66 + } 1.67 + 1.68 + heap[pos] = t; 1.69 + t->heap_offset = pos; 1.70 +} 1.71 + 1.72 +/* Float element @pos up @heap. */ 1.73 +static void up_heap(struct timer **heap, int pos) 1.74 +{ 1.75 + struct timer *t = heap[pos]; 1.76 + 1.77 + while ( (pos > 1) && (t->expires < heap[pos>>1]->expires) ) 1.78 + { 1.79 + heap[pos] = heap[pos>>1]; 1.80 + heap[pos]->heap_offset = pos; 1.81 + pos >>= 1; 1.82 + } 1.83 + 1.84 + heap[pos] = t; 1.85 + t->heap_offset = pos; 1.86 +} 1.87 + 1.88 + 1.89 +/* Delete @t from @heap. Return TRUE if new top of heap. */ 1.90 +static int remove_entry(struct timer **heap, struct timer *t) 1.91 +{ 1.92 + int sz = GET_HEAP_SIZE(heap); 1.93 + int pos = t->heap_offset; 1.94 + 1.95 + t->heap_offset = 0; 1.96 + 1.97 + if ( unlikely(pos == sz) ) 1.98 + { 1.99 + SET_HEAP_SIZE(heap, sz-1); 1.100 + goto out; 1.101 + } 1.102 + 1.103 + heap[pos] = heap[sz]; 1.104 + heap[pos]->heap_offset = pos; 1.105 + 1.106 + SET_HEAP_SIZE(heap, --sz); 1.107 + 1.108 + if ( (pos > 1) && (heap[pos]->expires < heap[pos>>1]->expires) ) 1.109 + up_heap(heap, pos); 1.110 + else 1.111 + down_heap(heap, pos); 1.112 + 1.113 + out: 1.114 + return (pos == 1); 1.115 +} 1.116 + 1.117 + 1.118 +/* Add new entry @t to @heap. Return TRUE if new top of heap. */ 1.119 +static int add_entry(struct timer ***pheap, struct timer *t) 1.120 +{ 1.121 + struct timer **heap = *pheap; 1.122 + int sz = GET_HEAP_SIZE(heap); 1.123 + 1.124 + /* Copy the heap if it is full. */ 1.125 + if ( unlikely(sz == GET_HEAP_LIMIT(heap)) ) 1.126 + { 1.127 + /* old_limit == (2^n)-1; new_limit == (2^(n+4))-1 */ 1.128 + int old_limit = GET_HEAP_LIMIT(heap); 1.129 + int new_limit = ((old_limit + 1) << 4) - 1; 1.130 + heap = xmalloc_array(struct timer *, new_limit + 1); 1.131 + BUG_ON(heap == NULL); 1.132 + memcpy(heap, *pheap, (old_limit + 1) * sizeof(*heap)); 1.133 + SET_HEAP_LIMIT(heap, new_limit); 1.134 + if ( old_limit != 0 ) 1.135 + xfree(*pheap); 1.136 + *pheap = heap; 1.137 + } 1.138 + 1.139 + SET_HEAP_SIZE(heap, ++sz); 1.140 + heap[sz] = t; 1.141 + t->heap_offset = sz; 1.142 + up_heap(heap, sz); 1.143 + return (t->heap_offset == 1); 1.144 +} 1.145 + 1.146 + 1.147 +/**************************************************************************** 1.148 + * TIMER OPERATIONS. 1.149 + */ 1.150 + 1.151 +static inline void __add_timer(struct timer *timer) 1.152 +{ 1.153 + int cpu = timer->cpu; 1.154 + if ( add_entry(&timers[cpu].heap, timer) ) 1.155 + cpu_raise_softirq(cpu, TIMER_SOFTIRQ); 1.156 +} 1.157 + 1.158 + 1.159 +static inline void __stop_timer(struct timer *timer) 1.160 +{ 1.161 + int cpu = timer->cpu; 1.162 + if ( remove_entry(timers[cpu].heap, timer) ) 1.163 + cpu_raise_softirq(cpu, TIMER_SOFTIRQ); 1.164 +} 1.165 + 1.166 + 1.167 +void set_timer(struct timer *timer, s_time_t expires) 1.168 +{ 1.169 + int cpu = timer->cpu; 1.170 + unsigned long flags; 1.171 + 1.172 + spin_lock_irqsave(&timers[cpu].lock, flags); 1.173 + ASSERT(timer != NULL); 1.174 + if ( active_timer(timer) ) 1.175 + __stop_timer(timer); 1.176 + timer->expires = expires; 1.177 + __add_timer(timer); 1.178 + spin_unlock_irqrestore(&timers[cpu].lock, flags); 1.179 +} 1.180 + 1.181 + 1.182 +void stop_timer(struct timer *timer) 1.183 +{ 1.184 + int cpu = timer->cpu; 1.185 + unsigned long flags; 1.186 + 1.187 + spin_lock_irqsave(&timers[cpu].lock, flags); 1.188 + ASSERT(timer != NULL); 1.189 + if ( active_timer(timer) ) 1.190 + __stop_timer(timer); 1.191 + spin_unlock_irqrestore(&timers[cpu].lock, flags); 1.192 +} 1.193 + 1.194 + 1.195 +static void timer_softirq_action(void) 1.196 +{ 1.197 + int cpu = smp_processor_id(); 1.198 + struct timer *t, **heap; 1.199 + s_time_t now; 1.200 + void (*fn)(void *); 1.201 + void *data; 1.202 + 1.203 + spin_lock_irq(&timers[cpu].lock); 1.204 + 1.205 + do { 1.206 + heap = timers[cpu].heap; 1.207 + now = NOW(); 1.208 + 1.209 + while ( (GET_HEAP_SIZE(heap) != 0) && 1.210 + ((t = heap[1])->expires < (now + TIMER_SLOP)) ) 1.211 + { 1.212 + remove_entry(heap, t); 1.213 + 1.214 + fn = t->function; 1.215 + data = t->data; 1.216 + 1.217 + if ( fn != NULL ) 1.218 + { 1.219 + spin_unlock_irq(&timers[cpu].lock); 1.220 + (*fn)(data); 1.221 + spin_lock_irq(&timers[cpu].lock); 1.222 + } 1.223 + 1.224 + /* Heap may have grown while the lock was released. */ 1.225 + heap = timers[cpu].heap; 1.226 + } 1.227 + } 1.228 + while ( !reprogram_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) ); 1.229 + 1.230 + spin_unlock_irq(&timers[cpu].lock); 1.231 +} 1.232 + 1.233 + 1.234 +static void dump_timerq(unsigned char key) 1.235 +{ 1.236 + struct timer *t; 1.237 + unsigned long flags; 1.238 + s_time_t now = NOW(); 1.239 + int i, j; 1.240 + 1.241 + printk("Dumping timer queues: NOW=0x%08X%08X\n", 1.242 + (u32)(now>>32), (u32)now); 1.243 + 1.244 + for_each_online_cpu( i ) 1.245 + { 1.246 + printk("CPU[%02d] ", i); 1.247 + spin_lock_irqsave(&timers[i].lock, flags); 1.248 + for ( j = 1; j <= GET_HEAP_SIZE(timers[i].heap); j++ ) 1.249 + { 1.250 + t = timers[i].heap[j]; 1.251 + printk (" %d : %p ex=0x%08X%08X %p\n", 1.252 + j, t, (u32)(t->expires>>32), (u32)t->expires, t->data); 1.253 + } 1.254 + spin_unlock_irqrestore(&timers[i].lock, flags); 1.255 + printk("\n"); 1.256 + } 1.257 +} 1.258 + 1.259 + 1.260 +void __init timer_init(void) 1.261 +{ 1.262 + static struct timer *dummy_heap; 1.263 + int i; 1.264 + 1.265 + open_softirq(TIMER_SOFTIRQ, timer_softirq_action); 1.266 + 1.267 + /* 1.268 + * All CPUs initially share an empty dummy heap. Only those CPUs that 1.269 + * are brought online will be dynamically allocated their own heap. 1.270 + */ 1.271 + SET_HEAP_SIZE(&dummy_heap, 0); 1.272 + SET_HEAP_LIMIT(&dummy_heap, 0); 1.273 + 1.274 + for ( i = 0; i < NR_CPUS; i++ ) 1.275 + { 1.276 + spin_lock_init(&timers[i].lock); 1.277 + timers[i].heap = &dummy_heap; 1.278 + } 1.279 + 1.280 + register_keyhandler('a', dump_timerq, "dump timer queues"); 1.281 +} 1.282 + 1.283 +/* 1.284 + * Local variables: 1.285 + * mode: C 1.286 + * c-set-style: "BSD" 1.287 + * c-basic-offset: 4 1.288 + * tab-width: 4 1.289 + * indent-tabs-mode: nil 1.290 + * End: 1.291 + */
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/xen/include/xen/timer.h Fri Jan 13 00:16:07 2006 +0100 2.3 @@ -0,0 +1,81 @@ 2.4 +/****************************************************************************** 2.5 + * timer.h 2.6 + * 2.7 + * Copyright (c) 2002-2003 Rolf Neugebauer 2.8 + * Copyright (c) 2002-2005 K A Fraser 2.9 + */ 2.10 + 2.11 +#ifndef _TIMER_H_ 2.12 +#define _TIMER_H_ 2.13 + 2.14 +#include <xen/spinlock.h> 2.15 +#include <xen/time.h> 2.16 +#include <xen/string.h> 2.17 + 2.18 +struct timer { 2.19 + /* System time expiry value (nanoseconds since boot). */ 2.20 + s_time_t expires; 2.21 + /* CPU on which this timer will be installed and executed. */ 2.22 + unsigned int cpu; 2.23 + /* On expiry, '(*function)(data)' will be executed in softirq context. */ 2.24 + void (*function)(void *); 2.25 + void *data; 2.26 + /* Timer-heap offset. */ 2.27 + unsigned int heap_offset; 2.28 +}; 2.29 + 2.30 +/* 2.31 + * All functions below can be called for any CPU from any CPU in any context. 2.32 + */ 2.33 + 2.34 +/* Returns TRUE if the given timer is on a timer list. */ 2.35 +static __inline__ int active_timer(struct timer *timer) 2.36 +{ 2.37 + return (timer->heap_offset != 0); 2.38 +} 2.39 + 2.40 +/* 2.41 + * It initialises the static fields of the timer structure. 2.42 + * It can be called multiple times to reinitialise a single (inactive) timer. 2.43 + */ 2.44 +static __inline__ void init_timer( 2.45 + struct timer *timer, 2.46 + void (*function)(void *), 2.47 + void *data, 2.48 + unsigned int cpu) 2.49 +{ 2.50 + memset(timer, 0, sizeof(*timer)); 2.51 + timer->function = function; 2.52 + timer->data = data; 2.53 + timer->cpu = cpu; 2.54 +} 2.55 + 2.56 +/* 2.57 + * Set the expiry time and activate a timer (which must previously have been 2.58 + * initialised by init_timer). 2.59 + */ 2.60 +extern void set_timer(struct timer *timer, s_time_t expires); 2.61 + 2.62 +/* 2.63 + * Deactivate a timer (which must previously have been initialised by 2.64 + * init_timer). This function has no effect if the timer is not currently 2.65 + * active. 2.66 + */ 2.67 +extern void stop_timer(struct timer *timer); 2.68 + 2.69 +/* 2.70 + * Initialisation. Must be called before any other timer function. 2.71 + */ 2.72 +extern void timer_init(void); 2.73 + 2.74 +#endif /* _TIMER_H_ */ 2.75 + 2.76 +/* 2.77 + * Local variables: 2.78 + * mode: C 2.79 + * c-set-style: "BSD" 2.80 + * c-basic-offset: 4 2.81 + * tab-width: 4 2.82 + * indent-tabs-mode: nil 2.83 + * End: 2.84 + */