Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
8.8 KiB

  1. #pragma include_alias("clist.h", "..\newjob\clist.h")
  2. #include "qmgrlib.h"
  3. #include "locks.hxx"
  4. #include "..\newjob\csd.h"
  5. #include "..\newjob\tasksched.h"
  6. //
  7. // Following items are needed to link properly.
  8. //
  9. HINSTANCE g_hInstance;
  10. SERVICE_STATUS_HANDLE ghServiceHandle;
  11. unsigned long g_LastServiceControl;
  12. bool IsServiceShuttingDown()
  13. {
  14. return false;
  15. }
  16. long SetServiceStartup( bool ignore )
  17. {
  18. return 0;
  19. }
  20. int InitializeBitsAllocator()
  21. {
  22. return 0;
  23. }
  24. SidHandle
  25. BITSAllocateAndInitializeSid(
  26. BYTE nSubAuthorityCount, // count of subauthorities
  27. DWORD dwSubAuthority0, // subauthority 0
  28. DWORD dwSubAuthority1 ); // subauthority 1
  29. //
  30. // Preceding items are needed to link properly.
  31. //
  32. #define MAX_QUEUED_WORK_ITEMS 30
  33. SidHandle g_NetworkUsersSid;
  34. long g_ThreadCount;
  35. long g_CancelCount;
  36. HANDLE * g_hThreads;
  37. HANDLE g_hWorkItemCreationThread;
  38. TaskScheduler * g_Lock;
  39. class TestWorkItem : public TaskSchedulerWorkItem
  40. {
  41. public:
  42. TestWorkItem( long index )
  43. {
  44. m_index = index;
  45. }
  46. virtual SidHandle GetSid() {
  47. return g_NetworkUsersSid;
  48. }
  49. virtual void OnDispatch();
  50. long m_index;
  51. };
  52. bool TakeAndReleaseLock( bool fWrite, long Delay, bool fComplete );
  53. struct
  54. {
  55. TestWorkItem * item;
  56. long complete;
  57. long cancelled;
  58. }
  59. g_PendingWorkItems[ MAX_QUEUED_WORK_ITEMS ];
  60. //------------------------------------------------------------------------
  61. void TestWorkItem::OnDispatch()
  62. {
  63. static int i;
  64. bool fWrite;
  65. if ((i % 7) == 0)
  66. {
  67. fWrite = true;
  68. }
  69. else
  70. {
  71. fWrite = false;
  72. }
  73. long Delay = -1;
  74. long SleepChoice = (i % 10);
  75. if (SleepChoice == 0)
  76. {
  77. // printf("Sleep 10\n");
  78. Delay = 10;
  79. }
  80. else if (SleepChoice == 5)
  81. {
  82. // printf("Sleep 0\n");
  83. Delay = 0;
  84. }
  85. bool fCancel;
  86. if ((i % 3) == 1)
  87. {
  88. fCancel = true;
  89. }
  90. else
  91. {
  92. fCancel = false;
  93. }
  94. long PreLockSleep = (i % 5);
  95. if (PreLockSleep < 3)
  96. {
  97. Sleep(10);
  98. }
  99. if (!TakeAndReleaseLock( fWrite, Delay, fCancel))
  100. {
  101. //
  102. // The work-item was cancelled.
  103. //
  104. g_Lock->AcknowledgeWorkItemCancel();
  105. InterlockedIncrement( &g_CancelCount );
  106. }
  107. else if (!fCancel)
  108. {
  109. g_Lock->CompleteWorkItem();
  110. }
  111. //
  112. // Mark the item complete.
  113. //
  114. if (m_index >= 0)
  115. {
  116. if (g_PendingWorkItems[m_index].item != this)
  117. {
  118. printf("error: index mismatch\n");
  119. exit(1);
  120. }
  121. // printf("completing item %p index %d\n", this, m_index);
  122. g_PendingWorkItems[m_index].complete = 1;
  123. }
  124. //
  125. // if ((i % 100000) == 0)
  126. {
  127. // printf("%d work items\n", i);
  128. }
  129. // if ((i % 1000) == 0)
  130. {
  131. // putchar('W');
  132. }
  133. ++i;
  134. }
  135. bool TakeAndReleaseLock( bool fWrite, long Delay, bool fComplete )
  136. {
  137. if (fWrite)
  138. {
  139. // printf("lock writer\n");
  140. if (g_Lock->LockWriter())
  141. {
  142. // cancelled
  143. return false;
  144. }
  145. }
  146. else
  147. {
  148. // printf("lock reader\n");
  149. if (g_Lock->LockReader())
  150. {
  151. // cancelled
  152. return false;
  153. }
  154. }
  155. if (Delay != -1)
  156. {
  157. Sleep(Delay);
  158. }
  159. if (fComplete)
  160. {
  161. g_Lock->CompleteWorkItem();
  162. }
  163. if (fWrite)
  164. {
  165. // printf("unlock writer\n");
  166. g_Lock->UnlockWriter();
  167. }
  168. else
  169. {
  170. // printf("unlock reader\n");
  171. g_Lock->UnlockReader();
  172. }
  173. return true;
  174. }
  175. DWORD WINAPI ThreadProc( LPVOID arg )
  176. {
  177. long index = long(arg);
  178. long i =0;
  179. do
  180. {
  181. bool fWrite;
  182. if ((i % 9) == index)
  183. {
  184. fWrite = true;
  185. }
  186. else
  187. {
  188. fWrite = false;
  189. }
  190. long Delay = -1;
  191. long SleepChoice = (i % 10);
  192. if (SleepChoice == 0)
  193. {
  194. // printf("Sleep 10\n");
  195. Delay = 10;
  196. }
  197. else if (SleepChoice == 5)
  198. {
  199. // printf("Sleep 0\n");
  200. Delay = 0;
  201. }
  202. if (!TakeAndReleaseLock( fWrite, Delay, false ))
  203. {
  204. printf("thread %d: cancel detected!", DWORD(arg));
  205. exit(1);
  206. }
  207. if ((i % 100000) == 0)
  208. {
  209. printf("thread %d: %d iterations\n", DWORD(arg), i);
  210. }
  211. if ((i % 1000) == 0)
  212. {
  213. putchar('0'+DWORD(arg));
  214. }
  215. ++i;
  216. }
  217. while ( 1 );
  218. }
  219. DWORD WINAPI WorkItemCreatorProc( LPVOID arg )
  220. {
  221. int i = 0;
  222. for (;;)
  223. {
  224. int index;
  225. if ((i % 1000) == 0)
  226. {
  227. putchar('w');
  228. }
  229. //
  230. // Clean out completed work items
  231. //
  232. for (index = 0; index < RTL_NUMBER_OF( g_PendingWorkItems ); ++index)
  233. {
  234. if (g_PendingWorkItems[index].complete)
  235. {
  236. // printf("clearing index %d\n", index);
  237. delete g_PendingWorkItems[index].item;
  238. g_PendingWorkItems[index].item = 0;
  239. g_PendingWorkItems[index].complete = 0;
  240. g_PendingWorkItems[index].cancelled = 0;
  241. }
  242. }
  243. //
  244. // Fill up the queue.
  245. //
  246. do
  247. {
  248. // find a spot
  249. for (index = 0; index < RTL_NUMBER_OF( g_PendingWorkItems ); ++index)
  250. {
  251. if (g_PendingWorkItems[index].item == 0)
  252. {
  253. break;
  254. }
  255. }
  256. //
  257. // A slot is available; create a new workitem for it.
  258. //
  259. if (index < RTL_NUMBER_OF( g_PendingWorkItems ))
  260. {
  261. TestWorkItem * item = new TestWorkItem( index );
  262. g_PendingWorkItems[index].item = item;
  263. g_Lock->InsertWorkItem( item, NULL );
  264. }
  265. }
  266. while ( index < RTL_NUMBER_OF( g_PendingWorkItems ) );
  267. //
  268. // let them drain away
  269. //
  270. do
  271. {
  272. for (index = RTL_NUMBER_OF( g_PendingWorkItems )-1; index >=0; --index)
  273. {
  274. if (g_PendingWorkItems[index].item != 0 &&
  275. g_PendingWorkItems[index].complete == 0 &&
  276. g_PendingWorkItems[index].cancelled == 0)
  277. {
  278. g_Lock->CancelWorkItem( g_PendingWorkItems[index].item );
  279. g_PendingWorkItems[index].cancelled = 1;
  280. break;
  281. }
  282. }
  283. Sleep(1);
  284. }
  285. while ( index >= 0 );
  286. ++i;
  287. }
  288. }
  289. void __cdecl wmain (int argc, wchar_t *argv[])
  290. {
  291. if (argc < 2)
  292. {
  293. printf("arg1 should be a thread count\n");
  294. return;
  295. }
  296. g_ThreadCount = _wtol( argv[1] );
  297. g_hThreads = new HANDLE[ g_ThreadCount ];
  298. if (!InitCompilerLibrary())
  299. {
  300. printf("init STL failed");
  301. return;
  302. }
  303. if ( !DetectProductVersion() )
  304. {
  305. printf("version detect failed");
  306. return;
  307. }
  308. if (0 != InitializeBitsAllocator())
  309. {
  310. printf("allocator init failed");
  311. return;
  312. }
  313. Log_Init();
  314. Log_StartLogger();
  315. g_NetworkUsersSid = BITSAllocateAndInitializeSid( 1, SECURITY_NETWORK_RID, 0);
  316. g_Lock = new TaskScheduler;
  317. for (int index = 0; index < RTL_NUMBER_OF( g_PendingWorkItems ); ++index)
  318. {
  319. g_PendingWorkItems[index].item = 0;
  320. g_PendingWorkItems[index].complete = 0;
  321. g_PendingWorkItems[index].cancelled = 0;
  322. }
  323. DWORD id;
  324. for (int i=0; i < g_ThreadCount; ++i)
  325. {
  326. g_hThreads[i] = CreateThread( NULL, 0, ThreadProc, LPVOID(i), 0, &id );
  327. if (0 == g_hThreads[i])
  328. {
  329. printf("error %d creating thread\n", GetLastError());
  330. }
  331. }
  332. g_hWorkItemCreationThread = CreateThread( NULL, 0, WorkItemCreatorProc, 0, 0, &id );
  333. if (0 == g_hWorkItemCreationThread)
  334. {
  335. printf("error %d creating thread\n", GetLastError());
  336. }
  337. Sleep( 1000 * 1000 );
  338. }