Skip to content

How the MCF thread model works

LIU Hao edited this page Nov 30, 2024 · 5 revisions

The now committed patch implements compiler, linker and standard library support for the MCF thread model. The CRT part has not been committed to mingw-w64.

Changes to GCC

If GCC is configured with --enable-threads=mcf:

  1. It has __USING_MCFGTHREAD__ as a pre-defined macro, which enables special code paths in libstdc++ and mingw-w64 CRT.
  2. It has -lmcfgthread -lntdll as default libraries. (NTDLL is only needed for static linking.)
  3. It installs 'gthr-mcf.h' as 'bits/gthr-default.h', which is just a wrapper for 'mcfgthread/gthr.h'.

In libgcc, most use of threading infrastructure is internal. In libstdc++, there are some public functions, which, when __USING_MCFGTHREAD__ is defined, should be redirected to MCF implementations:

  1. __cxa_thread_atexit(dtor, obj, dso): On Linux it is provided in libstdc++ and jumps to __cxa_thread_atexit_impl(dtor, obj, dso) in libc. Recent mingw-w64 provides this function, so it should be opted out to prefer the mingw-w64 one.
  2. __cxa_guard_acquire(guard): On Linux it is implemented with futex. On most other platforms it is implemented with a single static mutex. It should be opted to call __MCF_cxa_guard_acquire(guard).
  3. __cxa_guard_release(guard): It is opted to call __MCF_cxa_guard_release(guard).
  4. __cxa_guard_abort(guard): It is opted to call __MCF_cxa_guard_abort(guard).

Changes to mingw-w64

The mingw-w64 CRT needs these changes:

  1. Some process-termination routines in the Microsoft CRT effect non-standard behavior and have to be replaced (https://github.com/msys2/MINGW-packages/issues/2519). Because the Microsoft exit() should not be called any more, it is necessary to flush standard files after static destructors. This is done by calling __MCF_cxa_atexit(fflush, NULL, &__dso_handle) before __main().
  2. If a DLL entry-point function receives a DLL_PROCESS_DETACH notification, it shall call __MCF_cxa_finalize(&__dso_handle), as specified by the Itanium C++ ABI.
  3. _Exit(status): It is opted to call __MCF__Exit(status).
  4. _exit(status): It is equivalent to _Exit(status), and is opted to call __MCF__Exit(status).
  5. at_quick_exit(func): This function is linked statically by each module, and is opted to call __MCF_cxa_at_quick_exit(func, NULL, &__dso_handle).
  6. __cxa_at_quick_exit(dtor, obj, dso): It is opted to call __MCF_cxa_at_quick_exit(dtor, obj, dso).
  7. quick_exit(status): It is opted to call __MCF_quick_exit(status).
  8. atexit(func): This function is linked statically by each module, and is opted to call __MCF_cxa_atexit(func, NULL, &__dso_handle).
  9. __cxa_atexit(dtor, obj, dso): It is opted to call __MCF_cxa_atexit(dtor, obj, dso).
  10. exit(status): It is opted to call __MCF_exit(status).
  11. __cxa_finalize(dso): It is opted to call __MCF_cxa_finalize(dso).
  12. __cxa_at_thread_exit(dtor, obj, dso): It is opted to call __MCF_cxa_at_thread_exit(dtor, obj, dso).