aboutsummaryrefslogtreecommitdiff
path: root/extmod/modlwip.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2019-02-22 21:54:58 +1100
committerDamien George <damien.p.george@gmail.com>2019-02-26 23:32:19 +1100
commit39ea132e1daf851b962780cf122f41800b9e9a33 (patch)
tree2ff1a782d9365e082988769b6299c14dfc2ec11a /extmod/modlwip.c
parentcc63e19332bb8bf4134ef27116deeb1935ddf365 (diff)
extmod/modlwip: Add concurrency protection macros.
Some users of this module may require the LwIP stack to run at an elevated priority, to protect against concurrency issues with processing done by the underlying network interface. Since LwIP doesn't provide such protection it must be done here (the other option is to run LwIP in a separate thread, and use thread protection mechanisms, but that is a more heavyweight solution).
Diffstat (limited to 'extmod/modlwip.c')
-rw-r--r--extmod/modlwip.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index bd952111d..83104a487 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -447,9 +447,12 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
len = 0xffff;
}
+ MICROPY_PY_LWIP_ENTER
+
// FIXME: maybe PBUF_ROM?
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (p == NULL) {
+ MICROPY_PY_LWIP_EXIT
*_errno = MP_ENOMEM;
return -1;
}
@@ -467,6 +470,8 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
pbuf_free(p);
+ MICROPY_PY_LWIP_EXIT
+
// udp_sendto can return 1 on occasion for ESP8266 port. It's not known why
// but it seems that the send actually goes through without error in this case.
// So we treat such cases as a success until further investigation.
@@ -505,10 +510,14 @@ STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
struct pbuf *p = socket->incoming.pbuf;
+ MICROPY_PY_LWIP_ENTER
+
u16_t result = pbuf_copy_partial(p, buf, ((p->tot_len > len) ? len : p->tot_len), 0);
pbuf_free(p);
socket->incoming.pbuf = NULL;
+ MICROPY_PY_LWIP_EXIT
+
return (mp_uint_t) result;
}
@@ -526,11 +535,14 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
// Check for any pending errors
STREAM_ERROR_CHECK(socket);
+ MICROPY_PY_LWIP_ENTER
+
u16_t available = tcp_sndbuf(socket->pcb.tcp);
if (available == 0) {
// Non-blocking socket
if (socket->timeout == 0) {
+ MICROPY_PY_LWIP_EXIT
*_errno = MP_EAGAIN;
return MP_STREAM_ERROR;
}
@@ -543,11 +555,13 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
// reset) by error callback.
// Avoid sending too small packets, so wait until at least 16 bytes available
while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) {
+ MICROPY_PY_LWIP_EXIT
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
*_errno = MP_ETIMEDOUT;
return MP_STREAM_ERROR;
}
poll_sockets();
+ MICROPY_PY_LWIP_REENTER
}
// While we waited, something could happen
@@ -563,6 +577,8 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
err = tcp_output(socket->pcb.tcp);
}
+ MICROPY_PY_LWIP_EXIT
+
if (err != ERR_OK) {
*_errno = error_lookup_table[-err];
return MP_STREAM_ERROR;
@@ -608,6 +624,8 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
}
}
+ MICROPY_PY_LWIP_ENTER
+
assert(socket->pcb.tcp != NULL);
struct pbuf *p = socket->incoming.pbuf;
@@ -633,6 +651,8 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
}
tcp_recved(socket->pcb.tcp, len);
+ MICROPY_PY_LWIP_EXIT
+
return len;
}
@@ -865,16 +885,21 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
mp_raise_OSError(MP_EALREADY);
}
}
+
// Register our receive callback.
+ MICROPY_PY_LWIP_ENTER
tcp_recv(socket->pcb.tcp, _lwip_tcp_recv);
socket->state = STATE_CONNECTING;
err = tcp_connect(socket->pcb.tcp, &dest, port, _lwip_tcp_connected);
if (err != ERR_OK) {
+ MICROPY_PY_LWIP_EXIT
socket->state = STATE_NEW;
mp_raise_OSError(error_lookup_table[-err]);
}
socket->peer_port = (mp_uint_t)port;
memcpy(socket->peer, &dest, sizeof(socket->peer));
+ MICROPY_PY_LWIP_EXIT
+
// And now we wait...
if (socket->timeout != -1) {
for (mp_uint_t retries = socket->timeout / 100; retries--;) {
@@ -1209,6 +1234,8 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
mp_uint_t ret;
+ MICROPY_PY_LWIP_ENTER
+
if (request == MP_STREAM_POLL) {
uintptr_t flags = arg;
ret = 0;
@@ -1259,6 +1286,7 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
bool socket_is_listener = false;
if (socket->pcb.tcp == NULL) {
+ MICROPY_PY_LWIP_EXIT
return 0;
}
@@ -1305,6 +1333,8 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
ret = MP_STREAM_ERROR;
}
+ MICROPY_PY_LWIP_EXIT
+
return ret;
}
@@ -1452,7 +1482,10 @@ STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
getaddrinfo_state_t state;
state.status = 0;
+ MICROPY_PY_LWIP_ENTER
err_t ret = dns_gethostbyname(host, (ip_addr_t*)&state.ipaddr, lwip_getaddrinfo_cb, &state);
+ MICROPY_PY_LWIP_EXIT
+
switch (ret) {
case ERR_OK:
// cached