2 * Copyright (c) 2002, TransGaming Technologies Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
24 #include "wine/debug.h"
28 #include "wine/heap.h"
30 #include "cppexcept.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
39 CRITICAL_SECTION crit
;
42 static LOCKTABLEENTRY lock_table
[ _TOTAL_LOCKS
];
44 static inline void msvcrt_mlock_set_entry_initialized( int locknum
, BOOL initialized
)
46 lock_table
[ locknum
].bInit
= initialized
;
49 static inline void msvcrt_initialize_mlock( int locknum
)
51 InitializeCriticalSection( &(lock_table
[ locknum
].crit
) );
52 lock_table
[ locknum
].crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": LOCKTABLEENTRY.crit");
53 msvcrt_mlock_set_entry_initialized( locknum
, TRUE
);
56 static inline void msvcrt_uninitialize_mlock( int locknum
)
58 lock_table
[ locknum
].crit
.DebugInfo
->Spare
[0] = 0;
59 DeleteCriticalSection( &(lock_table
[ locknum
].crit
) );
60 msvcrt_mlock_set_entry_initialized( locknum
, FALSE
);
63 /**********************************************************************
64 * msvcrt_init_mt_locks (internal)
66 * Initialize the table lock. All other locks will be initialized
70 void msvcrt_init_mt_locks(void)
74 TRACE( "initializing mtlocks\n" );
76 /* Initialize the table */
77 for( i
=0; i
< _TOTAL_LOCKS
; i
++ )
79 msvcrt_mlock_set_entry_initialized( i
, FALSE
);
82 /* Initialize our lock table lock */
83 msvcrt_initialize_mlock( _LOCKTAB_LOCK
);
86 /**********************************************************************
89 void CDECL
_lock( int locknum
)
91 TRACE( "(%d)\n", locknum
);
93 /* If the lock doesn't exist yet, create it */
94 if( lock_table
[ locknum
].bInit
== FALSE
)
96 /* Lock while we're changing the lock table */
97 _lock( _LOCKTAB_LOCK
);
99 /* Check again if we've got a bit of a race on lock creation */
100 if( lock_table
[ locknum
].bInit
== FALSE
)
102 TRACE( ": creating lock #%d\n", locknum
);
103 msvcrt_initialize_mlock( locknum
);
106 /* Unlock ourselves */
107 _unlock( _LOCKTAB_LOCK
);
110 EnterCriticalSection( &(lock_table
[ locknum
].crit
) );
113 /**********************************************************************
116 * NOTE: There is no error detection to make sure the lock exists and is acquired.
118 void CDECL
_unlock( int locknum
)
120 TRACE( "(%d)\n", locknum
);
122 LeaveCriticalSection( &(lock_table
[ locknum
].crit
) );
125 #if _MSVCR_VER >= 100
134 typedef void (__cdecl
*yield_func
)(void);
140 SpinWait_state state
;
141 yield_func yield_func
;
144 /* ?_Value@_SpinCount@details@Concurrency@@SAIXZ */
145 unsigned int __cdecl
SpinCount__Value(void)
147 static unsigned int val
= -1;
155 val
= si
.dwNumberOfProcessors
>1 ? 4000 : 0;
161 /* ??0?$_SpinWait@$00@details@Concurrency@@QAE@P6AXXZ@Z */
162 /* ??0?$_SpinWait@$00@details@Concurrency@@QEAA@P6AXXZ@Z */
163 DEFINE_THISCALL_WRAPPER(SpinWait_ctor_yield
, 8)
164 SpinWait
* __thiscall
SpinWait_ctor_yield(SpinWait
*this, yield_func yf
)
166 TRACE("(%p %p)\n", this, yf
);
168 this->state
= SPINWAIT_INIT
;
170 this->yield_func
= yf
;
174 /* ??0?$_SpinWait@$0A@@details@Concurrency@@QAE@P6AXXZ@Z */
175 /* ??0?$_SpinWait@$0A@@details@Concurrency@@QEAA@P6AXXZ@Z */
176 DEFINE_THISCALL_WRAPPER(SpinWait_ctor
, 8)
177 SpinWait
* __thiscall
SpinWait_ctor(SpinWait
*this, yield_func yf
)
179 TRACE("(%p %p)\n", this, yf
);
181 this->state
= SPINWAIT_INIT
;
183 this->yield_func
= yf
;
187 /* ??_F?$_SpinWait@$00@details@Concurrency@@QAEXXZ */
188 /* ??_F?$_SpinWait@$00@details@Concurrency@@QEAAXXZ */
189 /* ??_F?$_SpinWait@$0A@@details@Concurrency@@QAEXXZ */
190 /* ??_F?$_SpinWait@$0A@@details@Concurrency@@QEAAXXZ */
191 DEFINE_THISCALL_WRAPPER(SpinWait_dtor
, 4)
192 void __thiscall
SpinWait_dtor(SpinWait
*this)
194 TRACE("(%p)\n", this);
197 /* ?_DoYield@?$_SpinWait@$00@details@Concurrency@@IAEXXZ */
198 /* ?_DoYield@?$_SpinWait@$00@details@Concurrency@@IEAAXXZ */
199 /* ?_DoYield@?$_SpinWait@$0A@@details@Concurrency@@IAEXXZ */
200 /* ?_DoYield@?$_SpinWait@$0A@@details@Concurrency@@IEAAXXZ */
201 DEFINE_THISCALL_WRAPPER(SpinWait__DoYield
, 4)
202 void __thiscall
SpinWait__DoYield(SpinWait
*this)
204 TRACE("(%p)\n", this);
210 /* ?_NumberOfSpins@?$_SpinWait@$00@details@Concurrency@@IAEKXZ */
211 /* ?_NumberOfSpins@?$_SpinWait@$00@details@Concurrency@@IEAAKXZ */
212 /* ?_NumberOfSpins@?$_SpinWait@$0A@@details@Concurrency@@IAEKXZ */
213 /* ?_NumberOfSpins@?$_SpinWait@$0A@@details@Concurrency@@IEAAKXZ */
214 DEFINE_THISCALL_WRAPPER(SpinWait__NumberOfSpins
, 4)
215 ULONG __thiscall
SpinWait__NumberOfSpins(SpinWait
*this)
217 TRACE("(%p)\n", this);
221 /* ?_SetSpinCount@?$_SpinWait@$00@details@Concurrency@@QAEXI@Z */
222 /* ?_SetSpinCount@?$_SpinWait@$00@details@Concurrency@@QEAAXI@Z */
223 /* ?_SetSpinCount@?$_SpinWait@$0A@@details@Concurrency@@QAEXI@Z */
224 /* ?_SetSpinCount@?$_SpinWait@$0A@@details@Concurrency@@QEAAXI@Z */
225 DEFINE_THISCALL_WRAPPER(SpinWait__SetSpinCount
, 8)
226 void __thiscall
SpinWait__SetSpinCount(SpinWait
*this, unsigned int spin
)
228 TRACE("(%p %d)\n", this, spin
);
231 this->state
= spin
? SPINWAIT_SPIN
: SPINWAIT_YIELD
;
234 /* ?_Reset@?$_SpinWait@$00@details@Concurrency@@IAEXXZ */
235 /* ?_Reset@?$_SpinWait@$00@details@Concurrency@@IEAAXXZ */
236 /* ?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IAEXXZ */
237 /* ?_Reset@?$_SpinWait@$0A@@details@Concurrency@@IEAAXXZ */
238 DEFINE_THISCALL_WRAPPER(SpinWait__Reset
, 4)
239 void __thiscall
SpinWait__Reset(SpinWait
*this)
241 SpinWait__SetSpinCount(this, SpinCount__Value());
244 /* ?_ShouldSpinAgain@?$_SpinWait@$00@details@Concurrency@@IAE_NXZ */
245 /* ?_ShouldSpinAgain@?$_SpinWait@$00@details@Concurrency@@IEAA_NXZ */
246 /* ?_ShouldSpinAgain@?$_SpinWait@$0A@@details@Concurrency@@IAE_NXZ */
247 /* ?_ShouldSpinAgain@?$_SpinWait@$0A@@details@Concurrency@@IEAA_NXZ */
248 DEFINE_THISCALL_WRAPPER(SpinWait__ShouldSpinAgain
, 4)
249 MSVCRT_bool __thiscall
SpinWait__ShouldSpinAgain(SpinWait
*this)
251 TRACE("(%p)\n", this);
254 return this->spin
> 0;
257 /* ?_SpinOnce@?$_SpinWait@$00@details@Concurrency@@QAE_NXZ */
258 /* ?_SpinOnce@?$_SpinWait@$00@details@Concurrency@@QEAA_NXZ */
259 /* ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QAE_NXZ */
260 /* ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QEAA_NXZ */
261 DEFINE_THISCALL_WRAPPER(SpinWait__SpinOnce
, 4)
262 MSVCRT_bool __thiscall
SpinWait__SpinOnce(SpinWait
*this)
264 switch(this->state
) {
266 SpinWait__Reset(this);
269 InterlockedDecrement((LONG
*)&this->spin
);
271 this->state
= this->unknown
? SPINWAIT_YIELD
: SPINWAIT_DONE
;
274 this->state
= SPINWAIT_DONE
;
278 SpinWait__Reset(this);
283 static HANDLE keyed_event
;
285 /* keep in sync with msvcp90/msvcp90.h */
286 typedef struct cs_queue
288 struct cs_queue
*next
;
289 #if _MSVCR_VER >= 110
297 ULONG_PTR unk_thread_id
;
299 #if _MSVCR_VER >= 110
308 /* ??0critical_section@Concurrency@@QAE@XZ */
309 /* ??0critical_section@Concurrency@@QEAA@XZ */
310 DEFINE_THISCALL_WRAPPER(critical_section_ctor
, 4)
311 critical_section
* __thiscall
critical_section_ctor(critical_section
*this)
313 TRACE("(%p)\n", this);
318 NtCreateKeyedEvent(&event
, GENERIC_READ
|GENERIC_WRITE
, NULL
, 0);
319 if(InterlockedCompareExchangePointer(&keyed_event
, event
, NULL
) != NULL
)
323 this->unk_thread_id
= 0;
324 this->head
= this->tail
= NULL
;
328 /* ??1critical_section@Concurrency@@QAE@XZ */
329 /* ??1critical_section@Concurrency@@QEAA@XZ */
330 DEFINE_THISCALL_WRAPPER(critical_section_dtor
, 4)
331 void __thiscall
critical_section_dtor(critical_section
*this)
333 TRACE("(%p)\n", this);
336 static void __cdecl
spin_wait_yield(void)
341 static inline void spin_wait_for_next_cs(cs_queue
*q
)
347 SpinWait_ctor(&sw
, &spin_wait_yield
);
348 SpinWait__Reset(&sw
);
350 SpinWait__SpinOnce(&sw
);
354 static inline void cs_set_head(critical_section
*cs
, cs_queue
*q
)
356 cs
->unk_thread_id
= GetCurrentThreadId();
357 cs
->unk_active
.next
= q
->next
;
358 cs
->head
= &cs
->unk_active
;
361 static inline void cs_lock(critical_section
*cs
, cs_queue
*q
)
365 if(cs
->unk_thread_id
== GetCurrentThreadId())
366 throw_exception(EXCEPTION_IMPROPER_LOCK
, 0, "Already locked");
368 memset(q
, 0, sizeof(*q
));
369 last
= InterlockedExchangePointer(&cs
->tail
, q
);
372 NtWaitForKeyedEvent(keyed_event
, q
, 0, NULL
);
376 if(InterlockedCompareExchangePointer(&cs
->tail
, &cs
->unk_active
, q
) != q
) {
377 spin_wait_for_next_cs(q
);
378 cs
->unk_active
.next
= q
->next
;
382 /* ?lock@critical_section@Concurrency@@QAEXXZ */
383 /* ?lock@critical_section@Concurrency@@QEAAXXZ */
384 DEFINE_THISCALL_WRAPPER(critical_section_lock
, 4)
385 void __thiscall
critical_section_lock(critical_section
*this)
389 TRACE("(%p)\n", this);
393 /* ?try_lock@critical_section@Concurrency@@QAE_NXZ */
394 /* ?try_lock@critical_section@Concurrency@@QEAA_NXZ */
395 DEFINE_THISCALL_WRAPPER(critical_section_try_lock
, 4)
396 MSVCRT_bool __thiscall
critical_section_try_lock(critical_section
*this)
400 TRACE("(%p)\n", this);
402 if(this->unk_thread_id
== GetCurrentThreadId())
405 memset(&q
, 0, sizeof(q
));
406 if(!InterlockedCompareExchangePointer(&this->tail
, &q
, NULL
)) {
407 cs_set_head(this, &q
);
408 if(InterlockedCompareExchangePointer(&this->tail
, &this->unk_active
, &q
) != &q
) {
409 spin_wait_for_next_cs(&q
);
410 this->unk_active
.next
= q
.next
;
417 /* ?unlock@critical_section@Concurrency@@QAEXXZ */
418 /* ?unlock@critical_section@Concurrency@@QEAAXXZ */
419 DEFINE_THISCALL_WRAPPER(critical_section_unlock
, 4)
420 void __thiscall
critical_section_unlock(critical_section
*this)
422 TRACE("(%p)\n", this);
424 this->unk_thread_id
= 0;
426 if(InterlockedCompareExchangePointer(&this->tail
, NULL
, &this->unk_active
)
427 == &this->unk_active
) return;
428 spin_wait_for_next_cs(&this->unk_active
);
430 #if _MSVCR_VER >= 110
434 if(!InterlockedExchange(&this->unk_active
.next
->free
, TRUE
))
437 next
= this->unk_active
.next
;
438 if(InterlockedCompareExchangePointer(&this->tail
, NULL
, next
) == next
) {
439 HeapFree(GetProcessHeap(), 0, next
);
442 spin_wait_for_next_cs(next
);
444 this->unk_active
.next
= next
->next
;
445 HeapFree(GetProcessHeap(), 0, next
);
449 NtReleaseKeyedEvent(keyed_event
, this->unk_active
.next
, 0, NULL
);
452 /* ?native_handle@critical_section@Concurrency@@QAEAAV12@XZ */
453 /* ?native_handle@critical_section@Concurrency@@QEAAAEAV12@XZ */
454 DEFINE_THISCALL_WRAPPER(critical_section_native_handle
, 4)
455 critical_section
* __thiscall
critical_section_native_handle(critical_section
*this)
457 TRACE("(%p)\n", this);
461 #if _MSVCR_VER >= 110
462 /* ?try_lock_for@critical_section@Concurrency@@QAE_NI@Z */
463 /* ?try_lock_for@critical_section@Concurrency@@QEAA_NI@Z */
464 DEFINE_THISCALL_WRAPPER(critical_section_try_lock_for
, 8)
465 MSVCRT_bool __thiscall
critical_section_try_lock_for(
466 critical_section
*this, unsigned int timeout
)
470 TRACE("(%p %d)\n", this, timeout
);
472 if(this->unk_thread_id
== GetCurrentThreadId())
473 throw_exception(EXCEPTION_IMPROPER_LOCK
, 0, "Already locked");
475 if(!(q
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*q
))))
476 return critical_section_try_lock(this);
478 last
= InterlockedExchangePointer(&this->tail
, q
);
485 GetSystemTimeAsFileTime(&ft
);
486 to
.QuadPart
= ((LONGLONG
)ft
.dwHighDateTime
<<32) +
487 ft
.dwLowDateTime
+ (LONGLONG
)timeout
*10000;
488 status
= NtWaitForKeyedEvent(keyed_event
, q
, 0, &to
);
489 if(status
== STATUS_TIMEOUT
) {
490 if(!InterlockedExchange(&q
->free
, TRUE
))
492 /* A thread has signaled the event and is block waiting. */
493 /* We need to catch the event to wake the thread. */
494 NtWaitForKeyedEvent(keyed_event
, q
, 0, NULL
);
498 cs_set_head(this, q
);
499 if(InterlockedCompareExchangePointer(&this->tail
, &this->unk_active
, q
) != q
) {
500 spin_wait_for_next_cs(q
);
501 this->unk_active
.next
= q
->next
;
504 HeapFree(GetProcessHeap(), 0, q
);
511 critical_section
*cs
;
519 } critical_section_scoped_lock
;
521 /* ??0scoped_lock@critical_section@Concurrency@@QAE@AAV12@@Z */
522 /* ??0scoped_lock@critical_section@Concurrency@@QEAA@AEAV12@@Z */
523 DEFINE_THISCALL_WRAPPER(critical_section_scoped_lock_ctor
, 8)
524 critical_section_scoped_lock
* __thiscall
critical_section_scoped_lock_ctor(
525 critical_section_scoped_lock
*this, critical_section
*cs
)
527 TRACE("(%p %p)\n", this, cs
);
529 cs_lock(this->cs
, &this->lock
.q
);
533 /* ??1scoped_lock@critical_section@Concurrency@@QAE@XZ */
534 /* ??1scoped_lock@critical_section@Concurrency@@QEAA@XZ */
535 DEFINE_THISCALL_WRAPPER(critical_section_scoped_lock_dtor
, 4)
536 void __thiscall
critical_section_scoped_lock_dtor(critical_section_scoped_lock
*this)
538 TRACE("(%p)\n", this);
539 critical_section_unlock(this->cs
);
545 } _NonReentrantPPLLock
;
547 /* ??0_NonReentrantPPLLock@details@Concurrency@@QAE@XZ */
548 /* ??0_NonReentrantPPLLock@details@Concurrency@@QEAA@XZ */
549 DEFINE_THISCALL_WRAPPER(_NonReentrantPPLLock_ctor
, 4)
550 _NonReentrantPPLLock
* __thiscall
_NonReentrantPPLLock_ctor(_NonReentrantPPLLock
*this)
552 TRACE("(%p)\n", this);
554 critical_section_ctor(&this->cs
);
558 /* ?_Acquire@_NonReentrantPPLLock@details@Concurrency@@QAEXPAX@Z */
559 /* ?_Acquire@_NonReentrantPPLLock@details@Concurrency@@QEAAXPEAX@Z */
560 DEFINE_THISCALL_WRAPPER(_NonReentrantPPLLock__Acquire
, 8)
561 void __thiscall
_NonReentrantPPLLock__Acquire(_NonReentrantPPLLock
*this, cs_queue
*q
)
563 TRACE("(%p %p)\n", this, q
);
564 cs_lock(&this->cs
, q
);
567 /* ?_Release@_NonReentrantPPLLock@details@Concurrency@@QAEXXZ */
568 /* ?_Release@_NonReentrantPPLLock@details@Concurrency@@QEAAXXZ */
569 DEFINE_THISCALL_WRAPPER(_NonReentrantPPLLock__Release
, 4)
570 void __thiscall
_NonReentrantPPLLock__Release(_NonReentrantPPLLock
*this)
572 TRACE("(%p)\n", this);
573 critical_section_unlock(&this->cs
);
583 /* ??0_ReentrantPPLLock@details@Concurrency@@QAE@XZ */
584 /* ??0_ReentrantPPLLock@details@Concurrency@@QEAA@XZ */
585 DEFINE_THISCALL_WRAPPER(_ReentrantPPLLock_ctor
, 4)
586 _ReentrantPPLLock
* __thiscall
_ReentrantPPLLock_ctor(_ReentrantPPLLock
*this)
588 TRACE("(%p)\n", this);
590 critical_section_ctor(&this->cs
);
596 /* ?_Acquire@_ReentrantPPLLock@details@Concurrency@@QAEXPAX@Z */
597 /* ?_Acquire@_ReentrantPPLLock@details@Concurrency@@QEAAXPEAX@Z */
598 DEFINE_THISCALL_WRAPPER(_ReentrantPPLLock__Acquire
, 8)
599 void __thiscall
_ReentrantPPLLock__Acquire(_ReentrantPPLLock
*this, cs_queue
*q
)
601 TRACE("(%p %p)\n", this, q
);
603 if(this->owner
== GetCurrentThreadId()) {
608 cs_lock(&this->cs
, q
);
610 this->owner
= GetCurrentThreadId();
613 /* ?_Release@_ReentrantPPLLock@details@Concurrency@@QAEXXZ */
614 /* ?_Release@_ReentrantPPLLock@details@Concurrency@@QEAAXXZ */
615 DEFINE_THISCALL_WRAPPER(_ReentrantPPLLock__Release
, 4)
616 void __thiscall
_ReentrantPPLLock__Release(_ReentrantPPLLock
*this)
618 TRACE("(%p)\n", this);
625 critical_section_unlock(&this->cs
);
630 _ReentrantPPLLock
*lock
;
638 } _ReentrantPPLLock__Scoped_lock
;
640 /* ??0_Scoped_lock@_ReentrantPPLLock@details@Concurrency@@QAE@AAV123@@Z */
641 /* ??0_Scoped_lock@_ReentrantPPLLock@details@Concurrency@@QEAA@AEAV123@@Z */
642 DEFINE_THISCALL_WRAPPER(_ReentrantPPLLock__Scoped_lock_ctor
, 8)
643 _ReentrantPPLLock__Scoped_lock
* __thiscall
_ReentrantPPLLock__Scoped_lock_ctor(
644 _ReentrantPPLLock__Scoped_lock
*this, _ReentrantPPLLock
*lock
)
646 TRACE("(%p %p)\n", this, lock
);
649 _ReentrantPPLLock__Acquire(this->lock
, &this->wait
.q
);
653 /* ??1_Scoped_lock@_ReentrantPPLLock@details@Concurrency@@QAE@XZ */
654 /* ??1_Scoped_lock@_ReentrantPPLLock@details@Concurrency@@QEAA@XZ */
655 DEFINE_THISCALL_WRAPPER(_ReentrantPPLLock__Scoped_lock_dtor
, 4)
656 void __thiscall
_ReentrantPPLLock__Scoped_lock_dtor(_ReentrantPPLLock__Scoped_lock
*this)
658 TRACE("(%p)\n", this);
660 _ReentrantPPLLock__Release(this->lock
);
663 /* ?_GetConcurrency@details@Concurrency@@YAIXZ */
664 unsigned int __cdecl
_GetConcurrency(void)
666 static unsigned int val
= -1;
674 val
= si
.dwNumberOfProcessors
;
680 #define EVT_RUNNING (void*)1
681 #define EVT_WAITING NULL
684 typedef struct thread_wait_entry
686 struct thread_wait
*wait
;
687 struct thread_wait_entry
*next
;
688 struct thread_wait_entry
*prev
;
691 typedef struct thread_wait
695 thread_wait_entry entries
[1];
700 thread_wait_entry
*waiters
;
705 static inline PLARGE_INTEGER
evt_timeout(PLARGE_INTEGER pTime
, unsigned int timeout
)
707 if(timeout
== COOPERATIVE_TIMEOUT_INFINITE
) return NULL
;
708 pTime
->QuadPart
= (ULONGLONG
)timeout
* -10000;
712 static void evt_add_queue(thread_wait_entry
**head
, thread_wait_entry
*entry
)
716 if(*head
) (*head
)->prev
= entry
;
720 static void evt_remove_queue(thread_wait_entry
**head
, thread_wait_entry
*entry
)
725 entry
->prev
->next
= entry
->next
;
726 if(entry
->next
) entry
->next
->prev
= entry
->prev
;
729 static MSVCRT_size_t
evt_end_wait(thread_wait
*wait
, event
**events
, int count
)
731 MSVCRT_size_t i
, ret
= COOPERATIVE_WAIT_TIMEOUT
;
733 for(i
= 0; i
< count
; i
++) {
734 critical_section_lock(&events
[i
]->cs
);
735 if(events
[i
] == wait
->signaled
) ret
= i
;
736 evt_remove_queue(&events
[i
]->waiters
, &wait
->entries
[i
]);
737 critical_section_unlock(&events
[i
]->cs
);
743 static inline int evt_transition(void **state
, void *from
, void *to
)
745 return InterlockedCompareExchangePointer(state
, to
, from
) == from
;
748 static MSVCRT_size_t
evt_wait(thread_wait
*wait
, event
**events
, int count
, MSVCRT_bool wait_all
, unsigned int timeout
)
754 wait
->signaled
= EVT_RUNNING
;
755 wait
->pending_waits
= wait_all
? count
: 1;
756 for(i
= 0; i
< count
; i
++) {
757 wait
->entries
[i
].wait
= wait
;
759 critical_section_lock(&events
[i
]->cs
);
760 evt_add_queue(&events
[i
]->waiters
, &wait
->entries
[i
]);
761 if(events
[i
]->signaled
) {
762 if(!InterlockedDecrement(&wait
->pending_waits
)) {
763 wait
->signaled
= events
[i
];
764 critical_section_unlock(&events
[i
]->cs
);
766 return evt_end_wait(wait
, events
, i
+1);
769 critical_section_unlock(&events
[i
]->cs
);
773 return evt_end_wait(wait
, events
, count
);
775 if(!evt_transition(&wait
->signaled
, EVT_RUNNING
, EVT_WAITING
))
776 return evt_end_wait(wait
, events
, count
);
778 status
= NtWaitForKeyedEvent(keyed_event
, wait
, 0, evt_timeout(&ntto
, timeout
));
780 if(status
&& !evt_transition(&wait
->signaled
, EVT_WAITING
, EVT_RUNNING
))
781 NtWaitForKeyedEvent(keyed_event
, wait
, 0, NULL
);
783 return evt_end_wait(wait
, events
, count
);
786 /* ??0event@Concurrency@@QAE@XZ */
787 /* ??0event@Concurrency@@QEAA@XZ */
788 DEFINE_THISCALL_WRAPPER(event_ctor
, 4)
789 event
* __thiscall
event_ctor(event
*this)
791 TRACE("(%p)\n", this);
793 this->waiters
= NULL
;
794 this->signaled
= FALSE
;
795 critical_section_ctor(&this->cs
);
800 /* ??1event@Concurrency@@QAE@XZ */
801 /* ??1event@Concurrency@@QEAA@XZ */
802 DEFINE_THISCALL_WRAPPER(event_dtor
, 4)
803 void __thiscall
event_dtor(event
*this)
805 TRACE("(%p)\n", this);
806 critical_section_dtor(&this->cs
);
808 ERR("there's a wait on destroyed event\n");
811 /* ?reset@event@Concurrency@@QAEXXZ */
812 /* ?reset@event@Concurrency@@QEAAXXZ */
813 DEFINE_THISCALL_WRAPPER(event_reset
, 4)
814 void __thiscall
event_reset(event
*this)
816 thread_wait_entry
*entry
;
818 TRACE("(%p)\n", this);
820 critical_section_lock(&this->cs
);
822 this->signaled
= FALSE
;
823 for(entry
=this->waiters
; entry
; entry
= entry
->next
)
824 InterlockedIncrement(&entry
->wait
->pending_waits
);
826 critical_section_unlock(&this->cs
);
829 /* ?set@event@Concurrency@@QAEXXZ */
830 /* ?set@event@Concurrency@@QEAAXXZ */
831 DEFINE_THISCALL_WRAPPER(event_set
, 4)
832 void __thiscall
event_set(event
*this)
834 thread_wait_entry
*wakeup
= NULL
;
835 thread_wait_entry
*entry
, *next
;
837 TRACE("(%p)\n", this);
839 critical_section_lock(&this->cs
);
840 if(!this->signaled
) {
841 this->signaled
= TRUE
;
842 for(entry
=this->waiters
; entry
; entry
=next
) {
844 if(!InterlockedDecrement(&entry
->wait
->pending_waits
)) {
845 if(InterlockedExchangePointer(&entry
->wait
->signaled
, this) == EVT_WAITING
) {
846 evt_remove_queue(&this->waiters
, entry
);
847 evt_add_queue(&wakeup
, entry
);
852 critical_section_unlock(&this->cs
);
854 for(entry
=wakeup
; entry
; entry
=next
) {
856 entry
->next
= entry
->prev
= NULL
;
857 NtReleaseKeyedEvent(keyed_event
, entry
->wait
, 0, NULL
);
861 /* ?wait@event@Concurrency@@QAEII@Z */
862 /* ?wait@event@Concurrency@@QEAA_KI@Z */
863 DEFINE_THISCALL_WRAPPER(event_wait
, 8)
864 MSVCRT_size_t __thiscall
event_wait(event
*this, unsigned int timeout
)
867 MSVCRT_size_t signaled
;
869 TRACE("(%p %u)\n", this, timeout
);
871 critical_section_lock(&this->cs
);
872 signaled
= this->signaled
;
873 critical_section_unlock(&this->cs
);
875 if(!timeout
) return signaled
? 0 : COOPERATIVE_WAIT_TIMEOUT
;
876 return signaled
? 0 : evt_wait(&wait
, &this, 1, FALSE
, timeout
);
879 /* ?wait_for_multiple@event@Concurrency@@SAIPAPAV12@I_NI@Z */
880 /* ?wait_for_multiple@event@Concurrency@@SA_KPEAPEAV12@_K_NI@Z */
881 int __cdecl
event_wait_for_multiple(event
**events
, MSVCRT_size_t count
, MSVCRT_bool wait_all
, unsigned int timeout
)
886 TRACE("(%p %ld %d %u)\n", events
, count
, wait_all
, timeout
);
891 wait
= heap_alloc(FIELD_OFFSET(thread_wait
, entries
[count
]));
893 throw_exception(EXCEPTION_BAD_ALLOC
, 0, "bad allocation");
894 ret
= evt_wait(wait
, events
, count
, wait_all
, timeout
);
901 #if _MSVCR_VER >= 110
902 typedef struct cv_queue
{
903 struct cv_queue
*next
;
908 /* cv_queue structure is not binary compatible */
910 critical_section lock
;
911 } _Condition_variable
;
913 /* ??0_Condition_variable@details@Concurrency@@QAE@XZ */
914 /* ??0_Condition_variable@details@Concurrency@@QEAA@XZ */
915 DEFINE_THISCALL_WRAPPER(_Condition_variable_ctor
, 4)
916 _Condition_variable
* __thiscall
_Condition_variable_ctor(_Condition_variable
*this)
918 TRACE("(%p)\n", this);
921 critical_section_ctor(&this->lock
);
925 /* ??1_Condition_variable@details@Concurrency@@QAE@XZ */
926 /* ??1_Condition_variable@details@Concurrency@@QEAA@XZ */
927 DEFINE_THISCALL_WRAPPER(_Condition_variable_dtor
, 4)
928 void __thiscall
_Condition_variable_dtor(_Condition_variable
*this)
930 TRACE("(%p)\n", this);
933 cv_queue
*next
= this->queue
->next
;
934 if(!this->queue
->expired
)
935 ERR("there's an active wait\n");
936 HeapFree(GetProcessHeap(), 0, this->queue
);
939 critical_section_dtor(&this->lock
);
942 /* ?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z */
943 /* ?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z */
944 DEFINE_THISCALL_WRAPPER(_Condition_variable_wait
, 8)
945 void __thiscall
_Condition_variable_wait(_Condition_variable
*this, critical_section
*cs
)
949 TRACE("(%p, %p)\n", this, cs
);
951 critical_section_lock(&this->lock
);
952 q
.next
= this->queue
;
955 critical_section_unlock(&this->lock
);
957 critical_section_unlock(cs
);
958 NtWaitForKeyedEvent(keyed_event
, &q
, 0, NULL
);
959 critical_section_lock(cs
);
962 /* ?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z */
963 /* ?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z */
964 DEFINE_THISCALL_WRAPPER(_Condition_variable_wait_for
, 12)
965 MSVCRT_bool __thiscall
_Condition_variable_wait_for(_Condition_variable
*this,
966 critical_section
*cs
, unsigned int timeout
)
973 TRACE("(%p %p %d)\n", this, cs
, timeout
);
975 if(!(q
= HeapAlloc(GetProcessHeap(), 0, sizeof(cv_queue
)))) {
976 throw_exception(EXCEPTION_BAD_ALLOC
, 0, "bad allocation");
979 critical_section_lock(&this->lock
);
980 q
->next
= this->queue
;
983 critical_section_unlock(&this->lock
);
985 critical_section_unlock(cs
);
987 GetSystemTimeAsFileTime(&ft
);
988 to
.QuadPart
= ((LONGLONG
)ft
.dwHighDateTime
<< 32) +
989 ft
.dwLowDateTime
+ (LONGLONG
)timeout
* 10000;
990 status
= NtWaitForKeyedEvent(keyed_event
, q
, 0, &to
);
991 if(status
== STATUS_TIMEOUT
) {
992 if(!InterlockedExchange(&q
->expired
, TRUE
)) {
993 critical_section_lock(cs
);
997 NtWaitForKeyedEvent(keyed_event
, q
, 0, 0);
1000 HeapFree(GetProcessHeap(), 0, q
);
1001 critical_section_lock(cs
);
1005 /* ?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ */
1006 /* ?notify_one@_Condition_variable@details@Concurrency@@QEAAXXZ */
1007 DEFINE_THISCALL_WRAPPER(_Condition_variable_notify_one
, 4)
1008 void __thiscall
_Condition_variable_notify_one(_Condition_variable
*this)
1012 TRACE("(%p)\n", this);
1018 critical_section_lock(&this->lock
);
1021 critical_section_unlock(&this->lock
);
1024 this->queue
= node
->next
;
1025 critical_section_unlock(&this->lock
);
1027 if(!InterlockedExchange(&node
->expired
, TRUE
)) {
1028 NtReleaseKeyedEvent(keyed_event
, node
, 0, NULL
);
1031 HeapFree(GetProcessHeap(), 0, node
);
1036 /* ?notify_all@_Condition_variable@details@Concurrency@@QAEXXZ */
1037 /* ?notify_all@_Condition_variable@details@Concurrency@@QEAAXXZ */
1038 DEFINE_THISCALL_WRAPPER(_Condition_variable_notify_all
, 4)
1039 void __thiscall
_Condition_variable_notify_all(_Condition_variable
*this)
1043 TRACE("(%p)\n", this);
1048 critical_section_lock(&this->lock
);
1051 critical_section_unlock(&this->lock
);
1054 cv_queue
*next
= ptr
->next
;
1056 if(!InterlockedExchange(&ptr
->expired
, TRUE
))
1057 NtReleaseKeyedEvent(keyed_event
, ptr
, 0, NULL
);
1059 HeapFree(GetProcessHeap(), 0, ptr
);
1065 #if _MSVCR_VER >= 100
1066 typedef struct rwl_queue
1068 struct rwl_queue
*next
;
1071 #define WRITER_WAITING 0x80000000
1072 /* FIXME: reader_writer_lock structure is not binary compatible
1073 * it can't exceed 28/56 bytes */
1079 rwl_queue
*writer_head
;
1080 rwl_queue
*writer_tail
;
1081 rwl_queue
*reader_head
;
1082 } reader_writer_lock
;
1084 /* ??0reader_writer_lock@Concurrency@@QAE@XZ */
1085 /* ??0reader_writer_lock@Concurrency@@QEAA@XZ */
1086 DEFINE_THISCALL_WRAPPER(reader_writer_lock_ctor
, 4)
1087 reader_writer_lock
* __thiscall
reader_writer_lock_ctor(reader_writer_lock
*this)
1089 TRACE("(%p)\n", this);
1094 NtCreateKeyedEvent(&event
, GENERIC_READ
|GENERIC_WRITE
, NULL
, 0);
1095 if (InterlockedCompareExchangePointer(&keyed_event
, event
, NULL
) != NULL
)
1099 memset(this, 0, sizeof(*this));
1103 /* ??1reader_writer_lock@Concurrency@@QAE@XZ */
1104 /* ??1reader_writer_lock@Concurrency@@QEAA@XZ */
1105 DEFINE_THISCALL_WRAPPER(reader_writer_lock_dtor
, 4)
1106 void __thiscall
reader_writer_lock_dtor(reader_writer_lock
*this)
1108 TRACE("(%p)\n", this);
1110 if (this->thread_id
!= 0 || this->count
)
1111 WARN("destroying locked reader_writer_lock\n");
1114 static inline void spin_wait_for_next_rwl(rwl_queue
*q
)
1120 SpinWait_ctor(&sw
, &spin_wait_yield
);
1121 SpinWait__Reset(&sw
);
1123 SpinWait__SpinOnce(&sw
);
1127 /* Remove when proper InterlockedOr implementation is added to wine */
1128 static LONG
InterlockedOr(LONG
*d
, LONG v
)
1131 while (~(l
= *d
) & v
)
1132 if (InterlockedCompareExchange(d
, l
|v
, l
) == l
) break;
1136 static LONG
InterlockedAnd(LONG
*d
, LONG v
)
1139 while ((l
& v
) != l
) {
1140 if((old
= InterlockedCompareExchange(d
, l
&v
, l
)) == l
) break;
1146 /* ?lock@reader_writer_lock@Concurrency@@QAEXXZ */
1147 /* ?lock@reader_writer_lock@Concurrency@@QEAAXXZ */
1148 DEFINE_THISCALL_WRAPPER(reader_writer_lock_lock
, 4)
1149 void __thiscall
reader_writer_lock_lock(reader_writer_lock
*this)
1151 rwl_queue q
= { NULL
}, *last
;
1153 TRACE("(%p)\n", this);
1155 if (this->thread_id
== GetCurrentThreadId())
1156 throw_exception(EXCEPTION_IMPROPER_LOCK
, 0, "Already locked");
1158 last
= InterlockedExchangePointer((void**)&this->writer_tail
, &q
);
1161 NtWaitForKeyedEvent(keyed_event
, &q
, 0, NULL
);
1163 this->writer_head
= &q
;
1164 if (InterlockedOr(&this->count
, WRITER_WAITING
))
1165 NtWaitForKeyedEvent(keyed_event
, &q
, 0, NULL
);
1168 this->thread_id
= GetCurrentThreadId();
1169 this->writer_head
= &this->active
;
1170 this->active
.next
= NULL
;
1171 if (InterlockedCompareExchangePointer((void**)&this->writer_tail
, &this->active
, &q
) != &q
) {
1172 spin_wait_for_next_rwl(&q
);
1173 this->active
.next
= q
.next
;
1177 /* ?lock_read@reader_writer_lock@Concurrency@@QAEXXZ */
1178 /* ?lock_read@reader_writer_lock@Concurrency@@QEAAXXZ */
1179 DEFINE_THISCALL_WRAPPER(reader_writer_lock_lock_read
, 4)
1180 void __thiscall
reader_writer_lock_lock_read(reader_writer_lock
*this)
1184 TRACE("(%p)\n", this);
1186 if (this->thread_id
== GetCurrentThreadId())
1187 throw_exception(EXCEPTION_IMPROPER_LOCK
, 0, "Already locked as writer");
1190 q
.next
= this->reader_head
;
1191 } while(InterlockedCompareExchangePointer((void**)&this->reader_head
, &q
, q
.next
) != q
.next
);
1197 while (!((count
= this->count
) & WRITER_WAITING
))
1198 if (InterlockedCompareExchange(&this->count
, count
+1, count
) == count
) break;
1200 if (count
& WRITER_WAITING
)
1201 NtWaitForKeyedEvent(keyed_event
, &q
, 0, NULL
);
1203 head
= InterlockedExchangePointer((void**)&this->reader_head
, NULL
);
1204 while(head
&& head
!= &q
) {
1205 rwl_queue
*next
= head
->next
;
1206 InterlockedIncrement(&this->count
);
1207 NtReleaseKeyedEvent(keyed_event
, head
, 0, NULL
);
1211 NtWaitForKeyedEvent(keyed_event
, &q
, 0, NULL
);
1215 /* ?try_lock@reader_writer_lock@Concurrency@@QAE_NXZ */
1216 /* ?try_lock@reader_writer_lock@Concurrency@@QEAA_NXZ */
1217 DEFINE_THISCALL_WRAPPER(reader_writer_lock_try_lock
, 4)
1218 MSVCRT_bool __thiscall
reader_writer_lock_try_lock(reader_writer_lock
*this)
1220 rwl_queue q
= { NULL
};
1222 TRACE("(%p)\n", this);
1224 if (this->thread_id
== GetCurrentThreadId())
1227 if (InterlockedCompareExchangePointer((void**)&this->writer_tail
, &q
, NULL
))
1229 this->writer_head
= &q
;
1230 if (!InterlockedCompareExchange(&this->count
, WRITER_WAITING
, 0)) {
1231 this->thread_id
= GetCurrentThreadId();
1232 this->writer_head
= &this->active
;
1233 this->active
.next
= NULL
;
1234 if (InterlockedCompareExchangePointer((void**)&this->writer_tail
, &this->active
, &q
) != &q
) {
1235 spin_wait_for_next_rwl(&q
);
1236 this->active
.next
= q
.next
;
1241 if (InterlockedCompareExchangePointer((void**)&this->writer_tail
, NULL
, &q
) == &q
)
1243 spin_wait_for_next_rwl(&q
);
1244 this->writer_head
= q
.next
;
1245 if (!InterlockedOr(&this->count
, WRITER_WAITING
)) {
1246 this->thread_id
= GetCurrentThreadId();
1247 this->writer_head
= &this->active
;
1248 this->active
.next
= q
.next
;
1254 /* ?try_lock_read@reader_writer_lock@Concurrency@@QAE_NXZ */
1255 /* ?try_lock_read@reader_writer_lock@Concurrency@@QEAA_NXZ */
1256 DEFINE_THISCALL_WRAPPER(reader_writer_lock_try_lock_read
, 4)
1257 MSVCRT_bool __thiscall
reader_writer_lock_try_lock_read(reader_writer_lock
*this)
1261 TRACE("(%p)\n", this);
1263 while (!((count
= this->count
) & WRITER_WAITING
))
1264 if (InterlockedCompareExchange(&this->count
, count
+1, count
) == count
) return TRUE
;
1268 /* ?unlock@reader_writer_lock@Concurrency@@QAEXXZ */
1269 /* ?unlock@reader_writer_lock@Concurrency@@QEAAXXZ */
1270 DEFINE_THISCALL_WRAPPER(reader_writer_lock_unlock
, 4)
1271 void __thiscall
reader_writer_lock_unlock(reader_writer_lock
*this)
1274 rwl_queue
*head
, *next
;
1276 TRACE("(%p)\n", this);
1278 if ((count
= this->count
) & ~WRITER_WAITING
) {
1279 count
= InterlockedDecrement(&this->count
);
1280 if (count
!= WRITER_WAITING
)
1282 NtReleaseKeyedEvent(keyed_event
, this->writer_head
, 0, NULL
);
1286 this->thread_id
= 0;
1287 next
= this->writer_head
->next
;
1289 NtReleaseKeyedEvent(keyed_event
, next
, 0, NULL
);
1292 InterlockedAnd(&this->count
, ~WRITER_WAITING
);
1293 head
= InterlockedExchangePointer((void**)&this->reader_head
, NULL
);
1296 InterlockedIncrement(&this->count
);
1297 NtReleaseKeyedEvent(keyed_event
, head
, 0, NULL
);
1301 if (InterlockedCompareExchangePointer((void**)&this->writer_tail
, NULL
, this->writer_head
) == this->writer_head
)
1303 InterlockedOr(&this->count
, WRITER_WAITING
);
1307 reader_writer_lock
*lock
;
1308 } reader_writer_lock_scoped_lock
;
1310 /* ??0scoped_lock@reader_writer_lock@Concurrency@@QAE@AAV12@@Z */
1311 /* ??0scoped_lock@reader_writer_lock@Concurrency@@QEAA@AEAV12@@Z */
1312 DEFINE_THISCALL_WRAPPER(reader_writer_lock_scoped_lock_ctor
, 8)
1313 reader_writer_lock_scoped_lock
* __thiscall
reader_writer_lock_scoped_lock_ctor(
1314 reader_writer_lock_scoped_lock
*this, reader_writer_lock
*lock
)
1316 TRACE("(%p %p)\n", this, lock
);
1319 reader_writer_lock_lock(lock
);
1323 /* ??1scoped_lock@reader_writer_lock@Concurrency@@QAE@XZ */
1324 /* ??1scoped_lock@reader_writer_lock@Concurrency@@QEAA@XZ */
1325 DEFINE_THISCALL_WRAPPER(reader_writer_lock_scoped_lock_dtor
, 4)
1326 void __thiscall
reader_writer_lock_scoped_lock_dtor(reader_writer_lock_scoped_lock
*this)
1328 TRACE("(%p)\n", this);
1329 reader_writer_lock_unlock(this->lock
);
1332 /* ??0scoped_lock_read@reader_writer_lock@Concurrency@@QAE@AAV12@@Z */
1333 /* ??0scoped_lock_read@reader_writer_lock@Concurrency@@QEAA@AEAV12@@Z */
1334 DEFINE_THISCALL_WRAPPER(reader_writer_lock_scoped_lock_read_ctor
, 8)
1335 reader_writer_lock_scoped_lock
* __thiscall
reader_writer_lock_scoped_lock_read_ctor(
1336 reader_writer_lock_scoped_lock
*this, reader_writer_lock
*lock
)
1338 TRACE("(%p %p)\n", this, lock
);
1341 reader_writer_lock_lock_read(lock
);
1345 /* ??1scoped_lock_read@reader_writer_lock@Concurrency@@QAE@XZ */
1346 /* ??1scoped_lock_read@reader_writer_lock@Concurrency@@QEAA@XZ */
1347 DEFINE_THISCALL_WRAPPER(reader_writer_lock_scoped_lock_read_dtor
, 4)
1348 void __thiscall
reader_writer_lock_scoped_lock_read_dtor(reader_writer_lock_scoped_lock
*this)
1350 TRACE("(%p)\n", this);
1351 reader_writer_lock_unlock(this->lock
);
1355 CRITICAL_SECTION cs
;
1356 } _ReentrantBlockingLock
;
1358 /* ??0_ReentrantBlockingLock@details@Concurrency@@QAE@XZ */
1359 /* ??0_ReentrantBlockingLock@details@Concurrency@@QEAA@XZ */
1360 DEFINE_THISCALL_WRAPPER(_ReentrantBlockingLock_ctor
, 4)
1361 _ReentrantBlockingLock
* __thiscall
_ReentrantBlockingLock_ctor(_ReentrantBlockingLock
*this)
1363 TRACE("(%p)\n", this);
1365 InitializeCriticalSection(&this->cs
);
1366 this->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": _ReentrantBlockingLock");
1370 /* ??1_ReentrantBlockingLock@details@Concurrency@@QAE@XZ */
1371 /* ??1_ReentrantBlockingLock@details@Concurrency@@QEAA@XZ */
1372 DEFINE_THISCALL_WRAPPER(_ReentrantBlockingLock_dtor
, 4)
1373 void __thiscall
_ReentrantBlockingLock_dtor(_ReentrantBlockingLock
*this)
1375 TRACE("(%p)\n", this);
1377 this->cs
.DebugInfo
->Spare
[0] = 0;
1378 DeleteCriticalSection(&this->cs
);
1381 /* ?_Acquire@_ReentrantBlockingLock@details@Concurrency@@QAEXXZ */
1382 /* ?_Acquire@_ReentrantBlockingLock@details@Concurrency@@QEAAXXZ */
1383 DEFINE_THISCALL_WRAPPER(_ReentrantBlockingLock__Acquire
, 4)
1384 void __thiscall
_ReentrantBlockingLock__Acquire(_ReentrantBlockingLock
*this)
1386 TRACE("(%p)\n", this);
1387 EnterCriticalSection(&this->cs
);
1390 /* ?_Release@_ReentrantBlockingLock@details@Concurrency@@QAEXXZ */
1391 /* ?_Release@_ReentrantBlockingLock@details@Concurrency@@QEAAXXZ */
1392 DEFINE_THISCALL_WRAPPER(_ReentrantBlockingLock__Release
, 4)
1393 void __thiscall
_ReentrantBlockingLock__Release(_ReentrantBlockingLock
*this)
1395 TRACE("(%p)\n", this);
1396 LeaveCriticalSection(&this->cs
);
1399 /* ?_TryAcquire@_ReentrantBlockingLock@details@Concurrency@@QAE_NXZ */
1400 /* ?_TryAcquire@_ReentrantBlockingLock@details@Concurrency@@QEAA_NXZ */
1401 DEFINE_THISCALL_WRAPPER(_ReentrantBlockingLock__TryAcquire
, 4)
1402 MSVCRT_bool __thiscall
_ReentrantBlockingLock__TryAcquire(_ReentrantBlockingLock
*this)
1404 TRACE("(%p)\n", this);
1405 return TryEnterCriticalSection(&this->cs
);
1409 #if _MSVCR_VER == 110
1410 static LONG shared_ptr_lock
;
1412 void __cdecl
_Lock_shared_ptr_spin_lock(void)
1416 while(InterlockedCompareExchange(&shared_ptr_lock
, 1, 0) != 0) {
1424 void __cdecl
_Unlock_shared_ptr_spin_lock(void)
1426 shared_ptr_lock
= 0;
1430 /**********************************************************************
1431 * msvcrt_free_locks (internal)
1433 * Uninitialize all mt locks. Assume that neither _lock or _unlock will
1434 * be called once we're calling this routine (ie _LOCKTAB_LOCK can be deleted)
1437 void msvcrt_free_locks(void)
1441 TRACE( ": uninitializing all mtlocks\n" );
1443 /* Uninitialize the table */
1444 for( i
=0; i
< _TOTAL_LOCKS
; i
++ )
1446 if( lock_table
[ i
].bInit
)
1448 msvcrt_uninitialize_mlock( i
);
1452 #if _MSVCR_VER >= 100
1454 NtClose(keyed_event
);