summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/unix/mpconfigport.h5
-rw-r--r--ports/unix/mpthreadport.c34
-rw-r--r--ports/unix/mpthreadport.h5
3 files changed, 32 insertions, 12 deletions
diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h
index 7991aba51..1d429bc42 100644
--- a/ports/unix/mpconfigport.h
+++ b/ports/unix/mpconfigport.h
@@ -342,4 +342,9 @@ void mp_unix_mark_exec(void);
#include <stdio.h>
#endif
+#if MICROPY_PY_THREAD
+#define MICROPY_BEGIN_ATOMIC_SECTION() (mp_thread_unix_begin_atomic_section(), 0)
+#define MICROPY_END_ATOMIC_SECTION(x) (void)x; mp_thread_unix_end_atomic_section()
+#endif
+
#endif // MICROPY_UNIX_MINIMAL
diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c
index c79521466..5012778be 100644
--- a/ports/unix/mpthreadport.c
+++ b/ports/unix/mpthreadport.c
@@ -60,7 +60,9 @@ typedef struct _thread_t {
STATIC pthread_key_t tls_key;
-// the mutex controls access to the linked list
+// The mutex is used for any code in this port that needs to be thread safe.
+// Specifically for thread management, access to the linked list is one example.
+// But also, e.g. scheduler state.
STATIC pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
STATIC thread_t *thread;
@@ -73,6 +75,14 @@ STATIC sem_t *thread_signal_done_p;
STATIC sem_t thread_signal_done;
#endif
+void mp_thread_unix_begin_atomic_section(void) {
+ pthread_mutex_lock(&thread_mutex);
+}
+
+void mp_thread_unix_end_atomic_section(void) {
+ pthread_mutex_unlock(&thread_mutex);
+}
+
// this signal handler is used to scan the regs and stack of a thread
STATIC void mp_thread_gc(int signo, siginfo_t *info, void *context) {
(void)info; // unused
@@ -123,14 +133,14 @@ void mp_thread_init(void) {
}
void mp_thread_deinit(void) {
- pthread_mutex_lock(&thread_mutex);
+ mp_thread_unix_begin_atomic_section();
while (thread->next != NULL) {
thread_t *th = thread;
thread = thread->next;
pthread_cancel(th->id);
free(th);
}
- pthread_mutex_unlock(&thread_mutex);
+ mp_thread_unix_end_atomic_section();
#if defined(__APPLE__)
sem_close(thread_signal_done_p);
sem_unlink(thread_signal_done_name);
@@ -146,7 +156,7 @@ void mp_thread_deinit(void) {
// the global root pointers (in mp_state_ctx) while another thread is doing a
// garbage collection and tracing these pointers.
void mp_thread_gc_others(void) {
- pthread_mutex_lock(&thread_mutex);
+ mp_thread_unix_begin_atomic_section();
for (thread_t *th = thread; th != NULL; th = th->next) {
gc_collect_root(&th->arg, 1);
if (th->id == pthread_self()) {
@@ -162,7 +172,7 @@ void mp_thread_gc_others(void) {
sem_wait(&thread_signal_done);
#endif
}
- pthread_mutex_unlock(&thread_mutex);
+ mp_thread_unix_end_atomic_section();
}
mp_state_thread_t *mp_thread_get_state(void) {
@@ -175,14 +185,14 @@ void mp_thread_set_state(mp_state_thread_t *state) {
void mp_thread_start(void) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
- pthread_mutex_lock(&thread_mutex);
+ mp_thread_unix_begin_atomic_section();
for (thread_t *th = thread; th != NULL; th = th->next) {
if (th->id == pthread_self()) {
th->ready = 1;
break;
}
}
- pthread_mutex_unlock(&thread_mutex);
+ mp_thread_unix_end_atomic_section();
}
void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
@@ -217,13 +227,13 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
goto er;
}
- pthread_mutex_lock(&thread_mutex);
+ mp_thread_unix_begin_atomic_section();
// create thread
pthread_t id;
ret = pthread_create(&id, &attr, entry, arg);
if (ret != 0) {
- pthread_mutex_unlock(&thread_mutex);
+ mp_thread_unix_end_atomic_section();
goto er;
}
@@ -238,7 +248,7 @@ void mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) {
th->next = thread;
thread = th;
- pthread_mutex_unlock(&thread_mutex);
+ mp_thread_unix_end_atomic_section();
return;
@@ -247,7 +257,7 @@ er:
}
void mp_thread_finish(void) {
- pthread_mutex_lock(&thread_mutex);
+ mp_thread_unix_begin_atomic_section();
thread_t *prev = NULL;
for (thread_t *th = thread; th != NULL; th = th->next) {
if (th->id == pthread_self()) {
@@ -261,7 +271,7 @@ void mp_thread_finish(void) {
}
prev = th;
}
- pthread_mutex_unlock(&thread_mutex);
+ mp_thread_unix_end_atomic_section();
}
void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
diff --git a/ports/unix/mpthreadport.h b/ports/unix/mpthreadport.h
index dfd2975c2..a7dbe08c4 100644
--- a/ports/unix/mpthreadport.h
+++ b/ports/unix/mpthreadport.h
@@ -31,3 +31,8 @@ typedef pthread_mutex_t mp_thread_mutex_t;
void mp_thread_init(void);
void mp_thread_deinit(void);
void mp_thread_gc_others(void);
+
+// Unix version of "enable/disable IRQs".
+// Functions as a port-global lock for any code that must be serialised.
+void mp_thread_unix_begin_atomic_section(void);
+void mp_thread_unix_end_atomic_section(void);