From e7434e1770bc895f0d5af423bb6cd4b06c618164 Mon Sep 17 00:00:00 2001 From: Itms Date: Mon, 16 Sep 2024 23:02:32 +0200 Subject: [PATCH] Use std::atomic instead of platform-dependant code This covers atomic add operations and atomic compare-and-switch operations. --- source/lib/allocators/page_aligned.cpp | 3 +- source/lib/code_generation.h | 2 +- source/lib/debug.cpp | 26 ++++++------- source/lib/module_init.cpp | 22 +++++------ source/lib/module_init.h | 6 ++- source/lib/sysdep/arch/x86_x64/apic.cpp | 4 +- source/lib/sysdep/arch/x86_x64/x86_x64.cpp | 12 +++--- source/lib/sysdep/os/win/acpi.cpp | 12 +++--- source/lib/sysdep/os/win/wdbg_sym.cpp | 14 +++---- source/lib/sysdep/os/win/wnuma.cpp | 8 ++-- source/lib/sysdep/os/win/wposix/waio.cpp | 19 +++++----- .../lib/sysdep/os/win/wposix/wfilesystem.cpp | 10 ++--- source/lib/sysdep/os/win/wposix/wpthread.cpp | 17 +++------ source/lib/sysdep/os/win/wposix/wpthread.h | 9 +---- source/lib/sysdep/os/win/wseh.cpp | 8 ++-- source/lib/sysdep/os/win/wvm.cpp | 37 ++++++++++--------- source/lib/sysdep/smbios.cpp | 4 +- source/lib/timer.cpp | 4 +- 18 files changed, 103 insertions(+), 114 deletions(-) diff --git a/source/lib/allocators/page_aligned.cpp b/source/lib/allocators/page_aligned.cpp index 4dea320815..9051945f7f 100644 --- a/source/lib/allocators/page_aligned.cpp +++ b/source/lib/allocators/page_aligned.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -24,7 +24,6 @@ #include "lib/allocators/page_aligned.h" #include "lib/alignment.h" -#include "lib/sysdep/cpu.h" // cpu_CAS //----------------------------------------------------------------------------- diff --git a/source/lib/code_generation.h b/source/lib/code_generation.h index 2b161f6788..d9b8de8ea8 100644 --- a/source/lib/code_generation.h +++ b/source/lib/code_generation.h @@ -44,7 +44,7 @@ * execute the code passed as a parameter only the first time this is * reached. * may be called at any time (in particular before main), but is not - * thread-safe. if that's important, use pthread_once() instead. + * thread-safe. if that's important, use std::call_once instead. **/ #define ONCE(ONCE_code__)\ STMT(\ diff --git a/source/lib/debug.cpp b/source/lib/debug.cpp index 215c68f224..15c0b8bf0b 100644 --- a/source/lib/debug.cpp +++ b/source/lib/debug.cpp @@ -173,13 +173,11 @@ Status debug_WriteCrashlog(const wchar_t* text) BUSY, FAILED }; - // note: the initial state is IDLE. we rely on zero-init because - // initializing local static objects from constants may happen when - // this is first called, which isn't thread-safe. (see C++ 6.7.4) - cassert(IDLE == 0); - static volatile intptr_t state; - if(!cpu_CAS(&state, IDLE, BUSY)) + static std::atomic state{ IDLE }; + + State initial{ IDLE }; + if(!state.compare_exchange_strong(initial, BUSY)) return ERR::REENTERED; // NOWARN OsPath pathname = ah_get_log_dir()/"crashlog.txt"; @@ -342,7 +340,7 @@ void debug_DisplayMessage(const wchar_t* caption, const wchar_t* msg) // errors (e.g. caused by atexit handlers) to come up, possibly causing an // infinite loop. hiding errors isn't good, but we assume that whoever clicked // exit really doesn't want to see any more messages. -static std::atomic isExiting; +static std::atomic isExiting{ false }; // this logic is applicable to any type of error. special cases such as // suppressing certain expected WARN_ERRs are done there. @@ -465,17 +463,17 @@ enum SkipStatus { INVALID, VALID, BUSY }; -static intptr_t skipStatus = INVALID; +static std::atomic skipStatus{ INVALID }; static Status errorToSkip; static size_t numSkipped; void debug_SkipErrors(Status err) { - if(cpu_CAS(&skipStatus, INVALID, BUSY)) + SkipStatus expected{ INVALID }; + if(skipStatus.compare_exchange_strong(expected, BUSY)) { errorToSkip = err; numSkipped = 0; - COMPILER_FENCE; skipStatus = VALID; // linearization point } else @@ -484,10 +482,10 @@ void debug_SkipErrors(Status err) size_t debug_StopSkippingErrors() { - if(cpu_CAS(&skipStatus, VALID, BUSY)) + SkipStatus expected{ VALID }; + if(skipStatus.compare_exchange_strong(expected, BUSY)) { const size_t ret = numSkipped; - COMPILER_FENCE; skipStatus = INVALID; // linearization point return ret; } @@ -500,11 +498,11 @@ size_t debug_StopSkippingErrors() static bool ShouldSkipError(Status err) { - if(cpu_CAS(&skipStatus, VALID, BUSY)) + SkipStatus expected{ VALID }; + if(skipStatus.compare_exchange_strong(expected, BUSY)) { numSkipped++; const bool ret = (err == errorToSkip); - COMPILER_FENCE; skipStatus = VALID; return ret; } diff --git a/source/lib/module_init.cpp b/source/lib/module_init.cpp index 20733b75e5..c5c891dcc5 100644 --- a/source/lib/module_init.cpp +++ b/source/lib/module_init.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -27,25 +27,25 @@ #include "precompiled.h" #include "lib/module_init.h" -#include "lib/sysdep/cpu.h" // cpu_CAS +#include "lib/sysdep/cpu.h" // not yet initialized, or already shutdown -static const ModuleInitState UNINITIALIZED = 0; // value documented in header +static const Status UNINITIALIZED = 0; // value documented in header // running user callback - concurrent ModuleInit callers must spin -static const ModuleInitState BUSY = ERR::AGAIN; // never returned +static const Status BUSY = ERR::AGAIN; // never returned // init succeeded; allow shutdown -static const ModuleInitState INITIALIZED = INFO::SKIPPED; +static const Status INITIALIZED = INFO::SKIPPED; Status ModuleInit(volatile ModuleInitState* initState, Status (*init)()) { for(;;) { - if(cpu_CAS(initState, UNINITIALIZED, BUSY)) + Status expected{ UNINITIALIZED }; + if(initState->compare_exchange_strong(expected, BUSY)) { Status ret = init(); - *initState = (ret == INFO::OK)? INITIALIZED : ret; - COMPILER_FENCE; + initState->store(ret == INFO::OK ? INITIALIZED : ret); return ret; } @@ -66,11 +66,11 @@ Status ModuleShutdown(volatile ModuleInitState* initState, void (*shutdown)()) { for(;;) { - if(cpu_CAS(initState, INITIALIZED, BUSY)) + Status expected{ INITIALIZED }; + if(initState->compare_exchange_strong(expected, BUSY)) { shutdown(); - *initState = UNINITIALIZED; - COMPILER_FENCE; + initState->store(UNINITIALIZED); return INFO::OK; } diff --git a/source/lib/module_init.h b/source/lib/module_init.h index c0ebc38045..dea0f8e764 100644 --- a/source/lib/module_init.h +++ b/source/lib/module_init.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -27,12 +27,14 @@ #ifndef INCLUDED_MODULE_INIT #define INCLUDED_MODULE_INIT +#include + /** * initialization state of a module (class, source file, etc.) * must be initialized to zero (e.g. by defining as a static variable). * DO NOT change the value! **/ -typedef intptr_t ModuleInitState; // intptr_t is required by cpu_CAS +typedef std::atomic ModuleInitState; /** * calls a user-defined init function if initState is zero. diff --git a/source/lib/sysdep/arch/x86_x64/apic.cpp b/source/lib/sysdep/arch/x86_x64/apic.cpp index 908155b06c..bd9ddbda96 100644 --- a/source/lib/sysdep/arch/x86_x64/apic.cpp +++ b/source/lib/sysdep/arch/x86_x64/apic.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -100,7 +100,7 @@ static Status InitApicIds() return status; } -static ModuleInitState apicInitState; +static ModuleInitState apicInitState{ 0 }; bool AreApicIdsReliable() diff --git a/source/lib/sysdep/arch/x86_x64/x86_x64.cpp b/source/lib/sysdep/arch/x86_x64/x86_x64.cpp index f69ecc14fb..4fa6eb343a 100644 --- a/source/lib/sysdep/arch/x86_x64/x86_x64.cpp +++ b/source/lib/sysdep/arch/x86_x64/x86_x64.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -97,7 +97,7 @@ static Status InitCpuid() bool cpuid(CpuidRegs* regs) { - static ModuleInitState initState; + static ModuleInitState initState{ 0 }; ModuleInit(&initState, InitCpuid); const u32 function = regs->eax; @@ -118,7 +118,7 @@ bool cpuid(CpuidRegs* regs) // keep in sync with enum Cap! static u32 caps[4]; -static ModuleInitState capsInitState; +static ModuleInitState capsInitState{ 0 }; static Status InitCaps() { @@ -199,7 +199,7 @@ static Status InitVendor() Vendors Vendor() { - static ModuleInitState initState; + static ModuleInitState initState{ 0 }; ModuleInit(&initState, InitVendor); return vendor; } @@ -210,7 +210,7 @@ Vendors Vendor() static size_t m_Model; static size_t m_Family; -static ModuleInitState signatureInitState; +static ModuleInitState signatureInitState{ 0 }; static Status InitSignature() { @@ -360,7 +360,7 @@ static Status InitIdentifierString() static const char* IdentifierString() { - static ModuleInitState initState; + static ModuleInitState initState{ 0 }; ModuleInit(&initState, InitIdentifierString); return identifierString; } diff --git a/source/lib/sysdep/os/win/acpi.cpp b/source/lib/sysdep/os/win/acpi.cpp index 316063571a..fa91e3a3dd 100644 --- a/source/lib/sysdep/os/win/acpi.cpp +++ b/source/lib/sysdep/os/win/acpi.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -24,11 +24,12 @@ #include "lib/sysdep/os/win/acpi.h" #include "lib/byte_order.h" -#include "lib/sysdep/cpu.h" #include "lib/module_init.h" #include "lib/sysdep/os/win/wfirmware.h" +#include + #pragma pack(1) typedef const volatile u8* PCV_u8; @@ -103,7 +104,7 @@ static bool ValidateTable(const AcpiTable* table, const char* signature = 0) return true; } -static void AllocateAndCopyTables(const AcpiTable**& tables, size_t& numTables) +static void AllocateAndCopyTables(std::atomic& tables, size_t& numTables) { const wfirmware::Provider provider = FOURCC_BE('A','C','P','I'); const wfirmware::TableIds tableIDs = wfirmware::GetTableIDs(provider); @@ -135,7 +136,7 @@ static void AllocateAndCopyTables(const AcpiTable**& tables, size_t& numTables) //----------------------------------------------------------------------------- // note: avoid global std::map etc. because we may be called before _cinit -static const AcpiTable** tables; // tables == 0 <=> not initialized +static std::atomic tables{ nullptr }; // tables == nullptr <=> not initialized static const AcpiTable* invalidTables; // tables == &invalidTables => init failed static size_t numTables; @@ -153,7 +154,8 @@ void acpi_Shutdown() const AcpiTable* acpi_GetTable(const char* signature) { - if(cpu_CAS(&tables, (const AcpiTable**)0, &invalidTables)) + const AcpiTable** initial{ nullptr }; + if(tables.compare_exchange_strong(initial, &invalidTables)) AllocateAndCopyTables(tables, numTables); // (typically only a few tables, linear search is OK) diff --git a/source/lib/sysdep/os/win/wdbg_sym.cpp b/source/lib/sysdep/os/win/wdbg_sym.cpp index 0c0a306c15..5b86c35f74 100644 --- a/source/lib/sysdep/os/win/wdbg_sym.cpp +++ b/source/lib/sysdep/os/win/wdbg_sym.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -33,13 +33,13 @@ #include "lib/byte_order.h" // movzx_le64 #include "lib/module_init.h" -#include "lib/sysdep/cpu.h" #include "lib/debug_stl.h" #include "lib/app_hooks.h" #include "lib/external_libraries/dbghelp.h" #include "lib/sysdep/os/win/wdbg.h" #include "lib/sysdep/os/win/wutil.h" +#include //---------------------------------------------------------------------------- // dbghelp @@ -95,7 +95,7 @@ static Status InitDbghelp() // symserv wants to access the internet. static void sym_init() { - static ModuleInitState initState; + static ModuleInitState initState{ 0 }; ModuleInit(&initState, InitDbghelp); } @@ -1717,8 +1717,9 @@ static Status dump_frame_cb(const STACKFRAME64* sf, uintptr_t UNUSED(userContext Status debug_DumpStack(wchar_t* buf, size_t maxChars, void* pcontext, const wchar_t* lastFuncToSkip) { - static intptr_t busy; - if(!cpu_CAS(&busy, 0, 1)) + static std::atomic busy{ false }; + + if(busy.exchange(true)) return ERR::REENTERED; // NOWARN out_init(buf, maxChars); @@ -1727,8 +1728,7 @@ Status debug_DumpStack(wchar_t* buf, size_t maxChars, void* pcontext, const wcha wdbg_assert(pcontext != 0); Status ret = wdbg_sym_WalkStack(dump_frame_cb, 0, *(CONTEXT*)pcontext, lastFuncToSkip); - COMPILER_FENCE; - busy = 0; + busy = false; return ret; } diff --git a/source/lib/sysdep/os/win/wnuma.cpp b/source/lib/sysdep/os/win/wnuma.cpp index ef72869d74..680cf07bef 100644 --- a/source/lib/sysdep/os/win/wnuma.cpp +++ b/source/lib/sysdep/os/win/wnuma.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -271,7 +271,7 @@ static void PopulateNodesFromProximityDomains(const ProximityDomains& proximityD //----------------------------------------------------------------------------- -static ModuleInitState initState; +static ModuleInitState initState{ 0 }; static Status InitTopology() { @@ -434,7 +434,7 @@ static Status InitRelativeDistance() double numa_Factor() { - static ModuleInitState _initState; + static ModuleInitState _initState{ 0 }; UNUSED2(ModuleInit(&_initState, InitRelativeDistance)); return relativeDistance; } @@ -464,7 +464,7 @@ static Status InitMemoryInterleaved() bool numa_IsMemoryInterleaved() { - static ModuleInitState _initState; + static ModuleInitState _initState{ 0 }; UNUSED2(ModuleInit(&_initState, InitMemoryInterleaved)); return isMemoryInterleaved; } diff --git a/source/lib/sysdep/os/win/wposix/waio.cpp b/source/lib/sysdep/os/win/wposix/waio.cpp index 0fdf7bea1b..f1e2a150ee 100644 --- a/source/lib/sysdep/os/win/wposix/waio.cpp +++ b/source/lib/sysdep/os/win/wposix/waio.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -35,12 +35,12 @@ #include "lib/bits.h" // round_up #include "lib/alignment.h" // IsAligned #include "lib/module_init.h" -#include "lib/sysdep/cpu.h" // cpu_AtomicAdd #include "lib/sysdep/filesystem.h" // O_DIRECT #include "lib/sysdep/os/win/wutil.h" // wutil_SetPrivilege #include "lib/sysdep/os/win/wiocp.h" #include "lib/sysdep/os/win/wposix/crt_posix.h" // _get_osfhandle +#include #include // (dynamic linking preserves compatibility with previous Windows versions) @@ -171,7 +171,7 @@ struct OvlAllocator // POD void Shutdown() { if(extant != 0) - debug_printf("waio: OvlAllocator::Shutdown with extant=%d\n", extant); + debug_printf("waio: OvlAllocator::Shutdown with extant=%d\n", extant.load()); InterlockedFlushSList(&freelist); @@ -208,14 +208,14 @@ struct OvlAllocator // POD ovl.OffsetHigh = u64_hi(offset); ovl.hEvent = 0; // (notification is via IOCP and/or polling) - cpu_AtomicAdd(&extant, +1); + ++extant; return &ovl; } void Deallocate(OVERLAPPED* ovl) { - cpu_AtomicAdd(&extant, -1); + --extant; const uintptr_t address = uintptr_t(ovl); ENSURE(uintptr_t(storage) <= address && address < uintptr_t(storage)+storageSize); @@ -236,7 +236,7 @@ struct OvlAllocator // POD # pragma warning(pop) #endif - volatile intptr_t extant; + std::atomic extant{ 0 }; }; @@ -306,7 +306,7 @@ struct FileControlBlocks // POD static const int firstDescriptor = 4000; FileControlBlock fcbs[maxFiles]; - CACHE_ALIGNED(volatile intptr_t) inUse[maxFiles]; + CACHE_ALIGNED(std::atomic) inUse[maxFiles]{ 0,0,0,0,0,0,0,0 }; void Init() { @@ -330,7 +330,8 @@ struct FileControlBlocks // POD { for(size_t i = 0; i < maxFiles; i++) { - if(cpu_CAS(&inUse[i], 0, 1)) + intptr_t expected{ 0 }; + if(inUse[i].compare_exchange_strong(expected, 1)) return &fcbs[i]; } @@ -366,7 +367,7 @@ static FileControlBlocks fileControlBlocks; //----------------------------------------------------------------------------- // init/shutdown -static ModuleInitState waio_initState; +static ModuleInitState waio_initState{ 0 }; // called from waio_Open (avoids overhead if this module is never used) static Status waio_Init() diff --git a/source/lib/sysdep/os/win/wposix/wfilesystem.cpp b/source/lib/sysdep/os/win/wposix/wfilesystem.cpp index 235135971d..102d5fde21 100644 --- a/source/lib/sysdep/os/win/wposix/wfilesystem.cpp +++ b/source/lib/sysdep/os/win/wposix/wfilesystem.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -24,12 +24,12 @@ #include "lib/sysdep/filesystem.h" #include "lib/debug.h" -#include "lib/sysdep/cpu.h" // cpu_CAS #include "lib/sysdep/os/win/wutil.h" // StatusFromWin #include "lib/sysdep/os/win/wposix/waio.h" // waio_reopen #include "lib/sysdep/os/win/wposix/wtime_internal.h" // wtime_utc_filetime_to_time_t #include "lib/sysdep/os/win/wposix/crt_posix.h" // _close, _lseeki64 etc. +#include //----------------------------------------------------------------------------- // WDIR suballocator @@ -57,11 +57,11 @@ struct WDIR // POD }; static WDIR wdir_storage; -static volatile intptr_t wdir_in_use; +static std::atomic wdir_in_use{ false }; static inline WDIR* wdir_alloc() { - if(cpu_CAS(&wdir_in_use, 0, 1)) // gained ownership + if(!wdir_in_use.exchange(true)) // gained ownership return &wdir_storage; // already in use (rare) - allocate from heap @@ -72,7 +72,7 @@ static inline void wdir_free(WDIR* d) { if(d == &wdir_storage) { - const bool ok = cpu_CAS(&wdir_in_use, 1, 0); // relinquish ownership + const bool ok = wdir_in_use.exchange(false); // relinquish ownership ENSURE(ok); // ensure it wasn't double-freed } else // allocated from heap diff --git a/source/lib/sysdep/os/win/wposix/wpthread.cpp b/source/lib/sysdep/os/win/wposix/wpthread.cpp index 3ed6605298..3740313b8c 100644 --- a/source/lib/sysdep/os/win/wposix/wpthread.cpp +++ b/source/lib/sysdep/os/win/wposix/wpthread.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -30,7 +30,6 @@ #include #include -#include "lib/sysdep/cpu.h" // cpu_CAS #include "lib/posix/posix_filesystem.h" // O_CREAT #include "lib/sysdep/os/win/wposix/wposix_internal.h" #include "lib/sysdep/os/win/wposix/wtime.h" // timespec @@ -86,14 +85,6 @@ pthread_t pthread_self() } -int pthread_once(pthread_once_t* once, void (*init_routine)()) -{ - if(cpu_CAS((volatile intptr_t*)once, 0, 1)) - init_routine(); - return 0; -} - - int pthread_getschedparam(pthread_t thread, int* policy, struct sched_param* param) { if(policy) @@ -147,7 +138,8 @@ static const size_t MAX_DTORS = 4; static struct { pthread_key_t key; - void (*dtor)(void*); + using dtortype = void (*)(void*); + std::atomic dtor{ nullptr }; } dtors[MAX_DTORS]; @@ -165,7 +157,8 @@ int pthread_key_create(pthread_key_t* key, void (*dtor)(void*)) size_t i; for(i = 0; i < MAX_DTORS; i++) { - if(cpu_CAS((volatile intptr_t*)&dtors[i].dtor, (intptr_t)0, (intptr_t)dtor)) + void (*zero)(void*) { nullptr }; + if(dtors[i].dtor.compare_exchange_strong(zero, dtor)) goto have_slot; } diff --git a/source/lib/sysdep/os/win/wposix/wpthread.h b/source/lib/sysdep/os/win/wposix/wpthread.h index 72d30a0aa4..439109af3c 100644 --- a/source/lib/sysdep/os/win/wposix/wpthread.h +++ b/source/lib/sysdep/os/win/wposix/wpthread.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -27,7 +27,6 @@ #ifndef INCLUDED_WPTHREAD #define INCLUDED_WPTHREAD - // // // @@ -53,12 +52,6 @@ enum // // -// one-time init -typedef intptr_t pthread_once_t; // required for cpu_CAS -#define PTHREAD_ONCE_INIT 0 // static pthread_once_t x = PTHREAD_ONCE_INIT; - -int pthread_once(pthread_once_t*, void (*init_routine)()); - // thread typedef uintptr_t pthread_t; diff --git a/source/lib/sysdep/os/win/wseh.cpp b/source/lib/sysdep/os/win/wseh.cpp index 977fc0dec3..2b45fabb73 100644 --- a/source/lib/sysdep/os/win/wseh.cpp +++ b/source/lib/sysdep/os/win/wseh.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -29,11 +29,11 @@ #include "lib/byte_order.h" // FOURCC #include "lib/utf8.h" -#include "lib/sysdep/cpu.h" #include "lib/sysdep/os/win/win.h" #include "lib/sysdep/os/win/wutil.h" #include "lib/sysdep/os/win/wdbg_sym.h" // wdbg_sym_WriteMinidump +#include #include // __security_init_cookie #define NEED_COOKIE_INIT @@ -249,8 +249,8 @@ long __stdcall wseh_ExceptionFilter(struct _EXCEPTION_POINTERS* ep) // make sure we don't recurse infinitely if this function raises an // SEH exception. (we may only have the guard page's 4 KB worth of // stack space if the exception is EXCEPTION_STACK_OVERFLOW) - static intptr_t nestingLevel = 0; - cpu_AtomicAdd(&nestingLevel, 1); + static std::atomic nestingLevel{ 0 }; + ++nestingLevel; if(nestingLevel >= 3) return EXCEPTION_CONTINUE_SEARCH; diff --git a/source/lib/sysdep/os/win/wvm.cpp b/source/lib/sysdep/os/win/wvm.cpp index 999a586347..c2fcd02780 100644 --- a/source/lib/sysdep/os/win/wvm.cpp +++ b/source/lib/sysdep/os/win/wvm.cpp @@ -31,11 +31,11 @@ #include "lib/alignment.h" // CACHE_ALIGNED #include "lib/bits.h" // round_down #include "lib/module_init.h" -#include "lib/sysdep/cpu.h" // cpu_AtomicAdd #include "lib/sysdep/numa.h" #include "lib/sysdep/os/win/wutil.h" #include "lib/timer.h" +#include #include namespace vm @@ -51,16 +51,16 @@ CACHE_ALIGNED(struct Statistics) // POD // thread-safe (required due to concurrent commits) void NotifyLargePageCommit() { - cpu_AtomicAdd(&largePageCommits, +1); + ++largePageCommits; } void NotifySmallPageCommit() { - cpu_AtomicAdd(&smallPageCommits, +1); + ++smallPageCommits; } - intptr_t largePageCommits; - intptr_t smallPageCommits; + std::atomic largePageCommits{ 0 }; + std::atomic smallPageCommits{ 0 }; }; static CACHE_ALIGNED(Statistics) statistics[os_cpu_MaxProcessors]; @@ -209,8 +209,9 @@ CACHE_ALIGNED(struct AddressRangeDescriptor) // POD Status Allocate(size_t size, size_t commitSize, PageType pageType, int prot) { // if this descriptor wasn't yet in use, mark it as busy - // (double-checking is cheaper than cpu_CAS) - if(base != 0 || !cpu_CAS(&base, intptr_t(0), intptr_t(this))) + // (double-checking is cheaper than compare_exchange) + void* unused{ nullptr }; + if(base != nullptr || !base.compare_exchange_strong(unused, static_cast(this))) return INFO::SKIPPED; ENSURE(size != 0); // probably indicates a bug in caller @@ -225,7 +226,7 @@ CACHE_ALIGNED(struct AddressRangeDescriptor) // POD // NB: it is meaningless to ask for large pages when reserving // (see ShouldUseLargePages). pageType only affects subsequent commits. - base = (intptr_t)AllocateLargeOrSmallPages(0, m_TotalSize, MEM_RESERVE); + base = AllocateLargeOrSmallPages(0, m_TotalSize, MEM_RESERVE); if(!base) { debug_printf("AllocateLargeOrSmallPages of %lld failed\n", (u64)m_TotalSize); @@ -233,25 +234,25 @@ CACHE_ALIGNED(struct AddressRangeDescriptor) // POD return ERR::NO_MEM; // NOWARN (error string is more helpful) } - alignedBase = round_up(uintptr_t(base), m_Alignment); + alignedBase = round_up(reinterpret_cast(base.load()), m_Alignment); alignedEnd = alignedBase + round_up(size, m_Alignment); return INFO::OK; } void Free() { - vm::Free((void*)base, m_TotalSize); - m_Alignment = alignedBase = alignedEnd = 0; + vm::Free(base, m_TotalSize); + m_Alignment = 0; m_TotalSize = 0; - COMPILER_FENCE; base = 0; // release descriptor for subsequent reuse + alignedBase = alignedEnd = 0; } bool Contains(uintptr_t address) const { // safety check: we should never see pointers in the no-man's-land // between the original and rounded up base addresses. - ENSURE(!(uintptr_t(base) <= address && address < alignedBase)); + ENSURE(!(reinterpret_cast(base.load()) <= address && address < alignedBase)); return (alignedBase <= address && address < alignedEnd); } @@ -274,7 +275,7 @@ CACHE_ALIGNED(struct AddressRangeDescriptor) // POD // (actual requested size / allocated address is required by // ReleaseAddressSpace due to variable alignment.) - volatile intptr_t base; // (type is dictated by cpu_CAS) + std::atomic base{ nullptr }; size_t m_TotalSize; // parameters to be relayed to vm::Commit @@ -444,8 +445,8 @@ static LONG CALLBACK VectoredHandler(const PEXCEPTION_POINTERS ep) static PVOID handler; -static ModuleInitState initState; -static volatile intptr_t references = 0; // atomic +static ModuleInitState initState{ 0 }; +static std::atomic references{ 0 }; static Status InitHandler() { @@ -466,12 +467,12 @@ static void ShutdownHandler() void BeginOnDemandCommits() { ModuleInit(&initState, InitHandler); - cpu_AtomicAdd(&references, +1); + ++references; } void EndOnDemandCommits() { - if(cpu_AtomicAdd(&references, -1) == 1) + if(references.fetch_sub(1) == 1) ModuleShutdown(&initState, ShutdownHandler); } diff --git a/source/lib/sysdep/smbios.cpp b/source/lib/sysdep/smbios.cpp index 6368f82c8a..9d6579b2dd 100644 --- a/source/lib/sysdep/smbios.cpp +++ b/source/lib/sysdep/smbios.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -690,7 +690,7 @@ void FieldStringizer::operator()(size_t flags, const char*& value, const Structures* GetStructures() { - static ModuleInitState initState; + static ModuleInitState initState{ 0 }; Status ret = ModuleInit(&initState, InitStructures); // (callers have to check if member pointers are nonzero anyway, so // we always return a valid pointer to simplify most use cases.) diff --git a/source/lib/timer.cpp b/source/lib/timer.cpp index 8cc9fd6e95..c9dedd17c0 100644 --- a/source/lib/timer.cpp +++ b/source/lib/timer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -111,7 +111,7 @@ void timer_Init() ENSURE(gettimeofday(&start, 0) == 0); #endif - static ModuleInitState initState; + static ModuleInitState initState{ 0 }; ModuleInit(&initState, InitResolution); ENSURE(resolution != 0.0); }