From a0009b1b1b93f03e5bee8c8cc785dd3b0cc0e82e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 21 Sep 2025 14:21:03 +0000 Subject: More progress in Windows implementation (doesn't work yet) --- .github/workflows/win-build.yml | 1 - unix/tclUnixThrd.c | 8 +-- win/configure | 114 ---------------------------------------- win/tcl.m4 | 2 - win/tclWinThrd.c | 72 ++++++++----------------- 5 files changed, 25 insertions(+), 172 deletions(-) diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index 2cea72a..355aa08 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -52,7 +52,6 @@ jobs: GCC_PARTIAL: > [ "", - "CFLAGS=-DNO_ATOMIC=1", "--disable-shared", "--enable-symbols=all" ] diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 3bffc6e..1ed8c81 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -206,11 +206,11 @@ PMutexLock( } else { pthread_mutex_lock(&pmutexPtr->mutex); #ifdef HAVE_PTHREAD_SPIN_LOCK - pthread_spin_lock(&pmutexPtr->lock); + pthread_spin_lock(&pmutexPtr->lock); #endif pmutexPtr->thread = mythread; #ifdef HAVE_PTHREAD_SPIN_LOCK - pthread_spin_unlock(&pmutexPtr->lock); + pthread_spin_unlock(&pmutexPtr->lock); #endif } } @@ -238,11 +238,11 @@ PMutexUnlock( pmutexPtr->counter--; } else { #ifdef HAVE_PTHREAD_SPIN_LOCK - pthread_spin_lock(&pmutexPtr->lock); + pthread_spin_lock(&pmutexPtr->lock); #endif pmutexPtr->thread = 0; #ifdef HAVE_PTHREAD_SPIN_LOCK - pthread_spin_unlock(&pmutexPtr->lock); + pthread_spin_unlock(&pmutexPtr->lock); #endif pthread_mutex_unlock(&pmutexPtr->mutex); } diff --git a/win/configure b/win/configure index 0ba54d1..ba54e6a 100755 --- a/win/configure +++ b/win/configure @@ -607,38 +607,6 @@ PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_unique_file="../generic/tcl.h" -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_STDIO_H -# include -#endif -#ifdef HAVE_STDLIB_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_header_c_list= ac_subst_vars='LTLIBOBJS LIBOBJS RES @@ -1570,41 +1538,6 @@ fi } # ac_fn_c_try_compile -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -printf %s "checking for $2... " >&6; } -if eval test \${$3+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - eval "$3=yes" -else case e in #( - e) eval "$3=no" ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; -esac -fi -eval ac_res=\$$3 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_compile - # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -2322,15 +2255,6 @@ main (int argc, char **argv) } " -as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" -as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" -as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" -as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" -as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" -as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" -as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" -as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" -as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false @@ -3944,35 +3868,6 @@ printf "%s\n" "#define STATIC_BUILD 1" >>confdefs.h # after SC_ENABLE_SHARED checks the configure switches. #-------------------------------------------------------------------- -ac_header= ac_cache= -for ac_item in $ac_header_c_list -do - if test $ac_cache; then - ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" - if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then - printf "%s\n" "#define $ac_item 1" >> confdefs.h - fi - ac_header= ac_cache= - elif test $ac_header; then - ac_cache=$ac_item - else - ac_header=$ac_item - fi -done - - - - - - - - -if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes -then : - -printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h - -fi # Step 0: Enable 64 bit support? @@ -4887,15 +4782,6 @@ printf "%s\n" "#define EXCEPTION_DISPOSITION int" >>confdefs.h fi - ac_fn_c_check_header_compile "$LINENO" "stdatomic.h" "ac_cv_header_stdatomic_h" "$ac_includes_default" -if test "x$ac_cv_header_stdatomic_h" = xyes -then : - -printf "%s\n" "#define HAVE_STDATOMIC_H 1" >>confdefs.h - -fi - - # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. diff --git a/win/tcl.m4 b/win/tcl.m4 index 1102438..96c1c81 100644 --- a/win/tcl.m4 +++ b/win/tcl.m4 @@ -946,8 +946,6 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) fi - AC_CHECK_HEADER(stdatomic.h, [AC_DEFINE(HAVE_STDATOMIC_H, 1, [Do we have ?])],) - # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index fdef89f..5b24574 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -13,16 +13,6 @@ #include "tclWinInt.h" -#if defined(HAVE_STDATOMIC_H) && defined(NO_ATOMIC) -/* TODO: for test purposes only, remove this before merge! */ -# undef HAVE_STDATOMIC_H -#endif - - -#ifdef HAVE_STDATOMIC_H -#include -#endif /* HAVE_STDATOMIC_H */ - /* Workaround for mingw versions which don't provide this in float.h */ #ifndef _MCW_EM # define _MCW_EM 0x0008001F /* Error masks */ @@ -66,7 +56,7 @@ static int allocOnce = 0; typedef struct WMutex { CRITICAL_SECTION crit; volatile Tcl_ThreadId thread; - volatile int counter; + int counter; } WMutex; #endif /* TCL_THREADS */ @@ -567,64 +557,43 @@ WMutexDestroy( DeleteCriticalSection(&wmutexPtr->crit); } -#ifdef HAVE_STDATOMIC_H - static void WMutexLock( WMutex *wmPtr) { - Tcl_ThreadId mythread = Tcl_GetCurrentThread(); - if (__atomic_load_n(&wmPtr->counter, __ATOMIC_RELAXED) == 0) { - EnterCriticalSection(&wmPtr->crit); - __atomic_store_n(&wmPtr->thread, mythread, __ATOMIC_RELAXED); - } else if (wmPtr->thread != Tcl_GetCurrentThread()) { - EnterCriticalSection(&wmPtr->crit); - __atomic_store_n(&wmPtr->thread, mythread, __ATOMIC_RELAXED); - __atomic_store_n(&wmPtr->counter, 0, __ATOMIC_RELAXED); - } - __atomic_add_fetch(&wmPtr->counter, 1, __ATOMIC_RELAXED); -} + Tcl_ThreadId mythread = Tcl_GetCurrentThread(); -static void -WMutexUnlock( - WMutex *wmPtr) -{ - if (__atomic_sub_fetch(&wmPtr->counter, 1, __ATOMIC_RELAXED) == 0) { - __atomic_store_n(&wmPtr->thread, 0, __ATOMIC_RELAXED); - LeaveCriticalSection(&wmPtr->crit); - } -} - -#else /* HAVE_STDATOMIC_H */ - -static void -WMutexLock( - WMutex *wmPtr) -{ - Tcl_ThreadId mythread = Tcl_GetCurrentThread(); - if (wmPtr->counter == 0) { + if (wmPtr->thread == mythread) { + // We owned the lock already, so it's recursive. + wmPtr->counter++; + } else if (InterlockedCompareExchangePointer((void *volatile *)&wmPtr->thread, (void *)mythread, 0) == NULL) { + // No-one owns the lock, so we can safely lock it. EnterCriticalSection(&wmPtr->crit); - InterlockedExchangePointer((void *volatile*)&wmPtr->thread, mythread); - } else if (wmPtr->thread != mythread) { + } else { + // Someone else owned the lock, so we can safely lock it. Then we own it. EnterCriticalSection(&wmPtr->crit); InterlockedExchangePointer((void *volatile*)&wmPtr->thread, mythread); - InterlockedExchange((volatile long int *)&wmPtr->counter, 0); } - InterlockedIncrement((volatile long int *)&wmPtr->counter); } static void WMutexUnlock( WMutex *wmPtr) { - if (InterlockedDecrement((volatile long int *)&wmPtr->counter) == 0) { + Tcl_ThreadId mythread = Tcl_GetCurrentThread(); + + if (wmPtr->thread != mythread) { + Tcl_Panic("mutex not owned"); + } + if (wmPtr->counter) { + // It's recursive + wmPtr->counter--; + } else { InterlockedExchangePointer((void *volatile*)&wmPtr->thread, 0); LeaveCriticalSection(&wmPtr->crit); } } -#endif /* HAVE_STDATOMIC_H */ - /* locally used prototype */ static void FinalizeConditionEvent(void *data); @@ -848,8 +817,8 @@ Tcl_ConditionWait( */ counter = wmPtr->counter; - wmPtr->thread = 0; wmPtr->counter = 0; + InterlockedExchangePointer((void *volatile*)&wmPtr->thread, 0); LeaveCriticalSection(&wmPtr->crit); timeout = 0; while (!timeout && (tsdPtr->flags & WIN_THREAD_BLOCKED)) { @@ -893,8 +862,9 @@ Tcl_ConditionWait( } LeaveCriticalSection(&winCondPtr->condLock); - Tcl_MutexLock(mutexPtr); + EnterCriticalSection(&wmPtr->crit); wmPtr->counter = counter; + InterlockedExchangePointer((void *volatile*)&wmPtr->thread, Tcl_GetCurrentThread()); } /* -- cgit v0.12