1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/* $Id$ */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/** @file
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Threads (Part 1), Ring-0 Driver, FreeBSD.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2007-2011 Oracle Corporation
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync *
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * available from http://www.virtualbox.org. This file is free software;
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * you can redistribute it and/or modify it under the terms of the GNU
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * General Public License (GPL) as published by the Free Software
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync *
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * The contents of this file may alternatively be used under the terms
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * of the Common Development and Distribution License Version 1.0
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * VirtualBox OSE distribution, in which case the provisions of the
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * CDDL are applicable instead of those of the GPL.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync *
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * You may elect to license modified versions of this file under the
10ecaf3570b345a45fe1687eb5512c4f39103887vboxsync * terms and conditions of either the GPL or the CDDL or both.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync/*******************************************************************************
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync* Header Files *
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync*******************************************************************************/
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include "the-freebsd-kernel.h"
76d5ffd3aac5ac54a361ad10b4369ef87da94fdbvboxsync#include "internal/iprt.h"
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include <iprt/thread.h>
76d5ffd3aac5ac54a361ad10b4369ef87da94fdbvboxsync
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync#include <iprt/asm.h>
f737cdef9a611a3ebe4cfd6da04c42ede272344cvboxsync#include <iprt/asm-amd64-x86.h>
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include <iprt/assert.h>
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync#include <iprt/err.h>
76d5ffd3aac5ac54a361ad10b4369ef87da94fdbvboxsync#include <iprt/mp.h>
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync#include "internal/thread.h"
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsyncRTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return (RTNATIVETHREAD)curthread;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsyncstatic int rtR0ThreadFbsdSleepCommon(RTMSINTERVAL cMillies)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync int rc;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync int cTicks;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /*
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * 0 ms sleep -> yield.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync if (!cMillies)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync RTThreadYield();
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VINF_SUCCESS;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync /*
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync * Translate milliseconds into ticks and go to sleep.
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync if (cMillies != RT_INDEFINITE_WAIT)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync if (hz == 1000)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync cTicks = cMillies;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync else if (hz == 100)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync cTicks = cMillies / 10;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync else
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync int64_t cTicks64 = ((uint64_t)cMillies * hz) / 1000;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync cTicks = (int)cTicks64;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync if (cTicks != cTicks64)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync cTicks = INT_MAX;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync else
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync cTicks = 0; /* requires giant lock! */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync rc = tsleep((void *)RTThreadSleep,
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync PZERO | PCATCH,
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync "iprtsl", /* max 6 chars */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync cTicks);
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync switch (rc)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync {
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync case 0:
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VINF_SUCCESS;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync case EWOULDBLOCK:
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VERR_TIMEOUT;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync case EINTR:
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync case ERESTART:
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VERR_INTERRUPTED;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync default:
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync AssertMsgFailed(("%d\n", rc));
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return VERR_NO_TRANSLATION;
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync }
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsyncRTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync{
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync return rtR0ThreadFbsdSleepCommon(cMillies);
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync}
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsyncRTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies)
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync{
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync return rtR0ThreadFbsdSleepCommon(cMillies);
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync}
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync
7f9158d55774800c9b8f2d35fde872c7434fd281vboxsync
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsyncRTDECL(bool) RTThreadYield(void)
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync{
267c6ded494154d020973d1c09366c3760336f43vboxsync#if __FreeBSD_version >= 900032
267c6ded494154d020973d1c09366c3760336f43vboxsync kern_yield(curthread->td_user_pri);
267c6ded494154d020973d1c09366c3760336f43vboxsync#else
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync uio_yield();
267c6ded494154d020973d1c09366c3760336f43vboxsync#endif
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync return false; /** @todo figure this one ... */
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync}
1f1986470af9f0bb750dd859b142dc2e952deb20vboxsync
445a156b9ab321242ed8ad2ee143626c05865acfvboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsyncRTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread)
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync{
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync Assert(hThread == NIL_RTTHREAD);
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync return curthread->td_critnest == 0
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync && ASMIntAreEnabled(); /** @todo is there a native freebsd function/macro for this? */
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync}
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsyncRTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread)
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync{
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync Assert(hThread == NIL_RTTHREAD);
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync return curthread->td_owepreempt == 1;
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync}
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
445a156b9ab321242ed8ad2ee143626c05865acfvboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsyncRTDECL(bool) RTThreadPreemptIsPendingTrusty(void)
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync{
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync /* yes, RTThreadPreemptIsPending is reliable. */
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync return true;
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync}
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
445a156b9ab321242ed8ad2ee143626c05865acfvboxsync
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsyncRTDECL(bool) RTThreadPreemptIsPossible(void)
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync{
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync /* yes, kernel preemption is possible. */
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync return true;
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync}
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsyncRTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState)
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync{
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync AssertPtr(pState);
4589067b02bb33c477d399abc0f999e5d3a8c146vboxsync Assert(pState->u32Reserved == 0);
4589067b02bb33c477d399abc0f999e5d3a8c146vboxsync pState->u32Reserved = 42;
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync critical_enter();
4589067b02bb33c477d399abc0f999e5d3a8c146vboxsync RT_ASSERT_PREEMPT_CPUID_DISABLE(pState);
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync}
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsyncRTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState)
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync{
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync AssertPtr(pState);
4589067b02bb33c477d399abc0f999e5d3a8c146vboxsync Assert(pState->u32Reserved == 42);
4589067b02bb33c477d399abc0f999e5d3a8c146vboxsync pState->u32Reserved = 0;
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
4589067b02bb33c477d399abc0f999e5d3a8c146vboxsync RT_ASSERT_PREEMPT_CPUID_RESTORE(pState);
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync critical_exit();
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync}
1f6aceca6eb044aee08cc9dacac639b0ea0c45f9vboxsync
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsyncRTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread)
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync{
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync Assert(hThread == NIL_RTTHREAD); NOREF(hThread);
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync /** @todo FreeBSD: Implement RTThreadIsInInterrupt. Required for guest
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync * additions! */
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync return !ASMIntAreEnabled();
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync}
670732e50b0d42e68d59a3bab835ba0e91b00c30vboxsync