From: Vibhav Pant vibhavp@gmail.com
--- dlls/ntdll/atom.c | 25 +++++++++++++++--------- dlls/ntdll/env.c | 16 ++++++++-------- dlls/ntdll/heap.c | 6 +++--- dlls/ntdll/loader.c | 9 +++++---- dlls/ntdll/sync.c | 4 ++-- dlls/ntdll/thread.c | 4 ++-- dlls/ntdll/threadpool.c | 42 +++++++++++++++++++++++++---------------- 7 files changed, 62 insertions(+), 44 deletions(-)
diff --git a/dlls/ntdll/atom.c b/dlls/ntdll/atom.c index 650210cc2cc..d0e0da5f38d 100644 --- a/dlls/ntdll/atom.c +++ b/dlls/ntdll/atom.c @@ -49,7 +49,7 @@ struct atom_handle };
-static NTSTATUS lock_atom_table( RTL_ATOM_TABLE table ) +static NTSTATUS lock_atom_table( RTL_ATOM_TABLE table ) __WINE_TRY_ACQUIRE(STATUS_SUCCESS, &table->CriticalSection) { if (!table) return STATUS_INVALID_PARAMETER; if (table->Signature != TABLE_SIGNATURE) return STATUS_INVALID_PARAMETER; @@ -57,7 +57,7 @@ static NTSTATUS lock_atom_table( RTL_ATOM_TABLE table ) return STATUS_SUCCESS; }
-static void unlock_atom_table( RTL_ATOM_TABLE table ) +static void unlock_atom_table( RTL_ATOM_TABLE table ) __WINE_RELEASE(&table->CriticalSection) { RtlLeaveCriticalSection( &table->CriticalSection ); } @@ -155,7 +155,7 @@ done: /****************************************************************** * RtlDeleteAtomFromAtomTable (NTDLL.@) */ -NTSTATUS WINAPI RtlDeleteAtomFromAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlDeleteAtomFromAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom ) { NTSTATUS status; struct atom_handle *handle; @@ -205,8 +205,10 @@ static ULONG integral_atom_name(WCHAR* buffer, ULONG len, RTL_ATOM atom) /****************************************************************** * RtlQueryAtomInAtomTable (NTDLL.@) */ -NTSTATUS WINAPI RtlQueryAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom, ULONG* ref, - ULONG* pin, WCHAR* name, ULONG* len ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlQueryAtomInAtomTable( RTL_ATOM_TABLE table, + RTL_ATOM atom, ULONG *ref, + ULONG *pin, WCHAR *name, + ULONG *len ) { NTSTATUS status; struct atom_handle *handle; @@ -290,7 +292,9 @@ NTSTATUS WINAPI RtlDestroyAtomTable( RTL_ATOM_TABLE table ) /****************************************************************** * RtlAddAtomToAtomTable (NTDLL.@) */ -NTSTATUS WINAPI RtlAddAtomToAtomTable( RTL_ATOM_TABLE table, const WCHAR* name, RTL_ATOM* atom ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlAddAtomToAtomTable( RTL_ATOM_TABLE table, + const WCHAR *name, + RTL_ATOM *atom ) { NTSTATUS status; size_t len; @@ -308,7 +312,9 @@ NTSTATUS WINAPI RtlAddAtomToAtomTable( RTL_ATOM_TABLE table, const WCHAR* name, /****************************************************************** * RtlLookupAtomInAtomTable (NTDLL.@) */ -NTSTATUS WINAPI RtlLookupAtomInAtomTable( RTL_ATOM_TABLE table, const WCHAR* name, RTL_ATOM* atom ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlLookupAtomInAtomTable( RTL_ATOM_TABLE table, + const WCHAR *name, + RTL_ATOM *atom ) { RTL_ATOM_TABLE_ENTRY *entry; NTSTATUS status; @@ -336,7 +342,8 @@ NTSTATUS WINAPI RtlLookupAtomInAtomTable( RTL_ATOM_TABLE table, const WCHAR* nam /****************************************************************** * RtlEmptyAtomTable (NTDLL.@) */ -NTSTATUS WINAPI RtlEmptyAtomTable( RTL_ATOM_TABLE table, BOOLEAN delete_pinned ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlEmptyAtomTable( RTL_ATOM_TABLE table, + BOOLEAN delete_pinned ) { struct atom_handle *handle; NTSTATUS status; @@ -368,7 +375,7 @@ NTSTATUS WINAPI RtlEmptyAtomTable( RTL_ATOM_TABLE table, BOOLEAN delete_pinned ) /****************************************************************** * RtlPinAtomInAtomTable (NTDLL.@) */ -NTSTATUS WINAPI RtlPinAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlPinAtomInAtomTable( RTL_ATOM_TABLE table, RTL_ATOM atom ) { struct atom_handle *handle; NTSTATUS status; diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c index 720597dcaf9..9af6f36c7cb 100644 --- a/dlls/ntdll/env.c +++ b/dlls/ntdll/env.c @@ -181,9 +181,8 @@ static LPCWSTR ENV_FindVariable(PCWSTR var, PCWSTR name, unsigned namelen) * all chars (except the null) are written and success is returned * (behavior of Win2k at least) */ -NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR env, - PUNICODE_STRING name, - PUNICODE_STRING value) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI +RtlQueryEnvironmentVariable_U( PWSTR env, PUNICODE_STRING name, PUNICODE_STRING value ) { NTSTATUS nts = STATUS_VARIABLE_NOT_FOUND; PCWSTR var; @@ -224,8 +223,9 @@ NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR env, /****************************************************************** * RtlQueryEnvironmentVariable [NTDLL.@] */ -NTSTATUS WINAPI RtlQueryEnvironmentVariable( WCHAR *env, const WCHAR *name, SIZE_T namelen, - WCHAR *value, SIZE_T value_length, SIZE_T *return_length ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI +RtlQueryEnvironmentVariable( WCHAR *env, const WCHAR *name, SIZE_T namelen, WCHAR *value, + SIZE_T value_length, SIZE_T *return_length ) { NTSTATUS nts = STATUS_VARIABLE_NOT_FOUND; SIZE_T len = 0; @@ -291,7 +291,7 @@ void WINAPI RtlSetCurrentEnvironment(PWSTR new_env, PWSTR* old_env) * RtlSetEnvironmentVariable [NTDLL.@] */ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name, - PUNICODE_STRING value) + PUNICODE_STRING value) __WINE_NO_THREAD_SAFETY_ANALYSIS { INT varlen, len, old_size; LPWSTR p, env; @@ -381,8 +381,8 @@ done: /****************************************************************************** * RtlExpandEnvironmentStrings (NTDLL.@) */ -NTSTATUS WINAPI RtlExpandEnvironmentStrings( const WCHAR *renv, WCHAR *src, SIZE_T src_len, - WCHAR *dst, SIZE_T count, SIZE_T *plen ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlExpandEnvironmentStrings( + const WCHAR *renv, WCHAR *src, SIZE_T src_len, WCHAR *dst, SIZE_T count, SIZE_T *plen ) { SIZE_T len, total_size = 1; /* 1 for terminating '\0' */ LPCWSTR env, var; diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 164b8714459..789e67e21d8 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -580,13 +580,13 @@ static inline ULONG heap_get_flags( const struct heap *heap, ULONG flags ) return heap->flags | flags; }
-static inline void heap_lock( struct heap *heap, ULONG flags ) +static inline void __WINE_NO_THREAD_SAFETY_ANALYSIS heap_lock( struct heap *heap, ULONG flags ) __WINE_ACQUIRE(&heap->cs) { if (flags & HEAP_NO_SERIALIZE) return; RtlEnterCriticalSection( &heap->cs ); }
-static inline void heap_unlock( struct heap *heap, ULONG flags ) +static inline void __WINE_NO_THREAD_SAFETY_ANALYSIS heap_unlock( struct heap *heap, ULONG flags ) __WINE_RELEASE(&heap->cs) { if (flags & HEAP_NO_SERIALIZE) return; RtlLeaveCriticalSection( &heap->cs ); @@ -2313,7 +2313,7 @@ BOOLEAN WINAPI RtlLockHeap( HANDLE handle ) * Success: TRUE. The Heap is unlocked. * Failure: FALSE, if heap is invalid. */ -BOOLEAN WINAPI RtlUnlockHeap( HANDLE handle ) +BOOLEAN __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlUnlockHeap( HANDLE handle ) { struct heap *heap; ULONG heap_flags; diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 2982b1e049b..53dd4bef342 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2030,7 +2030,8 @@ NTSTATUS WINAPI LdrUnregisterDllNotification( void *cookie ) * Note: some flags are not implemented. * Flag 0x01 is used to raise exceptions on errors. */ -NTSTATUS WINAPI LdrLockLoaderLock( ULONG flags, ULONG *result, ULONG_PTR *magic ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI LdrLockLoaderLock( ULONG flags, ULONG *result, + ULONG_PTR *magic ) { if (flags & ~0x2) FIXME( "flags %lx not supported\n", flags );
@@ -2062,7 +2063,7 @@ NTSTATUS WINAPI LdrLockLoaderLock( ULONG flags, ULONG *result, ULONG_PTR *magic /****************************************************************** * LdrUnlockLoaderUnlock (NTDLL.@) */ -NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG_PTR magic ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG_PTR magic ) { if (magic) { @@ -4265,7 +4266,7 @@ static void (WINAPI *pWow64LdrpInitialize)( CONTEXT *ctx );
void (WINAPI *pWow64PrepareForException)( EXCEPTION_RECORD *rec, CONTEXT *context ) = NULL;
-static void init_wow64( CONTEXT *context ) +static void init_wow64( CONTEXT *context ) __WINE_RELEASE(&loader_section) { if (!imports_fixup_done) { @@ -4374,7 +4375,7 @@ static void release_address_space(void) * Attach to all the loaded dlls. * If this is the first time, perform the full process initialization. */ -void loader_init( CONTEXT *context, void **entry ) +void __WINE_NO_THREAD_SAFETY_ANALYSIS loader_init( CONTEXT *context, void **entry ) __WINE_EXCLUDES(&loader_section) { static int attach_done; NTSTATUS status; diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 522ce0a2142..ac9375867f2 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -349,7 +349,7 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) /****************************************************************************** * RtlEnterCriticalSection (NTDLL.@) */ -NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit ) { if (crit->SpinCount) { @@ -431,7 +431,7 @@ BOOL WINAPI RtlIsCriticalSectionLockedByThread( RTL_CRITICAL_SECTION *crit ) /****************************************************************************** * RtlLeaveCriticalSection (NTDLL.@) */ -NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit ) +NTSTATUS __WINE_NO_THREAD_SAFETY_ANALYSIS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit ) { if (--crit->RecursionCount) { diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index bc6c2ddb741..962a6a95044 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -466,12 +466,12 @@ static RTL_CRITICAL_SECTION fls_section = { &fls_critsect_debug, -1, 0, 0, 0, 0
#define MAX_FLS_DATA_COUNT 0xff0
-static void lock_fls_data(void) +static void lock_fls_data(void) __WINE_ACQUIRE(&fls_section) { RtlEnterCriticalSection( &fls_section ); }
-static void unlock_fls_data(void) +static void unlock_fls_data(void) __WINE_RELEASE(&fls_section) { RtlLeaveCriticalSection( &fls_section ); } diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index 81cf894d943..5a585ed08dc 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -82,15 +82,17 @@ struct queue_timer HANDLE event; /* removal event */ };
+WINE_DECLARE_LOCK_FIELD_STUB(timer_queue, RTL_CRITICAL_SECTION, cs); struct timer_queue { DWORD magic; RTL_CRITICAL_SECTION cs; - struct list timers; /* sorted by expiration time */ + struct list timers __WINE_FIELD_GUARDED_BY(timer_queue, cs); /* sorted by expiration time */ BOOL quit; /* queue should be deleted; once set, never unset */ HANDLE event; HANDLE thread; }; +WINE_DEFINE_LOCK_FIELD_STUB(timer_queue, RTL_CRITICAL_SECTION, cs);
/* * Object-oriented thread pooling API @@ -99,6 +101,7 @@ struct timer_queue #define THREADPOOL_WORKER_TIMEOUT 5000 #define MAXIMUM_WAITQUEUE_OBJECTS (MAXIMUM_WAIT_OBJECTS - 1)
+WINE_DECLARE_LOCK_FIELD_STUB(threadpool, CRITICAL_SECTION, cs); /* internal threadpool representation */ struct threadpool { @@ -107,7 +110,7 @@ struct threadpool BOOL shutdown; CRITICAL_SECTION cs; /* Pools of work items, locked via .cs, order matches TP_CALLBACK_PRIORITY - high, normal, low. */ - struct list pools[3]; + struct list pools[3] __WINE_FIELD_GUARDED_BY(threadpool, cs); RTL_CONDITION_VARIABLE update_event; /* information about worker threads, locked via .cs */ int max_workers; @@ -117,6 +120,7 @@ struct threadpool HANDLE compl_port; TP_POOL_STACK_INFORMATION stack_info; }; +WINE_DEFINE_LOCK_FIELD_STUB(threadpool, CRITICAL_SECTION, cs);
enum threadpool_objtype { @@ -227,14 +231,16 @@ struct threadpool_instance };
/* internal threadpool group representation */ +WINE_DECLARE_LOCK_FIELD_STUB(threadpool_group, CRITICAL_SECTION, cs); struct threadpool_group { LONG refcount; BOOL shutdown; CRITICAL_SECTION cs; /* list of group members, locked via .cs */ - struct list members; + struct list members __WINE_FIELD_GUARDED_BY(threadpool_group, cs); }; +WINE_DEFINE_LOCK_FIELD_STUB(threadpool_group, CRITICAL_SECTION, cs);
/* global timerqueue object */ static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug; @@ -1053,7 +1059,7 @@ NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer, /*********************************************************************** * timerqueue_thread_proc (internal) */ -static void CALLBACK timerqueue_thread_proc( void *param ) +static void CALLBACK timerqueue_thread_proc( void *param ) __WINE_EXCLUDES(&timerqueue.cs) { ULONGLONG timeout_lower, timeout_upper, new_timeout; struct threadpool_object *other_timer; @@ -1170,7 +1176,7 @@ static NTSTATUS tp_new_worker_thread( struct threadpool *pool ) * Acquires a lock on the global timerqueue. When the lock is acquired * successfully, it is guaranteed that the timer thread is running. */ -static NTSTATUS tp_timerqueue_lock( struct threadpool_object *timer ) +static NTSTATUS tp_timerqueue_lock( struct threadpool_object *timer ) __WINE_EXCLUDES(&timerqueue.cs) { NTSTATUS status = STATUS_SUCCESS; assert( timer->type == TP_OBJECT_TYPE_TIMER ); @@ -1212,7 +1218,7 @@ static NTSTATUS tp_timerqueue_lock( struct threadpool_object *timer ) * * Releases a lock on the global timerqueue. */ -static void tp_timerqueue_unlock( struct threadpool_object *timer ) +static void tp_timerqueue_unlock( struct threadpool_object *timer ) __WINE_EXCLUDES(&timerqueue.cs) { assert( timer->type == TP_OBJECT_TYPE_TIMER );
@@ -1424,7 +1430,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) /*********************************************************************** * tp_waitqueue_lock (internal) */ -static NTSTATUS tp_waitqueue_lock( struct threadpool_object *wait ) +static NTSTATUS tp_waitqueue_lock( struct threadpool_object *wait ) __WINE_EXCLUDES(&waitqueue.cs) { struct waitqueue_bucket *bucket; NTSTATUS status; @@ -1502,7 +1508,7 @@ out: /*********************************************************************** * tp_waitqueue_unlock (internal) */ -static void tp_waitqueue_unlock( struct threadpool_object *wait ) +static void tp_waitqueue_unlock( struct threadpool_object *wait ) __WINE_EXCLUDES(&waitqueue.cs) { assert( wait->type == TP_OBJECT_TYPE_WAIT );
@@ -1521,7 +1527,7 @@ static void tp_waitqueue_unlock( struct threadpool_object *wait ) RtlLeaveCriticalSection( &waitqueue.cs ); }
-static void CALLBACK ioqueue_thread_proc( void *param ) +static void CALLBACK ioqueue_thread_proc( void *param ) __WINE_EXCLUDES(&ioqueue.cs) { struct io_completion *completion; struct threadpool_object *io; @@ -1617,7 +1623,7 @@ static void CALLBACK ioqueue_thread_proc( void *param ) RtlExitUserThread( 0 ); }
-static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file ) +static NTSTATUS tp_ioqueue_lock( struct threadpool_object *io, HANDLE file ) __WINE_EXCLUDES(&ioqueue.cs) { NTSTATUS status = STATUS_SUCCESS;
@@ -1824,7 +1830,7 @@ static NTSTATUS tp_threadpool_lock( struct threadpool **out, TP_CALLBACK_ENVIRON * * Releases a lock on a threadpool. */ -static void tp_threadpool_unlock( struct threadpool *pool ) +static void tp_threadpool_unlock( struct threadpool *pool ) __WINE_EXCLUDES(&pool->cs) { RtlEnterCriticalSection( &pool->cs ); pool->objcount--; @@ -1990,6 +1996,7 @@ static void tp_object_prio_queue( struct threadpool_object *object ) * function has to be VOID because TpPostWork can never fail on Windows. */ static void tp_object_submit( struct threadpool_object *object, BOOL signaled ) + __WINE_EXCLUDES( &object->pool->cs ) { struct threadpool *pool = object->pool; NTSTATUS status = STATUS_UNSUCCESSFUL; @@ -2028,7 +2035,7 @@ static void tp_object_submit( struct threadpool_object *object, BOOL signaled ) * * Cancels all currently pending callbacks for a specific object. */ -static void tp_object_cancel( struct threadpool_object *object ) +static void tp_object_cancel( struct threadpool_object *object ) __WINE_EXCLUDES(&object->pool->cs) { struct threadpool *pool = object->pool; LONG pending_callbacks = 0; @@ -2073,7 +2080,7 @@ static BOOL object_is_finished( struct threadpool_object *object, BOOL group ) * Waits until all pending and running callbacks of a specific object * have been processed. */ -static void tp_object_wait( struct threadpool_object *object, BOOL group_wait ) +static void tp_object_wait( struct threadpool_object *object, BOOL group_wait ) __WINE_EXCLUDES(&object->pool->cs) { struct threadpool *pool = object->pool;
@@ -2088,7 +2095,7 @@ static void tp_object_wait( struct threadpool_object *object, BOOL group_wait ) RtlLeaveCriticalSection( &pool->cs ); }
-static void tp_ioqueue_unlock( struct threadpool_object *io ) +static void tp_ioqueue_unlock( struct threadpool_object *io ) __WINE_EXCLUDES(&ioqueue.cs) { assert( io->type == TP_OBJECT_TYPE_IO );
@@ -2182,7 +2189,9 @@ static struct list *threadpool_get_next_item( const struct threadpool *pool ) * Executes a threadpool object callback, object->pool->cs has to be * held. */ -static void tp_object_execute( struct threadpool_object *object, BOOL wait_thread ) +static void __WINE_NO_THREAD_SAFETY_ANALYSIS tp_object_execute( struct threadpool_object *object, + BOOL wait_thread ) + __WINE_RELEASE(&object->pool->cs) { TP_CALLBACK_INSTANCE *callback_instance; struct threadpool_instance instance; @@ -2338,7 +2347,8 @@ skip_cleanup: /*********************************************************************** * threadpool_worker_proc (internal) */ -static void CALLBACK threadpool_worker_proc( void *param ) +static void CALLBACK __WINE_NO_THREAD_SAFETY_ANALYSIS threadpool_worker_proc( void *param ) + __WINE_EXCLUDES(((struct threadpool *)param )->cs) { struct threadpool *pool = param; LARGE_INTEGER timeout;