mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Thread improvements.
svn path=/trunk/; revision=646
This commit is contained in:
parent
4280f4f60d
commit
8c0b595a5e
7 changed files with 237 additions and 27 deletions
|
@ -3,6 +3,7 @@
|
|||
|
||||
#define NR_THREADS (0x5)
|
||||
|
||||
|
||||
DWORD WINAPI
|
||||
thread_main1(LPVOID param)
|
||||
{
|
||||
|
@ -11,6 +12,7 @@ thread_main1(LPVOID param)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI
|
||||
thread_main2(LPVOID param)
|
||||
{
|
||||
|
@ -19,33 +21,62 @@ 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;
|
||||
}
|
||||
|
|
|
@ -11,3 +11,4 @@
|
|||
#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)
|
||||
|
|
|
@ -23,6 +23,19 @@
|
|||
|
||||
/* 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,
|
||||
|
@ -55,7 +68,6 @@ HANDLE STDCALL CreateRemoteThread(HANDLE hProcess,
|
|||
BOOLEAN CreateSuspended = FALSE;
|
||||
PVOID BaseAddress;
|
||||
DWORD StackSize;
|
||||
ULONG BytesWritten;
|
||||
NTSTATUS Status;
|
||||
|
||||
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
||||
|
@ -94,18 +106,24 @@ HANDLE STDCALL CreateRemoteThread(HANDLE hProcess,
|
|||
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,
|
||||
|
|
|
@ -132,8 +132,8 @@ RtlCreateUserThread(HANDLE ProcessHandle,
|
|||
LONG StackZeroBits,
|
||||
PULONG StackReserved,
|
||||
PULONG StackCommit,
|
||||
PVOID StartAddress,
|
||||
HANDLE DebugPort,
|
||||
PTHREAD_START_ROUTINE StartAddress,
|
||||
PVOID Parameter,
|
||||
PHANDLE ThreadHandle,
|
||||
PCLIENT_ID ClientId)
|
||||
{
|
||||
|
@ -214,6 +214,9 @@ DPRINT("Checkpoint\n");
|
|||
ObjectAttributes.SecurityQualityOfService = NULL;
|
||||
|
||||
|
||||
if (*StackCommit < 4096)
|
||||
*StackCommit = 4096;
|
||||
|
||||
BaseAddress = 0;
|
||||
ZwAllocateVirtualMemory(ProcessHandle,
|
||||
&BaseAddress,
|
||||
|
@ -271,8 +274,8 @@ DPRINT("Checkpoint\n");
|
|||
NTSTATUS STDCALL
|
||||
RtlInitializeContext(HANDLE ProcessHandle,
|
||||
PCONTEXT Context,
|
||||
HANDLE DebugPort,
|
||||
PVOID StartAddress,
|
||||
PVOID Parameter,
|
||||
PTHREAD_START_ROUTINE StartAddress,
|
||||
PINITIAL_TEB InitialTeb)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
@ -289,8 +292,16 @@ RtlInitializeContext(HANDLE ProcessHandle,
|
|||
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;
|
||||
|
|
|
@ -151,6 +151,9 @@ BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
|
|||
|
||||
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);
|
||||
|
@ -200,6 +203,9 @@ NTSTATUS KeWaitForSingleObject(PVOID Object,
|
|||
|
||||
case ID_PROCESS_OBJECT:
|
||||
break;
|
||||
|
||||
case ID_THREAD_OBJECT:
|
||||
break;
|
||||
|
||||
case NotificationEvent:
|
||||
break;
|
||||
|
@ -222,7 +228,7 @@ NTSTATUS KeWaitForSingleObject(PVOID Object,
|
|||
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",
|
||||
|
@ -249,7 +255,91 @@ NTSTATUS KeWaitForMultipleObjects(ULONG Count,
|
|||
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)
|
||||
|
@ -267,7 +357,59 @@ NtWaitForMultipleObjects (
|
|||
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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
|
|||
CurrentThread->ThreadsProcess = NULL;
|
||||
KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
|
||||
CurrentThread->Tcb.State = THREAD_STATE_TERMINATED;
|
||||
KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
|
||||
ZwYieldExecution();
|
||||
for(;;);
|
||||
}
|
||||
|
@ -58,6 +59,7 @@ VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
|
|||
PiNrThreads--;
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
|
||||
Thread->Tcb.State = THREAD_STATE_TERMINATED;
|
||||
KeDispatcherObjectWake(&Thread->Tcb.DispatcherHeader);
|
||||
ObDereferenceObject(Thread->ThreadsProcess);
|
||||
Thread->ThreadsProcess = NULL;
|
||||
KeLowerIrql(oldlvl);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $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
|
||||
|
@ -259,7 +259,12 @@ PsInitializeThread (
|
|||
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,
|
||||
|
|
Loading…
Reference in a new issue