/* From the reference implementation http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD */ static unsigned long gnttab_end_transfer(grant_ref_t ref) { unsigned long frame; uint16_t flags; uint16_t *pflags = &gnttab_table[ref].flags; /* * If a transfer is not even yet started, try to reclaim the grant * reference and return failure (== 0). */ while (!((flags = *pflags) & GTF_transfer_committed)) { if (synch_cmpxchg(pflags, flags, 0) == flags) return 0; } /* If a transfer is in progress then wait until it is completed. */ while (!(flags & GTF_transfer_completed)) { flags = *pflags; } rmb(); /* Read the frame number /after/ reading completion status. */ frame = gnttab_table[ref].frame; BUG_ON(frame == 0); return frame; }
unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) { unsigned long frame; uint16_t flags; /* * If a transfer is not even yet started, try to reclaim the grant * reference and return failure (== 0). */ while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { if ( synch_cmpxchg(&shared[ref].flags, flags, 0) == flags ) return (0); cpu_spinwait(); } /* If a transfer is in progress then wait until it is completed. */ while (!(flags & GTF_transfer_completed)) { flags = shared[ref].flags; cpu_spinwait(); } /* Read the frame number /after/ reading completion status. */ rmb(); frame = shared[ref].frame; KASSERT(frame != 0, ("grant table inconsistent")); return (frame); }
unsigned long gnttab_end_transfer(grant_ref_t ref) { unsigned long frame; uint16_t flags; BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES); while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) { if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) { printk("Release unused transfer grant.\n"); put_free_entry(ref); return 0; } } /* If a transfer is in progress then wait until it is completed. */ while (!(flags & GTF_transfer_completed)) { flags = gnttab_table[ref].flags; } /* Read the frame number /after/ reading completion status. */ rmb(); frame = gnttab_table[ref].frame; put_free_entry(ref); return frame; }
void grants_end_access(grant_ref_t ref) { uint16_t flags, nflags; nflags = grant_entries[ref].flags; do { if ((flags = nflags) & (GTF_reading|GTF_writing)) fatal_error("grants_end_access: still in use\n"); } while ((nflags = synch_cmpxchg(&grant_entries[ref].flags, flags, 0)) != flags); free_list[ref] = free_entry; free_entry = ref; }
int gnttab_end_foreign_access_ref(grant_ref_t ref) { uint16_t flags, nflags; nflags = shared[ref].flags; do { if ( (flags = nflags) & (GTF_reading|GTF_writing) ) { printf("%s: WARNING: g.e. still in use!\n", __func__); return (0); } } while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != flags); return (1); }
CAMLprim value caml_gnttab_end_access(value v_ref) { grant_ref_t ref = Int_val(v_ref); uint16_t flags, nflags; BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES); nflags = gnttab_table[ref].flags; do { if ((flags = nflags) & (GTF_reading|GTF_writing)) { printk("WARNING: g.e. %d still in use! (%x)\n", ref, flags); return Val_unit; } } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) != flags); return Val_unit; }
int gnttab_end_access(grant_ref_t ref) { uint16_t flags, nflags; BUG_ON(ref >= NR_GRANT_ENTRIES || ref < NR_RESERVED_ENTRIES); nflags = gnttab_table[ref].flags; do { if ((flags = nflags) & (GTF_reading|GTF_writing)) { printk("WARNING: g.e. still in use! (%x)\n", flags); return 0; } } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) != flags); put_free_entry(ref); return 1; }