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

sys_arch.c
Go to the documentation of this file.
00001 #include "lwip/sys.h"
00002 
00003 #include "lwip/tcp.h"
00004 #include "lwip/pbuf.h"
00005 #include "lwip/err.h"
00006 
00007 #include "rosip.h"
00008 
00009 #include <debug.h>
00010 
00011 static LIST_ENTRY ThreadListHead;
00012 static KSPIN_LOCK ThreadListLock;
00013 
00014 KEVENT TerminationEvent;
00015 NPAGED_LOOKASIDE_LIST MessageLookasideList;
00016 NPAGED_LOOKASIDE_LIST QueueEntryLookasideList;
00017 
00018 static LARGE_INTEGER StartTime;
00019 
00020 typedef struct _thread_t
00021 {
00022     HANDLE Handle;
00023     void (* ThreadFunction)(void *arg);
00024     void *ThreadContext;
00025     LIST_ENTRY ListEntry;
00026 } *thread_t;
00027 
00028 u32_t sys_now(void)
00029 {
00030     LARGE_INTEGER CurrentTime;
00031     
00032     KeQuerySystemTime(&CurrentTime);
00033     
00034     return (CurrentTime.QuadPart - StartTime.QuadPart) / 10000;
00035 }
00036 
00037 void
00038 sys_arch_protect(sys_prot_t *lev)
00039 {
00040     /* Preempt the dispatcher */
00041     KeRaiseIrql(DISPATCH_LEVEL, lev);
00042 }
00043 
00044 void
00045 sys_arch_unprotect(sys_prot_t lev)
00046 {
00047     KeLowerIrql(lev);
00048 }
00049 
00050 err_t
00051 sys_sem_new(sys_sem_t *sem, u8_t count)
00052 {
00053     ASSERT(count == 0 || count == 1);
00054     
00055     /* It seems lwIP uses the semaphore implementation as either a completion event or a lock
00056      * so I optimize for this case by using a synchronization event and setting its initial state
00057      * to signalled for a lock and non-signalled for a completion event */
00058 
00059     KeInitializeEvent(&sem->Event, SynchronizationEvent, count);
00060     
00061     sem->Valid = 1;
00062     
00063     return ERR_OK;
00064 }
00065 
00066 int sys_sem_valid(sys_sem_t *sem)
00067 {
00068     return sem->Valid;
00069 }
00070 
00071 void sys_sem_set_invalid(sys_sem_t *sem)
00072 {
00073     sem->Valid = 0;
00074 }
00075 
00076 void
00077 sys_sem_free(sys_sem_t* sem)
00078 {
00079     /* No op (allocated in stack) */
00080     
00081     sys_sem_set_invalid(sem);
00082 }
00083 
00084 void
00085 sys_sem_signal(sys_sem_t* sem)
00086 {
00087     KeSetEvent(&sem->Event, IO_NO_INCREMENT, FALSE);
00088 }
00089 
00090 u32_t
00091 sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout)
00092 {
00093     LARGE_INTEGER LargeTimeout, PreWaitTime, PostWaitTime;
00094     UINT64 TimeDiff;
00095     NTSTATUS Status;
00096     PVOID WaitObjects[] = {&sem->Event, &TerminationEvent};
00097 
00098     LargeTimeout.QuadPart = Int32x32To64(timeout, -10000);
00099     
00100     KeQuerySystemTime(&PreWaitTime);
00101 
00102     Status = KeWaitForMultipleObjects(2,
00103                                       WaitObjects,
00104                                       WaitAny,
00105                                       Executive,
00106                                       KernelMode,
00107                                       FALSE,
00108                                       timeout != 0 ? &LargeTimeout : NULL,
00109                                       NULL);
00110     if (Status == STATUS_WAIT_0)
00111     {
00112         KeQuerySystemTime(&PostWaitTime);
00113         TimeDiff = PostWaitTime.QuadPart - PreWaitTime.QuadPart;
00114         TimeDiff /= 10000;
00115 
00116         return TimeDiff;
00117     }
00118     else if (Status == STATUS_WAIT_1)
00119     {
00120         /* DON'T remove ourselves from the thread list! */
00121         PsTerminateSystemThread(STATUS_SUCCESS);
00122         
00123         /* We should never get here! */
00124         ASSERT(FALSE);
00125         
00126         return 0;
00127     }
00128     
00129     return SYS_ARCH_TIMEOUT;
00130 }
00131 
00132 err_t
00133 sys_mbox_new(sys_mbox_t *mbox, int size)
00134 {    
00135     KeInitializeSpinLock(&mbox->Lock);
00136     
00137     InitializeListHead(&mbox->ListHead);
00138     
00139     KeInitializeEvent(&mbox->Event, NotificationEvent, FALSE);
00140     
00141     mbox->Valid = 1;
00142     
00143     return ERR_OK;
00144 }
00145 
00146 int sys_mbox_valid(sys_mbox_t *mbox)
00147 {
00148     return mbox->Valid;
00149 }
00150 
00151 void sys_mbox_set_invalid(sys_mbox_t *mbox)
00152 {
00153     mbox->Valid = 0;
00154 }
00155 
00156 void
00157 sys_mbox_free(sys_mbox_t *mbox)
00158 {
00159     ASSERT(IsListEmpty(&mbox->ListHead));
00160     
00161     sys_mbox_set_invalid(mbox);
00162 }
00163 
00164 void
00165 sys_mbox_post(sys_mbox_t *mbox, void *msg)
00166 {
00167     PLWIP_MESSAGE_CONTAINER Container;
00168     
00169     Container = ExAllocatePool(NonPagedPool, sizeof(*Container));
00170     ASSERT(Container);
00171     
00172     Container->Message = msg;
00173     
00174     ExInterlockedInsertTailList(&mbox->ListHead,
00175                                 &Container->ListEntry,
00176                                 &mbox->Lock);
00177     
00178     KeSetEvent(&mbox->Event, IO_NO_INCREMENT, FALSE);
00179 }
00180 
00181 u32_t
00182 sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
00183 {
00184     LARGE_INTEGER LargeTimeout, PreWaitTime, PostWaitTime;
00185     UINT64 TimeDiff;
00186     NTSTATUS Status;
00187     PVOID Message;
00188     PLWIP_MESSAGE_CONTAINER Container;
00189     PLIST_ENTRY Entry;
00190     KIRQL OldIrql;
00191     PVOID WaitObjects[] = {&mbox->Event, &TerminationEvent};
00192     
00193     LargeTimeout.QuadPart = Int32x32To64(timeout, -10000);
00194     
00195     KeQuerySystemTime(&PreWaitTime);
00196 
00197     Status = KeWaitForMultipleObjects(2,
00198                                       WaitObjects,
00199                                       WaitAny,
00200                                       Executive,
00201                                       KernelMode,
00202                                       FALSE,
00203                                       timeout != 0 ? &LargeTimeout : NULL,
00204                                       NULL);
00205 
00206     if (Status == STATUS_WAIT_0)
00207     {
00208         KeAcquireSpinLock(&mbox->Lock, &OldIrql);
00209         Entry = RemoveHeadList(&mbox->ListHead);
00210         ASSERT(Entry);
00211         if (IsListEmpty(&mbox->ListHead))
00212             KeClearEvent(&mbox->Event);
00213         KeReleaseSpinLock(&mbox->Lock, OldIrql);
00214         
00215         Container = CONTAINING_RECORD(Entry, LWIP_MESSAGE_CONTAINER, ListEntry);
00216         Message = Container->Message;
00217         ExFreePool(Container);
00218         
00219         if (msg)
00220             *msg = Message;
00221 
00222         KeQuerySystemTime(&PostWaitTime);
00223         TimeDiff = PostWaitTime.QuadPart - PreWaitTime.QuadPart;
00224         TimeDiff /= 10000;
00225         
00226         return TimeDiff;
00227     }
00228     else if (Status == STATUS_WAIT_1)
00229     {
00230         /* DON'T remove ourselves from the thread list! */
00231         PsTerminateSystemThread(STATUS_SUCCESS);
00232         
00233         /* We should never get here! */
00234         ASSERT(FALSE);
00235         
00236         return 0;
00237     }
00238     
00239     return SYS_ARCH_TIMEOUT;
00240 }
00241 
00242 u32_t
00243 sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
00244 {
00245     if (sys_arch_mbox_fetch(mbox, msg, 1) != SYS_ARCH_TIMEOUT)
00246         return 0;
00247     else
00248         return SYS_MBOX_EMPTY;
00249 }
00250 
00251 err_t
00252 sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
00253 {
00254     sys_mbox_post(mbox, msg);
00255 
00256     return ERR_OK;
00257 }
00258 
00259 VOID
00260 NTAPI
00261 LwipThreadMain(PVOID Context)
00262 {
00263     thread_t Container = (thread_t)Context;
00264     KIRQL OldIrql;
00265     
00266     ExInterlockedInsertHeadList(&ThreadListHead, &Container->ListEntry, &ThreadListLock);
00267     
00268     Container->ThreadFunction(Container->ThreadContext);
00269     
00270     KeAcquireSpinLock(&ThreadListLock, &OldIrql);
00271     RemoveEntryList(&Container->ListEntry);
00272     KeReleaseSpinLock(&ThreadListLock, OldIrql);
00273     
00274     ExFreePool(Container);
00275     
00276     PsTerminateSystemThread(STATUS_SUCCESS);
00277 }
00278 
00279 sys_thread_t
00280 sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
00281 {
00282     thread_t Container;
00283     NTSTATUS Status;
00284 
00285     Container = ExAllocatePool(NonPagedPool, sizeof(*Container));
00286     if (!Container)
00287         return 0;
00288 
00289     Container->ThreadFunction = thread;
00290     Container->ThreadContext = arg;
00291 
00292     Status = PsCreateSystemThread(&Container->Handle,
00293                                   THREAD_ALL_ACCESS,
00294                                   NULL,
00295                                   NULL,
00296                                   NULL,
00297                                   LwipThreadMain,
00298                                   Container);
00299 
00300     if (!NT_SUCCESS(Status))
00301     {
00302         ExFreePool(Container);
00303         return 0;
00304     }
00305 
00306     return 0;
00307 }
00308 
00309 void
00310 sys_init(void)
00311 {   
00312     KeInitializeSpinLock(&ThreadListLock);
00313     InitializeListHead(&ThreadListHead);
00314     
00315     KeQuerySystemTime(&StartTime);
00316     
00317     KeInitializeEvent(&TerminationEvent, NotificationEvent, FALSE);
00318     
00319     ExInitializeNPagedLookasideList(&MessageLookasideList,
00320                                     NULL,
00321                                     NULL,
00322                                     0,
00323                                     sizeof(struct lwip_callback_msg),
00324                                     LWIP_TAG,
00325                                     0);
00326     
00327     ExInitializeNPagedLookasideList(&QueueEntryLookasideList,
00328                                     NULL,
00329                                     NULL,
00330                                     0,
00331                                     sizeof(QUEUE_ENTRY),
00332                                     LWIP_TAG,
00333                                     0);
00334 }
00335 
00336 void
00337 sys_shutdown(void)
00338 {
00339     PLIST_ENTRY CurrentEntry;
00340     thread_t Container;
00341     
00342     /* Set the termination event */
00343     KeSetEvent(&TerminationEvent, IO_NO_INCREMENT, FALSE);
00344     
00345     /* Loop through the thread list and wait for each to die */
00346     while ((CurrentEntry = ExInterlockedRemoveHeadList(&ThreadListHead, &ThreadListLock)))
00347     {
00348         Container = CONTAINING_RECORD(CurrentEntry, struct _thread_t, ListEntry);
00349         
00350         if (Container->ThreadFunction)
00351         {
00352             KeWaitForSingleObject(Container->Handle,
00353                                   Executive,
00354                                   KernelMode,
00355                                   FALSE,
00356                                   NULL);
00357             
00358             ZwClose(Container->Handle);
00359         }
00360     }
00361     
00362     ExDeleteNPagedLookasideList(&MessageLookasideList);
00363     ExDeleteNPagedLookasideList(&QueueEntryLookasideList);
00364 }

Generated on Sat May 26 2012 04:35:02 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.