int ret;
struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
- //struct ltt_ust_session *usess;
- //struct ltt_ust_channel *ustchan;
+ struct ltt_ust_session *usess;
/* Short cut */
ksession = session->kernel_session;
+ usess = session->ust_session;
if (!session->enabled)
return LTTCOMM_UST_START_FAIL;
kernel_wait_quiescent(kernel_tracer_fd);
}
-#ifdef DISABLE
- /* Stop each UST session */
- DBG("Stop UST tracing");
- cds_list_for_each_entry(usess, &session->ust_session_list.head, list) {
- /* Flush all buffers before stopping */
- ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj);
- if (ret < 0) {
- ERR("UST metadata flush failed");
- }
-
- cds_list_for_each_entry(ustchan, &usess->channels.head, list) {
- ret = ustctl_flush_buffer(usess->sock, ustchan->obj);
- if (ret < 0) {
- ERR("UST flush buffer error");
- }
- }
+ /* Flag session that trace should start automatically */
+ if (usess) {
+ usess->start_trace = 0;
- ret = ustctl_stop_session(usess->sock, usess->handle);
+ ret = ust_app_stop_trace_all(usess);
if (ret < 0) {
- ret = LTTCOMM_KERN_STOP_FAIL;
+ ret = LTTCOMM_UST_START_FAIL;
goto error;
}
-
- ustctl_wait_quiescent(usess->sock);
}
-#endif
ret = LTTCOMM_OK;
goto error_rcu_unlock;
}
+ /* upon restart, we skip the setup, already done */
+ if (ua_sess->started)
+ goto skip_setup;
+
ret = create_ust_app_metadata(ua_sess, usess->pathname, app);
if (ret < 0) {
goto error_rcu_unlock;
if (ret < 0) {
goto error_rcu_unlock;
}
+ ua_sess->started = 1;
+skip_setup:
/* This start the UST tracing */
ret = ustctl_start_session(app->key.sock, ua_sess->handle);
if (ret < 0) {
return -1;
}
+/*
+ * Stop tracing for a specific UST session and app.
+ */
+int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app)
+{
+ int ret = 0;
+ struct ust_app_session *ua_sess;
+
+ DBG("Stopping tracing for ust app pid %d", app->key.pid);
+
+ rcu_read_lock();
+
+ ua_sess = lookup_session_by_app(usess, app);
+ if (ua_sess == NULL) {
+ /* Only malloc can failed so something is really wrong */
+ goto error_rcu_unlock;
+ }
+
+#if 0 /* only useful when periodical flush will be supported */
+ /* need to keep a handle on shm in session for this. */
+ /* Flush all buffers before stopping */
+ ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj);
+ if (ret < 0) {
+ ERR("UST metadata flush failed");
+ }
+
+ cds_list_for_each_entry(ustchan, &usess->channels.head, list) {
+ ret = ustctl_flush_buffer(usess->sock, ustchan->obj);
+ if (ret < 0) {
+ ERR("UST flush buffer error");
+ }
+ }
+#endif
+
+ /* This inhibits UST tracing */
+ ret = ustctl_stop_session(app->key.sock, ua_sess->handle);
+ if (ret < 0) {
+ ERR("Error stopping tracing for app pid: %d", app->key.pid);
+ goto error_rcu_unlock;
+ }
+
+ rcu_read_unlock();
+
+ /* Quiescent wait after stopping trace */
+ ustctl_wait_quiescent(app->key.sock);
+
+ return 0;
+
+error_rcu_unlock:
+ rcu_read_unlock();
+ return -1;
+}
+
/*
* Start tracing for the UST session.
*/
return 0;
}
+/*
+ * Start tracing for the UST session.
+ */
+int ust_app_stop_trace_all(struct ltt_ust_session *usess)
+{
+ int ret = 0;
+ struct cds_lfht_iter iter;
+ struct ust_app *app;
+
+ DBG("Stopping all UST traces");
+
+ rcu_read_lock();
+
+ cds_lfht_for_each_entry(ust_app_ht, &iter, app, node) {
+ ret = ust_app_stop_trace(usess, app);
+ if (ret < 0) {
+ /* Continue to next apps even on error */
+ continue;
+ }
+ }
+
+ rcu_read_unlock();
+
+ return 0;
+}
+
/*
* Add channels/events from UST global domain to registered apps at sock.
*/
struct ust_app_session {
int enabled;
+ /* started: has the session been in started state at any time ? */
+ int started; /* allows detection of start vs restart. */
int handle; /* Used has unique identifier */
unsigned int uid;
struct ltt_ust_metadata *metadata;
struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
unsigned long ust_app_list_count(void);
int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app);
+int ust_app_stop_trace(struct ltt_ust_session *usess, struct ust_app *app);
int ust_app_start_trace_all(struct ltt_ust_session *usess);
+int ust_app_stop_trace_all(struct ltt_ust_session *usess);
int ust_app_list_events(struct lttng_event **events);
void ust_app_global_update(struct ltt_ust_session *usess, int sock);