40static LONG context_id = -1;
41static LONG scheduler_id = -1;
47 TargetOversubscriptionFactor,
48 LocalContextCacheSize,
52 DynamicProgressFeedback,
58 struct _policy_container {
59 unsigned int policies[last_policy_id];
66#define call_Context_GetId(this) CALL_VTBL_FUNC(this, 0, \
67 unsigned int, (const Context*), (this))
68#define call_Context_GetVirtualProcessorId(this) CALL_VTBL_FUNC(this, 4, \
69 unsigned int, (const Context*), (this))
70#define call_Context_GetScheduleGroupId(this) CALL_VTBL_FUNC(this, 8, \
71 unsigned int, (const Context*), (this))
72#define call_Context_Unblock(this) CALL_VTBL_FUNC(this, 12, \
73 void, (Context*), (this))
74#define call_Context_IsSynchronouslyBlocked(this) CALL_VTBL_FUNC(this, 16, \
75 bool, (const Context*), (this))
76#define call_Context_dtor(this, flags) CALL_VTBL_FUNC(this, 20, \
77 Context*, (Context*, unsigned int), (this, flags))
78#define call_Context_Block(this) CALL_VTBL_FUNC(this, 24, \
79 void, (Context*), (this))
85union allocator_cache_entry {
88 union allocator_cache_entry *
next;
96struct scheduler_list {
97 struct Scheduler *scheduler;
98 struct scheduler_list *
next;
104 struct _StructuredTaskCollection *task_collection;
109 struct scheduler_list scheduler;
111 union allocator_cache_entry *allocator_cache[8];
113 struct _StructuredTaskCollection *task_collection;
116} ExternalContextBase;
117extern const vtable_ptr ExternalContextBase_vtable;
118static void ExternalContextBase_ctor(ExternalContextBase*);
120typedef struct Scheduler {
123#define call_Scheduler_Id(this) CALL_VTBL_FUNC(this, 4, unsigned int, (const Scheduler*), (this))
124#define call_Scheduler_GetNumberOfVirtualProcessors(this) CALL_VTBL_FUNC(this, 8, unsigned int, (const Scheduler*), (this))
125#define call_Scheduler_GetPolicy(this,policy) CALL_VTBL_FUNC(this, 12, \
126 SchedulerPolicy*, (Scheduler*,SchedulerPolicy*), (this,policy))
127#define call_Scheduler_Reference(this) CALL_VTBL_FUNC(this, 16, unsigned int, (Scheduler*), (this))
128#define call_Scheduler_Release(this) CALL_VTBL_FUNC(this, 20, unsigned int, (Scheduler*), (this))
129#define call_Scheduler_RegisterShutdownEvent(this,event) CALL_VTBL_FUNC(this, 24, void, (Scheduler*,HANDLE), (this,event))
130#define call_Scheduler_Attach(this) CALL_VTBL_FUNC(this, 28, void, (Scheduler*), (this))
132#define call_Scheduler_CreateScheduleGroup_loc(this,placement) CALL_VTBL_FUNC(this, 32, \
133 void*, (Scheduler*,void*), (this,placement))
134#define call_Scheduler_CreateScheduleGroup(this) CALL_VTBL_FUNC(this, 36, void*, (Scheduler*), (this))
135#define call_Scheduler_ScheduleTask_loc(this,proc,data,placement) CALL_VTBL_FUNC(this, 40, \
136 void, (Scheduler*,void (__cdecl*)(void*),void*,void*), (this,proc,data,placement))
137#define call_Scheduler_ScheduleTask(this,proc,data) CALL_VTBL_FUNC(this, 44, \
138 void, (Scheduler*,void (__cdecl*)(void*),void*), (this,proc,data))
139#define call_Scheduler_IsAvailableLocation(this,placement) CALL_VTBL_FUNC(this, 48, \
140 bool, (Scheduler*,const void*), (this,placement))
142#define call_Scheduler_CreateScheduleGroup(this) CALL_VTBL_FUNC(this, 32, void*, (Scheduler*), (this))
143#define call_Scheduler_ScheduleTask(this,proc,data) CALL_VTBL_FUNC(this, 36, \
144 void, (Scheduler*,void (__cdecl*)(void*),void*), (this,proc,data))
151 unsigned int virt_proc_no;
157 struct list scheduled_chores;
159extern const vtable_ptr ThreadScheduler_vtable;
162 Scheduler *scheduler;
183 SpinWait_state
state;
184 yield_func yield_func;
187#define FINISHED_INITIAL 0x80000000
188typedef struct _StructuredTaskCollection
195 volatile LONG finished;
198} _StructuredTaskCollection;
200bool __thiscall _StructuredTaskCollection__IsCanceling(_StructuredTaskCollection*);
204 TASK_COLLECTION_SUCCESS = 1,
205 TASK_COLLECTION_CANCELLED
206} _TaskCollectionStatus;
210 STRUCTURED_TASK_COLLECTION_CANCELLED = 0x2,
211 STRUCTURED_TASK_COLLECTION_STATUS_MASK = 0x7
212} _StructuredTaskCollectionStatusBits;
214typedef struct _UnrealizedChore
217 void (
__cdecl *chore_proc)(
struct _UnrealizedChore*);
218 _StructuredTaskCollection *task_collection;
219 void (
__cdecl *chore_wrapper)(
struct _UnrealizedChore*);
223struct scheduled_chore {
225 _UnrealizedChore *chore;
229typedef struct cs_queue
232 struct cs_queue *
next;
261} critical_section_scoped_lock;
266} _NonReentrantPPLLock;
270 _NonReentrantPPLLock *
lock;
278} _NonReentrantPPLLock__Scoped_lock;
289 _ReentrantPPLLock *
lock;
297} _ReentrantPPLLock__Scoped_lock;
305#define EVT_RUNNING (void*)1
306#define EVT_WAITING NULL
309typedef struct thread_wait_entry
311 struct thread_wait *wait;
312 struct thread_wait_entry *
next;
313 struct thread_wait_entry *prev;
316typedef struct thread_wait
321 thread_wait_entry entries[1];
326 thread_wait_entry *waiters;
332#define CV_WAKE (void*)1
333typedef struct cv_queue {
335 struct cv_queue *
next;
340 struct beacon *beacon;
341} _Cancellation_beacon;
347} _Condition_variable;
350typedef struct rwl_queue
352 struct rwl_queue *
next;
356#define WRITER_WAITING 0x80000000
364 rwl_queue *writer_head;
365 rwl_queue *writer_tail;
366 rwl_queue *reader_head;
370 reader_writer_lock *
lock;
371} reader_writer_lock_scoped_lock;
375} _ReentrantBlockingLock;
377#define TICKSPERMSEC 10000
385#define call__Timer_callback(this) CALL_VTBL_FUNC(this, 4, void, (_Timer*), (this))
390typedef exception improper_scheduler_attach;
391extern const vtable_ptr improper_scheduler_attach_vtable;
393typedef exception improper_scheduler_detach;
394extern const vtable_ptr improper_scheduler_detach_vtable;
396typedef exception invalid_multiple_scheduling;
397extern const vtable_ptr invalid_multiple_scheduling_vtable;
399typedef exception invalid_scheduler_policy_key;
400extern const vtable_ptr invalid_scheduler_policy_key_vtable;
402typedef exception invalid_scheduler_policy_thread_specification;
403extern const vtable_ptr invalid_scheduler_policy_thread_specification_vtable;
405typedef exception invalid_scheduler_policy_value;
406extern const vtable_ptr invalid_scheduler_policy_value_vtable;
414} scheduler_resource_allocation_error;
415extern const vtable_ptr scheduler_resource_allocation_error_vtable;
419 CONCRT_EVENT_GENERIC,
423 CONCRT_EVENT_UNBLOCK,
434 0, 0, &default_scheduler_cs,
436 0, 0, { (
DWORD_PTR)(__FILE__
": default_scheduler_cs") }
438static CRITICAL_SECTION default_scheduler_cs = { &default_scheduler_cs_debug, -1, 0, 0, 0, 0 };
439static SchedulerPolicy default_scheduler_policy;
440static ThreadScheduler *default_scheduler;
442static void create_default_scheduler(
void);
450 return __exception_ctor(
this,
str, &improper_lock_vtable);
456improper_lock*
__thiscall improper_lock_ctor(improper_lock *this)
458 return improper_lock_ctor_str(
this,
NULL);
462improper_lock *
__thiscall improper_lock_copy_ctor(improper_lock *this,
const improper_lock *rhs)
464 TRACE(
"(%p %p)\n",
this, rhs);
465 return __exception_copy_ctor(
this, rhs, &improper_lock_vtable);
471improper_scheduler_attach*
__thiscall improper_scheduler_attach_ctor_str(
472 improper_scheduler_attach *this,
const char *
str)
475 return __exception_ctor(
this,
str, &improper_scheduler_attach_vtable);
481improper_scheduler_attach*
__thiscall improper_scheduler_attach_ctor(
482 improper_scheduler_attach *this)
484 return improper_scheduler_attach_ctor_str(
this,
NULL);
488improper_scheduler_attach *
__thiscall improper_scheduler_attach_copy_ctor(
489 improper_scheduler_attach * _this,
const improper_scheduler_attach * rhs)
491 TRACE(
"(%p %p)\n", _this, rhs);
492 return __exception_copy_ctor(_this, rhs, &improper_scheduler_attach_vtable);
498improper_scheduler_detach*
__thiscall improper_scheduler_detach_ctor_str(
499 improper_scheduler_detach *this,
const char *
str)
502 return __exception_ctor(
this,
str, &improper_scheduler_detach_vtable);
508improper_scheduler_detach*
__thiscall improper_scheduler_detach_ctor(
509 improper_scheduler_detach *this)
511 return improper_scheduler_detach_ctor_str(
this,
NULL);
515improper_scheduler_detach *
__thiscall improper_scheduler_detach_copy_ctor(
516 improper_scheduler_detach * _this,
const improper_scheduler_detach * rhs)
518 TRACE(
"(%p %p)\n", _this, rhs);
519 return __exception_copy_ctor(_this, rhs, &improper_scheduler_detach_vtable);
526invalid_multiple_scheduling*
__thiscall invalid_multiple_scheduling_ctor_str(
527 invalid_multiple_scheduling *this,
const char *
str)
530 return __exception_ctor(
this,
str, &invalid_multiple_scheduling_vtable);
537invalid_multiple_scheduling*
__thiscall invalid_multiple_scheduling_ctor(
538 invalid_multiple_scheduling *this)
540 return invalid_multiple_scheduling_ctor_str(
this,
NULL);
544invalid_multiple_scheduling *
__thiscall invalid_multiple_scheduling_copy_ctor(
545 invalid_multiple_scheduling * _this,
const invalid_multiple_scheduling * rhs)
547 TRACE(
"(%p %p)\n", _this, rhs);
548 return __exception_copy_ctor(_this, rhs, &invalid_multiple_scheduling_vtable);
554invalid_scheduler_policy_key*
__thiscall invalid_scheduler_policy_key_ctor_str(
555 invalid_scheduler_policy_key *this,
const char *
str)
558 return __exception_ctor(
this,
str, &invalid_scheduler_policy_key_vtable);
564invalid_scheduler_policy_key*
__thiscall invalid_scheduler_policy_key_ctor(
565 invalid_scheduler_policy_key *this)
567 return invalid_scheduler_policy_key_ctor_str(
this,
NULL);
571invalid_scheduler_policy_key *
__thiscall invalid_scheduler_policy_key_copy_ctor(
572 invalid_scheduler_policy_key * _this,
const invalid_scheduler_policy_key * rhs)
574 TRACE(
"(%p %p)\n", _this, rhs);
575 return __exception_copy_ctor(_this, rhs, &invalid_scheduler_policy_key_vtable);
581invalid_scheduler_policy_thread_specification*
__thiscall invalid_scheduler_policy_thread_specification_ctor_str(
582 invalid_scheduler_policy_thread_specification *this,
const char *
str)
585 return __exception_ctor(
this,
str, &invalid_scheduler_policy_thread_specification_vtable);
591invalid_scheduler_policy_thread_specification*
__thiscall invalid_scheduler_policy_thread_specification_ctor(
592 invalid_scheduler_policy_thread_specification *this)
594 return invalid_scheduler_policy_thread_specification_ctor_str(
this,
NULL);
598invalid_scheduler_policy_thread_specification *
__thiscall invalid_scheduler_policy_thread_specification_copy_ctor(
599 invalid_scheduler_policy_thread_specification * _this,
const invalid_scheduler_policy_thread_specification * rhs)
601 TRACE(
"(%p %p)\n", _this, rhs);
602 return __exception_copy_ctor(_this, rhs, &invalid_scheduler_policy_thread_specification_vtable);
608invalid_scheduler_policy_value*
__thiscall invalid_scheduler_policy_value_ctor_str(
609 invalid_scheduler_policy_value *this,
const char *
str)
612 return __exception_ctor(
this,
str, &invalid_scheduler_policy_value_vtable);
618invalid_scheduler_policy_value*
__thiscall invalid_scheduler_policy_value_ctor(
619 invalid_scheduler_policy_value *this)
621 return invalid_scheduler_policy_value_ctor_str(
this,
NULL);
625invalid_scheduler_policy_value *
__thiscall invalid_scheduler_policy_value_copy_ctor(
626 invalid_scheduler_policy_value * _this,
const invalid_scheduler_policy_value * rhs)
628 TRACE(
"(%p %p)\n", _this, rhs);
629 return __exception_copy_ctor(_this, rhs, &invalid_scheduler_policy_value_vtable);
636missing_wait*
__thiscall missing_wait_ctor_str(
637 missing_wait *this,
const char *
str)
640 return __exception_ctor(
this,
str, &missing_wait_vtable);
647missing_wait*
__thiscall missing_wait_ctor(missing_wait *this)
649 return missing_wait_ctor_str(
this,
NULL);
653missing_wait *
__thiscall missing_wait_copy_ctor(
654 missing_wait * _this,
const missing_wait * rhs)
656 TRACE(
"(%p %p)\n", _this, rhs);
657 return __exception_copy_ctor(_this, rhs, &missing_wait_vtable);
663scheduler_resource_allocation_error*
__thiscall scheduler_resource_allocation_error_ctor_name(
667 __exception_ctor(&this->
e, name, &scheduler_resource_allocation_error_vtable);
675scheduler_resource_allocation_error*
__thiscall scheduler_resource_allocation_error_ctor(
676 scheduler_resource_allocation_error *this,
HRESULT hr)
678 return scheduler_resource_allocation_error_ctor_name(
this,
NULL,
hr);
682scheduler_resource_allocation_error*
__thiscall scheduler_resource_allocation_error_copy_ctor(
683 scheduler_resource_allocation_error *this,
684 const scheduler_resource_allocation_error *rhs)
686 TRACE(
"(%p,%p)\n",
this, rhs);
689 memcpy(
this, rhs,
sizeof(*
this));
691 scheduler_resource_allocation_error_ctor_name(
this, rhs->e.name, rhs->hr);
699 const scheduler_resource_allocation_error *this)
701 TRACE(
"(%p)\n",
this);
706 ".?AVimproper_lock@Concurrency@@")
708 ".?AVimproper_scheduler_attach@Concurrency@
@")
709DEFINE_RTTI_DATA1(improper_scheduler_detach, 0, &cexception_rtti_base_descriptor,
710 ".?AVimproper_scheduler_detach@Concurrency@
@")
711DEFINE_RTTI_DATA1(invalid_multiple_scheduling, 0, &cexception_rtti_base_descriptor,
712 ".?AVinvalid_multiple_scheduling@Concurrency@
@")
713DEFINE_RTTI_DATA1(invalid_scheduler_policy_key, 0, &cexception_rtti_base_descriptor,
714 ".?AVinvalid_scheduler_policy_key@Concurrency@
@")
715DEFINE_RTTI_DATA1(invalid_scheduler_policy_thread_specification, 0, &cexception_rtti_base_descriptor,
716 ".?AVinvalid_scheduler_policy_thread_specification@Concurrency@
@")
717DEFINE_RTTI_DATA1(invalid_scheduler_policy_value, 0, &cexception_rtti_base_descriptor,
718 ".?AVinvalid_scheduler_policy_value@Concurrency@
@")
719DEFINE_RTTI_DATA1(missing_wait, 0, &cexception_rtti_base_descriptor,
720 ".?AVmissing_wait@Concurrency@
@")
721DEFINE_RTTI_DATA1(scheduler_resource_allocation_error, 0, &cexception_rtti_base_descriptor,
722 ".?AVscheduler_resource_allocation_error@Concurrency@
@")
724DEFINE_CXX_DATA1(improper_lock, &cexception_cxx_type_info, cexception_dtor)
725DEFINE_CXX_DATA1(improper_scheduler_attach, &cexception_cxx_type_info, cexception_dtor)
726DEFINE_CXX_DATA1(improper_scheduler_detach, &cexception_cxx_type_info, cexception_dtor)
727DEFINE_CXX_DATA1(invalid_multiple_scheduling, &cexception_cxx_type_info, cexception_dtor)
728DEFINE_CXX_DATA1(invalid_scheduler_policy_key, &cexception_cxx_type_info, cexception_dtor)
729DEFINE_CXX_DATA1(invalid_scheduler_policy_thread_specification, &cexception_cxx_type_info, cexception_dtor)
730DEFINE_CXX_DATA1(invalid_scheduler_policy_value, &cexception_cxx_type_info, cexception_dtor)
732DEFINE_CXX_DATA1(missing_wait, &cexception_cxx_type_info, cexception_dtor)
734DEFINE_CXX_DATA1(scheduler_resource_allocation_error, &cexception_cxx_type_info, cexception_dtor)
736__ASM_BLOCK_BEGIN(concurrency_exception_vtables)
737 __ASM_VTABLE(improper_lock,
738 VTABLE_ADD_FUNC(cexception_vector_dtor)
739 VTABLE_ADD_FUNC(cexception_what));
740 __ASM_VTABLE(improper_scheduler_attach,
741 VTABLE_ADD_FUNC(cexception_vector_dtor)
742 VTABLE_ADD_FUNC(cexception_what));
743 __ASM_VTABLE(improper_scheduler_detach,
744 VTABLE_ADD_FUNC(cexception_vector_dtor)
745 VTABLE_ADD_FUNC(cexception_what));
746 __ASM_VTABLE(invalid_multiple_scheduling,
747 VTABLE_ADD_FUNC(cexception_vector_dtor)
748 VTABLE_ADD_FUNC(cexception_what));
749 __ASM_VTABLE(invalid_scheduler_policy_key,
750 VTABLE_ADD_FUNC(cexception_vector_dtor)
751 VTABLE_ADD_FUNC(cexception_what));
752 __ASM_VTABLE(invalid_scheduler_policy_thread_specification,
753 VTABLE_ADD_FUNC(cexception_vector_dtor)
754 VTABLE_ADD_FUNC(cexception_what));
755 __ASM_VTABLE(invalid_scheduler_policy_value,
756 VTABLE_ADD_FUNC(cexception_vector_dtor)
757 VTABLE_ADD_FUNC(cexception_what));
758 __ASM_VTABLE(missing_wait,
759 VTABLE_ADD_FUNC(cexception_vector_dtor)
760 VTABLE_ADD_FUNC(cexception_what));
761 __ASM_VTABLE(scheduler_resource_allocation_error,
762 VTABLE_ADD_FUNC(cexception_vector_dtor)
763 VTABLE_ADD_FUNC(cexception_what));
766static Context* try_get_current_context(void)
768 if (context_tls_index == TLS_OUT_OF_INDEXES)
770 return TlsGetValue(context_tls_index);
773static BOOL WINAPI init_context_tls_index(INIT_ONCE *once, void *param, void **context)
775 context_tls_index = TlsAlloc();
776 return context_tls_index != TLS_OUT_OF_INDEXES;
779static Context* get_current_context(void)
781 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
784 if(!InitOnceExecuteOnce(&init_once, init_context_tls_index, NULL, NULL))
786 scheduler_resource_allocation_error e;
787 scheduler_resource_allocation_error_ctor_name(&e, NULL,
788 HRESULT_FROM_WIN32(GetLastError()));
789 _CxxThrowException(&e, &scheduler_resource_allocation_error_exception_type);
792 ret = TlsGetValue(context_tls_index);
794 ExternalContextBase *context = operator_new(sizeof(ExternalContextBase));
795 ExternalContextBase_ctor(context);
796 TlsSetValue(context_tls_index, context);
797 ret = &context->context;
802static Scheduler* get_scheduler_from_context(Context *ctx)
804 ExternalContextBase *context = (ExternalContextBase*)ctx;
806 if (context->context.vtable != &ExternalContextBase_vtable)
808 return context->scheduler.scheduler;
811static Scheduler* try_get_current_scheduler(void)
813 Context *context = try_get_current_context();
819 ret = get_scheduler_from_context(context);
825static Scheduler* get_current_scheduler(
void)
832 ERR(
"unknown context set\n");
841 return get_current_context();
845unsigned int __cdecl Context_Id(
void)
849 return ctx ? call_Context_GetId(
ctx) : -1;
853void __cdecl Context_Block(
void)
857 call_Context_Block(
ctx);
862void __cdecl Context_Yield(
void)
864 static unsigned int once;
871void __cdecl Context__SpinYield(
void)
877bool __cdecl Context_IsCurrentTaskCollectionCanceling(
void)
879 ExternalContextBase *
ctx = (ExternalContextBase*)try_get_current_context();
883 if (
ctx &&
ctx->context.vtable != &ExternalContextBase_vtable) {
884 ERR(
"unknown context set\n");
888 if (
ctx &&
ctx->task_collection)
889 return _StructuredTaskCollection__IsCanceling(
ctx->task_collection);
900unsigned int __cdecl Context_ScheduleGroupId(
void)
904 return ctx ? call_Context_GetScheduleGroupId(
ctx) : -1;
908unsigned int __cdecl Context_VirtualProcessorId(
void)
912 return ctx ? call_Context_GetVirtualProcessorId(
ctx) : -1;
920 ret->context = Context_CurrentContext();
927 TRACE(
"(%p)\n",
this);
928 return call_Context_IsSynchronouslyBlocked(this->context);
935 TRACE(
"(%p)->()\n",
this);
942 FIXME(
"(%p)->() stub\n",
this);
949 FIXME(
"(%p)->() stub\n",
this);
954void __thiscall ExternalContextBase_Unblock(ExternalContextBase *this)
956 TRACE(
"(%p)->()\n",
this);
966 TRACE(
"(%p)->()\n",
this);
967 return this->blocked >= 1;
971void __thiscall ExternalContextBase_Block(ExternalContextBase *this)
975 TRACE(
"(%p)->()\n",
this);
981 blocked = this->blocked;
986void __thiscall ExternalContextBase_Yield(ExternalContextBase *this)
988 FIXME(
"(%p)->() stub\n",
this);
992void __thiscall ExternalContextBase_SpinYield(ExternalContextBase *this)
994 FIXME(
"(%p)->() stub\n",
this);
999 ExternalContextBase *this,
bool oversubscribe)
1001 FIXME(
"(%p)->(%x) stub\n",
this, oversubscribe);
1007 FIXME(
"(%p)->(%Iu) stub\n",
this,
size);
1018int __thiscall ExternalContextBase_EnterCriticalRegionHelper(ExternalContextBase *this)
1020 FIXME(
"(%p)->() stub\n",
this);
1025int __thiscall ExternalContextBase_EnterHyperCriticalRegionHelper(ExternalContextBase *this)
1027 FIXME(
"(%p)->() stub\n",
this);
1032int __thiscall ExternalContextBase_ExitCriticalRegionHelper(ExternalContextBase *this)
1034 FIXME(
"(%p)->() stub\n",
this);
1039int __thiscall ExternalContextBase_ExitHyperCriticalRegionHelper(ExternalContextBase *this)
1041 FIXME(
"(%p)->() stub\n",
this);
1046int __thiscall ExternalContextBase_GetCriticalRegionType(
const ExternalContextBase *this)
1048 FIXME(
"(%p)->() stub\n",
this);
1055 FIXME(
"(%p)->() stub\n",
this);
1059static void remove_scheduled_chores(Scheduler *scheduler,
const ExternalContextBase *
context)
1061 ThreadScheduler *tscheduler = (ThreadScheduler*)scheduler;
1062 struct scheduled_chore *sc, *
next;
1064 if (tscheduler->scheduler.vtable != &ThreadScheduler_vtable)
1069 struct scheduled_chore,
entry) {
1070 if (sc->chore->task_collection->context == &
context->context) {
1078static void ExternalContextBase_dtor(ExternalContextBase *
this)
1080 struct scheduler_list *scheduler_cur, *scheduler_next;
1081 union allocator_cache_entry *
next, *
cur;
1092 if (this->scheduler.scheduler) {
1093 remove_scheduled_chores(this->scheduler.scheduler,
this);
1094 call_Scheduler_Release(this->scheduler.scheduler);
1096 for(scheduler_cur=this->scheduler.next; scheduler_cur; scheduler_cur=scheduler_next) {
1097 scheduler_next = scheduler_cur->next;
1098 remove_scheduled_chores(scheduler_cur->scheduler,
this);
1099 call_Scheduler_Release(scheduler_cur->scheduler);
1106 ERR(
"beacons list is not empty - expect crash\n");
1118 ExternalContextBase_dtor(
this+
i);
1121 ExternalContextBase_dtor(
this);
1126 return &this->context;
1129static void ExternalContextBase_ctor(ExternalContextBase *
this)
1131 TRACE(
"(%p)->()\n",
this);
1133 memset(
this, 0,
sizeof(*
this));
1134 this->context.vtable = &ExternalContextBase_vtable;
1139 create_default_scheduler();
1140 this->scheduler.scheduler = &default_scheduler->scheduler;
1141 call_Scheduler_Reference(&default_scheduler->scheduler);
1146void *
CDECL Concurrency_Alloc(
size_t size)
1148 ExternalContextBase *
context = (ExternalContextBase*)get_current_context();
1149 union allocator_cache_entry *
p;
1152 if (
size <
sizeof(*
p))
1155 if (
context->context.vtable != &ExternalContextBase_vtable) {
1157 p->alloc.bucket = -1;
1161 C_ASSERT(
sizeof(
union allocator_cache_entry) <= 1 << 4);
1163 if (1 << (
i+4) >=
size)
break;
1167 p->alloc.bucket = -1;
1168 }
else if (
context->allocator_cache[
i]) {
1170 context->allocator_cache[
i] =
p->free.next;
1171 p->alloc.bucket =
i;
1174 p->alloc.bucket =
i;
1178 TRACE(
"(%Iu) returning %p\n",
size,
p->alloc.mem);
1179 return p->alloc.mem;
1184void CDECL Concurrency_Free(
void*
mem)
1186 union allocator_cache_entry *
p = (
union allocator_cache_entry*)((
char*)
mem-
FIELD_OFFSET(
union allocator_cache_entry,
alloc.mem));
1187 ExternalContextBase *
context = (ExternalContextBase*)get_current_context();
1188 int bucket =
p->alloc.bucket;
1192 if (
context->context.vtable != &ExternalContextBase_vtable) {
1196 (!
context->allocator_cache[bucket] ||
context->allocator_cache[bucket]->free.depth < 20)) {
1197 p->free.next =
context->allocator_cache[bucket];
1198 p->free.depth =
p->free.next ?
p->free.next->free.depth+1 : 0;
1199 context->allocator_cache[bucket] =
p;
1210 PolicyElementKey
policy,
unsigned int val)
1216 if (
policy == MinConcurrency) {
1217 invalid_scheduler_policy_key
e;
1218 invalid_scheduler_policy_key_ctor_str(&
e,
"MinConcurrency");
1221 if (
policy == MaxConcurrency) {
1222 invalid_scheduler_policy_key
e;
1223 invalid_scheduler_policy_key_ctor_str(&
e,
"MaxConcurrency");
1226 if (
policy >= last_policy_id) {
1227 invalid_scheduler_policy_key
e;
1228 invalid_scheduler_policy_key_ctor_str(&
e,
"Invalid policy");
1235 invalid_scheduler_policy_value
e;
1236 invalid_scheduler_policy_value_ctor_str(&
e,
"SchedulerKind");
1240 case TargetOversubscriptionFactor:
1242 invalid_scheduler_policy_value
e;
1243 invalid_scheduler_policy_value_ctor_str(&
e,
"TargetOversubscriptionFactor");
1247 case ContextPriority:
1252 invalid_scheduler_policy_value
e;
1253 invalid_scheduler_policy_value_ctor_str(&
e,
"ContextPriority");
1257 case SchedulingProtocol:
1258 case DynamicProgressFeedback:
1259 case WinRTInitialization:
1260 if (
val != 0 &&
val != 1) {
1261 invalid_scheduler_policy_value
e;
1262 invalid_scheduler_policy_value_ctor_str(&
e,
"SchedulingProtocol");
1270 ret = this->policy_container->policies[
policy];
1271 this->policy_container->policies[
policy] =
val;
1278void __thiscall SchedulerPolicy_SetConcurrencyLimits(SchedulerPolicy *this,
1279 unsigned int min_concurrency,
unsigned int max_concurrency)
1281 TRACE(
"(%p %d %d)\n",
this, min_concurrency, max_concurrency);
1283 if (min_concurrency > max_concurrency) {
1284 invalid_scheduler_policy_thread_specification
e;
1285 invalid_scheduler_policy_thread_specification_ctor_str(&
e,
NULL);
1288 if (!max_concurrency) {
1289 invalid_scheduler_policy_value
e;
1290 invalid_scheduler_policy_value_ctor_str(&
e,
"MaxConcurrency");
1294 this->policy_container->policies[MinConcurrency] = min_concurrency;
1295 this->policy_container->policies[MaxConcurrency] = max_concurrency;
1302 const SchedulerPolicy *this, PolicyElementKey
policy)
1306 if (
policy >= last_policy_id) {
1307 invalid_scheduler_policy_key
e;
1308 invalid_scheduler_policy_key_ctor_str(&
e,
"Invalid policy");
1311 return this->policy_container->policies[
policy];
1317SchedulerPolicy*
__thiscall SchedulerPolicy_ctor(SchedulerPolicy *this)
1319 TRACE(
"(%p)\n",
this);
1321 this->policy_container =
operator_new(
sizeof(*this->policy_container));
1323 this->policy_container->policies[SchedulerKind] = 0;
1324 this->policy_container->policies[MaxConcurrency] = -1;
1325 this->policy_container->policies[MinConcurrency] = 1;
1326 this->policy_container->policies[TargetOversubscriptionFactor] = 1;
1327 this->policy_container->policies[LocalContextCacheSize] = 8;
1328 this->policy_container->policies[ContextStackSize] = 0;
1330 this->policy_container->policies[SchedulingProtocol] = 0;
1331 this->policy_container->policies[DynamicProgressFeedback] = 1;
1338SchedulerPolicy*
WINAPIV SchedulerPolicy_ctor_policies(
1339 SchedulerPolicy *
this,
size_t n, ...)
1341 unsigned int min_concurrency, max_concurrency;
1345 TRACE(
"(%p %Iu)\n",
this,
n);
1347 SchedulerPolicy_ctor(
this);
1348 min_concurrency = this->policy_container->policies[MinConcurrency];
1349 max_concurrency = this->policy_container->policies[MaxConcurrency];
1352 for(
i=0;
i<
n;
i++) {
1356 if(
policy == MinConcurrency)
1357 min_concurrency =
val;
1358 else if(
policy == MaxConcurrency)
1359 max_concurrency =
val;
1361 SchedulerPolicy_SetPolicyValue(
this,
policy,
val);
1365 SchedulerPolicy_SetConcurrencyLimits(
this, min_concurrency, max_concurrency);
1372SchedulerPolicy*
__thiscall SchedulerPolicy_op_assign(
1373 SchedulerPolicy *this,
const SchedulerPolicy *rhs)
1375 TRACE(
"(%p %p)\n",
this, rhs);
1376 memcpy(this->policy_container->policies, rhs->policy_container->policies,
1377 sizeof(this->policy_container->policies));
1384SchedulerPolicy*
__thiscall SchedulerPolicy_copy_ctor(
1385 SchedulerPolicy *this,
const SchedulerPolicy *rhs)
1387 TRACE(
"(%p %p)\n",
this, rhs);
1388 SchedulerPolicy_ctor(
this);
1389 return SchedulerPolicy_op_assign(
this, rhs);
1397 TRACE(
"(%p)\n",
this);
1401static void ThreadScheduler_dtor(ThreadScheduler *
this)
1404 struct scheduled_chore *sc, *
next;
1406 if(this->
ref != 0)
WARN(
"ref = %ld\n", this->
ref);
1407 SchedulerPolicy_dtor(&this->policy);
1409 for(
i=0;
i<this->shutdown_count;
i++)
1413 this->
cs.DebugInfo->Spare[0] = 0;
1417 ERR(
"scheduled chore list is not empty\n");
1419 struct scheduled_chore,
entry)
1426 TRACE(
"(%p)\n",
this);
1433 TRACE(
"(%p)\n",
this);
1434 return this->virt_proc_no;
1438SchedulerPolicy*
__thiscall ThreadScheduler_GetPolicy(
1439 const ThreadScheduler *this, SchedulerPolicy *
ret)
1442 return SchedulerPolicy_copy_ctor(
ret, &this->policy);
1448 TRACE(
"(%p)\n",
this);
1457 TRACE(
"(%p)\n",
this);
1460 ThreadScheduler_dtor(
this);
1476 size = this->shutdown_size ? this->shutdown_size * 2 : 1;
1478 memcpy(shutdown_events, this->shutdown_events,
1479 this->shutdown_count *
sizeof(*shutdown_events));
1481 this->shutdown_size =
size;
1482 this->shutdown_events = shutdown_events;
1483 this->shutdown_events[this->shutdown_count++] =
event;
1491 ExternalContextBase *
context = (ExternalContextBase*)get_current_context();
1493 TRACE(
"(%p)\n",
this);
1495 if(
context->context.vtable != &ExternalContextBase_vtable) {
1496 ERR(
"unknown context set\n");
1500 if(
context->scheduler.scheduler == &this->scheduler) {
1501 improper_scheduler_attach
e;
1502 improper_scheduler_attach_ctor_str(&
e,
NULL);
1506 if(
context->scheduler.scheduler) {
1511 context->scheduler.scheduler = &this->scheduler;
1512 ThreadScheduler_Reference(
this);
1517 ThreadScheduler *this,
void *placement)
1519 FIXME(
"(%p %p) stub\n",
this, placement);
1524void*
__thiscall ThreadScheduler_CreateScheduleGroup(ThreadScheduler *this)
1526 FIXME(
"(%p) stub\n",
this);
1534 ThreadScheduler *scheduler;
1537void __cdecl CurrentScheduler_Detach(
void);
1541 schedule_task_arg
arg;
1547 if(&
arg.scheduler->scheduler != get_current_scheduler()) {
1548 ThreadScheduler_Attach(
arg.scheduler);
1551 ThreadScheduler_Release(
arg.scheduler);
1556 CurrentScheduler_Detach();
1560void __thiscall ThreadScheduler_ScheduleTask_loc(ThreadScheduler *this,
1563 static unsigned int once;
1564 schedule_task_arg *
arg;
1568 FIXME(
"(%p %p %p %p) semi-stub\n",
this,
proc,
data, placement);
1570 TRACE(
"(%p %p %p %p) semi-stub\n",
this,
proc,
data, placement);
1575 arg->scheduler =
this;
1576 ThreadScheduler_Reference(
this);
1580 scheduler_resource_allocation_error
e;
1582 ThreadScheduler_Release(
this);
1584 scheduler_resource_allocation_error_ctor_name(&
e,
NULL,
1593void __thiscall ThreadScheduler_ScheduleTask(ThreadScheduler *this,
1597 ThreadScheduler_ScheduleTask_loc(
this,
proc,
data,
NULL);
1602 const ThreadScheduler *this,
const void *placement)
1604 FIXME(
"(%p %p) stub\n",
this, placement);
1609Scheduler*
__thiscall ThreadScheduler_vector_dtor(ThreadScheduler *this,
unsigned int flags)
1617 ThreadScheduler_dtor(
this+
i);
1620 ThreadScheduler_dtor(
this);
1625 return &this->scheduler;
1628static ThreadScheduler* ThreadScheduler_ctor(ThreadScheduler *
this,
1629 const SchedulerPolicy *
policy)
1633 TRACE(
"(%p)->()\n",
this);
1635 this->scheduler.vtable = &ThreadScheduler_vtable;
1638 SchedulerPolicy_copy_ctor(&this->policy,
policy);
1641 this->virt_proc_no = SchedulerPolicy_GetPolicyValue(&this->policy, MaxConcurrency);
1645 this->shutdown_count = this->shutdown_size = 0;
1646 this->shutdown_events =
NULL;
1649 this->
cs.DebugInfo->Spare[0] = (
DWORD_PTR)(__FILE__
": ThreadScheduler");
1657Scheduler*
__cdecl Scheduler_Create(
const SchedulerPolicy *
policy)
1659 ThreadScheduler *
ret;
1664 return &ThreadScheduler_ctor(
ret,
policy)->scheduler;
1668void __cdecl Scheduler_ResetDefaultSchedulerPolicy(
void)
1673 if(default_scheduler_policy.policy_container)
1674 SchedulerPolicy_dtor(&default_scheduler_policy);
1675 SchedulerPolicy_ctor(&default_scheduler_policy);
1681void __cdecl Scheduler_SetDefaultSchedulerPolicy(
const SchedulerPolicy *
policy)
1686 if(!default_scheduler_policy.policy_container)
1687 SchedulerPolicy_copy_ctor(&default_scheduler_policy,
policy);
1689 SchedulerPolicy_op_assign(&default_scheduler_policy,
policy);
1695void __cdecl CurrentScheduler_Create(
const SchedulerPolicy *
policy)
1697 Scheduler *scheduler;
1701 scheduler = Scheduler_Create(
policy);
1702 call_Scheduler_Attach(scheduler);
1706void __cdecl CurrentScheduler_Detach(
void)
1708 ExternalContextBase *
context = (ExternalContextBase*)try_get_current_context();
1713 improper_scheduler_detach
e;
1714 improper_scheduler_detach_ctor_str(&
e,
NULL);
1718 if(
context->context.vtable != &ExternalContextBase_vtable) {
1719 ERR(
"unknown context set\n");
1723 if(!
context->scheduler.next) {
1724 improper_scheduler_detach
e;
1725 improper_scheduler_detach_ctor_str(&
e,
NULL);
1729 call_Scheduler_Release(
context->scheduler.scheduler);
1730 if(!
context->scheduler.next) {
1733 struct scheduler_list *
entry =
context->scheduler.next;
1740static void create_default_scheduler(
void)
1742 if(default_scheduler)
1746 if(!default_scheduler) {
1747 ThreadScheduler *scheduler;
1749 if(!default_scheduler_policy.policy_container)
1750 SchedulerPolicy_ctor(&default_scheduler_policy);
1753 ThreadScheduler_ctor(scheduler, &default_scheduler_policy);
1754 default_scheduler = scheduler;
1761Scheduler*
__cdecl CurrentScheduler_Get(
void)
1764 return get_current_scheduler();
1770void*
__cdecl CurrentScheduler_CreateScheduleGroup_loc(
void *placement)
1772 TRACE(
"(%p)\n", placement);
1773 return call_Scheduler_CreateScheduleGroup_loc(get_current_scheduler(), placement);
1779void*
__cdecl CurrentScheduler_CreateScheduleGroup(
void)
1782 return call_Scheduler_CreateScheduleGroup(get_current_scheduler());
1786unsigned int __cdecl CurrentScheduler_GetNumberOfVirtualProcessors(
void)
1788 Scheduler *scheduler = try_get_current_scheduler();
1794 return call_Scheduler_GetNumberOfVirtualProcessors(scheduler);
1798SchedulerPolicy*
__cdecl CurrentScheduler_GetPolicy(SchedulerPolicy *
policy)
1801 return call_Scheduler_GetPolicy(get_current_scheduler(),
policy);
1805unsigned int __cdecl CurrentScheduler_Id(
void)
1807 Scheduler *scheduler = try_get_current_scheduler();
1813 return call_Scheduler_Id(scheduler);
1819bool __cdecl CurrentScheduler_IsAvailableLocation(
const void *placement)
1821 Scheduler *scheduler = try_get_current_scheduler();
1823 TRACE(
"(%p)\n", placement);
1827 return call_Scheduler_IsAvailableLocation(scheduler, placement);
1836 call_Scheduler_RegisterShutdownEvent(get_current_scheduler(),
event);
1843 void *
data,
void *placement)
1846 call_Scheduler_ScheduleTask_loc(get_current_scheduler(),
proc,
data, placement);
1855 call_Scheduler_ScheduleTask(get_current_scheduler(),
proc,
data);
1861_Scheduler*
__thiscall _Scheduler_ctor_sched(_Scheduler *this, Scheduler *scheduler)
1863 TRACE(
"(%p %p)\n",
this, scheduler);
1865 this->scheduler = scheduler;
1872_Scheduler*
__thiscall _Scheduler_ctor(_Scheduler *this)
1874 return _Scheduler_ctor_sched(
this,
NULL);
1880Scheduler*
__thiscall _Scheduler__GetScheduler(_Scheduler *this)
1882 TRACE(
"(%p)\n",
this);
1883 return this->scheduler;
1891 TRACE(
"(%p)\n",
this);
1892 return call_Scheduler_Reference(this->scheduler);
1900 TRACE(
"(%p)\n",
this);
1901 return call_Scheduler_Release(this->scheduler);
1905_Scheduler*
__cdecl _CurrentScheduler__Get(_Scheduler *
ret)
1908 return _Scheduler_ctor_sched(
ret, get_current_scheduler());
1912unsigned int __cdecl _CurrentScheduler__GetNumberOfVirtualProcessors(
void)
1915 get_current_scheduler();
1916 return CurrentScheduler_GetNumberOfVirtualProcessors();
1920unsigned int __cdecl _CurrentScheduler__Id(
void)
1923 get_current_scheduler();
1924 return CurrentScheduler_Id();
1932 CurrentScheduler_ScheduleTask(
proc,
data);
1936unsigned int __cdecl SpinCount__Value(
void)
1938 static unsigned int val = -1;
1955SpinWait*
__thiscall SpinWait_ctor_yield(SpinWait *this, yield_func yf)
1957 TRACE(
"(%p %p)\n",
this, yf);
1959 this->
state = SPINWAIT_INIT;
1961 this->yield_func = yf;
1968SpinWait*
__thiscall SpinWait_ctor(SpinWait *this, yield_func yf)
1970 TRACE(
"(%p %p)\n",
this, yf);
1972 this->
state = SPINWAIT_INIT;
1974 this->yield_func = yf;
1985 TRACE(
"(%p)\n",
this);
1995 TRACE(
"(%p)\n",
this);
2008 TRACE(
"(%p)\n",
this);
2017void __thiscall SpinWait__SetSpinCount(SpinWait *this,
unsigned int spin)
2019 TRACE(
"(%p %d)\n",
this, spin);
2022 this->
state = spin ? SPINWAIT_SPIN : SPINWAIT_YIELD;
2032 SpinWait__SetSpinCount(
this, SpinCount__Value());
2042 TRACE(
"(%p)\n",
this);
2045 return this->spin > 0;
2055 switch(this->
state) {
2057 SpinWait__Reset(
this);
2062 this->
state = this->
unknown ? SPINWAIT_YIELD : SPINWAIT_DONE;
2064 case SPINWAIT_YIELD:
2065 this->
state = SPINWAIT_DONE;
2069 SpinWait__Reset(
this);
2074#if _MSVCR_VER >= 110
2079_StructuredTaskCollection*
__thiscall _StructuredTaskCollection_ctor(
2080 _StructuredTaskCollection *this,
void *
token)
2082 TRACE(
"(%p)\n",
this);
2085 FIXME(
"_StructuredTaskCollection with cancellation token not implemented!\n");
2087 memset(
this, 0,
sizeof(*
this));
2088 this->finished = FINISHED_INITIAL;
2094#if _MSVCR_VER >= 120
2100void __thiscall _StructuredTaskCollection_dtor(_StructuredTaskCollection *this)
2102 TRACE(
"(%p)\n",
this);
2106 missing_wait_ctor_str(&
e,
"Missing call to _RunAndWait");
2113static ThreadScheduler *get_thread_scheduler_from_context(
Context *
context)
2115 Scheduler *scheduler = get_scheduler_from_context(
context);
2116 if (scheduler && scheduler->vtable == &ThreadScheduler_vtable)
2117 return (ThreadScheduler*)scheduler;
2121struct execute_chore_data {
2122 _UnrealizedChore *chore;
2123 _StructuredTaskCollection *task_collection;
2131 _StructuredTaskCollection *this)
2133 ThreadScheduler *scheduler;
2134 void *prev_exception, *new_exception;
2135 struct scheduled_chore *sc, *
next;
2136 LONG removed = 0, finished = 1;
2137 struct beacon *beacon;
2139 TRACE(
"(%p)\n",
this);
2142 this->context = get_current_context();
2143 scheduler = get_thread_scheduler_from_context(this->context);
2149 prev_exception = new_exception;
2150 if ((
ULONG_PTR)prev_exception & STRUCTURED_TASK_COLLECTION_CANCELLED)
2152 new_exception = (
void*)((
ULONG_PTR)prev_exception |
2153 STRUCTURED_TASK_COLLECTION_CANCELLED);
2155 &this->
exception, new_exception, prev_exception))
2160 if (beacon->task_collection ==
this)
2167 struct scheduled_chore,
entry) {
2168 if (sc->chore->task_collection !=
this)
2170 sc->chore->task_collection =
NULL;
2182 call_Context_Unblock(this->event);
2187 struct execute_chore_data *
data = _data;
2188 void *prev_exception, *new_exception;
2194 _StructuredTaskCollection__Cancel(
data->task_collection);
2200 new_exception =
data->task_collection->exception;
2202 if ((
ULONG_PTR)new_exception & ~STRUCTURED_TASK_COLLECTION_STATUS_MASK) {
2207 prev_exception = new_exception;
2210 &
data->task_collection->exception, new_exception,
2211 prev_exception)) != prev_exception);
2212 data->task_collection->event = 0;
2218 ExternalContextBase *
ctx = (ExternalContextBase*)try_get_current_context();
2219 _StructuredTaskCollection *old_collection =
data;
2221 if (
ctx &&
ctx->context.vtable == &ExternalContextBase_vtable)
2222 ctx->task_collection = old_collection;
2225static void execute_chore(_UnrealizedChore *chore,
2226 _StructuredTaskCollection *task_collection)
2228 ExternalContextBase *
ctx = (ExternalContextBase*)try_get_current_context();
2229 struct execute_chore_data
data = { chore, task_collection };
2230 _StructuredTaskCollection *old_collection;
2232 TRACE(
"(%p %p)\n", chore, task_collection);
2234 if (
ctx &&
ctx->context.vtable == &ExternalContextBase_vtable)
2236 old_collection =
ctx->task_collection;
2237 ctx->task_collection = task_collection;
2244 if (!((
ULONG_PTR)task_collection->exception & ~STRUCTURED_TASK_COLLECTION_STATUS_MASK) &&
2246 chore->chore_proc(chore);
2258 _UnrealizedChore *chore =
data;
2259 struct _StructuredTaskCollection *task_collection = chore->task_collection;
2264 if (!task_collection)
2266 chore->task_collection =
NULL;
2271 call_Context_Unblock(task_collection->event);
2274static void __cdecl chore_wrapper(_UnrealizedChore *chore)
2278 execute_chore(chore, chore->task_collection);
2283static BOOL pick_and_execute_chore(ThreadScheduler *scheduler)
2286 struct scheduled_chore *sc;
2287 _UnrealizedChore *chore;
2289 TRACE(
"(%p)\n", scheduler);
2291 if (scheduler->scheduler.vtable != &ThreadScheduler_vtable)
2293 ERR(
"unknown scheduler set\n");
2309 chore->chore_wrapper(chore);
2313static void __cdecl _StructuredTaskCollection_scheduler_cb(
void *
data)
2315 pick_and_execute_chore((ThreadScheduler*)get_current_scheduler());
2318static bool schedule_chore(_StructuredTaskCollection *
this,
2319 _UnrealizedChore *chore, Scheduler **pscheduler)
2321 struct scheduled_chore *sc;
2322 ThreadScheduler *scheduler;
2324 if (chore->task_collection) {
2325 invalid_multiple_scheduling
e;
2326 invalid_multiple_scheduling_ctor_str(&
e,
"Chore scheduled multiple times");
2332 this->context = get_current_context();
2333 scheduler = get_thread_scheduler_from_context(this->context);
2335 ERR(
"unknown context or scheduler set\n");
2342 chore->task_collection =
this;
2343 chore->chore_wrapper = chore_wrapper;
2349 *pscheduler = &scheduler->scheduler;
2353#if _MSVCR_VER >= 110
2360 _StructuredTaskCollection *this, _UnrealizedChore *chore,
2363 Scheduler *scheduler;
2365 TRACE(
"(%p %p %p)\n",
this, chore, placement);
2367 if (schedule_chore(
this, chore, &scheduler))
2369 call_Scheduler_ScheduleTask_loc(scheduler,
2370 _StructuredTaskCollection_scheduler_cb,
NULL, placement);
2381 _StructuredTaskCollection *this, _UnrealizedChore *chore)
2383 Scheduler *scheduler;
2385 TRACE(
"(%p %p)\n",
this, chore);
2387 if (schedule_chore(
this, chore, &scheduler))
2389 call_Scheduler_ScheduleTask(scheduler,
2390 _StructuredTaskCollection_scheduler_cb,
NULL);
2407_TaskCollectionStatus
__stdcall _StructuredTaskCollection__RunAndWait(
2408 _StructuredTaskCollection *
this, _UnrealizedChore *chore)
2414 TRACE(
"(%p %p)\n",
this, chore);
2417 if (chore->task_collection) {
2418 invalid_multiple_scheduling
e;
2419 invalid_multiple_scheduling_ctor_str(&
e,
"Chore scheduled multiple times");
2422 execute_chore(chore,
this);
2425 if (this->context) {
2426 ThreadScheduler *scheduler = get_thread_scheduler_from_context(this->context);
2428 while (pick_and_execute_chore(scheduler)) ;
2432 this->
event = get_current_context();
2435 while (this->count != 0) {
2441 call_Context_Block(this->event);
2447 this->exception = 0;
2454 if (
exception & STRUCTURED_TASK_COLLECTION_CANCELLED)
2455 return TASK_COLLECTION_CANCELLED;
2456 return TASK_COLLECTION_SUCCESS;
2464 _StructuredTaskCollection *this)
2466 TRACE(
"(%p)\n",
this);
2467 return !!((
ULONG_PTR)this->exception & STRUCTURED_TASK_COLLECTION_CANCELLED);
2473void __thiscall _UnrealizedChore__CheckTaskCollection(_UnrealizedChore *this)
2483 TRACE(
"(%p)\n",
this);
2485 this->unk_active.ctx =
NULL;
2495 TRACE(
"(%p)\n",
this);
2498static void __cdecl spin_wait_yield(
void)
2503static inline void spin_wait_for_next_cs(cs_queue *
q)
2509 SpinWait_ctor(&sw, &spin_wait_yield);
2510 SpinWait__Reset(&sw);
2512 SpinWait__SpinOnce(&sw);
2518 cs->unk_active.ctx = get_current_context();
2519 cs->unk_active.
next =
q->next;
2520 cs->head = &
cs->unk_active;
2527 if(
cs->unk_active.ctx == get_current_context()) {
2529 improper_lock_ctor_str(&
e,
"Already locked");
2534 q->ctx = get_current_context();
2538 call_Context_Block(
q->ctx);
2543 spin_wait_for_next_cs(
q);
2544 cs->unk_active.
next =
q->next;
2555 TRACE(
"(%p)\n",
this);
2566 TRACE(
"(%p)\n",
this);
2568 if(this->unk_active.ctx == get_current_context())
2573 cs_set_head(
this, &
q);
2575 spin_wait_for_next_cs(&
q);
2576 this->unk_active.next =
q.next;
2588 TRACE(
"(%p)\n",
this);
2590 this->unk_active.ctx =
NULL;
2593 == &this->unk_active)
return;
2594 spin_wait_for_next_cs(&this->unk_active);
2596#if _MSVCR_VER >= 110
2603 next = this->unk_active.next;
2608 spin_wait_for_next_cs(
next);
2610 this->unk_active.next =
next->next;
2615 call_Context_Unblock(this->unk_active.next->ctx);
2623 TRACE(
"(%p)\n",
this);
2638struct timeout_unlock
2646 struct timeout_unlock *tu =
ctx;
2647 tu->timed_out =
TRUE;
2648 call_Context_Unblock(tu->ctx);
2654 struct timeout_unlock tu = {
ctx };
2659 call_Context_Block(
ctx);
2665 FIXME(
"throw exception?\n");
2671 call_Context_Block(
ctx);
2676 return tu.timed_out;
2679#if _MSVCR_VER >= 110
2691 if(this->unk_active.ctx ==
ctx) {
2693 improper_lock_ctor_str(&
e,
"Already locked");
2698 return critical_section_try_lock(
this);
2705 if(block_context_for(
q->ctx,
timeout))
2710 call_Context_Block(
ctx);
2714 cs_set_head(
this,
q);
2716 spin_wait_for_next_cs(
q);
2717 this->unk_active.next =
q->next;
2728critical_section_scoped_lock*
__thiscall critical_section_scoped_lock_ctor(
2740void __thiscall critical_section_scoped_lock_dtor(critical_section_scoped_lock *this)
2742 TRACE(
"(%p)\n",
this);
2743 critical_section_unlock(this->cs);
2749_NonReentrantPPLLock*
__thiscall _NonReentrantPPLLock_ctor(_NonReentrantPPLLock *this)
2751 TRACE(
"(%p)\n",
this);
2753 critical_section_ctor(&this->cs);
2760void __thiscall _NonReentrantPPLLock__Acquire(_NonReentrantPPLLock *this, cs_queue *
q)
2762 TRACE(
"(%p %p)\n",
this,
q);
2769void __thiscall _NonReentrantPPLLock__Release(_NonReentrantPPLLock *this)
2771 TRACE(
"(%p)\n",
this);
2772 critical_section_unlock(&this->cs);
2778_NonReentrantPPLLock__Scoped_lock*
__thiscall _NonReentrantPPLLock__Scoped_lock_ctor(
2779 _NonReentrantPPLLock__Scoped_lock *this, _NonReentrantPPLLock *
lock)
2784 _NonReentrantPPLLock__Acquire(this->lock, &this->wait.q);
2791void __thiscall _NonReentrantPPLLock__Scoped_lock_dtor(_NonReentrantPPLLock__Scoped_lock *this)
2793 TRACE(
"(%p)\n",
this);
2795 _NonReentrantPPLLock__Release(this->
lock);
2801_ReentrantPPLLock*
__thiscall _ReentrantPPLLock_ctor(_ReentrantPPLLock *this)
2803 TRACE(
"(%p)\n",
this);
2805 critical_section_ctor(&this->cs);
2814void __thiscall _ReentrantPPLLock__Acquire(_ReentrantPPLLock *this, cs_queue *
q)
2816 TRACE(
"(%p %p)\n",
this,
q);
2831void __thiscall _ReentrantPPLLock__Release(_ReentrantPPLLock *this)
2833 TRACE(
"(%p)\n",
this);
2840 critical_section_unlock(&this->cs);
2846_ReentrantPPLLock__Scoped_lock*
__thiscall _ReentrantPPLLock__Scoped_lock_ctor(
2847 _ReentrantPPLLock__Scoped_lock *this, _ReentrantPPLLock *
lock)
2852 _ReentrantPPLLock__Acquire(this->lock, &this->wait.q);
2859void __thiscall _ReentrantPPLLock__Scoped_lock_dtor(_ReentrantPPLLock__Scoped_lock *this)
2861 TRACE(
"(%p)\n",
this);
2863 _ReentrantPPLLock__Release(this->
lock);
2867unsigned int __cdecl _GetConcurrency(
void)
2869 static unsigned int val = -1;
2883static void evt_add_queue(thread_wait_entry **
head, thread_wait_entry *
entry)
2891static void evt_remove_queue(thread_wait_entry **
head, thread_wait_entry *
entry)
2895 else if(
entry->prev)
2907 evt_remove_queue(&
events[
i]->waiters, &wait->entries[
i]);
2908 critical_section_unlock(&
events[
i]->
cs);
2914static inline int evt_transition(
void **
state,
void *
from,
void *to)
2923 wait->signaled = EVT_RUNNING;
2924 wait->pending_waits = wait_all ?
count : 1;
2926 wait->entries[
i].wait = wait;
2929 evt_add_queue(&
events[
i]->waiters, &wait->entries[
i]);
2933 critical_section_unlock(&
events[
i]->
cs);
2935 return evt_end_wait(wait,
events,
i+1);
2938 critical_section_unlock(&
events[
i]->
cs);
2944 if(!evt_transition(&wait->signaled, EVT_RUNNING, EVT_WAITING))
2947 if(block_context_for(wait->ctx,
timeout) &&
2948 !evt_transition(&wait->signaled, EVT_WAITING, EVT_RUNNING))
2949 call_Context_Block(wait->ctx);
2959 TRACE(
"(%p)\n",
this);
2961 this->waiters =
NULL;
2962 this->signaled =
FALSE;
2963 critical_section_ctor(&this->cs);
2973 TRACE(
"(%p)\n",
this);
2974 critical_section_dtor(&this->cs);
2976 ERR(
"there's a wait on destroyed event\n");
2984 thread_wait_entry *
entry;
2986 TRACE(
"(%p)\n",
this);
2988 critical_section_lock(&this->cs);
2989 if(this->signaled) {
2990 this->signaled =
FALSE;
2994 critical_section_unlock(&this->cs);
3002 thread_wait_entry *wakeup =
NULL;
3005 TRACE(
"(%p)\n",
this);
3007 critical_section_lock(&this->cs);
3008 if(!this->signaled) {
3009 this->signaled =
TRUE;
3014 evt_remove_queue(&this->waiters,
entry);
3015 evt_add_queue(&wakeup,
entry);
3020 critical_section_unlock(&this->cs);
3025 call_Context_Unblock(
entry->wait->ctx);
3039 critical_section_lock(&this->cs);
3040 signaled = this->signaled;
3041 critical_section_unlock(&this->cs);
3044 wait.ctx = get_current_context();
3045 return signaled ? 0 : evt_wait(&wait, &
this, 1,
FALSE,
timeout);
3061 wait->ctx = get_current_context();
3068#if _MSVCR_VER >= 110
3073_Cancellation_beacon*
__thiscall _Cancellation_beacon_ctor(_Cancellation_beacon *this)
3075 ExternalContextBase *
ctx = (ExternalContextBase*)get_current_context();
3076 _StructuredTaskCollection *task_collection =
NULL;
3077 struct beacon *beacon;
3079 TRACE(
"(%p)\n",
this);
3081 if (
ctx->context.vtable == &ExternalContextBase_vtable) {
3082 task_collection =
ctx->task_collection;
3083 if (task_collection)
3084 ctx = (ExternalContextBase*)task_collection->context;
3087 if (
ctx->context.vtable != &ExternalContextBase_vtable) {
3088 ERR(
"unknown context\n");
3092 beacon =
malloc(
sizeof(*beacon));
3093 beacon->cancelling = Context_IsCurrentTaskCollectionCanceling();
3094 beacon->task_collection = task_collection;
3096 if (task_collection) {
3102 this->beacon = beacon;
3109void __thiscall _Cancellation_beacon_dtor(_Cancellation_beacon *this)
3111 TRACE(
"(%p)\n",
this);
3113 if (this->beacon->task_collection) {
3114 ExternalContextBase *
ctx = (ExternalContextBase*)this->beacon->task_collection->context;
3128bool __thiscall _Cancellation_beacon__Confirm_cancel(_Cancellation_beacon *this)
3132 TRACE(
"(%p)\n",
this);
3134 ret = Context_IsCurrentTaskCollectionCanceling();
3143_Condition_variable*
__thiscall _Condition_variable_ctor(_Condition_variable *this)
3145 TRACE(
"(%p)\n",
this);
3148 critical_section_ctor(&this->
lock);
3155void __thiscall _Condition_variable_dtor(_Condition_variable *this)
3157 TRACE(
"(%p)\n",
this);
3159 while(this->
queue) {
3161 if(!this->
queue->expired)
3162 ERR(
"there's an active wait\n");
3166 critical_section_dtor(&this->
lock);
3176 TRACE(
"(%p, %p)\n",
this,
cs);
3178 q.ctx = get_current_context();
3180 critical_section_lock(&this->
lock);
3181 q.next = this->
queue;
3183 critical_section_unlock(&this->
lock);
3185 critical_section_unlock(
cs);
3186 call_Context_Block(
q.ctx);
3187 critical_section_lock(
cs);
3193bool __thiscall _Condition_variable_wait_for(_Condition_variable *this,
3201 q->ctx = get_current_context();
3203 critical_section_lock(&this->
lock);
3204 q->next = this->
queue;
3206 critical_section_unlock(&this->
lock);
3208 critical_section_unlock(
cs);
3210 if(block_context_for(
q->ctx,
timeout)) {
3212 critical_section_lock(
cs);
3215 call_Context_Block(
q->ctx);
3219 critical_section_lock(
cs);
3226void __thiscall _Condition_variable_notify_one(_Condition_variable *this)
3230 TRACE(
"(%p)\n",
this);
3236 critical_section_lock(&this->
lock);
3239 critical_section_unlock(&this->
lock);
3243 critical_section_unlock(&this->
lock);
3245 node->next = CV_WAKE;
3247 call_Context_Unblock(
node->ctx);
3258void __thiscall _Condition_variable_notify_all(_Condition_variable *this)
3262 TRACE(
"(%p)\n",
this);
3267 critical_section_lock(&this->
lock);
3270 critical_section_unlock(&this->
lock);
3275 ptr->next = CV_WAKE;
3277 call_Context_Unblock(
ptr->ctx);
3288reader_writer_lock*
__thiscall reader_writer_lock_ctor(reader_writer_lock *this)
3290 TRACE(
"(%p)\n",
this);
3292 memset(
this, 0,
sizeof(*
this));
3301 TRACE(
"(%p)\n",
this);
3303 if (this->
thread_id != 0 || this->count)
3304 WARN(
"destroying locked reader_writer_lock\n");
3307static inline void spin_wait_for_next_rwl(rwl_queue *
q)
3313 SpinWait_ctor(&sw, &spin_wait_yield);
3314 SpinWait__Reset(&sw);
3316 SpinWait__SpinOnce(&sw);
3325 rwl_queue
q = {
NULL, get_current_context() }, *
last;
3327 TRACE(
"(%p)\n",
this);
3331 improper_lock_ctor_str(&
e,
"Already locked");
3338 call_Context_Block(
q.ctx);
3340 this->writer_head = &
q;
3342 call_Context_Block(
q.ctx);
3346 this->writer_head = &this->active;
3347 this->active.next =
NULL;
3349 spin_wait_for_next_rwl(&
q);
3350 this->active.next =
q.next;
3357void __thiscall reader_writer_lock_lock_read(reader_writer_lock *this)
3359 rwl_queue
q = {
NULL, get_current_context() };
3361 TRACE(
"(%p)\n",
this);
3365 improper_lock_ctor_str(&
e,
"Already locked as writer");
3370 q.next = this->reader_head;
3377 while (!((
count = this->count) & WRITER_WAITING))
3380 if (
count & WRITER_WAITING)
3381 call_Context_Block(
q.ctx);
3387 call_Context_Unblock(
head->ctx);
3391 call_Context_Block(
q.ctx);
3398bool __thiscall reader_writer_lock_try_lock(reader_writer_lock *this)
3400 rwl_queue
q = {
NULL };
3402 TRACE(
"(%p)\n",
this);
3409 this->writer_head = &
q;
3412 this->writer_head = &this->active;
3413 this->active.next =
NULL;
3415 spin_wait_for_next_rwl(&
q);
3416 this->active.next =
q.next;
3423 spin_wait_for_next_rwl(&
q);
3424 this->writer_head =
q.next;
3427 this->writer_head = &this->active;
3428 this->active.next =
q.next;
3437bool __thiscall reader_writer_lock_try_lock_read(reader_writer_lock *this)
3441 TRACE(
"(%p)\n",
this);
3443 while (!((
count = this->count) & WRITER_WAITING))
3451void __thiscall reader_writer_lock_unlock(reader_writer_lock *this)
3456 TRACE(
"(%p)\n",
this);
3458 if ((
count = this->count) & ~WRITER_WAITING) {
3460 if (
count != WRITER_WAITING)
3462 call_Context_Unblock(this->writer_head->ctx);
3467 next = this->writer_head->next;
3469 call_Context_Unblock(
next->ctx);
3477 call_Context_Unblock(
head->ctx);
3489reader_writer_lock_scoped_lock*
__thiscall reader_writer_lock_scoped_lock_ctor(
3490 reader_writer_lock_scoped_lock *this, reader_writer_lock *
lock)
3495 reader_writer_lock_lock(
lock);
3502void __thiscall reader_writer_lock_scoped_lock_dtor(reader_writer_lock_scoped_lock *this)
3504 TRACE(
"(%p)\n",
this);
3505 reader_writer_lock_unlock(this->
lock);
3511reader_writer_lock_scoped_lock*
__thiscall reader_writer_lock_scoped_lock_read_ctor(
3512 reader_writer_lock_scoped_lock *this, reader_writer_lock *
lock)
3517 reader_writer_lock_lock_read(
lock);
3524void __thiscall reader_writer_lock_scoped_lock_read_dtor(reader_writer_lock_scoped_lock *this)
3526 TRACE(
"(%p)\n",
this);
3527 reader_writer_lock_unlock(this->
lock);
3533_ReentrantBlockingLock*
__thiscall _ReentrantBlockingLock_ctor(_ReentrantBlockingLock *this)
3535 TRACE(
"(%p)\n",
this);
3538 this->cs.DebugInfo->Spare[0] = (
DWORD_PTR)(__FILE__
": _ReentrantBlockingLock");
3545void __thiscall _ReentrantBlockingLock_dtor(_ReentrantBlockingLock *this)
3547 TRACE(
"(%p)\n",
this);
3549 this->cs.DebugInfo->Spare[0] = 0;
3556void __thiscall _ReentrantBlockingLock__Acquire(_ReentrantBlockingLock *this)
3558 TRACE(
"(%p)\n",
this);
3565void __thiscall _ReentrantBlockingLock__Release(_ReentrantBlockingLock *this)
3567 TRACE(
"(%p)\n",
this);
3574bool __thiscall _ReentrantBlockingLock__TryAcquire(_ReentrantBlockingLock *this)
3576 TRACE(
"(%p)\n",
this);
3584_ReaderWriterLock*
__thiscall _ReaderWriterLock_ctor(_ReaderWriterLock *this)
3586 TRACE(
"(%p)\n",
this);
3597 block_context_for(get_current_context(),
time);
3618_Timer*
__thiscall _Timer_ctor(_Timer *this,
unsigned int elapse,
bool repeat)
3622 this->
vtable = &_Timer_vtable;
3624 this->elapse = elapse;
3632 TRACE(
"calling _Timer(%p) callback\n",
this);
3633 call__Timer_callback(
this);
3644 TRACE(
"(%p)\n",
this);
3649 FIXME(
"throw exception?\n");
3664 TRACE(
"(%p)\n",
this);
3677 TRACE(
"(%p)\n",
this);
3684_Timer*
__thiscall _Timer_vector_dtor(_Timer *this,
unsigned int flags)
3691 for (
i=*
ptr-1;
i>=0;
i--)
3692 _Timer_dtor(
this+
i);
3703#ifdef __ASM_USE_THISCALL_WRAPPER
3705#define DEFINE_VTBL_WRAPPER(off) \
3706 __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \
3710 "movl 0(%ecx), %eax\n\t" \
3711 "jmp *" #off "(%eax)\n\t")
3713DEFINE_VTBL_WRAPPER(0);
3714DEFINE_VTBL_WRAPPER(4);
3715DEFINE_VTBL_WRAPPER(8);
3716DEFINE_VTBL_WRAPPER(12);
3717DEFINE_VTBL_WRAPPER(16);
3718DEFINE_VTBL_WRAPPER(20);
3719DEFINE_VTBL_WRAPPER(24);
3720DEFINE_VTBL_WRAPPER(28);
3721DEFINE_VTBL_WRAPPER(32);
3722DEFINE_VTBL_WRAPPER(36);
3723DEFINE_VTBL_WRAPPER(40);
3724DEFINE_VTBL_WRAPPER(44);
3725DEFINE_VTBL_WRAPPER(48);
3731DEFINE_RTTI_DATA2(ExternalContextBase, 0, &ContextBase_rtti_base_descriptor,
3732 &Context_rtti_base_descriptor, ".?AVExternalContextBase@
details@Concurrency@
@")
3733DEFINE_RTTI_DATA0(Scheduler, 0, ".?AVScheduler@Concurrency@
@")
3734DEFINE_RTTI_DATA1(SchedulerBase, 0, &Scheduler_rtti_base_descriptor, ".?AVSchedulerBase@
details@Concurrency@
@")
3735DEFINE_RTTI_DATA2(ThreadScheduler, 0, &SchedulerBase_rtti_base_descriptor,
3736 &Scheduler_rtti_base_descriptor, ".?AVThreadScheduler@
details@Concurrency@
@")
3737DEFINE_RTTI_DATA0(_Timer, 0, ".?AV_Timer@
details@Concurrency@
@");
3739__ASM_BLOCK_BEGIN(concurrency_vtables)
3740 __ASM_VTABLE(ExternalContextBase,
3741 VTABLE_ADD_FUNC(ExternalContextBase_GetId)
3742 VTABLE_ADD_FUNC(ExternalContextBase_GetVirtualProcessorId)
3743 VTABLE_ADD_FUNC(ExternalContextBase_GetScheduleGroupId)
3744 VTABLE_ADD_FUNC(ExternalContextBase_Unblock)
3745 VTABLE_ADD_FUNC(ExternalContextBase_IsSynchronouslyBlocked)
3746 VTABLE_ADD_FUNC(ExternalContextBase_vector_dtor)
3747 VTABLE_ADD_FUNC(ExternalContextBase_Block)
3748 VTABLE_ADD_FUNC(ExternalContextBase_Yield)
3749 VTABLE_ADD_FUNC(ExternalContextBase_SpinYield)
3750 VTABLE_ADD_FUNC(ExternalContextBase_Oversubscribe)
3751 VTABLE_ADD_FUNC(ExternalContextBase_Alloc)
3752 VTABLE_ADD_FUNC(ExternalContextBase_Free)
3753 VTABLE_ADD_FUNC(ExternalContextBase_EnterCriticalRegionHelper)
3754 VTABLE_ADD_FUNC(ExternalContextBase_EnterHyperCriticalRegionHelper)
3755 VTABLE_ADD_FUNC(ExternalContextBase_ExitCriticalRegionHelper)
3756 VTABLE_ADD_FUNC(ExternalContextBase_ExitHyperCriticalRegionHelper)
3757 VTABLE_ADD_FUNC(ExternalContextBase_GetCriticalRegionType)
3758 VTABLE_ADD_FUNC(ExternalContextBase_GetContextKind));
3759 __ASM_VTABLE(ThreadScheduler,
3760 VTABLE_ADD_FUNC(ThreadScheduler_vector_dtor)
3761 VTABLE_ADD_FUNC(ThreadScheduler_Id)
3762 VTABLE_ADD_FUNC(ThreadScheduler_GetNumberOfVirtualProcessors)
3763 VTABLE_ADD_FUNC(ThreadScheduler_GetPolicy)
3764 VTABLE_ADD_FUNC(ThreadScheduler_Reference)
3765 VTABLE_ADD_FUNC(ThreadScheduler_Release)
3766 VTABLE_ADD_FUNC(ThreadScheduler_RegisterShutdownEvent)
3767 VTABLE_ADD_FUNC(ThreadScheduler_Attach)
3769 VTABLE_ADD_FUNC(ThreadScheduler_CreateScheduleGroup_loc)
3771 VTABLE_ADD_FUNC(ThreadScheduler_CreateScheduleGroup)
3773 VTABLE_ADD_FUNC(ThreadScheduler_ScheduleTask_loc)
3775 VTABLE_ADD_FUNC(ThreadScheduler_ScheduleTask)
3777 VTABLE_ADD_FUNC(ThreadScheduler_IsAvailableLocation)
3780 __ASM_VTABLE(_Timer,
3781 VTABLE_ADD_FUNC(_Timer_vector_dtor));
3784void msvcrt_init_concurrency(void *base)
3787 init_cexception_rtti(base);
3788 init_improper_lock_rtti(base);
3789 init_improper_scheduler_attach_rtti(base);
3790 init_improper_scheduler_detach_rtti(base);
3791 init_invalid_multiple_scheduling_rtti(base);
3792 init_invalid_scheduler_policy_key_rtti(base);
3793 init_invalid_scheduler_policy_thread_specification_rtti(base);
3794 init_invalid_scheduler_policy_value_rtti(base);
3795 init_missing_wait_rtti(base);
3796 init_scheduler_resource_allocation_error_rtti(base);
3797 init_Context_rtti(base);
3798 init_ContextBase_rtti(base);
3799 init_ExternalContextBase_rtti(base);
3800 init_Scheduler_rtti(base);
3801 init_SchedulerBase_rtti(base);
3802 init_ThreadScheduler_rtti(base);
3803 init__Timer_rtti(base);
3805 init_cexception_cxx_type_info(base);
3806 init_improper_lock_cxx(base);
3807 init_improper_scheduler_attach_cxx(base);
3808 init_improper_scheduler_detach_cxx(base);
3809 init_invalid_multiple_scheduling_cxx(base);
3810 init_invalid_scheduler_policy_key_cxx(base);
3811 init_invalid_scheduler_policy_thread_specification_cxx(base);
3812 init_invalid_scheduler_policy_value_cxx(base);
3813#if _MSVCR_VER >= 120
3814 init_missing_wait_cxx(base);
3816 init_scheduler_resource_allocation_error_cxx(base);
3820void msvcrt_free_concurrency(void)
3822 if (context_tls_index != TLS_OUT_OF_INDEXES)
3823 TlsFree(context_tls_index);
3824 if(default_scheduler_policy.policy_container)
3825 SchedulerPolicy_dtor(&default_scheduler_policy);
3826 if(default_scheduler) {
3827 ThreadScheduler_dtor(default_scheduler);
3828 operator_delete(default_scheduler);
3832void msvcrt_free_scheduler_thread(void)
3834 Context *context = try_get_current_context();
3835 if (!context) return;
3836 call_Context_dtor(context, 1);
3839#endif /* _MSVCR_VER >= 100 */
struct outqueuenode * tail
struct outqueuenode * head
WINBASEAPI _Check_return_ _Out_ AppPolicyProcessTerminationMethod * policy
#define InterlockedIncrement
#define InterlockedExchange
#define InterlockedDecrement
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
static void list_remove(struct list_entry *entry)
static int list_empty(struct list_entry *head)
static void list_add_head(struct list_entry *head, struct list_entry *entry)
static void list_init(struct list_entry *head)
static HINSTANCE instance
static WCHAR unknown[MAX_STRING_RESOURCE_LEN]
static const WCHAR empty[]
#define HeapFree(x, y, z)
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, IN DWORD dwSpinCount, IN DWORD flags)
PTP_TIMER WINAPI DECLSPEC_HOTPATCH CreateThreadpoolTimer(PTP_TIMER_CALLBACK callback, PVOID userdata, TP_CALLBACK_ENVIRON *environment)
PTP_WORK WINAPI DECLSPEC_HOTPATCH CreateThreadpoolWork(PTP_WORK_CALLBACK callback, PVOID userdata, TP_CALLBACK_ENVIRON *environment)
static UINT event_reset(msi_dialog *dialog, const WCHAR *argument)
void WINAPI _CxxThrowException(void *object, const cxx_exception_type *type)
void __cdecl __ExceptionPtrCreate(exception_ptr *)
void exception_ptr_from_record(exception_ptr *, EXCEPTION_RECORD *)
BOOL __cdecl __uncaught_exception(void)
void __cdecl __ExceptionPtrDestroy(exception_ptr *)
#define CREATE_EXCEPTION_OBJECT(exception_name)
void __cdecl __ExceptionPtrRethrow(const exception_ptr *)
#define DEFINE_CXX_TYPE_INFO(type)
#define DEFINE_RTTI_DATA1(name, off, cl1, mangled_name)
#define DEFINE_RTTI_DATA0(name, off, mangled_name)
void CDECL DECLSPEC_HOTPATCH operator_delete(void *mem)
void *CDECL DECLSPEC_HOTPATCH operator_new(size_t size)
#define INHERIT_THREAD_PRIORITY
#define COOPERATIVE_TIMEOUT_INFINITE
#define COOPERATIVE_WAIT_TIMEOUT
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
#define InterlockedExchangePointer(Target, Value)
GLint GLint GLsizei GLsizei GLsizei depth
GLuint GLuint GLsizei count
GLuint GLuint GLsizei GLenum type
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLdouble GLdouble GLdouble GLdouble q
GLenum const GLvoid * addr
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
#define EXCEPTION_EXECUTE_HANDLER
#define EXCEPTION_CONTINUE_SEARCH
NTSYSAPI NTSTATUS WINAPI RtlWaitOnAddress(const void *, const void *, SIZE_T, const LARGE_INTEGER *)
NTSYSAPI void WINAPI RtlWakeAddressSingle(const void *)
#define InterlockedCompareExchangePointer
#define InterlockedCompareExchange
#define memcpy(s1, s2, n)
CRITICAL_SECTION critical_section
static CRITICAL_SECTION cs_lock
static unsigned(__cdecl *hash_bstr)(bstr_t s)
#define DEFINE_THISCALL_WRAPPER(func, args)
static unsigned __int64 next
_Check_return_ _In_z_ wchar_t const _Inout_opt_ _Deref_prepost_opt_z_ wchar_t ** _Context
const char int int int static __inline const char * wine_dbgstr_a(const char *s)
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
PEXCEPTION_RECORD ExceptionRecord
LIST_ENTRY ProcessLocksList
DWORD dwNumberOfProcessors
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
WINBASEAPI VOID WINAPI WaitForThreadpoolTimerCallbacks(_Inout_ PTP_TIMER pti, _In_ BOOL fCancelPendingCallbacks)
WINBASEAPI VOID WINAPI CloseThreadpoolWork(_Inout_ PTP_WORK pwk)
WINBASEAPI VOID WINAPI CloseThreadpoolTimer(_Inout_ PTP_TIMER pti)
WINBASEAPI VOID WINAPI SetThreadpoolTimer(_Inout_ PTP_TIMER pti, _In_opt_ PFILETIME pftDueTime, _In_ DWORD msPeriod, _In_opt_ DWORD msWindowLength)
WINBASEAPI VOID WINAPI SubmitThreadpoolWork(_Inout_ PTP_WORK pwk)
#define FIELD_OFFSET(t, f)
DWORD WINAPI GetLastError(void)
BOOL WINAPI TryEnterCriticalSection(LPCRITICAL_SECTION)
DWORD WINAPI GetCurrentThreadId(void)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define TLS_OUT_OF_INDEXES
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define THREAD_PRIORITY_TIME_CRITICAL
#define THREAD_PRIORITY_NORMAL
#define THREAD_PRIORITY_IDLE
#define __EXCEPT_CTX(func, ctx)
#define __FINALLY_CTX(func, ctx)
static HRESULT HRESULT_FROM_WIN32(unsigned int x)
struct _TP_CALLBACK_INSTANCE * PTP_CALLBACK_INSTANCE
struct _TP_WORK * PTP_WORK
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
struct _TP_TIMER TP_TIMER
struct _TP_CALLBACK_INSTANCE TP_CALLBACK_INSTANCE