ThreadPoolMs.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "il2cpp-api.h"
  2. #include "il2cpp-config.h"
  3. #include "utils/dynamic_array.h"
  4. #include "vm/ThreadPoolMs.h"
  5. #include "vm/Domain.h"
  6. #include "vm/Array.h"
  7. #include "vm/Object.h"
  8. #include "vm/Runtime.h"
  9. #include "os/Atomic.h"
  10. #include "gc/WriteBarrier.h"
  11. #include "mono/ThreadPool/threadpool-ms.h"
  12. namespace il2cpp
  13. {
  14. namespace vm
  15. {
  16. Il2CppAsyncResult* ThreadPoolMs::DelegateBeginInvoke(Il2CppDelegate* delegate, void** params, Il2CppDelegate* asyncCallback, Il2CppObject* state)
  17. {
  18. #if IL2CPP_TINY
  19. IL2CPP_ASSERT(0 && "ThreadPoolMs::DelegateBeginInvoke should not be called with the Tiny profile.");
  20. return NULL;
  21. #else
  22. int numParams = delegate->method->parameters_count;
  23. il2cpp::utils::dynamic_array<void*> newParams(numParams + 2);
  24. for (int i = 0; i < numParams; ++i)
  25. newParams[i] = params[i];
  26. newParams[numParams] = asyncCallback;
  27. newParams[numParams + 1] = state;
  28. return threadpool_ms_begin_invoke(il2cpp::vm::Domain::GetCurrent(), (Il2CppObject*)delegate, const_cast<MethodInfo*>(delegate->method), newParams.data());
  29. #endif
  30. }
  31. Il2CppObject* ThreadPoolMs::DelegateEndInvoke(Il2CppAsyncResult* asyncResult, void **out_args)
  32. {
  33. #if IL2CPP_TINY
  34. IL2CPP_ASSERT(0 && "ThreadPoolMs::DelegateEndInvoke should not be called with the Tiny profile.");
  35. return NULL;
  36. #else
  37. Il2CppArray *arrayOutArgs;
  38. Il2CppObject *exc, *retVal;
  39. retVal = threadpool_ms_end_invoke(asyncResult, &arrayOutArgs, &exc);
  40. if (exc)
  41. il2cpp_raise_exception((Il2CppException*)exc);
  42. if (out_args)
  43. {
  44. const MethodInfo *method = asyncResult->async_delegate->method;
  45. void** outArgsPtr = (void**)il2cpp_array_addr(arrayOutArgs, Il2CppObject*, 0);
  46. il2cpp_array_size_t arrayOutArgsIndex = 0;
  47. for (size_t methodParameterIndex = 0; methodParameterIndex < method->parameters_count; methodParameterIndex++)
  48. {
  49. const Il2CppType* paramType = method->parameters[methodParameterIndex];
  50. // Assume that arrayOutArgs only contains parameters that are passed by reference.
  51. if (!paramType->byref)
  52. continue;
  53. IL2CPP_ASSERT(arrayOutArgsIndex < arrayOutArgs->max_length);
  54. Il2CppClass *paramClass = il2cpp_class_from_type(paramType);
  55. if (paramClass->byval_arg.valuetype)
  56. {
  57. IL2CPP_ASSERT(paramClass->native_size > 0 && "EndInvoke: Invalid native_size found when trying to copy a value type in the out_args.");
  58. // NOTE(gab): in case of value types, we need to copy the data over.
  59. memcpy(out_args[arrayOutArgsIndex], il2cpp::vm::Object::Unbox((Il2CppObject*)outArgsPtr[arrayOutArgsIndex]), paramClass->native_size);
  60. }
  61. else
  62. {
  63. *((void**)out_args[arrayOutArgsIndex]) = outArgsPtr[arrayOutArgsIndex];
  64. }
  65. arrayOutArgsIndex++;
  66. }
  67. }
  68. return retVal;
  69. #endif
  70. }
  71. Il2CppObject* ThreadPoolMs::MessageInvoke(Il2CppObject *target, Il2CppMethodMessage *msg, Il2CppObject **exc, Il2CppArray **out_args)
  72. {
  73. static Il2CppClass *object_array_klass = NULL;
  74. MethodInfo *method;
  75. Il2CppObject *ret;
  76. Il2CppArray *arr;
  77. int i, j, outarg_count = 0;
  78. method = (MethodInfo*)msg->method->method;
  79. for (i = 0; i < method->parameters_count; i++)
  80. {
  81. if (method->parameters[i]->byref)
  82. outarg_count++;
  83. }
  84. if (!object_array_klass)
  85. {
  86. Il2CppClass *klass;
  87. klass = il2cpp_array_class_get(il2cpp_defaults.object_class, 1);
  88. IL2CPP_ASSERT(klass);
  89. os::Atomic::FullMemoryBarrier();
  90. object_array_klass = klass;
  91. }
  92. arr = il2cpp_array_new_specific(object_array_klass, outarg_count);
  93. il2cpp::gc::WriteBarrier::GenericStore(out_args, arr);
  94. il2cpp::gc::WriteBarrier::GenericStoreNull(exc);
  95. ret = vm::Runtime::InvokeArray(method, method->klass->byval_arg.valuetype ? il2cpp_object_unbox(target) : target, method->parameters_count > 0 ? msg->args : NULL, (Il2CppException**)exc);
  96. for (i = 0, j = 0; i < method->parameters_count; i++)
  97. {
  98. if (method->parameters[i]->byref)
  99. {
  100. Il2CppObject* arg;
  101. arg = (Il2CppObject*)il2cpp_array_get(msg->args, void*, i);
  102. il2cpp_array_setref(*out_args, j, arg);
  103. j++;
  104. }
  105. }
  106. return ret;
  107. }
  108. void ThreadPoolMs::Suspend()
  109. {
  110. threadpool_ms_suspend();
  111. }
  112. void ThreadPoolMs::Resume()
  113. {
  114. threadpool_ms_resume();
  115. }
  116. } /* namespace vm */
  117. } /* namespace il2cpp */