wined3d: Pass a wined3d_context_gl structure to context_check_fbo_status().
[wine.git] / dlls / msvcp90 / misc.c
blobdac6a96564c2d0ac07aee29c5bc0d318f7482254
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 const 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 const 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_PLAIN 0x1
685 #define MTX_TRY 0x2
686 #define MTX_TIMED 0x4
687 #define MTX_RECURSIVE 0x100
688 #define MTX_LOCKED 3
689 typedef struct
691 DWORD flags;
692 critical_section cs;
693 DWORD thread_id;
694 DWORD count;
695 } *_Mtx_t;
697 #if _MSVCP_VER >= 140
698 typedef _Mtx_t _Mtx_arg_t;
699 #define MTX_T_FROM_ARG(m) (m)
700 #define MTX_T_TO_ARG(m) (m)
701 #else
702 typedef _Mtx_t *_Mtx_arg_t;
703 #define MTX_T_FROM_ARG(m) (*(m))
704 #define MTX_T_TO_ARG(m) (&(m))
705 #endif
707 void __cdecl _Mtx_init_in_situ(_Mtx_t mtx, int flags)
709 if(flags & ~(MTX_PLAIN | MTX_TRY | MTX_TIMED | MTX_RECURSIVE))
710 FIXME("unknown flags ignored: %x\n", flags);
712 mtx->flags = flags;
713 call_func1(critical_section_ctor, &mtx->cs);
714 mtx->thread_id = -1;
715 mtx->count = 0;
718 int __cdecl _Mtx_init(_Mtx_t *mtx, int flags)
720 *mtx = MSVCRT_operator_new(sizeof(**mtx));
721 _Mtx_init_in_situ(*mtx, flags);
722 return 0;
725 void __cdecl _Mtx_destroy_in_situ(_Mtx_t mtx)
727 call_func1(critical_section_dtor, &mtx->cs);
730 void __cdecl _Mtx_destroy(_Mtx_arg_t mtx)
732 call_func1(critical_section_dtor, &MTX_T_FROM_ARG(mtx)->cs);
733 MSVCRT_operator_delete(MTX_T_FROM_ARG(mtx));
736 int __cdecl _Mtx_current_owns(_Mtx_arg_t mtx)
738 return MTX_T_FROM_ARG(mtx)->thread_id == GetCurrentThreadId();
741 int __cdecl _Mtx_lock(_Mtx_arg_t mtx)
743 if(MTX_T_FROM_ARG(mtx)->thread_id != GetCurrentThreadId()) {
744 call_func1(critical_section_lock, &MTX_T_FROM_ARG(mtx)->cs);
745 MTX_T_FROM_ARG(mtx)->thread_id = GetCurrentThreadId();
746 }else if(!(MTX_T_FROM_ARG(mtx)->flags & MTX_RECURSIVE)
747 && MTX_T_FROM_ARG(mtx)->flags != MTX_PLAIN) {
748 return MTX_LOCKED;
751 MTX_T_FROM_ARG(mtx)->count++;
752 return 0;
755 int __cdecl _Mtx_unlock(_Mtx_arg_t mtx)
757 if(--MTX_T_FROM_ARG(mtx)->count)
758 return 0;
760 MTX_T_FROM_ARG(mtx)->thread_id = -1;
761 call_func1(critical_section_unlock, &MTX_T_FROM_ARG(mtx)->cs);
762 return 0;
765 int __cdecl _Mtx_trylock(_Mtx_arg_t mtx)
767 if(MTX_T_FROM_ARG(mtx)->thread_id != GetCurrentThreadId()) {
768 if(!call_func1(critical_section_trylock, &MTX_T_FROM_ARG(mtx)->cs))
769 return MTX_LOCKED;
770 MTX_T_FROM_ARG(mtx)->thread_id = GetCurrentThreadId();
771 }else if(!(MTX_T_FROM_ARG(mtx)->flags & MTX_RECURSIVE)
772 && MTX_T_FROM_ARG(mtx)->flags != MTX_PLAIN) {
773 return MTX_LOCKED;
776 MTX_T_FROM_ARG(mtx)->count++;
777 return 0;
780 critical_section* __cdecl _Mtx_getconcrtcs(_Mtx_arg_t mtx)
782 return &MTX_T_FROM_ARG(mtx)->cs;
785 static inline LONG interlocked_dec_if_nonzero( LONG *dest )
787 LONG val, tmp;
788 for (val = *dest;; val = tmp)
790 if (!val || (tmp = InterlockedCompareExchange( dest, val - 1, val )) == val)
791 break;
793 return val;
796 #define CND_TIMEDOUT 2
798 typedef struct
800 CONDITION_VARIABLE cv;
801 } *_Cnd_t;
803 #if _MSVCP_VER >= 140
804 typedef _Cnd_t _Cnd_arg_t;
805 #define CND_T_FROM_ARG(c) (c)
806 #define CND_T_TO_ARG(c) (c)
807 #else
808 typedef _Cnd_t *_Cnd_arg_t;
809 #define CND_T_FROM_ARG(c) (*(c))
810 #define CND_T_TO_ARG(c) (&(c))
811 #endif
813 static HANDLE keyed_event;
815 void __cdecl _Cnd_init_in_situ(_Cnd_t cnd)
817 InitializeConditionVariable(&cnd->cv);
819 if(!keyed_event) {
820 HANDLE event;
822 NtCreateKeyedEvent(&event, GENERIC_READ|GENERIC_WRITE, NULL, 0);
823 if(InterlockedCompareExchangePointer(&keyed_event, event, NULL) != NULL)
824 NtClose(event);
828 int __cdecl _Cnd_init(_Cnd_t *cnd)
830 *cnd = MSVCRT_operator_new(sizeof(**cnd));
831 _Cnd_init_in_situ(*cnd);
832 return 0;
835 int __cdecl _Cnd_wait(_Cnd_arg_t cnd, _Mtx_arg_t mtx)
837 CONDITION_VARIABLE *cv = &CND_T_FROM_ARG(cnd)->cv;
839 InterlockedExchangeAdd( (LONG *)&cv->Ptr, 1 );
840 _Mtx_unlock(mtx);
842 NtWaitForKeyedEvent(keyed_event, &cv->Ptr, FALSE, NULL);
844 _Mtx_lock(mtx);
845 return 0;
848 int __cdecl _Cnd_timedwait(_Cnd_arg_t cnd, _Mtx_arg_t mtx, const xtime *xt)
850 CONDITION_VARIABLE *cv = &CND_T_FROM_ARG(cnd)->cv;
851 LARGE_INTEGER timeout;
852 NTSTATUS status;
854 InterlockedExchangeAdd( (LONG *)&cv->Ptr, 1 );
855 _Mtx_unlock(mtx);
857 timeout.QuadPart = (ULONGLONG)(ULONG)_Xtime_diff_to_millis(xt) * -10000;
858 status = NtWaitForKeyedEvent(keyed_event, &cv->Ptr, FALSE, &timeout);
859 if (status)
861 if (!interlocked_dec_if_nonzero( (LONG *)&cv->Ptr ))
862 status = NtWaitForKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
865 _Mtx_lock(mtx);
866 return status ? CND_TIMEDOUT : 0;
869 int __cdecl _Cnd_broadcast(_Cnd_arg_t cnd)
871 CONDITION_VARIABLE *cv = &CND_T_FROM_ARG(cnd)->cv;
872 LONG val = InterlockedExchange( (LONG *)&cv->Ptr, 0 );
873 while (val-- > 0)
874 NtReleaseKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
875 return 0;
878 int __cdecl _Cnd_signal(_Cnd_arg_t cnd)
880 CONDITION_VARIABLE *cv = &CND_T_FROM_ARG(cnd)->cv;
881 if (interlocked_dec_if_nonzero( (LONG *)&cv->Ptr ))
882 NtReleaseKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
883 return 0;
886 void __cdecl _Cnd_destroy_in_situ(_Cnd_t cnd)
888 _Cnd_broadcast(CND_T_TO_ARG(cnd));
891 void __cdecl _Cnd_destroy(_Cnd_arg_t cnd)
893 if(cnd) {
894 _Cnd_broadcast(cnd);
895 MSVCRT_operator_delete(CND_T_FROM_ARG(cnd));
899 static struct {
900 int used;
901 int size;
903 struct _to_broadcast {
904 DWORD thread_id;
905 _Cnd_arg_t cnd;
906 _Mtx_arg_t mtx;
907 int *p;
908 } *to_broadcast;
909 } broadcast_at_thread_exit;
911 static CRITICAL_SECTION broadcast_at_thread_exit_cs;
912 static CRITICAL_SECTION_DEBUG broadcast_at_thread_exit_cs_debug =
914 0, 0, &broadcast_at_thread_exit_cs,
915 { &broadcast_at_thread_exit_cs_debug.ProcessLocksList, &broadcast_at_thread_exit_cs_debug.ProcessLocksList },
916 0, 0, { (DWORD_PTR)(__FILE__ ": broadcast_at_thread_exit_cs") }
918 static CRITICAL_SECTION broadcast_at_thread_exit_cs = { &broadcast_at_thread_exit_cs_debug, -1, 0, 0, 0, 0 };
920 void __cdecl _Cnd_register_at_thread_exit(_Cnd_arg_t cnd, _Mtx_arg_t mtx, int *p)
922 struct _to_broadcast *add;
924 TRACE("(%p %p %p)\n", cnd, mtx, p);
926 EnterCriticalSection(&broadcast_at_thread_exit_cs);
927 if(!broadcast_at_thread_exit.size) {
928 broadcast_at_thread_exit.to_broadcast = HeapAlloc(GetProcessHeap(),
929 0, 8*sizeof(broadcast_at_thread_exit.to_broadcast[0]));
930 if(!broadcast_at_thread_exit.to_broadcast) {
931 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
932 return;
934 broadcast_at_thread_exit.size = 8;
935 } else if(broadcast_at_thread_exit.size == broadcast_at_thread_exit.used) {
936 add = HeapReAlloc(GetProcessHeap(), 0, broadcast_at_thread_exit.to_broadcast,
937 broadcast_at_thread_exit.size*2*sizeof(broadcast_at_thread_exit.to_broadcast[0]));
938 if(!add) {
939 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
940 return;
942 broadcast_at_thread_exit.to_broadcast = add;
943 broadcast_at_thread_exit.size *= 2;
946 add = broadcast_at_thread_exit.to_broadcast + broadcast_at_thread_exit.used++;
947 add->thread_id = GetCurrentThreadId();
948 add->cnd = cnd;
949 add->mtx = mtx;
950 add->p = p;
951 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
954 void __cdecl _Cnd_unregister_at_thread_exit(_Mtx_arg_t mtx)
956 int i;
958 TRACE("(%p)\n", mtx);
960 EnterCriticalSection(&broadcast_at_thread_exit_cs);
961 for(i=0; i<broadcast_at_thread_exit.used; i++) {
962 if(broadcast_at_thread_exit.to_broadcast[i].mtx != mtx)
963 continue;
965 memmove(broadcast_at_thread_exit.to_broadcast+i, broadcast_at_thread_exit.to_broadcast+i+1,
966 (broadcast_at_thread_exit.used-i-1)*sizeof(broadcast_at_thread_exit.to_broadcast[0]));
967 broadcast_at_thread_exit.used--;
968 i--;
970 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
973 void __cdecl _Cnd_do_broadcast_at_thread_exit(void)
975 int i, id = GetCurrentThreadId();
977 TRACE("()\n");
979 EnterCriticalSection(&broadcast_at_thread_exit_cs);
980 for(i=0; i<broadcast_at_thread_exit.used; i++) {
981 if(broadcast_at_thread_exit.to_broadcast[i].thread_id != id)
982 continue;
984 _Mtx_unlock(broadcast_at_thread_exit.to_broadcast[i].mtx);
985 _Cnd_broadcast(broadcast_at_thread_exit.to_broadcast[i].cnd);
986 if(broadcast_at_thread_exit.to_broadcast[i].p)
987 *broadcast_at_thread_exit.to_broadcast[i].p = 1;
989 memmove(broadcast_at_thread_exit.to_broadcast+i, broadcast_at_thread_exit.to_broadcast+i+1,
990 (broadcast_at_thread_exit.used-i-1)*sizeof(broadcast_at_thread_exit.to_broadcast[0]));
991 broadcast_at_thread_exit.used--;
992 i--;
994 LeaveCriticalSection(&broadcast_at_thread_exit_cs);
997 #endif
999 #if _MSVCP_VER == 100
1000 typedef struct {
1001 const vtable_ptr *vtable;
1002 } error_category;
1004 typedef struct {
1005 error_category base;
1006 const char *type;
1007 } custom_category;
1008 static custom_category iostream_category;
1010 DEFINE_RTTI_DATA0(error_category, 0, ".?AVerror_category@std@@")
1011 DEFINE_RTTI_DATA1(iostream_category, 0, &error_category_rtti_base_descriptor, ".?AV_Iostream_error_category@std@@")
1013 extern const vtable_ptr MSVCP_iostream_category_vtable;
1015 static void iostream_category_ctor(custom_category *this)
1017 this->base.vtable = &MSVCP_iostream_category_vtable;
1018 this->type = "iostream";
1021 DEFINE_THISCALL_WRAPPER(custom_category_vector_dtor, 8)
1022 custom_category* __thiscall custom_category_vector_dtor(custom_category *this, unsigned int flags)
1024 TRACE("(%p %x)\n", this, flags);
1025 if(flags & 2) {
1026 /* we have an array, with the number of elements stored before the first object */
1027 INT_PTR i, *ptr = (INT_PTR *)this-1;
1029 for(i=*ptr-1; i>=0; i--)
1030 MSVCRT_operator_delete(ptr);
1031 } else {
1032 if(flags & 1)
1033 MSVCRT_operator_delete(this);
1036 return this;
1039 DEFINE_THISCALL_WRAPPER(custom_category_name, 4)
1040 const char* __thiscall custom_category_name(const custom_category *this)
1042 return this->type;
1045 DEFINE_THISCALL_WRAPPER(custom_category_message, 12)
1046 basic_string_char* __thiscall custom_category_message(const custom_category *this,
1047 basic_string_char *ret, int err)
1049 return MSVCP_basic_string_char_ctor_cstr(ret, strerror(err));
1052 DEFINE_THISCALL_WRAPPER(custom_category_default_error_condition, 12)
1053 /*error_condition*/void* __thiscall custom_category_default_error_condition(
1054 custom_category *this, /*error_condition*/void *ret, int code)
1056 FIXME("(%p %p %x) stub\n", this, ret, code);
1057 return NULL;
1060 DEFINE_THISCALL_WRAPPER(custom_category_equivalent, 12)
1061 MSVCP_bool __thiscall custom_category_equivalent(const custom_category *this,
1062 int code, const /*error_condition*/void *condition)
1064 FIXME("(%p %x %p) stub\n", this, code, condition);
1065 return FALSE;
1068 DEFINE_THISCALL_WRAPPER(custom_category_equivalent_code, 12)
1069 MSVCP_bool __thiscall custom_category_equivalent_code(custom_category *this,
1070 const /*error_code*/void *code, int condition)
1072 FIXME("(%p %p %x) stub\n", this, code, condition);
1073 return FALSE;
1076 DEFINE_THISCALL_WRAPPER(iostream_category_message, 12)
1077 basic_string_char* __thiscall iostream_category_message(const custom_category *this,
1078 basic_string_char *ret, int err)
1080 if(err == 1) return MSVCP_basic_string_char_ctor_cstr(ret, "iostream error");
1081 return MSVCP_basic_string_char_ctor_cstr(ret, strerror(err));
1084 /* ?iostream_category@std@@YAABVerror_category@1@XZ */
1085 /* ?iostream_category@std@@YAAEBVerror_category@1@XZ */
1086 const error_category* __cdecl std_iostream_category(void)
1088 TRACE("()\n");
1089 return &iostream_category.base;
1092 static custom_category system_category;
1093 DEFINE_RTTI_DATA1(system_category, 0, &error_category_rtti_base_descriptor, ".?AV_System_error_category@std@@")
1095 extern const vtable_ptr MSVCP_system_category_vtable;
1097 static void system_category_ctor(custom_category *this)
1099 this->base.vtable = &MSVCP_system_category_vtable;
1100 this->type = "system";
1103 /* ?system_category@std@@YAABVerror_category@1@XZ */
1104 /* ?system_category@std@@YAAEBVerror_category@1@XZ */
1105 const error_category* __cdecl std_system_category(void)
1107 TRACE("()\n");
1108 return &system_category.base;
1111 static custom_category generic_category;
1112 DEFINE_RTTI_DATA1(generic_category, 0, &error_category_rtti_base_descriptor, ".?AV_Generic_error_category@std@@")
1114 extern const vtable_ptr MSVCP_generic_category_vtable;
1116 static void generic_category_ctor(custom_category *this)
1118 this->base.vtable = &MSVCP_generic_category_vtable;
1119 this->type = "generic";
1122 /* ?generic_category@std@@YAABVerror_category@1@XZ */
1123 /* ?generic_category@std@@YAAEBVerror_category@1@XZ */
1124 const error_category* __cdecl std_generic_category(void)
1126 TRACE("()\n");
1127 return &generic_category.base;
1129 #endif
1131 #if _MSVCP_VER >= 110
1132 static CRITICAL_SECTION call_once_cs;
1133 static CRITICAL_SECTION_DEBUG call_once_cs_debug =
1135 0, 0, &call_once_cs,
1136 { &call_once_cs_debug.ProcessLocksList, &call_once_cs_debug.ProcessLocksList },
1137 0, 0, { (DWORD_PTR)(__FILE__ ": call_once_cs") }
1139 static CRITICAL_SECTION call_once_cs = { &call_once_cs_debug, -1, 0, 0, 0, 0 };
1141 void __cdecl _Call_onceEx(int *once, void (__cdecl *func)(void*), void *argv)
1143 TRACE("%p %p %p\n", once, func, argv);
1145 EnterCriticalSection(&call_once_cs);
1146 if(!*once) {
1147 /* FIXME: handle exceptions */
1148 func(argv);
1149 *once = 1;
1151 LeaveCriticalSection(&call_once_cs);
1154 static void __cdecl call_once_func_wrapper(void *func)
1156 ((void (__cdecl*)(void))func)();
1159 void __cdecl _Call_once(int *once, void (__cdecl *func)(void))
1161 TRACE("%p %p\n", once, func);
1162 _Call_onceEx(once, call_once_func_wrapper, func);
1165 void __cdecl _Do_call(void *this)
1167 CALL_VTBL_FUNC(this, 0, void, (void*), (this));
1169 #endif
1171 #if _MSVCP_VER >= 110
1172 typedef struct
1174 HANDLE hnd;
1175 DWORD id;
1176 } _Thrd_t;
1178 typedef int (__cdecl *_Thrd_start_t)(void*);
1180 #define _THRD_ERROR 4
1182 int __cdecl _Thrd_equal(_Thrd_t a, _Thrd_t b)
1184 TRACE("(%p %u %p %u)\n", a.hnd, a.id, b.hnd, b.id);
1185 return a.id == b.id;
1188 int __cdecl _Thrd_lt(_Thrd_t a, _Thrd_t b)
1190 TRACE("(%p %u %p %u)\n", a.hnd, a.id, b.hnd, b.id);
1191 return a.id < b.id;
1194 void __cdecl _Thrd_sleep(const xtime *t)
1196 TRACE("(%p)\n", t);
1197 Sleep(_Xtime_diff_to_millis(t));
1200 void __cdecl _Thrd_yield(void)
1202 TRACE("()\n");
1203 Sleep(0);
1206 static _Thrd_t thread_current(void)
1208 _Thrd_t ret;
1210 if(DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1211 GetCurrentProcess(), &ret.hnd, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
1212 CloseHandle(ret.hnd);
1213 } else {
1214 ret.hnd = 0;
1216 ret.id = GetCurrentThreadId();
1218 TRACE("(%p %u)\n", ret.hnd, ret.id);
1219 return ret;
1222 #ifndef __i386__
1223 _Thrd_t __cdecl _Thrd_current(void)
1225 return thread_current();
1227 #else
1228 ULONGLONG __cdecl _Thrd_current(void)
1230 union {
1231 _Thrd_t thr;
1232 ULONGLONG ull;
1233 } ret;
1235 C_ASSERT(sizeof(_Thrd_t) <= sizeof(ULONGLONG));
1237 ret.thr = thread_current();
1238 return ret.ull;
1240 #endif
1242 int __cdecl _Thrd_join(_Thrd_t thr, int *code)
1244 TRACE("(%p %u %p)\n", thr.hnd, thr.id, code);
1245 if (WaitForSingleObject(thr.hnd, INFINITE))
1246 return _THRD_ERROR;
1248 if (code)
1249 GetExitCodeThread(thr.hnd, (DWORD *)code);
1251 CloseHandle(thr.hnd);
1252 return 0;
1255 int __cdecl _Thrd_start(_Thrd_t *thr, LPTHREAD_START_ROUTINE proc, void *arg)
1257 TRACE("(%p %p %p)\n", thr, proc, arg);
1258 thr->hnd = CreateThread(NULL, 0, proc, arg, 0, &thr->id);
1259 return thr->hnd ? 0 : _THRD_ERROR;
1262 typedef struct
1264 _Thrd_start_t proc;
1265 void *arg;
1266 } thread_proc_arg;
1268 static DWORD WINAPI thread_proc_wrapper(void *arg)
1270 thread_proc_arg wrapped_arg = *((thread_proc_arg*)arg);
1271 free(arg);
1272 return wrapped_arg.proc(wrapped_arg.arg);
1275 int __cdecl _Thrd_create(_Thrd_t *thr, _Thrd_start_t proc, void *arg)
1277 thread_proc_arg *wrapped_arg;
1278 int ret;
1280 TRACE("(%p %p %p)\n", thr, proc, arg);
1282 wrapped_arg = malloc(sizeof(*wrapped_arg));
1283 if(!wrapped_arg)
1284 return _THRD_ERROR; /* TODO: probably different error should be returned here */
1286 wrapped_arg->proc = proc;
1287 wrapped_arg->arg = arg;
1288 ret = _Thrd_start(thr, thread_proc_wrapper, wrapped_arg);
1289 if(ret) free(wrapped_arg);
1290 return ret;
1293 int __cdecl _Thrd_detach(_Thrd_t thr)
1295 return CloseHandle(thr.hnd) ? 0 : _THRD_ERROR;
1298 typedef struct
1300 const vtable_ptr *vtable;
1301 _Cnd_t cnd;
1302 _Mtx_t mtx;
1303 MSVCP_bool launched;
1304 } _Pad;
1306 DEFINE_RTTI_DATA0(_Pad, 0, ".?AV_Pad@std@@")
1308 /* ??_7_Pad@std@@6B@ */
1309 extern const vtable_ptr MSVCP__Pad_vtable;
1311 unsigned int __cdecl _Thrd_hardware_concurrency(void)
1313 static unsigned int val = -1;
1315 TRACE("()\n");
1317 if(val == -1) {
1318 SYSTEM_INFO si;
1320 GetSystemInfo(&si);
1321 val = si.dwNumberOfProcessors;
1324 return val;
1327 unsigned int __cdecl _Thrd_id(void)
1329 TRACE("()\n");
1330 return GetCurrentThreadId();
1333 /* ??0_Pad@std@@QAE@XZ */
1334 /* ??0_Pad@std@@QEAA@XZ */
1335 DEFINE_THISCALL_WRAPPER(_Pad_ctor, 4)
1336 _Pad* __thiscall _Pad_ctor(_Pad *this)
1338 TRACE("(%p)\n", this);
1340 this->vtable = &MSVCP__Pad_vtable;
1341 _Cnd_init(&this->cnd);
1342 _Mtx_init(&this->mtx, 0);
1343 this->launched = FALSE;
1344 _Mtx_lock(MTX_T_TO_ARG(this->mtx));
1345 return this;
1348 /* ??4_Pad@std@@QAEAAV01@ABV01@@Z */
1349 /* ??4_Pad@std@@QEAAAEAV01@AEBV01@@Z */
1350 DEFINE_THISCALL_WRAPPER(_Pad_op_assign, 8)
1351 _Pad* __thiscall _Pad_op_assign(_Pad *this, const _Pad *copy)
1353 TRACE("(%p %p)\n", this, copy);
1355 this->cnd = copy->cnd;
1356 this->mtx = copy->mtx;
1357 this->launched = copy->launched;
1358 return this;
1361 /* ??0_Pad@std@@QAE@ABV01@@Z */
1362 /* ??0_Pad@std@@QEAA@AEBV01@@Z */
1363 DEFINE_THISCALL_WRAPPER(_Pad_copy_ctor, 8)
1364 _Pad* __thiscall _Pad_copy_ctor(_Pad *this, const _Pad *copy)
1366 TRACE("(%p %p)\n", this, copy);
1368 this->vtable = &MSVCP__Pad_vtable;
1369 return _Pad_op_assign(this, copy);
1372 /* ??1_Pad@std@@QAE@XZ */
1373 /* ??1_Pad@std@@QEAA@XZ */
1374 DEFINE_THISCALL_WRAPPER(_Pad_dtor, 4)
1375 void __thiscall _Pad_dtor(_Pad *this)
1377 TRACE("(%p)\n", this);
1379 _Mtx_unlock(MTX_T_TO_ARG(this->mtx));
1380 _Mtx_destroy(MTX_T_TO_ARG(this->mtx));
1381 _Cnd_destroy(CND_T_TO_ARG(this->cnd));
1384 DEFINE_THISCALL_WRAPPER(_Pad__Go, 4)
1385 #define call__Pad__Go(this) CALL_VTBL_FUNC(this, 0, unsigned int, (_Pad*), (this))
1386 unsigned int __thiscall _Pad__Go(_Pad *this)
1388 ERR("(%p) should not be called\n", this);
1389 return 0;
1392 static DWORD WINAPI launch_thread_proc(void *arg)
1394 _Pad *this = arg;
1395 return call__Pad__Go(this);
1398 /* ?_Launch@_Pad@std@@QAEXPAU_Thrd_imp_t@@@Z */
1399 /* ?_Launch@_Pad@std@@QEAAXPEAU_Thrd_imp_t@@@Z */
1400 DEFINE_THISCALL_WRAPPER(_Pad__Launch, 8)
1401 void __thiscall _Pad__Launch(_Pad *this, _Thrd_t *thr)
1403 TRACE("(%p %p)\n", this, thr);
1405 _Thrd_start(thr, launch_thread_proc, this);
1406 _Cnd_wait(CND_T_TO_ARG(this->cnd), MTX_T_TO_ARG(this->mtx));
1409 /* ?_Release@_Pad@std@@QAEXXZ */
1410 /* ?_Release@_Pad@std@@QEAAXXZ */
1411 DEFINE_THISCALL_WRAPPER(_Pad__Release, 4)
1412 void __thiscall _Pad__Release(_Pad *this)
1414 TRACE("(%p)\n", this);
1416 _Mtx_lock(MTX_T_TO_ARG(this->mtx));
1417 this->launched = TRUE;
1418 _Cnd_signal(CND_T_TO_ARG(this->cnd));
1419 _Mtx_unlock(MTX_T_TO_ARG(this->mtx));
1421 #endif
1423 #if _MSVCP_VER >= 100
1424 typedef struct _Page
1426 struct _Page *_Next;
1427 MSVCP_size_t _Mask;
1428 char data[1];
1429 } _Page;
1431 typedef struct
1433 LONG lock;
1434 _Page *head;
1435 _Page *tail;
1436 MSVCP_size_t head_pos;
1437 MSVCP_size_t tail_pos;
1438 } threadsafe_queue;
1440 #define QUEUES_NO 8
1441 typedef struct
1443 MSVCP_size_t tail_pos;
1444 MSVCP_size_t head_pos;
1445 threadsafe_queue queues[QUEUES_NO];
1446 } queue_data;
1448 typedef struct
1450 const vtable_ptr *vtable;
1451 queue_data *data; /* queue_data structure is not binary compatible */
1452 MSVCP_size_t alloc_count;
1453 MSVCP_size_t item_size;
1454 } _Concurrent_queue_base_v4;
1456 extern const vtable_ptr MSVCP__Concurrent_queue_base_v4_vtable;
1457 #if _MSVCP_VER == 100
1458 #define call__Concurrent_queue_base_v4__Move_item call__Concurrent_queue_base_v4__Copy_item
1459 #define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1460 0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
1461 #define call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
1462 4, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
1463 #define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
1464 12, _Page*, (_Concurrent_queue_base_v4*), (this))
1465 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
1466 16, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
1467 #else
1468 #define call__Concurrent_queue_base_v4__Move_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1469 0, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,void*), (this,dst,idx,src))
1470 #define call__Concurrent_queue_base_v4__Copy_item(this,dst,idx,src) CALL_VTBL_FUNC(this, \
1471 4, void, (_Concurrent_queue_base_v4*,_Page*,MSVCP_size_t,const void*), (this,dst,idx,src))
1472 #define call__Concurrent_queue_base_v4__Assign_and_destroy_item(this,dst,src,idx) CALL_VTBL_FUNC(this, \
1473 8, void, (_Concurrent_queue_base_v4*,void*,_Page*,MSVCP_size_t), (this,dst,src,idx))
1474 #define call__Concurrent_queue_base_v4__Allocate_page(this) CALL_VTBL_FUNC(this, \
1475 16, _Page*, (_Concurrent_queue_base_v4*), (this))
1476 #define call__Concurrent_queue_base_v4__Deallocate_page(this, page) CALL_VTBL_FUNC(this, \
1477 20, void, (_Concurrent_queue_base_v4*,_Page*), (this,page))
1478 #endif
1480 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IBEXXZ */
1481 /* ?_Internal_throw_exception@_Concurrent_queue_base_v4@details@Concurrency@@IEBAXXZ */
1482 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_throw_exception, 4)
1483 void __thiscall _Concurrent_queue_base_v4__Internal_throw_exception(
1484 const _Concurrent_queue_base_v4 *this)
1486 TRACE("(%p)\n", this);
1487 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1490 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IAE@I@Z */
1491 /* ??0_Concurrent_queue_base_v4@details@Concurrency@@IEAA@_K@Z */
1492 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_ctor, 8)
1493 _Concurrent_queue_base_v4* __thiscall _Concurrent_queue_base_v4_ctor(
1494 _Concurrent_queue_base_v4 *this, MSVCP_size_t size)
1496 TRACE("(%p %ld)\n", this, size);
1498 this->data = MSVCRT_operator_new(sizeof(*this->data));
1499 memset(this->data, 0, sizeof(*this->data));
1501 this->vtable = &MSVCP__Concurrent_queue_base_v4_vtable;
1502 this->item_size = size;
1504 /* alloc_count needs to be power of 2 */
1505 this->alloc_count =
1506 size <= 8 ? 32 :
1507 size <= 16 ? 16 :
1508 size <= 32 ? 8 :
1509 size <= 64 ? 4 :
1510 size <= 128 ? 2 : 1;
1511 return this;
1514 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MAE@XZ */
1515 /* ??1_Concurrent_queue_base_v4@details@Concurrency@@MEAA@XZ */
1516 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dtor, 4)
1517 void __thiscall _Concurrent_queue_base_v4_dtor(_Concurrent_queue_base_v4 *this)
1519 TRACE("(%p)\n", this);
1520 MSVCRT_operator_delete(this->data);
1523 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_vector_dtor, 8)
1524 _Concurrent_queue_base_v4* __thiscall _Concurrent_queue_base_v4_vector_dtor(
1525 _Concurrent_queue_base_v4 *this, unsigned int flags)
1527 TRACE("(%p %x)\n", this, flags);
1528 if(flags & 2) {
1529 /* we have an array, with the number of elements stored before the first object */
1530 INT_PTR i, *ptr = (INT_PTR *)this-1;
1532 for(i=*ptr-1; i>=0; i--)
1533 _Concurrent_queue_base_v4_dtor(this+i);
1534 MSVCRT_operator_delete(ptr);
1535 } else {
1536 if(flags & 1)
1537 _Concurrent_queue_base_v4_dtor(this);
1538 MSVCRT_operator_delete(this);
1541 return this;
1544 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IAEXXZ */
1545 /* ?_Internal_finish_clear@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXXZ */
1546 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_finish_clear, 4)
1547 void __thiscall _Concurrent_queue_base_v4__Internal_finish_clear(
1548 _Concurrent_queue_base_v4 *this)
1550 int i;
1552 TRACE("(%p)\n", this);
1554 for(i=0; i<QUEUES_NO; i++)
1556 if(this->data->queues[i].tail)
1557 call__Concurrent_queue_base_v4__Deallocate_page(this, this->data->queues[i].tail);
1561 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IBE_NXZ */
1562 /* ?_Internal_empty@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_NXZ */
1563 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_empty, 4)
1564 MSVCP_bool __thiscall _Concurrent_queue_base_v4__Internal_empty(
1565 const _Concurrent_queue_base_v4 *this)
1567 TRACE("(%p)\n", this);
1568 return this->data->head_pos == this->data->tail_pos;
1571 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IBEIXZ */
1572 /* ?_Internal_size@_Concurrent_queue_base_v4@details@Concurrency@@IEBA_KXZ */
1573 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_size, 4)
1574 MSVCP_size_t __thiscall _Concurrent_queue_base_v4__Internal_size(
1575 const _Concurrent_queue_base_v4 *this)
1577 TRACE("(%p)\n", this);
1578 return this->data->tail_pos - this->data->head_pos;
1581 static void spin_wait(int *counter)
1583 static int spin_limit = -1;
1585 if(spin_limit == -1)
1587 SYSTEM_INFO si;
1588 GetSystemInfo(&si);
1589 spin_limit = si.dwNumberOfProcessors>1 ? 4000 : 0;
1592 if(*counter >= spin_limit)
1594 *counter = 0;
1595 Sleep(0);
1597 else
1599 (*counter)++;
1603 #ifdef _WIN64
1604 static MSVCP_size_t InterlockedIncrementSizeT(MSVCP_size_t volatile *dest)
1606 MSVCP_size_t v;
1610 v = *dest;
1611 } while(InterlockedCompareExchange64((LONGLONG*)dest, v+1, v) != v);
1613 return v+1;
1615 #else
1616 #define InterlockedIncrementSizeT(dest) InterlockedIncrement((LONG*)dest)
1617 #endif
1619 static void CALLBACK queue_push_finally(BOOL normal, void *ctx)
1621 threadsafe_queue *queue = ctx;
1622 InterlockedIncrementSizeT(&queue->tail_pos);
1625 static void threadsafe_queue_push(threadsafe_queue *queue, MSVCP_size_t id,
1626 void *e, _Concurrent_queue_base_v4 *parent, BOOL copy)
1628 MSVCP_size_t page_id = id & ~(parent->alloc_count-1);
1629 int spin;
1630 _Page *p;
1632 spin = 0;
1633 while(queue->tail_pos != id)
1634 spin_wait(&spin);
1636 if(page_id == id)
1638 /* TODO: Add exception handling */
1639 p = call__Concurrent_queue_base_v4__Allocate_page(parent);
1640 p->_Next = NULL;
1641 p->_Mask = 0;
1643 spin = 0;
1644 while(InterlockedCompareExchange(&queue->lock, 1, 0))
1645 spin_wait(&spin);
1646 if(queue->tail)
1647 queue->tail->_Next = p;
1648 queue->tail = p;
1649 if(!queue->head)
1650 queue->head = p;
1651 queue->lock = 0;
1653 else
1655 p = queue->tail;
1658 __TRY
1660 if(copy)
1661 call__Concurrent_queue_base_v4__Copy_item(parent, p, id-page_id, e);
1662 else
1663 call__Concurrent_queue_base_v4__Move_item(parent, p, id-page_id, e);
1664 p->_Mask |= 1 << (id - page_id);
1666 __FINALLY_CTX(queue_push_finally, queue);
1669 static BOOL threadsafe_queue_pop(threadsafe_queue *queue, MSVCP_size_t id,
1670 void *e, _Concurrent_queue_base_v4 *parent)
1672 MSVCP_size_t page_id = id & ~(parent->alloc_count-1);
1673 int spin;
1674 _Page *p;
1675 BOOL ret = FALSE;
1677 spin = 0;
1678 while(queue->tail_pos <= id)
1679 spin_wait(&spin);
1681 spin = 0;
1682 while(queue->head_pos != id)
1683 spin_wait(&spin);
1685 p = queue->head;
1686 if(p->_Mask & (1 << (id-page_id)))
1688 /* TODO: Add exception handling */
1689 call__Concurrent_queue_base_v4__Assign_and_destroy_item(parent, e, p, id-page_id);
1690 ret = TRUE;
1693 if(id == page_id+parent->alloc_count-1)
1695 spin = 0;
1696 while(InterlockedCompareExchange(&queue->lock, 1, 0))
1697 spin_wait(&spin);
1698 queue->head = p->_Next;
1699 if(!queue->head)
1700 queue->tail = NULL;
1701 queue->lock = 0;
1703 /* TODO: Add exception handling */
1704 call__Concurrent_queue_base_v4__Deallocate_page(parent, p);
1707 InterlockedIncrementSizeT(&queue->head_pos);
1708 return ret;
1711 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPBX@Z */
1712 /* ?_Internal_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEBX@Z */
1713 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_push, 8)
1714 void __thiscall _Concurrent_queue_base_v4__Internal_push(
1715 _Concurrent_queue_base_v4 *this, void *e)
1717 MSVCP_size_t id;
1719 TRACE("(%p %p)\n", this, e);
1721 id = InterlockedIncrementSizeT(&this->data->tail_pos)-1;
1722 threadsafe_queue_push(this->data->queues + id % QUEUES_NO,
1723 id / QUEUES_NO, e, this, TRUE);
1726 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IAEXPAX@Z */
1727 /* ?_Internal_move_push@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXPEAX@Z */
1728 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_move_push, 8)
1729 void __thiscall _Concurrent_queue_base_v4__Internal_move_push(
1730 _Concurrent_queue_base_v4 *this, void *e)
1732 MSVCP_size_t id;
1734 TRACE("(%p %p)\n", this, e);
1736 id = InterlockedIncrementSizeT(&this->data->tail_pos)-1;
1737 threadsafe_queue_push(this->data->queues + id % QUEUES_NO,
1738 id / QUEUES_NO, e, this, FALSE);
1741 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IAE_NPAX@Z */
1742 /* ?_Internal_pop_if_present@_Concurrent_queue_base_v4@details@Concurrency@@IEAA_NPEAX@Z */
1743 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_pop_if_present, 8)
1744 MSVCP_bool __thiscall _Concurrent_queue_base_v4__Internal_pop_if_present(
1745 _Concurrent_queue_base_v4 *this, void *e)
1747 MSVCP_size_t id;
1749 TRACE("(%p %p)\n", this, e);
1755 id = this->data->head_pos;
1756 if(id == this->data->tail_pos) return FALSE;
1757 } while(InterlockedCompareExchangePointer((void**)&this->data->head_pos,
1758 (void*)(id+1), (void*)id) != (void*)id);
1759 } while(!threadsafe_queue_pop(this->data->queues + id % QUEUES_NO,
1760 id / QUEUES_NO, e, this));
1761 return TRUE;
1764 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IAEXAAV123@@Z */
1765 /* ?_Internal_swap@_Concurrent_queue_base_v4@details@Concurrency@@IEAAXAEAV123@@Z */
1766 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4__Internal_swap, 8)
1767 void __thiscall _Concurrent_queue_base_v4__Internal_swap(
1768 _Concurrent_queue_base_v4 *this, _Concurrent_queue_base_v4 *r)
1770 FIXME("(%p %p) stub\n", this, r);
1773 DEFINE_THISCALL_WRAPPER(_Concurrent_queue_base_v4_dummy, 4)
1774 void __thiscall _Concurrent_queue_base_v4_dummy(_Concurrent_queue_base_v4 *this)
1776 ERR("unexpected call\n");
1779 DEFINE_RTTI_DATA0(_Concurrent_queue_base_v4, 0, ".?AV_Concurrent_queue_base_v4@details@Concurrency@@")
1781 static int _Runtime_object_id;
1783 typedef struct
1785 const vtable_ptr *vtable;
1786 int id;
1787 } _Runtime_object;
1789 extern const vtable_ptr MSVCP__Runtime_object_vtable;
1791 /* ??0_Runtime_object@details@Concurrency@@QAE@H@Z */
1792 /* ??0_Runtime_object@details@Concurrency@@QEAA@H@Z */
1793 DEFINE_THISCALL_WRAPPER(_Runtime_object_ctor_id, 8)
1794 _Runtime_object* __thiscall _Runtime_object_ctor_id(_Runtime_object *this, int id)
1796 TRACE("(%p %d)\n", this, id);
1797 this->vtable = &MSVCP__Runtime_object_vtable;
1798 this->id = id;
1799 return this;
1802 /* ??0_Runtime_object@details@Concurrency@@QAE@XZ */
1803 /* ??0_Runtime_object@details@Concurrency@@QEAA@XZ */
1804 DEFINE_THISCALL_WRAPPER(_Runtime_object_ctor, 4)
1805 _Runtime_object* __thiscall _Runtime_object_ctor(_Runtime_object *this)
1807 TRACE("(%p)\n", this);
1808 this->vtable = &MSVCP__Runtime_object_vtable;
1809 this->id = InterlockedExchangeAdd(&_Runtime_object_id, 2);
1810 return this;
1813 DEFINE_THISCALL_WRAPPER(_Runtime_object__GetId, 4)
1814 int __thiscall _Runtime_object__GetId(_Runtime_object *this)
1816 TRACE("(%p)\n", this);
1817 return this->id;
1820 DEFINE_RTTI_DATA0(_Runtime_object, 0, ".?AV_Runtime_object@details@Concurrency@@")
1822 #endif
1824 #if _MSVCP_VER >= 100
1825 typedef struct __Concurrent_vector_base_v4
1827 void* (__cdecl *allocator)(struct __Concurrent_vector_base_v4 *, MSVCP_size_t);
1828 void *storage[3];
1829 MSVCP_size_t first_block;
1830 MSVCP_size_t early_size;
1831 void **segment;
1832 } _Concurrent_vector_base_v4;
1834 #define STORAGE_SIZE ARRAY_SIZE(this->storage)
1835 #define SEGMENT_SIZE (sizeof(void*) * 8)
1837 typedef struct compact_block
1839 MSVCP_size_t first_block;
1840 void *blocks[SEGMENT_SIZE];
1841 int size_check;
1842 }compact_block;
1844 /* based on wined3d_log2i from wined3d.h */
1845 /* Return the integer base-2 logarithm of (x|1). Result is 0 for x == 0. */
1846 static inline unsigned int log2i(unsigned int x)
1848 #ifdef HAVE___BUILTIN_CLZ
1849 return __builtin_clz(x|1) ^ 0x1f;
1850 #else
1851 static const unsigned int l[] =
1853 ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
1854 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1855 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1856 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1857 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1858 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1859 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1860 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
1861 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,
1864 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1865 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1866 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1867 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1868 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
1870 unsigned int i;
1872 x |= 1;
1873 return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
1874 #endif
1877 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KAII@Z */
1878 /* ?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KA_K_K@Z */
1879 MSVCP_size_t __cdecl _vector_base_v4__Segment_index_of(MSVCP_size_t x)
1881 unsigned int half;
1883 TRACE("(%lu)\n", x);
1885 if((sizeof(x) == 8) && (half = x >> 32))
1886 return log2i(half) + 32;
1888 return log2i(x);
1891 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IBEXI@Z */
1892 /* ?_Internal_throw_exception@_Concurrent_vector_base_v4@details@Concurrency@@IEBAX_K@Z */
1893 DEFINE_THISCALL_WRAPPER(_vector_base_v4__Internal_throw_exception, 8)
1894 void __thiscall _vector_base_v4__Internal_throw_exception(void/*_vector_base_v4*/ *this, MSVCP_size_t idx)
1896 static const struct {
1897 exception_type type;
1898 const char *msg;
1899 } exceptions[] = {
1900 { EXCEPTION_OUT_OF_RANGE, "Index out of range" },
1901 { EXCEPTION_OUT_OF_RANGE, "Index out of segments table range" },
1902 { EXCEPTION_RANGE_ERROR, "Index is inside segment which failed to be allocated" },
1905 TRACE("(%p %lu)\n", this, idx);
1907 if(idx < ARRAY_SIZE(exceptions))
1908 throw_exception(exceptions[idx].type, exceptions[idx].msg);
1911 #ifdef _WIN64
1912 #define InterlockedCompareExchangeSizeT(dest, exchange, cmp) InterlockedCompareExchangeSize((MSVCP_size_t *)dest, (MSVCP_size_t)exchange, (MSVCP_size_t)cmp)
1913 static MSVCP_size_t InterlockedCompareExchangeSize(MSVCP_size_t volatile *dest, MSVCP_size_t exchange, MSVCP_size_t cmp)
1915 MSVCP_size_t v;
1917 v = InterlockedCompareExchange64((LONGLONG*)dest, exchange, cmp);
1919 return v;
1921 #else
1922 #define InterlockedCompareExchangeSizeT(dest, exchange, cmp) InterlockedCompareExchange((LONG*)dest, (MSVCP_size_t)exchange, (MSVCP_size_t)cmp)
1923 #endif
1925 #define SEGMENT_ALLOC_MARKER ((void*)1)
1927 static void concurrent_vector_alloc_segment(_Concurrent_vector_base_v4 *this,
1928 MSVCP_size_t seg, MSVCP_size_t element_size)
1930 int spin;
1932 while(!this->segment[seg] || this->segment[seg] == SEGMENT_ALLOC_MARKER)
1934 spin = 0;
1935 while(this->segment[seg] == SEGMENT_ALLOC_MARKER)
1936 spin_wait(&spin);
1937 if(!InterlockedCompareExchangeSizeT((this->segment + seg),
1938 SEGMENT_ALLOC_MARKER, 0))
1939 __TRY
1941 if(seg == 0)
1942 this->segment[seg] = this->allocator(this, element_size * (1 << this->first_block));
1943 else if(seg < this->first_block)
1944 this->segment[seg] = (BYTE**)this->segment[0]
1945 + element_size * (1 << seg);
1946 else
1947 this->segment[seg] = this->allocator(this, element_size * (1 << seg));
1949 __EXCEPT_ALL
1951 this->segment[seg] = NULL;
1952 throw_exception(EXCEPTION_RERAISE, NULL);
1954 __ENDTRY
1955 if(!this->segment[seg])
1956 _vector_base_v4__Internal_throw_exception(this, 2);
1960 /* ??1_Concurrent_vector_base_v4@details@Concurrency@@IAE@XZ */
1961 /* ??1_Concurrent_vector_base_v4@details@Concurrency@@IEAA@XZ */
1962 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4_dtor, 4)
1963 void __thiscall _Concurrent_vector_base_v4_dtor(
1964 _Concurrent_vector_base_v4 *this)
1966 TRACE("(%p)\n", this);
1968 if(this->segment != this->storage)
1969 free(this->segment);
1972 /* ?_Internal_capacity@_Concurrent_vector_base_v4@details@Concurrency@@IBEIXZ */
1973 /* ?_Internal_capacity@_Concurrent_vector_base_v4@details@Concurrency@@IEBA_KXZ */
1974 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_capacity, 4)
1975 MSVCP_size_t __thiscall _Concurrent_vector_base_v4__Internal_capacity(
1976 const _Concurrent_vector_base_v4 *this)
1978 MSVCP_size_t last_block;
1979 int i;
1981 TRACE("(%p)\n", this);
1983 last_block = (this->segment == this->storage ? STORAGE_SIZE : SEGMENT_SIZE);
1984 for(i = 0; i < last_block; i++)
1986 if(!this->segment[i])
1987 return !i ? 0 : 1 << i;
1989 return 1 << i;
1992 /* ?_Internal_reserve@_Concurrent_vector_base_v4@details@Concurrency@@IAEXIII@Z */
1993 /* ?_Internal_reserve@_Concurrent_vector_base_v4@details@Concurrency@@IEAAX_K00@Z */
1994 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_reserve, 16)
1995 void __thiscall _Concurrent_vector_base_v4__Internal_reserve(
1996 _Concurrent_vector_base_v4 *this, MSVCP_size_t size,
1997 MSVCP_size_t element_size, MSVCP_size_t max_size)
1999 MSVCP_size_t block_idx, capacity;
2000 int i;
2001 void **new_segment;
2003 TRACE("(%p %ld %ld %ld)\n", this, size, element_size, max_size);
2005 if(size > max_size) _vector_base_v4__Internal_throw_exception(this, 0);
2006 capacity = _Concurrent_vector_base_v4__Internal_capacity(this);
2007 if(size <= capacity) return;
2008 block_idx = _vector_base_v4__Segment_index_of(size - 1);
2009 if(!this->first_block)
2010 InterlockedCompareExchangeSizeT(&this->first_block, block_idx + 1, 0);
2011 i = _vector_base_v4__Segment_index_of(capacity);
2012 if(this->storage == this->segment) {
2013 for(; i <= block_idx && i < STORAGE_SIZE; i++)
2014 concurrent_vector_alloc_segment(this, i, element_size);
2015 if(block_idx >= STORAGE_SIZE) {
2016 new_segment = malloc(SEGMENT_SIZE * sizeof(void*));
2017 if(new_segment == NULL) _vector_base_v4__Internal_throw_exception(this, 2);
2018 memset(new_segment, 0, SEGMENT_SIZE * sizeof(*new_segment));
2019 memcpy(new_segment, this->storage, STORAGE_SIZE * sizeof(*new_segment));
2020 if(InterlockedCompareExchangePointer((void*)&this->segment, new_segment,
2021 this->storage) != this->storage)
2022 free(new_segment);
2025 for(; i <= block_idx; i++)
2026 concurrent_vector_alloc_segment(this, i, element_size);
2029 /* ?_Internal_clear@_Concurrent_vector_base_v4@details@Concurrency@@IAEIP6AXPAXI@Z@Z */
2030 /* ?_Internal_clear@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_KP6AXPEAX_K@Z@Z */
2031 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_clear, 8)
2032 MSVCP_size_t __thiscall _Concurrent_vector_base_v4__Internal_clear(
2033 _Concurrent_vector_base_v4 *this, void (__cdecl *clear)(void*, MSVCP_size_t))
2035 MSVCP_size_t seg_no, elems;
2036 int i;
2038 TRACE("(%p %p)\n", this, clear);
2040 seg_no = this->early_size ? _vector_base_v4__Segment_index_of(this->early_size) + 1 : 0;
2041 for(i = seg_no - 1; i >= 0; i--) {
2042 elems = this->early_size - (1 << i & ~1);
2043 clear(this->segment[i], elems);
2044 this->early_size -= elems;
2046 while(seg_no < (this->segment == this->storage ? STORAGE_SIZE : SEGMENT_SIZE)) {
2047 if(!this->segment[seg_no]) break;
2048 seg_no++;
2050 return seg_no;
2053 /* ?_Internal_compact@_Concurrent_vector_base_v4@details@Concurrency@@IAEPAXIPAXP6AX0I@ZP6AX0PBXI@Z@Z */
2054 /* ?_Internal_compact@_Concurrent_vector_base_v4@details@Concurrency@@IEAAPEAX_KPEAXP6AX10@ZP6AX1PEBX0@Z@Z */
2055 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_compact, 20)
2056 void * __thiscall _Concurrent_vector_base_v4__Internal_compact(
2057 _Concurrent_vector_base_v4 *this, MSVCP_size_t element_size, void *v,
2058 void (__cdecl *clear)(void*, MSVCP_size_t),
2059 void (__cdecl *copy)(void*, const void*, MSVCP_size_t))
2061 compact_block *b;
2062 MSVCP_size_t size, alloc_size, seg_no, alloc_seg, copy_element, clear_element;
2063 int i;
2065 TRACE("(%p %ld %p %p %p)\n", this, element_size, v, clear, copy);
2067 size = this->early_size;
2068 alloc_size = _Concurrent_vector_base_v4__Internal_capacity(this);
2069 if(alloc_size == 0) return NULL;
2070 alloc_seg = _vector_base_v4__Segment_index_of(alloc_size - 1);
2071 if(!size) {
2072 this->first_block = 0;
2073 b = v;
2074 b->first_block = alloc_seg + 1;
2075 memset(b->blocks, 0, sizeof(b->blocks));
2076 memcpy(b->blocks, this->segment,
2077 (alloc_seg + 1) * sizeof(this->segment[0]));
2078 memset(this->segment, 0, sizeof(this->segment[0]) * (alloc_seg + 1));
2079 return v;
2081 seg_no = _vector_base_v4__Segment_index_of(size - 1);
2082 if(this->first_block == (seg_no + 1) && seg_no == alloc_seg) return NULL;
2083 b = v;
2084 b->first_block = this->first_block;
2085 memset(b->blocks, 0, sizeof(b->blocks));
2086 memcpy(b->blocks, this->segment,
2087 (alloc_seg + 1) * sizeof(this->segment[0]));
2088 if(this->first_block == (seg_no + 1) && seg_no != alloc_seg) {
2089 memset(b->blocks, 0, sizeof(b->blocks[0]) * (seg_no + 1));
2090 memset(&this->segment[seg_no + 1], 0, sizeof(this->segment[0]) * (alloc_seg - seg_no));
2091 return v;
2093 memset(this->segment, 0,
2094 (alloc_seg + 1) * sizeof(this->segment[0]));
2095 this->first_block = 0;
2096 _Concurrent_vector_base_v4__Internal_reserve(this, size, element_size,
2097 MSVCP_SIZE_T_MAX / element_size);
2098 for(i = 0; i < seg_no; i++)
2099 copy(this->segment[i], b->blocks[i], i ? 1 << i : 2);
2100 copy_element = size - ((1 << seg_no) & ~1);
2101 if(copy_element > 0)
2102 copy(this->segment[seg_no], b->blocks[seg_no], copy_element);
2103 for(i = 0; i < seg_no; i++)
2104 clear(b->blocks[i], i ? 1 << i : 2);
2105 clear_element = size - ((1 << seg_no) & ~1);
2106 if(clear_element > 0)
2107 clear(b->blocks[seg_no], clear_element);
2108 return v;
2111 /* ?_Internal_copy@_Concurrent_vector_base_v4@details@Concurrency@@IAEXABV123@IP6AXPAXPBXI@Z@Z */
2112 /* ?_Internal_copy@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEBV123@_KP6AXPEAXPEBX1@Z@Z */
2113 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_copy, 16)
2114 void __thiscall _Concurrent_vector_base_v4__Internal_copy(
2115 _Concurrent_vector_base_v4 *this, const _Concurrent_vector_base_v4 *v,
2116 MSVCP_size_t element_size, void (__cdecl *copy)(void*, const void*, MSVCP_size_t))
2118 MSVCP_size_t seg_no, v_size;
2119 int i;
2121 TRACE("(%p %p %ld %p)\n", this, v, element_size, copy);
2123 v_size = v->early_size;
2124 if(!v_size) {
2125 this->early_size = 0;
2126 return;
2128 _Concurrent_vector_base_v4__Internal_reserve(this, v_size,
2129 element_size, MSVCP_SIZE_T_MAX / element_size);
2130 seg_no = _vector_base_v4__Segment_index_of(v_size - 1);
2131 for(i = 0; i < seg_no; i++)
2132 copy(this->segment[i], v->segment[i], i ? 1 << i : 2);
2133 copy(this->segment[i], v->segment[i], v_size - (1 << i & ~1));
2134 this->early_size = v_size;
2137 /* ?_Internal_assign@_Concurrent_vector_base_v4@details@Concurrency@@IAEXABV123@IP6AXPAXI@ZP6AX1PBXI@Z4@Z */
2138 /* ?_Internal_assign@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEBV123@_KP6AXPEAX1@ZP6AX2PEBX1@Z5@Z */
2139 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_assign, 24)
2140 void __thiscall _Concurrent_vector_base_v4__Internal_assign(
2141 _Concurrent_vector_base_v4 *this, const _Concurrent_vector_base_v4 *v,
2142 MSVCP_size_t element_size, void (__cdecl *clear)(void*, MSVCP_size_t),
2143 void (__cdecl *assign)(void*, const void*, MSVCP_size_t),
2144 void (__cdecl *copy)(void*, const void*, MSVCP_size_t))
2146 MSVCP_size_t v_size, seg_no, v_seg_no, remain_element;
2147 int i;
2149 TRACE("(%p %p %ld %p %p %p)\n", this, v, element_size, clear, assign, copy);
2151 v_size = v->early_size;
2152 if(!v_size) {
2153 _Concurrent_vector_base_v4__Internal_clear(this, clear);
2154 return;
2156 if(!this->early_size) {
2157 _Concurrent_vector_base_v4__Internal_copy(this, v, element_size, copy);
2158 return;
2160 seg_no = _vector_base_v4__Segment_index_of(this->early_size - 1);
2161 v_seg_no = _vector_base_v4__Segment_index_of(v_size - 1);
2163 for(i = 0; i < min(seg_no, v_seg_no); i++)
2164 assign(this->segment[i], v->segment[i], i ? 1 << i : 2);
2165 remain_element = min(this->early_size, v_size) - (1 << i & ~1);
2166 if(remain_element != 0)
2167 assign(this->segment[i], v->segment[i], remain_element);
2169 if(this->early_size > v_size)
2171 if((i ? 1 << i : 2) - remain_element > 0)
2172 clear((BYTE**)this->segment[i] + element_size * remain_element,
2173 (i ? 1 << i : 2) - remain_element);
2174 if(i < seg_no)
2176 for(i++; i < seg_no; i++)
2177 clear(this->segment[i], 1 << i);
2178 clear(this->segment[i], this->early_size - (1 << i));
2181 else if(this->early_size < v_size)
2183 if((i ? 1 << i : 2) - remain_element > 0)
2184 copy((BYTE**)this->segment[i] + element_size * remain_element,
2185 (BYTE**)v->segment[i] + element_size * remain_element,
2186 (i ? 1 << i : 2) - remain_element);
2187 if(i < v_seg_no)
2189 _Concurrent_vector_base_v4__Internal_reserve(this, v_size,
2190 element_size, MSVCP_SIZE_T_MAX / element_size);
2191 for(i++; i < v_seg_no; i++)
2192 copy(this->segment[i], v->segment[i], 1 << i);
2193 copy(this->segment[i], v->segment[i], v->early_size - (1 << i));
2196 this->early_size = v_size;
2199 /* ?_Internal_grow_by@_Concurrent_vector_base_v4@details@Concurrency@@IAEIIIP6AXPAXPBXI@Z1@Z */
2200 /* ?_Internal_grow_by@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_K_K0P6AXPEAXPEBX0@Z2@Z */
2201 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_grow_by, 20)
2202 MSVCP_size_t __thiscall _Concurrent_vector_base_v4__Internal_grow_by(
2203 _Concurrent_vector_base_v4 *this, MSVCP_size_t count, MSVCP_size_t element_size,
2204 void (__cdecl *copy)(void*, const void*, MSVCP_size_t), const void *v)
2206 MSVCP_size_t size, seg_no, last_seg_no, remain_size;
2208 TRACE("(%p %ld %ld %p %p)\n", this, count, element_size, copy, v);
2210 if(count == 0) return this->early_size;
2211 do {
2212 size = this->early_size;
2213 _Concurrent_vector_base_v4__Internal_reserve(this, size + count, element_size,
2214 MSVCP_SIZE_T_MAX / element_size);
2215 } while(InterlockedCompareExchangeSizeT(&this->early_size, size + count, size) != size);
2217 seg_no = size ? _vector_base_v4__Segment_index_of(size - 1) : 0;
2218 last_seg_no = _vector_base_v4__Segment_index_of(size + count - 1);
2219 remain_size = min(size + count, 1 << (seg_no + 1)) - size;
2220 if(remain_size > 0)
2221 copy(((BYTE**)this->segment[seg_no] + element_size * (size - ((1 << seg_no) & ~1))), v,
2222 remain_size);
2223 if(seg_no != last_seg_no)
2225 for(seg_no++; seg_no < last_seg_no; seg_no++)
2226 copy(this->segment[seg_no], v, 1 << seg_no);
2227 copy(this->segment[last_seg_no], v, size + count - (1 << last_seg_no));
2229 return size;
2232 /* ?_Internal_grow_to_at_least_with_result@_Concurrent_vector_base_v4@details@Concurrency@@IAEIIIP6AXPAXPBXI@Z1@Z */
2233 /* ?_Internal_grow_to_at_least_with_result@_Concurrent_vector_base_v4@details@Concurrency@@IEAA_K_K0P6AXPEAXPEBX0@Z2@Z */
2234 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result, 20)
2235 MSVCP_size_t __thiscall _Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result(
2236 _Concurrent_vector_base_v4 *this, MSVCP_size_t count, MSVCP_size_t element_size,
2237 void (__cdecl *copy)(void*, const void*, MSVCP_size_t), const void *v)
2239 MSVCP_size_t size, seg_no, last_seg_no, remain_size;
2241 TRACE("(%p %ld %ld %p %p)\n", this, count, element_size, copy, v);
2243 _Concurrent_vector_base_v4__Internal_reserve(this, count, element_size,
2244 MSVCP_SIZE_T_MAX / element_size);
2245 do {
2246 size = this->early_size;
2247 if(size >= count) return size;
2248 } while(InterlockedCompareExchangeSizeT(&this->early_size, count, size) != size);
2250 seg_no = size ? _vector_base_v4__Segment_index_of(size - 1) : 0;
2251 last_seg_no = _vector_base_v4__Segment_index_of(count - 1);
2252 remain_size = min(count, 1 << (seg_no + 1)) - size;
2253 if(remain_size > 0)
2254 copy(((BYTE**)this->segment[seg_no] + element_size * (size - ((1 << seg_no) & ~1))), v,
2255 remain_size);
2256 if(seg_no != last_seg_no)
2258 for(seg_no++; seg_no < last_seg_no; seg_no++)
2259 copy(this->segment[seg_no], v, 1 << seg_no);
2260 copy(this->segment[last_seg_no], v, count - (1 << last_seg_no));
2262 return size;
2265 /* ?_Internal_push_back@_Concurrent_vector_base_v4@details@Concurrency@@IAEPAXIAAI@Z */
2266 /* ?_Internal_push_back@_Concurrent_vector_base_v4@details@Concurrency@@IEAAPEAX_KAEA_K@Z */
2267 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_push_back, 12)
2268 void * __thiscall _Concurrent_vector_base_v4__Internal_push_back(
2269 _Concurrent_vector_base_v4 *this, MSVCP_size_t element_size, MSVCP_size_t *idx)
2271 MSVCP_size_t index, seg, segment_base;
2272 void *data;
2274 TRACE("(%p %ld %p)\n", this, element_size, idx);
2276 do {
2277 index = this->early_size;
2278 _Concurrent_vector_base_v4__Internal_reserve(this, index + 1,
2279 element_size, MSVCP_SIZE_T_MAX / element_size);
2280 } while(InterlockedCompareExchangeSizeT(&this->early_size, index + 1, index) != index);
2281 seg = _vector_base_v4__Segment_index_of(index);
2282 segment_base = (seg == 0) ? 0 : (1 << seg);
2283 data = (BYTE*)this->segment[seg] + element_size * (index - segment_base);
2284 *idx = index;
2286 return data;
2289 /* ?_Internal_resize@_Concurrent_vector_base_v4@details@Concurrency@@IAEXIIIP6AXPAXI@ZP6AX0PBXI@Z2@Z */
2290 /* ?_Internal_resize@_Concurrent_vector_base_v4@details@Concurrency@@IEAAX_K00P6AXPEAX0@ZP6AX1PEBX0@Z3@Z */
2291 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_resize, 28)
2292 void __thiscall _Concurrent_vector_base_v4__Internal_resize(
2293 _Concurrent_vector_base_v4 *this, MSVCP_size_t resize, MSVCP_size_t element_size,
2294 MSVCP_size_t max_size, void (__cdecl *clear)(void*, MSVCP_size_t),
2295 void (__cdecl *copy)(void*, const void*, MSVCP_size_t), const void *v)
2297 MSVCP_size_t size, seg_no, end_seg_no, clear_element;
2299 TRACE("(%p %ld %ld %ld %p %p %p)\n", this, resize, element_size, max_size, clear, copy, v);
2301 if(resize > max_size) _vector_base_v4__Internal_throw_exception(this, 0);
2302 size = this->early_size;
2303 if(resize > size)
2304 _Concurrent_vector_base_v4__Internal_grow_to_at_least_with_result(this,
2305 resize, element_size, copy, v);
2306 else if(resize == 0)
2307 _Concurrent_vector_base_v4__Internal_clear(this, clear);
2308 else if(resize < size)
2310 seg_no = _vector_base_v4__Segment_index_of(size - 1);
2311 end_seg_no = _vector_base_v4__Segment_index_of(resize - 1);
2312 clear_element = size - (seg_no ? 1 << seg_no : 2);
2313 if(clear_element > 0)
2314 clear(this->segment[seg_no], clear_element);
2315 if(seg_no) seg_no--;
2316 for(; seg_no > end_seg_no; seg_no--)
2317 clear(this->segment[seg_no], 1 << seg_no);
2318 clear_element = (1 << (end_seg_no + 1)) - resize;
2319 if(clear_element > 0)
2320 clear((BYTE**)this->segment[end_seg_no] + element_size * (resize - ((1 << end_seg_no) & ~1)),
2321 clear_element);
2322 this->early_size = resize;
2326 /* ?_Internal_swap@_Concurrent_vector_base_v4@details@Concurrency@@IAEXAAV123@@Z */
2327 /* ?_Internal_swap@_Concurrent_vector_base_v4@details@Concurrency@@IEAAXAEAV123@@Z */
2328 DEFINE_THISCALL_WRAPPER(_Concurrent_vector_base_v4__Internal_swap, 8)
2329 void __thiscall _Concurrent_vector_base_v4__Internal_swap(
2330 _Concurrent_vector_base_v4 *this, _Concurrent_vector_base_v4 *v)
2332 _Concurrent_vector_base_v4 temp;
2334 TRACE("(%p %p)\n", this, v);
2336 temp = *this;
2337 *this = *v;
2338 *v = temp;
2339 if(v->segment == this->storage)
2340 v->segment = v->storage;
2341 if(this->segment == v->storage)
2342 this->segment = this->storage;
2344 #endif
2346 #ifndef __GNUC__
2347 void __asm_dummy_vtables(void) {
2348 #endif
2349 #if _MSVCP_VER == 100
2350 __ASM_VTABLE(iostream_category,
2351 VTABLE_ADD_FUNC(custom_category_vector_dtor)
2352 VTABLE_ADD_FUNC(custom_category_name)
2353 VTABLE_ADD_FUNC(iostream_category_message)
2354 VTABLE_ADD_FUNC(custom_category_default_error_condition)
2355 VTABLE_ADD_FUNC(custom_category_equivalent)
2356 VTABLE_ADD_FUNC(custom_category_equivalent_code));
2357 __ASM_VTABLE(system_category,
2358 VTABLE_ADD_FUNC(custom_category_vector_dtor)
2359 VTABLE_ADD_FUNC(custom_category_name)
2360 VTABLE_ADD_FUNC(custom_category_message)
2361 VTABLE_ADD_FUNC(custom_category_default_error_condition)
2362 VTABLE_ADD_FUNC(custom_category_equivalent)
2363 VTABLE_ADD_FUNC(custom_category_equivalent_code));
2364 __ASM_VTABLE(generic_category,
2365 VTABLE_ADD_FUNC(custom_category_vector_dtor)
2366 VTABLE_ADD_FUNC(custom_category_name)
2367 VTABLE_ADD_FUNC(custom_category_message)
2368 VTABLE_ADD_FUNC(custom_category_default_error_condition)
2369 VTABLE_ADD_FUNC(custom_category_equivalent)
2370 VTABLE_ADD_FUNC(custom_category_equivalent_code));
2371 #endif
2372 #if _MSVCP_VER >= 100
2373 __ASM_VTABLE(_Concurrent_queue_base_v4,
2374 #if _MSVCP_VER >= 110
2375 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
2376 #endif
2377 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
2378 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
2379 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_vector_dtor)
2380 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy)
2381 VTABLE_ADD_FUNC(_Concurrent_queue_base_v4_dummy));
2382 __ASM_VTABLE(_Runtime_object,
2383 VTABLE_ADD_FUNC(_Runtime_object__GetId));
2384 #endif
2385 #if _MSVCP_VER >= 110
2386 __ASM_VTABLE(_Pad,
2387 VTABLE_ADD_FUNC(_Pad__Go));
2388 #endif
2389 #ifndef __GNUC__
2391 #endif
2393 /*********************************************************************
2394 * __crtInitializeCriticalSectionEx (MSVCP140.@)
2396 BOOL CDECL MSVCP__crtInitializeCriticalSectionEx(
2397 CRITICAL_SECTION *cs, DWORD spin_count, DWORD flags)
2399 TRACE("(%p %x %x)\n", cs, spin_count, flags);
2400 return InitializeCriticalSectionEx(cs, spin_count, flags);
2403 /*********************************************************************
2404 * __crtCreateEventExW (MSVCP140.@)
2406 HANDLE CDECL MSVCP__crtCreateEventExW(
2407 SECURITY_ATTRIBUTES *attribs, LPCWSTR name, DWORD flags, DWORD access)
2409 TRACE("(%p %s 0x%08x 0x%08x)\n", attribs, debugstr_w(name), flags, access);
2410 return CreateEventExW(attribs, name, flags, access);
2413 /*********************************************************************
2414 * __crtGetTickCount64 (MSVCP140.@)
2416 ULONGLONG CDECL MSVCP__crtGetTickCount64(void)
2418 return GetTickCount64();
2421 /*********************************************************************
2422 * __crtGetCurrentProcessorNumber (MSVCP140.@)
2424 DWORD CDECL MSVCP__crtGetCurrentProcessorNumber(void)
2426 return GetCurrentProcessorNumber();
2429 /*********************************************************************
2430 * __crtFlushProcessWriteBuffers (MSVCP140.@)
2432 VOID CDECL MSVCP__crtFlushProcessWriteBuffers(void)
2434 return FlushProcessWriteBuffers();
2437 /*********************************************************************
2438 * __crtCreateSemaphoreExW (MSVCP140.@)
2440 HANDLE CDECL MSVCP__crtCreateSemaphoreExW(
2441 SECURITY_ATTRIBUTES *attribs, LONG initial_count, LONG max_count, LPCWSTR name,
2442 DWORD flags, DWORD access)
2444 TRACE("(%p %d %d %s 0x%08x 0x%08x)\n", attribs, initial_count, max_count, debugstr_w(name),
2445 flags, access);
2446 return CreateSemaphoreExW(attribs, initial_count, max_count, name, flags, access);
2449 /*********************************************************************
2450 * __crtCreateThreadpoolTimer (MSVCP140.@)
2452 PTP_TIMER CDECL MSVCP__crtCreateThreadpoolTimer(PTP_TIMER_CALLBACK callback,
2453 PVOID userdata, TP_CALLBACK_ENVIRON *environment)
2455 TRACE("(%p %p %p)\n", callback, userdata, environment);
2456 return CreateThreadpoolTimer(callback, userdata, environment);
2459 /*********************************************************************
2460 * __crtCloseThreadpoolTimer (MSVCP140.@)
2462 VOID CDECL MSVCP__crtCloseThreadpoolTimer(TP_TIMER *timer)
2464 TRACE("(%p)\n", timer);
2465 CloseThreadpoolTimer(timer);
2468 /*********************************************************************
2469 * __crtSetThreadpoolTimer (MSVCP140.@)
2471 VOID CDECL MSVCP__crtSetThreadpoolTimer(TP_TIMER *timer,
2472 FILETIME *due_time, DWORD period, DWORD window_length)
2474 TRACE("(%p %p 0x%08x 0x%08x)\n", timer, due_time, period, window_length);
2475 return SetThreadpoolTimer(timer, due_time, period, window_length);
2478 /*********************************************************************
2479 * __crtWaitForThreadpoolTimerCallbacks (MSVCP140.@)
2481 VOID CDECL MSVCP__crtWaitForThreadpoolTimerCallbacks(TP_TIMER *timer, BOOL cancel)
2483 TRACE("(%p %d)\n", timer, cancel);
2484 WaitForThreadpoolTimerCallbacks(timer, cancel);
2487 /*********************************************************************
2488 * __crtCreateThreadpoolWait (MSVCP140.@)
2490 PTP_WAIT CDECL MSVCP__crtCreateThreadpoolWait(PTP_WAIT_CALLBACK callback,
2491 PVOID userdata, TP_CALLBACK_ENVIRON *environment)
2493 TRACE("(%p %p %p)\n", callback, userdata, environment);
2494 return CreateThreadpoolWait(callback, userdata, environment);
2497 /*********************************************************************
2498 * __crtCloseThreadpoolWait (MSVCP140.@)
2500 VOID CDECL MSVCP__crtCloseThreadpoolWait(TP_WAIT *wait)
2502 TRACE("(%p)\n", wait);
2503 CloseThreadpoolWait(wait);
2506 /*********************************************************************
2507 * __crtSetThreadpoolWait (MSVCP140.@)
2509 VOID CDECL MSVCP__crtSetThreadpoolWait(TP_WAIT *wait, HANDLE handle, FILETIME *due_time)
2511 TRACE("(%p %p %p)\n", wait, handle, due_time);
2512 return SetThreadpoolWait(wait, handle, due_time);
2515 /*********************************************************************
2516 * __crtFreeLibraryWhenCallbackReturns (MSVCP140.@)
2518 VOID CDECL MSVCP__crtFreeLibraryWhenCallbackReturns(PTP_CALLBACK_INSTANCE instance, HMODULE mod)
2520 TRACE("(%p %p)\n", instance, mod);
2521 FreeLibraryWhenCallbackReturns(instance, mod);
2524 /* ?_Execute_once@std@@YAHAAUonce_flag@1@P6GHPAX1PAPAX@Z1@Z */
2525 /* ?_Execute_once@std@@YAHAEAUonce_flag@1@P6AHPEAX1PEAPEAX@Z1@Z */
2526 BOOL __cdecl _Execute_once(INIT_ONCE *flag, PINIT_ONCE_FN func, void *param)
2528 return InitOnceExecuteOnce(flag, func, param, NULL);
2531 #if _MSVCP_VER >= 100
2532 void init_misc(void *base)
2534 #ifdef __x86_64__
2535 #if _MSVCP_VER == 100
2536 init_error_category_rtti(base);
2537 init_iostream_category_rtti(base);
2538 init_system_category_rtti(base);
2539 init_generic_category_rtti(base);
2540 #endif
2541 #if _MSVCP_VER >= 100
2542 init__Concurrent_queue_base_v4_rtti(base);
2543 init__Runtime_object_rtti(base);
2544 #endif
2545 #if _MSVCP_VER >= 110
2546 init__Pad_rtti(base);
2547 #endif
2548 #endif
2550 #if _MSVCP_VER == 100
2551 iostream_category_ctor(&iostream_category);
2552 system_category_ctor(&system_category);
2553 generic_category_ctor(&generic_category);
2554 #endif
2557 void free_misc(void)
2559 #if _MSVCP_VER >= 110
2560 if(keyed_event)
2561 NtClose(keyed_event);
2562 HeapFree(GetProcessHeap(), 0, broadcast_at_thread_exit.to_broadcast);
2563 #endif
2565 #endif
2567 #if _MSVCP_VER >= 140
2568 LONGLONG __cdecl _Query_perf_counter(void)
2570 LARGE_INTEGER li;
2571 QueryPerformanceCounter(&li);
2572 return li.QuadPart;
2575 LONGLONG __cdecl _Query_perf_frequency(void)
2577 LARGE_INTEGER li;
2578 QueryPerformanceFrequency(&li);
2579 return li.QuadPart;
2581 #endif
2583 void __cdecl threads__Mtx_new(void **mtx)
2585 *mtx = MSVCRT_operator_new(sizeof(CRITICAL_SECTION));
2586 InitializeCriticalSection(*mtx);
2589 void __cdecl threads__Mtx_delete(void *mtx)
2591 DeleteCriticalSection(mtx);
2594 void __cdecl threads__Mtx_lock(void *mtx)
2596 EnterCriticalSection(mtx);
2599 void __cdecl threads__Mtx_unlock(void *mtx)
2601 LeaveCriticalSection(mtx);
2604 #if _MSVCP_VER >= 110
2605 static LONG shared_ptr_lock;
2607 void __cdecl _Lock_shared_ptr_spin_lock(void)
2609 LONG l = 0;
2611 while(InterlockedCompareExchange(&shared_ptr_lock, 1, 0) != 0) {
2612 if(l++ == 1000) {
2613 Sleep(0);
2614 l = 0;
2619 void __cdecl _Unlock_shared_ptr_spin_lock(void)
2621 shared_ptr_lock = 0;
2623 #endif
2625 #if _MSVCP_VER >= 100
2626 /* ?is_current_task_group_canceling@Concurrency@@YA_NXZ */
2627 MSVCP_bool __cdecl is_current_task_group_canceling(void)
2629 return Context_IsCurrentTaskCollectionCanceling();
2632 /* ?_GetCombinableSize@details@Concurrency@@YAIXZ */
2633 /* ?_GetCombinableSize@details@Concurrency@@YA_KXZ */
2634 MSVCP_size_t __cdecl _GetCombinableSize(void)
2636 FIXME("() stub\n");
2637 return 11;
2639 #endif
2641 #if _MSVCP_VER >= 140
2642 typedef struct {
2643 void *unk0;
2644 BYTE unk1;
2645 } task_continuation_context;
2647 /* ??0task_continuation_context@Concurrency@@AAE@XZ */
2648 /* ??0task_continuation_context@Concurrency@@AEAA@XZ */
2649 DEFINE_THISCALL_WRAPPER(task_continuation_context_ctor, 4)
2650 task_continuation_context* __thiscall task_continuation_context_ctor(task_continuation_context *this)
2652 TRACE("(%p)\n", this);
2653 memset(this, 0, sizeof(*this));
2654 return this;
2657 typedef struct {
2658 const vtable_ptr *vtable;
2659 void (__cdecl *func)(void);
2660 int unk[4];
2661 void *unk2[3];
2662 void *this;
2663 } function_void_cdecl_void;
2665 /* ?_Assign@_ContextCallback@details@Concurrency@@AAEXPAX@Z */
2666 /* ?_Assign@_ContextCallback@details@Concurrency@@AEAAXPEAX@Z */
2667 DEFINE_THISCALL_WRAPPER(_ContextCallback__Assign, 8)
2668 void __thiscall _ContextCallback__Assign(void *this, void *v)
2670 TRACE("(%p %p)\n", this, v);
2673 #define call_function_do_call(this) CALL_VTBL_FUNC(this, 8, void, (function_void_cdecl_void*), (this))
2674 #define call_function_do_clean(this,b) CALL_VTBL_FUNC(this, 16, void, (function_void_cdecl_void*,MSVCP_bool), (this, b))
2675 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QBEXV?$function@$$A6AXXZ@std@@_N@Z */
2676 /* ?_CallInContext@_ContextCallback@details@Concurrency@@QEBAXV?$function@$$A6AXXZ@std@@_N@Z */
2677 DEFINE_THISCALL_WRAPPER(_ContextCallback__CallInContext, 48)
2678 void __thiscall _ContextCallback__CallInContext(const void *this, function_void_cdecl_void func, MSVCP_bool b)
2680 TRACE("(%p %p %x)\n", this, func.func, b);
2681 call_function_do_call(func.this);
2682 call_function_do_clean(func.this, func.this!=&func);
2685 /* ?_Capture@_ContextCallback@details@Concurrency@@AAEXXZ */
2686 /* ?_Capture@_ContextCallback@details@Concurrency@@AEAAXXZ */
2687 DEFINE_THISCALL_WRAPPER(_ContextCallback__Capture, 4)
2688 void __thiscall _ContextCallback__Capture(void *this)
2690 TRACE("(%p)\n", this);
2693 /* ?_Reset@_ContextCallback@details@Concurrency@@AAEXXZ */
2694 /* ?_Reset@_ContextCallback@details@Concurrency@@AEAAXXZ */
2695 DEFINE_THISCALL_WRAPPER(_ContextCallback__Reset, 4)
2696 void __thiscall _ContextCallback__Reset(void *this)
2698 TRACE("(%p)\n", this);
2701 /* ?_IsCurrentOriginSTA@_ContextCallback@details@Concurrency@@CA_NXZ */
2702 MSVCP_bool __cdecl _ContextCallback__IsCurrentOriginSTA(void *this)
2704 TRACE("(%p)\n", this);
2705 return FALSE;
2708 typedef struct {
2709 /*_Task_impl_base*/void *task;
2710 MSVCP_bool scheduled;
2711 MSVCP_bool started;
2712 } _TaskEventLogger;
2714 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2715 /* ?_LogCancelTask@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2716 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogCancelTask, 4)
2717 void __thiscall _TaskEventLogger__LogCancelTask(_TaskEventLogger *this)
2719 TRACE("(%p)\n", this);
2722 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QAEX_N@Z */
2723 /* ?_LogScheduleTask@_TaskEventLogger@details@Concurrency@@QEAAX_N@Z */
2724 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogScheduleTask, 8)
2725 void __thiscall _TaskEventLogger__LogScheduleTask(_TaskEventLogger *this, MSVCP_bool continuation)
2727 TRACE("(%p %x)\n", this, continuation);
2730 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2731 /* ?_LogTaskCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2732 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskCompleted, 4)
2733 void __thiscall _TaskEventLogger__LogTaskCompleted(_TaskEventLogger *this)
2735 TRACE("(%p)\n", this);
2738 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2739 /* ?_LogTaskExecutionCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2740 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogTaskExecutionCompleted, 4)
2741 void __thiscall _TaskEventLogger__LogTaskExecutionCompleted(_TaskEventLogger *this)
2743 TRACE("(%p)\n", this);
2746 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2747 /* ?_LogWorkItemCompleted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2748 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemCompleted, 4)
2749 void __thiscall _TaskEventLogger__LogWorkItemCompleted(_TaskEventLogger *this)
2751 TRACE("(%p)\n", this);
2754 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QAEXXZ */
2755 /* ?_LogWorkItemStarted@_TaskEventLogger@details@Concurrency@@QEAAXXZ */
2756 DEFINE_THISCALL_WRAPPER(_TaskEventLogger__LogWorkItemStarted, 4)
2757 void __thiscall _TaskEventLogger__LogWorkItemStarted(_TaskEventLogger *this)
2759 TRACE("(%p)\n", this);
2762 typedef struct {
2763 PTP_WORK work;
2764 void (__cdecl *callback)(void*);
2765 void *arg;
2766 } _Threadpool_chore;
2768 /* ?_Reschedule_chore@details@Concurrency@@YAHPBU_Threadpool_chore@12@@Z */
2769 /* ?_Reschedule_chore@details@Concurrency@@YAHPEBU_Threadpool_chore@12@@Z */
2770 int __cdecl _Reschedule_chore(const _Threadpool_chore *chore)
2772 TRACE("(%p)\n", chore);
2774 SubmitThreadpoolWork(chore->work);
2775 return 0;
2778 static void WINAPI threadpool_callback(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work)
2780 _Threadpool_chore *chore = context;
2781 TRACE("calling chore callback: %p\n", chore);
2782 if (chore->callback)
2783 chore->callback(chore->arg);
2786 /* ?_Schedule_chore@details@Concurrency@@YAHPAU_Threadpool_chore@12@@Z */
2787 /* ?_Schedule_chore@details@Concurrency@@YAHPEAU_Threadpool_chore@12@@Z */
2788 int __cdecl _Schedule_chore(_Threadpool_chore *chore)
2790 TRACE("(%p)\n", chore);
2792 chore->work = CreateThreadpoolWork(threadpool_callback, chore, NULL);
2793 /* FIXME: what should be returned in case of error */
2794 if(!chore->work)
2795 return -1;
2797 return _Reschedule_chore(chore);
2800 /* ?_Release_chore@details@Concurrency@@YAXPAU_Threadpool_chore@12@@Z */
2801 /* ?_Release_chore@details@Concurrency@@YAXPEAU_Threadpool_chore@12@@Z */
2802 void __cdecl _Release_chore(_Threadpool_chore *chore)
2804 TRACE("(%p)\n", chore);
2806 if(!chore->work) return;
2807 CloseThreadpoolWork(chore->work);
2808 chore->work = NULL;
2810 #endif
2812 #if _MSVCP_VER >= 110 && _MSVCP_VER <= 120
2813 typedef struct {
2814 char dummy;
2815 } _Ph;
2817 /* ?_1@placeholders@std@@3V?$_Ph@$00@2@A */
2818 /* ?_20@placeholders@std@@3V?$_Ph@$0BE@@2@A */
2819 _Ph _Ph_1 = {0}, _Ph_2 = {0}, _Ph_3 = {0}, _Ph_4 = {0}, _Ph_5 = {0};
2820 _Ph _Ph_6 = {0}, _Ph_7 = {0}, _Ph_8 = {0}, _Ph_9 = {0}, _Ph_10 = {0};
2821 _Ph _Ph_11 = {0}, _Ph_12 = {0}, _Ph_13 = {0}, _Ph_14 = {0}, _Ph_15 = {0};
2822 _Ph _Ph_16 = {0}, _Ph_17 = {0}, _Ph_18 = {0}, _Ph_19 = {0}, _Ph_20 = {0};
2823 #endif
2825 #if _MSVCP_VER >= 140
2826 /* ?_IsNonBlockingThread@_Task_impl_base@details@Concurrency@@SA_NXZ */
2827 MSVCP_bool __cdecl _Task_impl_base__IsNonBlockingThread(void)
2829 FIXME("() stub\n");
2830 return FALSE;
2832 #endif
2834 #if _MSVCP_VER >= 110
2835 /* ?_Syserror_map@std@@YAPBDH@Z */
2836 /* ?_Syserror_map@std@@YAPEBDH@Z */
2837 const char* __cdecl _Syserror_map(int err)
2839 int i;
2841 TRACE("(%d)\n", err);
2843 for(i = 0; i < ARRAY_SIZE(syserror_map); i++)
2845 if(syserror_map[i].err == err)
2846 return syserror_map[i].str;
2848 return NULL;
2850 #endif
2852 #if _MSVCP_VER >= 140
2853 /* ?_Winerror_message@std@@YAKKPADK@Z */
2854 /* ?_Winerror_message@std@@YAKKPEADK@Z */
2855 ULONG __cdecl _Winerror_message(ULONG err, char *buf, ULONG size)
2857 TRACE("(%u %p %u)\n", err, buf, size);
2859 return FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
2860 NULL, err, 0, buf, size, NULL);
2863 /* ?_Winerror_map@std@@YAHH@Z */
2864 int __cdecl _Winerror_map(int err)
2866 int low = 0, high = ARRAY_SIZE(winerror_map) - 1, mid;
2868 while(low <= high)
2870 mid = (low + high) / 2;
2872 if(err == winerror_map[mid].winerr)
2873 return winerror_map[mid].doserr;
2874 if(err > winerror_map[mid].winerr)
2875 low = mid + 1;
2876 else
2877 high = mid - 1;
2880 return 0;
2882 #endif