lhmouse / mcfgthread Goto Github PK
View Code? Open in Web Editor NEWCornerstone of the MOST efficient std::thread on Windows for mingw-w64
Home Page: https://gcc-mcf.lhmouse.com/
License: Other
Cornerstone of the MOST efficient std::thread on Windows for mingw-w64
Home Page: https://gcc-mcf.lhmouse.com/
License: Other
Cleanup of thread-local storage.
In the case of dynamic linking this is done in response to the DLL_THREAD_DETACH
notification.
Fiber local storage is not an option because code that expects TLS objects to be preserved upon SwitchToFiber()
will be broken.
Initialization of the thread library before any other code.
In the case of dynamic linking this is done in response to the DLL_PROCESS_ATTACH
notification.
Due to a Windows bug a TLS callback is not invoked with such a notification if the executable was linked against only KERNEL32 and NTDLL. In order to cover all cases, we must modify MinGW-w64 startup code and perform the initialization before the __main()
function from libgcc.
Cleanup of the thread library.
In the case of dynamic linking this is done in response to the DLL_PROCESS_DETACH
notification.
Use of a DLL entry point function or a TLS callback is essential for the cleanup to be performed upon a call to the exit()
or ExitProcess()
function, either of which is out of our scope.
Find a solution to GCC PR80883.
Is it possible to define this function in every DLL?
Use named shared memory to allocate storage for process-wide objects.
rep movsb/stosb
is fast ( with large and aligned memory ) because of the ERMSB optimization.
But repz cmpsb
is not the case. It's not optimized.
RtlCompareMemory is slow because it uses repz cmpsb too. We can use memcmp in ntdll, which results in both less code and better performance.
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <Windows.h>
inline __attribute__((always_inline))
uint8_t __MCF_mequal(const void *__src, const void *__cmp, size_t __size) noexcept
{
uint8_t __result;
#if defined(__i386__) || defined(__amd64__)
intptr_t __si, __di, __cx;
__asm__(
"xorl %%eax, %%eax;"
"repz cmpsb;"
#ifdef __GCC_ASM_FLAG_OUTPUTS__
: "=@ccz"(__result), "=S"(__si), "=D"(__di), "=c"(__cx)
: "m"(*(const char(*)[])__src), "m"(*(const char(*)[])__cmp),
"S"(__src), "D"(__cmp), "c"(__size)
: "ax"
#else /* __GCC_ASM_FLAG_OUTPUTS__ */
"setzb %%al;"
: "=a"(__result), "=S"(__si), "=D"(__di), "=c"(__cx)
: "m"(*(const char(*)[])__src), "m"(*(const char(*)[])__cmp),
"S"(__src), "D"(__cmp), "c"(__size)
: "cc"
#endif /* __GCC_ASM_FLAG_OUTPUTS__ */
);
#else
/* Call the generic but slower version in NTDLL. */
SIZE_T __n = RtlCompareMemory(__src, __cmp, __size);
__result = __n == __size;
#endif
return __result;
}
// https://github.com/google/benchmark/blob/eacce0b503a81a2910cc1ea0439cf7bc39e3377d/include/benchmark/benchmark.h#L445
template <class Tp>
inline __attribute__((always_inline)) void DoNotOptimize(Tp const& value) {
asm volatile("" : : "r,m"(value) : "memory");
}
template <class Tp>
inline __attribute__((always_inline)) void DoNotOptimize(Tp& value) {
#if defined(__clang__)
asm volatile("" : "+r,m"(value) : : "memory");
#else
asm volatile("" : "+m,r"(value) : : "memory");
#endif
}
int main() {
using namespace std::chrono;
HMODULE ntdll = LoadLibraryA("ntdll.dll");
auto ntdll_memcmp = (decltype(memcmp)*)GetProcAddress(ntdll, "memcmp");
char buf1[2048] = "";
char buf2[2048] = "";
{
auto start = high_resolution_clock::now();
for (auto i = 0; i < 100000000; i++) {
DoNotOptimize(buf1);
DoNotOptimize(buf2);
DoNotOptimize(__MCF_mequal(buf1, buf2, 32));
}
std::printf("__MCF_mequal small: %llu\n", (uint64_t)(high_resolution_clock::now() - start).count());
}
{
auto start = high_resolution_clock::now();
for (auto i = 0; i < 100000000; i++) {
DoNotOptimize(buf1);
DoNotOptimize(buf2);
DoNotOptimize(ntdll_memcmp(buf1, buf2, 32));
}
std::printf("ntdll_memcmp small: %llu\n", (uint64_t)(high_resolution_clock::now() - start).count());
}
{
auto start = high_resolution_clock::now();
for (auto i = 0; i < 10000000; i++) {
DoNotOptimize(buf1);
DoNotOptimize(buf2);
DoNotOptimize(__MCF_mequal(buf1, buf2, 2048));
}
std::printf("__MCF_mequal large: %llu\n", (uint64_t)(high_resolution_clock::now() - start).count());
}
{
auto start = high_resolution_clock::now();
for (auto i = 0; i < 10000000; i++) {
DoNotOptimize(buf1);
DoNotOptimize(buf2);
DoNotOptimize(ntdll_memcmp(buf1, buf2, 2048));
}
std::printf("ntdll_memcmp large: %llu\n", (uint64_t)(high_resolution_clock::now() - start).count());
}
}
For example creating 1K threads and joining them, PingPang test for 1M times, compare with winpthread implementation & VC++'s std::thread implementation ( although not very meaningful )
该项目使用了很多未有微软文档的系统调用来保证运行效率
You say P without data 😄
RT
Should we add support for clang++ and libcxx on Windows?
If somebody wants to contribute, here is some pseudo documentation.
Code doing a ping-pong between two threads deadlocks when compiled with a mcfgthread-based cross-toolchain (64 bit, gcc 8.3.0-based, with the provided MCF patches applied) and run under wine >= 5.0 (5.0 on Ubuntu 20.04 x64, 5.9 on Arch Linux x64, plus various tests with Proton 5.0 using esync, again on Arch Linux x64). No problems when running under wine 3.0.
Here's the sample code: https://gist.github.com/cvtsi2sd/b9c534e6f447f35c781fc20deb3989b9
This also works fine (terminating with
turn: 1
count[0]: 50001
count[1]: 50000
tot_count: 100001
) when:
When it deadlocks (= exiting only due to timeout), I get it locked up at random stages.
comelz@7de7fbb980bd:/bug$ time WINEPATH=/opt/mingw64-mcf/x86_64-w64-mingw32/bin/ wine a.exe
Wait expired in thread 1 after 5 seconds
Status dump:
turn: 0
count[0]: 25
count[1]: 25
tot_count: 50
abnormal program termination
real 0m10.322s
user 0m0.122s
sys 0m0.140s
comelz@7de7fbb980bd:/bug$ time WINEPATH=/opt/mingw64-mcf/x86_64-w64-mingw32/bin/ wine a.exe
Wait expired in thread 1 after 5 seconds
Status dump:
turn: 0
count[0]: 2
count[1]: 2
tot_count: 4
abnormal program termination
real 0m5.306s
user 0m0.093s
sys 0m0.122s
comelz@7de7fbb980bd:/bug$ time WINEPATH=/opt/mingw64-mcf/x86_64-w64-mingw32/bin/ wine a.exe
Wait expired in thread 0 after 5 seconds
Status dump:
turn: 1
count[0]: 2
count[1]: 1
tot_count: 3
abnormal program termination
real 0m5.321s
user 0m0.111s
sys 0m0.113s
comelz@7de7fbb980bd:/bug$ time WINEPATH=/opt/mingw64-mcf/x86_64-w64-mingw32/bin/ wine a.exe
Wait expired in thread 1 after 5 seconds
Status dump:
turn: 0
count[0]: 7
count[1]: 7
tot_count: 14
abnormal program termination
real 0m5.301s
user 0m0.107s
sys 0m0.102s
Interestingly, if I don't run it under time
it seems to get further:
comelz@7de7fbb980bd:/bug$ WINEPATH=/opt/mingw64-mcf/x86_64-w64-mingw32/bin/ wine a.exe
Wait expired in thread 0 after 5 seconds
Status dump:
turn: 1
count[0]: 825
count[1]: 824
tot_count: 1649
abnormal program termination
comelz@7de7fbb980bd:/bug$ WINEPATH=/opt/mingw64-mcf/x86_64-w64-mingw32/bin/ wine a.exe
Wait expired in thread 0 after 5 seconds
Status dump:
turn: 1
count[0]: 120
count[1]: 119
tot_count: 239
abnormal program termination
comelz@7de7fbb980bd:/bug$ WINEPATH=/opt/mingw64-mcf/x86_64-w64-mingw32/bin/ wine a.exe
Wait expired in thread 0 after 5 seconds
Status dump:
turn: 1
count[0]: 39
count[1]: 38
tot_count: 77
abnormal program termination
Between wine 3.0 and wine 5.0 I noticed several changes in sync.c
, some to supposedly fix #36, some reimplementing SRW stuff basing it on futexes; I think they may be related, but I'm wondering if it's their implementation that is broken (it may be, I saw several very recent bugfixes to that file regarding keyed events), or the change of underlying implementation actually exposed a bug in MCF.
./configure CC=clang --disable-pch
We have a Makefile recipe for pre-compiled headers:
%.xi: %.i %reldir%/version.h config.h
${AM_V_CC}${LTCOMPILE} -ffreestanding -x c-header -Wno-error $< -o $@.o \
&& rm -rf $@.gch \
&& mkdir $@.gch \
&& . $@.lo \
&& (test "$${pic_object}" == none || mv -f %reldir%/$${pic_object} $@.gch/pic) \
&& (test "$${non_pic_object}" == none || mv -f %reldir%/$${non_pic_object} $@.gch/non_pic) \
&& rm -f $@.lo \
&& echo '#error PCH unusable' > $@
By default, libtool generates two types of object files: one for shared libraries and one for static libraries. Because shared ones are built with -DDLL_EXPORT -fPIC -DPIC
and static ones are built without such options, it is not feasible to share the same PCH for them. In this recipe we call libtool to compile the header precompiled.xi
and generate two 'object files', which are moved into the directory precompiled.xi.gch
. GCC is able to tell which .gch file matches the current configuration, and ignore the other.
Unfortunately, it looks like that Clang thinks the static PCH applies to shared builds and uses it to build object files for the DLL. Because the static PCH has been built without DLL_EXPORT
, __MCF_DLLEXPORT
is defined as empty (instead of the correct __declspec(dllexport)
), which causes functions to be not exported.
Refactoring of this library is almost complete, except the gthread wrappers. I am planning to incorporate it into the next gcc-mcf package.
Some symbol names might be unnecessarily too long, e.g. *tag*
.
To make the ABI stable, source level symbol versioning should be considered, e.g. inline namespace
and ABI tags. (However, this might make the symbol names longer.)
Hi,
On archlinux the package builds fine for x86_64-w64-mingw32 target but not for i686:
undefined reference to
__gcc_personality_sj0`
Seems this is should be part of the standard library:
$ grep -nr __gcc_personality_sj0 /usr/i686-w64-mingw32/lib/ Binary file /usr/i686-w64-mingw32/lib/libgcc_s.a matches
Any clue ?
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force -I m4
aclocal: warning: couldn't open directory 'm4': No such file or directory
autoreconf: configure.ac: tracing
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf --force
autoreconf: running: /usr/bin/autoheader --force
autoreconf: running: automake --add-missing --copy --force-missing
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/\${ <-- HERE ([^ \t=:+{}]+)}/ at /usr/bin/automake line 3936.
configure.ac:6: installing './compile'
configure.ac:9: installing './install-sh'
configure.ac:9: installing './missing'
Makefile.am: installing './depcomp'
autoreconf: Leaving directory `.'
~/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32 ~/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9
configure: WARNING: you should use --build, --host, --target
configure: WARNING: unrecognized options: --enable-shared, --enable-static
checking for i686-w64-mingw32-gcc... i686-w64-mingw32-gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.exe
checking for suffix of executables... .exe
checking whether we are cross compiling... yes
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether i686-w64-mingw32-gcc accepts -g... yes
checking for i686-w64-mingw32-gcc option to accept ISO C89... none needed
checking whether i686-w64-mingw32-gcc understands -c and -o together... yes
checking for i686-w64-mingw32-ranlib... i686-w64-mingw32-ranlib
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for i686-w64-mingw32-strip... i686-w64-mingw32-strip
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for style of include used by make... GNU
checking whether make supports nested variables... yes
checking dependency style of i686-w64-mingw32-gcc... gcc3
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
configure: WARNING: unrecognized options: --enable-shared, --enable-static
make all-am
make[1]: Entering directory '/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32'
depbase=`echo src/env/avl_tree.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/avl_tree.o -MD -MP -MF $depbase.Tpo -c -o src/env/avl_tree.o ../src/env/avl_tree.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/bail.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/bail.o -MD -MP -MF $depbase.Tpo -c -o src/env/bail.o ../src/env/bail.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/clocks.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/clocks.o -MD -MP -MF $depbase.Tpo -c -o src/env/clocks.o ../src/env/clocks.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/condition_variable.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/condition_variable.o -MD -MP -MF $depbase.Tpo -c -o src/env/condition_variable.o ../src/env/condition_variable.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/gthread.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/gthread.o -MD -MP -MF $depbase.Tpo -c -o src/env/gthread.o ../src/env/gthread.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/c11thread.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/c11thread.o -MD -MP -MF $depbase.Tpo -c -o src/env/c11thread.o ../src/env/c11thread.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/heap.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/heap.o -MD -MP -MF $depbase.Tpo -c -o src/env/heap.o ../src/env/heap.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/mutex.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/mutex.o -MD -MP -MF $depbase.Tpo -c -o src/env/mutex.o ../src/env/mutex.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/once_flag.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/once_flag.o -MD -MP -MF $depbase.Tpo -c -o src/env/once_flag.o ../src/env/once_flag.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/thread.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/thread.o -MD -MP -MF $depbase.Tpo -c -o src/env/thread.o ../src/env/thread.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/thread_env.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/thread_env.o -MD -MP -MF $depbase.Tpo -c -o src/env/thread_env.o ../src/env/thread_env.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/_seh_top.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/_seh_top.o -MD -MP -MF $depbase.Tpo -c -o src/env/_seh_top.o ../src/env/_seh_top.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/env/_nt_timeout.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/env/_nt_timeout.o -MD -MP -MF $depbase.Tpo -c -o src/env/_nt_timeout.o ../src/env/_nt_timeout.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/ext/assert.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/ext/assert.o -MD -MP -MF $depbase.Tpo -c -o src/ext/assert.o ../src/ext/assert.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/ext/itow.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/ext/itow.o -MD -MP -MF $depbase.Tpo -c -o src/ext/itow.o ../src/ext/itow.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/ext/wcpcpy.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/ext/wcpcpy.o -MD -MP -MF $depbase.Tpo -c -o src/ext/wcpcpy.o ../src/ext/wcpcpy.c &&\
mv -f $depbase.Tpo $depbase.Po
depbase=`echo src/dll_startup.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
i686-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I.. -std=c11 -Wall -Wextra -pedantic -pedantic-errors -Wstrict-prototypes -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wwrite-strings -pipe -mfpmath=both -march=nocona -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -MT src/dll_startup.o -MD -MP -MF $depbase.Tpo -c -o src/dll_startup.o ../src/dll_startup.c &&\
mv -f $depbase.Tpo $depbase.Po
i686-w64-mingw32-gcc -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4 -shared -static -nostdlib -Wl,-e@__MCFCRT_DllStartup,-subsystem,windows,--disable-runtime-pseudo-reloc,--disable-auto-import -Wl,--disable-stdcall-fixup,--enable-auto-image-base,--export-all-symbols,--out-implib,libmcfgthread.dll.a -o mcfgthread-7.dll src/env/avl_tree.o src/env/bail.o src/env/clocks.o src/env/condition_variable.o src/env/gthread.o src/env/c11thread.o src/env/heap.o src/env/mutex.o src/env/once_flag.o src/env/thread.o src/env/thread_env.o src/env/_seh_top.o src/env/_nt_timeout.o src/ext/assert.o src/ext/itow.o src/ext/wcpcpy.o src/dll_startup.o -lkernel32 -lntdll
src/env/gthread.o: In function `GthreadProc':
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/gthread.c:109: undefined reference to `__gcc_personality_sj0'
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/gthread.c:109: undefined reference to `_Unwind_SjLj_Register'
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/gthread.c:150: undefined reference to `_Unwind_SjLj_Unregister'
src/env/gthread.o: In function `_MCFCRT_SehTopUninstaller_x86':
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/_seh_top.h:30: undefined reference to `_Unwind_SjLj_Resume'
src/env/c11thread.o: In function `C11threadProc':
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/c11thread.c:107: undefined reference to `__gcc_personality_sj0'
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/c11thread.c:107: undefined reference to `_Unwind_SjLj_Register'
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/c11thread.c:146: undefined reference to `_Unwind_SjLj_Unregister'
src/env/c11thread.o: In function `_MCFCRT_SehTopUninstaller_x86':
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/_seh_top.h:30: undefined reference to `_Unwind_SjLj_Resume'
src/dll_startup.o: In function `@__MCFCRT_DllStartup':
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/dll_startup.c:16: undefined reference to `__gcc_personality_sj0'
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/dll_startup.c:16: undefined reference to `_Unwind_SjLj_Register'
src/dll_startup.o: In function `_MCFCRT_SehTopUninstaller_x86':
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/_seh_top.h:30: undefined reference to `_Unwind_SjLj_Unregister'
/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32/../src/env/_seh_top.h:30: undefined reference to `_Unwind_SjLj_Resume'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:579: mcfgthread-7.dll] Error 1
make[1]: Leaving directory '/home/xantares/projects/aur-scripts/mingw-w64-mcfgthread/src/mcfgthread-alpha-0.9/build-i686-w64-mingw32'
make: *** [Makefile:399: all] Error 2
It doesn't seem that GCC guys care about Windows mush. It's the business of MinGW.
http://mingw-w64.org/doku.php/contribute#c11_and_c_11_threading_support
飞翔的天地
The following code causes a deadlock in alpha-0.9 because thrd_exit
() does not signal the condition variable which the primary thread is sleeping on:
#include <mcfgthread/c11thread.h>
#include <stdlib.h>
int thread_proc(void *param){
// return 12345;
thrd_exit(12345);
}
int main(){
thrd_t tid;
int err;
if((err = thrd_create(&tid, &thread_proc, 0)) != thrd_success){
abort();
}
int exit_code;
if((err = thrd_join(tid, &exit_code)) != thrd_success){
abort();
}
return exit_code;
}
Been having trouble for some time with the restrict qualifier, and i suspected a bug with the mingw-w64 abi, but it turns out that mcfgthread redefines the qualifier in its own _crtdef.h which causes this error.
So i changed it to use a guard in case its allready defined which seems to have alleviated the problem.
This test from libstdc++ is failing.
(A copy of the source file could be obtained here in case of URL expiration.)
This faulty test tries to unlock an unlocked recursive_mutex, which is definitely undefined behavior. Specifically with mcfgthread, this causes assertion failure if NDEBUG
had not been defined when the library was built.
It is GNU people that shall fix it.
... in which case it fails with 0xc0000008
(STATUS_INVALID_HANDLE
).
On Windows 7 if the handle is null, the global keyed event with the name \KernelObjects\CritSecOutOfMemoryEvent
is used. Since this is not the case for Wine, a handle has to be opened explicitly at lease once per process. It must not be closed thereafter, unless as a result of process exit of course.
For example, memcpy for small buffer: https://godbolt.org/g/AkekLW
And buffers for memcpy with constant size are usually small and aligned
So don't do that.
In src/env/thread_env.c
:
static TlsObject *GetTlsObject(TlsThread *pThread, TlsKey *pKey){
_MCFCRT_ASSERT(pThread);
if(!pKey){
return nullptr;
}
TlsObject *const pObject = (TlsObject *)_MCFCRT_AvlFind(&(pThread->avlObjects), (intptr_t)pKey, &ObjectComparatorNodeKey);
if(pObject && (pObject->uCounter != pKey->uCounter)){ // [1]
const _MCFCRT_TlsDestructor pfnDestructor = pObject->pfnDestructor;
if(pfnDestructor){
(*pfnDestructor)(pObject->nContext, pObject->abyStorage);
}
TlsObject *const pPrev = pObject->pPrevByThread;
TlsObject *const pNext = pObject->pNextByThread;
if(pPrev){
pPrev->pNextByThread = pNext;
}
if(pNext){
pNext->pPrevByThread = pPrev;
}
_MCFCRT_AvlDetach((_MCFCRT_AvlNodeHeader *)pObject);
_MCFCRT_free(pObject);
return nullptr;
}
return pObject;
}
Since a TLS key is the address of a block of memory, if a key is allocated after another one is freed, they could accidentally have the same value. I was aware of it and, as a result, TLS keys were assigned auto incremental IDs (the uCounter
member) in order to check for reused keys. This turns out to be insufficient, as the if
statement at [1] only does the check once. If a TLS key is reused twice or more, GetTlsObject()
might not return a valid pointer even if the TLS object actually resides in the map.
According to this specification in POSIX 2013:
The
pthread_key_delete()
function shall be callable from within destructor functions. No destructor functions shall be invoked bypthread_key_delete()
. Any destructor function that may have been associated with key shall no longer be called upon thread exit.
This contradicts __gthread_key_delete()
in mcfgthread which preserves destructors deferred upon thread exit.
Neither the C11 standard nor the GNU documentation of __gthread_*
interfaces says a word about such behavior. Personally I refuse to regard POSIX crap. Nonetheless, any further discussion is welcome.
Hello,
I would like to know what exception model does it use for both x86 and x64 and what is the minimal windows version supported?
Also if it is possible to link libmcfgthread statically?
TIA.
谢谢您的卓越贡献,我有个问题我想咨询下。我用gcc-mcf.lhmouse.com/mingw-w64-gcc-mcf_20220606_12.1.1_x64-ucrt_fe50eb9db7d0a4c4ba907456ca4c9b5b3403a0fb.7z您这个toolchain编译mpv。但编译生成的mpv.exe需要依赖libmcfgthread-1.dll这个动态库。有没有办法把libmcfgthread-1.dll静态编译进mpv呢。这样的话只需要一个mpv.exe单文件就可以运行了。
thin lto不知道为何不能用。换posix的就行。你去修一下吧。
This is the only obstacle on our way to Windows XP support, at the moment.
Hey, I have recently found this Windows GCC distribution. The amount of prebuild stuff (boost, openssl, qslite, python and many others) is amazing but I have realized that your distro does not have make
tool.
Is there any specific reason behind this? The dmake
does not work with makefiles I have. I would really like to build with make
(just like with any other Windows GCC distibution) - is there any easy way to workaround this problem?
open https://mingw-w64.org/doku.php
Firefox:
It’s likely the website’s certificate is expired, which prevents Firefox from connecting securely. If you visit this site, attackers could try to steal information like your passwords, emails, or credit card details.
Chrome:
Your connection is not private
Attackers might be trying to steal your information from mingw-w64.org (for example, passwords, messages, or credit cards). Learn more
NET::ERR_CERT_DATE_INVALID
but mingw32/bin folder is contained in the releases folder of the repository.
Not sure if anyone had this before, but atleast it seems to affect atleast a few programs that use mcf vtk seems to dont like it at all and will throw this on exit 100% of the time.
At the moment, we have some global states as static variables:
Line 146 in 3768a1e
This is not a problem if mcfgthread is always linked as a shared library. But, there are people who prefer static linking. In the latter case, all static instances in an EXE and all DLLs it has loaded get distinct copies of these variables, and it is dangerous to pass thread handles, TLS key handles, etc. between them.
Therefore, I think we can place these data into a named shared memory region, so individual modules always refer to the same region.
@lhmouse, can you add your informative post: http://article.gmane.org/gmane.comp.gnu.mingw.w64.general/12629 to the wiki?
When trying to build your library under MSYS2 using mingw-64 I get this error:
"Building shared library...
x86_64-w64-mingw32-gcc -x c-header -DHAVE_CONFIG_H -Wall -Wextra -pedantic -pedantic-errors -Werror -Wwrite-strings -Wconversion -Wsign-conversion -Wsuggest-attribute=noreturn -Winvalid-pch -Wundef -Wshadow -Wstrict-aliasing=2 -Wstrict-overflow=5 -pipe -mno-stack-arg-probe -mno-accumulate-outgoing-args -mpush-args -masm=intel -ffreestanding -DNDEBUG $(echo "" "-include __pch.h -std=c11 -Wstrict-prototypes" | sed "s/-include __pch\.h//") -O3 -ffunction-sections -fdata-sections -m64 __pch.h -o __pch.h.gch
__pch.h:1:70: fatal error: /e/Programming/VersionControl/mcfgthread/src/env/_crtdef.h: No such file or directory
#include "/e/Programming/VersionControl/mcfgthread/src/env/_crtdef.h"
^
compilation terminated.
make: *** [Makefile:1143: __pch.h.gch] Error 1"
Yet when I do:
ls -al /e/Programming/VersionControl/mcfgthread/src/env/_crtdef.h
the output is:
-rw-r--r-- 1 eldnew8 None 2107 Apr 5 20:24 /e/Programming/VersionControl/mcfgthread/src/env/_crtdef.h
so clearly the file exists. Any ideas why gcc tells me that there is no such file or directory ?
The gcc-mcf.lhmouse.com web site is inaccessible.
我看到 AcquireSRWLockExclusive 和 SleepConditionVariableSRW 都是用 NtWaitForAlertByThreadId
https://github.com/processhacker/processhacker/blob/master/phnt/include/ntpsapi.h#L1656
关于SRWLock不支持timed_mutex的问题,NtWaitForAlertByThreadId 本身支持 timeout,只是 AcquireSRWLockExclusive 没开放出来
NtWaitForAlertByThreadId 比 NtWaitForKeyedEvent 参数更少,功能更专用,性能应该会比后者好
包括 rpcs3 也是优先 NtWaitForAlertByThreadId :https://github.com/valgusk/rpcs3-old-rpcn/blob/f6f12b3b0dfeedc260d44e3be713fcb03c9638eb/rpcs3/util/atomic.cpp#L1192
考虑一下?
I am geting this error in ubuntu 16.04:
root@ubuntu:/home/coin/mcfgthread# make
make all-am
make[1]: Entering directory '/home/coin/mcfgthread'
depbase=echo src/dll_startup.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'
;
gcc -DHAVE_CONFIG_H -I. -Wall -Wextra -pedantic -pedantic-errors -Werror -Wno-error=unused-parameter -Winvalid-pch -Wwrite-strings -Wconversion -Wsign-conversion -Wdouble-promotion -Wsuggest-attribute=noreturn -Wundef -Wshadow -Wstrict-aliasing=2 -pipe -mno-stack-arg-probe -masm=intel -ffreestanding -include __pch.h -std=c11 -Wstrict-prototypes -g -O2 -MT src/dll_startup.o -MD -MP -MF $depbase.Tpo -c -o src/dll_startup.o src/dll_startup.c &&
mv -f $depbase.Tpo $depbase.Po
In file included from src/mcfcrt.h:24:0,
from src/dll_startup.c:5:
src/env/thread.h:12:1: error: â__stdcall__â attribute ignored [-Werror=attributes]
typedef unsigned long (attribute((stdcall)) *_MCFCRT_NativeThreadProc)(
^
In file included from src/env/_seh_top.h:9:0,
from src/dll_startup.c:6:
src/env/mcfwin.h:30:21: fatal error: windows.h: No such file or directory
cc1: all warnings being treated as errors
compilation terminated.
Makefile:637: recipe for target 'src/dll_startup.o' failed
make[1]: *** [src/dll_startup.o] Error 1
make[1]: Leaving directory '/home/coin/mcfgthread'
Makefile:417: recipe for target 'all' failed
make: *** [all] Error 2
root@ubuntu:/home/coin/mcfgthread#
The follow program illustrates what happens:
E:\Desktop>cat test.c
#include <mcfgthread/c11thread.h>
int main(){
thrd_exit(1);
}
E:\Desktop>gcc test.c
E:\Desktop>a
The program has asked MCF CRT to terminate it abnormally. Please contact the author for detailed information.
Error description:
Assertion failed!
Expression: pControl
File: ../mcfgthread/src/env/_mopthread.c
Line: 189
Desc: Calling thread of __MCFCRT_MopthreadExit() was not created using __MCFCRT_MopthreadCreate().
Click OK to terminate the program; click Cancel to debug the program.
Note this crash happens because the primary thread is not created by mcfgthread. Consequently, although it seems possible to join with the thread, it is impossible to obtain its exit code, nor can we obtain the exit code of a thread created by __gthread_create()
, using thrd_join()
.
https://github.com/lhmouse/mcfgthread/blob/master/LICENSE.TXT
Could this be made more clear maybe?
We have boost 1.75.0-8
while the latest version is 1.77.0
Is there any reason to keep the old boost version?
Rationale: These three components do not depend on TLS cleanup callbacks. Programs that do not depend on TLS (especially legacy C programs that make use of CreateThread()
or _beginthreadex()
directly) might benefit from the possibility of static linking. The shared library is still provided for no additional cost.
http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_getspecific.html
A call to pthread_getspecific() for the thread-specific data key being destroyed
shall return the value NULL ...
Should we satisfy it somehow?
The various build shell scripts do not really match what is suggested as the build instructions for your library in the readme.md file. I followed the build shell scripts with my own changes for paths and such, but I think you should synchronize the information so that it is consistent. I realize that this is not a big issue but it confused me when I went to build your library.
In ReallyWaitForConditionVariable()
from src/condition_variabe.c
:
if(bSpinnable){
for(size_t i = 0; i < uMaxSpinCount; ++i){
{
uintptr_t uOld, uNew;
uOld = __atomic_load_n(puControl, __ATOMIC_RELAXED);
do {
bSignaled = !(uOld & MASK_WAITING);
if(!bSignaled){
break;
}
uNew = uOld & ~MASK_THREADS_SPINNING;
} while(_MCFCRT_EXPECT_NOT(!__atomic_compare_exchange_n(puControl, &uOld, uNew, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)));
}
if(_MCFCRT_EXPECT_NOT(bSignaled)){
(*pfnRelockCallback)(nContext, nUnlocked);
return true;
}
__builtin_ia32_pause();
}
}
A thread sets MASK_WAITING
before it begins spinning and the spinning wait is essentially waiting for that mask to be cleared. But this isn't a reliable protocol. Another thread may break in and set that mask, making the current thread miss the wakeup.
Hi, we're in the process of migrating some binaries to using mcfgthread, but unfortunately we're hitting a roadblock that we're not able to work around easily.
The binaries we're migrating are both 32bit and 64bit and need to live and coexist all in the same directory.
Here's an example tree structure of the binaries
.
├── bin1-32bit.exe
├── bin2-64bit.exe
└── bin3-32bit.exe
└── lib1-32bit.exe
└── lib1-64bit.exe
Ideally we'd like to ship the dll required by mcfgthread in that directory just like we're doing for all the other libraries, but unfortunately we cannot because the name of dll is the same that is mcfgthread-12.dll
. This makes effectively impossible to have two binaries for different architectures live in the same directory.
Do you think it might be feasible to change the name of the dll to include the architecture or any other way to distinguish between 32bit vs 64bit?
I realize this would be a breaking change, but if that's a concern (definitely a valid one) we could maybe setup additional pipelines that create the artifacts with the new names while keeping the old ones around for the foreseeable future.
What do you think?
RT
In RealWaitForOnceFlag()
in file src/env/once_flag.c
:
if(bMayTimeOut && _MCFCRT_EXPECT(u64UntilFastMonoClock == 0)){
return false;
}
The return false;
statement should be return _MCFCRT_kOnceResultTimedOut;
.
Gave it a go with a gcc-5.4.0 bootstrap and most of it builds but it keels over on objc it seems.
libtool: link: /f/projects/runtime/_gccbuild32/./gcc/xgcc -B/f/projects/runtime/_gccbuild32/./gcc/ -L/mingw32/i686-w64-mgw32/lib/ -isystem /mingw32/i686-w64-mingw32/include -isystem /mingw32/i686-w64-mingw32/sys-include -shared .libs/NX/init.o .libs/ivars.o .libs/memory.o .libs/methods.o .libs/nil_method.o .libs/objc-foreach.o .libs/objc-sync.o .libs/obj -shared-libgcc -o .libs/libobjc-4.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/libobjc.dll.
.libs/thr.o: I funktionen "objc_mutex_allocate":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:260: undefined reference to __gthread_objc_mutex_allocate' .libs/thr.o: I funktionen "objc_mutex_lock": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:316: undefined reference to
__gthread_objc_thread_id'
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:321: undefined reference to __gthread_objc_mutex_lock' .libs/thr.o: I funktionen "objc_mutex_deallocate": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:291: undefined reference to
__gthread_objc_mutex_deallocate'
.libs/thr.o: I funktionen "objc_mutex_trylock":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:346: undefined reference to __gthread_objc_thread_id' f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:351: undefined reference to
__gthread_objc_mutex_trylock'
.libs/thr.o: I funktionen "objc_mutex_unlock":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:378: undefined reference to `__gthread_objc_thread_id'
.libs/thr.o: I funktionen "objc_thread_detach":
:/projects/runtime/gcc-5.4.0/libobjc/thr.c:169: undefined reference to __gthread_objc_thread_detach' .libs/thr.o: I funktionen "objc_thread_set_data": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:235: undefined reference to
__gthread_objc_thread_set_data'
.libs/thr.o: I funktionen "objc_condition_allocate":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:415: undefined reference to __gthread_objc_condition_allocate' .libs/thr.o: I funktionen "objc_condition_broadcast": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:498: undefined reference to
__gthread_objc_condition_broadcast'
.libs/thr.o: I funktionen "objc_condition_deallocate":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:439: undefined reference to __gthread_objc_condition_deallocate' .libs/thr.o: I funktionen "objc_condition_wait": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:465: undefined reference to
__gthread_objc_thread_id'
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:478: undefined reference to __gthread_objc_condition_wait' .libs/thr.o: I funktionen "_objc_init_thread_system": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:78: undefined reference to
__gthread_objc_init_thread_system'
.libs/thr.o: I funktionen "objc_thread_set_priority":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:189: undefined reference to __gthread_objc_thread_set_priority' .libs/thr.o: I funktionen "objc_thread_get_priority": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:196: undefined reference to
__gthread_objc_thread_get_priority'
.libs/thr.o: I funktionen "objc_thread_yield":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:205: undefined reference to __gthread_objc_thread_yield' .libs/thr.o: I funktionen "objc_thread_id": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:227: undefined reference to
__gthread_objc_thread_id'
.libs/thr.o: I funktionen "objc_thread_set_data":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:235: undefined reference to __gthread_objc_thread_set_data' .libs/thr.o: I funktionen "objc_thread_get_data": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:243: undefined reference to
__gthread_objc_thread_get_data'
.libs/thr.o: I funktionen "objc_mutex_unlock":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:391: undefined reference to __gthread_objc_mutex_unlock' .libs/thr.o: I funktionen "objc_thread_exit": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:219: undefined reference to
__gthread_objc_thread_exit'
.libs/thr.o: I funktionen "objc_condition_broadcast":
f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:498: undefined reference to __gthread_objc_condition_broadcast' .libs/thr.o: I funktionen "objc_condition_signal": f:/projects/runtime/gcc-5.4.0/libobjc/thr.c:512: undefined reference to
__gthread_objc_condition_signal'
collect2.exe: error: ld returned 1 exit status
make[2]: *** [libobjc.la] Error 1
make[2]: Leaving directory /f/projects/runtime/_gccbuild32/i686-w64-mingw32/libobjc' make[1]: *** [all-target-libobjc] Error 2 make[1]: Leaving directory
/f/projects/runtime/_gccbuild32'
make: *** [all] Error 2
Thanks for your great job. I need mingw-w64-ucrt-x86_64-gcc-mcf as toolchain to compile mpv.
So I download it from https://gcc-mcf.lhmouse.com/
But mingw-w64-gcc-mcf_20211231_11.2.1_x64-ucrt didn't work because of this change. I know the latest patch should fix it. Newer mingw-w64-ucrt-x86_64-gcc-mcf hasn't been released yet. So I want to compile it by myself.
I don't know how to write CI.yml . So adding Github Actions will be great, thanks again.
The usage "provides sth. to use sth" is not a idiomatic expression and it is not grammatically correct. IMO ,it's better to use "provides sth. for sth".
e.g.
"This header provides APIs for mutexes."
"This header provides APIs for operating thread local storage(TLS)."
This is what we have at the moment:
Line 114 in e8fb31d
inline int my_add(int a, int b) { return a + b; }
static inline int my_add_alias(int a, int b) { return my_add(a, b); }
static inline
functions cannot be called inside extern inline
ones.inline int my_add(int a, int b) { return a + b; }
extern int my_add_alias(int a, int b) __MINGW_ASM_CALL(my_add);
inline int my_add(int a, int b) { return a + b; }
__MCF_GNU_INLINE int my_add_alias(int a, int b) __MINGW_ASM_CALL(my_add);
__MCF_GNU_INLINE int my_add_alias(int a, int b) { return my_add(a, b); }
inline int my_add(int a, int b) { return a + b; }
static __typeof__(my_add) my_add_alias __attribute__((__copy__(my_add), __weakref__("my_add")));
__copy__
copies the __dllexport__
attribute which requires external linkage.Upon return of _MCFCRT_TlsGet()
on [1] or [2] the content of *ppStorage
is left uninitialized and attempt to use that value results in undefined behavior:
TlsKey *const pKey = (TlsKey *)hTlsKey;
if(!pKey){
SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
TlsThread *const pThread = GetTlsForCurrentThread();
if(!pThread){
return true; // [1]
}
TlsObject *const pObject = GetTlsObject(pThread, pKey);
if(!pObject){
return true; // [2]
}
I'm using the prebuild compiler from https://gcc-mcf.lhmouse.com on Windows and I'm not sure what my projects should link with. I have noticed there are mcfgthread-12.dll
and libwinpthread-1.dll
in compiler's installation directory. Should my programs link to both? Is any of these libraries dependent on another?
I have very little knowledge of threading implementation, only using C++ standard library API. Not sure what is missing when I get undefined reference to pthread_mutex_init
which happened when I linked my program to libboost_filesystem.
Can you explain what-is-what/what-X-is-implementing-Y/what-X-depends-on-Y from mcfgthread, gthread, pthead, winpthread? What should I know and care about? I don't want to silently corrupt my executables by wrong compiler/linker options.
It uses CreateThread
However MSDN suggests using _beginthreadex when a thread calls the C run-time library (CRT) which I assume everyone ( that has Win32 programming experience ) knows.
Why did you do that?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.