xref: /reactos/ntoskrnl/ex/exintrin.c (revision 84344399)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            ntoskrnl/ex/exintrin.c
5  * PURPOSE:         Exported kernel functions which are now intrinsics
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #undef InterlockedIncrement
16 #undef InterlockedDecrement
17 #undef InterlockedCompareExchange
18 #undef InterlockedExchangeAdd
19 #undef InterlockedExchange
20 
21 //
22 // HAL Port to Inlined Port
23 //
24 #define H2I(Port) PtrToUshort(Port)
25 
26 /* FUNCTIONS ******************************************************************/
27 
28 /*
29  * @implemented
30  */
31 LONG
32 FASTCALL
33 InterlockedIncrement(IN LONG volatile *Addend)
34 {
35     //
36     // Call the intrinsic
37     //
38     return _InterlockedIncrement(Addend);
39 }
40 
41 /*
42  * @implemented
43  */
44 LONG
45 FASTCALL
46 InterlockedDecrement(IN LONG volatile *Addend)
47 {
48     //
49     // Call the intrinsic
50     //
51     return _InterlockedDecrement(Addend);
52 }
53 
54 /*
55  * @implemented
56  */
57 LONG
58 FASTCALL
59 InterlockedCompareExchange(IN OUT LONG volatile *Destination,
60                            IN LONG Exchange,
61                            IN LONG Comperand)
62 {
63     //
64     // Call the intrinsic
65     //
66     return _InterlockedCompareExchange(Destination, Exchange, Comperand);
67 }
68 
69 /*
70  * @implemented
71  */
72 LONG
73 FASTCALL
74 InterlockedExchange(IN OUT LONG volatile *Destination,
75                     IN LONG Value)
76 {
77     //
78     // Call the intrinsic
79     //
80     return _InterlockedExchange(Destination, Value);
81 }
82 
83 /*
84  * @implemented
85  */
86 LONG
87 FASTCALL
88 InterlockedExchangeAdd(IN OUT LONG volatile *Addend,
89                        IN LONG Increment)
90 {
91     //
92     // Call the intrinsic
93     //
94     return _InterlockedExchangeAdd(Addend, Increment);
95 }
96 
97 /*
98  * @implemented
99  */
100 VOID
101 NTAPI
102 ProbeForRead(IN CONST VOID *Address,
103              IN SIZE_T Length,
104              IN ULONG Alignment)
105 {
106     ULONG_PTR Last, Current = (ULONG_PTR)Address;
107     PAGED_CODE();
108 
109     /* Only probe if we have a valid length */
110     if (Length != 0)
111     {
112         /* Sanity check */
113         ASSERT((Alignment == 1) ||
114                (Alignment == 2) ||
115                (Alignment == 4) ||
116                (Alignment == 8) ||
117                (Alignment == 16));
118 
119         /* Check the alignment */
120         if ((Current & (Alignment - 1)) != 0)
121         {
122             /* Incorrect alignment */
123             ExRaiseDatatypeMisalignment();
124         }
125 
126         /* Get the end address */
127         Last = Current + Length - 1;
128         if ((Last < Current) || (Last >= (ULONG_PTR)MmUserProbeAddress))
129         {
130             /* Raise an access violation */
131             ExRaiseAccessViolation();
132         }
133 
134         /* ProbeForRead doesn't check if memory pages are readable! */
135     }
136 }
137 
138 /*
139  * @implemented
140  */
141 VOID
142 NTAPI
143 ProbeForWrite(IN PVOID Address,
144               IN SIZE_T Length,
145               IN ULONG Alignment)
146 {
147     ULONG_PTR Last, Current = (ULONG_PTR)Address;
148     PAGED_CODE();
149 
150     /* Only probe if we have a valid length */
151     if (Length != 0)
152     {
153         /* Sanity check */
154         ASSERT((Alignment == 1) ||
155                (Alignment == 2) ||
156                (Alignment == 4) ||
157                (Alignment == 8) ||
158                (Alignment == 16));
159 
160         /* Check the alignment */
161         if ((Current & (Alignment - 1)) != 0)
162         {
163             /* Incorrect alignment */
164             ExRaiseDatatypeMisalignment();
165         }
166 
167         /* Get the end address */
168         Last = Current + Length - 1;
169         if ((Last < Current) || (Last >= (ULONG_PTR)MmUserProbeAddress))
170         {
171             /* Raise an access violation */
172             ExRaiseAccessViolation();
173         }
174 
175         /* Round down to the last page */
176         Last = PAGE_ROUND_DOWN(Last) + PAGE_SIZE;
177         do
178         {
179             /* Attempt a write */
180             *(volatile CHAR*)Current = *(volatile CHAR*)Current;
181 
182             /* Go to the next address */
183             Current = PAGE_ROUND_DOWN(Current) + PAGE_SIZE;
184         } while (Current != Last);
185     }
186 }
187