X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fsession.c;h=138f4222263ebc6b1027df1b92348144429951d4;hb=4399cc0f41077cd975601a095fd272a2bf27bb99;hp=a3f6a86d3ef8226659f67f5fc222ed44726bf14c;hpb=1190c65397e8246bd3b437006bacc5b7dc9d2bde;p=libsigrok.git
diff --git a/src/session.c b/src/session.c
index a3f6a86d..138f4222 100644
--- a/src/session.c
+++ b/src/session.c
@@ -17,12 +17,13 @@
* along with this program. If not, see .
*/
+#include
#include
#include
#include
#include
#include
-#include "libsigrok.h"
+#include
#include "libsigrok-internal.h"
/** @cond PRIVATE */
@@ -358,6 +359,22 @@ SR_API int sr_session_trigger_set(struct sr_session *session, struct sr_trigger
return SR_OK;
}
+static gboolean sr_session_check_aborted(struct sr_session *session)
+{
+ gboolean stop;
+
+ g_mutex_lock(&session->stop_mutex);
+ stop = session->abort_session;
+ if (stop) {
+ sr_session_stop_sync(session);
+ /* But once is enough. */
+ session->abort_session = FALSE;
+ }
+ g_mutex_unlock(&session->stop_mutex);
+
+ return stop;
+}
+
/**
* Call every device in the current session's callback.
*
@@ -370,9 +387,8 @@ SR_API int sr_session_trigger_set(struct sr_session *session, struct sr_trigger
* sources to fire an event on the file descriptors, or
* any of their timeouts to activate. In other words, this
* can be used as a select loop.
- * If FALSE, all sources have their callback run, regardless
- * of file descriptor or timeout status.
- *
+ * If FALSE, return immediately if none of the sources has
+ * events pending.
* @retval SR_OK Success.
* @retval SR_ERR Error occurred.
*/
@@ -380,6 +396,11 @@ static int sr_session_iteration(struct sr_session *session, gboolean block)
{
unsigned int i;
int ret, timeout;
+ int revents;
+ gboolean stop_checked;
+ gboolean stopped;
+ struct source *source;
+ GPollFD *pollfd;
#ifdef HAVE_LIBUSB_1_0
int usb_timeout;
struct timeval tv;
@@ -389,7 +410,6 @@ static int sr_session_iteration(struct sr_session *session, gboolean block)
#ifdef HAVE_LIBUSB_1_0
if (session->ctx->usb_source_present) {
- timeout = block ? 0 : session->source_timeout;
ret = libusb_get_next_timeout(session->ctx->libusb_ctx, &tv);
if (ret < 0) {
sr_err("Error getting libusb timeout: %s",
@@ -403,34 +423,49 @@ static int sr_session_iteration(struct sr_session *session, gboolean block)
#endif
ret = g_poll(session->pollfds, session->num_sources, timeout);
+#ifdef G_OS_UNIX
+ if (ret < 0 && errno != EINTR) {
+ sr_err("Error in poll: %s", g_strerror(errno));
+ return SR_ERR;
+ }
+#else
+ if (ret < 0) {
+ sr_err("Error in poll: %d", ret);
+ return SR_ERR;
+ }
+#endif
+ stop_checked = FALSE;
+ stopped = FALSE;
+
for (i = 0; i < session->num_sources; i++) {
- if (session->pollfds[i].revents > 0 || (ret == 0
- && session->source_timeout == session->sources[i].timeout)) {
+ source = &session->sources[i];
+ pollfd = &session->pollfds[i];
+ revents = (ret > 0) ? pollfd->revents : 0;
+
+ if (revents > 0 || (ret == 0
+ && session->source_timeout == source->timeout)) {
/*
* Invoke the source's callback on an event,
* or if the poll timed out and this source
* asked for that timeout.
*/
- if (!session->sources[i].cb(session->pollfds[i].fd,
- session->pollfds[i].revents,
- session->sources[i].cb_data))
+ if (!source->cb(pollfd->fd, revents, source->cb_data))
sr_session_source_remove(session,
- session->sources[i].poll_object);
- }
- /*
- * We want to take as little time as possible to stop
- * the session if we have been told to do so. Therefore,
- * we check the flag after processing every source, not
- * just once per main event loop.
- */
- g_mutex_lock(&session->stop_mutex);
- if (session->abort_session) {
- sr_session_stop_sync(session);
- /* But once is enough. */
- session->abort_session = FALSE;
+ source->poll_object);
+ /*
+ * We want to take as little time as possible to stop
+ * the session if we have been told to do so. Therefore,
+ * we check the flag after processing every source, not
+ * just once per main event loop.
+ */
+ if (!stopped) {
+ stopped = sr_session_check_aborted(session);
+ stop_checked = TRUE;
+ }
}
- g_mutex_unlock(&session->stop_mutex);
}
+ if (!stop_checked)
+ sr_session_check_aborted(session);
return SR_OK;
}
@@ -663,16 +698,20 @@ static void datafeed_dump(const struct sr_datafeed_packet *packet)
const struct sr_datafeed_analog *analog;
const struct sr_datafeed_analog2 *analog2;
+ /* Please use the same order as in libsigrok.h. */
switch (packet->type) {
case SR_DF_HEADER:
sr_dbg("bus: Received SR_DF_HEADER packet.");
break;
- case SR_DF_TRIGGER:
- sr_dbg("bus: Received SR_DF_TRIGGER packet.");
+ case SR_DF_END:
+ sr_dbg("bus: Received SR_DF_END packet.");
break;
case SR_DF_META:
sr_dbg("bus: Received SR_DF_META packet.");
break;
+ case SR_DF_TRIGGER:
+ sr_dbg("bus: Received SR_DF_TRIGGER packet.");
+ break;
case SR_DF_LOGIC:
logic = packet->payload;
sr_dbg("bus: Received SR_DF_LOGIC packet (%" PRIu64 " bytes, "
@@ -683,20 +722,17 @@ static void datafeed_dump(const struct sr_datafeed_packet *packet)
sr_dbg("bus: Received SR_DF_ANALOG packet (%d samples).",
analog->num_samples);
break;
- case SR_DF_ANALOG2:
- analog2 = packet->payload;
- sr_dbg("bus: Received SR_DF_ANALOG2 packet (%d samples).",
- analog2->num_samples);
- break;
- case SR_DF_END:
- sr_dbg("bus: Received SR_DF_END packet.");
- break;
case SR_DF_FRAME_BEGIN:
sr_dbg("bus: Received SR_DF_FRAME_BEGIN packet.");
break;
case SR_DF_FRAME_END:
sr_dbg("bus: Received SR_DF_FRAME_END packet.");
break;
+ case SR_DF_ANALOG2:
+ analog2 = packet->payload;
+ sr_dbg("bus: Received SR_DF_ANALOG2 packet (%d samples).",
+ analog2->num_samples);
+ break;
default:
sr_dbg("bus: Received unknown packet type: %d.", packet->type);
break;
@@ -769,6 +805,7 @@ SR_PRIV int sr_session_send(const struct sr_dev_inst *sdi,
packet_in = packet_out;
}
}
+ packet = packet_in;
/*
* If the last transform did output a packet, pass it to all datafeed
@@ -854,6 +891,7 @@ SR_API int sr_session_source_add(struct sr_session *session, int fd,
p.fd = fd;
p.events = events;
+ p.revents = 0;
return _sr_session_source_add(session, &p, timeout, cb, cb_data, (gintptr)fd);
}
@@ -906,6 +944,7 @@ SR_API int sr_session_source_add_channel(struct sr_session *session,
#else
p.fd = g_io_channel_unix_get_fd(channel);
p.events = events;
+ p.revents = 0;
#endif
return _sr_session_source_add(session, &p, timeout, cb, cb_data, (gintptr)channel);