2 * Copyright 2010 Piotr Caban for CodeWeavers
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
29 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcp
);
32 struct __Container_proxy
;
35 struct __Container_proxy
*proxy
;
38 typedef struct __Iterator_base12
{
39 struct __Container_proxy
*proxy
;
40 struct __Iterator_base12
*next
;
43 typedef struct __Container_proxy
{
44 const _Container_base12
*cont
;
45 _Iterator_base12
*head
;
48 /* ??0_Mutex@std@@QAE@XZ */
49 /* ??0_Mutex@std@@QEAA@XZ */
50 DEFINE_THISCALL_WRAPPER(mutex_ctor
, 4)
51 mutex
* __thiscall
mutex_ctor(mutex
*this)
53 CRITICAL_SECTION
*cs
= MSVCRT_operator_new(sizeof(*cs
));
55 ERR("Out of memory\n");
56 throw_exception(EXCEPTION_BAD_ALLOC
, NULL
);
59 InitializeCriticalSection(cs
);
60 cs
->DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": _Mutex critical section");
65 /* ??1_Mutex@std@@QAE@XZ */
66 /* ??1_Mutex@std@@QEAA@XZ */
67 DEFINE_THISCALL_WRAPPER(mutex_dtor
, 4)
68 void __thiscall
mutex_dtor(mutex
*this)
70 ((CRITICAL_SECTION
*)this->mutex
)->DebugInfo
->Spare
[0] = 0;
71 DeleteCriticalSection(this->mutex
);
72 MSVCRT_operator_delete(this->mutex
);
75 /* ?_Lock@_Mutex@std@@QAEXXZ */
76 /* ?_Lock@_Mutex@std@@QEAAXXZ */
77 DEFINE_THISCALL_WRAPPER(mutex_lock
, 4)
78 void __thiscall
mutex_lock(mutex
*this)
80 EnterCriticalSection(this->mutex
);
83 /* ?_Unlock@_Mutex@std@@QAEXXZ */
84 /* ?_Unlock@_Mutex@std@@QEAAXXZ */
85 DEFINE_THISCALL_WRAPPER(mutex_unlock
, 4)
86 void __thiscall
mutex_unlock(mutex
*this)
88 LeaveCriticalSection(this->mutex
);
91 /* ?_Mutex_Lock@_Mutex@std@@CAXPAV12@@Z */
92 /* ?_Mutex_Lock@_Mutex@std@@CAXPEAV12@@Z */
93 void CDECL
mutex_mutex_lock(mutex
*m
)
98 /* ?_Mutex_Unlock@_Mutex@std@@CAXPAV12@@Z */
99 /* ?_Mutex_Unlock@_Mutex@std@@CAXPEAV12@@Z */
100 void CDECL
mutex_mutex_unlock(mutex
*m
)
105 /* ?_Mutex_ctor@_Mutex@std@@CAXPAV12@@Z */
106 /* ?_Mutex_ctor@_Mutex@std@@CAXPEAV12@@Z */
107 void CDECL
mutex_mutex_ctor(mutex
*m
)
112 /* ?_Mutex_dtor@_Mutex@std@@CAXPAV12@@Z */
113 /* ?_Mutex_dtor@_Mutex@std@@CAXPEAV12@@Z */
114 void CDECL
mutex_mutex_dtor(mutex
*m
)
119 static CRITICAL_SECTION lockit_cs
[_MAX_LOCK
];
122 static inline int get_locktype( _Lockit
*lockit
) { return lockit
->locktype
; }
123 static inline void set_locktype( _Lockit
*lockit
, int type
) { lockit
->locktype
= type
; }
125 static inline int get_locktype( _Lockit
*lockit
) { return 0; }
126 static inline void set_locktype( _Lockit
*lockit
, int type
) { }
129 /* ?_Lockit_ctor@_Lockit@std@@SAXH@Z */
130 void __cdecl
_Lockit_init(int locktype
) {
131 InitializeCriticalSection(&lockit_cs
[locktype
]);
132 lockit_cs
[locktype
].DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": _Lockit critical section");
135 /* ?_Lockit_dtor@_Lockit@std@@SAXH@Z */
136 void __cdecl
_Lockit_free(int locktype
)
138 lockit_cs
[locktype
].DebugInfo
->Spare
[0] = 0;
139 DeleteCriticalSection(&lockit_cs
[locktype
]);
142 void init_lockit(void) {
145 for(i
=0; i
<_MAX_LOCK
; i
++)
149 void free_lockit(void) {
152 for(i
=0; i
<_MAX_LOCK
; i
++)
156 /* ?_Lockit_ctor@_Lockit@std@@CAXPAV12@H@Z */
157 /* ?_Lockit_ctor@_Lockit@std@@CAXPEAV12@H@Z */
158 void __cdecl
_Lockit__Lockit_ctor_locktype(_Lockit
*lockit
, int locktype
)
160 set_locktype( lockit
, locktype
);
161 EnterCriticalSection(&lockit_cs
[locktype
]);
164 /* ?_Lockit_ctor@_Lockit@std@@CAXPAV12@@Z */
165 /* ?_Lockit_ctor@_Lockit@std@@CAXPEAV12@@Z */
166 void __cdecl
_Lockit__Lockit_ctor(_Lockit
*lockit
)
168 _Lockit__Lockit_ctor_locktype(lockit
, 0);
171 /* ??0_Lockit@std@@QAE@H@Z */
172 /* ??0_Lockit@std@@QEAA@H@Z */
173 DEFINE_THISCALL_WRAPPER(_Lockit_ctor_locktype
, 8)
174 _Lockit
* __thiscall
_Lockit_ctor_locktype(_Lockit
*this, int locktype
)
176 _Lockit__Lockit_ctor_locktype(this, locktype
);
180 /* ??0_Lockit@std@@QAE@XZ */
181 /* ??0_Lockit@std@@QEAA@XZ */
182 DEFINE_THISCALL_WRAPPER(_Lockit_ctor
, 4)
183 _Lockit
* __thiscall
_Lockit_ctor(_Lockit
*this)
185 _Lockit__Lockit_ctor_locktype(this, 0);
189 /* ?_Lockit_dtor@_Lockit@std@@CAXPAV12@@Z */
190 /* ?_Lockit_dtor@_Lockit@std@@CAXPEAV12@@Z */
191 void __cdecl
_Lockit__Lockit_dtor(_Lockit
*lockit
)
193 LeaveCriticalSection(&lockit_cs
[get_locktype( lockit
)]);
196 /* ??1_Lockit@std@@QAE@XZ */
197 /* ??1_Lockit@std@@QEAA@XZ */
198 DEFINE_THISCALL_WRAPPER(_Lockit_dtor
, 4)
199 void __thiscall
_Lockit_dtor(_Lockit
*this)
201 _Lockit__Lockit_dtor(this);
205 unsigned short __cdecl
wctype(const char *property
)
207 static const struct {
211 { "alnum", _DIGIT
|_ALPHA
},
213 { "cntrl", _CONTROL
},
215 { "graph", _DIGIT
|_PUNCT
|_ALPHA
},
217 { "print", _DIGIT
|_PUNCT
|_BLANK
|_ALPHA
},
225 for(i
=0; i
<sizeof(properties
)/sizeof(properties
[0]); i
++)
226 if(!strcmp(property
, properties
[i
].name
))
227 return properties
[i
].mask
;
232 typedef void (__cdecl
*MSVCP_new_handler_func
)(void);
233 static MSVCP_new_handler_func MSVCP_new_handler
;
234 static int __cdecl
new_handler_wrapper(MSVCP_size_t unused
)
240 /* ?set_new_handler@std@@YAP6AXXZP6AXXZ@Z */
241 MSVCP_new_handler_func __cdecl
set_new_handler(MSVCP_new_handler_func new_handler
)
243 MSVCP_new_handler_func old_handler
= MSVCP_new_handler
;
245 TRACE("%p\n", new_handler
);
247 MSVCP_new_handler
= new_handler
;
248 MSVCRT_set_new_handler(new_handler
? new_handler_wrapper
: NULL
);
252 /* ?set_new_handler@std@@YAP6AXXZH@Z */
253 MSVCP_new_handler_func __cdecl
set_new_handler_reset(int unused
)
255 return set_new_handler(NULL
);
258 /* _Container_base0 is used by apps compiled without iterator checking
259 * (i.e. with _ITERATOR_DEBUG_LEVEL=0 ).
260 * It provides empty versions of methods used by visual c++'s stl's
262 * msvcr100 has to provide them in case apps are compiled with /Od
263 * or the optimizer fails to inline those (empty) calls.
266 /* ?_Orphan_all@_Container_base0@std@@QAEXXZ */
267 /* ?_Orphan_all@_Container_base0@std@@QEAAXXZ */
268 DEFINE_THISCALL_WRAPPER(Container_base0_Orphan_all
, 4)
269 void __thiscall
Container_base0_Orphan_all(void *this)
273 /* ?_Swap_all@_Container_base0@std@@QAEXAAU12@@Z */
274 /* ?_Swap_all@_Container_base0@std@@QEAAXAEAU12@@Z */
275 DEFINE_THISCALL_WRAPPER(Container_base0_Swap_all
, 8)
276 void __thiscall
Container_base0_Swap_all(void *this, void *that
)
280 /* ??4_Container_base0@std@@QAEAAU01@ABU01@@Z */
281 /* ??4_Container_base0@std@@QEAAAEAU01@AEBU01@@Z */
282 DEFINE_THISCALL_WRAPPER(Container_base0_op_assign
, 8)
283 void* __thiscall
Container_base0_op_assign(void *this, const void *that
)
288 /* ??0_Container_base12@std@@QAE@ABU01@@Z */
289 /* ??0_Container_base12@std@@QEAA@AEBU01@@Z */
290 DEFINE_THISCALL_WRAPPER(_Container_base12_copy_ctor
, 8)
291 _Container_base12
* __thiscall
_Container_base12_copy_ctor(
292 _Container_base12
*this, _Container_base12
*that
)
298 /* ??0_Container_base12@std@@QAE@XZ */
299 /* ??0_Container_base12@std@@QEAA@XZ */
300 DEFINE_THISCALL_WRAPPER(_Container_base12_ctor
, 4)
301 _Container_base12
* __thiscall
_Container_base12_ctor(_Container_base12
*this)
307 /* ??1_Container_base12@std@@QAE@XZ */
308 /* ??1_Container_base12@std@@QEAA@XZ */
309 DEFINE_THISCALL_WRAPPER(_Container_base12_dtor
, 4)
310 void __thiscall
_Container_base12_dtor(_Container_base12
*this)
314 /* ??4_Container_base12@std@@QAEAAU01@ABU01@@Z */
315 /* ??4_Container_base12@std@@QEAAAEAU01@AEBU01@@ */
316 DEFINE_THISCALL_WRAPPER(_Container_base12_op_assign
, 8)
317 _Container_base12
* __thiscall
_Container_base12_op_assign(
318 _Container_base12
*this, const _Container_base12
*that
)
323 /* ?_Getpfirst@_Container_base12@std@@QBEPAPAU_Iterator_base12@2@XZ */
324 /* ?_Getpfirst@_Container_base12@std@@QEBAPEAPEAU_Iterator_base12@2@XZ */
325 DEFINE_THISCALL_WRAPPER(_Container_base12__Getpfirst
, 4)
326 _Iterator_base12
** __thiscall
_Container_base12__Getpfirst(_Container_base12
*this)
328 return this->proxy
? &this->proxy
->head
: NULL
;
331 /* ?_Orphan_all@_Container_base12@std@@QAEXXZ */
332 /* ?_Orphan_all@_Container_base12@std@@QEAAXXZ */
333 DEFINE_THISCALL_WRAPPER(_Container_base12__Orphan_all
, 4)
334 void __thiscall
_Container_base12__Orphan_all(_Container_base12
*this)
338 /* ?_Swap_all@_Container_base12@std@@QAEXAAU12@@Z */
339 /* ?_Swap_all@_Container_base12@std@@QEAAXAEAU12@@Z */
340 DEFINE_THISCALL_WRAPPER(_Container_base12__Swap_all
, 8)
341 void __thiscall
_Container_base12__Swap_all(
342 _Container_base12
*this, _Container_base12
*that
)
344 _Container_proxy
*tmp
;
347 this->proxy
= that
->proxy
;
351 this->proxy
->cont
= this;
353 that
->proxy
->cont
= that
;
356 #if _MSVCP_VER >= 110
358 #define SECSPERDAY 86400
359 /* 1601 to 1970 is 369 years plus 89 leap days */
360 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
361 #define TICKSPERSEC 10000000
362 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
363 #define NANOSEC_PER_MILLISEC 1000000
364 #define MILLISEC_PER_SEC 1000
365 #define NANOSEC_PER_SEC (NANOSEC_PER_MILLISEC * MILLISEC_PER_SEC)
367 typedef int MSVCRT_long
;
375 /* _Xtime_get_ticks */
376 LONGLONG __cdecl
_Xtime_get_ticks(void)
382 GetSystemTimeAsFileTime(&ft
);
383 return ((LONGLONG
)ft
.dwHighDateTime
<<32) + ft
.dwLowDateTime
- TICKS_1601_TO_1970
;
387 int __cdecl
xtime_get(xtime
* t
, int unknown
)
396 ticks
= _Xtime_get_ticks();
397 t
->sec
= ticks
/ TICKSPERSEC
;
398 t
->nsec
= ticks
% TICKSPERSEC
* 100;
402 /* _Xtime_diff_to_millis2 */
403 MSVCRT_long __cdecl
_Xtime_diff_to_millis2(const xtime
*t1
, const xtime
*t2
)
405 LONGLONG diff_sec
, diff_nsec
;
407 TRACE("(%p, %p)\n", t1
, t2
);
409 diff_sec
= t1
->sec
- t2
->sec
;
410 diff_nsec
= t1
->nsec
- t2
->nsec
;
412 diff_sec
+= diff_nsec
/ NANOSEC_PER_SEC
;
413 diff_nsec
%= NANOSEC_PER_SEC
;
416 diff_nsec
+= NANOSEC_PER_SEC
;
419 if (diff_sec
<0 || (diff_sec
==0 && diff_nsec
<0))
421 return diff_sec
* MILLISEC_PER_SEC
+
422 (diff_nsec
+ NANOSEC_PER_MILLISEC
- 1) / NANOSEC_PER_MILLISEC
;
425 /* _Xtime_diff_to_millis */
426 MSVCRT_long __cdecl
_Xtime_diff_to_millis(const xtime
*t
)
433 return _Xtime_diff_to_millis2(t
, &now
);
438 unsigned int __cdecl
_Random_device(void)
444 /* TODO: throw correct exception in case of failure */
446 throw_exception(EXCEPTION
, "random number generator failed\n");
451 #if _MSVCP_VER >= 110
452 #if defined(__i386__) && !defined(__arm__)
454 extern void *call_thiscall_func
;
455 __ASM_GLOBAL_FUNC(call_thiscall_func
,
462 #define call_func1(func,this) ((void* (WINAPI*)(void*,void*))&call_thiscall_func)(func,this)
466 #define call_func1(func,this) func(this)
468 #endif /* __i386__ */
470 #define MTX_MULTI_LOCK 0x100
480 #if _MSVCP_VER >= 140
481 typedef _Mtx_t _Mtx_arg_t
;
482 #define MTX_T_FROM_ARG(m) (m)
483 #define MTX_T_TO_ARG(m) (m)
485 typedef _Mtx_t
*_Mtx_arg_t
;
486 #define MTX_T_FROM_ARG(m) (*(m))
487 #define MTX_T_TO_ARG(m) (&(m))
490 void __cdecl
_Mtx_init_in_situ(_Mtx_t mtx
, int flags
)
492 if(flags
& ~MTX_MULTI_LOCK
)
493 FIXME("unknown flags ignored: %x\n", flags
);
496 call_func1(critical_section_ctor
, &mtx
->cs
);
501 int __cdecl
_Mtx_init(_Mtx_t
*mtx
, int flags
)
503 *mtx
= MSVCRT_operator_new(sizeof(**mtx
));
504 _Mtx_init_in_situ(*mtx
, flags
);
508 void __cdecl
_Mtx_destroy_in_situ(_Mtx_t mtx
)
510 call_func1(critical_section_dtor
, &mtx
->cs
);
513 void __cdecl
_Mtx_destroy(_Mtx_arg_t mtx
)
515 call_func1(critical_section_dtor
, &MTX_T_FROM_ARG(mtx
)->cs
);
516 MSVCRT_operator_delete(MTX_T_FROM_ARG(mtx
));
519 int __cdecl
_Mtx_current_owns(_Mtx_arg_t mtx
)
521 return MTX_T_FROM_ARG(mtx
)->thread_id
== GetCurrentThreadId();
524 int __cdecl
_Mtx_lock(_Mtx_arg_t mtx
)
526 if(MTX_T_FROM_ARG(mtx
)->thread_id
!= GetCurrentThreadId()) {
527 call_func1(critical_section_lock
, &MTX_T_FROM_ARG(mtx
)->cs
);
528 MTX_T_FROM_ARG(mtx
)->thread_id
= GetCurrentThreadId();
529 }else if(!(MTX_T_FROM_ARG(mtx
)->flags
& MTX_MULTI_LOCK
)) {
533 MTX_T_FROM_ARG(mtx
)->count
++;
537 int __cdecl
_Mtx_unlock(_Mtx_arg_t mtx
)
539 if(--MTX_T_FROM_ARG(mtx
)->count
)
542 MTX_T_FROM_ARG(mtx
)->thread_id
= -1;
543 call_func1(critical_section_unlock
, &MTX_T_FROM_ARG(mtx
)->cs
);
547 int __cdecl
_Mtx_trylock(_Mtx_arg_t mtx
)
549 if(MTX_T_FROM_ARG(mtx
)->thread_id
!= GetCurrentThreadId()) {
550 if(!call_func1(critical_section_trylock
, &MTX_T_FROM_ARG(mtx
)->cs
))
552 MTX_T_FROM_ARG(mtx
)->thread_id
= GetCurrentThreadId();
553 }else if(!(MTX_T_FROM_ARG(mtx
)->flags
& MTX_MULTI_LOCK
)) {
557 MTX_T_FROM_ARG(mtx
)->count
++;
561 critical_section
* __cdecl
_Mtx_getconcrtcs(_Mtx_arg_t mtx
)
563 return &MTX_T_FROM_ARG(mtx
)->cs
;
566 static inline LONG
interlocked_dec_if_nonzero( LONG
*dest
)
569 for (val
= *dest
;; val
= tmp
)
571 if (!val
|| (tmp
= InterlockedCompareExchange( dest
, val
- 1, val
)) == val
)
577 #define CND_TIMEDOUT 2
581 CONDITION_VARIABLE cv
;
584 #if _MSVCP_VER >= 140
585 typedef _Cnd_t _Cnd_arg_t
;
586 #define CND_T_FROM_ARG(c) (c)
587 #define CND_T_TO_ARG(c) (c)
589 typedef _Cnd_t
*_Cnd_arg_t
;
590 #define CND_T_FROM_ARG(c) (*(c))
591 #define CND_T_TO_ARG(c) (&(c))
594 static HANDLE keyed_event
;
596 void __cdecl
_Cnd_init_in_situ(_Cnd_t cnd
)
598 InitializeConditionVariable(&cnd
->cv
);
603 NtCreateKeyedEvent(&event
, GENERIC_READ
|GENERIC_WRITE
, NULL
, 0);
604 if(InterlockedCompareExchangePointer(&keyed_event
, event
, NULL
) != NULL
)
609 int __cdecl
_Cnd_init(_Cnd_t
*cnd
)
611 *cnd
= MSVCRT_operator_new(sizeof(**cnd
));
612 _Cnd_init_in_situ(*cnd
);
616 int __cdecl
_Cnd_wait(_Cnd_arg_t cnd
, _Mtx_arg_t mtx
)
618 CONDITION_VARIABLE
*cv
= &CND_T_FROM_ARG(cnd
)->cv
;
620 InterlockedExchangeAdd( (LONG
*)&cv
->Ptr
, 1 );
623 NtWaitForKeyedEvent(keyed_event
, &cv
->Ptr
, FALSE
, NULL
);
629 int __cdecl
_Cnd_timedwait(_Cnd_arg_t cnd
, _Mtx_arg_t mtx
, const xtime
*xt
)
631 CONDITION_VARIABLE
*cv
= &CND_T_FROM_ARG(cnd
)->cv
;
632 LARGE_INTEGER timeout
;
635 InterlockedExchangeAdd( (LONG
*)&cv
->Ptr
, 1 );
638 timeout
.QuadPart
= (ULONGLONG
)(ULONG
)_Xtime_diff_to_millis(xt
) * -10000;
639 status
= NtWaitForKeyedEvent(keyed_event
, &cv
->Ptr
, FALSE
, &timeout
);
642 if (!interlocked_dec_if_nonzero( (LONG
*)&cv
->Ptr
))
643 status
= NtWaitForKeyedEvent( keyed_event
, &cv
->Ptr
, FALSE
, NULL
);
647 return status
? CND_TIMEDOUT
: 0;
650 int __cdecl
_Cnd_broadcast(_Cnd_arg_t cnd
)
652 CONDITION_VARIABLE
*cv
= &CND_T_FROM_ARG(cnd
)->cv
;
653 LONG val
= InterlockedExchange( (LONG
*)&cv
->Ptr
, 0 );
655 NtReleaseKeyedEvent( keyed_event
, &cv
->Ptr
, FALSE
, NULL
);
659 int __cdecl
_Cnd_signal(_Cnd_arg_t cnd
)
661 CONDITION_VARIABLE
*cv
= &CND_T_FROM_ARG(cnd
)->cv
;
662 if (interlocked_dec_if_nonzero( (LONG
*)&cv
->Ptr
))
663 NtReleaseKeyedEvent( keyed_event
, &cv
->Ptr
, FALSE
, NULL
);
667 void __cdecl
_Cnd_destroy_in_situ(_Cnd_t cnd
)
669 _Cnd_broadcast(CND_T_TO_ARG(cnd
));
672 void __cdecl
_Cnd_destroy(_Cnd_arg_t cnd
)
676 MSVCRT_operator_delete(CND_T_FROM_ARG(cnd
));
684 struct _to_broadcast
{
690 } broadcast_at_thread_exit
;
692 static CRITICAL_SECTION broadcast_at_thread_exit_cs
;
693 static CRITICAL_SECTION_DEBUG broadcast_at_thread_exit_cs_debug
=
695 0, 0, &broadcast_at_thread_exit_cs
,
696 { &broadcast_at_thread_exit_cs_debug
.ProcessLocksList
, &broadcast_at_thread_exit_cs_debug
.ProcessLocksList
},
697 0, 0, { (DWORD_PTR
)(__FILE__
": broadcast_at_thread_exit_cs") }
699 static CRITICAL_SECTION broadcast_at_thread_exit_cs
= { &broadcast_at_thread_exit_cs_debug
, -1, 0, 0, 0, 0 };
701 void __cdecl
_Cnd_register_at_thread_exit(_Cnd_arg_t cnd
, _Mtx_arg_t mtx
, int *p
)
703 struct _to_broadcast
*add
;
705 TRACE("(%p %p %p)\n", cnd
, mtx
, p
);
707 EnterCriticalSection(&broadcast_at_thread_exit_cs
);
708 if(!broadcast_at_thread_exit
.size
) {
709 broadcast_at_thread_exit
.to_broadcast
= HeapAlloc(GetProcessHeap(),
710 0, 8*sizeof(broadcast_at_thread_exit
.to_broadcast
[0]));
711 if(!broadcast_at_thread_exit
.to_broadcast
) {
712 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
715 broadcast_at_thread_exit
.size
= 8;
716 } else if(broadcast_at_thread_exit
.size
== broadcast_at_thread_exit
.used
) {
717 add
= HeapReAlloc(GetProcessHeap(), 0, broadcast_at_thread_exit
.to_broadcast
,
718 broadcast_at_thread_exit
.size
*2*sizeof(broadcast_at_thread_exit
.to_broadcast
[0]));
720 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
723 broadcast_at_thread_exit
.to_broadcast
= add
;
724 broadcast_at_thread_exit
.size
*= 2;
727 add
= broadcast_at_thread_exit
.to_broadcast
+ broadcast_at_thread_exit
.used
++;
728 add
->thread_id
= GetCurrentThreadId();
732 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
735 void __cdecl
_Cnd_unregister_at_thread_exit(_Mtx_arg_t mtx
)
739 TRACE("(%p)\n", mtx
);
741 EnterCriticalSection(&broadcast_at_thread_exit_cs
);
742 for(i
=0; i
<broadcast_at_thread_exit
.used
; i
++) {
743 if(broadcast_at_thread_exit
.to_broadcast
[i
].mtx
!= mtx
)
746 memmove(broadcast_at_thread_exit
.to_broadcast
+i
, broadcast_at_thread_exit
.to_broadcast
+i
+1,
747 (broadcast_at_thread_exit
.used
-i
-1)*sizeof(broadcast_at_thread_exit
.to_broadcast
[0]));
748 broadcast_at_thread_exit
.used
--;
751 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
754 void __cdecl
_Cnd_do_broadcast_at_thread_exit(void)
756 int i
, id
= GetCurrentThreadId();
760 EnterCriticalSection(&broadcast_at_thread_exit_cs
);
761 for(i
=0; i
<broadcast_at_thread_exit
.used
; i
++) {
762 if(broadcast_at_thread_exit
.to_broadcast
[i
].thread_id
!= id
)
765 _Mtx_unlock(broadcast_at_thread_exit
.to_broadcast
[i
].mtx
);
766 _Cnd_broadcast(broadcast_at_thread_exit
.to_broadcast
[i
].cnd
);
767 if(broadcast_at_thread_exit
.to_broadcast
[i
].p
)
768 *broadcast_at_thread_exit
.to_broadcast
[i
].p
= 1;
770 memmove(broadcast_at_thread_exit
.to_broadcast
+i
, broadcast_at_thread_exit
.to_broadcast
+i
+1,
771 (broadcast_at_thread_exit
.used
-i
-1)*sizeof(broadcast_at_thread_exit
.to_broadcast
[0]));
772 broadcast_at_thread_exit
.used
--;
775 LeaveCriticalSection(&broadcast_at_thread_exit_cs
);
780 #if _MSVCP_VER == 100
782 const vtable_ptr
*vtable
;
789 static custom_category iostream_category
;
791 DEFINE_RTTI_DATA0(error_category
, 0, ".?AVerror_category@std@@")
792 DEFINE_RTTI_DATA1(iostream_category
, 0, &error_category_rtti_base_descriptor
, ".?AV_Iostream_error_category@std@@")
794 extern const vtable_ptr MSVCP_iostream_category_vtable
;
796 static void iostream_category_ctor(custom_category
*this)
798 this->base
.vtable
= &MSVCP_iostream_category_vtable
;
799 this->type
= "iostream";
802 DEFINE_THISCALL_WRAPPER(custom_category_vector_dtor
, 8)
803 custom_category
* __thiscall
custom_category_vector_dtor(custom_category
*this, unsigned int flags
)
805 TRACE("(%p %x)\n", this, flags
);
807 /* we have an array, with the number of elements stored before the first object */
808 INT_PTR i
, *ptr
= (INT_PTR
*)this-1;
810 for(i
=*ptr
-1; i
>=0; i
--)
811 MSVCRT_operator_delete(ptr
);
814 MSVCRT_operator_delete(this);
820 DEFINE_THISCALL_WRAPPER(custom_category_name
, 4)
821 const char* __thiscall
custom_category_name(const custom_category
*this)
826 DEFINE_THISCALL_WRAPPER(custom_category_message
, 12)
827 basic_string_char
* __thiscall
custom_category_message(const custom_category
*this,
828 basic_string_char
*ret
, int err
)
830 return MSVCP_basic_string_char_ctor_cstr(ret
, strerror(err
));
833 DEFINE_THISCALL_WRAPPER(custom_category_default_error_condition
, 12)
834 /*error_condition*/void* __thiscall
custom_category_default_error_condition(
835 custom_category
*this, /*error_condition*/void *ret
, int code
)
837 FIXME("(%p %p %x) stub\n", this, ret
, code
);
841 DEFINE_THISCALL_WRAPPER(custom_category_equivalent
, 12)
842 MSVCP_bool __thiscall
custom_category_equivalent(const custom_category
*this,
843 int code
, const /*error_condition*/void *condition
)
845 FIXME("(%p %x %p) stub\n", this, code
, condition
);
849 DEFINE_THISCALL_WRAPPER(custom_category_equivalent_code
, 12)
850 MSVCP_bool __thiscall
custom_category_equivalent_code(custom_category
*this,
851 const /*error_code*/void *code
, int condition
)
853 FIXME("(%p %p %x) stub\n", this, code
, condition
);
857 DEFINE_THISCALL_WRAPPER(iostream_category_message
, 12)
858 basic_string_char
* __thiscall
iostream_category_message(const custom_category
*this,
859 basic_string_char
*ret
, int err
)
861 if(err
== 1) return MSVCP_basic_string_char_ctor_cstr(ret
, "iostream error");
862 return MSVCP_basic_string_char_ctor_cstr(ret
, strerror(err
));
865 /* ?iostream_category@std@@YAABVerror_category@1@XZ */
866 /* ?iostream_category@std@@YAAEBVerror_category@1@XZ */
867 const error_category
* __cdecl
std_iostream_category(void)
870 return &iostream_category
.base
;
873 static custom_category system_category
;
874 DEFINE_RTTI_DATA1(system_category
, 0, &error_category_rtti_base_descriptor
, ".?AV_System_error_category@std@@")
876 extern const vtable_ptr MSVCP_system_category_vtable
;
878 static void system_category_ctor(custom_category
*this)
880 this->base
.vtable
= &MSVCP_system_category_vtable
;
881 this->type
= "system";
884 /* ?system_category@std@@YAABVerror_category@1@XZ */
885 /* ?system_category@std@@YAAEBVerror_category@1@XZ */
886 const error_category
* __cdecl
std_system_category(void)
889 return &system_category
.base
;
892 static custom_category generic_category
;
893 DEFINE_RTTI_DATA1(generic_category
, 0, &error_category_rtti_base_descriptor
, ".?AV_Generic_error_category@std@@")
895 extern const vtable_ptr MSVCP_generic_category_vtable
;
897 static void generic_category_ctor(custom_category
*this)
899 this->base
.vtable
= &MSVCP_generic_category_vtable
;
900 this->type
= "generic";
903 /* ?generic_category@std@@YAABVerror_category@1@XZ */
904 /* ?generic_category@std@@YAAEBVerror_category@1@XZ */
905 const error_category
* __cdecl
std_generic_category(void)
908 return &generic_category
.base
;
912 #if _MSVCP_VER >= 110
913 static CRITICAL_SECTION call_once_cs
;
914 static CRITICAL_SECTION_DEBUG call_once_cs_debug
=
917 { &call_once_cs_debug
.ProcessLocksList
, &call_once_cs_debug
.ProcessLocksList
},
918 0, 0, { (DWORD_PTR
)(__FILE__
": call_once_cs") }
920 static CRITICAL_SECTION call_once_cs
= { &call_once_cs_debug
, -1, 0, 0, 0, 0 };
922 void __cdecl
_Call_onceEx(int *once
, void (__cdecl
*func
)(void*), void *argv
)
924 TRACE("%p %p %p\n", once
, func
, argv
);
926 EnterCriticalSection(&call_once_cs
);
928 /* FIXME: handle exceptions */
932 LeaveCriticalSection(&call_once_cs
);
935 static void __cdecl
call_once_func_wrapper(void *func
)
937 ((void (__cdecl
*)(void))func
)();
940 void __cdecl
_Call_once(int *once
, void (__cdecl
*func
)(void))
942 TRACE("%p %p\n", once
, func
);
943 _Call_onceEx(once
, call_once_func_wrapper
, func
);
946 void __cdecl
_Do_call(void *this)
948 CALL_VTBL_FUNC(this, 0, void, (void*), (this));
952 #if _MSVCP_VER >= 110
959 typedef int (__cdecl
*_Thrd_start_t
)(void*);
961 #define _THRD_ERROR 4
963 int __cdecl
_Thrd_equal(_Thrd_t a
, _Thrd_t b
)
965 TRACE("(%p %u %p %u)\n", a
.hnd
, a
.id
, b
.hnd
, b
.id
);
969 int __cdecl
_Thrd_lt(_Thrd_t a
, _Thrd_t b
)
971 TRACE("(%p %u %p %u)\n", a
.hnd
, a
.id
, b
.hnd
, b
.id
);
975 void __cdecl
_Thrd_sleep(const xtime
*t
)
978 Sleep(_Xtime_diff_to_millis(t
));
981 void __cdecl
_Thrd_yield(void)
987 static _Thrd_t
thread_current(void)
991 if(DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
992 GetCurrentProcess(), &ret
.hnd
, 0, FALSE
, DUPLICATE_SAME_ACCESS
)) {
993 CloseHandle(ret
.hnd
);
997 ret
.id
= GetCurrentThreadId();
999 TRACE("(%p %u)\n", ret
.hnd
, ret
.id
);
1004 _Thrd_t __cdecl
_Thrd_current(void)
1006 return thread_current();
1009 ULONGLONG __cdecl
_Thrd_current(void)
1016 C_ASSERT(sizeof(_Thrd_t
) <= sizeof(ULONGLONG
));
1018 ret
.thr
= thread_current();
1023 int __cdecl
_Thrd_join(_Thrd_t thr
, int *code
)
1025 TRACE("(%p %u %p)\n", thr
.hnd
, thr
.id
, code
);
1026 if (WaitForSingleObject(thr
.hnd
, INFINITE
))
1030 GetExitCodeThread(thr
.hnd
, (DWORD
*)code
);
1032 CloseHandle(thr
.hnd
);
1036 int __cdecl
_Thrd_start(_Thrd_t
*thr
, LPTHREAD_START_ROUTINE proc
, void *arg
)
1038 TRACE("(%p %p %p)\n", thr
, proc
, arg
);
1039 thr
->hnd
= CreateThread(NULL
, 0, proc
, arg
, 0, &thr
->id
);
1040 return thr
->hnd
? 0 : _THRD_ERROR
;
1049 static DWORD WINAPI
thread_proc_wrapper(void *arg
)
1051 thread_proc_arg wrapped_arg
= *((thread_proc_arg
*)arg
);
1053 return wrapped_arg
.proc(wrapped_arg
.arg
);
1056 int __cdecl
_Thrd_create(_Thrd_t
*thr
, _Thrd_start_t proc
, void *arg
)
1058 thread_proc_arg
*wrapped_arg
;
1061 TRACE("(%p %p %p)\n", thr
, proc
, arg
);
1063 wrapped_arg
= malloc(sizeof(*wrapped_arg
));
1065 return _THRD_ERROR
; /* TODO: probably different error should be returned here */
1067 wrapped_arg
->proc
= proc
;
1068 wrapped_arg
->arg
= arg
;
1069 ret
= _Thrd_start(thr
, thread_proc_wrapper
, wrapped_arg
);
1070 if(ret
) free(wrapped_arg
);
1074 int __cdecl
_Thrd_detach(_Thrd_t thr
)
1076 return CloseHandle(thr
.hnd
) ? 0 : _THRD_ERROR
;
1081 const vtable_ptr
*vtable
;
1084 MSVCP_bool launched
;
1087 DEFINE_RTTI_DATA0(_Pad
, 0, ".?AV_Pad@std@@")
1089 /* ??_7_Pad@std@@6B@ */
1090 extern const vtable_ptr MSVCP__Pad_vtable
;
1092 unsigned int __cdecl
_Thrd_hardware_concurrency(void)
1094 static unsigned int val
= -1;
1102 val
= si
.dwNumberOfProcessors
;
1108 unsigned int __cdecl
_Thrd_id(void)
1111 return GetCurrentThreadId();
1114 /* ??0_Pad@std@@QAE@XZ */
1115 /* ??0_Pad@std@@QEAA@XZ */
1116 DEFINE_THISCALL_WRAPPER(_Pad_ctor
, 4)
1117 _Pad
* __thiscall
_Pad_ctor(_Pad
*this)
1119 TRACE("(%p)\n", this);
1121 this->vtable
= &MSVCP__Pad_vtable
;
1122 _Cnd_init(&this->cnd
);
1123 _Mtx_init(&this->mtx
, 0);
1124 this->launched
= FALSE
;
1125 _Mtx_lock(MTX_T_TO_ARG(this->mtx
));
1129 /* ??4_Pad@std@@QAEAAV01@ABV01@@Z */
1130 /* ??4_Pad@std@@QEAAAEAV01@AEBV01@@Z */
1131 DEFINE_THISCALL_WRAPPER(_Pad_op_assign
, 8)
1132 _Pad
* __thiscall
_Pad_op_assign(_Pad
*this, const _Pad
*copy
)
1134 TRACE("(%p %p)\n", this, copy
);
1136 this->cnd
= copy
->cnd
;
1137 this->mtx
= copy
->mtx
;
1138 this->launched
= copy
->launched
;
1142 /* ??0_Pad@std@@QAE@ABV01@@Z */
1143 /* ??0_Pad@std@@QEAA@AEBV01@@Z */
1144 DEFINE_THISCALL_WRAPPER(_Pad_copy_ctor
, 8)
1145 _Pad
* __thiscall
_Pad_copy_ctor(_Pad
*this, const _Pad
*copy
)
1147 TRACE("(%p %p)\n", this, copy
);
1149 this->vtable
= &MSVCP__Pad_vtable
;
1150 return _Pad_op_assign(this, copy
);
1153 /* ??1_Pad@std@@QAE@XZ */
1154 /* ??1_Pad@std@@QEAA@XZ */
1155 DEFINE_THISCALL_WRAPPER(_Pad_dtor
, 4)
1156 void __thiscall
_Pad_dtor(_Pad
*this)
1158 TRACE("(%p)\n", this);
1160 _Mtx_unlock(MTX_T_TO_ARG(this->mtx
));
1161 _Mtx_destroy(MTX_T_TO_ARG(this->mtx
));
1162 _Cnd_destroy(CND_T_TO_ARG(this->cnd
));
1165 DEFINE_THISCALL_WRAPPER(_Pad__Go
, 4)
1166 #define call__Pad__Go(this) CALL_VTBL_FUNC(this, 0, unsigned int, (_Pad*), (this))
1167 unsigned int __thiscall
_Pad__Go(_Pad
*this)
1169 ERR("(%p) should not be called\n", this);
1173 static DWORD WINAPI
launch_thread_proc(void *arg
)
1176 return call__Pad__Go(this);
1179 /* ?_Launch@_Pad@std@@QAEXPAU_Thrd_imp_t@@@Z */
1180 /* ?_Launch@_Pad@std@@QEAAXPEAU_Thrd_imp_t@@@Z */
1181 DEFINE_THISCALL_WRAPPER(_Pad__Launch
, 8)
1182 void __thiscall
_Pad__Launch(_Pad
*this, _Thrd_t
*thr
)
1184 TRACE("(%p %p)\n", this, thr
);
1186 _Thrd_start(thr
, launch_thread_proc
, this);
1187 _Cnd_wait(CND_T_TO_ARG(this->cnd
), MTX_T_TO_ARG(this->mtx
));
1190 /* ?_Release@_Pad@std@@QAEXXZ */
1191 /* ?_Release@_Pad@std@@QEAAXXZ */
1192 DEFINE_THISCALL_WRAPPER(_Pad__Release
, 4)
1193 void __thiscall
_Pad__Release(_Pad
*this)
1195 TRACE("(%p)\n", this);
1197 _Mtx_lock(MTX_T_TO_ARG(this->mtx
));
1198 this->launched
= TRUE
;
1199 _Cnd_signal(CND_T_TO_ARG(this->cnd
));
1200 _Mtx_unlock(MTX_T_TO_ARG(this->mtx
));
1204 #if _MSVCP_VER >= 100
1205 typedef struct _Page
1207 struct _Page
*_Next
;
1217 MSVCP_size_t head_pos
;
1218 MSVCP_size_t tail_pos
;
1224 MSVCP_size_t tail_pos
;
1225 MSVCP_size_t head_pos
;
1226 threadsafe_queue queues
[QUEUES_NO
];
1231 const vtable_ptr
*vtable
;
1232 queue_data
*data
; /* queue_data structure is not binary compatible */
1233 MSVCP_size_t alloc_count
;
1234 MSVCP_size_t item_size
;
1235 } _Concurrent_queue_base_v4
;
1237 extern const vtable_ptr MSVCP__Concurrent_queue_base_v4_vtable
;
1239 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IBEXXZ */
1240 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IEBAXXZ */
1241 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_throw_exception
, 4)
1242 void __thiscall
_Concurrent_queue_base_v4__Internal_throw_exception(
1243 const _Concurrent_queue_base_v4
*this)
1245 TRACE("(%p)\n", this);
1246 throw_exception(EXCEPTION_BAD_ALLOC
, NULL
);
1249 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IAE@I@Z */
1250 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IEAA@_K@Z */
1251 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_ctor
, 8)
1252 _Concurrent_queue_base_v4
* __thiscall
_Concurrent_queue_base_v4_ctor(
1253 _Concurrent_queue_base_v4
*this, MSVCP_size_t size
)
1255 TRACE("(%p %ld)\n", this, size
);
1257 this->data
= MSVCRT_operator_new(sizeof(*this->data
));
1258 memset(this->data
, 0, sizeof(*this->data
));
1260 this->vtable
= &MSVCP__Concurrent_queue_base_v4_vtable
;
1261 this->item_size
= size
;
1263 /* alloc_count needs to be power of 2 */
1269 size
<= 128 ? 2 : 1;
1273 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MAE@XZ */
1274 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MEAA@XZ */
1275 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dtor
, 4)
1276 void __thiscall
_Concurrent_queue_base_v4_dtor(_Concurrent_queue_base_v4
*this)
1278 FIXME("(%p) stub\n", this);
1281 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_vector_dtor
, 8)
1282 _Concurrent_queue_base_v4
* __thiscall
_Concurrent_queue_base_v4_vector_dtor(
1283 _Concurrent_queue_base_v4
*this, unsigned int flags
)
1285 TRACE("(%p %x)\n", this, flags
);
1287 /* we have an array, with the number of elements stored before the first object */
1288 INT_PTR i
, *ptr
= (INT_PTR
*)this-1;
1290 for(i
=*ptr
-1; i
>=0; i
--)
1291 _Concurrent_queue_base_v4_dtor(this+i
);
1292 MSVCRT_operator_delete(ptr
);
1295 _Concurrent_queue_base_v4_dtor(this);
1296 MSVCRT_operator_delete(this);
1302 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IAEXXZ */
1303 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXXZ */
1304 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_finish_clear
, 4)
1305 void __thiscall
_Concurrent_queue_base_v4__Internal_finish_clear(
1306 _Concurrent_queue_base_v4
*this)
1308 FIXME("(%p) stub\n", this);
1311 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IBE_NXZ */
1312 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_NXZ */
1313 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_empty
, 4)
1314 MSVCP_bool __thiscall
_Concurrent_queue_base_v4__Internal_empty(
1315 const _Concurrent_queue_base_v4
*this)
1317 FIXME("(%p) stub\n", this);
1321 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IBEIXZ */
1322 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_KXZ */
1323 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_size
, 4)
1324 MSVCP_size_t __thiscall
_Concurrent_queue_base_v4__Internal_size(
1325 const _Concurrent_queue_base_v4
*this)
1327 FIXME("(%p) stub\n", this);
1331 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPBX@Z */
1332 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEBX@Z */
1333 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_push
, 8)
1334 void __thiscall
_Concurrent_queue_base_v4__Internal_push(
1335 _Concurrent_queue_base_v4
*this, const void *e
)
1337 FIXME("(%p %p) stub\n", this, e
);
1340 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPAX@Z */
1341 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEAX@Z */
1342 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_move_push
, 8)
1343 void __thiscall
_Concurrent_queue_base_v4__Internal_move_push(
1344 _Concurrent_queue_base_v4
*this, void *e
)
1346 FIXME("(%p %p) stub\n", this, e
);
1349 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IAE_NPAX@Z */
1350 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IEAA_NPEAX@Z */
1351 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_pop_if_present
, 8)
1352 MSVCP_bool __thiscall
_Concurrent_queue_base_v4__Internal_pop_if_present(
1353 _Concurrent_queue_base_v4
*this, void *e
)
1355 FIXME("(%p %p) stub\n", this, e
);
1359 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IAEXAAV123@@Z */
1360 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXAEAV123@@Z */
1361 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_swap
, 8)
1362 void __thiscall
_Concurrent_queue_base_v4__Internal_swap(
1363 _Concurrent_queue_base_v4
*this, _Concurrent_queue_base_v4
*r
)
1365 FIXME("(%p %p) stub\n", this, r
);
1368 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dummy
, 4)
1369 void __thiscall
_Concurrent_queue_base_v4_dummy(_Concurrent_queue_base_v4
*this)
1371 ERR("unexpected call\n");
1374 DEFINE_RTTI_DATA0(_Concurrent_queue_base_v4
, 0, ".?AV_Concurrent_queue_base_v4@details@Concurrency@@")
1378 void __asm_dummy_vtables(void) {
1380 #if _MSVCP_VER == 100
1381 __ASM_VTABLE(iostream_category
,
1382 VTABLE_ADD_FUNC(custom_category_vector_dtor
)
1383 VTABLE_ADD_FUNC(custom_category_name
)
1384 VTABLE_ADD_FUNC(iostream_category_message
)
1385 VTABLE_ADD_FUNC(custom_category_default_error_condition
)
1386 VTABLE_ADD_FUNC(custom_category_equivalent
)
1387 VTABLE_ADD_FUNC(custom_category_equivalent_code
));
1388 __ASM_VTABLE(system_category
,
1389 VTABLE_ADD_FUNC(custom_category_vector_dtor
)
1390 VTABLE_ADD_FUNC(custom_category_name
)
1391 VTABLE_ADD_FUNC(custom_category_message
)
1392 VTABLE_ADD_FUNC(custom_category_default_error_condition
)
1393 VTABLE_ADD_FUNC(custom_category_equivalent
)
1394 VTABLE_ADD_FUNC(custom_category_equivalent_code
));
1395 __ASM_VTABLE(generic_category
,
1396 VTABLE_ADD_FUNC(custom_category_vector_dtor
)
1397 VTABLE_ADD_FUNC(custom_category_name
)
1398 VTABLE_ADD_FUNC(custom_category_message
)
1399 VTABLE_ADD_FUNC(custom_category_default_error_condition
)
1400 VTABLE_ADD_FUNC(custom_category_equivalent
)
1401 VTABLE_ADD_FUNC(custom_category_equivalent_code
));
1403 #if _MSVCP_VER >= 100
1404 __ASM_VTABLE(_Concurrent_queue_base_v4
,
1405 #if _MSVCP_VER >= 110
1406 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
)
1408 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
)
1409 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
)
1410 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_vector_dtor
)
1411 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
)
1412 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy
));
1414 #if _MSVCP_VER >= 110
1416 VTABLE_ADD_FUNC(_Pad__Go
));
1422 /*********************************************************************
1423 * __crtInitializeCriticalSectionEx (MSVCP140.@)
1425 BOOL CDECL
MSVCP__crtInitializeCriticalSectionEx(
1426 CRITICAL_SECTION
*cs
, DWORD spin_count
, DWORD flags
)
1428 TRACE("(%p %x %x)\n", cs
, spin_count
, flags
);
1429 return InitializeCriticalSectionEx(cs
, spin_count
, flags
);
1432 /*********************************************************************
1433 * __crtCreateEventExW (MSVCP140.@)
1435 HANDLE CDECL
MSVCP__crtCreateEventExW(
1436 SECURITY_ATTRIBUTES
*attribs
, LPCWSTR name
, DWORD flags
, DWORD access
)
1438 TRACE("(%p %s 0x%08x 0x%08x)\n", attribs
, debugstr_w(name
), flags
, access
);
1439 return CreateEventExW(attribs
, name
, flags
, access
);
1442 /*********************************************************************
1443 * __crtGetTickCount64 (MSVCP140.@)
1445 ULONGLONG CDECL
MSVCP__crtGetTickCount64(void)
1447 return GetTickCount64();
1450 /*********************************************************************
1451 * __crtGetCurrentProcessorNumber (MSVCP140.@)
1453 DWORD CDECL
MSVCP__crtGetCurrentProcessorNumber(void)
1455 return GetCurrentProcessorNumber();
1458 /*********************************************************************
1459 * __crtFlushProcessWriteBuffers (MSVCP140.@)
1461 VOID CDECL
MSVCP__crtFlushProcessWriteBuffers(void)
1463 return FlushProcessWriteBuffers();
1466 /*********************************************************************
1467 * __crtCreateSemaphoreExW (MSVCP140.@)
1469 HANDLE CDECL
MSVCP__crtCreateSemaphoreExW(
1470 SECURITY_ATTRIBUTES
*attribs
, LONG initial_count
, LONG max_count
, LPCWSTR name
,
1471 DWORD flags
, DWORD access
)
1473 TRACE("(%p %d %d %s 0x%08x 0x%08x)\n", attribs
, initial_count
, max_count
, debugstr_w(name
),
1475 return CreateSemaphoreExW(attribs
, initial_count
, max_count
, name
, flags
, access
);
1478 /*********************************************************************
1479 * __crtCreateThreadpoolTimer (MSVCP140.@)
1481 PTP_TIMER CDECL
MSVCP__crtCreateThreadpoolTimer(PTP_TIMER_CALLBACK callback
,
1482 PVOID userdata
, TP_CALLBACK_ENVIRON
*environment
)
1484 TRACE("(%p %p %p)\n", callback
, userdata
, environment
);
1485 return CreateThreadpoolTimer(callback
, userdata
, environment
);
1488 /*********************************************************************
1489 * __crtCloseThreadpoolTimer (MSVCP140.@)
1491 VOID CDECL
MSVCP__crtCloseThreadpoolTimer(TP_TIMER
*timer
)
1493 TRACE("(%p)\n", timer
);
1494 CloseThreadpoolTimer(timer
);
1497 /*********************************************************************
1498 * __crtSetThreadpoolTimer (MSVCP140.@)
1500 VOID CDECL
MSVCP__crtSetThreadpoolTimer(TP_TIMER
*timer
,
1501 FILETIME
*due_time
, DWORD period
, DWORD window_length
)
1503 TRACE("(%p %p 0x%08x 0x%08x)\n", timer
, due_time
, period
, window_length
);
1504 return SetThreadpoolTimer(timer
, due_time
, period
, window_length
);
1507 /*********************************************************************
1508 * __crtWaitForThreadpoolTimerCallbacks (MSVCP140.@)
1510 VOID CDECL
MSVCP__crtWaitForThreadpoolTimerCallbacks(TP_TIMER
*timer
, BOOL cancel
)
1512 TRACE("(%p %d)\n", timer
, cancel
);
1513 WaitForThreadpoolTimerCallbacks(timer
, cancel
);
1516 /*********************************************************************
1517 * __crtCreateThreadpoolWait (MSVCP140.@)
1519 PTP_WAIT CDECL
MSVCP__crtCreateThreadpoolWait(PTP_WAIT_CALLBACK callback
,
1520 PVOID userdata
, TP_CALLBACK_ENVIRON
*environment
)
1522 TRACE("(%p %p %p)\n", callback
, userdata
, environment
);
1523 return CreateThreadpoolWait(callback
, userdata
, environment
);
1526 /*********************************************************************
1527 * __crtCloseThreadpoolWait (MSVCP140.@)
1529 VOID CDECL
MSVCP__crtCloseThreadpoolWait(TP_WAIT
*wait
)
1531 TRACE("(%p)\n", wait
);
1532 CloseThreadpoolWait(wait
);
1535 /*********************************************************************
1536 * __crtSetThreadpoolWait (MSVCP140.@)
1538 VOID CDECL
MSVCP__crtSetThreadpoolWait(TP_WAIT
*wait
, HANDLE handle
, FILETIME
*due_time
)
1540 TRACE("(%p %p %p)\n", wait
, handle
, due_time
);
1541 return SetThreadpoolWait(wait
, handle
, due_time
);
1544 /*********************************************************************
1545 * __crtFreeLibraryWhenCallbackReturns (MSVCP140.@)
1547 VOID CDECL
MSVCP__crtFreeLibraryWhenCallbackReturns(PTP_CALLBACK_INSTANCE instance
, HMODULE mod
)
1549 TRACE("(%p %p)\n", instance
, mod
);
1550 FreeLibraryWhenCallbackReturns(instance
, mod
);
1553 /* ?_Execute_once@std@@YAHAAUonce_flag@1@P6GHPAX1PAPAX@Z1@Z */
1554 /* ?_Execute_once@std@@YAHAEAUonce_flag@1@P6AHPEAX1PEAPEAX@Z1@Z */
1555 BOOL __cdecl
_Execute_once(INIT_ONCE
*flag
, PINIT_ONCE_FN func
, void *param
)
1557 return InitOnceExecuteOnce(flag
, func
, param
, NULL
);
1560 #if _MSVCP_VER >= 100
1561 void init_misc(void *base
)
1564 #if _MSVCP_VER == 100
1565 init_error_category_rtti(base
);
1566 init_iostream_category_rtti(base
);
1567 init_system_category_rtti(base
);
1568 init_generic_category_rtti(base
);
1570 #if _MSVCP_VER >= 100
1571 init__Concurrent_queue_base_v4_rtti(base
);
1573 #if _MSVCP_VER >= 110
1574 init__Pad_rtti(base
);
1578 #if _MSVCP_VER == 100
1579 iostream_category_ctor(&iostream_category
);
1580 system_category_ctor(&system_category
);
1581 generic_category_ctor(&generic_category
);
1585 void free_misc(void)
1587 #if _MSVCP_VER >= 110
1589 NtClose(keyed_event
);
1590 HeapFree(GetProcessHeap(), 0, broadcast_at_thread_exit
.to_broadcast
);
1595 #if _MSVCP_VER >= 140
1596 LONGLONG __cdecl
_Query_perf_counter(void)
1599 QueryPerformanceCounter(&li
);
1603 LONGLONG __cdecl
_Query_perf_frequency(void)
1606 QueryPerformanceFrequency(&li
);
1611 void __cdecl
threads__Mtx_new(void **mtx
)
1613 *mtx
= MSVCRT_operator_new(sizeof(CRITICAL_SECTION
));
1614 InitializeCriticalSection(*mtx
);
1617 void __cdecl
threads__Mtx_delete(void *mtx
)
1619 DeleteCriticalSection(mtx
);
1622 void __cdecl
threads__Mtx_lock(void *mtx
)
1624 EnterCriticalSection(mtx
);
1627 void __cdecl
threads__Mtx_unlock(void *mtx
)
1629 LeaveCriticalSection(mtx
);
1632 #if _MSVCP_VER >= 110
1633 static LONG shared_ptr_lock
;
1635 void __cdecl
_Lock_shared_ptr_spin_lock(void)
1639 while(InterlockedCompareExchange(&shared_ptr_lock
, 1, 0) != 0) {
1647 void __cdecl
_Unlock_shared_ptr_spin_lock(void)
1649 shared_ptr_lock
= 0;
1653 #if _MSVCP_VER >= 100
1654 /* ?is_current_task_group_canceling@Concurrency@@YA_NXZ */
1655 MSVCP_bool __cdecl
is_current_task_group_canceling(void)
1657 return Context_IsCurrentTaskCollectionCanceling();
1661 #if _MSVCP_VER >= 140
1665 } task_continuation_context
;
1667 /* ??0task_continuation_context@Concurrency@@AAE@XZ */
1668 /* ??0task_continuation_context@Concurrency@@AEAA@XZ */
1669 DEFINE_THISCALL_WRAPPER(task_continuation_context_ctor
, 4)
1670 task_continuation_context
* __thiscall
task_continuation_context_ctor(task_continuation_context
*this)
1672 TRACE("(%p)\n", this);
1673 memset(this, 0, sizeof(*this));
1678 const vtable_ptr
*vtable
;
1679 void (__cdecl
*func
)(void);
1683 } function_void_cdecl_void
;
1685 /* ?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z */
1686 /* ?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z */
1687 DEFINE_THISCALL_WRAPPER(_ContextCallback__Assign
, 8)
1688 void __thiscall
_ContextCallback__Assign(void *this, void *v
)
1690 TRACE("(%p %p)\n", this, v
);
1693 #define call_function_do_call(this) CALL_VTBL_FUNC(this, 8, void, (function_void_cdecl_void*), (this))
1694 #define call_function_do_clean(this,b) CALL_VTBL_FUNC(this, 16, void, (function_void_cdecl_void*,MSVCP_bool), (this, b))
1695 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z */
1696 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z */
1697 DEFINE_THISCALL_WRAPPER(_ContextCallback__CallInContext
, 48)
1698 void __thiscall
_ContextCallback__CallInContext(const void *this, function_void_cdecl_void func
, MSVCP_bool b
)
1700 TRACE("(%p %p %x)\n", this, func
.func
, b
);
1701 call_function_do_call(func
.this);
1702 call_function_do_clean(func
.this, func
.this!=&func
);
1705 /* ?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ */
1706 /* ?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ */
1707 DEFINE_THISCALL_WRAPPER(_ContextCallback__Capture
, 4)
1708 void __thiscall
_ContextCallback__Capture(void *this)
1710 TRACE("(%p)\n", this);
1713 /* ?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ */
1714 /* ?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ */
1715 DEFINE_THISCALL_WRAPPER(_ContextCallback__Reset
, 4)
1716 void __thiscall
_ContextCallback__Reset(void *this)
1718 TRACE("(%p)\n", this);
1721 /* ?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ */
1722 MSVCP_bool __cdecl
_ContextCallback__IsCurrentOriginSTA(void *this)
1724 TRACE("(%p)\n", this);
1729 /*_Task_impl_base*/void *task
;
1730 MSVCP_bool scheduled
;
1734 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1735 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1736 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogCancelTask
, 4)
1737 void __thiscall
_TaskEventLogger__LogCancelTask(_TaskEventLogger
*this)
1739 TRACE("(%p)\n", this);
1742 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z */
1743 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z */
1744 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogScheduleTask
, 8)
1745 void __thiscall
_TaskEventLogger__LogScheduleTask(_TaskEventLogger
*this, MSVCP_bool continuation
)
1747 TRACE("(%p %x)\n", this, continuation
);
1750 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1751 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1752 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskCompleted
, 4)
1753 void __thiscall
_TaskEventLogger__LogTaskCompleted(_TaskEventLogger
*this)
1755 TRACE("(%p)\n", this);
1758 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1759 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1760 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskExecutionCompleted
, 4)
1761 void __thiscall
_TaskEventLogger__LogTaskExecutionCompleted(_TaskEventLogger
*this)
1763 TRACE("(%p)\n", this);
1766 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1767 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1768 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemCompleted
, 4)
1769 void __thiscall
_TaskEventLogger__LogWorkItemCompleted(_TaskEventLogger
*this)
1771 TRACE("(%p)\n", this);
1774 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1775 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1776 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemStarted
, 4)
1777 void __thiscall
_TaskEventLogger__LogWorkItemStarted(_TaskEventLogger
*this)
1779 TRACE("(%p)\n", this);
1784 void (__cdecl
*callback
)(void*);
1786 } _Threadpool_chore
;
1788 /* ?_Reschedule_chore@details@Concurrency@@YAHPBU_Threadpool_chore@12@@Z */
1789 /* ?_Reschedule_chore@details@Concurrency@@YAHPEBU_Threadpool_chore@12@@Z */
1790 int __cdecl
_Reschedule_chore(const _Threadpool_chore
*chore
)
1792 TRACE("(%p)\n", chore
);
1794 SubmitThreadpoolWork(chore
->work
);
1798 static void WINAPI
threadpool_callback(PTP_CALLBACK_INSTANCE instance
, void *context
, PTP_WORK work
)
1800 _Threadpool_chore
*chore
= context
;
1801 TRACE("calling chore callback: %p\n", chore
);
1802 if (chore
->callback
)
1803 chore
->callback(chore
->arg
);
1806 /* ?_Schedule_chore@details@Concurrency@@YAHPAU_Threadpool_chore@12@@Z */
1807 /* ?_Schedule_chore@details@Concurrency@@YAHPEAU_Threadpool_chore@12@@Z */
1808 int __cdecl
_Schedule_chore(_Threadpool_chore
*chore
)
1810 TRACE("(%p)\n", chore
);
1812 chore
->work
= CreateThreadpoolWork(threadpool_callback
, chore
, NULL
);
1813 /* FIXME: what should be returned in case of error */
1817 return _Reschedule_chore(chore
);
1820 /* ?_Release_chore@details@Concurrency@@YAXPAU_Threadpool_chore@12@@Z */
1821 /* ?_Release_chore@details@Concurrency@@YAXPEAU_Threadpool_chore@12@@Z */
1822 void __cdecl
_Release_chore(_Threadpool_chore
*chore
)
1824 TRACE("(%p)\n", chore
);
1826 if(!chore
->work
) return;
1827 CloseThreadpoolWork(chore
->work
);
1832 #if _MSVCP_VER >= 110 && _MSVCP_VER <= 120
1837 /* ?_1@placeholders@std@@3V?$_Ph@$00@2@A */
1838 /* ?_20@placeholders@std@@3V?$_Ph@$0BE@@2@A */
1839 _Ph _Ph_1
= {0}, _Ph_2
= {0}, _Ph_3
= {0}, _Ph_4
= {0}, _Ph_5
= {0};
1840 _Ph _Ph_6
= {0}, _Ph_7
= {0}, _Ph_8
= {0}, _Ph_9
= {0}, _Ph_10
= {0};
1841 _Ph _Ph_11
= {0}, _Ph_12
= {0}, _Ph_13
= {0}, _Ph_14
= {0}, _Ph_15
= {0};
1842 _Ph _Ph_16
= {0}, _Ph_17
= {0}, _Ph_18
= {0}, _Ph_19
= {0}, _Ph_20
= {0};
1845 #if _MSVCP_VER >= 100
1846 /* based on wined3d_log2i from wined3d.h */
1847 /* Return the integer base-2 logarithm of (x|1). Result is 0 for x == 0. */
1848 static inline unsigned int log2i(unsigned int x
)
1850 #ifdef HAVE___BUILTIN_CLZ
1851 return __builtin_clz(x
|1) ^ 0x1f;
1853 static const unsigned int l
[] =
1855 ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
1856 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1857 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1858 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1859 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1860 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1861 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1862 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1863 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1864 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1865 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1866 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1867 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1868 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1869 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1870 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1875 return (i
= x
>> 16) ? (x
= i
>> 8) ? l
[x
] + 24 : l
[i
] + 16 : (i
= x
>> 8) ? l
[i
] + 8 : l
[x
];
1879 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KAII@Z */
1880 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KA_K_K@Z */
1881 MSVCP_size_t __cdecl
_vector_base_v4__Segment_index_of(MSVCP_size_t x
)
1885 TRACE("(%lu)\n", x
);
1887 if((sizeof(x
) == 8) && (half
= x
>> 32))
1888 return log2i(half
) + 32;
1893 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IBEXI@Z */
1894 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IEBAX_K@Z */
1895 DEFINE_THISCALL_WRAPPER(_vector_base_v4__Internal_throw_exception
, 8)
1896 void __thiscall
_vector_base_v4__Internal_throw_exception(void/*_vector_base_v4*/ *this, MSVCP_size_t idx
)
1898 static const struct {
1899 exception_type type
;
1902 { EXCEPTION_OUT_OF_RANGE
, "Index out of range" },
1903 { EXCEPTION_OUT_OF_RANGE
, "Index out of segments table range" },
1904 { EXCEPTION_RANGE_ERROR
, "Index is inside segment which failed to be allocated" },
1907 TRACE("(%p %lu)\n", this, idx
);
1909 if(idx
< sizeof(exceptions
)/sizeof(exceptions
[0]))
1910 throw_exception(exceptions
[idx
].type
, exceptions
[idx
].msg
);