TestDllSafety.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) Electronic Arts Inc. All rights reserved.
  3. ///////////////////////////////////////////////////////////////////////////////
  4. #include <EATest/EATest.h>
  5. #include <eathread/eathread.h>
  6. #include <eathread/eathread_atomic.h>
  7. #include <eathread/eathread_thread.h>
  8. #include <EAStdC/EAString.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <EAMain/EAEntryPointMain.inl>
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // operator new
  15. // EASTL requires the following new operators to be defined.
  16. //
  17. void* operator new[](size_t size, const char*, int, unsigned, const char*, int)
  18. {
  19. return new char[size];
  20. }
  21. void* operator new[](size_t size, size_t, size_t, const char*, int, unsigned, const char*, int)
  22. {
  23. return new char[size];
  24. }
  25. const int NUM_THREADS = 5;
  26. ///////////////////////////////////////////////////////////////////////////////
  27. // Structure where a single instance is passed to every active thread.
  28. //
  29. struct GlobalData
  30. {
  31. EA::Thread::AtomicInt32 i;
  32. GlobalData()
  33. : i(0)
  34. {}
  35. };
  36. typedef void (*DLL_ENTRY)(GlobalData*);
  37. ///////////////////////////////////////////////////////////////////////////////
  38. // Thread Entry
  39. //
  40. intptr_t ThreadFunction(void* pData)
  41. {
  42. GlobalData* const pGlobalData = static_cast<GlobalData*>(pData);
  43. while(!pGlobalData->i)
  44. {
  45. EA::Thread::ThreadSleep(50);
  46. }
  47. return 0;
  48. }
  49. ///////////////////////////////////////////////////////////////////////////////
  50. // The function export below MUST be here as it forces lib files to be
  51. // generated for the DLL's being built.
  52. //
  53. extern "C"
  54. EA_EXPORT void ForceLibFilesToBeGenerated(GlobalData* pGlobal)
  55. {
  56. using namespace EA::Thread;
  57. using namespace EA::UnitTest;
  58. // Start two threads in this DLL instance
  59. Thread thread;
  60. for(size_t i = 0; i < NUM_THREADS; i++)
  61. thread.Begin(ThreadFunction, pGlobal);
  62. // Get the number of threads in the system
  63. ThreadEnumData enumData[32];
  64. size_t count = EnumerateThreads(enumData, EAArrayCount(enumData));
  65. //Report("Number of DLL threads detected: %d\n", count);
  66. for(size_t i = 0; i < count; i++)
  67. enumData[i].Release();
  68. }
  69. ///////////////////////////////////////////////////////////////////////////////
  70. // Main
  71. //
  72. int EAMain(int argc, char** argv)
  73. {
  74. using namespace EA::Thread;
  75. using namespace EA::UnitTest;
  76. int nErrorCount = 0;
  77. GlobalData data;
  78. // TODO: DLL usage must be made portable through support at various levels of our technology stack.
  79. #if defined(EA_PLATFORM_MICROSOFT) && defined(EA_PLATFORM_WIN32)
  80. HINSTANCE__* mod1 = LoadLibrary("EAThreadTestDllSafetyMod1.dll");
  81. HINSTANCE__* mod2 = LoadLibrary("EAThreadTestDllSafetyMod2.dll");
  82. DLL_ENTRY dllmain1 = (DLL_ENTRY)GetProcAddress(mod1, "ForceLibFilesToBeGenerated");
  83. DLL_ENTRY dllmain2 = (DLL_ENTRY)GetProcAddress(mod2, "ForceLibFilesToBeGenerated");
  84. if(dllmain1 != NULL)
  85. dllmain1(&data);
  86. if(dllmain2 != NULL)
  87. dllmain2(&data);
  88. #endif
  89. EA::EAMain::PlatformStartup();
  90. {
  91. // Start n threads in this DLL instance
  92. Thread thread;
  93. for(size_t i = 0; i < NUM_THREADS; i++)
  94. thread.Begin(ThreadFunction, &data);
  95. // Get the number of threads in the system and validate.
  96. ThreadEnumData enumData[32];
  97. size_t count = EnumerateThreads(enumData, EAArrayCount(enumData));
  98. Report("Number of threads detected: %d/%d. \n", count, NUM_THREADS*3);
  99. EATEST_VERIFY_MSG(count >= NUM_THREADS, "Thread tracking data isn't DLL safe. We are missing data generated in other DLL's.");
  100. for(size_t i = 0; i < count; i++)
  101. enumData[i].Release();
  102. // Release the threads
  103. data.i++;
  104. }
  105. EA::EAMain::PlatformShutdown(nErrorCount);
  106. #if defined(EA_PLATFORM_MICROSOFT) && defined(EA_PLATFORM_WIN32)
  107. FreeLibrary(mod1);
  108. FreeLibrary(mod2);
  109. #endif
  110. return nErrorCount;
  111. }