Index: /trunk/src/VBox/Runtime/r0drv/freebsd/alloc-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/alloc-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/alloc-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,117 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Memory Allocation, Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/param.h>
+
+#include "r0drv/alloc-r0drv.h"
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/* These two statements will define two globals and add initializers
+   and destructors that will be called at load/unload time (I think). */
+MALLOC_DEFINE(M_IPRTHEAP, "iprtheap", "innotek Portable Runtime - heap");
+MALLOC_DEFINE(M_IPRTCONT, "iprtcont", "innotek Portable Runtime - contiguous");
+
+
+PRTMEMHDR rtMemAlloc(size_t cb, uint32_t fFlags)
+{
+    PRTMEMHDR pHdr;
+    Assert(cb != sizeof(void *)); /* 99% of pointer sized allocations are wrong. */
+
+    /** @todo Just like OS/2, FreeBSD doesn't need this header. */
+    pHdr = (PRTMEMHDR)malloc(cb + sizeof(RTMEMHDR), M_IPRTHEAP,
+                             fFlags & RTMEMHDR_FLAG_ZEROED ? M_NOWAIT | M_ZERO : M_NOWAIT);
+    if (pHdr)
+    {
+        pHdr->u32Magic   = RTMEMHDR_MAGIC;
+        pHdr->fFlags     = fFlags;
+        pHdr->cb         = cb;
+        pHdr->u32Padding = 0;
+        return pHdr;
+    }
+    return NULL;
+}
+
+
+void rtMemFree(PRTMEMHDR pHdr)
+{
+    pHdr->u32Magic += 1;
+    free(pHdr, M_IPRTHEAP);
+}
+
+
+RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb)
+{
+    void *pv;
+
+    /*
+     * Validate input.
+     */
+    AssertPtr(pPhys);
+    Assert(cb > 0);
+
+    /*
+     * This API works in pages, so no need to do any size aligning.
+     */
+    pv = contigmalloc(cb,                   /* size */
+                      M_IPRTCONT,           /* type */
+                      M_NOWAIT | M_ZERO,    /* flags */
+                      0,                    /* lowest physical address*/
+                      _4G-1,                /* highest physical address */
+                      PAGE_SIZE,            /* alignment. */
+                      0);                   /* boundrary */
+    if (pv)
+    {
+        Assert(!((uintptr_t)pv & PAGE_OFFSET_MASK));
+        *pPhys = vtophys(pv);
+        Assert(!(*pPhys & PAGE_OFFSET_MASK));
+    }
+    return pv;
+}
+
+
+RTR0DECL(void) RTMemContFree(void *pv, size_t cb)
+{
+    if (pv)
+    {
+        AssertMsg(!((uintptr_t)pv & PAGE_OFFSET_MASK), ("pv=%p\n", pv));
+        contigfree(pv, cb, M_IPRTCONT);
+    }
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/assert-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/assert-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/assert-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,75 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Assertion Workers, Ring-0 Drivers, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/assert.h>
+#include <iprt/log.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+
+
+RTDECL(void) AssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
+{
+#ifdef IN_GUEST_R0
+    RTLogBackdoorPrintf("\n!!Assertion Failed!!\n"
+                        "Expression: %s\n"
+                        "Location  : %s(%d) %s\n",
+                        pszExpr, pszFile, uLine, pszFunction);
+#endif
+
+    printf("\r\n!!Assertion Failed!!\r\n"
+           "Expression: %s\r\n"
+           "Location  : %s(%d) %s\r\n",
+           pszExpr, pszFile, uLine, pszFunction);
+}
+
+
+RTDECL(void) AssertMsg2(const char *pszFormat, ...)
+{
+    va_list va;
+    char    szMsg[256];
+
+#ifdef IN_GUEST_R0
+    va_start(va, pszFormat);
+    RTLogBackdoorPrintfV(pszFormat, va);
+    va_end(va);
+#endif
+
+    va_start(va, pszFormat);
+    RTStrPrintf(szMsg, sizeof(szMsg) - 1, pszFormat, va);
+    szMsg[sizeof(szMsg) - 1] = '\0';
+    printf("%s", szMsg);
+    va_end(va);
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/initterm-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/initterm-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/initterm-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,52 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Initialization & Termination, Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/err.h>
+
+#include "internal/initterm.h"
+
+
+int rtR0InitNative(void)
+{
+    /* nothing to do */
+    return VINF_SUCCESS;
+}
+
+
+void rtR0TermNative(void)
+{
+    /* nothing to undo */
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/process-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/process-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/process-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,50 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Process Management, Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/process.h>
+
+
+RTDECL(RTPROCESS) RTProcSelf(void)
+{
+    struct proc *pSelf = curproc;
+    return pSelf->p_pid;
+}
+
+
+RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void)
+{
+    return (RTR0PROCESS)curproc;
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/semevent-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/semevent-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/semevent-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,251 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Single Release Event Semaphores, Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/semaphore.h>
+#include <iprt/alloc.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+
+#include "internal/magics.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * FreeBSD event semaphore.
+ */
+typedef struct RTSEMEVENTINTERNAL
+{
+    /** Magic value (RTSEMEVENT_MAGIC). */
+    uint32_t volatile   u32Magic;
+    /** The number of waiting threads. */
+    uint32_t volatile   cWaiters;
+    /** Set if the event object is signaled. */
+    uint8_t volatile    fSignaled;
+    /** The number of threads in the process of waking up. */
+    uint32_t volatile   cWaking;
+    /** The FreeBSD spinlock protecting this structure. */
+    struct mtx          Mtx;
+} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
+
+
+RTDECL(int)  RTSemEventCreate(PRTSEMEVENT pEventSem)
+{
+    Assert(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
+    AssertPtrReturn(pEventSem, VERR_INVALID_POINTER);
+
+    PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pEventInt));
+    if (pEventInt)
+    {
+        pEventInt->u32Magic = RTSEMEVENT_MAGIC;
+        pEventInt->cWaiters = 0;
+        pEventInt->cWaking = 0;
+        pEventInt->fSignaled = 0;
+        mtx_init(&pEventInt->Mtx, "IPRT Event Semaphore", NULL, MTX_SPIN);
+        *pEventSem = pEventInt;
+        return VINF_SUCCESS;
+    }
+    return VERR_NO_MEMORY;
+}
+
+
+RTDECL(int)  RTSemEventDestroy(RTSEMEVENT EventSem)
+{
+    if (EventSem == NIL_RTSEMEVENT)     /* don't bitch */
+        return VERR_INVALID_HANDLE;
+    PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
+    AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
+                    ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
+                    VERR_INVALID_HANDLE);
+
+    mtx_lock_spin(&pEventInt->Mtx);
+    ASMAtomicIncU32(&pEventInt->u32Magic); /* make the handle invalid */
+    if (pEventInt->cWaiters > 0)
+    {
+        /* abort waiting thread, last man cleans up. */
+        ASMAtomicXchgU32(&pEventInt->cWaking, pEventInt->cWaking + pEventInt->cWaiters);
+        wakeup(pEventInt);
+        mtx_unlock_spin(&pEventInt->Mtx);
+    }
+    else if (pEventInt->cWaking)
+        /* the last waking thread is gonna do the cleanup */
+        mtx_unlock_spin(&pEventInt->Mtx);
+    else
+    {
+        mtx_unlock_spin(&pEventInt->Mtx);
+        mtx_destroy(&pEventInt->Mtx);
+        RTMemFree(pEventInt);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int)  RTSemEventSignal(RTSEMEVENT EventSem)
+{
+    PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
+    AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
+                    ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
+                    VERR_INVALID_HANDLE);
+
+    mtx_lock_spin(&pEventInt->Mtx);
+
+    if (pEventInt->cWaiters > 0)
+    {
+        ASMAtomicDecU32(&pEventInt->cWaiters);
+        ASMAtomicIncU32(&pEventInt->cWaking);
+        wakeup_one(pEventInt);
+    }
+    else
+        ASMAtomicXchgU8(&pEventInt->fSignaled, true);
+
+    mtx_unlock_spin(&pEventInt->Mtx);
+    return VINF_SUCCESS;
+}
+
+
+static int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, bool fInterruptible)
+{
+    int rc;
+    PRTSEMEVENTINTERNAL pEventInt = (PRTSEMEVENTINTERNAL)EventSem;
+    AssertPtrReturn(pEventInt, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pEventInt->u32Magic == RTSEMEVENT_MAGIC,
+                    ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic),
+                    VERR_INVALID_HANDLE);
+
+    mtx_lock_spin(&pEventInt->Mtx);
+
+    if (pEventInt->fSignaled)
+    {
+        Assert(!pEventInt->cWaiters);
+        ASMAtomicXchgU8(&pEventInt->fSignaled, false);
+        rc = VINF_SUCCESS;
+    }
+    else
+    {
+        /*
+         * Translate milliseconds into ticks and go to sleep.
+         */
+        int cTicks;
+        if (cMillies != RT_INDEFINITE_WAIT)
+        {
+            if (hz == 1000)
+                cTicks = cMillies;
+            else if (hz == 100)
+                cTicks = cMillies / 10;
+            else
+            {
+                int64_t cTicks64 = ((uint64_t)cMillies * hz) / 1000;
+                cTicks = (int)cTicks64;
+                if (cTicks != cTicks64)
+                    cTicks = INT_MAX;
+            }
+        }
+        else
+            cTicks = 0;
+
+        ASMAtomicIncU32(&pEventInt->cWaiters);
+
+        rc = msleep(pEventInt,          /* block id */
+                    &pEventInt->Mtx,
+                    fInterruptible ? PZERO | PCATCH : PZERO,
+                    "iprtev",           /* max 6 chars */
+                    cTicks);
+        switch (rc)
+        {
+            case 0:
+                if (pEventInt->u32Magic == RTSEMEVENT_MAGIC)
+                {
+                    ASMAtomicDecU32(&pEventInt->cWaking);
+                    rc = VINF_SUCCESS;
+                }
+                else
+                {
+                    rc = VERR_SEM_DESTROYED; /** @todo this isn't necessarily correct, we've
+                                              * could've woken up just before destruction... */
+                    if (!ASMAtomicDecU32(&pEventInt->cWaking))
+                    {
+                        /* The event was destroyed, as the last thread do the cleanup.
+                           we don't actually know whether */
+                        mtx_unlock_spin(&pEventInt->Mtx);
+                        mtx_destroy(&pEventInt->Mtx);
+                        RTMemFree(pEventInt);
+                        return rc;
+                    }
+                }
+                break;
+
+            case EWOULDBLOCK:
+                Assert(cMillies != RT_INDEFINITE_WAIT);
+                if (pEventInt->cWaiters > 0)
+                    ASMAtomicDecU32(&pEventInt->cWaiters);
+                rc = VERR_TIMEOUT;
+                break;
+
+            case EINTR:
+            case ERESTART:
+                Assert(fInterruptible);
+                if (pEventInt->cWaiters > 0)
+                    ASMAtomicDecU32(&pEventInt->cWaiters);
+                rc = VERR_INTERRUPTED;
+                break;
+
+            default:
+                AssertMsgFailed(("msleep -> %d\n", rc));
+                rc = VERR_GENERAL_FAILURE;
+                break;
+        }
+    }
+
+    mtx_unlock_spin(&pEventInt->Mtx);
+    return rc;
+}
+
+
+RTDECL(int)  RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
+{
+    return rtSemEventWait(EventSem, cMillies, false /* not interruptible */);
+}
+
+
+RTDECL(int)  RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies)
+{
+    return rtSemEventWait(EventSem, cMillies, true /* interruptible */);
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/semeventmulti-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/semeventmulti-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/semeventmulti-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,261 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Multiple Release Event Semaphores, Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/semaphore.h>
+#include <iprt/alloc.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+
+#include "internal/magics.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * FreeBSD multiple release event semaphore.
+ */
+typedef struct RTSEMEVENTMULTIINTERNAL
+{
+    /** Magic value (RTSEMEVENTMULTI_MAGIC). */
+    uint32_t volatile   u32Magic;
+    /** The number of waiting threads. */
+    uint32_t volatile   cWaiters;
+    /** Set if the event object is signaled. */
+    uint8_t volatile    fSignaled;
+    /** The number of threads in the process of waking up. */
+    uint32_t volatile   cWaking;
+    /** The FreeBSD spinlock protecting this structure. */
+    struct mtx          Mtx;
+} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
+
+
+RTDECL(int)  RTSemEventMultiCreate(PRTSEMEVENTMULTI pEventMultiSem)
+{
+    Assert(sizeof(RTSEMEVENTMULTIINTERNAL) > sizeof(void *));
+    AssertPtrReturn(pEventMultiSem, VERR_INVALID_POINTER);
+
+    PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pEventMultiInt));
+    if (pEventMultiInt)
+    {
+        pEventMultiInt->u32Magic = RTSEMEVENTMULTI_MAGIC;
+        pEventMultiInt->cWaiters = 0;
+        pEventMultiInt->cWaking = 0;
+        pEventMultiInt->fSignaled = 0;
+        mtx_init(&pEventMultiInt->Mtx, "IPRT Multiple Release Event Semaphore", NULL, MTX_SPIN);
+        *pEventMultiSem = pEventMultiInt;
+        return VINF_SUCCESS;
+    }
+    return VERR_NO_MEMORY;
+}
+
+
+RTDECL(int)  RTSemEventMultiDestroy(RTSEMEVENTMULTI EventMultiSem)
+{
+    if (EventMultiSem == NIL_RTSEMEVENTMULTI)     /* don't bitch */
+        return VERR_INVALID_HANDLE;
+    PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
+    AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
+                    ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
+                    VERR_INVALID_HANDLE);
+
+    mtx_lock_spin(&pEventMultiInt->Mtx);
+    ASMAtomicIncU32(&pEventMultiInt->u32Magic); /* make the handle invalid */
+    if (pEventMultiInt->cWaiters > 0)
+    {
+        /* abort waiting thread, last man cleans up. */
+        ASMAtomicXchgU32(&pEventMultiInt->cWaking, pEventMultiInt->cWaking + pEventMultiInt->cWaiters);
+        wakeup(pEventMultiInt);
+        mtx_unlock_spin(&pEventMultiInt->Mtx);
+    }
+    else if (pEventMultiInt->cWaking)
+        /* the last waking thread is gonna do the cleanup */
+        mtx_unlock_spin(&pEventMultiInt->Mtx);
+    else
+    {
+        mtx_unlock_spin(&pEventMultiInt->Mtx);
+        mtx_destroy(&pEventMultiInt->Mtx);
+        RTMemFree(pEventMultiInt);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int)  RTSemEventMultiSignal(RTSEMEVENTMULTI EventMultiSem)
+{
+    PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
+    AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
+                    ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
+                    VERR_INVALID_HANDLE);
+
+    mtx_lock_spin(&pEventMultiInt->Mtx);
+
+    ASMAtomicXchgU8(&pEventMultiInt->fSignaled, true);
+    if (pEventMultiInt->cWaiters > 0)
+    {
+        ASMAtomicXchgU32(&pEventMultiInt->cWaking, pEventMultiInt->cWaking + pEventMultiInt->cWaiters);
+        ASMAtomicXchgU32(&pEventMultiInt->cWaiters, 0);
+        wakeup(pEventMultiInt);
+    }
+
+    mtx_unlock_spin(&pEventMultiInt->Mtx);
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int)  RTSemEventMultiReset(RTSEMEVENTMULTI EventMultiSem)
+{
+    PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
+    AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
+                    ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
+                    VERR_INVALID_HANDLE);
+
+    mtx_lock_spin(&pEventMultiInt->Mtx);
+    ASMAtomicXchgU8(&pEventMultiInt->fSignaled, false);
+    mtx_unlock_spin(&pEventMultiInt->Mtx);
+    return VINF_SUCCESS;
+}
+
+
+static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fInterruptible)
+{
+    int rc;
+    PRTSEMEVENTMULTIINTERNAL pEventMultiInt = (PRTSEMEVENTMULTIINTERNAL)EventMultiSem;
+    AssertPtrReturn(pEventMultiInt, VERR_INVALID_HANDLE);
+    AssertMsgReturn(pEventMultiInt->u32Magic == RTSEMEVENTMULTI_MAGIC,
+                    ("pEventMultiInt=%p u32Magic=%#x\n", pEventMultiInt, pEventMultiInt->u32Magic),
+                    VERR_INVALID_HANDLE);
+
+    mtx_lock_spin(&pEventMultiInt->Mtx);
+
+    if (pEventMultiInt->fSignaled)
+        rc = VINF_SUCCESS;
+    else
+    {
+        /*
+         * Translate milliseconds into ticks and go to sleep.
+         */
+        int cTicks;
+        if (cMillies != RT_INDEFINITE_WAIT)
+        {
+            if (hz == 1000)
+                cTicks = cMillies;
+            else if (hz == 100)
+                cTicks = cMillies / 10;
+            else
+            {
+                int64_t cTicks64 = ((uint64_t)cMillies * hz) / 1000;
+                cTicks = (int)cTicks64;
+                if (cTicks != cTicks64)
+                    cTicks = INT_MAX;
+            }
+        }
+        else
+            cTicks = 0;
+
+        ASMAtomicIncU32(&pEventMultiInt->cWaiters);
+
+        rc = msleep(pEventMultiInt,     /* block id */
+                    &pEventMultiInt->Mtx,
+                    fInterruptible ? PZERO | PCATCH : PZERO,
+                    "iprtev",           /* max 6 chars */
+                    cTicks);
+        switch (rc)
+        {
+            case 0:
+                if (pEventMultiInt->u32Magic == RTSEMEVENT_MAGIC)
+                {
+                    ASMAtomicDecU32(&pEventMultiInt->cWaking);
+                    rc = VINF_SUCCESS;
+                }
+                else
+                {
+                    rc = VERR_SEM_DESTROYED; /** @todo this isn't necessarily correct, we've
+                                              * could've woken up just before destruction... */
+                    if (!ASMAtomicDecU32(&pEventMultiInt->cWaking))
+                    {
+                        /* The event was destroyed, as the last thread do the cleanup.
+                           we don't actually know whether */
+                        mtx_unlock_spin(&pEventMultiInt->Mtx);
+                        mtx_destroy(&pEventMultiInt->Mtx);
+                        RTMemFree(pEventMultiInt);
+                        return rc;
+                    }
+                }
+                break;
+
+            case EWOULDBLOCK:
+                Assert(cMillies != RT_INDEFINITE_WAIT);
+                if (pEventMultiInt->cWaiters > 0)
+                    ASMAtomicDecU32(&pEventMultiInt->cWaiters);
+                rc = VERR_TIMEOUT;
+                break;
+
+            case EINTR:
+            case ERESTART:
+                Assert(fInterruptible);
+                if (pEventMultiInt->cWaiters > 0)
+                    ASMAtomicDecU32(&pEventMultiInt->cWaiters);
+                rc = VERR_INTERRUPTED;
+                break;
+
+            default:
+                AssertMsgFailed(("msleep -> %d\n", rc));
+                rc = VERR_GENERAL_FAILURE;
+                break;
+        }
+    }
+
+    mtx_unlock_spin(&pEventMultiInt->Mtx);
+    return rc;
+}
+
+
+RTDECL(int)  RTSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
+{
+    return rtSemEventMultiWait(EventMultiSem, cMillies, false /* not interruptible */);
+}
+
+
+RTDECL(int)  RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies)
+{
+    return rtSemEventMultiWait(EventMultiSem, cMillies, true /* interruptible */);
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/semfastmutex-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/semfastmutex-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/semfastmutex-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,119 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Fast Mutex Semaphores, Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/semaphore.h>
+#include <iprt/err.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+
+#include "internal/magics.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Wrapper for the FreeBSD (sleep) mutex.
+ */
+typedef struct RTSEMFASTMUTEXINTERNAL
+{
+    /** Magic value (RTSEMFASTMUTEX_MAGIC). */
+    uint32_t            u32Magic;
+    /** The FreeBSD (sleep) mutex. */
+    struct mtx          Mtx;
+} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL;
+
+
+RTDECL(int)  RTSemFastMutexCreate(PRTSEMFASTMUTEX pMutexSem)
+{
+    AssertCompile(sizeof(RTSEMFASTMUTEXINTERNAL) > sizeof(void *));
+    AssertPtrReturn(pMutexSem, VERR_INVALID_POINTER);
+
+    PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)RTMemAlloc(sizeof(*pFastInt));
+    if (pFastInt)
+    {
+        pFastInt->u32Magic = RTSEMFASTMUTEX_MAGIC;
+        mtx_init(&pFastInt->Mtx, "IPRT Fast Mutex Semaphore", NULL, MTX_DEF | MTX_RECURSE);
+        *pMutexSem = pFastInt;
+        return VINF_SUCCESS;
+    }
+    return VERR_NO_MEMORY;
+}
+
+
+RTDECL(int)  RTSemFastMutexDestroy(RTSEMFASTMUTEX MutexSem)
+{
+    if (MutexSem == NIL_RTSEMFASTMUTEX) /* don't bitch */
+        return VERR_INVALID_PARAMETER;
+    PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
+    AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
+                    ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
+                    VERR_INVALID_PARAMETER);
+
+    ASMAtomicXchgU32(&pFastInt->u32Magic, RTSEMFASTMUTEX_MAGIC_DEAD);
+    mtx_destroy(&pFastInt->Mtx);
+    RTMemFree(pFastInt);
+
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int)  RTSemFastMutexRequest(RTSEMFASTMUTEX MutexSem)
+{
+    PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
+    AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
+                    ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
+                    VERR_INVALID_PARAMETER);
+
+    mtx_lock(&pFastInt->Mtx);
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int)  RTSemFastMutexRelease(RTSEMFASTMUTEX MutexSem)
+{
+    PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
+    AssertPtrReturn(pFastInt, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(pFastInt->u32Magic == RTSEMFASTMUTEX_MAGIC,
+                    ("pFastInt->u32Magic=%RX32 pFastInt=%p\n", pFastInt->u32Magic, pFastInt),
+                    VERR_INVALID_PARAMETER);
+
+    mtx_unlock(&pFastInt->Mtx);
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/spinlock-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/spinlock-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/spinlock-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,144 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Spinlocks, Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/spinlock.h>
+#include <iprt/err.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+
+#include "internal/magics.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Wrapper for the struct mtx type.
+ */
+typedef struct RTSPINLOCKINTERNAL
+{
+    /** Spinlock magic value (RTSPINLOCK_MAGIC). */
+    uint32_t volatile   u32Magic;
+    /** A FreeBSD spinlock. (mtx can be both sleep and spin lock.) */
+    struct mtx          Mtx;
+} RTSPINLOCKINTERNAL, *PRTSPINLOCKINTERNAL;
+
+
+RTDECL(int)  RTSpinlockCreate(PRTSPINLOCK pSpinlock)
+{
+    /*
+     * Allocate.
+     */
+    AssertCompile(sizeof(RTSPINLOCKINTERNAL) > sizeof(void *));
+    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)RTMemAlloc(sizeof(*pSpinlockInt));
+    if (!pSpinlockInt)
+        return VERR_NO_MEMORY;
+
+    /*
+     * Initialize & return.
+     */
+    pSpinlockInt->u32Magic = RTSPINLOCK_MAGIC;
+    mtx_init(&pSpinlockInt->Mtx, "IPRT Spinlock", NULL, MTX_SPIN);
+    *pSpinlock = pSpinlockInt;
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int)  RTSpinlockDestroy(RTSPINLOCK Spinlock)
+{
+    /*
+     * Validate input.
+     */
+    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
+    if (!pSpinlockInt)
+        return VERR_INVALID_PARAMETER;
+    AssertMsgReturn(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
+                    ("Invalid spinlock %p magic=%#x\n", pSpinlockInt, pSpinlockInt->u32Magic),
+                    VERR_INVALID_PARAMETER);
+
+    /*
+     * Make the lock invalid and release the memory.
+     */
+    ASMAtomicIncU32(&pSpinlockInt->u32Magic);
+    mtx_destroy(&pSpinlockInt->Mtx);
+    RTMemFree(pSpinlockInt);
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(void) RTSpinlockAcquireNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
+{
+    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
+    AssertPtr(pSpinlockInt);
+    Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
+    NOREF(pTmp);
+
+    mtx_lock_spin(&pSpinlockInt->Mtx);
+}
+
+
+RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
+{
+    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
+    AssertPtr(pSpinlockInt);
+    Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
+    NOREF(pTmp);
+
+    mtx_unlock_spin(&pSpinlockInt->Mtx);
+}
+
+
+RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
+{
+    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
+    AssertPtr(pSpinlockInt);
+    Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
+    NOREF(pTmp);
+
+    mtx_lock_spin(&pSpinlockInt->Mtx);
+}
+
+
+RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
+{
+    PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
+    AssertPtr(pSpinlockInt);
+    Assert(pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC);
+    NOREF(pTmp);
+
+    mtx_unlock_spin(&pSpinlockInt->Mtx);
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/the-freebsd-kernel.h
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/the-freebsd-kernel.h	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/the-freebsd-kernel.h	(revision 3680)
@@ -0,0 +1,61 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Ring-0 Driver, The FreeBSD Kernel Headers.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ___the_freebsd_kernel_h
+#define ___the_freebsd_kernel_h
+
+#include <iprt/types.h>
+
+/* Deal with conflicts first. */
+#include <sys/param.h>
+#undef PVM
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/uio.h>
+#include <sys/libkern.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/limits.h>
+#include <sys/unistd.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sched.h>
+#include <vm/vm.h>              /* for vtophys */
+#include <vm/pmap.h>            /* for vtophys */
+
+/*#ifdef __cplusplus
+# error "This header doesn't work for C++ code. Sorry, typical kernel crap."
+#endif*/
+
+#endif
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/thread-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/thread-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/thread-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,108 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Threads (Part 1), Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/thread.h>
+#include <iprt/err.h>
+#include <iprt/assert.h>
+
+#include "internal/thread.h"
+
+
+RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
+{
+    return (RTNATIVETHREAD)curthread;
+}
+
+
+RTDECL(int) RTThreadSleep(unsigned cMillies)
+{
+    int rc;
+    int cTicks;
+
+    /*
+     * 0 ms sleep -> yield.
+     */
+    if (!cMillies)
+    {
+        RTThreadYield();
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Translate milliseconds into ticks and go to sleep.
+     */
+    if (cMillies != RT_INDEFINITE_WAIT)
+    {
+        if (hz == 1000)
+            cTicks = cMillies;
+        else if (hz == 100)
+            cTicks = cMillies / 10;
+        else
+        {
+            int64_t cTicks64 = ((uint64_t)cMillies * hz) / 1000;
+            cTicks = (int)cTicks64;
+            if (cTicks != cTicks64)
+                cTicks = INT_MAX;
+        }
+    }
+    else
+        cTicks = 0;     /* requires giant lock! */
+
+    rc = tsleep((void *)RTThreadSleep,
+                PZERO | PCATCH,
+                "iprtsl",           /* max 6 chars */
+                cTicks);
+    switch (rc)
+    {
+        case 0:
+            return VINF_SUCCESS;
+        case EWOULDBLOCK:
+            return VERR_TIMEOUT;
+        case EINTR:
+        case ERESTART:
+            return VERR_INTERRUPTED;
+        default:
+            AssertMsgFailed(("%d\n", rc));
+            return VERR_NO_TRANSLATION;
+    }
+}
+
+
+RTDECL(bool) RTThreadYield(void)
+{
+    uio_yield();
+    return false; /** @todo figure this one ... */
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/thread2-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/thread2-r0drv-freebsd.c	(revision 3680)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/thread2-r0drv-freebsd.c	(revision 3680)
@@ -0,0 +1,125 @@
+/* $Id$ */
+/** @file
+ * innotek Portable Runtime - Threads (Part 2), Ring-0 Driver, FreeBSD.
+ */
+
+/*
+ * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-freebsd-kernel.h"
+
+#include <iprt/thread.h>
+#include <iprt/err.h>
+#include <iprt/assert.h>
+
+#include "internal/thread.h"
+
+
+int rtThreadNativeInit(void)
+{
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(RTTHREAD) RTThreadSelf(void)
+{
+    return rtThreadGetByNative(RTThreadNativeSelf());
+}
+
+
+int rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
+{
+    int iPriority;
+
+    switch (enmType)
+    {
+        case RTTHREADTYPE_INFREQUENT_POLLER:    iPriority = PZERO + 8;      break;
+        case RTTHREADTYPE_EMULATION:            iPriority = PZERO + 4;      break;
+        case RTTHREADTYPE_DEFAULT:              iPriority = PZERO;          break;
+        case RTTHREADTYPE_MSG_PUMP:             iPriority = PZERO - 4;      break;
+        case RTTHREADTYPE_IO:                   iPriority = PRIBIO;         break;
+        case RTTHREADTYPE_TIMER:                iPriority = PRI_MIN_KERN;   break;
+        default:
+            AssertMsgFailed(("enmType=%d\n", enmType));
+            return VERR_INVALID_PARAMETER;
+    }
+
+    /* Do like they're doing in subr_ntoskrnl.c... */
+    mtx_lock_spin(&sched_lock);
+    sched_prio(curthread, iPriority);
+#if __FreeBSD_version < 600000
+    curthread->td_base_pri = iPriority;
+#endif
+    mtx_unlock_spin(&sched_lock);
+
+    return VINF_SUCCESS;
+}
+
+
+int rtThreadNativeAdopt(PRTTHREADINT pThread)
+{
+    NOREF(pThread);
+    /* There is nothing special that needs doing here, but the
+       user really better know what he's cooking. */
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Native thread main function.
+ *
+ * @param   pvThreadInt     The thread structure.
+ */
+static void rtThreadNativeMain(void *pvThreadInt)
+{
+    const struct thread *Self = curthread;
+    PRTTHREADINT pThreadInt = (PRTTHREADINT)pvThreadInt;
+    int rc;
+
+    rc = rtThreadMain(pThreadInt, (RTNATIVETHREAD)Self, &pThreadInt->szName[0]);
+
+    kthread_exit(rc);
+}
+
+
+int rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread)
+{
+    int rc;
+    struct proc *pProc;
+
+    rc = kthread_create(rtThreadNativeMain, pThreadInt, &pProc, RFHIGHPID, 0, "%s", pThreadInt->szName);
+    if (!rc)
+    {
+        *pNativeThread = (RTNATIVETHREAD)FIRST_THREAD_IN_PROC(pProc);
+        rc = VINF_SUCCESS;
+    }
+    else
+        rc = RTErrConvertFromErrno(rc);
+    return rc;
+}
+
