void side_call_variadic(const struct side_event_state *state,
const struct side_arg_vec *side_arg_vec,
const struct side_arg_dynamic_struct *var_struct);
+void side_call_key(const struct side_event_state *state,
+ const struct side_arg_vec *side_arg_vec,
+ void *key);
+void side_call_variadic_key(const struct side_event_state *state,
+ const struct side_arg_vec *side_arg_vec,
+ const struct side_arg_dynamic_struct *var_struct,
+ void *key);
struct side_events_register_handle *side_events_register(struct side_event_description **events,
uint32_t nr_events);
int side_tracer_callback_register(struct side_event_description *desc,
side_tracer_callback_func call,
- void *priv);
+ void *priv, void *key);
int side_tracer_callback_variadic_register(struct side_event_description *desc,
side_tracer_callback_variadic_func call_variadic,
- void *priv);
+ void *priv, void *key);
int side_tracer_callback_unregister(struct side_event_description *desc,
side_tracer_callback_func call,
- void *priv);
+ void *priv, void *key);
int side_tracer_callback_variadic_unregister(struct side_event_description *desc,
side_tracer_callback_variadic_func call_variadic,
- void *priv);
+ void *priv, void *key);
enum side_tracer_notification {
SIDE_TRACER_NOTIFICATION_INSERT_EVENTS,
void *priv);
} u;
void *priv;
+ void *key;
};
static struct side_rcu_gp_state rcu_gp;
*/
const char side_empty_callback[sizeof(struct side_callback)];
-void side_call(const struct side_event_state *event_state, const struct side_arg_vec *side_arg_vec)
+void side_call_key(const struct side_event_state *event_state, const struct side_arg_vec *side_arg_vec, void *key)
{
struct side_rcu_read_state rcu_read_state;
const struct side_event_state_0 *es0;
// TODO: call kernel write.
}
side_rcu_read_begin(&rcu_gp, &rcu_read_state);
- for (side_cb = side_rcu_dereference(es0->callbacks); side_cb->u.call != NULL; side_cb++)
+ for (side_cb = side_rcu_dereference(es0->callbacks); side_cb->u.call != NULL; side_cb++) {
+ /* A NULL key is always a match. */
+ if (key && side_cb->key && side_cb->key != key)
+ continue;
side_cb->u.call(es0->desc, side_arg_vec, side_cb->priv);
+ }
side_rcu_read_end(&rcu_gp, &rcu_read_state);
}
-void side_call_variadic(const struct side_event_state *event_state,
+void side_call(const struct side_event_state *event_state, const struct side_arg_vec *side_arg_vec)
+{
+ side_call_key(event_state, side_arg_vec, NULL);
+}
+
+void side_call_variadic_key(const struct side_event_state *event_state,
const struct side_arg_vec *side_arg_vec,
- const struct side_arg_dynamic_struct *var_struct)
+ const struct side_arg_dynamic_struct *var_struct,
+ void *key)
{
struct side_rcu_read_state rcu_read_state;
const struct side_event_state_0 *es0;
// TODO: call kernel write.
}
side_rcu_read_begin(&rcu_gp, &rcu_read_state);
- for (side_cb = side_rcu_dereference(es0->callbacks); side_cb->u.call_variadic != NULL; side_cb++)
+ for (side_cb = side_rcu_dereference(es0->callbacks); side_cb->u.call_variadic != NULL; side_cb++) {
+ /* A NULL key is always a match. */
+ if (key && side_cb->key && side_cb->key != key)
+ continue;
side_cb->u.call_variadic(es0->desc, side_arg_vec, var_struct, side_cb->priv);
+ }
side_rcu_read_end(&rcu_gp, &rcu_read_state);
}
+void side_call_variadic(const struct side_event_state *event_state,
+ const struct side_arg_vec *side_arg_vec,
+ const struct side_arg_dynamic_struct *var_struct)
+{
+ side_call_variadic_key(event_state, side_arg_vec, var_struct, NULL);
+}
+
static
const struct side_callback *side_tracer_callback_lookup(
const struct side_event_description *desc,
- void *call, void *priv)
+ void *call, void *priv, void *key)
{
struct side_event_state *event_state = side_ptr_get(desc->state);
const struct side_event_state_0 *es0;
abort();
es0 = side_container_of(event_state, const struct side_event_state_0, parent);
for (cb = es0->callbacks; cb->u.call != NULL; cb++) {
- if ((void *) cb->u.call == call && cb->priv == priv)
+ if ((void *) cb->u.call == call && cb->priv == priv && cb->key == key)
return cb;
}
return NULL;
static
int _side_tracer_callback_register(struct side_event_description *desc,
- void *call, void *priv)
+ void *call, void *priv, void *key)
{
struct side_event_state *event_state;
struct side_callback *old_cb, *new_cb;
goto unlock;
}
/* Reject duplicate (call, priv) tuples. */
- if (side_tracer_callback_lookup(desc, call, priv)) {
+ if (side_tracer_callback_lookup(desc, call, priv, key)) {
ret = SIDE_ERROR_EXIST;
goto unlock;
}
new_cb[old_nr_cb].u.call =
(side_tracer_callback_func) call;
new_cb[old_nr_cb].priv = priv;
+ new_cb[old_nr_cb].key = key;
/* High order bits are already zeroed. */
side_rcu_assign_pointer(es0->callbacks, new_cb);
side_rcu_wait_grace_period(&rcu_gp);
int side_tracer_callback_register(struct side_event_description *desc,
side_tracer_callback_func call,
- void *priv)
+ void *priv, void *key)
{
if (desc->flags & SIDE_EVENT_FLAG_VARIADIC)
return SIDE_ERROR_INVAL;
- return _side_tracer_callback_register(desc, (void *) call, priv);
+ return _side_tracer_callback_register(desc, (void *) call, priv, key);
}
int side_tracer_callback_variadic_register(struct side_event_description *desc,
side_tracer_callback_variadic_func call_variadic,
- void *priv)
+ void *priv, void *key)
{
if (!(desc->flags & SIDE_EVENT_FLAG_VARIADIC))
return SIDE_ERROR_INVAL;
- return _side_tracer_callback_register(desc, (void *) call_variadic, priv);
+ return _side_tracer_callback_register(desc, (void *) call_variadic, priv, key);
}
static int _side_tracer_callback_unregister(struct side_event_description *desc,
- void *call, void *priv)
+ void *call, void *priv, void *key)
{
struct side_event_state *event_state;
struct side_callback *old_cb, *new_cb;
if (side_unlikely(event_state->version != 0))
abort();
es0 = side_container_of(event_state, struct side_event_state_0, parent);
- cb_pos = side_tracer_callback_lookup(desc, call, priv);
+ cb_pos = side_tracer_callback_lookup(desc, call, priv, key);
if (!cb_pos) {
ret = SIDE_ERROR_NOENT;
goto unlock;
int side_tracer_callback_unregister(struct side_event_description *desc,
side_tracer_callback_func call,
- void *priv)
+ void *priv, void *key)
{
if (desc->flags & SIDE_EVENT_FLAG_VARIADIC)
return SIDE_ERROR_INVAL;
- return _side_tracer_callback_unregister(desc, (void *) call, priv);
+ return _side_tracer_callback_unregister(desc, (void *) call, priv, key);
}
int side_tracer_callback_variadic_unregister(struct side_event_description *desc,
side_tracer_callback_variadic_func call_variadic,
- void *priv)
+ void *priv, void *key)
{
if (!(desc->flags & SIDE_EVENT_FLAG_VARIADIC))
return SIDE_ERROR_INVAL;
- return _side_tracer_callback_unregister(desc, (void *) call_variadic, priv);
+ return _side_tracer_callback_unregister(desc, (void *) call_variadic, priv, key);
}
struct side_events_register_handle *side_events_register(struct side_event_description **events, uint32_t nr_events)