static grant_entry_t *shared;
+static struct gnttab_free_callback *gnttab_free_callback_list = NULL;
+
/*
* Lock-free grant-entry allocator
*/
return fh;
}
+static void do_free_callbacks(void)
+{
+ struct gnttab_free_callback *callback = gnttab_free_callback_list;
+ gnttab_free_callback_list = NULL;
+ while (callback) {
+ schedule_work(callback->work);
+ callback = callback->next;
+ }
+}
+
static inline void
put_free_entry(
grant_ref_t ref)
grant_ref_t fh, nfh = gnttab_free_head;
do { gnttab_free_list[ref] = fh = nfh; wmb(); }
while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) );
+ if ( unlikely(gnttab_free_callback_list) )
+ do_free_callbacks();
}
/*
}
void
-gnttab_free_grant_references( u16 count, grant_ref_t head )
+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)...? */
- grant_ref_t to_die = 0, next = head;
- int i;
+ grant_ref_t ref;
- for ( i = 0; i < count; i++ )
- {
- to_die = next;
- next = gnttab_free_list[next];
- put_free_entry( to_die );
+ while (*head != terminal) {
+ ref = *head;
+ *head = gnttab_free_list[*head];
+ put_free_entry(ref);
}
}
*private_head = release;
}
+void
+gnttab_request_free_callback(struct gnttab_free_callback *callback,
+ struct work_struct *work)
+{
+ callback->work = work;
+ callback->next = gnttab_free_callback_list;
+ gnttab_free_callback_list = callback;
+}
+
/*
* ProcFS operations
*/
#define NR_GRANT_FRAMES 4
#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
+struct work_struct;
+
+struct gnttab_free_callback {
+ struct gnttab_free_callback *next;
+ struct work_struct *work;
+};
+
int
gnttab_grant_foreign_access(
domid_t domid, unsigned long frame, int readonly);
gnttab_alloc_grant_references(
u16 count, grant_ref_t *pprivate_head, grant_ref_t *private_terminal );
+void
+gnttab_free_grant_reference(
+ grant_ref_t ref );
+
void
gnttab_free_grant_references(
- u16 count, grant_ref_t private_head );
+ grant_ref_t *head, grant_ref_t terminal );
int
gnttab_claim_grant_reference( grant_ref_t *pprivate_head, grant_ref_t terminal
gnttab_release_grant_reference(
grant_ref_t *private_head, grant_ref_t release );
+void
+gnttab_request_free_callback(
+ struct gnttab_free_callback *callback, struct work_struct *work );
+
void
gnttab_grant_foreign_access_ref(
grant_ref_t ref, domid_t domid, unsigned long frame, int readonly);