diff --git a/ports/unix/file.c b/ports/unix/file.c index 6c6e26b0b2..8a165283f7 100644 --- a/ports/unix/file.c +++ b/ports/unix/file.c @@ -35,6 +35,7 @@ #include "py/stream.h" #include "py/builtin.h" #include "py/mphal.h" +#include "py/mpthread.h" #include "fdfile.h" #if MICROPY_PY_IO && !MICROPY_VFS @@ -65,7 +66,9 @@ STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); + MP_THREAD_GIL_EXIT(); mp_int_t r = read(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); if (r == -1) { *errcode = errno; return MP_STREAM_ERROR; @@ -82,14 +85,18 @@ STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in return size; } #endif + MP_THREAD_GIL_EXIT(); mp_int_t r = write(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); while (r == -1 && errno == EINTR) { if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } + MP_THREAD_GIL_EXIT(); r = write(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); } if (r == -1) { *errcode = errno; @@ -104,7 +111,9 @@ STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i switch (request) { case MP_STREAM_SEEK: { struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg; + MP_THREAD_GIL_EXIT(); off_t off = lseek(o->fd, s->offset, s->whence); + MP_THREAD_GIL_ENTER(); if (off == (off_t)-1) { *errcode = errno; return MP_STREAM_ERROR; @@ -113,13 +122,18 @@ STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i return 0; } case MP_STREAM_FLUSH: - if (fsync(o->fd) < 0) { + MP_THREAD_GIL_EXIT(); + int ret = fsync(o->fd); + MP_THREAD_GIL_ENTER(); + if (ret == -1) { *errcode = errno; return MP_STREAM_ERROR; } return 0; case MP_STREAM_CLOSE: + MP_THREAD_GIL_EXIT(); close(o->fd); + MP_THREAD_GIL_ENTER(); #ifdef MICROPY_CPYTHON_COMPAT o->fd = -1; #endif @@ -198,7 +212,9 @@ STATIC mp_obj_t fdfile_open(const mp_obj_type_t *type, mp_arg_val_t *args) { } const char *fname = mp_obj_str_get_str(fid); + MP_THREAD_GIL_EXIT(); int fd = open(fname, mode_x | mode_rw, 0644); + MP_THREAD_GIL_ENTER(); if (fd == -1) { mp_raise_OSError(errno); } diff --git a/ports/unix/main.c b/ports/unix/main.c index 9147feb32d..fcf8b1558c 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -64,7 +64,9 @@ long heap_size = 1024*1024 * (sizeof(mp_uint_t) / 4); STATIC void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; + MP_THREAD_GIL_EXIT(); ssize_t dummy = write(STDERR_FILENO, str, len); + MP_THREAD_GIL_ENTER(); mp_uos_dupterm_tx_strn(str, len); (void)dummy; } diff --git a/ports/unix/modos.c b/ports/unix/modos.c index c3b0c20b2b..e5bd5da1eb 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -38,6 +38,7 @@ #include "py/runtime.h" #include "py/objtuple.h" #include "py/mphal.h" +#include "py/mpthread.h" #include "extmod/vfs.h" #include "extmod/misc.h" @@ -49,7 +50,9 @@ STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) { struct stat sb; const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); int res = stat(path, &sb); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(res, errno); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); @@ -89,7 +92,9 @@ STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) { STRUCT_STATVFS sb; const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); int res = STATVFS(path, &sb); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(res, errno); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); @@ -116,7 +121,9 @@ STATIC mp_obj_t mod_os_remove(mp_obj_t path_in) { // of that function. But Python remove() follows ANSI C, and explicitly // required to raise exception on attempt to remove a directory. Thus, // call POSIX unlink() here. + MP_THREAD_GIL_EXIT(); int r = unlink(path); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); @@ -128,7 +135,9 @@ STATIC mp_obj_t mod_os_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) { const char *old_path = mp_obj_str_get_str(old_path_in); const char *new_path = mp_obj_str_get_str(new_path_in); + MP_THREAD_GIL_EXIT(); int r = rename(old_path, new_path); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); @@ -139,7 +148,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_os_rename_obj, mod_os_rename); STATIC mp_obj_t mod_os_rmdir(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); int r = rmdir(path); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); @@ -150,7 +161,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_rmdir_obj, mod_os_rmdir); STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) { const char *cmd = mp_obj_str_get_str(cmd_in); + MP_THREAD_GIL_EXIT(); int r = system(cmd); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); @@ -170,11 +183,13 @@ MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_obj, mod_os_getenv); STATIC mp_obj_t mod_os_mkdir(mp_obj_t path_in) { // TODO: Accept mode param const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); #ifdef _WIN32 int r = mkdir(path); #else int r = mkdir(path, 0777); #endif + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); return mp_const_none; } @@ -192,13 +207,16 @@ STATIC mp_obj_t listdir_next(mp_obj_t self_in) { if (self->dir == NULL) { goto done; } + MP_THREAD_GIL_EXIT(); struct dirent *dirent = readdir(self->dir); if (dirent == NULL) { closedir(self->dir); + MP_THREAD_GIL_ENTER(); self->dir = NULL; done: return MP_OBJ_STOP_ITERATION; } + MP_THREAD_GIL_ENTER(); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); t->items[0] = mp_obj_new_str(dirent->d_name, strlen(dirent->d_name)); @@ -235,7 +253,9 @@ STATIC mp_obj_t mod_os_ilistdir(size_t n_args, const mp_obj_t *args) { } mp_obj_listdir_t *o = m_new_obj(mp_obj_listdir_t); o->base.type = &mp_type_polymorph_iter; + MP_THREAD_GIL_EXIT(); o->dir = opendir(path); + MP_THREAD_GIL_ENTER(); o->iternext = listdir_next; return MP_OBJ_FROM_PTR(o); } diff --git a/ports/unix/moduselect.c b/ports/unix/moduselect.c index d9b02ddc62..4a095ec292 100644 --- a/ports/unix/moduselect.c +++ b/ports/unix/moduselect.c @@ -39,6 +39,7 @@ #include "py/objlist.h" #include "py/objtuple.h" #include "py/mphal.h" +#include "py/mpthread.h" #include "fdfile.h" #define DEBUG 0 @@ -188,7 +189,9 @@ STATIC int poll_poll_internal(size_t n_args, const mp_obj_t *args) { self->flags = flags; + MP_THREAD_GIL_EXIT(); int n_ready = poll(self->entries, self->len, timeout); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(n_ready, errno); return n_ready; } diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 9b82378bb4..b436ddf7fc 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -45,6 +45,7 @@ #include "py/stream.h" #include "py/builtin.h" #include "py/mphal.h" +#include "py/mpthread.h" /* The idea of this module is to implement reasonable minimum of @@ -93,7 +94,9 @@ STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in); + MP_THREAD_GIL_EXIT(); mp_int_t r = read(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); if (r == -1) { int err = errno; // On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO @@ -110,7 +113,9 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in); + MP_THREAD_GIL_EXIT(); mp_int_t r = write(o->fd, buf, size); + MP_THREAD_GIL_ENTER(); if (r == -1) { int err = errno; // On blocking socket, we get EAGAIN in case SO_RCVTIMEO/SO_SNDTIMEO @@ -137,7 +142,9 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i // The rationale MicroPython follows is that close() just releases // file descriptor. If you're interested to catch I/O errors before // closing fd, fsync() it. + MP_THREAD_GIL_EXIT(); close(self->fd); + MP_THREAD_GIL_ENTER(); return 0; case MP_STREAM_GET_FILENO: @@ -159,7 +166,9 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); + MP_THREAD_GIL_ENTER(); int err = errno; if (r == -1 && self->blocking && err == EINPROGRESS) { // EINPROGRESS on a blocking socket means the operation timed out @@ -174,7 +183,9 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); return mp_const_none; } @@ -182,7 +193,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); + MP_THREAD_GIL_EXIT(); int r = listen(self->fd, MP_OBJ_SMALL_INT_VALUE(backlog_in)); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); return mp_const_none; } @@ -194,7 +207,9 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) { //struct sockaddr_storage addr; byte addr[32]; socklen_t addr_len = sizeof(addr); + MP_THREAD_GIL_EXIT(); int fd = accept(self->fd, (struct sockaddr*)&addr, &addr_len); + MP_THREAD_GIL_ENTER(); int err = errno; if (fd == -1 && self->blocking && err == EAGAIN) { // EAGAIN on a blocking socket means the operation timed out @@ -223,7 +238,9 @@ STATIC mp_obj_t socket_recv(size_t n_args, const mp_obj_t *args) { } byte *buf = m_new(byte, sz); + MP_THREAD_GIL_EXIT(); int out_sz = recv(self->fd, buf, sz, flags); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(out_sz, errno); mp_obj_t ret = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz); @@ -245,7 +262,9 @@ STATIC mp_obj_t socket_recvfrom(size_t n_args, const mp_obj_t *args) { socklen_t addr_len = sizeof(addr); byte *buf = m_new(byte, sz); + MP_THREAD_GIL_EXIT(); int out_sz = recvfrom(self->fd, buf, sz, flags, (struct sockaddr*)&addr, &addr_len); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(out_sz, errno); mp_obj_t buf_o = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz); @@ -272,7 +291,9 @@ STATIC mp_obj_t socket_send(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); int out_sz = send(self->fd, bufinfo.buf, bufinfo.len, flags); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(out_sz, errno); return MP_OBJ_NEW_SMALL_INT(out_sz); @@ -292,8 +313,10 @@ STATIC mp_obj_t socket_sendto(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo, addr_bi; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(dst_addr, &addr_bi, MP_BUFFER_READ); + MP_THREAD_GIL_EXIT(); int out_sz = sendto(self->fd, bufinfo.buf, bufinfo.len, flags, (struct sockaddr *)addr_bi.buf, addr_bi.len); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(out_sz, errno); return MP_OBJ_NEW_SMALL_INT(out_sz); @@ -319,7 +342,9 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { optval = bufinfo.buf; optlen = bufinfo.len; } + MP_THREAD_GIL_EXIT(); int r = setsockopt(self->fd, level, option, optval, optlen); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); return mp_const_none; } @@ -328,14 +353,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_s STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in); int val = mp_obj_is_true(flag_in); + MP_THREAD_GIL_EXIT(); int flags = fcntl(self->fd, F_GETFL, 0); - RAISE_ERRNO(flags, errno); + if (flags == -1) { + MP_THREAD_GIL_ENTER(); + RAISE_ERRNO(flags, errno); + } if (val) { flags &= ~O_NONBLOCK; } else { flags |= O_NONBLOCK; } flags = fcntl(self->fd, F_SETFL, flags); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(flags, errno); self->blocking = val; return mp_const_none; @@ -368,9 +398,14 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { if (new_blocking) { int r; + MP_THREAD_GIL_EXIT(); r = setsockopt(self->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); - RAISE_ERRNO(r, errno); + if (r == -1) { + MP_THREAD_GIL_ENTER(); + RAISE_ERRNO(r, errno); + } r = setsockopt(self->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval)); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(r, errno); } @@ -415,7 +450,9 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz } } + MP_THREAD_GIL_EXIT(); int fd = socket(family, type, proto); + MP_THREAD_GIL_ENTER(); RAISE_ERRNO(fd, errno); return MP_OBJ_FROM_PTR(socket_new(fd)); } @@ -537,7 +574,9 @@ STATIC mp_obj_t mod_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { } struct addrinfo *addr_list; + MP_THREAD_GIL_EXIT(); int res = getaddrinfo(host, serv, &hints, &addr_list); + MP_THREAD_GIL_ENTER(); if (res != 0) { // CPython: socket.gaierror diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index f435c3ff3c..2f01aff0f9 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -285,7 +285,12 @@ void mp_unix_mark_exec(void); #if MICROPY_PY_OS_DUPTERM #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #else -#define MP_PLAT_PRINT_STRN(str, len) do { ssize_t ret = write(1, str, len); (void)ret; } while (0) +#define MP_PLAT_PRINT_STRN(str, len) do { \ + MP_THREAD_GIL_EXIT(); \ + ssize_t ret = write(1, str, len); \ + MP_THREAD_GIL_ENTER(); \ + (void)ret; \ +} while (0) #endif #ifdef __linux__ diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 9b009dc502..3e14409efb 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -31,6 +31,7 @@ #include #include "py/mphal.h" +#include "py/mpthread.h" #include "py/runtime.h" #include "extmod/misc.h" @@ -160,7 +161,9 @@ int mp_hal_stdin_rx_chr(void) { } else { main_term:; #endif + MP_THREAD_GIL_EXIT(); int ret = read(0, &c, 1); + MP_THREAD_GIL_ENTER(); if (ret == 0) { c = 4; // EOF, ctrl-D } else if (c == '\n') { @@ -173,7 +176,9 @@ int mp_hal_stdin_rx_chr(void) { } void mp_hal_stdout_tx_strn(const char *str, size_t len) { + MP_THREAD_GIL_EXIT(); int ret = write(1, str, len); + MP_THREAD_GIL_ENTER(); mp_uos_dupterm_tx_strn(str, len); (void)ret; // to suppress compiler warning }