msvcp100: Add _Concurrent_queue_base_v4 push/pop implementation.
[wine.git] / dlls / msvcp90 / misc.c
blobb3e546ae10030792bbac17456ffe268cbcf23467
1 /*
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
19 #include "config.h"
21 #include <stdarg.h>
22 #include <limits.h>
24 #include "msvcp90.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
32 struct __Container_proxy;
34 typedef struct {
35 struct __Container_proxy *proxy;
36 } _Container_base12;
38 typedef struct __Iterator_base12 {
39 struct __Container_proxy *proxy;
40 struct __Iterator_base12 *next;
41 } _Iterator_base12;
43 typedef struct __Container_proxy {
44 const _Container_base12 *cont;
45 _Iterator_base12 *head;
46 } _Container_proxy;
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));
54 if(!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");
61 this->mutex = cs;
62 return this;
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)
95 mutex_lock(m);
98 /* ?_Mutex_Unlock@_Mutex@std@@CAXPAV12@@Z */
99 /* ?_Mutex_Unlock@_Mutex@std@@CAXPEAV12@@Z */
100 void CDECL mutex_mutex_unlock(mutex *m)
102 mutex_unlock(m);
105 /* ?_Mutex_ctor@_Mutex@std@@CAXPAV12@@Z */
106 /* ?_Mutex_ctor@_Mutex@std@@CAXPEAV12@@Z */
107 void CDECL mutex_mutex_ctor(mutex *m)
109 mutex_ctor(m);
112 /* ?_Mutex_dtor@_Mutex@std@@CAXPAV12@@Z */
113 /* ?_Mutex_dtor@_Mutex@std@@CAXPEAV12@@Z */
114 void CDECL mutex_mutex_dtor(mutex *m)
116 mutex_dtor(m);
119 static CRITICAL_SECTION lockit_cs[_MAX_LOCK];
121 #if _MSVCP_VER >= 70
122 static inline int get_locktype( _Lockit *lockit ) { return lockit->locktype; }
123 static inline void set_locktype( _Lockit *lockit, int type ) { lockit->locktype = type; }
124 #else
125 static inline int get_locktype( _Lockit *lockit ) { return 0; }
126 static inline void set_locktype( _Lockit *lockit, int type ) { }
127 #endif
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) {
143 int i;
145 for(i=0; i<_MAX_LOCK; i++)
146 _Lockit_init(i);
149 void free_lockit(void) {
150 int i;
152 for(i=0; i<_MAX_LOCK; i++)
153 _Lockit_free(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);
177 return this;
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);
186 return this;
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);
204 /* wctype */
205 unsigned short __cdecl wctype(const char *property)
207 static const struct {
208 const char *name;
209 unsigned short mask;
210 } properties[] = {
211 { "alnum", _DIGIT|_ALPHA },
212 { "alpha", _ALPHA },
213 { "cntrl", _CONTROL },
214 { "digit", _DIGIT },
215 { "graph", _DIGIT|_PUNCT|_ALPHA },
216 { "lower", _LOWER },
217 { "print", _DIGIT|_PUNCT|_BLANK|_ALPHA },
218 { "punct", _PUNCT },
219 { "space", _SPACE },
220 { "upper", _UPPER },
221 { "xdigit", _HEX }
223 unsigned int i;
225 for(i=0; i<sizeof(properties)/sizeof(properties[0]); i++)
226 if(!strcmp(property, properties[i].name))
227 return properties[i].mask;
229 return 0;
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)
236 MSVCP_new_handler();
237 return 1;
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);
249 return old_handler;
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
261 * iterator checking.
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)
285 return this;
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)
294 this->proxy = NULL;
295 return this;
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)
303 this->proxy = NULL;
304 return 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)
320 return this;
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;
346 tmp = this->proxy;
347 this->proxy = that->proxy;
348 that->proxy = tmp;
350 if(this->proxy)
351 this->proxy->cont = this;
352 if(that->proxy)
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;
369 /* xtime */
370 typedef struct {
371 __time64_t sec;
372 MSVCRT_long nsec;
373 } xtime;
375 /* _Xtime_get_ticks */
376 LONGLONG __cdecl _Xtime_get_ticks(void)
378 FILETIME ft;
380 TRACE("\n");
382 GetSystemTimeAsFileTime(&ft);
383 return ((LONGLONG)ft.dwHighDateTime<<32) + ft.dwLowDateTime - TICKS_1601_TO_1970;
386 /* _xtime_get */
387 int __cdecl xtime_get(xtime* t, int unknown)
389 LONGLONG ticks;
391 TRACE("(%p)\n", t);
393 if(unknown != 1)
394 return 0;
396 ticks = _Xtime_get_ticks();
397 t->sec = ticks / TICKSPERSEC;
398 t->nsec = ticks % TICKSPERSEC * 100;
399 return 1;
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;
414 if (diff_nsec < 0) {
415 diff_sec -= 1;
416 diff_nsec += NANOSEC_PER_SEC;
419 if (diff_sec<0 || (diff_sec==0 && diff_nsec<0))
420 return 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)
428 xtime now;
430 TRACE("%p\n", t);
432 xtime_get(&now, 1);
433 return _Xtime_diff_to_millis2(t, &now);
435 #endif
437 #if _MSVCP_VER >= 90
438 unsigned int __cdecl _Random_device(void)
440 unsigned int ret;
442 TRACE("\n");
444 /* TODO: throw correct exception in case of failure */
445 if(rand_s(&ret))
446 throw_exception(EXCEPTION, "random number generator failed\n");
447 return ret;
449 #endif
451 #if _MSVCP_VER >= 110
452 #if defined(__i386__) && !defined(__arm__)
454 extern void *call_thiscall_func;
455 __ASM_GLOBAL_FUNC(call_thiscall_func,
456 "popl %eax\n\t"
457 "popl %edx\n\t"
458 "popl %ecx\n\t"
459 "pushl %eax\n\t"
460 "jmp *%edx\n\t")
462 #define call_func1(func,this) ((void* (WINAPI*)(void*,void*))&call_thiscall_func)(func,this)
464 #else /* __i386__ */
466 #define call_func1(func,this) func(this)
468 #endif /* __i386__ */
470 #define MTX_MULTI_LOCK 0x100
471 #define MTX_LOCKED 3
472 typedef struct
474 DWORD flags;
475 critical_section cs;
476 DWORD thread_id;
477 DWORD count;
478 } *_Mtx_t;
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)
484 #else
485 typedef _Mtx_t *_Mtx_arg_t;
486 #define MTX_T_FROM_ARG(m) (*(m))
487 #define MTX_T_TO_ARG(m) (&(m))
488 #endif
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);
495 mtx->flags = flags;
496 call_func1(critical_section_ctor, &mtx->cs);
497 mtx->thread_id = -1;
498 mtx->count = 0;
501 int __cdecl _Mtx_init(_Mtx_t *mtx, int flags)
503 *mtx = MSVCRT_operator_new(sizeof(**mtx));
504 _Mtx_init_in_situ(*mtx, flags);
505 return 0;
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)) {
530 return MTX_LOCKED;
533 MTX_T_FROM_ARG(mtx)->count++;
534 return 0;
537 int __cdecl _Mtx_unlock(_Mtx_arg_t mtx)
539 if(--MTX_T_FROM_ARG(mtx)->count)
540 return 0;
542 MTX_T_FROM_ARG(mtx)->thread_id = -1;
543 call_func1(critical_section_unlock, &MTX_T_FROM_ARG(mtx)->cs);
544 return 0;
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))
551 return MTX_LOCKED;
552 MTX_T_FROM_ARG(mtx)->thread_id = GetCurrentThreadId();
553 }else if(!(MTX_T_FROM_ARG(mtx)->flags & MTX_MULTI_LOCK)) {
554 return MTX_LOCKED;
557 MTX_T_FROM_ARG(mtx)->count++;
558 return 0;
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 )
568 LONG val, tmp;
569 for (val = *dest;; val = tmp)
571 if (!val || (tmp = InterlockedCompareExchange( dest, val - 1, val )) == val)
572 break;
574 return val;
577 #define CND_TIMEDOUT 2
579 typedef struct
581 CONDITION_VARIABLE cv;
582 } *_Cnd_t;
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)
588 #else
589 typedef _Cnd_t *_Cnd_arg_t;
590 #define CND_T_FROM_ARG(c) (*(c))
591 #define CND_T_TO_ARG(c) (&(c))
592 #endif
594 static HANDLE keyed_event;
596 void __cdecl _Cnd_init_in_situ(_Cnd_t cnd)
598 InitializeConditionVariable(&cnd->cv);
600 if(!keyed_event) {
601 HANDLE event;
603 NtCreateKeyedEvent(&event, GENERIC_READ|GENERIC_WRITE, NULL, 0);
604 if(InterlockedCompareExchangePointer(&keyed_event, event, NULL) != NULL)
605 NtClose(event);
609 int __cdecl _Cnd_init(_Cnd_t *cnd)
611 *cnd = MSVCRT_operator_new(sizeof(**cnd));
612 _Cnd_init_in_situ(*cnd);
613 return 0;
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 );
621 _Mtx_unlock(mtx);
623 NtWaitForKeyedEvent(keyed_event, &cv->Ptr, FALSE, NULL);
625 _Mtx_lock(mtx);
626 return 0;
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;
633 NTSTATUS status;
635 InterlockedExchangeAdd( (LONG *)&cv->Ptr, 1 );
636 _Mtx_unlock(mtx);
638 timeout.QuadPart = (ULONGLONG)(ULONG)_Xtime_diff_to_millis(xt) * -10000;
639 status = NtWaitForKeyedEvent(keyed_event, &cv->Ptr, FALSE, &timeout);
640 if (status)
642 if (!interlocked_dec_if_nonzero( (LONG *)&cv->Ptr ))
643 status = NtWaitForKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
646 _Mtx_lock(mtx);
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 );
654 while (val-- > 0)
655 NtReleaseKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
656 return 0;
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 );
664 return 0;
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)
674 if(cnd) {
675 _Cnd_broadcast(cnd);
676 MSVCRT_operator_delete(CND_T_FROM_ARG(cnd));
680 static struct {
681 int used;
682 int size;
684 struct _to_broadcast {
685 DWORD thread_id;
686 _Cnd_arg_t cnd;
687 _Mtx_arg_t mtx;
688 int *p;
689 } *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);
713 return;
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]));
719 if(!add) {
720 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
721 return;
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();
729 add->cnd = cnd;
730 add->mtx = mtx;
731 add->p = p;
732 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
735 void __cdecl _Cnd_unregister_at_thread_exit(_Mtx_arg_t mtx)
737 int i;
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)
744 continue;
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--;
749 i--;
751 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
754 void __cdecl _Cnd_do_broadcast_at_thread_exit(void)
756 int i, id = GetCurrentThreadId();
758 TRACE("()\n");
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)
763 continue;
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--;
773 i--;
775 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
778 #endif
780 #if _MSVCP_VER == 100
781 typedef struct {
782 const vtable_ptr *vtable;
783 } error_category;
785 typedef struct {
786 error_category base;
787 const char *type;
788 } custom_category;
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);
806 if(flags & 2) {
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);
812 } else {
813 if(flags & 1)
814 MSVCRT_operator_delete(this);
817 return this;
820 DEFINE_THISCALL_WRAPPER(custom_category_name, 4)
821 const char* __thiscall custom_category_name(const custom_category *this)
823 return this->type;
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);
838 return NULL;
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);
846 return FALSE;
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);
854 return FALSE;
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)
869 TRACE("()\n");
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)
888 TRACE("()\n");
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)
907 TRACE("()\n");
908 return &generic_category.base;
910 #endif
912 #if _MSVCP_VER >= 110
913 static CRITICAL_SECTION call_once_cs;
914 static CRITICAL_SECTION_DEBUG call_once_cs_debug =
916 0, 0, &call_once_cs,
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);
927 if(!*once) {
928 /* FIXME: handle exceptions */
929 func(argv);
930 *once = 1;
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));
950 #endif
952 #if _MSVCP_VER >= 110
953 typedef struct
955 HANDLE hnd;
956 DWORD id;
957 } _Thrd_t;
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);
966 return a.id == 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);
972 return a.id < b.id;
975 void __cdecl _Thrd_sleep(const xtime *t)
977 TRACE("(%p)\n", t);
978 Sleep(_Xtime_diff_to_millis(t));
981 void __cdecl _Thrd_yield(void)
983 TRACE("()\n");
984 Sleep(0);
987 static _Thrd_t thread_current(void)
989 _Thrd_t ret;
991 if(DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
992 GetCurrentProcess(), &ret.hnd, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
993 CloseHandle(ret.hnd);
994 } else {
995 ret.hnd = 0;
997 ret.id = GetCurrentThreadId();
999 TRACE("(%p %u)\n", ret.hnd, ret.id);
1000 return ret;
1003 #ifndef __i386__
1004 _Thrd_t __cdecl _Thrd_current(void)
1006 return thread_current();
1008 #else
1009 ULONGLONG __cdecl _Thrd_current(void)
1011 union {
1012 _Thrd_t thr;
1013 ULONGLONG ull;
1014 } ret;
1016 C_ASSERT(sizeof(_Thrd_t) <= sizeof(ULONGLONG));
1018 ret.thr = thread_current();
1019 return ret.ull;
1021 #endif
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))
1027 return _THRD_ERROR;
1029 if (code)
1030 GetExitCodeThread(thr.hnd, (DWORD *)code);
1032 CloseHandle(thr.hnd);
1033 return 0;
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;
1043 typedef struct
1045 _Thrd_start_t proc;
1046 void *arg;
1047 } thread_proc_arg;
1049 static DWORD WINAPI thread_proc_wrapper(void *arg)
1051 thread_proc_arg wrapped_arg = *((thread_proc_arg*)arg);
1052 free(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;
1059 int ret;
1061 TRACE("(%p %p %p)\n", thr, proc, arg);
1063 wrapped_arg = malloc(sizeof(*wrapped_arg));
1064 if(!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);
1071 return ret;
1074 int __cdecl _Thrd_detach(_Thrd_t thr)
1076 return CloseHandle(thr.hnd) ? 0 : _THRD_ERROR;
1079 typedef struct
1081 const vtable_ptr *vtable;
1082 _Cnd_t cnd;
1083 _Mtx_t mtx;
1084 MSVCP_bool launched;
1085 } _Pad;
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;
1096 TRACE("()\n");
1098 if(val == -1) {
1099 SYSTEM_INFO si;
1101 GetSystemInfo(&si);
1102 val = si.dwNumberOfProcessors;
1105 return val;
1108 unsigned int __cdecl _Thrd_id(void)
1110 TRACE("()\n");
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));
1126 return this;
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;
1139 return this;
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);
1170 return 0;
1173 static DWORD WINAPI launch_thread_proc(void *arg)
1175 _Pad *this = 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));
1202 #endif
1204 #if _MSVCP_VER >= 100
1205 typedef struct _Page
1207 struct _Page *_Next;
1208 MSVCP_size_t _Mask;
1209 char data[1];
1210 } _Page;
1212 typedef struct
1214 LONG lock;
1215 _Page *head;
1216 _Page *tail;
1217 MSVCP_size_t head_pos;
1218 MSVCP_size_t tail_pos;
1219 } threadsafe_queue;
1221 #define QUEUES_NO 8
1222 typedef struct
1224 MSVCP_size_t tail_pos;
1225 MSVCP_size_t head_pos;
1226 threadsafe_queue queues[QUEUES_NO];
1227 } queue_data;
1229 typedef struct
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;
1238 #if _MSVCP_VER == 100
1239 #define call__Concurrent_queue_base_v4__Move_item call__Concurrent_queue_base_v4__Copy_item
1240 #define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1241 0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
1242 #define call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
1243 4, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
1244 #define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
1245 12, _Page*, (_Concurrent_queue_base_v4*), (this))
1246 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
1247 16, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
1248 #else
1249 #define call__Concurrent_queue_base_v4__Move_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1250 0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,void*), (this,dst,idx,src))
1251 #define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1252 4, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
1253 #define call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
1254 8, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
1255 #define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
1256 16, _Page*, (_Concurrent_queue_base_v4*), (this))
1257 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
1258 20, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
1259 #endif
1261 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IBEXXZ */
1262 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IEBAXXZ */
1263 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_throw_exception, 4)
1264 void __thiscall _Concurrent_queue_base_v4__Internal_throw_exception(
1265 const _Concurrent_queue_base_v4 *this)
1267 TRACE("(%p)\n", this);
1268 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1271 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IAE@I@Z */
1272 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IEAA@_K@Z */
1273 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_ctor, 8)
1274 _Concurrent_queue_base_v4* __thiscall _Concurrent_queue_base_v4_ctor(
1275 _Concurrent_queue_base_v4 *this, MSVCP_size_t size)
1277 TRACE("(%p %ld)\n", this, size);
1279 this->data = MSVCRT_operator_new(sizeof(*this->data));
1280 memset(this->data, 0, sizeof(*this->data));
1282 this->vtable = &MSVCP__Concurrent_queue_base_v4_vtable;
1283 this->item_size = size;
1285 /* alloc_count needs to be power of 2 */
1286 this->alloc_count =
1287 size <= 8 ? 32 :
1288 size <= 16 ? 16 :
1289 size <= 32 ? 8 :
1290 size <= 64 ? 4 :
1291 size <= 128 ? 2 : 1;
1292 return this;
1295 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MAE@XZ */
1296 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MEAA@XZ */
1297 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dtor, 4)
1298 void __thiscall _Concurrent_queue_base_v4_dtor(_Concurrent_queue_base_v4 *this)
1300 TRACE("(%p)\n", this);
1301 MSVCRT_operator_delete(this->data);
1304 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_vector_dtor, 8)
1305 _Concurrent_queue_base_v4* __thiscall _Concurrent_queue_base_v4_vector_dtor(
1306 _Concurrent_queue_base_v4 *this, unsigned int flags)
1308 TRACE("(%p %x)\n", this, flags);
1309 if(flags & 2) {
1310 /* we have an array, with the number of elements stored before the first object */
1311 INT_PTR i, *ptr = (INT_PTR *)this-1;
1313 for(i=*ptr-1; i>=0; i--)
1314 _Concurrent_queue_base_v4_dtor(this+i);
1315 MSVCRT_operator_delete(ptr);
1316 } else {
1317 if(flags & 1)
1318 _Concurrent_queue_base_v4_dtor(this);
1319 MSVCRT_operator_delete(this);
1322 return this;
1325 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IAEXXZ */
1326 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXXZ */
1327 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_finish_clear, 4)
1328 void __thiscall _Concurrent_queue_base_v4__Internal_finish_clear(
1329 _Concurrent_queue_base_v4 *this)
1331 int i;
1333 TRACE("(%p)\n", this);
1335 for(i=0; i<QUEUES_NO; i++)
1337 if(this->data->queues[i].tail)
1338 call__Concurrent_queue_base_v4__Deallocate_page(this, this->data->queues[i].tail);
1342 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IBE_NXZ */
1343 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_NXZ */
1344 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_empty, 4)
1345 MSVCP_bool __thiscall _Concurrent_queue_base_v4__Internal_empty(
1346 const _Concurrent_queue_base_v4 *this)
1348 TRACE("(%p)\n", this);
1349 return this->data->head_pos == this->data->tail_pos;
1352 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IBEIXZ */
1353 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_KXZ */
1354 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_size, 4)
1355 MSVCP_size_t __thiscall _Concurrent_queue_base_v4__Internal_size(
1356 const _Concurrent_queue_base_v4 *this)
1358 TRACE("(%p)\n", this);
1359 return this->data->tail_pos - this->data->head_pos;
1362 static void spin_wait(int *counter)
1364 static int spin_limit = -1;
1366 if(spin_limit == -1)
1368 SYSTEM_INFO si;
1369 GetSystemInfo(&si);
1370 spin_limit = si.dwNumberOfProcessors>1 ? 4000 : 0;
1373 if(*counter >= spin_limit)
1375 *counter = 0;
1376 Sleep(0);
1378 else
1380 (*counter)++;
1384 #ifdef _WIN64
1385 static MSVCP_size_t InterlockedIncrementSizeT(MSVCP_size_t volatile *dest)
1387 MSVCP_size_t v;
1391 v = *dest;
1392 } while(InterlockedCompareExchange64((LONGLONG*)dest, v+1, v) != v);
1394 return v+1;
1396 #else
1397 #define InterlockedIncrementSizeT(dest) InterlockedIncrement((LONG*)dest)
1398 #endif
1400 static void threadsafe_queue_push(threadsafe_queue *queue, MSVCP_size_t id,
1401 void *e, _Concurrent_queue_base_v4 *parent, BOOL copy)
1403 MSVCP_size_t page_id = id & ~(parent->alloc_count-1);
1404 int spin;
1405 _Page *p;
1407 spin = 0;
1408 while(queue->tail_pos != id)
1409 spin_wait(&spin);
1411 if(page_id == id)
1413 /* TODO: Add exception handling */
1414 p = call__Concurrent_queue_base_v4__Allocate_page(parent);
1415 p->_Next = NULL;
1416 p->_Mask = 0;
1418 spin = 0;
1419 while(InterlockedCompareExchange(&queue->lock, 1, 0))
1420 spin_wait(&spin);
1421 if(queue->tail)
1422 queue->tail->_Next = p;
1423 queue->tail = p;
1424 if(!queue->head)
1425 queue->head = p;
1426 queue->lock = 0;
1428 else
1430 p = queue->tail;
1433 /* TODO: Add exception handling */
1434 if(copy)
1435 call__Concurrent_queue_base_v4__Copy_item(parent, p, id-page_id, e);
1436 else
1437 call__Concurrent_queue_base_v4__Move_item(parent, p, id-page_id, e);
1438 p->_Mask |= 1 << (id - page_id);
1439 InterlockedIncrementSizeT(&queue->tail_pos);
1442 static void threadsafe_queue_pop(threadsafe_queue *queue, MSVCP_size_t id,
1443 void *e, _Concurrent_queue_base_v4 *parent)
1445 MSVCP_size_t page_id = id & ~(parent->alloc_count-1);
1446 int spin;
1447 _Page *p;
1449 spin = 0;
1450 while(queue->tail_pos <= id)
1451 spin_wait(&spin);
1453 spin = 0;
1454 while(queue->head_pos != id)
1455 spin_wait(&spin);
1457 p = queue->head;
1458 /* TODO: Add exception handling */
1459 call__Concurrent_queue_base_v4__Assign_and_destroy_item(parent, e, p, id-page_id);
1461 if(id == page_id+parent->alloc_count-1)
1463 spin = 0;
1464 while(InterlockedCompareExchange(&queue->lock, 1, 0))
1465 spin_wait(&spin);
1466 queue->head = p->_Next;
1467 if(!queue->head)
1468 queue->tail = NULL;
1469 queue->lock = 0;
1471 /* TODO: Add exception handling */
1472 call__Concurrent_queue_base_v4__Deallocate_page(parent, p);
1474 InterlockedIncrementSizeT(&queue->head_pos);
1477 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPBX@Z */
1478 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEBX@Z */
1479 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_push, 8)
1480 void __thiscall _Concurrent_queue_base_v4__Internal_push(
1481 _Concurrent_queue_base_v4 *this, void *e)
1483 MSVCP_size_t id;
1485 TRACE("(%p %p)\n", this, e);
1487 id = InterlockedIncrementSizeT(&this->data->tail_pos)-1;
1488 threadsafe_queue_push(this->data->queues + id % QUEUES_NO,
1489 id / QUEUES_NO, e, this, TRUE);
1492 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPAX@Z */
1493 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEAX@Z */
1494 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_move_push, 8)
1495 void __thiscall _Concurrent_queue_base_v4__Internal_move_push(
1496 _Concurrent_queue_base_v4 *this, void *e)
1498 MSVCP_size_t id;
1500 TRACE("(%p %p)\n", this, e);
1502 id = InterlockedIncrementSizeT(&this->data->tail_pos)-1;
1503 threadsafe_queue_push(this->data->queues + id % QUEUES_NO,
1504 id / QUEUES_NO, e, this, FALSE);
1507 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IAE_NPAX@Z */
1508 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IEAA_NPEAX@Z */
1509 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_pop_if_present, 8)
1510 MSVCP_bool __thiscall _Concurrent_queue_base_v4__Internal_pop_if_present(
1511 _Concurrent_queue_base_v4 *this, void *e)
1513 MSVCP_size_t id;
1515 TRACE("(%p %p)\n", this, e);
1519 id = this->data->head_pos;
1520 if(id == this->data->tail_pos) return FALSE;
1521 } while(InterlockedCompareExchangePointer((void**)&this->data->head_pos,
1522 (void*)(id+1), (void*)id) != (void*)id);
1523 threadsafe_queue_pop(this->data->queues + id % QUEUES_NO, id / QUEUES_NO, e, this);
1524 return TRUE;
1527 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IAEXAAV123@@Z */
1528 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXAEAV123@@Z */
1529 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_swap, 8)
1530 void __thiscall _Concurrent_queue_base_v4__Internal_swap(
1531 _Concurrent_queue_base_v4 *this, _Concurrent_queue_base_v4 *r)
1533 FIXME("(%p %p) stub\n", this, r);
1536 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dummy, 4)
1537 void __thiscall _Concurrent_queue_base_v4_dummy(_Concurrent_queue_base_v4 *this)
1539 ERR("unexpected call\n");
1542 DEFINE_RTTI_DATA0(_Concurrent_queue_base_v4, 0, ".?AV_Concurrent_queue_base_v4@details@Concurrency@@")
1543 #endif
1545 #ifndef __GNUC__
1546 void __asm_dummy_vtables(void) {
1547 #endif
1548 #if _MSVCP_VER == 100
1549 __ASM_VTABLE(iostream_category,
1550 VTABLE_ADD_FUNC(custom_category_vector_dtor)
1551 VTABLE_ADD_FUNC(custom_category_name)
1552 VTABLE_ADD_FUNC(iostream_category_message)
1553 VTABLE_ADD_FUNC(custom_category_default_error_condition)
1554 VTABLE_ADD_FUNC(custom_category_equivalent)
1555 VTABLE_ADD_FUNC(custom_category_equivalent_code));
1556 __ASM_VTABLE(system_category,
1557 VTABLE_ADD_FUNC(custom_category_vector_dtor)
1558 VTABLE_ADD_FUNC(custom_category_name)
1559 VTABLE_ADD_FUNC(custom_category_message)
1560 VTABLE_ADD_FUNC(custom_category_default_error_condition)
1561 VTABLE_ADD_FUNC(custom_category_equivalent)
1562 VTABLE_ADD_FUNC(custom_category_equivalent_code));
1563 __ASM_VTABLE(generic_category,
1564 VTABLE_ADD_FUNC(custom_category_vector_dtor)
1565 VTABLE_ADD_FUNC(custom_category_name)
1566 VTABLE_ADD_FUNC(custom_category_message)
1567 VTABLE_ADD_FUNC(custom_category_default_error_condition)
1568 VTABLE_ADD_FUNC(custom_category_equivalent)
1569 VTABLE_ADD_FUNC(custom_category_equivalent_code));
1570 #endif
1571 #if _MSVCP_VER >= 100
1572 __ASM_VTABLE(_Concurrent_queue_base_v4,
1573 #if _MSVCP_VER >= 110
1574 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
1575 #endif
1576 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
1577 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
1578 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_vector_dtor)
1579 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
1580 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy));
1581 #endif
1582 #if _MSVCP_VER >= 110
1583 __ASM_VTABLE(_Pad,
1584 VTABLE_ADD_FUNC(_Pad__Go));
1585 #endif
1586 #ifndef __GNUC__
1588 #endif
1590 /*********************************************************************
1591 * __crtInitializeCriticalSectionEx (MSVCP140.@)
1593 BOOL CDECL MSVCP__crtInitializeCriticalSectionEx(
1594 CRITICAL_SECTION *cs, DWORD spin_count, DWORD flags)
1596 TRACE("(%p %x %x)\n", cs, spin_count, flags);
1597 return InitializeCriticalSectionEx(cs, spin_count, flags);
1600 /*********************************************************************
1601 * __crtCreateEventExW (MSVCP140.@)
1603 HANDLE CDECL MSVCP__crtCreateEventExW(
1604 SECURITY_ATTRIBUTES *attribs, LPCWSTR name, DWORD flags, DWORD access)
1606 TRACE("(%p %s 0x%08x 0x%08x)\n", attribs, debugstr_w(name), flags, access);
1607 return CreateEventExW(attribs, name, flags, access);
1610 /*********************************************************************
1611 * __crtGetTickCount64 (MSVCP140.@)
1613 ULONGLONG CDECL MSVCP__crtGetTickCount64(void)
1615 return GetTickCount64();
1618 /*********************************************************************
1619 * __crtGetCurrentProcessorNumber (MSVCP140.@)
1621 DWORD CDECL MSVCP__crtGetCurrentProcessorNumber(void)
1623 return GetCurrentProcessorNumber();
1626 /*********************************************************************
1627 * __crtFlushProcessWriteBuffers (MSVCP140.@)
1629 VOID CDECL MSVCP__crtFlushProcessWriteBuffers(void)
1631 return FlushProcessWriteBuffers();
1634 /*********************************************************************
1635 * __crtCreateSemaphoreExW (MSVCP140.@)
1637 HANDLE CDECL MSVCP__crtCreateSemaphoreExW(
1638 SECURITY_ATTRIBUTES *attribs, LONG initial_count, LONG max_count, LPCWSTR name,
1639 DWORD flags, DWORD access)
1641 TRACE("(%p %d %d %s 0x%08x 0x%08x)\n", attribs, initial_count, max_count, debugstr_w(name),
1642 flags, access);
1643 return CreateSemaphoreExW(attribs, initial_count, max_count, name, flags, access);
1646 /*********************************************************************
1647 * __crtCreateThreadpoolTimer (MSVCP140.@)
1649 PTP_TIMER CDECL MSVCP__crtCreateThreadpoolTimer(PTP_TIMER_CALLBACK callback,
1650 PVOID userdata, TP_CALLBACK_ENVIRON *environment)
1652 TRACE("(%p %p %p)\n", callback, userdata, environment);
1653 return CreateThreadpoolTimer(callback, userdata, environment);
1656 /*********************************************************************
1657 * __crtCloseThreadpoolTimer (MSVCP140.@)
1659 VOID CDECL MSVCP__crtCloseThreadpoolTimer(TP_TIMER *timer)
1661 TRACE("(%p)\n", timer);
1662 CloseThreadpoolTimer(timer);
1665 /*********************************************************************
1666 * __crtSetThreadpoolTimer (MSVCP140.@)
1668 VOID CDECL MSVCP__crtSetThreadpoolTimer(TP_TIMER *timer,
1669 FILETIME *due_time, DWORD period, DWORD window_length)
1671 TRACE("(%p %p 0x%08x 0x%08x)\n", timer, due_time, period, window_length);
1672 return SetThreadpoolTimer(timer, due_time, period, window_length);
1675 /*********************************************************************
1676 * __crtWaitForThreadpoolTimerCallbacks (MSVCP140.@)
1678 VOID CDECL MSVCP__crtWaitForThreadpoolTimerCallbacks(TP_TIMER *timer, BOOL cancel)
1680 TRACE("(%p %d)\n", timer, cancel);
1681 WaitForThreadpoolTimerCallbacks(timer, cancel);
1684 /*********************************************************************
1685 * __crtCreateThreadpoolWait (MSVCP140.@)
1687 PTP_WAIT CDECL MSVCP__crtCreateThreadpoolWait(PTP_WAIT_CALLBACK callback,
1688 PVOID userdata, TP_CALLBACK_ENVIRON *environment)
1690 TRACE("(%p %p %p)\n", callback, userdata, environment);
1691 return CreateThreadpoolWait(callback, userdata, environment);
1694 /*********************************************************************
1695 * __crtCloseThreadpoolWait (MSVCP140.@)
1697 VOID CDECL MSVCP__crtCloseThreadpoolWait(TP_WAIT *wait)
1699 TRACE("(%p)\n", wait);
1700 CloseThreadpoolWait(wait);
1703 /*********************************************************************
1704 * __crtSetThreadpoolWait (MSVCP140.@)
1706 VOID CDECL MSVCP__crtSetThreadpoolWait(TP_WAIT *wait, HANDLE handle, FILETIME *due_time)
1708 TRACE("(%p %p %p)\n", wait, handle, due_time);
1709 return SetThreadpoolWait(wait, handle, due_time);
1712 /*********************************************************************
1713 * __crtFreeLibraryWhenCallbackReturns (MSVCP140.@)
1715 VOID CDECL MSVCP__crtFreeLibraryWhenCallbackReturns(PTP_CALLBACK_INSTANCE instance, HMODULE mod)
1717 TRACE("(%p %p)\n", instance, mod);
1718 FreeLibraryWhenCallbackReturns(instance, mod);
1721 /* ?_Execute_once@std@@YAHAAUonce_flag@1@P6GHPAX1PAPAX@Z1@Z */
1722 /* ?_Execute_once@std@@YAHAEAUonce_flag@1@P6AHPEAX1PEAPEAX@Z1@Z */
1723 BOOL __cdecl _Execute_once(INIT_ONCE *flag, PINIT_ONCE_FN func, void *param)
1725 return InitOnceExecuteOnce(flag, func, param, NULL);
1728 #if _MSVCP_VER >= 100
1729 void init_misc(void *base)
1731 #ifdef __x86_64__
1732 #if _MSVCP_VER == 100
1733 init_error_category_rtti(base);
1734 init_iostream_category_rtti(base);
1735 init_system_category_rtti(base);
1736 init_generic_category_rtti(base);
1737 #endif
1738 #if _MSVCP_VER >= 100
1739 init__Concurrent_queue_base_v4_rtti(base);
1740 #endif
1741 #if _MSVCP_VER >= 110
1742 init__Pad_rtti(base);
1743 #endif
1744 #endif
1746 #if _MSVCP_VER == 100
1747 iostream_category_ctor(&iostream_category);
1748 system_category_ctor(&system_category);
1749 generic_category_ctor(&generic_category);
1750 #endif
1753 void free_misc(void)
1755 #if _MSVCP_VER >= 110
1756 if(keyed_event)
1757 NtClose(keyed_event);
1758 HeapFree(GetProcessHeap(), 0, broadcast_at_thread_exit.to_broadcast);
1759 #endif
1761 #endif
1763 #if _MSVCP_VER >= 140
1764 LONGLONG __cdecl _Query_perf_counter(void)
1766 LARGE_INTEGER li;
1767 QueryPerformanceCounter(&li);
1768 return li.QuadPart;
1771 LONGLONG __cdecl _Query_perf_frequency(void)
1773 LARGE_INTEGER li;
1774 QueryPerformanceFrequency(&li);
1775 return li.QuadPart;
1777 #endif
1779 void __cdecl threads__Mtx_new(void **mtx)
1781 *mtx = MSVCRT_operator_new(sizeof(CRITICAL_SECTION));
1782 InitializeCriticalSection(*mtx);
1785 void __cdecl threads__Mtx_delete(void *mtx)
1787 DeleteCriticalSection(mtx);
1790 void __cdecl threads__Mtx_lock(void *mtx)
1792 EnterCriticalSection(mtx);
1795 void __cdecl threads__Mtx_unlock(void *mtx)
1797 LeaveCriticalSection(mtx);
1800 #if _MSVCP_VER >= 110
1801 static LONG shared_ptr_lock;
1803 void __cdecl _Lock_shared_ptr_spin_lock(void)
1805 LONG l = 0;
1807 while(InterlockedCompareExchange(&shared_ptr_lock, 1, 0) != 0) {
1808 if(l++ == 1000) {
1809 Sleep(0);
1810 l = 0;
1815 void __cdecl _Unlock_shared_ptr_spin_lock(void)
1817 shared_ptr_lock = 0;
1819 #endif
1821 #if _MSVCP_VER >= 100
1822 /* ?is_current_task_group_canceling@Concurrency@@YA_NXZ */
1823 MSVCP_bool __cdecl is_current_task_group_canceling(void)
1825 return Context_IsCurrentTaskCollectionCanceling();
1827 #endif
1829 #if _MSVCP_VER >= 140
1830 typedef struct {
1831 void *unk0;
1832 BYTE unk1;
1833 } task_continuation_context;
1835 /* ??0task_continuation_context@Concurrency@@AAE@XZ */
1836 /* ??0task_continuation_context@Concurrency@@AEAA@XZ */
1837 DEFINE_THISCALL_WRAPPER(task_continuation_context_ctor, 4)
1838 task_continuation_context* __thiscall task_continuation_context_ctor(task_continuation_context *this)
1840 TRACE("(%p)\n", this);
1841 memset(this, 0, sizeof(*this));
1842 return this;
1845 typedef struct {
1846 const vtable_ptr *vtable;
1847 void (__cdecl *func)(void);
1848 int unk[4];
1849 void *unk2[3];
1850 void *this;
1851 } function_void_cdecl_void;
1853 /* ?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z */
1854 /* ?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z */
1855 DEFINE_THISCALL_WRAPPER(_ContextCallback__Assign, 8)
1856 void __thiscall _ContextCallback__Assign(void *this, void *v)
1858 TRACE("(%p %p)\n", this, v);
1861 #define call_function_do_call(this) CALL_VTBL_FUNC(this, 8, void, (function_void_cdecl_void*), (this))
1862 #define call_function_do_clean(this,b) CALL_VTBL_FUNC(this, 16, void, (function_void_cdecl_void*,MSVCP_bool), (this, b))
1863 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z */
1864 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z */
1865 DEFINE_THISCALL_WRAPPER(_ContextCallback__CallInContext, 48)
1866 void __thiscall _ContextCallback__CallInContext(const void *this, function_void_cdecl_void func, MSVCP_bool b)
1868 TRACE("(%p %p %x)\n", this, func.func, b);
1869 call_function_do_call(func.this);
1870 call_function_do_clean(func.this, func.this!=&func);
1873 /* ?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ */
1874 /* ?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ */
1875 DEFINE_THISCALL_WRAPPER(_ContextCallback__Capture, 4)
1876 void __thiscall _ContextCallback__Capture(void *this)
1878 TRACE("(%p)\n", this);
1881 /* ?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ */
1882 /* ?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ */
1883 DEFINE_THISCALL_WRAPPER(_ContextCallback__Reset, 4)
1884 void __thiscall _ContextCallback__Reset(void *this)
1886 TRACE("(%p)\n", this);
1889 /* ?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ */
1890 MSVCP_bool __cdecl _ContextCallback__IsCurrentOriginSTA(void *this)
1892 TRACE("(%p)\n", this);
1893 return FALSE;
1896 typedef struct {
1897 /*_Task_impl_base*/void *task;
1898 MSVCP_bool scheduled;
1899 MSVCP_bool started;
1900 } _TaskEventLogger;
1902 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1903 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1904 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogCancelTask, 4)
1905 void __thiscall _TaskEventLogger__LogCancelTask(_TaskEventLogger *this)
1907 TRACE("(%p)\n", this);
1910 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z */
1911 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z */
1912 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogScheduleTask, 8)
1913 void __thiscall _TaskEventLogger__LogScheduleTask(_TaskEventLogger *this, MSVCP_bool continuation)
1915 TRACE("(%p %x)\n", this, continuation);
1918 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1919 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1920 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskCompleted, 4)
1921 void __thiscall _TaskEventLogger__LogTaskCompleted(_TaskEventLogger *this)
1923 TRACE("(%p)\n", this);
1926 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1927 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1928 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskExecutionCompleted, 4)
1929 void __thiscall _TaskEventLogger__LogTaskExecutionCompleted(_TaskEventLogger *this)
1931 TRACE("(%p)\n", this);
1934 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1935 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1936 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemCompleted, 4)
1937 void __thiscall _TaskEventLogger__LogWorkItemCompleted(_TaskEventLogger *this)
1939 TRACE("(%p)\n", this);
1942 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
1943 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
1944 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemStarted, 4)
1945 void __thiscall _TaskEventLogger__LogWorkItemStarted(_TaskEventLogger *this)
1947 TRACE("(%p)\n", this);
1950 typedef struct {
1951 PTP_WORK work;
1952 void (__cdecl *callback)(void*);
1953 void *arg;
1954 } _Threadpool_chore;
1956 /* ?_Reschedule_chore@details@Concurrency@@YAHPBU_Threadpool_chore@12@@Z */
1957 /* ?_Reschedule_chore@details@Concurrency@@YAHPEBU_Threadpool_chore@12@@Z */
1958 int __cdecl _Reschedule_chore(const _Threadpool_chore *chore)
1960 TRACE("(%p)\n", chore);
1962 SubmitThreadpoolWork(chore->work);
1963 return 0;
1966 static void WINAPI threadpool_callback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work)
1968 _Threadpool_chore *chore = context;
1969 TRACE("calling chore callback: %p\n", chore);
1970 if (chore->callback)
1971 chore->callback(chore->arg);
1974 /* ?_Schedule_chore@details@Concurrency@@YAHPAU_Threadpool_chore@12@@Z */
1975 /* ?_Schedule_chore@details@Concurrency@@YAHPEAU_Threadpool_chore@12@@Z */
1976 int __cdecl _Schedule_chore(_Threadpool_chore *chore)
1978 TRACE("(%p)\n", chore);
1980 chore->work = CreateThreadpoolWork(threadpool_callback, chore, NULL);
1981 /* FIXME: what should be returned in case of error */
1982 if(!chore->work)
1983 return -1;
1985 return _Reschedule_chore(chore);
1988 /* ?_Release_chore@details@Concurrency@@YAXPAU_Threadpool_chore@12@@Z */
1989 /* ?_Release_chore@details@Concurrency@@YAXPEAU_Threadpool_chore@12@@Z */
1990 void __cdecl _Release_chore(_Threadpool_chore *chore)
1992 TRACE("(%p)\n", chore);
1994 if(!chore->work) return;
1995 CloseThreadpoolWork(chore->work);
1996 chore->work = NULL;
1998 #endif
2000 #if _MSVCP_VER >= 110 && _MSVCP_VER <= 120
2001 typedef struct {
2002 char dummy;
2003 } _Ph;
2005 /* ?_1@placeholders@std@@3V?$_Ph@$00@2@A */
2006 /* ?_20@placeholders@std@@3V?$_Ph@$0BE@@2@A */
2007 _Ph _Ph_1 = {0}, _Ph_2 = {0}, _Ph_3 = {0}, _Ph_4 = {0}, _Ph_5 = {0};
2008 _Ph _Ph_6 = {0}, _Ph_7 = {0}, _Ph_8 = {0}, _Ph_9 = {0}, _Ph_10 = {0};
2009 _Ph _Ph_11 = {0}, _Ph_12 = {0}, _Ph_13 = {0}, _Ph_14 = {0}, _Ph_15 = {0};
2010 _Ph _Ph_16 = {0}, _Ph_17 = {0}, _Ph_18 = {0}, _Ph_19 = {0}, _Ph_20 = {0};
2011 #endif
2013 #if _MSVCP_VER >= 100
2014 /* based on wined3d_log2i from wined3d.h */
2015 /* Return the integer base-2 logarithm of (x|1). Result is 0 for x == 0. */
2016 static inline unsigned int log2i(unsigned int x)
2018 #ifdef HAVE___BUILTIN_CLZ
2019 return __builtin_clz(x|1) ^ 0x1f;
2020 #else
2021 static const unsigned int l[] =
2023 ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
2024 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2025 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2026 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2027 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2028 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2029 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2030 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2031 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2032 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2033 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2034 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2035 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2036 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2037 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2038 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2040 unsigned int i;
2042 x |= 1;
2043 return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
2044 #endif
2047 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KAII@Z */
2048 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KA_K_K@Z */
2049 MSVCP_size_t __cdecl _vector_base_v4__Segment_index_of(MSVCP_size_t x)
2051 unsigned int half;
2053 TRACE("(%lu)\n", x);
2055 if((sizeof(x) == 8) && (half = x >> 32))
2056 return log2i(half) + 32;
2058 return log2i(x);
2061 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IBEXI@Z */
2062 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IEBAX_K@Z */
2063 DEFINE_THISCALL_WRAPPER(_vector_base_v4__Internal_throw_exception, 8)
2064 void __thiscall _vector_base_v4__Internal_throw_exception(void/*_vector_base_v4*/ *this, MSVCP_size_t idx)
2066 static const struct {
2067 exception_type type;
2068 const char *msg;
2069 } exceptions[] = {
2070 { EXCEPTION_OUT_OF_RANGE, "Index out of range" },
2071 { EXCEPTION_OUT_OF_RANGE, "Index out of segments table range" },
2072 { EXCEPTION_RANGE_ERROR, "Index is inside segment which failed to be allocated" },
2075 TRACE("(%p %lu)\n", this, idx);
2077 if(idx < sizeof(exceptions)/sizeof(exceptions[0]))
2078 throw_exception(exceptions[idx].type, exceptions[idx].msg);
2080 #endif