xref: /reactos/ntoskrnl/ex/i386/fastinterlck_asm.S (revision 0f3da974)
1c2c66affSColin Finck/*
2c2c66affSColin Finck * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck * PROJECT:         ReactOS kernel
4c2c66affSColin Finck * FILE:            ntoskrnl/ex/i386/fastinterlck_asm.S
5c2c66affSColin Finck * PURPOSE:         FASTCALL Interlocked Functions
6c2c66affSColin Finck * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck/* INCLUDES ******************************************************************/
10c2c66affSColin Finck
11c2c66affSColin Finck#include <asm.inc>
12c2c66affSColin Finck#include <ks386.inc>
13c2c66affSColin Finck#include <internal/i386/asmmacro.S>
14c2c66affSColin Finck
15c2c66affSColin Finck/* FUNCTIONS ****************************************************************/
16c2c66affSColin Finck
17c2c66affSColin Finck.code32
18c2c66affSColin Finck
19c2c66affSColin Finck/*
20c2c66affSColin Finck * NOTE: These functions must obey the following rules:
21c2c66affSColin Finck *  - Acquire locks only on MP systems.
22c2c66affSColin Finck *  - Be safe at HIGH_LEVEL (no paged access).
23c2c66affSColin Finck *  - Preserve flags.
24*0f3da974SHermès Bélusca-Maïto *  - Disable interrupts.
25c2c66affSColin Finck */
26c2c66affSColin Finck
27c2c66affSColin Finck/*VOID
28c2c66affSColin Finck *FASTCALL
29c2c66affSColin Finck *ExInterlockedAddLargeStatistic(IN PLARGE_INTEGER Addend,
30c2c66affSColin Finck *                               IN ULONG Increment)
31c2c66affSColin Finck */
32c2c66affSColin FinckPUBLIC @ExInterlockedAddLargeStatistic@8
33c2c66affSColin Finck@ExInterlockedAddLargeStatistic@8:
34c2c66affSColin Finck
35c2c66affSColin Finck#ifdef CONFIG_SMP
36c2c66affSColin Finck    /* Do the addition */
37c2c66affSColin Finck    lock add [ecx], edx
38c2c66affSColin Finck
39c2c66affSColin Finck    /* Check for carry bit and return */
40c2c66affSColin Finck    jc .l1
41c2c66affSColin Finck    ret
42c2c66affSColin Finck
43c2c66affSColin Finck.l1:
44c2c66affSColin Finck    /* Add carry */
45c2c66affSColin Finck    lock adc dword ptr [ecx+4], 0
46c2c66affSColin Finck#else
47c2c66affSColin Finck    /* Do the addition and add the carry */
48c2c66affSColin Finck    add dword ptr [ecx], edx
49c2c66affSColin Finck    adc dword ptr [ecx+4], 0
50c2c66affSColin Finck#endif
51c2c66affSColin Finck    /* Return */
52c2c66affSColin Finck    ret
53c2c66affSColin Finck
54c2c66affSColin Finck
55c2c66affSColin Finck
56c2c66affSColin Finck/*PSINGLE_LIST_ENTRY
57c2c66affSColin Finck *FASTCALL
58c2c66affSColin Finck *ExInterlockedPopEntrySList(IN PSINGLE_LIST_ENTRY ListHead,
59c2c66affSColin Finck *                           IN PKSPIN_LOCK Lock)
60c2c66affSColin Finck */
61c2c66affSColin FinckPUBLIC @ExInterlockedPopEntrySList@8
62c2c66affSColin FinckPUBLIC @InterlockedPopEntrySList@4
63c2c66affSColin FinckPUBLIC _ExpInterlockedPopEntrySListResume@0
64c2c66affSColin FinckPUBLIC _ExpInterlockedPopEntrySListFault@0
65c2c66affSColin FinckPUBLIC _ExpInterlockedPopEntrySListEnd@0
66c2c66affSColin Finck@ExInterlockedPopEntrySList@8:
67c2c66affSColin Finck@InterlockedPopEntrySList@4:
68c2c66affSColin Finck
69c2c66affSColin Finck    /* Save registers */
70c2c66affSColin Finck    push ebx
71c2c66affSColin Finck    push ebp
72c2c66affSColin Finck
73c2c66affSColin Finck    /* Pointer to list */
74c2c66affSColin Finck    mov ebp, ecx
75c2c66affSColin Finck
76c2c66affSColin Finck    /* Get sequence number and link pointer */
77c2c66affSColin Finck_ExpInterlockedPopEntrySListResume@0:
78c2c66affSColin Finck    mov edx, [ebp+4]
79c2c66affSColin Finck    mov eax, [ebp]
80c2c66affSColin Finck
81c2c66affSColin Finck    /* Check if the list is empty */
82c2c66affSColin Finck    or eax, eax
83c2c66affSColin Finck    jz .l7
84c2c66affSColin Finck
85c2c66affSColin Finck    /* Copy depth and adjust it */
86c2c66affSColin Finck    lea ecx, [edx-1]
87c2c66affSColin Finck
88c2c66affSColin Finck    /* Get next pointer and do the exchange */
89c2c66affSColin Finck_ExpInterlockedPopEntrySListFault@0:
90c2c66affSColin Finck    mov ebx, [eax]
91c2c66affSColin Finck_ExpInterlockedPopEntrySListEnd@0:
92c2c66affSColin Finck    LOCK cmpxchg8b qword ptr [ebp]
93c2c66affSColin Finck    jnz _ExpInterlockedPopEntrySListResume@0
94c2c66affSColin Finck
95c2c66affSColin Finck    /* Restore registers and return */
96c2c66affSColin Finck.l7:
97c2c66affSColin Finck    pop ebp
98c2c66affSColin Finck    pop ebx
99c2c66affSColin Finck    ret
100c2c66affSColin Finck
101c2c66affSColin Finck/*PSINGLE_LIST_ENTRY
102c2c66affSColin Finck *FASTCALL
103c2c66affSColin Finck *ExInterlockedPushEntrySList(IN PSINGLE_LIST_ENTRY ListHead,
104c2c66affSColin Finck *                            IN PSINGLE_LIST_ENTRY ListEntry,
105c2c66affSColin Finck *                            IN PKSPIN_LOCK Lock)
106c2c66affSColin Finck */
107c2c66affSColin FinckPUBLIC @ExInterlockedPushEntrySList@12
108c2c66affSColin Finck@ExInterlockedPushEntrySList@12:
109c2c66affSColin Finck
110c2c66affSColin Finck    /* So we can fall through below */
111c2c66affSColin Finck    pop [esp]
112c2c66affSColin Finck
113c2c66affSColin FinckPUBLIC @InterlockedPushEntrySList@8
114c2c66affSColin Finck@InterlockedPushEntrySList@8:
115c2c66affSColin Finck
116c2c66affSColin Finck    /* Save registers */
117c2c66affSColin Finck    push ebx
118c2c66affSColin Finck    push ebp
119c2c66affSColin Finck
120c2c66affSColin Finck    /* Pointer to list */
121c2c66affSColin Finck    mov ebp, ecx
122c2c66affSColin Finck    mov ebx, edx
123c2c66affSColin Finck
124c2c66affSColin Finck    /* Get sequence number and link pointer */
125c2c66affSColin Finck    mov edx, [ebp+4]
126c2c66affSColin Finck    mov eax, [ebp]
127c2c66affSColin Finck
128c2c66affSColin Finck.l8:
129c2c66affSColin Finck    /* Set link pointer */
130c2c66affSColin Finck    mov [ebx], eax
131c2c66affSColin Finck
132c2c66affSColin Finck    /* Copy sequence number and adjust it */
133c2c66affSColin Finck    lea ecx, [edx + HEX(10001)]
134c2c66affSColin Finck
135c2c66affSColin Finck    /* Do the exchange */
136c2c66affSColin Finck    LOCK cmpxchg8b qword ptr [ebp]
137c2c66affSColin Finck    jnz .l8
138c2c66affSColin Finck
139c2c66affSColin Finck    /* Restore registers and return */
140c2c66affSColin Finck    pop ebp
141c2c66affSColin Finck    pop ebx
142c2c66affSColin Finck    ret
143c2c66affSColin Finck
144c2c66affSColin Finck/*PSINGLE_LIST_ENTRY
145c2c66affSColin Finck *FASTCALL
146c2c66affSColin Finck *ExInterlockedFlushSList(IN PSINGLE_LIST_ENTRY ListHead)
147c2c66affSColin Finck */
148c2c66affSColin FinckPUBLIC @ExInterlockedFlushSList@4
149c2c66affSColin Finck@ExInterlockedFlushSList@4:
150c2c66affSColin Finck
151c2c66affSColin Finck    /* Save registers */
152c2c66affSColin Finck    push ebx
153c2c66affSColin Finck    push ebp
154c2c66affSColin Finck
155c2c66affSColin Finck    /* Clear ebx */
156c2c66affSColin Finck    xor ebx, ebx
157c2c66affSColin Finck
158c2c66affSColin Finck    /* Pointer to list */
159c2c66affSColin Finck    mov ebp, ecx
160c2c66affSColin Finck
161c2c66affSColin Finck    /* Get sequence number and link pointer */
162c2c66affSColin Finck    mov edx, [ebp+4]
163c2c66affSColin Finck    mov eax, [ebp]
164c2c66affSColin Finck
165c2c66affSColin Finck.l9:
166c2c66affSColin Finck    /* Check if the list is empty */
167c2c66affSColin Finck    or eax, eax
168c2c66affSColin Finck    jz .l10
169c2c66affSColin Finck
170c2c66affSColin Finck    /* Clear depth and pointer */
171c2c66affSColin Finck    mov ecx, edx
172c2c66affSColin Finck    mov cx, bx
173c2c66affSColin Finck
174c2c66affSColin Finck    /* Do the exchange */
175c2c66affSColin Finck    LOCK cmpxchg8b qword ptr [ebp]
176c2c66affSColin Finck    jnz .l9
177c2c66affSColin Finck
178c2c66affSColin Finck    /* Restore registers and return */
179c2c66affSColin Finck.l10:
180c2c66affSColin Finck    pop ebp
181c2c66affSColin Finck    pop ebx
182c2c66affSColin Finck    ret
183c2c66affSColin Finck
184c2c66affSColin FinckEND
185c2c66affSColin Finck/* EOF */
186