Source code of Windows XP (NT5)
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.

339 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. tfile.c
  5. Abstract:
  6. Test program for Win32 Base File API calls
  7. Author:
  8. Mark Lucovsky (markl) 26-Sep-1990
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <assert.h>
  15. #include <stdio.h>
  16. #include <windows.h>
  17. #include <string.h>
  18. #include <memory.h>
  19. #define xassert ASSERT
  20. typedef struct _aio {
  21. LIST_ENTRY Links;
  22. HANDLE ReadHandle;
  23. HANDLE WriteHandle;
  24. LPVOID Buffer;
  25. OVERLAPPED Overlapped;
  26. } AIO, *PAIO;
  27. HANDLE IoReadsDoneEvent;
  28. HANDLE IoWritesDoneEvent;
  29. HANDLE IoWorkerListLock;
  30. HANDLE IoWorkerListSemaphore;
  31. LIST_ENTRY IoRequestList;
  32. ULONG IoCount;
  33. ULONG IoReadCount;
  34. ULONG IoWriteCount;
  35. #define BSIZE 2048
  36. VOID
  37. WriteIoComplete(
  38. DWORD dwErrorCode,
  39. DWORD dwNumberOfBytesTransfered,
  40. LPOVERLAPPED lpOverlapped
  41. )
  42. {
  43. PAIO paio;
  44. //
  45. // If an I/O error occured, display the error and then exit
  46. //
  47. if ( dwErrorCode ) {
  48. printf("FATAL I/O Error %ld I/O Context %lx.%lx\n",
  49. dwErrorCode,
  50. lpOverlapped,
  51. lpOverlapped->hEvent
  52. );
  53. ExitProcess(dwErrorCode);
  54. }
  55. paio = (PAIO)CONTAINING_RECORD(lpOverlapped,AIO,Overlapped);
  56. if ( InterlockedDecrement(&IoWriteCount) == 0 ) {
  57. SetEvent(IoWritesDoneEvent);
  58. }
  59. LocalFree(paio->Buffer);
  60. LocalFree(paio);
  61. }
  62. VOID
  63. ReadIoComplete(
  64. DWORD dwErrorCode,
  65. DWORD dwNumberOfBytesTransfered,
  66. LPOVERLAPPED lpOverlapped
  67. )
  68. {
  69. PAIO paio;
  70. BOOL IoOperationStatus;
  71. //
  72. // If an I/O error occured, display the error and then exit
  73. //
  74. if ( dwErrorCode ) {
  75. printf("FATAL I/O Error %ld I/O Context %lx.%lx\n",
  76. dwErrorCode,
  77. lpOverlapped,
  78. lpOverlapped->hEvent
  79. );
  80. ExitProcess(dwErrorCode);
  81. }
  82. paio = (PAIO)CONTAINING_RECORD(lpOverlapped,AIO,Overlapped);
  83. //printf("%s",paio->Buffer);
  84. IoOperationStatus = WriteFileEx(
  85. paio->WriteHandle,
  86. paio->Buffer,
  87. dwNumberOfBytesTransfered,
  88. &paio->Overlapped,
  89. WriteIoComplete
  90. );
  91. //
  92. // Test to see if I/O was queued successfully
  93. //
  94. if ( !IoOperationStatus ) {
  95. if ( GetLastError() != ERROR_HANDLE_EOF ) {
  96. printf("FATAL I/O Error %ld\n",
  97. GetLastError()
  98. );
  99. ExitProcess(1);
  100. }
  101. }
  102. if ( InterlockedDecrement(&IoReadCount) == 0 ) {
  103. SetEvent(IoReadsDoneEvent);
  104. }
  105. }
  106. VOID
  107. IoWorkerThread(
  108. PVOID Unused
  109. )
  110. {
  111. HANDLE HandleVector[2];
  112. DWORD CompletionStatus;
  113. PAIO paio;
  114. BOOL IoOperationStatus;
  115. HandleVector[0] = IoWorkerListLock;
  116. HandleVector[1] = IoWorkerListSemaphore;
  117. for(;;){
  118. //
  119. // Do an alertable wait on the handle vector. Both objects
  120. // becoming signaled at the same time means there is an
  121. // I/O request in the queue, and the caller has exclusive
  122. // access to the queue
  123. //
  124. CompletionStatus = WaitForMultipleObjectsEx(
  125. 2,
  126. HandleVector,
  127. TRUE,
  128. 0xffffffff,
  129. TRUE
  130. );
  131. //
  132. // If the wait failed, error out
  133. //
  134. if ( CompletionStatus == 0xffffffff ) {
  135. printf("FATAL WAIT ERROR %ld\n",GetLastError());
  136. ExitProcess(1);
  137. }
  138. //
  139. // If an I/O completion occured, then wait for another
  140. // I/O request or I/O completion
  141. //
  142. if ( CompletionStatus != WAIT_IO_COMPLETION ) {
  143. //
  144. // Wait was satisfied. We now have exclusive ownership of the
  145. // I/O request queue, and there is something on the queue.
  146. // Note that to insert something on the queue, the inserter
  147. // gets the list lock (mutex), inserts an entry, signals the
  148. // list semaphore, and finally releases the list lock
  149. //
  150. paio = (PAIO)RemoveHeadList(&IoRequestList);
  151. ReleaseMutex(IoWorkerListLock);
  152. IoOperationStatus = ReadFileEx(
  153. paio->ReadHandle,
  154. paio->Buffer,
  155. paio->Overlapped.Internal,
  156. &paio->Overlapped,
  157. ReadIoComplete
  158. );
  159. //
  160. // Test to see if I/O was queued successfully
  161. //
  162. if ( !IoOperationStatus ) {
  163. if ( GetLastError() != ERROR_HANDLE_EOF ) {
  164. printf("FATAL I/O Error %ld\n",
  165. GetLastError()
  166. );
  167. ExitProcess(1);
  168. }
  169. }
  170. //
  171. // The I/O was successfully queued. Go back into the alertable
  172. // wait waiting for I/O completion, or for more I/O requests
  173. //
  174. }
  175. }
  176. }
  177. DWORD
  178. main(
  179. int argc,
  180. char *argv[],
  181. char *envp[]
  182. )
  183. {
  184. HANDLE iFile,oFile;
  185. DWORD FileSize;
  186. PAIO paio;
  187. DWORD WaitStatus;
  188. DWORD Offset;
  189. HANDLE CompletionHandles[2];
  190. HANDLE Thread;
  191. DWORD ThreadId;
  192. if ( argc < 2 ) {
  193. printf("Usage: trd source-file destination-file\n");
  194. }
  195. iFile = CreateFile(
  196. argv[1],
  197. GENERIC_READ,
  198. FILE_SHARE_READ,
  199. NULL,
  200. OPEN_EXISTING,
  201. FILE_FLAG_OVERLAPPED,
  202. NULL
  203. );
  204. if ( iFile == INVALID_HANDLE_VALUE ) {
  205. printf("OPEN %s failed %ld\n",argv[1],GetLastError());
  206. ExitProcess(1);
  207. }
  208. oFile = CreateFile(
  209. argv[2],
  210. GENERIC_READ | GENERIC_WRITE,
  211. FILE_SHARE_READ,
  212. NULL,
  213. CREATE_ALWAYS,
  214. FILE_FLAG_OVERLAPPED,
  215. NULL
  216. );
  217. if ( oFile == INVALID_HANDLE_VALUE ) {
  218. printf("OPEN %s failed %ld\n",argv[2],GetLastError());
  219. ExitProcess(1);
  220. }
  221. IoReadsDoneEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  222. IoWritesDoneEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  223. IoWorkerListLock = CreateMutex(NULL,FALSE,NULL);;
  224. IoWorkerListSemaphore = CreateSemaphore(NULL,0,0x7fffffff,NULL);
  225. xassert(IoReadsDoneEvent);
  226. xassert(IoWritesDoneEvent);
  227. xassert(IoWorkerListLock);
  228. xassert(IoWorkerListSemaphore);
  229. InitializeListHead(&IoRequestList);
  230. Thread = CreateThread(NULL,0L,IoWorkerThread,0,0,&ThreadId);
  231. xassert(Thread);
  232. Offset = 0;
  233. FileSize = GetFileSize(iFile,NULL);
  234. WaitStatus = WaitForSingleObject(IoWorkerListLock,-1);
  235. xassert(WaitStatus == 0);
  236. while(FileSize >= BSIZE) {
  237. FileSize -= BSIZE;
  238. paio = LocalAlloc(LMEM_ZEROINIT,sizeof(*paio));
  239. xassert(paio);
  240. paio->Buffer = LocalAlloc(LMEM_ZEROINIT,BSIZE+1);
  241. xassert(paio->Buffer);
  242. paio->ReadHandle = iFile;
  243. paio->WriteHandle = oFile;
  244. paio->Overlapped.Internal = BSIZE;
  245. paio->Overlapped.Offset = Offset;
  246. Offset += BSIZE;
  247. IoCount++;
  248. if ( IoCount & 1 ) {
  249. InsertTailList(&IoRequestList,&paio->Links);
  250. }
  251. else {
  252. InsertHeadList(&IoRequestList,&paio->Links);
  253. }
  254. ReleaseSemaphore(IoWorkerListSemaphore,1,NULL);
  255. }
  256. if ( FileSize != 0 ) {
  257. paio = LocalAlloc(LMEM_ZEROINIT,sizeof(*paio));
  258. xassert(paio);
  259. paio->Buffer = LocalAlloc(LMEM_ZEROINIT,FileSize+1);
  260. xassert(paio->Buffer);
  261. paio->ReadHandle = iFile;
  262. paio->WriteHandle = oFile;
  263. paio->Overlapped.interlockInternal = FileSize;
  264. paio->Overlapped.Offset = Offset;
  265. IoCount++;
  266. if ( IoCount & 1 ) {
  267. InsertTailList(&IoRequestList,&paio->Links);
  268. }
  269. else {
  270. InsertHeadList(&IoRequestList,&paio->Links);
  271. }
  272. ReleaseSemaphore(IoWorkerListSemaphore,1,NULL);
  273. }
  274. IoReadCount = IoCount;
  275. IoWriteCount = IoCount;
  276. ReleaseMutex(IoWorkerListLock);
  277. CompletionHandles[0] = IoReadsDoneEvent;
  278. CompletionHandles[1] = IoWritesDoneEvent;
  279. WaitStatus = WaitForMultipleObjects(2,CompletionHandles,TRUE,0xffffffff);
  280. xassert(WaitStatus != 0xffffffff);
  281. CloseHandle(iFile);
  282. CloseHandle(oFile);
  283. return 1;
  284. }