[collectd] [PATCH 4/5] sigrok: Use separate thread for all I/O
Bert Vermeulen
bert at biot.com
Mon Jul 22 18:21:20 CEST 2013
---
src/sigrok.c | 110 +++++++++++++++++++++++++++++++++++------------------------
1 file changed, 66 insertions(+), 44 deletions(-)
diff --git a/src/sigrok.c b/src/sigrok.c
index ea1e95e..89ef61c 100644
--- a/src/sigrok.c
+++ b/src/sigrok.c
@@ -19,15 +19,22 @@
#include "collectd.h"
#include "common.h"
#include "plugin.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <pthread.h>
+
#include <glib.h>
#include <libsigrok/libsigrok.h>
+/* Minimum interval between dispatches coming from this plugin. The RRD
+ * plugin, at least, complains when written to with sub-second intervals.*/
#define DEFAULT_MIN_WRITE_INTERVAL 1
+static pthread_t sr_thread;
+static int sr_thread_running = FALSE;
GSList *config_devices;
static struct sr_session *session = NULL;
static int num_devices;
@@ -222,34 +229,27 @@ static void plugin_feed_callback(const struct sr_dev_inst *sdi,
}
-static int plugin_read(user_data_t *ud)
-{
-
- sr_session_iteration(FALSE);
-
- return 0;
-}
-
-static int plugin_init(void)
+static void *thread_init(void *arg)
{
struct sr_dev_driver *drv, **drvlist;
struct sr_config *src;
GSList *devlist, *drvopts, *l;
struct config_device *cfdev;
- struct timespec ts;
int ret, i;
char hwident[512];
+ (void)arg;
+
sr_log_callback_set(cd_logger, NULL);
sr_log_loglevel_set(loglevel);
if ((ret = sr_init(&sr_ctx)) != SR_OK) {
ERROR("Failed to initialize libsigrok: %s.", sr_strerror(ret));
- return 1;
+ return NULL;
}
if (!(session = sr_session_new()))
- return 1;
+ return NULL;
num_devices = 0;
drvlist = sr_driver_list();
@@ -264,37 +264,37 @@ static int plugin_init(void)
}
if (!drv) {
ERROR("sigrok: Unknown driver '%s'.", cfdev->driver);
- return 1;
+ return NULL;
}
if (sr_driver_init(sr_ctx, drv) != SR_OK)
- return 1;
+ return NULL;
drvopts = NULL;
if (cfdev->conn) {
if (!(src = malloc(sizeof(struct sr_config))))
- return 1;
+ return NULL;
src->key = SR_CONF_CONN;
src->data = g_variant_new_string(cfdev->conn);
drvopts = g_slist_append(drvopts, src);
}
if (cfdev->serialcomm) {
if (!(src = malloc(sizeof(struct sr_config))))
- return 1;
+ return NULL;
src->key = SR_CONF_SERIALCOMM;
src->data = g_variant_new_string(cfdev->serialcomm);
drvopts = g_slist_append(drvopts, src);
}
devlist = sr_driver_scan(drv, drvopts);
g_slist_free_full(drvopts, (GDestroyNotify)free_drvopts);
- if (!devlist) {
- INFO("sigrok: No devices found.");
- return 0;
- }
+ if (!devlist)
+ /* No devices found for this driver. */
+ continue;
+
if (g_slist_length(devlist) > 1) {
INFO("sigrok: %d sigrok devices for device entry '%s': must be 1.",
g_slist_length(devlist), cfdev->name);
- return 1;
+ return NULL;
}
cfdev->sdi = devlist->data;
g_slist_free(devlist);
@@ -305,28 +305,54 @@ static int plugin_init(void)
INFO("sigrok: Device '%s' is a %s.", cfdev->name, hwident);
if (sr_dev_open(cfdev->sdi) != SR_OK)
- return 1;
+ return NULL;
if (sr_session_dev_add(cfdev->sdi) != SR_OK)
- return 1;
+ return NULL;
num_devices++;
}
if (num_devices > 0) {
/* Do this only when we're sure there's hardware to talk to. */
- ts.tv_sec = 0;
- ts.tv_nsec = 1000000L;
- plugin_register_complex_read("sigrok", "sigrok", plugin_read,
- &ts, NULL);
-
if (sr_session_datafeed_callback_add(plugin_feed_callback, NULL) != SR_OK)
- return 1;
+ return NULL;
+ /* Start acquisition on all devices. */
if (sr_session_start() != SR_OK)
- return 1;
- } else
- sr_session_destroy();
+ return NULL;
+
+ /* Main loop, runs forever. */
+ sr_session_run();
+
+ sr_session_stop();
+ sr_session_dev_remove_all();
+ }
+
+ sr_session_destroy();
+
+ sr_exit(sr_ctx);
+
+ pthread_exit(NULL);
+ sr_thread_running = FALSE;
+
+ return NULL;
+}
+
+static int plugin_init(void)
+{
+ int status;
+
+ if (sr_thread_running) {
+ ERROR("sigrok: Thread already running.");
+ return -1;
+ }
+
+ if ((status = plugin_thread_create(&sr_thread, NULL, thread_init, NULL)) != 0) {
+ ERROR("sigrok: Failed to create thread: %s.", strerror(status));
+ return -1;
+ }
+ sr_thread_running = TRUE;
return 0;
}
@@ -336,24 +362,20 @@ static int plugin_shutdown(void)
struct config_device *cfdev;
GSList *l;
- if (num_devices > 0) {
- sr_session_stop();
- sr_session_dev_remove_all();
- sr_session_destroy();
+ if (sr_thread_running) {
+ pthread_cancel(sr_thread);
+ pthread_join(sr_thread, NULL);
}
for (l = config_devices; l; l = l->next) {
cfdev = l->data;
free(cfdev->name);
- if (cfdev->driver)
- free(cfdev->driver);
- if (cfdev->conn)
- free(cfdev->conn);
- if (cfdev->serialcomm)
- free(cfdev->serialcomm);
+ free(cfdev->driver);
+ free(cfdev->conn);
+ free(cfdev->serialcomm);
+ free(cfdev);
}
-
- sr_exit(sr_ctx);
+ g_slist_free(config_devices);
return 0;
}
--
1.8.1.2
More information about the collectd
mailing list