summaryrefslogtreecommitdiffstats
path: root/private/mvdm/v86/monitor/i386/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/v86/monitor/i386/thread.c')
-rw-r--r--private/mvdm/v86/monitor/i386/thread.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/private/mvdm/v86/monitor/i386/thread.c b/private/mvdm/v86/monitor/i386/thread.c
new file mode 100644
index 000000000..41d3b50e5
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/thread.c
@@ -0,0 +1,338 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Thread.c
+
+Abstract:
+
+ This file contains functions for tracking and manipulating threads
+
+Author:
+
+ Dave Hastings (daveh) 18-Apr-1992
+
+Revision History:
+
+--*/
+
+#include <monitorp.h>
+#include <malloc.h>
+
+//
+// Local Types
+//
+
+typedef struct _MonitorThread {
+ struct _MonitorThread *Previous;
+ struct _MonitorThread *Next;
+ PVOID Teb;
+ HANDLE Thread;
+} MONITORTHREAD, *PMONITORTHREAD;
+
+//
+// Local Variables
+//
+
+PMONITORTHREAD ThreadList = NULL; // List of all threads registered
+
+VOID
+cpu_createthread(
+ HANDLE Thread
+ )
+/*++
+
+Routine Description:
+
+ This routine adds a thread to the list of threads that could be executing
+ in application mode.
+
+Arguments:
+
+ Thread -- Supplies a thread handle
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMONITORTHREAD NewThread, CurrentThread;
+ THREAD_BASIC_INFORMATION ThreadInfo;
+ HANDLE MonitorThreadHandle;
+ NTSTATUS Status;
+
+ //
+ // Correctly initialize the floating point context for the thread
+ //
+ InitialContext.ContextFlags = CONTEXT_FLOATING_POINT;
+
+ if (DebugContextActive)
+ InitialContext.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
+
+ Status = NtSetContextThread(
+ Thread,
+ &InitialContext
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NtVdm terminating : Could not set float context for\n"
+ " thread handle 0x%x, status %lx\n", Thread, Status);
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+ //
+ // Set up a structure to keep track of the new thread
+ //
+ NewThread = malloc(sizeof(MONITORTHREAD));
+
+ if (!NewThread) {
+#if DBG
+ DbgPrint("NTVDM: Could not allocate space for new thread\n");
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+ //
+ // Create a handle for the monitor to use
+ //
+
+ Status = NtDuplicateObject(
+ NtCurrentProcess(),
+ Thread,
+ NtCurrentProcess(),
+ &MonitorThreadHandle,
+ 0,
+ 0,
+ DUPLICATE_SAME_ACCESS
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NTVDM: Could not duplicate thread handle\n");
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+ NewThread->Thread = MonitorThreadHandle;
+
+ Status = NtQueryInformationThread(
+ MonitorThreadHandle,
+ ThreadBasicInformation,
+ &ThreadInfo,
+ sizeof(THREAD_BASIC_INFORMATION),
+ NULL
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NTVDM: Could not get thread information\n");
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+ NewThread->Teb = ThreadInfo.TebBaseAddress;
+ ((PTEB)(NewThread->Teb))->Vdm = &VdmTib;
+
+ //
+ // Insert the new thread in the list. The list is sorted in ascending
+ // order of Teb address
+ //
+ if (!ThreadList) {
+ ThreadList = NewThread;
+ NewThread->Next = NULL;
+ NewThread->Previous = NULL;
+ return;
+ }
+
+ CurrentThread = ThreadList;
+ while ((CurrentThread->Next) && (CurrentThread->Teb < NewThread->Teb)) {
+ CurrentThread = CurrentThread->Next;
+ }
+
+ if (NewThread->Teb > CurrentThread->Teb) {
+ CurrentThread->Next = NewThread;
+ NewThread->Previous = CurrentThread;
+ NewThread->Next = NULL;
+ } else {
+ ASSERT((CurrentThread->Teb != NewThread->Teb));
+ NewThread->Previous = CurrentThread->Previous;
+ NewThread->Next = CurrentThread;
+ CurrentThread->Previous = NewThread;
+ if (NewThread->Previous) {
+ NewThread->Previous->Next = NewThread;
+ } else {
+ ThreadList = NewThread;
+ }
+ }
+}
+
+VOID
+cpu_exitthread(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine frees the thread tracking information, and closes the thread
+ handle
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID CurrentTeb;
+ NTSTATUS Status;
+ PMONITORTHREAD ThreadInfo;
+
+ CurrentTeb = NtCurrentTeb();
+
+ ThreadInfo = ThreadList;
+
+ //
+ // Find this thread in the list
+ //
+ while ((ThreadInfo) && (ThreadInfo->Teb != CurrentTeb)) {
+ ThreadInfo = ThreadInfo->Next;
+ }
+
+ if (!ThreadInfo) {
+#if DBG
+ DbgPrint("NTVDM: Could not find thread in list\n");
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+ //
+ // Close our handle to this thread
+ //
+ Status = NtClose(ThreadInfo->Thread);
+#if DBG
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint("NTVDM: Could not close thread handle\n");
+ }
+#endif
+
+ //
+ // Remove this thread from the list
+ //
+ if (ThreadInfo->Previous) {
+ ThreadInfo->Previous->Next = ThreadInfo->Next;
+ } else {
+ ThreadList = ThreadInfo->Next;
+ }
+
+ if (ThreadInfo->Next) {
+ ThreadInfo->Next->Previous = ThreadInfo->Previous;
+ }
+
+ free(ThreadInfo);
+}
+
+HANDLE
+ThreadLookUp(
+ PVOID Teb
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the handle for the specified thread.
+
+Arguments:
+
+ Teb -- Supplies the teb pointer of the thread
+
+Return Value:
+
+ Returns the handle of the thread, or NULL
+
+--*/
+{
+ PMONITORTHREAD Thread;
+
+ Thread = ThreadList;
+
+ while ((Thread) && (Thread->Teb != Teb)) {
+ Thread = Thread->Next;
+ }
+
+ if (Thread) {
+ return Thread->Thread;
+ } else {
+ return NULL;
+ }
+}
+
+BOOL
+ThreadSetDebugContext(
+ PULONG pDebugRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine sets the debug registers for all the threads that the
+ monitor knows about.
+
+Arguments:
+
+ pDebugRegisters -- Pointer to 6 dwords containing the requested debug
+ register contents.
+
+Return Value:
+
+ none
+
+--*/
+{
+ PMONITORTHREAD Thread;
+ NTSTATUS Status;
+
+ Thread = ThreadList;
+ InitialContext.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+
+ InitialContext.Dr0 = *pDebugRegisters++;
+ InitialContext.Dr1 = *pDebugRegisters++;
+ InitialContext.Dr2 = *pDebugRegisters++;
+ InitialContext.Dr3 = *pDebugRegisters++;
+ InitialContext.Dr6 = *pDebugRegisters++;
+ InitialContext.Dr7 = *pDebugRegisters++;
+
+ while (Thread) {
+
+ Status = NtSetContextThread(
+ Thread->Thread,
+ &InitialContext
+ );
+
+ if (!NT_SUCCESS(Status))
+ break;
+
+ Thread = Thread->Next;
+ }
+
+ if (!NT_SUCCESS(Status))
+ return (FALSE);
+ else {
+ DebugContextActive = ((InitialContext.Dr7 & 0x0f) != 0);
+ return (TRUE);
+ }
+
+}
+