Skip to content

Commit d2c6656

Browse files
committed
Split the pthread library out of libc. NFC
1 parent c4ecb13 commit d2c6656

File tree

6 files changed

+151
-100
lines changed

6 files changed

+151
-100
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ See docs/process.md for more on how version tagging works.
9595
to support older browsers you may need to transpile it. If you use
9696
`file_packager` via emcc the output will be transpiled as part of the emcc
9797
output. (#22805)
98+
- The pthread part of libc now live in a separate libpthread (or
99+
libpthread-stub). This library is automatically included so this change
100+
will only effect those building with `-nostdlib` or `-nolibc`. (#22735)
98101

99102
3.1.70 - 10/25/24
100103
-----------------

embuilder.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@
7171
'libGL-webgl2-ofb-getprocaddr',
7272
'libGL-ww-getprocaddr',
7373
'libhtml5',
74+
'libpthread',
75+
'libpthread-stub',
76+
'libpthread-debug',
77+
'libpthread-debug-stub',
7478
'libsockets',
7579
'libsockets-ww',
7680
'libstubs',

test/test_core.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4589,10 +4589,10 @@ def test_dylink_postsets_chunking(self):
45894589

45904590
@with_dylink_reversed
45914591
@parameterized({
4592-
'libcxx': ('libc,libc++,libmalloc,libc++abi',),
4592+
'libcxx': ('libc,libpthread,libc++,libmalloc,libc++abi',),
45934593
'all': ('1',),
4594-
'missing': ('libc,libmalloc,libc++abi', False, False, False),
4595-
'missing_assertions': ('libc,libmalloc,libc++abi', False, False, True),
4594+
'missing': ('libc,libpthread,libmalloc,libc++abi', False, False, False),
4595+
'missing_assertions': ('libc,libpthread,libmalloc,libc++abi', False, False, True),
45964596
})
45974597
def test_dylink_syslibs(self, syslibs, expect_pass=True, with_reversed=True, assertions=True):
45984598
# one module uses libcxx, need to force its inclusion when it isn't the main

test/test_other.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6123,9 +6123,9 @@ def test_fs_dev_random(self):
61236123
# partial list, but ok since we grab them as needed
61246124
'parial': [{'EMCC_FORCE_STDLIBS': 'libc++'}, False],
61256125
# fail! not enough stdlibs
6126-
'partial_only': [{'EMCC_FORCE_STDLIBS': 'libc++,libc,libc++abi', 'EMCC_ONLY_FORCED_STDLIBS': '1'}, True],
6126+
'partial_only': [{'EMCC_FORCE_STDLIBS': 'libc++,libc,libpthread,libc++abi', 'EMCC_ONLY_FORCED_STDLIBS': '1'}, True],
61276127
# force all the needed stdlibs, so this works even though we ignore the input file
6128-
'full_only': [{'EMCC_FORCE_STDLIBS': 'libc,libc++abi,libc++,libmalloc', 'EMCC_ONLY_FORCED_STDLIBS': '1'}, False],
6128+
'full_only': [{'EMCC_FORCE_STDLIBS': 'libc,libpthread,libc++abi,libc++,libmalloc', 'EMCC_ONLY_FORCED_STDLIBS': '1'}, False],
61296129
})
61306130
def test_only_force_stdlibs(self, env, fail):
61316131
cmd = [EMXX, test_file('hello_libcxx.cpp')]
@@ -6156,7 +6156,7 @@ def test_only_force_stdlibs_2(self):
61566156
}
61576157
}
61586158
''')
6159-
with env_modify({'EMCC_FORCE_STDLIBS': 'libc,libc++abi,libc++,libmalloc', 'EMCC_ONLY_FORCED_STDLIBS': '1'}):
6159+
with env_modify({'EMCC_FORCE_STDLIBS': 'libc,libpthread,libc++abi,libc++,libmalloc', 'EMCC_ONLY_FORCED_STDLIBS': '1'}):
61606160
self.run_process([EMXX, 'src.cpp', '-sDISABLE_EXCEPTION_CATCHING=0'])
61616161
self.assertContained('Caught exception: std::exception', self.run_js('a.out.js'))
61626162

@@ -12476,10 +12476,10 @@ def test_nostdlib(self):
1247612476
self.assertContained(err, self.expect_fail([EMCC, test_file('unistd/close.c'), '-nodefaultlibs']))
1247712477

1247812478
# Build again but with explit system libraries
12479-
libs = ['-lc', '-lcompiler_rt']
12479+
libs = ['-lc', '-lpthread', '-lcompiler_rt']
1248012480
self.run_process([EMCC, test_file('unistd/close.c'), '-nostdlib'] + libs)
1248112481
self.run_process([EMCC, test_file('unistd/close.c'), '-nodefaultlibs'] + libs)
12482-
self.run_process([EMCC, test_file('unistd/close.c'), '-nolibc', '-lc'])
12482+
self.run_process([EMCC, test_file('unistd/close.c'), '-nolibc', '-lc', '-lpthread'])
1248312483
self.run_process([EMCC, test_file('unistd/close.c'), '-nostartfiles'])
1248412484

1248512485
def test_argument_match(self):
@@ -13378,12 +13378,13 @@ def test_offset_convertor_plus_wasm2js(self):
1337813378

1337913379
def test_standard_library_mapping(self):
1338013380
# Test the `-l` flags on the command line get mapped the correct libraries variant
13381-
libs = ['-lc', '-lbulkmemory', '-lcompiler_rt', '-lmalloc']
13381+
libs = ['-lc', '-lpthread', '-lbulkmemory', '-lcompiler_rt', '-lmalloc']
1338213382
err = self.run_process([EMCC, test_file('hello_world.c'), '-pthread', '-nodefaultlibs', '-v'] + libs, stderr=PIPE).stderr
1338313383

1338413384
# Check that the linker was run with `-mt` variants because `-pthread` was passed.
1338513385
self.assertContained(' -lc-mt-debug ', err)
1338613386
self.assertContained(' -ldlmalloc-mt ', err)
13387+
self.assertContained(' -lpthread-debug ', err)
1338713388
self.assertContained(' -lcompiler_rt-mt ', err)
1338813389

1338913390
def test_explicit_gl_linking(self):

tools/link.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2784,7 +2784,6 @@ def map_to_js_libs(library_name):
27842784
'dl': [],
27852785
'm': [],
27862786
'rt': [],
2787-
'pthread': [],
27882787
# This is the name of GNU's C++ standard library. We ignore it here
27892788
# for compatibility with GNU toolchains.
27902789
'stdc++': [],

tools/system_libs.py

Lines changed: 134 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,138 @@ class libnoexit(Library):
978978
src_files = ['atexit_dummy.c']
979979

980980

981+
class libpthread(MuslInternalLibrary,
982+
DebugLibrary,
983+
AsanInstrumentedLibrary):
984+
name = 'libpthread'
985+
# See libc
986+
cflags = ['-Os', '-fno-inline-functions', '-fno-builtin']
987+
cflags += ['-Wno-unused-but-set-variable',
988+
'-Wno-unused-variable',
989+
'-Wno-shift-op-parentheses',
990+
'-Wno-unused-label',
991+
'-Wno-logical-op-parentheses',
992+
'-Wno-bitwise-op-parentheses']
993+
994+
def __init__(self, **kwargs):
995+
self.is_stub = kwargs.pop('stub')
996+
super().__init__(**kwargs)
997+
998+
def get_cflags(self):
999+
cflags = super().get_cflags()
1000+
if not self.is_stub:
1001+
cflags += ['-pthread']
1002+
return cflags
1003+
1004+
def get_base_name(self):
1005+
name = super().get_base_name()
1006+
if self.is_stub:
1007+
name += '-stub'
1008+
return name
1009+
1010+
@classmethod
1011+
def vary_on(cls):
1012+
return super().vary_on() + ['stub']
1013+
1014+
@classmethod
1015+
def get_default_variation(cls, **kwargs):
1016+
return super().get_default_variation(stub=not settings.PTHREADS, **kwargs)
1017+
1018+
def get_files(self):
1019+
files = files_in_path(
1020+
path='system/lib/pthread',
1021+
filenames=['thread_profiler.c'])
1022+
1023+
if self.is_stub:
1024+
# Include just a subset of the thread directory
1025+
files += files_in_path(
1026+
path='system/lib/libc/musl/src/thread',
1027+
filenames=[
1028+
'pthread_self.c',
1029+
'pthread_cleanup_push.c',
1030+
'pthread_attr_init.c',
1031+
'pthread_attr_destroy.c',
1032+
'pthread_attr_get.c',
1033+
'pthread_attr_setdetachstate.c',
1034+
'pthread_attr_setguardsize.c',
1035+
'pthread_attr_setinheritsched.c',
1036+
'pthread_attr_setschedparam.c',
1037+
'pthread_attr_setschedpolicy.c',
1038+
'pthread_attr_setscope.c',
1039+
'pthread_attr_setstack.c',
1040+
'pthread_attr_setstacksize.c',
1041+
'pthread_getconcurrency.c',
1042+
'pthread_getcpuclockid.c',
1043+
'pthread_getschedparam.c',
1044+
'pthread_setschedprio.c',
1045+
'pthread_setconcurrency.c',
1046+
'default_attr.c',
1047+
# C11 thread library functions
1048+
'call_once.c',
1049+
'tss_create.c',
1050+
'tss_delete.c',
1051+
'tss_set.c',
1052+
'cnd_broadcast.c',
1053+
'cnd_destroy.c',
1054+
'cnd_init.c',
1055+
'cnd_signal.c',
1056+
'cnd_timedwait.c',
1057+
'cnd_wait.c',
1058+
'mtx_destroy.c',
1059+
'mtx_init.c',
1060+
'mtx_lock.c',
1061+
'mtx_timedlock.c',
1062+
'mtx_trylock.c',
1063+
'mtx_unlock.c',
1064+
'thrd_create.c',
1065+
'thrd_exit.c',
1066+
'thrd_join.c',
1067+
'thrd_sleep.c',
1068+
'thrd_yield.c',
1069+
])
1070+
files += files_in_path(
1071+
path='system/lib/pthread',
1072+
filenames=[
1073+
'library_pthread_stub.c',
1074+
'pthread_self_stub.c',
1075+
'proxying_stub.c',
1076+
])
1077+
else:
1078+
files += glob_in_path(
1079+
path='system/lib/libc/musl/src/thread',
1080+
glob_pattern='*.c',
1081+
excludes=[
1082+
'clone.c',
1083+
'pthread_create.c',
1084+
'pthread_kill.c', 'pthread_sigmask.c',
1085+
'__set_thread_area.c', 'synccall.c',
1086+
'__syscall_cp.c', '__tls_get_addr.c',
1087+
'__unmapself.c',
1088+
# Empty files, simply ignore them.
1089+
'syscall_cp.c', 'tls.c',
1090+
# TODO: Support these. See #12216.
1091+
'pthread_setname_np.c',
1092+
'pthread_getname_np.c',
1093+
])
1094+
files += files_in_path(
1095+
path='system/lib/pthread',
1096+
filenames=[
1097+
'library_pthread.c',
1098+
'em_task_queue.c',
1099+
'proxying.c',
1100+
'proxying_legacy.c',
1101+
'thread_mailbox.c',
1102+
'pthread_create.c',
1103+
'pthread_kill.c',
1104+
'emscripten_thread_init.c',
1105+
'emscripten_thread_state.S',
1106+
'emscripten_futex_wait.c',
1107+
'emscripten_futex_wake.c',
1108+
'emscripten_yield.c',
1109+
])
1110+
return files
1111+
1112+
9811113
class libc(MuslInternalLibrary,
9821114
DebugLibrary,
9831115
AsanInstrumentedLibrary,
@@ -1091,7 +1223,7 @@ def get_files(self):
10911223
ignore = [
10921224
'ipc', 'passwd', 'signal', 'sched', 'time', 'linux',
10931225
'aio', 'exit', 'legacy', 'mq', 'setjmp',
1094-
'ldso', 'malloc'
1226+
'ldso', 'malloc', 'thread'
10951227
]
10961228

10971229
# individual files
@@ -1113,91 +1245,6 @@ def get_files(self):
11131245

11141246
ignore += LIBC_SOCKETS
11151247

1116-
if self.is_mt:
1117-
ignore += [
1118-
'clone.c',
1119-
'pthread_create.c',
1120-
'pthread_kill.c', 'pthread_sigmask.c',
1121-
'__set_thread_area.c', 'synccall.c',
1122-
'__syscall_cp.c', '__tls_get_addr.c',
1123-
'__unmapself.c',
1124-
# Empty files, simply ignore them.
1125-
'syscall_cp.c', 'tls.c',
1126-
# TODO: Support these. See #12216.
1127-
'pthread_setname_np.c',
1128-
'pthread_getname_np.c',
1129-
]
1130-
libc_files += files_in_path(
1131-
path='system/lib/pthread',
1132-
filenames=[
1133-
'library_pthread.c',
1134-
'em_task_queue.c',
1135-
'proxying.c',
1136-
'proxying_legacy.c',
1137-
'thread_mailbox.c',
1138-
'pthread_create.c',
1139-
'pthread_kill.c',
1140-
'emscripten_thread_init.c',
1141-
'emscripten_thread_state.S',
1142-
'emscripten_futex_wait.c',
1143-
'emscripten_futex_wake.c',
1144-
'emscripten_yield.c',
1145-
])
1146-
else:
1147-
ignore += ['thread']
1148-
libc_files += files_in_path(
1149-
path='system/lib/libc/musl/src/thread',
1150-
filenames=[
1151-
'pthread_self.c',
1152-
'pthread_cleanup_push.c',
1153-
'pthread_attr_init.c',
1154-
'pthread_attr_destroy.c',
1155-
'pthread_attr_get.c',
1156-
'pthread_attr_setdetachstate.c',
1157-
'pthread_attr_setguardsize.c',
1158-
'pthread_attr_setinheritsched.c',
1159-
'pthread_attr_setschedparam.c',
1160-
'pthread_attr_setschedpolicy.c',
1161-
'pthread_attr_setscope.c',
1162-
'pthread_attr_setstack.c',
1163-
'pthread_attr_setstacksize.c',
1164-
'pthread_getconcurrency.c',
1165-
'pthread_getcpuclockid.c',
1166-
'pthread_getschedparam.c',
1167-
'pthread_setschedprio.c',
1168-
'pthread_setconcurrency.c',
1169-
'default_attr.c',
1170-
# C11 thread library functions
1171-
'call_once.c',
1172-
'tss_create.c',
1173-
'tss_delete.c',
1174-
'tss_set.c',
1175-
'cnd_broadcast.c',
1176-
'cnd_destroy.c',
1177-
'cnd_init.c',
1178-
'cnd_signal.c',
1179-
'cnd_timedwait.c',
1180-
'cnd_wait.c',
1181-
'mtx_destroy.c',
1182-
'mtx_init.c',
1183-
'mtx_lock.c',
1184-
'mtx_timedlock.c',
1185-
'mtx_trylock.c',
1186-
'mtx_unlock.c',
1187-
'thrd_create.c',
1188-
'thrd_exit.c',
1189-
'thrd_join.c',
1190-
'thrd_sleep.c',
1191-
'thrd_yield.c',
1192-
])
1193-
libc_files += files_in_path(
1194-
path='system/lib/pthread',
1195-
filenames=[
1196-
'library_pthread_stub.c',
1197-
'pthread_self_stub.c',
1198-
'proxying_stub.c',
1199-
])
1200-
12011248
# These files are in libc directories, but only built in libc_optz.
12021249
ignore += [
12031250
'pow_small.c', 'log_small.c', 'log2_small.c'
@@ -1313,10 +1360,6 @@ def get_files(self):
13131360
if settings.RELOCATABLE:
13141361
libc_files += files_in_path(path='system/lib/libc', filenames=['dynlink.c'])
13151362

1316-
libc_files += files_in_path(
1317-
path='system/lib/pthread',
1318-
filenames=['thread_profiler.c'])
1319-
13201363
libc_files += glob_in_path('system/lib/libc/compat', '*.c')
13211364

13221365
# Check for missing file in non_lto_files list. Do this here
@@ -2382,6 +2425,7 @@ def add_sanitizer_libs():
23822425
if settings.ALLOW_UNIMPLEMENTED_SYSCALLS:
23832426
add_library('libstubs')
23842427
if '-nolibc' not in args:
2428+
add_library('libpthread')
23852429
if not settings.EXIT_RUNTIME:
23862430
add_library('libnoexit')
23872431
add_library('libc')

0 commit comments

Comments
 (0)