[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Cleanup grant table code.
# HG changeset patch # User cl349@xxxxxxxxxxxxxxxxxxxx # Node ID 5b1ed5b394513cf79f07cece754d2de3b710430a # Parent eecb74e515fdebadb1a6f5f1b9ee658aad22c2dc Cleanup grant table code. - keep count of free references - let callbacks specify the number of references they need at least - get rid of terminal reference - simplify and more correct locking for callbacks Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx> diff -r eecb74e515fd -r 5b1ed5b39451 linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Tue Aug 23 09:33:48 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Tue Aug 23 13:11:31 2005 @@ -46,55 +46,76 @@ EXPORT_SYMBOL(gnttab_grant_foreign_access_ref); EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref); -static grant_ref_t gnttab_free_list[NR_GRANT_ENTRIES]; +#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) +#define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1) + +static grant_ref_t gnttab_list[NR_GRANT_ENTRIES]; +static int gnttab_free_count = NR_GRANT_ENTRIES; static grant_ref_t gnttab_free_head; +static spinlock_t gnttab_list_lock = SPIN_LOCK_UNLOCKED; static grant_entry_t *shared; static struct gnttab_free_callback *gnttab_free_callback_list = NULL; -static spinlock_t gnttab_free_callback_list_lock = SPIN_LOCK_UNLOCKED; - -/* - * Lock-free grant-entry allocator - */ - -static inline int -get_free_entry( - void) -{ - grant_ref_t fh, nfh = gnttab_free_head; - do { if ( unlikely((fh = nfh) == NR_GRANT_ENTRIES) ) return -1; } - while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, - gnttab_free_list[fh])) != fh) ); - return fh; -} - -static void do_free_callbacks(unsigned long flags) + +static int +get_free_entries(int count) +{ + unsigned long flags; + int ref; + grant_ref_t head; + spin_lock_irqsave(&gnttab_list_lock, flags); + if (gnttab_free_count < count) { + spin_unlock_irqrestore(&gnttab_list_lock, flags); + return -1; + } + ref = head = gnttab_free_head; + gnttab_free_count -= count; + while (count-- > 1) + head = gnttab_list[head]; + gnttab_free_head = gnttab_list[head]; + gnttab_list[head] = GNTTAB_LIST_END; + spin_unlock_irqrestore(&gnttab_list_lock, flags); + return ref; +} + +#define get_free_entry() get_free_entries(1) + +static void +do_free_callbacks(void) { struct gnttab_free_callback *callback = gnttab_free_callback_list, *next; gnttab_free_callback_list = NULL; - spin_unlock_irqrestore(&gnttab_free_callback_list_lock, flags); while (callback) { next = callback->next; - callback->next = NULL; - callback->fn(callback->arg); + if (gnttab_free_count >= callback->count) { + callback->next = NULL; + callback->fn(callback->arg); + } else { + callback->next = gnttab_free_callback_list; + gnttab_free_callback_list = callback; + } callback = next; } } static inline void -put_free_entry( - grant_ref_t ref) -{ - grant_ref_t fh, nfh = gnttab_free_head; +check_free_callbacks(void) +{ + if (unlikely(gnttab_free_callback_list)) + do_free_callbacks(); +} + +static void +put_free_entry(grant_ref_t ref) +{ unsigned long flags; - do { gnttab_free_list[ref] = fh = nfh; wmb(); } - while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) ); - spin_lock_irqsave(&gnttab_free_callback_list_lock, flags); - if ( unlikely(gnttab_free_callback_list) ) - do_free_callbacks(flags); - else - spin_unlock_irqrestore(&gnttab_free_callback_list_lock, flags); + spin_lock_irqsave(&gnttab_list_lock, flags); + gnttab_list[ref] = gnttab_free_head; + gnttab_free_head = ref; + gnttab_free_count++; + check_free_callbacks(); + spin_unlock_irqrestore(&gnttab_list_lock, flags); } /* @@ -102,8 +123,7 @@ */ int -gnttab_grant_foreign_access( - domid_t domid, unsigned long frame, int readonly) +gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly) { int ref; @@ -119,8 +139,8 @@ } void -gnttab_grant_foreign_access_ref( - grant_ref_t ref, domid_t domid, unsigned long frame, int readonly) +gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, + unsigned long frame, int readonly) { shared[ref].frame = frame; shared[ref].domid = domid; @@ -130,7 +150,7 @@ int -gnttab_query_foreign_access( grant_ref_t ref ) +gnttab_query_foreign_access(grant_ref_t ref) { u16 nflags; @@ -140,7 +160,7 @@ } void -gnttab_end_foreign_access( grant_ref_t ref, int readonly ) +gnttab_end_foreign_access(grant_ref_t ref, int readonly) { u16 flags, nflags; @@ -155,8 +175,7 @@ } int -gnttab_grant_foreign_transfer( - domid_t domid, unsigned long pfn ) +gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn) { int ref; @@ -172,8 +191,8 @@ } void -gnttab_grant_foreign_transfer_ref( - grant_ref_t ref, domid_t domid, unsigned long pfn ) +gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid, + unsigned long pfn) { shared[ref].frame = pfn; shared[ref].domid = domid; @@ -182,8 +201,7 @@ } unsigned long -gnttab_end_foreign_transfer( - grant_ref_t ref) +gnttab_end_foreign_transfer(grant_ref_t ref) { unsigned long frame = 0; u16 flags; @@ -212,80 +230,79 @@ } void -gnttab_free_grant_reference( grant_ref_t ref ) +gnttab_free_grant_reference(grant_ref_t ref) { put_free_entry(ref); } void -gnttab_free_grant_references( grant_ref_t *head, - grant_ref_t terminal ) -{ - /* TODO: O(N)...? */ +gnttab_free_grant_references(grant_ref_t head) +{ grant_ref_t ref; - - while (*head != terminal) { - ref = *head; - *head = gnttab_free_list[*head]; - put_free_entry(ref); + unsigned long flags; + int count = 1; + if (head == GNTTAB_LIST_END) + return; + spin_lock_irqsave(&gnttab_list_lock, flags); + ref = head; + while (gnttab_list[ref] != GNTTAB_LIST_END) { + ref = gnttab_list[ref]; + count++; } -} - -int -gnttab_alloc_grant_references( u16 count, - grant_ref_t *head, - grant_ref_t *terminal ) -{ - int i; - grant_ref_t h = gnttab_free_head; - - for ( i = 0; i < count; i++ ) - if ( unlikely(get_free_entry() == -1) ) - goto not_enough_refs; + gnttab_list[ref] = gnttab_free_head; + gnttab_free_head = head; + gnttab_free_count += count; + check_free_callbacks(); + spin_unlock_irqrestore(&gnttab_list_lock, flags); +} + +int +gnttab_alloc_grant_references(u16 count, grant_ref_t *head) +{ + int h = get_free_entries(count); + + if (h == -1) + return -ENOSPC; *head = h; - *terminal = gnttab_free_head; return 0; - -not_enough_refs: - gnttab_free_head = h; - return -ENOSPC; -} - -int -gnttab_claim_grant_reference( grant_ref_t *private_head, - grant_ref_t terminal ) -{ - grant_ref_t g; - if ( unlikely((g = *private_head) == terminal) ) +} + +int +gnttab_claim_grant_reference(grant_ref_t *private_head) +{ + grant_ref_t g = *private_head; + if (unlikely(g == GNTTAB_LIST_END)) return -ENOSPC; - *private_head = gnttab_free_list[g]; + *private_head = gnttab_list[g]; return g; } void -gnttab_release_grant_reference( grant_ref_t *private_head, - grant_ref_t release ) -{ - gnttab_free_list[release] = *private_head; +gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release) +{ + gnttab_list[release] = *private_head; *private_head = release; } void gnttab_request_free_callback(struct gnttab_free_callback *callback, - void (*fn)(void *), void *arg) + void (*fn)(void *), void *arg, u16 count) { unsigned long flags; + spin_lock_irqsave(&gnttab_list_lock, flags); if (callback->next) - return; + goto out; callback->fn = fn; callback->arg = arg; - spin_lock_irqsave(&gnttab_free_callback_list_lock, flags); + callback->count = count; callback->next = gnttab_free_callback_list; gnttab_free_callback_list = callback; - spin_unlock_irqrestore(&gnttab_free_callback_list_lock, flags); + check_free_callbacks(); + out: + spin_unlock_irqrestore(&gnttab_list_lock, flags); } /* @@ -296,8 +313,9 @@ static struct proc_dir_entry *grant_pde; -static int grant_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long data) +static int +grant_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long data) { int ret; privcmd_hypercall_t hypercall; @@ -335,8 +353,9 @@ ioctl: grant_ioctl, }; -static int grant_read(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int +grant_read(char *page, char **start, off_t off, int count, int *eof, + void *data) { int len; unsigned int i; @@ -365,8 +384,9 @@ return len; } -static int grant_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int +grant_write(struct file *file, const char __user *buffer, unsigned long count, + void *data) { /* TODO: implement this */ return -ENOSYS; @@ -374,7 +394,8 @@ #endif /* CONFIG_PROC_FS */ -int gnttab_resume(void) +int +gnttab_resume(void) { gnttab_setup_table_t setup; unsigned long frames[NR_GRANT_FRAMES]; @@ -393,7 +414,8 @@ return 0; } -int gnttab_suspend(void) +int +gnttab_suspend(void) { int i; @@ -403,7 +425,8 @@ return 0; } -static int __init gnttab_init(void) +static int __init +gnttab_init(void) { int i; @@ -412,7 +435,7 @@ shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END); for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) - gnttab_free_list[i] = i + 1; + gnttab_list[i] = i + 1; #ifdef CONFIG_PROC_FS /* diff -r eecb74e515fd -r 5b1ed5b39451 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Aug 23 09:33:48 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Aug 23 13:11:31 2005 @@ -237,15 +237,16 @@ unsigned long id; unsigned int fsect, lsect; int ref; - grant_ref_t gref_head, gref_terminal; + grant_ref_t gref_head; if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) return 1; if (gnttab_alloc_grant_references(BLKIF_MAX_SEGMENTS_PER_REQUEST, - &gref_head, &gref_terminal) < 0) { + &gref_head) < 0) { gnttab_request_free_callback(&info->callback, - blkif_restart_queue_callback, info); + blkif_restart_queue_callback, info, + BLKIF_MAX_SEGMENTS_PER_REQUEST); return 1; } @@ -270,7 +271,7 @@ fsect = bvec->bv_offset >> 9; lsect = fsect + (bvec->bv_len >> 9) - 1; /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); + ref = gnttab_claim_grant_reference(&gref_head); ASSERT( ref != -ENOSPC ); gnttab_grant_foreign_access_ref( @@ -294,7 +295,7 @@ /* Keep a private copy so we can reissue requests when recovering. */ pickle_request(&blk_shadow[id], ring_req); - gnttab_free_grant_references(&gref_head, gref_terminal); + gnttab_free_grant_references(gref_head); return 0; } @@ -738,7 +739,7 @@ blk_shadow[req->id].request = (unsigned long)id; /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); + ref = gnttab_claim_grant_reference(&gref_head); ASSERT( ref != -ENOSPC ); gnttab_grant_foreign_access_ref( @@ -790,7 +791,7 @@ req->handle = handle; req->nr_segments = 1; /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head, gref_terminal); + ref = gnttab_claim_grant_reference(&gref_head); ASSERT( ref != -ENOSPC ); gnttab_grant_foreign_access_ref( diff -r eecb74e515fd -r 5b1ed5b39451 linux-2.6-xen-sparse/include/asm-xen/gnttab.h --- a/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Tue Aug 23 09:33:48 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/gnttab.h Tue Aug 23 13:11:31 2005 @@ -19,68 +19,46 @@ /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ #define NR_GRANT_FRAMES 4 -#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) struct gnttab_free_callback { struct gnttab_free_callback *next; void (*fn)(void *); void *arg; + u16 count; }; -int -gnttab_grant_foreign_access( - domid_t domid, unsigned long frame, int readonly); +int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, + int readonly); -void -gnttab_end_foreign_access( - grant_ref_t ref, int readonly); +void gnttab_end_foreign_access(grant_ref_t ref, int readonly); -int -gnttab_grant_foreign_transfer( - domid_t domid, unsigned long pfn); +int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn); -unsigned long -gnttab_end_foreign_transfer( - grant_ref_t ref); +unsigned long gnttab_end_foreign_transfer(grant_ref_t ref); -int -gnttab_query_foreign_access( - grant_ref_t ref ); +int gnttab_query_foreign_access(grant_ref_t ref); /* * operations on reserved batches of grant references */ -int -gnttab_alloc_grant_references( - u16 count, grant_ref_t *pprivate_head, grant_ref_t *private_terminal ); +int gnttab_alloc_grant_references(u16 count, grant_ref_t *pprivate_head); -void -gnttab_free_grant_reference( - grant_ref_t ref ); +void gnttab_free_grant_reference(grant_ref_t ref); -void -gnttab_free_grant_references( - grant_ref_t *head, grant_ref_t terminal ); +void gnttab_free_grant_references(grant_ref_t head); -int -gnttab_claim_grant_reference( grant_ref_t *pprivate_head, grant_ref_t terminal -); +int gnttab_claim_grant_reference(grant_ref_t *pprivate_head); -void -gnttab_release_grant_reference( - grant_ref_t *private_head, grant_ref_t release ); +void gnttab_release_grant_reference(grant_ref_t *private_head, + grant_ref_t release); -void -gnttab_request_free_callback( - struct gnttab_free_callback *callback, void (*fn)(void *), void *arg); +void gnttab_request_free_callback(struct gnttab_free_callback *callback, + void (*fn)(void *), void *arg, u16 count); -void -gnttab_grant_foreign_access_ref( - grant_ref_t ref, domid_t domid, unsigned long frame, int readonly); +void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, + unsigned long frame, int readonly); -void -gnttab_grant_foreign_transfer_ref( - grant_ref_t, domid_t domid, unsigned long pfn); - +void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, + unsigned long pfn); #endif /* __ASM_GNTTAB_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |