Skip to content
Snippets Groups Projects
Commit 109f3a66 authored by Clemens Terasa's avatar Clemens Terasa
Browse files

serial: Add barrier to synchronize

Add a pthread barrier to synchronize the Rx/Tx threads and remove the
Tx pipe as it becomes useless.

This fixes the issue when the serial test is run inside bit.

BCS 746-000147
parent a4ecc2e2
Branches rocko
No related tags found
1 merge request!10serial: Add barrier to synchronize
......@@ -28,7 +28,7 @@ struct serial_test_data {
int result_error;
int result_package_duration;
int rx_ctrl_fds[2];
int tx_ctrl_fds[2];
pthread_barrier_t barrier;
};
enum{
......@@ -117,8 +117,6 @@ void cleanup(void * data)
{
struct serial_test_data * test_data = (struct serial_test_data * ) data;
close_fd(&test_data->tx_ctrl_fds[1]);
close_fd(&test_data->tx_ctrl_fds[0]);
close_fd(&test_data->rx_ctrl_fds[1]);
close_fd(&test_data->rx_ctrl_fds[0]);
close_fd(&test_data->tty_fd);
......@@ -248,9 +246,8 @@ static void * setup(int argc, char **argv)
if (pipe(test_data->rx_ctrl_fds))
goto error;
ioctl(test_data->rx_ctrl_fds[0], FIONBIO, &nbio);
if (pipe(test_data->tx_ctrl_fds))
goto error;
ioctl(test_data->tx_ctrl_fds[0], FIONBIO, &nbio);
/* Barrier fo the send and receive thread */
if (pthread_barrier_init(&test_data->barrier, NULL, 2)) { tst_print(TBROK, "Unable to create barrier. Error:%d, %s", errno, strerror(errno)); goto error; }
if (tcflush(test_data->tty_fd, TCIOFLUSH)) { tst_print(TBROK, "Unable to flush the serial file descriptor. Error:%d, %s", errno, strerror(errno)); goto error; }
return test_data;
......@@ -274,47 +271,22 @@ void *receive_thread(void *data)
};
tst_print(DEBUG, "%30s %d %s",__FILE__, __LINE__, __func__);
while (test_data->packages_sent < test_data->count) {
const int tx_send = TX_STATE_START_SENDING;
while (true) {
struct timeval timeout = timeout_const;
int pipe_status = RX_STATE_START;
int bytes_received = 0, duration = 0;
// Sync with transmitting thread
if(write(test_data->tx_ctrl_fds[1], &tx_send, sizeof(tx_send))<0)
tst_print(TBROK, "Unable to send tx sync signal %i %s", errno, strerror(errno));
do {
FD_ZERO(&rfds);
FD_SET(test_data->rx_ctrl_fds[0], &rfds);
timeout = timeout_const;
retval = select(test_data->rx_ctrl_fds[0]+1, &rfds, NULL, NULL, &timeout);
if (retval < 0) {
tst_print(TBROK, "Unable to synchonize RX thread: %i %s", errno, strerror(errno));
continue;
}
else if (retval == 0) {
tst_print(TINFO,"Rx sync timeout!");
continue;
}
if (FD_ISSET(test_data->rx_ctrl_fds[0], &rfds)) {
// Consume all signals
while(read(test_data->rx_ctrl_fds[0], &pipe_status, sizeof(pipe_status))>0) {
if (pipe_status == RX_STATE_EXIT)
return NULL;
}
}
} while (pipe_status != RX_STATE_RECEIVING);
pthread_barrier_wait(&test_data->barrier);
while(read(test_data->rx_ctrl_fds[0], &pipe_status, sizeof(pipe_status))>0) {
if (pipe_status == RX_STATE_EXIT)
return NULL;
}
gettimeofday( &rx_started, NULL);
while (bytes_received < test_data->nbytes) {
FD_ZERO(&rfds);
FD_SET(test_data->tty_fd, &rfds);
maxrfd = test_data->tty_fd;
// Let the timeout or reception handle the exit
if(pipe_status != RX_STATE_EXIT) {
FD_SET(test_data->rx_ctrl_fds[0], &rfds);
maxrfd = MAX(maxrfd, test_data->rx_ctrl_fds[0]);
}
timeout = timeout_const;
retval = select(maxrfd+1, &rfds, NULL, NULL, &timeout);
......@@ -347,15 +319,6 @@ void *receive_thread(void *data)
bytes_received += ret;
}
}
if(pipe_status != RX_STATE_EXIT &&
FD_ISSET(test_data->rx_ctrl_fds[0], &rfds)) {
int bytes_read = read(test_data->rx_ctrl_fds[0], &pipe_status, sizeof(pipe_status));
if (bytes_read != sizeof(pipe_status)) {
tst_print(TBROK, "Could not read bytes from input: %i %s", errno, strerror(errno));
}
if(write(test_data->rx_ctrl_fds[1], &pipe_status, sizeof(pipe_status))<0)
tst_print(TBROK, "Unable to re-send pipe status signal %i %s", errno, strerror(errno));
}
}
duration = time_ms_since( &rx_started );
// validate the data
......@@ -378,9 +341,8 @@ void *receive_thread(void *data)
void transmit(struct serial_test_data * test_data)
{
const int rx_state_exit = RX_STATE_EXIT;
const int rx_state_rcv = RX_STATE_RECEIVING;
int bytes_sent;
fd_set rfds, wfds;
fd_set wfds;
int retval=0;
const struct timeval timeout_const = {
.tv_sec=test_data->timeout/1000,
......@@ -390,7 +352,6 @@ void transmit(struct serial_test_data * test_data)
do{
struct timeval tx_timeout = timeout_const;
int pipe_status = TX_STATE_IDLE;
bytes_sent = 0;
......@@ -400,26 +361,7 @@ void transmit(struct serial_test_data * test_data)
// Sync with receiver thread
tcdrain(test_data->tty_fd);
do{
FD_ZERO(&rfds);
FD_SET(test_data->tx_ctrl_fds[0], &rfds);
tx_timeout = timeout_const;
retval = select(test_data->tx_ctrl_fds[0]+1, &rfds, NULL, NULL, &tx_timeout);
if (retval < 0) {
tst_print(TBROK, "Could not read bytes from input: %i %s", errno, strerror(errno));
continue;
}
else if (retval == 0) {
tst_print(TINFO,"Tx sync timeout!");
continue;
}
if (FD_ISSET(test_data->tx_ctrl_fds[0], &rfds)) {
// Consume all signals
while(read(test_data->tx_ctrl_fds[0], &pipe_status, sizeof(pipe_status))>0);
}
} while (pipe_status != TX_STATE_START_SENDING);
if(write(test_data->rx_ctrl_fds[1], &rx_state_rcv, sizeof(rx_state_rcv))<0)
tst_print(TBROK, "Unable to send rx sync signal %i %s", errno, strerror(errno));
pthread_barrier_wait(&test_data->barrier);
tst_print(DEBUG, "%d tx: Sending ...", __LINE__);
fill_transmit_buffer(test_data->send_buffer, test_data->nbytes);
......@@ -459,6 +401,7 @@ void transmit(struct serial_test_data * test_data)
if(write(test_data->rx_ctrl_fds[1], &rx_state_exit, sizeof(rx_state_exit))<0)
tst_print(TBROK, "Unable to send rx exit signal %i %s", errno, strerror(errno));
pthread_barrier_wait(&test_data->barrier);
return;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment