[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / include / internal / io_x.h
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/include/io_x.h
5 * PURPOSE: Internal Inlined Functions for the I/O Manager
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 static
10 __inline
11 VOID
12 IopLockFileObject(IN PFILE_OBJECT FileObject)
13 {
14 /* Lock the FO and check for contention */
15 InterlockedIncrement((PLONG)&FileObject->Waiters);
16 while (InterlockedCompareExchange((PLONG)&FileObject->Busy, TRUE, FALSE) != FALSE)
17 {
18 /* FIXME - pause for a little while? */
19 }
20 InterlockedDecrement((PLONG)&FileObject->Waiters);
21 }
22
23 static
24 __inline
25 VOID
26 IopUnlockFileObject(IN PFILE_OBJECT FileObject)
27 {
28 /* Unlock the FO and wake any waiters up */
29 InterlockedExchange((PLONG)&FileObject->Busy, FALSE);
30 if (FileObject->Waiters) KeSetEvent(&FileObject->Lock, 0, FALSE);
31 }
32
33 FORCEINLINE
34 VOID
35 IopQueueIrpToThread(IN PIRP Irp)
36 {
37 KIRQL OldIrql;
38
39 /* Raise to APC Level */
40 KeRaiseIrql(APC_LEVEL, &OldIrql);
41
42 /* Insert it into the list */
43 InsertHeadList(&Irp->Tail.Overlay.Thread->IrpList, &Irp->ThreadListEntry);
44
45 /* Lower irql */
46 KeLowerIrql(OldIrql);
47 }
48
49 FORCEINLINE
50 VOID
51 IopUnQueueIrpFromThread(IN PIRP Irp)
52 {
53 /* Remove it from the list and reset it */
54 RemoveEntryList(&Irp->ThreadListEntry);
55 InitializeListHead(&Irp->ThreadListEntry);
56 }
57
58 static
59 __inline
60 VOID
61 IopUpdateOperationCount(IN IOP_TRANSFER_TYPE Type)
62 {
63 PLARGE_INTEGER CountToChange;
64
65 /* Make sure I/O operations are being counted */
66 if (IoCountOperations)
67 {
68 if (Type == IopReadTransfer)
69 {
70 /* Increase read count */
71 IoReadOperationCount++;
72 CountToChange = &PsGetCurrentProcess()->ReadOperationCount;
73 }
74 else if (Type == IopWriteTransfer)
75 {
76 /* Increase write count */
77 IoWriteOperationCount++;
78 CountToChange = &PsGetCurrentProcess()->WriteOperationCount;
79 }
80 else
81 {
82 /* Increase other count */
83 IoOtherOperationCount++;
84 CountToChange = &PsGetCurrentProcess()->OtherOperationCount;
85 }
86
87 /* Increase the process-wide count */
88 ExInterlockedAddLargeStatistic(CountToChange, 1);
89 }
90 }
91
92 static
93 __inline
94 VOID
95 IopUpdateTransferCount(IN IOP_TRANSFER_TYPE Type, IN ULONG TransferCount)
96 {
97 PLARGE_INTEGER CountToChange;
98 PLARGE_INTEGER TransferToChange;
99
100 /* Make sure I/O operations are being counted */
101 if (IoCountOperations)
102 {
103 if (Type == IopReadTransfer)
104 {
105 /* Increase read count */
106 CountToChange = &PsGetCurrentProcess()->ReadTransferCount;
107 TransferToChange = &IoReadTransferCount;
108 }
109 else if (Type == IopWriteTransfer)
110 {
111 /* Increase write count */
112 CountToChange = &PsGetCurrentProcess()->WriteTransferCount;
113 TransferToChange = &IoWriteTransferCount;
114 }
115 else
116 {
117 /* Increase other count */
118 CountToChange = &PsGetCurrentProcess()->OtherTransferCount;
119 TransferToChange = &IoOtherTransferCount;
120 }
121
122 /* Increase the process-wide count */
123 ExInterlockedAddLargeStatistic(CountToChange, TransferCount);
124
125 /* Increase global count */
126 ExInterlockedAddLargeStatistic(TransferToChange, TransferCount);
127 }
128 }
129
130 static
131 __inline
132 BOOLEAN
133 IopValidateOpenPacket(IN POPEN_PACKET OpenPacket)
134 {
135 /* Validate the packet */
136 if (!(OpenPacket) ||
137 (OpenPacket->Type != IO_TYPE_OPEN_PACKET) ||
138 (OpenPacket->Size != sizeof(OPEN_PACKET)))
139 {
140 /* Fail */
141 return FALSE;
142 }
143
144 /* Good packet */
145 return TRUE;
146 }