From: Daniel Lezcano Date: Wed, 27 May 2015 18:22:02 +0000 (+0200) Subject: baylibre-acme: Optimize reading of values from sysfs. X-Git-Tag: libsigrok-0.4.0~474 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=4e88b86cc81ce6569c4bbf947fc2f0f47f4ce8a1;p=libsigrok.git baylibre-acme: Optimize reading of values from sysfs. Opening a file has a cost (security, allocation, syscalls). The read_sample() function always does an open/read/close sequence. In order to optimize that, let's open the file at the moment the acquisition starts, close it when the acquisition stops and make read_sample() only lseek() to the beginning of the file and read the value. Signed-off-by: Daniel Lezcano Signed-off-by: Bartosz Golaszewski --- diff --git a/src/hardware/baylibre-acme/api.c b/src/hardware/baylibre-acme/api.c index 6827a16b..c91a9063 100644 --- a/src/hardware/baylibre-acme/api.c +++ b/src/hardware/baylibre-acme/api.c @@ -318,6 +318,34 @@ static int config_list(uint32_t key, GVariant **data, return ret; } +static void dev_acquisition_close(const struct sr_dev_inst *sdi) +{ + GSList *chl; + struct sr_channel *ch; + + for (chl = sdi->channels; chl; chl = chl->next) { + ch = chl->data; + bl_acme_close_channel(ch); + } +} + +static int dev_acquisition_open(const struct sr_dev_inst *sdi) +{ + GSList *chl; + struct sr_channel *ch; + + for (chl = sdi->channels; chl; chl = chl->next) { + ch = chl->data; + if (bl_acme_open_channel(ch)) { + sr_err("Error opening channel %s", ch->name); + dev_acquisition_close(sdi); + return SR_ERR; + } + } + + return 0; +} + static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; @@ -327,6 +355,9 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; + if (dev_acquisition_open(sdi)) + return SR_ERR; + devc = sdi->priv; devc->samples_read = 0; diff --git a/src/hardware/baylibre-acme/protocol.c b/src/hardware/baylibre-acme/protocol.c index f8fdb595..dfd634bb 100644 --- a/src/hardware/baylibre-acme/protocol.c +++ b/src/hardware/baylibre-acme/protocol.c @@ -33,6 +33,7 @@ struct channel_group_priv { struct channel_priv { int ch_type; + int fd; struct channel_group_priv *probe; }; @@ -494,10 +495,32 @@ static float adjust_data(int val, int type) static float read_sample(struct sr_channel *ch) { struct channel_priv *chp; - char path[64], *file, buf[16]; + char buf[16]; ssize_t len; int fd; + chp = ch->priv; + fd = chp->fd; + + lseek(fd, 0, SEEK_SET); + + len = read(fd, buf, sizeof(buf)); + if (len < 0) { + sr_err("Error reading from channel %s (hwmon: %s): %s", + ch->name, chp->probe->hwmon_num, strerror(errno)); + ch->enabled = FALSE; + return -1.0; + } + + return adjust_data(strtol(buf, NULL, 10), chp->ch_type); +} + +SR_PRIV int bl_acme_open_channel(struct sr_channel *ch) +{ + struct channel_priv *chp; + char path[64], *file; + int fd; + chp = ch->priv; switch (chp->ch_type) { @@ -508,27 +531,31 @@ static float read_sample(struct sr_channel *ch) case TEMP_OUT: file = "temp2_input"; break; default: sr_err("Invalid channel type: %d.", chp->ch_type); - return -1.0; + return SR_ERR; } snprintf(path, sizeof(path), "/sys/class/hwmon/hwmon%d/%s", chp->probe->hwmon_num, file); + fd = open(path, O_RDONLY); if (fd < 0) { sr_err("Error opening %s: %s", path, strerror(errno)); ch->enabled = FALSE; - return -1.0; + return SR_ERR; } - len = read(fd, buf, sizeof(buf)); - close(fd); - if (len < 0) { - sr_err("Error reading from %s: %s", path, strerror(errno)); - ch->enabled = FALSE; - return -1.0; - } + chp->fd = fd; - return adjust_data(strtol(buf, NULL, 10), chp->ch_type); + return 0; +} + +SR_PRIV void bl_acme_close_channel(struct sr_channel *ch) +{ + struct channel_priv *chp; + + chp = ch->priv; + close(chp->fd); + chp->fd = -1; } SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data) diff --git a/src/hardware/baylibre-acme/protocol.h b/src/hardware/baylibre-acme/protocol.h index 13c00fe6..4600211b 100644 --- a/src/hardware/baylibre-acme/protocol.h +++ b/src/hardware/baylibre-acme/protocol.h @@ -98,4 +98,7 @@ SR_PRIV int bl_acme_set_power_off(const struct sr_channel_group *cg, SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data); +SR_PRIV int bl_acme_open_channel(struct sr_channel *ch); + +SR_PRIV void bl_acme_close_channel(struct sr_channel *ch); #endif