diff options
author | Eric <ewild@sysmocom.de> | 2020-07-17 20:46:25 +0200 |
---|---|---|
committer | Eric <ewild@sysmocom.de> | 2020-08-26 17:35:18 +0200 |
commit | 056c5d8fab676340873a5a8327a3ac669734f6ee (patch) | |
tree | 71cbd75575e78a53b28644f3d8f175884fb82fb4 | |
parent | 6ada823b1a124f3e28199cd42bda311822b2640b (diff) |
ipc: manually poll chan sock fds
We can't wait, we're in select, but we need to wait for a response from
the other side of the ipc interface -> only select our channels, so
other registered osmo fds are left alone, and we don't accidentally
handle stuff that should happen afterwards.
Change-Id: I4ffc8d825e5b4eba0fca8ea821b1d84e2b923266
-rw-r--r-- | Transceiver52M/device/ipc/IPCDevice.cpp | 78 | ||||
-rw-r--r-- | Transceiver52M/device/ipc/IPCDevice.h | 1 |
2 files changed, 62 insertions, 17 deletions
diff --git a/Transceiver52M/device/ipc/IPCDevice.cpp b/Transceiver52M/device/ipc/IPCDevice.cpp index febd668..b1a747c 100644 --- a/Transceiver52M/device/ipc/IPCDevice.cpp +++ b/Transceiver52M/device/ipc/IPCDevice.cpp @@ -837,6 +837,42 @@ out_close: return -1; } +void IPCDevice::manually_poll_sock_fds() { + struct timeval wait = {0, 100000}; + fd_set crfds, cwfds; + int max_fd = 0; + + FD_ZERO(&crfds); + FD_ZERO(&cwfds); + for(int i = 0; i < chans; i++) { + struct osmo_fd* curr_fd = &sk_chan_state[i].conn_bfd; + max_fd = curr_fd->fd > max_fd ? curr_fd->fd : max_fd; + + if(curr_fd->when & OSMO_FD_READ) + FD_SET(curr_fd->fd, &crfds); + if(curr_fd->when & OSMO_FD_WRITE) + FD_SET(curr_fd->fd, &cwfds); + } + + select(max_fd+1, &crfds, &cwfds, 0, &wait); + + for(int i = 0; i < chans; i++) { + int flags = 0; + struct osmo_fd* ofd = &sk_chan_state[i].conn_bfd; + + if (FD_ISSET(ofd->fd, &crfds)) { + flags |= OSMO_FD_READ; + FD_CLR(ofd->fd, &crfds); + } + + if (FD_ISSET(ofd->fd, &cwfds)) { + flags |= OSMO_FD_WRITE; + FD_CLR(ofd->fd, &cwfds); + } + if(flags) + ipc_chan_sock_cb(ofd, flags); + } +} /* the call stack is rather difficult here, we're already in select: >~"#0 IPCDevice::start (this=<optimized out>) at IPCDevice.cpp:789\n" >~"#1 in RadioInterface::start (this=0x614000001640) at radioInterface.cpp:187\n" @@ -859,6 +895,7 @@ bool IPCDevice::start() struct msgb *msg; struct ipc_sk_chan_if *ipc_prim; + struct timeval timer_now, timeout; for(int i = 0; i < chans; i++) { msg = ipc_msgb_alloc(IPC_IF_MSG_START_REQ); @@ -870,23 +907,26 @@ bool IPCDevice::start() ipc_sock_send(&sk_chan_state[i], msg); } - int chan_started_count = 0, retrycount = 0; - while (chan_started_count != chans && retrycount < 5) { + gettimeofday(&timeout, 0); + timeout.tv_sec += 2; + + int chan_started_count = 0; + while (chan_started_count != chans) { chan_started_count = 0; /* just poll here, we're already in select, so there is no other way to drive * the fds and "wait" for a response or retry */ - usleep(100000); - osmo_select_main(1); + manually_poll_sock_fds(); for(unsigned int i = 0; i < ARRAY_SIZE(trx_is_started); i++) if(trx_is_started[i] == true) chan_started_count++; - retrycount++; + + gettimeofday(&timer_now, 0); + if(timercmp(&timer_now, &timeout, >)) + return false; } - if(retrycount >= 5) - return false; int max_bufs_to_flush = 0; for(unsigned int i = 0; i < shm_dec->num_chans; i++) { @@ -903,6 +943,7 @@ bool IPCDevice::stop() { struct msgb *msg; struct ipc_sk_chan_if *ipc_prim; + struct timeval timer_now, timeout; if (!started) return true; @@ -915,30 +956,33 @@ bool IPCDevice::stop() ipc_prim = (struct ipc_sk_chan_if *)msg->data; ipc_prim->u.start_req.dummy = 0; - ipc_sock_send(&sk_chan_state[i], msg); } } - int chan_started_count = 0, retrycount = 0; + gettimeofday(&timeout, 0); + timeout.tv_sec += 2; + + int chan_started_count = 0; do { chan_started_count = 0; /* just poll here, we're already in select, so there is no other way to drive * the fds and "wait" for a response or retry */ - usleep(100000); - osmo_select_main(1); + manually_poll_sock_fds(); for(unsigned int i = 0; i < ARRAY_SIZE(trx_is_started); i++) if(trx_is_started[i] == true) chan_started_count++; - retrycount++; - } while (chan_started_count > 0 && retrycount < 5); - if(retrycount > 4) - LOGC(DDEV, ERR) << "No response to stop msg received, terminating anyway..."; - else - LOGC(DDEV, NOTICE) << "All chanels stopped, termianting..."; + gettimeofday(&timer_now, 0); + if(timercmp(&timer_now, &timeout, >)) { + LOGC(DDEV, ERR) << "No response to stop msg received, terminating anyway..."; + break; + } + } while (chan_started_count > 0); + + LOGC(DDEV, NOTICE) << "All chanels stopped, terminating..."; /* reset internal buffer timestamps */ for (size_t i = 0; i < rx_buffers.size(); i++) diff --git a/Transceiver52M/device/ipc/IPCDevice.h b/Transceiver52M/device/ipc/IPCDevice.h index 592b202..2429eee 100644 --- a/Transceiver52M/device/ipc/IPCDevice.h +++ b/Transceiver52M/device/ipc/IPCDevice.h @@ -82,6 +82,7 @@ class IPCDevice : public RadioDevice { virtual bool flush_recv(size_t num_pkts); void update_stream_stats_rx(size_t chan, bool *overrun); void update_stream_stats_tx(size_t chan, bool *underrun); + void manually_poll_sock_fds(); public: virtual void ipc_sock_close(ipc_sock_state *state); |