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 CSR Sub System 00004 * FILE: subsys/csr/csrsrv/wait.c 00005 * PURPOSE: CSR Server DLL Wait Implementation 00006 * PROGRAMMERS: Emanuele Aliberti 00007 * Alex Ionescu (alex@relsoft.net) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include "srv.h" 00013 00014 #define NDEBUG 00015 #include <debug.h> 00016 00017 /* DATA **********************************************************************/ 00018 00019 RTL_CRITICAL_SECTION CsrWaitListsLock; 00020 00021 /* PRIVATE FUNCTIONS *********************************************************/ 00022 00023 /*++ 00024 * @name CsrInitializeWait 00025 * 00026 * The CsrInitializeWait routine initializes a CSR Wait Object. 00027 * 00028 * @param WaitFunction 00029 * Pointer to the function that will handle this wait. 00030 * 00031 * @param CsrWaitThread 00032 * Pointer to the CSR Thread that will perform the wait. 00033 * 00034 * @param WaitApiMessage 00035 * Pointer to the CSR API Message associated to this wait. 00036 * 00037 * @param WaitContext 00038 * Pointer to a user-defined parameter associated to this wait. 00039 * 00040 * @param NewWaitBlock 00041 * Pointed to the initialized CSR Wait Block for this wait. 00042 * 00043 * @return TRUE in case of success, FALSE othwerwise. 00044 * 00045 * @remarks None. 00046 * 00047 *--*/ 00048 BOOLEAN 00049 NTAPI 00050 CsrInitializeWait(IN CSR_WAIT_FUNCTION WaitFunction, 00051 IN PCSR_THREAD CsrWaitThread, 00052 IN OUT PCSR_API_MESSAGE WaitApiMessage, 00053 IN PVOID WaitContext, 00054 OUT PCSR_WAIT_BLOCK *NewWaitBlock) 00055 { 00056 ULONG Size; 00057 PCSR_WAIT_BLOCK WaitBlock; 00058 00059 /* Calculate the size of the wait block */ 00060 Size = sizeof(CSR_WAIT_BLOCK) - 00061 sizeof(WaitBlock->WaitApiMessage) + 00062 WaitApiMessage->Header.u1.s1.TotalLength; 00063 00064 /* Allocate the Wait Block */ 00065 WaitBlock = RtlAllocateHeap(CsrHeap, 0, Size); 00066 if (!WaitBlock) 00067 { 00068 /* Fail */ 00069 WaitApiMessage->Status = STATUS_NO_MEMORY; 00070 return FALSE; 00071 } 00072 00073 /* Initialize it */ 00074 WaitBlock->Size = Size; 00075 WaitBlock->WaitThread = CsrWaitThread; 00076 WaitBlock->WaitContext = WaitContext; 00077 WaitBlock->WaitFunction = WaitFunction; 00078 WaitBlock->UserWaitList.Flink = NULL; 00079 WaitBlock->UserWaitList.Blink = NULL; 00080 WaitBlock->WaitList = WaitBlock->UserWaitList; 00081 00082 /* Copy the message */ 00083 RtlMoveMemory(&WaitBlock->WaitApiMessage, 00084 WaitApiMessage, 00085 WaitApiMessage->Header.u1.s1.TotalLength); 00086 00087 /* Return the block */ 00088 *NewWaitBlock = WaitBlock; 00089 return TRUE; 00090 } 00091 00092 /*++ 00093 * @name CsrNotifyWaitBlock 00094 * 00095 * The CsrNotifyWaitBlock routine calls the wait function for a registered 00096 * CSR Wait Block, and replies to the attached CSR API Message, if any. 00097 * 00098 * @param WaitBlock 00099 * Pointer to the CSR Wait Block 00100 * 00101 * @param WaitList 00102 * Pointer to the wait list for this wait. 00103 * 00104 * @param WaitArgument[1-2] 00105 * User-defined values to pass to the wait function. 00106 * 00107 * @param WaitFlags 00108 * Wait flags for this wait. 00109 * 00110 * @param DereferenceThread 00111 * Specifies whether the CSR Thread should be dereferenced at the 00112 * end of this wait. 00113 * 00114 * @return TRUE in case of success, FALSE otherwise. 00115 * 00116 * @remarks After a wait block is notified, the wait function becomes invalid. 00117 * 00118 *--*/ 00119 BOOLEAN 00120 NTAPI 00121 CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock, 00122 IN PLIST_ENTRY WaitList, 00123 IN PVOID WaitArgument1, 00124 IN PVOID WaitArgument2, 00125 IN ULONG WaitFlags, 00126 IN BOOLEAN DereferenceThread) 00127 { 00128 /* Call the wait function */ 00129 if ((WaitBlock->WaitFunction)(WaitList, 00130 WaitBlock->WaitThread, 00131 &WaitBlock->WaitApiMessage, 00132 WaitBlock->WaitContext, 00133 WaitArgument1, 00134 WaitArgument2, 00135 WaitFlags)) 00136 { 00137 /* The wait is done, clear the block */ 00138 WaitBlock->WaitThread->WaitBlock = NULL; 00139 00140 /* Check for captured arguments */ 00141 if (WaitBlock->WaitApiMessage.CsrCaptureData) 00142 { 00143 /* Release them */ 00144 CsrReleaseCapturedArguments(&WaitBlock->WaitApiMessage); 00145 } 00146 00147 /* Reply to the port */ 00148 NtReplyPort(WaitBlock->WaitThread->Process->ClientPort, 00149 (PPORT_MESSAGE)&WaitBlock->WaitApiMessage); 00150 00151 /* Check if we should dereference the thread */ 00152 if (DereferenceThread) 00153 { 00154 /* Remove it from the Wait List */ 00155 if (WaitBlock->WaitList.Flink) 00156 { 00157 RemoveEntryList(&WaitBlock->WaitList); 00158 } 00159 00160 /* Remove it from the User Wait List */ 00161 if (WaitBlock->UserWaitList.Flink) 00162 { 00163 RemoveEntryList(&WaitBlock->UserWaitList); 00164 } 00165 00166 /* Dereference teh thread */ 00167 CsrDereferenceThread(WaitBlock->WaitThread); 00168 00169 /* Free the wait block */ 00170 RtlFreeHeap(CsrHeap, 0, WaitBlock); 00171 } 00172 else 00173 { 00174 /* The wait is complete, but the thread is being kept alive */ 00175 WaitBlock->WaitFunction = NULL; 00176 } 00177 00178 /* The wait suceeded */ 00179 return TRUE; 00180 } 00181 00182 /* The wait failed */ 00183 return FALSE; 00184 } 00185 00186 /* PUBLIC FUNCTIONS **********************************************************/ 00187 00188 /*++ 00189 * @name CsrCreateWait 00190 * @implemented NT4 00191 * 00192 * The CsrCreateWait routine creates a CSR Wait. 00193 * 00194 * @param WaitList 00195 * Pointer to a list entry of the waits to associate. 00196 * 00197 * @param WaitFunction 00198 * Pointer to the function that will handle this wait. 00199 * 00200 * @param CsrWaitThread 00201 * Pointer to the CSR Thread that will perform the wait. 00202 * 00203 * @param WaitApiMessage 00204 * Pointer to the CSR API Message associated to this wait. 00205 * 00206 * @param WaitContext 00207 * Pointer to a user-defined parameter associated to this wait. 00208 * 00209 * @param UserWaitList 00210 * Pointer to a list entry of the user-defined waits to associate. 00211 * 00212 * @return TRUE in case of success, FALSE otherwise. 00213 * 00214 * @remarks None. 00215 * 00216 *--*/ 00217 BOOLEAN 00218 NTAPI 00219 CsrCreateWait(IN PLIST_ENTRY WaitList, 00220 IN CSR_WAIT_FUNCTION WaitFunction, 00221 IN PCSR_THREAD CsrWaitThread, 00222 IN OUT PCSR_API_MESSAGE WaitApiMessage, 00223 IN PVOID WaitContext, 00224 IN PLIST_ENTRY UserWaitList OPTIONAL) 00225 { 00226 PCSR_WAIT_BLOCK WaitBlock; 00227 00228 /* Initialize the wait */ 00229 if (!CsrInitializeWait(WaitFunction, 00230 CsrWaitThread, 00231 WaitApiMessage, 00232 WaitContext, 00233 &WaitBlock)) 00234 { 00235 return FALSE; 00236 } 00237 00238 /* Acquire the Wait Lock */ 00239 CsrAcquireWaitLock(); 00240 00241 /* Make sure the thread wasn't destroyed */ 00242 if (CsrWaitThread->Flags & CsrThreadTerminated) 00243 { 00244 /* Fail the wait */ 00245 RtlFreeHeap(CsrHeap, 0, WaitBlock); 00246 CsrReleaseWaitLock(); 00247 return FALSE; 00248 } 00249 00250 /* Insert the wait in the queue */ 00251 InsertTailList(WaitList, &WaitBlock->WaitList); 00252 00253 /* Insert the User Wait too, if one was given */ 00254 if (UserWaitList) InsertTailList(UserWaitList, &WaitBlock->UserWaitList); 00255 00256 /* Return */ 00257 CsrReleaseWaitLock(); 00258 return TRUE; 00259 } 00260 00261 /*++ 00262 * @name CsrDereferenceWait 00263 * @implemented NT4 00264 * 00265 * The CsrDereferenceWait routine derefences a CSR Wait Block. 00266 * 00267 * @param WaitList 00268 * Pointer to the Wait List associated to the wait. 00269 00270 * @return None. 00271 * 00272 * @remarks None. 00273 * 00274 *--*/ 00275 VOID 00276 NTAPI 00277 CsrDereferenceWait(IN PLIST_ENTRY WaitList) 00278 { 00279 PLIST_ENTRY NextEntry; 00280 PCSR_WAIT_BLOCK WaitBlock; 00281 00282 /* Acquire the Process and Wait Locks */ 00283 CsrAcquireProcessLock(); 00284 CsrAcquireWaitLock(); 00285 00286 /* Set the list pointers */ 00287 NextEntry = WaitList->Flink; 00288 00289 /* Start the loop */ 00290 while (NextEntry != WaitList) 00291 { 00292 /* Get the wait block */ 00293 WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList); 00294 00295 /* Move to the next entry */ 00296 NextEntry = NextEntry->Flink; 00297 00298 /* Check if there's no Wait Routine */ 00299 if (!WaitBlock->WaitFunction) 00300 { 00301 /* Remove it from the Wait List */ 00302 if (WaitBlock->WaitList.Flink) 00303 { 00304 RemoveEntryList(&WaitBlock->WaitList); 00305 } 00306 00307 /* Remove it from the User Wait List */ 00308 if (WaitBlock->UserWaitList.Flink) 00309 { 00310 RemoveEntryList(&WaitBlock->UserWaitList); 00311 } 00312 00313 /* Dereference the thread waiting on it */ 00314 CsrDereferenceThread(WaitBlock->WaitThread); 00315 00316 /* Free the block */ 00317 RtlFreeHeap(CsrHeap, 0, WaitBlock); 00318 } 00319 } 00320 00321 /* Release the locks */ 00322 CsrReleaseWaitLock(); 00323 CsrReleaseProcessLock(); 00324 } 00325 00326 /*++ 00327 * @name CsrMoveSatisfiedWait 00328 * @implemented NT5 00329 * 00330 * The CsrMoveSatisfiedWait routine moves satisfied waits from a wait list 00331 * to another list entry. 00332 * 00333 * @param NewEntry 00334 * Pointer to a list entry where the satisfied waits will be added. 00335 * 00336 * @param WaitList 00337 * Pointer to a list entry to analyze for satisfied waits. 00338 * 00339 * @return None. 00340 * 00341 * @remarks None. 00342 * 00343 *--*/ 00344 VOID 00345 NTAPI 00346 CsrMoveSatisfiedWait(IN PLIST_ENTRY NewEntry, 00347 IN PLIST_ENTRY WaitList) 00348 { 00349 PLIST_ENTRY NextEntry; 00350 PCSR_WAIT_BLOCK WaitBlock; 00351 00352 /* Acquire the Wait Lock */ 00353 CsrAcquireWaitLock(); 00354 00355 /* Set the List pointers */ 00356 NextEntry = WaitList->Flink; 00357 00358 /* Start looping */ 00359 while (NextEntry != WaitList) 00360 { 00361 /* Get the Wait block */ 00362 WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList); 00363 00364 /* Go to the next entry */ 00365 NextEntry = NextEntry->Flink; 00366 00367 /* Check if there is a Wait Callback */ 00368 if (WaitBlock->WaitFunction) 00369 { 00370 /* Remove it from the Wait Block Queue */ 00371 RemoveEntryList(&WaitBlock->WaitList); 00372 00373 /* Insert the new entry */ 00374 InsertTailList(&WaitBlock->WaitList, NewEntry); 00375 } 00376 } 00377 00378 /* Release the wait lock */ 00379 CsrReleaseWaitLock(); 00380 } 00381 00382 /*++ 00383 * @name CsrNotifyWait 00384 * @implemented NT4 00385 * 00386 * The CsrNotifyWait notifies a CSR Wait Block. 00387 * 00388 * @param WaitList 00389 * Pointer to the list entry for this wait. 00390 * 00391 * @param WaitType 00392 * Type of the wait to perform, either WaitAny or WaitAll. 00393 * 00394 * @param WaitArgument[1-2] 00395 * User-defined argument to pass on to the wait function. 00396 * 00397 * @return TRUE in case of success, FALSE othwerwise. 00398 * 00399 * @remarks None. 00400 * 00401 *--*/ 00402 BOOLEAN 00403 NTAPI 00404 CsrNotifyWait(IN PLIST_ENTRY WaitList, 00405 IN ULONG WaitType, 00406 IN PVOID WaitArgument1, 00407 IN PVOID WaitArgument2) 00408 { 00409 PLIST_ENTRY NextEntry; 00410 PCSR_WAIT_BLOCK WaitBlock; 00411 BOOLEAN NotifySuccess = FALSE; 00412 00413 /* Acquire the Wait Lock */ 00414 CsrAcquireWaitLock(); 00415 00416 /* Set the List pointers */ 00417 NextEntry = WaitList->Flink; 00418 00419 /* Start looping */ 00420 while (NextEntry != WaitList) 00421 { 00422 /* Get the Wait block */ 00423 WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList); 00424 00425 /* Go to the next entry */ 00426 NextEntry = NextEntry->Flink; 00427 00428 /* Check if there is a Wait Callback */ 00429 if (WaitBlock->WaitFunction) 00430 { 00431 /* Notify the Waiter */ 00432 NotifySuccess |= CsrNotifyWaitBlock(WaitBlock, 00433 WaitList, 00434 WaitArgument1, 00435 WaitArgument2, 00436 0, 00437 FALSE); 00438 00439 /* We've already done a wait, so leave unless this is a Wait All */ 00440 if (WaitType != WaitAll) break; 00441 } 00442 } 00443 00444 /* Release the wait lock and return */ 00445 CsrReleaseWaitLock(); 00446 return NotifySuccess; 00447 } 00448 00449 /* EOF */ Generated on Sun May 27 2012 04:28:08 for ReactOS by
1.7.6.1
|