From 0eef971494cb29971e1ced6436b1dffd621d6039 Mon Sep 17 00:00:00 2001
From: Justine Tunney <jtunney@gmail.com>
Date: Sun, 28 Apr 2024 07:03:56 -0700
Subject: [PATCH] Add much of C11 threads.h API

---
 libc/BUILD.mk                 |  1 +
 libc/calls/pthread_yield_np.c |  1 +
 libc/intrin/cosmo_once.c      |  2 ++
 libc/isystem/threads.h        |  4 ++++
 libc/thread/pthread_equal.c   |  2 ++
 libc/thread/pthread_exit.c    |  2 ++
 libc/thread/pthread_self.c    |  2 ++
 libc/thread/thrd_create.c     | 35 ++++++++++++++++++++++++++++++++++
 libc/thread/thrd_detach.c     | 26 +++++++++++++++++++++++++
 libc/thread/thrd_join.c       | 29 ++++++++++++++++++++++++++++
 libc/thread/threads.h         | 36 +++++++++++++++++++++++++++++++++++
 third_party/BUILD.mk          |  1 +
 12 files changed, 141 insertions(+)
 create mode 100644 libc/isystem/threads.h
 create mode 100644 libc/thread/thrd_create.c
 create mode 100644 libc/thread/thrd_detach.c
 create mode 100644 libc/thread/thrd_join.c
 create mode 100644 libc/thread/threads.h

diff --git a/libc/BUILD.mk b/libc/BUILD.mk
index caff0ca1a..523020830 100644
--- a/libc/BUILD.mk
+++ b/libc/BUILD.mk
@@ -242,6 +242,7 @@ libc/isystem/system_error \
 libc/isystem/termios.h \
 libc/isystem/tgmath.h \
 libc/isystem/thread \
+libc/isystem/threads.h \
 libc/isystem/time.h \
 libc/isystem/tmmintrin.h \
 libc/isystem/tuple \
diff --git a/libc/calls/pthread_yield_np.c b/libc/calls/pthread_yield_np.c
index 079387712..dd209e6be 100644
--- a/libc/calls/pthread_yield_np.c
+++ b/libc/calls/pthread_yield_np.c
@@ -38,4 +38,5 @@ int pthread_yield_np(void) {
   return 0;
 }
 
+__weak_reference(pthread_yield_np, thrd_yield);
 __weak_reference(pthread_yield_np, pthread_yield);
diff --git a/libc/intrin/cosmo_once.c b/libc/intrin/cosmo_once.c
index a18edb2bb..a6658deb0 100644
--- a/libc/intrin/cosmo_once.c
+++ b/libc/intrin/cosmo_once.c
@@ -61,3 +61,5 @@ errno_t cosmo_once(atomic_uint *once, void init(void)) {
       return EINVAL;
   }
 }
+
+__weak_reference(cosmo_once, call_once);
diff --git a/libc/isystem/threads.h b/libc/isystem/threads.h
new file mode 100644
index 000000000..28df0eba9
--- /dev/null
+++ b/libc/isystem/threads.h
@@ -0,0 +1,4 @@
+#ifndef _THREADS_H
+#define _THREADS_H
+#include "libc/thread/threads.h"
+#endif /* _THREADS_H */
diff --git a/libc/thread/pthread_equal.c b/libc/thread/pthread_equal.c
index 30e1ff99a..4bef0a23e 100644
--- a/libc/thread/pthread_equal.c
+++ b/libc/thread/pthread_equal.c
@@ -26,3 +26,5 @@
 int pthread_equal(pthread_t t1, pthread_t t2) {
   return t1 == t2;
 }
+
+__weak_reference(pthread_equal, thrd_equal);
diff --git a/libc/thread/pthread_exit.c b/libc/thread/pthread_exit.c
index 06e9a8943..75bef400b 100644
--- a/libc/thread/pthread_exit.c
+++ b/libc/thread/pthread_exit.c
@@ -171,3 +171,5 @@ wontreturn void pthread_exit(void *rc) {
   // this is a child thread
   longjmp(pt->pt_exiter, 1);
 }
+
+__weak_reference(pthread_exit, thr_exit);
diff --git a/libc/thread/pthread_self.c b/libc/thread/pthread_self.c
index efb924981..91703a873 100644
--- a/libc/thread/pthread_self.c
+++ b/libc/thread/pthread_self.c
@@ -27,3 +27,5 @@
 pthread_t pthread_self(void) {
   return __get_tls()->tib_pthread;
 }
+
+__weak_reference(pthread_self, thrd_current);
diff --git a/libc/thread/thrd_create.c b/libc/thread/thrd_create.c
new file mode 100644
index 000000000..01101afe1
--- /dev/null
+++ b/libc/thread/thrd_create.c
@@ -0,0 +1,35 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2024 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/errno.h"
+#include "libc/thread/thread.h"
+#include "libc/thread/threads.h"
+
+int thrd_create(thrd_t *th, thrd_start_t func, void *arg) {
+  errno_t err;
+  err = pthread_create(th, 0, (void *(*)(void *))func, arg);
+  if (!err)
+    return thrd_success;
+  if (err == ENOMEM)
+    return thrd_nomem;
+  if (err == EAGAIN)
+    return thrd_busy;
+  if (err == EAGAIN)
+    return thrd_busy;
+  return thrd_error;
+}
diff --git a/libc/thread/thrd_detach.c b/libc/thread/thrd_detach.c
new file mode 100644
index 000000000..a604fca3e
--- /dev/null
+++ b/libc/thread/thrd_detach.c
@@ -0,0 +1,26 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2024 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/thread/thread.h"
+#include "libc/thread/threads.h"
+
+int thrd_detach(thrd_t th) {
+  if (pthread_detach(th))
+    return thrd_error;
+  return thrd_success;
+}
diff --git a/libc/thread/thrd_join.c b/libc/thread/thrd_join.c
new file mode 100644
index 000000000..12a7ebdac
--- /dev/null
+++ b/libc/thread/thrd_join.c
@@ -0,0 +1,29 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8                               :vi │
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2024 Justine Alexandra Roberts Tunney                              │
+│                                                                              │
+│ Permission to use, copy, modify, and/or distribute this software for         │
+│ any purpose with or without fee is hereby granted, provided that the         │
+│ above copyright notice and this permission notice appear in all copies.      │
+│                                                                              │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
+│ PERFORMANCE OF THIS SOFTWARE.                                                │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/thread/thread.h"
+#include "libc/thread/threads.h"
+
+int thrd_join(thrd_t th, int *res) {
+  void *pres;
+  if (pthread_join(th, &pres))
+    return thrd_error;
+  if (res)
+    *res = (uintptr_t)pres;
+  return thrd_success;
+}
diff --git a/libc/thread/threads.h b/libc/thread/threads.h
new file mode 100644
index 000000000..89bbedab6
--- /dev/null
+++ b/libc/thread/threads.h
@@ -0,0 +1,36 @@
+#ifndef COSMOPOLITAN_LIBC_THREAD_THREADS_H_
+#define COSMOPOLITAN_LIBC_THREAD_THREADS_H_
+COSMOPOLITAN_C_START_
+
+#define TSS_DTOR_ITERATIONS 4
+
+enum {
+  thrd_success = 0,
+  thrd_busy = 1,
+  thrd_error = 2,
+  thrd_nomem = 3,
+  thrd_timedout = 4,
+};
+
+enum {
+  mtx_plain = 0,
+  mtx_recursive = 1,
+  mtx_timed = 2,
+};
+
+typedef uintptr_t thrd_t;
+typedef void (*tss_dtor_t)(void *);
+typedef int (*thrd_start_t)(void *);
+typedef _Atomic(uint32_t) once_flag;
+
+void call_once(once_flag *, void (*)(void));
+int thrd_create(thrd_t *, thrd_start_t, void *);
+void thrd_exit(int) wontreturn;
+int thrd_join(thrd_t, int *);
+int thrd_detach(thrd_t);
+int thrd_equal(thrd_t, thrd_t);
+thrd_t thrd_current(void);
+void thrd_yield(void);
+
+COSMOPOLITAN_C_END_
+#endif /* COSMOPOLITAN_LIBC_THREAD_THREADS_H_ */
diff --git a/third_party/BUILD.mk b/third_party/BUILD.mk
index 36eef50ad..a019e5847 100644
--- a/third_party/BUILD.mk
+++ b/third_party/BUILD.mk
@@ -20,6 +20,7 @@ o/$(MODE)/third_party:				\
 	o/$(MODE)/third_party/libcxxabi		\
 	o/$(MODE)/third_party/libunwind		\
 	o/$(MODE)/third_party/linenoise		\
+	o/$(MODE)/third_party/llm		\
 	o/$(MODE)/third_party/lua		\
 	o/$(MODE)/third_party/lz4cli		\
 	o/$(MODE)/third_party/make		\