mirror of
git://sigrok.org/libserialport
synced 2023-08-10 21:13:24 +03:00
Move repetitive timeout code into helper functions.
This commit is contained in:
parent
9a7945af84
commit
32dbe2d298
156
serialport.c
156
serialport.c
@ -63,9 +63,18 @@ struct time {
|
|||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct timeout {
|
||||||
|
unsigned int ms;
|
||||||
|
struct time start, delta, now, end;
|
||||||
|
struct timeval delta_tv;
|
||||||
|
bool overflow;
|
||||||
|
};
|
||||||
|
|
||||||
#define TIME_ZERO {.tv = {0, 0}}
|
#define TIME_ZERO {.tv = {0, 0}}
|
||||||
#define TIME_MS(ms) {.tv = {ms / 1000, (ms % 1000) * 1000}}
|
#define TIME_MS(ms) {.tv = {ms / 1000, (ms % 1000) * 1000}}
|
||||||
|
|
||||||
|
const struct time max_delta = TIME_MS(INT_MAX);
|
||||||
|
|
||||||
static void time_get(struct time *time)
|
static void time_get(struct time *time)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
@ -119,6 +128,53 @@ static unsigned int time_as_ms(const struct time *time)
|
|||||||
return time->tv.tv_sec * 1000 + time->tv.tv_usec / 1000;
|
return time->tv.tv_sec * 1000 + time->tv.tv_usec / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void timeout_start(struct timeout *timeout, unsigned int timeout_ms)
|
||||||
|
{
|
||||||
|
timeout->ms = timeout_ms;
|
||||||
|
|
||||||
|
timeout->overflow = (timeout->ms > INT_MAX);
|
||||||
|
|
||||||
|
/* Get time at start of operation. */
|
||||||
|
time_get(&timeout->start);
|
||||||
|
/* Define duration of timeout. */
|
||||||
|
time_set_ms(&timeout->delta, timeout_ms);
|
||||||
|
/* Calculate time at which we should give up. */
|
||||||
|
time_add(&timeout->start, &timeout->delta, &timeout->end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool timeout_check(struct timeout *timeout)
|
||||||
|
{
|
||||||
|
if (timeout->ms == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
time_get(&timeout->now);
|
||||||
|
time_sub(&timeout->end, &timeout->now, &timeout->delta);
|
||||||
|
if ((timeout->overflow = time_greater(&timeout->delta, &max_delta)))
|
||||||
|
timeout->delta = max_delta;
|
||||||
|
|
||||||
|
return time_greater(&timeout->now, &timeout->end);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct timeval *timeout_timeval(struct timeout *timeout)
|
||||||
|
{
|
||||||
|
if (timeout->ms == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
time_as_timeval(&timeout->delta, &timeout->delta_tv);
|
||||||
|
|
||||||
|
return &timeout->delta_tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int timeout_remaining_ms(struct timeout *timeout)
|
||||||
|
{
|
||||||
|
if (timeout->ms == 0)
|
||||||
|
return -1;
|
||||||
|
else if (timeout->overflow)
|
||||||
|
return INT_MAX;
|
||||||
|
else
|
||||||
|
return time_as_ms(&timeout->delta);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
|
SP_API enum sp_return sp_get_port_by_name(const char *portname, struct sp_port **port_ptr)
|
||||||
@ -887,19 +943,12 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
|
|||||||
#else
|
#else
|
||||||
size_t bytes_written = 0;
|
size_t bytes_written = 0;
|
||||||
unsigned char *ptr = (unsigned char *) buf;
|
unsigned char *ptr = (unsigned char *) buf;
|
||||||
struct time start, delta, now, end = TIME_ZERO;
|
struct timeout timeout;
|
||||||
int started = 0;
|
int started = 0;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (timeout_ms) {
|
timeout_start(&timeout, timeout_ms);
|
||||||
/* Get time at start of operation. */
|
|
||||||
time_get(&start);
|
|
||||||
/* Define duration of timeout. */
|
|
||||||
time_set_ms(&delta, timeout_ms);
|
|
||||||
/* Calculate time at which we should give up. */
|
|
||||||
time_add(&start, &delta, &end);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(port->fd, &fds);
|
FD_SET(port->fd, &fds);
|
||||||
@ -911,16 +960,10 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf,
|
|||||||
* to avoid any issues if a short timeout is reached before
|
* to avoid any issues if a short timeout is reached before
|
||||||
* select() is even run.
|
* select() is even run.
|
||||||
*/
|
*/
|
||||||
struct timeval tv;
|
if (started && timeout_check(&timeout))
|
||||||
if (timeout_ms && started) {
|
|
||||||
time_get(&now);
|
|
||||||
if (time_greater(&now, &end))
|
|
||||||
/* Timeout has expired. */
|
|
||||||
break;
|
break;
|
||||||
time_sub(&end, &now, &delta);
|
|
||||||
time_as_timeval(&delta, &tv);
|
result = select(port->fd + 1, NULL, &fds, NULL, timeout_timeval(&timeout));
|
||||||
}
|
|
||||||
result = select(port->fd + 1, NULL, &fds, NULL, timeout_ms ? &tv : NULL);
|
|
||||||
started = 1;
|
started = 1;
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
@ -1108,19 +1151,12 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
|
|||||||
#else
|
#else
|
||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
unsigned char *ptr = (unsigned char *) buf;
|
unsigned char *ptr = (unsigned char *) buf;
|
||||||
struct time start, delta, now, end = TIME_ZERO;
|
struct timeout timeout;
|
||||||
int started = 0;
|
int started = 0;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (timeout_ms) {
|
timeout_start(&timeout, timeout_ms);
|
||||||
/* Get time at start of operation. */
|
|
||||||
time_get(&start);
|
|
||||||
/* Define duration of timeout. */
|
|
||||||
time_set_ms(&delta, timeout_ms);
|
|
||||||
/* Calculate time at which we should give up. */
|
|
||||||
time_add(&start, &delta, &end);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(port->fd, &fds);
|
FD_SET(port->fd, &fds);
|
||||||
@ -1132,16 +1168,11 @@ SP_API enum sp_return sp_blocking_read(struct sp_port *port, void *buf,
|
|||||||
* to avoid any issues if a short timeout is reached before
|
* to avoid any issues if a short timeout is reached before
|
||||||
* select() is even run.
|
* select() is even run.
|
||||||
*/
|
*/
|
||||||
struct timeval tv;
|
if (started && timeout_check(&timeout))
|
||||||
if (timeout_ms && started) {
|
|
||||||
time_get(&now);
|
|
||||||
if (time_greater(&now, &end))
|
|
||||||
/* Timeout has expired. */
|
/* Timeout has expired. */
|
||||||
break;
|
break;
|
||||||
time_sub(&end, &now, &delta);
|
|
||||||
time_as_timeval(&delta, &tv);
|
result = select(port->fd + 1, &fds, NULL, NULL, timeout_timeval(&timeout));
|
||||||
}
|
|
||||||
result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &tv : NULL);
|
|
||||||
started = 1;
|
started = 1;
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
@ -1246,19 +1277,12 @@ SP_API enum sp_return sp_blocking_read_next(struct sp_port *port, void *buf,
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
struct time start, delta, now, end = TIME_ZERO;
|
struct timeout timeout;
|
||||||
int started = 0;
|
int started = 0;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (timeout_ms) {
|
timeout_start(&timeout, timeout_ms);
|
||||||
/* Get time at start of operation. */
|
|
||||||
time_get(&start);
|
|
||||||
/* Define duration of timeout. */
|
|
||||||
time_set_ms(&delta, timeout_ms);
|
|
||||||
/* Calculate time at which we should give up. */
|
|
||||||
time_add(&start, &delta, &end);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(port->fd, &fds);
|
FD_SET(port->fd, &fds);
|
||||||
@ -1270,16 +1294,11 @@ SP_API enum sp_return sp_blocking_read_next(struct sp_port *port, void *buf,
|
|||||||
* to avoid any issues if a short timeout is reached before
|
* to avoid any issues if a short timeout is reached before
|
||||||
* select() is even run.
|
* select() is even run.
|
||||||
*/
|
*/
|
||||||
struct timeval tv;
|
if (started && timeout_check(&timeout))
|
||||||
if (timeout_ms && started) {
|
|
||||||
time_get(&now);
|
|
||||||
if (time_greater(&now, &end))
|
|
||||||
/* Timeout has expired. */
|
/* Timeout has expired. */
|
||||||
break;
|
break;
|
||||||
time_sub(&end, &now, &delta);
|
|
||||||
time_as_timeval(&delta, &tv);
|
result = select(port->fd + 1, &fds, NULL, NULL, timeout_timeval(&timeout));
|
||||||
}
|
|
||||||
result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &tv : NULL);
|
|
||||||
started = 1;
|
started = 1;
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
@ -1530,10 +1549,8 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
|
|||||||
|
|
||||||
RETURN_OK();
|
RETURN_OK();
|
||||||
#else
|
#else
|
||||||
struct time start, delta, now, end = TIME_ZERO;
|
struct timeout timeout;
|
||||||
const struct time max_delta = TIME_MS(INT_MAX);
|
int started = 0, result;
|
||||||
int started = 0, timeout_overflow = 0;
|
|
||||||
int result, timeout_remaining_ms;
|
|
||||||
struct pollfd *pollfds;
|
struct pollfd *pollfds;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -1552,14 +1569,7 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
|
|||||||
pollfds[i].events |= POLLERR;
|
pollfds[i].events |= POLLERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout_ms) {
|
timeout_start(&timeout, timeout_ms);
|
||||||
/* Get time at start of operation. */
|
|
||||||
time_get(&start);
|
|
||||||
/* Define duration of timeout. */
|
|
||||||
time_set_ms(&delta, timeout_ms);
|
|
||||||
/* Calculate time at which we should give up. */
|
|
||||||
time_add(&start, &delta, &end);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop until an event occurs. */
|
/* Loop until an event occurs. */
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -1568,24 +1578,12 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
|
|||||||
* to avoid any issues if a short timeout is reached before
|
* to avoid any issues if a short timeout is reached before
|
||||||
* poll() is even run.
|
* poll() is even run.
|
||||||
*/
|
*/
|
||||||
if (!timeout_ms) {
|
if (started && timeout_check(&timeout)) {
|
||||||
timeout_remaining_ms = -1;
|
|
||||||
} else if (!started) {
|
|
||||||
timeout_overflow = (timeout_ms > INT_MAX);
|
|
||||||
timeout_remaining_ms = timeout_overflow ? INT_MAX : timeout_ms;
|
|
||||||
} else {
|
|
||||||
time_get(&now);
|
|
||||||
if (time_greater(&now, &end)) {
|
|
||||||
DEBUG("Wait timed out");
|
DEBUG("Wait timed out");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
time_sub(&end, &now, &delta);
|
|
||||||
if ((timeout_overflow = time_greater(&delta, &max_delta)))
|
|
||||||
delta = max_delta;
|
|
||||||
timeout_remaining_ms = time_as_ms(&delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = poll(pollfds, event_set->count, timeout_remaining_ms);
|
result = poll(pollfds, event_set->count, timeout_remaining_ms(&timeout));
|
||||||
started = 1;
|
started = 1;
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
@ -1598,7 +1596,7 @@ SP_API enum sp_return sp_wait(struct sp_event_set *event_set,
|
|||||||
}
|
}
|
||||||
} else if (result == 0) {
|
} else if (result == 0) {
|
||||||
DEBUG("poll() timed out");
|
DEBUG("poll() timed out");
|
||||||
if (!timeout_overflow)
|
if (!timeout.overflow)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
DEBUG("poll() completed");
|
DEBUG("poll() completed");
|
||||||
|
Loading…
Reference in New Issue
Block a user