11 static LIST_ENTRY ThreadListHead
;
12 static KSPIN_LOCK ThreadListLock
;
14 KEVENT TerminationEvent
;
15 NPAGED_LOOKASIDE_LIST MessageLookasideList
;
16 NPAGED_LOOKASIDE_LIST QueueEntryLookasideList
;
18 static LARGE_INTEGER StartTime
;
20 typedef struct _thread_t
23 void (* ThreadFunction
)(void *arg
);
30 LARGE_INTEGER CurrentTime
;
32 KeQuerySystemTime(&CurrentTime
);
34 return (CurrentTime
.QuadPart
- StartTime
.QuadPart
) / 10000;
38 sys_arch_protect(sys_prot_t
*lev
)
40 /* Preempt the dispatcher */
41 KeRaiseIrql(DISPATCH_LEVEL
, lev
);
45 sys_arch_unprotect(sys_prot_t lev
)
51 sys_sem_new(sys_sem_t
*sem
, u8_t count
)
53 ASSERT(count
== 0 || count
== 1);
55 /* It seems lwIP uses the semaphore implementation as either a completion event or a lock
56 * so I optimize for this case by using a synchronization event and setting its initial state
57 * to signalled for a lock and non-signalled for a completion event */
59 KeInitializeEvent(&sem
->Event
, SynchronizationEvent
, count
);
66 int sys_sem_valid(sys_sem_t
*sem
)
71 void sys_sem_set_invalid(sys_sem_t
*sem
)
77 sys_sem_free(sys_sem_t
* sem
)
79 /* No op (allocated in stack) */
81 sys_sem_set_invalid(sem
);
85 sys_sem_signal(sys_sem_t
* sem
)
87 KeSetEvent(&sem
->Event
, IO_NO_INCREMENT
, FALSE
);
91 sys_arch_sem_wait(sys_sem_t
* sem
, u32_t timeout
)
93 LARGE_INTEGER LargeTimeout
, PreWaitTime
, PostWaitTime
;
96 PVOID WaitObjects
[] = {&sem
->Event
, &TerminationEvent
};
98 LargeTimeout
.QuadPart
= Int32x32To64(timeout
, -10000);
100 KeQuerySystemTime(&PreWaitTime
);
102 Status
= KeWaitForMultipleObjects(2,
108 timeout
!= 0 ? &LargeTimeout
: NULL
,
110 if (Status
== STATUS_WAIT_0
)
112 KeQuerySystemTime(&PostWaitTime
);
113 TimeDiff
= PostWaitTime
.QuadPart
- PreWaitTime
.QuadPart
;
118 else if (Status
== STATUS_WAIT_1
)
120 /* DON'T remove ourselves from the thread list! */
121 PsTerminateSystemThread(STATUS_SUCCESS
);
123 /* We should never get here! */
129 return SYS_ARCH_TIMEOUT
;
133 sys_mbox_new(sys_mbox_t
*mbox
, int size
)
135 KeInitializeSpinLock(&mbox
->Lock
);
137 InitializeListHead(&mbox
->ListHead
);
139 KeInitializeEvent(&mbox
->Event
, NotificationEvent
, FALSE
);
146 int sys_mbox_valid(sys_mbox_t
*mbox
)
151 void sys_mbox_set_invalid(sys_mbox_t
*mbox
)
157 sys_mbox_free(sys_mbox_t
*mbox
)
159 ASSERT(IsListEmpty(&mbox
->ListHead
));
161 sys_mbox_set_invalid(mbox
);
165 sys_mbox_post(sys_mbox_t
*mbox
, void *msg
)
167 PLWIP_MESSAGE_CONTAINER Container
;
169 Container
= ExAllocatePool(NonPagedPool
, sizeof(*Container
));
172 Container
->Message
= msg
;
174 ExInterlockedInsertTailList(&mbox
->ListHead
,
175 &Container
->ListEntry
,
178 KeSetEvent(&mbox
->Event
, IO_NO_INCREMENT
, FALSE
);
182 sys_arch_mbox_fetch(sys_mbox_t
*mbox
, void **msg
, u32_t timeout
)
184 LARGE_INTEGER LargeTimeout
, PreWaitTime
, PostWaitTime
;
188 PLWIP_MESSAGE_CONTAINER Container
;
191 PVOID WaitObjects
[] = {&mbox
->Event
, &TerminationEvent
};
193 LargeTimeout
.QuadPart
= Int32x32To64(timeout
, -10000);
195 KeQuerySystemTime(&PreWaitTime
);
197 Status
= KeWaitForMultipleObjects(2,
203 timeout
!= 0 ? &LargeTimeout
: NULL
,
206 if (Status
== STATUS_WAIT_0
)
208 KeAcquireSpinLock(&mbox
->Lock
, &OldIrql
);
209 Entry
= RemoveHeadList(&mbox
->ListHead
);
211 if (IsListEmpty(&mbox
->ListHead
))
212 KeClearEvent(&mbox
->Event
);
213 KeReleaseSpinLock(&mbox
->Lock
, OldIrql
);
215 Container
= CONTAINING_RECORD(Entry
, LWIP_MESSAGE_CONTAINER
, ListEntry
);
216 Message
= Container
->Message
;
217 ExFreePool(Container
);
222 KeQuerySystemTime(&PostWaitTime
);
223 TimeDiff
= PostWaitTime
.QuadPart
- PreWaitTime
.QuadPart
;
228 else if (Status
== STATUS_WAIT_1
)
230 /* DON'T remove ourselves from the thread list! */
231 PsTerminateSystemThread(STATUS_SUCCESS
);
233 /* We should never get here! */
239 return SYS_ARCH_TIMEOUT
;
243 sys_arch_mbox_tryfetch(sys_mbox_t
*mbox
, void **msg
)
245 if (sys_arch_mbox_fetch(mbox
, msg
, 1) != SYS_ARCH_TIMEOUT
)
248 return SYS_MBOX_EMPTY
;
252 sys_mbox_trypost(sys_mbox_t
*mbox
, void *msg
)
254 sys_mbox_post(mbox
, msg
);
261 LwipThreadMain(PVOID Context
)
263 thread_t Container
= (thread_t
)Context
;
266 ExInterlockedInsertHeadList(&ThreadListHead
, &Container
->ListEntry
, &ThreadListLock
);
268 Container
->ThreadFunction(Container
->ThreadContext
);
270 KeAcquireSpinLock(&ThreadListLock
, &OldIrql
);
271 RemoveEntryList(&Container
->ListEntry
);
272 KeReleaseSpinLock(&ThreadListLock
, OldIrql
);
274 ExFreePool(Container
);
276 PsTerminateSystemThread(STATUS_SUCCESS
);
280 sys_thread_new(const char *name
, lwip_thread_fn thread
, void *arg
, int stacksize
, int prio
)
285 Container
= ExAllocatePool(NonPagedPool
, sizeof(*Container
));
289 Container
->ThreadFunction
= thread
;
290 Container
->ThreadContext
= arg
;
292 Status
= PsCreateSystemThread(&Container
->Handle
,
300 if (!NT_SUCCESS(Status
))
302 ExFreePool(Container
);
312 KeInitializeSpinLock(&ThreadListLock
);
313 InitializeListHead(&ThreadListHead
);
315 KeQuerySystemTime(&StartTime
);
317 KeInitializeEvent(&TerminationEvent
, NotificationEvent
, FALSE
);
319 ExInitializeNPagedLookasideList(&MessageLookasideList
,
323 sizeof(struct lwip_callback_msg
),
327 ExInitializeNPagedLookasideList(&QueueEntryLookasideList
,
339 PLIST_ENTRY CurrentEntry
;
342 /* Set the termination event */
343 KeSetEvent(&TerminationEvent
, IO_NO_INCREMENT
, FALSE
);
345 /* Loop through the thread list and wait for each to die */
346 while ((CurrentEntry
= ExInterlockedRemoveHeadList(&ThreadListHead
, &ThreadListLock
)))
348 Container
= CONTAINING_RECORD(CurrentEntry
, struct _thread_t
, ListEntry
);
350 if (Container
->ThreadFunction
)
352 KeWaitForSingleObject(Container
->Handle
,
358 ZwClose(Container
->Handle
);
362 ExDeleteNPagedLookasideList(&MessageLookasideList
);
363 ExDeleteNPagedLookasideList(&QueueEntryLookasideList
);