WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Cleanup grant table code., Xen patchbot -unstable <=