Skip to content

Commit a05277a

Browse files
authored
Implement a stub pthreads library for THREAD_MODEL=single (#518)
~~This patch series first starts with a number of commits stubbing out functions in the existing `THREAD_model=posix` code. According to "The Open Group Base Specifications Issue 7, 2018 edition", there are a number of mandatory functions which have not been provided. There are also some optional functions that have been partially provided in a not-useful way (e.g. get but no set function). For these, I have chosen to clean them up and remove the get functions for consistency.~~ EDIT: These have been split off into separate PRs and merged. The remainder of the patches then build up a stub implementation of pthreads for `THREAD_MODEL=single`. I have done my best to try to make sure that all functions are as conforming as possible (under the assumption that another thread cannot ever be launched). This means that objects such as mutexes and rwlocks actually do update their state and will correctly fail when locks cannot be acquired. When an inevitable deadlock occurs, I have chosen to return EDEADLK when it has been explicitly listed as a permissible return value, and to invoke `__builtin_trap` otherwise. I have tested this by rebuilding libc++ with threads enabled and then smoke-testing Clang/LLVM-on-WASI to make sure that it can compile a simple program. I have not run any more-extensive conformance testing. Fixes #501
1 parent 5ed3ec5 commit a05277a

17 files changed

+672
-47
lines changed

Makefile

Lines changed: 77 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ DLMALLOC_SOURCES = $(DLMALLOC_SRC_DIR)/dlmalloc.c
7676
DLMALLOC_INC = $(DLMALLOC_DIR)/include
7777
EMMALLOC_DIR = emmalloc
7878
EMMALLOC_SOURCES = $(EMMALLOC_DIR)/emmalloc.c
79+
STUB_PTHREADS_DIR = stub-pthreads
7980
LIBC_BOTTOM_HALF_DIR = libc-bottom-half
8081
LIBC_BOTTOM_HALF_CLOUDLIBC_SRC = $(LIBC_BOTTOM_HALF_DIR)/cloudlibc/src
8182
LIBC_BOTTOM_HALF_CLOUDLIBC_SRC_INC = $(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)/include
@@ -142,6 +143,8 @@ LIBWASI_EMULATED_SIGNAL_SOURCES = \
142143
LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES = \
143144
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/signal/psignal.c \
144145
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/string/strsignal.c
146+
LIBWASI_EMULATED_PTHREAD_SOURCES = \
147+
$(STUB_PTHREADS_DIR)/stub-pthreads-emulated.c
145148
LIBDL_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/misc/dl.c
146149
LIBSETJMP_SOURCES = $(LIBC_TOP_HALF_MUSL_SRC_DIR)/setjmp/wasm32/rt.c
147150
LIBC_BOTTOM_HALF_CRT_SOURCES = $(wildcard $(LIBC_BOTTOM_HALF_DIR)/crt/*.c)
@@ -274,88 +277,93 @@ LIBC_TOP_HALF_MUSL_SOURCES += \
274277
)
275278
endif
276279

277-
ifeq ($(THREAD_MODEL), posix)
280+
# pthreads functions (possibly stub) for either thread model
278281
LIBC_TOP_HALF_MUSL_SOURCES += \
279282
$(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
280-
env/__init_tls.c \
281-
stdio/__lockfile.c \
282-
stdio/flockfile.c \
283-
stdio/ftrylockfile.c \
284-
stdio/funlockfile.c \
285-
thread/__lock.c \
286-
thread/__wait.c \
287-
thread/__timedwait.c \
288283
thread/default_attr.c \
289284
thread/pthread_attr_destroy.c \
290285
thread/pthread_attr_get.c \
291286
thread/pthread_attr_init.c \
292287
thread/pthread_attr_setdetachstate.c \
293288
thread/pthread_attr_setguardsize.c \
289+
thread/pthread_attr_setschedparam.c \
294290
thread/pthread_attr_setstack.c \
295291
thread/pthread_attr_setstacksize.c \
296-
thread/pthread_attr_setschedparam.c \
297-
thread/pthread_barrier_destroy.c \
298-
thread/pthread_barrier_init.c \
299-
thread/pthread_barrier_wait.c \
300292
thread/pthread_barrierattr_destroy.c \
301293
thread/pthread_barrierattr_init.c \
302294
thread/pthread_barrierattr_setpshared.c \
303-
thread/pthread_cleanup_push.c \
304295
thread/pthread_cancel.c \
305-
thread/pthread_cond_broadcast.c \
306-
thread/pthread_cond_destroy.c \
307-
thread/pthread_cond_init.c \
308-
thread/pthread_cond_signal.c \
309-
thread/pthread_cond_timedwait.c \
310-
thread/pthread_cond_wait.c \
296+
thread/pthread_cleanup_push.c \
311297
thread/pthread_condattr_destroy.c \
312298
thread/pthread_condattr_init.c \
313299
thread/pthread_condattr_setclock.c \
314300
thread/pthread_condattr_setpshared.c \
315-
thread/pthread_create.c \
316-
thread/pthread_detach.c \
317301
thread/pthread_equal.c \
318-
thread/pthread_getattr_np.c \
319302
thread/pthread_getspecific.c \
320-
thread/pthread_join.c \
321303
thread/pthread_key_create.c \
322-
thread/pthread_mutex_consistent.c \
323304
thread/pthread_mutex_destroy.c \
324305
thread/pthread_mutex_init.c \
325-
thread/pthread_mutex_getprioceiling.c \
326-
thread/pthread_mutex_lock.c \
327-
thread/pthread_mutex_timedlock.c \
328-
thread/pthread_mutex_trylock.c \
329-
thread/pthread_mutex_unlock.c \
330306
thread/pthread_mutexattr_destroy.c \
331307
thread/pthread_mutexattr_init.c \
332308
thread/pthread_mutexattr_setprotocol.c \
333309
thread/pthread_mutexattr_setpshared.c \
334310
thread/pthread_mutexattr_setrobust.c \
335311
thread/pthread_mutexattr_settype.c \
336-
thread/pthread_once.c \
337312
thread/pthread_rwlock_destroy.c \
338313
thread/pthread_rwlock_init.c \
339-
thread/pthread_rwlock_rdlock.c \
340-
thread/pthread_rwlock_timedrdlock.c \
341-
thread/pthread_rwlock_timedwrlock.c \
342-
thread/pthread_rwlock_tryrdlock.c \
343-
thread/pthread_rwlock_trywrlock.c \
344-
thread/pthread_rwlock_unlock.c \
345-
thread/pthread_rwlock_wrlock.c \
346314
thread/pthread_rwlockattr_destroy.c \
347315
thread/pthread_rwlockattr_init.c \
348316
thread/pthread_rwlockattr_setpshared.c \
317+
thread/pthread_self.c \
349318
thread/pthread_setcancelstate.c \
350319
thread/pthread_setcanceltype.c \
351320
thread/pthread_setspecific.c \
352-
thread/pthread_self.c \
353321
thread/pthread_spin_destroy.c \
354322
thread/pthread_spin_init.c \
323+
thread/pthread_testcancel.c \
324+
)
325+
ifeq ($(THREAD_MODEL), posix)
326+
# pthreads functions needed for actual thread support
327+
LIBC_TOP_HALF_MUSL_SOURCES += \
328+
$(addprefix $(LIBC_TOP_HALF_MUSL_SRC_DIR)/, \
329+
env/__init_tls.c \
330+
stdio/__lockfile.c \
331+
stdio/flockfile.c \
332+
stdio/ftrylockfile.c \
333+
stdio/funlockfile.c \
334+
thread/__lock.c \
335+
thread/__wait.c \
336+
thread/__timedwait.c \
337+
thread/pthread_barrier_destroy.c \
338+
thread/pthread_barrier_init.c \
339+
thread/pthread_barrier_wait.c \
340+
thread/pthread_cond_broadcast.c \
341+
thread/pthread_cond_destroy.c \
342+
thread/pthread_cond_init.c \
343+
thread/pthread_cond_signal.c \
344+
thread/pthread_cond_timedwait.c \
345+
thread/pthread_cond_wait.c \
346+
thread/pthread_create.c \
347+
thread/pthread_detach.c \
348+
thread/pthread_getattr_np.c \
349+
thread/pthread_join.c \
350+
thread/pthread_mutex_consistent.c \
351+
thread/pthread_mutex_getprioceiling.c \
352+
thread/pthread_mutex_lock.c \
353+
thread/pthread_mutex_timedlock.c \
354+
thread/pthread_mutex_trylock.c \
355+
thread/pthread_mutex_unlock.c \
356+
thread/pthread_once.c \
357+
thread/pthread_rwlock_rdlock.c \
358+
thread/pthread_rwlock_timedrdlock.c \
359+
thread/pthread_rwlock_timedwrlock.c \
360+
thread/pthread_rwlock_tryrdlock.c \
361+
thread/pthread_rwlock_trywrlock.c \
362+
thread/pthread_rwlock_unlock.c \
363+
thread/pthread_rwlock_wrlock.c \
355364
thread/pthread_spin_lock.c \
356365
thread/pthread_spin_trylock.c \
357366
thread/pthread_spin_unlock.c \
358-
thread/pthread_testcancel.c \
359367
thread/sem_destroy.c \
360368
thread/sem_getvalue.c \
361369
thread/sem_init.c \
@@ -366,6 +374,16 @@ LIBC_TOP_HALF_MUSL_SOURCES += \
366374
thread/wasm32/wasi_thread_start.s \
367375
)
368376
endif
377+
ifeq ($(THREAD_MODEL), single)
378+
# pthreads stubs for single-threaded environment
379+
LIBC_TOP_HALF_MUSL_SOURCES += \
380+
$(STUB_PTHREADS_DIR)/barrier.c \
381+
$(STUB_PTHREADS_DIR)/condvar.c \
382+
$(STUB_PTHREADS_DIR)/mutex.c \
383+
$(STUB_PTHREADS_DIR)/rwlock.c \
384+
$(STUB_PTHREADS_DIR)/spinlock.c \
385+
$(STUB_PTHREADS_DIR)/stub-pthreads-good.c
386+
endif
369387

370388
MUSL_PRINTSCAN_SOURCES = \
371389
$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal/floatscan.c \
@@ -418,10 +436,10 @@ ifeq ($(THREAD_MODEL), posix)
418436
# https://reviews.llvm.org/D130053).
419437
CFLAGS += -mthread-model posix -pthread -ftls-model=local-exec
420438
ASMFLAGS += -matomics
439+
endif
421440

422441
# Include cloudlib's directory to access the structure definition of clockid_t
423442
CFLAGS += -I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)
424-
endif
425443

426444
ifneq ($(LTO),no)
427445
ifeq ($(LTO),full)
@@ -490,6 +508,7 @@ LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS = $(call objs,$(LIBWASI_EMULATED_PROCESS_CL
490508
LIBWASI_EMULATED_GETPID_OBJS = $(call objs,$(LIBWASI_EMULATED_GETPID_SOURCES))
491509
LIBWASI_EMULATED_SIGNAL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_SOURCES))
492510
LIBWASI_EMULATED_SIGNAL_MUSL_OBJS = $(call objs,$(LIBWASI_EMULATED_SIGNAL_MUSL_SOURCES))
511+
LIBWASI_EMULATED_PTHREAD_OBJS = $(call objs,$(LIBWASI_EMULATED_PTHREAD_SOURCES))
493512
LIBDL_OBJS = $(call objs,$(LIBDL_SOURCES))
494513
LIBSETJMP_OBJS = $(call objs,$(LIBSETJMP_SOURCES))
495514
LIBC_BOTTOM_HALF_CRT_OBJS = $(call objs,$(LIBC_BOTTOM_HALF_CRT_SOURCES))
@@ -593,6 +612,7 @@ LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULA
593612
LIBWASI_EMULATED_GETPID_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_GETPID_OBJS))
594613
LIBWASI_EMULATED_SIGNAL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_OBJS))
595614
LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS))
615+
LIBWASI_EMULATED_PTHREAD_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBWASI_EMULATED_PTHREAD_OBJS))
596616
LIBDL_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBDL_OBJS))
597617
LIBSETJMP_SO_OBJS = $(patsubst %.o,%.pic.o,$(LIBSETJMP_OBJS))
598618
BULK_MEMORY_SO_OBJS = $(patsubst %.o,%.pic.o,$(BULK_MEMORY_OBJS))
@@ -608,6 +628,7 @@ PIC_OBJS = \
608628
$(LIBWASI_EMULATED_GETPID_SO_OBJS) \
609629
$(LIBWASI_EMULATED_SIGNAL_SO_OBJS) \
610630
$(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS) \
631+
$(LIBWASI_EMULATED_PTHREAD_SO_OBJS) \
611632
$(LIBDL_SO_OBJS) \
612633
$(LIBSETJMP_SO_OBJS) \
613634
$(BULK_MEMORY_SO_OBJS) \
@@ -649,6 +670,8 @@ $(OBJDIR)/libwasi-emulated-getpid.so.a: $(LIBWASI_EMULATED_GETPID_SO_OBJS)
649670

650671
$(OBJDIR)/libwasi-emulated-signal.so.a: $(LIBWASI_EMULATED_SIGNAL_SO_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_SO_OBJS)
651672

673+
$(OBJDIR)/libwasi-emulated-pthread.so.a: $(LIBWASI_EMULATED_PTHREAD_SO_OBJS)
674+
652675
$(OBJDIR)/libdl.so.a: $(LIBDL_SO_OBJS)
653676

654677
$(OBJDIR)/libsetjmp.so.a: $(LIBSETJMP_SO_OBJS)
@@ -667,6 +690,8 @@ $(SYSROOT_LIB)/libwasi-emulated-getpid.a: $(LIBWASI_EMULATED_GETPID_OBJS)
667690

668691
$(SYSROOT_LIB)/libwasi-emulated-signal.a: $(LIBWASI_EMULATED_SIGNAL_OBJS) $(LIBWASI_EMULATED_SIGNAL_MUSL_OBJS)
669692

693+
$(SYSROOT_LIB)/libwasi-emulated-pthread.a: $(LIBWASI_EMULATED_PTHREAD_OBJS)
694+
670695
$(SYSROOT_LIB)/libdl.a: $(LIBDL_OBJS)
671696

672697
$(SYSROOT_LIB)/libsetjmp.a: $(LIBSETJMP_OBJS)
@@ -769,6 +794,12 @@ $(FTS_OBJS): CFLAGS += \
769794
$(LIBWASI_EMULATED_PROCESS_CLOCKS_OBJS) $(LIBWASI_EMULATED_PROCESS_CLOCKS_SO_OBJS): CFLAGS += \
770795
-I$(LIBC_BOTTOM_HALF_CLOUDLIBC_SRC)
771796

797+
$(LIBWASI_EMULATED_PTHREAD_OBJS) $(LIBWASI_EMULATED_PTHREAD_SO_OBJS): CFLAGS += \
798+
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/include \
799+
-I$(LIBC_TOP_HALF_MUSL_SRC_DIR)/internal \
800+
-I$(LIBC_TOP_HALF_MUSL_DIR)/arch/wasm32 \
801+
-D_WASI_EMULATED_PTHREAD
802+
772803
# emmalloc uses a lot of pointer type-punning, which is UB under strict aliasing,
773804
# and this was found to have real miscompilations in wasi-libc#421.
774805
$(EMMALLOC_OBJS): CFLAGS += \
@@ -820,6 +851,7 @@ LIBC_SO = \
820851
$(SYSROOT_LIB)/libwasi-emulated-process-clocks.so \
821852
$(SYSROOT_LIB)/libwasi-emulated-getpid.so \
822853
$(SYSROOT_LIB)/libwasi-emulated-signal.so \
854+
$(SYSROOT_LIB)/libwasi-emulated-pthread.so \
823855
$(SYSROOT_LIB)/libdl.so
824856
ifeq ($(BUILD_LIBSETJMP),yes)
825857
LIBC_SO += \
@@ -838,6 +870,10 @@ STATIC_LIBS = \
838870
$(SYSROOT_LIB)/libwasi-emulated-getpid.a \
839871
$(SYSROOT_LIB)/libwasi-emulated-signal.a \
840872
$(SYSROOT_LIB)/libdl.a
873+
ifneq ($(THREAD_MODEL), posix)
874+
STATIC_LIBS += \
875+
$(SYSROOT_LIB)/libwasi-emulated-pthread.a
876+
endif
841877
ifeq ($(BUILD_LIBSETJMP),yes)
842878
STATIC_LIBS += \
843879
$(SYSROOT_LIB)/libsetjmp.a

0 commit comments

Comments
 (0)