1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/* $Id$ */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/** @file
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * IPRT - Threads (Part 2), Ring-0 Driver, NT.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/*
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Copyright (C) 2006-2011 Oracle Corporation
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * available from http://www.virtualbox.org. This file is free software;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * General Public License (GPL) as published by the Free Software
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * The contents of this file may alternatively be used under the terms
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * of the Common Development and Distribution License Version 1.0
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * VirtualBox OSE distribution, in which case the provisions of the
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * CDDL are applicable instead of those of the GPL.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * You may elect to license modified versions of this file under the
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * terms and conditions of either the GPL or the CDDL or both.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/*******************************************************************************
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync* Header Files *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync*******************************************************************************/
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include "the-nt-kernel.h"
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include <iprt/thread.h>
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include <iprt/assert.h>
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include <iprt/err.h>
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include "internal/thread.h"
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncDECLHIDDEN(int) rtThreadNativeInit(void)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* No TLS in Ring-0. :-/ */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return VINF_SUCCESS;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncRTDECL(RTTHREAD) RTThreadSelf(void)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return rtThreadGetByNative((RTNATIVETHREAD)PsGetCurrentThread());
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncDECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /*
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Convert the IPRT priority type to NT priority.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * The NT priority is in the range 0..32, with realtime starting
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * at 16 and the default for user processes at 8. (Should try find
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * the appropriate #defines for some of this...)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync KPRIORITY Priority;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync switch (enmType)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case RTTHREADTYPE_INFREQUENT_POLLER: Priority = 6; break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case RTTHREADTYPE_EMULATION: Priority = 7; break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case RTTHREADTYPE_DEFAULT: Priority = 8; break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case RTTHREADTYPE_MSG_PUMP: Priority = 9; break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case RTTHREADTYPE_IO: Priority = LOW_REALTIME_PRIORITY; break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case RTTHREADTYPE_TIMER: Priority = MAXIMUM_PRIORITY; break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync default:
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync AssertMsgFailed(("enmType=%d\n", enmType));
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return VERR_INVALID_PARAMETER;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /*
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Do the actual modification.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /*KPRIORITY oldPririty = */KeSetPriorityThread((PKTHREAD)pThread->Core.Key, Priority);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return VINF_SUCCESS;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncDECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return VERR_NOT_IMPLEMENTED;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncDECLHIDDEN(void) rtThreadNativeWaitKludge(PRTTHREADINT pThread)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync PVOID pvThreadObj = pThread->Core.Key;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync NTSTATUS rcNt = KeWaitForSingleObject(pvThreadObj, Executive, KernelMode, FALSE, NULL);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync AssertMsg(rcNt == STATUS_SUCCESS, ("rcNt=%#x\n", rcNt));
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncDECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync NOREF(pThread);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/**
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * Native kernel thread wrapper function.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * This will forward to rtThreadMain and do termination upon return.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync *
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * @param pvArg Pointer to the argument package.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncstatic VOID __stdcall rtThreadNativeMain(PVOID pvArg)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync PETHREAD Self = PsGetCurrentThread();
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync PRTTHREADINT pThread = (PRTTHREADINT)pvArg;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync rtThreadMain(pThread, (RTNATIVETHREAD)Self, &pThread->szName[0]);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ObDereferenceObject(Self); /* the rtThreadNativeCreate ref. */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncDECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /*
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * PsCreateSysemThread create a thread an give us a handle in return.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * We requests the object for that handle and then close it, so what
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * we keep around is the pointer to the thread object and not a handle.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync * The thread will dereference the object before returning.
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync HANDLE hThread = NULL;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync OBJECT_ATTRIBUTES ObjAttr;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync InitializeObjectAttributes(&ObjAttr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync NTSTATUS rc = PsCreateSystemThread(&hThread,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync THREAD_ALL_ACCESS,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync &ObjAttr,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync NULL /* ProcessHandle - kernel */,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync NULL /* ClientID - kernel */,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync rtThreadNativeMain,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync pThreadInt);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (NT_SUCCESS(rc))
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync PVOID pvThreadObj;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync rc = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL /* object type */,
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync KernelMode, &pvThreadObj, NULL /* handle info */);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (NT_SUCCESS(rc))
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ZwClose(hThread);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync *pNativeThread = (RTNATIVETHREAD)pvThreadObj;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync else
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync AssertMsgFailed(("%#x\n", rc));
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return RTErrConvertFromNtStatus(rc);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync