ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

wait.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.