Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensys_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
1.7.6.1
|