# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1224585597 -3600
# Node ID ecdbcd27490facb15dbffb5b8591d73503708f72
# Parent 3ba06e8098cb3a5583dc5d38fc4f7138348bf897
timer: No dynamic memory allocation with IRQs disabled.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/common/timer.c | 56 +++++++++++++++++++++++++++--------------------------
1 files changed, 29 insertions(+), 27 deletions(-)
diff -r 3ba06e8098cb -r ecdbcd27490f xen/common/timer.c
--- a/xen/common/timer.c Tue Oct 21 11:39:22 2008 +0100
+++ b/xen/common/timer.c Tue Oct 21 11:39:57 2008 +0100
@@ -114,34 +114,19 @@ static int remove_from_heap(struct timer
/* Add new entry @t to @heap. Return TRUE if new top of heap. */
-static int add_to_heap(struct timer ***pheap, struct timer *t)
-{
- struct timer **heap = *pheap;
+static int add_to_heap(struct timer **heap, struct timer *t)
+{
int sz = GET_HEAP_SIZE(heap);
- /* Copy the heap if it is full. */
+ /* Fail if the heap 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;
- if ( in_irq() )
- goto out;
- heap = xmalloc_array(struct timer *, new_limit + 1);
- if ( heap == NULL )
- goto out;
- memcpy(heap, *pheap, (old_limit + 1) * sizeof(*heap));
- SET_HEAP_LIMIT(heap, new_limit);
- if ( old_limit != 0 )
- xfree(*pheap);
- *pheap = heap;
- }
+ return 0;
SET_HEAP_SIZE(heap, ++sz);
heap[sz] = t;
t->heap_offset = sz;
up_heap(heap, sz);
- out:
+
return (t->heap_offset == 1);
}
@@ -210,7 +195,7 @@ static int add_entry(struct timers *time
/* Try to add to heap. t->heap_offset indicates whether we succeed. */
t->heap_offset = 0;
t->status = TIMER_STATUS_in_heap;
- rc = add_to_heap(&timers->heap, t);
+ rc = add_to_heap(timers->heap, t);
if ( t->heap_offset != 0 )
return rc;
@@ -368,6 +353,27 @@ static void timer_softirq_action(void)
void *data;
ts = &this_cpu(timers);
+ heap = ts->heap;
+
+ /* If we are using overflow linked list, try to allocate a larger heap. */
+ if ( unlikely(ts->list != NULL) )
+ {
+ /* 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;
+ struct timer **newheap = xmalloc_array(struct timer *, new_limit + 1);
+ if ( newheap != NULL )
+ {
+ spin_lock_irq(&ts->lock);
+ memcpy(newheap, heap, (old_limit + 1) * sizeof(*heap));
+ SET_HEAP_LIMIT(newheap, new_limit);
+ ts->heap = newheap;
+ spin_unlock_irq(&ts->lock);
+ if ( old_limit != 0 )
+ xfree(heap);
+ heap = newheap;
+ }
+ }
spin_lock_irq(&ts->lock);
@@ -380,9 +386,8 @@ static void timer_softirq_action(void)
t->status = TIMER_STATUS_inactive;
add_entry(ts, t);
}
-
- heap = ts->heap;
- now = NOW();
+
+ now = NOW();
while ( (GET_HEAP_SIZE(heap) != 0) &&
((t = heap[1])->expires < (now + TIMER_SLOP)) )
@@ -397,9 +402,6 @@ static void timer_softirq_action(void)
spin_unlock_irq(&ts->lock);
(*fn)(data);
spin_lock_irq(&ts->lock);
-
- /* Heap may have grown while the lock was released. */
- heap = ts->heap;
}
deadline = GET_HEAP_SIZE(heap) ? heap[1]->expires : 0;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|