Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,19 @@ jobs:
# compile. It is run as well as built so that something links afterwards,
# which is what distinguishes a source that compiles from a package that
# works.
# ⭐ A THREAD CREATED FROM C++ IS THE THREAD THAT IS JOINED.
#
# musl's C++ `pthread_t` was `unsigned long`, which is thirty-two bits on
# Windows, so every std::thread there faulted when joined. The probe's
# static_assert is the criterion and the run shows the value surviving a
# started context. musl/PATCHES.md, `include/alltypes.h.in`.
- name: A thread created from C++ is the thread that is joined
env:
MCPP_TARGET: ${{ matrix.target }}
run: |
bash tools/run-probe.sh examples/threads-cxx threads-cxx
grep -q 'value 42, result is the argument' examples/threads-cxx/run.log

- name: A program may use the names the internal overlay defines
env:
MCPP_TARGET: ${{ matrix.target }}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ musl reaches its kernel through seven inline functions declared once per
architecture. Replacing that one header is the whole of the redirection; the
1345 sources that make up the library are compiled unmodified.

`musl/PATCHES.md` lists the whole of what is not unmodified: **four patched
`musl/PATCHES.md` lists the whole of what is not unmodified: **five patched
lines**, all of one kind — a machine word carried through a variable declared
`long`, which is not a machine word on one of the three targets — and **eleven
replaced sources**. Five of the eleven are replaced for the same reason: each
Expand Down
13 changes: 13 additions & 0 deletions examples/threads-cxx/mcpp.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "threads-cxx"
version = "0.1.0"

[dependencies]
openkal-musl = { path = "../.." }

[targets.threads-cxx]
kind = "bin"
main = "src/main.cpp"

[build]
cxx_runtime = "host-coupled"
42 changes: 42 additions & 0 deletions examples/threads-cxx/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* A thread created from C++ is the thread that is joined.
*
* musl declares `pthread_t' twice: a pointer for C, and `unsigned long' for C++.
* The two agree wherever a long holds a pointer, which is every architecture
* musl was written for. Windows is LLP64 --- a long is thirty-two bits --- so a
* C++ program kept the lower half of the thread's address, and pthread_join read
* through the truncated value. libc++'s std::thread stores exactly this type,
* so every std::thread on that system ended in an access violation when joined.
*
* ⭐ THE static_assert IS THE CRITERION, and it is a compile-time one: before the
* change this file does not compile for x86_64-windows-gnu. The run afterwards
* shows that the value survives the round trip through a started context.
*/
#include <pthread.h>
#include <stdio.h>

static_assert(sizeof(pthread_t) >= sizeof(void*), "pthread_t must hold the address musl stores in it");

static void* work(void* arg)
{
*static_cast<int*>(arg) = 42;
return arg;
}

int main()
{
int failures = 0;
int value = 0;
pthread_t thread;
if (pthread_create(&thread, nullptr, work, &value) != 0) {
puts("pthread_create failed");
return 1;
}
void* result = nullptr;
const int joined = pthread_join(thread, &result);
printf("joined: %d, value %d, result %s\n", joined, value, result == &value ? "is the argument" : "is not the argument");
if (joined != 0) ++failures;
if (value != 42) ++failures;
if (result != &value) ++failures;
printf("-- failures: %d --\n", failures);
return failures == 0 ? 0 : 1;
}
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
namespace = "mcpplibs"
name = "openkal-musl"
version = "0.13.1"
version = "0.13.2"
description = "musl 1.2.5 redirected onto openkal: one C library, ported once, above every implementation of the specification rather than above one kernel."
license = "Apache-2.0"

Expand Down
2 changes: 1 addition & 1 deletion musl-generated/aarch64-macos/bits/alltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ typedef unsigned useconds_t;

#ifdef __cplusplus
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
typedef unsigned long pthread_t;
typedef unsigned _Addr pthread_t;
#define __DEFINED_pthread_t
#endif

Expand Down
2 changes: 1 addition & 1 deletion musl-generated/aarch64/bits/alltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ typedef unsigned useconds_t;

#ifdef __cplusplus
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
typedef unsigned long pthread_t;
typedef unsigned _Addr pthread_t;
#define __DEFINED_pthread_t
#endif

Expand Down
2 changes: 1 addition & 1 deletion musl-generated/riscv64/bits/alltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ typedef unsigned useconds_t;

#ifdef __cplusplus
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
typedef unsigned long pthread_t;
typedef unsigned _Addr pthread_t;
#define __DEFINED_pthread_t
#endif

Expand Down
2 changes: 1 addition & 1 deletion musl-generated/x86_64-windows/bits/alltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ typedef unsigned useconds_t;

#ifdef __cplusplus
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
typedef unsigned long pthread_t;
typedef unsigned _Addr pthread_t;
#define __DEFINED_pthread_t
#endif

Expand Down
2 changes: 1 addition & 1 deletion musl-generated/x86_64/bits/alltypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ typedef unsigned useconds_t;

#ifdef __cplusplus
#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
typedef unsigned long pthread_t;
typedef unsigned _Addr pthread_t;
#define __DEFINED_pthread_t
#endif

Expand Down
24 changes: 23 additions & 1 deletion musl/PATCHES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# What was changed in musl, and why

musl 1.2.5 is vendored here unmodified except for the four lines below, and the
musl 1.2.5 is vendored here unmodified except for the five lines below, and the
list is exhaustive: `git log -p -- musl/` shows every one of them. Each is
recorded with the reason, because a port that silently edits the library it
ports is a port nobody can check.
Expand Down Expand Up @@ -31,6 +31,28 @@ offset beyond two gigabytes would be truncated, and both would happen silently.
already widen it because their arguments are wider than a `long`. On every
target musl supports, the changed line says what the original said.

## `include/alltypes.h.in`, one declaration

```diff
-TYPEDEF unsigned long pthread_t;
+TYPEDEF unsigned _Addr pthread_t;
```

musl declares `pthread_t` twice: as a pointer for C, and as an integer for C++,
because C++ needs a type it can compare and hash. The integer was written
`unsigned long`, which holds a pointer on every architecture musl supports.

Windows is LLP64, so a C++ program above this library kept the lower half of the
thread's address. `pthread_join` then read through the truncated value: libc++'s
`std::thread` stores exactly this type, and every `std::thread` on that system
ended in an access violation when it was joined (`0xC0000005`, measured on
windows-2022 and under Wine). `_Addr` is the type musl already uses for
`size_t`, `uintptr_t` and `ptrdiff_t`; it is `long` on every other target here,
so the changed line says what the original said there.

The five generated `alltypes.h` headers carry the same one-line change.
`examples/threads-cxx` does not compile for `x86_64-windows-gnu` without it.

## `src/stdio/vfwscanf.c`, `src/stdlib/wcstol.c`, `src/stdlib/wcstod.c`

```diff
Expand Down
2 changes: 1 addition & 1 deletion musl/include/alltypes.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ TYPEDEF int key_t;
TYPEDEF unsigned useconds_t;

#ifdef __cplusplus
TYPEDEF unsigned long pthread_t;
TYPEDEF unsigned _Addr pthread_t;
#else
TYPEDEF struct __pthread * pthread_t;
#endif
Expand Down
Loading