mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-11-01 03:48:57 +08:00 
			
		
		
		
	mdbx: provide SRWL stub for Windows XP/2000.
Change-Id: I438373a4952298efc88ca4c1a92c88e173b82f98
This commit is contained in:
		| @@ -779,7 +779,7 @@ struct MDBX_env { | |||||||
|   } me_dbgeo;      /* */ |   } me_dbgeo;      /* */ | ||||||
|  |  | ||||||
| #if defined(_WIN32) || defined(_WIN64) | #if defined(_WIN32) || defined(_WIN64) | ||||||
|   SRWLOCK me_remap_guard; |   MDBX_srwlock me_remap_guard; | ||||||
|   /* Workaround for LockFileEx and WriteFile multithread bug */ |   /* Workaround for LockFileEx and WriteFile multithread bug */ | ||||||
|   CRITICAL_SECTION me_windowsbug_lock; |   CRITICAL_SECTION me_windowsbug_lock; | ||||||
| #else | #else | ||||||
|   | |||||||
| @@ -156,7 +156,7 @@ void mdbx_txn_unlock(MDBX_env *env) { | |||||||
| #define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN | #define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN | ||||||
|  |  | ||||||
| int mdbx_rdt_lock(MDBX_env *env) { | int mdbx_rdt_lock(MDBX_env *env) { | ||||||
|   AcquireSRWLockShared(&env->me_remap_guard); |   mdbx_srwlock_AcquireShared(&env->me_remap_guard); | ||||||
|   if (env->me_lfd == INVALID_HANDLE_VALUE) |   if (env->me_lfd == INVALID_HANDLE_VALUE) | ||||||
|     return MDBX_SUCCESS; /* readonly database in readonly filesystem */ |     return MDBX_SUCCESS; /* readonly database in readonly filesystem */ | ||||||
|  |  | ||||||
| @@ -165,7 +165,7 @@ int mdbx_rdt_lock(MDBX_env *env) { | |||||||
|     return MDBX_SUCCESS; |     return MDBX_SUCCESS; | ||||||
|  |  | ||||||
|   int rc = GetLastError(); |   int rc = GetLastError(); | ||||||
|   ReleaseSRWLockShared(&env->me_remap_guard); |   mdbx_srwlock_ReleaseShared(&env->me_remap_guard); | ||||||
|   return rc; |   return rc; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -175,7 +175,7 @@ void mdbx_rdt_unlock(MDBX_env *env) { | |||||||
|     if (!funlock(env->me_lfd, LCK_UPPER)) |     if (!funlock(env->me_lfd, LCK_UPPER)) | ||||||
|       mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError()); |       mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError()); | ||||||
|   } |   } | ||||||
|   ReleaseSRWLockShared(&env->me_remap_guard); |   mdbx_srwlock_ReleaseShared(&env->me_remap_guard); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int suspend_and_append(mdbx_handle_array_t **array, | static int suspend_and_append(mdbx_handle_array_t **array, | ||||||
| @@ -573,3 +573,103 @@ int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) { | |||||||
|     return rc; |     return rc; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | //---------------------------------------------------------------------------- | ||||||
|  | // Stub for slim read-write lock | ||||||
|  | // Copyright (C) 1995-2002 Brad Wilson | ||||||
|  |  | ||||||
|  | static void WINAPI stub_srwlock_Init(MDBX_srwlock *srwl) { | ||||||
|  |   srwl->readerCount = srwl->writerCount = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void WINAPI stub_srwlock_AcquireShared(MDBX_srwlock *srwl) { | ||||||
|  |   while (true) { | ||||||
|  |     assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); | ||||||
|  |  | ||||||
|  |     //  If there's a writer already, spin without unnecessarily | ||||||
|  |     //  interlocking the CPUs | ||||||
|  |     if (srwl->writerCount != 0) { | ||||||
|  |       YieldProcessor(); | ||||||
|  |       continue; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //  Add to the readers list | ||||||
|  |     _InterlockedIncrement(&srwl->readerCount); | ||||||
|  |  | ||||||
|  |     // Check for writers again (we may have been pre-empted). If | ||||||
|  |     // there are no writers writing or waiting, then we're done. | ||||||
|  |     if (srwl->writerCount == 0) | ||||||
|  |       break; | ||||||
|  |  | ||||||
|  |     // Remove from the readers list, spin, try again | ||||||
|  |     _InterlockedDecrement(&srwl->readerCount); | ||||||
|  |     YieldProcessor(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void WINAPI stub_srwlock_ReleaseShared(MDBX_srwlock *srwl) { | ||||||
|  |   assert(srwl->readerCount > 0); | ||||||
|  |   _InterlockedDecrement(&srwl->readerCount); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void WINAPI stub_srwlock_AcquireExclusive(MDBX_srwlock *srwl) { | ||||||
|  |   while (true) { | ||||||
|  |     assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); | ||||||
|  |  | ||||||
|  |     //  If there's a writer already, spin without unnecessarily | ||||||
|  |     //  interlocking the CPUs | ||||||
|  |     if (srwl->writerCount != 0) { | ||||||
|  |       YieldProcessor(); | ||||||
|  |       continue; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // See if we can become the writer (expensive, because it inter- | ||||||
|  |     // locks the CPUs, so writing should be an infrequent process) | ||||||
|  |     if (_InterlockedExchange(&srwl->writerCount, 1) == 0) | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Now we're the writer, but there may be outstanding readers. | ||||||
|  |   // Spin until there aren't any more; new readers will wait now | ||||||
|  |   // that we're the writer. | ||||||
|  |   while (srwl->readerCount != 0) { | ||||||
|  |     assert(srwl->writerCount >= 0 && srwl->readerCount >= 0); | ||||||
|  |     YieldProcessor(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void WINAPI stub_srwlock_ReleaseExclusive(MDBX_srwlock *srwl) { | ||||||
|  |   assert(srwl->writerCount == 1 && srwl->readerCount >= 0); | ||||||
|  |   srwl->writerCount = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void WINAPI srwlock_thunk_init(MDBX_srwlock *srwl) { | ||||||
|  |   HINSTANCE hInst = GetModuleHandleA("kernel32.dll"); | ||||||
|  |   MDBX_srwlock_function init = | ||||||
|  |       (MDBX_srwlock_function)GetProcAddress(hInst, "InitializeSRWLock"); | ||||||
|  |   if (init != NULL) { | ||||||
|  |     mdbx_srwlock_AcquireShared = | ||||||
|  |         (MDBX_srwlock_function)GetProcAddress(hInst, "AcquireSRWLockShared"); | ||||||
|  |     mdbx_srwlock_ReleaseShared = | ||||||
|  |         (MDBX_srwlock_function)GetProcAddress(hInst, "ReleaseSRWLockShared"); | ||||||
|  |     mdbx_srwlock_AcquireExclusive = | ||||||
|  |         (MDBX_srwlock_function)GetProcAddress(hInst, "AcquireSRWLockExclusive"); | ||||||
|  |     mdbx_srwlock_ReleaseExclusive = | ||||||
|  |         (MDBX_srwlock_function)GetProcAddress(hInst, "ReleaseSRWLockExclusive"); | ||||||
|  |   } else { | ||||||
|  |     init = stub_srwlock_Init; | ||||||
|  |     mdbx_srwlock_AcquireShared = stub_srwlock_AcquireShared; | ||||||
|  |     mdbx_srwlock_ReleaseShared = stub_srwlock_ReleaseShared; | ||||||
|  |     mdbx_srwlock_AcquireExclusive = stub_srwlock_AcquireExclusive; | ||||||
|  |     mdbx_srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive; | ||||||
|  |   } | ||||||
|  |   mdbx_compiler_barrier(); | ||||||
|  |   mdbx_srwlock_Init = init; | ||||||
|  |   mdbx_srwlock_Init(srwl); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | MDBX_srwlock_function mdbx_srwlock_Init = srwlock_thunk_init; | ||||||
|  | MDBX_srwlock_function mdbx_srwlock_AcquireShared; | ||||||
|  | MDBX_srwlock_function mdbx_srwlock_ReleaseShared; | ||||||
|  | MDBX_srwlock_function mdbx_srwlock_AcquireExclusive; | ||||||
|  | MDBX_srwlock_function mdbx_srwlock_ReleaseExclusive; | ||||||
|   | |||||||
| @@ -2003,7 +2003,7 @@ static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno, | |||||||
|   /* Acquire guard in exclusive mode for: |   /* Acquire guard in exclusive mode for: | ||||||
|    *   - to avoid collision between read and write txns around env->me_dbgeo; |    *   - to avoid collision between read and write txns around env->me_dbgeo; | ||||||
|    *   - to avoid attachment of new reading threads (see mdbx_rdt_lock); */ |    *   - to avoid attachment of new reading threads (see mdbx_rdt_lock); */ | ||||||
|   AcquireSRWLockExclusive(&env->me_remap_guard); |   mdbx_srwlock_AcquireExclusive(&env->me_remap_guard); | ||||||
|   mdbx_handle_array_t *suspended = NULL; |   mdbx_handle_array_t *suspended = NULL; | ||||||
|   mdbx_handle_array_t array_onstack; |   mdbx_handle_array_t array_onstack; | ||||||
|   int rc = MDBX_SUCCESS; |   int rc = MDBX_SUCCESS; | ||||||
| @@ -2083,7 +2083,7 @@ bailout: | |||||||
|  |  | ||||||
| #if defined(_WIN32) || defined(_WIN64) | #if defined(_WIN32) || defined(_WIN64) | ||||||
|   int err = MDBX_SUCCESS; |   int err = MDBX_SUCCESS; | ||||||
|   ReleaseSRWLockExclusive(&env->me_remap_guard); |   mdbx_srwlock_ReleaseExclusive(&env->me_remap_guard); | ||||||
|   if (suspended) { |   if (suspended) { | ||||||
|     err = mdbx_resume_threads_after_remap(suspended); |     err = mdbx_resume_threads_after_remap(suspended); | ||||||
|     if (suspended != &array_onstack) |     if (suspended != &array_onstack) | ||||||
| @@ -4912,7 +4912,7 @@ int __cold mdbx_env_create(MDBX_env **penv) { | |||||||
|     goto bailout; |     goto bailout; | ||||||
|  |  | ||||||
| #if defined(_WIN32) || defined(_WIN64) | #if defined(_WIN32) || defined(_WIN64) | ||||||
|   InitializeSRWLock(&env->me_remap_guard); |   mdbx_srwlock_Init(&env->me_remap_guard); | ||||||
|   InitializeCriticalSection(&env->me_windowsbug_lock); |   InitializeCriticalSection(&env->me_windowsbug_lock); | ||||||
| #else | #else | ||||||
|   rc = mdbx_fastmutex_init(&env->me_remap_guard); |   rc = mdbx_fastmutex_init(&env->me_remap_guard); | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								src/osal.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/osal.h
									
									
									
									
									
								
							| @@ -560,6 +560,23 @@ LIBMDBX_API void mdbx_txn_unlock(MDBX_env *env); | |||||||
| int mdbx_rpid_set(MDBX_env *env); | int mdbx_rpid_set(MDBX_env *env); | ||||||
| int mdbx_rpid_clear(MDBX_env *env); | int mdbx_rpid_clear(MDBX_env *env); | ||||||
|  |  | ||||||
|  | #if defined(_WIN32) || defined(_WIN64) | ||||||
|  | typedef struct MDBX_srwlock { | ||||||
|  |   union { | ||||||
|  |     struct { | ||||||
|  |       long volatile readerCount; | ||||||
|  |       long volatile writerCount; | ||||||
|  |     }; | ||||||
|  |     RTL_SRWLOCK native; | ||||||
|  |   }; | ||||||
|  | } MDBX_srwlock; | ||||||
|  |  | ||||||
|  | typedef void(WINAPI *MDBX_srwlock_function)(MDBX_srwlock *); | ||||||
|  | extern MDBX_srwlock_function mdbx_srwlock_Init, mdbx_srwlock_AcquireShared, | ||||||
|  |     mdbx_srwlock_ReleaseShared, mdbx_srwlock_AcquireExclusive, | ||||||
|  |     mdbx_srwlock_ReleaseExclusive; | ||||||
|  | #endif /* Windows */ | ||||||
|  |  | ||||||
| /* Checks reader by pid. | /* Checks reader by pid. | ||||||
|  * |  * | ||||||
|  * Returns: |  * Returns: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user