[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] timer: No dynamic memory allocation with IRQs disabled.
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |