Commit 7f23c57d authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcr100: Add critical_section class implementation.

parent dab64179
...@@ -83,30 +83,6 @@ void msvcrt_init_mt_locks(void) ...@@ -83,30 +83,6 @@ void msvcrt_init_mt_locks(void)
} }
/********************************************************************** /**********************************************************************
* msvcrt_free_mt_locks (internal)
*
* Uninitialize all mt locks. Assume that neither _lock or _unlock will
* be called once we're calling this routine (ie _LOCKTAB_LOCK can be deleted)
*
*/
void msvcrt_free_mt_locks(void)
{
int i;
TRACE( ": uninitializing all mtlocks\n" );
/* Uninitialize the table */
for( i=0; i < _TOTAL_LOCKS; i++ )
{
if( lock_table[ i ].bInit )
{
msvcrt_uninitialize_mlock( i );
}
}
}
/**********************************************************************
* _lock (MSVCRT.@) * _lock (MSVCRT.@)
*/ */
void CDECL _lock( int locknum ) void CDECL _lock( int locknum )
...@@ -309,10 +285,24 @@ MSVCRT_bool __thiscall SpinWait__SpinOnce(SpinWait *this) ...@@ -309,10 +285,24 @@ MSVCRT_bool __thiscall SpinWait__SpinOnce(SpinWait *this)
} }
} }
static HANDLE keyed_event;
typedef struct cs_queue
{
struct cs_queue *next;
} cs_queue;
typedef struct typedef struct
{ {
void *unknown[3]; ULONG_PTR unk_thread_id;
void *head; cs_queue unk_active;
#if _MSVCR_VER >= 110
void *unknown[2];
int unknown2[2];
#else
void *unknown[1];
#endif
cs_queue *head;
void *tail; void *tail;
} critical_section; } critical_section;
...@@ -321,7 +311,18 @@ typedef struct ...@@ -321,7 +311,18 @@ typedef struct
DEFINE_THISCALL_WRAPPER(critical_section_ctor, 4) DEFINE_THISCALL_WRAPPER(critical_section_ctor, 4)
critical_section* __thiscall critical_section_ctor(critical_section *this) critical_section* __thiscall critical_section_ctor(critical_section *this)
{ {
FIXME("(%p) stub\n", this); TRACE("(%p)\n", this);
if(!keyed_event) {
HANDLE event;
NtCreateKeyedEvent(&event, GENERIC_READ|GENERIC_WRITE, NULL, 0);
if(InterlockedCompareExchangePointer(&keyed_event, event, NULL) != NULL)
NtClose(event);
}
this->unk_thread_id = 0;
this->head = this->tail = NULL;
return this; return this;
} }
...@@ -330,7 +331,32 @@ critical_section* __thiscall critical_section_ctor(critical_section *this) ...@@ -330,7 +331,32 @@ critical_section* __thiscall critical_section_ctor(critical_section *this)
DEFINE_THISCALL_WRAPPER(critical_section_dtor, 4) DEFINE_THISCALL_WRAPPER(critical_section_dtor, 4)
void __thiscall critical_section_dtor(critical_section *this) void __thiscall critical_section_dtor(critical_section *this)
{ {
FIXME("(%p) stub\n", this); TRACE("(%p)\n", this);
}
static void __cdecl spin_wait_yield(void)
{
Sleep(0);
}
static inline void spin_wait_for_next_cs(cs_queue *q)
{
SpinWait sw;
if(q->next) return;
SpinWait_ctor(&sw, &spin_wait_yield);
SpinWait__Reset(&sw);
while(!q->next)
SpinWait__SpinOnce(&sw);
SpinWait_dtor(&sw);
}
static inline void cs_set_head(critical_section *cs, cs_queue *q)
{
cs->unk_thread_id = GetCurrentThreadId();
cs->unk_active.next = q->next;
cs->head = &cs->unk_active;
} }
/* ?lock@critical_section@Concurrency@@QAEXXZ */ /* ?lock@critical_section@Concurrency@@QAEXXZ */
...@@ -338,7 +364,26 @@ void __thiscall critical_section_dtor(critical_section *this) ...@@ -338,7 +364,26 @@ void __thiscall critical_section_dtor(critical_section *this)
DEFINE_THISCALL_WRAPPER(critical_section_lock, 4) DEFINE_THISCALL_WRAPPER(critical_section_lock, 4)
void __thiscall critical_section_lock(critical_section *this) void __thiscall critical_section_lock(critical_section *this)
{ {
FIXME("(%p) stub\n", this); cs_queue q, *last;
TRACE("(%p)\n", this);
if(this->unk_thread_id == GetCurrentThreadId()) {
FIXME("throw exception\n");
return;
}
q.next = NULL;
last = InterlockedExchangePointer(&this->tail, &q);
if(last) {
last->next = &q;
NtWaitForKeyedEvent(keyed_event, &q, 0, NULL);
}
this->unk_active.next = NULL;
if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, &q) != &q)
spin_wait_for_next_cs(&q);
cs_set_head(this, &q);
} }
/* ?try_lock@critical_section@Concurrency@@QAE_NXZ */ /* ?try_lock@critical_section@Concurrency@@QAE_NXZ */
...@@ -346,7 +391,24 @@ void __thiscall critical_section_lock(critical_section *this) ...@@ -346,7 +391,24 @@ void __thiscall critical_section_lock(critical_section *this)
DEFINE_THISCALL_WRAPPER(critical_section_try_lock, 4) DEFINE_THISCALL_WRAPPER(critical_section_try_lock, 4)
MSVCRT_bool __thiscall critical_section_try_lock(critical_section *this) MSVCRT_bool __thiscall critical_section_try_lock(critical_section *this)
{ {
FIXME("(%p) stub\n", this); cs_queue q;
TRACE("(%p)\n", this);
if(this->unk_thread_id == GetCurrentThreadId()) {
FIXME("throw exception\n");
return FALSE;
}
q.next = NULL;
if(!InterlockedCompareExchangePointer(&this->tail, &q, NULL)) {
this->unk_active.next = NULL;
if(InterlockedCompareExchangePointer(&this->tail, &this->unk_active, &q) != &q)
spin_wait_for_next_cs(&q);
cs_set_head(this, &q);
return TRUE;
}
return FALSE; return FALSE;
} }
...@@ -355,7 +417,15 @@ MSVCRT_bool __thiscall critical_section_try_lock(critical_section *this) ...@@ -355,7 +417,15 @@ MSVCRT_bool __thiscall critical_section_try_lock(critical_section *this)
DEFINE_THISCALL_WRAPPER(critical_section_unlock, 4) DEFINE_THISCALL_WRAPPER(critical_section_unlock, 4)
void __thiscall critical_section_unlock(critical_section *this) void __thiscall critical_section_unlock(critical_section *this)
{ {
FIXME("(%p) stub\n", this); TRACE("(%p)\n", this);
this->unk_thread_id = 0;
this->head = NULL;
if(InterlockedCompareExchangePointer(&this->tail, NULL, &this->unk_active)
== &this->unk_active) return;
spin_wait_for_next_cs(&this->unk_active);
NtReleaseKeyedEvent(keyed_event, this->unk_active.next, 0, NULL);
} }
/* ?native_handle@critical_section@Concurrency@@QAEAAV12@XZ */ /* ?native_handle@critical_section@Concurrency@@QAEAAV12@XZ */
...@@ -394,3 +464,31 @@ void __thiscall critical_section_scoped_lock_dtor(critical_section_scoped_lock * ...@@ -394,3 +464,31 @@ void __thiscall critical_section_scoped_lock_dtor(critical_section_scoped_lock *
critical_section_unlock(this->cs); critical_section_unlock(this->cs);
} }
#endif #endif
/**********************************************************************
* msvcrt_free_locks (internal)
*
* Uninitialize all mt locks. Assume that neither _lock or _unlock will
* be called once we're calling this routine (ie _LOCKTAB_LOCK can be deleted)
*
*/
void msvcrt_free_locks(void)
{
int i;
TRACE( ": uninitializing all mtlocks\n" );
/* Uninitialize the table */
for( i=0; i < _TOTAL_LOCKS; i++ )
{
if( lock_table[ i ].bInit )
{
msvcrt_uninitialize_mlock( i );
}
}
#if _MSVCR_VER >= 100
if(keyed_event)
NtClose(keyed_event);
#endif
}
...@@ -106,7 +106,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) ...@@ -106,7 +106,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
} }
msvcrt_init_mt_locks(); msvcrt_init_mt_locks();
if(!msvcrt_init_locale()) { if(!msvcrt_init_locale()) {
msvcrt_free_mt_locks(); msvcrt_free_locks();
msvcrt_free_tls_mem(); msvcrt_free_tls_mem();
msvcrt_destroy_heap(); msvcrt_destroy_heap();
return FALSE; return FALSE;
...@@ -130,7 +130,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) ...@@ -130,7 +130,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
msvcrt_free_io(); msvcrt_free_io();
if (lpvReserved) break; if (lpvReserved) break;
msvcrt_free_popen_data(); msvcrt_free_popen_data();
msvcrt_free_mt_locks(); msvcrt_free_locks();
msvcrt_free_console(); msvcrt_free_console();
msvcrt_free_args(); msvcrt_free_args();
msvcrt_free_signals(); msvcrt_free_signals();
......
...@@ -261,7 +261,7 @@ typedef void (__cdecl *free_func_t)(void*); ...@@ -261,7 +261,7 @@ typedef void (__cdecl *free_func_t)(void*);
/* Setup and teardown multi threaded locks */ /* Setup and teardown multi threaded locks */
extern void msvcrt_init_mt_locks(void) DECLSPEC_HIDDEN; extern void msvcrt_init_mt_locks(void) DECLSPEC_HIDDEN;
extern void msvcrt_free_mt_locks(void) DECLSPEC_HIDDEN; extern void msvcrt_free_locks(void) DECLSPEC_HIDDEN;
extern void msvcrt_init_exception(void*) DECLSPEC_HIDDEN; extern void msvcrt_init_exception(void*) DECLSPEC_HIDDEN;
extern BOOL msvcrt_init_locale(void) DECLSPEC_HIDDEN; extern BOOL msvcrt_init_locale(void) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment