Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Sep 2019 00:29:25 +0000 (UTC)
From:      Jan Beich <jbeich@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r512864 - in head/emulators/rpcs3: . files
Message-ID:  <201909260029.x8Q0TPrK015459@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jbeich
Date: Thu Sep 26 00:29:25 2019
New Revision: 512864
URL: https://svnweb.freebsd.org/changeset/ports/512864

Log:
  emulators/rpcs3: update to 0.0.6.8777
  
  Changes:	https://github.com/RPCS3/rpcs3/compare/5ec35c7da...5ac631e03

Added:
  head/emulators/rpcs3/files/extra-patch-revert-9710473a2e3e   (contents, props changed)
Deleted:
  head/emulators/rpcs3/files/patch-llvm_cmake_modules_HandleLLVMOptions.cmake
Modified:
  head/emulators/rpcs3/Makefile   (contents, props changed)
  head/emulators/rpcs3/distinfo   (contents, props changed)
  head/emulators/rpcs3/files/extra-patch-revert-4504ac2d1248   (contents, props changed)

Modified: head/emulators/rpcs3/Makefile
==============================================================================
--- head/emulators/rpcs3/Makefile	Thu Sep 26 00:29:09 2019	(r512863)
+++ head/emulators/rpcs3/Makefile	Thu Sep 26 00:29:25 2019	(r512864)
@@ -2,13 +2,10 @@
 
 PORTNAME=	rpcs3
 DISTVERSIONPREFIX=	v
-DISTVERSION=	0.0.7-8760 # git rev-list --count HEAD
-DISTVERSIONSUFFIX=	-g5ec35c7da
+DISTVERSION=	0.0.7-8777 # git rev-list --count HEAD
+DISTVERSIONSUFFIX=	-g5ac631e03
 CATEGORIES=	emulators
 
-PATCH_SITES=	https://github.com/${GH_ACCOUNT}/${GH_PROJECT}/commit/
-PATCHFILES+=	0d9c9c4358e9.patch:-p1
-
 MAINTAINER=	jbeich@FreeBSD.org
 COMMENT=	PS3 emulator/debugger
 
@@ -51,7 +48,9 @@ LLD_UNSAFE=	yes # XXX ports/219089
 .endif
 
 # XXX Remove after FreeBSD 11.2/12.0 reach EOL i.e., around 2020-02-01
+# XXX Switch to bundled libc++ to avoid error-prone reverts
 .if !exists(/usr/include/c++/v1/charconv) && exists(/usr/lib/libc++.so)
+EXTRA_PATCHES+=	${PATCHDIR}/extra-patch-revert-9710473a2e3e
 EXTRA_PATCHES+=	${PATCHDIR}/extra-patch-revert-f9ad6358563b
 EXTRA_PATCHES+=	${PATCHDIR}/extra-patch-revert-4504ac2d1248
 EXTRA_PATCHES+=	${PATCHDIR}/extra-patch-revert-5bd17a44c972

Modified: head/emulators/rpcs3/distinfo
==============================================================================
--- head/emulators/rpcs3/distinfo	Thu Sep 26 00:29:09 2019	(r512863)
+++ head/emulators/rpcs3/distinfo	Thu Sep 26 00:29:25 2019	(r512864)
@@ -1,6 +1,6 @@
-TIMESTAMP = 1569197741
-SHA256 (RPCS3-rpcs3-v0.0.7-8760-g5ec35c7da_GH0.tar.gz) = 8be1b5ee89331f539e575d375fb094b3e1f8c11800afbd2f0e338a7f94f7d5b5
-SIZE (RPCS3-rpcs3-v0.0.7-8760-g5ec35c7da_GH0.tar.gz) = 5601486
+TIMESTAMP = 1569442852
+SHA256 (RPCS3-rpcs3-v0.0.7-8777-g5ac631e03_GH0.tar.gz) = 991dce4b8471b0252b12d8fd206dc94d1fdefa014d06ab773b01cc85a7a239ba
+SIZE (RPCS3-rpcs3-v0.0.7-8777-g5ac631e03_GH0.tar.gz) = 5599517
 SHA256 (RPCS3-hidapi-hidapi-0.8.0-rc1-27-g9220f5e_GH0.tar.gz) = 3120e0b701943f452760e45f9fc1ac50bab356ad4c807b4cac4598041c5ca1a5
 SIZE (RPCS3-hidapi-hidapi-0.8.0-rc1-27-g9220f5e_GH0.tar.gz) = 105400
 SHA256 (RPCS3-llvm-b860b5e8f4ee_GH0.tar.gz) = c151972a0c8ceac568c24b61e63d2ecbdac0f125185e23fc2238e0a14048256e
@@ -19,5 +19,3 @@ SHA256 (USCiLab-cereal-v1.2.0_GH0.tar.gz) = 1ccf3ed205
 SIZE (USCiLab-cereal-v1.2.0_GH0.tar.gz) = 299883
 SHA256 (zeux-pugixml-v1.9-51-g8bf806c_GH0.tar.gz) = 37bed90f3dadb642acca41508391d1409a75af05f34f13da56c866d5c3c4b00d
 SIZE (zeux-pugixml-v1.9-51-g8bf806c_GH0.tar.gz) = 560956
-SHA256 (0d9c9c4358e9.patch) = 10fbe5b4a92917ecceb0870c8c30a28fa518432ce2facee621cc8816e7e1c8b8
-SIZE (0d9c9c4358e9.patch) = 920

Modified: head/emulators/rpcs3/files/extra-patch-revert-4504ac2d1248
==============================================================================
--- head/emulators/rpcs3/files/extra-patch-revert-4504ac2d1248	Thu Sep 26 00:29:09 2019	(r512863)
+++ head/emulators/rpcs3/files/extra-patch-revert-4504ac2d1248	Thu Sep 26 00:29:25 2019	(r512864)
@@ -71,20 +71,25 @@ rpcs3/util/atomic.cpp:307:5: error: use of undeclared 
  #ifdef _WIN32
  		LARGE_INTEGER qw;
  		qw.QuadPart = -static_cast<s64>(timeout / 100);
-@@ -260,13 +245,6 @@ void atomic_storage_futex::wait(const void* data, std:
+@@ -259,18 +244,6 @@ void atomic_storage_futex::wait(const void* data, std:
+ 		{
+ 			if (value & s_waiter_mask)
  			{
- 				value -= s_waiter_mask & -s_waiter_mask;
- 
 -#ifdef _WIN32
 -				if (!fallback)
 -				{
+-					if ((value & s_signal_mask) == 0)
+-					{
+-						return false;
+-					}
+-
 -					value -= s_signal_mask & -s_signal_mask;
 -				}
 -#endif
 -
+ 				value -= s_waiter_mask & -s_waiter_mask;
+ 
  				if ((value & s_waiter_mask) == 0)
- 				{
- 					// Reset on last waiter
 @@ -279,7 +257,7 @@ void atomic_storage_futex::wait(const void* data, std:
  			return false;
  		});

Added: head/emulators/rpcs3/files/extra-patch-revert-9710473a2e3e
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/emulators/rpcs3/files/extra-patch-revert-9710473a2e3e	Thu Sep 26 00:29:25 2019	(r512864)
@@ -0,0 +1,783 @@
+--- Utilities/sync.h.orig	2019-09-25 20:20:52 UTC
++++ Utilities/sync.h
+@@ -15,6 +15,7 @@
+ #include <linux/futex.h>
+ #include <sys/time.h>
+ #include <unistd.h>
++#else
+ #endif
+ #include <algorithm>
+ #include <ctime>
+@@ -24,8 +25,12 @@
+ #include <unordered_map>
+ 
+ #ifdef _WIN32
+-DYNAMIC_IMPORT("ntdll.dll", NtWaitForSingleObject, NTSTATUS(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
++DYNAMIC_IMPORT("ntdll.dll", NtWaitForKeyedEvent, NTSTATUS(HANDLE Handle, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
++DYNAMIC_IMPORT("ntdll.dll", NtReleaseKeyedEvent, NTSTATUS(HANDLE Handle, PVOID Key, BOOLEAN Alertable, PLARGE_INTEGER Timeout));
+ DYNAMIC_IMPORT("ntdll.dll", NtDelayExecution, NTSTATUS(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval));
++inline utils::dynamic_import<BOOL(volatile VOID* Address, PVOID CompareAddress, SIZE_T AddressSize, DWORD dwMilliseconds)> OptWaitOnAddress("kernel32.dll", "WaitOnAddress");
++inline utils::dynamic_import<VOID(PVOID Address)> OptWakeByAddressSingle("kernel32.dll", "WakeByAddressSingle");
++inline utils::dynamic_import<VOID(PVOID Address)> OptWakeByAddressAll("kernel32.dll", "WakeByAddressAll");
+ #endif
+ 
+ #ifndef __linux__
+--- rpcs3/util/atomic.cpp.orig	2019-09-25 20:20:52 UTC
++++ rpcs3/util/atomic.cpp
+@@ -1,24 +1,11 @@
+ #include "atomic.hpp"
+ 
+-// USE_FUTEX takes precedence over USE_POSIX
+-
+-#ifdef __linux__
+-#define USE_FUTEX
+-#define USE_POSIX
+-#endif
+-
+ #include "Utilities/sync.h"
+ #include "Utilities/asm.h"
+ 
+-#ifdef USE_POSIX
+-#include <semaphore.h>
+-#endif
+-
+ #include <map>
+ #include <mutex>
+ #include <condition_variable>
+-#include <iterator>
+-#include <memory>
+ 
+ // Total number of entries, should be a power of 2.
+ static constexpr std::uintptr_t s_hashtable_size = 1u << 22;
+@@ -35,18 +22,8 @@ static constexpr u64 s_waiter_mask = 0x7fff'0000'0000'
+ //
+ static constexpr u64 s_collision_bit = 0x8000'0000'0000'0000;
+ 
+-#ifdef USE_FUTEX
+-static constexpr u64 s_sema_mask = 0;
+-#else
+-// Number of search groups (defines max semaphore count as gcount * 64)
+-static constexpr u32 s_sema_gcount = 64;
+-
+-// Bits encoding allocated semaphore index (zero = not allocated yet)
+-static constexpr u64 s_sema_mask = (64 * s_sema_gcount - 1) << 2;
+-#endif
+-
+ // Implementation detail (remaining bits out of 32 available for futex)
+-static constexpr u64 s_signal_mask = 0xffffffff & ~(s_waiter_mask | s_pointer_mask | s_collision_bit | s_sema_mask);
++static constexpr u64 s_signal_mask = 0xffffffff & ~(s_waiter_mask | s_pointer_mask | s_collision_bit);
+ 
+ // Callback for wait() function, returns false if wait should return
+ static thread_local bool(*s_tls_wait_cb)(const void* data) = [](const void*)
+@@ -54,140 +31,6 @@ static thread_local bool(*s_tls_wait_cb)(const void* d
+ 	return true;
+ };
+ 
+-#ifndef USE_FUTEX
+-
+-#ifdef USE_POSIX
+-using sema_handle = sem_t;
+-#elif defined(_WIN32)
+-using sema_handle = HANDLE;
+-#else
+-namespace
+-{
+-	struct dumb_sema
+-	{
+-		u64 count = 0;
+-		std::mutex mutex;
+-		std::condition_variable cond;
+-	};
+-}
+-
+-using sema_handle = std::unique_ptr<dumb_sema>;
+-#endif
+-
+-// Array of native semaphores
+-static sema_handle s_sema_list[64 * s_sema_gcount]{};
+-
+-// Array of associated reference counters
+-static atomic_t<u64> s_sema_refs[64 * s_sema_gcount]{};
+-
+-// Allocation bits (reserve first bit)
+-static atomic_t<u64> s_sema_bits[s_sema_gcount]{1};
+-
+-static u32 sema_alloc()
+-{
+-	// Diversify search start points to reduce contention and increase immediate success chance
+-#ifdef _WIN32
+-	const u32 start = GetCurrentProcessorNumber();
+-#elif __linux__
+-	const u32 start = sched_getcpu();
+-#else
+-	const u32 start = __rdtsc();
+-#endif
+-
+-	for (u32 i = 0; i < s_sema_gcount * 3; i++)
+-	{
+-		const u32 group = (i + start) % s_sema_gcount;
+-
+-		const auto [bits, ok] = s_sema_bits[group].fetch_op([](u64& bits)
+-		{
+-			if (~bits)
+-			{
+-				// Set lowest clear bit
+-				bits |= bits + 1;
+-				return true;
+-			}
+-
+-			return false;
+-		});
+-
+-		if (ok)
+-		{
+-			// Find lowest clear bit
+-			const u32 id = group * 64 + utils::cnttz64(~bits, false);
+-
+-#ifdef USE_POSIX
+-			// Initialize semaphore (should be very fast)
+-			sem_init(&s_sema_list[id], 0, 0);
+-#elif defined(_WIN32)
+-			if (!s_sema_list[id])
+-			{
+-				s_sema_list[id] = CreateSemaphoreW(nullptr, 0, 0x7fff'ffff, nullptr);
+-			}
+-#else
+-			if (!s_sema_list[id])
+-			{
+-				s_sema_list[id] = std::make_unique<dumb_sema>();
+-			}
+-#endif
+-
+-			// Initialize ref counter
+-			if (s_sema_refs[id]++)
+-			{
+-				std::abort();
+-			}
+-
+-			return id;
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-static void sema_free(u32 id)
+-{
+-	if (id && id < 64 * s_sema_gcount)
+-	{
+-		// Dereference first
+-		if (--s_sema_refs[id])
+-		{
+-			return;
+-		}
+-
+-#ifdef USE_POSIX
+-		// Destroy semaphore (should be very fast)
+-		sem_destroy(&s_sema_list[id]);
+-#else
+-		// No action required
+-#endif
+-
+-		// Reset allocation bit
+-		s_sema_bits[id / 64] &= ~(1ull << (id % 64));
+-	}
+-}
+-
+-static bool sema_get(u32 id)
+-{
+-	if (id && id < 64 * s_sema_gcount)
+-	{
+-		// Increment only if the semaphore is allocated
+-		if (s_sema_refs[id].fetch_op([](u64& refs)
+-		{
+-			if (refs)
+-			{
+-				// Increase reference from non-zero value
+-				refs++;
+-			}
+-		}))
+-		{
+-			return true;
+-		}
+-	}
+-
+-	return false;
+-}
+-
+-#endif
+-
+ static inline bool ptr_cmp(const void* data, std::size_t size, u64 old_value, u64 mask)
+ {
+ 	switch (size)
+@@ -308,8 +151,27 @@ namespace
+ 	}
+ }
+ 
++#if !defined(_WIN32) && !defined(__linux__)
++
+ void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_value, u64 timeout, u64 mask)
+ {
++	fallback_wait(data, size, old_value, timeout, mask);
++}
++
++void atomic_storage_futex::notify_one(const void* data)
++{
++	fallback_notify_one(data);
++}
++
++void atomic_storage_futex::notify_all(const void* data)
++{
++	fallback_notify_all(data);
++}
++
++#else
++
++void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_value, u64 timeout, u64 mask)
++{
+ 	if (!timeout)
+ 	{
+ 		return;
+@@ -323,8 +185,6 @@ void atomic_storage_futex::wait(const void* data, std:
+ 
+ 	bool fallback = false;
+ 
+-	u32 sema_id = -1;
+-
+ 	const auto [_, ok] = entry.fetch_op([&](u64& value)
+ 	{
+ 		if ((value & s_waiter_mask) == s_waiter_mask || (value & s_signal_mask) == s_signal_mask)
+@@ -333,15 +193,15 @@ void atomic_storage_futex::wait(const void* data, std:
+ 			return false;
+ 		}
+ 
+-#ifndef USE_FUTEX
+-		sema_id = (value & s_sema_mask) >> 2;
+-#endif
+-
+ 		if (!value || (value & s_pointer_mask) == (iptr & s_pointer_mask))
+ 		{
+ 			// Store pointer bits
+ 			value |= (iptr & s_pointer_mask);
+ 			fallback = false;
++
++#ifdef _WIN32
++			value += s_signal_mask & -s_signal_mask;
++#endif
+ 		}
+ 		else
+ 		{
+@@ -361,93 +221,13 @@ void atomic_storage_futex::wait(const void* data, std:
+ 		return;
+ 	}
+ 
+-#ifndef USE_FUTEX
+-	for (u32 loop_count = 0; !fallback && loop_count < 7; loop_count++)
+-	{
+-		// Try to allocate a semaphore
+-		if (!sema_id)
+-		{
+-			const u32 sema = sema_alloc();
+-
+-			if (!sema)
+-			{
+-				break;
+-			}
+-
+-			sema_id = entry.atomic_op([&](u64& value) -> u32
+-			{
+-				if (value & s_sema_mask)
+-				{
+-					return (value & s_sema_mask) >> 2;
+-				}
+-
+-				// Insert allocated semaphore
+-				value += s_signal_mask & -s_signal_mask;
+-				value |= (u64{sema} << 2);
+-				return 0;
+-			});
+-
+-			if (sema_id)
+-			{
+-				// Drop unnecessary allocation
+-				sema_free(sema);
+-			}
+-			else
+-			{
+-				sema_id = sema;
+-				break;
+-			}
+-		}
+-
+-		if (!sema_get(sema_id))
+-		{
+-			sema_id = 0;
+-			continue;
+-		}
+-
+-		// Try to increment sig (check semaphore validity)
+-		const auto [_old, ok] = entry.fetch_op([&](u64& value)
+-		{
+-			if ((value & s_signal_mask) == s_signal_mask)
+-			{
+-				return false;
+-			}
+-
+-			if ((value & s_sema_mask) >> 2 != sema_id)
+-			{
+-				return false;
+-			}
+-
+-			value += s_signal_mask & -s_signal_mask;
+-			return true;
+-		});
+-
+-		if (!ok)
+-		{
+-			sema_free(sema_id);
+-			sema_id = 0;
+-
+-			if ((_old & s_signal_mask) == s_signal_mask)
+-			{
+-				// Break on signal overflow
+-				break;
+-			}
+-
+-			continue;
+-		}
+-
+-		break;
+-	}
+-#endif
+-
+ 	if (fallback)
+ 	{
+ 		fallback_wait(data, size, old_value, timeout, mask);
+ 	}
+-	else if (sema_id && ptr_cmp(data, size, old_value, mask) && s_tls_wait_cb(data))
++	else if (ptr_cmp(data, size, old_value, mask) && s_tls_wait_cb(data))
+ 	{
+-#ifndef USE_FUTEX
+-#if defined(_WIN32) && !defined(USE_POSIX)
++#ifdef _WIN32
+ 		LARGE_INTEGER qw;
+ 		qw.QuadPart = -static_cast<s64>(timeout / 100);
+ 
+@@ -457,60 +237,13 @@ void atomic_storage_futex::wait(const void* data, std:
+ 			qw.QuadPart -= 1;
+ 		}
+ 
+-		if (!NtWaitForSingleObject(s_sema_list[sema_id], false, timeout + 1 ? &qw : nullptr))
++		if (!NtWaitForKeyedEvent(nullptr, &entry, false, timeout + 1 ? &qw : nullptr))
+ 		{
+-			fallback = true;
++			// Return if no errors, continue if timed out
++			s_tls_wait_cb(nullptr);
++			return;
+ 		}
+-#elif defined(USE_POSIX)
+-		struct timespec ts;
+-		clock_gettime(CLOCK_REALTIME, &ts);
+-		ts.tv_sec  += timeout / 1'000'000'000;
+-		ts.tv_nsec += timeout % 1'000'000'000;
+-		ts.tv_sec  += ts.tv_nsec / 1'000'000'000;
+-		ts.tv_nsec %= 1'000'000'000;
+-
+-		// It's pretty unreliable because it uses absolute time, which may jump backwards. Sigh.
+-		if (timeout + 1)
+-		{
+-			if (sem_timedwait(&s_sema_list[sema_id], &ts) == 0)
+-			{
+-				fallback = true;
+-			}
+-		}
+-		else
+-		{
+-			if (sem_wait(&s_sema_list[sema_id]) == 0)
+-			{
+-				fallback = true;
+-			}
+-		}
+ #else
+-		dumb_sema& sema = *s_sema_list[sema_id];
+-
+-		std::unique_lock lock(sema.mutex);
+-
+-		if (timeout + 1)
+-		{
+-			sema.cond.wait_for(lock, std::chrono::nanoseconds(timeout), [&]
+-			{
+-				return sema.count > 0;
+-			});
+-		}
+-		else
+-		{
+-			sema.cond.wait(lock, [&]
+-			{
+-				return sema.count > 0;
+-			});
+-		}
+-
+-		if (sema.count > 0)
+-		{
+-			sema.count--;
+-			fallback = true;
+-		}
+-#endif
+-#else
+ 		struct timespec ts;
+ 		ts.tv_sec  = timeout / 1'000'000'000;
+ 		ts.tv_nsec = timeout % 1'000'000'000;
+@@ -519,11 +252,6 @@ void atomic_storage_futex::wait(const void* data, std:
+ #endif
+ 	}
+ 
+-	if (!sema_id)
+-	{
+-		fallback = true;
+-	}
+-
+ 	while (true)
+ 	{
+ 		// Try to decrement
+@@ -531,21 +259,15 @@ void atomic_storage_futex::wait(const void* data, std:
+ 		{
+ 			if (value & s_waiter_mask)
+ 			{
+-#ifndef USE_FUTEX
+-				// If timeout
++#ifdef _WIN32
+ 				if (!fallback)
+ 				{
+-					if ((value & s_signal_mask) == 0 || (value & s_sema_mask) >> 2 != sema_id)
++					if ((value & s_signal_mask) == 0)
+ 					{
+ 						return false;
+ 					}
+ 
+ 					value -= s_signal_mask & -s_signal_mask;
+-
+-					if ((value & s_signal_mask) == 0)
+-					{
+-						value &= ~s_sema_mask;
+-					}
+ 				}
+ #endif
+ 
+@@ -568,45 +290,22 @@ void atomic_storage_futex::wait(const void* data, std:
+ 			break;
+ 		}
+ 
+-#ifndef USE_FUTEX
+-#if defined(_WIN32) && !defined(USE_POSIX)
++#ifdef _WIN32
+ 		static LARGE_INTEGER instant{};
+ 
+-		if (!NtWaitForSingleObject(s_sema_list[sema_id], false, &instant))
++		if (!NtWaitForKeyedEvent(nullptr, &entry, false, &instant))
+ 		{
+-			fallback = true;
++			break;
+ 		}
+-#elif defined(USE_POSIX)
+-		if (sem_trywait(&s_sema_list[sema_id]) == 0)
+-		{
+-			fallback = true;
+-		}
+ #else
+-		dumb_sema& sema = *s_sema_list[sema_id];
+-
+-		std::unique_lock lock(sema.mutex);
+-
+-		if (sema.count > 0)
+-		{
+-			sema.count--;
+-			fallback = true;
+-		}
++		// Unreachable
++		std::terminate();
+ #endif
+-#endif
+ 	}
+ 
+-#ifndef USE_FUTEX
+-	if (sema_id)
+-	{
+-		sema_free(sema_id);
+-	}
+-#endif
+-
+ 	s_tls_wait_cb(nullptr);
+ }
+ 
+-#ifdef USE_FUTEX
+-
+ void atomic_storage_futex::notify_one(const void* data)
+ {
+ 	const std::uintptr_t iptr = reinterpret_cast<std::uintptr_t>(data);
+@@ -617,6 +316,23 @@ void atomic_storage_futex::notify_one(const void* data
+ 	{
+ 		if (value & s_waiter_mask && (value & s_pointer_mask) == (iptr & s_pointer_mask))
+ 		{
++#ifdef _WIN32
++			if ((value & s_signal_mask) == 0)
++			{
++				// No relevant waiters, do nothing
++				return false;
++			}
++
++			// Try to decrement if possible
++			value -= s_waiter_mask & -s_waiter_mask;
++			value -= s_signal_mask & -s_signal_mask;
++
++			if ((value & s_waiter_mask) == 0)
++			{
++				// Reset on last waiter
++				value = 0;
++			}
++#else
+ 			if ((value & s_signal_mask) == s_signal_mask)
+ 			{
+ 				// Signal overflow, do nothing
+@@ -631,7 +347,7 @@ void atomic_storage_futex::notify_one(const void* data
+ 				notify_all(data);
+ 				return false;
+ 			}
+-
++#endif
+ 			return true;
+ 		}
+ 		else if (value & s_waiter_mask && value & s_collision_bit)
+@@ -645,7 +361,11 @@ void atomic_storage_futex::notify_one(const void* data
+ 
+ 	if (ok)
+ 	{
++#ifdef _WIN32
++		NtReleaseKeyedEvent(nullptr, &entry, false, nullptr);
++#else
+ 		futex(reinterpret_cast<char*>(&entry) + 4 * IS_BE_MACHINE, FUTEX_WAKE_PRIVATE, 1);
++#endif
+ 	}
+ }
+ 
+@@ -655,6 +375,53 @@ void atomic_storage_futex::notify_all(const void* data
+ 
+ 	atomic_t<u64>& entry = s_hashtable[(iptr >> 2) % s_hashtable_size];
+ 
++	// Try to consume everything
++#ifdef _WIN32
++	const auto [old, ok] = entry.fetch_op([&](u64& value)
++	{
++		if (value & s_waiter_mask)
++		{
++			if ((value & s_pointer_mask) == (iptr & s_pointer_mask))
++			{
++				if ((value & s_signal_mask) == 0)
++				{
++					// No relevant waiters, do nothing
++					return false;
++				}
++
++				const u64 count = (value & s_signal_mask) / (s_signal_mask & -s_signal_mask);
++				value -= (s_waiter_mask & -s_waiter_mask) * count;
++				value -= (s_signal_mask & -s_signal_mask) * count;
++
++				if ((value & s_waiter_mask) == 0)
++				{
++					// Reset on last waiter
++					value = 0;
++				}
++
++				return true;
++			}
++
++			if (value & s_collision_bit)
++			{
++				fallback_notify_all(data);
++				return false;
++			}
++		}
++
++		return false;
++	});
++
++	if (!ok)
++	{
++		return;
++	}
++
++	for (u64 count = old & s_signal_mask; count; count -= s_signal_mask & -s_signal_mask)
++	{
++		NtReleaseKeyedEvent(nullptr, &entry, false, nullptr);
++	}
++#else
+ 	const auto [_, ok] = entry.fetch_op([&](u64& value)
+ 	{
+ 		if (value & s_waiter_mask)
+@@ -685,6 +452,7 @@ void atomic_storage_futex::notify_all(const void* data
+ 	{
+ 		futex(reinterpret_cast<char*>(&entry) + 4 * IS_BE_MACHINE, FUTEX_WAKE_PRIVATE, 0x7fffffff);
+ 	}
++#endif
+ }
+ 
+ #endif
+@@ -704,158 +472,3 @@ void atomic_storage_futex::raw_notify(const void* data
+ 		notify_all(data);
+ 	}
+ }
+-
+-#ifndef USE_FUTEX
+-
+-void atomic_storage_futex::notify_one(const void* data)
+-{
+-	const std::uintptr_t iptr = reinterpret_cast<std::uintptr_t>(data);
+-
+-	atomic_t<u64>& entry = s_hashtable[(iptr >> 2) % s_hashtable_size];
+-
+-	const u64 value = entry;
+-
+-	if (value & s_waiter_mask && (value & s_pointer_mask) == (iptr & s_pointer_mask))
+-	{
+-		if ((value & s_signal_mask) == 0 || (value & s_sema_mask) == 0)
+-		{
+-			// No relevant waiters, do nothing
+-			return;
+-		}
+-	}
+-	else if (value & s_waiter_mask && value & s_collision_bit)
+-	{
+-		fallback_notify_one(data);
+-		return;
+-	}
+-	else
+-	{
+-		return;
+-	}
+-
+-	const u32 sema_id = (value & s_sema_mask) >> 2;
+-
+-	if (!sema_get(sema_id))
+-	{
+-		return;
+-	}
+-
+-	const auto [_, ok] = entry.fetch_op([&](u64& value)
+-	{
+-		if ((value & s_waiter_mask) == 0 || (value & s_pointer_mask) != (iptr & s_pointer_mask))
+-		{
+-			return false;
+-		}
+-
+-		if ((value & s_signal_mask) == 0 || (value & s_sema_mask) >> 2 != sema_id)
+-		{
+-			return false;
+-		}
+-
+-		value -= s_signal_mask & -s_signal_mask;
+-
+-		// Reset allocated semaphore on last waiter
+-		if ((value & s_signal_mask) == 0)
+-		{
+-			value &= ~s_sema_mask;
+-		}
+-
+-		return true;
+-	});
+-
+-	if (ok)
+-	{
+-#ifdef USE_POSIX
+-		sem_post(&s_sema_list[sema_id]);
+-#elif defined(_WIN32)
+-		ReleaseSemaphore(s_sema_list[sema_id], 1, nullptr);
+-#else
+-		dumb_sema& sema = *s_sema_list[sema_id];
+-
+-		sema.mutex.lock();
+-		sema.count += 1;
+-		sema.mutex.unlock();
+-		sema.cond.notify_one();
+-#endif
+-	}
+-
+-	sema_free(sema_id);
+-}
+-
+-void atomic_storage_futex::notify_all(const void* data)
+-{
+-	const std::uintptr_t iptr = reinterpret_cast<std::uintptr_t>(data);
+-
+-	atomic_t<u64>& entry = s_hashtable[(iptr >> 2) % s_hashtable_size];
+-
+-	const u64 value = entry;
+-
+-	if (value & s_waiter_mask && (value & s_pointer_mask) == (iptr & s_pointer_mask))
+-	{
+-		if ((value & s_signal_mask) == 0 || (value & s_sema_mask) == 0)
+-		{
+-			// No relevant waiters, do nothing
+-			return;
+-		}
+-	}
+-	else if (value & s_waiter_mask && value & s_collision_bit)
+-	{
+-		fallback_notify_all(data);
+-		return;
+-	}
+-	else
+-	{
+-		return;
+-	}
+-
+-	const u32 sema_id = (value & s_sema_mask) >> 2;
+-
+-	if (!sema_get(sema_id))
+-	{
+-		return;
+-	}
+-
+-	const auto [_, count] = entry.fetch_op([&](u64& value) -> u32
+-	{
+-		if ((value & s_waiter_mask) == 0 || (value & s_pointer_mask) != (iptr & s_pointer_mask))
+-		{
+-			return 0;
+-		}
+-
+-		if ((value & s_signal_mask) == 0 || (value & s_sema_mask) >> 2 != sema_id)
+-		{
+-			return 0;
+-		}
+-
+-		const u32 r = (value & s_signal_mask) / (s_signal_mask & -s_signal_mask);
+-		value &= ~s_sema_mask;
+-		value &= ~s_signal_mask;
+-		return r;
+-	});
+-
+-#ifdef USE_POSIX
+-	for (u32 i = 0; i < count; i++)
+-	{
+-		sem_post(&s_sema_list[sema_id]);
+-	}
+-#elif defined(_WIN32)
+-	if (count)
+-	{
+-		ReleaseSemaphore(s_sema_list[sema_id], count, nullptr);
+-	}
+-#else
+-	if (count)
+-	{
+-		dumb_sema& sema = *s_sema_list[sema_id];
+-
+-		sema.mutex.lock();
+-		sema.count += count;
+-		sema.mutex.unlock();
+-		sema.cond.notify_all();
+-	}
+-#endif
+-
+-	sema_free(sema_id);
+-}
+-
+-#endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909260029.x8Q0TPrK015459>