- Fix multiple LPC race conditions.
[reactos.git] / reactos / ntoskrnl / include / internal / lpc_x.h
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/include/lpc_x.h
5 * PURPOSE: Intenral Inlined Functions for Local Procedure Call
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 //
10 // Gets the message type, removing the kernel-mode flag
11 //
12 #define LpcpGetMessageType(x) \
13 ((x)->u2.s2.Type &~ LPC_KERNELMODE_MESSAGE)
14
15 //
16 // Waits on an LPC semaphore for a receive operation
17 //
18 #define LpcpReceiveWait(s, w) \
19 { \
20 LPCTRACE(LPC_REPLY_DEBUG, "Wait: %p\n", s); \
21 Status = KeWaitForSingleObject(s, \
22 WrLpcReceive, \
23 w, \
24 FALSE, \
25 NULL); \
26 LPCTRACE(LPC_REPLY_DEBUG, "Wait done: %lx\n", Status); \
27 }
28
29 //
30 // Waits on an LPC semaphore for a reply operation
31 //
32 #define LpcpReplyWait(s, w) \
33 { \
34 LPCTRACE(LPC_SEND_DEBUG, "Wait: %p\n", s); \
35 Status = KeWaitForSingleObject(s, \
36 WrLpcReply, \
37 w, \
38 FALSE, \
39 NULL); \
40 LPCTRACE(LPC_SEND_DEBUG, "Wait done: %lx\n", Status); \
41 if (Status == STATUS_USER_APC) \
42 { \
43 /* We were preempted by an APC */ \
44 if (KeReadStateSemaphore(s)) \
45 { \
46 /* It's still signaled, so wait on it */ \
47 KeWaitForSingleObject(s, \
48 WrExecutive, \
49 KernelMode, \
50 FALSE, \
51 NULL); \
52 Status = STATUS_SUCCESS; \
53 } \
54 } \
55 }
56
57 //
58 // Waits on an LPC semaphore for a connect operation
59 //
60 #define LpcpConnectWait(s, w) \
61 { \
62 LPCTRACE(LPC_CONNECT_DEBUG, "Wait: %p\n", s); \
63 Status = KeWaitForSingleObject(s, \
64 Executive, \
65 w, \
66 FALSE, \
67 NULL); \
68 LPCTRACE(LPC_CONNECT_DEBUG, "Wait done: %lx\n", Status);\
69 if (Status == STATUS_USER_APC) \
70 { \
71 /* We were preempted by an APC */ \
72 if (KeReadStateSemaphore(s)) \
73 { \
74 /* It's still signaled, so wait on it */ \
75 KeWaitForSingleObject(s, \
76 WrExecutive, \
77 KernelMode, \
78 FALSE, \
79 NULL); \
80 Status = STATUS_SUCCESS; \
81 } \
82 } \
83 }
84
85 //
86 // Releases an LPC Semaphore to complete a wait
87 //
88 #define LpcpCompleteWait(s) \
89 { \
90 /* Release the semaphore */ \
91 LPCTRACE(LPC_SEND_DEBUG, "Release: %p\n", s); \
92 KeReleaseSemaphore(s, 1, 1, FALSE); \
93 }
94
95 //
96 // Allocates a new message
97 //
98 PLPCP_MESSAGE
99 FORCEINLINE
100 LpcpAllocateFromPortZone(VOID)
101 {
102 PLPCP_MESSAGE Message;
103
104 /* Allocate a message from the port zone while holding the lock */
105 KeAcquireGuardedMutex(&LpcpLock);
106 Message = ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside);
107 if (!Message)
108 {
109 /* Fail, and let caller cleanup */
110 KeReleaseGuardedMutex(&LpcpLock);
111 return NULL;
112 }
113
114 /* Initialize it */
115 InitializeListHead(&Message->Entry);
116 Message->RepliedToThread = NULL;
117 Message->Request.u2.ZeroInit = 0;
118
119 /* Release the lock */
120 KeReleaseGuardedMutex(&LpcpLock);
121 return Message;
122 }