#define NR_THREADS (0x5)
+
DWORD WINAPI
thread_main1(LPVOID param)
{
return 0;
}
+
DWORD WINAPI
thread_main2(LPVOID param)
{
return 0;
}
+
int main (void)
{
+ HANDLE hThread;
DWORD i=0;
DWORD id;
-
- printf("Creating %d threads...\n",NR_THREADS);
-// for (i=0;i<NR_THREADS;i++)
-// {
+
+#if 0
+ printf("Creating %d threads...\n",NR_THREADS*2);
+ for (i=0;i<NR_THREADS;i++)
+ {
CreateThread(NULL,
0,
- thread_main1,
- (LPVOID)i,
+ thread_main1,
+ (LPVOID)i,
0,
&id);
-#if 0
+
CreateThread(NULL,
0,
- thread_main2,
- (LPVOID)i,
+ thread_main2,
+ (LPVOID)i,
0,
&id);
}
-#endif
- printf("Threads created...\n");
-// Sleep (5000);
- SuspendThread (GetCurrentThread());
+ printf("All threads created...\n");
+
+ /*
+ * Waiting for threads is not implemented yet.
+ * If you want to see all threads running, uncomment the
+ * call to SuspendThread(). The test application will
+ * freeze after all threads are created.
+ */
+/* SuspendThread (GetCurrentThread()); */
+
+#else
+
+ printf("Creating thread...\n");
+
+ hThread = CreateThread(NULL,
+ 0,
+ thread_main1,
+ (LPVOID)i,
+ 0,
+ &id);
+
+ printf("Thread created. Waiting for termination...\n");
+
+ WaitForSingleObject (hThread,
+ -1);
+
+ CloseHandle (hThread);
+
+ printf("Thread terminated...\n");
+#endif
return 0;
}
#define ID_EVENT_OBJECT (ID_BASE_OBJECT + 5)
#define ID_TIMER_OBJECT (ID_BASE_OBJECT + 6)
#define ID_PROCESS_OBJECT (ID_BASE_OBJECT + 7)
+#define ID_THREAD_OBJECT (ID_BASE_OBJECT + 8)
/* FUNCTIONS *****************************************************************/
+static VOID STDCALL
+ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter)
+{
+ UINT uExitCode;
+
+ uExitCode = (lpStartAddress)(lpParameter);
+
+ NtTerminateThread(NtCurrentThread(),
+ uExitCode);
+}
+
+
HANDLE STDCALL CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
BOOLEAN CreateSuspended = FALSE;
PVOID BaseAddress;
DWORD StackSize;
- ULONG BytesWritten;
NTSTATUS Status;
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
DPRINT("Stack base address: %p\n", BaseAddress);
memset(&ThreadContext,0,sizeof(CONTEXT));
- ThreadContext.Eip = (LONG)lpStartAddress;
+// ThreadContext.Eip = (LONG)lpStartAddress;
+ ThreadContext.Eip = (LONG)ThreadStartup;
ThreadContext.SegGs = USER_DS;
ThreadContext.SegFs = USER_DS;
ThreadContext.SegEs = USER_DS;
ThreadContext.SegDs = USER_DS;
ThreadContext.SegCs = USER_CS;
ThreadContext.SegSs = USER_DS;
- ThreadContext.Esp = (ULONG)(BaseAddress + StackSize - 8);
+ ThreadContext.Esp = (ULONG)(BaseAddress + StackSize - 12);
ThreadContext.EFlags = (1<<1) + (1<<9);
- /* write lpParameter to highest stack address */
- *((PBYTE)(BaseAddress + StackSize - 4)) = lpParameter;
+ /* initialize call stack */
+ *((PULONG)(BaseAddress + StackSize - 4)) = (ULONG)lpParameter;
+ *((PULONG)(BaseAddress + StackSize - 8)) = (ULONG)lpStartAddress;
+ *((PULONG)(BaseAddress + StackSize - 12)) = 0xdeadbeef;
+
+ DPRINT("Esp: %p\n", ThreadContext.Esp);
+ DPRINT("Eip: %p\n", ThreadContext.Eip);
Status = NtCreateThread(&ThreadHandle,
THREAD_ALL_ACCESS,
LONG StackZeroBits,
PULONG StackReserved,
PULONG StackCommit,
- PVOID StartAddress,
- HANDLE DebugPort,
+ PTHREAD_START_ROUTINE StartAddress,
+ PVOID Parameter,
PHANDLE ThreadHandle,
PCLIENT_ID ClientId)
{
ObjectAttributes.SecurityQualityOfService = NULL;
+ if (*StackCommit < 4096)
+ *StackCommit = 4096;
+
BaseAddress = 0;
ZwAllocateVirtualMemory(ProcessHandle,
&BaseAddress,
NTSTATUS STDCALL
RtlInitializeContext(HANDLE ProcessHandle,
PCONTEXT Context,
- HANDLE DebugPort,
- PVOID StartAddress,
+ PVOID Parameter,
+ PTHREAD_START_ROUTINE StartAddress,
PINITIAL_TEB InitialTeb)
{
NTSTATUS Status;
Context->SegDs = USER_DS;
Context->SegCs = USER_CS;
Context->SegSs = USER_DS;
- Context->Esp = InitialTeb->StackBase - InitialTeb->StackCommit;
+ Context->Esp = (ULONG)InitialTeb->StackBase +
+ (DWORD)InitialTeb->StackCommit - 8;
Context->EFlags = (1<<1)+(1<<9);
+
+
+ /* copy Parameter to thread stack */
+ *((PULONG)(InitialTeb->StackBase + (DWORD)InitialTeb->StackCommit - 4))
+ = (DWORD)Parameter;
+
+
/* #endif */
Status = STATUS_SUCCESS;
case ID_PROCESS_OBJECT:
return(KeDispatcherObjectWakeAll(hdr));
+
+ case ID_THREAD_OBJECT:
+ return(KeDispatcherObjectWakeAll(hdr));
}
DbgPrint("Dispatcher object %x has unknown type\n",hdr);
KeBugCheck(0);
case ID_PROCESS_OBJECT:
break;
+
+ case ID_THREAD_OBJECT:
+ break;
case NotificationEvent:
break;
blk.Object=Object;
blk.Thread=KeGetCurrentThread();
blk.WaitKey = WaitReason; // Assumed
- blk.WaitType = WaitMode; // Assumed
+ blk.WaitType = WaitAll;
blk.NextWaitBlock = NULL;
InsertTailList(&(hdr->WaitListHead),&(blk.WaitListEntry));
// DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
PLARGE_INTEGER Timeout,
PKWAIT_BLOCK WaitBlockArray)
{
+#if 0
+ DISPATCHER_HEADER* hdr;
+ PKWAIT_BLOCK blk;
+ ULONG Counter;
+
+ DPRINT("Entering KeWaitForSingleObject(Object %x) "
+ "PsGetCurrentThread() %x\n",Object,PsGetCurrentThread());
+
+ KeAcquireDispatcherDatabaseLock(FALSE);
+
+ for (Counter = 0; Counter < Count; Counter++)
+ {
+ hdr = (DISPATCHER_HEADER *)Object[Counter];
+
+ DPRINT("hdr->SignalState %d\n", hdr->SignalState);
+
+ if (hdr->SignalState > 0)
+ {
+ switch (hdr->Type)
+ {
+ case SynchronizationEvent:
+ hdr->SignalState = FALSE;
+ break;
+
+ case SemaphoreType:
+ break;
+
+ case ID_PROCESS_OBJECT:
+ break;
+
+ case ID_THREAD_OBJECT:
+ break;
+
+ case NotificationEvent:
+ break;
+
+ default:
+ DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n",
+ __FILE__,__LINE__,hdr);
+ KeBugCheck(0);
+
+ }
+ KeReleaseDispatcherDatabaseLock(FALSE);
+ return(STATUS_SUCCESS);
+ }
+ }
+
+ if (Timeout != NULL)
+ {
+ KeAddThreadTimeout(KeGetCurrentThread(),Timeout);
+ }
+
+ for (Counter = 0; Counter < Count; Counter++)
+ {
+ hdr = (DISPATCHER_HEADER *)Object[Counter];
+
+ blk = &WaitBlockArray[Counter];
+
+ blk->Object=Object[Counter];
+ blk->Thread=KeGetCurrentThread();
+ blk->WaitKey = WaitReason; // Assumed
+ blk->WaitType = WaitType;
+ blk->NextWaitBlock = NULL;
+ InsertTailList(&(hdr->WaitListHead),&(blk.WaitListEntry));
+// DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
+// hdr->WaitListHead.Flink,hdr->WaitListHead.Blink);
+ }
+
+ KeReleaseDispatcherDatabaseLock(FALSE);
+
+ DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__,
+ KeGetCurrentIrql());
+
+ PsSuspendThread(PsGetCurrentThread());
+
+ if (Timeout != NULL)
+ {
+ KeCancelTimer(&KeGetCurrentThread()->Timer);
+ }
+ DPRINT("Returning from KeWaitForMultipleObject()\n");
+
+ return(STATUS_SUCCESS);
+#else
UNIMPLEMENTED;
+#endif
}
VOID KeInitializeDispatcher(VOID)
IN PLARGE_INTEGER Time
)
{
- UNIMPLEMENTED;
+#if 0
+ KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
+ PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS];
+ NTSTATUS Status;
+ ULONG i, j;
+
+
+ DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, Time %x)\n",
+ Count,Object,Alertable,Time);
+
+ if (Count > MAXIMUM_WAIT_OBJECTS)
+ return ...; /* WAIT_FAIL */
+
+ /* reference all objects */
+ for (i = 0; i < Count; i++)
+ {
+ Status = ObReferenceObjectByHandle(Object[i],
+ SYNCHRONIZE,
+ NULL,
+ UserMode,
+ &ObjectPtrArray[i],
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ /* dereference all referenced objects */
+ for (j = 0; j < i; i++)
+ {
+ ObDereferenceObject(ObjectPtrArray[j]);
+ }
+
+ return(Status);
+ }
+ }
+
+ Status = KeWaitForMultipleObjects(Count,
+ ObjectPtrArray,
+ WaitType,
+ UserMode,
+ UserMode,
+ Alertable,
+ Time,
+ WaitBlockArray);
+
+ /* dereference all objects */
+ for (i = 0; i < Count; i++)
+ {
+ ObDereferenceObject(ObjectPtrArray[i]);
+ }
+
+ return(Status);
+#else
+ UNIMPLEMENTED;
+#endif
}
CurrentThread->ThreadsProcess = NULL;
KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
CurrentThread->Tcb.State = THREAD_STATE_TERMINATED;
+ KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
ZwYieldExecution();
for(;;);
}
PiNrThreads--;
KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
Thread->Tcb.State = THREAD_STATE_TERMINATED;
+ KeDispatcherObjectWake(&Thread->Tcb.DispatcherHeader);
ObDereferenceObject(Thread->ThreadsProcess);
Thread->ThreadsProcess = NULL;
KeLowerIrql(oldlvl);
-/* $Id: thread.c,v 1.25 1999/08/29 06:59:11 ea Exp $
+/* $Id: thread.c,v 1.26 1999/09/06 21:28:33 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]);
InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]);
Thread->Tcb.KernelApcDisable = 1;
-
+
+ KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader,
+ ID_THREAD_OBJECT,
+ sizeof(ETHREAD),
+ FALSE);
+
if (ProcessHandle != NULL)
{
Status = ObReferenceObjectByHandle(ProcessHandle,