2 * msvcrt.dll C++ objects
4 * Copyright 2017 Piotr Caban
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
29 #include "cppexcept.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
36 static int context_id
= -1;
40 #define DEFINE_VTBL_WRAPPER(off) \
41 __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \
45 "movl 0(%ecx), %eax\n\t" \
46 "jmp *" #off "(%eax)\n\t")
48 DEFINE_VTBL_WRAPPER(0);
49 DEFINE_VTBL_WRAPPER(4);
50 DEFINE_VTBL_WRAPPER(8);
51 DEFINE_VTBL_WRAPPER(20);
56 const vtable_ptr
*vtable
;
58 #define call_Context_GetId(this) CALL_VTBL_FUNC(this, 0, \
59 unsigned int, (const Context*), (this))
60 #define call_Context_GetVirtualProcessorId(this) CALL_VTBL_FUNC(this, 4, \
61 unsigned int, (const Context*), (this))
62 #define call_Context_GetScheduleGroupId(this) CALL_VTBL_FUNC(this, 8, \
63 unsigned int, (const Context*), (this))
64 #define call_Context_dtor(this, flags) CALL_VTBL_FUNC(this, 20, \
65 Context*, (Context*, unsigned int), (this, flags))
70 } ExternalContextBase
;
71 extern const vtable_ptr MSVCRT_ExternalContextBase_vtable
;
72 static void ExternalContextBase_ctor(ExternalContextBase
*);
74 static int context_tls_index
= TLS_OUT_OF_INDEXES
;
76 static Context
* try_get_current_context(void)
78 if (context_tls_index
== TLS_OUT_OF_INDEXES
)
80 return TlsGetValue(context_tls_index
);
83 static Context
* get_current_context(void)
87 if (context_tls_index
== TLS_OUT_OF_INDEXES
) {
88 int tls_index
= TlsAlloc();
89 if (tls_index
== TLS_OUT_OF_INDEXES
) {
90 throw_scheduler_resource_allocation_error(NULL
,
91 HRESULT_FROM_WIN32(GetLastError()));
95 if(InterlockedCompareExchange(&context_tls_index
, tls_index
, TLS_OUT_OF_INDEXES
) != TLS_OUT_OF_INDEXES
)
99 ret
= TlsGetValue(context_tls_index
);
101 ExternalContextBase
*context
= MSVCRT_operator_new(sizeof(ExternalContextBase
));
102 ExternalContextBase_ctor(context
);
103 TlsSetValue(context_tls_index
, context
);
104 ret
= &context
->context
;
109 /* ?CurrentContext@Context@Concurrency@@SAPAV12@XZ */
110 /* ?CurrentContext@Context@Concurrency@@SAPEAV12@XZ */
111 Context
* __cdecl
Context_CurrentContext(void)
114 return get_current_context();
117 /* ?Id@Context@Concurrency@@SAIXZ */
118 unsigned int __cdecl
Context_Id(void)
120 Context
*ctx
= try_get_current_context();
122 return ctx
? call_Context_GetId(ctx
) : -1;
125 /* ?Block@Context@Concurrency@@SAXXZ */
126 void __cdecl
Context_Block(void)
131 /* ?Yield@Context@Concurrency@@SAXXZ */
132 void __cdecl
Context_Yield(void)
137 /* ?_SpinYield@Context@Concurrency@@SAXXZ */
138 void __cdecl
Context__SpinYield(void)
143 /* ?IsCurrentTaskCollectionCanceling@Context@Concurrency@@SA_NXZ */
144 MSVCRT_bool __cdecl
Context_IsCurrentTaskCollectionCanceling(void)
150 /* ?Oversubscribe@Context@Concurrency@@SAX_N@Z */
151 void __cdecl
Context_Oversubscribe(MSVCRT_bool begin
)
153 FIXME("(%x)\n", begin
);
156 /* ?ScheduleGroupId@Context@Concurrency@@SAIXZ */
157 unsigned int __cdecl
Context_ScheduleGroupId(void)
159 Context
*ctx
= try_get_current_context();
161 return ctx
? call_Context_GetScheduleGroupId(ctx
) : -1;
164 /* ?VirtualProcessorId@Context@Concurrency@@SAIXZ */
165 unsigned int __cdecl
Context_VirtualProcessorId(void)
167 Context
*ctx
= try_get_current_context();
169 return ctx
? call_Context_GetVirtualProcessorId(ctx
) : -1;
172 DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetId
, 4)
173 unsigned int __thiscall
ExternalContextBase_GetId(const ExternalContextBase
*this)
175 TRACE("(%p)->()\n", this);
179 DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetVirtualProcessorId
, 4)
180 unsigned int __thiscall
ExternalContextBase_GetVirtualProcessorId(const ExternalContextBase
*this)
182 FIXME("(%p)->() stub\n", this);
186 DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetScheduleGroupId
, 4)
187 unsigned int __thiscall
ExternalContextBase_GetScheduleGroupId(const ExternalContextBase
*this)
189 FIXME("(%p)->() stub\n", this);
193 DEFINE_THISCALL_WRAPPER(ExternalContextBase_Unblock
, 4)
194 void __thiscall
ExternalContextBase_Unblock(ExternalContextBase
*this)
196 FIXME("(%p)->() stub\n", this);
199 DEFINE_THISCALL_WRAPPER(ExternalContextBase_IsSynchronouslyBlocked
, 4)
200 MSVCRT_bool __thiscall
ExternalContextBase_IsSynchronouslyBlocked(const ExternalContextBase
*this)
202 FIXME("(%p)->() stub\n", this);
206 static void ExternalContextBase_dtor(ExternalContextBase
*this)
210 DEFINE_THISCALL_WRAPPER(ExternalContextBase_vector_dtor
, 8)
211 Context
* __thiscall
ExternalContextBase_vector_dtor(ExternalContextBase
*this, unsigned int flags
)
213 TRACE("(%p %x)\n", this, flags
);
215 /* we have an array, with the number of elements stored before the first object */
216 INT_PTR i
, *ptr
= (INT_PTR
*)this-1;
218 for(i
=*ptr
-1; i
>=0; i
--)
219 ExternalContextBase_dtor(this+i
);
220 MSVCRT_operator_delete(ptr
);
222 ExternalContextBase_dtor(this);
224 MSVCRT_operator_delete(this);
227 return &this->context
;
230 static void ExternalContextBase_ctor(ExternalContextBase
*this)
232 TRACE("(%p)->()\n", this);
233 this->context
.vtable
= &MSVCRT_ExternalContextBase_vtable
;
234 this->id
= InterlockedIncrement(&context_id
);
237 extern const vtable_ptr MSVCRT_type_info_vtable
;
238 DEFINE_RTTI_DATA0(Context
, 0, ".?AVContext@Concurrency@@")
239 DEFINE_RTTI_DATA1(ContextBase
, 0, &Context_rtti_base_descriptor
, ".?AVContextBase@details@Concurrency@@")
240 DEFINE_RTTI_DATA2(ExternalContextBase
, 0, &ContextBase_rtti_base_descriptor
,
241 &Context_rtti_base_descriptor
, ".?AVExternalContextBase@details@Concurrency@@")
244 void __asm_dummy_vtables(void) {
246 __ASM_VTABLE(ExternalContextBase
,
247 VTABLE_ADD_FUNC(ExternalContextBase_GetId
)
248 VTABLE_ADD_FUNC(ExternalContextBase_GetVirtualProcessorId
)
249 VTABLE_ADD_FUNC(ExternalContextBase_GetScheduleGroupId
)
250 VTABLE_ADD_FUNC(ExternalContextBase_Unblock
)
251 VTABLE_ADD_FUNC(ExternalContextBase_IsSynchronouslyBlocked
)
252 VTABLE_ADD_FUNC(ExternalContextBase_vector_dtor
));
257 void msvcrt_init_scheduler(void *base
)
260 init_Context_rtti(base
);
261 init_ContextBase_rtti(base
);
262 init_ExternalContextBase_rtti(base
);
266 void msvcrt_free_scheduler(void)
268 if (context_tls_index
!= TLS_OUT_OF_INDEXES
)
269 TlsFree(context_tls_index
);
272 void msvcrt_free_scheduler_thread(void)
274 Context
*context
= try_get_current_context();
275 if (!context
) return;
276 call_Context_dtor(context
, 1);
279 #endif /* _MSVCR_VER >= 100 */