for (i = 0; i < VMCI_EVENT_MAX; i++)
INIT_LIST_HEAD(&subscriber_array[i]);
return VMCI_SUCCESS;
}
void vmci_event_exit(void)
{ int e;
/* We free all memory at exit. */ for (e = 0; e < VMCI_EVENT_MAX; e++) { struct vmci_subscription *cur, *p2;
list_for_each_entry_safe(cur, p2, &subscriber_array[e], node) {
/* * We should never get here because all events * should have been unregistered before we try * to unload the driver module.
*/
pr_warn("Unexpected free events occurring\n");
list_del(&cur->node);
kfree(cur);
}
}
}
/* * Find entry. Assumes subscriber_mutex is held.
*/ staticstruct vmci_subscription *event_find(u32 sub_id)
{ int e;
for (e = 0; e < VMCI_EVENT_MAX; e++) { struct vmci_subscription *cur;
list_for_each_entry(cur, &subscriber_array[e], node) { if (cur->id == sub_id) return cur;
}
} return NULL;
}
/* * Actually delivers the events to the subscribers. * The callback function for each subscriber is invoked.
*/ staticvoid event_deliver(struct vmci_event_msg *event_msg)
{ struct vmci_subscription *cur; struct list_head *subscriber_list;
u32 sanitized_event, max_vmci_event;
/* * Dispatcher for the VMCI_EVENT_RECEIVE datagrams. Calls all * subscribers for given event.
*/ int vmci_event_dispatch(struct vmci_datagram *msg)
{ struct vmci_event_msg *event_msg = (struct vmci_event_msg *)msg;
if (!VMCI_EVENT_VALID(event_msg->event_data.event)) return VMCI_ERROR_EVENT_UNKNOWN;
event_deliver(event_msg); return VMCI_SUCCESS;
}
/* * vmci_event_subscribe() - Subscribe to a given event. * @event: The event to subscribe to. * @callback: The callback to invoke upon the event. * @callback_data: Data to pass to the callback. * @subscription_id: ID used to track subscription. Used with * vmci_event_unsubscribe() * * Subscribes to the provided event. The callback specified will be * fired from RCU critical section and therefore must not sleep.
*/ int vmci_event_subscribe(u32 event,
vmci_event_cb callback, void *callback_data,
u32 *new_subscription_id)
{ struct vmci_subscription *sub; int attempts; int retval; bool have_new_id = false;
/* Creation of a new event is always allowed. */ for (attempts = 0; attempts < VMCI_EVENT_MAX_ATTEMPTS; attempts++) { static u32 subscription_id; /* * We try to get an id a couple of time before * claiming we are out of resources.
*/
/* Test for duplicate id. */ if (!event_find(++subscription_id)) {
sub->id = subscription_id;
have_new_id = true; break;
}
}
/* * vmci_event_unsubscribe() - unsubscribe from an event. * @sub_id: A subscription ID as provided by vmci_event_subscribe() * * Unsubscribe from given event. Removes it from list and frees it. * Will return callback_data if requested by caller.
*/ int vmci_event_unsubscribe(u32 sub_id)
{ struct vmci_subscription *s;
mutex_lock(&subscriber_mutex);
s = event_find(sub_id); if (s)
list_del_rcu(&s->node);
mutex_unlock(&subscriber_mutex);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.