summaryrefslogtreecommitdiffstats
path: root/src/VBox/Runtime/r0drv/os2
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Runtime/r0drv/os2')
-rw-r--r--src/VBox/Runtime/r0drv/os2/Makefile.kup0
-rw-r--r--src/VBox/Runtime/r0drv/os2/RTR0AssertPanicSystem-r0drv-os2.asm138
-rw-r--r--src/VBox/Runtime/r0drv/os2/RTR0Os2DHQueryDOSVar.asm217
-rw-r--r--src/VBox/Runtime/r0drv/os2/RTR0Os2DHVMGlobalToProcess.asm148
-rw-r--r--src/VBox/Runtime/r0drv/os2/alloc-r0drv-os2.cpp141
-rw-r--r--src/VBox/Runtime/r0drv/os2/assert-r0drv-os2.cpp168
-rw-r--r--src/VBox/Runtime/r0drv/os2/assertA-r0drv-os2.asm81
-rw-r--r--src/VBox/Runtime/r0drv/os2/initterm-r0drv-os2.cpp132
-rw-r--r--src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp633
-rw-r--r--src/VBox/Runtime/r0drv/os2/memuserkernel-r0drv-os2.cpp101
-rw-r--r--src/VBox/Runtime/r0drv/os2/os2imports.imp121
-rw-r--r--src/VBox/Runtime/r0drv/os2/process-r0drv-os2.cpp88
-rw-r--r--src/VBox/Runtime/r0drv/os2/semevent-r0drv-os2.cpp311
-rw-r--r--src/VBox/Runtime/r0drv/os2/semeventmulti-r0drv-os2.cpp321
-rw-r--r--src/VBox/Runtime/r0drv/os2/semfastmutex-r0drv-os2.cpp149
-rw-r--r--src/VBox/Runtime/r0drv/os2/spinlock-r0drv-os2.cpp165
-rw-r--r--src/VBox/Runtime/r0drv/os2/the-os2-kernel.h93
-rw-r--r--src/VBox/Runtime/r0drv/os2/thread-r0drv-os2.cpp225
-rw-r--r--src/VBox/Runtime/r0drv/os2/thread2-r0drv-os2.cpp120
-rw-r--r--src/VBox/Runtime/r0drv/os2/time-r0drv-os2.cpp126
-rw-r--r--src/VBox/Runtime/r0drv/os2/timer-r0drv-os2.cpp419
-rw-r--r--src/VBox/Runtime/r0drv/os2/timerA-r0drv-os2.asm252
22 files changed, 4149 insertions, 0 deletions
diff --git a/src/VBox/Runtime/r0drv/os2/Makefile.kup b/src/VBox/Runtime/r0drv/os2/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/Makefile.kup
diff --git a/src/VBox/Runtime/r0drv/os2/RTR0AssertPanicSystem-r0drv-os2.asm b/src/VBox/Runtime/r0drv/os2/RTR0AssertPanicSystem-r0drv-os2.asm
new file mode 100644
index 00000000..a42f3762
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/RTR0AssertPanicSystem-r0drv-os2.asm
@@ -0,0 +1,138 @@
+; $Id: RTR0AssertPanicSystem-r0drv-os2.asm $
+;; @file
+; IPRT - RTR0AssertPanicSystem, Ring-0 Driver, OS/2.
+;
+
+;
+; Contributed by knut st. osmundsen.
+;
+; Copyright (C) 2007-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; Copyright (c) 1999-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 *
+;*******************************************************************************
+%define RT_INCL_16BIT_SEGMENTS
+%include "iprt/asmdefs.mac"
+
+
+;*******************************************************************************
+;* Defined Constants And Macros *
+;*******************************************************************************
+%define DevHlp_InternalError 02bh
+
+
+;*******************************************************************************
+;* External Symbols *
+;*******************************************************************************
+extern KernThunkStackTo16
+extern KernThunkStackTo32
+extern NAME(g_szRTAssertMsg)
+extern NAME(g_cchRTAssertMsg)
+extern NAME(g_fpfnDevHlp)
+
+
+BEGINCODE
+
+BEGINPROC_EXPORTED RTR0AssertPanicSystem
+ push ebp
+ mov ebp, esp
+ push esi
+ push edi
+ push ds
+
+ ;
+ ; Try detect debug kernel... later one day.
+ ;
+
+
+ ;
+ ; Raise an IPE.
+ ;
+ call KernThunkStackTo16
+ ;jmp far dword NAME(RTR0AssertPanicSystem_16) wrt CODE16
+ db 066h
+ db 0eah
+ dw NAME(RTR0AssertPanicSystem_16) wrt CODE16
+ dw CODE16
+BEGINCODE16
+GLOBALNAME RTR0AssertPanicSystem_16
+ ; mov ax, seg NAME(g_szRTAssertMsg) - makes wlink crash.
+ mov ax, DATA16
+ mov ds, ax
+ mov si, NAME(g_szRTAssertMsg)
+ mov di, [NAME(g_cchRTAssertMsg)]
+ mov dl, DevHlp_InternalError
+ call far [NAME(g_fpfnDevHlp)]
+
+ ; Doesn't normally return, but in case it does...
+ ;jmp far dword NAME(RTR0AssertPanicSystem_32)
+ db 066h
+ db 0eah
+ dd NAME(RTR0AssertPanicSystem_32)
+ dw TEXT32 wrt FLAT
+BEGINCODE32:
+GLOBALNAME RTR0AssertPanicSystem_32
+ call KernThunkStackTo32
+ mov eax, 1
+ pop ds
+ pop edi
+ pop esi
+ leave
+ ret
+ENDPROC RTR0AssertPanicSystem
+
diff --git a/src/VBox/Runtime/r0drv/os2/RTR0Os2DHQueryDOSVar.asm b/src/VBox/Runtime/r0drv/os2/RTR0Os2DHQueryDOSVar.asm
new file mode 100644
index 00000000..681d77eb
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/RTR0Os2DHQueryDOSVar.asm
@@ -0,0 +1,217 @@
+; $Id: RTR0Os2DHQueryDOSVar.asm $
+;; @file
+; IPRT - DevHelp_GetDOSVar, Ring-0 Driver, OS/2.
+;
+
+;
+; Contributed by knut st. osmundsen.
+;
+; Copyright (C) 2007-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; Copyright (c) 1999-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 *
+;*******************************************************************************
+%define RT_INCL_16BIT_SEGMENTS
+%include "iprt/asmdefs.mac"
+%include "iprt/err.mac"
+
+
+;*******************************************************************************
+;* External Symbols *
+;*******************************************************************************
+extern KernThunkStackTo32
+extern KernThunkStackTo16
+extern NAME(g_fpfnDevHlp)
+
+
+;*******************************************************************************
+;* Defined Constants And Macros *
+;*******************************************************************************
+%define DevHlp_GetDOSVar 24h
+
+
+BEGINCODE
+
+;
+; Jump table used by RTR0Os2DHQueryDOSVar
+;
+DosVarJumpTab:
+ dd 0 ; 0 - Reserved
+ dd Load1600 ; 1 - GIS
+ dd Load1616 ; 2 - LIS
+ dd 0 ; 3 - Reserved
+ dd Load1616 ; 4 - VectorSDF
+ dd Load1616 ; 5 - VectorReboot
+ dd Load1616 ; 6 - VectorMSATS
+ dd AsIs ; 7 - YieldFlag (Resched)
+ dd AsIs ; 8 - TCYieldFlag (TCResched)
+ dd AsIs ; 9 - DOSTable
+ dd Load1616 ; a - VectorDEKKO
+ dd AsIs ; b - CodePgBuff
+ dd Load1616 ; c - VectorRIPL
+ dd AsIs ; d - InterruptLevel
+ dd AsIs ; e - DevClassTables
+ dd AsIs ; f - DMQS_Sel
+ dd AsIs ;10 - APMInfo
+ dd LoadWord ;11 - APM_Length (length of above structure)
+DosVarJumpTabEnd:
+%define DosVarJumpTabSize (DosVarJumpTabEnd - DosVarJumpTab) / 4
+
+;;
+; Unified DevHelp_GetDOSVar -> Far 16:16 pointer wrapper.
+;
+; @param iVar [ebp + 08h] Variable.
+; @param iMember [ebp + 0ch] Member.
+; @param pfp [ebp + 10h] Where to store the variable address (pointer to 16:16).
+;
+BEGINPROC_EXPORTED RTR0Os2DHQueryDOSVar
+ ; switch stack first.
+ call KernThunkStackTo16
+
+ ; normal prolog.
+ push ebp
+ mov ebp, esp
+ push dword [NAME(g_fpfnDevHlp)] ; ebp - 4
+ push ebx ; save ebx
+ push es ; save es
+
+ ; setup the devhelp call and switch to
+ mov eax, [ebp + 08h] ; iVar (8-bit)
+ mov ecx, [ebp + 0ch] ; iMember (16-bit)
+ mov dl, DevHlp_GetDOSVar
+
+ ; jump to the 16-bit code.
+ ;jmp far dword NAME(RTR0Os2DHQueryDOSVar_16) wrt CODE16
+ db 066h
+ db 0eah
+ dw NAME(RTR0Os2DHQueryDOSVar_16) wrt CODE16
+ dw CODE16
+BEGINCODE16
+GLOBALNAME RTR0Os2DHQueryDOSVar_16
+ call far [ss:ebp - 4]
+
+ ;jmp far dword NAME(RTR0Os2DHQueryDOSVar) wrt FLAT
+ db 066h
+ db 0eah
+ dd NAME(RTR0Os2DHQueryDOSVar_32) ;wrt FLAT
+ dw TEXT32 wrt FLAT
+BEGINCODE
+GLOBALNAME RTR0Os2DHQueryDOSVar_32
+ jc Error1
+
+ ;
+ ; Make ax:ebx contain the pointer and take action according
+ ; to the variable jump table.
+ ;
+ and ebx, 0000ffffh ; clean high part of ebx
+ movzx ecx, byte [ebp + 08] ; iVar
+ cmp ecx, DosVarJumpTabSize
+ jg Error2
+ jmp [DosVarJumpTab + ecx * 4]
+
+ ; Load Word at ax:ebx.
+LoadWord:
+ mov es, ax
+ movzx edx, word [es:ebx]
+ jmp StoreIt
+
+ ; Load selector at ax:ebx.
+Load1600:
+ mov es, ax
+ movzx edx, word [es:ebx]
+ shl edx, 16
+ jmp StoreIt
+
+ ; Load 16:16 ptr at ax:ebx.
+Load1616:
+ mov es, ax
+ mov edx, dword [es:ebx]
+ jmp StoreIt
+
+ ; Move ax:bx into edx.
+AsIs:
+ mov dx, ax
+ shl edx, 16
+ mov dx, bx
+ jmp StoreIt
+
+Error2:
+ mov eax, VERR_INVALID_PARAMETER
+ jmp Done
+
+Error1:
+ mov eax, VERR_GENERAL_FAILURE
+ jmp Done
+
+StoreIt:
+ mov ecx, [ebp + 10h]
+ mov [ecx], edx
+ xor eax, eax ; return success (VINF_SUCCESS == 0)
+
+Done:
+ pop es
+ pop ebx
+ leave
+
+ ; switch stack back and return.
+ push eax
+ call KernThunkStackTo32
+ pop eax
+ ret
+ENDPROC RTR0Os2DHQueryDOSVar
+
diff --git a/src/VBox/Runtime/r0drv/os2/RTR0Os2DHVMGlobalToProcess.asm b/src/VBox/Runtime/r0drv/os2/RTR0Os2DHVMGlobalToProcess.asm
new file mode 100644
index 00000000..a946080f
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/RTR0Os2DHVMGlobalToProcess.asm
@@ -0,0 +1,148 @@
+; $Id: RTR0Os2DHVMGlobalToProcess.asm $
+;; @file
+; IPRT - DevHelp_VMGlobalToProcess, Ring-0 Driver, OS/2.
+;
+
+;
+; Contributed by knut st. osmundsen.
+;
+; Copyright (C) 2007-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; 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 *
+;*******************************************************************************
+%define RT_INCL_16BIT_SEGMENTS
+%include "iprt/asmdefs.mac"
+%include "iprt/err.mac"
+
+
+;*******************************************************************************
+;* External Symbols *
+;*******************************************************************************
+extern KernThunkStackTo32
+extern KernThunkStackTo16
+extern NAME(g_fpfnDevHlp)
+
+
+;*******************************************************************************
+;* Defined Constants And Macros *
+;*******************************************************************************
+%define DevHlp_VMGlobalToProcess 05ah
+
+
+BEGINCODE
+
+;;
+; VMGlobalToProcess wrapper.
+;
+; @param fFlags [ebp + 08h] Flags
+; @param pvR0 [ebp + 0ch] Ring-0 memory.
+; @param cb [ebp + 10h] Size of memory object to map.
+; @param ppR3 [ebp + 14h] Where to store the address of the ring-3 mapping.
+;
+BEGINPROC_EXPORTED RTR0Os2DHVMGlobalToProcess
+ ; switch stack first.
+ call KernThunkStackTo16
+
+ ; normal prolog.
+ push ebp
+ mov ebp, esp
+ push dword [NAME(g_fpfnDevHlp)] ; ebp - 4
+ push ebx ; save ebx
+
+ ; setup the devhelp call
+ mov eax, [ebp + 08h] ; fFlags
+ mov ebx, [ebp + 0ch] ; pvR0
+ mov ecx, [ebp + 10h] ; cb
+ mov dl, DevHlp_VMGlobalToProcess
+
+ ; jump to the 16-bit code.
+ ;jmp far dword NAME(RTR0Os2DHQueryDOSVar_16) wrt CODE16
+ db 066h
+ db 0eah
+ dw NAME(RTR0Os2DHVMGlobalToProcess_16) wrt CODE16
+ dw CODE16
+BEGINCODE16
+GLOBALNAME RTR0Os2DHVMGlobalToProcess_16
+ call far [ss:ebp - 4]
+
+ ;jmp far dword NAME(RTR0Os2DHVMGlobalToProcess_32) wrt FLAT
+ db 066h
+ db 0eah
+ dd NAME(RTR0Os2DHVMGlobalToProcess_32) ;wrt FLAT
+ dw TEXT32 wrt FLAT
+BEGINCODE
+GLOBALNAME RTR0Os2DHVMGlobalToProcess_32
+ jc .done
+
+ ; save the result.
+ mov edx, [ebp + 14h] ; ppvR3
+ mov [edx], eax
+ xor eax, eax
+
+.done:
+ pop ebx
+ leave
+
+ ; switch stack back and return.
+ push eax
+ call KernThunkStackTo32
+ pop eax
+ ret
+ENDPROC RTR0Os2DHVMGlobalToProcess
+
diff --git a/src/VBox/Runtime/r0drv/os2/alloc-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/alloc-r0drv-os2.cpp
new file mode 100644
index 00000000..c966649e
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/alloc-r0drv-os2.cpp
@@ -0,0 +1,141 @@
+/* $Id: alloc-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Memory Allocation, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/mem.h>
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+#include <iprt/param.h>
+#include "r0drv/alloc-r0drv.h" /** @todo drop the r0drv/alloc-r0drv.cpp stuff on OS/2? */
+
+
+DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr)
+{
+ if (fFlags & RTMEMHDR_FLAG_ANY_CTX)
+ return VERR_NOT_SUPPORTED;
+
+ void *pv = NULL;
+ APIRET rc = KernVMAlloc(cb + sizeof(RTMEMHDR), VMDHA_FIXED, &pv, (void **)-1, NULL);
+ if (RT_UNLIKELY(rc != NO_ERROR))
+ return RTErrConvertFromOS2(rc);
+
+ PRTMEMHDR pHdr = (PRTMEMHDR)pv;
+ pHdr->u32Magic = RTMEMHDR_MAGIC;
+ pHdr->fFlags = fFlags;
+ pHdr->cb = cb;
+ pHdr->cbReq = cb;
+ *ppHdr = pHdr;
+ return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(void) rtR0MemFree(PRTMEMHDR pHdr)
+{
+ pHdr->u32Magic += 1;
+ APIRET rc = KernVMFree(pHdr);
+ Assert(!rc); NOREF(rc);
+}
+
+
+RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb)
+{
+ /*
+ * Validate input.
+ */
+ AssertPtr(pPhys);
+ Assert(cb > 0);
+
+ /*
+ * All physical memory in OS/2 is below 4GB, so this should be kind of easy.
+ */
+ cb = RT_ALIGN_Z(cb, PAGE_SIZE); /* -> page aligned result. */
+ PVOID pv = NULL;
+ PVOID PhysAddr = (PVOID)~0UL;
+ APIRET rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG, &pv, &PhysAddr, NULL);
+ if (!rc)
+ {
+ Assert(PhysAddr != (PVOID)~0UL);
+ Assert(!((uintptr_t)pv & PAGE_OFFSET_MASK));
+ *pPhys = (uintptr_t)PhysAddr;
+ return pv;
+ }
+ return NULL;
+}
+
+
+RTR0DECL(void) RTMemContFree(void *pv, size_t cb)
+{
+ if (pv)
+ {
+ AssertMsg(!((uintptr_t)pv & PAGE_OFFSET_MASK), ("pv=%p\n", pv));
+ KernVMFree(pv);
+ }
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/assert-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/assert-r0drv-os2.cpp
new file mode 100644
index 00000000..27ad1089
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/assert-r0drv-os2.cpp
@@ -0,0 +1,168 @@
+/* $Id: assert-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Assertion Workers, Ring-0 Drivers, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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 <iprt/assert.h>
+#include <iprt/log.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+
+#include <VBox/log.h>
+
+#include "internal/assert.h"
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+RT_C_DECLS_BEGIN /* for watcom */
+/** The last assert message. (in DATA16) */
+extern char g_szRTAssertMsg[2048];
+/** The length of the last assert message. (in DATA16) */
+extern size_t g_cchRTAssertMsg;
+RT_C_DECLS_END
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+static DECLCALLBACK(size_t) rtR0Os2AssertOutputCB(void *pvArg, const char *pachChars, size_t cbChars);
+
+
+DECLHIDDEN(void) rtR0AssertNativeMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
+{
+#if defined(DEBUG_bird)
+ RTLogComPrintf("\n!!Assertion Failed!!\n"
+ "Expression: %s\n"
+ "Location : %s(%d) %s\n",
+ pszExpr, pszFile, uLine, pszFunction);
+#endif
+
+ g_cchRTAssertMsg = RTStrPrintf(g_szRTAssertMsg, sizeof(g_szRTAssertMsg),
+ "\r\n!!Assertion Failed!!\r\n"
+ "Expression: %s\r\n"
+ "Location : %s(%d) %s\r\n",
+ pszExpr, pszFile, uLine, pszFunction);
+}
+
+
+DECLHIDDEN(void) rtR0AssertNativeMsg2V(bool fInitial, const char *pszFormat, va_list va)
+{
+#if defined(DEBUG_bird)
+ va_list vaCopy;
+ va_copy(vaCopy, va);
+ RTLogComPrintfV(pszFormat, vaCopy);
+ va_end(vaCopy);
+#endif
+
+ size_t cch = g_cchRTAssertMsg;
+ char *pch = &g_szRTAssertMsg[cch];
+ cch += RTStrFormatV(rtR0Os2AssertOutputCB, &pch, NULL, NULL, pszFormat, va);
+ g_cchRTAssertMsg = cch;
+
+ NOREF(fInitial);
+}
+
+
+/**
+ * Output callback.
+ *
+ * @returns number of bytes written.
+ * @param pvArg Pointer to a char pointer with the current output position.
+ * @param pachChars Pointer to an array of utf-8 characters.
+ * @param cbChars Number of bytes in the character array pointed to by pachChars.
+ */
+static DECLCALLBACK(size_t) rtR0Os2AssertOutputCB(void *pvArg, const char *pachChars, size_t cbChars)
+{
+ char **ppch = (char **)pvArg;
+ char *pch = *ppch;
+
+ while (cbChars-- > 0)
+ {
+ const char ch = *pachChars++;
+ if (ch == '\r')
+ continue;
+ if (ch == '\n')
+ {
+ if (pch + 1 >= &g_szRTAssertMsg[sizeof(g_szRTAssertMsg)])
+ break;
+ *pch++ = '\r';
+ }
+ if (pch + 1 >= &g_szRTAssertMsg[sizeof(g_szRTAssertMsg)])
+ break;
+ *pch++ = ch;
+ }
+ *pch = '\0';
+
+ size_t cbWritten = pch - *ppch;
+ *ppch = pch;
+ return cbWritten;
+}
+
+
+/* RTR0AssertPanicSystem is implemented in RTR0AssertPanicSystem-r0drv-os2.asm */
+
diff --git a/src/VBox/Runtime/r0drv/os2/assertA-r0drv-os2.asm b/src/VBox/Runtime/r0drv/os2/assertA-r0drv-os2.asm
new file mode 100644
index 00000000..e3e34715
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/assertA-r0drv-os2.asm
@@ -0,0 +1,81 @@
+; $Id: assertA-r0drv-os2.asm $
+;; @file
+; IPRT - DevHelp_GetDOSVar, Ring-0 Driver, OS/2.
+;
+
+;
+; Contributed by knut st. osmundsen.
+;
+; Copyright (C) 2007-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; Copyright (c) 1999-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 *
+;*******************************************************************************
+%define RT_INCL_16BIT_SEGMENTS
+%include "iprt/asmdefs.mac"
+
+BEGINDATA16
+
+;; The last assert message. (see assert-r0drv-os2.cpp)
+EXPORTEDNAME g_szRTAssertMsg
+times 2048 db 0
+
+;; The length of the last assert message.
+EXPORTEDNAME g_cchRTAssertMsg
+ dd 0
+
diff --git a/src/VBox/Runtime/r0drv/os2/initterm-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/initterm-r0drv-os2.cpp
new file mode 100644
index 00000000..98821c29
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/initterm-r0drv-os2.cpp
@@ -0,0 +1,132 @@
+/* $Id: initterm-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Initialization & Termination, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+
+#include "internal/initterm.h"
+#include <iprt/errcore.h>
+#include <iprt/assert.h>
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** Pointer to the 1st DOS variable table. */
+PCDOSTABLE g_pDosTable = NULL;
+/** Pointer to the 2nd DOS variable table. */
+PCDOSTABLE2 g_pDosTable2 = NULL;
+/** Pointer to the global info segment. */
+PGINFOSEG g_pGIS = NULL;
+/** Far 16:16 pointer to the local info segment.
+ * IIRC this must be converted to a flat pointer when accessed to work correctly on SMP systems. */
+RTFAR16 g_fpLIS = {0, 0};
+
+
+DECLHIDDEN(int) rtR0InitNative(void)
+{
+ /*
+ * Get the DOS Tables.
+ */
+ RTFAR16 fp;
+ int rc = RTR0Os2DHQueryDOSVar(DHGETDOSV_DOSTABLES, 0, &fp);
+ AssertMsgReturn(!rc, ("rc=%d\n", rc), VERR_INTERNAL_ERROR);
+ g_pDosTable = (PCDOSTABLE)RTR0Os2Virt2Flat(fp);
+ AssertReturn(g_pDosTable, VERR_INTERNAL_ERROR);
+ g_pDosTable2 = (PCDOSTABLE2)((const uint8_t *)g_pDosTable + g_pDosTable->cul * sizeof(ULONG) + 1);
+
+ /*
+ * Get the addresses of the two info segments.
+ */
+ rc = RTR0Os2DHQueryDOSVar(DHGETDOSV_SYSINFOSEG, 0, &fp);
+ AssertMsgReturn(!rc, ("rc=%d\n", rc), VERR_INTERNAL_ERROR);
+ g_pGIS = (PGINFOSEG)RTR0Os2Virt2Flat(fp);
+ rc = RTR0Os2DHQueryDOSVar(DHGETDOSV_LOCINFOSEG, 0, &fp);
+ AssertMsgReturn(!rc, ("rc=%d\n", rc), VERR_INTERNAL_ERROR);
+ g_fpLIS = fp;
+
+ return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(void) rtR0TermNative(void)
+{
+ /* nothing to do here yet. */
+}
+
+
+/**
+ * Converts a 16:16 pointer to a flat pointer.
+ *
+ * @returns Flat pointer (NULL if fp is NULL).
+ * @param fp Far pointer to convert.
+ */
+RTR0DECL(void *) RTR0Os2Virt2Flat(RTFAR16 fp)
+{
+ return (void *)KernSelToFlat(((uint32_t)fp.sel << 16) | fp.off);
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp
new file mode 100644
index 00000000..b79a0424
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp
@@ -0,0 +1,633 @@
+/* $Id: memobj-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Ring-0 Memory Objects, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+
+#include <iprt/memobj.h>
+#include <iprt/mem.h>
+#include <iprt/err.h>
+#include <iprt/assert.h>
+#include <iprt/log.h>
+#include <iprt/param.h>
+#include <iprt/process.h>
+#include "internal/memobj.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * The OS/2 version of the memory object structure.
+ */
+typedef struct RTR0MEMOBJDARWIN
+{
+ /** The core structure. */
+ RTR0MEMOBJINTERNAL Core;
+ /** Lock for the ring-3 / ring-0 pinned objectes.
+ * This member might not be allocated for some object types. */
+ KernVMLock_t Lock;
+ /** Array of physical pages.
+ * This array can be 0 in length for some object types. */
+ KernPageList_t aPages[1];
+} RTR0MEMOBJOS2, *PRTR0MEMOBJOS2;
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+static void rtR0MemObjFixPageList(KernPageList_t *paPages, ULONG cPages, ULONG cPagesRet);
+
+
+DECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
+{
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)pMem;
+ int rc;
+
+ switch (pMemOs2->Core.enmType)
+ {
+ case RTR0MEMOBJTYPE_PHYS_NC:
+ AssertMsgFailed(("RTR0MEMOBJTYPE_PHYS_NC\n"));
+ return VERR_INTERNAL_ERROR;
+
+ case RTR0MEMOBJTYPE_PHYS:
+ if (!pMemOs2->Core.pv)
+ break;
+
+ case RTR0MEMOBJTYPE_MAPPING:
+ if (pMemOs2->Core.u.Mapping.R0Process == NIL_RTR0PROCESS)
+ break;
+
+ RT_FALL_THRU();
+ case RTR0MEMOBJTYPE_PAGE:
+ case RTR0MEMOBJTYPE_LOW:
+ case RTR0MEMOBJTYPE_CONT:
+ rc = KernVMFree(pMemOs2->Core.pv);
+ AssertMsg(!rc, ("rc=%d type=%d pv=%p cb=%#zx\n", rc, pMemOs2->Core.enmType, pMemOs2->Core.pv, pMemOs2->Core.cb));
+ break;
+
+ case RTR0MEMOBJTYPE_LOCK:
+ rc = KernVMUnlock(&pMemOs2->Lock);
+ AssertMsg(!rc, ("rc=%d\n", rc));
+ break;
+
+ case RTR0MEMOBJTYPE_RES_VIRT:
+ default:
+ AssertMsgFailed(("enmType=%d\n", pMemOs2->Core.enmType));
+ return VERR_INTERNAL_ERROR;
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable, const char *pszTag)
+{
+ NOREF(fExecutable);
+
+ /* create the object. */
+ const ULONG cPages = cb >> PAGE_SHIFT;
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF_DYN(RTR0MEMOBJOS2, aPages[cPages]),
+ RTR0MEMOBJTYPE_PAGE, NULL, cb, pszTag);
+ if (pMemOs2)
+ {
+ /* do the allocation. */
+ int rc = KernVMAlloc(cb, VMDHA_FIXED, &pMemOs2->Core.pv, (PPVOID)-1, NULL);
+ if (!rc)
+ {
+ ULONG cPagesRet = cPages;
+ rc = KernLinToPageList(pMemOs2->Core.pv, cb, &pMemOs2->aPages[0], &cPagesRet);
+ if (!rc)
+ {
+ rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet);
+ pMemOs2->Core.fFlags |= RTR0MEMOBJ_FLAGS_UNINITIALIZED_AT_ALLOC; /* doesn't seem to be possible to zero anything */
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ KernVMFree(pMemOs2->Core.pv);
+ }
+ rtR0MemObjDelete(&pMemOs2->Core);
+ return RTErrConvertFromOS2(rc);
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocLarge(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, size_t cbLargePage, uint32_t fFlags,
+ const char *pszTag)
+{
+ return rtR0MemObjFallbackAllocLarge(ppMem, cb, cbLargePage, fFlags, pszTag);
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable, const char *pszTag)
+{
+ NOREF(fExecutable);
+
+ /* create the object. */
+ const ULONG cPages = cb >> PAGE_SHIFT;
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF_DYN(RTR0MEMOBJOS2, aPages[cPages]),
+ RTR0MEMOBJTYPE_LOW, NULL, cb, pszTag);
+ if (pMemOs2)
+ {
+ /* do the allocation. */
+ int rc = KernVMAlloc(cb, VMDHA_FIXED, &pMemOs2->Core.pv, (PPVOID)-1, NULL);
+ if (!rc)
+ {
+ ULONG cPagesRet = cPages;
+ rc = KernLinToPageList(pMemOs2->Core.pv, cb, &pMemOs2->aPages[0], &cPagesRet);
+ if (!rc)
+ {
+ rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet);
+ pMemOs2->Core.fFlags |= RTR0MEMOBJ_FLAGS_UNINITIALIZED_AT_ALLOC; /* doesn't seem to be possible to zero anything */
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ KernVMFree(pMemOs2->Core.pv);
+ }
+ rtR0MemObjDelete(&pMemOs2->Core);
+ rc = RTErrConvertFromOS2(rc);
+ return rc == VERR_NO_MEMORY ? VERR_NO_LOW_MEMORY : rc;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable, const char *pszTag)
+{
+ NOREF(fExecutable);
+
+ /* create the object. */
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_CONT,
+ NULL, cb, pszTag);
+ if (pMemOs2)
+ {
+ /* do the allocation. */
+ ULONG ulPhys = ~0UL;
+ int rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG, &pMemOs2->Core.pv, (PPVOID)&ulPhys, NULL);
+ if (!rc)
+ {
+ Assert(ulPhys != ~0UL);
+ pMemOs2->Core.fFlags |= RTR0MEMOBJ_FLAGS_UNINITIALIZED_AT_ALLOC; /* doesn't seem to be possible to zero anything */
+ pMemOs2->Core.u.Cont.Phys = ulPhys;
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ rtR0MemObjDelete(&pMemOs2->Core);
+ return RTErrConvertFromOS2(rc);
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment,
+ const char *pszTag)
+{
+ AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%RHp\n", PhysHighest), VERR_NOT_SUPPORTED);
+
+ /** @todo alignment */
+ if (uAlignment != PAGE_SIZE)
+ return VERR_NOT_SUPPORTED;
+
+ /* create the object. */
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_PHYS,
+ NULL, cb, pszTag);
+ if (pMemOs2)
+ {
+ /* do the allocation. */
+ ULONG ulPhys = ~0UL;
+ int rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG | (PhysHighest < _4G ? VMDHA_16M : 0),
+ &pMemOs2->Core.pv, (PPVOID)&ulPhys, NULL);
+ if (!rc)
+ {
+ Assert(ulPhys != ~0UL);
+ pMemOs2->Core.fFlags |= RTR0MEMOBJ_FLAGS_UNINITIALIZED_AT_ALLOC; /* doesn't seem to be possible to zero anything */
+ pMemOs2->Core.u.Phys.fAllocated = true;
+ pMemOs2->Core.u.Phys.PhysBase = ulPhys;
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ rtR0MemObjDelete(&pMemOs2->Core);
+ return RTErrConvertFromOS2(rc);
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, const char *pszTag)
+{
+ /** @todo rtR0MemObjNativeAllocPhysNC / os2. */
+ return rtR0MemObjNativeAllocPhys(ppMem, cb, PhysHighest, PAGE_SIZE, pszTag);
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy,
+ const char *pszTag)
+{
+ AssertReturn(uCachePolicy == RTMEM_CACHE_POLICY_DONT_CARE, VERR_NOT_SUPPORTED);
+
+ /* create the object. */
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_PHYS,
+ NULL, cb, pszTag);
+ if (pMemOs2)
+ {
+ /* there is no allocation here, right? it needs to be mapped somewhere first. */
+ pMemOs2->Core.u.Phys.fAllocated = false;
+ pMemOs2->Core.u.Phys.PhysBase = Phys;
+ pMemOs2->Core.u.Phys.uCachePolicy = uCachePolicy;
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess,
+ RTR0PROCESS R0Process, const char *pszTag)
+{
+ AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
+
+ /* create the object. */
+ const ULONG cPages = cb >> PAGE_SHIFT;
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF_DYN(RTR0MEMOBJOS2, aPages[cPages]),
+ RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb, pszTag);
+ if (pMemOs2)
+ {
+ /* lock it. */
+ ULONG cPagesRet = cPages;
+ int rc = KernVMLock(VMDHL_LONG | (fAccess & RTMEM_PROT_WRITE ? VMDHL_WRITE : 0),
+ (void *)R3Ptr, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet);
+ if (!rc)
+ {
+ rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet);
+ Assert(cb == pMemOs2->Core.cb);
+ Assert(R3Ptr == (RTR3PTR)pMemOs2->Core.pv);
+ pMemOs2->Core.u.Lock.R0Process = R0Process;
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ rtR0MemObjDelete(&pMemOs2->Core);
+ return RTErrConvertFromOS2(rc);
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess, const char *pszTag)
+{
+ /* create the object. */
+ const ULONG cPages = cb >> PAGE_SHIFT;
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF_DYN(RTR0MEMOBJOS2, aPages[cPages]),
+ RTR0MEMOBJTYPE_LOCK, pv, cb, pszTag);
+ if (pMemOs2)
+ {
+ /* lock it. */
+ ULONG cPagesRet = cPages;
+ int rc = KernVMLock(VMDHL_LONG | (fAccess & RTMEM_PROT_WRITE ? VMDHL_WRITE : 0),
+ pv, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet);
+ if (!rc)
+ {
+ rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet);
+ pMemOs2->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ rtR0MemObjDelete(&pMemOs2->Core);
+ return RTErrConvertFromOS2(rc);
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment,
+ const char *pszTag)
+{
+ RT_NOREF(ppMem, pvFixed, cb, uAlignment, pszTag);
+ return VERR_NOT_SUPPORTED;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment,
+ RTR0PROCESS R0Process, const char *pszTag)
+{
+ RT_NOREF(ppMem, R3PtrFixed, cb, uAlignment, R0Process, pszTag);
+ return VERR_NOT_SUPPORTED;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
+ unsigned fProt, size_t offSub, size_t cbSub, const char *pszTag)
+{
+ AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPORTED);
+
+ /*
+ * Check that the specified alignment is supported.
+ */
+ if (uAlignment > PAGE_SIZE)
+ return VERR_NOT_SUPPORTED;
+
+/** @todo finish the implementation. */
+
+ int rc;
+ void *pvR0 = NULL;
+ PRTR0MEMOBJOS2 pMemToMapOs2 = (PRTR0MEMOBJOS2)pMemToMap;
+ switch (pMemToMapOs2->Core.enmType)
+ {
+ /*
+ * These has kernel mappings.
+ */
+ case RTR0MEMOBJTYPE_PAGE:
+ case RTR0MEMOBJTYPE_LOW:
+ case RTR0MEMOBJTYPE_CONT:
+ pvR0 = pMemToMapOs2->Core.pv;
+ break;
+
+ case RTR0MEMOBJTYPE_PHYS:
+ pvR0 = pMemToMapOs2->Core.pv;
+ if (!pvR0)
+ {
+ /* no ring-0 mapping, so allocate a mapping in the process. */
+ AssertMsgReturn(fProt & RTMEM_PROT_WRITE, ("%#x\n", fProt), VERR_NOT_SUPPORTED);
+ Assert(!pMemToMapOs2->Core.u.Phys.fAllocated);
+ ULONG ulPhys = (ULONG)pMemToMapOs2->Core.u.Phys.PhysBase;
+ AssertReturn(ulPhys == pMemToMapOs2->Core.u.Phys.PhysBase, VERR_OUT_OF_RANGE);
+ rc = KernVMAlloc(pMemToMapOs2->Core.cb, VMDHA_PHYS, &pvR0, (PPVOID)&ulPhys, NULL);
+ if (rc)
+ return RTErrConvertFromOS2(rc);
+ pMemToMapOs2->Core.pv = pvR0;
+ }
+ break;
+
+ case RTR0MEMOBJTYPE_PHYS_NC:
+ AssertMsgFailed(("RTR0MEMOBJTYPE_PHYS_NC\n"));
+ return VERR_INTERNAL_ERROR_3;
+
+ case RTR0MEMOBJTYPE_LOCK:
+ if (pMemToMapOs2->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
+ return VERR_NOT_SUPPORTED; /** @todo implement this... */
+ pvR0 = pMemToMapOs2->Core.pv;
+ break;
+
+ case RTR0MEMOBJTYPE_RES_VIRT:
+ case RTR0MEMOBJTYPE_MAPPING:
+ default:
+ AssertMsgFailed(("enmType=%d\n", pMemToMapOs2->Core.enmType));
+ return VERR_INTERNAL_ERROR;
+ }
+
+ /*
+ * Create a dummy mapping object for it.
+ *
+ * All mappings are read/write/execute in OS/2 and there isn't
+ * any cache options, so sharing is ok. And the main memory object
+ * isn't actually freed until all the mappings have been freed up
+ * (reference counting).
+ */
+ if (!cbSub)
+ cbSub = pMemToMapOs2->Core.cb - offSub;
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING,
+ (uint8_t *)pvR0 + offSub, cbSub, pszTag);
+ if (pMemOs2)
+ {
+ pMemOs2->Core.u.Mapping.R0Process = NIL_RTR0PROCESS;
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
+ unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub, const char *pszTag)
+{
+ AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
+ AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
+ if (uAlignment > PAGE_SIZE)
+ return VERR_NOT_SUPPORTED;
+ AssertMsgReturn(!offSub && !cbSub, ("%#zx %#zx\n", offSub, cbSub), VERR_NOT_SUPPORTED); /** @todo implement sub maps */
+
+ int rc;
+ void *pvR0;
+ void *pvR3 = NULL;
+ PRTR0MEMOBJOS2 pMemToMapOs2 = (PRTR0MEMOBJOS2)pMemToMap;
+ switch (pMemToMapOs2->Core.enmType)
+ {
+ /*
+ * These has kernel mappings.
+ */
+ case RTR0MEMOBJTYPE_PAGE:
+ case RTR0MEMOBJTYPE_LOW:
+ case RTR0MEMOBJTYPE_CONT:
+ pvR0 = pMemToMapOs2->Core.pv;
+ break;
+
+ case RTR0MEMOBJTYPE_PHYS:
+ pvR0 = pMemToMapOs2->Core.pv;
+#if 0/* this is wrong. */
+ if (!pvR0)
+ {
+ /* no ring-0 mapping, so allocate a mapping in the process. */
+ AssertMsgReturn(fProt & RTMEM_PROT_WRITE, ("%#x\n", fProt), VERR_NOT_SUPPORTED);
+ Assert(!pMemToMapOs2->Core.u.Phys.fAllocated);
+ ULONG ulPhys = pMemToMapOs2->Core.u.Phys.PhysBase;
+ rc = KernVMAlloc(pMemToMapOs2->Core.cb, VMDHA_PHYS | VMDHA_PROCESS, &pvR3, (PPVOID)&ulPhys, NULL);
+ if (rc)
+ return RTErrConvertFromOS2(rc);
+ }
+ break;
+#endif
+ return VERR_NOT_SUPPORTED;
+
+ case RTR0MEMOBJTYPE_PHYS_NC:
+ AssertMsgFailed(("RTR0MEMOBJTYPE_PHYS_NC\n"));
+ return VERR_INTERNAL_ERROR_5;
+
+ case RTR0MEMOBJTYPE_LOCK:
+ if (pMemToMapOs2->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
+ return VERR_NOT_SUPPORTED; /** @todo implement this... */
+ pvR0 = pMemToMapOs2->Core.pv;
+ break;
+
+ case RTR0MEMOBJTYPE_RES_VIRT:
+ case RTR0MEMOBJTYPE_MAPPING:
+ default:
+ AssertMsgFailed(("enmType=%d\n", pMemToMapOs2->Core.enmType));
+ return VERR_INTERNAL_ERROR;
+ }
+
+ /*
+ * Map the ring-0 memory into the current process.
+ */
+ if (!pvR3)
+ {
+ Assert(pvR0);
+ ULONG flFlags = 0;
+ if (uAlignment == PAGE_SIZE)
+ flFlags |= VMDHGP_4MB;
+ if (fProt & RTMEM_PROT_WRITE)
+ flFlags |= VMDHGP_WRITE;
+ rc = RTR0Os2DHVMGlobalToProcess(flFlags, pvR0, pMemToMapOs2->Core.cb, &pvR3);
+ if (rc)
+ return RTErrConvertFromOS2(rc);
+ }
+ Assert(pvR3);
+
+ /*
+ * Create a mapping object for it.
+ */
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING,
+ pvR3, pMemToMapOs2->Core.cb, pszTag);
+ if (pMemOs2)
+ {
+ Assert(pMemOs2->Core.pv == pvR3);
+ pMemOs2->Core.u.Mapping.R0Process = R0Process;
+ *ppMem = &pMemOs2->Core;
+ return VINF_SUCCESS;
+ }
+ KernVMFree(pvR3);
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
+{
+ NOREF(pMem);
+ NOREF(offSub);
+ NOREF(cbSub);
+ NOREF(fProt);
+ return VERR_NOT_SUPPORTED;
+}
+
+
+DECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
+{
+ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)pMem;
+
+ switch (pMemOs2->Core.enmType)
+ {
+ case RTR0MEMOBJTYPE_PAGE:
+ case RTR0MEMOBJTYPE_LOW:
+ case RTR0MEMOBJTYPE_LOCK:
+ case RTR0MEMOBJTYPE_PHYS_NC:
+ return pMemOs2->aPages[iPage].Addr;
+
+ case RTR0MEMOBJTYPE_CONT:
+ return pMemOs2->Core.u.Cont.Phys + (iPage << PAGE_SHIFT);
+
+ case RTR0MEMOBJTYPE_PHYS:
+ return pMemOs2->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT);
+
+ case RTR0MEMOBJTYPE_RES_VIRT:
+ case RTR0MEMOBJTYPE_MAPPING:
+ default:
+ return NIL_RTHCPHYS;
+ }
+}
+
+
+/**
+ * Expands the page list so we can index pages directly.
+ *
+ * @param paPages The page list array to fix.
+ * @param cPages The number of pages that's supposed to go into the list.
+ * @param cPagesRet The actual number of pages in the list.
+ */
+static void rtR0MemObjFixPageList(KernPageList_t *paPages, ULONG cPages, ULONG cPagesRet)
+{
+ Assert(cPages >= cPagesRet);
+ if (cPages != cPagesRet)
+ {
+ ULONG iIn = cPagesRet;
+ ULONG iOut = cPages;
+ do
+ {
+ iIn--;
+ iOut--;
+ Assert(iIn <= iOut);
+
+ KernPageList_t Page = paPages[iIn];
+ Assert(!(Page.Addr & PAGE_OFFSET_MASK));
+ Assert(Page.Size == RT_ALIGN_Z(Page.Size, PAGE_SIZE));
+
+ if (Page.Size > PAGE_SIZE)
+ {
+ do
+ {
+ Page.Size -= PAGE_SIZE;
+ paPages[iOut].Addr = Page.Addr + Page.Size;
+ paPages[iOut].Size = PAGE_SIZE;
+ iOut--;
+ } while (Page.Size > PAGE_SIZE);
+ }
+
+ paPages[iOut].Addr = Page.Addr;
+ paPages[iOut].Size = PAGE_SIZE;
+ } while ( iIn != iOut
+ && iIn > 0);
+ }
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/memuserkernel-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/memuserkernel-r0drv-os2.cpp
new file mode 100644
index 00000000..eb4825a3
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/memuserkernel-r0drv-os2.cpp
@@ -0,0 +1,101 @@
+/* $Id: memuserkernel-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - User & Kernel Memory, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Copyright (C) 2009-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include "the-os2-kernel.h"
+
+#include <iprt/mem.h>
+#include <iprt/errcore.h>
+
+
+RTR0DECL(int) RTR0MemUserCopyFrom(void *pvDst, RTR3PTR R3PtrSrc, size_t cb)
+{
+ int rc = KernCopyIn(pvDst, (void *)R3PtrSrc, cb);
+ if (RT_LIKELY(rc == 0))
+ return VINF_SUCCESS;
+ return VERR_ACCESS_DENIED;
+}
+
+
+RTR0DECL(int) RTR0MemUserCopyTo(RTR3PTR R3PtrDst, void const *pvSrc, size_t cb)
+{
+ int rc = KernCopyOut((void *)R3PtrDst, (void *)pvSrc, cb);
+ if (RT_LIKELY(rc == 0))
+ return VINF_SUCCESS;
+ return VERR_ACCESS_DENIED;
+}
+
+
+RTR0DECL(bool) RTR0MemUserIsValidAddr(RTR3PTR R3Ptr)
+{
+ /** @todo this is all wrong, but I'm too lazy to figure out how to make it
+ * correct. Checking the user DS limit would work if it wasn't maxed
+ * out by SDD, VPC or someone. The version (+SMP) would help on older
+ * OS/2 versions where the limit is 512MB. */
+ return R3Ptr < UINT32_C(0xc0000000); /* 3GB */
+}
+
+
+RTR0DECL(bool) RTR0MemKernelIsValidAddr(void *pv)
+{
+ /** @todo this is all wrong, see RTR0MemUserIsValidAddr. */
+ return (uintptr_t)pv >= UINT32_C(0x20000000); /* 512MB */
+}
+
+
+RTR0DECL(bool) RTR0MemAreKrnlAndUsrDifferent(void)
+{
+ /** @todo this is all wrong, see RTR0MemUserIsValidAddr. */
+ return false;
+}
+
+
+RTR0DECL(int) RTR0MemKernelCopyFrom(void *pvDst, void const *pvSrc, size_t cb)
+{
+ RT_NOREF(pvDst, pvSrc, cb);
+ return VERR_NOT_SUPPORTED;
+}
+
+
+RTR0DECL(int) RTR0MemKernelCopyTo(void *pvDst, void const *pvSrc, size_t cb)
+{
+ RT_NOREF(pvDst, pvSrc, cb);
+ return VERR_NOT_SUPPORTED;
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/os2imports.imp b/src/VBox/Runtime/r0drv/os2/os2imports.imp
new file mode 100644
index 00000000..26feb406
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/os2imports.imp
@@ -0,0 +1,121 @@
+;
+; DOSCALLS
+;
+DOS16OPEN DOSCALLS 70 ?
+DOS16CLOSE DOSCALLS 59 ?
+DOS16READ DOSCALLS 137 ?
+DOS16WRITE DOSCALL1 138 ?
+DOS16IREAD DOSCALL1 79 ?
+DOS16IWRITE DOSCALL1 87 ?
+DOS16DEVIOCTL DOSCALL1 53 ?
+DOS16DEVIOCTL2 DOSCALL1 99 ?
+DOS16FSATTACH DOSCALL1 181 ?
+DOS16FSCTL DOSCALL1 183 ?
+
+;
+; KEE
+;
+KernAllocSpinLock KEE 10 ?
+KernFreeSpinLock KEE 11 ?
+KernAcquireSpinLock KEE 12 ?
+KernReleaseSpinLock KEE 13 ?
+KernAllocMutexLock KEE 20 ?
+KernFreeMutexLock KEE 21 ?
+KernRequestSharedMutex KEE 22 ?
+KernReleaseSharedMutex KEE 23 ?
+KernTryRequestSharedMutex KEE 24 ?
+KernRequestExclusiveMutex KEE 25 ?
+KernReleaseExclusiveMutex KEE 26 ?
+KernTryRequestExclusiveMutex KEE 27 ?
+KernBlock KEE 30 ?
+KernWakeup KEE 31 ?
+KernThunkStackTo16 KEE 40 ?
+KernThunkStackTo32 KEE 41 ?
+KernSerialize16BitDD KEE 42 ?
+KernUnserialize16BitDD KEE 43 ?
+KernArmHook KEE 44 ?
+KernAllocateContextHook KEE 45 ?
+KernCopyIn KEE 50 ?
+KernCopyOut KEE 51 ?
+KernVMAlloc KEE 60 ?
+KernVMFree KEE 61 ?
+KernVMLock KEE 62 ?
+KernVMUnlock KEE 63 ?
+KernLinToPageList KEE 64 ?
+KernVMSetMem KEE 65 ?
+KernSelToFlat KEE 66 ?
+KernDynamicAPI KEE 70 ?
+KernRASSysTrace KEE 80 ?
+KernPerfSysTrace KEE 81 ?
+_KernSISData KEE 90 ?
+_KernLISData KEE 91 ?
+_KernInterruptLevel KEE 92 ?
+_KernTKSSBase KEE 93 ?
+_KernKEEVersion KEE 94 ?
+KernLockFile KEE 100 ?
+KernUnLockFile KEE 101 ?
+KernGetFileSize KEE 102 ?
+KernTestFileCache KEE 103 ?
+KernReadFileAt KEE 104 ?
+KernReadFileAtCache KEE 105 ?
+KernReturnFileCache KEE 106 ?
+KernCreateUconvObject KEE 120 ?
+KernStrFromUcs KEE 121 ?
+KernStrToUcs KEE 122 ?
+
+FSH_SEGALLOC FSHELPER 1 ?
+FSH_SEGFREE FSHELPER 2 ?
+FSH_SEGREALLOC FSHELPER 3 ?
+FSH_FORCENOSWAP FSHELPER 4 ?
+FSH_INTERR FSHELPER 5 ?
+FSH_SEMREQUEST FSHELPER 6 ?
+FSH_SEMCLEAR FSHELPER 7 ?
+FSH_PROBEBUF FSHELPER 8 ?
+FSH_GETPRIORITY FSHELPER 9 ?
+FSH_IOSEMCLEAR FSHELPER 10 ?
+FSH_FLUSHBUF FSHELPER 11 ?
+FSH_CRITERROR FSHELPER 12 ?
+FSH_DEVIOCTL FSHELPER 13 ?
+FSH_GETVOLPARM FSHELPER 14 ?
+FSH_FINDDUPHVPB FSHELPER 15 ?
+FSH_DOVOLIO FSHELPER 16 ?
+FSH_ADDSHARE FSHELPER 17 ?
+FSH_REMOVESHARE FSHELPER 18 ?
+FSH_GETOVERLAPBUF FSHELPER 19 ?
+FSH_ISCURDIRPREFIX FSHELPER 20 ?
+FSH_LOADCHAR FSHELPER 21 ?
+FSH_PREVCHAR FSHELPER 22 ?
+FSH_STORECHAR FSHELPER 23 ?
+FSH_SEMSET FSHELPER 24 ?
+FSH_SEMSETWAIT FSHELPER 25 ?
+FSH_SEMWAIT FSHELPER 26 ?
+FSH_WILDMATCH FSHELPER 27 ?
+FSH_YIELD FSHELPER 28 ?
+FSH_DOVOLIO2 FSHELPER 29 ?
+FSH_FINDCHAR FSHELPER 30 ?
+MFSH_SETBOOTDRIVE FSHELPER 31 ?
+FSH_CANONICALIZE FSHELPER 32 ?
+MFSH_DOVOLIO FSHELPER 33 ?
+MFSH_INTERR FSHELPER 34 ?
+MFSH_SEGALLOC FSHELPER 35 ?
+MFSH_SEGFREE FSHELPER 36 ?
+MFSH_SEGREALLOC FSHELPER 37 ?
+MFSH_CALLRM FSHELPER 38 ?
+MFSH_LOCK FSHELPER 39 ?
+MFSH_PHYSTOVIRT FSHELPER 40 ?
+MFSH_UNLOCK FSHELPER 41 ?
+MFSH_UNPHYSTOVIRT FSHELPER 42 ?
+MFSH_VIRT2PHYS FSHELPER 43 ?
+FSH_QSYSINFO FSHELPER 44 ?
+FSH_NAMEFROMSFN FSHELPER 45 ?
+FSH_UPPERCASE FSHELPER 46 ?
+FSH_CHECKEANAME FSHELPER 47 ?
+FSH_CALLDRIVER FSHELPER 48 ?
+FSH_SETVOLUME FSHELPER 49 ?
+FSH_STACKSPACE FSHELPER 50 ?
+FSH_REGISTERPERFCTRS FSHELPER 51 ?
+FSH_IOBOOST FSHELPER 52 ?
+FSH_QUERYSERVERTHREAD FSHELPER 53 ?
+FSH_QUERYOPLOCK FSHELPER 54 ?
+FSH_EXTENDTIMESLICE FSHELPER 55 ?
+
diff --git a/src/VBox/Runtime/r0drv/os2/process-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/process-r0drv-os2.cpp
new file mode 100644
index 00000000..e128c0c6
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/process-r0drv-os2.cpp
@@ -0,0 +1,88 @@
+/* $Id: process-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Process Management, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+
+#include <iprt/process.h>
+#include <iprt/assert.h>
+
+
+RTDECL(RTPROCESS) RTProcSelf(void)
+{
+ PLINFOSEG pLIS = (PLINFOSEG)RTR0Os2Virt2Flat(g_fpLIS);
+ AssertReturn(pLIS, NIL_RTPROCESS);
+ return pLIS->pidCurrent;
+}
+
+
+RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void)
+{
+ /* make this ptda later... */
+ return (RTR0PROCESS)RTProcSelf();
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/semevent-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/semevent-r0drv-os2.cpp
new file mode 100644
index 00000000..22825633
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/semevent-r0drv-os2.cpp
@@ -0,0 +1,311 @@
+/* $Id: semevent-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Single Release Event Semaphores, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/semaphore.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/lockvalidator.h>
+
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * OS/2 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 OS/2 spinlock protecting this structure. */
+ SpinLock_t Spinlock;
+} RTSEMEVENTINTERNAL, *PRTSEMEVENTINTERNAL;
+
+
+RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
+{
+ return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
+}
+
+
+RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
+{
+ AssertReturn(!(fFlags & ~(RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)), VERR_INVALID_PARAMETER);
+ Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL));
+ AssertCompile(sizeof(RTSEMEVENTINTERNAL) > sizeof(void *));
+ AssertPtrReturn(phEventSem, VERR_INVALID_POINTER);
+ RT_NOREF(hClass, pszNameFmt);
+
+ PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)RTMemAlloc(sizeof(*pThis));
+ if (!pThis)
+ return VERR_NO_MEMORY;
+
+ pThis->u32Magic = RTSEMEVENT_MAGIC;
+ pThis->cWaiters = 0;
+ pThis->cWaking = 0;
+ pThis->fSignaled = 0;
+ KernAllocSpinLock(&pThis->Spinlock);
+
+ *phEventSem = pThis;
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
+{
+ PRTSEMEVENTINTERNAL pThis = hEventSem;
+ if (pThis == NIL_RTSEMEVENT)
+ return VINF_SUCCESS;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+
+ KernAcquireSpinLock(&pThis->Spinlock);
+ ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
+ if (pThis->cWaiters > 0)
+ {
+ /* abort waiting thread, last man cleans up. */
+ ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
+ ULONG cThreads;
+ KernWakeup((ULONG)pThis, WAKEUP_DATA | WAKEUP_BOOST, &cThreads, (ULONG)VERR_SEM_DESTROYED);
+ KernReleaseSpinLock(&pThis->Spinlock);
+ }
+ else if (pThis->cWaking)
+ /* the last waking thread is gonna do the cleanup */
+ KernReleaseSpinLock(&pThis->Spinlock);
+ else
+ {
+ KernReleaseSpinLock(&pThis->Spinlock);
+ KernFreeSpinLock(&pThis->Spinlock);
+ RTMemFree(pThis);
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
+{
+ PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+
+ KernAcquireSpinLock(&pThis->Spinlock);
+
+ if (pThis->cWaiters > 0)
+ {
+ ASMAtomicDecU32(&pThis->cWaiters);
+ ASMAtomicIncU32(&pThis->cWaking);
+ ULONG cThreads;
+ KernWakeup((ULONG)pThis, WAKEUP_DATA | WAKEUP_ONE, &cThreads, VINF_SUCCESS);
+ if (RT_UNLIKELY(!cThreads))
+ {
+ /* shouldn't ever happen on OS/2 */
+ ASMAtomicXchgU8(&pThis->fSignaled, true);
+ ASMAtomicDecU32(&pThis->cWaking);
+ ASMAtomicIncU32(&pThis->cWaiters);
+ }
+ }
+ else
+ ASMAtomicXchgU8(&pThis->fSignaled, true);
+
+ KernReleaseSpinLock(&pThis->Spinlock);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
+ *
+ * @returns VBox status code.
+ * @param pThis The event semaphore.
+ * @param fFlags See RTSemEventWaitEx.
+ * @param uTimeout See RTSemEventWaitEx.
+ * @param pSrcPos The source code position of the wait.
+ */
+static int rtR0SemEventOs2Wait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
+ PCRTLOCKVALSRCPOS pSrcPos)
+{
+ /*
+ * Validate and convert input.
+ */
+ if (!pThis)
+ return VERR_INVALID_HANDLE;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
+ AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
+
+ ULONG cMsTimeout = rtR0SemWaitOs2ConvertTimeout(fFlags, uTimeout);
+ ULONG fBlock = BLOCK_SPINLOCK;
+ if (!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE))
+ fBlock |= BLOCK_UNINTERRUPTABLE;
+
+ /*
+ * Do the job.
+ */
+ KernAcquireSpinLock(&pThis->Spinlock);
+
+ int rc;
+ if (pThis->fSignaled)
+ {
+ Assert(!pThis->cWaiters);
+ ASMAtomicXchgU8(&pThis->fSignaled, false);
+ rc = VINF_SUCCESS;
+ }
+ else
+ {
+ ASMAtomicIncU32(&pThis->cWaiters);
+
+ ULONG ulData = (ULONG)VERR_INTERNAL_ERROR;
+ rc = KernBlock((ULONG)pThis, cMsTimeout, fBlock,
+ &pThis->Spinlock,
+ &ulData);
+ switch (rc)
+ {
+ case NO_ERROR:
+ rc = (int)ulData;
+ Assert(rc == VINF_SUCCESS || rc == VERR_SEM_DESTROYED);
+ Assert(pThis->cWaking > 0);
+ if ( !ASMAtomicDecU32(&pThis->cWaking)
+ && pThis->u32Magic != RTSEMEVENT_MAGIC)
+ {
+ /* The event was destroyed (ulData == VINF_SUCCESS if it was after we awoke), as
+ the last thread do the cleanup. */
+ KernReleaseSpinLock(&pThis->Spinlock);
+ KernFreeSpinLock(&pThis->Spinlock);
+ RTMemFree(pThis);
+ return rc;
+ }
+ break;
+
+ case ERROR_TIMEOUT:
+ Assert(cMsTimeout != SEM_INDEFINITE_WAIT);
+ ASMAtomicDecU32(&pThis->cWaiters);
+ rc = VERR_TIMEOUT;
+ break;
+
+ case ERROR_INTERRUPT:
+ Assert(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
+ ASMAtomicDecU32(&pThis->cWaiters);
+ rc = VERR_INTERRUPTED;
+ break;
+
+ default:
+ AssertMsgFailed(("rc=%d\n", rc));
+ rc = VERR_GENERAL_FAILURE;
+ break;
+ }
+ }
+
+ KernReleaseSpinLock(&pThis->Spinlock);
+ return rc;
+}
+
+
+RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
+{
+#ifndef RTSEMEVENT_STRICT
+ return rtR0SemEventOs2Wait(hEventSem, fFlags, uTimeout, NULL);
+#else
+ RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
+ return rtR0SemEventOs2Wait(hEventSem, fFlags, uTimeout, &SrcPos);
+#endif
+}
+
+
+RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
+ return rtR0SemEventOs2Wait(hEventSem, fFlags, uTimeout, &SrcPos);
+}
+
+
+RTDECL(uint32_t) RTSemEventGetResolution(void)
+{
+ return 32000000; /* 32ms */
+}
+
+
+RTR0DECL(bool) RTSemEventIsSignalSafe(void)
+{
+ return true;
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/semeventmulti-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/semeventmulti-r0drv-os2.cpp
new file mode 100644
index 00000000..e8404929
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/semeventmulti-r0drv-os2.cpp
@@ -0,0 +1,321 @@
+/* $Id: semeventmulti-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/semaphore.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/lockvalidator.h>
+#include <iprt/mem.h>
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * OS/2 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 OS/2 spinlock protecting this structure. */
+ SpinLock_t Spinlock;
+} RTSEMEVENTMULTIINTERNAL, *PRTSEMEVENTMULTIINTERNAL;
+
+
+RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
+{
+ return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
+}
+
+
+RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
+ const char *pszNameFmt, ...)
+{
+ AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
+ AssertPtrReturn(phEventMultiSem, VERR_INVALID_POINTER);
+
+ AssertCompile(sizeof(RTSEMEVENTMULTIINTERNAL) > sizeof(void *));
+ PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)RTMemAlloc(sizeof(*pThis));
+ if (pThis)
+ {
+ pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
+ pThis->cWaiters = 0;
+ pThis->cWaking = 0;
+ pThis->fSignaled = 0;
+ KernAllocSpinLock(&pThis->Spinlock);
+
+ *phEventMultiSem = pThis;
+ return VINF_SUCCESS;
+ }
+ RT_NOREF(hClass, pszNameFmt);
+ return VERR_NO_MEMORY;
+}
+
+
+RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
+{
+ PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
+ if (pThis == NIL_RTSEMEVENTMULTI)
+ return VINF_SUCCESS;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
+
+ KernAcquireSpinLock(&pThis->Spinlock);
+ ASMAtomicIncU32(&pThis->u32Magic); /* make the handle invalid */
+ if (pThis->cWaiters > 0)
+ {
+ /* abort waiting thread, last man cleans up. */
+ ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
+ ULONG cThreads;
+ KernWakeup((ULONG)pThis, WAKEUP_DATA | WAKEUP_BOOST, &cThreads, (ULONG)VERR_SEM_DESTROYED);
+ KernReleaseSpinLock(&pThis->Spinlock);
+ }
+ else if (pThis->cWaking)
+ /* the last waking thread is gonna do the cleanup */
+ KernReleaseSpinLock(&pThis->Spinlock);
+ else
+ {
+ KernReleaseSpinLock(&pThis->Spinlock);
+ KernFreeSpinLock(&pThis->Spinlock);
+ RTMemFree(pThis);
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
+{
+ PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
+ ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
+ VERR_INVALID_HANDLE);
+
+ KernAcquireSpinLock(&pThis->Spinlock);
+
+ ASMAtomicXchgU8(&pThis->fSignaled, true);
+ if (pThis->cWaiters > 0)
+ {
+ ASMAtomicXchgU32(&pThis->cWaking, pThis->cWaking + pThis->cWaiters);
+ ASMAtomicXchgU32(&pThis->cWaiters, 0);
+ ULONG cThreads;
+ KernWakeup((ULONG)pThis, WAKEUP_DATA, &cThreads, VINF_SUCCESS);
+ }
+
+ KernReleaseSpinLock(&pThis->Spinlock);
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
+{
+ PRTSEMEVENTMULTIINTERNAL pThis = (PRTSEMEVENTMULTIINTERNAL)hEventMultiSem;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
+ ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
+ VERR_INVALID_HANDLE);
+
+ KernAcquireSpinLock(&pThis->Spinlock);
+ ASMAtomicXchgU8(&pThis->fSignaled, false);
+ KernReleaseSpinLock(&pThis->Spinlock);
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
+ *
+ * @returns VBox status code.
+ * @param pThis The event semaphore.
+ * @param fFlags See RTSemEventWaitEx.
+ * @param uTimeout See RTSemEventWaitEx.
+ * @param pSrcPos The source code position of the wait.
+ */
+static int rtR0SemEventMultiOs2Wait(PRTSEMEVENTMULTIINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
+ PCRTLOCKVALSRCPOS pSrcPos)
+{
+ RT_NOREF(pSrcPos);
+
+ /*
+ * Validate and convert the input.
+ */
+ if (!pThis)
+ return VERR_INVALID_HANDLE;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
+ ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
+ VERR_INVALID_HANDLE);
+ AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
+
+ ULONG cMsTimeout = rtR0SemWaitOs2ConvertTimeout(fFlags, uTimeout);
+ ULONG fBlock = BLOCK_SPINLOCK;
+ if (!(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE))
+ fBlock |= BLOCK_UNINTERRUPTABLE;
+
+ /*
+ * Do the job.
+ */
+ KernAcquireSpinLock(&pThis->Spinlock);
+
+ int rc;
+ if (pThis->fSignaled)
+ rc = VINF_SUCCESS;
+ else
+ {
+ ASMAtomicIncU32(&pThis->cWaiters);
+
+ ULONG ulData = (ULONG)VERR_INTERNAL_ERROR;
+ rc = KernBlock((ULONG)pThis, cMsTimeout, fBlock,
+ &pThis->Spinlock,
+ &ulData);
+ switch (rc)
+ {
+ case NO_ERROR:
+ rc = (int)ulData;
+ Assert(rc == VINF_SUCCESS || rc == VERR_SEM_DESTROYED);
+ Assert(pThis->cWaking > 0);
+ if ( !ASMAtomicDecU32(&pThis->cWaking)
+ && pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)
+ {
+ /* The event was destroyed (ulData == VINF_SUCCESS if it was after we awoke), as
+ the last thread do the cleanup. */
+ KernReleaseSpinLock(&pThis->Spinlock);
+ KernFreeSpinLock(&pThis->Spinlock);
+ RTMemFree(pThis);
+ return VINF_SUCCESS;
+ }
+ rc = VINF_SUCCESS;
+ break;
+
+ case ERROR_TIMEOUT:
+ Assert(cMsTimeout != SEM_INDEFINITE_WAIT);
+ ASMAtomicDecU32(&pThis->cWaiters);
+ rc = VERR_TIMEOUT;
+ break;
+
+ case ERROR_INTERRUPT:
+ Assert(fFlags & RTSEMWAIT_FLAGS_INTERRUPTIBLE);
+ ASMAtomicDecU32(&pThis->cWaiters);
+ rc = VERR_INTERRUPTED;
+ break;
+
+ default:
+ AssertMsgFailed(("rc=%d\n", rc));
+ rc = VERR_GENERAL_FAILURE;
+ break;
+ }
+ }
+
+ KernReleaseSpinLock(&pThis->Spinlock);
+ return rc;
+}
+
+
+RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
+{
+#ifndef RTSEMEVENT_STRICT
+ return rtR0SemEventMultiOs2Wait(hEventMultiSem, fFlags, uTimeout, NULL);
+#else
+ RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
+ return rtR0SemEventMultiOs2Wait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
+#endif
+}
+
+
+RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
+ return rtR0SemEventMultiOs2Wait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
+}
+
+
+RTDECL(uint32_t) RTSemEventMultiGetResolution(void)
+{
+ return 32000000; /* 32ms */
+}
+
+
+RTR0DECL(bool) RTSemEventMultiIsSignalSafe(void)
+{
+ return true;
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/semfastmutex-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/semfastmutex-r0drv-os2.cpp
new file mode 100644
index 00000000..14daa32e
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/semfastmutex-r0drv-os2.cpp
@@ -0,0 +1,149 @@
+/* $Id: semfastmutex-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Fast Mutex Semaphores, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+
+#include <iprt/semaphore.h>
+#include <iprt/errcore.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * Wrapper for the OS/2 KEE mutex semaphore.
+ */
+typedef struct RTSEMFASTMUTEXINTERNAL
+{
+ /** Magic value (RTSEMFASTMUTEX_MAGIC). */
+ uint32_t u32Magic;
+ /** The KEE mutex. */
+ MutexLock_t Mtx;
+} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL;
+
+
+RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx)
+{
+ AssertCompile(sizeof(RTSEMFASTMUTEXINTERNAL) > sizeof(void *));
+ AssertPtrReturn(phFastMtx, VERR_INVALID_POINTER);
+
+ PRTSEMFASTMUTEXINTERNAL pThis = (PRTSEMFASTMUTEXINTERNAL)RTMemAlloc(sizeof(*pThis));
+ if (pThis)
+ {
+ pThis->u32Magic = RTSEMFASTMUTEX_MAGIC;
+ KernAllocMutexLock(&pThis->Mtx);
+
+ *phFastMtx = pThis;
+ return VINF_SUCCESS;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx)
+{
+ PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx;
+ if (pThis == NIL_RTSEMFASTMUTEX)
+ return VINF_SUCCESS;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
+
+ ASMAtomicWriteU32(&pThis->u32Magic, RTSEMFASTMUTEX_MAGIC_DEAD);
+ KernFreeMutexLock(&pThis->Mtx);
+ RTMemFree(pThis);
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx)
+{
+ PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
+
+ KernRequestExclusiveMutex(&pThis->Mtx);
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx)
+{
+ PRTSEMFASTMUTEXINTERNAL pThis = hFastMtx;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertMsgReturn(pThis->u32Magic == RTSEMFASTMUTEX_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
+
+ KernReleaseExclusiveMutex(&pThis->Mtx);
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/spinlock-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/spinlock-r0drv-os2.cpp
new file mode 100644
index 00000000..92d0b144
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/spinlock-r0drv-os2.cpp
@@ -0,0 +1,165 @@
+/* $Id: spinlock-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Spinlocks, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+
+#include <iprt/spinlock.h>
+#include <iprt/errcore.h>
+#include <iprt/alloc.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#ifdef RT_STRICT
+# include <iprt/asm-amd64-x86.h>
+#endif
+
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * Wrapper for the SpinLock_t type.
+ */
+typedef struct RTSPINLOCKINTERNAL
+{
+ /** Spinlock magic value (RTSPINLOCK_MAGIC). */
+ uint32_t volatile u32Magic;
+ /** Spinlock creation flags. */
+ uint32_t fFlags;
+ /** The OS/2 spinlock structure. */
+ SpinLock_t Spinlock;
+} RTSPINLOCKINTERNAL, *PRTSPINLOCKINTERNAL;
+
+
+RTDECL(int) RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char *pszName)
+{
+ AssertReturn(fFlags == RTSPINLOCK_FLAGS_INTERRUPT_SAFE || fFlags == RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, VERR_INVALID_PARAMETER);
+ RT_NOREF(pszName);
+
+ /*
+ * Allocate.
+ */
+ AssertCompile(sizeof(RTSPINLOCKINTERNAL) > sizeof(void *));
+ PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)RTMemAlloc(sizeof(*pThis));
+ if (!pThis)
+ return VERR_NO_MEMORY;
+
+ /*
+ * Initialize & return.
+ */
+ pThis->u32Magic = RTSPINLOCK_MAGIC;
+ pThis->fFlags = fFlags;
+ KernAllocSpinLock(&pThis->Spinlock);
+ *pSpinlock = pThis;
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTSpinlockDestroy(RTSPINLOCK Spinlock)
+{
+ /*
+ * Validate input.
+ */
+ PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
+ if (!pThis)
+ return VERR_INVALID_PARAMETER;
+ AssertMsgReturn(pThis->u32Magic == RTSPINLOCK_MAGIC,
+ ("Invalid spinlock %p magic=%#x\n", pThis, pThis->u32Magic),
+ VERR_INVALID_PARAMETER);
+
+ /*
+ * Make the lock invalid and release the memory.
+ */
+ ASMAtomicIncU32(&pThis->u32Magic);
+ KernFreeSpinLock(&pThis->Spinlock);
+ RTMemFree(pThis);
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock)
+{
+ PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
+ AssertPtr(pThis);
+ Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
+
+ KernAcquireSpinLock(&pThis->Spinlock);
+ Assert(!ASMIntAreEnabled()); /** @todo verify that interrupts are disabled. */
+}
+
+
+RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock)
+{
+ PRTSPINLOCKINTERNAL pThis = (PRTSPINLOCKINTERNAL)Spinlock;
+ AssertPtr(pThis);
+ Assert(pThis->u32Magic == RTSPINLOCK_MAGIC);
+
+ KernReleaseSpinLock(&pThis->Spinlock);
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/the-os2-kernel.h b/src/VBox/Runtime/r0drv/os2/the-os2-kernel.h
new file mode 100644
index 00000000..5380aba1
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/the-os2-kernel.h
@@ -0,0 +1,93 @@
+/* $Id: the-os2-kernel.h $ */
+/** @file
+ * IPRT - Ring-0 Driver, The OS/2 Kernel Headers.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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 IPRT_INCLUDED_SRC_r0drv_os2_the_os2_kernel_h
+#define IPRT_INCLUDED_SRC_r0drv_os2_the_os2_kernel_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+#define INCL_ERRORS
+#define INCL_DOSSEMAPHORES /* for SEM_INDEFINITE_WAIT */
+#undef RT_MAX
+#include <os2ddk/bsekee.h>
+#include <os2ddk/devhlp.h>
+#undef RT_MAX
+
+RT_C_DECLS_BEGIN
+
+extern PCDOSTABLE g_pDosTable;
+extern PCDOSTABLE2 g_pDosTable2;
+extern PGINFOSEG g_pGIS;
+extern RTFAR16 g_fpLIS;
+
+RTR0DECL(void *) RTR0Os2Virt2Flat(RTFAR16 fp);
+DECLASM(int) RTR0Os2DHQueryDOSVar(uint8_t iVar, uint16_t iSub, PRTFAR16 pfp);
+DECLASM(int) RTR0Os2DHVMGlobalToProcess(ULONG fFlags, PVOID pvR0, ULONG cb, PPVOID ppvR3);
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_SRC_r0drv_os2_the_os2_kernel_h */
diff --git a/src/VBox/Runtime/r0drv/os2/thread-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/thread-r0drv-os2.cpp
new file mode 100644
index 00000000..9b6ff7da
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/thread-r0drv-os2.cpp
@@ -0,0 +1,225 @@
+/* $Id: thread-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Threads (Part 1), Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/thread.h>
+
+#include <iprt/asm.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mp.h>
+#include "internal/thread.h"
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** Per-cpu preemption counters. */
+static int32_t volatile g_acPreemptDisabled[256];
+
+
+
+RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
+{
+ PLINFOSEG pLIS = (PLINFOSEG)RTR0Os2Virt2Flat(g_fpLIS);
+ AssertMsgReturn(pLIS, ("g_fpLIS=%04x:%04x - logging too early again?\n", g_fpLIS.sel, g_fpLIS.off), NIL_RTNATIVETHREAD);
+ return pLIS->tidCurrent | (pLIS->pidCurrent << 16);
+}
+
+
+static int rtR0ThreadOs2SleepCommon(RTMSINTERVAL cMillies)
+{
+ int rc = KernBlock((ULONG)RTThreadSleep,
+ cMillies == RT_INDEFINITE_WAIT ? SEM_INDEFINITE_WAIT : cMillies,
+ 0, NULL, NULL);
+ switch (rc)
+ {
+ case NO_ERROR:
+ return VINF_SUCCESS;
+ case ERROR_TIMEOUT:
+ return VERR_TIMEOUT;
+ case ERROR_INTERRUPT:
+ return VERR_INTERRUPTED;
+ default:
+ AssertMsgFailed(("%d\n", rc));
+ return VERR_NO_TRANSLATION;
+ }
+}
+
+
+RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
+{
+ return rtR0ThreadOs2SleepCommon(cMillies);
+}
+
+
+RTDECL(int) RTThreadSleepNoBlock(RTMSINTERVAL cMillies)
+{
+ return rtR0ThreadOs2SleepCommon(cMillies);
+}
+
+
+RTDECL(bool) RTThreadYield(void)
+{
+ /** @todo implement me (requires a devhelp) */
+ return false;
+}
+
+
+RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread)
+{
+ Assert(hThread == NIL_RTTHREAD);
+ int32_t c = g_acPreemptDisabled[ASMGetApicId()];
+ AssertMsg(c >= 0 && c < 32, ("%d\n", c));
+ return c == 0
+ && ASMIntAreEnabled();
+}
+
+
+RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread)
+{
+ Assert(hThread == NIL_RTTHREAD);
+
+ union
+ {
+ RTFAR16 fp;
+ uint8_t fResched;
+ } u;
+ int rc = RTR0Os2DHQueryDOSVar(DHGETDOSV_YIELDFLAG, 0, &u.fp);
+ AssertReturn(rc == 0, false);
+ if (u.fResched)
+ return true;
+
+ /** @todo Check if DHGETDOSV_YIELDFLAG includes TCYIELDFLAG. */
+ rc = RTR0Os2DHQueryDOSVar(DHGETDOSV_TCYIELDFLAG, 0, &u.fp);
+ AssertReturn(rc == 0, false);
+ if (u.fResched)
+ return true;
+ return false;
+}
+
+
+RTDECL(bool) RTThreadPreemptIsPendingTrusty(void)
+{
+ /* yes, RTThreadPreemptIsPending is reliable. */
+ return true;
+}
+
+
+RTDECL(bool) RTThreadPreemptIsPossible(void)
+{
+ /* no kernel preemption on OS/2. */
+ return false;
+}
+
+
+RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState)
+{
+ AssertPtr(pState);
+ Assert(pState->u32Reserved == 0);
+
+ /* No preemption on OS/2, so do our own accounting. */
+ int32_t c = ASMAtomicIncS32(&g_acPreemptDisabled[ASMGetApicId()]);
+ AssertMsg(c > 0 && c < 32, ("%d\n", c));
+ pState->u32Reserved = c;
+ RT_ASSERT_PREEMPT_CPUID_DISABLE(pState);
+}
+
+
+RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState)
+{
+ AssertPtr(pState);
+ AssertMsg(pState->u32Reserved > 0 && pState->u32Reserved < 32, ("%d\n", pState->u32Reserved));
+ RT_ASSERT_PREEMPT_CPUID_RESTORE(pState);
+
+ /* No preemption on OS/2, so do our own accounting. */
+ int32_t volatile *pc = &g_acPreemptDisabled[ASMGetApicId()];
+ AssertMsg(pState->u32Reserved == (uint32_t)*pc, ("uchDummy=%d *pc=%d \n", pState->u32Reserved, *pc));
+ ASMAtomicUoWriteS32(pc, pState->u32Reserved - 1);
+ pState->u32Reserved = 0;
+}
+
+
+RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread)
+{
+ Assert(hThread == NIL_RTTHREAD); NOREF(hThread);
+
+ union
+ {
+ RTFAR16 fp;
+ uint8_t cInterruptLevel;
+ } u;
+ /** @todo OS/2: verify the usage of DHGETDOSV_INTERRUPTLEV. */
+ int rc = RTR0Os2DHQueryDOSVar(DHGETDOSV_INTERRUPTLEV, 0, &u.fp);
+ AssertReturn(rc == 0, true);
+
+ return u.cInterruptLevel > 0;
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/thread2-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/thread2-r0drv-os2.cpp
new file mode 100644
index 00000000..1b484343
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/thread2-r0drv-os2.cpp
@@ -0,0 +1,120 @@
+/* $Id: thread2-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Threads (Part 2), Ring-0 Driver, Generic Stubs.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+
+#include <iprt/thread.h>
+#include <iprt/errcore.h>
+#include "internal/thread.h"
+
+
+DECLHIDDEN(int) rtThreadNativeInit(void)
+{
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(RTTHREAD) RTThreadSelf(void)
+{
+ return rtThreadGetByNative(RTThreadNativeSelf());
+}
+
+
+DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
+{
+ NOREF(pThread);
+ NOREF(enmType);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
+{
+ NOREF(pThread);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+DECLHIDDEN(void) rtThreadNativeWaitKludge(PRTTHREADINT pThread)
+{
+ NOREF(pThread);
+}
+
+
+DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
+{
+ NOREF(pThread);
+}
+
+
+DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread)
+{
+ NOREF(pNativeThread);
+ NOREF(pThreadInt);
+ return VERR_NOT_IMPLEMENTED;
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/time-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/time-r0drv-os2.cpp
new file mode 100644
index 00000000..283a87bd
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/time-r0drv-os2.cpp
@@ -0,0 +1,126 @@
+/* $Id: time-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Time, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+
+#include <iprt/time.h>
+
+
+RTDECL(uint64_t) RTTimeNanoTS(void)
+{
+ /** @remark OS/2 Ring-0: will wrap after 48 days. */
+ return g_pGIS->msecs * UINT64_C(1000000);
+}
+
+
+RTDECL(uint64_t) RTTimeMilliTS(void)
+{
+ /** @remark OS/2 Ring-0: will wrap after 48 days. */
+ return g_pGIS->msecs;
+}
+
+
+RTDECL(uint64_t) RTTimeSystemNanoTS(void)
+{
+ /** @remark OS/2 Ring-0: will wrap after 48 days. */
+ return g_pGIS->msecs * UINT64_C(1000000);
+}
+
+
+RTDECL(uint64_t) RTTimeSystemMilliTS(void)
+{
+ /** @remark OS/2 Ring-0: will wrap after 48 days. */
+ return g_pGIS->msecs;
+}
+
+
+RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
+{
+ /*
+ * Get the seconds since the unix epoch (local time) and current hundredths.
+ */
+ GINFOSEG volatile *pGIS = (GINFOSEG volatile *)g_pGIS;
+ UCHAR uchHundredths;
+ ULONG ulSeconds;
+ do
+ {
+ uchHundredths = pGIS->hundredths;
+ ulSeconds = pGIS->time;
+ } while ( uchHundredths == pGIS->hundredths
+ && ulSeconds == pGIS->time);
+
+ /*
+ * Combine the two and convert to UCT (later).
+ */
+ uint64_t u64 = ulSeconds * UINT64_C(1000000000) + (uint32_t)uchHundredths * 10000000;
+ /** @todo convert from local to UCT. */
+
+ /** @remark OS/2 Ring-0: Currently returns local time instead of UCT. */
+ return RTTimeSpecSetNano(pTime, u64);
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/timer-r0drv-os2.cpp b/src/VBox/Runtime/r0drv/os2/timer-r0drv-os2.cpp
new file mode 100644
index 00000000..7a332cd5
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/timer-r0drv-os2.cpp
@@ -0,0 +1,419 @@
+/* $Id: timer-r0drv-os2.cpp $ */
+/** @file
+ * IPRT - Memory Allocation, Ring-0 Driver, OS/2.
+ */
+
+/*
+ * Contributed by knut st. osmundsen.
+ *
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * 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-os2-kernel.h"
+
+#include <iprt/timer.h>
+#include <iprt/time.h>
+#include <iprt/spinlock.h>
+#include <iprt/err.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/alloc.h>
+
+#include "internal/magics.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * The internal representation of an OS/2 timer handle.
+ */
+typedef struct RTTIMER
+{
+ /** Magic.
+ * This is RTTIMER_MAGIC, but changes to something else before the timer
+ * is destroyed to indicate clearly that thread should exit. */
+ uint32_t volatile u32Magic;
+ /** The next timer in the timer list. */
+ PRTTIMER pNext;
+ /** Flag indicating the timer is suspended. */
+ uint8_t volatile fSuspended;
+ /** Cleared at the start of timer processing, set when calling pfnTimer.
+ * If any timer changes occurs while doing the callback this will be used to resume the cycle. */
+ bool fDone;
+ /** Callback. */
+ PFNRTTIMER pfnTimer;
+ /** User argument. */
+ void *pvUser;
+ /** The timer interval. 0 if one-shot. */
+ uint64_t u64NanoInterval;
+ /** The start of the current run.
+ * This is used to calculate when the timer ought to fire the next time. */
+ uint64_t volatile u64StartTS;
+ /** The start of the current run.
+ * This is used to calculate when the timer ought to fire the next time. */
+ uint64_t volatile u64NextTS;
+ /** The current tick number (since u64StartTS). */
+ uint64_t volatile iTick;
+} RTTIMER;
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** Spinlock protecting the timers. */
+static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
+/** The timer head. */
+static PRTTIMER volatile g_pTimerHead = NULL;
+/** The number of active timers. */
+static uint32_t volatile g_cActiveTimers = 0;
+/** The number of active timers. */
+static uint32_t volatile g_cTimers = 0;
+/** The change number.
+ * This is used to detect list changes during the timer callback loop. */
+static uint32_t volatile g_u32ChangeNo;
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+RT_C_DECLS_BEGIN
+DECLASM(void) rtTimerOs2Tick(void);
+DECLASM(int) rtTimerOs2Arm(void);
+DECLASM(int) rtTimerOs2Dearm(void);
+RT_C_DECLS_END
+
+
+
+RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser)
+{
+ *ppTimer = NULL;
+
+ /*
+ * We don't support the fancy MP features.
+ */
+ if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
+ return VERR_NOT_SUPPORTED;
+
+ /*
+ * Lazy initialize the spinlock.
+ */
+ if (g_Spinlock == NIL_RTSPINLOCK)
+ {
+ RTSPINLOCK Spinlock;
+ int rc = RTSpinlockCreate(&Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTTimerOS2");
+ AssertRCReturn(rc, rc);
+ //bool fRc;
+ //ASMAtomicCmpXchgSize(&g_Spinlock, Spinlock, NIL_RTSPINLOCK, fRc);
+ //if (!fRc)
+ if (!ASMAtomicCmpXchgPtr((void * volatile *)&g_Spinlock, Spinlock, NIL_RTSPINLOCK))
+ RTSpinlockDestroy(Spinlock);
+ }
+
+ /*
+ * Allocate and initialize the timer handle.
+ */
+ PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
+ if (!pTimer)
+ return VERR_NO_MEMORY;
+
+ pTimer->u32Magic = RTTIMER_MAGIC;
+ pTimer->pNext = NULL;
+ pTimer->fSuspended = true;
+ pTimer->pfnTimer = pfnTimer;
+ pTimer->pvUser = pvUser;
+ pTimer->u64NanoInterval = u64NanoInterval;
+ pTimer->u64StartTS = 0;
+
+ /*
+ * Insert the timer into the list (LIFO atm).
+ */
+ RTSpinlockAcquire(g_Spinlock);
+ g_u32ChangeNo++;
+ pTimer->pNext = g_pTimerHead;
+ g_pTimerHead = pTimer;
+ g_cTimers++;
+ RTSpinlockRelease(g_Spinlock);
+
+ *ppTimer = pTimer;
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Validates the timer handle.
+ *
+ * @returns true if valid, false if invalid.
+ * @param pTimer The handle.
+ */
+DECLINLINE(bool) rtTimerIsValid(PRTTIMER pTimer)
+{
+ AssertPtrReturn(pTimer, false);
+ AssertReturn(pTimer->u32Magic == RTTIMER_MAGIC, false);
+ return true;
+}
+
+
+RTDECL(int) RTTimerDestroy(PRTTIMER pTimer)
+{
+ /* It's ok to pass NULL pointer. */
+ if (pTimer == /*NIL_RTTIMER*/ NULL)
+ return VINF_SUCCESS;
+ if (!rtTimerIsValid(pTimer))
+ return VERR_INVALID_HANDLE;
+
+ /*
+ * Remove it from the list.
+ */
+ RTSpinlockAcquire(g_Spinlock);
+ g_u32ChangeNo++;
+ if (g_pTimerHead == pTimer)
+ g_pTimerHead = pTimer->pNext;
+ else
+ {
+ PRTTIMER pPrev = g_pTimerHead;
+ while (pPrev->pNext != pTimer)
+ {
+ pPrev = pPrev->pNext;
+ if (RT_UNLIKELY(!pPrev))
+ {
+ RTSpinlockRelease(g_Spinlock);
+ return VERR_INVALID_HANDLE;
+ }
+ }
+ pPrev->pNext = pTimer->pNext;
+ }
+ Assert(g_cTimers > 0);
+ g_cTimers--;
+ if (!pTimer->fSuspended)
+ {
+ Assert(g_cActiveTimers > 0);
+ g_cActiveTimers--;
+ if (!g_cActiveTimers)
+ rtTimerOs2Dearm();
+ }
+ RTSpinlockRelease(g_Spinlock);
+
+ /*
+ * Free the associated resources.
+ */
+ pTimer->u32Magic++;
+ RTMemFree(pTimer);
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First)
+{
+ if (!rtTimerIsValid(pTimer))
+ return VERR_INVALID_HANDLE;
+ if (!pTimer->fSuspended)
+ return VERR_TIMER_ACTIVE;
+
+ /*
+ * Calc when it should start firing and give the thread a kick so it get going.
+ */
+ u64First += RTTimeNanoTS();
+
+ RTSpinlockAcquire(g_Spinlock);
+ g_u32ChangeNo++;
+ if (!g_cActiveTimers)
+ {
+ int rc = rtTimerOs2Arm();
+ if (RT_FAILURE(rc))
+ {
+ RTSpinlockRelease(g_Spinlock);
+ return rc;
+ }
+ }
+ g_cActiveTimers++;
+ pTimer->fSuspended = false;
+ pTimer->fDone = true; /* next tick, not current! */
+ pTimer->iTick = 0;
+ pTimer->u64StartTS = u64First;
+ pTimer->u64NextTS = u64First;
+ RTSpinlockRelease(g_Spinlock);
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTTimerStop(PRTTIMER pTimer)
+{
+ if (!rtTimerIsValid(pTimer))
+ return VERR_INVALID_HANDLE;
+ if (pTimer->fSuspended)
+ return VERR_TIMER_SUSPENDED;
+
+ /*
+ * Suspend the timer.
+ */
+ RTSpinlockAcquire(g_Spinlock);
+ g_u32ChangeNo++;
+ pTimer->fSuspended = true;
+ Assert(g_cActiveTimers > 0);
+ g_cActiveTimers--;
+ if (!g_cActiveTimers)
+ rtTimerOs2Dearm();
+ RTSpinlockRelease(g_Spinlock);
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval)
+{
+ if (!rtTimerIsValid(pTimer))
+ return VERR_INVALID_HANDLE;
+ RT_NOREF(u64NanoInterval);
+ return VERR_NOT_SUPPORTED;
+}
+
+
+DECLASM(void) rtTimerOs2Tick(void)
+{
+ /*
+ * Query the current time and then take the lock.
+ */
+ const uint64_t u64NanoTS = RTTimeNanoTS();
+
+ RTSpinlockAcquire(g_Spinlock);
+
+ /*
+ * Clear the fDone flag.
+ */
+ PRTTIMER pTimer;
+ for (pTimer = g_pTimerHead; pTimer; pTimer = pTimer->pNext)
+ pTimer->fDone = false;
+
+ /*
+ * Walk the timer list and do the callbacks for any active timer.
+ */
+ uint32_t u32CurChangeNo = g_u32ChangeNo;
+ pTimer = g_pTimerHead;
+ while (pTimer)
+ {
+ PRTTIMER pNext = pTimer->pNext;
+ if ( !pTimer->fSuspended
+ && !pTimer->fDone
+ && pTimer->u64NextTS <= u64NanoTS)
+ {
+ pTimer->fDone = true;
+ pTimer->iTick++;
+
+ /* calculate the next timeout */
+ if (!pTimer->u64NanoInterval)
+ pTimer->fSuspended = true;
+ else
+ {
+ pTimer->u64NextTS = pTimer->u64StartTS + pTimer->iTick * pTimer->u64NanoInterval;
+ if (pTimer->u64NextTS < u64NanoTS)
+ pTimer->u64NextTS = u64NanoTS + RTTimerGetSystemGranularity() / 2;
+ }
+
+ /* do the callout */
+ PFNRTTIMER pfnTimer = pTimer->pfnTimer;
+ void *pvUser = pTimer->pvUser;
+ RTSpinlockRelease(g_Spinlock);
+ pfnTimer(pTimer, pvUser, pTimer->iTick);
+
+ RTSpinlockAcquire(g_Spinlock);
+
+ /* check if anything changed. */
+ if (u32CurChangeNo != g_u32ChangeNo)
+ {
+ u32CurChangeNo = g_u32ChangeNo;
+ pNext = g_pTimerHead;
+ }
+ }
+
+ /* next */
+ pTimer = pNext;
+ }
+
+ RTSpinlockRelease(g_Spinlock);
+}
+
+
+RTDECL(uint32_t) RTTimerGetSystemGranularity(void)
+{
+ return 32000000; /* 32ms */
+}
+
+
+RTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted)
+{
+ RT_NOREF(u32Request, pu32Granted);
+ return VERR_NOT_SUPPORTED;
+}
+
+
+RTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted)
+{
+ RT_NOREF(u32Granted);
+ return VERR_NOT_SUPPORTED;
+}
+
+
+RTDECL(bool) RTTimerCanDoHighResolution(void)
+{
+ return false;
+}
+
diff --git a/src/VBox/Runtime/r0drv/os2/timerA-r0drv-os2.asm b/src/VBox/Runtime/r0drv/os2/timerA-r0drv-os2.asm
new file mode 100644
index 00000000..49b2a86a
--- /dev/null
+++ b/src/VBox/Runtime/r0drv/os2/timerA-r0drv-os2.asm
@@ -0,0 +1,252 @@
+; $Id: timerA-r0drv-os2.asm $
+;; @file
+; IPRT - DevHelp_VMGlobalToProcess, Ring-0 Driver, OS/2.
+;
+
+;
+; Contributed by knut st. osmundsen.
+;
+; Copyright (C) 2007-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+; --------------------------------------------------------------------
+;
+; This code is based on:
+;
+; 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 *
+;*******************************************************************************
+%define RT_INCL_16BIT_SEGMENTS
+%include "iprt/asmdefs.mac"
+%include "iprt/err.mac"
+
+
+;*******************************************************************************
+;* External Symbols *
+;*******************************************************************************
+extern KernThunkStackTo32
+extern KernThunkStackTo16
+extern NAME(rtTimerOs2Tick)
+extern NAME(RTErrConvertFromOS2)
+BEGINDATA16
+extern NAME(g_fpfnDevHlp)
+
+
+;*******************************************************************************
+;* Defined Constants And Macros *
+;*******************************************************************************
+%define DevHlp_SetTimer 01dh
+%define DevHlp_ResetTimer 01eh
+
+
+BEGINCODE
+
+;;
+; Arms the our OS/2 timer.
+;
+; @returns IPRT status code.
+;
+BEGINPROC_EXPORTED rtTimerOs2Arm
+ call KernThunkStackTo16
+ push ebp
+ mov ebp, esp
+
+ ; jump to the 16-bit code.
+ ;jmp far dword NAME(rtTimerOs2Arm_16) wrt CODE16
+ db 066h
+ db 0eah
+ dw NAME(rtTimerOs2Arm_16) wrt CODE16
+ dw CODE16
+BEGINCODE16
+GLOBALNAME rtTimerOs2Arm_16
+
+ ; setup and do the call
+ push ds
+ push es
+ mov dx, DATA16
+ mov ds, dx
+ mov es, dx
+
+ mov ax, NAME(rtTimerOs2TickAsm) wrt CODE16
+ mov dl, DevHlp_SetTimer
+ call far [NAME(g_fpfnDevHlp)]
+
+ pop es
+ pop ds
+
+ ;jmp far dword NAME(rtTimerOs2Arm_32) wrt FLAT
+ db 066h
+ db 0eah
+ dd NAME(rtTimerOs2Arm_32) ;wrt FLAT
+ dw TEXT32 wrt FLAT
+BEGINCODE
+GLOBALNAME rtTimerOs2Arm_32
+ jc .error
+ xor eax, eax
+.done:
+
+ leave
+ push eax
+ call KernThunkStackTo32
+ pop eax
+ ret
+
+ ; convert the error code.
+.error:
+ and eax, 0ffffh
+ call NAME(RTErrConvertFromOS2)
+ jmp .done
+ENDPROC rtTimerOs2Arm
+
+
+;;
+; Dearms the our OS/2 timer.
+;
+; @returns IPRT status code.
+;
+BEGINPROC_EXPORTED rtTimerOs2Dearm
+ call KernThunkStackTo16
+ push ebp
+ mov ebp, esp
+
+ ; jump to the 16-bit code.
+ ;jmp far dword NAME(rtTimerOs2Dearm_16) wrt CODE16
+ db 066h
+ db 0eah
+ dw NAME(rtTimerOs2Dearm_16) wrt CODE16
+ dw CODE16
+BEGINCODE16
+GLOBALNAME rtTimerOs2Dearm_16
+
+ ; setup and do the call
+ push ds
+ push es
+ mov dx, DATA16
+ mov ds, dx
+ mov es, dx
+
+ mov ax, NAME(rtTimerOs2TickAsm) wrt CODE16
+ mov dl, DevHlp_ResetTimer
+ call far [NAME(g_fpfnDevHlp)]
+
+ pop es
+ pop ds
+
+ ;jmp far dword NAME(rtTimerOs2Dearm_32) wrt FLAT
+ db 066h
+ db 0eah
+ dd NAME(rtTimerOs2Dearm_32) ;wrt FLAT
+ dw TEXT32 wrt FLAT
+BEGINCODE
+GLOBALNAME rtTimerOs2Dearm_32
+ jc .error
+ xor eax, eax
+.done:
+
+ ; epilogue
+ leave
+ push eax
+ call KernThunkStackTo32
+ pop eax
+ ret
+
+ ; convert the error code.
+.error:
+ and eax, 0ffffh
+ call NAME(RTErrConvertFromOS2)
+ jmp .done
+ENDPROC rtTimerOs2Dearm
+
+
+BEGINCODE16
+
+;;
+; OS/2 timer tick callback.
+;
+BEGINPROC rtTimerOs2TickAsm
+ push ds
+ push es
+ push ecx
+ push edx
+ push eax
+
+ mov ax, DATA32 wrt FLAT
+ mov ds, ax
+ mov es, ax
+
+ ;jmp far dword NAME(rtTimerOs2TickAsm_32) wrt FLAT
+ db 066h
+ db 0eah
+ dd NAME(rtTimerOs2TickAsm_32) ;wrt FLAT
+ dw TEXT32 wrt FLAT
+BEGINCODE
+GLOBALNAME rtTimerOs2TickAsm_32
+ call KernThunkStackTo32
+ call NAME(rtTimerOs2Tick)
+ call KernThunkStackTo16
+
+ ;jmp far dword NAME(rtTimerOs2TickAsm_16) wrt CODE16
+ db 066h
+ db 0eah
+ dw NAME(rtTimerOs2TickAsm_16) wrt CODE16
+ dw CODE16
+BEGINCODE16
+GLOBALNAME rtTimerOs2TickAsm_16
+
+ pop eax
+ pop edx
+ pop ecx
+ pop es
+ pop ds
+ retf
+ENDPROC rtTimerOs2TickAsm