tcp: fix lock contention in tcp_write()
@@ -952,30 +952,16 @@ ssize_t tcp_write(tcpconn_t *c, const void *buf, size_t len)
size_t winlen;
ssize_t ret;
- spin_lock_np(&c->lock);
-
- /* block until there is an actionable event */
- while (!c->tx_closed &&
- (c->pcb.state < TCP_STATE_ESTABLISHED || c->tx_exclusive ||
- wraps_lte(c->pcb.snd_una + c->pcb.snd_wnd + 1, c->pcb.snd_nxt))) {
- waitq_wait(&c->tx_wq, &c->lock);
- }
-
- /* is the socket closed? */
- if (c->tx_closed) {
- spin_unlock_np(&c->lock);
- return c->err ? -c->err : -EPIPE;
- }
-
- /* an extra byte allows for window probing */
- winlen = c->pcb.snd_una + c->pcb.snd_wnd - c->pcb.snd_nxt + 1;
+ /* block until the data can be sent */
+ ret = tcp_write_wait(c, &winlen);
+ if (ret)
+ return ret;
/* actually send the data */
ret = tcp_tx_send(c, buf, MIN(len, winlen), true);
- c->ack_delayed = (ret < 0);
- tcp_timer_update(c);
- spin_unlock_np(&c->lock);
+ /* catch up on any pending work */
+ tcp_write_finish(c);
return ret;
}
