diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2019-06-14 18:01:21 +0200 |
---|---|---|
committer | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2019-06-14 18:34:12 +0200 |
commit | dc0d7aad38f21629074416c2b2e8a5cf9c269785 (patch) | |
tree | 4f14a9643843baf1cf453ae91fabc9bd7f903266 | |
parent | 5d0b8b4ac73d434160c1b71a7922ad7309082a46 (diff) | |
download | microcom-dc0d7aad38f21629074416c2b2e8a5cf9c269785.tar.gz microcom-dc0d7aad38f21629074416c2b2e8a5cf9c269785.tar.xz |
can: Get rid of pthread for can transfers
Since there are ios specific read and write callbacks the needed overhead
for can transfers can be implemented in these which makes the separate
thread superfluous. This simplifies the can driver considerably.
As a consequence microcom doesn't need pthreads any more and the
respective changes in configure.ac can go away, too. The configuration
for lgtm which assert that the AX_PTHREAD macro is available can be
dropped and the travis configuration can be simplified accordingly.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Closes: https://github.com/pengutronix/microcom/issues/8
-rw-r--r-- | .travis.yml | 4 | ||||
-rw-r--r-- | can.c | 137 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | lgtm.yml | 5 |
4 files changed, 47 insertions, 105 deletions
diff --git a/.travis.yml b/.travis.yml index 87116f4..0723a3a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,6 @@ language: c compiler: gcc dist: trusty -addons: - apt: - packages: - - autoconf-archive script: - autoreconf -fi - ./configure @@ -15,7 +15,6 @@ * */ -#include <pthread.h> #include <stdlib.h> #include <string.h> #include <string.h> @@ -34,29 +33,59 @@ #include "microcom.h" -enum socket_local_enum { - SOCKET_CANSIDE, - SOCKET_TERMSIDE, - SOCKET_MAX, -}; - struct can_data { - int socket_can; - int socket_local[SOCKET_MAX]; int can_id; }; static struct can_data data; -static pthread_t can_thread; static ssize_t can_write(struct ios_ops *ios, const void *buf, size_t count) { - return write(ios->fd, buf, count); + size_t loopcount; + ssize_t ret = 0, err; + + struct can_frame to_can = { + .can_id = data.can_id, + }; + + while (count > 0) { + loopcount = min(count, sizeof(to_can.data)); + memcpy(to_can.data, buf, loopcount); + to_can.can_dlc = loopcount; +retry: + err = write(ios->fd, &to_can, sizeof(to_can)); + if (err < 0 && errno == EINTR) + goto retry; + + if (err < 0) + return err; + + assert(err < count); + buf += err; + count -= err; + ret += err; + } + + return ret; } static ssize_t can_read(struct ios_ops *ios, void *buf, size_t count) { - return read(ios->fd, buf, count); + struct can_frame from_can; + ssize_t ret; + +retry: + ret = read(ios->fd, &from_can, sizeof(from_can)); + if (ret < 0 && errno != EINTR) + goto retry; + + if (ret < 0) + return ret; + + assert(count >= from_can.can_dlc); + memcpy(buf, from_can.data, from_can.can_dlc); + + return from_can.can_dlc; } static int can_set_speed(struct ios_ops *ios, unsigned long speed) @@ -76,75 +105,10 @@ static int can_send_break(struct ios_ops *ios) static void can_exit(struct ios_ops *ios) { - shutdown(ios->fd, SHUT_RDWR); close(ios->fd); - pthread_join(can_thread, NULL); free(ios); } -static void *can_thread_fun(void *_data) -{ - struct can_data *data = _data; - struct can_frame to_can = { - .can_id = data->can_id, - }; - struct can_frame from_can; - fd_set ready; - int ret, fd_max; - - fd_max = max(data->socket_can, data->socket_local[SOCKET_CANSIDE]); - fd_max++; - - while (1) { - FD_ZERO(&ready); - FD_SET(data->socket_can, &ready); - FD_SET(data->socket_local[SOCKET_CANSIDE], &ready); - - ret = select(fd_max, &ready, NULL, NULL, NULL); - if (ret == -1) { - if (errno == EINTR) - continue; - goto exit; - } - - /* CAN -> TERMINAL */ - if (FD_ISSET(data->socket_can, &ready)) { - ret = read(data->socket_can, &from_can, sizeof(from_can)); - if ((ret == -1 && errno != EINTR) || - ret != sizeof(from_can)) - goto exit; - - ret = write(data->socket_local[SOCKET_CANSIDE], - from_can.data, from_can.can_dlc); - if ((ret == -1 && errno != EINTR) || - ret != from_can.can_dlc) - goto exit; - } - - /* TERMINAL -> CAN */ - if (FD_ISSET(data->socket_local[SOCKET_CANSIDE], &ready)) { - ret = read(data->socket_local[SOCKET_CANSIDE], - to_can.data, sizeof(to_can.data)); - if ((ret == -1 && errno != EINTR) || - ret == 0) - goto exit; - - to_can.can_dlc = ret; - ret = write(data->socket_can, &to_can, sizeof(to_can)); - if ((ret == -1 && errno != EINTR) || - ret != sizeof(to_can)) - goto exit; - } - } - - exit: - shutdown(data->socket_local[SOCKET_CANSIDE], SHUT_RDWR); - close(data->socket_local[SOCKET_CANSIDE]); - close(data->socket_can); - - return NULL; -} - struct ios_ops *can_init(char *interface_id) { struct ios_ops *ios; @@ -201,39 +165,30 @@ struct ios_ops *can_init(char *interface_id) /* no cleanups on failure, we exit anyway */ - data.socket_can = socket(PF_CAN, SOCK_RAW, CAN_RAW); - if (data.socket_can < 0) { + ios->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); + if (ios->fd < 0) { perror("socket"); return NULL; } - if (setsockopt(data.socket_can, SOL_CAN_RAW, CAN_RAW_FILTER, + if (setsockopt(ios->fd, SOL_CAN_RAW, CAN_RAW_FILTER, filter, sizeof(filter))) { perror("setsockopt"); return NULL; } strcpy(ifr.ifr_name, interface); - if (ioctl(data.socket_can, SIOCGIFINDEX, &ifr)) { + if (ioctl(ios->fd, SIOCGIFINDEX, &ifr)) { printf("%s: %s\n", interface, strerror(errno)); return NULL; } addr.can_ifindex = ifr.ifr_ifindex; - if (bind(data.socket_can, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + if (bind(ios->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return NULL; } - if (socketpair(AF_UNIX, SOCK_STREAM, 0, data.socket_local) < 0) { - perror("socketpair"); - return NULL; - } - - if (pthread_create(&can_thread, NULL, can_thread_fun, &data) != 0) - return NULL; - - ios->fd = data.socket_local[SOCKET_TERMSIDE]; printf("connected to %s (rx_id=%x, tx_id=%x)\n", interface, filter->can_id, data.can_id); diff --git a/configure.ac b/configure.ac index 18b4346..d1a90b6 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,6 @@ AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC -AX_PTHREAD AC_SYS_LARGEFILE # Checks for libraries. @@ -38,10 +37,7 @@ AS_IF([test "x$enable_can" != "xno"], ]) AS_IF([test "x$enable_can" = "xyes"], - [AC_DEFINE([USE_CAN], [1], [Define if can mode should be built-in]) - LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - CC="$PTHREAD_CC"]) + [AC_DEFINE([USE_CAN], [1], [Define if can mode should be built-in])]) AM_CONDITIONAL([CAN], [test "x$enable_can" = "xyes"]) diff --git a/lgtm.yml b/lgtm.yml deleted file mode 100644 index 3c21140..0000000 --- a/lgtm.yml +++ /dev/null @@ -1,5 +0,0 @@ -extraction: - cpp: - prepare: - packages: - - autoconf-archive |