d3d8: Do not specify WINED3D_TEXTURE_CREATE_MAPPABLE in d3d8_device_CreateDepthStenci...
[wine.git] / dlls / msvcp90 / misc.c
blobaa29fb98ba451bcfc15f479275d656166dd0ed12
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>
23 #include <errno.h>
25 #include "msvcp90.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winternl.h"
30 #include "wine/debug.h"
31 #include "wine/exception.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
34 #if _MSVCP_VER >= 110
35 /* error strings generated with glibc strerror */
36 static const char str_EPERM[] = "operation not permitted";
37 static const char str_ENOENT[] = "no such file or directory";
38 static const char str_ESRCH[] = "no such process";
39 static const char str_EINTR[] = "interrupted system call";
40 static const char str_EIO[] = "input/output error";
41 static const char str_ENXIO[] = "no such device or address";
42 static const char str_E2BIG[] = "argument list too long";
43 static const char str_ENOEXEC[] = "exec format error";
44 static const char str_EBADF[] = "bad file descriptor";
45 static const char str_ECHILD[] = "no child processes";
46 static const char str_EAGAIN[] = "resource temporarily unavailable";
47 static const char str_ENOMEM[] = "cannot allocate memory";
48 static const char str_EACCES[] = "permission denied";
49 static const char str_EFAULT[] = "bad address";
50 static const char str_EBUSY[] = "device or resource busy";
51 static const char str_EEXIST[] = "file exists";
52 static const char str_EXDEV[] = "invalid cross-device link";
53 static const char str_ENODEV[] = "no such device";
54 static const char str_ENOTDIR[] = "not a directory";
55 static const char str_EISDIR[] = "is a directory";
56 static const char str_EINVAL[] = "invalid argument";
57 static const char str_ENFILE[] = "too many open files in system";
58 static const char str_EMFILE[] = "too many open files";
59 static const char str_ENOTTY[] = "inappropriate ioctl for device";
60 static const char str_EFBIG[] = "file too large";
61 static const char str_ENOSPC[] = "no space left on device";
62 static const char str_ESPIPE[] = "illegal seek";
63 static const char str_EROFS[] = "read-only file system";
64 static const char str_EMLINK[] = "too many links";
65 static const char str_EPIPE[] = "broken pipe";
66 static const char str_EDOM[] = "numerical argument out of domain";
67 static const char str_ERANGE[] = "numerical result out of range";
68 static const char str_EDEADLK[] = "resource deadlock avoided";
69 static const char str_ENAMETOOLONG[] = "file name too long";
70 static const char str_ENOLCK[] = "no locks available";
71 static const char str_ENOSYS[] = "function not implemented";
72 static const char str_ENOTEMPTY[] = "directory not empty";
73 static const char str_EILSEQ[] = "invalid or incomplete multibyte or wide character";
74 static const char str_EADDRINUSE[] = "address already in use";
75 static const char str_EADDRNOTAVAIL[] = "cannot assign requested address";
76 static const char str_EAFNOSUPPORT[] = "address family not supported by protocol";
77 static const char str_EALREADY[] = "operation already in progress";
78 static const char str_EBADMSG[] = "not a data message";
79 static const char str_ECANCELED[] = "operation Canceled";
80 static const char str_ECONNABORTED[] = "software caused connection abort";
81 static const char str_ECONNREFUSED[] = "connection refused";
82 static const char str_ECONNRESET[] = "connection reset by peer";
83 static const char str_EDESTADDRREQ[] = "destination address required";
84 static const char str_EHOSTUNREACH[] = "no route to host";
85 static const char str_EIDRM[] = "identifier removed";
86 static const char str_EINPROGRESS[] = "operation now in progress";
87 static const char str_EISCONN[] = "transport endpoint is already connected";
88 static const char str_ELOOP[] = "too many symbolic links encountered";
89 static const char str_EMSGSIZE[] = "message too long";
90 static const char str_ENETDOWN[] = "network is down";
91 static const char str_ENETRESET[] = "network dropped connection because of reset";
92 static const char str_ENETUNREACH[] = "network is unreachable";
93 static const char str_ENOBUFS[] = "no buffer space available";
94 static const char str_ENODATA[] = "no data available";
95 static const char str_ENOLINK[] = "link has been severed";
96 static const char str_ENOMSG[] = "no message of desired type";
97 static const char str_ENOPROTOOPT[] = "protocol not available";
98 static const char str_ENOSR[] = "out of streams resources";
99 static const char str_ENOSTR[] = "device not a stream";
100 static const char str_ENOTCONN[] = "transport endpoint is not connected";
101 static const char str_ENOTRECOVERABLE[] = "state not recoverable";
102 static const char str_ENOTSOCK[] = "socket operation on non-socket";
103 static const char str_ENOTSUP[] = "not supported";
104 static const char str_EOPNOTSUPP[] = "operation not supported on transport endpoint";
105 static const char str_EOVERFLOW[] = "value too large for defined data type";
106 static const char str_EOWNERDEAD[] = "owner died";
107 static const char str_EPROTO[] = "protocol error";
108 static const char str_EPROTONOSUPPORT[] = "protocol not supported";
109 static const char str_EPROTOTYPE[] = "protocol wrong type for socket";
110 static const char str_ETIME[] = "timer expired";
111 static const char str_ETIMEDOUT[] = "connection timed out";
112 static const char str_ETXTBSY[] = "text file busy";
113 static const char str_EWOULDBLOCK[] = "operation would block";
115 static struct {
116 int err;
117 const char *str;
118 } syserror_map[] =
120 {EPERM, str_EPERM},
121 {ENOENT, str_ENOENT},
122 {ESRCH, str_ESRCH},
123 {EINTR, str_EINTR},
124 {EIO, str_EIO},
125 {ENXIO, str_ENXIO},
126 {E2BIG, str_E2BIG},
127 {ENOEXEC, str_ENOEXEC},
128 {EBADF, str_EBADF},
129 {ECHILD, str_ECHILD},
130 {EAGAIN, str_EAGAIN},
131 {ENOMEM, str_ENOMEM},
132 {EACCES, str_EACCES},
133 {EFAULT, str_EFAULT},
134 {EBUSY, str_EBUSY},
135 {EEXIST, str_EEXIST},
136 {EXDEV, str_EXDEV},
137 {ENODEV, str_ENODEV},
138 {ENOTDIR, str_ENOTDIR},
139 {EISDIR, str_EISDIR},
140 {EINVAL, str_EINVAL},
141 {ENFILE, str_ENFILE},
142 {EMFILE, str_EMFILE},
143 {ENOTTY, str_ENOTTY},
144 {EFBIG, str_EFBIG},
145 {ENOSPC, str_ENOSPC},
146 {ESPIPE, str_ESPIPE},
147 {EROFS, str_EROFS},
148 {EMLINK, str_EMLINK},
149 {EPIPE, str_EPIPE},
150 {EDOM, str_EDOM},
151 {ERANGE, str_ERANGE},
152 {EDEADLK, str_EDEADLK},
153 {ENAMETOOLONG, str_ENAMETOOLONG},
154 {ENOLCK, str_ENOLCK},
155 {ENOSYS, str_ENOSYS},
156 {ENOTEMPTY, str_ENOTEMPTY},
157 {EILSEQ, str_EILSEQ},
158 {EADDRINUSE, str_EADDRINUSE},
159 {EADDRNOTAVAIL, str_EADDRNOTAVAIL},
160 {EAFNOSUPPORT, str_EAFNOSUPPORT},
161 {EALREADY, str_EALREADY},
162 {EBADMSG, str_EBADMSG},
163 {ECANCELED, str_ECANCELED},
164 {ECONNABORTED, str_ECONNABORTED},
165 {ECONNREFUSED, str_ECONNREFUSED},
166 {ECONNRESET, str_ECONNRESET},
167 {EDESTADDRREQ, str_EDESTADDRREQ},
168 {EHOSTUNREACH, str_EHOSTUNREACH},
169 {EIDRM, str_EIDRM},
170 {EINPROGRESS, str_EINPROGRESS},
171 {EISCONN, str_EISCONN},
172 {ELOOP, str_ELOOP},
173 {EMSGSIZE, str_EMSGSIZE},
174 {ENETDOWN, str_ENETDOWN},
175 {ENETRESET, str_ENETRESET},
176 {ENETUNREACH, str_ENETUNREACH},
177 {ENOBUFS, str_ENOBUFS},
178 {ENODATA, str_ENODATA},
179 {ENOLINK, str_ENOLINK},
180 {ENOMSG, str_ENOMSG},
181 {ENOPROTOOPT, str_ENOPROTOOPT},
182 {ENOSR, str_ENOSR},
183 {ENOSTR, str_ENOSTR},
184 {ENOTCONN, str_ENOTCONN},
185 {ENOTRECOVERABLE, str_ENOTRECOVERABLE},
186 {ENOTSOCK, str_ENOTSOCK},
187 {ENOTSUP, str_ENOTSUP},
188 {EOPNOTSUPP, str_EOPNOTSUPP},
189 {EOVERFLOW, str_EOVERFLOW},
190 {EOWNERDEAD, str_EOWNERDEAD},
191 {EPROTO, str_EPROTO},
192 {EPROTONOSUPPORT, str_EPROTONOSUPPORT},
193 {EPROTOTYPE, str_EPROTOTYPE},
194 {ETIME, str_ETIME},
195 {ETIMEDOUT, str_ETIMEDOUT},
196 {ETXTBSY, str_ETXTBSY},
197 {EWOULDBLOCK, str_EWOULDBLOCK},
199 #endif
201 #if _MSVCP_VER >= 140
202 static struct {
203 int winerr;
204 int doserr;
205 } winerror_map[] =
207 {ERROR_INVALID_FUNCTION, ENOSYS}, {ERROR_FILE_NOT_FOUND, ENOENT},
208 {ERROR_PATH_NOT_FOUND, ENOENT}, {ERROR_TOO_MANY_OPEN_FILES, EMFILE},
209 {ERROR_ACCESS_DENIED, EACCES}, {ERROR_INVALID_HANDLE, EINVAL},
210 {ERROR_NOT_ENOUGH_MEMORY, ENOMEM}, {ERROR_INVALID_ACCESS, EACCES},
211 {ERROR_OUTOFMEMORY, ENOMEM}, {ERROR_INVALID_DRIVE, ENODEV},
212 {ERROR_CURRENT_DIRECTORY, EACCES}, {ERROR_NOT_SAME_DEVICE, EXDEV},
213 {ERROR_WRITE_PROTECT, EACCES}, {ERROR_BAD_UNIT, ENODEV},
214 {ERROR_NOT_READY, EAGAIN}, {ERROR_SEEK, EIO}, {ERROR_WRITE_FAULT, EIO},
215 {ERROR_READ_FAULT, EIO}, {ERROR_SHARING_VIOLATION, EACCES},
216 {ERROR_LOCK_VIOLATION, ENOLCK}, {ERROR_HANDLE_DISK_FULL, ENOSPC},
217 {ERROR_NOT_SUPPORTED, ENOTSUP}, {ERROR_DEV_NOT_EXIST, ENODEV},
218 {ERROR_FILE_EXISTS, EEXIST}, {ERROR_CANNOT_MAKE, EACCES},
219 {ERROR_INVALID_PARAMETER, EINVAL}, {ERROR_OPEN_FAILED, EIO},
220 {ERROR_BUFFER_OVERFLOW, ENAMETOOLONG}, {ERROR_DISK_FULL, ENOSPC},
221 {ERROR_INVALID_NAME, EINVAL}, {ERROR_NEGATIVE_SEEK, EINVAL},
222 {ERROR_BUSY_DRIVE, EBUSY}, {ERROR_DIR_NOT_EMPTY, ENOTEMPTY},
223 {ERROR_BUSY, EBUSY}, {ERROR_ALREADY_EXISTS, EEXIST},
224 {ERROR_LOCKED, ENOLCK}, {ERROR_DIRECTORY, EINVAL},
225 {ERROR_OPERATION_ABORTED, ECANCELED}, {ERROR_NOACCESS, EACCES},
226 {ERROR_CANTOPEN, EIO}, {ERROR_CANTREAD, EIO}, {ERROR_CANTWRITE, EIO},
227 {ERROR_RETRY, EAGAIN}, {ERROR_OPEN_FILES, EBUSY},
228 {ERROR_DEVICE_IN_USE, EBUSY}, {ERROR_REPARSE_TAG_INVALID, EINVAL},
229 {WSAEINTR, EINTR}, {WSAEBADF, EBADF}, {WSAEACCES, EACCES},
230 {WSAEFAULT, EFAULT}, {WSAEINVAL, EINVAL}, {WSAEMFILE, EMFILE},
231 {WSAEWOULDBLOCK, EWOULDBLOCK}, {WSAEINPROGRESS, EINPROGRESS},
232 {WSAEALREADY, EALREADY}, {WSAENOTSOCK, ENOTSOCK},
233 {WSAEDESTADDRREQ, EDESTADDRREQ}, {WSAEMSGSIZE, EMSGSIZE},
234 {WSAEPROTOTYPE, EPROTOTYPE}, {WSAENOPROTOOPT, ENOPROTOOPT},
235 {WSAEPROTONOSUPPORT, EPROTONOSUPPORT}, {WSAEOPNOTSUPP, EOPNOTSUPP},
236 {WSAEAFNOSUPPORT, EAFNOSUPPORT}, {WSAEADDRINUSE, EADDRINUSE},
237 {WSAEADDRNOTAVAIL, EADDRNOTAVAIL}, {WSAENETDOWN, ENETDOWN},
238 {WSAENETUNREACH, ENETUNREACH}, {WSAENETRESET, ENETRESET},
239 {WSAECONNABORTED, ECONNABORTED}, {WSAECONNRESET, ECONNRESET},
240 {WSAENOBUFS, ENOBUFS}, {WSAEISCONN, EISCONN}, {WSAENOTCONN, ENOTCONN},
241 {WSAETIMEDOUT, ETIMEDOUT}, {WSAECONNREFUSED, ECONNREFUSED},
242 {WSAENAMETOOLONG, ENAMETOOLONG}, {WSAEHOSTUNREACH, EHOSTUNREACH}
244 #endif
246 struct __Container_proxy;
248 typedef struct {
249 struct __Container_proxy *proxy;
250 } _Container_base12;
252 typedef struct __Iterator_base12 {
253 struct __Container_proxy *proxy;
254 struct __Iterator_base12 *next;
255 } _Iterator_base12;
257 typedef struct __Container_proxy {
258 const _Container_base12 *cont;
259 _Iterator_base12 *head;
260 } _Container_proxy;
262 /* ??0_Mutex@std@@QAE@XZ */
263 /* ??0_Mutex@std@@QEAA@XZ */
264 DEFINE_THISCALL_WRAPPER(mutex_ctor, 4)
265 mutex* __thiscall mutex_ctor(mutex *this)
267 CRITICAL_SECTION *cs = MSVCRT_operator_new(sizeof(*cs));
268 if(!cs) {
269 ERR("Out of memory\n");
270 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
273 InitializeCriticalSection(cs);
274 cs->DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": _Mutex critical section");
275 this->mutex = cs;
276 return this;
279 /* ??1_Mutex@std@@QAE@XZ */
280 /* ??1_Mutex@std@@QEAA@XZ */
281 DEFINE_THISCALL_WRAPPER(mutex_dtor, 4)
282 void __thiscall mutex_dtor(mutex *this)
284 ((CRITICAL_SECTION*)this->mutex)->DebugInfo->Spare[0] = 0;
285 DeleteCriticalSection(this->mutex);
286 MSVCRT_operator_delete(this->mutex);
289 /* ?_Lock@_Mutex@std@@QAEXXZ */
290 /* ?_Lock@_Mutex@std@@QEAAXXZ */
291 DEFINE_THISCALL_WRAPPER(mutex_lock, 4)
292 void __thiscall mutex_lock(mutex *this)
294 EnterCriticalSection(this->mutex);
297 /* ?_Unlock@_Mutex@std@@QAEXXZ */
298 /* ?_Unlock@_Mutex@std@@QEAAXXZ */
299 DEFINE_THISCALL_WRAPPER(mutex_unlock, 4)
300 void __thiscall mutex_unlock(mutex *this)
302 LeaveCriticalSection(this->mutex);
305 /* ?_Mutex_Lock@_Mutex@std@@CAXPAV12@@Z */
306 /* ?_Mutex_Lock@_Mutex@std@@CAXPEAV12@@Z */
307 void CDECL mutex_mutex_lock(mutex *m)
309 mutex_lock(m);
312 /* ?_Mutex_Unlock@_Mutex@std@@CAXPAV12@@Z */
313 /* ?_Mutex_Unlock@_Mutex@std@@CAXPEAV12@@Z */
314 void CDECL mutex_mutex_unlock(mutex *m)
316 mutex_unlock(m);
319 /* ?_Mutex_ctor@_Mutex@std@@CAXPAV12@@Z */
320 /* ?_Mutex_ctor@_Mutex@std@@CAXPEAV12@@Z */
321 void CDECL mutex_mutex_ctor(mutex *m)
323 mutex_ctor(m);
326 /* ?_Mutex_dtor@_Mutex@std@@CAXPAV12@@Z */
327 /* ?_Mutex_dtor@_Mutex@std@@CAXPEAV12@@Z */
328 void CDECL mutex_mutex_dtor(mutex *m)
330 mutex_dtor(m);
333 static CRITICAL_SECTION lockit_cs[_MAX_LOCK];
335 #if _MSVCP_VER >= 70
336 static inline int get_locktype( _Lockit *lockit ) { return lockit->locktype; }
337 static inline void set_locktype( _Lockit *lockit, int type ) { lockit->locktype = type; }
338 #else
339 static inline int get_locktype( _Lockit *lockit ) { return 0; }
340 static inline void set_locktype( _Lockit *lockit, int type ) { }
341 #endif
343 /* ?_Lockit_ctor@_Lockit@std@@SAXH@Z */
344 void __cdecl _Lockit_init(int locktype) {
345 InitializeCriticalSection(&lockit_cs[locktype]);
346 lockit_cs[locktype].DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": _Lockit critical section");
349 /* ?_Lockit_dtor@_Lockit@std@@SAXH@Z */
350 void __cdecl _Lockit_free(int locktype)
352 lockit_cs[locktype].DebugInfo->Spare[0] = 0;
353 DeleteCriticalSection(&lockit_cs[locktype]);
356 void init_lockit(void) {
357 int i;
359 for(i=0; i<_MAX_LOCK; i++)
360 _Lockit_init(i);
363 void free_lockit(void) {
364 int i;
366 for(i=0; i<_MAX_LOCK; i++)
367 _Lockit_free(i);
370 /* ?_Lockit_ctor@_Lockit@std@@CAXPAV12@H@Z */
371 /* ?_Lockit_ctor@_Lockit@std@@CAXPEAV12@H@Z */
372 void __cdecl _Lockit__Lockit_ctor_locktype(_Lockit *lockit, int locktype)
374 set_locktype( lockit, locktype );
375 EnterCriticalSection(&lockit_cs[locktype]);
378 /* ?_Lockit_ctor@_Lockit@std@@CAXPAV12@@Z */
379 /* ?_Lockit_ctor@_Lockit@std@@CAXPEAV12@@Z */
380 void __cdecl _Lockit__Lockit_ctor(_Lockit *lockit)
382 _Lockit__Lockit_ctor_locktype(lockit, 0);
385 /* ??0_Lockit@std@@QAE@H@Z */
386 /* ??0_Lockit@std@@QEAA@H@Z */
387 DEFINE_THISCALL_WRAPPER(_Lockit_ctor_locktype, 8)
388 _Lockit* __thiscall _Lockit_ctor_locktype(_Lockit *this, int locktype)
390 _Lockit__Lockit_ctor_locktype(this, locktype);
391 return this;
394 /* ??0_Lockit@std@@QAE@XZ */
395 /* ??0_Lockit@std@@QEAA@XZ */
396 DEFINE_THISCALL_WRAPPER(_Lockit_ctor, 4)
397 _Lockit* __thiscall _Lockit_ctor(_Lockit *this)
399 _Lockit__Lockit_ctor_locktype(this, 0);
400 return this;
403 /* ?_Lockit_dtor@_Lockit@std@@CAXPAV12@@Z */
404 /* ?_Lockit_dtor@_Lockit@std@@CAXPEAV12@@Z */
405 void __cdecl _Lockit__Lockit_dtor(_Lockit *lockit)
407 LeaveCriticalSection(&lockit_cs[get_locktype( lockit )]);
410 /* ??1_Lockit@std@@QAE@XZ */
411 /* ??1_Lockit@std@@QEAA@XZ */
412 DEFINE_THISCALL_WRAPPER(_Lockit_dtor, 4)
413 void __thiscall _Lockit_dtor(_Lockit *this)
415 _Lockit__Lockit_dtor(this);
418 /* wctype */
419 unsigned short __cdecl wctype(const char *property)
421 static const struct {
422 const char *name;
423 unsigned short mask;
424 } properties[] = {
425 { "alnum", _DIGIT|_ALPHA },
426 { "alpha", _ALPHA },
427 { "cntrl", _CONTROL },
428 { "digit", _DIGIT },
429 { "graph", _DIGIT|_PUNCT|_ALPHA },
430 { "lower", _LOWER },
431 { "print", _DIGIT|_PUNCT|_BLANK|_ALPHA },
432 { "punct", _PUNCT },
433 { "space", _SPACE },
434 { "upper", _UPPER },
435 { "xdigit", _HEX }
437 unsigned int i;
439 for(i = 0; i < ARRAY_SIZE(properties); i++)
440 if(!strcmp(property, properties[i].name))
441 return properties[i].mask;
443 return 0;
446 typedef void (__cdecl *MSVCP_new_handler_func)(void);
447 static MSVCP_new_handler_func MSVCP_new_handler;
448 static int __cdecl new_handler_wrapper(MSVCP_size_t unused)
450 MSVCP_new_handler();
451 return 1;
454 /* ?set_new_handler@std@@YAP6AXXZP6AXXZ@Z */
455 MSVCP_new_handler_func __cdecl set_new_handler(MSVCP_new_handler_func new_handler)
457 MSVCP_new_handler_func old_handler = MSVCP_new_handler;
459 TRACE("%p\n", new_handler);
461 MSVCP_new_handler = new_handler;
462 MSVCRT_set_new_handler(new_handler ? new_handler_wrapper : NULL);
463 return old_handler;
466 /* ?set_new_handler@std@@YAP6AXXZH@Z */
467 MSVCP_new_handler_func __cdecl set_new_handler_reset(int unused)
469 return set_new_handler(NULL);
472 /* _Container_base0 is used by apps compiled without iterator checking
473 * (i.e. with _ITERATOR_DEBUG_LEVEL=0 ).
474 * It provides empty versions of methods used by visual c++'s stl's
475 * iterator checking.
476 * msvcr100 has to provide them in case apps are compiled with /Od
477 * or the optimizer fails to inline those (empty) calls.
480 /* ?_Orphan_all@_Container_base0@std@@QAEXXZ */
481 /* ?_Orphan_all@_Container_base0@std@@QEAAXXZ */
482 DEFINE_THISCALL_WRAPPER(Container_base0_Orphan_all, 4)
483 void __thiscall Container_base0_Orphan_all(void *this)
487 /* ?_Swap_all@_Container_base0@std@@QAEXAAU12@@Z */
488 /* ?_Swap_all@_Container_base0@std@@QEAAXAEAU12@@Z */
489 DEFINE_THISCALL_WRAPPER(Container_base0_Swap_all, 8)
490 void __thiscall Container_base0_Swap_all(void *this, void *that)
494 /* ??4_Container_base0@std@@QAEAAU01@ABU01@@Z */
495 /* ??4_Container_base0@std@@QEAAAEAU01@AEBU01@@Z */
496 DEFINE_THISCALL_WRAPPER(Container_base0_op_assign, 8)
497 void* __thiscall Container_base0_op_assign(void *this, const void *that)
499 return this;
502 /* ??0_Container_base12@std@@QAE@ABU01@@Z */
503 /* ??0_Container_base12@std@@QEAA@AEBU01@@Z */
504 DEFINE_THISCALL_WRAPPER(_Container_base12_copy_ctor, 8)
505 _Container_base12* __thiscall _Container_base12_copy_ctor(
506 _Container_base12 *this, _Container_base12 *that)
508 this->proxy = NULL;
509 return this;
512 /* ??0_Container_base12@std@@QAE@XZ */
513 /* ??0_Container_base12@std@@QEAA@XZ */
514 DEFINE_THISCALL_WRAPPER(_Container_base12_ctor, 4)
515 _Container_base12* __thiscall _Container_base12_ctor(_Container_base12 *this)
517 this->proxy = NULL;
518 return this;
521 /* ??1_Container_base12@std@@QAE@XZ */
522 /* ??1_Container_base12@std@@QEAA@XZ */
523 DEFINE_THISCALL_WRAPPER(_Container_base12_dtor, 4)
524 void __thiscall _Container_base12_dtor(_Container_base12 *this)
528 /* ??4_Container_base12@std@@QAEAAU01@ABU01@@Z */
529 /* ??4_Container_base12@std@@QEAAAEAU01@AEBU01@@ */
530 DEFINE_THISCALL_WRAPPER(_Container_base12_op_assign, 8)
531 _Container_base12* __thiscall _Container_base12_op_assign(
532 _Container_base12 *this, const _Container_base12 *that)
534 return this;
537 /* ?_Getpfirst@_Container_base12@std@@QBEPAPAU_Iterator_base12@2@XZ */
538 /* ?_Getpfirst@_Container_base12@std@@QEBAPEAPEAU_Iterator_base12@2@XZ */
539 DEFINE_THISCALL_WRAPPER(_Container_base12__Getpfirst, 4)
540 _Iterator_base12** __thiscall _Container_base12__Getpfirst(_Container_base12 *this)
542 return this->proxy ? &this->proxy->head : NULL;
545 /* ?_Orphan_all@_Container_base12@std@@QAEXXZ */
546 /* ?_Orphan_all@_Container_base12@std@@QEAAXXZ */
547 DEFINE_THISCALL_WRAPPER(_Container_base12__Orphan_all, 4)
548 void __thiscall _Container_base12__Orphan_all(_Container_base12 *this)
552 /* ?_Swap_all@_Container_base12@std@@QAEXAAU12@@Z */
553 /* ?_Swap_all@_Container_base12@std@@QEAAXAEAU12@@Z */
554 DEFINE_THISCALL_WRAPPER(_Container_base12__Swap_all, 8)
555 void __thiscall _Container_base12__Swap_all(
556 _Container_base12 *this, _Container_base12 *that)
558 _Container_proxy *tmp;
560 tmp = this->proxy;
561 this->proxy = that->proxy;
562 that->proxy = tmp;
564 if(this->proxy)
565 this->proxy->cont = this;
566 if(that->proxy)
567 that->proxy->cont = that;
570 #if _MSVCP_VER >= 110
572 #define SECSPERDAY 86400
573 /* 1601 to 1970 is 369 years plus 89 leap days */
574 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
575 #define TICKSPERSEC 10000000
576 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
577 #define NANOSEC_PER_MILLISEC 1000000
578 #define MILLISEC_PER_SEC 1000
579 #define NANOSEC_PER_SEC (NANOSEC_PER_MILLISEC * MILLISEC_PER_SEC)
581 typedef int MSVCRT_long;
583 /* xtime */
584 typedef struct {
585 __time64_t sec;
586 MSVCRT_long nsec;
587 } xtime;
589 /* _Xtime_get_ticks */
590 LONGLONG __cdecl _Xtime_get_ticks(void)
592 FILETIME ft;
594 TRACE("\n");
596 GetSystemTimeAsFileTime(&ft);
597 return ((LONGLONG)ft.dwHighDateTime<<32) + ft.dwLowDateTime - TICKS_1601_TO_1970;
600 /* _xtime_get */
601 int __cdecl xtime_get(xtime* t, int unknown)
603 LONGLONG ticks;
605 TRACE("(%p)\n", t);
607 if(unknown != 1)
608 return 0;
610 ticks = _Xtime_get_ticks();
611 t->sec = ticks / TICKSPERSEC;
612 t->nsec = ticks % TICKSPERSEC * 100;
613 return 1;
616 /* _Xtime_diff_to_millis2 */
617 MSVCRT_long __cdecl _Xtime_diff_to_millis2(const xtime *t1, const xtime *t2)
619 LONGLONG diff_sec, diff_nsec;
621 TRACE("(%p, %p)\n", t1, t2);
623 diff_sec = t1->sec - t2->sec;
624 diff_nsec = t1->nsec - t2->nsec;
626 diff_sec += diff_nsec / NANOSEC_PER_SEC;
627 diff_nsec %= NANOSEC_PER_SEC;
628 if (diff_nsec < 0) {
629 diff_sec -= 1;
630 diff_nsec += NANOSEC_PER_SEC;
633 if (diff_sec<0 || (diff_sec==0 && diff_nsec<0))
634 return 0;
635 return diff_sec * MILLISEC_PER_SEC +
636 (diff_nsec + NANOSEC_PER_MILLISEC - 1) / NANOSEC_PER_MILLISEC;
639 /* _Xtime_diff_to_millis */
640 MSVCRT_long __cdecl _Xtime_diff_to_millis(const xtime *t)
642 xtime now;
644 TRACE("%p\n", t);
646 xtime_get(&now, 1);
647 return _Xtime_diff_to_millis2(t, &now);
649 #endif
651 #if _MSVCP_VER >= 90
652 unsigned int __cdecl _Random_device(void)
654 unsigned int ret;
656 TRACE("\n");
658 /* TODO: throw correct exception in case of failure */
659 if(rand_s(&ret))
660 throw_exception(EXCEPTION, "random number generator failed\n");
661 return ret;
663 #endif
665 #if _MSVCP_VER >= 110
666 #if defined(__i386__)
668 extern void *call_thiscall_func;
669 __ASM_GLOBAL_FUNC(call_thiscall_func,
670 "popl %eax\n\t"
671 "popl %edx\n\t"
672 "popl %ecx\n\t"
673 "pushl %eax\n\t"
674 "jmp *%edx\n\t")
676 #define call_func1(func,this) ((void* (WINAPI*)(void*,void*))&call_thiscall_func)(func,this)
678 #else /* __i386__ */
680 #define call_func1(func,this) func(this)
682 #endif /* __i386__ */
684 #define MTX_MULTI_LOCK 0x100
685 #define MTX_LOCKED 3
686 typedef struct
688 DWORD flags;
689 critical_section cs;
690 DWORD thread_id;
691 DWORD count;
692 } *_Mtx_t;
694 #if _MSVCP_VER >= 140
695 typedef _Mtx_t _Mtx_arg_t;
696 #define MTX_T_FROM_ARG(m) (m)
697 #define MTX_T_TO_ARG(m) (m)
698 #else
699 typedef _Mtx_t *_Mtx_arg_t;
700 #define MTX_T_FROM_ARG(m) (*(m))
701 #define MTX_T_TO_ARG(m) (&(m))
702 #endif
704 void __cdecl _Mtx_init_in_situ(_Mtx_t mtx, int flags)
706 if(flags & ~MTX_MULTI_LOCK)
707 FIXME("unknown flags ignored: %x\n", flags);
709 mtx->flags = flags;
710 call_func1(critical_section_ctor, &mtx->cs);
711 mtx->thread_id = -1;
712 mtx->count = 0;
715 int __cdecl _Mtx_init(_Mtx_t *mtx, int flags)
717 *mtx = MSVCRT_operator_new(sizeof(**mtx));
718 _Mtx_init_in_situ(*mtx, flags);
719 return 0;
722 void __cdecl _Mtx_destroy_in_situ(_Mtx_t mtx)
724 call_func1(critical_section_dtor, &mtx->cs);
727 void __cdecl _Mtx_destroy(_Mtx_arg_t mtx)
729 call_func1(critical_section_dtor, &MTX_T_FROM_ARG(mtx)->cs);
730 MSVCRT_operator_delete(MTX_T_FROM_ARG(mtx));
733 int __cdecl _Mtx_current_owns(_Mtx_arg_t mtx)
735 return MTX_T_FROM_ARG(mtx)->thread_id == GetCurrentThreadId();
738 int __cdecl _Mtx_lock(_Mtx_arg_t mtx)
740 if(MTX_T_FROM_ARG(mtx)->thread_id != GetCurrentThreadId()) {
741 call_func1(critical_section_lock, &MTX_T_FROM_ARG(mtx)->cs);
742 MTX_T_FROM_ARG(mtx)->thread_id = GetCurrentThreadId();
743 }else if(!(MTX_T_FROM_ARG(mtx)->flags & MTX_MULTI_LOCK)) {
744 return MTX_LOCKED;
747 MTX_T_FROM_ARG(mtx)->count++;
748 return 0;
751 int __cdecl _Mtx_unlock(_Mtx_arg_t mtx)
753 if(--MTX_T_FROM_ARG(mtx)->count)
754 return 0;
756 MTX_T_FROM_ARG(mtx)->thread_id = -1;
757 call_func1(critical_section_unlock, &MTX_T_FROM_ARG(mtx)->cs);
758 return 0;
761 int __cdecl _Mtx_trylock(_Mtx_arg_t mtx)
763 if(MTX_T_FROM_ARG(mtx)->thread_id != GetCurrentThreadId()) {
764 if(!call_func1(critical_section_trylock, &MTX_T_FROM_ARG(mtx)->cs))
765 return MTX_LOCKED;
766 MTX_T_FROM_ARG(mtx)->thread_id = GetCurrentThreadId();
767 }else if(!(MTX_T_FROM_ARG(mtx)->flags & MTX_MULTI_LOCK)) {
768 return MTX_LOCKED;
771 MTX_T_FROM_ARG(mtx)->count++;
772 return 0;
775 critical_section* __cdecl _Mtx_getconcrtcs(_Mtx_arg_t mtx)
777 return &MTX_T_FROM_ARG(mtx)->cs;
780 static inline LONG interlocked_dec_if_nonzero( LONG *dest )
782 LONG val, tmp;
783 for (val = *dest;; val = tmp)
785 if (!val || (tmp = InterlockedCompareExchange( dest, val - 1, val )) == val)
786 break;
788 return val;
791 #define CND_TIMEDOUT 2
793 typedef struct
795 CONDITION_VARIABLE cv;
796 } *_Cnd_t;
798 #if _MSVCP_VER >= 140
799 typedef _Cnd_t _Cnd_arg_t;
800 #define CND_T_FROM_ARG(c) (c)
801 #define CND_T_TO_ARG(c) (c)
802 #else
803 typedef _Cnd_t *_Cnd_arg_t;
804 #define CND_T_FROM_ARG(c) (*(c))
805 #define CND_T_TO_ARG(c) (&(c))
806 #endif
808 static HANDLE keyed_event;
810 void __cdecl _Cnd_init_in_situ(_Cnd_t cnd)
812 InitializeConditionVariable(&cnd->cv);
814 if(!keyed_event) {
815 HANDLE event;
817 NtCreateKeyedEvent(&event, GENERIC_READ|GENERIC_WRITE, NULL, 0);
818 if(InterlockedCompareExchangePointer(&keyed_event, event, NULL) != NULL)
819 NtClose(event);
823 int __cdecl _Cnd_init(_Cnd_t *cnd)
825 *cnd = MSVCRT_operator_new(sizeof(**cnd));
826 _Cnd_init_in_situ(*cnd);
827 return 0;
830 int __cdecl _Cnd_wait(_Cnd_arg_t cnd, _Mtx_arg_t mtx)
832 CONDITION_VARIABLE *cv = &CND_T_FROM_ARG(cnd)->cv;
834 InterlockedExchangeAdd( (LONG *)&cv->Ptr, 1 );
835 _Mtx_unlock(mtx);
837 NtWaitForKeyedEvent(keyed_event, &cv->Ptr, FALSE, NULL);
839 _Mtx_lock(mtx);
840 return 0;
843 int __cdecl _Cnd_timedwait(_Cnd_arg_t cnd, _Mtx_arg_t mtx, const xtime *xt)
845 CONDITION_VARIABLE *cv = &CND_T_FROM_ARG(cnd)->cv;
846 LARGE_INTEGER timeout;
847 NTSTATUS status;
849 InterlockedExchangeAdd( (LONG *)&cv->Ptr, 1 );
850 _Mtx_unlock(mtx);
852 timeout.QuadPart = (ULONGLONG)(ULONG)_Xtime_diff_to_millis(xt) * -10000;
853 status = NtWaitForKeyedEvent(keyed_event, &cv->Ptr, FALSE, &timeout);
854 if (status)
856 if (!interlocked_dec_if_nonzero( (LONG *)&cv->Ptr ))
857 status = NtWaitForKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
860 _Mtx_lock(mtx);
861 return status ? CND_TIMEDOUT : 0;
864 int __cdecl _Cnd_broadcast(_Cnd_arg_t cnd)
866 CONDITION_VARIABLE *cv = &CND_T_FROM_ARG(cnd)->cv;
867 LONG val = InterlockedExchange( (LONG *)&cv->Ptr, 0 );
868 while (val-- > 0)
869 NtReleaseKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
870 return 0;
873 int __cdecl _Cnd_signal(_Cnd_arg_t cnd)
875 CONDITION_VARIABLE *cv = &CND_T_FROM_ARG(cnd)->cv;
876 if (interlocked_dec_if_nonzero( (LONG *)&cv->Ptr ))
877 NtReleaseKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
878 return 0;
881 void __cdecl _Cnd_destroy_in_situ(_Cnd_t cnd)
883 _Cnd_broadcast(CND_T_TO_ARG(cnd));
886 void __cdecl _Cnd_destroy(_Cnd_arg_t cnd)
888 if(cnd) {
889 _Cnd_broadcast(cnd);
890 MSVCRT_operator_delete(CND_T_FROM_ARG(cnd));
894 static struct {
895 int used;
896 int size;
898 struct _to_broadcast {
899 DWORD thread_id;
900 _Cnd_arg_t cnd;
901 _Mtx_arg_t mtx;
902 int *p;
903 } *to_broadcast;
904 } broadcast_at_thread_exit;
906 static CRITICAL_SECTION broadcast_at_thread_exit_cs;
907 static CRITICAL_SECTION_DEBUG broadcast_at_thread_exit_cs_debug =
909 0, 0, &broadcast_at_thread_exit_cs,
910 { &broadcast_at_thread_exit_cs_debug.ProcessLocksList, &broadcast_at_thread_exit_cs_debug.ProcessLocksList },
911 0, 0, { (DWORD_PTR)(__FILE__ ": broadcast_at_thread_exit_cs") }
913 static CRITICAL_SECTION broadcast_at_thread_exit_cs = { &broadcast_at_thread_exit_cs_debug, -1, 0, 0, 0, 0 };
915 void __cdecl _Cnd_register_at_thread_exit(_Cnd_arg_t cnd, _Mtx_arg_t mtx, int *p)
917 struct _to_broadcast *add;
919 TRACE("(%p %p %p)\n", cnd, mtx, p);
921 EnterCriticalSection(&broadcast_at_thread_exit_cs);
922 if(!broadcast_at_thread_exit.size) {
923 broadcast_at_thread_exit.to_broadcast = HeapAlloc(GetProcessHeap(),
924 0, 8*sizeof(broadcast_at_thread_exit.to_broadcast[0]));
925 if(!broadcast_at_thread_exit.to_broadcast) {
926 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
927 return;
929 broadcast_at_thread_exit.size = 8;
930 } else if(broadcast_at_thread_exit.size == broadcast_at_thread_exit.used) {
931 add = HeapReAlloc(GetProcessHeap(), 0, broadcast_at_thread_exit.to_broadcast,
932 broadcast_at_thread_exit.size*2*sizeof(broadcast_at_thread_exit.to_broadcast[0]));
933 if(!add) {
934 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
935 return;
937 broadcast_at_thread_exit.to_broadcast = add;
938 broadcast_at_thread_exit.size *= 2;
941 add = broadcast_at_thread_exit.to_broadcast + broadcast_at_thread_exit.used++;
942 add->thread_id = GetCurrentThreadId();
943 add->cnd = cnd;
944 add->mtx = mtx;
945 add->p = p;
946 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
949 void __cdecl _Cnd_unregister_at_thread_exit(_Mtx_arg_t mtx)
951 int i;
953 TRACE("(%p)\n", mtx);
955 EnterCriticalSection(&broadcast_at_thread_exit_cs);
956 for(i=0; i<broadcast_at_thread_exit.used; i++) {
957 if(broadcast_at_thread_exit.to_broadcast[i].mtx != mtx)
958 continue;
960 memmove(broadcast_at_thread_exit.to_broadcast+i, broadcast_at_thread_exit.to_broadcast+i+1,
961 (broadcast_at_thread_exit.used-i-1)*sizeof(broadcast_at_thread_exit.to_broadcast[0]));
962 broadcast_at_thread_exit.used--;
963 i--;
965 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
968 void __cdecl _Cnd_do_broadcast_at_thread_exit(void)
970 int i, id = GetCurrentThreadId();
972 TRACE("()\n");
974 EnterCriticalSection(&broadcast_at_thread_exit_cs);
975 for(i=0; i<broadcast_at_thread_exit.used; i++) {
976 if(broadcast_at_thread_exit.to_broadcast[i].thread_id != id)
977 continue;
979 _Mtx_unlock(broadcast_at_thread_exit.to_broadcast[i].mtx);
980 _Cnd_broadcast(broadcast_at_thread_exit.to_broadcast[i].cnd);
981 if(broadcast_at_thread_exit.to_broadcast[i].p)
982 *broadcast_at_thread_exit.to_broadcast[i].p = 1;
984 memmove(broadcast_at_thread_exit.to_broadcast+i, broadcast_at_thread_exit.to_broadcast+i+1,
985 (broadcast_at_thread_exit.used-i-1)*sizeof(broadcast_at_thread_exit.to_broadcast[0]));
986 broadcast_at_thread_exit.used--;
987 i--;
989 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
992 #endif
994 #if _MSVCP_VER == 100
995 typedef struct {
996 const vtable_ptr *vtable;
997 } error_category;
999 typedef struct {
1000 error_category base;
1001 const char *type;
1002 } custom_category;
1003 static custom_category iostream_category;
1005 DEFINE_RTTI_DATA0(error_category, 0, ".?AVerror_category@std@@")
1006 DEFINE_RTTI_DATA1(iostream_category, 0, &error_category_rtti_base_descriptor, ".?AV_Iostream_error_category@std@@")
1008 extern const vtable_ptr MSVCP_iostream_category_vtable;
1010 static void iostream_category_ctor(custom_category *this)
1012 this->base.vtable = &MSVCP_iostream_category_vtable;
1013 this->type = "iostream";
1016 DEFINE_THISCALL_WRAPPER(custom_category_vector_dtor, 8)
1017 custom_category* __thiscall custom_category_vector_dtor(custom_category *this, unsigned int flags)
1019 TRACE("(%p %x)\n", this, flags);
1020 if(flags & 2) {
1021 /* we have an array, with the number of elements stored before the first object */
1022 INT_PTR i, *ptr = (INT_PTR *)this-1;
1024 for(i=*ptr-1; i>=0; i--)
1025 MSVCRT_operator_delete(ptr);
1026 } else {
1027 if(flags & 1)
1028 MSVCRT_operator_delete(this);
1031 return this;
1034 DEFINE_THISCALL_WRAPPER(custom_category_name, 4)
1035 const char* __thiscall custom_category_name(const custom_category *this)
1037 return this->type;
1040 DEFINE_THISCALL_WRAPPER(custom_category_message, 12)
1041 basic_string_char* __thiscall custom_category_message(const custom_category *this,
1042 basic_string_char *ret, int err)
1044 return MSVCP_basic_string_char_ctor_cstr(ret, strerror(err));
1047 DEFINE_THISCALL_WRAPPER(custom_category_default_error_condition, 12)
1048 /*error_condition*/void* __thiscall custom_category_default_error_condition(
1049 custom_category *this, /*error_condition*/void *ret, int code)
1051 FIXME("(%p %p %x) stub\n", this, ret, code);
1052 return NULL;
1055 DEFINE_THISCALL_WRAPPER(custom_category_equivalent, 12)
1056 MSVCP_bool __thiscall custom_category_equivalent(const custom_category *this,
1057 int code, const /*error_condition*/void *condition)
1059 FIXME("(%p %x %p) stub\n", this, code, condition);
1060 return FALSE;
1063 DEFINE_THISCALL_WRAPPER(custom_category_equivalent_code, 12)
1064 MSVCP_bool __thiscall custom_category_equivalent_code(custom_category *this,
1065 const /*error_code*/void *code, int condition)
1067 FIXME("(%p %p %x) stub\n", this, code, condition);
1068 return FALSE;
1071 DEFINE_THISCALL_WRAPPER(iostream_category_message, 12)
1072 basic_string_char* __thiscall iostream_category_message(const custom_category *this,
1073 basic_string_char *ret, int err)
1075 if(err == 1) return MSVCP_basic_string_char_ctor_cstr(ret, "iostream error");
1076 return MSVCP_basic_string_char_ctor_cstr(ret, strerror(err));
1079 /* ?iostream_category@std@@YAABVerror_category@1@XZ */
1080 /* ?iostream_category@std@@YAAEBVerror_category@1@XZ */
1081 const error_category* __cdecl std_iostream_category(void)
1083 TRACE("()\n");
1084 return &iostream_category.base;
1087 static custom_category system_category;
1088 DEFINE_RTTI_DATA1(system_category, 0, &error_category_rtti_base_descriptor, ".?AV_System_error_category@std@@")
1090 extern const vtable_ptr MSVCP_system_category_vtable;
1092 static void system_category_ctor(custom_category *this)
1094 this->base.vtable = &MSVCP_system_category_vtable;
1095 this->type = "system";
1098 /* ?system_category@std@@YAABVerror_category@1@XZ */
1099 /* ?system_category@std@@YAAEBVerror_category@1@XZ */
1100 const error_category* __cdecl std_system_category(void)
1102 TRACE("()\n");
1103 return &system_category.base;
1106 static custom_category generic_category;
1107 DEFINE_RTTI_DATA1(generic_category, 0, &error_category_rtti_base_descriptor, ".?AV_Generic_error_category@std@@")
1109 extern const vtable_ptr MSVCP_generic_category_vtable;
1111 static void generic_category_ctor(custom_category *this)
1113 this->base.vtable = &MSVCP_generic_category_vtable;
1114 this->type = "generic";
1117 /* ?generic_category@std@@YAABVerror_category@1@XZ */
1118 /* ?generic_category@std@@YAAEBVerror_category@1@XZ */
1119 const error_category* __cdecl std_generic_category(void)
1121 TRACE("()\n");
1122 return &generic_category.base;
1124 #endif
1126 #if _MSVCP_VER >= 110
1127 static CRITICAL_SECTION call_once_cs;
1128 static CRITICAL_SECTION_DEBUG call_once_cs_debug =
1130 0, 0, &call_once_cs,
1131 { &call_once_cs_debug.ProcessLocksList, &call_once_cs_debug.ProcessLocksList },
1132 0, 0, { (DWORD_PTR)(__FILE__ ": call_once_cs") }
1134 static CRITICAL_SECTION call_once_cs = { &call_once_cs_debug, -1, 0, 0, 0, 0 };
1136 void __cdecl _Call_onceEx(int *once, void (__cdecl *func)(void*), void *argv)
1138 TRACE("%p %p %p\n", once, func, argv);
1140 EnterCriticalSection(&call_once_cs);
1141 if(!*once) {
1142 /* FIXME: handle exceptions */
1143 func(argv);
1144 *once = 1;
1146 LeaveCriticalSection(&call_once_cs);
1149 static void __cdecl call_once_func_wrapper(void *func)
1151 ((void (__cdecl*)(void))func)();
1154 void __cdecl _Call_once(int *once, void (__cdecl *func)(void))
1156 TRACE("%p %p\n", once, func);
1157 _Call_onceEx(once, call_once_func_wrapper, func);
1160 void __cdecl _Do_call(void *this)
1162 CALL_VTBL_FUNC(this, 0, void, (void*), (this));
1164 #endif
1166 #if _MSVCP_VER >= 110
1167 typedef struct
1169 HANDLE hnd;
1170 DWORD id;
1171 } _Thrd_t;
1173 typedef int (__cdecl *_Thrd_start_t)(void*);
1175 #define _THRD_ERROR 4
1177 int __cdecl _Thrd_equal(_Thrd_t a, _Thrd_t b)
1179 TRACE("(%p %u %p %u)\n", a.hnd, a.id, b.hnd, b.id);
1180 return a.id == b.id;
1183 int __cdecl _Thrd_lt(_Thrd_t a, _Thrd_t b)
1185 TRACE("(%p %u %p %u)\n", a.hnd, a.id, b.hnd, b.id);
1186 return a.id < b.id;
1189 void __cdecl _Thrd_sleep(const xtime *t)
1191 TRACE("(%p)\n", t);
1192 Sleep(_Xtime_diff_to_millis(t));
1195 void __cdecl _Thrd_yield(void)
1197 TRACE("()\n");
1198 Sleep(0);
1201 static _Thrd_t thread_current(void)
1203 _Thrd_t ret;
1205 if(DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1206 GetCurrentProcess(), &ret.hnd, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
1207 CloseHandle(ret.hnd);
1208 } else {
1209 ret.hnd = 0;
1211 ret.id = GetCurrentThreadId();
1213 TRACE("(%p %u)\n", ret.hnd, ret.id);
1214 return ret;
1217 #ifndef __i386__
1218 _Thrd_t __cdecl _Thrd_current(void)
1220 return thread_current();
1222 #else
1223 ULONGLONG __cdecl _Thrd_current(void)
1225 union {
1226 _Thrd_t thr;
1227 ULONGLONG ull;
1228 } ret;
1230 C_ASSERT(sizeof(_Thrd_t) <= sizeof(ULONGLONG));
1232 ret.thr = thread_current();
1233 return ret.ull;
1235 #endif
1237 int __cdecl _Thrd_join(_Thrd_t thr, int *code)
1239 TRACE("(%p %u %p)\n", thr.hnd, thr.id, code);
1240 if (WaitForSingleObject(thr.hnd, INFINITE))
1241 return _THRD_ERROR;
1243 if (code)
1244 GetExitCodeThread(thr.hnd, (DWORD *)code);
1246 CloseHandle(thr.hnd);
1247 return 0;
1250 int __cdecl _Thrd_start(_Thrd_t *thr, LPTHREAD_START_ROUTINE proc, void *arg)
1252 TRACE("(%p %p %p)\n", thr, proc, arg);
1253 thr->hnd = CreateThread(NULL, 0, proc, arg, 0, &thr->id);
1254 return thr->hnd ? 0 : _THRD_ERROR;
1257 typedef struct
1259 _Thrd_start_t proc;
1260 void *arg;
1261 } thread_proc_arg;
1263 static DWORD WINAPI thread_proc_wrapper(void *arg)
1265 thread_proc_arg wrapped_arg = *((thread_proc_arg*)arg);
1266 free(arg);
1267 return wrapped_arg.proc(wrapped_arg.arg);
1270 int __cdecl _Thrd_create(_Thrd_t *thr, _Thrd_start_t proc, void *arg)
1272 thread_proc_arg *wrapped_arg;
1273 int ret;
1275 TRACE("(%p %p %p)\n", thr, proc, arg);
1277 wrapped_arg = malloc(sizeof(*wrapped_arg));
1278 if(!wrapped_arg)
1279 return _THRD_ERROR; /* TODO: probably different error should be returned here */
1281 wrapped_arg->proc = proc;
1282 wrapped_arg->arg = arg;
1283 ret = _Thrd_start(thr, thread_proc_wrapper, wrapped_arg);
1284 if(ret) free(wrapped_arg);
1285 return ret;
1288 int __cdecl _Thrd_detach(_Thrd_t thr)
1290 return CloseHandle(thr.hnd) ? 0 : _THRD_ERROR;
1293 typedef struct
1295 const vtable_ptr *vtable;
1296 _Cnd_t cnd;
1297 _Mtx_t mtx;
1298 MSVCP_bool launched;
1299 } _Pad;
1301 DEFINE_RTTI_DATA0(_Pad, 0, ".?AV_Pad@std@@")
1303 /* ??_7_Pad@std@@6B@ */
1304 extern const vtable_ptr MSVCP__Pad_vtable;
1306 unsigned int __cdecl _Thrd_hardware_concurrency(void)
1308 static unsigned int val = -1;
1310 TRACE("()\n");
1312 if(val == -1) {
1313 SYSTEM_INFO si;
1315 GetSystemInfo(&si);
1316 val = si.dwNumberOfProcessors;
1319 return val;
1322 unsigned int __cdecl _Thrd_id(void)
1324 TRACE("()\n");
1325 return GetCurrentThreadId();
1328 /* ??0_Pad@std@@QAE@XZ */
1329 /* ??0_Pad@std@@QEAA@XZ */
1330 DEFINE_THISCALL_WRAPPER(_Pad_ctor, 4)
1331 _Pad* __thiscall _Pad_ctor(_Pad *this)
1333 TRACE("(%p)\n", this);
1335 this->vtable = &MSVCP__Pad_vtable;
1336 _Cnd_init(&this->cnd);
1337 _Mtx_init(&this->mtx, 0);
1338 this->launched = FALSE;
1339 _Mtx_lock(MTX_T_TO_ARG(this->mtx));
1340 return this;
1343 /* ??4_Pad@std@@QAEAAV01@ABV01@@Z */
1344 /* ??4_Pad@std@@QEAAAEAV01@AEBV01@@Z */
1345 DEFINE_THISCALL_WRAPPER(_Pad_op_assign, 8)
1346 _Pad* __thiscall _Pad_op_assign(_Pad *this, const _Pad *copy)
1348 TRACE("(%p %p)\n", this, copy);
1350 this->cnd = copy->cnd;
1351 this->mtx = copy->mtx;
1352 this->launched = copy->launched;
1353 return this;
1356 /* ??0_Pad@std@@QAE@ABV01@@Z */
1357 /* ??0_Pad@std@@QEAA@AEBV01@@Z */
1358 DEFINE_THISCALL_WRAPPER(_Pad_copy_ctor, 8)
1359 _Pad* __thiscall _Pad_copy_ctor(_Pad *this, const _Pad *copy)
1361 TRACE("(%p %p)\n", this, copy);
1363 this->vtable = &MSVCP__Pad_vtable;
1364 return _Pad_op_assign(this, copy);
1367 /* ??1_Pad@std@@QAE@XZ */
1368 /* ??1_Pad@std@@QEAA@XZ */
1369 DEFINE_THISCALL_WRAPPER(_Pad_dtor, 4)
1370 void __thiscall _Pad_dtor(_Pad *this)
1372 TRACE("(%p)\n", this);
1374 _Mtx_unlock(MTX_T_TO_ARG(this->mtx));
1375 _Mtx_destroy(MTX_T_TO_ARG(this->mtx));
1376 _Cnd_destroy(CND_T_TO_ARG(this->cnd));
1379 DEFINE_THISCALL_WRAPPER(_Pad__Go, 4)
1380 #define call__Pad__Go(this) CALL_VTBL_FUNC(this, 0, unsigned int, (_Pad*), (this))
1381 unsigned int __thiscall _Pad__Go(_Pad *this)
1383 ERR("(%p) should not be called\n", this);
1384 return 0;
1387 static DWORD WINAPI launch_thread_proc(void *arg)
1389 _Pad *this = arg;
1390 return call__Pad__Go(this);
1393 /* ?_Launch@_Pad@std@@QAEXPAU_Thrd_imp_t@@@Z */
1394 /* ?_Launch@_Pad@std@@QEAAXPEAU_Thrd_imp_t@@@Z */
1395 DEFINE_THISCALL_WRAPPER(_Pad__Launch, 8)
1396 void __thiscall _Pad__Launch(_Pad *this, _Thrd_t *thr)
1398 TRACE("(%p %p)\n", this, thr);
1400 _Thrd_start(thr, launch_thread_proc, this);
1401 _Cnd_wait(CND_T_TO_ARG(this->cnd), MTX_T_TO_ARG(this->mtx));
1404 /* ?_Release@_Pad@std@@QAEXXZ */
1405 /* ?_Release@_Pad@std@@QEAAXXZ */
1406 DEFINE_THISCALL_WRAPPER(_Pad__Release, 4)
1407 void __thiscall _Pad__Release(_Pad *this)
1409 TRACE("(%p)\n", this);
1411 _Mtx_lock(MTX_T_TO_ARG(this->mtx));
1412 this->launched = TRUE;
1413 _Cnd_signal(CND_T_TO_ARG(this->cnd));
1414 _Mtx_unlock(MTX_T_TO_ARG(this->mtx));
1416 #endif
1418 #if _MSVCP_VER >= 100
1419 typedef struct _Page
1421 struct _Page *_Next;
1422 MSVCP_size_t _Mask;
1423 char data[1];
1424 } _Page;
1426 typedef struct
1428 LONG lock;
1429 _Page *head;
1430 _Page *tail;
1431 MSVCP_size_t head_pos;
1432 MSVCP_size_t tail_pos;
1433 } threadsafe_queue;
1435 #define QUEUES_NO 8
1436 typedef struct
1438 MSVCP_size_t tail_pos;
1439 MSVCP_size_t head_pos;
1440 threadsafe_queue queues[QUEUES_NO];
1441 } queue_data;
1443 typedef struct
1445 const vtable_ptr *vtable;
1446 queue_data *data; /* queue_data structure is not binary compatible */
1447 MSVCP_size_t alloc_count;
1448 MSVCP_size_t item_size;
1449 } _Concurrent_queue_base_v4;
1451 extern const vtable_ptr MSVCP__Concurrent_queue_base_v4_vtable;
1452 #if _MSVCP_VER == 100
1453 #define call__Concurrent_queue_base_v4__Move_item call__Concurrent_queue_base_v4__Copy_item
1454 #define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1455 0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
1456 #define call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
1457 4, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
1458 #define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
1459 12, _Page*, (_Concurrent_queue_base_v4*), (this))
1460 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
1461 16, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
1462 #else
1463 #define call__Concurrent_queue_base_v4__Move_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1464 0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,void*), (this,dst,idx,src))
1465 #define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1466 4, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
1467 #define call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
1468 8, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
1469 #define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
1470 16, _Page*, (_Concurrent_queue_base_v4*), (this))
1471 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
1472 20, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
1473 #endif
1475 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IBEXXZ */
1476 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IEBAXXZ */
1477 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_throw_exception, 4)
1478 void __thiscall _Concurrent_queue_base_v4__Internal_throw_exception(
1479 const _Concurrent_queue_base_v4 *this)
1481 TRACE("(%p)\n", this);
1482 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1485 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IAE@I@Z */
1486 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IEAA@_K@Z */
1487 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_ctor, 8)
1488 _Concurrent_queue_base_v4* __thiscall _Concurrent_queue_base_v4_ctor(
1489 _Concurrent_queue_base_v4 *this, MSVCP_size_t size)
1491 TRACE("(%p %ld)\n", this, size);
1493 this->data = MSVCRT_operator_new(sizeof(*this->data));
1494 memset(this->data, 0, sizeof(*this->data));
1496 this->vtable = &MSVCP__Concurrent_queue_base_v4_vtable;
1497 this->item_size = size;
1499 /* alloc_count needs to be power of 2 */
1500 this->alloc_count =
1501 size <= 8 ? 32 :
1502 size <= 16 ? 16 :
1503 size <= 32 ? 8 :
1504 size <= 64 ? 4 :
1505 size <= 128 ? 2 : 1;
1506 return this;
1509 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MAE@XZ */
1510 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MEAA@XZ */
1511 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dtor, 4)
1512 void __thiscall _Concurrent_queue_base_v4_dtor(_Concurrent_queue_base_v4 *this)
1514 TRACE("(%p)\n", this);
1515 MSVCRT_operator_delete(this->data);
1518 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_vector_dtor, 8)
1519 _Concurrent_queue_base_v4* __thiscall _Concurrent_queue_base_v4_vector_dtor(
1520 _Concurrent_queue_base_v4 *this, unsigned int flags)
1522 TRACE("(%p %x)\n", this, flags);
1523 if(flags & 2) {
1524 /* we have an array, with the number of elements stored before the first object */
1525 INT_PTR i, *ptr = (INT_PTR *)this-1;
1527 for(i=*ptr-1; i>=0; i--)
1528 _Concurrent_queue_base_v4_dtor(this+i);
1529 MSVCRT_operator_delete(ptr);
1530 } else {
1531 if(flags & 1)
1532 _Concurrent_queue_base_v4_dtor(this);
1533 MSVCRT_operator_delete(this);
1536 return this;
1539 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IAEXXZ */
1540 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXXZ */
1541 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_finish_clear, 4)
1542 void __thiscall _Concurrent_queue_base_v4__Internal_finish_clear(
1543 _Concurrent_queue_base_v4 *this)
1545 int i;
1547 TRACE("(%p)\n", this);
1549 for(i=0; i<QUEUES_NO; i++)
1551 if(this->data->queues[i].tail)
1552 call__Concurrent_queue_base_v4__Deallocate_page(this, this->data->queues[i].tail);
1556 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IBE_NXZ */
1557 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_NXZ */
1558 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_empty, 4)
1559 MSVCP_bool __thiscall _Concurrent_queue_base_v4__Internal_empty(
1560 const _Concurrent_queue_base_v4 *this)
1562 TRACE("(%p)\n", this);
1563 return this->data->head_pos == this->data->tail_pos;
1566 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IBEIXZ */
1567 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_KXZ */
1568 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_size, 4)
1569 MSVCP_size_t __thiscall _Concurrent_queue_base_v4__Internal_size(
1570 const _Concurrent_queue_base_v4 *this)
1572 TRACE("(%p)\n", this);
1573 return this->data->tail_pos - this->data->head_pos;
1576 static void spin_wait(int *counter)
1578 static int spin_limit = -1;
1580 if(spin_limit == -1)
1582 SYSTEM_INFO si;
1583 GetSystemInfo(&si);
1584 spin_limit = si.dwNumberOfProcessors>1 ? 4000 : 0;
1587 if(*counter >= spin_limit)
1589 *counter = 0;
1590 Sleep(0);
1592 else
1594 (*counter)++;
1598 #ifdef _WIN64
1599 static MSVCP_size_t InterlockedIncrementSizeT(MSVCP_size_t volatile *dest)
1601 MSVCP_size_t v;
1605 v = *dest;
1606 } while(InterlockedCompareExchange64((LONGLONG*)dest, v+1, v) != v);
1608 return v+1;
1610 #else
1611 #define InterlockedIncrementSizeT(dest) InterlockedIncrement((LONG*)dest)
1612 #endif
1614 static void CALLBACK queue_push_finally(BOOL normal, void *ctx)
1616 threadsafe_queue *queue = ctx;
1617 InterlockedIncrementSizeT(&queue->tail_pos);
1620 static void threadsafe_queue_push(threadsafe_queue *queue, MSVCP_size_t id,
1621 void *e, _Concurrent_queue_base_v4 *parent, BOOL copy)
1623 MSVCP_size_t page_id = id & ~(parent->alloc_count-1);
1624 int spin;
1625 _Page *p;
1627 spin = 0;
1628 while(queue->tail_pos != id)
1629 spin_wait(&spin);
1631 if(page_id == id)
1633 /* TODO: Add exception handling */
1634 p = call__Concurrent_queue_base_v4__Allocate_page(parent);
1635 p->_Next = NULL;
1636 p->_Mask = 0;
1638 spin = 0;
1639 while(InterlockedCompareExchange(&queue->lock, 1, 0))
1640 spin_wait(&spin);
1641 if(queue->tail)
1642 queue->tail->_Next = p;
1643 queue->tail = p;
1644 if(!queue->head)
1645 queue->head = p;
1646 queue->lock = 0;
1648 else
1650 p = queue->tail;
1653 __TRY
1655 if(copy)
1656 call__Concurrent_queue_base_v4__Copy_item(parent, p, id-page_id, e);
1657 else
1658 call__Concurrent_queue_base_v4__Move_item(parent, p, id-page_id, e);
1659 p->_Mask |= 1 << (id - page_id);
1661 __FINALLY_CTX(queue_push_finally, queue);
1664 static BOOL threadsafe_queue_pop(threadsafe_queue *queue, MSVCP_size_t id,
1665 void *e, _Concurrent_queue_base_v4 *parent)
1667 MSVCP_size_t page_id = id & ~(parent->alloc_count-1);
1668 int spin;
1669 _Page *p;
1670 BOOL ret = FALSE;
1672 spin = 0;
1673 while(queue->tail_pos <= id)
1674 spin_wait(&spin);
1676 spin = 0;
1677 while(queue->head_pos != id)
1678 spin_wait(&spin);
1680 p = queue->head;
1681 if(p->_Mask & (1 << (id-page_id)))
1683 /* TODO: Add exception handling */
1684 call__Concurrent_queue_base_v4__Assign_and_destroy_item(parent, e, p, id-page_id);
1685 ret = TRUE;
1688 if(id == page_id+parent->alloc_count-1)
1690 spin = 0;
1691 while(InterlockedCompareExchange(&queue->lock, 1, 0))
1692 spin_wait(&spin);
1693 queue->head = p->_Next;
1694 if(!queue->head)
1695 queue->tail = NULL;
1696 queue->lock = 0;
1698 /* TODO: Add exception handling */
1699 call__Concurrent_queue_base_v4__Deallocate_page(parent, p);
1702 InterlockedIncrementSizeT(&queue->head_pos);
1703 return ret;
1706 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPBX@Z */
1707 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEBX@Z */
1708 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_push, 8)
1709 void __thiscall _Concurrent_queue_base_v4__Internal_push(
1710 _Concurrent_queue_base_v4 *this, void *e)
1712 MSVCP_size_t id;
1714 TRACE("(%p %p)\n", this, e);
1716 id = InterlockedIncrementSizeT(&this->data->tail_pos)-1;
1717 threadsafe_queue_push(this->data->queues + id % QUEUES_NO,
1718 id / QUEUES_NO, e, this, TRUE);
1721 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPAX@Z */
1722 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEAX@Z */
1723 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_move_push, 8)
1724 void __thiscall _Concurrent_queue_base_v4__Internal_move_push(
1725 _Concurrent_queue_base_v4 *this, void *e)
1727 MSVCP_size_t id;
1729 TRACE("(%p %p)\n", this, e);
1731 id = InterlockedIncrementSizeT(&this->data->tail_pos)-1;
1732 threadsafe_queue_push(this->data->queues + id % QUEUES_NO,
1733 id / QUEUES_NO, e, this, FALSE);
1736 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IAE_NPAX@Z */
1737 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IEAA_NPEAX@Z */
1738 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_pop_if_present, 8)
1739 MSVCP_bool __thiscall _Concurrent_queue_base_v4__Internal_pop_if_present(
1740 _Concurrent_queue_base_v4 *this, void *e)
1742 MSVCP_size_t id;
1744 TRACE("(%p %p)\n", this, e);
1750 id = this->data->head_pos;
1751 if(id == this->data->tail_pos) return FALSE;
1752 } while(InterlockedCompareExchangePointer((void**)&this->data->head_pos,
1753 (void*)(id+1), (void*)id) != (void*)id);
1754 } while(!threadsafe_queue_pop(this->data->queues + id % QUEUES_NO,
1755 id / QUEUES_NO, e, this));
1756 return TRUE;
1759 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IAEXAAV123@@Z */
1760 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXAEAV123@@Z */
1761 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_swap, 8)
1762 void __thiscall _Concurrent_queue_base_v4__Internal_swap(
1763 _Concurrent_queue_base_v4 *this, _Concurrent_queue_base_v4 *r)
1765 FIXME("(%p %p) stub\n", this, r);
1768 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dummy, 4)
1769 void __thiscall _Concurrent_queue_base_v4_dummy(_Concurrent_queue_base_v4 *this)
1771 ERR("unexpected call\n");
1774 DEFINE_RTTI_DATA0(_Concurrent_queue_base_v4, 0, ".?AV_Concurrent_queue_base_v4@details@Concurrency@@")
1776 static int _Runtime_object_id;
1778 typedef struct
1780 const vtable_ptr *vtable;
1781 int id;
1782 } _Runtime_object;
1784 extern const vtable_ptr MSVCP__Runtime_object_vtable;
1786 /* ??0_Runtime_object@details@Concurrency@@QAE@H@Z */
1787 /* ??0_Runtime_object@details@Concurrency@@QEAA@H@Z */
1788 DEFINE_THISCALL_WRAPPER(_Runtime_object_ctor_id, 8)
1789 _Runtime_object* __thiscall _Runtime_object_ctor_id(_Runtime_object *this, int id)
1791 TRACE("(%p %d)\n", this, id);
1792 this->vtable = &MSVCP__Runtime_object_vtable;
1793 this->id = id;
1794 return this;
1797 /* ??0_Runtime_object@details@Concurrency@@QAE@XZ */
1798 /* ??0_Runtime_object@details@Concurrency@@QEAA@XZ */
1799 DEFINE_THISCALL_WRAPPER(_Runtime_object_ctor, 4)
1800 _Runtime_object* __thiscall _Runtime_object_ctor(_Runtime_object *this)
1802 TRACE("(%p)\n", this);
1803 this->vtable = &MSVCP__Runtime_object_vtable;
1804 this->id = InterlockedExchangeAdd(&_Runtime_object_id, 2);
1805 return this;
1808 DEFINE_THISCALL_WRAPPER(_Runtime_object__GetId, 4)
1809 int __thiscall _Runtime_object__GetId(_Runtime_object *this)
1811 TRACE("(%p)\n", this);
1812 return this->id;
1815 DEFINE_RTTI_DATA0(_Runtime_object, 0, ".?AV_Runtime_object@details@Concurrency@@")
1817 #endif
1819 #if _MSVCP_VER >= 100
1820 typedef struct __Concurrent_vector_base_v4
1822 void* (__cdecl *allocator)(struct __Concurrent_vector_base_v4 *, MSVCP_size_t);
1823 void *storage[3];
1824 MSVCP_size_t first_block;
1825 MSVCP_size_t early_size;
1826 void **segment;
1827 } _Concurrent_vector_base_v4;
1829 #define STORAGE_SIZE ARRAY_SIZE(this->storage)
1830 #define SEGMENT_SIZE (sizeof(void*) * 8)
1832 typedef struct compact_block
1834 MSVCP_size_t first_block;
1835 void *blocks[SEGMENT_SIZE];
1836 int size_check;
1837 }compact_block;
1839 /* based on wined3d_log2i from wined3d.h */
1840 /* Return the integer base-2 logarithm of (x|1). Result is 0 for x == 0. */
1841 static inline unsigned int log2i(unsigned int x)
1843 #ifdef HAVE___BUILTIN_CLZ
1844 return __builtin_clz(x|1) ^ 0x1f;
1845 #else
1846 static const unsigned int l[] =
1848 ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
1849 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1850 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1851 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1852 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1853 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1854 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1855 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1856 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1857 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1858 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1859 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1860 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1861 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1862 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1863 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1865 unsigned int i;
1867 x |= 1;
1868 return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
1869 #endif
1872 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KAII@Z */
1873 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KA_K_K@Z */
1874 MSVCP_size_t __cdecl _vector_base_v4__Segment_index_of(MSVCP_size_t x)
1876 unsigned int half;
1878 TRACE("(%lu)\n", x);
1880 if((sizeof(x) == 8) && (half = x >> 32))
1881 return log2i(half) + 32;
1883 return log2i(x);
1886 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IBEXI@Z */
1887 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IEBAX_K@Z */
1888 DEFINE_THISCALL_WRAPPER(_vector_base_v4__Internal_throw_exception, 8)
1889 void __thiscall _vector_base_v4__Internal_throw_exception(void/*_vector_base_v4*/ *this, MSVCP_size_t idx)
1891 static const struct {
1892 exception_type type;
1893 const char *msg;
1894 } exceptions[] = {
1895 { EXCEPTION_OUT_OF_RANGE, "Index out of range" },
1896 { EXCEPTION_OUT_OF_RANGE, "Index out of segments table range" },
1897 { EXCEPTION_RANGE_ERROR, "Index is inside segment which failed to be allocated" },
1900 TRACE("(%p %lu)\n", this, idx);
1902 if(idx < ARRAY_SIZE(exceptions))
1903 throw_exception(exceptions[idx].type, exceptions[idx].msg);
1906 #ifdef _WIN64
1907 #define InterlockedCompareExchangeSizeT(dest, exchange, cmp) InterlockedCompareExchangeSize((MSVCP_size_t *)dest, (MSVCP_size_t)exchange, (MSVCP_size_t)cmp)
1908 static MSVCP_size_t InterlockedCompareExchangeSize(MSVCP_size_t volatile *dest, MSVCP_size_t exchange, MSVCP_size_t cmp)
1910 MSVCP_size_t v;
1912 v = InterlockedCompareExchange64((LONGLONG*)dest, exchange, cmp);
1914 return v;
1916 #else
1917 #define InterlockedCompareExchangeSizeT(dest, exchange, cmp) InterlockedCompareExchange((LONG*)dest, (MSVCP_size_t)exchange, (MSVCP_size_t)cmp)
1918 #endif
1920 #define SEGMENT_ALLOC_MARKER ((void*)1)
1922 static void concurrent_vector_alloc_segment(_Concurrent_vector_base_v4 *this,
1923 MSVCP_size_t seg, MSVCP_size_t element_size)
1925 int spin;
1927 while(!this->segment[seg] || this->segment[seg] == SEGMENT_ALLOC_MARKER)
1929 spin = 0;
1930 while(this->segment[seg] == SEGMENT_ALLOC_MARKER)
1931 spin_wait(&spin);
1932 if(!InterlockedCompareExchangeSizeT((this->segment + seg),
1933 SEGMENT_ALLOC_MARKER, 0))
1934 __TRY
1936 if(seg == 0)
1937 this->segment[seg] = this->allocator(this, element_size * (1 << this->first_block));
1938 else if(seg < this->first_block)
1939 this->segment[seg] = (BYTE**)this->segment[0]
1940 + element_size * (1 << seg);
1941 else
1942 this->segment[seg] = this->allocator(this, element_size * (1 << seg));
1944 __EXCEPT_ALL
1946 this->segment[seg] = NULL;
1947 throw_exception(EXCEPTION_RERAISE, NULL);
1949 __ENDTRY
1950 if(!this->segment[seg])
1951 _vector_base_v4__Internal_throw_exception(this, 2);
1955 /* ??1_Concurrent_vector_base_v4@details@Concurrency@@IAE@XZ */
1956 /* ??1_Concurrent_vector_base_v4@details@Concurrency@@IEAA@XZ */
1957 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4_dtor, 4)
1958 void __thiscall _Concurrent_vector_base_v4_dtor(
1959 _Concurrent_vector_base_v4 *this)
1961 TRACE("(%p)\n", this);
1963 if(this->segment != this->storage)
1964 free(this->segment);
1967 /* ?_Internal_capacity@_Concurrent_vector_base_v4@details@Concurrency@@IBEIXZ */
1968 /* ?_Internal_capacity@_Concurrent_vector_base_v4@details@Concurrency@@IEBA_KXZ */
1969 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_capacity, 4)
1970 MSVCP_size_t __thiscall _Concurrent_vector_base_v4__Internal_capacity(
1971 const _Concurrent_vector_base_v4 *this)
1973 MSVCP_size_t last_block;
1974 int i;
1976 TRACE("(%p)\n", this);
1978 last_block = (this->segment == this->storage ? STORAGE_SIZE : SEGMENT_SIZE);
1979 for(i = 0; i < last_block; i++)
1981 if(!this->segment[i])
1982 return !i ? 0 : 1 << i;
1984 return 1 << i;
1987 /* ?_Internal_reserve@_Concurrent_vector_base_v4@details@Concurrency@@IAEXIII@Z */
1988 /* ?_Internal_reserve@_Concurrent_vector_base_v4@details@Concurrency@@IEAAX_K00@Z */
1989 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_reserve, 16)
1990 void __thiscall _Concurrent_vector_base_v4__Internal_reserve(
1991 _Concurrent_vector_base_v4 *this, MSVCP_size_t size,
1992 MSVCP_size_t element_size, MSVCP_size_t max_size)
1994 MSVCP_size_t block_idx, capacity;
1995 int i;
1996 void **new_segment;
1998 TRACE("(%p %ld %ld %ld)\n", this, size, element_size, max_size);
2000 if(size > max_size) _vector_base_v4__Internal_throw_exception(this, 0);
2001 capacity = _Concurrent_vector_base_v4__Internal_capacity(this);
2002 if(size <= capacity) return;
2003 block_idx = _vector_base_v4__Segment_index_of(size - 1);
2004 if(!this->first_block)
2005 InterlockedCompareExchangeSizeT(&this->first_block, block_idx + 1, 0);
2006 i = _vector_base_v4__Segment_index_of(capacity);
2007 if(this->storage == this->segment) {
2008 for(; i <= block_idx && i < STORAGE_SIZE; i++)
2009 concurrent_vector_alloc_segment(this, i, element_size);
2010 if(block_idx >= STORAGE_SIZE) {
2011 new_segment = malloc(SEGMENT_SIZE * sizeof(void*));
2012 if(new_segment == NULL) _vector_base_v4__Internal_throw_exception(this, 2);
2013 memset(new_segment, 0, SEGMENT_SIZE * sizeof(*new_segment));
2014 memcpy(new_segment, this->storage, STORAGE_SIZE * sizeof(*new_segment));
2015 if(InterlockedCompareExchangePointer((void*)&this->segment, new_segment,
2016 this->storage) != this->storage)
2017 free(new_segment);
2020 for(; i <= block_idx; i++)
2021 concurrent_vector_alloc_segment(this, i, element_size);
2024 /* ?_Internal_clear@_Concurrent_vector_base_v4@details@Concurrency@@IAEIP6AXPAXI@Z@Z */
2025 /* ?_Internal_clear@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_KP6AXPEAX_K@Z@Z */
2026 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_clear, 8)
2027 MSVCP_size_t __thiscall _Concurrent_vector_base_v4__Internal_clear(
2028 _Concurrent_vector_base_v4 *this, void (__cdecl *clear)(void*, MSVCP_size_t))
2030 MSVCP_size_t seg_no, elems;
2031 int i;
2033 TRACE("(%p %p)\n", this, clear);
2035 seg_no = this->early_size ? _vector_base_v4__Segment_index_of(this->early_size) + 1 : 0;
2036 for(i = seg_no - 1; i >= 0; i--) {
2037 elems = this->early_size - (1 << i & ~1);
2038 clear(this->segment[i], elems);
2039 this->early_size -= elems;
2041 while(seg_no < (this->segment == this->storage ? STORAGE_SIZE : SEGMENT_SIZE)) {
2042 if(!this->segment[seg_no]) break;
2043 seg_no++;
2045 return seg_no;
2048 /* ?_Internal_compact@_Concurrent_vector_base_v4@details@Concurrency@@IAEPAXIPAXP6AX0I@ZP6AX0PBXI@Z@Z */
2049 /* ?_Internal_compact@_Concurrent_vector_base_v4@details@Concurrency@@IEAAPEAX_KPEAXP6AX10@ZP6AX1PEBX0@Z@Z */
2050 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_compact, 20)
2051 void * __thiscall _Concurrent_vector_base_v4__Internal_compact(
2052 _Concurrent_vector_base_v4 *this, MSVCP_size_t element_size, void *v,
2053 void (__cdecl *clear)(void*, MSVCP_size_t),
2054 void (__cdecl *copy)(void*, const void*, MSVCP_size_t))
2056 compact_block *b;
2057 MSVCP_size_t size, alloc_size, seg_no, alloc_seg, copy_element, clear_element;
2058 int i;
2060 TRACE("(%p %ld %p %p %p)\n", this, element_size, v, clear, copy);
2062 size = this->early_size;
2063 alloc_size = _Concurrent_vector_base_v4__Internal_capacity(this);
2064 if(alloc_size == 0) return NULL;
2065 alloc_seg = _vector_base_v4__Segment_index_of(alloc_size - 1);
2066 if(!size) {
2067 this->first_block = 0;
2068 b = v;
2069 b->first_block = alloc_seg + 1;
2070 memset(b->blocks, 0, sizeof(b->blocks));
2071 memcpy(b->blocks, this->segment,
2072 (alloc_seg + 1) * sizeof(this->segment[0]));
2073 memset(this->segment, 0, sizeof(this->segment[0]) * (alloc_seg + 1));
2074 return v;
2076 seg_no = _vector_base_v4__Segment_index_of(size - 1);
2077 if(this->first_block == (seg_no + 1) && seg_no == alloc_seg) return NULL;
2078 b = v;
2079 b->first_block = this->first_block;
2080 memset(b->blocks, 0, sizeof(b->blocks));
2081 memcpy(b->blocks, this->segment,
2082 (alloc_seg + 1) * sizeof(this->segment[0]));
2083 if(this->first_block == (seg_no + 1) && seg_no != alloc_seg) {
2084 memset(b->blocks, 0, sizeof(b->blocks[0]) * (seg_no + 1));
2085 memset(&this->segment[seg_no + 1], 0, sizeof(this->segment[0]) * (alloc_seg - seg_no));
2086 return v;
2088 memset(this->segment, 0,
2089 (alloc_seg + 1) * sizeof(this->segment[0]));
2090 this->first_block = 0;
2091 _Concurrent_vector_base_v4__Internal_reserve(this, size, element_size,
2092 MSVCP_SIZE_T_MAX / element_size);
2093 for(i = 0; i < seg_no; i++)
2094 copy(this->segment[i], b->blocks[i], i ? 1 << i : 2);
2095 copy_element = size - ((1 << seg_no) & ~1);
2096 if(copy_element > 0)
2097 copy(this->segment[seg_no], b->blocks[seg_no], copy_element);
2098 for(i = 0; i < seg_no; i++)
2099 clear(b->blocks[i], i ? 1 << i : 2);
2100 clear_element = size - ((1 << seg_no) & ~1);
2101 if(clear_element > 0)
2102 clear(b->blocks[seg_no], clear_element);
2103 return v;
2106 /* ?_Internal_copy@_Concurrent_vector_base_v4@details@Concurrency@@IAEXABV123@IP6AXPAXPBXI@Z@Z */
2107 /* ?_Internal_copy@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEBV123@_KP6AXPEAXPEBX1@Z@Z */
2108 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_copy, 16)
2109 void __thiscall _Concurrent_vector_base_v4__Internal_copy(
2110 _Concurrent_vector_base_v4 *this, const _Concurrent_vector_base_v4 *v,
2111 MSVCP_size_t element_size, void (__cdecl *copy)(void*, const void*, MSVCP_size_t))
2113 MSVCP_size_t seg_no, v_size;
2114 int i;
2116 TRACE("(%p %p %ld %p)\n", this, v, element_size, copy);
2118 v_size = v->early_size;
2119 if(!v_size) {
2120 this->early_size = 0;
2121 return;
2123 _Concurrent_vector_base_v4__Internal_reserve(this, v_size,
2124 element_size, MSVCP_SIZE_T_MAX / element_size);
2125 seg_no = _vector_base_v4__Segment_index_of(v_size - 1);
2126 for(i = 0; i < seg_no; i++)
2127 copy(this->segment[i], v->segment[i], i ? 1 << i : 2);
2128 copy(this->segment[i], v->segment[i], v_size - (1 << i & ~1));
2129 this->early_size = v_size;
2132 /* ?_Internal_assign@_Concurrent_vector_base_v4@details@Concurrency@@IAEXABV123@IP6AXPAXI@ZP6AX1PBXI@Z4@Z */
2133 /* ?_Internal_assign@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEBV123@_KP6AXPEAX1@ZP6AX2PEBX1@Z5@Z */
2134 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_assign, 24)
2135 void __thiscall _Concurrent_vector_base_v4__Internal_assign(
2136 _Concurrent_vector_base_v4 *this, const _Concurrent_vector_base_v4 *v,
2137 MSVCP_size_t element_size, void (__cdecl *clear)(void*, MSVCP_size_t),
2138 void (__cdecl *assign)(void*, const void*, MSVCP_size_t),
2139 void (__cdecl *copy)(void*, const void*, MSVCP_size_t))
2141 MSVCP_size_t v_size, seg_no, v_seg_no, remain_element;
2142 int i;
2144 TRACE("(%p %p %ld %p %p %p)\n", this, v, element_size, clear, assign, copy);
2146 v_size = v->early_size;
2147 if(!v_size) {
2148 _Concurrent_vector_base_v4__Internal_clear(this, clear);
2149 return;
2151 if(!this->early_size) {
2152 _Concurrent_vector_base_v4__Internal_copy(this, v, element_size, copy);
2153 return;
2155 seg_no = _vector_base_v4__Segment_index_of(this->early_size - 1);
2156 v_seg_no = _vector_base_v4__Segment_index_of(v_size - 1);
2158 for(i = 0; i < min(seg_no, v_seg_no); i++)
2159 assign(this->segment[i], v->segment[i], i ? 1 << i : 2);
2160 remain_element = min(this->early_size, v_size) - (1 << i & ~1);
2161 if(remain_element != 0)
2162 assign(this->segment[i], v->segment[i], remain_element);
2164 if(this->early_size > v_size)
2166 if((i ? 1 << i : 2) - remain_element > 0)
2167 clear((BYTE**)this->segment[i] + element_size * remain_element,
2168 (i ? 1 << i : 2) - remain_element);
2169 if(i < seg_no)
2171 for(i++; i < seg_no; i++)
2172 clear(this->segment[i], 1 << i);
2173 clear(this->segment[i], this->early_size - (1 << i));
2176 else if(this->early_size < v_size)
2178 if((i ? 1 << i : 2) - remain_element > 0)
2179 copy((BYTE**)this->segment[i] + element_size * remain_element,
2180 (BYTE**)v->segment[i] + element_size * remain_element,
2181 (i ? 1 << i : 2) - remain_element);
2182 if(i < v_seg_no)
2184 _Concurrent_vector_base_v4__Internal_reserve(this, v_size,
2185 element_size, MSVCP_SIZE_T_MAX / element_size);
2186 for(i++; i < v_seg_no; i++)
2187 copy(this->segment[i], v->segment[i], 1 << i);
2188 copy(this->segment[i], v->segment[i], v->early_size - (1 << i));
2191 this->early_size = v_size;
2194 /* ?_Internal_grow_by@_Concurrent_vector_base_v4@details@Concurrency@@IAEIIIP6AXPAXPBXI@Z1@Z */
2195 /* ?_Internal_grow_by@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_K_K0P6AXPEAXPEBX0@Z2@Z */
2196 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_grow_by, 20)
2197 MSVCP_size_t __thiscall _Concurrent_vector_base_v4__Internal_grow_by(
2198 _Concurrent_vector_base_v4 *this, MSVCP_size_t count, MSVCP_size_t element_size,
2199 void (__cdecl *copy)(void*, const void*, MSVCP_size_t), const void *v)
2201 MSVCP_size_t size, seg_no, last_seg_no, remain_size;
2203 TRACE("(%p %ld %ld %p %p)\n", this, count, element_size, copy, v);
2205 if(count == 0) return this->early_size;
2206 do {
2207 size = this->early_size;
2208 _Concurrent_vector_base_v4__Internal_reserve(this, size + count, element_size,
2209 MSVCP_SIZE_T_MAX / element_size);
2210 } while(InterlockedCompareExchangeSizeT(&this->early_size, size + count, size) != size);
2212 seg_no = size ? _vector_base_v4__Segment_index_of(size - 1) : 0;
2213 last_seg_no = _vector_base_v4__Segment_index_of(size + count - 1);
2214 remain_size = min(size + count, 1 << (seg_no + 1)) - size;
2215 if(remain_size > 0)
2216 copy(((BYTE**)this->segment[seg_no] + element_size * (size - ((1 << seg_no) & ~1))), v,
2217 remain_size);
2218 if(seg_no != last_seg_no)
2220 for(seg_no++; seg_no < last_seg_no; seg_no++)
2221 copy(this->segment[seg_no], v, 1 << seg_no);
2222 copy(this->segment[last_seg_no], v, size + count - (1 << last_seg_no));
2224 return size;
2227 /* ?_Internal_grow_to_at_least_with_result@_Concurrent_vector_base_v4@details@Concurrency@@IAEIIIP6AXPAXPBXI@Z1@Z */
2228 /* ?_Internal_grow_to_at_least_with_result@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_K_K0P6AXPEAXPEBX0@Z2@Z */
2229 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result, 20)
2230 MSVCP_size_t __thiscall _Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result(
2231 _Concurrent_vector_base_v4 *this, MSVCP_size_t count, MSVCP_size_t element_size,
2232 void (__cdecl *copy)(void*, const void*, MSVCP_size_t), const void *v)
2234 MSVCP_size_t size, seg_no, last_seg_no, remain_size;
2236 TRACE("(%p %ld %ld %p %p)\n", this, count, element_size, copy, v);
2238 _Concurrent_vector_base_v4__Internal_reserve(this, count, element_size,
2239 MSVCP_SIZE_T_MAX / element_size);
2240 do {
2241 size = this->early_size;
2242 if(size >= count) return size;
2243 } while(InterlockedCompareExchangeSizeT(&this->early_size, count, size) != size);
2245 seg_no = size ? _vector_base_v4__Segment_index_of(size - 1) : 0;
2246 last_seg_no = _vector_base_v4__Segment_index_of(count - 1);
2247 remain_size = min(count, 1 << (seg_no + 1)) - size;
2248 if(remain_size > 0)
2249 copy(((BYTE**)this->segment[seg_no] + element_size * (size - ((1 << seg_no) & ~1))), v,
2250 remain_size);
2251 if(seg_no != last_seg_no)
2253 for(seg_no++; seg_no < last_seg_no; seg_no++)
2254 copy(this->segment[seg_no], v, 1 << seg_no);
2255 copy(this->segment[last_seg_no], v, count - (1 << last_seg_no));
2257 return size;
2260 /* ?_Internal_push_back@_Concurrent_vector_base_v4@details@Concurrency@@IAEPAXIAAI@Z */
2261 /* ?_Internal_push_back@_Concurrent_vector_base_v4@details@Concurrency@@IEAAPEAX_KAEA_K@Z */
2262 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_push_back, 12)
2263 void * __thiscall _Concurrent_vector_base_v4__Internal_push_back(
2264 _Concurrent_vector_base_v4 *this, MSVCP_size_t element_size, MSVCP_size_t *idx)
2266 MSVCP_size_t index, seg, segment_base;
2267 void *data;
2269 TRACE("(%p %ld %p)\n", this, element_size, idx);
2271 do {
2272 index = this->early_size;
2273 _Concurrent_vector_base_v4__Internal_reserve(this, index + 1,
2274 element_size, MSVCP_SIZE_T_MAX / element_size);
2275 } while(InterlockedCompareExchangeSizeT(&this->early_size, index + 1, index) != index);
2276 seg = _vector_base_v4__Segment_index_of(index);
2277 segment_base = (seg == 0) ? 0 : (1 << seg);
2278 data = (BYTE*)this->segment[seg] + element_size * (index - segment_base);
2279 *idx = index;
2281 return data;
2284 /* ?_Internal_resize@_Concurrent_vector_base_v4@details@Concurrency@@IAEXIIIP6AXPAXI@ZP6AX0PBXI@Z2@Z */
2285 /* ?_Internal_resize@_Concurrent_vector_base_v4@details@Concurrency@@IEAAX_K00P6AXPEAX0@ZP6AX1PEBX0@Z3@Z */
2286 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_resize, 28)
2287 void __thiscall _Concurrent_vector_base_v4__Internal_resize(
2288 _Concurrent_vector_base_v4 *this, MSVCP_size_t resize, MSVCP_size_t element_size,
2289 MSVCP_size_t max_size, void (__cdecl *clear)(void*, MSVCP_size_t),
2290 void (__cdecl *copy)(void*, const void*, MSVCP_size_t), const void *v)
2292 MSVCP_size_t size, seg_no, end_seg_no, clear_element;
2294 TRACE("(%p %ld %ld %ld %p %p %p)\n", this, resize, element_size, max_size, clear, copy, v);
2296 if(resize > max_size) _vector_base_v4__Internal_throw_exception(this, 0);
2297 size = this->early_size;
2298 if(resize > size)
2299 _Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result(this,
2300 resize, element_size, copy, v);
2301 else if(resize == 0)
2302 _Concurrent_vector_base_v4__Internal_clear(this, clear);
2303 else if(resize < size)
2305 seg_no = _vector_base_v4__Segment_index_of(size - 1);
2306 end_seg_no = _vector_base_v4__Segment_index_of(resize - 1);
2307 clear_element = size - (seg_no ? 1 << seg_no : 2);
2308 if(clear_element > 0)
2309 clear(this->segment[seg_no], clear_element);
2310 if(seg_no) seg_no--;
2311 for(; seg_no > end_seg_no; seg_no--)
2312 clear(this->segment[seg_no], 1 << seg_no);
2313 clear_element = (1 << (end_seg_no + 1)) - resize;
2314 if(clear_element > 0)
2315 clear((BYTE**)this->segment[end_seg_no] + element_size * (resize - ((1 << end_seg_no) & ~1)),
2316 clear_element);
2317 this->early_size = resize;
2321 /* ?_Internal_swap@_Concurrent_vector_base_v4@details@Concurrency@@IAEXAAV123@@Z */
2322 /* ?_Internal_swap@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEAV123@@Z */
2323 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_swap, 8)
2324 void __thiscall _Concurrent_vector_base_v4__Internal_swap(
2325 _Concurrent_vector_base_v4 *this, _Concurrent_vector_base_v4 *v)
2327 _Concurrent_vector_base_v4 temp;
2329 TRACE("(%p %p)\n", this, v);
2331 temp = *this;
2332 *this = *v;
2333 *v = temp;
2334 if(v->segment == this->storage)
2335 v->segment = v->storage;
2336 if(this->segment == v->storage)
2337 this->segment = this->storage;
2339 #endif
2341 #ifndef __GNUC__
2342 void __asm_dummy_vtables(void) {
2343 #endif
2344 #if _MSVCP_VER == 100
2345 __ASM_VTABLE(iostream_category,
2346 VTABLE_ADD_FUNC(custom_category_vector_dtor)
2347 VTABLE_ADD_FUNC(custom_category_name)
2348 VTABLE_ADD_FUNC(iostream_category_message)
2349 VTABLE_ADD_FUNC(custom_category_default_error_condition)
2350 VTABLE_ADD_FUNC(custom_category_equivalent)
2351 VTABLE_ADD_FUNC(custom_category_equivalent_code));
2352 __ASM_VTABLE(system_category,
2353 VTABLE_ADD_FUNC(custom_category_vector_dtor)
2354 VTABLE_ADD_FUNC(custom_category_name)
2355 VTABLE_ADD_FUNC(custom_category_message)
2356 VTABLE_ADD_FUNC(custom_category_default_error_condition)
2357 VTABLE_ADD_FUNC(custom_category_equivalent)
2358 VTABLE_ADD_FUNC(custom_category_equivalent_code));
2359 __ASM_VTABLE(generic_category,
2360 VTABLE_ADD_FUNC(custom_category_vector_dtor)
2361 VTABLE_ADD_FUNC(custom_category_name)
2362 VTABLE_ADD_FUNC(custom_category_message)
2363 VTABLE_ADD_FUNC(custom_category_default_error_condition)
2364 VTABLE_ADD_FUNC(custom_category_equivalent)
2365 VTABLE_ADD_FUNC(custom_category_equivalent_code));
2366 #endif
2367 #if _MSVCP_VER >= 100
2368 __ASM_VTABLE(_Concurrent_queue_base_v4,
2369 #if _MSVCP_VER >= 110
2370 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
2371 #endif
2372 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
2373 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
2374 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_vector_dtor)
2375 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
2376 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy));
2377 __ASM_VTABLE(_Runtime_object,
2378 VTABLE_ADD_FUNC(_Runtime_object__GetId));
2379 #endif
2380 #if _MSVCP_VER >= 110
2381 __ASM_VTABLE(_Pad,
2382 VTABLE_ADD_FUNC(_Pad__Go));
2383 #endif
2384 #ifndef __GNUC__
2386 #endif
2388 /*********************************************************************
2389 * __crtInitializeCriticalSectionEx (MSVCP140.@)
2391 BOOL CDECL MSVCP__crtInitializeCriticalSectionEx(
2392 CRITICAL_SECTION *cs, DWORD spin_count, DWORD flags)
2394 TRACE("(%p %x %x)\n", cs, spin_count, flags);
2395 return InitializeCriticalSectionEx(cs, spin_count, flags);
2398 /*********************************************************************
2399 * __crtCreateEventExW (MSVCP140.@)
2401 HANDLE CDECL MSVCP__crtCreateEventExW(
2402 SECURITY_ATTRIBUTES *attribs, LPCWSTR name, DWORD flags, DWORD access)
2404 TRACE("(%p %s 0x%08x 0x%08x)\n", attribs, debugstr_w(name), flags, access);
2405 return CreateEventExW(attribs, name, flags, access);
2408 /*********************************************************************
2409 * __crtGetTickCount64 (MSVCP140.@)
2411 ULONGLONG CDECL MSVCP__crtGetTickCount64(void)
2413 return GetTickCount64();
2416 /*********************************************************************
2417 * __crtGetCurrentProcessorNumber (MSVCP140.@)
2419 DWORD CDECL MSVCP__crtGetCurrentProcessorNumber(void)
2421 return GetCurrentProcessorNumber();
2424 /*********************************************************************
2425 * __crtFlushProcessWriteBuffers (MSVCP140.@)
2427 VOID CDECL MSVCP__crtFlushProcessWriteBuffers(void)
2429 return FlushProcessWriteBuffers();
2432 /*********************************************************************
2433 * __crtCreateSemaphoreExW (MSVCP140.@)
2435 HANDLE CDECL MSVCP__crtCreateSemaphoreExW(
2436 SECURITY_ATTRIBUTES *attribs, LONG initial_count, LONG max_count, LPCWSTR name,
2437 DWORD flags, DWORD access)
2439 TRACE("(%p %d %d %s 0x%08x 0x%08x)\n", attribs, initial_count, max_count, debugstr_w(name),
2440 flags, access);
2441 return CreateSemaphoreExW(attribs, initial_count, max_count, name, flags, access);
2444 /*********************************************************************
2445 * __crtCreateThreadpoolTimer (MSVCP140.@)
2447 PTP_TIMER CDECL MSVCP__crtCreateThreadpoolTimer(PTP_TIMER_CALLBACK callback,
2448 PVOID userdata, TP_CALLBACK_ENVIRON *environment)
2450 TRACE("(%p %p %p)\n", callback, userdata, environment);
2451 return CreateThreadpoolTimer(callback, userdata, environment);
2454 /*********************************************************************
2455 * __crtCloseThreadpoolTimer (MSVCP140.@)
2457 VOID CDECL MSVCP__crtCloseThreadpoolTimer(TP_TIMER *timer)
2459 TRACE("(%p)\n", timer);
2460 CloseThreadpoolTimer(timer);
2463 /*********************************************************************
2464 * __crtSetThreadpoolTimer (MSVCP140.@)
2466 VOID CDECL MSVCP__crtSetThreadpoolTimer(TP_TIMER *timer,
2467 FILETIME *due_time, DWORD period, DWORD window_length)
2469 TRACE("(%p %p 0x%08x 0x%08x)\n", timer, due_time, period, window_length);
2470 return SetThreadpoolTimer(timer, due_time, period, window_length);
2473 /*********************************************************************
2474 * __crtWaitForThreadpoolTimerCallbacks (MSVCP140.@)
2476 VOID CDECL MSVCP__crtWaitForThreadpoolTimerCallbacks(TP_TIMER *timer, BOOL cancel)
2478 TRACE("(%p %d)\n", timer, cancel);
2479 WaitForThreadpoolTimerCallbacks(timer, cancel);
2482 /*********************************************************************
2483 * __crtCreateThreadpoolWait (MSVCP140.@)
2485 PTP_WAIT CDECL MSVCP__crtCreateThreadpoolWait(PTP_WAIT_CALLBACK callback,
2486 PVOID userdata, TP_CALLBACK_ENVIRON *environment)
2488 TRACE("(%p %p %p)\n", callback, userdata, environment);
2489 return CreateThreadpoolWait(callback, userdata, environment);
2492 /*********************************************************************
2493 * __crtCloseThreadpoolWait (MSVCP140.@)
2495 VOID CDECL MSVCP__crtCloseThreadpoolWait(TP_WAIT *wait)
2497 TRACE("(%p)\n", wait);
2498 CloseThreadpoolWait(wait);
2501 /*********************************************************************
2502 * __crtSetThreadpoolWait (MSVCP140.@)
2504 VOID CDECL MSVCP__crtSetThreadpoolWait(TP_WAIT *wait, HANDLE handle, FILETIME *due_time)
2506 TRACE("(%p %p %p)\n", wait, handle, due_time);
2507 return SetThreadpoolWait(wait, handle, due_time);
2510 /*********************************************************************
2511 * __crtFreeLibraryWhenCallbackReturns (MSVCP140.@)
2513 VOID CDECL MSVCP__crtFreeLibraryWhenCallbackReturns(PTP_CALLBACK_INSTANCE instance, HMODULE mod)
2515 TRACE("(%p %p)\n", instance, mod);
2516 FreeLibraryWhenCallbackReturns(instance, mod);
2519 /* ?_Execute_once@std@@YAHAAUonce_flag@1@P6GHPAX1PAPAX@Z1@Z */
2520 /* ?_Execute_once@std@@YAHAEAUonce_flag@1@P6AHPEAX1PEAPEAX@Z1@Z */
2521 BOOL __cdecl _Execute_once(INIT_ONCE *flag, PINIT_ONCE_FN func, void *param)
2523 return InitOnceExecuteOnce(flag, func, param, NULL);
2526 #if _MSVCP_VER >= 100
2527 void init_misc(void *base)
2529 #ifdef __x86_64__
2530 #if _MSVCP_VER == 100
2531 init_error_category_rtti(base);
2532 init_iostream_category_rtti(base);
2533 init_system_category_rtti(base);
2534 init_generic_category_rtti(base);
2535 #endif
2536 #if _MSVCP_VER >= 100
2537 init__Concurrent_queue_base_v4_rtti(base);
2538 init__Runtime_object_rtti(base);
2539 #endif
2540 #if _MSVCP_VER >= 110
2541 init__Pad_rtti(base);
2542 #endif
2543 #endif
2545 #if _MSVCP_VER == 100
2546 iostream_category_ctor(&iostream_category);
2547 system_category_ctor(&system_category);
2548 generic_category_ctor(&generic_category);
2549 #endif
2552 void free_misc(void)
2554 #if _MSVCP_VER >= 110
2555 if(keyed_event)
2556 NtClose(keyed_event);
2557 HeapFree(GetProcessHeap(), 0, broadcast_at_thread_exit.to_broadcast);
2558 #endif
2560 #endif
2562 #if _MSVCP_VER >= 140
2563 LONGLONG __cdecl _Query_perf_counter(void)
2565 LARGE_INTEGER li;
2566 QueryPerformanceCounter(&li);
2567 return li.QuadPart;
2570 LONGLONG __cdecl _Query_perf_frequency(void)
2572 LARGE_INTEGER li;
2573 QueryPerformanceFrequency(&li);
2574 return li.QuadPart;
2576 #endif
2578 void __cdecl threads__Mtx_new(void **mtx)
2580 *mtx = MSVCRT_operator_new(sizeof(CRITICAL_SECTION));
2581 InitializeCriticalSection(*mtx);
2584 void __cdecl threads__Mtx_delete(void *mtx)
2586 DeleteCriticalSection(mtx);
2589 void __cdecl threads__Mtx_lock(void *mtx)
2591 EnterCriticalSection(mtx);
2594 void __cdecl threads__Mtx_unlock(void *mtx)
2596 LeaveCriticalSection(mtx);
2599 #if _MSVCP_VER >= 110
2600 static LONG shared_ptr_lock;
2602 void __cdecl _Lock_shared_ptr_spin_lock(void)
2604 LONG l = 0;
2606 while(InterlockedCompareExchange(&shared_ptr_lock, 1, 0) != 0) {
2607 if(l++ == 1000) {
2608 Sleep(0);
2609 l = 0;
2614 void __cdecl _Unlock_shared_ptr_spin_lock(void)
2616 shared_ptr_lock = 0;
2618 #endif
2620 #if _MSVCP_VER >= 100
2621 /* ?is_current_task_group_canceling@Concurrency@@YA_NXZ */
2622 MSVCP_bool __cdecl is_current_task_group_canceling(void)
2624 return Context_IsCurrentTaskCollectionCanceling();
2627 /* ?_GetCombinableSize@details@Concurrency@@YAIXZ */
2628 /* ?_GetCombinableSize@details@Concurrency@@YA_KXZ */
2629 MSVCP_size_t __cdecl _GetCombinableSize(void)
2631 FIXME("() stub\n");
2632 return 11;
2634 #endif
2636 #if _MSVCP_VER >= 140
2637 typedef struct {
2638 void *unk0;
2639 BYTE unk1;
2640 } task_continuation_context;
2642 /* ??0task_continuation_context@Concurrency@@AAE@XZ */
2643 /* ??0task_continuation_context@Concurrency@@AEAA@XZ */
2644 DEFINE_THISCALL_WRAPPER(task_continuation_context_ctor, 4)
2645 task_continuation_context* __thiscall task_continuation_context_ctor(task_continuation_context *this)
2647 TRACE("(%p)\n", this);
2648 memset(this, 0, sizeof(*this));
2649 return this;
2652 typedef struct {
2653 const vtable_ptr *vtable;
2654 void (__cdecl *func)(void);
2655 int unk[4];
2656 void *unk2[3];
2657 void *this;
2658 } function_void_cdecl_void;
2660 /* ?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z */
2661 /* ?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z */
2662 DEFINE_THISCALL_WRAPPER(_ContextCallback__Assign, 8)
2663 void __thiscall _ContextCallback__Assign(void *this, void *v)
2665 TRACE("(%p %p)\n", this, v);
2668 #define call_function_do_call(this) CALL_VTBL_FUNC(this, 8, void, (function_void_cdecl_void*), (this))
2669 #define call_function_do_clean(this,b) CALL_VTBL_FUNC(this, 16, void, (function_void_cdecl_void*,MSVCP_bool), (this, b))
2670 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z */
2671 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z */
2672 DEFINE_THISCALL_WRAPPER(_ContextCallback__CallInContext, 48)
2673 void __thiscall _ContextCallback__CallInContext(const void *this, function_void_cdecl_void func, MSVCP_bool b)
2675 TRACE("(%p %p %x)\n", this, func.func, b);
2676 call_function_do_call(func.this);
2677 call_function_do_clean(func.this, func.this!=&func);
2680 /* ?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ */
2681 /* ?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ */
2682 DEFINE_THISCALL_WRAPPER(_ContextCallback__Capture, 4)
2683 void __thiscall _ContextCallback__Capture(void *this)
2685 TRACE("(%p)\n", this);
2688 /* ?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ */
2689 /* ?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ */
2690 DEFINE_THISCALL_WRAPPER(_ContextCallback__Reset, 4)
2691 void __thiscall _ContextCallback__Reset(void *this)
2693 TRACE("(%p)\n", this);
2696 /* ?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ */
2697 MSVCP_bool __cdecl _ContextCallback__IsCurrentOriginSTA(void *this)
2699 TRACE("(%p)\n", this);
2700 return FALSE;
2703 typedef struct {
2704 /*_Task_impl_base*/void *task;
2705 MSVCP_bool scheduled;
2706 MSVCP_bool started;
2707 } _TaskEventLogger;
2709 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2710 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2711 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogCancelTask, 4)
2712 void __thiscall _TaskEventLogger__LogCancelTask(_TaskEventLogger *this)
2714 TRACE("(%p)\n", this);
2717 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z */
2718 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z */
2719 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogScheduleTask, 8)
2720 void __thiscall _TaskEventLogger__LogScheduleTask(_TaskEventLogger *this, MSVCP_bool continuation)
2722 TRACE("(%p %x)\n", this, continuation);
2725 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2726 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2727 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskCompleted, 4)
2728 void __thiscall _TaskEventLogger__LogTaskCompleted(_TaskEventLogger *this)
2730 TRACE("(%p)\n", this);
2733 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2734 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2735 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskExecutionCompleted, 4)
2736 void __thiscall _TaskEventLogger__LogTaskExecutionCompleted(_TaskEventLogger *this)
2738 TRACE("(%p)\n", this);
2741 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2742 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2743 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemCompleted, 4)
2744 void __thiscall _TaskEventLogger__LogWorkItemCompleted(_TaskEventLogger *this)
2746 TRACE("(%p)\n", this);
2749 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2750 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2751 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemStarted, 4)
2752 void __thiscall _TaskEventLogger__LogWorkItemStarted(_TaskEventLogger *this)
2754 TRACE("(%p)\n", this);
2757 typedef struct {
2758 PTP_WORK work;
2759 void (__cdecl *callback)(void*);
2760 void *arg;
2761 } _Threadpool_chore;
2763 /* ?_Reschedule_chore@details@Concurrency@@YAHPBU_Threadpool_chore@12@@Z */
2764 /* ?_Reschedule_chore@details@Concurrency@@YAHPEBU_Threadpool_chore@12@@Z */
2765 int __cdecl _Reschedule_chore(const _Threadpool_chore *chore)
2767 TRACE("(%p)\n", chore);
2769 SubmitThreadpoolWork(chore->work);
2770 return 0;
2773 static void WINAPI threadpool_callback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work)
2775 _Threadpool_chore *chore = context;
2776 TRACE("calling chore callback: %p\n", chore);
2777 if (chore->callback)
2778 chore->callback(chore->arg);
2781 /* ?_Schedule_chore@details@Concurrency@@YAHPAU_Threadpool_chore@12@@Z */
2782 /* ?_Schedule_chore@details@Concurrency@@YAHPEAU_Threadpool_chore@12@@Z */
2783 int __cdecl _Schedule_chore(_Threadpool_chore *chore)
2785 TRACE("(%p)\n", chore);
2787 chore->work = CreateThreadpoolWork(threadpool_callback, chore, NULL);
2788 /* FIXME: what should be returned in case of error */
2789 if(!chore->work)
2790 return -1;
2792 return _Reschedule_chore(chore);
2795 /* ?_Release_chore@details@Concurrency@@YAXPAU_Threadpool_chore@12@@Z */
2796 /* ?_Release_chore@details@Concurrency@@YAXPEAU_Threadpool_chore@12@@Z */
2797 void __cdecl _Release_chore(_Threadpool_chore *chore)
2799 TRACE("(%p)\n", chore);
2801 if(!chore->work) return;
2802 CloseThreadpoolWork(chore->work);
2803 chore->work = NULL;
2805 #endif
2807 #if _MSVCP_VER >= 110 && _MSVCP_VER <= 120
2808 typedef struct {
2809 char dummy;
2810 } _Ph;
2812 /* ?_1@placeholders@std@@3V?$_Ph@$00@2@A */
2813 /* ?_20@placeholders@std@@3V?$_Ph@$0BE@@2@A */
2814 _Ph _Ph_1 = {0}, _Ph_2 = {0}, _Ph_3 = {0}, _Ph_4 = {0}, _Ph_5 = {0};
2815 _Ph _Ph_6 = {0}, _Ph_7 = {0}, _Ph_8 = {0}, _Ph_9 = {0}, _Ph_10 = {0};
2816 _Ph _Ph_11 = {0}, _Ph_12 = {0}, _Ph_13 = {0}, _Ph_14 = {0}, _Ph_15 = {0};
2817 _Ph _Ph_16 = {0}, _Ph_17 = {0}, _Ph_18 = {0}, _Ph_19 = {0}, _Ph_20 = {0};
2818 #endif
2820 #if _MSVCP_VER >= 140
2821 /* ?_IsNonBlockingThread@_Task_impl_base@details@Concurrency@@SA_NXZ */
2822 MSVCP_bool __cdecl _Task_impl_base__IsNonBlockingThread(void)
2824 FIXME("() stub\n");
2825 return FALSE;
2827 #endif
2829 #if _MSVCP_VER >= 110
2830 /* ?_Syserror_map@std@@YAPBDH@Z */
2831 /* ?_Syserror_map@std@@YAPEBDH@Z */
2832 const char* __cdecl _Syserror_map(int err)
2834 int i;
2836 TRACE("(%d)\n", err);
2838 for(i = 0; i < ARRAY_SIZE(syserror_map); i++)
2840 if(syserror_map[i].err == err)
2841 return syserror_map[i].str;
2843 return NULL;
2845 #endif
2847 #if _MSVCP_VER >= 140
2848 /* ?_Winerror_message@std@@YAKKPADK@Z */
2849 /* ?_Winerror_message@std@@YAKKPEADK@Z */
2850 ULONG __cdecl _Winerror_message(ULONG err, char *buf, ULONG size)
2852 TRACE("(%u %p %u)\n", err, buf, size);
2854 return FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
2855 NULL, err, 0, buf, size, NULL);
2858 /* ?_Winerror_map@std@@YAHH@Z */
2859 int __cdecl _Winerror_map(int err)
2861 int low = 0, high = ARRAY_SIZE(winerror_map) - 1, mid;
2863 while(low <= high)
2865 mid = (low + high) / 2;
2867 if(err == winerror_map[mid].winerr)
2868 return winerror_map[mid].doserr;
2869 if(err > winerror_map[mid].winerr)
2870 low = mid + 1;
2871 else
2872 high = mid - 1;
2875 return 0;
2877 #endif