Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwait.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS system libraries 00004 * PURPOSE: Rtl user wait functions 00005 * FILE: lib/rtl/wait.c 00006 * PROGRAMERS: 00007 * Alex Ionescu (alex@relsoft.net) 00008 * Eric Kohl 00009 * KJK::Hyperion 00010 */ 00011 00012 /* INCLUDES *****************************************************************/ 00013 00014 #include <rtl.h> 00015 00016 #define NDEBUG 00017 #include <debug.h> 00018 00019 typedef struct _RTLP_WAIT 00020 { 00021 HANDLE Object; 00022 BOOLEAN CallbackInProgress; 00023 HANDLE CancelEvent; 00024 LONG DeleteCount; 00025 HANDLE CompletionEvent; 00026 ULONG Flags; 00027 WAITORTIMERCALLBACKFUNC Callback; 00028 PVOID Context; 00029 ULONG Milliseconds; 00030 } RTLP_WAIT, *PRTLP_WAIT; 00031 00032 /* PRIVATE FUNCTIONS *******************************************************/ 00033 00034 static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, ULONG timeout ) 00035 { 00036 if (timeout == INFINITE) return NULL; 00037 pTime->QuadPart = (ULONGLONG)timeout * -10000; 00038 return pTime; 00039 } 00040 00041 static VOID 00042 NTAPI 00043 Wait_thread_proc(LPVOID Arg) 00044 { 00045 PRTLP_WAIT Wait = (PRTLP_WAIT) Arg; 00046 NTSTATUS Status; 00047 BOOLEAN alertable = (Wait->Flags & WT_EXECUTEINIOTHREAD) ? TRUE : FALSE; 00048 HANDLE handles[2] = { Wait->Object, Wait->CancelEvent }; 00049 LARGE_INTEGER timeout; 00050 HANDLE completion_event; 00051 00052 // TRACE("\n"); 00053 00054 while (TRUE) 00055 { 00056 Status = NtWaitForMultipleObjects( 2, 00057 handles, 00058 WaitAny, 00059 alertable, 00060 get_nt_timeout( &timeout, Wait->Milliseconds ) ); 00061 00062 if (Status == STATUS_WAIT_0 || Status == STATUS_TIMEOUT) 00063 { 00064 BOOLEAN TimerOrWaitFired; 00065 00066 if (Status == STATUS_WAIT_0) 00067 { 00068 // TRACE( "object %p signaled, calling callback %p with context %p\n", 00069 // Wait->Object, Wait->Callback, 00070 // Wait->Context ); 00071 TimerOrWaitFired = FALSE; 00072 } 00073 else 00074 { 00075 // TRACE( "wait for object %p timed out, calling callback %p with context %p\n", 00076 // Wait->Object, Wait->Callback, 00077 // Wait->Context ); 00078 TimerOrWaitFired = TRUE; 00079 } 00080 Wait->CallbackInProgress = TRUE; 00081 Wait->Callback( Wait->Context, TimerOrWaitFired ); 00082 Wait->CallbackInProgress = FALSE; 00083 00084 if (Wait->Flags & WT_EXECUTEONLYONCE) 00085 break; 00086 } 00087 else 00088 break; 00089 } 00090 00091 completion_event = Wait->CompletionEvent; 00092 if (completion_event) NtSetEvent( completion_event, NULL ); 00093 00094 if (InterlockedIncrement( &Wait->DeleteCount ) == 2 ) 00095 { 00096 NtClose( Wait->CancelEvent ); 00097 RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); 00098 } 00099 } 00100 00101 00102 /* FUNCTIONS ***************************************************************/ 00103 00104 00105 /*********************************************************************** 00106 * RtlRegisterWait 00107 * 00108 * Registers a wait for a handle to become signaled. 00109 * 00110 * PARAMS 00111 * NewWaitObject [I] Handle to the new wait object. Use RtlDeregisterWait() to free it. 00112 * Object [I] Object to wait to become signaled. 00113 * Callback [I] Callback function to execute when the wait times out or the handle is signaled. 00114 * Context [I] Context to pass to the callback function when it is executed. 00115 * Milliseconds [I] Number of milliseconds to wait before timing out. 00116 * Flags [I] Flags. See notes. 00117 * 00118 * RETURNS 00119 * Success: STATUS_SUCCESS. 00120 * Failure: Any NTSTATUS code. 00121 * 00122 * NOTES 00123 * Flags can be one or more of the following: 00124 *|WT_EXECUTEDEFAULT - Executes the work item in a non-I/O worker thread. 00125 *|WT_EXECUTEINIOTHREAD - Executes the work item in an I/O worker thread. 00126 *|WT_EXECUTEINPERSISTENTTHREAD - Executes the work item in a thread that is persistent. 00127 *|WT_EXECUTELONGFUNCTION - Hints that the execution can take a long time. 00128 *|WT_TRANSFER_IMPERSONATION - Executes the function with the current access token. 00129 */ 00130 NTSTATUS 00131 NTAPI 00132 RtlRegisterWait(PHANDLE NewWaitObject, 00133 HANDLE Object, 00134 WAITORTIMERCALLBACKFUNC Callback, 00135 PVOID Context, 00136 ULONG Milliseconds, 00137 ULONG Flags) 00138 { 00139 PRTLP_WAIT Wait; 00140 NTSTATUS Status; 00141 00142 //TRACE( "(%p, %p, %p, %p, %d, 0x%x)\n", NewWaitObject, Object, Callback, Context, Milliseconds, Flags ); 00143 00144 Wait = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(RTLP_WAIT) ); 00145 if (!Wait) 00146 return STATUS_NO_MEMORY; 00147 00148 Wait->Object = Object; 00149 Wait->Callback = Callback; 00150 Wait->Context = Context; 00151 Wait->Milliseconds = Milliseconds; 00152 Wait->Flags = Flags; 00153 Wait->CallbackInProgress = FALSE; 00154 Wait->DeleteCount = 0; 00155 Wait->CompletionEvent = NULL; 00156 00157 Status = NtCreateEvent( &Wait->CancelEvent, 00158 EVENT_ALL_ACCESS, 00159 NULL, 00160 TRUE, 00161 FALSE ); 00162 00163 if (Status != STATUS_SUCCESS) 00164 { 00165 RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); 00166 return Status; 00167 } 00168 00169 Status = RtlQueueWorkItem( Wait_thread_proc, 00170 Wait, 00171 Flags & ~WT_EXECUTEONLYONCE ); 00172 00173 if (Status != STATUS_SUCCESS) 00174 { 00175 NtClose( Wait->CancelEvent ); 00176 RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); 00177 return Status; 00178 } 00179 00180 *NewWaitObject = Wait; 00181 return Status; 00182 } 00183 00184 /*********************************************************************** 00185 * RtlDeregisterWaitEx 00186 * 00187 * Cancels a wait operation and frees the resources associated with calling 00188 * RtlRegisterWait(). 00189 * 00190 * PARAMS 00191 * WaitObject [I] Handle to the wait object to free. 00192 * 00193 * RETURNS 00194 * Success: STATUS_SUCCESS. 00195 * Failure: Any NTSTATUS code. 00196 */ 00197 NTSTATUS 00198 NTAPI 00199 RtlDeregisterWaitEx(HANDLE WaitHandle, 00200 HANDLE CompletionEvent) 00201 { 00202 PRTLP_WAIT Wait = (PRTLP_WAIT) WaitHandle; 00203 NTSTATUS Status = STATUS_SUCCESS; 00204 00205 //TRACE( "(%p)\n", WaitHandle ); 00206 00207 NtSetEvent( Wait->CancelEvent, NULL ); 00208 if (Wait->CallbackInProgress) 00209 { 00210 if (CompletionEvent != NULL) 00211 { 00212 if (CompletionEvent == INVALID_HANDLE_VALUE) 00213 { 00214 Status = NtCreateEvent( &CompletionEvent, 00215 EVENT_ALL_ACCESS, 00216 NULL, 00217 TRUE, 00218 FALSE ); 00219 00220 if (Status != STATUS_SUCCESS) 00221 return Status; 00222 00223 (void)InterlockedExchangePointer( &Wait->CompletionEvent, CompletionEvent ); 00224 00225 if (Wait->CallbackInProgress) 00226 NtWaitForSingleObject( CompletionEvent, FALSE, NULL ); 00227 00228 NtClose( CompletionEvent ); 00229 } 00230 else 00231 { 00232 (void)InterlockedExchangePointer( &Wait->CompletionEvent, CompletionEvent ); 00233 00234 if (Wait->CallbackInProgress) 00235 Status = STATUS_PENDING; 00236 } 00237 } 00238 else 00239 Status = STATUS_PENDING; 00240 } 00241 00242 if (InterlockedIncrement( &Wait->DeleteCount ) == 2 ) 00243 { 00244 Status = STATUS_SUCCESS; 00245 NtClose( Wait->CancelEvent ); 00246 RtlFreeHeap( RtlGetProcessHeap(), 0, Wait ); 00247 } 00248 00249 return Status; 00250 } 00251 00252 /*********************************************************************** 00253 * RtlDeregisterWait 00254 * 00255 * Cancels a wait operation and frees the resources associated with calling 00256 * RtlRegisterWait(). 00257 * 00258 * PARAMS 00259 * WaitObject [I] Handle to the wait object to free. 00260 * 00261 * RETURNS 00262 * Success: STATUS_SUCCESS. 00263 * Failure: Any NTSTATUS code. 00264 */ 00265 NTSTATUS 00266 NTAPI 00267 RtlDeregisterWait(HANDLE WaitHandle) 00268 { 00269 return RtlDeregisterWaitEx(WaitHandle, NULL); 00270 } 00271 00272 /* EOF */ Generated on Sun May 27 2012 04:28:08 for ReactOS by
1.7.6.1
|