diff options
Diffstat (limited to 'src/VBox/Runtime/r0drv/os2')
22 files changed, 3454 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..17e37052 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/RTR0AssertPanicSystem-r0drv-os2.asm @@ -0,0 +1,104 @@ +; $Id: RTR0AssertPanicSystem-r0drv-os2.asm $ +;; @file +; IPRT - RTR0AssertPanicSystem, Ring-0 Driver, OS/2. +; + +; +; 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..e0c94b7f --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/RTR0Os2DHQueryDOSVar.asm @@ -0,0 +1,183 @@ +; $Id: RTR0Os2DHQueryDOSVar.asm $ +;; @file +; IPRT - DevHelp_GetDOSVar, Ring-0 Driver, OS/2. +; + +; +; 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..e1b44d42 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/RTR0Os2DHVMGlobalToProcess.asm @@ -0,0 +1,114 @@ +; $Id: RTR0Os2DHVMGlobalToProcess.asm $ +;; @file +; IPRT - DevHelp_VMGlobalToProcess, Ring-0 Driver, OS/2. +; + +; +; 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..c448a987 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/alloc-r0drv-os2.cpp @@ -0,0 +1,107 @@ +/* $Id: alloc-r0drv-os2.cpp $ */ +/** @file + * IPRT - Memory Allocation, Ring-0 Driver, OS/2. + */ + +/* + * 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..7c08db34 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/assert-r0drv-os2.cpp @@ -0,0 +1,134 @@ +/* $Id: assert-r0drv-os2.cpp $ */ +/** @file + * IPRT - Assertion Workers, Ring-0 Drivers, OS/2. + */ + +/* + * 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..0e0808aa --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/assertA-r0drv-os2.asm @@ -0,0 +1,47 @@ +; $Id: assertA-r0drv-os2.asm $ +;; @file +; IPRT - DevHelp_GetDOSVar, Ring-0 Driver, OS/2. +; + +; +; 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..d77fbd68 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/initterm-r0drv-os2.cpp @@ -0,0 +1,98 @@ +/* $Id: initterm-r0drv-os2.cpp $ */ +/** @file + * IPRT - Initialization & Termination, Ring-0 Driver, OS/2. + */ + +/* + * 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..4fb0abd8 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp @@ -0,0 +1,572 @@ +/* $Id: memobj-r0drv-os2.cpp $ */ +/** @file + * IPRT - Ring-0 Memory Objects, OS/2. + */ + +/* + * 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) +{ + 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); + if (!pMemOs2) + return VERR_NO_MEMORY; + + /* 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); + *ppMem = &pMemOs2->Core; + return VINF_SUCCESS; + } + KernVMFree(pMemOs2->Core.pv); + } + rtR0MemObjDelete(&pMemOs2->Core); + return RTErrConvertFromOS2(rc); +} + + +DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) +{ + 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); + if (!pMemOs2) + return VERR_NO_MEMORY; + + /* 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); + *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; +} + + +DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) +{ + NOREF(fExecutable); + + /* create the object. */ + PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_CONT, NULL, cb); + if (!pMemOs2) + return VERR_NO_MEMORY; + + /* 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.u.Cont.Phys = ulPhys; + *ppMem = &pMemOs2->Core; + return VINF_SUCCESS; + } + rtR0MemObjDelete(&pMemOs2->Core); + return RTErrConvertFromOS2(rc); +} + + +DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment) +{ + 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); + if (!pMemOs2) + return VERR_NO_MEMORY; + + /* 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.u.Phys.fAllocated = true; + pMemOs2->Core.u.Phys.PhysBase = ulPhys; + *ppMem = &pMemOs2->Core; + return VINF_SUCCESS; + } + rtR0MemObjDelete(&pMemOs2->Core); + return RTErrConvertFromOS2(rc); +} + + +DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest) +{ + /** @todo rtR0MemObjNativeAllocPhys / darwin. */ + return rtR0MemObjNativeAllocPhys(ppMem, cb, PhysHighest, PAGE_SIZE); +} + + +DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy) +{ + 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); + if (!pMemOs2) + return VERR_NO_MEMORY; + + /* 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; +} + + +DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, + RTR0PROCESS R0Process) +{ + 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); + if (!pMemOs2) + return VERR_NO_MEMORY; + + /* 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); +} + + +DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess) +{ + /* create the object. */ + const ULONG cPages = cb >> PAGE_SHIFT; + PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF_DYN(RTR0MEMOBJOS2, aPages[cPages]), + RTR0MEMOBJTYPE_LOCK, pv, cb); + if (!pMemOs2) + return VERR_NO_MEMORY; + + /* 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); +} + + +DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment) +{ + RT_NOREF(ppMem, pvFixed, cb, uAlignment); + return VERR_NOT_SUPPORTED; +} + + +DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, + RTR0PROCESS R0Process) +{ + RT_NOREF(ppMem, R3PtrFixed, cb, uAlignment, R0Process); + return VERR_NOT_SUPPORTED; +} + + +DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, + unsigned fProt, size_t offSub, size_t cbSub) +{ + AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED); + 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). + */ + PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_UOFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING, + pvR0, pMemToMapOs2->Core.cb); + 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) +{ + 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; + + 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); + 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..c1251db6 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/memuserkernel-r0drv-os2.cpp @@ -0,0 +1,91 @@ +/* $Id: memuserkernel-r0drv-os2.cpp $ */ +/** @file + * IPRT - User & Kernel Memory, Ring-0 Driver, OS/2. + */ + +/* + * Copyright (C) 2009-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE 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. + */ + + +/********************************************************************************************************************************* +* 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..585f1143 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/process-r0drv-os2.cpp @@ -0,0 +1,54 @@ +/* $Id: process-r0drv-os2.cpp $ */ +/** @file + * IPRT - Process Management, Ring-0 Driver, OS/2. + */ + +/* + * 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..98950c6a --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/semevent-r0drv-os2.cpp @@ -0,0 +1,271 @@ +/* $Id: semevent-r0drv-os2.cpp $ */ +/** @file + * IPRT - Single Release Event Semaphores, Ring-0 Driver, OS/2. + */ + +/* + * 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 */ +} + 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..c7f8bfbd --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/semeventmulti-r0drv-os2.cpp @@ -0,0 +1,281 @@ +/* $Id: semeventmulti-r0drv-os2.cpp $ */ +/** @file + * IPRT - Multiple Release Event Semaphores, Ring-0 Driver, OS/2. + */ + +/* + * 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 */ +} + 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..c00a4233 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/semfastmutex-r0drv-os2.cpp @@ -0,0 +1,115 @@ +/* $Id: semfastmutex-r0drv-os2.cpp $ */ +/** @file + * IPRT - Fast Mutex Semaphores, Ring-0 Driver, OS/2. + */ + +/* + * 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..a83f8839 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/spinlock-r0drv-os2.cpp @@ -0,0 +1,131 @@ +/* $Id: spinlock-r0drv-os2.cpp $ */ +/** @file + * IPRT - Spinlocks, Ring-0 Driver, OS/2. + */ + +/* + * 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..bd4a0c94 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/the-os2-kernel.h @@ -0,0 +1,59 @@ +/* $Id: the-os2-kernel.h $ */ +/** @file + * IPRT - Ring-0 Driver, The OS/2 Kernel Headers. + */ + +/* + * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef 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..5910d0c3 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/thread-r0drv-os2.cpp @@ -0,0 +1,191 @@ +/* $Id: thread-r0drv-os2.cpp $ */ +/** @file + * IPRT - Threads (Part 1), Ring-0 Driver, OS/2. + */ + +/* + * 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..41c2634e --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/thread2-r0drv-os2.cpp @@ -0,0 +1,86 @@ +/* $Id: thread2-r0drv-os2.cpp $ */ +/** @file + * IPRT - Threads (Part 2), Ring-0 Driver, Generic Stubs. + */ + +/* + * 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..de749de8 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/time-r0drv-os2.cpp @@ -0,0 +1,92 @@ +/* $Id: time-r0drv-os2.cpp $ */ +/** @file + * IPRT - Time, Ring-0 Driver, OS/2. + */ + +/* + * 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..08f8bc55 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/timer-r0drv-os2.cpp @@ -0,0 +1,385 @@ +/* $Id: timer-r0drv-os2.cpp $ */ +/** @file + * IPRT - Memory Allocation, Ring-0 Driver, OS/2. + */ + +/* + * 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) +{ + AssertReturn(VALID_PTR(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..474f8576 --- /dev/null +++ b/src/VBox/Runtime/r0drv/os2/timerA-r0drv-os2.asm @@ -0,0 +1,218 @@ +; $Id: timerA-r0drv-os2.asm $ +;; @file +; IPRT - DevHelp_VMGlobalToProcess, Ring-0 Driver, OS/2. +; + +; +; 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 |