Giter VIP home page Giter VIP logo

mcfgthread's People

Contributors

lhmouse avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mcfgthread's Issues

TODO list of static linking support

  • 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.

Please reconsider implementing the standard memory functions yourself

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());
  }
}

Any speed test / performance comparation?

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 😄

Condition variable deadlock when running under wine >=5.0

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:

  • compiled and run with "regular" Linux g++ (Ubuntu 18.04 gcc 7.5.0);
  • compiled (in 32 bit mode) with g++ 4.8.0 dw2+win32 patched with (an older version of) MegaNZ thread (https://github.com/meganz/mingw-std-threads), both on wine 3.0 and wine 5.0
  • compiled (in 64 bit mode) with g++ 7.1.1 seh+posix (=winpthread), both on wine 3.0 and wine 5.0.

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.

Clang pre-compiled header causes functions to be not exported from DLL

TL; DR: Disable pre-compiled headers if you are using Clang:

./configure CC=clang --disable-pch

Details

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 complete

Refactoring of this library is almost complete, except the gthread wrappers. I am planning to incorporate it into the next gcc-mcf package.

Notable enhancements

  1. Rewrote totally to become better looking and well commented.
  2. Added detailed testcases for unit-testing.
  3. Changed the container of thread-local objects from an AVL tree to a hash table.

Issue on symbols

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.)

link error for i686-w64-mingw32 target

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

thrd_exit() causes deadlock

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;
}

restrict qualifier collision

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.

libstdc++ recursive_mutex test is failing

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 Wine 3.0 `NtWaitForKeyedEvent()` does not accept null handles

... 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.

Spurious loss of TLS object in case that a key is reused multiple times

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.

__gthread_key_delete() and destructors

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 by pthread_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.

关于静态编译的问题

谢谢您的卓越贡献,我有个问题我想咨询下。我用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单文件就可以运行了。

附仓库地址:https://github.com/eko5624/mpv-winbuild

make tool support?

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?

[Not about MCF] mingw-w64.org certificate has been expired for weeks

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

assert in TLS_OUT_OF_INDEXES

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.

Make global data shareable between static libraries

At the moment, we have some global states as static variables:

/* Define global data last to ensure that all of them have all been

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.

Compilation problem with MSYS2

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 ?

About NtWaitForAlertByThreadId and NtAlertThreadByThreadId

我看到 AcquireSRWLockExclusive 和 SleepConditionVariableSRW 都是用 NtWaitForAlertByThreadId

image

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

考虑一下?

compilation error

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#

Calling `thrd_exit()` in the primary thread results in a crash.

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().

Move mutex, cond var and once flag to a separate static library

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.

Build instructions do not match

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.

A thread spinning on a CV could miss a wakeup

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.

Add way to distinguish 32bit vs 64bit mcfgthread-12.dll

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?

libobjc not building

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

Suggestion: Add Github Actions to compile mcfgthread.

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.

Wiki: English Syntax Error near 'provides sth. to use'

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)."

Deadlock in exit(0) (LLD)

First thanks for your wonderful library.

Here is a bit of prehistory.

Still, while LLD built with your gcc successfully completes all parallel_fors, it deadlocks at exit(0).

Implement inline aliases in a more 'proper' way

Alternative 0 (current): static function pointers

This is what we have at the moment:

# define __MCF_ALIAS(alias, target) static __typeof__(target)* const alias = (target)

  • Pros:
    • The alias yields the same value as its target (thanks to function-to-pointer conversion).
    • Direct calls to the alias can be inlined.
  • Cons:
    • Taking the address of such an alias explicitly yields a wrong type (a pointer-to-pointer-to-function).

Alternative 1: static inline wrapper functions

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);  }
  • Pros:
    • Direct calls to the alias can be inlined.
    • Taking the address of such an alias explicitly yields the correct type (a pointer-to-function).
  • Cons:
    • The alias yields a different value from its target.
    • Indirect calls may bloat binaries.
    • static inline functions cannot be called inside extern inline ones.

Alternative 2: ASM aliases

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);
  • Pros:
    • The alias yields the same value as its target.
    • Taking the address of such an alias explicitly yields the correct type (a pointer-to-function).
  • Cons:
    • Direct calls to the alias cannot be inlined.

Alternative 3: static inline wrapper functions with ASM aliases

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);  }
  • Pros:
    • The alias yields the same value as its target.
    • Taking the address of such an alias explicitly yields the correct type (a pointer-to-function).
    • Direct calls to the alias can be inlined.
  • Cons:
    • It's too verbose to be implementable with a single macro.
    • This cause errors with Clang.

Alternative 4: weak aliases

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")));
  • Pros:
    • This seems to work around all the issues above.
  • Cons:
    • It does not compile because __copy__ copies the __dllexport__ attribute which requires external linkage.
    • Sometimes it leads to crashes.

Uninitialized pointer bug in _MCFCRT_TlsGet()

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]
    }

mcfgthread, gthread, pthead and linking

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.

Question about thread.c

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.