context: emit events for driver

Make new private events to monitor the state of driver nodes. This
can be used to implement profiling.
This commit is contained in:
Wim Taymans 2020-01-30 17:21:33 +01:00
parent 9f0c5d403e
commit cd21f5292b
3 changed files with 35 additions and 9 deletions

View file

@ -257,6 +257,7 @@ struct pw_context *pw_context_new(struct pw_loop *main_loop,
spa_list_init(&this->export_list);
spa_list_init(&this->driver_list);
spa_hook_list_init(&this->listener_list);
spa_hook_list_init(&this->driver_listener_list);
this->core = pw_context_create_core(this, pw_properties_copy(properties), 0);
if (this->core == NULL) {

View file

@ -780,7 +780,7 @@ static void dump_states(struct pw_impl_node *driver)
a->finish_time,
a->awake_time - a->signal_time,
a->finish_time - a->awake_time,
t->activation->status, t->activation->pending_sync);
a->status, a->pending_sync);
}
}
@ -1285,6 +1285,7 @@ static void update_position(struct pw_impl_node *node, int all_ready)
if (a->position.state == SPA_IO_POSITION_STATE_STARTING) {
if (!all_ready && --a->sync_left == 0) {
pw_log_warn(NAME" %p: sync timeout, going to RUNNING", node);
pw_context_driver_emit_timeout(node->context, node);
dump_states(node);
all_ready = true;
}
@ -1313,9 +1314,11 @@ static int node_ready(void *data, int status)
if (a->state[0].pending != 0) {
pw_log_warn(NAME" %p: graph not finished", node);
pw_context_driver_emit_incomplete(node->context, node);
dump_states(node);
node->rt.target.signal(node->rt.target.data);
}
pw_context_driver_emit_start(node->context, node);
sync_type = check_updates(node, &reposition_owner);
owner[0] = ATOMIC_LOAD(a->segment_owner[0]);
@ -1400,6 +1403,8 @@ static int node_xrun(void *data, uint64_t trigger, uint64_t delay, struct spa_po
pw_log_debug(NAME" %p: XRun! count:%u time:%"PRIu64" delay:%"PRIu64" max:%"PRIu64,
this, a->xrun_count, trigger, delay, a->max_delay);
pw_context_driver_emit_xrun(this->context, this);
return 0;
}

View file

@ -185,14 +185,6 @@ struct pw_global {
struct spa_list resource_list; /**< The list of resources of this global */
};
#define pw_context_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_context_events, m, v, ##__VA_ARGS__)
#define pw_context_emit_destroy(c) pw_context_emit(c, destroy, 0)
#define pw_context_emit_free(c) pw_context_emit(c, free, 0)
#define pw_context_emit_info_changed(c,i) pw_context_emit(c, info_changed, 0, i)
#define pw_context_emit_check_access(c,cl) pw_context_emit(c, check_access, 0, cl)
#define pw_context_emit_global_added(c,g) pw_context_emit(c, global_added, 0, g)
#define pw_context_emit_global_removed(c,g) pw_context_emit(c, global_removed, 0, g)
#define pw_core_resource(r,m,v,...) pw_resource_call(r, struct pw_core_events, m, v, ##__VA_ARGS__)
#define pw_core_resource_info(r,...) pw_core_resource(r,info,0,__VA_ARGS__)
#define pw_core_resource_done(r,...) pw_core_resource(r,done,0,__VA_ARGS__)
@ -223,10 +215,37 @@ pw_core_resource_errorf(struct pw_resource *resource, uint32_t id, int seq,
va_end(args);
}
#define pw_context_driver_emit(c,m,v,...) spa_hook_list_call_simple(&c->driver_listener_list, struct pw_context_driver_events, m, v, ##__VA_ARGS__)
#define pw_context_driver_emit_start(c,n) pw_context_driver_emit(c, start, 0, n)
#define pw_context_driver_emit_xrun(c,n) pw_context_driver_emit(c, xrun, 0, n)
#define pw_context_driver_emit_incomplete(c,n) pw_context_driver_emit(c, incomplete, 0, n)
#define pw_context_driver_emit_timeout(c,n) pw_context_driver_emit(c, timeout, 0, n)
struct pw_context_driver_events {
#define PW_VERSION_CONTEXT_DRIVER_EVENTS 0
uint32_t version;
/** The driver graph is started */
void (*start) (void *data, struct pw_impl_node *node);
/** The driver under/overruns */
void (*xrun) (void *data, struct pw_impl_node *node);
/** The driver could not complete the graph */
void (*incomplete) (void *data, struct pw_impl_node *node);
/** The driver got a sync timeout */
void (*timeout) (void *data, struct pw_impl_node *node);
};
#define pw_registry_resource(r,m,v,...) pw_resource_call(r, struct pw_registry_events,m,v,##__VA_ARGS__)
#define pw_registry_resource_global(r,...) pw_registry_resource(r,global,0,__VA_ARGS__)
#define pw_registry_resource_global_remove(r,...) pw_registry_resource(r,global_remove,0,__VA_ARGS__)
#define pw_context_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_context_events, m, v, ##__VA_ARGS__)
#define pw_context_emit_destroy(c) pw_context_emit(c, destroy, 0)
#define pw_context_emit_free(c) pw_context_emit(c, free, 0)
#define pw_context_emit_info_changed(c,i) pw_context_emit(c, info_changed, 0, i)
#define pw_context_emit_check_access(c,cl) pw_context_emit(c, check_access, 0, cl)
#define pw_context_emit_global_added(c,g) pw_context_emit(c, global_added, 0, g)
#define pw_context_emit_global_removed(c,g) pw_context_emit(c, global_removed, 0, g)
struct pw_context {
struct pw_impl_core *core; /**< core object */
@ -254,6 +273,7 @@ struct pw_context {
struct spa_list export_list; /**< list of export types */
struct spa_list driver_list; /**< list of driver nodes */
struct spa_hook_list driver_listener_list;
struct spa_hook_list listener_list;
struct pw_loop *main_loop; /**< main loop for control */