diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2012-10-26 16:25:44 +0000 |
---|---|---|
committer | <> | 2012-11-12 12:15:52 +0000 |
commit | 58ed4748338f9466599adfc8a9171280ed99e23f (patch) | |
tree | 02027d99ded4fb56a64aa9489ac2eb487e7858ab /include/iprt | |
download | VirtualBox-58ed4748338f9466599adfc8a9171280ed99e23f.tar.gz |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.2.4.tar.bz2.VirtualBox-4.2.4
Diffstat (limited to 'include/iprt')
131 files changed, 69151 insertions, 0 deletions
diff --git a/include/iprt/Makefile.kup b/include/iprt/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/include/iprt/Makefile.kup diff --git a/include/iprt/alloc.h b/include/iprt/alloc.h new file mode 100644 index 00000000..e30b7f87 --- /dev/null +++ b/include/iprt/alloc.h @@ -0,0 +1,33 @@ +/** @file + * IPRT - Memory Allocation. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_alloc_h +#define ___iprt_alloc_h + +/* Forwarding to the canonical header. */ +#include <iprt/mem.h> + +#endif + diff --git a/include/iprt/alloca.h b/include/iprt/alloca.h new file mode 100644 index 00000000..4aa00e6a --- /dev/null +++ b/include/iprt/alloca.h @@ -0,0 +1,56 @@ +/** @file + * IPRT - alloca(). + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_alloca_h +#define ___iprt_alloca_h + +#if defined(IN_RC) || defined(IN_RING0_AGNOSTIC) +# error "No alloca() in raw-mode and agnostic ring-0 context as it may have external dependencies like libgcc." +#endif + +/* + * If there are more difficult platforms out there, we'll do OS + * specific #ifdefs. But for now we'll just include the headers + * which normally contains the alloca() prototype. + * When we're in kernel territory it starts getting a bit more + * interesting of course... + */ +#if defined(IN_RING0) \ + && (defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)) +/* ASSUMES GNU C */ +# define alloca(cb) __builtin_alloca(cb) + +#else +# include <stdlib.h> +# if !defined(RT_OS_DARWIN) && !defined(RT_OS_FREEBSD) +# include <malloc.h> +# endif +# ifdef RT_OS_SOLARIS +# include <alloca.h> +# endif +#endif + +#endif + diff --git a/include/iprt/asm-amd64-x86.h b/include/iprt/asm-amd64-x86.h new file mode 100644 index 00000000..22efb441 --- /dev/null +++ b/include/iprt/asm-amd64-x86.h @@ -0,0 +1,2701 @@ +/** @file + * IPRT - AMD64 and x86 Specific Assembly Functions. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_asm_amd64_x86_h +#define ___iprt_asm_amd64_x86_h + +#include <iprt/types.h> +#if !defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86) +# error "Not on AMD64 or x86" +#endif + +#if defined(_MSC_VER) && RT_INLINE_ASM_USES_INTRIN +# include <intrin.h> + /* Emit the intrinsics at all optimization levels. */ +# pragma intrinsic(_ReadWriteBarrier) +# pragma intrinsic(__cpuid) +# pragma intrinsic(_enable) +# pragma intrinsic(_disable) +# pragma intrinsic(__rdtsc) +# pragma intrinsic(__readmsr) +# pragma intrinsic(__writemsr) +# pragma intrinsic(__outbyte) +# pragma intrinsic(__outbytestring) +# pragma intrinsic(__outword) +# pragma intrinsic(__outwordstring) +# pragma intrinsic(__outdword) +# pragma intrinsic(__outdwordstring) +# pragma intrinsic(__inbyte) +# pragma intrinsic(__inbytestring) +# pragma intrinsic(__inword) +# pragma intrinsic(__inwordstring) +# pragma intrinsic(__indword) +# pragma intrinsic(__indwordstring) +# pragma intrinsic(__invlpg) +# pragma intrinsic(__wbinvd) +# pragma intrinsic(__readcr0) +# pragma intrinsic(__readcr2) +# pragma intrinsic(__readcr3) +# pragma intrinsic(__readcr4) +# pragma intrinsic(__writecr0) +# pragma intrinsic(__writecr3) +# pragma intrinsic(__writecr4) +# pragma intrinsic(__readdr) +# pragma intrinsic(__writedr) +# ifdef RT_ARCH_AMD64 +# pragma intrinsic(__readcr8) +# pragma intrinsic(__writecr8) +# endif +#endif + + + +/** @defgroup grp_rt_asm_amd64_x86 AMD64 and x86 Specific ASM Routines + * @ingroup grp_rt_asm + * @{ + */ + +/** @todo find a more proper place for this structure? */ +#pragma pack(1) +/** IDTR */ +typedef struct RTIDTR +{ + /** Size of the IDT. */ + uint16_t cbIdt; + /** Address of the IDT. */ + uintptr_t pIdt; +} RTIDTR, *PRTIDTR; +#pragma pack() + +#pragma pack(1) +/** GDTR */ +typedef struct RTGDTR +{ + /** Size of the GDT. */ + uint16_t cbGdt; + /** Address of the GDT. */ + uintptr_t pGdt; +} RTGDTR, *PRTGDTR; +#pragma pack() + + +/** + * Gets the content of the IDTR CPU register. + * @param pIdtr Where to store the IDTR contents. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMGetIDTR(PRTIDTR pIdtr); +#else +DECLINLINE(void) ASMGetIDTR(PRTIDTR pIdtr) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("sidt %0" : "=m" (*pIdtr)); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pIdtr] + sidt [rax] +# else + mov eax, [pIdtr] + sidt [eax] +# endif + } +# endif +} +#endif + + +/** + * Sets the content of the IDTR CPU register. + * @param pIdtr Where to load the IDTR contents from + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMSetIDTR(const RTIDTR *pIdtr); +#else +DECLINLINE(void) ASMSetIDTR(const RTIDTR *pIdtr) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lidt %0" : : "m" (*pIdtr)); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pIdtr] + lidt [rax] +# else + mov eax, [pIdtr] + lidt [eax] +# endif + } +# endif +} +#endif + + +/** + * Gets the content of the GDTR CPU register. + * @param pGdtr Where to store the GDTR contents. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMGetGDTR(PRTGDTR pGdtr); +#else +DECLINLINE(void) ASMGetGDTR(PRTGDTR pGdtr) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("sgdt %0" : "=m" (*pGdtr)); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pGdtr] + sgdt [rax] +# else + mov eax, [pGdtr] + sgdt [eax] +# endif + } +# endif +} +#endif + +/** + * Get the cs register. + * @returns cs. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(RTSEL) ASMGetCS(void); +#else +DECLINLINE(RTSEL) ASMGetCS(void) +{ + RTSEL SelCS; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("movw %%cs, %0\n\t" : "=r" (SelCS)); +# else + __asm + { + mov ax, cs + mov [SelCS], ax + } +# endif + return SelCS; +} +#endif + + +/** + * Get the DS register. + * @returns DS. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(RTSEL) ASMGetDS(void); +#else +DECLINLINE(RTSEL) ASMGetDS(void) +{ + RTSEL SelDS; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("movw %%ds, %0\n\t" : "=r" (SelDS)); +# else + __asm + { + mov ax, ds + mov [SelDS], ax + } +# endif + return SelDS; +} +#endif + + +/** + * Get the ES register. + * @returns ES. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(RTSEL) ASMGetES(void); +#else +DECLINLINE(RTSEL) ASMGetES(void) +{ + RTSEL SelES; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("movw %%es, %0\n\t" : "=r" (SelES)); +# else + __asm + { + mov ax, es + mov [SelES], ax + } +# endif + return SelES; +} +#endif + + +/** + * Get the FS register. + * @returns FS. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(RTSEL) ASMGetFS(void); +#else +DECLINLINE(RTSEL) ASMGetFS(void) +{ + RTSEL SelFS; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("movw %%fs, %0\n\t" : "=r" (SelFS)); +# else + __asm + { + mov ax, fs + mov [SelFS], ax + } +# endif + return SelFS; +} +# endif + + +/** + * Get the GS register. + * @returns GS. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(RTSEL) ASMGetGS(void); +#else +DECLINLINE(RTSEL) ASMGetGS(void) +{ + RTSEL SelGS; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("movw %%gs, %0\n\t" : "=r" (SelGS)); +# else + __asm + { + mov ax, gs + mov [SelGS], ax + } +# endif + return SelGS; +} +#endif + + +/** + * Get the SS register. + * @returns SS. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(RTSEL) ASMGetSS(void); +#else +DECLINLINE(RTSEL) ASMGetSS(void) +{ + RTSEL SelSS; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("movw %%ss, %0\n\t" : "=r" (SelSS)); +# else + __asm + { + mov ax, ss + mov [SelSS], ax + } +# endif + return SelSS; +} +#endif + + +/** + * Get the TR register. + * @returns TR. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(RTSEL) ASMGetTR(void); +#else +DECLINLINE(RTSEL) ASMGetTR(void) +{ + RTSEL SelTR; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("str %w0\n\t" : "=r" (SelTR)); +# else + __asm + { + str ax + mov [SelTR], ax + } +# endif + return SelTR; +} +#endif + + +/** + * Get the [RE]FLAGS register. + * @returns [RE]FLAGS. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(RTCCUINTREG) ASMGetFlags(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetFlags(void) +{ + RTCCUINTREG uFlags; +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("pushfq\n\t" + "popq %0\n\t" + : "=r" (uFlags)); +# else + __asm__ __volatile__("pushfl\n\t" + "popl %0\n\t" + : "=r" (uFlags)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + pushfq + pop [uFlags] +# else + pushfd + pop [uFlags] +# endif + } +# endif + return uFlags; +} +#endif + + +/** + * Set the [RE]FLAGS register. + * @param uFlags The new [RE]FLAGS value. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMSetFlags(RTCCUINTREG uFlags); +#else +DECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags) +{ +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("pushq %0\n\t" + "popfq\n\t" + : : "g" (uFlags)); +# else + __asm__ __volatile__("pushl %0\n\t" + "popfl\n\t" + : : "g" (uFlags)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + push [uFlags] + popfq +# else + push [uFlags] + popfd +# endif + } +# endif +} +#endif + + +/** + * Gets the content of the CPU timestamp counter register. + * + * @returns TSC. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint64_t) ASMReadTSC(void); +#else +DECLINLINE(uint64_t) ASMReadTSC(void) +{ + RTUINT64U u; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rdtsc\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi)); +# else +# if RT_INLINE_ASM_USES_INTRIN + u.u = __rdtsc(); +# else + __asm + { + rdtsc + mov [u.s.Lo], eax + mov [u.s.Hi], edx + } +# endif +# endif + return u.u; +} +#endif + + +/** + * Performs the cpuid instruction returning all registers. + * + * @param uOperator CPUID operation (eax). + * @param pvEAX Where to store eax. + * @param pvEBX Where to store ebx. + * @param pvECX Where to store ecx. + * @param pvEDX Where to store edx. + * @remark We're using void pointers to ease the use of special bitfield structures and such. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX); +#else +DECLINLINE(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX) +{ +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + RTCCUINTREG uRAX, uRBX, uRCX, uRDX; + __asm__ __volatile__ ("cpuid\n\t" + : "=a" (uRAX), + "=b" (uRBX), + "=c" (uRCX), + "=d" (uRDX) + : "0" (uOperator), "2" (0)); + *(uint32_t *)pvEAX = (uint32_t)uRAX; + *(uint32_t *)pvEBX = (uint32_t)uRBX; + *(uint32_t *)pvECX = (uint32_t)uRCX; + *(uint32_t *)pvEDX = (uint32_t)uRDX; +# else + __asm__ __volatile__ ("xchgl %%ebx, %1\n\t" + "cpuid\n\t" + "xchgl %%ebx, %1\n\t" + : "=a" (*(uint32_t *)pvEAX), + "=r" (*(uint32_t *)pvEBX), + "=c" (*(uint32_t *)pvECX), + "=d" (*(uint32_t *)pvEDX) + : "0" (uOperator), "2" (0)); +# endif + +# elif RT_INLINE_ASM_USES_INTRIN + int aInfo[4]; + __cpuid(aInfo, uOperator); + *(uint32_t *)pvEAX = aInfo[0]; + *(uint32_t *)pvEBX = aInfo[1]; + *(uint32_t *)pvECX = aInfo[2]; + *(uint32_t *)pvEDX = aInfo[3]; + +# else + uint32_t uEAX; + uint32_t uEBX; + uint32_t uECX; + uint32_t uEDX; + __asm + { + push ebx + mov eax, [uOperator] + cpuid + mov [uEAX], eax + mov [uEBX], ebx + mov [uECX], ecx + mov [uEDX], edx + pop ebx + } + *(uint32_t *)pvEAX = uEAX; + *(uint32_t *)pvEBX = uEBX; + *(uint32_t *)pvECX = uECX; + *(uint32_t *)pvEDX = uEDX; +# endif +} +#endif + + +/** + * Performs the cpuid instruction returning all registers. + * Some subfunctions of cpuid take ECX as additional parameter (currently known for EAX=4) + * + * @param uOperator CPUID operation (eax). + * @param uIdxECX ecx index + * @param pvEAX Where to store eax. + * @param pvEBX Where to store ebx. + * @param pvECX Where to store ecx. + * @param pvEDX Where to store edx. + * @remark We're using void pointers to ease the use of special bitfield structures and such. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX); +#else +DECLINLINE(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX) +{ +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + RTCCUINTREG uRAX, uRBX, uRCX, uRDX; + __asm__ ("cpuid\n\t" + : "=a" (uRAX), + "=b" (uRBX), + "=c" (uRCX), + "=d" (uRDX) + : "0" (uOperator), + "2" (uIdxECX)); + *(uint32_t *)pvEAX = (uint32_t)uRAX; + *(uint32_t *)pvEBX = (uint32_t)uRBX; + *(uint32_t *)pvECX = (uint32_t)uRCX; + *(uint32_t *)pvEDX = (uint32_t)uRDX; +# else + __asm__ ("xchgl %%ebx, %1\n\t" + "cpuid\n\t" + "xchgl %%ebx, %1\n\t" + : "=a" (*(uint32_t *)pvEAX), + "=r" (*(uint32_t *)pvEBX), + "=c" (*(uint32_t *)pvECX), + "=d" (*(uint32_t *)pvEDX) + : "0" (uOperator), + "2" (uIdxECX)); +# endif + +# elif RT_INLINE_ASM_USES_INTRIN + int aInfo[4]; + /* ??? another intrinsic ??? */ + __cpuid(aInfo, uOperator); + *(uint32_t *)pvEAX = aInfo[0]; + *(uint32_t *)pvEBX = aInfo[1]; + *(uint32_t *)pvECX = aInfo[2]; + *(uint32_t *)pvEDX = aInfo[3]; + +# else + uint32_t uEAX; + uint32_t uEBX; + uint32_t uECX; + uint32_t uEDX; + __asm + { + push ebx + mov eax, [uOperator] + mov ecx, [uIdxECX] + cpuid + mov [uEAX], eax + mov [uEBX], ebx + mov [uECX], ecx + mov [uEDX], edx + pop ebx + } + *(uint32_t *)pvEAX = uEAX; + *(uint32_t *)pvEBX = uEBX; + *(uint32_t *)pvECX = uECX; + *(uint32_t *)pvEDX = uEDX; +# endif +} +#endif + + +/** + * Performs the cpuid instruction returning ecx and edx. + * + * @param uOperator CPUID operation (eax). + * @param pvECX Where to store ecx. + * @param pvEDX Where to store edx. + * @remark We're using void pointers to ease the use of special bitfield structures and such. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX); +#else +DECLINLINE(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX) +{ + uint32_t uEBX; + ASMCpuId(uOperator, &uOperator, &uEBX, pvECX, pvEDX); +} +#endif + + +/** + * Performs the cpuid instruction returning eax. + * + * @param uOperator CPUID operation (eax). + * @returns EAX after cpuid operation. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMCpuId_EAX(uint32_t uOperator); +#else +DECLINLINE(uint32_t) ASMCpuId_EAX(uint32_t uOperator) +{ + RTCCUINTREG xAX; +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ ("cpuid" + : "=a" (xAX) + : "0" (uOperator) + : "rbx", "rcx", "rdx"); +# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__) + __asm__ ("push %%ebx\n\t" + "cpuid\n\t" + "pop %%ebx\n\t" + : "=a" (xAX) + : "0" (uOperator) + : "ecx", "edx"); +# else + __asm__ ("cpuid" + : "=a" (xAX) + : "0" (uOperator) + : "edx", "ecx", "ebx"); +# endif + +# elif RT_INLINE_ASM_USES_INTRIN + int aInfo[4]; + __cpuid(aInfo, uOperator); + xAX = aInfo[0]; + +# else + __asm + { + push ebx + mov eax, [uOperator] + cpuid + mov [xAX], eax + pop ebx + } +# endif + return (uint32_t)xAX; +} +#endif + + +/** + * Performs the cpuid instruction returning ebx. + * + * @param uOperator CPUID operation (eax). + * @returns EBX after cpuid operation. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMCpuId_EBX(uint32_t uOperator); +#else +DECLINLINE(uint32_t) ASMCpuId_EBX(uint32_t uOperator) +{ + RTCCUINTREG xBX; +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + RTCCUINTREG uSpill; + __asm__ ("cpuid" + : "=a" (uSpill), + "=b" (xBX) + : "0" (uOperator) + : "rdx", "rcx"); +# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__) + __asm__ ("push %%ebx\n\t" + "cpuid\n\t" + "mov %%ebx, %%edx\n\t" + "pop %%ebx\n\t" + : "=a" (uOperator), + "=d" (xBX) + : "0" (uOperator) + : "ecx"); +# else + __asm__ ("cpuid" + : "=a" (uOperator), + "=b" (xBX) + : "0" (uOperator) + : "edx", "ecx"); +# endif + +# elif RT_INLINE_ASM_USES_INTRIN + int aInfo[4]; + __cpuid(aInfo, uOperator); + xBX = aInfo[1]; + +# else + __asm + { + push ebx + mov eax, [uOperator] + cpuid + mov [xBX], ebx + pop ebx + } +# endif + return (uint32_t)xBX; +} +#endif + + +/** + * Performs the cpuid instruction returning ecx. + * + * @param uOperator CPUID operation (eax). + * @returns ECX after cpuid operation. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMCpuId_ECX(uint32_t uOperator); +#else +DECLINLINE(uint32_t) ASMCpuId_ECX(uint32_t uOperator) +{ + RTCCUINTREG xCX; +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + RTCCUINTREG uSpill; + __asm__ ("cpuid" + : "=a" (uSpill), + "=c" (xCX) + : "0" (uOperator) + : "rbx", "rdx"); +# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__) + __asm__ ("push %%ebx\n\t" + "cpuid\n\t" + "pop %%ebx\n\t" + : "=a" (uOperator), + "=c" (xCX) + : "0" (uOperator) + : "edx"); +# else + __asm__ ("cpuid" + : "=a" (uOperator), + "=c" (xCX) + : "0" (uOperator) + : "ebx", "edx"); + +# endif + +# elif RT_INLINE_ASM_USES_INTRIN + int aInfo[4]; + __cpuid(aInfo, uOperator); + xCX = aInfo[2]; + +# else + __asm + { + push ebx + mov eax, [uOperator] + cpuid + mov [xCX], ecx + pop ebx + } +# endif + return (uint32_t)xCX; +} +#endif + + +/** + * Performs the cpuid instruction returning edx. + * + * @param uOperator CPUID operation (eax). + * @returns EDX after cpuid operation. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMCpuId_EDX(uint32_t uOperator); +#else +DECLINLINE(uint32_t) ASMCpuId_EDX(uint32_t uOperator) +{ + RTCCUINTREG xDX; +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + RTCCUINTREG uSpill; + __asm__ ("cpuid" + : "=a" (uSpill), + "=d" (xDX) + : "0" (uOperator) + : "rbx", "rcx"); +# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__) + __asm__ ("push %%ebx\n\t" + "cpuid\n\t" + "pop %%ebx\n\t" + : "=a" (uOperator), + "=d" (xDX) + : "0" (uOperator) + : "ecx"); +# else + __asm__ ("cpuid" + : "=a" (uOperator), + "=d" (xDX) + : "0" (uOperator) + : "ebx", "ecx"); +# endif + +# elif RT_INLINE_ASM_USES_INTRIN + int aInfo[4]; + __cpuid(aInfo, uOperator); + xDX = aInfo[3]; + +# else + __asm + { + push ebx + mov eax, [uOperator] + cpuid + mov [xDX], edx + pop ebx + } +# endif + return (uint32_t)xDX; +} +#endif + + +/** + * Checks if the current CPU supports CPUID. + * + * @returns true if CPUID is supported. + */ +DECLINLINE(bool) ASMHasCpuId(void) +{ +#ifdef RT_ARCH_AMD64 + return true; /* ASSUME that all amd64 compatible CPUs have cpuid. */ +#else /* !RT_ARCH_AMD64 */ + bool fRet = false; +# if RT_INLINE_ASM_GNU_STYLE + uint32_t u1; + uint32_t u2; + __asm__ ("pushf\n\t" + "pop %1\n\t" + "mov %1, %2\n\t" + "xorl $0x200000, %1\n\t" + "push %1\n\t" + "popf\n\t" + "pushf\n\t" + "pop %1\n\t" + "cmpl %1, %2\n\t" + "setne %0\n\t" + "push %2\n\t" + "popf\n\t" + : "=m" (fRet), "=r" (u1), "=r" (u2)); +# else + __asm + { + pushfd + pop eax + mov ebx, eax + xor eax, 0200000h + push eax + popfd + pushfd + pop eax + cmp eax, ebx + setne fRet + push ebx + popfd + } +# endif + return fRet; +#endif /* !RT_ARCH_AMD64 */ +} + + +/** + * Gets the APIC ID of the current CPU. + * + * @returns the APIC ID. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint8_t) ASMGetApicId(void); +#else +DECLINLINE(uint8_t) ASMGetApicId(void) +{ + RTCCUINTREG xBX; +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + RTCCUINTREG uSpill; + __asm__ __volatile__ ("cpuid" + : "=a" (uSpill), + "=b" (xBX) + : "0" (1) + : "rcx", "rdx"); +# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__) + RTCCUINTREG uSpill; + __asm__ __volatile__ ("mov %%ebx,%1\n\t" + "cpuid\n\t" + "xchgl %%ebx,%1\n\t" + : "=a" (uSpill), + "=rm" (xBX) + : "0" (1) + : "ecx", "edx"); +# else + RTCCUINTREG uSpill; + __asm__ __volatile__ ("cpuid" + : "=a" (uSpill), + "=b" (xBX) + : "0" (1) + : "ecx", "edx"); +# endif + +# elif RT_INLINE_ASM_USES_INTRIN + int aInfo[4]; + __cpuid(aInfo, 1); + xBX = aInfo[1]; + +# else + __asm + { + push ebx + mov eax, 1 + cpuid + mov [xBX], ebx + pop ebx + } +# endif + return (uint8_t)(xBX >> 24); +} +#endif + + +/** + * Tests if it a genuine Intel CPU based on the ASMCpuId(0) output. + * + * @returns true/false. + * @param uEBX EBX return from ASMCpuId(0) + * @param uECX ECX return from ASMCpuId(0) + * @param uEDX EDX return from ASMCpuId(0) + */ +DECLINLINE(bool) ASMIsIntelCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX) +{ + return uEBX == UINT32_C(0x756e6547) + && uECX == UINT32_C(0x6c65746e) + && uEDX == UINT32_C(0x49656e69); +} + + +/** + * Tests if this is a genuine Intel CPU. + * + * @returns true/false. + * @remarks ASSUMES that cpuid is supported by the CPU. + */ +DECLINLINE(bool) ASMIsIntelCpu(void) +{ + uint32_t uEAX, uEBX, uECX, uEDX; + ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX); + return ASMIsIntelCpuEx(uEBX, uECX, uEDX); +} + + +/** + * Tests if it a authentic AMD CPU based on the ASMCpuId(0) output. + * + * @returns true/false. + * @param uEBX EBX return from ASMCpuId(0) + * @param uECX ECX return from ASMCpuId(0) + * @param uEDX EDX return from ASMCpuId(0) + */ +DECLINLINE(bool) ASMIsAmdCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX) +{ + return uEBX == UINT32_C(0x68747541) + && uECX == UINT32_C(0x444d4163) + && uEDX == UINT32_C(0x69746e65); +} + + +/** + * Tests if this is an authentic AMD CPU. + * + * @returns true/false. + * @remarks ASSUMES that cpuid is supported by the CPU. + */ +DECLINLINE(bool) ASMIsAmdCpu(void) +{ + uint32_t uEAX, uEBX, uECX, uEDX; + ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX); + return ASMIsAmdCpuEx(uEBX, uECX, uEDX); +} + + +/** + * Extracts the CPU family from ASMCpuId(1) or ASMCpuId(0x80000001) + * + * @returns Family. + * @param uEAX EAX return from ASMCpuId(1) or ASMCpuId(0x80000001). + */ +DECLINLINE(uint32_t) ASMGetCpuFamily(uint32_t uEAX) +{ + return ((uEAX >> 8) & 0xf) == 0xf + ? ((uEAX >> 20) & 0x7f) + 0xf + : ((uEAX >> 8) & 0xf); +} + + +/** + * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001), Intel variant. + * + * @returns Model. + * @param uEAX EAX from ASMCpuId(1) or ASMCpuId(0x80000001). + */ +DECLINLINE(uint32_t) ASMGetCpuModelIntel(uint32_t uEAX) +{ + return ((uEAX >> 8) & 0xf) == 0xf || (((uEAX >> 8) & 0xf) == 0x6) /* family! */ + ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0) + : ((uEAX >> 4) & 0xf); +} + + +/** + * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001), AMD variant. + * + * @returns Model. + * @param uEAX EAX from ASMCpuId(1) or ASMCpuId(0x80000001). + */ +DECLINLINE(uint32_t) ASMGetCpuModelAMD(uint32_t uEAX) +{ + return ((uEAX >> 8) & 0xf) == 0xf + ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0) + : ((uEAX >> 4) & 0xf); +} + + +/** + * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001) + * + * @returns Model. + * @param uEAX EAX from ASMCpuId(1) or ASMCpuId(0x80000001). + * @param fIntel Whether it's an intel CPU. Use ASMIsIntelCpuEx() or ASMIsIntelCpu(). + */ +DECLINLINE(uint32_t) ASMGetCpuModel(uint32_t uEAX, bool fIntel) +{ + return ((uEAX >> 8) & 0xf) == 0xf || (((uEAX >> 8) & 0xf) == 0x6 && fIntel) /* family! */ + ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0) + : ((uEAX >> 4) & 0xf); +} + + +/** + * Extracts the CPU stepping from ASMCpuId(1) or ASMCpuId(0x80000001) + * + * @returns Model. + * @param uEAX EAX from ASMCpuId(1) or ASMCpuId(0x80000001). + */ +DECLINLINE(uint32_t) ASMGetCpuStepping(uint32_t uEAX) +{ + return uEAX & 0xf; +} + + +/** + * Get cr0. + * @returns cr0. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetCR0(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetCR0(void) +{ + RTCCUINTREG uCR0; +# if RT_INLINE_ASM_USES_INTRIN + uCR0 = __readcr0(); + +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%cr0, %0\t\n" : "=r" (uCR0)); +# else + __asm__ __volatile__("movl %%cr0, %0\t\n" : "=r" (uCR0)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, cr0 + mov [uCR0], rax +# else + mov eax, cr0 + mov [uCR0], eax +# endif + } +# endif + return uCR0; +} +#endif + + +/** + * Sets the CR0 register. + * @param uCR0 The new CR0 value. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetCR0(RTCCUINTREG uCR0); +#else +DECLINLINE(void) ASMSetCR0(RTCCUINTREG uCR0) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writecr0(uCR0); + +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%cr0\n\t" :: "r" (uCR0)); +# else + __asm__ __volatile__("movl %0, %%cr0\n\t" :: "r" (uCR0)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uCR0] + mov cr0, rax +# else + mov eax, [uCR0] + mov cr0, eax +# endif + } +# endif +} +#endif + + +/** + * Get cr2. + * @returns cr2. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetCR2(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetCR2(void) +{ + RTCCUINTREG uCR2; +# if RT_INLINE_ASM_USES_INTRIN + uCR2 = __readcr2(); + +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%cr2, %0\t\n" : "=r" (uCR2)); +# else + __asm__ __volatile__("movl %%cr2, %0\t\n" : "=r" (uCR2)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, cr2 + mov [uCR2], rax +# else + mov eax, cr2 + mov [uCR2], eax +# endif + } +# endif + return uCR2; +} +#endif + + +/** + * Sets the CR2 register. + * @param uCR2 The new CR0 value. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMSetCR2(RTCCUINTREG uCR2); +#else +DECLINLINE(void) ASMSetCR2(RTCCUINTREG uCR2) +{ +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%cr2\n\t" :: "r" (uCR2)); +# else + __asm__ __volatile__("movl %0, %%cr2\n\t" :: "r" (uCR2)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uCR2] + mov cr2, rax +# else + mov eax, [uCR2] + mov cr2, eax +# endif + } +# endif +} +#endif + + +/** + * Get cr3. + * @returns cr3. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetCR3(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetCR3(void) +{ + RTCCUINTREG uCR3; +# if RT_INLINE_ASM_USES_INTRIN + uCR3 = __readcr3(); + +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%cr3, %0\t\n" : "=r" (uCR3)); +# else + __asm__ __volatile__("movl %%cr3, %0\t\n" : "=r" (uCR3)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, cr3 + mov [uCR3], rax +# else + mov eax, cr3 + mov [uCR3], eax +# endif + } +# endif + return uCR3; +} +#endif + + +/** + * Sets the CR3 register. + * + * @param uCR3 New CR3 value. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetCR3(RTCCUINTREG uCR3); +#else +DECLINLINE(void) ASMSetCR3(RTCCUINTREG uCR3) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writecr3(uCR3); + +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%cr3\n\t" : : "r" (uCR3)); +# else + __asm__ __volatile__("movl %0, %%cr3\n\t" : : "r" (uCR3)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uCR3] + mov cr3, rax +# else + mov eax, [uCR3] + mov cr3, eax +# endif + } +# endif +} +#endif + + +/** + * Reloads the CR3 register. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMReloadCR3(void); +#else +DECLINLINE(void) ASMReloadCR3(void) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writecr3(__readcr3()); + +# elif RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG u; +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%cr3, %0\n\t" + "movq %0, %%cr3\n\t" + : "=r" (u)); +# else + __asm__ __volatile__("movl %%cr3, %0\n\t" + "movl %0, %%cr3\n\t" + : "=r" (u)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, cr3 + mov cr3, rax +# else + mov eax, cr3 + mov cr3, eax +# endif + } +# endif +} +#endif + + +/** + * Get cr4. + * @returns cr4. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetCR4(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetCR4(void) +{ + RTCCUINTREG uCR4; +# if RT_INLINE_ASM_USES_INTRIN + uCR4 = __readcr4(); + +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%cr4, %0\t\n" : "=r" (uCR4)); +# else + __asm__ __volatile__("movl %%cr4, %0\t\n" : "=r" (uCR4)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, cr4 + mov [uCR4], rax +# else + push eax /* just in case */ + /*mov eax, cr4*/ + _emit 0x0f + _emit 0x20 + _emit 0xe0 + mov [uCR4], eax + pop eax +# endif + } +# endif + return uCR4; +} +#endif + + +/** + * Sets the CR4 register. + * + * @param uCR4 New CR4 value. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetCR4(RTCCUINTREG uCR4); +#else +DECLINLINE(void) ASMSetCR4(RTCCUINTREG uCR4) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writecr4(uCR4); + +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%cr4\n\t" : : "r" (uCR4)); +# else + __asm__ __volatile__("movl %0, %%cr4\n\t" : : "r" (uCR4)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uCR4] + mov cr4, rax +# else + mov eax, [uCR4] + _emit 0x0F + _emit 0x22 + _emit 0xE0 /* mov cr4, eax */ +# endif + } +# endif +} +#endif + + +/** + * Get cr8. + * @returns cr8. + * @remark The lock prefix hack for access from non-64-bit modes is NOT used and 0 is returned. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetCR8(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetCR8(void) +{ +# ifdef RT_ARCH_AMD64 + RTCCUINTREG uCR8; +# if RT_INLINE_ASM_USES_INTRIN + uCR8 = __readcr8(); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("movq %%cr8, %0\t\n" : "=r" (uCR8)); +# else + __asm + { + mov rax, cr8 + mov [uCR8], rax + } +# endif + return uCR8; +# else /* !RT_ARCH_AMD64 */ + return 0; +# endif /* !RT_ARCH_AMD64 */ +} +#endif + + +/** + * Enables interrupts (EFLAGS.IF). + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMIntEnable(void); +#else +DECLINLINE(void) ASMIntEnable(void) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm("sti\n"); +# elif RT_INLINE_ASM_USES_INTRIN + _enable(); +# else + __asm sti +# endif +} +#endif + + +/** + * Disables interrupts (!EFLAGS.IF). + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMIntDisable(void); +#else +DECLINLINE(void) ASMIntDisable(void) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm("cli\n"); +# elif RT_INLINE_ASM_USES_INTRIN + _disable(); +# else + __asm cli +# endif +} +#endif + + +/** + * Disables interrupts and returns previous xFLAGS. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMIntDisableFlags(void); +#else +DECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void) +{ + RTCCUINTREG xFlags; +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("pushfq\n\t" + "cli\n\t" + "popq %0\n\t" + : "=r" (xFlags)); +# else + __asm__ __volatile__("pushfl\n\t" + "cli\n\t" + "popl %0\n\t" + : "=r" (xFlags)); +# endif +# elif RT_INLINE_ASM_USES_INTRIN && !defined(RT_ARCH_X86) + xFlags = ASMGetFlags(); + _disable(); +# else + __asm { + pushfd + cli + pop [xFlags] + } +# endif + return xFlags; +} +#endif + + +/** + * Are interrupts enabled? + * + * @returns true / false. + */ +DECLINLINE(RTCCUINTREG) ASMIntAreEnabled(void) +{ + RTCCUINTREG uFlags = ASMGetFlags(); + return uFlags & 0x200 /* X86_EFL_IF */ ? true : false; +} + + +/** + * Halts the CPU until interrupted. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMHalt(void); +#else +DECLINLINE(void) ASMHalt(void) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("hlt\n\t"); +# else + __asm { + hlt + } +# endif +} +#endif + + +/** + * Reads a machine specific register. + * + * @returns Register content. + * @param uRegister Register to read. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint64_t) ASMRdMsr(uint32_t uRegister); +#else +DECLINLINE(uint64_t) ASMRdMsr(uint32_t uRegister) +{ + RTUINT64U u; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rdmsr\n\t" + : "=a" (u.s.Lo), + "=d" (u.s.Hi) + : "c" (uRegister)); + +# elif RT_INLINE_ASM_USES_INTRIN + u.u = __readmsr(uRegister); + +# else + __asm + { + mov ecx, [uRegister] + rdmsr + mov [u.s.Lo], eax + mov [u.s.Hi], edx + } +# endif + + return u.u; +} +#endif + + +/** + * Writes a machine specific register. + * + * @returns Register content. + * @param uRegister Register to write to. + * @param u64Val Value to write. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val); +#else +DECLINLINE(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val) +{ + RTUINT64U u; + + u.u = u64Val; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("wrmsr\n\t" + ::"a" (u.s.Lo), + "d" (u.s.Hi), + "c" (uRegister)); + +# elif RT_INLINE_ASM_USES_INTRIN + __writemsr(uRegister, u.u); + +# else + __asm + { + mov ecx, [uRegister] + mov edx, [u.s.Hi] + mov eax, [u.s.Lo] + wrmsr + } +# endif +} +#endif + + +/** + * Reads low part of a machine specific register. + * + * @returns Register content. + * @param uRegister Register to read. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMRdMsr_Low(uint32_t uRegister); +#else +DECLINLINE(uint32_t) ASMRdMsr_Low(uint32_t uRegister) +{ + uint32_t u32; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rdmsr\n\t" + : "=a" (u32) + : "c" (uRegister) + : "edx"); + +# elif RT_INLINE_ASM_USES_INTRIN + u32 = (uint32_t)__readmsr(uRegister); + +#else + __asm + { + mov ecx, [uRegister] + rdmsr + mov [u32], eax + } +# endif + + return u32; +} +#endif + + +/** + * Reads high part of a machine specific register. + * + * @returns Register content. + * @param uRegister Register to read. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMRdMsr_High(uint32_t uRegister); +#else +DECLINLINE(uint32_t) ASMRdMsr_High(uint32_t uRegister) +{ + uint32_t u32; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rdmsr\n\t" + : "=d" (u32) + : "c" (uRegister) + : "eax"); + +# elif RT_INLINE_ASM_USES_INTRIN + u32 = (uint32_t)(__readmsr(uRegister) >> 32); + +# else + __asm + { + mov ecx, [uRegister] + rdmsr + mov [u32], edx + } +# endif + + return u32; +} +#endif + + +/** + * Gets dr0. + * + * @returns dr0. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetDR0(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetDR0(void) +{ + RTCCUINTREG uDR0; +# if RT_INLINE_ASM_USES_INTRIN + uDR0 = __readdr(0); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%dr0, %0\n\t" : "=r" (uDR0)); +# else + __asm__ __volatile__("movl %%dr0, %0\n\t" : "=r" (uDR0)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, dr0 + mov [uDR0], rax +# else + mov eax, dr0 + mov [uDR0], eax +# endif + } +# endif + return uDR0; +} +#endif + + +/** + * Gets dr1. + * + * @returns dr1. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetDR1(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetDR1(void) +{ + RTCCUINTREG uDR1; +# if RT_INLINE_ASM_USES_INTRIN + uDR1 = __readdr(1); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%dr1, %0\n\t" : "=r" (uDR1)); +# else + __asm__ __volatile__("movl %%dr1, %0\n\t" : "=r" (uDR1)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, dr1 + mov [uDR1], rax +# else + mov eax, dr1 + mov [uDR1], eax +# endif + } +# endif + return uDR1; +} +#endif + + +/** + * Gets dr2. + * + * @returns dr2. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetDR2(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetDR2(void) +{ + RTCCUINTREG uDR2; +# if RT_INLINE_ASM_USES_INTRIN + uDR2 = __readdr(2); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%dr2, %0\n\t" : "=r" (uDR2)); +# else + __asm__ __volatile__("movl %%dr2, %0\n\t" : "=r" (uDR2)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, dr2 + mov [uDR2], rax +# else + mov eax, dr2 + mov [uDR2], eax +# endif + } +# endif + return uDR2; +} +#endif + + +/** + * Gets dr3. + * + * @returns dr3. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetDR3(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetDR3(void) +{ + RTCCUINTREG uDR3; +# if RT_INLINE_ASM_USES_INTRIN + uDR3 = __readdr(3); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%dr3, %0\n\t" : "=r" (uDR3)); +# else + __asm__ __volatile__("movl %%dr3, %0\n\t" : "=r" (uDR3)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, dr3 + mov [uDR3], rax +# else + mov eax, dr3 + mov [uDR3], eax +# endif + } +# endif + return uDR3; +} +#endif + + +/** + * Gets dr6. + * + * @returns dr6. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetDR6(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetDR6(void) +{ + RTCCUINTREG uDR6; +# if RT_INLINE_ASM_USES_INTRIN + uDR6 = __readdr(6); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%dr6, %0\n\t" : "=r" (uDR6)); +# else + __asm__ __volatile__("movl %%dr6, %0\n\t" : "=r" (uDR6)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, dr6 + mov [uDR6], rax +# else + mov eax, dr6 + mov [uDR6], eax +# endif + } +# endif + return uDR6; +} +#endif + + +/** + * Reads and clears DR6. + * + * @returns DR6. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetAndClearDR6(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetAndClearDR6(void) +{ + RTCCUINTREG uDR6; +# if RT_INLINE_ASM_USES_INTRIN + uDR6 = __readdr(6); + __writedr(6, 0xffff0ff0U); /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */ +# elif RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG uNewValue = 0xffff0ff0U;/* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */ +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%dr6, %0\n\t" + "movq %1, %%dr6\n\t" + : "=r" (uDR6) + : "r" (uNewValue)); +# else + __asm__ __volatile__("movl %%dr6, %0\n\t" + "movl %1, %%dr6\n\t" + : "=r" (uDR6) + : "r" (uNewValue)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, dr6 + mov [uDR6], rax + mov rcx, rax + mov ecx, 0ffff0ff0h; /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */ + mov dr6, rcx +# else + mov eax, dr6 + mov [uDR6], eax + mov ecx, 0ffff0ff0h; /* 31-16 and 4-11 are 1's, 12 is zero. */ + mov dr6, ecx +# endif + } +# endif + return uDR6; +} +#endif + + +/** + * Gets dr7. + * + * @returns dr7. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(RTCCUINTREG) ASMGetDR7(void); +#else +DECLINLINE(RTCCUINTREG) ASMGetDR7(void) +{ + RTCCUINTREG uDR7; +# if RT_INLINE_ASM_USES_INTRIN + uDR7 = __readdr(7); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %%dr7, %0\n\t" : "=r" (uDR7)); +# else + __asm__ __volatile__("movl %%dr7, %0\n\t" : "=r" (uDR7)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, dr7 + mov [uDR7], rax +# else + mov eax, dr7 + mov [uDR7], eax +# endif + } +# endif + return uDR7; +} +#endif + + +/** + * Sets dr0. + * + * @param uDRVal Debug register value to write + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetDR0(RTCCUINTREG uDRVal); +#else +DECLINLINE(void) ASMSetDR0(RTCCUINTREG uDRVal) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writedr(0, uDRVal); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%dr0\n\t" : : "r" (uDRVal)); +# else + __asm__ __volatile__("movl %0, %%dr0\n\t" : : "r" (uDRVal)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uDRVal] + mov dr0, rax +# else + mov eax, [uDRVal] + mov dr0, eax +# endif + } +# endif +} +#endif + + +/** + * Sets dr1. + * + * @param uDRVal Debug register value to write + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetDR1(RTCCUINTREG uDRVal); +#else +DECLINLINE(void) ASMSetDR1(RTCCUINTREG uDRVal) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writedr(1, uDRVal); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%dr1\n\t" : : "r" (uDRVal)); +# else + __asm__ __volatile__("movl %0, %%dr1\n\t" : : "r" (uDRVal)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uDRVal] + mov dr1, rax +# else + mov eax, [uDRVal] + mov dr1, eax +# endif + } +# endif +} +#endif + + +/** + * Sets dr2. + * + * @param uDRVal Debug register value to write + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetDR2(RTCCUINTREG uDRVal); +#else +DECLINLINE(void) ASMSetDR2(RTCCUINTREG uDRVal) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writedr(2, uDRVal); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%dr2\n\t" : : "r" (uDRVal)); +# else + __asm__ __volatile__("movl %0, %%dr2\n\t" : : "r" (uDRVal)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uDRVal] + mov dr2, rax +# else + mov eax, [uDRVal] + mov dr2, eax +# endif + } +# endif +} +#endif + + +/** + * Sets dr3. + * + * @param uDRVal Debug register value to write + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetDR3(RTCCUINTREG uDRVal); +#else +DECLINLINE(void) ASMSetDR3(RTCCUINTREG uDRVal) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writedr(3, uDRVal); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%dr3\n\t" : : "r" (uDRVal)); +# else + __asm__ __volatile__("movl %0, %%dr3\n\t" : : "r" (uDRVal)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uDRVal] + mov dr3, rax +# else + mov eax, [uDRVal] + mov dr3, eax +# endif + } +# endif +} +#endif + + +/** + * Sets dr6. + * + * @param uDRVal Debug register value to write + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetDR6(RTCCUINTREG uDRVal); +#else +DECLINLINE(void) ASMSetDR6(RTCCUINTREG uDRVal) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writedr(6, uDRVal); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%dr6\n\t" : : "r" (uDRVal)); +# else + __asm__ __volatile__("movl %0, %%dr6\n\t" : : "r" (uDRVal)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uDRVal] + mov dr6, rax +# else + mov eax, [uDRVal] + mov dr6, eax +# endif + } +# endif +} +#endif + + +/** + * Sets dr7. + * + * @param uDRVal Debug register value to write + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSetDR7(RTCCUINTREG uDRVal); +#else +DECLINLINE(void) ASMSetDR7(RTCCUINTREG uDRVal) +{ +# if RT_INLINE_ASM_USES_INTRIN + __writedr(7, uDRVal); +# elif RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("movq %0, %%dr7\n\t" : : "r" (uDRVal)); +# else + __asm__ __volatile__("movl %0, %%dr7\n\t" : : "r" (uDRVal)); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [uDRVal] + mov dr7, rax +# else + mov eax, [uDRVal] + mov dr7, eax +# endif + } +# endif +} +#endif + + +/** + * Writes a 8-bit unsigned integer to an I/O port, ordered. + * + * @param Port I/O port to write to. + * @param u8 8-bit integer to write. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMOutU8(RTIOPORT Port, uint8_t u8); +#else +DECLINLINE(void) ASMOutU8(RTIOPORT Port, uint8_t u8) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("outb %b1, %w0\n\t" + :: "Nd" (Port), + "a" (u8)); + +# elif RT_INLINE_ASM_USES_INTRIN + __outbyte(Port, u8); + +# else + __asm + { + mov dx, [Port] + mov al, [u8] + out dx, al + } +# endif +} +#endif + + +/** + * Reads a 8-bit unsigned integer from an I/O port, ordered. + * + * @returns 8-bit integer. + * @param Port I/O port to read from. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint8_t) ASMInU8(RTIOPORT Port); +#else +DECLINLINE(uint8_t) ASMInU8(RTIOPORT Port) +{ + uint8_t u8; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("inb %w1, %b0\n\t" + : "=a" (u8) + : "Nd" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + u8 = __inbyte(Port); + +# else + __asm + { + mov dx, [Port] + in al, dx + mov [u8], al + } +# endif + return u8; +} +#endif + + +/** + * Writes a 16-bit unsigned integer to an I/O port, ordered. + * + * @param Port I/O port to write to. + * @param u16 16-bit integer to write. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMOutU16(RTIOPORT Port, uint16_t u16); +#else +DECLINLINE(void) ASMOutU16(RTIOPORT Port, uint16_t u16) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("outw %w1, %w0\n\t" + :: "Nd" (Port), + "a" (u16)); + +# elif RT_INLINE_ASM_USES_INTRIN + __outword(Port, u16); + +# else + __asm + { + mov dx, [Port] + mov ax, [u16] + out dx, ax + } +# endif +} +#endif + + +/** + * Reads a 16-bit unsigned integer from an I/O port, ordered. + * + * @returns 16-bit integer. + * @param Port I/O port to read from. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint16_t) ASMInU16(RTIOPORT Port); +#else +DECLINLINE(uint16_t) ASMInU16(RTIOPORT Port) +{ + uint16_t u16; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("inw %w1, %w0\n\t" + : "=a" (u16) + : "Nd" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + u16 = __inword(Port); + +# else + __asm + { + mov dx, [Port] + in ax, dx + mov [u16], ax + } +# endif + return u16; +} +#endif + + +/** + * Writes a 32-bit unsigned integer to an I/O port, ordered. + * + * @param Port I/O port to write to. + * @param u32 32-bit integer to write. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMOutU32(RTIOPORT Port, uint32_t u32); +#else +DECLINLINE(void) ASMOutU32(RTIOPORT Port, uint32_t u32) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("outl %1, %w0\n\t" + :: "Nd" (Port), + "a" (u32)); + +# elif RT_INLINE_ASM_USES_INTRIN + __outdword(Port, u32); + +# else + __asm + { + mov dx, [Port] + mov eax, [u32] + out dx, eax + } +# endif +} +#endif + + +/** + * Reads a 32-bit unsigned integer from an I/O port, ordered. + * + * @returns 32-bit integer. + * @param Port I/O port to read from. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMInU32(RTIOPORT Port); +#else +DECLINLINE(uint32_t) ASMInU32(RTIOPORT Port) +{ + uint32_t u32; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("inl %w1, %0\n\t" + : "=a" (u32) + : "Nd" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + u32 = __indword(Port); + +# else + __asm + { + mov dx, [Port] + in eax, dx + mov [u32], eax + } +# endif + return u32; +} +#endif + + +/** + * Writes a string of 8-bit unsigned integer items to an I/O port, ordered. + * + * @param Port I/O port to write to. + * @param pau8 Pointer to the string buffer. + * @param c The number of items to write. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMOutStrU8(RTIOPORT Port, uint8_t const *pau8, size_t c); +#else +DECLINLINE(void) ASMOutStrU8(RTIOPORT Port, uint8_t const *pau8, size_t c) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rep; outsb\n\t" + : "+S" (pau8), + "+c" (c) + : "d" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + __outbytestring(Port, (unsigned char *)pau8, (unsigned long)c); + +# else + __asm + { + mov dx, [Port] + mov ecx, [c] + mov eax, [pau8] + xchg esi, eax + rep outsb + xchg esi, eax + } +# endif +} +#endif + + +/** + * Reads a string of 8-bit unsigned integer items from an I/O port, ordered. + * + * @param Port I/O port to read from. + * @param pau8 Pointer to the string buffer (output). + * @param c The number of items to read. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMInStrU8(RTIOPORT Port, uint8_t *pau8, size_t c); +#else +DECLINLINE(void) ASMInStrU8(RTIOPORT Port, uint8_t *pau8, size_t c) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rep; insb\n\t" + : "+D" (pau8), + "+c" (c) + : "d" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + __inbytestring(Port, pau8, (unsigned long)c); + +# else + __asm + { + mov dx, [Port] + mov ecx, [c] + mov eax, [pau8] + xchg edi, eax + rep insb + xchg edi, eax + } +# endif +} +#endif + + +/** + * Writes a string of 16-bit unsigned integer items to an I/O port, ordered. + * + * @param Port I/O port to write to. + * @param pau16 Pointer to the string buffer. + * @param c The number of items to write. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMOutStrU16(RTIOPORT Port, uint16_t const *pau16, size_t c); +#else +DECLINLINE(void) ASMOutStrU16(RTIOPORT Port, uint16_t const *pau16, size_t c) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rep; outsw\n\t" + : "+S" (pau16), + "+c" (c) + : "d" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + __outwordstring(Port, (unsigned short *)pau16, (unsigned long)c); + +# else + __asm + { + mov dx, [Port] + mov ecx, [c] + mov eax, [pau16] + xchg esi, eax + rep outsw + xchg esi, eax + } +# endif +} +#endif + + +/** + * Reads a string of 16-bit unsigned integer items from an I/O port, ordered. + * + * @param Port I/O port to read from. + * @param pau16 Pointer to the string buffer (output). + * @param c The number of items to read. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMInStrU16(RTIOPORT Port, uint16_t *pau16, size_t c); +#else +DECLINLINE(void) ASMInStrU16(RTIOPORT Port, uint16_t *pau16, size_t c) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rep; insw\n\t" + : "+D" (pau16), + "+c" (c) + : "d" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + __inwordstring(Port, pau16, (unsigned long)c); + +# else + __asm + { + mov dx, [Port] + mov ecx, [c] + mov eax, [pau16] + xchg edi, eax + rep insw + xchg edi, eax + } +# endif +} +#endif + + +/** + * Writes a string of 32-bit unsigned integer items to an I/O port, ordered. + * + * @param Port I/O port to write to. + * @param pau32 Pointer to the string buffer. + * @param c The number of items to write. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMOutStrU32(RTIOPORT Port, uint32_t const *pau32, size_t c); +#else +DECLINLINE(void) ASMOutStrU32(RTIOPORT Port, uint32_t const *pau32, size_t c) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rep; outsl\n\t" + : "+S" (pau32), + "+c" (c) + : "d" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + __outdwordstring(Port, (unsigned long *)pau32, (unsigned long)c); + +# else + __asm + { + mov dx, [Port] + mov ecx, [c] + mov eax, [pau32] + xchg esi, eax + rep outsd + xchg esi, eax + } +# endif +} +#endif + + +/** + * Reads a string of 32-bit unsigned integer items from an I/O port, ordered. + * + * @param Port I/O port to read from. + * @param pau32 Pointer to the string buffer (output). + * @param c The number of items to read. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMInStrU32(RTIOPORT Port, uint32_t *pau32, size_t c); +#else +DECLINLINE(void) ASMInStrU32(RTIOPORT Port, uint32_t *pau32, size_t c) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rep; insl\n\t" + : "+D" (pau32), + "+c" (c) + : "d" (Port)); + +# elif RT_INLINE_ASM_USES_INTRIN + __indwordstring(Port, (unsigned long *)pau32, (unsigned long)c); + +# else + __asm + { + mov dx, [Port] + mov ecx, [c] + mov eax, [pau32] + xchg edi, eax + rep insd + xchg edi, eax + } +# endif +} +#endif + + +/** + * Invalidate page. + * + * @param pv Address of the page to invalidate. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMInvalidatePage(void *pv); +#else +DECLINLINE(void) ASMInvalidatePage(void *pv) +{ +# if RT_INLINE_ASM_USES_INTRIN + __invlpg(pv); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("invlpg %0\n\t" + : : "m" (*(uint8_t *)pv)); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pv] + invlpg [rax] +# else + mov eax, [pv] + invlpg [eax] +# endif + } +# endif +} +#endif + + +/** + * Write back the internal caches and invalidate them. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMWriteBackAndInvalidateCaches(void); +#else +DECLINLINE(void) ASMWriteBackAndInvalidateCaches(void) +{ +# if RT_INLINE_ASM_USES_INTRIN + __wbinvd(); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("wbinvd"); +# else + __asm + { + wbinvd + } +# endif +} +#endif + + +/** + * Invalidate internal and (perhaps) external caches without first + * flushing dirty cache lines. Use with extreme care. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMInvalidateInternalCaches(void); +#else +DECLINLINE(void) ASMInvalidateInternalCaches(void) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("invd"); +# else + __asm + { + invd + } +# endif +} +#endif + + +/** + * Memory load/store fence, waits for any pending writes and reads to complete. + * Requires the X86_CPUID_FEATURE_EDX_SSE2 CPUID bit set. + */ +DECLINLINE(void) ASMMemoryFenceSSE2(void) +{ +#if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__ (".byte 0x0f,0xae,0xf0\n\t"); +#elif RT_INLINE_ASM_USES_INTRIN + _mm_mfence(); +#else + __asm + { + _emit 0x0f + _emit 0xae + _emit 0xf0 + } +#endif +} + + +/** + * Memory store fence, waits for any writes to complete. + * Requires the X86_CPUID_FEATURE_EDX_SSE CPUID bit set. + */ +DECLINLINE(void) ASMWriteFenceSSE(void) +{ +#if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__ (".byte 0x0f,0xae,0xf8\n\t"); +#elif RT_INLINE_ASM_USES_INTRIN + _mm_sfence(); +#else + __asm + { + _emit 0x0f + _emit 0xae + _emit 0xf8 + } +#endif +} + + +/** + * Memory load fence, waits for any pending reads to complete. + * Requires the X86_CPUID_FEATURE_EDX_SSE2 CPUID bit set. + */ +DECLINLINE(void) ASMReadFenceSSE2(void) +{ +#if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__ (".byte 0x0f,0xae,0xe8\n\t"); +#elif RT_INLINE_ASM_USES_INTRIN + _mm_lfence(); +#else + __asm + { + _emit 0x0f + _emit 0xae + _emit 0xe8 + } +#endif +} + +/** @} */ +#endif + diff --git a/include/iprt/asm-math.h b/include/iprt/asm-math.h new file mode 100644 index 00000000..a3acdf1e --- /dev/null +++ b/include/iprt/asm-math.h @@ -0,0 +1,319 @@ +/** @file + * IPRT - Assembly Routines for Optimizing some Integers Math Operations. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_asm_math_h +#define ___iprt_asm_math_h + +#include <iprt/types.h> + + +/** @defgroup grp_rt_asm_math Interger Math Optimizations + * @ingroup grp_rt_asm + * @{ */ + +/** + * Multiplies two unsigned 32-bit values returning an unsigned 64-bit result. + * + * @returns u32F1 * u32F2. + */ +#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) +DECLASM(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2); +#else +DECLINLINE(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2) +{ +# ifdef RT_ARCH_X86 + uint64_t u64; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("mull %%edx" + : "=A" (u64) + : "a" (u32F2), "d" (u32F1)); +# else + __asm + { + mov edx, [u32F1] + mov eax, [u32F2] + mul edx + mov dword ptr [u64], eax + mov dword ptr [u64 + 4], edx + } +# endif + return u64; +# else /* generic: */ + return (uint64_t)u32F1 * u32F2; +# endif +} +#endif + + +/** + * Multiplies two signed 32-bit values returning a signed 64-bit result. + * + * @returns u32F1 * u32F2. + */ +#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) +DECLASM(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2); +#else +DECLINLINE(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2) +{ +# ifdef RT_ARCH_X86 + int64_t i64; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("imull %%edx" + : "=A" (i64) + : "a" (i32F2), "d" (i32F1)); +# else + __asm + { + mov edx, [i32F1] + mov eax, [i32F2] + imul edx + mov dword ptr [i64], eax + mov dword ptr [i64 + 4], edx + } +# endif + return i64; +# else /* generic: */ + return (int64_t)i32F1 * i32F2; +# endif +} +#endif + + +/** + * Divides a 64-bit unsigned by a 32-bit unsigned returning an unsigned 32-bit result. + * + * @returns u64 / u32. + */ +#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) +DECLASM(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32); +#else +DECLINLINE(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32) +{ +# ifdef RT_ARCH_X86 +# if RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG uDummy; + __asm__ __volatile__("divl %3" + : "=a" (u32), "=d"(uDummy) + : "A" (u64), "r" (u32)); +# else + __asm + { + mov eax, dword ptr [u64] + mov edx, dword ptr [u64 + 4] + mov ecx, [u32] + div ecx + mov [u32], eax + } +# endif + return u32; +# else /* generic: */ + return (uint32_t)(u64 / u32); +# endif +} +#endif + + +/** + * Divides a 64-bit signed by a 32-bit signed returning a signed 32-bit result. + * + * @returns u64 / u32. + */ +#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) +DECLASM(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32); +#else +DECLINLINE(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32) +{ +# ifdef RT_ARCH_X86 +# if RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG iDummy; + __asm__ __volatile__("idivl %3" + : "=a" (i32), "=d"(iDummy) + : "A" (i64), "r" (i32)); +# else + __asm + { + mov eax, dword ptr [i64] + mov edx, dword ptr [i64 + 4] + mov ecx, [i32] + idiv ecx + mov [i32], eax + } +# endif + return i32; +# else /* generic: */ + return (int32_t)(i64 / i32); +# endif +} +#endif + + +/** + * Performs 64-bit unsigned by a 32-bit unsigned division with a 32-bit unsigned result, + * returning the rest. + * + * @returns u64 % u32. + * + * @remarks It is important that the result is <= UINT32_MAX or we'll overflow and crash. + */ +#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) +DECLASM(uint32_t) ASMModU64ByU32RetU32(uint64_t u64, uint32_t u32); +#else +DECLINLINE(uint32_t) ASMModU64ByU32RetU32(uint64_t u64, uint32_t u32) +{ +# ifdef RT_ARCH_X86 +# if RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG uDummy; + __asm__ __volatile__("divl %3" + : "=a" (uDummy), "=d"(u32) + : "A" (u64), "r" (u32)); +# else + __asm + { + mov eax, dword ptr [u64] + mov edx, dword ptr [u64 + 4] + mov ecx, [u32] + div ecx + mov [u32], edx + } +# endif + return u32; +# else /* generic: */ + return (uint32_t)(u64 % u32); +# endif +} +#endif + + +/** + * Performs 64-bit signed by a 32-bit signed division with a 32-bit signed result, + * returning the rest. + * + * @returns u64 % u32. + * + * @remarks It is important that the result is <= UINT32_MAX or we'll overflow and crash. + */ +#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) +DECLASM(int32_t) ASMModS64ByS32RetS32(int64_t i64, int32_t i32); +#else +DECLINLINE(int32_t) ASMModS64ByS32RetS32(int64_t i64, int32_t i32) +{ +# ifdef RT_ARCH_X86 +# if RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG iDummy; + __asm__ __volatile__("idivl %3" + : "=a" (iDummy), "=d"(i32) + : "A" (i64), "r" (i32)); +# else + __asm + { + mov eax, dword ptr [i64] + mov edx, dword ptr [i64 + 4] + mov ecx, [i32] + idiv ecx + mov [i32], edx + } +# endif + return i32; +# else /* generic: */ + return (int32_t)(i64 % i32); +# endif +} +#endif + + +/** + * Multiple a 64-bit by a 32-bit integer and divide the result by a 32-bit integer + * using a 96 bit intermediate result. + * @note Don't use 64-bit C arithmetic here since some gcc compilers generate references to + * __udivdi3 and __umoddi3 even if this inline function is not used. + * + * @returns (u64A * u32B) / u32C. + * @param u64A The 64-bit value. + * @param u32B The 32-bit value to multiple by A. + * @param u32C The 32-bit value to divide A*B by. + * + * @remarks Architecture specific. + */ +#if RT_INLINE_ASM_EXTERNAL || !defined(__GNUC__) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86)) +DECLASM(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C); +#else +DECLINLINE(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C) +{ +# if RT_INLINE_ASM_GNU_STYLE +# ifdef RT_ARCH_AMD64 + uint64_t u64Result, u64Spill; + __asm__ __volatile__("mulq %2\n\t" + "divq %3\n\t" + : "=a" (u64Result), + "=d" (u64Spill) + : "r" ((uint64_t)u32B), + "r" ((uint64_t)u32C), + "0" (u64A), + "1" (0)); + return u64Result; +# else + uint32_t u32Dummy; + uint64_t u64Result; + __asm__ __volatile__("mull %%ecx \n\t" /* eax = u64Lo.lo = (u64A.lo * u32B).lo + edx = u64Lo.hi = (u64A.lo * u32B).hi */ + "xchg %%eax,%%esi \n\t" /* esi = u64Lo.lo + eax = u64A.hi */ + "xchg %%edx,%%edi \n\t" /* edi = u64Low.hi + edx = u32C */ + "xchg %%edx,%%ecx \n\t" /* ecx = u32C + edx = u32B */ + "mull %%edx \n\t" /* eax = u64Hi.lo = (u64A.hi * u32B).lo + edx = u64Hi.hi = (u64A.hi * u32B).hi */ + "addl %%edi,%%eax \n\t" /* u64Hi.lo += u64Lo.hi */ + "adcl $0,%%edx \n\t" /* u64Hi.hi += carry */ + "divl %%ecx \n\t" /* eax = u64Hi / u32C + edx = u64Hi % u32C */ + "movl %%eax,%%edi \n\t" /* edi = u64Result.hi = u64Hi / u32C */ + "movl %%esi,%%eax \n\t" /* eax = u64Lo.lo */ + "divl %%ecx \n\t" /* u64Result.lo */ + "movl %%edi,%%edx \n\t" /* u64Result.hi */ + : "=A"(u64Result), "=c"(u32Dummy), + "=S"(u32Dummy), "=D"(u32Dummy) + : "a"((uint32_t)u64A), + "S"((uint32_t)(u64A >> 32)), + "c"(u32B), + "D"(u32C)); + return u64Result; +# endif +# else + RTUINT64U u; + uint64_t u64Lo = (uint64_t)(u64A & 0xffffffff) * u32B; + uint64_t u64Hi = (uint64_t)(u64A >> 32) * u32B; + u64Hi += (u64Lo >> 32); + u.s.Hi = (uint32_t)(u64Hi / u32C); + u.s.Lo = (uint32_t)((((u64Hi % u32C) << 32) + (u64Lo & 0xffffffff)) / u32C); + return u.u; +# endif +} +#endif + +/** @} */ +#endif + diff --git a/include/iprt/asm.h b/include/iprt/asm.h new file mode 100644 index 00000000..abaef3a0 --- /dev/null +++ b/include/iprt/asm.h @@ -0,0 +1,4643 @@ +/** @file + * IPRT - Assembly Functions. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_asm_h +#define ___iprt_asm_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/assert.h> +/** @def RT_INLINE_ASM_USES_INTRIN + * Defined as 1 if we're using a _MSC_VER 1400. + * Otherwise defined as 0. + */ + +/* Solaris 10 header ugliness */ +#ifdef u +# undef u +#endif + +#if defined(_MSC_VER) && RT_INLINE_ASM_USES_INTRIN +# include <intrin.h> + /* Emit the intrinsics at all optimization levels. */ +# pragma intrinsic(_ReadWriteBarrier) +# pragma intrinsic(__cpuid) +# pragma intrinsic(__stosd) +# pragma intrinsic(__stosw) +# pragma intrinsic(__stosb) +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanReverse) +# pragma intrinsic(_bittest) +# pragma intrinsic(_bittestandset) +# pragma intrinsic(_bittestandreset) +# pragma intrinsic(_bittestandcomplement) +# pragma intrinsic(_byteswap_ushort) +# pragma intrinsic(_byteswap_ulong) +# pragma intrinsic(_interlockedbittestandset) +# pragma intrinsic(_interlockedbittestandreset) +# pragma intrinsic(_InterlockedAnd) +# pragma intrinsic(_InterlockedOr) +# pragma intrinsic(_InterlockedIncrement) +# pragma intrinsic(_InterlockedDecrement) +# pragma intrinsic(_InterlockedExchange) +# pragma intrinsic(_InterlockedExchangeAdd) +# pragma intrinsic(_InterlockedCompareExchange) +# pragma intrinsic(_InterlockedCompareExchange64) +# ifdef RT_ARCH_AMD64 +# pragma intrinsic(__stosq) +# pragma intrinsic(_byteswap_uint64) +# pragma intrinsic(_InterlockedExchange64) +# pragma intrinsic(_InterlockedExchangeAdd64) +# pragma intrinsic(_InterlockedAnd64) +# pragma intrinsic(_InterlockedOr64) +# pragma intrinsic(_InterlockedIncrement64) +# pragma intrinsic(_InterlockedDecrement64) +# endif +#endif + + +/** @defgroup grp_rt_asm ASM - Assembly Routines + * @ingroup grp_rt + * + * @remarks The difference between ordered and unordered atomic operations are that + * the former will complete outstanding reads and writes before continuing + * while the latter doesn't make any promises about the order. Ordered + * operations doesn't, it seems, make any 100% promise wrt to whether + * the operation will complete before any subsequent memory access. + * (please, correct if wrong.) + * + * ASMAtomicSomething operations are all ordered, while ASMAtomicUoSomething + * are unordered (note the Uo). + * + * @remarks Some remarks about __volatile__: Without this keyword gcc is allowed to reorder + * or even optimize assembler instructions away. For instance, in the following code + * the second rdmsr instruction is optimized away because gcc treats that instruction + * as deterministic: + * + * @code + * static inline uint64_t rdmsr_low(int idx) + * { + * uint32_t low; + * __asm__ ("rdmsr" : "=a"(low) : "c"(idx) : "edx"); + * } + * ... + * uint32_t msr1 = rdmsr_low(1); + * foo(msr1); + * msr1 = rdmsr_low(1); + * bar(msr1); + * @endcode + * + * The input parameter of rdmsr_low is the same for both calls and therefore gcc will + * use the result of the first call as input parameter for bar() as well. For rdmsr this + * is not acceptable as this instruction is _not_ deterministic. This applies to reading + * machine status information in general. + * + * @{ + */ + + +/** @def RT_INLINE_ASM_GCC_4_3_X_X86 + * Used to work around some 4.3.x register allocation issues in this version of + * the compiler. So far this workaround is still required for 4.4 and 4.5. */ +#ifdef __GNUC__ +# define RT_INLINE_ASM_GCC_4_3_X_X86 (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 && defined(__i386__)) +#endif +#ifndef RT_INLINE_ASM_GCC_4_3_X_X86 +# define RT_INLINE_ASM_GCC_4_3_X_X86 0 +#endif + +/** @def RT_INLINE_DONT_USE_CMPXCHG8B + * i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5493) screws up + * RTSemRWRequestWrite semsemrw-lockless-generic.cpp in release builds. PIC + * mode, x86. + * + * Some gcc 4.3.x versions may have register allocation issues with cmpxchg8b + * when in PIC mode on x86. + */ +#ifndef RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC +# define RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC \ + ( (defined(PIC) || defined(__PIC__)) \ + && defined(RT_ARCH_X86) \ + && ( RT_INLINE_ASM_GCC_4_3_X_X86 \ + || defined(RT_OS_DARWIN)) ) +#endif + + +/** @def ASMReturnAddress + * Gets the return address of the current (or calling if you like) function or method. + */ +#ifdef _MSC_VER +# ifdef __cplusplus +extern "C" +# endif +void * _ReturnAddress(void); +# pragma intrinsic(_ReturnAddress) +# define ASMReturnAddress() _ReturnAddress() +#elif defined(__GNUC__) || defined(DOXYGEN_RUNNING) +# define ASMReturnAddress() __builtin_return_address(0) +#else +# error "Unsupported compiler." +#endif + + +/** + * Compiler memory barrier. + * + * Ensure that the compiler does not use any cached (register/tmp stack) memory + * values or any outstanding writes when returning from this function. + * + * This function must be used if non-volatile data is modified by a + * device or the VMM. Typical cases are port access, MMIO access, + * trapping instruction, etc. + */ +#if RT_INLINE_ASM_GNU_STYLE +# define ASMCompilerBarrier() do { __asm__ __volatile__("" : : : "memory"); } while (0) +#elif RT_INLINE_ASM_USES_INTRIN +# define ASMCompilerBarrier() do { _ReadWriteBarrier(); } while (0) +#else /* 2003 should have _ReadWriteBarrier() but I guess we're at 2002 level then... */ +DECLINLINE(void) ASMCompilerBarrier(void) +{ + __asm + { + } +} +#endif + + +/** @def ASMBreakpoint + * Debugger Breakpoint. + * @deprecated Use RT_BREAKPOINT instead. + * @internal + */ +#define ASMBreakpoint() RT_BREAKPOINT() + + +/** + * Spinloop hint for platforms that have these, empty function on the other + * platforms. + * + * x86 & AMD64: The PAUSE variant of NOP for helping hyperthreaded CPUs detecting + * spin locks. + */ +#if RT_INLINE_ASM_EXTERNAL && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)) +DECLASM(void) ASMNopPause(void); +#else +DECLINLINE(void) ASMNopPause(void) +{ +# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__(".byte 0xf3,0x90\n\t"); +# else + __asm { + _emit 0f3h + _emit 090h + } +# endif +# else + /* dummy */ +# endif +} +#endif + + +/** + * Atomically Exchange an unsigned 8-bit value, ordered. + * + * @returns Current *pu8 value + * @param pu8 Pointer to the 8-bit variable to update. + * @param u8 The 8-bit value to assign to *pu8. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(uint8_t) ASMAtomicXchgU8(volatile uint8_t *pu8, uint8_t u8); +#else +DECLINLINE(uint8_t) ASMAtomicXchgU8(volatile uint8_t *pu8, uint8_t u8) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("xchgb %0, %1\n\t" + : "=m" (*pu8), + "=q" (u8) /* =r - busted on g++ (GCC) 3.4.4 20050721 (Red Hat 3.4.4-2) */ + : "1" (u8), + "m" (*pu8)); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rdx, [pu8] + mov al, [u8] + xchg [rdx], al + mov [u8], al +# else + mov edx, [pu8] + mov al, [u8] + xchg [edx], al + mov [u8], al +# endif + } +# endif + return u8; +} +#endif + + +/** + * Atomically Exchange a signed 8-bit value, ordered. + * + * @returns Current *pu8 value + * @param pi8 Pointer to the 8-bit variable to update. + * @param i8 The 8-bit value to assign to *pi8. + */ +DECLINLINE(int8_t) ASMAtomicXchgS8(volatile int8_t *pi8, int8_t i8) +{ + return (int8_t)ASMAtomicXchgU8((volatile uint8_t *)pi8, (uint8_t)i8); +} + + +/** + * Atomically Exchange a bool value, ordered. + * + * @returns Current *pf value + * @param pf Pointer to the 8-bit variable to update. + * @param f The 8-bit value to assign to *pi8. + */ +DECLINLINE(bool) ASMAtomicXchgBool(volatile bool *pf, bool f) +{ +#ifdef _MSC_VER + return !!ASMAtomicXchgU8((volatile uint8_t *)pf, (uint8_t)f); +#else + return (bool)ASMAtomicXchgU8((volatile uint8_t *)pf, (uint8_t)f); +#endif +} + + +/** + * Atomically Exchange an unsigned 16-bit value, ordered. + * + * @returns Current *pu16 value + * @param pu16 Pointer to the 16-bit variable to update. + * @param u16 The 16-bit value to assign to *pu16. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(uint16_t) ASMAtomicXchgU16(volatile uint16_t *pu16, uint16_t u16); +#else +DECLINLINE(uint16_t) ASMAtomicXchgU16(volatile uint16_t *pu16, uint16_t u16) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("xchgw %0, %1\n\t" + : "=m" (*pu16), + "=r" (u16) + : "1" (u16), + "m" (*pu16)); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rdx, [pu16] + mov ax, [u16] + xchg [rdx], ax + mov [u16], ax +# else + mov edx, [pu16] + mov ax, [u16] + xchg [edx], ax + mov [u16], ax +# endif + } +# endif + return u16; +} +#endif + + +/** + * Atomically Exchange a signed 16-bit value, ordered. + * + * @returns Current *pu16 value + * @param pi16 Pointer to the 16-bit variable to update. + * @param i16 The 16-bit value to assign to *pi16. + */ +DECLINLINE(int16_t) ASMAtomicXchgS16(volatile int16_t *pi16, int16_t i16) +{ + return (int16_t)ASMAtomicXchgU16((volatile uint16_t *)pi16, (uint16_t)i16); +} + + +/** + * Atomically Exchange an unsigned 32-bit value, ordered. + * + * @returns Current *pu32 value + * @param pu32 Pointer to the 32-bit variable to update. + * @param u32 The 32-bit value to assign to *pu32. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMAtomicXchgU32(volatile uint32_t *pu32, uint32_t u32); +#else +DECLINLINE(uint32_t) ASMAtomicXchgU32(volatile uint32_t *pu32, uint32_t u32) +{ +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("xchgl %0, %1\n\t" + : "=m" (*pu32), + "=r" (u32) + : "1" (u32), + "m" (*pu32)); + +# elif RT_INLINE_ASM_USES_INTRIN + u32 = _InterlockedExchange((long *)pu32, u32); + +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rdx, [pu32] + mov eax, u32 + xchg [rdx], eax + mov [u32], eax +# else + mov edx, [pu32] + mov eax, u32 + xchg [edx], eax + mov [u32], eax +# endif + } +# endif + return u32; +} +#endif + + +/** + * Atomically Exchange a signed 32-bit value, ordered. + * + * @returns Current *pu32 value + * @param pi32 Pointer to the 32-bit variable to update. + * @param i32 The 32-bit value to assign to *pi32. + */ +DECLINLINE(int32_t) ASMAtomicXchgS32(volatile int32_t *pi32, int32_t i32) +{ + return (int32_t)ASMAtomicXchgU32((volatile uint32_t *)pi32, (uint32_t)i32); +} + + +/** + * Atomically Exchange an unsigned 64-bit value, ordered. + * + * @returns Current *pu64 value + * @param pu64 Pointer to the 64-bit variable to update. + * @param u64 The 64-bit value to assign to *pu64. + */ +#if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \ + || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC +DECLASM(uint64_t) ASMAtomicXchgU64(volatile uint64_t *pu64, uint64_t u64); +#else +DECLINLINE(uint64_t) ASMAtomicXchgU64(volatile uint64_t *pu64, uint64_t u64) +{ +# if defined(RT_ARCH_AMD64) +# if RT_INLINE_ASM_USES_INTRIN + u64 = _InterlockedExchange64((__int64 *)pu64, u64); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("xchgq %0, %1\n\t" + : "=m" (*pu64), + "=r" (u64) + : "1" (u64), + "m" (*pu64)); +# else + __asm + { + mov rdx, [pu64] + mov rax, [u64] + xchg [rdx], rax + mov [u64], rax + } +# endif +# else /* !RT_ARCH_AMD64 */ +# if RT_INLINE_ASM_GNU_STYLE +# if defined(PIC) || defined(__PIC__) + uint32_t u32EBX = (uint32_t)u64; + __asm__ __volatile__(/*"xchgl %%esi, %5\n\t"*/ + "xchgl %%ebx, %3\n\t" + "1:\n\t" + "lock; cmpxchg8b (%5)\n\t" + "jnz 1b\n\t" + "movl %3, %%ebx\n\t" + /*"xchgl %%esi, %5\n\t"*/ + : "=A" (u64), + "=m" (*pu64) + : "0" (*pu64), + "m" ( u32EBX ), + "c" ( (uint32_t)(u64 >> 32) ), + "S" (pu64)); +# else /* !PIC */ + __asm__ __volatile__("1:\n\t" + "lock; cmpxchg8b %1\n\t" + "jnz 1b\n\t" + : "=A" (u64), + "=m" (*pu64) + : "0" (*pu64), + "b" ( (uint32_t)u64 ), + "c" ( (uint32_t)(u64 >> 32) )); +# endif +# else + __asm + { + mov ebx, dword ptr [u64] + mov ecx, dword ptr [u64 + 4] + mov edi, pu64 + mov eax, dword ptr [edi] + mov edx, dword ptr [edi + 4] + retry: + lock cmpxchg8b [edi] + jnz retry + mov dword ptr [u64], eax + mov dword ptr [u64 + 4], edx + } +# endif +# endif /* !RT_ARCH_AMD64 */ + return u64; +} +#endif + + +/** + * Atomically Exchange an signed 64-bit value, ordered. + * + * @returns Current *pi64 value + * @param pi64 Pointer to the 64-bit variable to update. + * @param i64 The 64-bit value to assign to *pi64. + */ +DECLINLINE(int64_t) ASMAtomicXchgS64(volatile int64_t *pi64, int64_t i64) +{ + return (int64_t)ASMAtomicXchgU64((volatile uint64_t *)pi64, (uint64_t)i64); +} + + +/** + * Atomically Exchange a pointer value, ordered. + * + * @returns Current *ppv value + * @param ppv Pointer to the pointer variable to update. + * @param pv The pointer value to assign to *ppv. + */ +DECLINLINE(void *) ASMAtomicXchgPtr(void * volatile *ppv, const void *pv) +{ +#if ARCH_BITS == 32 + return (void *)ASMAtomicXchgU32((volatile uint32_t *)(void *)ppv, (uint32_t)pv); +#elif ARCH_BITS == 64 + return (void *)ASMAtomicXchgU64((volatile uint64_t *)(void *)ppv, (uint64_t)pv); +#else +# error "ARCH_BITS is bogus" +#endif +} + + +/** + * Convenience macro for avoiding the annoying casting with ASMAtomicXchgPtr. + * + * @returns Current *pv value + * @param ppv Pointer to the pointer variable to update. + * @param pv The pointer value to assign to *ppv. + * @param Type The type of *ppv, sans volatile. + */ +#ifdef __GNUC__ +# define ASMAtomicXchgPtrT(ppv, pv, Type) \ + __extension__ \ + ({\ + __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \ + Type const pvTypeChecked = (pv); \ + Type pvTypeCheckedRet = (__typeof__(*(ppv))) ASMAtomicXchgPtr((void * volatile *)ppvTypeChecked, (void *)pvTypeChecked); \ + pvTypeCheckedRet; \ + }) +#else +# define ASMAtomicXchgPtrT(ppv, pv, Type) \ + (Type)ASMAtomicXchgPtr((void * volatile *)(ppv), (void *)(pv)) +#endif + + +/** + * Atomically Exchange a raw-mode context pointer value, ordered. + * + * @returns Current *ppv value + * @param ppvRC Pointer to the pointer variable to update. + * @param pvRC The pointer value to assign to *ppv. + */ +DECLINLINE(RTRCPTR) ASMAtomicXchgRCPtr(RTRCPTR volatile *ppvRC, RTRCPTR pvRC) +{ + return (RTRCPTR)ASMAtomicXchgU32((uint32_t volatile *)(void *)ppvRC, (uint32_t)pvRC); +} + + +/** + * Atomically Exchange a ring-0 pointer value, ordered. + * + * @returns Current *ppv value + * @param ppvR0 Pointer to the pointer variable to update. + * @param pvR0 The pointer value to assign to *ppv. + */ +DECLINLINE(RTR0PTR) ASMAtomicXchgR0Ptr(RTR0PTR volatile *ppvR0, RTR0PTR pvR0) +{ +#if R0_ARCH_BITS == 32 + return (RTR0PTR)ASMAtomicXchgU32((volatile uint32_t *)(void *)ppvR0, (uint32_t)pvR0); +#elif R0_ARCH_BITS == 64 + return (RTR0PTR)ASMAtomicXchgU64((volatile uint64_t *)(void *)ppvR0, (uint64_t)pvR0); +#else +# error "R0_ARCH_BITS is bogus" +#endif +} + + +/** + * Atomically Exchange a ring-3 pointer value, ordered. + * + * @returns Current *ppv value + * @param ppvR3 Pointer to the pointer variable to update. + * @param pvR3 The pointer value to assign to *ppv. + */ +DECLINLINE(RTR3PTR) ASMAtomicXchgR3Ptr(RTR3PTR volatile *ppvR3, RTR3PTR pvR3) +{ +#if R3_ARCH_BITS == 32 + return (RTR3PTR)ASMAtomicXchgU32((volatile uint32_t *)(void *)ppvR3, (uint32_t)pvR3); +#elif R3_ARCH_BITS == 64 + return (RTR3PTR)ASMAtomicXchgU64((volatile uint64_t *)(void *)ppvR3, (uint64_t)pvR3); +#else +# error "R3_ARCH_BITS is bogus" +#endif +} + + +/** @def ASMAtomicXchgHandle + * Atomically Exchange a typical IPRT handle value, ordered. + * + * @param ph Pointer to the value to update. + * @param hNew The new value to assigned to *pu. + * @param phRes Where to store the current *ph value. + * + * @remarks This doesn't currently work for all handles (like RTFILE). + */ +#if HC_ARCH_BITS == 32 +# define ASMAtomicXchgHandle(ph, hNew, phRes) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \ + AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \ + *(uint32_t *)(phRes) = ASMAtomicXchgU32((uint32_t volatile *)(ph), (const uint32_t)(hNew)); \ + } while (0) +#elif HC_ARCH_BITS == 64 +# define ASMAtomicXchgHandle(ph, hNew, phRes) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \ + AssertCompile(sizeof(*(phRes)) == sizeof(uint64_t)); \ + *(uint64_t *)(phRes) = ASMAtomicXchgU64((uint64_t volatile *)(ph), (const uint64_t)(hNew)); \ + } while (0) +#else +# error HC_ARCH_BITS +#endif + + +/** + * Atomically Exchange a value which size might differ + * between platforms or compilers, ordered. + * + * @param pu Pointer to the variable to update. + * @param uNew The value to assign to *pu. + * @todo This is busted as its missing the result argument. + */ +#define ASMAtomicXchgSize(pu, uNew) \ + do { \ + switch (sizeof(*(pu))) { \ + case 1: ASMAtomicXchgU8((volatile uint8_t *)(void *)(pu), (uint8_t)(uNew)); break; \ + case 2: ASMAtomicXchgU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \ + case 4: ASMAtomicXchgU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \ + case 8: ASMAtomicXchgU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \ + default: AssertMsgFailed(("ASMAtomicXchgSize: size %d is not supported\n", sizeof(*(pu)))); \ + } \ + } while (0) + +/** + * Atomically Exchange a value which size might differ + * between platforms or compilers, ordered. + * + * @param pu Pointer to the variable to update. + * @param uNew The value to assign to *pu. + * @param puRes Where to store the current *pu value. + */ +#define ASMAtomicXchgSizeCorrect(pu, uNew, puRes) \ + do { \ + switch (sizeof(*(pu))) { \ + case 1: *(uint8_t *)(puRes) = ASMAtomicXchgU8((volatile uint8_t *)(void *)(pu), (uint8_t)(uNew)); break; \ + case 2: *(uint16_t *)(puRes) = ASMAtomicXchgU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \ + case 4: *(uint32_t *)(puRes) = ASMAtomicXchgU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \ + case 8: *(uint64_t *)(puRes) = ASMAtomicXchgU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \ + default: AssertMsgFailed(("ASMAtomicXchgSize: size %d is not supported\n", sizeof(*(pu)))); \ + } \ + } while (0) + + + +/** + * Atomically Compare and Exchange an unsigned 8-bit value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pu8 Pointer to the value to update. + * @param u8New The new value to assigned to *pu8. + * @param u8Old The old value to *pu8 compare with. + */ +#if RT_INLINE_ASM_EXTERNAL || !RT_INLINE_ASM_GNU_STYLE +DECLASM(bool) ASMAtomicCmpXchgU8(volatile uint8_t *pu8, const uint8_t u8New, const uint8_t u8Old); +#else +DECLINLINE(bool) ASMAtomicCmpXchgU8(volatile uint8_t *pu8, const uint8_t u8New, uint8_t u8Old) +{ + uint8_t u8Ret; + __asm__ __volatile__("lock; cmpxchgb %3, %0\n\t" + "setz %1\n\t" + : "=m" (*pu8), + "=qm" (u8Ret), + "=a" (u8Old) + : "q" (u8New), + "2" (u8Old), + "m" (*pu8)); + return (bool)u8Ret; +} +#endif + + +/** + * Atomically Compare and Exchange a signed 8-bit value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pi8 Pointer to the value to update. + * @param i8New The new value to assigned to *pi8. + * @param i8Old The old value to *pi8 compare with. + */ +DECLINLINE(bool) ASMAtomicCmpXchgS8(volatile int8_t *pi8, const int8_t i8New, const int8_t i8Old) +{ + return ASMAtomicCmpXchgU8((volatile uint8_t *)pi8, (const uint8_t)i8New, (const uint8_t)i8Old); +} + + +/** + * Atomically Compare and Exchange a bool value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pf Pointer to the value to update. + * @param fNew The new value to assigned to *pf. + * @param fOld The old value to *pf compare with. + */ +DECLINLINE(bool) ASMAtomicCmpXchgBool(volatile bool *pf, const bool fNew, const bool fOld) +{ + return ASMAtomicCmpXchgU8((volatile uint8_t *)pf, (const uint8_t)fNew, (const uint8_t)fOld); +} + + +/** + * Atomically Compare and Exchange an unsigned 32-bit value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pu32 Pointer to the value to update. + * @param u32New The new value to assigned to *pu32. + * @param u32Old The old value to *pu32 compare with. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(bool) ASMAtomicCmpXchgU32(volatile uint32_t *pu32, const uint32_t u32New, const uint32_t u32Old); +#else +DECLINLINE(bool) ASMAtomicCmpXchgU32(volatile uint32_t *pu32, const uint32_t u32New, uint32_t u32Old) +{ +# if RT_INLINE_ASM_GNU_STYLE + uint8_t u8Ret; + __asm__ __volatile__("lock; cmpxchgl %3, %0\n\t" + "setz %1\n\t" + : "=m" (*pu32), + "=qm" (u8Ret), + "=a" (u32Old) + : "r" (u32New), + "2" (u32Old), + "m" (*pu32)); + return (bool)u8Ret; + +# elif RT_INLINE_ASM_USES_INTRIN + return (uint32_t)_InterlockedCompareExchange((long *)pu32, u32New, u32Old) == u32Old; + +# else + uint32_t u32Ret; + __asm + { +# ifdef RT_ARCH_AMD64 + mov rdx, [pu32] +# else + mov edx, [pu32] +# endif + mov eax, [u32Old] + mov ecx, [u32New] +# ifdef RT_ARCH_AMD64 + lock cmpxchg [rdx], ecx +# else + lock cmpxchg [edx], ecx +# endif + setz al + movzx eax, al + mov [u32Ret], eax + } + return !!u32Ret; +# endif +} +#endif + + +/** + * Atomically Compare and Exchange a signed 32-bit value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pi32 Pointer to the value to update. + * @param i32New The new value to assigned to *pi32. + * @param i32Old The old value to *pi32 compare with. + */ +DECLINLINE(bool) ASMAtomicCmpXchgS32(volatile int32_t *pi32, const int32_t i32New, const int32_t i32Old) +{ + return ASMAtomicCmpXchgU32((volatile uint32_t *)pi32, (uint32_t)i32New, (uint32_t)i32Old); +} + + +/** + * Atomically Compare and exchange an unsigned 64-bit value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pu64 Pointer to the 64-bit variable to update. + * @param u64New The 64-bit value to assign to *pu64. + * @param u64Old The value to compare with. + */ +#if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \ + || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC +DECLASM(bool) ASMAtomicCmpXchgU64(volatile uint64_t *pu64, const uint64_t u64New, const uint64_t u64Old); +#else +DECLINLINE(bool) ASMAtomicCmpXchgU64(volatile uint64_t *pu64, uint64_t u64New, uint64_t u64Old) +{ +# if RT_INLINE_ASM_USES_INTRIN + return (uint64_t)_InterlockedCompareExchange64((__int64 *)pu64, u64New, u64Old) == u64Old; + +# elif defined(RT_ARCH_AMD64) +# if RT_INLINE_ASM_GNU_STYLE + uint8_t u8Ret; + __asm__ __volatile__("lock; cmpxchgq %3, %0\n\t" + "setz %1\n\t" + : "=m" (*pu64), + "=qm" (u8Ret), + "=a" (u64Old) + : "r" (u64New), + "2" (u64Old), + "m" (*pu64)); + return (bool)u8Ret; +# else + bool fRet; + __asm + { + mov rdx, [pu32] + mov rax, [u64Old] + mov rcx, [u64New] + lock cmpxchg [rdx], rcx + setz al + mov [fRet], al + } + return fRet; +# endif +# else /* !RT_ARCH_AMD64 */ + uint32_t u32Ret; +# if RT_INLINE_ASM_GNU_STYLE +# if defined(PIC) || defined(__PIC__) + uint32_t u32EBX = (uint32_t)u64New; + uint32_t u32Spill; + __asm__ __volatile__("xchgl %%ebx, %4\n\t" + "lock; cmpxchg8b (%6)\n\t" + "setz %%al\n\t" + "movl %4, %%ebx\n\t" + "movzbl %%al, %%eax\n\t" + : "=a" (u32Ret), + "=d" (u32Spill), +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 + "+m" (*pu64) +# else + "=m" (*pu64) +# endif + : "A" (u64Old), + "m" ( u32EBX ), + "c" ( (uint32_t)(u64New >> 32) ), + "S" (pu64)); +# else /* !PIC */ + uint32_t u32Spill; + __asm__ __volatile__("lock; cmpxchg8b %2\n\t" + "setz %%al\n\t" + "movzbl %%al, %%eax\n\t" + : "=a" (u32Ret), + "=d" (u32Spill), + "+m" (*pu64) + : "A" (u64Old), + "b" ( (uint32_t)u64New ), + "c" ( (uint32_t)(u64New >> 32) )); +# endif + return (bool)u32Ret; +# else + __asm + { + mov ebx, dword ptr [u64New] + mov ecx, dword ptr [u64New + 4] + mov edi, [pu64] + mov eax, dword ptr [u64Old] + mov edx, dword ptr [u64Old + 4] + lock cmpxchg8b [edi] + setz al + movzx eax, al + mov dword ptr [u32Ret], eax + } + return !!u32Ret; +# endif +# endif /* !RT_ARCH_AMD64 */ +} +#endif + + +/** + * Atomically Compare and exchange a signed 64-bit value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pi64 Pointer to the 64-bit variable to update. + * @param i64 The 64-bit value to assign to *pu64. + * @param i64Old The value to compare with. + */ +DECLINLINE(bool) ASMAtomicCmpXchgS64(volatile int64_t *pi64, const int64_t i64, const int64_t i64Old) +{ + return ASMAtomicCmpXchgU64((volatile uint64_t *)pi64, (uint64_t)i64, (uint64_t)i64Old); +} + + +/** + * Atomically Compare and Exchange a pointer value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param ppv Pointer to the value to update. + * @param pvNew The new value to assigned to *ppv. + * @param pvOld The old value to *ppv compare with. + */ +DECLINLINE(bool) ASMAtomicCmpXchgPtrVoid(void * volatile *ppv, const void *pvNew, const void *pvOld) +{ +#if ARCH_BITS == 32 + return ASMAtomicCmpXchgU32((volatile uint32_t *)(void *)ppv, (uint32_t)pvNew, (uint32_t)pvOld); +#elif ARCH_BITS == 64 + return ASMAtomicCmpXchgU64((volatile uint64_t *)(void *)ppv, (uint64_t)pvNew, (uint64_t)pvOld); +#else +# error "ARCH_BITS is bogus" +#endif +} + + +/** + * Atomically Compare and Exchange a pointer value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param ppv Pointer to the value to update. + * @param pvNew The new value to assigned to *ppv. + * @param pvOld The old value to *ppv compare with. + * + * @remarks This is relatively type safe on GCC platforms. + */ +#ifdef __GNUC__ +# define ASMAtomicCmpXchgPtr(ppv, pvNew, pvOld) \ + __extension__ \ + ({\ + __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \ + __typeof__(*(ppv)) const pvNewTypeChecked = (pvNew); \ + __typeof__(*(ppv)) const pvOldTypeChecked = (pvOld); \ + bool fMacroRet = ASMAtomicCmpXchgPtrVoid((void * volatile *)ppvTypeChecked, \ + (void *)pvNewTypeChecked, (void *)pvOldTypeChecked); \ + fMacroRet; \ + }) +#else +# define ASMAtomicCmpXchgPtr(ppv, pvNew, pvOld) \ + ASMAtomicCmpXchgPtrVoid((void * volatile *)(ppv), (void *)(pvNew), (void *)(pvOld)) +#endif + + +/** @def ASMAtomicCmpXchgHandle + * Atomically Compare and Exchange a typical IPRT handle value, ordered. + * + * @param ph Pointer to the value to update. + * @param hNew The new value to assigned to *pu. + * @param hOld The old value to *pu compare with. + * @param fRc Where to store the result. + * + * @remarks This doesn't currently work for all handles (like RTFILE). + */ +#if HC_ARCH_BITS == 32 +# define ASMAtomicCmpXchgHandle(ph, hNew, hOld, fRc) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \ + (fRc) = ASMAtomicCmpXchgU32((uint32_t volatile *)(ph), (const uint32_t)(hNew), (const uint32_t)(hOld)); \ + } while (0) +#elif HC_ARCH_BITS == 64 +# define ASMAtomicCmpXchgHandle(ph, hNew, hOld, fRc) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \ + (fRc) = ASMAtomicCmpXchgU64((uint64_t volatile *)(ph), (const uint64_t)(hNew), (const uint64_t)(hOld)); \ + } while (0) +#else +# error HC_ARCH_BITS +#endif + + +/** @def ASMAtomicCmpXchgSize + * Atomically Compare and Exchange a value which size might differ + * between platforms or compilers, ordered. + * + * @param pu Pointer to the value to update. + * @param uNew The new value to assigned to *pu. + * @param uOld The old value to *pu compare with. + * @param fRc Where to store the result. + */ +#define ASMAtomicCmpXchgSize(pu, uNew, uOld, fRc) \ + do { \ + switch (sizeof(*(pu))) { \ + case 4: (fRc) = ASMAtomicCmpXchgU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew), (uint32_t)(uOld)); \ + break; \ + case 8: (fRc) = ASMAtomicCmpXchgU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew), (uint64_t)(uOld)); \ + break; \ + default: AssertMsgFailed(("ASMAtomicCmpXchgSize: size %d is not supported\n", sizeof(*(pu)))); \ + (fRc) = false; \ + break; \ + } \ + } while (0) + + +/** + * Atomically Compare and Exchange an unsigned 32-bit value, additionally + * passes back old value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pu32 Pointer to the value to update. + * @param u32New The new value to assigned to *pu32. + * @param u32Old The old value to *pu32 compare with. + * @param pu32Old Pointer store the old value at. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(bool) ASMAtomicCmpXchgExU32(volatile uint32_t *pu32, const uint32_t u32New, const uint32_t u32Old, uint32_t *pu32Old); +#else +DECLINLINE(bool) ASMAtomicCmpXchgExU32(volatile uint32_t *pu32, const uint32_t u32New, const uint32_t u32Old, uint32_t *pu32Old) +{ +# if RT_INLINE_ASM_GNU_STYLE + uint8_t u8Ret; + __asm__ __volatile__("lock; cmpxchgl %3, %0\n\t" + "setz %1\n\t" + : "=m" (*pu32), + "=qm" (u8Ret), + "=a" (*pu32Old) + : "r" (u32New), + "a" (u32Old), + "m" (*pu32)); + return (bool)u8Ret; + +# elif RT_INLINE_ASM_USES_INTRIN + return (*pu32Old =_InterlockedCompareExchange((long *)pu32, u32New, u32Old)) == u32Old; + +# else + uint32_t u32Ret; + __asm + { +# ifdef RT_ARCH_AMD64 + mov rdx, [pu32] +# else + mov edx, [pu32] +# endif + mov eax, [u32Old] + mov ecx, [u32New] +# ifdef RT_ARCH_AMD64 + lock cmpxchg [rdx], ecx + mov rdx, [pu32Old] + mov [rdx], eax +# else + lock cmpxchg [edx], ecx + mov edx, [pu32Old] + mov [edx], eax +# endif + setz al + movzx eax, al + mov [u32Ret], eax + } + return !!u32Ret; +# endif +} +#endif + + +/** + * Atomically Compare and Exchange a signed 32-bit value, additionally + * passes back old value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pi32 Pointer to the value to update. + * @param i32New The new value to assigned to *pi32. + * @param i32Old The old value to *pi32 compare with. + * @param pi32Old Pointer store the old value at. + */ +DECLINLINE(bool) ASMAtomicCmpXchgExS32(volatile int32_t *pi32, const int32_t i32New, const int32_t i32Old, int32_t *pi32Old) +{ + return ASMAtomicCmpXchgExU32((volatile uint32_t *)pi32, (uint32_t)i32New, (uint32_t)i32Old, (uint32_t *)pi32Old); +} + + +/** + * Atomically Compare and exchange an unsigned 64-bit value, additionally + * passing back old value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pu64 Pointer to the 64-bit variable to update. + * @param u64New The 64-bit value to assign to *pu64. + * @param u64Old The value to compare with. + * @param pu64Old Pointer store the old value at. + */ +#if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \ + || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC +DECLASM(bool) ASMAtomicCmpXchgExU64(volatile uint64_t *pu64, const uint64_t u64New, const uint64_t u64Old, uint64_t *pu64Old); +#else +DECLINLINE(bool) ASMAtomicCmpXchgExU64(volatile uint64_t *pu64, const uint64_t u64New, const uint64_t u64Old, uint64_t *pu64Old) +{ +# if RT_INLINE_ASM_USES_INTRIN + return (*pu64Old =_InterlockedCompareExchange64((__int64 *)pu64, u64New, u64Old)) == u64Old; + +# elif defined(RT_ARCH_AMD64) +# if RT_INLINE_ASM_GNU_STYLE + uint8_t u8Ret; + __asm__ __volatile__("lock; cmpxchgq %3, %0\n\t" + "setz %1\n\t" + : "=m" (*pu64), + "=qm" (u8Ret), + "=a" (*pu64Old) + : "r" (u64New), + "a" (u64Old), + "m" (*pu64)); + return (bool)u8Ret; +# else + bool fRet; + __asm + { + mov rdx, [pu32] + mov rax, [u64Old] + mov rcx, [u64New] + lock cmpxchg [rdx], rcx + mov rdx, [pu64Old] + mov [rdx], rax + setz al + mov [fRet], al + } + return fRet; +# endif +# else /* !RT_ARCH_AMD64 */ +# if RT_INLINE_ASM_GNU_STYLE + uint64_t u64Ret; +# if defined(PIC) || defined(__PIC__) + /* NB: this code uses a memory clobber description, because the clean + * solution with an output value for *pu64 makes gcc run out of registers. + * This will cause suboptimal code, and anyone with a better solution is + * welcome to improve this. */ + __asm__ __volatile__("xchgl %%ebx, %1\n\t" + "lock; cmpxchg8b %3\n\t" + "xchgl %%ebx, %1\n\t" + : "=A" (u64Ret) + : "DS" ((uint32_t)u64New), + "c" ((uint32_t)(u64New >> 32)), + "m" (*pu64), + "0" (u64Old) + : "memory" ); +# else /* !PIC */ + __asm__ __volatile__("lock; cmpxchg8b %4\n\t" + : "=A" (u64Ret), + "=m" (*pu64) + : "b" ((uint32_t)u64New), + "c" ((uint32_t)(u64New >> 32)), + "m" (*pu64), + "0" (u64Old)); +# endif + *pu64Old = u64Ret; + return u64Ret == u64Old; +# else + uint32_t u32Ret; + __asm + { + mov ebx, dword ptr [u64New] + mov ecx, dword ptr [u64New + 4] + mov edi, [pu64] + mov eax, dword ptr [u64Old] + mov edx, dword ptr [u64Old + 4] + lock cmpxchg8b [edi] + mov ebx, [pu64Old] + mov [ebx], eax + setz al + movzx eax, al + add ebx, 4 + mov [ebx], edx + mov dword ptr [u32Ret], eax + } + return !!u32Ret; +# endif +# endif /* !RT_ARCH_AMD64 */ +} +#endif + + +/** + * Atomically Compare and exchange a signed 64-bit value, additionally + * passing back old value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param pi64 Pointer to the 64-bit variable to update. + * @param i64 The 64-bit value to assign to *pu64. + * @param i64Old The value to compare with. + * @param pi64Old Pointer store the old value at. + */ +DECLINLINE(bool) ASMAtomicCmpXchgExS64(volatile int64_t *pi64, const int64_t i64, const int64_t i64Old, int64_t *pi64Old) +{ + return ASMAtomicCmpXchgExU64((volatile uint64_t *)pi64, (uint64_t)i64, (uint64_t)i64Old, (uint64_t *)pi64Old); +} + +/** @def ASMAtomicCmpXchgExHandle + * Atomically Compare and Exchange a typical IPRT handle value, ordered. + * + * @param ph Pointer to the value to update. + * @param hNew The new value to assigned to *pu. + * @param hOld The old value to *pu compare with. + * @param fRc Where to store the result. + * @param phOldVal Pointer to where to store the old value. + * + * @remarks This doesn't currently work for all handles (like RTFILE). + */ +#if HC_ARCH_BITS == 32 +# define ASMAtomicCmpXchgExHandle(ph, hNew, hOld, fRc, phOldVal) \ + do { \ + AssertCompile(sizeof(*ph) == sizeof(uint32_t)); \ + AssertCompile(sizeof(*phOldVal) == sizeof(uint32_t)); \ + (fRc) = ASMAtomicCmpXchgExU32((volatile uint32_t *)(pu), (uint32_t)(uNew), (uint32_t)(uOld), (uint32_t *)(puOldVal)); \ + } while (0) +#elif HC_ARCH_BITS == 64 +# define ASMAtomicCmpXchgExHandle(ph, hNew, hOld, fRc, phOldVal) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \ + AssertCompile(sizeof(*(phOldVal)) == sizeof(uint64_t)); \ + (fRc) = ASMAtomicCmpXchgExU64((volatile uint64_t *)(pu), (uint64_t)(uNew), (uint64_t)(uOld), (uint64_t *)(puOldVal)); \ + } while (0) +#else +# error HC_ARCH_BITS +#endif + + +/** @def ASMAtomicCmpXchgExSize + * Atomically Compare and Exchange a value which size might differ + * between platforms or compilers. Additionally passes back old value. + * + * @param pu Pointer to the value to update. + * @param uNew The new value to assigned to *pu. + * @param uOld The old value to *pu compare with. + * @param fRc Where to store the result. + * @param puOldVal Pointer to where to store the old value. + */ +#define ASMAtomicCmpXchgExSize(pu, uNew, uOld, fRc, puOldVal) \ + do { \ + switch (sizeof(*(pu))) { \ + case 4: (fRc) = ASMAtomicCmpXchgExU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew), (uint32_t)(uOld), (uint32_t *)(uOldVal)); \ + break; \ + case 8: (fRc) = ASMAtomicCmpXchgExU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew), (uint64_t)(uOld), (uint64_t *)(uOldVal)); \ + break; \ + default: AssertMsgFailed(("ASMAtomicCmpXchgSize: size %d is not supported\n", sizeof(*(pu)))); \ + (fRc) = false; \ + (uOldVal) = 0; \ + break; \ + } \ + } while (0) + + +/** + * Atomically Compare and Exchange a pointer value, additionally + * passing back old value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param ppv Pointer to the value to update. + * @param pvNew The new value to assigned to *ppv. + * @param pvOld The old value to *ppv compare with. + * @param ppvOld Pointer store the old value at. + */ +DECLINLINE(bool) ASMAtomicCmpXchgExPtrVoid(void * volatile *ppv, const void *pvNew, const void *pvOld, void **ppvOld) +{ +#if ARCH_BITS == 32 + return ASMAtomicCmpXchgExU32((volatile uint32_t *)(void *)ppv, (uint32_t)pvNew, (uint32_t)pvOld, (uint32_t *)ppvOld); +#elif ARCH_BITS == 64 + return ASMAtomicCmpXchgExU64((volatile uint64_t *)(void *)ppv, (uint64_t)pvNew, (uint64_t)pvOld, (uint64_t *)ppvOld); +#else +# error "ARCH_BITS is bogus" +#endif +} + + +/** + * Atomically Compare and Exchange a pointer value, additionally + * passing back old value, ordered. + * + * @returns true if xchg was done. + * @returns false if xchg wasn't done. + * + * @param ppv Pointer to the value to update. + * @param pvNew The new value to assigned to *ppv. + * @param pvOld The old value to *ppv compare with. + * @param ppvOld Pointer store the old value at. + * + * @remarks This is relatively type safe on GCC platforms. + */ +#ifdef __GNUC__ +# define ASMAtomicCmpXchgExPtr(ppv, pvNew, pvOld, ppvOld) \ + __extension__ \ + ({\ + __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \ + __typeof__(*(ppv)) const pvNewTypeChecked = (pvNew); \ + __typeof__(*(ppv)) const pvOldTypeChecked = (pvOld); \ + __typeof__(*(ppv)) * const ppvOldTypeChecked = (ppvOld); \ + bool fMacroRet = ASMAtomicCmpXchgExPtrVoid((void * volatile *)ppvTypeChecked, \ + (void *)pvNewTypeChecked, (void *)pvOldTypeChecked, \ + (void **)ppvOldTypeChecked); \ + fMacroRet; \ + }) +#else +# define ASMAtomicCmpXchgExPtr(ppv, pvNew, pvOld, ppvOld) \ + ASMAtomicCmpXchgExPtrVoid((void * volatile *)(ppv), (void *)(pvNew), (void *)(pvOld), (void **)(ppvOld)) +#endif + + +/** + * Serialize Instruction. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMSerializeInstruction(void); +#else +DECLINLINE(void) ASMSerializeInstruction(void) +{ +# if RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG xAX = 0; +# ifdef RT_ARCH_AMD64 + __asm__ ("cpuid" + : "=a" (xAX) + : "0" (xAX) + : "rbx", "rcx", "rdx"); +# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__) + __asm__ ("push %%ebx\n\t" + "cpuid\n\t" + "pop %%ebx\n\t" + : "=a" (xAX) + : "0" (xAX) + : "ecx", "edx"); +# else + __asm__ ("cpuid" + : "=a" (xAX) + : "0" (xAX) + : "ebx", "ecx", "edx"); +# endif + +# elif RT_INLINE_ASM_USES_INTRIN + int aInfo[4]; + __cpuid(aInfo, 0); + +# else + __asm + { + push ebx + xor eax, eax + cpuid + pop ebx + } +# endif +} +#endif + + +/** + * Memory fence, waits for any pending writes and reads to complete. + */ +DECLINLINE(void) ASMMemoryFence(void) +{ + /** @todo use mfence? check if all cpus we care for support it. */ + uint32_t volatile u32; + ASMAtomicXchgU32(&u32, 0); +} + + +/** + * Write fence, waits for any pending writes to complete. + */ +DECLINLINE(void) ASMWriteFence(void) +{ + /** @todo use sfence? check if all cpus we care for support it. */ + ASMMemoryFence(); +} + + +/** + * Read fence, waits for any pending reads to complete. + */ +DECLINLINE(void) ASMReadFence(void) +{ + /** @todo use lfence? check if all cpus we care for support it. */ + ASMMemoryFence(); +} + + +/** + * Atomically reads an unsigned 8-bit value, ordered. + * + * @returns Current *pu8 value + * @param pu8 Pointer to the 8-bit variable to read. + */ +DECLINLINE(uint8_t) ASMAtomicReadU8(volatile uint8_t *pu8) +{ + ASMMemoryFence(); + return *pu8; /* byte reads are atomic on x86 */ +} + + +/** + * Atomically reads an unsigned 8-bit value, unordered. + * + * @returns Current *pu8 value + * @param pu8 Pointer to the 8-bit variable to read. + */ +DECLINLINE(uint8_t) ASMAtomicUoReadU8(volatile uint8_t *pu8) +{ + return *pu8; /* byte reads are atomic on x86 */ +} + + +/** + * Atomically reads a signed 8-bit value, ordered. + * + * @returns Current *pi8 value + * @param pi8 Pointer to the 8-bit variable to read. + */ +DECLINLINE(int8_t) ASMAtomicReadS8(volatile int8_t *pi8) +{ + ASMMemoryFence(); + return *pi8; /* byte reads are atomic on x86 */ +} + + +/** + * Atomically reads a signed 8-bit value, unordered. + * + * @returns Current *pi8 value + * @param pi8 Pointer to the 8-bit variable to read. + */ +DECLINLINE(int8_t) ASMAtomicUoReadS8(volatile int8_t *pi8) +{ + return *pi8; /* byte reads are atomic on x86 */ +} + + +/** + * Atomically reads an unsigned 16-bit value, ordered. + * + * @returns Current *pu16 value + * @param pu16 Pointer to the 16-bit variable to read. + */ +DECLINLINE(uint16_t) ASMAtomicReadU16(volatile uint16_t *pu16) +{ + ASMMemoryFence(); + Assert(!((uintptr_t)pu16 & 1)); + return *pu16; +} + + +/** + * Atomically reads an unsigned 16-bit value, unordered. + * + * @returns Current *pu16 value + * @param pu16 Pointer to the 16-bit variable to read. + */ +DECLINLINE(uint16_t) ASMAtomicUoReadU16(volatile uint16_t *pu16) +{ + Assert(!((uintptr_t)pu16 & 1)); + return *pu16; +} + + +/** + * Atomically reads a signed 16-bit value, ordered. + * + * @returns Current *pi16 value + * @param pi16 Pointer to the 16-bit variable to read. + */ +DECLINLINE(int16_t) ASMAtomicReadS16(volatile int16_t *pi16) +{ + ASMMemoryFence(); + Assert(!((uintptr_t)pi16 & 1)); + return *pi16; +} + + +/** + * Atomically reads a signed 16-bit value, unordered. + * + * @returns Current *pi16 value + * @param pi16 Pointer to the 16-bit variable to read. + */ +DECLINLINE(int16_t) ASMAtomicUoReadS16(volatile int16_t *pi16) +{ + Assert(!((uintptr_t)pi16 & 1)); + return *pi16; +} + + +/** + * Atomically reads an unsigned 32-bit value, ordered. + * + * @returns Current *pu32 value + * @param pu32 Pointer to the 32-bit variable to read. + */ +DECLINLINE(uint32_t) ASMAtomicReadU32(volatile uint32_t *pu32) +{ + ASMMemoryFence(); + Assert(!((uintptr_t)pu32 & 3)); + return *pu32; +} + + +/** + * Atomically reads an unsigned 32-bit value, unordered. + * + * @returns Current *pu32 value + * @param pu32 Pointer to the 32-bit variable to read. + */ +DECLINLINE(uint32_t) ASMAtomicUoReadU32(volatile uint32_t *pu32) +{ + Assert(!((uintptr_t)pu32 & 3)); + return *pu32; +} + + +/** + * Atomically reads a signed 32-bit value, ordered. + * + * @returns Current *pi32 value + * @param pi32 Pointer to the 32-bit variable to read. + */ +DECLINLINE(int32_t) ASMAtomicReadS32(volatile int32_t *pi32) +{ + ASMMemoryFence(); + Assert(!((uintptr_t)pi32 & 3)); + return *pi32; +} + + +/** + * Atomically reads a signed 32-bit value, unordered. + * + * @returns Current *pi32 value + * @param pi32 Pointer to the 32-bit variable to read. + */ +DECLINLINE(int32_t) ASMAtomicUoReadS32(volatile int32_t *pi32) +{ + Assert(!((uintptr_t)pi32 & 3)); + return *pi32; +} + + +/** + * Atomically reads an unsigned 64-bit value, ordered. + * + * @returns Current *pu64 value + * @param pu64 Pointer to the 64-bit variable to read. + * The memory pointed to must be writable. + * @remark This will fault if the memory is read-only! + */ +#if (RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)) \ + || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC +DECLASM(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64); +#else +DECLINLINE(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64) +{ + uint64_t u64; +# ifdef RT_ARCH_AMD64 + Assert(!((uintptr_t)pu64 & 7)); +/*# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__( "mfence\n\t" + "movq %1, %0\n\t" + : "=r" (u64) + : "m" (*pu64)); +# else + __asm + { + mfence + mov rdx, [pu64] + mov rax, [rdx] + mov [u64], rax + } +# endif*/ + ASMMemoryFence(); + u64 = *pu64; +# else /* !RT_ARCH_AMD64 */ +# if RT_INLINE_ASM_GNU_STYLE +# if defined(PIC) || defined(__PIC__) + uint32_t u32EBX = 0; + Assert(!((uintptr_t)pu64 & 7)); + __asm__ __volatile__("xchgl %%ebx, %3\n\t" + "lock; cmpxchg8b (%5)\n\t" + "movl %3, %%ebx\n\t" + : "=A" (u64), +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 + "+m" (*pu64) +# else + "=m" (*pu64) +# endif + : "0" (0ULL), + "m" (u32EBX), + "c" (0), + "S" (pu64)); +# else /* !PIC */ + __asm__ __volatile__("lock; cmpxchg8b %1\n\t" + : "=A" (u64), + "+m" (*pu64) + : "0" (0ULL), + "b" (0), + "c" (0)); +# endif +# else + Assert(!((uintptr_t)pu64 & 7)); + __asm + { + xor eax, eax + xor edx, edx + mov edi, pu64 + xor ecx, ecx + xor ebx, ebx + lock cmpxchg8b [edi] + mov dword ptr [u64], eax + mov dword ptr [u64 + 4], edx + } +# endif +# endif /* !RT_ARCH_AMD64 */ + return u64; +} +#endif + + +/** + * Atomically reads an unsigned 64-bit value, unordered. + * + * @returns Current *pu64 value + * @param pu64 Pointer to the 64-bit variable to read. + * The memory pointed to must be writable. + * @remark This will fault if the memory is read-only! + */ +#if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \ + || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC +DECLASM(uint64_t) ASMAtomicUoReadU64(volatile uint64_t *pu64); +#else +DECLINLINE(uint64_t) ASMAtomicUoReadU64(volatile uint64_t *pu64) +{ + uint64_t u64; +# ifdef RT_ARCH_AMD64 + Assert(!((uintptr_t)pu64 & 7)); +/*# if RT_INLINE_ASM_GNU_STYLE + Assert(!((uintptr_t)pu64 & 7)); + __asm__ __volatile__("movq %1, %0\n\t" + : "=r" (u64) + : "m" (*pu64)); +# else + __asm + { + mov rdx, [pu64] + mov rax, [rdx] + mov [u64], rax + } +# endif */ + u64 = *pu64; +# else /* !RT_ARCH_AMD64 */ +# if RT_INLINE_ASM_GNU_STYLE +# if defined(PIC) || defined(__PIC__) + uint32_t u32EBX = 0; + uint32_t u32Spill; + Assert(!((uintptr_t)pu64 & 7)); + __asm__ __volatile__("xor %%eax,%%eax\n\t" + "xor %%ecx,%%ecx\n\t" + "xor %%edx,%%edx\n\t" + "xchgl %%ebx, %3\n\t" + "lock; cmpxchg8b (%4)\n\t" + "movl %3, %%ebx\n\t" + : "=A" (u64), +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 + "+m" (*pu64), +# else + "=m" (*pu64), +# endif + "=c" (u32Spill) + : "m" (u32EBX), + "S" (pu64)); +# else /* !PIC */ + __asm__ __volatile__("lock; cmpxchg8b %1\n\t" + : "=A" (u64), + "+m" (*pu64) + : "0" (0ULL), + "b" (0), + "c" (0)); +# endif +# else + Assert(!((uintptr_t)pu64 & 7)); + __asm + { + xor eax, eax + xor edx, edx + mov edi, pu64 + xor ecx, ecx + xor ebx, ebx + lock cmpxchg8b [edi] + mov dword ptr [u64], eax + mov dword ptr [u64 + 4], edx + } +# endif +# endif /* !RT_ARCH_AMD64 */ + return u64; +} +#endif + + +/** + * Atomically reads a signed 64-bit value, ordered. + * + * @returns Current *pi64 value + * @param pi64 Pointer to the 64-bit variable to read. + * The memory pointed to must be writable. + * @remark This will fault if the memory is read-only! + */ +DECLINLINE(int64_t) ASMAtomicReadS64(volatile int64_t *pi64) +{ + return (int64_t)ASMAtomicReadU64((volatile uint64_t *)pi64); +} + + +/** + * Atomically reads a signed 64-bit value, unordered. + * + * @returns Current *pi64 value + * @param pi64 Pointer to the 64-bit variable to read. + * The memory pointed to must be writable. + * @remark This will fault if the memory is read-only! + */ +DECLINLINE(int64_t) ASMAtomicUoReadS64(volatile int64_t *pi64) +{ + return (int64_t)ASMAtomicUoReadU64((volatile uint64_t *)pi64); +} + + +/** + * Atomically reads a size_t value, ordered. + * + * @returns Current *pcb value + * @param pcb Pointer to the size_t variable to read. + */ +DECLINLINE(size_t) ASMAtomicReadZ(size_t volatile *pcb) +{ +#if ARCH_BITS == 64 + return ASMAtomicReadU64((uint64_t volatile *)pcb); +#elif ARCH_BITS == 32 + return ASMAtomicReadU32((uint32_t volatile *)pcb); +#else +# error "Unsupported ARCH_BITS value" +#endif +} + + +/** + * Atomically reads a size_t value, unordered. + * + * @returns Current *pcb value + * @param pcb Pointer to the size_t variable to read. + */ +DECLINLINE(size_t) ASMAtomicUoReadZ(size_t volatile *pcb) +{ +#if ARCH_BITS == 64 + return ASMAtomicUoReadU64((uint64_t volatile *)pcb); +#elif ARCH_BITS == 32 + return ASMAtomicUoReadU32((uint32_t volatile *)pcb); +#else +# error "Unsupported ARCH_BITS value" +#endif +} + + +/** + * Atomically reads a pointer value, ordered. + * + * @returns Current *pv value + * @param ppv Pointer to the pointer variable to read. + * + * @remarks Please use ASMAtomicReadPtrT, it provides better type safety and + * requires less typing (no casts). + */ +DECLINLINE(void *) ASMAtomicReadPtr(void * volatile *ppv) +{ +#if ARCH_BITS == 32 + return (void *)ASMAtomicReadU32((volatile uint32_t *)(void *)ppv); +#elif ARCH_BITS == 64 + return (void *)ASMAtomicReadU64((volatile uint64_t *)(void *)ppv); +#else +# error "ARCH_BITS is bogus" +#endif +} + +/** + * Convenience macro for avoiding the annoying casting with ASMAtomicReadPtr. + * + * @returns Current *pv value + * @param ppv Pointer to the pointer variable to read. + * @param Type The type of *ppv, sans volatile. + */ +#ifdef __GNUC__ +# define ASMAtomicReadPtrT(ppv, Type) \ + __extension__ \ + ({\ + __typeof__(*(ppv)) volatile *ppvTypeChecked = (ppv); \ + Type pvTypeChecked = (__typeof__(*(ppv))) ASMAtomicReadPtr((void * volatile *)ppvTypeChecked); \ + pvTypeChecked; \ + }) +#else +# define ASMAtomicReadPtrT(ppv, Type) \ + (Type)ASMAtomicReadPtr((void * volatile *)(ppv)) +#endif + + +/** + * Atomically reads a pointer value, unordered. + * + * @returns Current *pv value + * @param ppv Pointer to the pointer variable to read. + * + * @remarks Please use ASMAtomicUoReadPtrT, it provides better type safety and + * requires less typing (no casts). + */ +DECLINLINE(void *) ASMAtomicUoReadPtr(void * volatile *ppv) +{ +#if ARCH_BITS == 32 + return (void *)ASMAtomicUoReadU32((volatile uint32_t *)(void *)ppv); +#elif ARCH_BITS == 64 + return (void *)ASMAtomicUoReadU64((volatile uint64_t *)(void *)ppv); +#else +# error "ARCH_BITS is bogus" +#endif +} + + +/** + * Convenience macro for avoiding the annoying casting with ASMAtomicUoReadPtr. + * + * @returns Current *pv value + * @param ppv Pointer to the pointer variable to read. + * @param Type The type of *ppv, sans volatile. + */ +#ifdef __GNUC__ +# define ASMAtomicUoReadPtrT(ppv, Type) \ + __extension__ \ + ({\ + __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \ + Type pvTypeChecked = (__typeof__(*(ppv))) ASMAtomicUoReadPtr((void * volatile *)ppvTypeChecked); \ + pvTypeChecked; \ + }) +#else +# define ASMAtomicUoReadPtrT(ppv, Type) \ + (Type)ASMAtomicUoReadPtr((void * volatile *)(ppv)) +#endif + + +/** + * Atomically reads a boolean value, ordered. + * + * @returns Current *pf value + * @param pf Pointer to the boolean variable to read. + */ +DECLINLINE(bool) ASMAtomicReadBool(volatile bool *pf) +{ + ASMMemoryFence(); + return *pf; /* byte reads are atomic on x86 */ +} + + +/** + * Atomically reads a boolean value, unordered. + * + * @returns Current *pf value + * @param pf Pointer to the boolean variable to read. + */ +DECLINLINE(bool) ASMAtomicUoReadBool(volatile bool *pf) +{ + return *pf; /* byte reads are atomic on x86 */ +} + + +/** + * Atomically read a typical IPRT handle value, ordered. + * + * @param ph Pointer to the handle variable to read. + * @param phRes Where to store the result. + * + * @remarks This doesn't currently work for all handles (like RTFILE). + */ +#if HC_ARCH_BITS == 32 +# define ASMAtomicReadHandle(ph, phRes) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \ + AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \ + *(uint32_t *)(phRes) = ASMAtomicReadU32((uint32_t volatile *)(ph)); \ + } while (0) +#elif HC_ARCH_BITS == 64 +# define ASMAtomicReadHandle(ph, phRes) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \ + AssertCompile(sizeof(*(phRes)) == sizeof(uint64_t)); \ + *(uint64_t *)(phRes) = ASMAtomicReadU64((uint64_t volatile *)(ph)); \ + } while (0) +#else +# error HC_ARCH_BITS +#endif + + +/** + * Atomically read a typical IPRT handle value, unordered. + * + * @param ph Pointer to the handle variable to read. + * @param phRes Where to store the result. + * + * @remarks This doesn't currently work for all handles (like RTFILE). + */ +#if HC_ARCH_BITS == 32 +# define ASMAtomicUoReadHandle(ph, phRes) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \ + AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \ + *(uint32_t *)(phRes) = ASMAtomicUoReadU32((uint32_t volatile *)(ph)); \ + } while (0) +#elif HC_ARCH_BITS == 64 +# define ASMAtomicUoReadHandle(ph, phRes) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \ + AssertCompile(sizeof(*(phRes)) == sizeof(uint64_t)); \ + *(uint64_t *)(phRes) = ASMAtomicUoReadU64((uint64_t volatile *)(ph)); \ + } while (0) +#else +# error HC_ARCH_BITS +#endif + + +/** + * Atomically read a value which size might differ + * between platforms or compilers, ordered. + * + * @param pu Pointer to the variable to read. + * @param puRes Where to store the result. + */ +#define ASMAtomicReadSize(pu, puRes) \ + do { \ + switch (sizeof(*(pu))) { \ + case 1: *(uint8_t *)(puRes) = ASMAtomicReadU8( (volatile uint8_t *)(void *)(pu)); break; \ + case 2: *(uint16_t *)(puRes) = ASMAtomicReadU16((volatile uint16_t *)(void *)(pu)); break; \ + case 4: *(uint32_t *)(puRes) = ASMAtomicReadU32((volatile uint32_t *)(void *)(pu)); break; \ + case 8: *(uint64_t *)(puRes) = ASMAtomicReadU64((volatile uint64_t *)(void *)(pu)); break; \ + default: AssertMsgFailed(("ASMAtomicReadSize: size %d is not supported\n", sizeof(*(pu)))); \ + } \ + } while (0) + + +/** + * Atomically read a value which size might differ + * between platforms or compilers, unordered. + * + * @param pu Pointer to the variable to read. + * @param puRes Where to store the result. + */ +#define ASMAtomicUoReadSize(pu, puRes) \ + do { \ + switch (sizeof(*(pu))) { \ + case 1: *(uint8_t *)(puRes) = ASMAtomicUoReadU8( (volatile uint8_t *)(void *)(pu)); break; \ + case 2: *(uint16_t *)(puRes) = ASMAtomicUoReadU16((volatile uint16_t *)(void *)(pu)); break; \ + case 4: *(uint32_t *)(puRes) = ASMAtomicUoReadU32((volatile uint32_t *)(void *)(pu)); break; \ + case 8: *(uint64_t *)(puRes) = ASMAtomicUoReadU64((volatile uint64_t *)(void *)(pu)); break; \ + default: AssertMsgFailed(("ASMAtomicReadSize: size %d is not supported\n", sizeof(*(pu)))); \ + } \ + } while (0) + + +/** + * Atomically writes an unsigned 8-bit value, ordered. + * + * @param pu8 Pointer to the 8-bit variable. + * @param u8 The 8-bit value to assign to *pu8. + */ +DECLINLINE(void) ASMAtomicWriteU8(volatile uint8_t *pu8, uint8_t u8) +{ + ASMAtomicXchgU8(pu8, u8); +} + + +/** + * Atomically writes an unsigned 8-bit value, unordered. + * + * @param pu8 Pointer to the 8-bit variable. + * @param u8 The 8-bit value to assign to *pu8. + */ +DECLINLINE(void) ASMAtomicUoWriteU8(volatile uint8_t *pu8, uint8_t u8) +{ + *pu8 = u8; /* byte writes are atomic on x86 */ +} + + +/** + * Atomically writes a signed 8-bit value, ordered. + * + * @param pi8 Pointer to the 8-bit variable to read. + * @param i8 The 8-bit value to assign to *pi8. + */ +DECLINLINE(void) ASMAtomicWriteS8(volatile int8_t *pi8, int8_t i8) +{ + ASMAtomicXchgS8(pi8, i8); +} + + +/** + * Atomically writes a signed 8-bit value, unordered. + * + * @param pi8 Pointer to the 8-bit variable to write. + * @param i8 The 8-bit value to assign to *pi8. + */ +DECLINLINE(void) ASMAtomicUoWriteS8(volatile int8_t *pi8, int8_t i8) +{ + *pi8 = i8; /* byte writes are atomic on x86 */ +} + + +/** + * Atomically writes an unsigned 16-bit value, ordered. + * + * @param pu16 Pointer to the 16-bit variable to write. + * @param u16 The 16-bit value to assign to *pu16. + */ +DECLINLINE(void) ASMAtomicWriteU16(volatile uint16_t *pu16, uint16_t u16) +{ + ASMAtomicXchgU16(pu16, u16); +} + + +/** + * Atomically writes an unsigned 16-bit value, unordered. + * + * @param pu16 Pointer to the 16-bit variable to write. + * @param u16 The 16-bit value to assign to *pu16. + */ +DECLINLINE(void) ASMAtomicUoWriteU16(volatile uint16_t *pu16, uint16_t u16) +{ + Assert(!((uintptr_t)pu16 & 1)); + *pu16 = u16; +} + + +/** + * Atomically writes a signed 16-bit value, ordered. + * + * @param pi16 Pointer to the 16-bit variable to write. + * @param i16 The 16-bit value to assign to *pi16. + */ +DECLINLINE(void) ASMAtomicWriteS16(volatile int16_t *pi16, int16_t i16) +{ + ASMAtomicXchgS16(pi16, i16); +} + + +/** + * Atomically writes a signed 16-bit value, unordered. + * + * @param pi16 Pointer to the 16-bit variable to write. + * @param i16 The 16-bit value to assign to *pi16. + */ +DECLINLINE(void) ASMAtomicUoWriteS16(volatile int16_t *pi16, int16_t i16) +{ + Assert(!((uintptr_t)pi16 & 1)); + *pi16 = i16; +} + + +/** + * Atomically writes an unsigned 32-bit value, ordered. + * + * @param pu32 Pointer to the 32-bit variable to write. + * @param u32 The 32-bit value to assign to *pu32. + */ +DECLINLINE(void) ASMAtomicWriteU32(volatile uint32_t *pu32, uint32_t u32) +{ + ASMAtomicXchgU32(pu32, u32); +} + + +/** + * Atomically writes an unsigned 32-bit value, unordered. + * + * @param pu32 Pointer to the 32-bit variable to write. + * @param u32 The 32-bit value to assign to *pu32. + */ +DECLINLINE(void) ASMAtomicUoWriteU32(volatile uint32_t *pu32, uint32_t u32) +{ + Assert(!((uintptr_t)pu32 & 3)); + *pu32 = u32; +} + + +/** + * Atomically writes a signed 32-bit value, ordered. + * + * @param pi32 Pointer to the 32-bit variable to write. + * @param i32 The 32-bit value to assign to *pi32. + */ +DECLINLINE(void) ASMAtomicWriteS32(volatile int32_t *pi32, int32_t i32) +{ + ASMAtomicXchgS32(pi32, i32); +} + + +/** + * Atomically writes a signed 32-bit value, unordered. + * + * @param pi32 Pointer to the 32-bit variable to write. + * @param i32 The 32-bit value to assign to *pi32. + */ +DECLINLINE(void) ASMAtomicUoWriteS32(volatile int32_t *pi32, int32_t i32) +{ + Assert(!((uintptr_t)pi32 & 3)); + *pi32 = i32; +} + + +/** + * Atomically writes an unsigned 64-bit value, ordered. + * + * @param pu64 Pointer to the 64-bit variable to write. + * @param u64 The 64-bit value to assign to *pu64. + */ +DECLINLINE(void) ASMAtomicWriteU64(volatile uint64_t *pu64, uint64_t u64) +{ + ASMAtomicXchgU64(pu64, u64); +} + + +/** + * Atomically writes an unsigned 64-bit value, unordered. + * + * @param pu64 Pointer to the 64-bit variable to write. + * @param u64 The 64-bit value to assign to *pu64. + */ +DECLINLINE(void) ASMAtomicUoWriteU64(volatile uint64_t *pu64, uint64_t u64) +{ + Assert(!((uintptr_t)pu64 & 7)); +#if ARCH_BITS == 64 + *pu64 = u64; +#else + ASMAtomicXchgU64(pu64, u64); +#endif +} + + +/** + * Atomically writes a signed 64-bit value, ordered. + * + * @param pi64 Pointer to the 64-bit variable to write. + * @param i64 The 64-bit value to assign to *pi64. + */ +DECLINLINE(void) ASMAtomicWriteS64(volatile int64_t *pi64, int64_t i64) +{ + ASMAtomicXchgS64(pi64, i64); +} + + +/** + * Atomically writes a signed 64-bit value, unordered. + * + * @param pi64 Pointer to the 64-bit variable to write. + * @param i64 The 64-bit value to assign to *pi64. + */ +DECLINLINE(void) ASMAtomicUoWriteS64(volatile int64_t *pi64, int64_t i64) +{ + Assert(!((uintptr_t)pi64 & 7)); +#if ARCH_BITS == 64 + *pi64 = i64; +#else + ASMAtomicXchgS64(pi64, i64); +#endif +} + + +/** + * Atomically writes a boolean value, unordered. + * + * @param pf Pointer to the boolean variable to write. + * @param f The boolean value to assign to *pf. + */ +DECLINLINE(void) ASMAtomicWriteBool(volatile bool *pf, bool f) +{ + ASMAtomicWriteU8((uint8_t volatile *)pf, f); +} + + +/** + * Atomically writes a boolean value, unordered. + * + * @param pf Pointer to the boolean variable to write. + * @param f The boolean value to assign to *pf. + */ +DECLINLINE(void) ASMAtomicUoWriteBool(volatile bool *pf, bool f) +{ + *pf = f; /* byte writes are atomic on x86 */ +} + + +/** + * Atomically writes a pointer value, ordered. + * + * @param ppv Pointer to the pointer variable to write. + * @param pv The pointer value to assign to *ppv. + */ +DECLINLINE(void) ASMAtomicWritePtrVoid(void * volatile *ppv, const void *pv) +{ +#if ARCH_BITS == 32 + ASMAtomicWriteU32((volatile uint32_t *)(void *)ppv, (uint32_t)pv); +#elif ARCH_BITS == 64 + ASMAtomicWriteU64((volatile uint64_t *)(void *)ppv, (uint64_t)pv); +#else +# error "ARCH_BITS is bogus" +#endif +} + + +/** + * Atomically writes a pointer value, ordered. + * + * @param ppv Pointer to the pointer variable to write. + * @param pv The pointer value to assign to *ppv. If NULL use + * ASMAtomicWriteNullPtr or you'll land in trouble. + * + * @remarks This is relatively type safe on GCC platforms when @a pv isn't + * NULL. + */ +#ifdef __GNUC__ +# define ASMAtomicWritePtr(ppv, pv) \ + do \ + { \ + __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \ + __typeof__(*(ppv)) const pvTypeChecked = (pv); \ + \ + AssertCompile(sizeof(*ppv) == sizeof(void *)); \ + AssertCompile(sizeof(pv) == sizeof(void *)); \ + Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \ + \ + ASMAtomicWritePtrVoid((void * volatile *)(ppvTypeChecked), (void *)(pvTypeChecked)); \ + } while (0) +#else +# define ASMAtomicWritePtr(ppv, pv) \ + do \ + { \ + AssertCompile(sizeof(*ppv) == sizeof(void *)); \ + AssertCompile(sizeof(pv) == sizeof(void *)); \ + Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \ + \ + ASMAtomicWritePtrVoid((void * volatile *)(ppv), (void *)(pv)); \ + } while (0) +#endif + + +/** + * Atomically sets a pointer to NULL, ordered. + * + * @param ppv Pointer to the pointer variable that should be set to NULL. + * + * @remarks This is relatively type safe on GCC platforms. + */ +#ifdef __GNUC__ +# define ASMAtomicWriteNullPtr(ppv) \ + do \ + { \ + __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \ + AssertCompile(sizeof(*ppv) == sizeof(void *)); \ + Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \ + ASMAtomicWritePtrVoid((void * volatile *)(ppvTypeChecked), NULL); \ + } while (0) +#else +# define ASMAtomicWriteNullPtr(ppv) \ + do \ + { \ + AssertCompile(sizeof(*ppv) == sizeof(void *)); \ + Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \ + ASMAtomicWritePtrVoid((void * volatile *)(ppv), NULL); \ + } while (0) +#endif + + +/** + * Atomically writes a pointer value, unordered. + * + * @returns Current *pv value + * @param ppv Pointer to the pointer variable. + * @param pv The pointer value to assign to *ppv. If NULL use + * ASMAtomicUoWriteNullPtr or you'll land in trouble. + * + * @remarks This is relatively type safe on GCC platforms when @a pv isn't + * NULL. + */ +#ifdef __GNUC__ +# define ASMAtomicUoWritePtr(ppv, pv) \ + do \ + { \ + __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \ + __typeof__(*(ppv)) const pvTypeChecked = (pv); \ + \ + AssertCompile(sizeof(*ppv) == sizeof(void *)); \ + AssertCompile(sizeof(pv) == sizeof(void *)); \ + Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \ + \ + *(ppvTypeChecked) = pvTypeChecked; \ + } while (0) +#else +# define ASMAtomicUoWritePtr(ppv, pv) \ + do \ + { \ + AssertCompile(sizeof(*ppv) == sizeof(void *)); \ + AssertCompile(sizeof(pv) == sizeof(void *)); \ + Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \ + *(ppv) = pv; \ + } while (0) +#endif + + +/** + * Atomically sets a pointer to NULL, unordered. + * + * @param ppv Pointer to the pointer variable that should be set to NULL. + * + * @remarks This is relatively type safe on GCC platforms. + */ +#ifdef __GNUC__ +# define ASMAtomicUoWriteNullPtr(ppv) \ + do \ + { \ + __typeof__(*(ppv)) volatile * const ppvTypeChecked = (ppv); \ + AssertCompile(sizeof(*ppv) == sizeof(void *)); \ + Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \ + *(ppvTypeChecked) = NULL; \ + } while (0) +#else +# define ASMAtomicUoWriteNullPtr(ppv) \ + do \ + { \ + AssertCompile(sizeof(*ppv) == sizeof(void *)); \ + Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \ + *(ppv) = NULL; \ + } while (0) +#endif + + +/** + * Atomically write a typical IPRT handle value, ordered. + * + * @param ph Pointer to the variable to update. + * @param hNew The value to assign to *ph. + * + * @remarks This doesn't currently work for all handles (like RTFILE). + */ +#if HC_ARCH_BITS == 32 +# define ASMAtomicWriteHandle(ph, hNew) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \ + ASMAtomicWriteU32((uint32_t volatile *)(ph), (const uint32_t)(hNew)); \ + } while (0) +#elif HC_ARCH_BITS == 64 +# define ASMAtomicWriteHandle(ph, hNew) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \ + ASMAtomicWriteU64((uint64_t volatile *)(ph), (const uint64_t)(hNew)); \ + } while (0) +#else +# error HC_ARCH_BITS +#endif + + +/** + * Atomically write a typical IPRT handle value, unordered. + * + * @param ph Pointer to the variable to update. + * @param hNew The value to assign to *ph. + * + * @remarks This doesn't currently work for all handles (like RTFILE). + */ +#if HC_ARCH_BITS == 32 +# define ASMAtomicUoWriteHandle(ph, hNew) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \ + ASMAtomicUoWriteU32((uint32_t volatile *)(ph), (const uint32_t)hNew); \ + } while (0) +#elif HC_ARCH_BITS == 64 +# define ASMAtomicUoWriteHandle(ph, hNew) \ + do { \ + AssertCompile(sizeof(*(ph)) == sizeof(uint64_t)); \ + ASMAtomicUoWriteU64((uint64_t volatile *)(ph), (const uint64_t)hNew); \ + } while (0) +#else +# error HC_ARCH_BITS +#endif + + +/** + * Atomically write a value which size might differ + * between platforms or compilers, ordered. + * + * @param pu Pointer to the variable to update. + * @param uNew The value to assign to *pu. + */ +#define ASMAtomicWriteSize(pu, uNew) \ + do { \ + switch (sizeof(*(pu))) { \ + case 1: ASMAtomicWriteU8( (volatile uint8_t *)(void *)(pu), (uint8_t )(uNew)); break; \ + case 2: ASMAtomicWriteU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \ + case 4: ASMAtomicWriteU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \ + case 8: ASMAtomicWriteU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \ + default: AssertMsgFailed(("ASMAtomicWriteSize: size %d is not supported\n", sizeof(*(pu)))); \ + } \ + } while (0) + +/** + * Atomically write a value which size might differ + * between platforms or compilers, unordered. + * + * @param pu Pointer to the variable to update. + * @param uNew The value to assign to *pu. + */ +#define ASMAtomicUoWriteSize(pu, uNew) \ + do { \ + switch (sizeof(*(pu))) { \ + case 1: ASMAtomicUoWriteU8( (volatile uint8_t *)(void *)(pu), (uint8_t )(uNew)); break; \ + case 2: ASMAtomicUoWriteU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \ + case 4: ASMAtomicUoWriteU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \ + case 8: ASMAtomicUoWriteU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \ + default: AssertMsgFailed(("ASMAtomicWriteSize: size %d is not supported\n", sizeof(*(pu)))); \ + } \ + } while (0) + + + +/** + * Atomically exchanges and adds to a 32-bit value, ordered. + * + * @returns The old value. + * @param pu32 Pointer to the value. + * @param u32 Number to add. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMAtomicAddU32(uint32_t volatile *pu32, uint32_t u32); +#else +DECLINLINE(uint32_t) ASMAtomicAddU32(uint32_t volatile *pu32, uint32_t u32) +{ +# if RT_INLINE_ASM_USES_INTRIN + u32 = _InterlockedExchangeAdd((long *)pu32, u32); + return u32; + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; xaddl %0, %1\n\t" + : "=r" (u32), + "=m" (*pu32) + : "0" (u32), + "m" (*pu32) + : "memory"); + return u32; +# else + __asm + { + mov eax, [u32] +# ifdef RT_ARCH_AMD64 + mov rdx, [pu32] + lock xadd [rdx], eax +# else + mov edx, [pu32] + lock xadd [edx], eax +# endif + mov [u32], eax + } + return u32; +# endif +} +#endif + + +/** + * Atomically exchanges and adds to a signed 32-bit value, ordered. + * + * @returns The old value. + * @param pi32 Pointer to the value. + * @param i32 Number to add. + */ +DECLINLINE(int32_t) ASMAtomicAddS32(int32_t volatile *pi32, int32_t i32) +{ + return (int32_t)ASMAtomicAddU32((uint32_t volatile *)pi32, (uint32_t)i32); +} + + +/** + * Atomically exchanges and adds to a 64-bit value, ordered. + * + * @returns The old value. + * @param pu64 Pointer to the value. + * @param u64 Number to add. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint64_t) ASMAtomicAddU64(uint64_t volatile *pu64, uint64_t u64); +#else +DECLINLINE(uint64_t) ASMAtomicAddU64(uint64_t volatile *pu64, uint64_t u64) +{ +# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64) + u64 = _InterlockedExchangeAdd64((__int64 *)pu64, u64); + return u64; + +# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64) + __asm__ __volatile__("lock; xaddq %0, %1\n\t" + : "=r" (u64), + "=m" (*pu64) + : "0" (u64), + "m" (*pu64) + : "memory"); + return u64; +# else + uint64_t u64Old; + for (;;) + { + uint64_t u64New; + u64Old = ASMAtomicUoReadU64(pu64); + u64New = u64Old + u64; + if (ASMAtomicCmpXchgU64(pu64, u64New, u64Old)) + break; + ASMNopPause(); + } + return u64Old; +# endif +} +#endif + + +/** + * Atomically exchanges and adds to a signed 64-bit value, ordered. + * + * @returns The old value. + * @param pi64 Pointer to the value. + * @param i64 Number to add. + */ +DECLINLINE(int64_t) ASMAtomicAddS64(int64_t volatile *pi64, int64_t i64) +{ + return (int64_t)ASMAtomicAddU64((uint64_t volatile *)pi64, (uint64_t)i64); +} + + +/** + * Atomically exchanges and adds to a size_t value, ordered. + * + * @returns The old value. + * @param pcb Pointer to the size_t value. + * @param cb Number to add. + */ +DECLINLINE(size_t) ASMAtomicAddZ(size_t volatile *pcb, size_t cb) +{ +#if ARCH_BITS == 64 + return ASMAtomicAddU64((uint64_t volatile *)pcb, cb); +#elif ARCH_BITS == 32 + return ASMAtomicAddU32((uint32_t volatile *)pcb, cb); +#else +# error "Unsupported ARCH_BITS value" +#endif +} + + +/** + * Atomically exchanges and adds a value which size might differ between + * platforms or compilers, ordered. + * + * @param pu Pointer to the variable to update. + * @param uNew The value to add to *pu. + * @param puOld Where to store the old value. + */ +#define ASMAtomicAddSize(pu, uNew, puOld) \ + do { \ + switch (sizeof(*(pu))) { \ + case 4: *(uint32_t *)(puOld) = ASMAtomicAddU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \ + case 8: *(uint64_t *)(puOld) = ASMAtomicAddU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \ + default: AssertMsgFailed(("ASMAtomicAddSize: size %d is not supported\n", sizeof(*(pu)))); \ + } \ + } while (0) + + +/** + * Atomically exchanges and subtracts to an unsigned 32-bit value, ordered. + * + * @returns The old value. + * @param pu32 Pointer to the value. + * @param u32 Number to subtract. + */ +DECLINLINE(uint32_t) ASMAtomicSubU32(uint32_t volatile *pu32, uint32_t u32) +{ + return ASMAtomicAddU32(pu32, (uint32_t)-(int32_t)u32); +} + + +/** + * Atomically exchanges and subtracts to a signed 32-bit value, ordered. + * + * @returns The old value. + * @param pi32 Pointer to the value. + * @param i32 Number to subtract. + */ +DECLINLINE(int32_t) ASMAtomicSubS32(int32_t volatile *pi32, int32_t i32) +{ + return (int32_t)ASMAtomicAddU32((uint32_t volatile *)pi32, (uint32_t)-i32); +} + + +/** + * Atomically exchanges and subtracts to an unsigned 64-bit value, ordered. + * + * @returns The old value. + * @param pu64 Pointer to the value. + * @param u64 Number to subtract. + */ +DECLINLINE(uint64_t) ASMAtomicSubU64(uint64_t volatile *pu64, uint64_t u64) +{ + return ASMAtomicAddU64(pu64, (uint64_t)-(int64_t)u64); +} + + +/** + * Atomically exchanges and subtracts to a signed 64-bit value, ordered. + * + * @returns The old value. + * @param pi64 Pointer to the value. + * @param i64 Number to subtract. + */ +DECLINLINE(int64_t) ASMAtomicSubS64(int64_t volatile *pi64, int64_t i64) +{ + return (int64_t)ASMAtomicAddU64((uint64_t volatile *)pi64, (uint64_t)-i64); +} + + +/** + * Atomically exchanges and subtracts to a size_t value, ordered. + * + * @returns The old value. + * @param pcb Pointer to the size_t value. + * @param cb Number to subtract. + */ +DECLINLINE(size_t) ASMAtomicSubZ(size_t volatile *pcb, size_t cb) +{ +#if ARCH_BITS == 64 + return ASMAtomicSubU64((uint64_t volatile *)pcb, cb); +#elif ARCH_BITS == 32 + return ASMAtomicSubU32((uint32_t volatile *)pcb, cb); +#else +# error "Unsupported ARCH_BITS value" +#endif +} + + +/** + * Atomically exchanges and subtracts a value which size might differ between + * platforms or compilers, ordered. + * + * @param pu Pointer to the variable to update. + * @param uNew The value to subtract to *pu. + * @param puOld Where to store the old value. + */ +#define ASMAtomicSubSize(pu, uNew, puOld) \ + do { \ + switch (sizeof(*(pu))) { \ + case 4: *(uint32_t *)(puOld) = ASMAtomicSubU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \ + case 8: *(uint64_t *)(puOld) = ASMAtomicSubU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \ + default: AssertMsgFailed(("ASMAtomicSubSize: size %d is not supported\n", sizeof(*(pu)))); \ + } \ + } while (0) + + +/** + * Atomically increment a 32-bit value, ordered. + * + * @returns The new value. + * @param pu32 Pointer to the value to increment. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMAtomicIncU32(uint32_t volatile *pu32); +#else +DECLINLINE(uint32_t) ASMAtomicIncU32(uint32_t volatile *pu32) +{ + uint32_t u32; +# if RT_INLINE_ASM_USES_INTRIN + u32 = _InterlockedIncrement((long *)pu32); + return u32; + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; xaddl %0, %1\n\t" + : "=r" (u32), + "=m" (*pu32) + : "0" (1), + "m" (*pu32) + : "memory"); + return u32+1; +# else + __asm + { + mov eax, 1 +# ifdef RT_ARCH_AMD64 + mov rdx, [pu32] + lock xadd [rdx], eax +# else + mov edx, [pu32] + lock xadd [edx], eax +# endif + mov u32, eax + } + return u32+1; +# endif +} +#endif + + +/** + * Atomically increment a signed 32-bit value, ordered. + * + * @returns The new value. + * @param pi32 Pointer to the value to increment. + */ +DECLINLINE(int32_t) ASMAtomicIncS32(int32_t volatile *pi32) +{ + return (int32_t)ASMAtomicIncU32((uint32_t volatile *)pi32); +} + + +/** + * Atomically increment a 64-bit value, ordered. + * + * @returns The new value. + * @param pu64 Pointer to the value to increment. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint64_t) ASMAtomicIncU64(uint64_t volatile *pu64); +#else +DECLINLINE(uint64_t) ASMAtomicIncU64(uint64_t volatile *pu64) +{ +# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64) + uint64_t u64; + u64 = _InterlockedIncrement64((__int64 *)pu64); + return u64; + +# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64) + uint64_t u64; + __asm__ __volatile__("lock; xaddq %0, %1\n\t" + : "=r" (u64), + "=m" (*pu64) + : "0" (1), + "m" (*pu64) + : "memory"); + return u64 + 1; +# else + return ASMAtomicAddU64(pu64, 1) + 1; +# endif +} +#endif + + +/** + * Atomically increment a signed 64-bit value, ordered. + * + * @returns The new value. + * @param pi64 Pointer to the value to increment. + */ +DECLINLINE(int64_t) ASMAtomicIncS64(int64_t volatile *pi64) +{ + return (int64_t)ASMAtomicIncU64((uint64_t volatile *)pi64); +} + + +/** + * Atomically increment a size_t value, ordered. + * + * @returns The new value. + * @param pcb Pointer to the value to increment. + */ +DECLINLINE(int64_t) ASMAtomicIncZ(size_t volatile *pcb) +{ +#if ARCH_BITS == 64 + return ASMAtomicIncU64((uint64_t volatile *)pcb); +#elif ARCH_BITS == 32 + return ASMAtomicIncU32((uint32_t volatile *)pcb); +#else +# error "Unsupported ARCH_BITS value" +#endif +} + + +/** + * Atomically decrement an unsigned 32-bit value, ordered. + * + * @returns The new value. + * @param pu32 Pointer to the value to decrement. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMAtomicDecU32(uint32_t volatile *pu32); +#else +DECLINLINE(uint32_t) ASMAtomicDecU32(uint32_t volatile *pu32) +{ + uint32_t u32; +# if RT_INLINE_ASM_USES_INTRIN + u32 = _InterlockedDecrement((long *)pu32); + return u32; + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; xaddl %0, %1\n\t" + : "=r" (u32), + "=m" (*pu32) + : "0" (-1), + "m" (*pu32) + : "memory"); + return u32-1; +# else + __asm + { + mov eax, -1 +# ifdef RT_ARCH_AMD64 + mov rdx, [pu32] + lock xadd [rdx], eax +# else + mov edx, [pu32] + lock xadd [edx], eax +# endif + mov u32, eax + } + return u32-1; +# endif +} +#endif + + +/** + * Atomically decrement a signed 32-bit value, ordered. + * + * @returns The new value. + * @param pi32 Pointer to the value to decrement. + */ +DECLINLINE(int32_t) ASMAtomicDecS32(int32_t volatile *pi32) +{ + return (int32_t)ASMAtomicDecU32((uint32_t volatile *)pi32); +} + + +/** + * Atomically decrement an unsigned 64-bit value, ordered. + * + * @returns The new value. + * @param pu64 Pointer to the value to decrement. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint64_t) ASMAtomicDecU64(uint64_t volatile *pu64); +#else +DECLINLINE(uint64_t) ASMAtomicDecU64(uint64_t volatile *pu64) +{ +# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64) + uint64_t u64 = _InterlockedDecrement64((__int64 volatile *)pu64); + return u64; + +# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64) + uint64_t u64; + __asm__ __volatile__("lock; xaddq %q0, %1\n\t" + : "=r" (u64), + "=m" (*pu64) + : "0" (~(uint64_t)0), + "m" (*pu64) + : "memory"); + return u64-1; +# else + return ASMAtomicAddU64(pu64, UINT64_MAX) - 1; +# endif +} +#endif + + +/** + * Atomically decrement a signed 64-bit value, ordered. + * + * @returns The new value. + * @param pi64 Pointer to the value to decrement. + */ +DECLINLINE(int64_t) ASMAtomicDecS64(int64_t volatile *pi64) +{ + return (int64_t)ASMAtomicDecU64((uint64_t volatile *)pi64); +} + + +/** + * Atomically decrement a size_t value, ordered. + * + * @returns The new value. + * @param pcb Pointer to the value to decrement. + */ +DECLINLINE(int64_t) ASMAtomicDecZ(size_t volatile *pcb) +{ +#if ARCH_BITS == 64 + return ASMAtomicDecU64((uint64_t volatile *)pcb); +#elif ARCH_BITS == 32 + return ASMAtomicDecU32((uint32_t volatile *)pcb); +#else +# error "Unsupported ARCH_BITS value" +#endif +} + + +/** + * Atomically Or an unsigned 32-bit value, ordered. + * + * @param pu32 Pointer to the pointer variable to OR u32 with. + * @param u32 The value to OR *pu32 with. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMAtomicOrU32(uint32_t volatile *pu32, uint32_t u32); +#else +DECLINLINE(void) ASMAtomicOrU32(uint32_t volatile *pu32, uint32_t u32) +{ +# if RT_INLINE_ASM_USES_INTRIN + _InterlockedOr((long volatile *)pu32, (long)u32); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; orl %1, %0\n\t" + : "=m" (*pu32) + : "ir" (u32), + "m" (*pu32)); +# else + __asm + { + mov eax, [u32] +# ifdef RT_ARCH_AMD64 + mov rdx, [pu32] + lock or [rdx], eax +# else + mov edx, [pu32] + lock or [edx], eax +# endif + } +# endif +} +#endif + + +/** + * Atomically Or a signed 32-bit value, ordered. + * + * @param pi32 Pointer to the pointer variable to OR u32 with. + * @param i32 The value to OR *pu32 with. + */ +DECLINLINE(void) ASMAtomicOrS32(int32_t volatile *pi32, int32_t i32) +{ + ASMAtomicOrU32((uint32_t volatile *)pi32, i32); +} + + +/** + * Atomically Or an unsigned 64-bit value, ordered. + * + * @param pu64 Pointer to the pointer variable to OR u64 with. + * @param u64 The value to OR *pu64 with. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMAtomicOrU64(uint64_t volatile *pu64, uint64_t u64); +#else +DECLINLINE(void) ASMAtomicOrU64(uint64_t volatile *pu64, uint64_t u64) +{ +# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64) + _InterlockedOr64((__int64 volatile *)pu64, (__int64)u64); + +# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64) + __asm__ __volatile__("lock; orq %1, %q0\n\t" + : "=m" (*pu64) + : "r" (u64), + "m" (*pu64)); +# else + for (;;) + { + uint64_t u64Old = ASMAtomicUoReadU64(pu64); + uint64_t u64New = u64Old | u64; + if (ASMAtomicCmpXchgU64(pu64, u64New, u64Old)) + break; + ASMNopPause(); + } +# endif +} +#endif + + +/** + * Atomically Or a signed 64-bit value, ordered. + * + * @param pi64 Pointer to the pointer variable to OR u64 with. + * @param i64 The value to OR *pu64 with. + */ +DECLINLINE(void) ASMAtomicOrS64(int64_t volatile *pi64, int64_t i64) +{ + ASMAtomicOrU64((uint64_t volatile *)pi64, i64); +} +/** + * Atomically And an unsigned 32-bit value, ordered. + * + * @param pu32 Pointer to the pointer variable to AND u32 with. + * @param u32 The value to AND *pu32 with. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMAtomicAndU32(uint32_t volatile *pu32, uint32_t u32); +#else +DECLINLINE(void) ASMAtomicAndU32(uint32_t volatile *pu32, uint32_t u32) +{ +# if RT_INLINE_ASM_USES_INTRIN + _InterlockedAnd((long volatile *)pu32, u32); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; andl %1, %0\n\t" + : "=m" (*pu32) + : "ir" (u32), + "m" (*pu32)); +# else + __asm + { + mov eax, [u32] +# ifdef RT_ARCH_AMD64 + mov rdx, [pu32] + lock and [rdx], eax +# else + mov edx, [pu32] + lock and [edx], eax +# endif + } +# endif +} +#endif + + +/** + * Atomically And a signed 32-bit value, ordered. + * + * @param pi32 Pointer to the pointer variable to AND i32 with. + * @param i32 The value to AND *pi32 with. + */ +DECLINLINE(void) ASMAtomicAndS32(int32_t volatile *pi32, int32_t i32) +{ + ASMAtomicAndU32((uint32_t volatile *)pi32, (uint32_t)i32); +} + + +/** + * Atomically And an unsigned 64-bit value, ordered. + * + * @param pu64 Pointer to the pointer variable to AND u64 with. + * @param u64 The value to AND *pu64 with. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMAtomicAndU64(uint64_t volatile *pu64, uint64_t u64); +#else +DECLINLINE(void) ASMAtomicAndU64(uint64_t volatile *pu64, uint64_t u64) +{ +# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64) + _InterlockedAnd64((__int64 volatile *)pu64, u64); + +# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64) + __asm__ __volatile__("lock; andq %1, %0\n\t" + : "=m" (*pu64) + : "r" (u64), + "m" (*pu64)); +# else + for (;;) + { + uint64_t u64Old = ASMAtomicUoReadU64(pu64); + uint64_t u64New = u64Old & u64; + if (ASMAtomicCmpXchgU64(pu64, u64New, u64Old)) + break; + ASMNopPause(); + } +# endif +} +#endif + + +/** + * Atomically And a signed 64-bit value, ordered. + * + * @param pi64 Pointer to the pointer variable to AND i64 with. + * @param i64 The value to AND *pi64 with. + */ +DECLINLINE(void) ASMAtomicAndS64(int64_t volatile *pi64, int64_t i64) +{ + ASMAtomicAndU64((uint64_t volatile *)pi64, (uint64_t)i64); +} + + + +/** @def RT_ASM_PAGE_SIZE + * We try avoid dragging in iprt/param.h here. + * @internal + */ +#if defined(RT_ARCH_SPARC64) +# define RT_ASM_PAGE_SIZE 0x2000 +# if defined(PAGE_SIZE) && !defined(NT_INCLUDED) +# if PAGE_SIZE != 0x2000 +# error "PAGE_SIZE is not 0x2000!" +# endif +# endif +#else +# define RT_ASM_PAGE_SIZE 0x1000 +# if defined(PAGE_SIZE) && !defined(NT_INCLUDED) +# if PAGE_SIZE != 0x1000 +# error "PAGE_SIZE is not 0x1000!" +# endif +# endif +#endif + +/** + * Zeros a 4K memory page. + * + * @param pv Pointer to the memory block. This must be page aligned. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMMemZeroPage(volatile void *pv); +# else +DECLINLINE(void) ASMMemZeroPage(volatile void *pv) +{ +# if RT_INLINE_ASM_USES_INTRIN +# ifdef RT_ARCH_AMD64 + __stosq((unsigned __int64 *)pv, 0, RT_ASM_PAGE_SIZE / 8); +# else + __stosd((unsigned long *)pv, 0, RT_ASM_PAGE_SIZE / 4); +# endif + +# elif RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG uDummy; +# ifdef RT_ARCH_AMD64 + __asm__ __volatile__("rep stosq" + : "=D" (pv), + "=c" (uDummy) + : "0" (pv), + "c" (RT_ASM_PAGE_SIZE >> 3), + "a" (0) + : "memory"); +# else + __asm__ __volatile__("rep stosl" + : "=D" (pv), + "=c" (uDummy) + : "0" (pv), + "c" (RT_ASM_PAGE_SIZE >> 2), + "a" (0) + : "memory"); +# endif +# else + __asm + { +# ifdef RT_ARCH_AMD64 + xor rax, rax + mov ecx, 0200h + mov rdi, [pv] + rep stosq +# else + xor eax, eax + mov ecx, 0400h + mov edi, [pv] + rep stosd +# endif + } +# endif +} +# endif + + +/** + * Zeros a memory block with a 32-bit aligned size. + * + * @param pv Pointer to the memory block. + * @param cb Number of bytes in the block. This MUST be aligned on 32-bit! + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMMemZero32(volatile void *pv, size_t cb); +#else +DECLINLINE(void) ASMMemZero32(volatile void *pv, size_t cb) +{ +# if RT_INLINE_ASM_USES_INTRIN +# ifdef RT_ARCH_AMD64 + if (!(cb & 7)) + __stosq((unsigned __int64 *)pv, 0, cb / 8); + else +# endif + __stosd((unsigned long *)pv, 0, cb / 4); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rep stosl" + : "=D" (pv), + "=c" (cb) + : "0" (pv), + "1" (cb >> 2), + "a" (0) + : "memory"); +# else + __asm + { + xor eax, eax +# ifdef RT_ARCH_AMD64 + mov rcx, [cb] + shr rcx, 2 + mov rdi, [pv] +# else + mov ecx, [cb] + shr ecx, 2 + mov edi, [pv] +# endif + rep stosd + } +# endif +} +#endif + + +/** + * Fills a memory block with a 32-bit aligned size. + * + * @param pv Pointer to the memory block. + * @param cb Number of bytes in the block. This MUST be aligned on 32-bit! + * @param u32 The value to fill with. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMMemFill32(volatile void *pv, size_t cb, uint32_t u32); +#else +DECLINLINE(void) ASMMemFill32(volatile void *pv, size_t cb, uint32_t u32) +{ +# if RT_INLINE_ASM_USES_INTRIN +# ifdef RT_ARCH_AMD64 + if (!(cb & 7)) + __stosq((unsigned __int64 *)pv, RT_MAKE_U64(u32, u32), cb / 8); + else +# endif + __stosd((unsigned long *)pv, u32, cb / 4); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("rep stosl" + : "=D" (pv), + "=c" (cb) + : "0" (pv), + "1" (cb >> 2), + "a" (u32) + : "memory"); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rcx, [cb] + shr rcx, 2 + mov rdi, [pv] +# else + mov ecx, [cb] + shr ecx, 2 + mov edi, [pv] +# endif + mov eax, [u32] + rep stosd + } +# endif +} +#endif + + +/** + * Checks if a memory page is all zeros. + * + * @returns true / false. + * + * @param pvPage Pointer to the page. Must be aligned on 16 byte + * boundary + */ +DECLINLINE(bool) ASMMemIsZeroPage(void const *pvPage) +{ +# if 0 /*RT_INLINE_ASM_GNU_STYLE - this is actually slower... */ + union { RTCCUINTREG r; bool f; } uAX; + RTCCUINTREG xCX, xDI; + Assert(!((uintptr_t)pvPage & 15)); + __asm__ __volatile__("repe; " +# ifdef RT_ARCH_AMD64 + "scasq\n\t" +# else + "scasl\n\t" +# endif + "setnc %%al\n\t" + : "=&c" (xCX), + "=&D" (xDI), + "=&a" (uAX.r) + : "mr" (pvPage), +# ifdef RT_ARCH_AMD64 + "0" (RT_ASM_PAGE_SIZE/8), +# else + "0" (RT_ASM_PAGE_SIZE/4), +# endif + "1" (pvPage), + "2" (0)); + return uAX.f; +# else + uintptr_t const *puPtr = (uintptr_t const *)pvPage; + int cLeft = RT_ASM_PAGE_SIZE / sizeof(uintptr_t) / 8; + Assert(!((uintptr_t)pvPage & 15)); + for (;;) + { + if (puPtr[0]) return false; + if (puPtr[4]) return false; + + if (puPtr[2]) return false; + if (puPtr[6]) return false; + + if (puPtr[1]) return false; + if (puPtr[5]) return false; + + if (puPtr[3]) return false; + if (puPtr[7]) return false; + + if (!--cLeft) + return true; + puPtr += 8; + } + return true; +# endif +} + + +/** + * Checks if a memory block is filled with the specified byte. + * + * This is a sort of inverted memchr. + * + * @returns Pointer to the byte which doesn't equal u8. + * @returns NULL if all equal to u8. + * + * @param pv Pointer to the memory block. + * @param cb Number of bytes in the block. This MUST be aligned on 32-bit! + * @param u8 The value it's supposed to be filled with. + * + * @todo Fix name, it is a predicate function but it's not returning boolean! + */ +DECLINLINE(void *) ASMMemIsAll8(void const *pv, size_t cb, uint8_t u8) +{ +/** @todo rewrite this in inline assembly? */ + uint8_t const *pb = (uint8_t const *)pv; + for (; cb; cb--, pb++) + if (RT_UNLIKELY(*pb != u8)) + return (void *)pb; + return NULL; +} + + +/** + * Checks if a memory block is filled with the specified 32-bit value. + * + * This is a sort of inverted memchr. + * + * @returns Pointer to the first value which doesn't equal u32. + * @returns NULL if all equal to u32. + * + * @param pv Pointer to the memory block. + * @param cb Number of bytes in the block. This MUST be aligned on 32-bit! + * @param u32 The value it's supposed to be filled with. + * + * @todo Fix name, it is a predicate function but it's not returning boolean! + */ +DECLINLINE(uint32_t *) ASMMemIsAllU32(void const *pv, size_t cb, uint32_t u32) +{ +/** @todo rewrite this in inline assembly? */ + uint32_t const *pu32 = (uint32_t const *)pv; + for (; cb; cb -= 4, pu32++) + if (RT_UNLIKELY(*pu32 != u32)) + return (uint32_t *)pu32; + return NULL; +} + + +/** + * Probes a byte pointer for read access. + * + * While the function will not fault if the byte is not read accessible, + * the idea is to do this in a safe place like before acquiring locks + * and such like. + * + * Also, this functions guarantees that an eager compiler is not going + * to optimize the probing away. + * + * @param pvByte Pointer to the byte. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(uint8_t) ASMProbeReadByte(const void *pvByte); +#else +DECLINLINE(uint8_t) ASMProbeReadByte(const void *pvByte) +{ + /** @todo verify that the compiler actually doesn't optimize this away. (intel & gcc) */ + uint8_t u8; +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("movb (%1), %0\n\t" + : "=r" (u8) + : "r" (pvByte)); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pvByte] + mov al, [rax] +# else + mov eax, [pvByte] + mov al, [eax] +# endif + mov [u8], al + } +# endif + return u8; +} +#endif + +/** + * Probes a buffer for read access page by page. + * + * While the function will fault if the buffer is not fully read + * accessible, the idea is to do this in a safe place like before + * acquiring locks and such like. + * + * Also, this functions guarantees that an eager compiler is not going + * to optimize the probing away. + * + * @param pvBuf Pointer to the buffer. + * @param cbBuf The size of the buffer in bytes. Must be >= 1. + */ +DECLINLINE(void) ASMProbeReadBuffer(const void *pvBuf, size_t cbBuf) +{ + /** @todo verify that the compiler actually doesn't optimize this away. (intel & gcc) */ + /* the first byte */ + const uint8_t *pu8 = (const uint8_t *)pvBuf; + ASMProbeReadByte(pu8); + + /* the pages in between pages. */ + while (cbBuf > RT_ASM_PAGE_SIZE) + { + ASMProbeReadByte(pu8); + cbBuf -= RT_ASM_PAGE_SIZE; + pu8 += RT_ASM_PAGE_SIZE; + } + + /* the last byte */ + ASMProbeReadByte(pu8 + cbBuf - 1); +} + + + +/** @defgroup grp_inline_bits Bit Operations + * @{ + */ + + +/** + * Sets a bit in a bitmap. + * + * @param pvBitmap Pointer to the bitmap. This should be 32-bit aligned. + * @param iBit The bit to set. + * + * @remarks The 32-bit aligning of pvBitmap is not a strict requirement. + * However, doing so will yield better performance as well as avoiding + * traps accessing the last bits in the bitmap. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMBitSet(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(void) ASMBitSet(volatile void *pvBitmap, int32_t iBit) +{ +# if RT_INLINE_ASM_USES_INTRIN + _bittestandset((long *)pvBitmap, iBit); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("btsl %1, %0" + : "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + mov edx, [iBit] + bts [rax], edx +# else + mov eax, [pvBitmap] + mov edx, [iBit] + bts [eax], edx +# endif + } +# endif +} +#endif + + +/** + * Atomically sets a bit in a bitmap, ordered. + * + * @param pvBitmap Pointer to the bitmap. Must be 32-bit aligned, otherwise + * the memory access isn't atomic! + * @param iBit The bit to set. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMAtomicBitSet(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(void) ASMAtomicBitSet(volatile void *pvBitmap, int32_t iBit) +{ + AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap)); +# if RT_INLINE_ASM_USES_INTRIN + _interlockedbittestandset((long *)pvBitmap, iBit); +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; btsl %1, %0" + : "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + mov edx, [iBit] + lock bts [rax], edx +# else + mov eax, [pvBitmap] + mov edx, [iBit] + lock bts [eax], edx +# endif + } +# endif +} +#endif + + +/** + * Clears a bit in a bitmap. + * + * @param pvBitmap Pointer to the bitmap. + * @param iBit The bit to clear. + * + * @remarks The 32-bit aligning of pvBitmap is not a strict requirement. + * However, doing so will yield better performance as well as avoiding + * traps accessing the last bits in the bitmap. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMBitClear(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(void) ASMBitClear(volatile void *pvBitmap, int32_t iBit) +{ +# if RT_INLINE_ASM_USES_INTRIN + _bittestandreset((long *)pvBitmap, iBit); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("btrl %1, %0" + : "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + mov edx, [iBit] + btr [rax], edx +# else + mov eax, [pvBitmap] + mov edx, [iBit] + btr [eax], edx +# endif + } +# endif +} +#endif + + +/** + * Atomically clears a bit in a bitmap, ordered. + * + * @param pvBitmap Pointer to the bitmap. Must be 32-bit aligned, otherwise + * the memory access isn't atomic! + * @param iBit The bit to toggle set. + * @remarks No memory barrier, take care on smp. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMAtomicBitClear(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(void) ASMAtomicBitClear(volatile void *pvBitmap, int32_t iBit) +{ + AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap)); +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; btrl %1, %0" + : "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + mov edx, [iBit] + lock btr [rax], edx +# else + mov eax, [pvBitmap] + mov edx, [iBit] + lock btr [eax], edx +# endif + } +# endif +} +#endif + + +/** + * Toggles a bit in a bitmap. + * + * @param pvBitmap Pointer to the bitmap. + * @param iBit The bit to toggle. + * + * @remarks The 32-bit aligning of pvBitmap is not a strict requirement. + * However, doing so will yield better performance as well as avoiding + * traps accessing the last bits in the bitmap. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(void) ASMBitToggle(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(void) ASMBitToggle(volatile void *pvBitmap, int32_t iBit) +{ +# if RT_INLINE_ASM_USES_INTRIN + _bittestandcomplement((long *)pvBitmap, iBit); +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("btcl %1, %0" + : "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + mov edx, [iBit] + btc [rax], edx +# else + mov eax, [pvBitmap] + mov edx, [iBit] + btc [eax], edx +# endif + } +# endif +} +#endif + + +/** + * Atomically toggles a bit in a bitmap, ordered. + * + * @param pvBitmap Pointer to the bitmap. Must be 32-bit aligned, otherwise + * the memory access isn't atomic! + * @param iBit The bit to test and set. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(void) ASMAtomicBitToggle(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(void) ASMAtomicBitToggle(volatile void *pvBitmap, int32_t iBit) +{ + AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap)); +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; btcl %1, %0" + : "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + mov edx, [iBit] + lock btc [rax], edx +# else + mov eax, [pvBitmap] + mov edx, [iBit] + lock btc [eax], edx +# endif + } +# endif +} +#endif + + +/** + * Tests and sets a bit in a bitmap. + * + * @returns true if the bit was set. + * @returns false if the bit was clear. + * + * @param pvBitmap Pointer to the bitmap. + * @param iBit The bit to test and set. + * + * @remarks The 32-bit aligning of pvBitmap is not a strict requirement. + * However, doing so will yield better performance as well as avoiding + * traps accessing the last bits in the bitmap. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(bool) ASMBitTestAndSet(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(bool) ASMBitTestAndSet(volatile void *pvBitmap, int32_t iBit) +{ + union { bool f; uint32_t u32; uint8_t u8; } rc; +# if RT_INLINE_ASM_USES_INTRIN + rc.u8 = _bittestandset((long *)pvBitmap, iBit); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("btsl %2, %1\n\t" + "setc %b0\n\t" + "andl $1, %0\n\t" + : "=q" (rc.u32), + "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { + mov edx, [iBit] +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + bts [rax], edx +# else + mov eax, [pvBitmap] + bts [eax], edx +# endif + setc al + and eax, 1 + mov [rc.u32], eax + } +# endif + return rc.f; +} +#endif + + +/** + * Atomically tests and sets a bit in a bitmap, ordered. + * + * @returns true if the bit was set. + * @returns false if the bit was clear. + * + * @param pvBitmap Pointer to the bitmap. Must be 32-bit aligned, otherwise + * the memory access isn't atomic! + * @param iBit The bit to set. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(bool) ASMAtomicBitTestAndSet(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(bool) ASMAtomicBitTestAndSet(volatile void *pvBitmap, int32_t iBit) +{ + union { bool f; uint32_t u32; uint8_t u8; } rc; + AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap)); +# if RT_INLINE_ASM_USES_INTRIN + rc.u8 = _interlockedbittestandset((long *)pvBitmap, iBit); +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; btsl %2, %1\n\t" + "setc %b0\n\t" + "andl $1, %0\n\t" + : "=q" (rc.u32), + "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { + mov edx, [iBit] +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + lock bts [rax], edx +# else + mov eax, [pvBitmap] + lock bts [eax], edx +# endif + setc al + and eax, 1 + mov [rc.u32], eax + } +# endif + return rc.f; +} +#endif + + +/** + * Tests and clears a bit in a bitmap. + * + * @returns true if the bit was set. + * @returns false if the bit was clear. + * + * @param pvBitmap Pointer to the bitmap. + * @param iBit The bit to test and clear. + * + * @remarks The 32-bit aligning of pvBitmap is not a strict requirement. + * However, doing so will yield better performance as well as avoiding + * traps accessing the last bits in the bitmap. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(bool) ASMBitTestAndClear(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(bool) ASMBitTestAndClear(volatile void *pvBitmap, int32_t iBit) +{ + union { bool f; uint32_t u32; uint8_t u8; } rc; +# if RT_INLINE_ASM_USES_INTRIN + rc.u8 = _bittestandreset((long *)pvBitmap, iBit); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("btrl %2, %1\n\t" + "setc %b0\n\t" + "andl $1, %0\n\t" + : "=q" (rc.u32), + "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { + mov edx, [iBit] +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + btr [rax], edx +# else + mov eax, [pvBitmap] + btr [eax], edx +# endif + setc al + and eax, 1 + mov [rc.u32], eax + } +# endif + return rc.f; +} +#endif + + +/** + * Atomically tests and clears a bit in a bitmap, ordered. + * + * @returns true if the bit was set. + * @returns false if the bit was clear. + * + * @param pvBitmap Pointer to the bitmap. Must be 32-bit aligned, otherwise + * the memory access isn't atomic! + * @param iBit The bit to test and clear. + * + * @remarks No memory barrier, take care on smp. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(bool) ASMAtomicBitTestAndClear(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(bool) ASMAtomicBitTestAndClear(volatile void *pvBitmap, int32_t iBit) +{ + union { bool f; uint32_t u32; uint8_t u8; } rc; + AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap)); +# if RT_INLINE_ASM_USES_INTRIN + rc.u8 = _interlockedbittestandreset((long *)pvBitmap, iBit); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; btrl %2, %1\n\t" + "setc %b0\n\t" + "andl $1, %0\n\t" + : "=q" (rc.u32), + "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { + mov edx, [iBit] +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + lock btr [rax], edx +# else + mov eax, [pvBitmap] + lock btr [eax], edx +# endif + setc al + and eax, 1 + mov [rc.u32], eax + } +# endif + return rc.f; +} +#endif + + +/** + * Tests and toggles a bit in a bitmap. + * + * @returns true if the bit was set. + * @returns false if the bit was clear. + * + * @param pvBitmap Pointer to the bitmap. + * @param iBit The bit to test and toggle. + * + * @remarks The 32-bit aligning of pvBitmap is not a strict requirement. + * However, doing so will yield better performance as well as avoiding + * traps accessing the last bits in the bitmap. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(bool) ASMBitTestAndToggle(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(bool) ASMBitTestAndToggle(volatile void *pvBitmap, int32_t iBit) +{ + union { bool f; uint32_t u32; uint8_t u8; } rc; +# if RT_INLINE_ASM_USES_INTRIN + rc.u8 = _bittestandcomplement((long *)pvBitmap, iBit); + +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("btcl %2, %1\n\t" + "setc %b0\n\t" + "andl $1, %0\n\t" + : "=q" (rc.u32), + "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { + mov edx, [iBit] +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + btc [rax], edx +# else + mov eax, [pvBitmap] + btc [eax], edx +# endif + setc al + and eax, 1 + mov [rc.u32], eax + } +# endif + return rc.f; +} +#endif + + +/** + * Atomically tests and toggles a bit in a bitmap, ordered. + * + * @returns true if the bit was set. + * @returns false if the bit was clear. + * + * @param pvBitmap Pointer to the bitmap. Must be 32-bit aligned, otherwise + * the memory access isn't atomic! + * @param iBit The bit to test and toggle. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(bool) ASMAtomicBitTestAndToggle(volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(bool) ASMAtomicBitTestAndToggle(volatile void *pvBitmap, int32_t iBit) +{ + union { bool f; uint32_t u32; uint8_t u8; } rc; + AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap)); +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("lock; btcl %2, %1\n\t" + "setc %b0\n\t" + "andl $1, %0\n\t" + : "=q" (rc.u32), + "=m" (*(volatile long *)pvBitmap) + : "Ir" (iBit), + "m" (*(volatile long *)pvBitmap) + : "memory"); +# else + __asm + { + mov edx, [iBit] +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + lock btc [rax], edx +# else + mov eax, [pvBitmap] + lock btc [eax], edx +# endif + setc al + and eax, 1 + mov [rc.u32], eax + } +# endif + return rc.f; +} +#endif + + +/** + * Tests if a bit in a bitmap is set. + * + * @returns true if the bit is set. + * @returns false if the bit is clear. + * + * @param pvBitmap Pointer to the bitmap. + * @param iBit The bit to test. + * + * @remarks The 32-bit aligning of pvBitmap is not a strict requirement. + * However, doing so will yield better performance as well as avoiding + * traps accessing the last bits in the bitmap. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(bool) ASMBitTest(const volatile void *pvBitmap, int32_t iBit); +#else +DECLINLINE(bool) ASMBitTest(const volatile void *pvBitmap, int32_t iBit) +{ + union { bool f; uint32_t u32; uint8_t u8; } rc; +# if RT_INLINE_ASM_USES_INTRIN + rc.u32 = _bittest((long *)pvBitmap, iBit); +# elif RT_INLINE_ASM_GNU_STYLE + + __asm__ __volatile__("btl %2, %1\n\t" + "setc %b0\n\t" + "andl $1, %0\n\t" + : "=q" (rc.u32) + : "m" (*(const volatile long *)pvBitmap), + "Ir" (iBit) + : "memory"); +# else + __asm + { + mov edx, [iBit] +# ifdef RT_ARCH_AMD64 + mov rax, [pvBitmap] + bt [rax], edx +# else + mov eax, [pvBitmap] + bt [eax], edx +# endif + setc al + and eax, 1 + mov [rc.u32], eax + } +# endif + return rc.f; +} +#endif + + +/** + * Clears a bit range within a bitmap. + * + * @param pvBitmap Pointer to the bitmap. + * @param iBitStart The First bit to clear. + * @param iBitEnd The first bit not to clear. + */ +DECLINLINE(void) ASMBitClearRange(volatile void *pvBitmap, int32_t iBitStart, int32_t iBitEnd) +{ + if (iBitStart < iBitEnd) + { + volatile uint32_t *pu32 = (volatile uint32_t *)pvBitmap + (iBitStart >> 5); + int iStart = iBitStart & ~31; + int iEnd = iBitEnd & ~31; + if (iStart == iEnd) + *pu32 &= ((1 << (iBitStart & 31)) - 1) | ~((1 << (iBitEnd & 31)) - 1); + else + { + /* bits in first dword. */ + if (iBitStart & 31) + { + *pu32 &= (1 << (iBitStart & 31)) - 1; + pu32++; + iBitStart = iStart + 32; + } + + /* whole dword. */ + if (iBitStart != iEnd) + ASMMemZero32(pu32, (iEnd - iBitStart) >> 3); + + /* bits in last dword. */ + if (iBitEnd & 31) + { + pu32 = (volatile uint32_t *)pvBitmap + (iBitEnd >> 5); + *pu32 &= ~((1 << (iBitEnd & 31)) - 1); + } + } + } +} + + +/** + * Sets a bit range within a bitmap. + * + * @param pvBitmap Pointer to the bitmap. + * @param iBitStart The First bit to set. + * @param iBitEnd The first bit not to set. + */ +DECLINLINE(void) ASMBitSetRange(volatile void *pvBitmap, int32_t iBitStart, int32_t iBitEnd) +{ + if (iBitStart < iBitEnd) + { + volatile uint32_t *pu32 = (volatile uint32_t *)pvBitmap + (iBitStart >> 5); + int iStart = iBitStart & ~31; + int iEnd = iBitEnd & ~31; + if (iStart == iEnd) + *pu32 |= ((1 << (iBitEnd - iBitStart)) - 1) << iBitStart; + else + { + /* bits in first dword. */ + if (iBitStart & 31) + { + *pu32 |= ~((1 << (iBitStart & 31)) - 1); + pu32++; + iBitStart = iStart + 32; + } + + /* whole dword. */ + if (iBitStart != iEnd) + ASMMemFill32(pu32, (iEnd - iBitStart) >> 3, ~UINT32_C(0)); + + /* bits in last dword. */ + if (iBitEnd & 31) + { + pu32 = (volatile uint32_t *)pvBitmap + (iBitEnd >> 5); + *pu32 |= (1 << (iBitEnd & 31)) - 1; + } + } + } +} + + +/** + * Finds the first clear bit in a bitmap. + * + * @returns Index of the first zero bit. + * @returns -1 if no clear bit was found. + * @param pvBitmap Pointer to the bitmap. + * @param cBits The number of bits in the bitmap. Multiple of 32. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(int) ASMBitFirstClear(const volatile void *pvBitmap, uint32_t cBits); +#else +DECLINLINE(int) ASMBitFirstClear(const volatile void *pvBitmap, uint32_t cBits) +{ + if (cBits) + { + int32_t iBit; +# if RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG uEAX, uECX, uEDI; + cBits = RT_ALIGN_32(cBits, 32); + __asm__ __volatile__("repe; scasl\n\t" + "je 1f\n\t" +# ifdef RT_ARCH_AMD64 + "lea -4(%%rdi), %%rdi\n\t" + "xorl (%%rdi), %%eax\n\t" + "subq %5, %%rdi\n\t" +# else + "lea -4(%%edi), %%edi\n\t" + "xorl (%%edi), %%eax\n\t" + "subl %5, %%edi\n\t" +# endif + "shll $3, %%edi\n\t" + "bsfl %%eax, %%edx\n\t" + "addl %%edi, %%edx\n\t" + "1:\t\n" + : "=d" (iBit), + "=&c" (uECX), + "=&D" (uEDI), + "=&a" (uEAX) + : "0" (0xffffffff), + "mr" (pvBitmap), + "1" (cBits >> 5), + "2" (pvBitmap), + "3" (0xffffffff)); +# else + cBits = RT_ALIGN_32(cBits, 32); + __asm + { +# ifdef RT_ARCH_AMD64 + mov rdi, [pvBitmap] + mov rbx, rdi +# else + mov edi, [pvBitmap] + mov ebx, edi +# endif + mov edx, 0ffffffffh + mov eax, edx + mov ecx, [cBits] + shr ecx, 5 + repe scasd + je done + +# ifdef RT_ARCH_AMD64 + lea rdi, [rdi - 4] + xor eax, [rdi] + sub rdi, rbx +# else + lea edi, [edi - 4] + xor eax, [edi] + sub edi, ebx +# endif + shl edi, 3 + bsf edx, eax + add edx, edi + done: + mov [iBit], edx + } +# endif + return iBit; + } + return -1; +} +#endif + + +/** + * Finds the next clear bit in a bitmap. + * + * @returns Index of the first zero bit. + * @returns -1 if no clear bit was found. + * @param pvBitmap Pointer to the bitmap. + * @param cBits The number of bits in the bitmap. Multiple of 32. + * @param iBitPrev The bit returned from the last search. + * The search will start at iBitPrev + 1. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(int) ASMBitNextClear(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev); +#else +DECLINLINE(int) ASMBitNextClear(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev) +{ + const volatile uint32_t *pau32Bitmap = (const volatile uint32_t *)pvBitmap; + int iBit = ++iBitPrev & 31; + if (iBit) + { + /* + * Inspect the 32-bit word containing the unaligned bit. + */ + uint32_t u32 = ~pau32Bitmap[iBitPrev / 32] >> iBit; + +# if RT_INLINE_ASM_USES_INTRIN + unsigned long ulBit = 0; + if (_BitScanForward(&ulBit, u32)) + return ulBit + iBitPrev; +# else +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("bsf %1, %0\n\t" + "jnz 1f\n\t" + "movl $-1, %0\n\t" + "1:\n\t" + : "=r" (iBit) + : "r" (u32)); +# else + __asm + { + mov edx, [u32] + bsf eax, edx + jnz done + mov eax, 0ffffffffh + done: + mov [iBit], eax + } +# endif + if (iBit >= 0) + return iBit + iBitPrev; +# endif + + /* + * Skip ahead and see if there is anything left to search. + */ + iBitPrev |= 31; + iBitPrev++; + if (cBits <= (uint32_t)iBitPrev) + return -1; + } + + /* + * 32-bit aligned search, let ASMBitFirstClear do the dirty work. + */ + iBit = ASMBitFirstClear(&pau32Bitmap[iBitPrev / 32], cBits - iBitPrev); + if (iBit >= 0) + iBit += iBitPrev; + return iBit; +} +#endif + + +/** + * Finds the first set bit in a bitmap. + * + * @returns Index of the first set bit. + * @returns -1 if no clear bit was found. + * @param pvBitmap Pointer to the bitmap. + * @param cBits The number of bits in the bitmap. Multiple of 32. + */ +#if RT_INLINE_ASM_EXTERNAL +DECLASM(int) ASMBitFirstSet(const volatile void *pvBitmap, uint32_t cBits); +#else +DECLINLINE(int) ASMBitFirstSet(const volatile void *pvBitmap, uint32_t cBits) +{ + if (cBits) + { + int32_t iBit; +# if RT_INLINE_ASM_GNU_STYLE + RTCCUINTREG uEAX, uECX, uEDI; + cBits = RT_ALIGN_32(cBits, 32); + __asm__ __volatile__("repe; scasl\n\t" + "je 1f\n\t" +# ifdef RT_ARCH_AMD64 + "lea -4(%%rdi), %%rdi\n\t" + "movl (%%rdi), %%eax\n\t" + "subq %5, %%rdi\n\t" +# else + "lea -4(%%edi), %%edi\n\t" + "movl (%%edi), %%eax\n\t" + "subl %5, %%edi\n\t" +# endif + "shll $3, %%edi\n\t" + "bsfl %%eax, %%edx\n\t" + "addl %%edi, %%edx\n\t" + "1:\t\n" + : "=d" (iBit), + "=&c" (uECX), + "=&D" (uEDI), + "=&a" (uEAX) + : "0" (0xffffffff), + "mr" (pvBitmap), + "1" (cBits >> 5), + "2" (pvBitmap), + "3" (0)); +# else + cBits = RT_ALIGN_32(cBits, 32); + __asm + { +# ifdef RT_ARCH_AMD64 + mov rdi, [pvBitmap] + mov rbx, rdi +# else + mov edi, [pvBitmap] + mov ebx, edi +# endif + mov edx, 0ffffffffh + xor eax, eax + mov ecx, [cBits] + shr ecx, 5 + repe scasd + je done +# ifdef RT_ARCH_AMD64 + lea rdi, [rdi - 4] + mov eax, [rdi] + sub rdi, rbx +# else + lea edi, [edi - 4] + mov eax, [edi] + sub edi, ebx +# endif + shl edi, 3 + bsf edx, eax + add edx, edi + done: + mov [iBit], edx + } +# endif + return iBit; + } + return -1; +} +#endif + + +/** + * Finds the next set bit in a bitmap. + * + * @returns Index of the next set bit. + * @returns -1 if no set bit was found. + * @param pvBitmap Pointer to the bitmap. + * @param cBits The number of bits in the bitmap. Multiple of 32. + * @param iBitPrev The bit returned from the last search. + * The search will start at iBitPrev + 1. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(int) ASMBitNextSet(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev); +#else +DECLINLINE(int) ASMBitNextSet(const volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev) +{ + const volatile uint32_t *pau32Bitmap = (const volatile uint32_t *)pvBitmap; + int iBit = ++iBitPrev & 31; + if (iBit) + { + /* + * Inspect the 32-bit word containing the unaligned bit. + */ + uint32_t u32 = pau32Bitmap[iBitPrev / 32] >> iBit; + +# if RT_INLINE_ASM_USES_INTRIN + unsigned long ulBit = 0; + if (_BitScanForward(&ulBit, u32)) + return ulBit + iBitPrev; +# else +# if RT_INLINE_ASM_GNU_STYLE + __asm__ __volatile__("bsf %1, %0\n\t" + "jnz 1f\n\t" + "movl $-1, %0\n\t" + "1:\n\t" + : "=r" (iBit) + : "r" (u32)); +# else + __asm + { + mov edx, [u32] + bsf eax, edx + jnz done + mov eax, 0ffffffffh + done: + mov [iBit], eax + } +# endif + if (iBit >= 0) + return iBit + iBitPrev; +# endif + + /* + * Skip ahead and see if there is anything left to search. + */ + iBitPrev |= 31; + iBitPrev++; + if (cBits <= (uint32_t)iBitPrev) + return -1; + } + + /* + * 32-bit aligned search, let ASMBitFirstClear do the dirty work. + */ + iBit = ASMBitFirstSet(&pau32Bitmap[iBitPrev / 32], cBits - iBitPrev); + if (iBit >= 0) + iBit += iBitPrev; + return iBit; +} +#endif + + +/** + * Finds the first bit which is set in the given 32-bit integer. + * Bits are numbered from 1 (least significant) to 32. + * + * @returns index [1..32] of the first set bit. + * @returns 0 if all bits are cleared. + * @param u32 Integer to search for set bits. + * @remark Similar to ffs() in BSD. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(unsigned) ASMBitFirstSetU32(uint32_t u32); +#else +DECLINLINE(unsigned) ASMBitFirstSetU32(uint32_t u32) +{ +# if RT_INLINE_ASM_USES_INTRIN + unsigned long iBit; + if (_BitScanForward(&iBit, u32)) + iBit++; + else + iBit = 0; +# elif RT_INLINE_ASM_GNU_STYLE + uint32_t iBit; + __asm__ __volatile__("bsf %1, %0\n\t" + "jnz 1f\n\t" + "xorl %0, %0\n\t" + "jmp 2f\n" + "1:\n\t" + "incl %0\n" + "2:\n\t" + : "=r" (iBit) + : "rm" (u32)); +# else + uint32_t iBit; + _asm + { + bsf eax, [u32] + jnz found + xor eax, eax + jmp done + found: + inc eax + done: + mov [iBit], eax + } +# endif + return iBit; +} +#endif + + +/** + * Finds the first bit which is set in the given 32-bit integer. + * Bits are numbered from 1 (least significant) to 32. + * + * @returns index [1..32] of the first set bit. + * @returns 0 if all bits are cleared. + * @param i32 Integer to search for set bits. + * @remark Similar to ffs() in BSD. + */ +DECLINLINE(unsigned) ASMBitFirstSetS32(int32_t i32) +{ + return ASMBitFirstSetU32((uint32_t)i32); +} + + +/** + * Finds the last bit which is set in the given 32-bit integer. + * Bits are numbered from 1 (least significant) to 32. + * + * @returns index [1..32] of the last set bit. + * @returns 0 if all bits are cleared. + * @param u32 Integer to search for set bits. + * @remark Similar to fls() in BSD. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(unsigned) ASMBitLastSetU32(uint32_t u32); +#else +DECLINLINE(unsigned) ASMBitLastSetU32(uint32_t u32) +{ +# if RT_INLINE_ASM_USES_INTRIN + unsigned long iBit; + if (_BitScanReverse(&iBit, u32)) + iBit++; + else + iBit = 0; +# elif RT_INLINE_ASM_GNU_STYLE + uint32_t iBit; + __asm__ __volatile__("bsrl %1, %0\n\t" + "jnz 1f\n\t" + "xorl %0, %0\n\t" + "jmp 2f\n" + "1:\n\t" + "incl %0\n" + "2:\n\t" + : "=r" (iBit) + : "rm" (u32)); +# else + uint32_t iBit; + _asm + { + bsr eax, [u32] + jnz found + xor eax, eax + jmp done + found: + inc eax + done: + mov [iBit], eax + } +# endif + return iBit; +} +#endif + + +/** + * Finds the last bit which is set in the given 32-bit integer. + * Bits are numbered from 1 (least significant) to 32. + * + * @returns index [1..32] of the last set bit. + * @returns 0 if all bits are cleared. + * @param i32 Integer to search for set bits. + * @remark Similar to fls() in BSD. + */ +DECLINLINE(unsigned) ASMBitLastSetS32(int32_t i32) +{ + return ASMBitLastSetU32((uint32_t)i32); +} + +/** + * Reverse the byte order of the given 16-bit integer. + * + * @returns Revert + * @param u16 16-bit integer value. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint16_t) ASMByteSwapU16(uint16_t u16); +#else +DECLINLINE(uint16_t) ASMByteSwapU16(uint16_t u16) +{ +# if RT_INLINE_ASM_USES_INTRIN + u16 = _byteswap_ushort(u16); +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ ("rorw $8, %0" : "=r" (u16) : "0" (u16)); +# else + _asm + { + mov ax, [u16] + ror ax, 8 + mov [u16], ax + } +# endif + return u16; +} +#endif + + +/** + * Reverse the byte order of the given 32-bit integer. + * + * @returns Revert + * @param u32 32-bit integer value. + */ +#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN +DECLASM(uint32_t) ASMByteSwapU32(uint32_t u32); +#else +DECLINLINE(uint32_t) ASMByteSwapU32(uint32_t u32) +{ +# if RT_INLINE_ASM_USES_INTRIN + u32 = _byteswap_ulong(u32); +# elif RT_INLINE_ASM_GNU_STYLE + __asm__ ("bswapl %0" : "=r" (u32) : "0" (u32)); +# else + _asm + { + mov eax, [u32] + bswap eax + mov [u32], eax + } +# endif + return u32; +} +#endif + + +/** + * Reverse the byte order of the given 64-bit integer. + * + * @returns Revert + * @param u64 64-bit integer value. + */ +DECLINLINE(uint64_t) ASMByteSwapU64(uint64_t u64) +{ +#if defined(RT_ARCH_AMD64) && RT_INLINE_ASM_USES_INTRIN + u64 = _byteswap_uint64(u64); +#else + u64 = (uint64_t)ASMByteSwapU32((uint32_t)u64) << 32 + | (uint64_t)ASMByteSwapU32((uint32_t)(u64 >> 32)); +#endif + return u64; +} + + +/** @} */ + + +/** @} */ + +#endif + diff --git a/include/iprt/asmdefs.mac b/include/iprt/asmdefs.mac new file mode 100644 index 00000000..665c674b --- /dev/null +++ b/include/iprt/asmdefs.mac @@ -0,0 +1,774 @@ +;; @file +; IPRT - Global YASM/NASM macros +; + +; +; Copyright (C) 2006-2007 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. +; + +%ifndef ___iprt_asmdefs_mac +%define ___iprt_asmdefs_mac + + +;; @defgroup grp_rt_cdefs_size Size Constants +; (Of course, these are binary computer terms, not SI.) +; @{ +;; 1 K (Kilo) (1 024). +%define _1K 000000400h +;; 4 K (Kilo) (4 096). +%define _4K 000001000h +;; 32 K (Kilo) (32 678). +%define _32K 000008000h +;; 64 K (Kilo) (65 536). +%define _64K 000010000h +;; 128 K (Kilo) (131 072). +%define _128K 000020000h +;; 256 K (Kilo) (262 144). +%define _256K 000040000h +;; 512 K (Kilo) (524 288). +%define _512K 000080000h +;; 1 M (Mega) (1 048 576). +%define _1M 000100000h +;; 2 M (Mega) (2 097 152). +%define _2M 000200000h +;; 4 M (Mega) (4 194 304). +%define _4M 000400000h +;; 1 G (Giga) (1 073 741 824). +%define _1G 040000000h +;; 2 G (Giga) (2 147 483 648). +%define _2G 00000000080000000h +;; 4 G (Giga) (4 294 967 296). +%define _4G 00000000100000000h +;; 1 T (Tera) (1 099 511 627 776). +%define _1T 00000010000000000h +;; 1 P (Peta) (1 125 899 906 842 624). +%define _1P 00004000000000000h +;; 1 E (Exa) (1 152 921 504 606 846 976). +%define _1E 01000000000000000h +;; 2 E (Exa) (2 305 843 009 213 693 952). +%define _2E 02000000000000000h +;; @} + + +;; +; Make the mask for the given bit. +%define RT_BIT(bit) (1 << bit) + +;; +; Align code, pad with INT3. +%define ALIGNCODE(alignment) align alignment, db 0cch + +;; +; Align data, pad with ZEROs. +%define ALIGNDATA(alignment) align alignment, db 0 + +;; +; Align BSS, pad with ZEROs. +%define ALIGNBSS(alignment) align alignment, resb 1 + +;; +; NAME_OVERLOAD can be defined by a .asm module to modify all the +; names created using the name macros in this files. +; This is handy when you've got some kind of template code. +%ifndef NAME_OVERLOAD + %define NAME_OVERLOAD(name) name +%endif + +;; +; Mangles the given name so it can be referenced using DECLASM() in the +; C/C++ world. +%ifdef RT_ARCH_X86 + %ifdef RT_OS_OS2 + %define NAME(name) _ %+ NAME_OVERLOAD(name) + %endif + %ifdef RT_OS_WINDOWS + %define NAME(name) _ %+ NAME_OVERLOAD(name) + %endif +%endif +%ifdef RT_OS_DARWIN + %define NAME(name) _ %+ NAME_OVERLOAD(name) +%endif +%ifndef NAME + %define NAME(name) NAME_OVERLOAD(name) +%endif + +;; +; Mangles the given C name so it will _import_ the right symbol. +%ifdef ASM_FORMAT_PE +%define IMPNAME(name) __imp_ %+ NAME(name) +%else +%define IMPNAME(name) NAME(name) +%endif + +;; +; Gets the pointer to an imported object. +%ifdef ASM_FORMAT_PE + %ifdef RT_ARCH_AMD64 + %define IMP(name) qword [IMPNAME(name) wrt rip] + %else + %define IMP(name) dword [IMPNAME(name)] + %endif +%else + %define IMP(name) IMPNAME(name) +%endif + +;; +; Gets the pointer to an imported object, version 2. +%ifdef ASM_FORMAT_PE + %ifdef RT_ARCH_AMD64 + %define IMP2(name) qword [IMPNAME(name) wrt rip] + %else + %define IMP2(name) dword [IMPNAME(name)] + %endif +%else + %ifdef RT_ARCH_AMD64 + %define IMP2(name) IMPNAME(name) wrt rip + %else + %define IMP2(name) IMPNAME(name) + %endif +%endif + + + +;; +; Global marker which is DECLASM() compatible. +%macro GLOBALNAME 1, +%ifndef ASM_FORMAT_BIN +global NAME(%1) +%endif +NAME(%1): +%endmacro + +;; +; Global exported marker which is DECLASM() compatible. +%macro EXPORTEDNAME 1, + %ifdef ASM_FORMAT_PE + export %1=NAME(%1) + %endif + %ifdef __NASM__ + %ifdef ASM_FORMAT_OMF + export NAME(%1) NAME(%1) + %endif +%endif +GLOBALNAME %1 +%endmacro + +;; +; Global marker which is DECLASM() compatible. +%macro GLOBALNAME_EX 2, +%ifndef ASM_FORMAT_BIN + %ifdef ASM_FORMAT_ELF +global NAME(%1):%2 + %else +global NAME(%1) + %endif +%endif +NAME(%1): +%endmacro + +;; +; Global exported marker which is DECLASM() compatible. +%macro EXPORTEDNAME_EX 2, + %ifdef ASM_FORMAT_PE + export %1=NAME(%1) + %endif + %ifdef __NASM__ + %ifdef ASM_FORMAT_OMF + export NAME(%1) NAME(%1) + %endif +%endif +GLOBALNAME_EX %1, %2 +%endmacro + +;; +; Begins a C callable procedure. +%macro BEGINPROC 1 +GLOBALNAME_EX %1, function hidden +%endmacro + +;; +; Begins a C callable exported procedure. +%macro BEGINPROC_EXPORTED 1 +EXPORTEDNAME_EX %1, function +%endmacro + +;; +; Ends a C callable procedure. +%macro ENDPROC 1 +GLOBALNAME_EX %1 %+ _EndProc, function hidden +%ifdef ASM_FORMAT_ELF +size NAME(%1) NAME(%1 %+ _EndProc) - NAME(%1) +size NAME(%1 %+ _EndProc) 0 +%endif + db 0xCC, 0xCC, 0xCC, 0xCC +%endmacro + + +; +; Do OMF and Mach-O/Yasm segment definitions +; +; Both format requires this to get the segment order right, in the Mach-O/Yasm case +; it's only to make sure the .bss section ends up last (it's not declared here). +; +%ifdef ASM_FORMAT_OMF + + ; 16-bit segments first (OMF / OS/2 specific). + %ifdef RT_INCL_16BIT_SEGMENTS + segment DATA16 public CLASS=FAR_DATA align=16 use16 + segment DATA16_INIT public CLASS=FAR_DATA align=16 use16 + group DGROUP16 DATA16 DATA16_INIT + + ;; + ; Begins 16-bit data + %macro BEGINDATA16 0 + segment DATA16 + %endmacro + + ;; + ; Begins 16-bit init data + %macro BEGINDATA16INIT 0 + segment DATA16_INIT + %endmacro + + segment CODE16 public CLASS=FAR_CODE align=16 use16 + segment CODE16_INIT public CLASS=FAR_CODE align=16 use16 + group CGROUP16 CODE16 CODE16_INIT + + ;; + ; Begins 16-bit code + %macro BEGINCODE16 0 + segment CODE16 + %endmacro + + ;; + ; Begins 16-bit init code + %macro BEGINCODE16INIT 0 + segment CODE16_INIT + %endmacro + + %endif + + ; 32-bit segments. + segment TEXT32 public CLASS=CODE align=16 use32 flat + segment DATA32 public CLASS=DATA align=16 use32 flat + segment BSS32 public CLASS=BSS align=16 use32 flat + + ; Make the TEXT32 segment default. + segment TEXT32 +%endif + +%ifdef ASM_FORMAT_MACHO + %ifdef __YASM__ + [section .text] + [section .data] + %endif +%endif + + +;; +; Begins code +%ifdef ASM_FORMAT_OMF + %macro BEGINCODE 0 + segment TEXT32 + %endmacro +%else +%macro BEGINCODE 0 +[section .text] +%endmacro +%endif + +;; +; Begins constant (read-only) data +; +; @remarks This is mapped to the CODE section/segment when there isn't +; any dedicated const section/segment. (There is code that +; assumes this, so don't try change it.) +%ifdef ASM_FORMAT_OMF + %macro BEGINCONST 0 + segment TEXT32 + %endmacro +%else + %macro BEGINCONST 0 + %ifdef ASM_FORMAT_MACHO ;; @todo check the other guys too. + [section .rodata] + %else + [section .text] + %endif + %endmacro +%endif + +;; +; Begins initialized data +%ifdef ASM_FORMAT_OMF + %macro BEGINDATA 0 + segment DATA32 + %endmacro +%else +%macro BEGINDATA 0 +[section .data] +%endmacro +%endif + +;; +; Begins uninitialized data +%ifdef ASM_FORMAT_OMF + %macro BEGINBSS 0 + segment BSS32 + %endmacro +%else +%macro BEGINBSS 0 +[section .bss] +%endmacro +%endif + + + +;; @def ARCH_BITS +; Defines the bit count of the current context. +%ifndef ARCH_BITS + %ifdef RT_ARCH_AMD64 + %define ARCH_BITS 64 + %else + %define ARCH_BITS 32 + %endif +%endif + +;; @def HC_ARCH_BITS +; Defines the host architechture bit count. +%ifndef HC_ARCH_BITS + %ifndef IN_RC + %define HC_ARCH_BITS ARCH_BITS + %else + %define HC_ARCH_BITS 32 + %endif +%endif + +;; @def R3_ARCH_BITS +; Defines the host ring-3 architechture bit count. +%ifndef R3_ARCH_BITS + %ifdef IN_RING3 + %define R3_ARCH_BITS ARCH_BITS + %else + %define R3_ARCH_BITS HC_ARCH_BITS + %endif +%endif + +;; @def R0_ARCH_BITS +; Defines the host ring-0 architechture bit count. +%ifndef R0_ARCH_BITS + %ifdef IN_RING0 + %define R0_ARCH_BITS ARCH_BITS + %else + %define R0_ARCH_BITS HC_ARCH_BITS + %endif +%endif + +;; @def GC_ARCH_BITS +; Defines the guest architechture bit count. +%ifndef GC_ARCH_BITS + %ifdef IN_RC + %define GC_ARCH_BITS ARCH_BITS + %else + %define GC_ARCH_BITS 32 + %endif +%endif + + + +;; @def RTHCPTR_DEF +; The pesudo-instruction used to declare an initialized pointer variable in the host context. +%if HC_ARCH_BITS == 64 + %define RTHCPTR_DEF dq +%else + %define RTHCPTR_DEF dd +%endif + +;; @def RTHCPTR_RES +; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer +; variable of the host context. +%if HC_ARCH_BITS == 64 + %define RTHCPTR_RES resq +%else + %define RTHCPTR_RES resd +%endif + +;; @def RTHCPTR_PRE +; The memory operand prefix used for a pointer in the host context. +%if HC_ARCH_BITS == 64 + %define RTHCPTR_PRE qword +%else + %define RTHCPTR_PRE dword +%endif + +;; @def RTHCPTR_CB +; The size in bytes of a pointer in the host context. +%if HC_ARCH_BITS == 64 + %define RTHCPTR_CB 8 +%else + %define RTHCPTR_CB 4 +%endif + + + +;; @def RTR0PTR_DEF +; The pesudo-instruction used to declare an initialized pointer variable in the ring-0 host context. +%if R0_ARCH_BITS == 64 + %define RTR0PTR_DEF dq +%else + %define RTR0PTR_DEF dd +%endif + +;; @def RTR0PTR_RES +; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer +; variable of the ring-0 host context. +%if R0_ARCH_BITS == 64 + %define RTR0PTR_RES resq +%else + %define RTR0PTR_RES resd +%endif + +;; @def RTR0PTR_PRE +; The memory operand prefix used for a pointer in the ring-0 host context. +%if R0_ARCH_BITS == 64 + %define RTR0PTR_PRE qword +%else + %define RTR0PTR_PRE dword +%endif + +;; @def RTR0PTR_CB +; The size in bytes of a pointer in the ring-0 host context. +%if R0_ARCH_BITS == 64 + %define RTR0PTR_CB 8 +%else + %define RTR0PTR_CB 4 +%endif + + + +;; @def RTR3PTR_DEF +; The pesudo-instruction used to declare an initialized pointer variable in the ring-3 host context. +%if R3_ARCH_BITS == 64 + %define RTR3PTR_DEF dq +%else + %define RTR3PTR_DEF dd +%endif + +;; @def RTR3PTR_RES +; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer +; variable of the ring-3 host context. +%if R3_ARCH_BITS == 64 + %define RTR3PTR_RES resq +%else + %define RTR3PTR_RES resd +%endif + +;; @def RTR3PTR_PRE +; The memory operand prefix used for a pointer in the ring-3 host context. +%if R3_ARCH_BITS == 64 + %define RTR3PTR_PRE qword +%else + %define RTR3PTR_PRE dword +%endif + +;; @def RTR3PTR_CB +; The size in bytes of a pointer in the ring-3 host context. +%if R3_ARCH_BITS == 64 + %define RTR3PTR_CB 8 +%else + %define RTR3PTR_CB 4 +%endif + + + +;; @def RTGCPTR_DEF +; The pesudo-instruction used to declare an initialized pointer variable in the guest context. +%if GC_ARCH_BITS == 64 + %define RTGCPTR_DEF dq +%else + %define RTGCPTR_DEF dd +%endif + +;; @def RTGCPTR_RES +; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer +; variable of the guest context. +%if GC_ARCH_BITS == 64 + %define RTGCPTR_RES resq +%else + %define RTGCPTR_RES resd +%endif + +%define RTGCPTR32_RES resd +%define RTGCPTR64_RES resq + +;; @def RTGCPTR_PRE +; The memory operand prefix used for a pointer in the guest context. +%if GC_ARCH_BITS == 64 + %define RTGCPTR_PRE qword +%else + %define RTGCPTR_PRE dword +%endif + +;; @def RTGCPTR_CB +; The size in bytes of a pointer in the guest context. +%if GC_ARCH_BITS == 64 + %define RTGCPTR_CB 8 +%else + %define RTGCPTR_CB 4 +%endif + + +;; @def RTRCPTR_DEF +; The pesudo-instruction used to declare an initialized pointer variable in the raw mode context. +%define RTRCPTR_DEF dd + +;; @def RTRCPTR_RES +; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer +; variable of the raw mode context. +%define RTRCPTR_RES resd + +;; @def RTRCPTR_PRE +; The memory operand prefix used for a pointer in the raw mode context. +%define RTRCPTR_PRE dword + +;; @def RTRCPTR_CB +; The size in bytes of a pointer in the raw mode context. +%define RTRCPTR_CB 4 + + +;; @def RT_CCPTR_DEF +; The pesudo-instruction used to declare an initialized pointer variable in the current context. + +;; @def RT_CCPTR_RES +; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer +; variable of the current context. + +;; @def RT_CCPTR_PRE +; The memory operand prefix used for a pointer in the current context. + +;; @def RT_CCPTR_CB +; The size in bytes of a pointer in the current context. + +%ifdef IN_RC + %define RTCCPTR_DEF RTRCPTR_DEF + %define RTCCPTR_RES RTRCPTR_RES + %define RTCCPTR_PRE RTRCPTR_PRE + %define RTCCPTR_CB RTRCPTR_CB +%else + %ifdef IN_RING0 + %define RTCCPTR_DEF RTR0PTR_DEF + %define RTCCPTR_RES RTR0PTR_RES + %define RTCCPTR_PRE RTR0PTR_PRE + %define RTCCPTR_CB RTR0PTR_CB + %else + %define RTCCPTR_DEF RTR3PTR_DEF + %define RTCCPTR_RES RTR3PTR_RES + %define RTCCPTR_PRE RTR3PTR_PRE + %define RTCCPTR_CB RTR3PTR_CB + %endif +%endif + + + +;; @def RTHCPHYS_DEF +; The pesudo-instruction used to declare an initialized host physical address. +%define RTHCPHYS_DEF dq + +;; @def RTHCPTR_RES +; The pesudo-instruction used to declare (=reserve space for) an uninitialized +; host physical address variable +%define RTHCPHYS_RES resq + +;; @def RTHCPTR_PRE +; The memory operand prefix used for a host physical address. +%define RTHCPHYS_PRE qword + +;; @def RTHCPHYS_CB +; The size in bytes of a host physical address. +%define RTHCPHYS_CB 8 + + + +;; @def RTGCPHYS_DEF +; The pesudo-instruction used to declare an initialized guest physical address. +%define RTGCPHYS_DEF dq + +;; @def RTGCPHYS_RES +; The pesudo-instruction used to declare (=reserve space for) an uninitialized +; guest physical address variable +%define RTGCPHYS_RES resq + +;; @def RTGCPTR_PRE +; The memory operand prefix used for a guest physical address. +%define RTGCPHYS_PRE qword + +;; @def RTGCPHYS_CB +; The size in bytes of a guest physical address. +%define RTGCPHYS_CB 8 + + + +;; +; The size of the long double C/C++ type. +; On 32-bit Darwin this is 16 bytes, on L4, Linux, OS/2 and Windows +; it's 12 bytes. +; @todo figure out what 64-bit Windows does (I don't recall right now). +%ifdef RT_ARCH_X86 + %ifdef RT_OS_DARWIN + %define RTLRD_CB 16 + %else + %define RTLRD_CB 12 + %endif +%else + %define RTLRD_CB 16 +%endif + + + +;; @def ASM_CALL64_GCC +; Indicates that we're using the GCC 64-bit calling convention. +; @see @ref sec_vboxrem_amd64_compare (in VBoxREMWrapper.cpp) for an ABI description. + +;; @def ASM_CALL64_MSC +; Indicates that we're using the Microsoft 64-bit calling convention (fastcall on steroids). +; @see @ref sec_vboxrem_amd64_compare (in VBoxREMWrapper.cpp) for an ABI description. + +; Note: On X86 we're using cdecl unconditionally. There is not yet any common +; calling convention on AMD64, that's why we need to support two different ones.) + +%ifdef RT_ARCH_AMD64 + %ifndef ASM_CALL64_GCC + %ifndef ASM_CALL64_MSC + ; define it based on the object format. + %ifdef ASM_FORMAT_PE + %define ASM_CALL64_MSC + %else + %define ASM_CALL64_GCC + %endif + %endif + %else + ; sanity check. + %ifdef ASM_CALL64_MSC + %error "Only one of the ASM_CALL64_* defines should be defined!" + %endif + %endif +%endif + + +;; @def RT_NOCRT +; Symbol name wrapper for the No-CRT bits. +; +; In order to coexist in the same process as other CRTs, we need to +; decorate the symbols such that they don't conflict the ones in the +; other CRTs. The result of such conflicts / duplicate symbols can +; confuse the dynamic loader on unix like systems. +; +; @remark Always feed the name to this macro first and then pass the result +; on to the next *NAME* macro. +; +%ifndef RT_WITHOUT_NOCRT_WRAPPERS + %define RT_NOCRT(name) nocrt_ %+ name +%else + %define RT_NOCRT(name) name +%endif + +;; @def RT_NOCRT_BEGINPROC +; Starts a NOCRT procedure, taking care of name wrapping and aliasing. +; +; Aliasing (weak ones, if supported) will be created when RT_WITH_NOCRT_ALIASES +; is defined and RT_WITHOUT_NOCRT_WRAPPERS isn't. +; +%macro RT_NOCRT_BEGINPROC 1 +%ifdef RT_WITH_NOCRT_ALIASES +BEGINPROC RT_NOCRT(%1) +%ifdef ASM_FORMAT_ELF +global NAME(%1) +weak NAME(%1) +NAME(%1): +%else +GLOBALNAME %1 +%endif +%else ; !RT_WITH_NOCRT_ALIASES +BEGINPROC RT_NOCRT(%1) +%endif ; !RT_WITH_NOCRT_ALIASES +%endmacro ; RT_NOCRT_BEGINPROC + +%ifdef RT_WITH_NOCRT_ALIASES + %ifdef RT_WITHOUT_NOCRT_WRAPPERS + %error "RT_WITH_NOCRT_ALIASES and RT_WITHOUT_NOCRT_WRAPPERS doesn't mix." + %endif +%endif + + + +;; @def xS +; The stack unit size / The register unit size. + +;; @def xSP +; The stack pointer register (RSP or ESP). + +;; @def xBP +; The base pointer register (RBP or ESP). + +;; @def xAX +; RAX or EAX depending on context. + +;; @def xBX +; RBX or EBX depending on context. + +;; @def xCX +; RCX or ECX depending on context. + +;; @def xDX +; RDX or EDX depending on context. + +;; @def xDI +; RDI or EDI depending on context. + +;; @def xSI +; RSI or ESI depending on context. + +;; @def xWrtRIP +; 'wrt rip' for AMD64 targets, nothing for x86 ones. + +%ifdef RT_ARCH_AMD64 + %define xS 8 + %define xSP rsp + %define xBP rbp + %define xAX rax + %define xBX rbx + %define xCX rcx + %define xDX rdx + %define xDI rdi + %define xSI rsi + %define xWrtRIP wrt rip +%else + %define xS 4 + %define xSP esp + %define xBP ebp + %define xAX eax + %define xBX ebx + %define xCX ecx + %define xDX edx + %define xDI edi + %define xSI esi + %define xWrtRIP +%endif + +%endif diff --git a/include/iprt/assert.h b/include/iprt/assert.h new file mode 100644 index 00000000..ec1631d1 --- /dev/null +++ b/include/iprt/assert.h @@ -0,0 +1,2675 @@ +/** @file + * IPRT - Assertions. + */ + +/* + * Copyright (C) 2006-2012 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. + */ + +#ifndef ___iprt_assert_h +#define ___iprt_assert_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + +/** @defgroup grp_rt_assert Assert - Assertions + * @ingroup grp_rt + * + * Assertions are generally used to check preconditions and other + * assumptions. Sometimes it is also used to catch odd errors or errors + * that one would like to inspect in the debugger. They should not be + * used for errors that happen frequently. + * + * IPRT provides a host of assertion macros, so many that it can be a bit + * overwhelming at first. Don't despair, there is a system (surprise). + * + * First there are four families of assertions: + * - Assert - The normal strict build only assertions. + * - AssertLogRel - Calls LogRel() in non-strict builds, otherwise like Assert. + * - AssertRelease - Triggers in all builds. + * - AssertFatal - Triggers in all builds and cannot be continued. + * + * Then there are variations wrt to argument list and behavior on failure: + * - Msg - Custom RTStrPrintf-like message with the assertion message. + * - Return - Return the specific rc on failure. + * - ReturnVoid - Return (void) on failure. + * - Break - Break (out of switch/loop) on failure. + * - Stmt - Execute the specified statement(s) on failure. + * - RC - Assert RT_SUCCESS. + * - RCSuccess - Assert VINF_SUCCESS. + * + * In addition there is a very special family AssertCompile that can be + * used for some limited compile-time checking, like structure sizes and member + * alignment. This family doesn't have the same variations. + * + * + * @remarks As you might have noticed, the macros don't follow the + * coding guidelines wrt to macros supposedly being all uppercase + * and underscored. For various reasons they don't, and nobody + * has complained yet. Wonder why... :-) + * + * @remarks Each project has its own specific guidelines on how to use + * assertions, so the above is just trying to give you the general idea + * from the IPRT point of view. + * + * @{ + */ + +RT_C_DECLS_BEGIN + +/** + * The 1st part of an assert message. + * + * @param pszExpr Expression. Can be NULL. + * @param uLine Location line number. + * @param pszFile Location file name. + * @param pszFunction Location function name. + */ +RTDECL(void) RTAssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction); +/** + * Weak version of RTAssertMsg1 that can be overridden locally in a module to + * modify, redirect or otherwise mess with the assertion output. + * + * @copydoc RTAssertMsg1 + */ +RTDECL(void) RTAssertMsg1Weak(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction); + +/** + * The 2nd (optional) part of an assert message. + * + * @param pszFormat Printf like format string. + * @param ... Arguments to that string. + */ +RTDECL(void) RTAssertMsg2(const char *pszFormat, ...); +/** + * Weak version of RTAssertMsg2 that forwards to RTAssertMsg2WeakV. + * + * There is not need to override this, check out RTAssertMsg2WeakV instead! + * + * @copydoc RTAssertMsg2 + */ +RTDECL(void) RTAssertMsg2Weak(const char *pszFormat, ...); + +/** + * The 2nd (optional) part of an assert message. + * + * @param pszFormat Printf like format string. + * @param va Arguments to that string. + */ +RTDECL(void) RTAssertMsg2V(const char *pszFormat, va_list va); +/** + * Weak version of RTAssertMsg2V that can be overridden locally in a module to + * modify, redirect or otherwise mess with the assertion output. + * + * @copydoc RTAssertMsg2V + */ +RTDECL(void) RTAssertMsg2WeakV(const char *pszFormat, va_list va); + +/** + * Additional information which should be appended to the 2nd part of an + * assertion message. + * + * @param pszFormat Printf like format string. + * @param ... Arguments to that string. + */ +RTDECL(void) RTAssertMsg2Add(const char *pszFormat, ...); +/** + * Weak version of RTAssertMsg2Add that forwards to RTAssertMsg2AddWeakV. + * + * There is not need to override this, check out RTAssertMsg2AddWeakV instead! + * + * @copydoc RTAssertMsg2Add + */ +RTDECL(void) RTAssertMsg2AddWeak(const char *pszFormat, ...); + +/** + * Additional information which should be appended to the 2nd part of an + * assertion message. + * + * @param pszFormat Printf like format string. + * @param va Arguments to that string. + */ +RTDECL(void) RTAssertMsg2AddV(const char *pszFormat, va_list va); +/** + * Weak version of RTAssertMsg2AddV that can be overridden locally in a module + * to modify, redirect or otherwise mess with the assertion output. + * + * @copydoc RTAssertMsg2AddV + */ +RTDECL(void) RTAssertMsg2AddWeakV(const char *pszFormat, va_list va); + +#ifdef IN_RING0 +/** + * Panics the system as the result of a fail assertion. + */ +RTR0DECL(void) RTR0AssertPanicSystem(void); +#endif /* IN_RING0 */ + +/** + * Overridable function that decides whether assertions executes the panic + * (breakpoint) or not. + * + * The generic implementation will return true. + * + * @returns true if the breakpoint should be hit, false if it should be ignored. + * + * @remark The RTDECL() makes this a bit difficult to override on Windows. So, + * you'll have to use RTASSERT_HAVE_SHOULD_PANIC or + * RTASSERT_HAVE_SHOULD_PANIC_PRIVATE there to control the kind of + * prototype. + */ +#if !defined(RTASSERT_HAVE_SHOULD_PANIC) && !defined(RTASSERT_HAVE_SHOULD_PANIC_PRIVATE) +RTDECL(bool) RTAssertShouldPanic(void); +#elif defined(RTASSERT_HAVE_SHOULD_PANIC_PRIVATE) +bool RTAssertShouldPanic(void); +#else +DECLEXPORT(bool) RTCALL RTAssertShouldPanic(void); +#endif + +/** + * Controls whether the assertions should be quiet or noisy (default). + * + * @returns The old setting. + * @param fQuiet The new setting. + */ +RTDECL(bool) RTAssertSetQuiet(bool fQuiet); + +/** + * Are assertions quiet or noisy? + * + * @returns True if they are quiet, false if noisy. + */ +RTDECL(bool) RTAssertAreQuiet(void); + +/** + * Makes the assertions panic (default) or not. + * + * @returns The old setting. + * @param fPanic The new setting. + */ +RTDECL(bool) RTAssertSetMayPanic(bool fPanic); + +/** + * Can assertion panic. + * + * @returns True if they can, false if not. + */ +RTDECL(bool) RTAssertMayPanic(void); + + +/** @name Globals for crash analysis + * @remarks This is the full potential set, it + * @{ + */ +/** The last assert message, 1st part. */ +extern RTDATADECL(char) g_szRTAssertMsg1[1024]; +/** The last assert message, 2nd part. */ +extern RTDATADECL(char) g_szRTAssertMsg2[4096]; +/** The last assert message, expression. */ +extern RTDATADECL(const char * volatile) g_pszRTAssertExpr; +/** The last assert message, file name. */ +extern RTDATADECL(const char * volatile) g_pszRTAssertFile; +/** The last assert message, line number. */ +extern RTDATADECL(uint32_t volatile) g_u32RTAssertLine; +/** The last assert message, function name. */ +extern RTDATADECL(const char * volatile) g_pszRTAssertFunction; +/** @} */ + +RT_C_DECLS_END + +/** @def RTAssertDebugBreak() + * Debugger breakpoint instruction. + * + * @remarks This macro does not depend on RT_STRICT. + */ +#define RTAssertDebugBreak() do { RT_BREAKPOINT(); } while (0) + + + +/** @name Compile time assertions. + * + * These assertions are used to check structure sizes, member/size alignments + * and similar compile time expressions. + * + * @{ + */ + +/** + * RTASSERTTYPE is the type the AssertCompile() macro redefines. + * It has no other function and shouldn't be used. + * Visual C++ uses this. + */ +typedef int RTASSERTTYPE[1]; + +/** + * RTASSERTVAR is the type the AssertCompile() macro redefines. + * It has no other function and shouldn't be used. + * GCC uses this. + */ +#ifdef __GNUC__ +RT_C_DECLS_BEGIN +#endif +extern int RTASSERTVAR[1]; +#ifdef __GNUC__ +RT_C_DECLS_END +#endif + +/** @def RTASSERT_HAVE_STATIC_ASSERT + * Indicates that the compiler implements static_assert(expr, msg). + */ +#ifdef _MSC_VER +# if _MSC_VER >= 1600 && defined(__cplusplus) +# define RTASSERT_HAVE_STATIC_ASSERT +# endif +#endif +#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define RTASSERT_HAVE_STATIC_ASSERT +#endif +#ifdef DOXYGEN_RUNNING +# define RTASSERT_HAVE_STATIC_ASSERT +#endif + +/** @def AssertCompileNS + * Asserts that a compile-time expression is true. If it's not break the build. + * + * This differs from AssertCompile in that it accepts some more expressions + * than what C++0x allows - NS = Non-standard. + * + * @param expr Expression which should be true. + */ +#ifdef __GNUC__ +# define AssertCompileNS(expr) extern int RTASSERTVAR[1] __attribute__((unused)), RTASSERTVAR[(expr) ? 1 : 0] __attribute__((unused)) +#else +# define AssertCompileNS(expr) typedef int RTASSERTTYPE[(expr) ? 1 : 0] +#endif + +/** @def AssertCompile + * Asserts that a C++0x compile-time expression is true. If it's not break the + * build. + * @param expr Expression which should be true. + */ +#ifdef RTASSERT_HAVE_STATIC_ASSERT +# define AssertCompile(expr) static_assert(!!(expr), #expr) +#else +# define AssertCompile(expr) AssertCompileNS(expr) +#endif + +/** @def AssertCompileSize + * Asserts a size at compile. + * @param type The type. + * @param size The expected type size. + */ +#define AssertCompileSize(type, size) \ + AssertCompile(sizeof(type) == (size)) + +/** @def AssertCompileSizeAlignment + * Asserts a size alignment at compile. + * @param type The type. + * @param align The size alignment to assert. + */ +#define AssertCompileSizeAlignment(type, align) \ + AssertCompile(!(sizeof(type) & ((align) - 1))) + +/** @def AssertCompileMemberSize + * Asserts a member offset alignment at compile. + * @param type The type. + * @param member The member. + * @param size The member size to assert. + */ +#define AssertCompileMemberSize(type, member, size) \ + AssertCompile(RT_SIZEOFMEMB(type, member) == (size)) + +/** @def AssertCompileMemberSizeAlignment + * Asserts a member size alignment at compile. + * @param type The type. + * @param member The member. + * @param align The member size alignment to assert. + */ +#define AssertCompileMemberSizeAlignment(type, member, align) \ + AssertCompile(!(RT_SIZEOFMEMB(type, member) & ((align) - 1))) + +/** @def AssertCompileMemberAlignment + * Asserts a member offset alignment at compile. + * @param type The type. + * @param member The member. + * @param align The member offset alignment to assert. + */ +#if defined(__GNUC__) +# if __GNUC__ >= 4 +# define AssertCompileMemberAlignment(type, member, align) \ + AssertCompile(!(__builtin_offsetof(type, member) & ((align) - 1))) +# else +# define AssertCompileMemberAlignment(type, member, align) \ + AssertCompile(!(RT_OFFSETOF(type, member) & ((align) - 1))) +# endif +#else +# define AssertCompileMemberAlignment(type, member, align) \ + AssertCompile(!(RT_OFFSETOF(type, member) & ((align) - 1))) +#endif + +/** @def AssertCompileMemberOffset + * Asserts an offset of a structure member at compile. + * @param type The type. + * @param member The member. + * @param off The expected offset. + */ +#if defined(__GNUC__) +# if __GNUC__ >= 4 +# define AssertCompileMemberOffset(type, member, off) \ + AssertCompile(__builtin_offsetof(type, member) == (off)) +# else +# define AssertCompileMemberOffset(type, member, off) \ + AssertCompile(RT_OFFSETOF(type, member) == (off)) +# endif +#else +# define AssertCompileMemberOffset(type, member, off) \ + AssertCompile(RT_OFFSETOF(type, member) == (off)) +#endif + +/** @def AssertCompile2MemberOffsets + * Asserts that two (sub-structure) members in union have the same offset. + * @param type The type. + * @param member1 The first member. + * @param member2 The second member. + */ +#if defined(__GNUC__) +# if __GNUC__ >= 4 +# define AssertCompile2MemberOffsets(type, member1, member2) \ + AssertCompile(__builtin_offsetof(type, member1) == __builtin_offsetof(type, member2)) +# else +# define AssertCompile2MemberOffsets(type, member1, member2) \ + AssertCompile(RT_OFFSETOF(type, member1) == RT_OFFSETOF(type, member2)) +# endif +#else +# define AssertCompile2MemberOffsets(type, member1, member2) \ + AssertCompile(RT_OFFSETOF(type, member1) == RT_OFFSETOF(type, member2)) +#endif + +/** @def AssertCompileAdjacentMembers + * Asserts that two structure members are adjacent. + * @param type The type. + * @param member1 The first member. + * @param member2 The second member. + */ +#if defined(__GNUC__) +# if __GNUC__ >= 4 +# define AssertCompileAdjacentMembers(type, member1, member2) \ + AssertCompile(__builtin_offsetof(type, member1) + RT_SIZEOFMEMB(type, member1) == __builtin_offsetof(type, member2)) +# else +# define AssertCompileAdjacentMembers(type, member1, member2) \ + AssertCompile(RT_OFFSETOF(type, member1) + RT_SIZEOFMEMB(type, member1) == RT_OFFSETOF(type, member2)) +# endif +#else +# define AssertCompileAdjacentMembers(type, member1, member2) \ + AssertCompile(RT_OFFSETOF(type, member1) + RT_SIZEOFMEMB(type, member1) == RT_OFFSETOF(type, member2)) +#endif + +/** @def AssertCompileMembersAtSameOffset + * Asserts that members of two different structures are at the same offset. + * @param type1 The first type. + * @param member1 The first member. + * @param type2 The second type. + * @param member2 The second member. + */ +#if defined(__GNUC__) +# if __GNUC__ >= 4 +# define AssertCompileMembersAtSameOffset(type1, member1, type2, member2) \ + AssertCompile(__builtin_offsetof(type1, member1) == __builtin_offsetof(type2, member2)) +# else +# define AssertCompileMembersAtSameOffset(type1, member1, type2, member2) \ + AssertCompile(RT_OFFSETOF(type1, member1) == RT_OFFSETOF(type2, member2)) +# endif +#else +# define AssertCompileMembersAtSameOffset(type1, member1, type2, member2) \ + AssertCompile(RT_OFFSETOF(type1, member1) == RT_OFFSETOF(type2, member2)) +#endif + +/** @def AssertCompileMembersSameSize + * Asserts that members of two different structures have the same size. + * @param type1 The first type. + * @param member1 The first member. + * @param type2 The second type. + * @param member2 The second member. + */ +#define AssertCompileMembersSameSize(type1, member1, type2, member2) \ + AssertCompile(RT_SIZEOFMEMB(type1, member1) == RT_SIZEOFMEMB(type2, member2)) + +/** @def AssertCompileMembersSameSizeAndOffset + * Asserts that members of two different structures have the same size and are + * at the same offset. + * @param type1 The first type. + * @param member1 The first member. + * @param type2 The second type. + * @param member2 The second member. + */ +#if defined(__GNUC__) +# if __GNUC__ >= 4 +# define AssertCompileMembersSameSizeAndOffset(type1, member1, type2, member2) \ + AssertCompile(__builtin_offsetof(type1, member1) == __builtin_offsetof(type2, member2) && RT_SIZEOFMEMB(type1, member1) == RT_SIZEOFMEMB(type2, member2)) +# else +# define AssertCompileMembersSameSizeAndOffset(type1, member1, type2, member2) \ + AssertCompile(RT_OFFSETOF(type1, member1) == RT_OFFSETOF(type2, member2) && RT_SIZEOFMEMB(type1, member1) == RT_SIZEOFMEMB(type2, member2)) +# endif +#else +# define AssertCompileMembersSameSizeAndOffset(type1, member1, type2, member2) \ + AssertCompile(RT_OFFSETOF(type1, member1) == RT_OFFSETOF(type2, member2) && RT_SIZEOFMEMB(type1, member1) == RT_SIZEOFMEMB(type2, member2)) +#endif + +/** @} */ + + + +/** @name Assertions + * + * These assertions will only trigger when RT_STRICT is defined. When it is + * undefined they will all be no-ops and generate no code. + * + * @{ + */ + + +/** @def RTASSERT_QUIET + * This can be defined to shut up the messages for a file where this would be + * problematic because the message printing code path passes thru it. + * @internal */ +#ifdef DOXYGEN_RUNNING +# define RTASSERT_QUIET +#endif +#if defined(RTASSERT_QUIET) && !defined(DOXYGEN_RUNNING) +# define RTAssertMsg1Weak(pszExpr, uLine, pszfile, pszFunction) \ + do { } while (0) +# define RTAssertMsg2Weak if (0) RTAssertMsg2Weak +#endif + +/** @def RTAssertDoPanic + * Raises an assertion panic appropriate to the current context. + * @remarks This macro does not depend on RT_STRICT. + */ +#if defined(IN_RING0) \ + && (defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)) +# define RTAssertDoPanic() RTR0AssertPanicSystem() +#else +# define RTAssertDoPanic() RTAssertDebugBreak() +#endif + +/** @def AssertBreakpoint() + * Assertion Breakpoint. + * @deprecated Use RTAssertPanic or RTAssertDebugBreak instead. + */ +#ifdef RT_STRICT +# define AssertBreakpoint() RTAssertDebugBreak() +#else +# define AssertBreakpoint() do { } while (0) +#endif + +/** @def RTAssertPanic() + * If RT_STRICT is defined this macro will invoke RTAssertDoPanic if + * RTAssertShouldPanic returns true. If RT_STRICT isn't defined it won't do any + * thing. + */ +#if defined(RT_STRICT) && !defined(RTASSERT_DONT_PANIC) +# define RTAssertPanic() do { if (RTAssertShouldPanic()) RTAssertDoPanic(); } while (0) +#else +# define RTAssertPanic() do { } while (0) +#endif + +/** @def Assert + * Assert that an expression is true. If false, hit breakpoint. + * @param expr Expression which should be true. + */ +#ifdef RT_STRICT +# define Assert(expr) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + } \ + } while (0) +#else +# define Assert(expr) do { } while (0) +#endif + + +/** @def AssertStmt + * Assert that an expression is true. If false, hit breakpoint and execute the + * statement. + * @param expr Expression which should be true. + * @param stmt Statement to execute on failure. + */ +#ifdef RT_STRICT +# define AssertStmt(expr, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + } \ + } while (0) +#else +# define AssertStmt(expr, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + stmt; \ + } \ + } while (0) +#endif + + +/** @def AssertReturn + * Assert that an expression is true and returns if it isn't. + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + * @param rc What is to be presented to return. + */ +#ifdef RT_STRICT +# define AssertReturn(expr, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + return (rc); \ + } \ + } while (0) +#else +# define AssertReturn(expr, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + return (rc); \ + } while (0) +#endif + +/** @def AssertReturnStmt + * Assert that an expression is true, if it isn't execute the given statement + * and return rc. + * + * In RT_STRICT mode it will hit a breakpoint before executing the statement and + * returning. + * + * @param expr Expression which should be true. + * @param stmt Statement to execute before returning on failure. + * @param rc What is to be presented to return. + */ +#ifdef RT_STRICT +# define AssertReturnStmt(expr, stmt, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + return (rc); \ + } \ + } while (0) +#else +# define AssertReturnStmt(expr, stmt, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + stmt; \ + return (rc); \ + } \ + } while (0) +#endif + +/** @def AssertReturnVoid + * Assert that an expression is true and returns if it isn't. + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + */ +#ifdef RT_STRICT +# define AssertReturnVoid(expr) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + return; \ + } \ + } while (0) +#else +# define AssertReturnVoid(expr) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + return; \ + } while (0) +#endif + +/** @def AssertReturnVoidStmt + * Assert that an expression is true, if it isn't execute the given statement + * and return. + * + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + * @param stmt Statement to execute before returning on failure. + */ +#ifdef RT_STRICT +# define AssertReturnVoidStmt(expr, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + return; \ + } \ + } while (0) +#else +# define AssertReturnVoidStmt(expr, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + stmt; \ + return; \ + } \ + } while (0) +#endif + + +/** @def AssertBreak + * Assert that an expression is true and breaks if it isn't. + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + */ +#ifdef RT_STRICT +# define AssertBreak(expr) \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + break; \ + } else do {} while (0) +#else +# define AssertBreak(expr) \ + if (RT_UNLIKELY(!(expr))) \ + break; \ + else do {} while (0) +#endif + +/** @def AssertBreakStmt + * Assert that an expression is true and breaks if it isn't. + * In RT_STRICT mode it will hit a breakpoint before doing break. + * + * @param expr Expression which should be true. + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#ifdef RT_STRICT +# define AssertBreakStmt(expr, stmt) \ + if (RT_UNLIKELY(!(expr))) { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + break; \ + } else do {} while (0) +#else +# define AssertBreakStmt(expr, stmt) \ + if (RT_UNLIKELY(!(expr))) { \ + stmt; \ + break; \ + } else do {} while (0) +#endif + + +/** @def AssertMsg + * Assert that an expression is true. If it's not print message and hit breakpoint. + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#ifdef RT_STRICT +# define AssertMsg(expr, a) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + } \ + } while (0) +#else +# define AssertMsg(expr, a) do { } while (0) +#endif + +/** @def AssertMsgStmt + * Assert that an expression is true. If it's not print message and hit + * breakpoint and execute the statement. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute in case of a failed assertion. + * + * @remarks The expression and statement will be evaluated in all build types. + */ +#ifdef RT_STRICT +# define AssertMsgStmt(expr, a, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + stmt; \ + } \ + } while (0) +#else +# define AssertMsgStmt(expr, a, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + stmt; \ + } \ + } while (0) +#endif + +/** @def AssertMsgReturn + * Assert that an expression is true and returns if it isn't. + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param rc What is to be presented to return. + */ +#ifdef RT_STRICT +# define AssertMsgReturn(expr, a, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + return (rc); \ + } \ + } while (0) +#else +# define AssertMsgReturn(expr, a, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + return (rc); \ + } while (0) +#endif + +/** @def AssertMsgReturnStmt + * Assert that an expression is true, if it isn't execute the statement and + * return. + * + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before returning in case of a failed + * assertion. + * @param rc What is to be presented to return. + */ +#ifdef RT_STRICT +# define AssertMsgReturnStmt(expr, a, stmt, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + stmt; \ + return (rc); \ + } \ + } while (0) +#else +# define AssertMsgReturnStmt(expr, a, stmt, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + stmt; \ + return (rc); \ + } \ + } while (0) +#endif + +/** @def AssertMsgReturnVoid + * Assert that an expression is true and returns if it isn't. + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#ifdef RT_STRICT +# define AssertMsgReturnVoid(expr, a) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + return; \ + } \ + } while (0) +#else +# define AssertMsgReturnVoid(expr, a) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + return; \ + } while (0) +#endif + +/** @def AssertMsgReturnVoidStmt + * Assert that an expression is true, if it isn't execute the statement and + * return. + * + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#ifdef RT_STRICT +# define AssertMsgReturnVoidStmt(expr, a, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + stmt; \ + return; \ + } \ + } while (0) +#else +# define AssertMsgReturnVoidStmt(expr, a, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + stmt; \ + return; \ + } \ + } while (0) +#endif + + +/** @def AssertMsgBreak + * Assert that an expression is true and breaks if it isn't. + * In RT_STRICT mode it will hit a breakpoint before returning. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#ifdef RT_STRICT +# define AssertMsgBreak(expr, a) \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + break; \ + } else do {} while (0) +#else +# define AssertMsgBreak(expr, a) \ + if (RT_UNLIKELY(!(expr))) \ + break; \ + else do {} while (0) +#endif + +/** @def AssertMsgBreakStmt + * Assert that an expression is true and breaks if it isn't. + * In RT_STRICT mode it will hit a breakpoint before doing break. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#ifdef RT_STRICT +# define AssertMsgBreakStmt(expr, a, stmt) \ + if (RT_UNLIKELY(!(expr))) { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + stmt; \ + break; \ + } else do {} while (0) +#else +# define AssertMsgBreakStmt(expr, a, stmt) \ + if (RT_UNLIKELY(!(expr))) { \ + stmt; \ + break; \ + } else do {} while (0) +#endif + +/** @def AssertFailed + * An assertion failed hit breakpoint. + */ +#ifdef RT_STRICT +# define AssertFailed() \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + } while (0) +#else +# define AssertFailed() do { } while (0) +#endif + +/** @def AssertFailedReturn + * An assertion failed, hit breakpoint (RT_STRICT mode only) and return. + * + * @param rc The rc to return. + */ +#ifdef RT_STRICT +# define AssertFailedReturn(rc) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + return (rc); \ + } while (0) +#else +# define AssertFailedReturn(rc) \ + do { \ + return (rc); \ + } while (0) +#endif + +/** @def AssertFailedReturnStmt + * An assertion failed, hit breakpoint (RT_STRICT mode only), execute a + * statement and return a value. + * + * @param stmt The statement to execute before returning. + * @param rc The value to return. + */ +#ifdef RT_STRICT +# define AssertFailedReturnStmt(stmt, rc) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + return (rc); \ + } while (0) +#else +# define AssertFailedReturnStmt(stmt, rc) \ + do { \ + stmt; \ + return (rc); \ + } while (0) +#endif + +/** @def AssertFailedReturnVoid + * An assertion failed, hit breakpoint (RT_STRICT mode only) and return. + */ +#ifdef RT_STRICT +# define AssertFailedReturnVoid() \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + return; \ + } while (0) +#else +# define AssertFailedReturnVoid() \ + do { \ + return; \ + } while (0) +#endif + +/** @def AssertFailedReturnVoidStmt + * An assertion failed, hit breakpoint (RT_STRICT mode only), execute a + * statement and return. + * + * @param stmt The statement to execute before returning. + */ +#ifdef RT_STRICT +# define AssertFailedReturnVoidStmt(stmt) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + return; \ + } while (0) +#else +# define AssertFailedReturnVoidStmt(stmt) \ + do { \ + stmt; \ + return; \ + } while (0) +#endif + + +/** @def AssertFailedBreak + * An assertion failed, hit breakpoint (RT_STRICT mode only) and break. + */ +#ifdef RT_STRICT +# define AssertFailedBreak() \ + if (1) { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + break; \ + } else do {} while (0) +#else +# define AssertFailedBreak() \ + if (1) \ + break; \ + else do {} while (0) +#endif + +/** @def AssertFailedBreakStmt + * An assertion failed, hit breakpoint (RT_STRICT mode only), execute + * the given statement and break. + * + * @param stmt Statement to execute before break. + */ +#ifdef RT_STRICT +# define AssertFailedBreakStmt(stmt) \ + if (1) { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + break; \ + } else do {} while (0) +#else +# define AssertFailedBreakStmt(stmt) \ + if (1) { \ + stmt; \ + break; \ + } else do {} while (0) +#endif + + +/** @def AssertMsgFailed + * An assertion failed print a message and a hit breakpoint. + * + * @param a printf argument list (in parenthesis). + */ +#ifdef RT_STRICT +# define AssertMsgFailed(a) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + } while (0) +#else +# define AssertMsgFailed(a) do { } while (0) +#endif + +/** @def AssertMsgFailedReturn + * An assertion failed, hit breakpoint with message (RT_STRICT mode only) and return. + * + * @param a printf argument list (in parenthesis). + * @param rc What is to be presented to return. + */ +#ifdef RT_STRICT +# define AssertMsgFailedReturn(a, rc) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + return (rc); \ + } while (0) +#else +# define AssertMsgFailedReturn(a, rc) \ + do { \ + return (rc); \ + } while (0) +#endif + +/** @def AssertMsgFailedReturnVoid + * An assertion failed, hit breakpoint with message (RT_STRICT mode only) and return. + * + * @param a printf argument list (in parenthesis). + */ +#ifdef RT_STRICT +# define AssertMsgFailedReturnVoid(a) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + return; \ + } while (0) +#else +# define AssertMsgFailedReturnVoid(a) \ + do { \ + return; \ + } while (0) +#endif + + +/** @def AssertMsgFailedBreak + * An assertion failed, hit breakpoint with message (RT_STRICT mode only) and break. + * + * @param a printf argument list (in parenthesis). + */ +#ifdef RT_STRICT +# define AssertMsgFailedBreak(a) \ + if (1) { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + break; \ + } else do {} while (0) +#else +# define AssertMsgFailedBreak(a) \ + if (1) \ + break; \ + else do {} while (0) +#endif + +/** @def AssertMsgFailedBreakStmt + * An assertion failed, hit breakpoint (RT_STRICT mode only), execute + * the given statement and break. + * + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before break. + */ +#ifdef RT_STRICT +# define AssertMsgFailedBreakStmt(a, stmt) \ + if (1) { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertPanic(); \ + stmt; \ + break; \ + } else do {} while (0) +#else +# define AssertMsgFailedBreakStmt(a, stmt) \ + if (1) { \ + stmt; \ + break; \ + } else do {} while (0) +#endif + +/** @} */ + + + +/** @name Release Log Assertions + * + * These assertions will work like normal strict assertion when RT_STRICT is + * defined and LogRel statements when RT_STRICT is undefined. Typically used for + * things which shouldn't go wrong, but when it does you'd like to know one way + * or the other. + * + * @{ + */ + +/** @def RTAssertLogRelMsg1 + * RTAssertMsg1Weak (strict builds) / LogRel wrapper (non-strict). + */ +#ifdef RT_STRICT +# define RTAssertLogRelMsg1(pszExpr, iLine, pszFile, pszFunction) \ + RTAssertMsg1Weak(pszExpr, iLine, pszFile, pszFunction) +#else +# define RTAssertLogRelMsg1(pszExpr, iLine, pszFile, pszFunction) \ + LogRel(("AssertLogRel %s(%d) %s: %s\n",\ + (pszFile), (iLine), (pszFunction), (pszExpr) )) +#endif + +/** @def RTAssertLogRelMsg2 + * RTAssertMsg2Weak (strict builds) / LogRel wrapper (non-strict). + */ +#ifdef RT_STRICT +# define RTAssertLogRelMsg2(a) RTAssertMsg2Weak a +#else +# define RTAssertLogRelMsg2(a) LogRel(a) +#endif + +/** @def AssertLogRel + * Assert that an expression is true. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + */ +#define AssertLogRel(expr) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + } \ + } while (0) + +/** @def AssertLogRelReturn + * Assert that an expression is true, return \a rc if it isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param rc What is to be presented to return. + */ +#define AssertLogRelReturn(expr, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + return (rc); \ + } \ + } while (0) + +/** @def AssertLogRelReturnVoid + * Assert that an expression is true, return void if it isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + */ +#define AssertLogRelReturnVoid(expr) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + return; \ + } \ + } while (0) + +/** @def AssertLogRelBreak + * Assert that an expression is true, break if it isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + */ +#define AssertLogRelBreak(expr) \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + break; \ + } \ + else do {} while (0) + +/** @def AssertLogRelBreakStmt + * Assert that an expression is true, execute \a stmt and break if it isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#define AssertLogRelBreakStmt(expr, stmt) \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + break; \ + } else do {} while (0) + +/** @def AssertLogRelMsg + * Assert that an expression is true. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#define AssertLogRelMsg(expr, a) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + } \ + } while (0) + +/** @def AssertLogRelMsgStmt + * Assert that an expression is true, execute \a stmt and break if it isn't + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute in case of a failed assertion. + */ +#define AssertLogRelMsgStmt(expr, a, stmt) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + stmt; \ + } \ + } while (0) + +/** @def AssertLogRelMsgReturn + * Assert that an expression is true, return \a rc if it isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param rc What is to be presented to return. + */ +#define AssertLogRelMsgReturn(expr, a, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + return (rc); \ + } \ + } while (0) + +/** @def AssertLogRelMsgReturnStmt + * Assert that an expression is true, execute @a stmt and return @a rcRet if it + * isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before returning in case of a failed + * assertion. + * @param rcRet What is to be presented to return. + */ +#define AssertLogRelMsgReturnStmt(expr, a, stmt, rcRet) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + stmt; \ + return (rcRet); \ + } \ + } while (0) + +/** @def AssertLogRelMsgReturnVoid + * Assert that an expression is true, return (void) if it isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#define AssertLogRelMsgReturnVoid(expr, a) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + return; \ + } \ + } while (0) + +/** @def AssertLogRelMsgBreak + * Assert that an expression is true, break if it isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#define AssertLogRelMsgBreak(expr, a) \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + break; \ + } \ + else do {} while (0) + +/** @def AssertLogRelMsgBreakStmt + * Assert that an expression is true, execute \a stmt and break if it isn't. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#define AssertLogRelMsgBreakStmt(expr, a, stmt) \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + stmt; \ + break; \ + } else do {} while (0) + +/** @def AssertLogRelFailed + * An assertion failed. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + */ +#define AssertLogRelFailed() \ + do { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + } while (0) + +/** @def AssertLogRelFailedReturn + * An assertion failed. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param rc What is to be presented to return. + */ +#define AssertLogRelFailedReturn(rc) \ + do { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + return (rc); \ + } while (0) + +/** @def AssertLogRelFailedReturnVoid + * An assertion failed, hit a breakpoint and return. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + */ +#define AssertLogRelFailedReturnVoid() \ + do { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + return; \ + } while (0) + +/** @def AssertLogRelFailedBreak + * An assertion failed, break. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + */ +#define AssertLogRelFailedBreak() \ + if (1) \ + { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + break; \ + } else do {} while (0) + +/** @def AssertLogRelFailedBreakStmt + * An assertion failed, execute \a stmt and break. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param stmt Statement to execute before break. + */ +#define AssertLogRelFailedBreakStmt(stmt) \ + if (1) \ + { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertPanic(); \ + stmt; \ + break; \ + } else do {} while (0) + +/** @def AssertLogRelMsgFailed + * An assertion failed. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param a printf argument list (in parenthesis). + */ +#define AssertLogRelMsgFailed(a) \ + do { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + } while (0) + +/** @def AssertLogRelMsgFailedReturn + * An assertion failed, return \a rc. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param a printf argument list (in parenthesis). + * @param rc What is to be presented to return. + */ +#define AssertLogRelMsgFailedReturn(a, rc) \ + do { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + return (rc); \ + } while (0) + +/** @def AssertLogRelMsgFailedReturn + * An assertion failed, execute @a stmt and return @a rc. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before returning in case of a failed + * assertion. + * @param rc What is to be presented to return. + */ +#define AssertLogRelMsgFailedReturnStmt(a, stmt, rc) \ + do { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + stmt; \ + return (rc); \ + } while (0) + +/** @def AssertLogRelMsgFailedReturnVoid + * An assertion failed, return void. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param a printf argument list (in parenthesis). + */ +#define AssertLogRelMsgFailedReturnVoid(a) \ + do { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + return; \ + } while (0) + +/** @def AssertLogRelMsgFailedReturnVoid + * An assertion failed, execute @a stmt and return void. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before returning in case of a failed + * assertion. + */ +#define AssertLogRelMsgFailedReturnVoidStmt(a, stmt) \ + do { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + stmt; \ + return; \ + } while (0) + +/** @def AssertLogRelMsgFailedBreak + * An assertion failed, break. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param a printf argument list (in parenthesis). + */ +#define AssertLogRelMsgFailedBreak(a) \ + if (1)\ + { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + break; \ + } else do {} while (0) + +/** @def AssertLogRelMsgFailedBreakStmt + * An assertion failed, execute \a stmt and break. + * Strict builds will hit a breakpoint, non-strict will only do LogRel. + * + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before break. + */ +#define AssertLogRelMsgFailedBreakStmt(a, stmt) \ + if (1) \ + { \ + RTAssertLogRelMsg1((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertLogRelMsg2(a); \ + RTAssertPanic(); \ + stmt; \ + break; \ + } else do {} while (0) + +/** @} */ + + + +/** @name Release Assertions + * + * These assertions are always enabled. + * @{ + */ + +/** @def RTAssertReleasePanic() + * Invokes RTAssertShouldPanic and RTAssertDoPanic. + * + * It might seem odd that RTAssertShouldPanic is necessary when its result isn't + * checked, but it's done since RTAssertShouldPanic is overrideable and might be + * used to bail out before taking down the system (the VMMR0 case). + */ +#define RTAssertReleasePanic() do { RTAssertShouldPanic(); RTAssertDoPanic(); } while (0) + + +/** @def AssertRelease + * Assert that an expression is true. If it's not hit a breakpoint. + * + * @param expr Expression which should be true. + */ +#define AssertRelease(expr) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + } \ + } while (0) + +/** @def AssertReleaseReturn + * Assert that an expression is true, hit a breakpoint and return if it isn't. + * + * @param expr Expression which should be true. + * @param rc What is to be presented to return. + */ +#define AssertReleaseReturn(expr, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + return (rc); \ + } \ + } while (0) + +/** @def AssertReleaseReturnVoid + * Assert that an expression is true, hit a breakpoint and return if it isn't. + * + * @param expr Expression which should be true. + */ +#define AssertReleaseReturnVoid(expr) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + return; \ + } \ + } while (0) + + +/** @def AssertReleaseBreak + * Assert that an expression is true, hit a breakpoint and break if it isn't. + * + * @param expr Expression which should be true. + */ +#define AssertReleaseBreak(expr) \ + if { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + break; \ + } \ + } else do {} while (0) + +/** @def AssertReleaseBreakStmt + * Assert that an expression is true, hit a breakpoint and break if it isn't. + * + * @param expr Expression which should be true. + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#define AssertReleaseBreakStmt(expr, stmt) \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + stmt; \ + break; \ + } else do {} while (0) + + +/** @def AssertReleaseMsg + * Assert that an expression is true, print the message and hit a breakpoint if it isn't. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#define AssertReleaseMsg(expr, a) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + } \ + } while (0) + +/** @def AssertReleaseMsgReturn + * Assert that an expression is true, print the message and hit a breakpoint and return if it isn't. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param rc What is to be presented to return. + */ +#define AssertReleaseMsgReturn(expr, a, rc) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + return (rc); \ + } \ + } while (0) + +/** @def AssertReleaseMsgReturnVoid + * Assert that an expression is true, print the message and hit a breakpoint and return if it isn't. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#define AssertReleaseMsgReturnVoid(expr, a) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + return; \ + } \ + } while (0) + + +/** @def AssertReleaseMsgBreak + * Assert that an expression is true, print the message and hit a breakpoint and break if it isn't. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#define AssertReleaseMsgBreak(expr, a) \ + if (RT_UNLIKELY(!(expr))) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + break; \ + } else do {} while (0) + +/** @def AssertReleaseMsgBreakStmt + * Assert that an expression is true, print the message and hit a breakpoint and break if it isn't. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#define AssertReleaseMsgBreakStmt(expr, a, stmt) \ + if (RT_UNLIKELY(!(expr))) { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + stmt; \ + break; \ + } else do {} while (0) + + +/** @def AssertReleaseFailed + * An assertion failed, hit a breakpoint. + */ +#define AssertReleaseFailed() \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + } while (0) + +/** @def AssertReleaseFailedReturn + * An assertion failed, hit a breakpoint and return. + * + * @param rc What is to be presented to return. + */ +#define AssertReleaseFailedReturn(rc) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + return (rc); \ + } while (0) + +/** @def AssertReleaseFailedReturnVoid + * An assertion failed, hit a breakpoint and return. + */ +#define AssertReleaseFailedReturnVoid() \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + return; \ + } while (0) + + +/** @def AssertReleaseFailedBreak + * An assertion failed, hit a breakpoint and break. + */ +#define AssertReleaseFailedBreak() \ + if (1) { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + break; \ + } else do {} while (0) + +/** @def AssertReleaseFailedBreakStmt + * An assertion failed, hit a breakpoint and break. + * + * @param stmt Statement to execute before break. + */ +#define AssertReleaseFailedBreakStmt(stmt) \ + if (1) { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + stmt; \ + break; \ + } else do {} while (0) + + +/** @def AssertReleaseMsgFailed + * An assertion failed, print a message and hit a breakpoint. + * + * @param a printf argument list (in parenthesis). + */ +#define AssertReleaseMsgFailed(a) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + } while (0) + +/** @def AssertReleaseMsgFailedReturn + * An assertion failed, print a message, hit a breakpoint and return. + * + * @param a printf argument list (in parenthesis). + * @param rc What is to be presented to return. + */ +#define AssertReleaseMsgFailedReturn(a, rc) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + return (rc); \ + } while (0) + +/** @def AssertReleaseMsgFailedReturnVoid + * An assertion failed, print a message, hit a breakpoint and return. + * + * @param a printf argument list (in parenthesis). + */ +#define AssertReleaseMsgFailedReturnVoid(a) \ + do { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + return; \ + } while (0) + + +/** @def AssertReleaseMsgFailedBreak + * An assertion failed, print a message, hit a breakpoint and break. + * + * @param a printf argument list (in parenthesis). + */ +#define AssertReleaseMsgFailedBreak(a) \ + if (1) { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + break; \ + } else do {} while (0) + +/** @def AssertReleaseMsgFailedBreakStmt + * An assertion failed, print a message, hit a breakpoint and break. + * + * @param a printf argument list (in parenthesis). + * @param stmt Statement to execute before break. + */ +#define AssertReleaseMsgFailedBreakStmt(a, stmt) \ + if (1) { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + stmt; \ + break; \ + } else do {} while (0) + +/** @} */ + + + +/** @name Fatal Assertions + * These are similar to release assertions except that you cannot ignore them in + * any way, they will loop for ever if RTAssertDoPanic returns. + * + * @{ + */ + +/** @def AssertFatal + * Assert that an expression is true. If it's not hit a breakpoint (for ever). + * + * @param expr Expression which should be true. + */ +#define AssertFatal(expr) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + for (;;) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + } \ + } while (0) + +/** @def AssertFatalMsg + * Assert that an expression is true, print the message and hit a breakpoint (for ever) if it isn't. + * + * @param expr Expression which should be true. + * @param a printf argument list (in parenthesis). + */ +#define AssertFatalMsg(expr, a) \ + do { \ + if (RT_UNLIKELY(!(expr))) \ + for (;;) \ + { \ + RTAssertMsg1Weak(#expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + } \ + } while (0) + +/** @def AssertFatalFailed + * An assertion failed, hit a breakpoint (for ever). + */ +#define AssertFatalFailed() \ + do { \ + for (;;) \ + { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertReleasePanic(); \ + } \ + } while (0) + +/** @def AssertFatalMsgFailed + * An assertion failed, print a message and hit a breakpoint (for ever). + * + * @param a printf argument list (in parenthesis). + */ +#define AssertFatalMsgFailed(a) \ + do { \ + for (;;) \ + { \ + RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, __PRETTY_FUNCTION__); \ + RTAssertMsg2Weak a; \ + RTAssertReleasePanic(); \ + } \ + } while (0) + +/** @} */ + + + +/** @name Convenience Assertions Macros + * @{ + */ + +/** @def AssertRC + * Asserts a iprt status code successful. + * + * On failure it will print info about the rc and hit a breakpoint. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRC(rc) AssertMsgRC(rc, ("%Rra\n", (rc))) + +/** @def AssertRCReturn + * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and return if it isn't. + * + * @param rc iprt status code. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCReturn(rc, rcRet) AssertMsgRCReturn(rc, ("%Rra\n", (rc)), rcRet) + +/** @def AssertRCReturn + * Asserts a iprt status code successful, bitch (RT_STRICT mode only), execute + * @a stmt and returns @a rcRet if it isn't. + * + * @param rc iprt status code. + * @param stmt Statement to execute before returning in case of a failed + * assertion. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCReturnStmt(rc, stmt, rcRet) AssertMsgRCReturnStmt(rc, ("%Rra\n", (rc)), stmt, rcRet) + +/** @def AssertRCReturnVoid + * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and return if it isn't. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCReturnVoid(rc) AssertMsgRCReturnVoid(rc, ("%Rra\n", (rc))) + +/** @def AssertReturnVoidStmt + * Asserts a iprt status code successful, bitch (RT_STRICT mode only), and + * execute the given statement/return if it isn't. + * + * @param rc iprt status code. + * @param stmt Statement to execute before returning on failure. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCReturnVoidStmt(rc, stmt) AssertMsgRCReturnVoidStmt(rc, ("%Rra\n", (rc)), stmt) + +/** @def AssertRCBreak + * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and break if it isn't. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCBreak(rc) AssertMsgRCBreak(rc, ("%Rra\n", (rc))) + +/** @def AssertRCBreakStmt + * Asserts a iprt status code successful, bitch (RT_STRICT mode only) and break if it isn't. + * + * @param rc iprt status code. + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCBreakStmt(rc, stmt) AssertMsgRCBreakStmt(rc, ("%Rra\n", (rc)), stmt) + +/** @def AssertMsgRC + * Asserts a iprt status code successful. + * + * It prints a custom message and hits a breakpoint on FAILURE. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertMsgRC(rc, msg) \ + do { AssertMsg(RT_SUCCESS_NP(rc), msg); NOREF(rc); } while (0) + +/** @def AssertMsgRCReturn + * Asserts a iprt status code successful and if it's not return the specified status code. + * + * If RT_STRICT is defined the message will be printed and a breakpoint hit before it returns + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertMsgRCReturn(rc, msg, rcRet) \ + do { AssertMsgReturn(RT_SUCCESS_NP(rc), msg, rcRet); NOREF(rc); } while (0) + +/** @def AssertMsgRCReturnStmt + * Asserts a iprt status code successful and if it's not execute @a stmt and + * return the specified status code (@a rcRet). + * + * If RT_STRICT is defined the message will be printed and a breakpoint hit before it returns + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param stmt Statement to execute before returning in case of a failed + * assertion. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertMsgRCReturnStmt(rc, msg, stmt, rcRet) \ + do { AssertMsgReturnStmt(RT_SUCCESS_NP(rc), msg, stmt, rcRet); NOREF(rc); } while (0) + +/** @def AssertMsgRCReturnVoid + * Asserts a iprt status code successful and if it's not return. + * + * If RT_STRICT is defined the message will be printed and a breakpoint hit before it returns + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertMsgRCReturnVoid(rc, msg) \ + do { AssertMsgReturnVoid(RT_SUCCESS_NP(rc), msg); NOREF(rc); } while (0) + +/** @def AssertMsgRCReturnVoidStmt + * Asserts a iprt status code successful and execute statement/break if it's not. + * + * If RT_STRICT is defined the message will be printed and a breakpoint hit before it returns + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertMsgRCReturnVoidStmt(rc, msg, stmt) \ + do { AssertMsgReturnVoidStmt(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } while (0) + +/** @def AssertMsgRCBreak + * Asserts a iprt status code successful and if it's not break. + * + * If RT_STRICT is defined the message will be printed and a breakpoint hit before it breaks + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertMsgRCBreak(rc, msg) \ + if (1) { AssertMsgBreak(RT_SUCCESS(rc), msg); NOREF(rc); } else do {} while (0) + +/** @def AssertMsgRCBreakStmt + * Asserts a iprt status code successful and execute statement/break if it's not. + * + * If RT_STRICT is defined the message will be printed and a breakpoint hit before it returns + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertMsgRCBreakStmt(rc, msg, stmt) \ + if (1) { AssertMsgBreakStmt(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } else do {} while (0) + +/** @def AssertRCSuccess + * Asserts an iprt status code equals VINF_SUCCESS. + * + * On failure it will print info about the rc and hit a breakpoint. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCSuccess(rc) do { AssertMsg((rc) == VINF_SUCCESS, ("%Rra\n", (rc))); NOREF(rc); } while (0) + +/** @def AssertRCSuccessReturn + * Asserts that an iprt status code equals VINF_SUCCESS, bitch (RT_STRICT mode only) and return if it isn't. + * + * @param rc iprt status code. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCSuccessReturn(rc, rcRet) AssertMsgReturn((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), rcRet) + +/** @def AssertRCSuccessReturnVoid + * Asserts that an iprt status code equals VINF_SUCCESS, bitch (RT_STRICT mode only) and return if it isn't. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCSuccessReturnVoid(rc) AssertMsgReturnVoid((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + +/** @def AssertRCSuccessBreak + * Asserts that an iprt status code equals VINF_SUCCESS, bitch (RT_STRICT mode only) and break if it isn't. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCSuccessBreak(rc) AssertMsgBreak((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + +/** @def AssertRCSuccessBreakStmt + * Asserts that an iprt status code equals VINF_SUCCESS, bitch (RT_STRICT mode only) and break if it isn't. + * + * @param rc iprt status code. + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. In release mode is NOREF()'ed. + */ +#define AssertRCSuccessBreakStmt(rc, stmt) AssertMsgBreakStmt((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), stmt) + + +/** @def AssertLogRelRC + * Asserts a iprt status code successful. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRC(rc) AssertLogRelMsgRC(rc, ("%Rra\n", (rc))) + +/** @def AssertLogRelRCReturn + * Asserts a iprt status code successful, returning \a rc if it isn't. + * + * @param rc iprt status code. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCReturn(rc, rcRet) AssertLogRelMsgRCReturn(rc, ("%Rra\n", (rc)), rcRet) + +/** @def AssertLogRelRCReturnStmt + * Asserts a iprt status code successful, executing \a stmt and returning \a rc + * if it isn't. + * + * @param rc iprt status code. + * @param stmt Statement to execute before returning in case of a failed + * assertion. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCReturnStmt(rc, stmt, rcRet) AssertLogRelMsgRCReturnStmt(rc, ("%Rra\n", (rc)), stmt, rcRet) + +/** @def AssertLogRelRCReturnVoid + * Asserts a iprt status code successful, returning (void) if it isn't. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCReturnVoid(rc) AssertLogRelMsgRCReturnVoid(rc, ("%Rra\n", (rc))) + +/** @def AssertLogRelRCBreak + * Asserts a iprt status code successful, breaking if it isn't. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCBreak(rc) AssertLogRelMsgRCBreak(rc, ("%Rra\n", (rc))) + +/** @def AssertLogRelRCBreakStmt + * Asserts a iprt status code successful, execute \a statement and break if it isn't. + * + * @param rc iprt status code. + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCBreakStmt(rc, stmt) AssertLogRelMsgRCBreakStmt(rc, ("%Rra\n", (rc)), stmt) + +/** @def AssertLogRelMsgRC + * Asserts a iprt status code successful. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. + */ +#define AssertLogRelMsgRC(rc, msg) AssertLogRelMsg(RT_SUCCESS_NP(rc), msg) + +/** @def AssertLogRelMsgRCReturn + * Asserts a iprt status code successful. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelMsgRCReturn(rc, msg, rcRet) AssertLogRelMsgReturn(RT_SUCCESS_NP(rc), msg, rcRet) + +/** @def AssertLogRelMsgRCReturnStmt + * Asserts a iprt status code successful, execute \a stmt and return on + * failure. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param stmt Statement to execute before returning in case of a failed + * assertion. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelMsgRCReturnStmt(rc, msg, stmt, rcRet) AssertLogRelMsgReturnStmt(RT_SUCCESS_NP(rc), msg, stmt, rcRet) + +/** @def AssertLogRelMsgRCReturnVoid + * Asserts a iprt status code successful. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. + */ +#define AssertLogRelMsgRCReturnVoid(rc, msg) AssertLogRelMsgReturnVoid(RT_SUCCESS_NP(rc), msg) + +/** @def AssertLogRelMsgRCBreak + * Asserts a iprt status code successful. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. + */ +#define AssertLogRelMsgRCBreak(rc, msg) AssertLogRelMsgBreak(RT_SUCCESS(rc), msg) + +/** @def AssertLogRelMsgRCBreakStmt + * Asserts a iprt status code successful, execute \a stmt and break if it isn't. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelMsgRCBreakStmt(rc, msg, stmt) AssertLogRelMsgBreakStmt(RT_SUCCESS_NP(rc), msg, stmt) + +/** @def AssertLogRelRCSuccess + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCSuccess(rc) AssertLogRelMsg((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + +/** @def AssertLogRelRCSuccessReturn + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * @param rc iprt status code. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCSuccessReturn(rc, rcRet) AssertLogRelMsgReturn((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), rcRet) + +/** @def AssertLogRelRCSuccessReturnVoid + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCSuccessReturnVoid(rc) AssertLogRelMsgReturnVoid((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + +/** @def AssertLogRelRCSuccessBreak + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCSuccessBreak(rc) AssertLogRelMsgBreak((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + +/** @def AssertLogRelRCSuccessBreakStmt + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * @param rc iprt status code. + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. + */ +#define AssertLogRelRCSuccessBreakStmt(rc, stmt) AssertLogRelMsgBreakStmt((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), stmt) + + +/** @def AssertReleaseRC + * Asserts a iprt status code successful. + * + * On failure information about the error will be printed and a breakpoint hit. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRC(rc) AssertReleaseMsgRC(rc, ("%Rra\n", (rc))) + +/** @def AssertReleaseRCReturn + * Asserts a iprt status code successful, returning if it isn't. + * + * On failure information about the error will be printed, a breakpoint hit + * and finally returning from the function if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCReturn(rc, rcRet) AssertReleaseMsgRCReturn(rc, ("%Rra\n", (rc)), rcRet) + +/** @def AssertReleaseRCReturnVoid + * Asserts a iprt status code successful, returning if it isn't. + * + * On failure information about the error will be printed, a breakpoint hit + * and finally returning from the function if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCReturnVoid(rc) AssertReleaseMsgRCReturnVoid(rc, ("%Rra\n", (rc))) + +/** @def AssertReleaseRCBreak + * Asserts a iprt status code successful, breaking if it isn't. + * + * On failure information about the error will be printed, a breakpoint hit + * and finally breaking the current statement if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCBreak(rc) AssertReleaseMsgRCBreak(rc, ("%Rra\n", (rc))) + +/** @def AssertReleaseRCBreakStmt + * Asserts a iprt status code successful, break if it isn't. + * + * On failure information about the error will be printed, a breakpoint hit + * and finally the break statement will be issued if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCBreakStmt(rc, stmt) AssertReleaseMsgRCBreakStmt(rc, ("%Rra\n", (rc)), stmt) + +/** @def AssertReleaseMsgRC + * Asserts a iprt status code successful. + * + * On failure a custom message is printed and a breakpoint is hit. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. + */ +#define AssertReleaseMsgRC(rc, msg) AssertReleaseMsg(RT_SUCCESS_NP(rc), msg) + +/** @def AssertReleaseMsgRCReturn + * Asserts a iprt status code successful. + * + * On failure a custom message is printed, a breakpoint is hit, and finally + * returning from the function if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseMsgRCReturn(rc, msg, rcRet) AssertReleaseMsgReturn(RT_SUCCESS_NP(rc), msg, rcRet) + +/** @def AssertReleaseMsgRCReturnVoid + * Asserts a iprt status code successful. + * + * On failure a custom message is printed, a breakpoint is hit, and finally + * returning from the function if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. + */ +#define AssertReleaseMsgRCReturnVoid(rc, msg) AssertReleaseMsgReturnVoid(RT_SUCCESS_NP(rc), msg) + +/** @def AssertReleaseMsgRCBreak + * Asserts a iprt status code successful. + * + * On failure a custom message is printed, a breakpoint is hit, and finally + * breaking the current status if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. + */ +#define AssertReleaseMsgRCBreak(rc, msg) AssertReleaseMsgBreak(RT_SUCCESS(rc), msg) + +/** @def AssertReleaseMsgRCBreakStmt + * Asserts a iprt status code successful. + * + * On failure a custom message is printed, a breakpoint is hit, and finally + * the break statement is issued if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseMsgRCBreakStmt(rc, msg, stmt) AssertReleaseMsgBreakStmt(RT_SUCCESS_NP(rc), msg, stmt) + +/** @def AssertReleaseRCSuccess + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * On failure information about the error will be printed and a breakpoint hit. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCSuccess(rc) AssertReleaseMsg((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + +/** @def AssertReleaseRCSuccessReturn + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * On failure information about the error will be printed, a breakpoint hit + * and finally returning from the function if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @param rcRet What is to be presented to return. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCSuccessReturn(rc, rcRet) AssertReleaseMsgReturn((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), rcRet) + +/** @def AssertReleaseRCSuccessReturnVoid + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * On failure information about the error will be printed, a breakpoint hit + * and finally returning from the function if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCSuccessReturnVoid(rc) AssertReleaseMsgReturnVoid((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + +/** @def AssertReleaseRCSuccessBreak + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * On failure information about the error will be printed, a breakpoint hit + * and finally breaking the current statement if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCSuccessBreak(rc) AssertReleaseMsgBreak((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + +/** @def AssertReleaseRCSuccessBreakStmt + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * On failure information about the error will be printed, a breakpoint hit + * and finally the break statement will be issued if the breakpoint is somehow ignored. + * + * @param rc iprt status code. + * @param stmt Statement to execute before break in case of a failed assertion. + * @remark rc is referenced multiple times. + */ +#define AssertReleaseRCSuccessBreakStmt(rc, stmt) AssertReleaseMsgBreakStmt((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), stmt) + + +/** @def AssertFatalRC + * Asserts a iprt status code successful. + * + * On failure information about the error will be printed and a breakpoint hit. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertFatalRC(rc) AssertFatalMsgRC(rc, ("%Rra\n", (rc))) + +/** @def AssertReleaseMsgRC + * Asserts a iprt status code successful. + * + * On failure a custom message is printed and a breakpoint is hit. + * + * @param rc iprt status code. + * @param msg printf argument list (in parenthesis). + * @remark rc is referenced multiple times. + */ +#define AssertFatalMsgRC(rc, msg) AssertFatalMsg(RT_SUCCESS_NP(rc), msg) + +/** @def AssertFatalRCSuccess + * Asserts that an iprt status code equals VINF_SUCCESS. + * + * On failure information about the error will be printed and a breakpoint hit. + * + * @param rc iprt status code. + * @remark rc is referenced multiple times. + */ +#define AssertFatalRCSuccess(rc) AssertFatalMsg((rc) == VINF_SUCCESS, ("%Rra\n", (rc))) + + +/** @def AssertPtr + * Asserts that a pointer is valid. + * + * @param pv The pointer. + */ +#define AssertPtr(pv) AssertMsg(VALID_PTR(pv), ("%p\n", (pv))) + +/** @def AssertPtrReturn + * Asserts that a pointer is valid. + * + * @param pv The pointer. + * @param rcRet What is to be presented to return. + */ +#define AssertPtrReturn(pv, rcRet) AssertMsgReturn(VALID_PTR(pv), ("%p\n", (pv)), rcRet) + +/** @def AssertPtrReturnVoid + * Asserts that a pointer is valid. + * + * @param pv The pointer. + */ +#define AssertPtrReturnVoid(pv) AssertMsgReturnVoid(VALID_PTR(pv), ("%p\n", (pv))) + +/** @def AssertPtrBreak + * Asserts that a pointer is valid. + * + * @param pv The pointer. + */ +#define AssertPtrBreak(pv) AssertMsgBreak(VALID_PTR(pv), ("%p\n", (pv))) + +/** @def AssertPtrBreakStmt + * Asserts that a pointer is valid. + * + * @param pv The pointer. + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#define AssertPtrBreakStmt(pv, stmt) AssertMsgBreakStmt(VALID_PTR(pv), ("%p\n", (pv)), stmt) + +/** @def AssertPtrNull + * Asserts that a pointer is valid or NULL. + * + * @param pv The pointer. + */ +#define AssertPtrNull(pv) AssertMsg(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv))) + +/** @def AssertPtrNullReturn + * Asserts that a pointer is valid or NULL. + * + * @param pv The pointer. + * @param rcRet What is to be presented to return. + */ +#define AssertPtrNullReturn(pv, rcRet) AssertMsgReturn(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv)), rcRet) + +/** @def AssertPtrNullReturnVoid + * Asserts that a pointer is valid or NULL. + * + * @param pv The pointer. + */ +#define AssertPtrNullReturnVoid(pv) AssertMsgReturnVoid(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv))) + +/** @def AssertPtrNullBreak + * Asserts that a pointer is valid or NULL. + * + * @param pv The pointer. + */ +#define AssertPtrNullBreak(pv) AssertMsgBreak(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv))) + +/** @def AssertPtrNullBreakStmt + * Asserts that a pointer is valid or NULL. + * + * @param pv The pointer. + * @param stmt Statement to execute before break in case of a failed assertion. + */ +#define AssertPtrNullBreakStmt(pv, stmt) AssertMsgBreakStmt(VALID_PTR(pv) || (pv) == NULL, ("%p\n", (pv)), stmt) + +/** @def AssertGCPhys32 + * Asserts that the high dword of a physical address is zero + * + * @param GCPhys The address (RTGCPHYS). + */ +#define AssertGCPhys32(GCPhys) AssertMsg(VALID_PHYS32(GCPhys), ("%RGp\n", (RTGCPHYS)(GCPhys))) + +/** @def AssertGCPtr32 + * Asserts that the high dword of a physical address is zero + * + * @param GCPtr The address (RTGCPTR). + */ +#if GC_ARCH_BITS == 32 +# define AssertGCPtr32(GCPtr) do { } while (0) +#else +# define AssertGCPtr32(GCPtr) AssertMsg(!((GCPtr) & UINT64_C(0xffffffff00000000)), ("%RGv\n", GCPtr)) +#endif + +/** @def AssertForEach + * Equivalent to Assert for each value of the variable from the starting + * value to the finishing one. + * + * @param var Name of the counter variable. + * @param vartype Type of the counter variable. + * @param first Lowest inclusive value of the counter variable. + * This must be free from side effects. + * @param end Highest exclusive value of the counter variable. + * This must be free from side effects. + * @param expr Expression which should be true for each value of @a var. + */ +#define AssertForEach(var, vartype, first, end, expr) \ + do { \ + vartype var; \ + Assert((first) == (first) && (end) == (end)); /* partial check for side effects */ \ + for (var = (first); var < (end); var++) \ + AssertMsg(expr, ("%s = %#RX64 (%RI64)", #var, (uint64_t)var, (int64_t)var)); \ + } while (0) + +/** @} */ + +/** @} */ + +#endif + diff --git a/include/iprt/avl.h b/include/iprt/avl.h new file mode 100644 index 00000000..9c1b99df --- /dev/null +++ b/include/iprt/avl.h @@ -0,0 +1,1114 @@ +/** @file + * IPRT - AVL Trees. + */ + +/* + * Copyright (C) 1999-2003 knut st. osmundsen <bird-src-spam@anduin.net> + * + * 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. + */ + +#ifndef ___iprt_avl_h +#define ___iprt_avl_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_avl RTAvl - AVL Trees + * @ingroup grp_rt + * @{ + */ + + +/** AVL tree of void pointers. + * @{ + */ + +/** + * AVL key type + */ +typedef void * AVLPVKEY; + +/** + * AVL Core node. + */ +typedef struct _AVLPVNodeCore +{ + AVLPVKEY Key; /** Key value. */ + struct _AVLPVNodeCore *pLeft; /** Pointer to left leaf node. */ + struct _AVLPVNodeCore *pRight; /** Pointer to right leaf node. */ + unsigned char uchHeight; /** Height of this tree: max(height(left), height(right)) + 1 */ +} AVLPVNODECORE, *PAVLPVNODECORE, **PPAVLPVNODECORE; + +/** A tree with void pointer keys. */ +typedef PAVLPVNODECORE AVLPVTREE; +/** Pointer to a tree with void pointer keys. */ +typedef PPAVLPVNODECORE PAVLPVTREE; + +/** Callback function for AVLPVDoWithAll(). */ +typedef DECLCALLBACK(int) AVLPVCALLBACK(PAVLPVNODECORE, void *); +/** Pointer to callback function for AVLPVDoWithAll(). */ +typedef AVLPVCALLBACK *PAVLPVCALLBACK; + +/* + * Functions. + */ +RTDECL(bool) RTAvlPVInsert(PAVLPVTREE ppTree, PAVLPVNODECORE pNode); +RTDECL(PAVLPVNODECORE) RTAvlPVRemove(PAVLPVTREE ppTree, AVLPVKEY Key); +RTDECL(PAVLPVNODECORE) RTAvlPVGet(PAVLPVTREE ppTree, AVLPVKEY Key); +RTDECL(PAVLPVNODECORE) RTAvlPVGetBestFit(PAVLPVTREE ppTree, AVLPVKEY Key, bool fAbove); +RTDECL(PAVLPVNODECORE) RTAvlPVRemoveBestFit(PAVLPVTREE ppTree, AVLPVKEY Key, bool fAbove); +RTDECL(int) RTAvlPVDoWithAll(PAVLPVTREE ppTree, int fFromLeft, PAVLPVCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlPVDestroy(PAVLPVTREE ppTree, PAVLPVCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + +/** AVL tree of unsigned long. + * @{ + */ + +/** + * AVL key type + */ +typedef unsigned long AVLULKEY; + +/** + * AVL Core node. + */ +typedef struct _AVLULNodeCore +{ + AVLULKEY Key; /** Key value. */ + struct _AVLULNodeCore *pLeft; /** Pointer to left leaf node. */ + struct _AVLULNodeCore *pRight; /** Pointer to right leaf node. */ + unsigned char uchHeight; /** Height of this tree: max(height(left), height(right)) + 1 */ +} AVLULNODECORE, *PAVLULNODECORE, **PPAVLULNODECORE; + + +/** Callback function for AVLULDoWithAll(). */ +typedef DECLCALLBACK(int) AVLULCALLBACK(PAVLULNODECORE, void*); +/** Pointer to callback function for AVLULDoWithAll(). */ +typedef AVLULCALLBACK *PAVLULCALLBACK; + + +/* + * Functions. + */ +RTDECL(bool) RTAvlULInsert(PPAVLULNODECORE ppTree, PAVLULNODECORE pNode); +RTDECL(PAVLULNODECORE) RTAvlULRemove(PPAVLULNODECORE ppTree, AVLULKEY Key); +RTDECL(PAVLULNODECORE) RTAvlULGet(PPAVLULNODECORE ppTree, AVLULKEY Key); +RTDECL(PAVLULNODECORE) RTAvlULGetBestFit(PPAVLULNODECORE ppTree, AVLULKEY Key, bool fAbove); +RTDECL(PAVLULNODECORE) RTAvlULRemoveBestFit(PPAVLULNODECORE ppTree, AVLULKEY Key, bool fAbove); +RTDECL(int) RTAvlULDoWithAll(PPAVLULNODECORE ppTree, int fFromLeft, PAVLULCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlULDestroy(PPAVLULNODECORE pTree, PAVLULCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + + +/** AVL tree of void pointer ranges. + * @{ + */ + +/** + * AVL key type + */ +typedef void *AVLRPVKEY; + +/** + * AVL Core node. + */ +typedef struct AVLRPVNodeCore +{ + AVLRPVKEY Key; /**< First key value in the range (inclusive). */ + AVLRPVKEY KeyLast; /**< Last key value in the range (inclusive). */ + struct AVLRPVNodeCore *pLeft; /**< Pointer to left leaf node. */ + struct AVLRPVNodeCore *pRight; /**< Pointer to right leaf node. */ + unsigned char uchHeight; /**< Height of this tree: max(height(left), height(right)) + 1 */ +} AVLRPVNODECORE, *PAVLRPVNODECORE, **PPAVLRPVNODECORE; + +/** A tree with void pointer keys. */ +typedef PAVLRPVNODECORE AVLRPVTREE; +/** Pointer to a tree with void pointer keys. */ +typedef PPAVLRPVNODECORE PAVLRPVTREE; + +/** Callback function for AVLPVDoWithAll(). */ +typedef DECLCALLBACK(int) AVLRPVCALLBACK(PAVLRPVNODECORE, void *); +/** Pointer to callback function for AVLPVDoWithAll(). */ +typedef AVLRPVCALLBACK *PAVLRPVCALLBACK; + +/* + * Functions. + */ +RTDECL(bool) RTAvlrPVInsert(PAVLRPVTREE ppTree, PAVLRPVNODECORE pNode); +RTDECL(PAVLRPVNODECORE) RTAvlrPVRemove(PAVLRPVTREE ppTree, AVLRPVKEY Key); +RTDECL(PAVLRPVNODECORE) RTAvlrPVGet(PAVLRPVTREE ppTree, AVLRPVKEY Key); +RTDECL(PAVLRPVNODECORE) RTAvlrPVRangeGet(PAVLRPVTREE ppTree, AVLRPVKEY Key); +RTDECL(PAVLRPVNODECORE) RTAvlrPVRangeRemove(PAVLRPVTREE ppTree, AVLRPVKEY Key); +RTDECL(PAVLRPVNODECORE) RTAvlrPVGetBestFit(PAVLRPVTREE ppTree, AVLRPVKEY Key, bool fAbove); +RTDECL(PAVLRPVNODECORE) RTAvlrPVRemoveBestFit(PAVLRPVTREE ppTree, AVLRPVKEY Key, bool fAbove); +RTDECL(int) RTAvlrPVDoWithAll(PAVLRPVTREE ppTree, int fFromLeft, PAVLRPVCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlrPVDestroy(PAVLRPVTREE ppTree, PAVLRPVCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + + +/** AVL tree of uint32_t + * @{ + */ + +/** AVL key type. */ +typedef uint32_t AVLU32KEY; + +/** AVL Core node. */ +typedef struct _AVLU32NodeCore +{ + AVLU32KEY Key; /**< Key value. */ + struct _AVLU32NodeCore *pLeft; /**< Pointer to left leaf node. */ + struct _AVLU32NodeCore *pRight; /**< Pointer to right leaf node. */ + unsigned char uchHeight; /**< Height of this tree: max(height(left), height(right)) + 1 */ +} AVLU32NODECORE, *PAVLU32NODECORE, **PPAVLU32NODECORE; + +/** A tree with void pointer keys. */ +typedef PAVLU32NODECORE AVLU32TREE; +/** Pointer to a tree with void pointer keys. */ +typedef PPAVLU32NODECORE PAVLU32TREE; + +/** Callback function for AVLU32DoWithAll() & AVLU32Destroy(). */ +typedef DECLCALLBACK(int) AVLU32CALLBACK(PAVLU32NODECORE, void*); +/** Pointer to callback function for AVLU32DoWithAll() & AVLU32Destroy(). */ +typedef AVLU32CALLBACK *PAVLU32CALLBACK; + + +/* + * Functions. + */ +RTDECL(bool) RTAvlU32Insert(PAVLU32TREE pTree, PAVLU32NODECORE pNode); +RTDECL(PAVLU32NODECORE) RTAvlU32Remove(PAVLU32TREE pTree, AVLU32KEY Key); +RTDECL(PAVLU32NODECORE) RTAvlU32Get(PAVLU32TREE pTree, AVLU32KEY Key); +RTDECL(PAVLU32NODECORE) RTAvlU32GetBestFit(PAVLU32TREE pTree, AVLU32KEY Key, bool fAbove); +RTDECL(PAVLU32NODECORE) RTAvlU32RemoveBestFit(PAVLU32TREE pTree, AVLU32KEY Key, bool fAbove); +RTDECL(int) RTAvlU32DoWithAll(PAVLU32TREE pTree, int fFromLeft, PAVLU32CALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlU32Destroy(PAVLU32TREE pTree, PAVLU32CALLBACK pfnCallBack, void *pvParam); + +/** @} */ + +/** + * AVL uint32_t type for the relative offset pointer scheme. + */ +typedef int32_t AVLOU32; + +typedef uint32_t AVLOU32KEY; + +/** + * AVL Core node. + */ +typedef struct _AVLOU32NodeCore +{ + /** Key value. */ + AVLOU32KEY Key; + /** Offset to the left leaf node, relative to this field. */ + AVLOU32 pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLOU32 pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLOU32NODECORE, *PAVLOU32NODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLOU32 AVLOU32TREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLOU32TREE *PAVLOU32TREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLOU32TREE *PPAVLOU32NODECORE; + +/** Callback function for RTAvloU32DoWithAll(). */ +typedef DECLCALLBACK(int) AVLOU32CALLBACK(PAVLOU32NODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvloU32DoWithAll(). */ +typedef AVLOU32CALLBACK *PAVLOU32CALLBACK; + +RTDECL(bool) RTAvloU32Insert(PAVLOU32TREE pTree, PAVLOU32NODECORE pNode); +RTDECL(PAVLOU32NODECORE) RTAvloU32Remove(PAVLOU32TREE pTree, AVLOU32KEY Key); +RTDECL(PAVLOU32NODECORE) RTAvloU32Get(PAVLOU32TREE pTree, AVLOU32KEY Key); +RTDECL(int) RTAvloU32DoWithAll(PAVLOU32TREE pTree, int fFromLeft, PAVLOU32CALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLOU32NODECORE) RTAvloU32GetBestFit(PAVLOU32TREE ppTree, AVLOU32KEY Key, bool fAbove); +RTDECL(PAVLOU32NODECORE) RTAvloU32RemoveBestFit(PAVLOU32TREE ppTree, AVLOU32KEY Key, bool fAbove); +RTDECL(int) RTAvloU32Destroy(PAVLOU32TREE pTree, PAVLOU32CALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + +/** AVL tree of uint32_t, list duplicates. + * @{ + */ + +/** AVL key type. */ +typedef uint32_t AVLLU32KEY; + +/** AVL Core node. */ +typedef struct _AVLLU32NodeCore +{ + AVLLU32KEY Key; /**< Key value. */ + unsigned char uchHeight; /**< Height of this tree: max(height(left), height(right)) + 1 */ + struct _AVLLU32NodeCore *pLeft; /**< Pointer to left leaf node. */ + struct _AVLLU32NodeCore *pRight; /**< Pointer to right leaf node. */ + struct _AVLLU32NodeCore *pList; /**< Pointer to next node with the same key. */ +} AVLLU32NODECORE, *PAVLLU32NODECORE, **PPAVLLU32NODECORE; + +/** Callback function for RTAvllU32DoWithAll() & RTAvllU32Destroy(). */ +typedef DECLCALLBACK(int) AVLLU32CALLBACK(PAVLLU32NODECORE, void*); +/** Pointer to callback function for RTAvllU32DoWithAll() & RTAvllU32Destroy(). */ +typedef AVLLU32CALLBACK *PAVLLU32CALLBACK; + + +/* + * Functions. + */ +RTDECL(bool) RTAvllU32Insert(PPAVLLU32NODECORE ppTree, PAVLLU32NODECORE pNode); +RTDECL(PAVLLU32NODECORE) RTAvllU32Remove(PPAVLLU32NODECORE ppTree, AVLLU32KEY Key); +RTDECL(PAVLLU32NODECORE) RTAvllU32RemoveNode(PPAVLLU32NODECORE ppTree, PAVLLU32NODECORE pNode); +RTDECL(PAVLLU32NODECORE) RTAvllU32Get(PPAVLLU32NODECORE ppTree, AVLLU32KEY Key); +RTDECL(PAVLLU32NODECORE) RTAvllU32GetBestFit(PPAVLLU32NODECORE ppTree, AVLLU32KEY Key, bool fAbove); +RTDECL(PAVLLU32NODECORE) RTAvllU32RemoveBestFit(PPAVLLU32NODECORE ppTree, AVLLU32KEY Key, bool fAbove); +RTDECL(int) RTAvllU32DoWithAll(PPAVLLU32NODECORE ppTree, int fFromLeft, PAVLLU32CALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvllU32Destroy(PPAVLLU32NODECORE pTree, PAVLLU32CALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + + +/** AVL tree of uint64_t ranges. + * @{ + */ + +/** + * AVL key type + */ +typedef uint64_t AVLRU64KEY; + +/** + * AVL Core node. + */ +typedef struct AVLRU64NodeCore +{ + AVLRU64KEY Key; /**< First key value in the range (inclusive). */ + AVLRU64KEY KeyLast; /**< Last key value in the range (inclusive). */ + struct AVLRU64NodeCore *pLeft; /**< Pointer to left leaf node. */ + struct AVLRU64NodeCore *pRight; /**< Pointer to right leaf node. */ + unsigned char uchHeight; /**< Height of this tree: max(height(left), height(right)) + 1 */ +} AVLRU64NODECORE, *PAVLRU64NODECORE, **PPAVLRU64NODECORE; + +/** A tree with void pointer keys. */ +typedef PAVLRU64NODECORE AVLRU64TREE; +/** Pointer to a tree with void pointer keys. */ +typedef PPAVLRU64NODECORE PAVLRU64TREE; + +/** Callback function for AVLRU64DoWithAll(). */ +typedef DECLCALLBACK(int) AVLRU64CALLBACK(PAVLRU64NODECORE, void *); +/** Pointer to callback function for AVLU64DoWithAll(). */ +typedef AVLRU64CALLBACK *PAVLRU64CALLBACK; + +/* + * Functions. + */ +RTDECL(bool) RTAvlrU64Insert(PAVLRU64TREE ppTree, PAVLRU64NODECORE pNode); +RTDECL(PAVLRU64NODECORE) RTAvlrU64Remove(PAVLRU64TREE ppTree, AVLRU64KEY Key); +RTDECL(PAVLRU64NODECORE) RTAvlrU64Get(PAVLRU64TREE ppTree, AVLRU64KEY Key); +RTDECL(PAVLRU64NODECORE) RTAvlrU64RangeGet(PAVLRU64TREE ppTree, AVLRU64KEY Key); +RTDECL(PAVLRU64NODECORE) RTAvlrU64RangeRemove(PAVLRU64TREE ppTree, AVLRU64KEY Key); +RTDECL(PAVLRU64NODECORE) RTAvlrU64GetBestFit(PAVLRU64TREE ppTree, AVLRU64KEY Key, bool fAbove); +RTDECL(PAVLRU64NODECORE) RTAvlrU64RemoveBestFit(PAVLRU64TREE ppTree, AVLRU64KEY Key, bool fAbove); +RTDECL(int) RTAvlrU64DoWithAll(PAVLRU64TREE ppTree, int fFromLeft, PAVLRU64CALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlrU64Destroy(PAVLRU64TREE ppTree, PAVLRU64CALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + + +/** AVL tree of RTGCPHYSes - using relative offsets internally. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef int32_t AVLOGCPHYS; + +/** + * AVL Core node. + */ +typedef struct _AVLOGCPhysNodeCore +{ + /** Key value. */ + RTGCPHYS Key; + /** Offset to the left leaf node, relative to this field. */ + AVLOGCPHYS pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLOGCPHYS pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; + /** Padding */ + unsigned char Padding[7]; +} AVLOGCPHYSNODECORE, *PAVLOGCPHYSNODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLOGCPHYS AVLOGCPHYSTREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLOGCPHYSTREE *PAVLOGCPHYSTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLOGCPHYSTREE *PPAVLOGCPHYSNODECORE; + +/** Callback function for RTAvloGCPhysDoWithAll() and RTAvloGCPhysDestroy(). */ +typedef DECLCALLBACK(int) AVLOGCPHYSCALLBACK(PAVLOGCPHYSNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvloGCPhysDoWithAll() and RTAvloGCPhysDestroy(). */ +typedef AVLOGCPHYSCALLBACK *PAVLOGCPHYSCALLBACK; + +RTDECL(bool) RTAvloGCPhysInsert(PAVLOGCPHYSTREE pTree, PAVLOGCPHYSNODECORE pNode); +RTDECL(PAVLOGCPHYSNODECORE) RTAvloGCPhysRemove(PAVLOGCPHYSTREE pTree, RTGCPHYS Key); +RTDECL(PAVLOGCPHYSNODECORE) RTAvloGCPhysGet(PAVLOGCPHYSTREE pTree, RTGCPHYS Key); +RTDECL(int) RTAvloGCPhysDoWithAll(PAVLOGCPHYSTREE pTree, int fFromLeft, PAVLOGCPHYSCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLOGCPHYSNODECORE) RTAvloGCPhysGetBestFit(PAVLOGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove); +RTDECL(PAVLOGCPHYSNODECORE) RTAvloGCPhysRemoveBestFit(PAVLOGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove); +RTDECL(int) RTAvloGCPhysDestroy(PAVLOGCPHYSTREE pTree, PAVLOGCPHYSCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + +/** AVL tree of RTGCPHYS ranges - using relative offsets internally. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef int32_t AVLROGCPHYS; + +/** + * AVL Core node. + */ +typedef struct _AVLROGCPhysNodeCore +{ + /** First key value in the range (inclusive). */ + RTGCPHYS Key; + /** Last key value in the range (inclusive). */ + RTGCPHYS KeyLast; + /** Offset to the left leaf node, relative to this field. */ + AVLROGCPHYS pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLROGCPHYS pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; + /** Padding */ + unsigned char Padding[7]; +} AVLROGCPHYSNODECORE, *PAVLROGCPHYSNODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLROGCPHYS AVLROGCPHYSTREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLROGCPHYSTREE *PAVLROGCPHYSTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLROGCPHYSTREE *PPAVLROGCPHYSNODECORE; + +/** Callback function for RTAvlroGCPhysDoWithAll() and RTAvlroGCPhysDestroy(). */ +typedef DECLCALLBACK(int) AVLROGCPHYSCALLBACK(PAVLROGCPHYSNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlroGCPhysDoWithAll() and RTAvlroGCPhysDestroy(). */ +typedef AVLROGCPHYSCALLBACK *PAVLROGCPHYSCALLBACK; + +RTDECL(bool) RTAvlroGCPhysInsert(PAVLROGCPHYSTREE pTree, PAVLROGCPHYSNODECORE pNode); +RTDECL(PAVLROGCPHYSNODECORE) RTAvlroGCPhysRemove(PAVLROGCPHYSTREE pTree, RTGCPHYS Key); +RTDECL(PAVLROGCPHYSNODECORE) RTAvlroGCPhysGet(PAVLROGCPHYSTREE pTree, RTGCPHYS Key); +RTDECL(PAVLROGCPHYSNODECORE) RTAvlroGCPhysRangeGet(PAVLROGCPHYSTREE pTree, RTGCPHYS Key); +RTDECL(PAVLROGCPHYSNODECORE) RTAvlroGCPhysRangeRemove(PAVLROGCPHYSTREE pTree, RTGCPHYS Key); +RTDECL(PAVLROGCPHYSNODECORE) RTAvlroGCPhysGetBestFit(PAVLROGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove); +RTDECL(int) RTAvlroGCPhysDoWithAll(PAVLROGCPHYSTREE pTree, int fFromLeft, PAVLROGCPHYSCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlroGCPhysDestroy(PAVLROGCPHYSTREE pTree, PAVLROGCPHYSCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLROGCPHYSNODECORE) RTAvlroGCPhysGetRoot(PAVLROGCPHYSTREE pTree); +RTDECL(PAVLROGCPHYSNODECORE) RTAvlroGCPhysGetLeft(PAVLROGCPHYSNODECORE pNode); +RTDECL(PAVLROGCPHYSNODECORE) RTAvlroGCPhysGetRight(PAVLROGCPHYSNODECORE pNode); + +/** @} */ + + +/** AVL tree of RTGCPTRs. + * @{ + */ + +/** + * AVL Core node. + */ +typedef struct _AVLGCPtrNodeCore +{ + /** Key value. */ + RTGCPTR Key; + /** Pointer to the left node. */ + struct _AVLGCPtrNodeCore *pLeft; + /** Pointer to the right node. */ + struct _AVLGCPtrNodeCore *pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLGCPTRNODECORE, *PAVLGCPTRNODECORE, **PPAVLGCPTRNODECORE; + +/** A tree of RTGCPTR keys. */ +typedef PAVLGCPTRNODECORE AVLGCPTRTREE; +/** Pointer to a tree of RTGCPTR keys. */ +typedef PPAVLGCPTRNODECORE PAVLGCPTRTREE; + +/** Callback function for RTAvlGCPtrDoWithAll(). */ +typedef DECLCALLBACK(int) AVLGCPTRCALLBACK(PAVLGCPTRNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlGCPtrDoWithAll(). */ +typedef AVLGCPTRCALLBACK *PAVLGCPTRCALLBACK; + +RTDECL(bool) RTAvlGCPtrInsert(PAVLGCPTRTREE pTree, PAVLGCPTRNODECORE pNode); +RTDECL(PAVLGCPTRNODECORE) RTAvlGCPtrRemove(PAVLGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLGCPTRNODECORE) RTAvlGCPtrGet(PAVLGCPTRTREE pTree, RTGCPTR Key); +RTDECL(int) RTAvlGCPtrDoWithAll(PAVLGCPTRTREE pTree, int fFromLeft, PAVLGCPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLGCPTRNODECORE) RTAvlGCPtrGetBestFit(PAVLGCPTRTREE ppTree, RTGCPTR Key, bool fAbove); +RTDECL(PAVLGCPTRNODECORE) RTAvlGCPtrRemoveBestFit(PAVLGCPTRTREE ppTree, RTGCPTR Key, bool fAbove); +RTDECL(int) RTAvlGCPtrDestroy(PAVLGCPTRTREE pTree, PAVLGCPTRCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + +/** AVL tree of RTGCPTRs - using relative offsets internally. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef int32_t AVLOGCPTR; + +/** + * AVL Core node. + */ +typedef struct _AVLOGCPtrNodeCore +{ + /** Key value. */ + RTGCPTR Key; + /** Offset to the left leaf node, relative to this field. */ + AVLOGCPTR pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLOGCPTR pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; + unsigned char padding[GC_ARCH_BITS == 64 ? 7 : 3]; +} AVLOGCPTRNODECORE, *PAVLOGCPTRNODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLOGCPTR AVLOGCPTRTREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLOGCPTRTREE *PAVLOGCPTRTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLOGCPTRTREE *PPAVLOGCPTRNODECORE; + +/** Callback function for RTAvloGCPtrDoWithAll(). */ +typedef DECLCALLBACK(int) AVLOGCPTRCALLBACK(PAVLOGCPTRNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvloGCPtrDoWithAll(). */ +typedef AVLOGCPTRCALLBACK *PAVLOGCPTRCALLBACK; + +RTDECL(bool) RTAvloGCPtrInsert(PAVLOGCPTRTREE pTree, PAVLOGCPTRNODECORE pNode); +RTDECL(PAVLOGCPTRNODECORE) RTAvloGCPtrRemove(PAVLOGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLOGCPTRNODECORE) RTAvloGCPtrGet(PAVLOGCPTRTREE pTree, RTGCPTR Key); +RTDECL(int) RTAvloGCPtrDoWithAll(PAVLOGCPTRTREE pTree, int fFromLeft, PAVLOGCPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLOGCPTRNODECORE) RTAvloGCPtrGetBestFit(PAVLOGCPTRTREE ppTree, RTGCPTR Key, bool fAbove); +RTDECL(PAVLOGCPTRNODECORE) RTAvloGCPtrRemoveBestFit(PAVLOGCPTRTREE ppTree, RTGCPTR Key, bool fAbove); +RTDECL(int) RTAvloGCPtrDestroy(PAVLOGCPTRTREE pTree, PAVLOGCPTRCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + +/** AVL tree of RTGCPTR ranges. + * @{ + */ + +/** + * AVL Core node. + */ +typedef struct _AVLRGCPtrNodeCore +{ + /** First key value in the range (inclusive). */ + RTGCPTR Key; + /** Last key value in the range (inclusive). */ + RTGCPTR KeyLast; + /** Offset to the left leaf node, relative to this field. */ + struct _AVLRGCPtrNodeCore *pLeft; + /** Offset to the right leaf node, relative to this field. */ + struct _AVLRGCPtrNodeCore *pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLRGCPTRNODECORE, *PAVLRGCPTRNODECORE; + +/** A offset base tree with RTGCPTR keys. */ +typedef PAVLRGCPTRNODECORE AVLRGCPTRTREE; +/** Pointer to an offset base tree with RTGCPTR keys. */ +typedef AVLRGCPTRTREE *PAVLRGCPTRTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLRGCPTRTREE *PPAVLRGCPTRNODECORE; + +/** Callback function for RTAvlrGCPtrDoWithAll() and RTAvlrGCPtrDestroy(). */ +typedef DECLCALLBACK(int) AVLRGCPTRCALLBACK(PAVLRGCPTRNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlrGCPtrDoWithAll() and RTAvlrGCPtrDestroy(). */ +typedef AVLRGCPTRCALLBACK *PAVLRGCPTRCALLBACK; + +RTDECL(bool) RTAvlrGCPtrInsert( PAVLRGCPTRTREE pTree, PAVLRGCPTRNODECORE pNode); +RTDECL(PAVLRGCPTRNODECORE) RTAvlrGCPtrRemove( PAVLRGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLRGCPTRNODECORE) RTAvlrGCPtrGet( PAVLRGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLRGCPTRNODECORE) RTAvlrGCPtrGetBestFit( PAVLRGCPTRTREE pTree, RTGCPTR Key, bool fAbove); +RTDECL(PAVLRGCPTRNODECORE) RTAvlrGCPtrRangeGet( PAVLRGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLRGCPTRNODECORE) RTAvlrGCPtrRangeRemove( PAVLRGCPTRTREE pTree, RTGCPTR Key); +RTDECL(int) RTAvlrGCPtrDoWithAll( PAVLRGCPTRTREE pTree, int fFromLeft, PAVLRGCPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlrGCPtrDestroy( PAVLRGCPTRTREE pTree, PAVLRGCPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLRGCPTRNODECORE) RTAvlrGCPtrGetRoot( PAVLRGCPTRTREE pTree); +RTDECL(PAVLRGCPTRNODECORE) RTAvlrGCPtrGetLeft( PAVLRGCPTRNODECORE pNode); +RTDECL(PAVLRGCPTRNODECORE) RTAvlrGCPtrGetRight( PAVLRGCPTRNODECORE pNode); + +/** @} */ + + +/** AVL tree of RTGCPTR ranges - using relative offsets internally. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef int32_t AVLROGCPTR; + +/** + * AVL Core node. + */ +typedef struct _AVLROGCPtrNodeCore +{ + /** First key value in the range (inclusive). */ + RTGCPTR Key; + /** Last key value in the range (inclusive). */ + RTGCPTR KeyLast; + /** Offset to the left leaf node, relative to this field. */ + AVLROGCPTR pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLROGCPTR pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; + unsigned char padding[GC_ARCH_BITS == 64 ? 7 : 7]; +} AVLROGCPTRNODECORE, *PAVLROGCPTRNODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLROGCPTR AVLROGCPTRTREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLROGCPTRTREE *PAVLROGCPTRTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLROGCPTRTREE *PPAVLROGCPTRNODECORE; + +/** Callback function for RTAvlroGCPtrDoWithAll() and RTAvlroGCPtrDestroy(). */ +typedef DECLCALLBACK(int) AVLROGCPTRCALLBACK(PAVLROGCPTRNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlroGCPtrDoWithAll() and RTAvlroGCPtrDestroy(). */ +typedef AVLROGCPTRCALLBACK *PAVLROGCPTRCALLBACK; + +RTDECL(bool) RTAvlroGCPtrInsert(PAVLROGCPTRTREE pTree, PAVLROGCPTRNODECORE pNode); +RTDECL(PAVLROGCPTRNODECORE) RTAvlroGCPtrRemove(PAVLROGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLROGCPTRNODECORE) RTAvlroGCPtrGet(PAVLROGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLROGCPTRNODECORE) RTAvlroGCPtrGetBestFit(PAVLROGCPTRTREE ppTree, RTGCPTR Key, bool fAbove); +RTDECL(PAVLROGCPTRNODECORE) RTAvlroGCPtrRangeGet(PAVLROGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLROGCPTRNODECORE) RTAvlroGCPtrRangeRemove(PAVLROGCPTRTREE pTree, RTGCPTR Key); +RTDECL(int) RTAvlroGCPtrDoWithAll(PAVLROGCPTRTREE pTree, int fFromLeft, PAVLROGCPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlroGCPtrDestroy(PAVLROGCPTRTREE pTree, PAVLROGCPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLROGCPTRNODECORE) RTAvlroGCPtrGetRoot(PAVLROGCPTRTREE pTree); +RTDECL(PAVLROGCPTRNODECORE) RTAvlroGCPtrGetLeft(PAVLROGCPTRNODECORE pNode); +RTDECL(PAVLROGCPTRNODECORE) RTAvlroGCPtrGetRight(PAVLROGCPTRNODECORE pNode); + +/** @} */ + + +/** AVL tree of RTGCPTR ranges (overlapping supported) - using relative offsets internally. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef int32_t AVLROOGCPTR; + +/** + * AVL Core node. + */ +typedef struct _AVLROOGCPtrNodeCore +{ + /** First key value in the range (inclusive). */ + RTGCPTR Key; + /** Last key value in the range (inclusive). */ + RTGCPTR KeyLast; + /** Offset to the left leaf node, relative to this field. */ + AVLROOGCPTR pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLROOGCPTR pRight; + /** Pointer to the list of string with the same key. Don't touch. */ + AVLROOGCPTR pList; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLROOGCPTRNODECORE, *PAVLROOGCPTRNODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLROOGCPTR AVLROOGCPTRTREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLROOGCPTRTREE *PAVLROOGCPTRTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLROOGCPTRTREE *PPAVLROOGCPTRNODECORE; + +/** Callback function for RTAvlrooGCPtrDoWithAll() and RTAvlrooGCPtrDestroy(). */ +typedef DECLCALLBACK(int) AVLROOGCPTRCALLBACK(PAVLROOGCPTRNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlrooGCPtrDoWithAll() and RTAvlrooGCPtrDestroy(). */ +typedef AVLROOGCPTRCALLBACK *PAVLROOGCPTRCALLBACK; + +RTDECL(bool) RTAvlrooGCPtrInsert(PAVLROOGCPTRTREE pTree, PAVLROOGCPTRNODECORE pNode); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrRemove(PAVLROOGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrGet(PAVLROOGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrGetBestFit(PAVLROOGCPTRTREE ppTree, RTGCPTR Key, bool fAbove); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrRangeGet(PAVLROOGCPTRTREE pTree, RTGCPTR Key); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrRangeRemove(PAVLROOGCPTRTREE pTree, RTGCPTR Key); +RTDECL(int) RTAvlrooGCPtrDoWithAll(PAVLROOGCPTRTREE pTree, int fFromLeft, PAVLROOGCPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlrooGCPtrDestroy(PAVLROOGCPTRTREE pTree, PAVLROOGCPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrGetRoot(PAVLROOGCPTRTREE pTree); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrGetLeft(PAVLROOGCPTRNODECORE pNode); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrGetRight(PAVLROOGCPTRNODECORE pNode); +RTDECL(PAVLROOGCPTRNODECORE) RTAvlrooGCPtrGetNextEqual(PAVLROOGCPTRNODECORE pNode); + +/** @} */ + + +/** AVL tree of RTUINTPTR. + * @{ + */ + +/** + * AVL RTUINTPTR node core. + */ +typedef struct _AVLUIntPtrNodeCore +{ + /** Key value. */ + RTUINTPTR Key; + /** Offset to the left leaf node, relative to this field. */ + struct _AVLUIntPtrNodeCore *pLeft; + /** Offset to the right leaf node, relative to this field. */ + struct _AVLUIntPtrNodeCore *pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLUINTPTRNODECORE; +/** Pointer to a RTUINTPTR AVL node core.*/ +typedef AVLUINTPTRNODECORE *PAVLUINTPTRNODECORE; + +/** A pointer based tree with RTUINTPTR keys. */ +typedef PAVLUINTPTRNODECORE AVLUINTPTRTREE; +/** Pointer to an offset base tree with RTUINTPTR keys. */ +typedef AVLUINTPTRTREE *PAVLUINTPTRTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a pointer. */ +typedef AVLUINTPTRTREE *PPAVLUINTPTRNODECORE; + +/** Callback function for RTAvlUIntPtrDoWithAll() and RTAvlUIntPtrDestroy(). */ +typedef DECLCALLBACK(int) AVLUINTPTRCALLBACK(PAVLUINTPTRNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlUIntPtrDoWithAll() and RTAvlUIntPtrDestroy(). */ +typedef AVLUINTPTRCALLBACK *PAVLUINTPTRCALLBACK; + +RTDECL(bool) RTAvlUIntPtrInsert( PAVLUINTPTRTREE pTree, PAVLUINTPTRNODECORE pNode); +RTDECL(PAVLUINTPTRNODECORE) RTAvlUIntPtrRemove( PAVLUINTPTRTREE pTree, RTUINTPTR Key); +RTDECL(PAVLUINTPTRNODECORE) RTAvlUIntPtrGet( PAVLUINTPTRTREE pTree, RTUINTPTR Key); +RTDECL(PAVLUINTPTRNODECORE) RTAvlUIntPtrGetBestFit(PAVLUINTPTRTREE pTree, RTUINTPTR Key, bool fAbove); +RTDECL(int) RTAvlUIntPtrDoWithAll( PAVLUINTPTRTREE pTree, int fFromLeft, PAVLUINTPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlUIntPtrDestroy( PAVLUINTPTRTREE pTree, PAVLUINTPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLUINTPTRNODECORE) RTAvlUIntPtrGetRoot( PAVLUINTPTRTREE pTree); +RTDECL(PAVLUINTPTRNODECORE) RTAvlUIntPtrGetLeft( PAVLUINTPTRNODECORE pNode); +RTDECL(PAVLUINTPTRNODECORE) RTAvlUIntPtrGetRight( PAVLUINTPTRNODECORE pNode); + +/** @} */ + + +/** AVL tree of RTUINTPTR ranges. + * @{ + */ + +/** + * AVL RTUINTPTR range node core. + */ +typedef struct _AVLRUIntPtrNodeCore +{ + /** First key value in the range (inclusive). */ + RTUINTPTR Key; + /** Last key value in the range (inclusive). */ + RTUINTPTR KeyLast; + /** Offset to the left leaf node, relative to this field. */ + struct _AVLRUIntPtrNodeCore *pLeft; + /** Offset to the right leaf node, relative to this field. */ + struct _AVLRUIntPtrNodeCore *pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLRUINTPTRNODECORE; +/** Pointer to an AVL RTUINTPTR range node code. */ +typedef AVLRUINTPTRNODECORE *PAVLRUINTPTRNODECORE; + +/** A pointer based tree with RTUINTPTR ranges. */ +typedef PAVLRUINTPTRNODECORE AVLRUINTPTRTREE; +/** Pointer to a pointer based tree with RTUINTPTR ranges. */ +typedef AVLRUINTPTRTREE *PAVLRUINTPTRTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a pointer. */ +typedef AVLRUINTPTRTREE *PPAVLRUINTPTRNODECORE; + +/** Callback function for RTAvlrUIntPtrDoWithAll() and RTAvlrUIntPtrDestroy(). */ +typedef DECLCALLBACK(int) AVLRUINTPTRCALLBACK(PAVLRUINTPTRNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlrUIntPtrDoWithAll() and RTAvlrUIntPtrDestroy(). */ +typedef AVLRUINTPTRCALLBACK *PAVLRUINTPTRCALLBACK; + +RTDECL(bool) RTAvlrUIntPtrInsert( PAVLRUINTPTRTREE pTree, PAVLRUINTPTRNODECORE pNode); +RTDECL(PAVLRUINTPTRNODECORE) RTAvlrUIntPtrRemove( PAVLRUINTPTRTREE pTree, RTUINTPTR Key); +RTDECL(PAVLRUINTPTRNODECORE) RTAvlrUIntPtrGet( PAVLRUINTPTRTREE pTree, RTUINTPTR Key); +RTDECL(PAVLRUINTPTRNODECORE) RTAvlrUIntPtrGetBestFit( PAVLRUINTPTRTREE pTree, RTUINTPTR Key, bool fAbove); +RTDECL(PAVLRUINTPTRNODECORE) RTAvlrUIntPtrRangeGet( PAVLRUINTPTRTREE pTree, RTUINTPTR Key); +RTDECL(PAVLRUINTPTRNODECORE) RTAvlrUIntPtrRangeRemove(PAVLRUINTPTRTREE pTree, RTUINTPTR Key); +RTDECL(int) RTAvlrUIntPtrDoWithAll( PAVLRUINTPTRTREE pTree, int fFromLeft, PAVLRUINTPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlrUIntPtrDestroy( PAVLRUINTPTRTREE pTree, PAVLRUINTPTRCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLRUINTPTRNODECORE) RTAvlrUIntPtrGetRoot( PAVLRUINTPTRTREE pTree); +RTDECL(PAVLRUINTPTRNODECORE) RTAvlrUIntPtrGetLeft( PAVLRUINTPTRNODECORE pNode); +RTDECL(PAVLRUINTPTRNODECORE) RTAvlrUIntPtrGetRight( PAVLRUINTPTRNODECORE pNode); + +/** @} */ + + +/** AVL tree of RTHCPHYSes - using relative offsets internally. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef int32_t AVLOHCPHYS; + +/** + * AVL Core node. + */ +typedef struct _AVLOHCPhysNodeCore +{ + /** Key value. */ + RTHCPHYS Key; + /** Offset to the left leaf node, relative to this field. */ + AVLOHCPHYS pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLOHCPHYS pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64 + unsigned char Padding[7]; /**< Alignment padding. */ +#endif +} AVLOHCPHYSNODECORE, *PAVLOHCPHYSNODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLOHCPHYS AVLOHCPHYSTREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLOHCPHYSTREE *PAVLOHCPHYSTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLOHCPHYSTREE *PPAVLOHCPHYSNODECORE; + +/** Callback function for RTAvloHCPhysDoWithAll() and RTAvloHCPhysDestroy(). */ +typedef DECLCALLBACK(int) AVLOHCPHYSCALLBACK(PAVLOHCPHYSNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvloHCPhysDoWithAll() and RTAvloHCPhysDestroy(). */ +typedef AVLOHCPHYSCALLBACK *PAVLOHCPHYSCALLBACK; + +RTDECL(bool) RTAvloHCPhysInsert(PAVLOHCPHYSTREE pTree, PAVLOHCPHYSNODECORE pNode); +RTDECL(PAVLOHCPHYSNODECORE) RTAvloHCPhysRemove(PAVLOHCPHYSTREE pTree, RTHCPHYS Key); +RTDECL(PAVLOHCPHYSNODECORE) RTAvloHCPhysGet(PAVLOHCPHYSTREE pTree, RTHCPHYS Key); +RTDECL(int) RTAvloHCPhysDoWithAll(PAVLOHCPHYSTREE pTree, int fFromLeft, PAVLOHCPHYSCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLOHCPHYSNODECORE) RTAvloHCPhysGetBestFit(PAVLOHCPHYSTREE ppTree, RTHCPHYS Key, bool fAbove); +RTDECL(PAVLOHCPHYSNODECORE) RTAvloHCPhysRemoveBestFit(PAVLOHCPHYSTREE ppTree, RTHCPHYS Key, bool fAbove); +RTDECL(int) RTAvloHCPhysDestroy(PAVLOHCPHYSTREE pTree, PAVLOHCPHYSCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + + +/** AVL tree of RTIOPORTs - using relative offsets internally. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef int32_t AVLOIOPORTPTR; + +/** + * AVL Core node. + */ +typedef struct _AVLOIOPortNodeCore +{ + /** Offset to the left leaf node, relative to this field. */ + AVLOIOPORTPTR pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLOIOPORTPTR pRight; + /** Key value. */ + RTIOPORT Key; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLOIOPORTNODECORE, *PAVLOIOPORTNODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLOIOPORTPTR AVLOIOPORTTREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLOIOPORTTREE *PAVLOIOPORTTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLOIOPORTTREE *PPAVLOIOPORTNODECORE; + +/** Callback function for RTAvloIOPortDoWithAll() and RTAvloIOPortDestroy(). */ +typedef DECLCALLBACK(int) AVLOIOPORTCALLBACK(PAVLOIOPORTNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvloIOPortDoWithAll() and RTAvloIOPortDestroy(). */ +typedef AVLOIOPORTCALLBACK *PAVLOIOPORTCALLBACK; + +RTDECL(bool) RTAvloIOPortInsert(PAVLOIOPORTTREE pTree, PAVLOIOPORTNODECORE pNode); +RTDECL(PAVLOIOPORTNODECORE) RTAvloIOPortRemove(PAVLOIOPORTTREE pTree, RTIOPORT Key); +RTDECL(PAVLOIOPORTNODECORE) RTAvloIOPortGet(PAVLOIOPORTTREE pTree, RTIOPORT Key); +RTDECL(int) RTAvloIOPortDoWithAll(PAVLOIOPORTTREE pTree, int fFromLeft, PAVLOIOPORTCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLOIOPORTNODECORE) RTAvloIOPortGetBestFit(PAVLOIOPORTTREE ppTree, RTIOPORT Key, bool fAbove); +RTDECL(PAVLOIOPORTNODECORE) RTAvloIOPortRemoveBestFit(PAVLOIOPORTTREE ppTree, RTIOPORT Key, bool fAbove); +RTDECL(int) RTAvloIOPortDestroy(PAVLOIOPORTTREE pTree, PAVLOIOPORTCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + +/** AVL tree of RTIOPORT ranges - using relative offsets internally. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef int32_t AVLROIOPORTPTR; + +/** + * AVL Core node. + */ +typedef struct _AVLROIOPortNodeCore +{ + /** First key value in the range (inclusive). */ + RTIOPORT Key; + /** Last key value in the range (inclusive). */ + RTIOPORT KeyLast; + /** Offset to the left leaf node, relative to this field. */ + AVLROIOPORTPTR pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLROIOPORTPTR pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLROIOPORTNODECORE, *PAVLROIOPORTNODECORE; + +/** A offset base tree with uint32_t keys. */ +typedef AVLROIOPORTPTR AVLROIOPORTTREE; +/** Pointer to an offset base tree with uint32_t keys. */ +typedef AVLROIOPORTTREE *PAVLROIOPORTTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLROIOPORTTREE *PPAVLROIOPORTNODECORE; + +/** Callback function for RTAvlroIOPortDoWithAll() and RTAvlroIOPortDestroy(). */ +typedef DECLCALLBACK(int) AVLROIOPORTCALLBACK(PAVLROIOPORTNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlroIOPortDoWithAll() and RTAvlroIOPortDestroy(). */ +typedef AVLROIOPORTCALLBACK *PAVLROIOPORTCALLBACK; + +RTDECL(bool) RTAvlroIOPortInsert(PAVLROIOPORTTREE pTree, PAVLROIOPORTNODECORE pNode); +RTDECL(PAVLROIOPORTNODECORE) RTAvlroIOPortRemove(PAVLROIOPORTTREE pTree, RTIOPORT Key); +RTDECL(PAVLROIOPORTNODECORE) RTAvlroIOPortGet(PAVLROIOPORTTREE pTree, RTIOPORT Key); +RTDECL(PAVLROIOPORTNODECORE) RTAvlroIOPortRangeGet(PAVLROIOPORTTREE pTree, RTIOPORT Key); +RTDECL(PAVLROIOPORTNODECORE) RTAvlroIOPortRangeRemove(PAVLROIOPORTTREE pTree, RTIOPORT Key); +RTDECL(int) RTAvlroIOPortDoWithAll(PAVLROIOPORTTREE pTree, int fFromLeft, PAVLROIOPORTCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlroIOPortDestroy(PAVLROIOPORTTREE pTree, PAVLROIOPORTCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + +/** AVL tree of RTHCPHYSes. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef struct _AVLHCPhysNodeCore *AVLHCPHYSPTR; + +/** + * AVL Core node. + */ +typedef struct _AVLHCPhysNodeCore +{ + /** Offset to the left leaf node, relative to this field. */ + AVLHCPHYSPTR pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLHCPHYSPTR pRight; + /** Key value. */ + RTHCPHYS Key; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLHCPHYSNODECORE, *PAVLHCPHYSNODECORE; + +/** A offset base tree with RTHCPHYS keys. */ +typedef AVLHCPHYSPTR AVLHCPHYSTREE; +/** Pointer to an offset base tree with RTHCPHYS keys. */ +typedef AVLHCPHYSTREE *PAVLHCPHYSTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLHCPHYSTREE *PPAVLHCPHYSNODECORE; + +/** Callback function for RTAvlHCPhysDoWithAll() and RTAvlHCPhysDestroy(). */ +typedef DECLCALLBACK(int) AVLHCPHYSCALLBACK(PAVLHCPHYSNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlHCPhysDoWithAll() and RTAvlHCPhysDestroy(). */ +typedef AVLHCPHYSCALLBACK *PAVLHCPHYSCALLBACK; + +RTDECL(bool) RTAvlHCPhysInsert(PAVLHCPHYSTREE pTree, PAVLHCPHYSNODECORE pNode); +RTDECL(PAVLHCPHYSNODECORE) RTAvlHCPhysRemove(PAVLHCPHYSTREE pTree, RTHCPHYS Key); +RTDECL(PAVLHCPHYSNODECORE) RTAvlHCPhysGet(PAVLHCPHYSTREE pTree, RTHCPHYS Key); +RTDECL(int) RTAvlHCPhysDoWithAll(PAVLHCPHYSTREE pTree, int fFromLeft, PAVLHCPHYSCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLHCPHYSNODECORE) RTAvlHCPhysGetBestFit(PAVLHCPHYSTREE ppTree, RTHCPHYS Key, bool fAbove); +RTDECL(PAVLHCPHYSNODECORE) RTAvlHCPhysRemoveBestFit(PAVLHCPHYSTREE ppTree, RTHCPHYS Key, bool fAbove); +RTDECL(int) RTAvlHCPhysDestroy(PAVLHCPHYSTREE pTree, PAVLHCPHYSCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + +/** AVL tree of RTGCPHYSes. + * @{ + */ + +/** + * AVL 'pointer' type for the relative offset pointer scheme. + */ +typedef struct _AVLGCPhysNodeCore *AVLGCPHYSPTR; + +/** + * AVL Core node. + */ +typedef struct _AVLGCPhysNodeCore +{ + /** Offset to the left leaf node, relative to this field. */ + AVLGCPHYSPTR pLeft; + /** Offset to the right leaf node, relative to this field. */ + AVLGCPHYSPTR pRight; + /** Key value. */ + RTGCPHYS Key; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLGCPHYSNODECORE, *PAVLGCPHYSNODECORE; + +/** A offset base tree with RTGCPHYS keys. */ +typedef AVLGCPHYSPTR AVLGCPHYSTREE; +/** Pointer to an offset base tree with RTGCPHYS keys. */ +typedef AVLGCPHYSTREE *PAVLGCPHYSTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLGCPHYSTREE *PPAVLGCPHYSNODECORE; + +/** Callback function for RTAvlGCPhysDoWithAll() and RTAvlGCPhysDestroy(). */ +typedef DECLCALLBACK(int) AVLGCPHYSCALLBACK(PAVLGCPHYSNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlGCPhysDoWithAll() and RTAvlGCPhysDestroy(). */ +typedef AVLGCPHYSCALLBACK *PAVLGCPHYSCALLBACK; + +RTDECL(bool) RTAvlGCPhysInsert(PAVLGCPHYSTREE pTree, PAVLGCPHYSNODECORE pNode); +RTDECL(PAVLGCPHYSNODECORE) RTAvlGCPhysRemove(PAVLGCPHYSTREE pTree, RTGCPHYS Key); +RTDECL(PAVLGCPHYSNODECORE) RTAvlGCPhysGet(PAVLGCPHYSTREE pTree, RTGCPHYS Key); +RTDECL(int) RTAvlGCPhysDoWithAll(PAVLGCPHYSTREE pTree, int fFromLeft, PAVLGCPHYSCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLGCPHYSNODECORE) RTAvlGCPhysGetBestFit(PAVLGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove); +RTDECL(PAVLGCPHYSNODECORE) RTAvlGCPhysRemoveBestFit(PAVLGCPHYSTREE ppTree, RTGCPHYS Key, bool fAbove); +RTDECL(int) RTAvlGCPhysDestroy(PAVLGCPHYSTREE pTree, PAVLGCPHYSCALLBACK pfnCallBack, void *pvParam); + +/** @} */ + + +/** AVL tree of RTFOFF ranges. + * @{ + */ + +/** + * AVL Core node. + */ +typedef struct _AVLRFOFFNodeCore +{ + /** First key value in the range (inclusive). */ + RTFOFF Key; + /** Last key value in the range (inclusive). */ + RTFOFF KeyLast; + /** Offset to the left leaf node, relative to this field. */ + struct _AVLRFOFFNodeCore *pLeft; + /** Offset to the right leaf node, relative to this field. */ + struct _AVLRFOFFNodeCore *pRight; + /** Height of this tree: max(height(left), height(right)) + 1 */ + unsigned char uchHeight; +} AVLRFOFFNODECORE, *PAVLRFOFFNODECORE; + +/** A pointer based tree with RTFOFF ranges. */ +typedef PAVLRFOFFNODECORE AVLRFOFFTREE; +/** Pointer to a pointer based tree with RTFOFF ranges. */ +typedef AVLRFOFFTREE *PAVLRFOFFTREE; + +/** Pointer to an internal tree pointer. + * In this case it's a pointer to a relative offset. */ +typedef AVLRFOFFTREE *PPAVLRFOFFNODECORE; + +/** Callback function for RTAvlrGCPtrDoWithAll() and RTAvlrGCPtrDestroy(). */ +typedef DECLCALLBACK(int) AVLRFOFFCALLBACK(PAVLRFOFFNODECORE pNode, void *pvUser); +/** Pointer to callback function for RTAvlrGCPtrDoWithAll() and RTAvlrGCPtrDestroy(). */ +typedef AVLRFOFFCALLBACK *PAVLRFOFFCALLBACK; + +RTDECL(bool) RTAvlrFileOffsetInsert( PAVLRFOFFTREE pTree, PAVLRFOFFNODECORE pNode); +RTDECL(PAVLRFOFFNODECORE) RTAvlrFileOffsetRemove( PAVLRFOFFTREE pTree, RTFOFF Key); +RTDECL(PAVLRFOFFNODECORE) RTAvlrFileOffsetGet( PAVLRFOFFTREE pTree, RTFOFF Key); +RTDECL(PAVLRFOFFNODECORE) RTAvlrFileOffsetGetBestFit( PAVLRFOFFTREE pTree, RTFOFF Key, bool fAbove); +RTDECL(PAVLRFOFFNODECORE) RTAvlrFileOffsetRangeGet( PAVLRFOFFTREE pTree, RTFOFF Key); +RTDECL(PAVLRFOFFNODECORE) RTAvlrFileOffsetRangeRemove( PAVLRFOFFTREE pTree, RTFOFF Key); +RTDECL(int) RTAvlrFileOffsetDoWithAll( PAVLRFOFFTREE pTree, int fFromLeft, PAVLRFOFFCALLBACK pfnCallBack, void *pvParam); +RTDECL(int) RTAvlrFileOffsetDestroy( PAVLRFOFFTREE pTree, PAVLRFOFFCALLBACK pfnCallBack, void *pvParam); +RTDECL(PAVLRFOFFNODECORE) RTAvlrFileOffsetGetRoot( PAVLRFOFFTREE pTree); +RTDECL(PAVLRFOFFNODECORE) RTAvlrFileOffsetGetLeft( PAVLRFOFFNODECORE pNode); +RTDECL(PAVLRFOFFNODECORE) RTAvlrFileOffsetGetRight( PAVLRFOFFNODECORE pNode); + +/** @} */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/base64.h b/include/iprt/base64.h new file mode 100644 index 00000000..b52f48e1 --- /dev/null +++ b/include/iprt/base64.h @@ -0,0 +1,119 @@ +/** @file + * IPRT - Base64, MIME content transfer encoding. + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_base64_h +#define ___iprt_base64_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_base64 RTBase64 - Base64, MIME content transfer encoding. + * @ingroup grp_rt + * @{ + */ + +/** @def RTBASE64_EOL_SIZE + * The size of the end-of-line marker. */ +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +# define RTBASE64_EOL_SIZE (sizeof("\r\n") - 1) +#else +# define RTBASE64_EOL_SIZE (sizeof("\n") - 1) +#endif + +/** + * Calculates the decoded data size for a Base64 encoded string. + * + * @returns The length in bytes. -1 if the encoding is bad. + * + * @param pszString The Base64 encoded string. + * @param ppszEnd If not NULL, this will point to the first char + * following the Base64 encoded text block. If + * NULL the entire string is assumed to be Base64. + */ +RTDECL(ssize_t) RTBase64DecodedSize(const char *pszString, char **ppszEnd); + +/** + * Decodes a Base64 encoded string into the buffer supplied by the caller. + * + * @returns IPRT status code. + * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. pcbActual will not + * be set, nor will ppszEnd. + * @retval VERR_INVALID_BASE64_ENCODING if the encoding is wrong. + * + * @param pszString The Base64 string. Whether the entire string or + * just the start of the string is in Base64 depends + * on whether ppszEnd is specified or not. + * @param pvData Where to store the decoded data. + * @param cbData The size of the output buffer that pvData points to. + * @param pcbActual Where to store the actual number of bytes returned. + * Optional. + * @param ppszEnd Indicates that the string may contain other stuff + * after the Base64 encoded data when not NULL. Will + * be set to point to the first char that's not part of + * the encoding. If NULL the entire string must be part + * of the Base64 encoded data. + */ +RTDECL(int) RTBase64Decode(const char *pszString, void *pvData, size_t cbData, size_t *pcbActual, char **ppszEnd); + +/** + * Calculates the length of the Base64 encoding of a given number of bytes of + * data. + * + * This will assume line breaks every 64 chars. A RTBase64EncodedLengthEx + * function can be added if closer control over the output is found to be + * required. + * + * @returns The Base64 string length. + * @param cbData The number of bytes to encode. + */ +RTDECL(size_t) RTBase64EncodedLength(size_t cbData); + +/** + * Encodes the specifed data into a Base64 string, the caller supplies the + * output buffer. + * + * This will make the same assumptions about line breaks and EOL size as + * RTBase64EncodedLength() does. A RTBase64EncodeEx function can be added if + * more strict control over the output formatting is found necessary. + * + * @returns IRPT status code. + * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer + * may contain an invalid Base64 string. + * + * @param pvData The data to encode. + * @param cbData The number of bytes to encode. + * @param pszBuf Where to put the Base64 string. + * @param cbBuf The size of the output buffer, including the terminator. + * @param pcchActual The actual number of characters returned. + */ +RTDECL(int) RTBase64Encode(const void *pvData, size_t cbData, char *pszBuf, size_t cbBuf, size_t *pcchActual); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/buildconfig.h b/include/iprt/buildconfig.h new file mode 100644 index 00000000..9e4a9c57 --- /dev/null +++ b/include/iprt/buildconfig.h @@ -0,0 +1,125 @@ +/** @file + * IPRT - Build Configuration Information + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_buildconfig_h +#define ___iprt_buildconfig_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_buildconfig RTBldCfg - Build Configuration Information + * @ingroup grp_rt + * @{ + */ + +/** + * Gets the source code management revision of the IPRT build. + * @returns Source code management revision number. + */ +RTDECL(uint32_t) RTBldCfgRevision(void); + +/** + * Gets the source code management revision of the IPRT build. + * @returns Read only string containing the revision number. + */ +RTDECL(const char *) RTBldCfgRevisionStr(void); + +/** + * Gets the product version string. + * + * This will be a string on the form "x.y.z[_string]". + * + * @returns Read only version string. + * + * @remarks This is a build time configuration thing that the product using IPRT + * will set. It is therefore not any IPRT version, but rather the + * version of that product. + */ +RTDECL(const char *) RTBldCfgVersion(void); + +/** + * Gets the major product version number. + * @returns Major product version number. + * @remarks See RTBldCfgVersion. + */ +RTDECL(uint32_t) RTBldCfgVersionMajor(void); + +/** + * Gets the minor product version number. + * @returns Minor product version number. + * @remarks See RTBldCfgVersion. + */ +RTDECL(uint32_t) RTBldCfgVersionMinor(void); + +/** + * Gets the product build number. + * @returns Product build number. + * @remarks See RTBldCfgVersion. + */ +RTDECL(uint32_t) RTBldCfgVersionBuild(void); + +/** + * Gets the build target name. + * + * @returns Read only build target string. + */ +RTDECL(const char *) RTBldCfgTarget(void); + +/** + * Gets the build target architecture name. + * + * @returns Read only build target architecture string. + */ +RTDECL(const char *) RTBldCfgTargetArch(void); + +/** + * Gets the build target-dot-architecture name. + * + * @returns Read only build target-dot-architecture string. + */ +RTDECL(const char *) RTBldCfgTargetDotArch(void); + +/** + * Gets the build type name. + * + * @returns Read only build type string. + */ +RTDECL(const char *) RTBldCfgType(void); + +/** + * Gets the name of the compiler used for building IPRT. + * + * @returns Read only compiler name. + */ +RTDECL(const char *) RTBldCfgCompiler(void); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/cdefs.h b/include/iprt/cdefs.h new file mode 100644 index 00000000..db52defa --- /dev/null +++ b/include/iprt/cdefs.h @@ -0,0 +1,2500 @@ +/** @file + * IPRT - Common C and C++ definitions. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_cdefs_h +#define ___iprt_cdefs_h + + +/** @defgroup grp_rt_cdefs IPRT Common Definitions and Macros + * @{ + */ + +/* + * Include sys/cdefs.h if present, if not define the stuff we need. + */ +#ifdef HAVE_SYS_CDEFS_H +# if defined(RT_ARCH_LINUX) && defined(__KERNEL__) +# error "oops" +# endif +# include <sys/cdefs.h> +#else + +/** @def RT_C_DECLS_BEGIN + * Used to start a block of function declarations which are shared + * between C and C++ program. + */ + +/** @def RT_C_DECLS_END + * Used to end a block of function declarations which are shared + * between C and C++ program. + */ + +# if defined(__cplusplus) +# define RT_C_DECLS_BEGIN extern "C" { +# define RT_C_DECLS_END } +# else +# define RT_C_DECLS_BEGIN +# define RT_C_DECLS_END +# endif + +#endif + + +/* + * Shut up DOXYGEN warnings and guide it properly thru the code. + */ +#ifdef DOXYGEN_RUNNING +# define __AMD64__ +# define __X86__ +# define RT_ARCH_AMD64 +# define RT_ARCH_X86 +# define IN_RING0 +# define IN_RING3 +# define IN_RC +# define IN_RC +# define IN_RT_RC +# define IN_RT_R0 +# define IN_RT_R3 +# define IN_RT_STATIC +# define RT_STRICT +# define RT_NO_STRICT +# define RT_LOCK_STRICT +# define RT_LOCK_NO_STRICT +# define RT_LOCK_STRICT_ORDER +# define RT_LOCK_NO_STRICT_ORDER +# define Breakpoint +# define RT_NO_DEPRECATED_MACROS +# define RT_EXCEPTIONS_ENABLED +# define RT_BIG_ENDIAN +# define RT_LITTLE_ENDIAN +# define RT_COMPILER_GROKS_64BIT_BITFIELDS +# define RT_COMPILER_WITH_80BIT_LONG_DOUBLE +# define RT_NO_VISIBILITY_HIDDEN +#endif /* DOXYGEN_RUNNING */ + +/** @def RT_ARCH_X86 + * Indicates that we're compiling for the X86 architecture. + */ + +/** @def RT_ARCH_AMD64 + * Indicates that we're compiling for the AMD64 architecture. + */ + +/** @def RT_ARCH_SPARC + * Indicates that we're compiling for the SPARC V8 architecture (32-bit). + */ + +/** @def RT_ARCH_SPARC64 + * Indicates that we're compiling for the SPARC V9 architecture (64-bit). + */ +#if !defined(RT_ARCH_X86) \ + && !defined(RT_ARCH_AMD64) \ + && !defined(RT_ARCH_SPARC) \ + && !defined(RT_ARCH_SPARC64) \ + && !defined(RT_ARCH_ARM) +# if defined(__amd64__) || defined(__x86_64__) || defined(_M_X64) || defined(__AMD64__) +# define RT_ARCH_AMD64 +# elif defined(__i386__) || defined(_M_IX86) || defined(__X86__) +# define RT_ARCH_X86 +# elif defined(__sparcv9) +# define RT_ARCH_SPARC64 +# elif defined(__sparc__) +# define RT_ARCH_SPARC +# elif defined(__arm__) || defined(__arm32__) +# define RT_ARCH_ARM +# else /* PORTME: append test for new archs. */ +# error "Check what predefined macros your compiler uses to indicate architecture." +# endif +/* PORTME: append new archs checks. */ +#elif defined(RT_ARCH_X86) && defined(RT_ARCH_AMD64) +# error "Both RT_ARCH_X86 and RT_ARCH_AMD64 cannot be defined at the same time!" +#elif defined(RT_ARCH_X86) && defined(RT_ARCH_SPARC) +# error "Both RT_ARCH_X86 and RT_ARCH_SPARC cannot be defined at the same time!" +#elif defined(RT_ARCH_X86) && defined(RT_ARCH_SPARC64) +# error "Both RT_ARCH_X86 and RT_ARCH_SPARC64 cannot be defined at the same time!" +#elif defined(RT_ARCH_AMD64) && defined(RT_ARCH_SPARC) +# error "Both RT_ARCH_AMD64 and RT_ARCH_SPARC cannot be defined at the same time!" +#elif defined(RT_ARCH_AMD64) && defined(RT_ARCH_SPARC64) +# error "Both RT_ARCH_AMD64 and RT_ARCH_SPARC64 cannot be defined at the same time!" +#elif defined(RT_ARCH_SPARC) && defined(RT_ARCH_SPARC64) +# error "Both RT_ARCH_SPARC and RT_ARCH_SPARC64 cannot be defined at the same time!" +#elif defined(RT_ARCH_ARM) && defined(RT_ARCH_AMD64) +# error "Both RT_ARCH_ARM and RT_ARCH_AMD64 cannot be defined at the same time!" +#elif defined(RT_ARCH_ARM) && defined(RT_ARCH_X86) +# error "Both RT_ARCH_ARM and RT_ARCH_X86 cannot be defined at the same time!" +#elif defined(RT_ARCH_ARM) && defined(RT_ARCH_SPARC64) +# error "Both RT_ARCH_ARM and RT_ARCH_SPARC64 cannot be defined at the same time!" +#elif defined(RT_ARCH_ARM) && defined(RT_ARCH_SPARC) +# error "Both RT_ARCH_ARM and RT_ARCH_SPARC cannot be defined at the same time!" +#endif + + +/** @def __X86__ + * Indicates that we're compiling for the X86 architecture. + * @deprecated + */ + +/** @def __AMD64__ + * Indicates that we're compiling for the AMD64 architecture. + * @deprecated + */ +#if !defined(__X86__) && !defined(__AMD64__) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)) +# if defined(RT_ARCH_AMD64) +# define __AMD64__ +# elif defined(RT_ARCH_X86) +# define __X86__ +# else +# error "Check what predefined macros your compiler uses to indicate architecture." +# endif +#elif defined(__X86__) && defined(__AMD64__) +# error "Both __X86__ and __AMD64__ cannot be defined at the same time!" +#elif defined(__X86__) && !defined(RT_ARCH_X86) +# error "__X86__ without RT_ARCH_X86!" +#elif defined(__AMD64__) && !defined(RT_ARCH_AMD64) +# error "__AMD64__ without RT_ARCH_AMD64!" +#endif + +/** @def RT_BIG_ENDIAN + * Defined if the architecture is big endian. */ +/** @def RT_LITTLE_ENDIAN + * Defined if the architecture is little endian. */ +#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(RT_ARCH_ARM) +# define RT_LITTLE_ENDIAN +#elif defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64) +# define RT_BIG_ENDIAN +#else +# error "PORTME: architecture endianess" +#endif +#if defined(RT_BIG_ENDIAN) && defined(RT_LITTLE_ENDIAN) +# error "Both RT_BIG_ENDIAN and RT_LITTLE_ENDIAN are defined" +#endif + + +/** @def IN_RING0 + * Used to indicate that we're compiling code which is running + * in Ring-0 Host Context. + */ + +/** @def IN_RING3 + * Used to indicate that we're compiling code which is running + * in Ring-3 Host Context. + */ + +/** @def IN_RC + * Used to indicate that we're compiling code which is running + * in the Raw-mode Context (implies R0). + */ +#if !defined(IN_RING3) && !defined(IN_RING0) && !defined(IN_RC) && !defined(IN_RC) +# error "You must define which context the compiled code should run in; IN_RING3, IN_RING0 or IN_RC" +#endif +#if (defined(IN_RING3) && (defined(IN_RING0) || defined(IN_RC)) ) \ + || (defined(IN_RING0) && (defined(IN_RING3) || defined(IN_RC)) ) \ + || (defined(IN_RC) && (defined(IN_RING3) || defined(IN_RING0)) ) +# error "Only one of the IN_RING3, IN_RING0, IN_RC defines should be defined." +#endif + + +/** @def ARCH_BITS + * Defines the bit count of the current context. + */ +#if !defined(ARCH_BITS) || defined(DOXYGEN_RUNNING) +# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_SPARC64) +# define ARCH_BITS 64 +# else +# define ARCH_BITS 32 +# endif +#endif + +/** @def HC_ARCH_BITS + * Defines the host architecture bit count. + */ +#if !defined(HC_ARCH_BITS) || defined(DOXYGEN_RUNNING) +# ifndef IN_RC +# define HC_ARCH_BITS ARCH_BITS +# else +# define HC_ARCH_BITS 32 +# endif +#endif + +/** @def GC_ARCH_BITS + * Defines the guest architecture bit count. + */ +#if !defined(GC_ARCH_BITS) && !defined(DOXYGEN_RUNNING) +# ifdef VBOX_WITH_64_BITS_GUESTS +# define GC_ARCH_BITS 64 +# else +# define GC_ARCH_BITS 32 +# endif +#endif + +/** @def R3_ARCH_BITS + * Defines the host ring-3 architecture bit count. + */ +#if !defined(R3_ARCH_BITS) || defined(DOXYGEN_RUNNING) +# ifdef IN_RING3 +# define R3_ARCH_BITS ARCH_BITS +# else +# define R3_ARCH_BITS HC_ARCH_BITS +# endif +#endif + +/** @def R0_ARCH_BITS + * Defines the host ring-0 architecture bit count. + */ +#if !defined(R0_ARCH_BITS) || defined(DOXYGEN_RUNNING) +# ifdef IN_RING0 +# define R0_ARCH_BITS ARCH_BITS +# else +# define R0_ARCH_BITS HC_ARCH_BITS +# endif +#endif + +/** @def GC_ARCH_BITS + * Defines the guest architecture bit count. + */ +#if !defined(GC_ARCH_BITS) || defined(DOXYGEN_RUNNING) +# ifdef IN_RC +# define GC_ARCH_BITS ARCH_BITS +# else +# define GC_ARCH_BITS 32 +# endif +#endif + + +/** @def CTXTYPE + * Declare a type differently in GC, R3 and R0. + * + * @param GCType The GC type. + * @param R3Type The R3 type. + * @param R0Type The R0 type. + * @remark For pointers used only in one context use RCPTRTYPE(), R3R0PTRTYPE(), R3PTRTYPE() or R0PTRTYPE(). + */ +#ifdef IN_RC +# define CTXTYPE(GCType, R3Type, R0Type) GCType +#elif defined(IN_RING3) +# define CTXTYPE(GCType, R3Type, R0Type) R3Type +#else +# define CTXTYPE(GCType, R3Type, R0Type) R0Type +#endif + +/** @def RCPTRTYPE + * Declare a pointer which is used in the raw mode context but appears in structure(s) used by + * both HC and RC. The main purpose is to make sure structures have the same + * size when built for different architectures. + * + * @param RCType The RC type. + */ +#define RCPTRTYPE(RCType) CTXTYPE(RCType, RTRCPTR, RTRCPTR) + +/** @def R3R0PTRTYPE + * Declare a pointer which is used in HC, is explicitly valid in ring 3 and 0, + * but appears in structure(s) used by both HC and GC. The main purpose is to + * make sure structures have the same size when built for different architectures. + * + * @param R3R0Type The R3R0 type. + * @remarks This used to be called HCPTRTYPE. + */ +#define R3R0PTRTYPE(R3R0Type) CTXTYPE(RTHCPTR, R3R0Type, R3R0Type) + +/** @def R3PTRTYPE + * Declare a pointer which is used in R3 but appears in structure(s) used by + * both HC and GC. The main purpose is to make sure structures have the same + * size when built for different architectures. + * + * @param R3Type The R3 type. + */ +#define R3PTRTYPE(R3Type) CTXTYPE(RTHCUINTPTR, R3Type, RTHCUINTPTR) + +/** @def R0PTRTYPE + * Declare a pointer which is used in R0 but appears in structure(s) used by + * both HC and GC. The main purpose is to make sure structures have the same + * size when built for different architectures. + * + * @param R0Type The R0 type. + */ +#define R0PTRTYPE(R0Type) CTXTYPE(RTHCUINTPTR, RTHCUINTPTR, R0Type) + +/** @def CTXSUFF + * Adds the suffix of the current context to the passed in + * identifier name. The suffix is HC or GC. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param var Identifier name. + * @deprecated Use CTX_SUFF. Do NOT use this for new code. + */ +/** @def OTHERCTXSUFF + * Adds the suffix of the other context to the passed in + * identifier name. The suffix is HC or GC. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param var Identifier name. + * @deprecated Use CTX_SUFF. Do NOT use this for new code. + */ +#ifdef IN_RC +# define CTXSUFF(var) var##GC +# define OTHERCTXSUFF(var) var##HC +#else +# define CTXSUFF(var) var##HC +# define OTHERCTXSUFF(var) var##GC +#endif + +/** @def CTXALLSUFF + * Adds the suffix of the current context to the passed in + * identifier name. The suffix is R3, R0 or GC. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param var Identifier name. + * @deprecated Use CTX_SUFF. Do NOT use this for new code. + */ +#ifdef IN_RC +# define CTXALLSUFF(var) var##GC +#elif defined(IN_RING0) +# define CTXALLSUFF(var) var##R0 +#else +# define CTXALLSUFF(var) var##R3 +#endif + +/** @def CTX_SUFF + * Adds the suffix of the current context to the passed in + * identifier name. The suffix is R3, R0 or RC. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param var Identifier name. + * + * @remark This will replace CTXALLSUFF and CTXSUFF before long. + */ +#ifdef IN_RC +# define CTX_SUFF(var) var##RC +#elif defined(IN_RING0) +# define CTX_SUFF(var) var##R0 +#else +# define CTX_SUFF(var) var##R3 +#endif + +/** @def CTX_SUFF_Z + * Adds the suffix of the current context to the passed in + * identifier name, combining RC and R0 into RZ. + * The suffix thus is R3 or RZ. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param var Identifier name. + * + * @remark This will replace CTXALLSUFF and CTXSUFF before long. + */ +#ifdef IN_RING3 +# define CTX_SUFF_Z(var) var##R3 +#else +# define CTX_SUFF_Z(var) var##RZ +#endif + + +/** @def CTXMID + * Adds the current context as a middle name of an identifier name + * The middle name is HC or GC. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param first First name. + * @param last Surname. + */ +/** @def OTHERCTXMID + * Adds the other context as a middle name of an identifier name + * The middle name is HC or GC. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param first First name. + * @param last Surname. + * @deprecated use CTX_MID or CTX_MID_Z + */ +#ifdef IN_RC +# define CTXMID(first, last) first##GC##last +# define OTHERCTXMID(first, last) first##HC##last +#else +# define CTXMID(first, last) first##HC##last +# define OTHERCTXMID(first, last) first##GC##last +#endif + +/** @def CTXALLMID + * Adds the current context as a middle name of an identifier name. + * The middle name is R3, R0 or GC. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param first First name. + * @param last Surname. + * @deprecated use CTX_MID or CTX_MID_Z + */ +#ifdef IN_RC +# define CTXALLMID(first, last) first##GC##last +#elif defined(IN_RING0) +# define CTXALLMID(first, last) first##R0##last +#else +# define CTXALLMID(first, last) first##R3##last +#endif + +/** @def CTX_MID + * Adds the current context as a middle name of an identifier name. + * The middle name is R3, R0 or RC. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param first First name. + * @param last Surname. + */ +#ifdef IN_RC +# define CTX_MID(first, last) first##RC##last +#elif defined(IN_RING0) +# define CTX_MID(first, last) first##R0##last +#else +# define CTX_MID(first, last) first##R3##last +#endif + +/** @def CTX_MID_Z + * Adds the current context as a middle name of an identifier name, combining RC + * and R0 into RZ. + * The middle name thus is either R3 or RZ. + * + * This is macro should only be used in shared code to avoid a forest of ifdefs. + * @param first First name. + * @param last Surname. + */ +#ifdef IN_RING3 +# define CTX_MID_Z(first, last) first##R3##last +#else +# define CTX_MID_Z(first, last) first##RZ##last +#endif + + +/** @def R3STRING + * A macro which in GC and R0 will return a dummy string while in R3 it will return + * the parameter. + * + * This is typically used to wrap description strings in structures shared + * between R3, R0 and/or GC. The intention is to avoid the \#ifdef IN_RING3 mess. + * + * @param pR3String The R3 string. Only referenced in R3. + * @see R0STRING and GCSTRING + */ +#ifdef IN_RING3 +# define R3STRING(pR3String) (pR3String) +#else +# define R3STRING(pR3String) ("<R3_STRING>") +#endif + +/** @def R0STRING + * A macro which in GC and R3 will return a dummy string while in R0 it will return + * the parameter. + * + * This is typically used to wrap description strings in structures shared + * between R3, R0 and/or GC. The intention is to avoid the \#ifdef IN_RING0 mess. + * + * @param pR0String The R0 string. Only referenced in R0. + * @see R3STRING and GCSTRING + */ +#ifdef IN_RING0 +# define R0STRING(pR0String) (pR0String) +#else +# define R0STRING(pR0String) ("<R0_STRING>") +#endif + +/** @def RCSTRING + * A macro which in R3 and R0 will return a dummy string while in RC it will return + * the parameter. + * + * This is typically used to wrap description strings in structures shared + * between R3, R0 and/or RC. The intention is to avoid the \#ifdef IN_RC mess. + * + * @param pRCString The RC string. Only referenced in RC. + * @see R3STRING, R0STRING + */ +#ifdef IN_RC +# define RCSTRING(pRCString) (pRCString) +#else +# define RCSTRING(pRCString) ("<RC_STRING>") +#endif + + +/** @def RT_NOTHING + * A macro that expands to nothing. + * This is primarily intended as a dummy argument for macros to avoid the + * undefined behavior passing empty arguments to an macro (ISO C90 and C++98, + * gcc v4.4 warns about it). + */ +#define RT_NOTHING + +/** @def RT_GCC_EXTENSION + * Macro for shutting up GCC warnings about using language extensions. */ +#ifdef __GNUC__ +# define RT_GCC_EXTENSION __extension__ +#else +# define RT_GCC_EXTENSION +#endif + +/** @def RT_COMPILER_GROKS_64BIT_BITFIELDS + * Macro that is defined if the compiler understands 64-bit bitfields. */ +#if !defined(RT_OS_OS2) || (!defined(__IBMC__) && !defined(__IBMCPP__)) +# define RT_COMPILER_GROKS_64BIT_BITFIELDS +#endif + +/** @def RT_COMPILER_WITH_80BIT_LONG_DOUBLE + * Macro that is defined if the compiler implements long double as the + * IEEE extended precision floating. */ +#if (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)) && !defined(RT_OS_WINDOWS) +# define RT_COMPILER_WITH_80BIT_LONG_DOUBLE +#endif + + +/** @def RT_EXCEPTIONS_ENABLED + * Defined when C++ exceptions are enabled. + */ +#if !defined(RT_EXCEPTIONS_ENABLED) \ + && defined(__cplusplus) \ + && ( (defined(_MSC_VER) && defined(_CPPUNWIND)) \ + || (defined(__GNUC__) && defined(__EXCEPTIONS))) +# define RT_EXCEPTIONS_ENABLED +#endif + +/** @def RT_NO_THROW + * How to express that a function doesn't throw C++ exceptions + * and the compiler can thus save itself the bother of trying + * to catch any of them. Put this between the closing parenthesis + * and the semicolon in function prototypes (and implementation if C++). + */ +#ifdef RT_EXCEPTIONS_ENABLED +# define RT_NO_THROW throw() +#else +# define RT_NO_THROW +#endif + +/** @def RT_THROW + * How to express that a method or function throws a type of exceptions. Some + * compilers does not want this kind of information and will warning about it. + * + * @param type The type exception. + * + * @remarks If the actual throwing is done from the header, enclose it by + * \#ifdef RT_EXCEPTIONS_ENABLED ... \#else ... \#endif so the header + * compiles cleanly without exceptions enabled. + * + * Do NOT use this for the actual throwing of exceptions! + */ +#ifdef RT_EXCEPTIONS_ENABLED +# ifdef _MSC_VER +# if _MSC_VER >= 1310 +# define RT_THROW(type) +# else +# define RT_THROW(type) throw(type) +# endif +# else +# define RT_THROW(type) throw(type) +# endif +#else +# define RT_THROW(type) +#endif + +/** @def RT_GCC_SUPPORTS_VISIBILITY_HIDDEN + * Indicates that the "hidden" visibility attribute can be used (GCC) */ +#if defined(__GNUC__) +# if __GNUC__ >= 4 && !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) +# define RT_GCC_SUPPORTS_VISIBILITY_HIDDEN +# endif +#endif + +/** @def RTCALL + * The standard calling convention for the Runtime interfaces. + */ +#ifdef _MSC_VER +# define RTCALL __cdecl +#elif defined(RT_OS_OS2) +# define RTCALL __cdecl +#elif defined(__GNUC__) && defined(IN_RING0) && defined(RT_ARCH_X86) /** @todo consider dropping IN_RING0 here. */ +# define RTCALL __attribute__((cdecl,regparm(0))) /* regparm(0) deals with -mregparm=x use in the linux kernel. */ +#else +# define RTCALL +#endif + +/** @def DECLEXPORT + * How to declare an exported function. + * @param type The return type of the function declaration. + */ +#if defined(_MSC_VER) || defined(RT_OS_OS2) +# define DECLEXPORT(type) __declspec(dllexport) type +#elif defined(RT_USE_VISIBILITY_DEFAULT) +# define DECLEXPORT(type) __attribute__((visibility("default"))) type +#else +# define DECLEXPORT(type) type +#endif + +/** @def DECLIMPORT + * How to declare an imported function. + * @param type The return type of the function declaration. + */ +#if defined(_MSC_VER) || (defined(RT_OS_OS2) && !defined(__IBMC__) && !defined(__IBMCPP__)) +# define DECLIMPORT(type) __declspec(dllimport) type +#else +# define DECLIMPORT(type) type +#endif + +/** @def DECLHIDDEN + * How to declare a non-exported function or variable. + * @param type The return type of the function or the data type of the variable. + */ +#if !defined(RT_GCC_SUPPORTS_VISIBILITY_HIDDEN) || defined(RT_NO_VISIBILITY_HIDDEN) +# define DECLHIDDEN(type) type +#else +# define DECLHIDDEN(type) __attribute__((visibility("hidden"))) type +#endif + +/** @def DECL_HIDDEN_CONST + * Workaround for g++ warnings when applying the hidden attribute to a const + * definition. Use DECLHIDDEN for the declaration. + * @param a_Type The return type of the function or the data type of + * the variable. + */ +#if defined(__cplusplus) && defined(__GNUC__) +# define DECL_HIDDEN_CONST(a_Type) a_Type +#else +# define DECL_HIDDEN_CONST(a_Type) DECLHIDDEN(a_Type) +#endif + +/** @def DECL_INVALID + * How to declare a function not available for linking in the current context. + * The purpose is to create compile or like time errors when used. This isn't + * possible on all platforms. + * @param type The return type of the function. + */ +#if defined(_MSC_VER) +# define DECL_INVALID(type) __declspec(dllimport) type __stdcall +#elif defined(__GNUC__) && defined(__cplusplus) +# define DECL_INVALID(type) extern "C++" type +#else +# define DECL_INVALID(type) type +#endif + +/** @def DECLASM + * How to declare an internal assembly function. + * @param type The return type of the function declaration. + */ +#ifdef __cplusplus +# if defined(_MSC_VER) || defined(RT_OS_OS2) +# define DECLASM(type) extern "C" type __cdecl +# elif defined(__GNUC__) && defined(RT_ARCH_X86) +# define DECLASM(type) extern "C" type __attribute__((cdecl,regparm(0))) +# else +# define DECLASM(type) extern "C" type +# endif +#else +# if defined(_MSC_VER) || defined(RT_OS_OS2) +# define DECLASM(type) type __cdecl +# elif defined(__GNUC__) && defined(RT_ARCH_X86) +# define DECLASM(type) type __attribute__((cdecl,regparm(0))) +# else +# define DECLASM(type) type +# endif +#endif + +/** @def DECLASMTYPE + * How to declare an internal assembly function type. + * @param type The return type of the function. + */ +# if defined(_MSC_VER) || defined(RT_OS_OS2) +# define DECLASMTYPE(type) type __cdecl +#else +# define DECLASMTYPE(type) type +#endif + +/** @def DECLNORETURN + * How to declare a function which does not return. + * @note: This macro can be combined with other macros, for example + * @code + * EMR3DECL(DECLNORETURN(void)) foo(void); + * @endcode + */ +#ifdef _MSC_VER +# define DECLNORETURN(type) __declspec(noreturn) type +#elif defined(__GNUC__) +# define DECLNORETURN(type) __attribute__((noreturn)) type +#else +# define DECLNORETURN(type) type +#endif + +/** @def DECLWEAK + * How to declare a variable which is not necessarily resolved at + * runtime. + * @note: This macro can be combined with other macros, for example + * @code + * EMR3DECL(DECLWEAK(int)) foo; + * @endcode + */ +#if defined(__GNUC__) +# define DECLWEAK(type) type __attribute__((weak)) +#else +# define DECLWEAK(type) type +#endif + +/** @def DECLCALLBACK + * How to declare an call back function type. + * @param type The return type of the function declaration. + */ +#define DECLCALLBACK(type) type RTCALL + +/** @def DECLCALLBACKPTR + * How to declare an call back function pointer. + * @param type The return type of the function declaration. + * @param name The name of the variable member. + */ +#define DECLCALLBACKPTR(type, name) type (RTCALL * name) + +/** @def DECLCALLBACKMEMBER + * How to declare an call back function pointer member. + * @param type The return type of the function declaration. + * @param name The name of the struct/union/class member. + */ +#define DECLCALLBACKMEMBER(type, name) type (RTCALL * name) + +/** @def DECLR3CALLBACKMEMBER + * How to declare an call back function pointer member - R3 Ptr. + * @param type The return type of the function declaration. + * @param name The name of the struct/union/class member. + * @param args The argument list enclosed in parentheses. + */ +#ifdef IN_RING3 +# define DECLR3CALLBACKMEMBER(type, name, args) type (RTCALL * name) args +#else +# define DECLR3CALLBACKMEMBER(type, name, args) RTR3PTR name +#endif + +/** @def DECLRCCALLBACKMEMBER + * How to declare an call back function pointer member - RC Ptr. + * @param type The return type of the function declaration. + * @param name The name of the struct/union/class member. + * @param args The argument list enclosed in parentheses. + */ +#ifdef IN_RC +# define DECLRCCALLBACKMEMBER(type, name, args) type (RTCALL * name) args +#else +# define DECLRCCALLBACKMEMBER(type, name, args) RTRCPTR name +#endif + +/** @def DECLR0CALLBACKMEMBER + * How to declare an call back function pointer member - R0 Ptr. + * @param type The return type of the function declaration. + * @param name The name of the struct/union/class member. + * @param args The argument list enclosed in parentheses. + */ +#ifdef IN_RING0 +# define DECLR0CALLBACKMEMBER(type, name, args) type (RTCALL * name) args +#else +# define DECLR0CALLBACKMEMBER(type, name, args) RTR0PTR name +#endif + +/** @def DECLINLINE + * How to declare a function as inline. + * @param type The return type of the function declaration. + * @remarks Don't use this macro on C++ methods. + */ +#ifdef __GNUC__ +# define DECLINLINE(type) static __inline__ type +#elif defined(__cplusplus) +# define DECLINLINE(type) inline type +#elif defined(_MSC_VER) +# define DECLINLINE(type) _inline type +#elif defined(__IBMC__) +# define DECLINLINE(type) _Inline type +#else +# define DECLINLINE(type) inline type +#endif + + +/** @def DECL_FORCE_INLINE + * How to declare a function as inline and try convince the compiler to always + * inline it regardless of optimization switches. + * @param type The return type of the function declaration. + * @remarks Use sparsely and with care. Don't use this macro on C++ methods. + */ +#ifdef __GNUC__ +# define DECL_FORCE_INLINE(type) __attribute__((__always_inline__)) DECLINLINE(type) +#elif defined(_MSC_VER) +# define DECL_FORCE_INLINE(type) __forceinline type +#else +# define DECL_FORCE_INLINE(type) DECLINLINE(type) +#endif + + +/** @def DECL_NO_INLINE + * How to declare a function telling the compiler not to inline it. + * @param scope The function scope, static or RT_NOTHING. + * @param type The return type of the function declaration. + * @remarks Don't use this macro on C++ methods. + */ +#ifdef __GNUC__ +# define DECL_NO_INLINE(scope,type) __attribute__((noinline)) scope type +#elif defined(_MSC_VER) +# define DECL_NO_INLINE(scope,type) __declspec(noinline) scope type +#else +# define DECL_NO_INLINE(scope,type) scope type +#endif + + +/** @def IN_RT_STATIC + * Used to indicate whether we're linking against a static IPRT + * or not. The IPRT symbols will be declared as hidden (if + * supported). Note that this define has no effect without setting + * IN_RT_R0, IN_RT_R3 or IN_RT_RC indicators are set first. + */ + +/** @def IN_RT_R0 + * Used to indicate whether we're inside the same link module as + * the HC Ring-0 Runtime Library. + */ +/** @def RTR0DECL(type) + * Runtime Library HC Ring-0 export or import declaration. + * @param type The return type of the function declaration. + */ +#ifdef IN_RT_R0 +# ifdef IN_RT_STATIC +# define RTR0DECL(type) DECLHIDDEN(type) RTCALL +# else +# define RTR0DECL(type) DECLEXPORT(type) RTCALL +# endif +#else +# define RTR0DECL(type) DECLIMPORT(type) RTCALL +#endif + +/** @def IN_RT_R3 + * Used to indicate whether we're inside the same link module as + * the HC Ring-3 Runtime Library. + */ +/** @def RTR3DECL(type) + * Runtime Library HC Ring-3 export or import declaration. + * @param type The return type of the function declaration. + */ +#ifdef IN_RT_R3 +# ifdef IN_RT_STATIC +# define RTR3DECL(type) DECLHIDDEN(type) RTCALL +# else +# define RTR3DECL(type) DECLEXPORT(type) RTCALL +# endif +#else +# define RTR3DECL(type) DECLIMPORT(type) RTCALL +#endif + +/** @def IN_RT_RC + * Used to indicate whether we're inside the same link module as the raw-mode + * context (RC) runtime library. + */ +/** @def RTRCDECL(type) + * Runtime Library raw-mode context export or import declaration. + * @param type The return type of the function declaration. + */ +#ifdef IN_RT_RC +# ifdef IN_RT_STATIC +# define RTRCDECL(type) DECLHIDDEN(type) RTCALL +# else +# define RTRCDECL(type) DECLEXPORT(type) RTCALL +# endif +#else +# define RTRCDECL(type) DECLIMPORT(type) RTCALL +#endif + +/** @def RTDECL(type) + * Runtime Library export or import declaration. + * Functions declared using this macro exists in all contexts. + * @param type The return type of the function declaration. + */ +#if defined(IN_RT_R3) || defined(IN_RT_RC) || defined(IN_RT_R0) +# ifdef IN_RT_STATIC +# define RTDECL(type) DECLHIDDEN(type) RTCALL +# else +# define RTDECL(type) DECLEXPORT(type) RTCALL +# endif +#else +# define RTDECL(type) DECLIMPORT(type) RTCALL +#endif + +/** @def RTDATADECL(type) + * Runtime Library export or import declaration. + * Data declared using this macro exists in all contexts. + * @param type The return type of the function declaration. + */ +#if defined(IN_RT_R3) || defined(IN_RT_RC) || defined(IN_RT_R0) +# ifdef IN_RT_STATIC +# define RTDATADECL(type) DECLHIDDEN(type) +# else +# define RTDATADECL(type) DECLEXPORT(type) +# endif +#else +# define RTDATADECL(type) DECLIMPORT(type) +#endif + +/** @def RT_DECL_CLASS + * Declares an class living in the runtime. + */ +#if defined(IN_RT_R3) || defined(IN_RT_RC) || defined(IN_RT_R0) +# ifdef IN_RT_STATIC +# define RT_DECL_CLASS +# else +# define RT_DECL_CLASS DECLEXPORT_CLASS +# endif +#else +# define RT_DECL_CLASS DECLIMPORT_CLASS +#endif + + +/** @def RT_NOCRT + * Symbol name wrapper for the No-CRT bits. + * + * In order to coexist in the same process as other CRTs, we need to + * decorate the symbols such that they don't conflict the ones in the + * other CRTs. The result of such conflicts / duplicate symbols can + * confuse the dynamic loader on Unix like systems. + * + * Define RT_WITHOUT_NOCRT_WRAPPERS to drop the wrapping. + * Define RT_WITHOUT_NOCRT_WRAPPER_ALIASES to drop the aliases to the + * wrapped names. + */ +/** @def RT_NOCRT_STR + * Same as RT_NOCRT only it'll return a double quoted string of the result. + */ +#ifndef RT_WITHOUT_NOCRT_WRAPPERS +# define RT_NOCRT(name) nocrt_ ## name +# define RT_NOCRT_STR(name) "nocrt_" # name +#else +# define RT_NOCRT(name) name +# define RT_NOCRT_STR(name) #name +#endif + + + +/** @def RT_LIKELY + * Give the compiler a hint that an expression is very likely to hold true. + * + * Some compilers support explicit branch prediction so that the CPU backend + * can hint the processor and also so that code blocks can be reordered such + * that the predicted path sees a more linear flow, thus improving cache + * behaviour, etc. + * + * IPRT provides the macros RT_LIKELY() and RT_UNLIKELY() as a way to utilize + * this compiler feature when present. + * + * A few notes about the usage: + * + * - Generally, use RT_UNLIKELY() with error condition checks (unless you + * have some _strong_ reason to do otherwise, in which case document it), + * and/or RT_LIKELY() with success condition checks, assuming you want + * to optimize for the success path. + * + * - Other than that, if you don't know the likelihood of a test succeeding + * from empirical or other 'hard' evidence, don't make predictions unless + * you happen to be a Dirk Gently. + * + * - These macros are meant to be used in places that get executed a lot. It + * is wasteful to make predictions in code that is executed rarely (e.g. + * at subsystem initialization time) as the basic block reordering that this + * affects can often generate larger code. + * + * - Note that RT_SUCCESS() and RT_FAILURE() already makes use of RT_LIKELY() + * and RT_UNLIKELY(). Should you wish for prediction free status checks, + * use the RT_SUCCESS_NP() and RT_FAILURE_NP() macros instead. + * + * + * @returns the boolean result of the expression. + * @param expr The expression that's very likely to be true. + * @see RT_UNLIKELY + */ +/** @def RT_UNLIKELY + * Give the compiler a hint that an expression is highly unlikely to hold true. + * + * See the usage instructions give in the RT_LIKELY() docs. + * + * @returns the boolean result of the expression. + * @param expr The expression that's very unlikely to be true. + * @see RT_LIKELY + */ +#if defined(__GNUC__) +# if __GNUC__ >= 3 && !defined(FORTIFY_RUNNING) +# define RT_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define RT_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +# else +# define RT_LIKELY(expr) (expr) +# define RT_UNLIKELY(expr) (expr) +# endif +#else +# define RT_LIKELY(expr) (expr) +# define RT_UNLIKELY(expr) (expr) +#endif + + +/** @def RT_STR + * Returns the argument as a string constant. + * @param str Argument to stringify. */ +#define RT_STR(str) #str +/** @def RT_XSTR + * Returns the expanded argument as a string. + * @param str Argument to expand and stringy. */ +#define RT_XSTR(str) RT_STR(str) + +/** @def RT_CONCAT + * Concatenate the expanded arguments without any extra spaces in between. + * + * @param a The first part. + * @param b The second part. + */ +#define RT_CONCAT(a,b) RT_CONCAT_HLP(a,b) +/** RT_CONCAT helper, don't use. */ +#define RT_CONCAT_HLP(a,b) a##b + +/** @def RT_CONCAT + * Concatenate the expanded arguments without any extra spaces in between. + * + * @param a The 1st part. + * @param b The 2nd part. + * @param c The 3rd part. + */ +#define RT_CONCAT3(a,b,c) RT_CONCAT3_HLP(a,b,c) +/** RT_CONCAT3 helper, don't use. */ +#define RT_CONCAT3_HLP(a,b,c) a##b##c + +/** @def RT_CONCAT + * Concatenate the expanded arguments without any extra spaces in between. + * + * @param a The 1st part. + * @param b The 2nd part. + * @param c The 3rd part. + */ +#define RT_CONCAT4(a,b,c,d) RT_CONCAT4_HLP(a,b,c,d) +/** RT_CONCAT4 helper, don't use. */ +#define RT_CONCAT4_HLP(a,b,c,d) a##b##c##d + +/** + * String constant tuple - string constant, strlen(string constant). + * + * @param a_szConst String constant. + */ +#define RT_STR_TUPLE(a_szConst) a_szConst, (sizeof(a_szConst) - 1) + + +/** @def RT_BIT + * Convert a bit number into an integer bitmask (unsigned). + * @param bit The bit number. + */ +#define RT_BIT(bit) ( 1U << (bit) ) + +/** @def RT_BIT_32 + * Convert a bit number into a 32-bit bitmask (unsigned). + * @param bit The bit number. + */ +#define RT_BIT_32(bit) ( UINT32_C(1) << (bit) ) + +/** @def RT_BIT_64 + * Convert a bit number into a 64-bit bitmask (unsigned). + * @param bit The bit number. + */ +#define RT_BIT_64(bit) ( UINT64_C(1) << (bit) ) + +/** @def RT_ALIGN + * Align macro. + * @param u Value to align. + * @param uAlignment The alignment. Power of two! + * + * @remark Be extremely careful when using this macro with type which sizeof != sizeof int. + * When possible use any of the other RT_ALIGN_* macros. And when that's not + * possible, make 101% sure that uAlignment is specified with a right sized type. + * + * Specifying an unsigned 32-bit alignment constant with a 64-bit value will give + * you a 32-bit return value! + * + * In short: Don't use this macro. Use RT_ALIGN_T() instead. + */ +#define RT_ALIGN(u, uAlignment) ( ((u) + ((uAlignment) - 1)) & ~((uAlignment) - 1) ) + +/** @def RT_ALIGN_T + * Align macro. + * @param u Value to align. + * @param uAlignment The alignment. Power of two! + * @param type Integer type to use while aligning. + * @remark This macro is the preferred alignment macro, it doesn't have any of the pitfalls RT_ALIGN has. + */ +#define RT_ALIGN_T(u, uAlignment, type) ( ((type)(u) + ((uAlignment) - 1)) & ~(type)((uAlignment) - 1) ) + +/** @def RT_ALIGN_32 + * Align macro for a 32-bit value. + * @param u32 Value to align. + * @param uAlignment The alignment. Power of two! + */ +#define RT_ALIGN_32(u32, uAlignment) RT_ALIGN_T(u32, uAlignment, uint32_t) + +/** @def RT_ALIGN_64 + * Align macro for a 64-bit value. + * @param u64 Value to align. + * @param uAlignment The alignment. Power of two! + */ +#define RT_ALIGN_64(u64, uAlignment) RT_ALIGN_T(u64, uAlignment, uint64_t) + +/** @def RT_ALIGN_Z + * Align macro for size_t. + * @param cb Value to align. + * @param uAlignment The alignment. Power of two! + */ +#define RT_ALIGN_Z(cb, uAlignment) RT_ALIGN_T(cb, uAlignment, size_t) + +/** @def RT_ALIGN_P + * Align macro for pointers. + * @param pv Value to align. + * @param uAlignment The alignment. Power of two! + */ +#define RT_ALIGN_P(pv, uAlignment) RT_ALIGN_PT(pv, uAlignment, void *) + +/** @def RT_ALIGN_PT + * Align macro for pointers with type cast. + * @param u Value to align. + * @param uAlignment The alignment. Power of two! + * @param CastType The type to cast the result to. + */ +#define RT_ALIGN_PT(u, uAlignment, CastType) ( (CastType)RT_ALIGN_T(u, uAlignment, uintptr_t) ) + +/** @def RT_ALIGN_R3PT + * Align macro for ring-3 pointers with type cast. + * @param u Value to align. + * @param uAlignment The alignment. Power of two! + * @param CastType The type to cast the result to. + */ +#define RT_ALIGN_R3PT(u, uAlignment, CastType) ( (CastType)RT_ALIGN_T(u, uAlignment, RTR3UINTPTR) ) + +/** @def RT_ALIGN_R0PT + * Align macro for ring-0 pointers with type cast. + * @param u Value to align. + * @param uAlignment The alignment. Power of two! + * @param CastType The type to cast the result to. + */ +#define RT_ALIGN_R0PT(u, uAlignment, CastType) ( (CastType)RT_ALIGN_T(u, uAlignment, RTR0UINTPTR) ) + +/** @def RT_ALIGN_GCPT + * Align macro for GC pointers with type cast. + * @param u Value to align. + * @param uAlignment The alignment. Power of two! + * @param CastType The type to cast the result to. + */ +#define RT_ALIGN_GCPT(u, uAlignment, CastType) ( (CastType)RT_ALIGN_T(u, uAlignment, RTGCUINTPTR) ) + + +/** @def RT_OFFSETOF + * Our own special offsetof() variant, returns a signed result. + * + * This differs from the usual offsetof() in that it's not relying on builtin + * compiler stuff and thus can use variables in arrays the structure may + * contain. This is useful to determine the sizes of structures ending + * with a variable length field. + * + * @returns offset into the structure of the specified member. signed. + * @param type Structure type. + * @param member Member. + */ +#define RT_OFFSETOF(type, member) ( (int)(uintptr_t)&( ((type *)(void *)0)->member) ) + +/** @def RT_UOFFSETOF + * Our own special offsetof() variant, returns an unsigned result. + * + * This differs from the usual offsetof() in that it's not relying on builtin + * compiler stuff and thus can use variables in arrays the structure may + * contain. This is useful to determine the sizes of structures ending + * with a variable length field. + * + * @returns offset into the structure of the specified member. unsigned. + * @param type Structure type. + * @param member Member. + */ +#define RT_UOFFSETOF(type, member) ( (uintptr_t)&( ((type *)(void *)0)->member) ) + +/** @def RT_OFFSETOF_ADD + * RT_OFFSETOF with an addend. + * + * @returns offset into the structure of the specified member. signed. + * @param type Structure type. + * @param member Member. + * @param addend The addend to add to the offset. + */ +#define RT_OFFSETOF_ADD(type, member, addend) ( (int)RT_UOFFSETOF_ADD(type, member, addend) ) + +/** @def RT_UOFFSETOF_ADD + * RT_UOFFSETOF with an addend. + * + * @returns offset into the structure of the specified member. signed. + * @param type Structure type. + * @param member Member. + * @param addend The addend to add to the offset. + */ +#define RT_UOFFSETOF_ADD(type, member, addend) ( (uintptr_t)&( ((type *)(void *)(uintptr_t)(addend))->member) ) + +/** @def RT_SIZEOFMEMB + * Get the size of a structure member. + * + * @returns size of the structure member. + * @param type Structure type. + * @param member Member. + */ +#define RT_SIZEOFMEMB(type, member) ( sizeof(((type *)(void *)0)->member) ) + +/** @def RT_FROM_MEMBER + * Convert a pointer to a structure member into a pointer to the structure. + * + * @returns pointer to the structure. + * @param pMem Pointer to the member. + * @param Type Structure type. + * @param Member Member name. + */ +#define RT_FROM_MEMBER(pMem, Type, Member) ( (Type *) ((uint8_t *)(void *)(pMem) - RT_UOFFSETOF(Type, Member)) ) + +/** @def RT_FROM_CPP_MEMBER + * Same as RT_FROM_MEMBER except it avoids the annoying g++ warnings about + * invalid access to non-static data member of NULL object. + * + * @returns pointer to the structure. + * @param pMem Pointer to the member. + * @param Type Structure type. + * @param Member Member name. + * + * @remarks Using the __builtin_offsetof does not shut up the compiler. + */ +#if defined(__GNUC__) && defined(__cplusplus) +# define RT_FROM_CPP_MEMBER(pMem, Type, Member) \ + ( (Type *) ((uintptr_t)(pMem) - (uintptr_t)&((Type *)0x1000)->Member + 0x1000U) ) +#else +# define RT_FROM_CPP_MEMBER(pMem, Type, Member) RT_FROM_MEMBER(pMem, Type, Member) +#endif + +/** @def RT_ELEMENTS + * Calculates the number of elements in a statically sized array. + * @returns Element count. + * @param aArray Array in question. + */ +#define RT_ELEMENTS(aArray) ( sizeof(aArray) / sizeof((aArray)[0]) ) + +/** + * Checks if the value is a power of two. + * + * @returns true if power of two, false if not. + * @param uVal The value to test. + * @remarks 0 is a power of two. + * @see VERR_NOT_POWER_OF_TWO + */ +#define RT_IS_POWER_OF_TWO(uVal) ( ((uVal) & ((uVal) - 1)) == 0) + +#ifdef RT_OS_OS2 +/* Undefine RT_MAX since there is an unfortunate clash with the max + resource type define in os2.h. */ +# undef RT_MAX +#endif + +/** @def RT_MAX + * Finds the maximum value. + * @returns The higher of the two. + * @param Value1 Value 1 + * @param Value2 Value 2 + */ +#define RT_MAX(Value1, Value2) ( (Value1) >= (Value2) ? (Value1) : (Value2) ) + +/** @def RT_MIN + * Finds the minimum value. + * @returns The lower of the two. + * @param Value1 Value 1 + * @param Value2 Value 2 + */ +#define RT_MIN(Value1, Value2) ( (Value1) <= (Value2) ? (Value1) : (Value2) ) + +/** @def RT_CLAMP + * Clamps the value to minimum and maximum values. + * @returns The clamped value. + * @param Value The value to check. + * @param Min Minimum value. + * @param Max Maximum value. + */ +#define RT_CLAMP(Value, Min, Max) ( (Value) > (Max) ? (Max) : (Value) < (Min) ? (Min) : (Value) ) + +/** @def RT_ABS + * Get the absolute (non-negative) value. + * @returns The absolute value of Value. + * @param Value The value. + */ +#define RT_ABS(Value) ( (Value) >= 0 ? (Value) : -(Value) ) + +/** @def RT_BOOL + * Turn non-zero/zero into true/false + * @returns The resulting boolean value. + * @param Value The value. + */ +#define RT_BOOL(Value) ( !!(Value) ) + +/** @def RT_LO_U8 + * Gets the low uint8_t of a uint16_t or something equivalent. */ +#ifdef __GNUC__ +# define RT_LO_U8(a) __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint16_t)); (uint8_t)(a); }) +#else +# define RT_LO_U8(a) ( (uint8_t)(a) ) +#endif +/** @def RT_HI_U16 + * Gets the high uint16_t of a uint32_t or something equivalent). */ +#ifdef __GNUC__ +# define RT_HI_U8(a) __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint16_t)); (uint8_t)((a) >> 8); }) +#else +# define RT_HI_U8(a) ( (uint8_t)((a) >> 8) ) +#endif + +/** @def RT_LO_U16 + * Gets the low uint16_t of a uint32_t or something equivalent. */ +#ifdef __GNUC__ +# define RT_LO_U16(a) __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint64_t)); (uint32_t)(a); }) +#else +# define RT_LO_U16(a) ( (uint32_t)(a) ) +#endif +/** @def RT_HI_U16 + * Gets the high uint16_t of a uint32_t or something equivalent). */ +#ifdef __GNUC__ +# define RT_HI_U16(a) __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint32_t)); (uint16_t)((a) >> 16); }) +#else +# define RT_HI_U16(a) ( (uint16_t)((a) >> 16) ) +#endif + +/** @def RT_LO_U32 + * Gets the low uint32_t of a uint64_t or something equivalent. */ +#ifdef __GNUC__ +# define RT_LO_U32(a) __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint64_t)); (uint32_t)(a); }) +#else +# define RT_LO_U32(a) ( (uint32_t)(a) ) +#endif +/** @def RT_HI_U32 + * Gets the high uint32_t of a uint64_t or something equivalent). */ +#ifdef __GNUC__ +# define RT_HI_U32(a) __extension__ ({ AssertCompile(sizeof((a)) == sizeof(uint64_t)); (uint32_t)((a) >> 32); }) +#else +# define RT_HI_U32(a) ( (uint32_t)((a) >> 32) ) +#endif + +/** @def RT_BYTE1 + * Gets the first byte of something. */ +#define RT_BYTE1(a) ( (a) & 0xff ) +/** @def RT_BYTE2 + * Gets the second byte of something. */ +#define RT_BYTE2(a) ( ((a) >> 8) & 0xff ) +/** @def RT_BYTE3 + * Gets the second byte of something. */ +#define RT_BYTE3(a) ( ((a) >> 16) & 0xff ) +/** @def RT_BYTE4 + * Gets the fourth byte of something. */ +#define RT_BYTE4(a) ( ((a) >> 24) & 0xff ) +/** @def RT_BYTE5 + * Gets the fifth byte of something. */ +#define RT_BYTE5(a) ( ((a) >> 32) & 0xff ) +/** @def RT_BYTE6 + * Gets the sixth byte of something. */ +#define RT_BYTE6(a) ( ((a) >> 40) & 0xff ) +/** @def RT_BYTE7 + * Gets the seventh byte of something. */ +#define RT_BYTE7(a) ( ((a) >> 48) & 0xff ) +/** @def RT_BYTE8 + * Gets the eight byte of something. */ +#define RT_BYTE8(a) ( ((a) >> 56) & 0xff ) + + +/** @def RT_LODWORD + * Gets the low dword (=uint32_t) of something. + * @deprecated Use RT_LO_U32. */ +#define RT_LODWORD(a) ( (uint32_t)(a) ) +/** @def RT_HIDWORD + * Gets the high dword (=uint32_t) of a 64-bit of something. + * @deprecated Use RT_HI_U32. */ +#define RT_HIDWORD(a) ( (uint32_t)((a) >> 32) ) + +/** @def RT_LOWORD + * Gets the low word (=uint16_t) of something. + * @deprecated Use RT_LO_U16. */ +#define RT_LOWORD(a) ( (a) & 0xffff ) +/** @def RT_HIWORD + * Gets the high word (=uint16_t) of a 32-bit something. + * @deprecated Use RT_HI_U16. */ +#define RT_HIWORD(a) ( (a) >> 16 ) + +/** @def RT_LOBYTE + * Gets the low byte of something. + * @deprecated Use RT_LO_U8. */ +#define RT_LOBYTE(a) ( (a) & 0xff ) +/** @def RT_HIBYTE + * Gets the low byte of a 16-bit something. + * @deprecated Use RT_HI_U8. */ +#define RT_HIBYTE(a) ( (a) >> 8 ) + + +/** @def RT_MAKE_U64 + * Constructs a uint64_t value from two uint32_t values. + */ +#define RT_MAKE_U64(Lo, Hi) ( (uint64_t)((uint32_t)(Hi)) << 32 | (uint32_t)(Lo) ) + +/** @def RT_MAKE_U64_FROM_U16 + * Constructs a uint64_t value from four uint16_t values. + */ +#define RT_MAKE_U64_FROM_U16(w0, w1, w2, w3) \ + ((uint64_t)( (uint64_t)((uint16_t)(w3)) << 48 \ + | (uint64_t)((uint16_t)(w2)) << 32 \ + | (uint32_t)((uint16_t)(w1)) << 16 \ + | (uint16_t)(w0) )) + +/** @def RT_MAKE_U64_FROM_U8 + * Constructs a uint64_t value from eight uint8_t values. + */ +#define RT_MAKE_U64_FROM_U8(b0, b1, b2, b3, b4, b5, b6, b7) \ + ((uint64_t)( (uint64_t)((uint8_t)(b7)) << 56 \ + | (uint64_t)((uint8_t)(b6)) << 48 \ + | (uint64_t)((uint8_t)(b5)) << 40 \ + | (uint64_t)((uint8_t)(b4)) << 32 \ + | (uint32_t)((uint8_t)(b3)) << 24 \ + | (uint32_t)((uint8_t)(b2)) << 16 \ + | (uint16_t)((uint8_t)(b1)) << 8 \ + | (uint8_t)(b0) )) + +/** @def RT_MAKE_U32 + * Constructs a uint32_t value from two uint16_t values. + */ +#define RT_MAKE_U32(Lo, Hi) \ + ((uint32_t)( (uint32_t)((uint16_t)(Hi)) << 16 \ + | (uint16_t)(Lo) )) + +/** @def RT_MAKE_U32_FROM_U8 + * Constructs a uint32_t value from four uint8_t values. + */ +#define RT_MAKE_U32_FROM_U8(b0, b1, b2, b3) \ + ((uint32_t)( (uint32_t)((uint8_t)(b3)) << 24 \ + | (uint32_t)((uint8_t)(b2)) << 16 \ + | (uint16_t)((uint8_t)(b1)) << 8 \ + | (uint8_t)(b0) )) + +/** @def RT_MAKE_U16 + * Constructs a uint16_t value from two uint8_t values. + */ +#define RT_MAKE_U16(Lo, Hi) \ + ((uint16_t)( (uint16_t)((uint8_t)(Hi)) << 8 \ + | (uint8_t)(Lo) )) + + +/** @def RT_BSWAP_U64 + * Reverses the byte order of an uint64_t value. */ +#if 0 +# define RT_BSWAP_U64(u64) RT_BSWAP_U64_C(u64) +#elif defined(__GNUC__) +# define RT_BSWAP_U64(u64) (__builtin_constant_p((u64)) \ + ? RT_BSWAP_U64_C(u64) : ASMByteSwapU64(u64)) +#else +# define RT_BSWAP_U64(u64) ASMByteSwapU64(u64) +#endif + +/** @def RT_BSWAP_U32 + * Reverses the byte order of an uint32_t value. */ +#if 0 +# define RT_BSWAP_U32(u32) RT_BSWAP_U32_C(u32) +#elif defined(__GNUC__) +# define RT_BSWAP_U32(u32) (__builtin_constant_p((u32)) \ + ? RT_BSWAP_U32_C(u32) : ASMByteSwapU32(u32)) +#else +# define RT_BSWAP_U32(u32) ASMByteSwapU32(u32) +#endif + +/** @def RT_BSWAP_U16 + * Reverses the byte order of an uint16_t value. */ +#if 0 +# define RT_BSWAP_U16(u16) RT_BSWAP_U16_C(u16) +#elif defined(__GNUC__) +# define RT_BSWAP_U16(u16) (__builtin_constant_p((u16)) \ + ? RT_BSWAP_U16_C(u16) : ASMByteSwapU16(u16)) +#else +# define RT_BSWAP_U16(u16) ASMByteSwapU16(u16) +#endif + + +/** @def RT_BSWAP_U64_C + * Reverses the byte order of an uint64_t constant. */ +#define RT_BSWAP_U64_C(u64) RT_MAKE_U64(RT_BSWAP_U32_C((u64) >> 32), RT_BSWAP_U32_C((u64) & 0xffffffff)) + +/** @def RT_BSWAP_U32_C + * Reverses the byte order of an uint32_t constant. */ +#define RT_BSWAP_U32_C(u32) RT_MAKE_U32_FROM_U8(RT_BYTE4(u32), RT_BYTE3(u32), RT_BYTE2(u32), RT_BYTE1(u32)) + +/** @def RT_BSWAP_U16_C + * Reverses the byte order of an uint16_t constant. */ +#define RT_BSWAP_U16_C(u16) RT_MAKE_U16(RT_HIBYTE(u16), RT_LOBYTE(u16)) + + +/** @def RT_H2LE_U64 + * Converts an uint64_t value from host to little endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2LE_U64(u64) RT_BSWAP_U64(u64) +#else +# define RT_H2LE_U64(u64) (u64) +#endif + +/** @def RT_H2LE_U64_C + * Converts an uint64_t constant from host to little endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2LE_U64_C(u64) RT_BSWAP_U64_C(u64) +#else +# define RT_H2LE_U64_C(u64) (u64) +#endif + +/** @def RT_H2LE_U32 + * Converts an uint32_t value from host to little endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2LE_U32(u32) RT_BSWAP_U32(u32) +#else +# define RT_H2LE_U32(u32) (u32) +#endif + +/** @def RT_H2LE_U32_C + * Converts an uint32_t constant from host to little endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2LE_U32_C(u32) RT_BSWAP_U32_C(u32) +#else +# define RT_H2LE_U32_C(u32) (u32) +#endif + +/** @def RT_H2LE_U16 + * Converts an uint16_t value from host to little endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2LE_U16(u16) RT_BSWAP_U16(u16) +#else +# define RT_H2LE_U16(u16) (u16) +#endif + +/** @def RT_H2LE_U16_C + * Converts an uint16_t constant from host to little endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2LE_U16_C(u16) RT_BSWAP_U16_C(u16) +#else +# define RT_H2LE_U16_C(u16) (u16) +#endif + + +/** @def RT_LE2H_U64 + * Converts an uint64_t value from little endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_LE2H_U64(u64) RT_BSWAP_U64(u64) +#else +# define RT_LE2H_U64(u64) (u64) +#endif + +/** @def RT_LE2H_U64_C + * Converts an uint64_t constant from little endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_LE2H_U64_C(u64) RT_BSWAP_U64_C(u64) +#else +# define RT_LE2H_U64_C(u64) (u64) +#endif + +/** @def RT_LE2H_U32 + * Converts an uint32_t value from little endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_LE2H_U32(u32) RT_BSWAP_U32(u32) +#else +# define RT_LE2H_U32(u32) (u32) +#endif + +/** @def RT_LE2H_U32_C + * Converts an uint32_t constant from little endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_LE2H_U32_C(u32) RT_BSWAP_U32_C(u32) +#else +# define RT_LE2H_U32_C(u32) (u32) +#endif + +/** @def RT_LE2H_U16 + * Converts an uint16_t value from little endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_LE2H_U16(u16) RT_BSWAP_U16(u16) +#else +# define RT_LE2H_U16(u16) (u16) +#endif + +/** @def RT_LE2H_U16_C + * Converts an uint16_t constant from little endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_LE2H_U16_C(u16) RT_BSWAP_U16_C(u16) +#else +# define RT_LE2H_U16_C(u16) (u16) +#endif + + +/** @def RT_H2BE_U64 + * Converts an uint64_t value from host to big endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2BE_U64(u64) (u64) +#else +# define RT_H2BE_U64(u64) RT_BSWAP_U64(u64) +#endif + +/** @def RT_H2BE_U64_C + * Converts an uint64_t constant from host to big endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2BE_U64_C(u64) (u64) +#else +# define RT_H2BE_U64_C(u64) RT_BSWAP_U64_C(u64) +#endif + +/** @def RT_H2BE_U32 + * Converts an uint32_t value from host to big endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2BE_U32(u32) (u32) +#else +# define RT_H2BE_U32(u32) RT_BSWAP_U32(u32) +#endif + +/** @def RT_H2BE_U32_C + * Converts an uint32_t constant from host to big endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2BE_U32_C(u32) (u32) +#else +# define RT_H2BE_U32_C(u32) RT_BSWAP_U32_C(u32) +#endif + +/** @def RT_H2BE_U16 + * Converts an uint16_t value from host to big endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2BE_U16(u16) (u16) +#else +# define RT_H2BE_U16(u16) RT_BSWAP_U16(u16) +#endif + +/** @def RT_H2BE_U16_C + * Converts an uint16_t constant from host to big endian byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_H2BE_U16_C(u16) (u16) +#else +# define RT_H2BE_U16_C(u16) RT_BSWAP_U16_C(u16) +#endif + +/** @def RT_BE2H_U64 + * Converts an uint64_t value from big endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_BE2H_U64(u64) (u64) +#else +# define RT_BE2H_U64(u64) RT_BSWAP_U64(u64) +#endif + +/** @def RT_BE2H_U64 + * Converts an uint64_t constant from big endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_BE2H_U64_C(u64) (u64) +#else +# define RT_BE2H_U64_C(u64) RT_BSWAP_U64_C(u64) +#endif + +/** @def RT_BE2H_U32 + * Converts an uint32_t value from big endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_BE2H_U32(u32) (u32) +#else +# define RT_BE2H_U32(u32) RT_BSWAP_U32(u32) +#endif + +/** @def RT_BE2H_U32_C + * Converts an uint32_t value from big endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_BE2H_U32_C(u32) (u32) +#else +# define RT_BE2H_U32_C(u32) RT_BSWAP_U32_C(u32) +#endif + +/** @def RT_BE2H_U16 + * Converts an uint16_t value from big endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_BE2H_U16(u16) (u16) +#else +# define RT_BE2H_U16(u16) RT_BSWAP_U16(u16) +#endif + +/** @def RT_BE2H_U16_C + * Converts an uint16_t constant from big endian to host byte order. */ +#ifdef RT_BIG_ENDIAN +# define RT_BE2H_U16_C(u16) (u16) +#else +# define RT_BE2H_U16_C(u16) RT_BSWAP_U16_C(u16) +#endif + + +/** @def RT_H2N_U64 + * Converts an uint64_t value from host to network byte order. */ +#define RT_H2N_U64(u64) RT_H2BE_U64(u64) + +/** @def RT_H2N_U64_C + * Converts an uint64_t constant from host to network byte order. */ +#define RT_H2N_U64_C(u64) RT_H2BE_U64_C(u64) + +/** @def RT_H2N_U32 + * Converts an uint32_t value from host to network byte order. */ +#define RT_H2N_U32(u32) RT_H2BE_U32(u32) + +/** @def RT_H2N_U32_C + * Converts an uint32_t constant from host to network byte order. */ +#define RT_H2N_U32_C(u32) RT_H2BE_U32_C(u32) + +/** @def RT_H2N_U16 + * Converts an uint16_t value from host to network byte order. */ +#define RT_H2N_U16(u16) RT_H2BE_U16(u16) + +/** @def RT_H2N_U16_C + * Converts an uint16_t constant from host to network byte order. */ +#define RT_H2N_U16_C(u16) RT_H2BE_U16_C(u16) + +/** @def RT_N2H_U64 + * Converts an uint64_t value from network to host byte order. */ +#define RT_N2H_U64(u64) RT_BE2H_U64(u64) + +/** @def RT_N2H_U64_C + * Converts an uint64_t constant from network to host byte order. */ +#define RT_N2H_U64_C(u64) RT_BE2H_U64_C(u64) + +/** @def RT_N2H_U32 + * Converts an uint32_t value from network to host byte order. */ +#define RT_N2H_U32(u32) RT_BE2H_U32(u32) + +/** @def RT_N2H_U32_C + * Converts an uint32_t constant from network to host byte order. */ +#define RT_N2H_U32_C(u32) RT_BE2H_U32_C(u32) + +/** @def RT_N2H_U16 + * Converts an uint16_t value from network to host byte order. */ +#define RT_N2H_U16(u16) RT_BE2H_U16(u16) + +/** @def RT_N2H_U16_C + * Converts an uint16_t value from network to host byte order. */ +#define RT_N2H_U16_C(u16) RT_BE2H_U16_C(u16) + + +/* + * The BSD sys/param.h + machine/param.h file is a major source of + * namespace pollution. Kill off some of the worse ones unless we're + * compiling kernel code. + */ +#if defined(RT_OS_DARWIN) \ + && !defined(KERNEL) \ + && !defined(RT_NO_BSD_PARAM_H_UNDEFING) \ + && ( defined(_SYS_PARAM_H_) || defined(_I386_PARAM_H_) ) +/* sys/param.h: */ +# undef PSWP +# undef PVM +# undef PINOD +# undef PRIBO +# undef PVFS +# undef PZERO +# undef PSOCK +# undef PWAIT +# undef PLOCK +# undef PPAUSE +# undef PUSER +# undef PRIMASK +# undef MINBUCKET +# undef MAXALLOCSAVE +# undef FSHIFT +# undef FSCALE + +/* i386/machine.h: */ +# undef ALIGN +# undef ALIGNBYTES +# undef DELAY +# undef STATUS_WORD +# undef USERMODE +# undef BASEPRI +# undef MSIZE +# undef CLSIZE +# undef CLSIZELOG2 +#endif + +/** @def NIL_OFFSET + * NIL offset. + * Whenever we use offsets instead of pointers to save space and relocation effort + * NIL_OFFSET shall be used as the equivalent to NULL. + */ +#define NIL_OFFSET (~0U) + +/** @def NOREF + * Keeps the compiler from bitching about an unused parameter. + */ +#define NOREF(var) (void)(var) + +/** @def RT_BREAKPOINT + * Emit a debug breakpoint instruction. + * + * @remarks In the x86/amd64 gnu world we add a nop instruction after the int3 + * to force gdb to remain at the int3 source line. + * @remarks The L4 kernel will try make sense of the breakpoint, thus the jmp on + * x86/amd64. + */ +#ifdef __GNUC__ +# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) +# if !defined(__L4ENV__) +# define RT_BREAKPOINT() __asm__ __volatile__("int $3\n\tnop\n\t") +# else +# define RT_BREAKPOINT() __asm__ __volatile__("int3; jmp 1f; 1:\n\t") +# endif +# elif defined(RT_ARCH_SPARC64) +# define RT_BREAKPOINT() __asm__ __volatile__("illtrap 0\n\t") /** @todo Sparc64: this is just a wild guess. */ +# elif defined(RT_ARCH_SPARC) +# define RT_BREAKPOINT() __asm__ __volatile__("unimp 0\n\t") /** @todo Sparc: this is just a wild guess (same as Sparc64, just different name). */ +# endif +#endif +#ifdef _MSC_VER +# define RT_BREAKPOINT() __debugbreak() +#endif +#if defined(__IBMC__) || defined(__IBMCPP__) +# define RT_BREAKPOINT() __interrupt(3) +#endif +#ifndef RT_BREAKPOINT +# error "This compiler/arch is not supported!" +#endif + + +/** @defgroup grp_rt_cdefs_size Size Constants + * (Of course, these are binary computer terms, not SI.) + * @{ + */ +/** 1 K (Kilo) (1 024). */ +#define _1K 0x00000400 +/** 2 K (Kilo) (2 048). */ +#define _2K 0x00000800 +/** 4 K (Kilo) (4 096). */ +#define _4K 0x00001000 +/** 8 K (Kilo) (8 192). */ +#define _8K 0x00002000 +/** 16 K (Kilo) (16 384). */ +#define _16K 0x00004000 +/** 32 K (Kilo) (32 678). */ +#define _32K 0x00008000 +/** 64 K (Kilo) (65 536). */ +#define _64K 0x00010000 +/** 128 K (Kilo) (131 072). */ +#define _128K 0x00020000 +/** 256 K (Kilo) (262 144). */ +#define _256K 0x00040000 +/** 512 K (Kilo) (524 288). */ +#define _512K 0x00080000 +/** 1 M (Mega) (1 048 576). */ +#define _1M 0x00100000 +/** 2 M (Mega) (2 097 152). */ +#define _2M 0x00200000 +/** 4 M (Mega) (4 194 304). */ +#define _4M 0x00400000 +/** 1 G (Giga) (1 073 741 824). (32-bit) */ +#define _1G 0x40000000 +/** 1 G (Giga) (1 073 741 824). (64-bit) */ +#define _1G64 0x40000000LL +/** 2 G (Giga) (2 147 483 648). (32-bit) */ +#define _2G32 0x80000000U +/** 2 G (Giga) (2 147 483 648). (64-bit) */ +#define _2G 0x0000000080000000LL +/** 4 G (Giga) (4 294 967 296). */ +#define _4G 0x0000000100000000LL +/** 1 T (Tera) (1 099 511 627 776). */ +#define _1T 0x0000010000000000LL +/** 1 P (Peta) (1 125 899 906 842 624). */ +#define _1P 0x0004000000000000LL +/** 1 E (Exa) (1 152 921 504 606 846 976). */ +#define _1E 0x1000000000000000LL +/** 2 E (Exa) (2 305 843 009 213 693 952). */ +#define _2E 0x2000000000000000ULL +/** @} */ + +/** @defgroup grp_rt_cdefs_decimal_grouping Decimal Constant Grouping Macros + * @{ */ +#define RT_D1(g1) g1 +#define RT_D2(g1, g2) g1#g2 +#define RT_D3(g1, g2, g3) g1#g2#g3 +#define RT_D4(g1, g2, g3, g4) g1#g2#g3#g4 +#define RT_D5(g1, g2, g3, g4, g5) g1#g2#g3#g4#g5 +#define RT_D6(g1, g2, g3, g4, g5, g6) g1#g2#g3#g4#g5#g6 +#define RT_D7(g1, g2, g3, g4, g5, g6, g7) g1#g2#g3#g4#g5#g6#g7 + +#define RT_D1_U(g1) UINT32_C(g1) +#define RT_D2_U(g1, g2) UINT32_C(g1#g2) +#define RT_D3_U(g1, g2, g3) UINT32_C(g1#g2#g3) +#define RT_D4_U(g1, g2, g3, g4) UINT64_C(g1#g2#g3#g4) +#define RT_D5_U(g1, g2, g3, g4, g5) UINT64_C(g1#g2#g3#g4#g5) +#define RT_D6_U(g1, g2, g3, g4, g5, g6) UINT64_C(g1#g2#g3#g4#g5#g6) +#define RT_D7_U(g1, g2, g3, g4, g5, g6, g7) UINT64_C(g1#g2#g3#g4#g5#g6#g7) + +#define RT_D1_S(g1) INT32_C(g1) +#define RT_D2_S(g1, g2) INT32_C(g1#g2) +#define RT_D3_S(g1, g2, g3) INT32_C(g1#g2#g3) +#define RT_D4_S(g1, g2, g3, g4) INT64_C(g1#g2#g3#g4) +#define RT_D5_S(g1, g2, g3, g4, g5) INT64_C(g1#g2#g3#g4#g5) +#define RT_D6_S(g1, g2, g3, g4, g5, g6) INT64_C(g1#g2#g3#g4#g5#g6) +#define RT_D7_S(g1, g2, g3, g4, g5, g6, g7) INT64_C(g1#g2#g3#g4#g5#g6#g7) + +#define RT_D1_U32(g1) UINT32_C(g1) +#define RT_D2_U32(g1, g2) UINT32_C(g1#g2) +#define RT_D3_U32(g1, g2, g3) UINT32_C(g1#g2#g3) +#define RT_D4_U32(g1, g2, g3, g4) UINT32_C(g1#g2#g3#g4) + +#define RT_D1_S32(g1) INT32_C(g1) +#define RT_D2_S32(g1, g2) INT32_C(g1#g2) +#define RT_D3_S32(g1, g2, g3) INT32_C(g1#g2#g3) +#define RT_D4_S32(g1, g2, g3, g4) INT32_C(g1#g2#g3#g4) + +#define RT_D1_U64(g1) UINT64_C(g1) +#define RT_D2_U64(g1, g2) UINT64_C(g1#g2) +#define RT_D3_U64(g1, g2, g3) UINT64_C(g1#g2#g3) +#define RT_D4_U64(g1, g2, g3, g4) UINT64_C(g1#g2#g3#g4) +#define RT_D5_U64(g1, g2, g3, g4, g5) UINT64_C(g1#g2#g3#g4#g5) +#define RT_D6_U64(g1, g2, g3, g4, g5, g6) UINT64_C(g1#g2#g3#g4#g5#g6) +#define RT_D7_U64(g1, g2, g3, g4, g5, g6, g7) UINT64_C(g1#g2#g3#g4#g5#g6#g7) + +#define RT_D1_S64(g1) INT64_C(g1) +#define RT_D2_S64(g1, g2) INT64_C(g1#g2) +#define RT_D3_S64(g1, g2, g3) INT64_C(g1#g2#g3) +#define RT_D4_S64(g1, g2, g3, g4) INT64_C(g1#g2#g3#g4) +#define RT_D5_S64(g1, g2, g3, g4, g5) INT64_C(g1#g2#g3#g4#g5) +#define RT_D6_S64(g1, g2, g3, g4, g5, g6) INT64_C(g1#g2#g3#g4#g5#g6) +#define RT_D7_S64(g1, g2, g3, g4, g5, g6, g7) INT64_C(g1#g2#g3#g4#g5#g6#g7) +/** @} */ + + +/** @defgroup grp_rt_cdefs_time Time Constants + * @{ + */ +/** 1 hour expressed in nanoseconds (64-bit). */ +#define RT_NS_1HOUR UINT64_C(3600000000000) +/** 1 minute expressed in nanoseconds (64-bit). */ +#define RT_NS_1MIN UINT64_C(60000000000) +/** 45 second expressed in nanoseconds. */ +#define RT_NS_45SEC UINT64_C(45000000000) +/** 30 second expressed in nanoseconds. */ +#define RT_NS_30SEC UINT64_C(30000000000) +/** 20 second expressed in nanoseconds. */ +#define RT_NS_20SEC UINT64_C(20000000000) +/** 15 second expressed in nanoseconds. */ +#define RT_NS_15SEC UINT64_C(15000000000) +/** 10 second expressed in nanoseconds. */ +#define RT_NS_10SEC UINT64_C(10000000000) +/** 1 second expressed in nanoseconds. */ +#define RT_NS_1SEC UINT32_C(1000000000) +/** 100 millsecond expressed in nanoseconds. */ +#define RT_NS_100MS UINT32_C(100000000) +/** 10 millsecond expressed in nanoseconds. */ +#define RT_NS_10MS UINT32_C(10000000) +/** 1 millsecond expressed in nanoseconds. */ +#define RT_NS_1MS UINT32_C(1000000) +/** 100 microseconds expressed in nanoseconds. */ +#define RT_NS_100US UINT32_C(100000) +/** 10 microseconds expressed in nanoseconds. */ +#define RT_NS_10US UINT32_C(10000) +/** 1 microsecond expressed in nanoseconds. */ +#define RT_NS_1US UINT32_C(1000) + +/** 1 second expressed in nanoseconds - 64-bit type. */ +#define RT_NS_1SEC_64 UINT64_C(1000000000) +/** 100 millsecond expressed in nanoseconds - 64-bit type. */ +#define RT_NS_100MS_64 UINT64_C(100000000) +/** 10 millsecond expressed in nanoseconds - 64-bit type. */ +#define RT_NS_10MS_64 UINT64_C(10000000) +/** 1 millsecond expressed in nanoseconds - 64-bit type. */ +#define RT_NS_1MS_64 UINT64_C(1000000) +/** 100 microseconds expressed in nanoseconds - 64-bit type. */ +#define RT_NS_100US_64 UINT64_C(100000) +/** 10 microseconds expressed in nanoseconds - 64-bit type. */ +#define RT_NS_10US_64 UINT64_C(10000) +/** 1 microsecond expressed in nanoseconds - 64-bit type. */ +#define RT_NS_1US_64 UINT64_C(1000) + +/** 1 hour expressed in microseconds. */ +#define RT_US_1HOUR UINT32_C(3600000000) +/** 1 minute expressed in microseconds. */ +#define RT_US_1MIN UINT32_C(60000000) +/** 1 second expressed in microseconds. */ +#define RT_US_1SEC UINT32_C(1000000) +/** 100 millsecond expressed in microseconds. */ +#define RT_US_100MS UINT32_C(100000) +/** 10 millsecond expressed in microseconds. */ +#define RT_US_10MS UINT32_C(10000) +/** 1 millsecond expressed in microseconds. */ +#define RT_US_1MS UINT32_C(1000) + +/** 1 hour expressed in microseconds - 64-bit type. */ +#define RT_US_1HOUR_64 UINT64_C(3600000000) +/** 1 minute expressed in microseconds - 64-bit type. */ +#define RT_US_1MIN_64 UINT64_C(60000000) +/** 1 second expressed in microseconds - 64-bit type. */ +#define RT_US_1SEC_64 UINT64_C(1000000) +/** 100 millsecond expressed in microseconds - 64-bit type. */ +#define RT_US_100MS_64 UINT64_C(100000) +/** 10 millsecond expressed in microseconds - 64-bit type. */ +#define RT_US_10MS_64 UINT64_C(10000) +/** 1 millsecond expressed in microseconds - 64-bit type. */ +#define RT_US_1MS_64 UINT64_C(1000) + +/** 1 hour expressed in milliseconds. */ +#define RT_MS_1HOUR UINT32_C(3600000) +/** 1 minute expressed in milliseconds. */ +#define RT_MS_1MIN UINT32_C(60000) +/** 1 second expressed in milliseconds. */ +#define RT_MS_1SEC UINT32_C(1000) + +/** 1 hour expressed in milliseconds - 64-bit type. */ +#define RT_MS_1HOUR_64 UINT64_C(3600000) +/** 1 minute expressed in milliseconds - 64-bit type. */ +#define RT_MS_1MIN_64 UINT64_C(60000) +/** 1 second expressed in milliseconds - 64-bit type. */ +#define RT_MS_1SEC_64 UINT64_C(1000) + +/** The number of seconds per week. */ +#define RT_SEC_1WEEK UINT32_C(604800) +/** The number of seconds per day. */ +#define RT_SEC_1DAY UINT32_C(86400) +/** The number of seconds per hour. */ +#define RT_SEC_1HOUR UINT32_C(3600) + +/** The number of seconds per week - 64-bit type. */ +#define RT_SEC_1WEEK_64 UINT64_C(604800) +/** The number of seconds per day - 64-bit type. */ +#define RT_SEC_1DAY_64 UINT64_C(86400) +/** The number of seconds per hour - 64-bit type. */ +#define RT_SEC_1HOUR_64 UINT64_C(3600) +/** @} */ + + +/** @defgroup grp_rt_cdefs_dbgtype Debug Info Types + * @{ */ +/** Other format. */ +#define RT_DBGTYPE_OTHER RT_BIT_32(0) +/** Stabs. */ +#define RT_DBGTYPE_STABS RT_BIT_32(1) +/** Debug With Arbitrary Record Format (DWARF). */ +#define RT_DBGTYPE_DWARF RT_BIT_32(2) +/** Microsoft Codeview debug info. */ +#define RT_DBGTYPE_CODEVIEW RT_BIT_32(3) +/** Watcom debug info. */ +#define RT_DBGTYPE_WATCOM RT_BIT_32(4) +/** IBM High Level Language debug info. */ +#define RT_DBGTYPE_HLL RT_BIT_32(5) +/** Old OS/2 and Windows symbol file. */ +#define RT_DBGTYPE_SYM RT_BIT_32(6) +/** Map file. */ +#define RT_DBGTYPE_MAP RT_BIT_32(7) +/** @} */ + + +/** @defgroup grp_rt_cdefs_exetype Executable Image Types + * @{ */ +/** Some other format. */ +#define RT_EXETYPE_OTHER RT_BIT_32(0) +/** Portable Executable. */ +#define RT_EXETYPE_PE RT_BIT_32(1) +/** Linear eXecutable. */ +#define RT_EXETYPE_LX RT_BIT_32(2) +/** Linear Executable. */ +#define RT_EXETYPE_LE RT_BIT_32(3) +/** New Executable. */ +#define RT_EXETYPE_NE RT_BIT_32(4) +/** DOS Executable (Mark Zbikowski). */ +#define RT_EXETYPE_MZ RT_BIT_32(5) +/** COM Executable. */ +#define RT_EXETYPE_COM RT_BIT_32(6) +/** a.out Executable. */ +#define RT_EXETYPE_AOUT RT_BIT_32(7) +/** Executable and Linkable Format. */ +#define RT_EXETYPE_ELF RT_BIT_32(8) +/** Mach-O Executable (including FAT ones). */ +#define RT_EXETYPE_MACHO RT_BIT_32(9) +/** TE from UEFI. */ +#define RT_EXETYPE_TE RT_BIT_32(9) +/** @} */ + + +/** @def VALID_PTR + * Pointer validation macro. + * @param ptr The pointer. + */ +#if defined(RT_ARCH_AMD64) +# ifdef IN_RING3 +# if defined(RT_OS_DARWIN) /* first 4GB is reserved for legacy kernel. */ +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) >= _4G \ + && !((uintptr_t)(ptr) & 0xffff800000000000ULL) ) +# elif defined(RT_OS_SOLARIS) /* The kernel only used the top 2TB, but keep it simple. */ +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U \ + && ( ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0xffff800000000000ULL \ + || ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0) ) +# else +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U \ + && !((uintptr_t)(ptr) & 0xffff800000000000ULL) ) +# endif +# else /* !IN_RING3 */ +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U \ + && ( ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0xffff800000000000ULL \ + || ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0) ) +# endif /* !IN_RING3 */ + +#elif defined(RT_ARCH_X86) +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U ) + +#elif defined(RT_ARCH_SPARC64) +# ifdef IN_RING3 +# if defined(RT_OS_SOLARIS) +/** Sparc64 user mode: According to Figure 9.4 in solaris internals */ +/** @todo # define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x80004000U >= 0x80004000U + 0x100000000ULL ) - figure this. */ +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x80000000U >= 0x80000000U + 0x100000000ULL ) +# else +# error "Port me" +# endif +# else /* !IN_RING3 */ +# if defined(RT_OS_SOLARIS) +/** @todo Sparc64 kernel mode: This is according to Figure 11.1 in solaris + * internals. Verify in sources. */ +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) >= 0x01000000U ) +# else +# error "Port me" +# endif +# endif /* !IN_RING3 */ + +#elif defined(RT_ARCH_SPARC) +# ifdef IN_RING3 +# ifdef RT_OS_SOLARIS +/** Sparc user mode: According to + * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/sun4/os/startup.c#510 */ +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x400000U >= 0x400000U + 0x2000U ) + +# else +# error "Port me" +# endif +# else /* !IN_RING3 */ +# ifdef RT_OS_SOLARIS +/** @todo Sparc kernel mode: Check the sources! */ +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U ) +# else +# error "Port me" +# endif +# endif /* !IN_RING3 */ + +#elif defined(RT_ARCH_ARM) +/* ASSUMES that at least the last and first 4K are out of bounds. */ +# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U ) + +#else +# error "Architecture identifier missing / not implemented." +#endif + +/** Old name for RT_VALID_PTR. */ +#define VALID_PTR(ptr) RT_VALID_PTR(ptr) + +/** @def RT_VALID_ALIGNED_PTR + * Pointer validation macro that also checks the alignment. + * @param ptr The pointer. + * @param align The alignment, must be a power of two. + */ +#define RT_VALID_ALIGNED_PTR(ptr, align) \ + ( !((uintptr_t)(ptr) & (uintptr_t)((align) - 1)) \ + && VALID_PTR(ptr) ) + + +/** @def VALID_PHYS32 + * 32 bits physical address validation macro. + * @param Phys The RTGCPHYS address. + */ +#define VALID_PHYS32(Phys) ( (uint64_t)(Phys) < (uint64_t)_4G ) + +/** @def N_ + * The \#define N_ is used to mark a string for translation. This is usable in + * any part of the code, as it is only used by the tools that create message + * catalogs. This macro is a no-op as far as the compiler and code generation + * is concerned. + * + * If you want to both mark a string for translation and translate it, use _(). + */ +#define N_(s) (s) + +/** @def _ + * The \#define _ is used to mark a string for translation and to translate it + * in one step. + * + * If you want to only mark a string for translation, use N_(). + */ +#define _(s) gettext(s) + + +/** @def __PRETTY_FUNCTION__ + * With GNU C we'd like to use the builtin __PRETTY_FUNCTION__, so define that + * for the other compilers. + */ +#if !defined(__GNUC__) && !defined(__PRETTY_FUNCTION__) +# ifdef _MSC_VER +# define __PRETTY_FUNCTION__ __FUNCSIG__ +# else +# define __PRETTY_FUNCTION__ __FUNCTION__ +# endif +#endif + + +/** @def RT_STRICT + * The \#define RT_STRICT controls whether or not assertions and other runtime + * checks should be compiled in or not. This is defined when DEBUG is defined. + * If RT_NO_STRICT is defined, it will unconditionally be undefined. + * + * If you want assertions which are not subject to compile time options use + * the AssertRelease*() flavors. + */ +#if !defined(RT_STRICT) && defined(DEBUG) +# define RT_STRICT +#endif +#ifdef RT_NO_STRICT +# undef RT_STRICT +#endif + +/** @todo remove this: */ +#if !defined(RT_LOCK_STRICT) && !defined(DEBUG_bird) +# define RT_LOCK_NO_STRICT +#endif +#if !defined(RT_LOCK_STRICT_ORDER) && !defined(DEBUG_bird) +# define RT_LOCK_NO_STRICT_ORDER +#endif + +/** @def RT_LOCK_STRICT + * The \#define RT_LOCK_STRICT controls whether deadlock detection and related + * checks are done in the lock and semaphore code. It is by default enabled in + * RT_STRICT builds, but this behavior can be overridden by defining + * RT_LOCK_NO_STRICT. */ +#if !defined(RT_LOCK_STRICT) && !defined(RT_LOCK_NO_STRICT) && defined(RT_STRICT) +# define RT_LOCK_STRICT +#endif +/** @def RT_LOCK_NO_STRICT + * The \#define RT_LOCK_NO_STRICT disables RT_LOCK_STRICT. */ +#if defined(RT_LOCK_NO_STRICT) && defined(RT_LOCK_STRICT) +# undef RT_LOCK_STRICT +#endif + +/** @def RT_LOCK_STRICT_ORDER + * The \#define RT_LOCK_STRICT_ORDER controls whether locking order is checked + * by the lock and semaphore code. It is by default enabled in RT_STRICT + * builds, but this behavior can be overridden by defining + * RT_LOCK_NO_STRICT_ORDER. */ +#if !defined(RT_LOCK_STRICT_ORDER) && !defined(RT_LOCK_NO_STRICT_ORDER) && defined(RT_STRICT) +# define RT_LOCK_STRICT_ORDER +#endif +/** @def RT_LOCK_NO_STRICT_ORDER + * The \#define RT_LOCK_NO_STRICT_ORDER disables RT_LOCK_STRICT_ORDER. */ +#if defined(RT_LOCK_NO_STRICT_ORDER) && defined(RT_LOCK_STRICT_ORDER) +# undef RT_LOCK_STRICT_ORDER +#endif + + +/** Source position. */ +#define RT_SRC_POS __FILE__, __LINE__, __PRETTY_FUNCTION__ + +/** Source position declaration. */ +#define RT_SRC_POS_DECL const char *pszFile, unsigned iLine, const char *pszFunction + +/** Source position arguments. */ +#define RT_SRC_POS_ARGS pszFile, iLine, pszFunction + +/** Applies NOREF() to the source position arguments. */ +#define RT_SRC_POS_NOREF() do { NOREF(pszFile); NOREF(iLine); NOREF(pszFunction); } while (0) + + +/** @def RT_INLINE_ASM_EXTERNAL + * Defined as 1 if the compiler does not support inline assembly. + * The ASM* functions will then be implemented in external .asm files. + */ +#if (defined(_MSC_VER) && defined(RT_ARCH_AMD64)) \ + || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86)) +# define RT_INLINE_ASM_EXTERNAL 1 +#else +# define RT_INLINE_ASM_EXTERNAL 0 +#endif + +/** @def RT_INLINE_ASM_GNU_STYLE + * Defined as 1 if the compiler understands GNU style inline assembly. + */ +#if defined(_MSC_VER) +# define RT_INLINE_ASM_GNU_STYLE 0 +#else +# define RT_INLINE_ASM_GNU_STYLE 1 +#endif + +/** @def RT_INLINE_ASM_USES_INTRIN + * Defined as 1 if the compiler have and uses intrin.h. Otherwise it is 0. */ +#ifdef _MSC_VER +# if _MSC_VER >= 1400 +# define RT_INLINE_ASM_USES_INTRIN 1 +# endif +#endif +#ifndef RT_INLINE_ASM_USES_INTRIN +# define RT_INLINE_ASM_USES_INTRIN 0 +#endif + +/** @} */ + + +/** @defgroup grp_rt_cdefs_cpp Special Macros for C++ + * @ingroup grp_rt_cdefs + * @{ + */ + +#ifdef __cplusplus + +/** @def DECLEXPORT_CLASS + * How to declare an exported class. Place this macro after the 'class' + * keyword in the declaration of every class you want to export. + * + * @note It is necessary to use this macro even for inner classes declared + * inside the already exported classes. This is a GCC specific requirement, + * but it seems not to harm other compilers. + */ +#if defined(_MSC_VER) || defined(RT_OS_OS2) +# define DECLEXPORT_CLASS __declspec(dllexport) +#elif defined(RT_USE_VISIBILITY_DEFAULT) +# define DECLEXPORT_CLASS __attribute__((visibility("default"))) +#else +# define DECLEXPORT_CLASS +#endif + +/** @def DECLIMPORT_CLASS + * How to declare an imported class Place this macro after the 'class' + * keyword in the declaration of every class you want to export. + * + * @note It is necessary to use this macro even for inner classes declared + * inside the already exported classes. This is a GCC specific requirement, + * but it seems not to harm other compilers. + */ +#if defined(_MSC_VER) || (defined(RT_OS_OS2) && !defined(__IBMC__) && !defined(__IBMCPP__)) +# define DECLIMPORT_CLASS __declspec(dllimport) +#elif defined(RT_USE_VISIBILITY_DEFAULT) +# define DECLIMPORT_CLASS __attribute__((visibility("default"))) +#else +# define DECLIMPORT_CLASS +#endif + +/** @def WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP + * Macro to work around error C2593 of the not-so-smart MSVC 7.x ambiguity + * resolver. The following snippet clearly demonstrates the code causing this + * error: + * @code + * class A + * { + * public: + * operator bool() const { return false; } + * operator int*() const { return NULL; } + * }; + * int main() + * { + * A a; + * if (!a); + * if (a && 0); + * return 0; + * } + * @endcode + * The code itself seems pretty valid to me and GCC thinks the same. + * + * This macro fixes the compiler error by explicitly overloading implicit + * global operators !, && and || that take the given class instance as one of + * their arguments. + * + * The best is to use this macro right after the class declaration. + * + * @note The macro expands to nothing for compilers other than MSVC. + * + * @param Cls Class to apply the workaround to + */ +#if defined(_MSC_VER) +# define WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP(Cls) \ + inline bool operator! (const Cls &that) { return !bool (that); } \ + inline bool operator&& (const Cls &that, bool b) { return bool (that) && b; } \ + inline bool operator|| (const Cls &that, bool b) { return bool (that) || b; } \ + inline bool operator&& (bool b, const Cls &that) { return b && bool (that); } \ + inline bool operator|| (bool b, const Cls &that) { return b || bool (that); } +#else +# define WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP(Cls) +#endif + +/** @def WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP_TPL + * Version of WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP for template classes. + * + * @param Tpl Name of the template class to apply the workaround to + * @param ArgsDecl arguments of the template, as declared in |<>| after the + * |template| keyword, including |<>| + * @param Args arguments of the template, as specified in |<>| after the + * template class name when using the, including |<>| + * + * Example: + * @code + * // template class declaration + * template <class C> + * class Foo { ... }; + * // applied workaround + * WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP_TPL (Foo, <class C>, <C>) + * @endcode + */ +#if defined(_MSC_VER) +# define WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP_TPL(Tpl, ArgsDecl, Args) \ + template ArgsDecl \ + inline bool operator! (const Tpl Args &that) { return !bool (that); } \ + template ArgsDecl \ + inline bool operator&& (const Tpl Args &that, bool b) { return bool (that) && b; } \ + template ArgsDecl \ + inline bool operator|| (const Tpl Args &that, bool b) { return bool (that) || b; } \ + template ArgsDecl \ + inline bool operator&& (bool b, const Tpl Args &that) { return b && bool (that); } \ + template ArgsDecl \ + inline bool operator|| (bool b, const Tpl Args &that) { return b || bool (that); } +#else +# define WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP_TPL(Tpl, ArgsDecl, Args) +#endif + + +/** @def DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP + * Declares the copy constructor and the assignment operation as inlined no-ops + * (non-existent functions) for the given class. Use this macro inside the + * private section if you want to effectively disable these operations for your + * class. + * + * @param Cls class name to declare for + */ + +#define DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(Cls) \ + inline Cls (const Cls &); \ + inline Cls &operator= (const Cls &); + + +/** @def DECLARE_CLS_NEW_DELETE_NOOP + * Declares the new and delete operations as no-ops (non-existent functions) + * for the given class. Use this macro inside the private section if you want + * to effectively limit creating class instances on the stack only. + * + * @note The destructor of the given class must not be virtual, otherwise a + * compile time error will occur. Note that this is not a drawback: having + * the virtual destructor for a stack-based class is absolutely useless + * (the real class of the stack-based instance is always known to the compiler + * at compile time, so it will always call the correct destructor). + * + * @param Cls class name to declare for + */ +#define DECLARE_CLS_NEW_DELETE_NOOP(Cls) \ + inline static void *operator new (size_t); \ + inline static void operator delete (void *); + +#endif /* __cplusplus */ + +/** @} */ + +#endif + diff --git a/include/iprt/cdrom.h b/include/iprt/cdrom.h new file mode 100644 index 00000000..927ee153 --- /dev/null +++ b/include/iprt/cdrom.h @@ -0,0 +1,181 @@ +/** @file + * IPRT CD/DVD/BD-ROM Drive API. + */ + +/* + * Copyright (C) 2012 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. + */ + +#ifndef ___iprt_cdrom_h +#define ___iprt_cdrom_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_cdrom IPRT CD/DVD/BD-ROM Drive API + * + * The user of the API is currently resposible for serializing calls to it. + * + * @{ + */ + +/** CD-ROM drive handle. */ +typedef struct RTCDROMINT *RTCDROM; +/** Pointer to a CD-ROM handle. */ +typedef RTCDROM *PRTCDROM; +/** NIL CD-ROM handle value. */ +#define NIL_RTCDROM ((RTCDROM)0) + + +/** @name CD-ROM open flags. + * @{ */ +#define RTCDROM_O_READ RT_BIT(0) +#define RTCDROM_O_WRITE RT_BIT(1) +#define RTCDROM_O_CONTROL RT_BIT(2) +#define RTCDROM_O_QUERY RT_BIT(3) +#define RTCDROM_O_ALL_ACCESS (RTCDROM_O_READ | RTCDROM_O_WRITE | RTCDROM_O_CONTROL | RTCDROM_O_QUERY) +/** @} */ + +/** + * Opens the CD-ROM drive (by name). + * + * @returns IPRT status code. + * @param pszName The CD-ROM name (path). + * @param fFlags Open flags, see RTCDROM_O_XXX. + * @param phCdrom Where to return the CDROM handle. + */ +RTDECL(int) RTCdromOpen(const char *psz, uint32_t fFlags, PRTCDROM phCdrom); + +/** + * Retains a reference to the CD-ROM handle. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * @param hCdrom The CD-ROM handle to retain. + */ +RTDECL(uint32_t) RTCdromRetain(RTCDROM hCdrom); + +/** + * Releases a reference to the CD-ROM handle. + * + * When the reference count reaches zero, the CD-ROM handle is destroy. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * @param hCdrom The CD-ROM handle to retain. + */ +RTDECL(uint32_t) RTCdromRelease(RTCDROM hCdrom); + +/** + * Query the primary mount point of the CD-ROM. + * + * @returns IPRT status code. + * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer will be + * set to an empty string if possible. + * + * @param hCdrom The CD-ROM handle. + * @param pszMountPoint Where to return the mount point. + * @param cbMountPoint The size of the mount point buffer. + */ +RTDECL(int) RTCdromQueryMountPoint(RTCDROM hCdrom, char *pszMountPoint, size_t cbMountPoint); + +/** + * Unmounts all file-system mounts related to the CD-ROM. + * + * @returns IPRT status code. + * @param hCdrom The CD-ROM handle. + */ +RTDECL(int) RTCdromUnmount(RTCDROM hCdrom); + +/** + * Ejects the CD-ROM from the drive. + * + * @returns IPRT status code. + * @param hCdrom The CD-ROM handle. + * @param fForce If set, unmount and unlock will be performed. + */ +RTDECL(int) RTCdromEject(RTCDROM hCdrom, bool fForce); + +/** + * Locks the CD-ROM so it cannot be ejected by the user or system. + * + * @returns IPRT status code. + * @param hCdrom The CD-ROM handle. + */ +RTDECL(int) RTCdromLock(RTCDROM hCdrom); + +/** + * Unlocks the CD-ROM so it can be ejected by the user or system. + * + * @returns IPRT status code. + * @param hCdrom The CD-ROM handle. + */ +RTDECL(int) RTCdromUnlock(RTCDROM hCdrom); + + +/** @name Ordinal / Enumeration + * @{ */ +/** + * Get the current number of CD-ROMs. + * + * This is handy for using RTCdromOpenByOrdinal() or RTCdromOrdinalToName() to + * perform some kind of enumeration of all drives. + * + * @returns Number of CD-ROM drivers in the system. + */ +RTDECL(unsigned) RTCdromCount(void); + +/** + * Translates an CD-ROM drive ordinal number to a path suitable for RTCdromOpen. + * + * @returns IRPT status code. + * @retval VINF_SUCCESS on success, with the name in the buffer. + * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer will be + * set to an empty string if possible, in order to prevent trouble. + * @retval VERR_OUT_OF_RANGE if the ordinal number is higher than the current + * number of CD-ROM drives. + * + * @param iCdrom The CD-ROM drive ordinal. Starts at 0. + * @param pszName Where to return the name (path). + * @param cbName Size of the output buffer. + * + * @remarks The ordinals are volatile. They may change as drives are attached + * or detected from the host. + */ +RTDECL(int) RTCdromOrdinalToName(unsigned iCdrom, char *pszName, size_t cbName); + +/** + * Combination of RTCdromOrdinalToName() and RTCdromOpen(). + * + * @returns IPRT status code. + * @param pszName The CD-ROM name (path). + * @param fFlags Open flags, see RTCDROM_O_XXX. + * @param phCdrom Where to return the CDROM handle . + * @remarks See remarks on RTCdromOrdinalToName(). + */ +RTDECL(int) RTCdromOpenByOrdinal(unsigned iCdrom, uint32_t fFlags, PRTCDROM phCdrom); + +/** @} */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/cidr.h b/include/iprt/cidr.h new file mode 100644 index 00000000..5e054186 --- /dev/null +++ b/include/iprt/cidr.h @@ -0,0 +1,61 @@ +/** @file + * IPRT - TCP/IP. + */ + +/* + * Copyright (C) 2008 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. + */ + + +#ifndef ___iprt_ip_h +#define ___iprt_ip_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +/** @defgroup grp_rt_cidr RTCidr - Classless Inter-Domain Routing notation + * @ingroup grp_rt + * @{ + */ +RT_C_DECLS_BEGIN + +/** An IPv4 address. */ +typedef uint32_t RTIPV4ADDR; +/** Pointer to an IPv4 address. */ +typedef RTIPV4ADDR *PRTIPV4ADDR; +/** Pointer to a const IPv4 address. */ +typedef RTIPV4ADDR const *PCRTIPV4ADDR; + + +/** + * Parse a string which contains an IP address in CIDR (Classless Inter-Domain Routing) notation. + * + * @return iprt status code. + * + * @param pszAddress The IP address in CIDR specificaion. + * @param pNetwork The determined IP address / network. + * @param pNetmask The determined netmask. + */ +RTDECL(int) RTCidrStrToIPv4(const char *pszAddress, PRTIPV4ADDR pNetwork, PRTIPV4ADDR pNetmask); + +RT_C_DECLS_END +/** @} */ + +#endif diff --git a/include/iprt/circbuf.h b/include/iprt/circbuf.h new file mode 100644 index 00000000..b0c58ffe --- /dev/null +++ b/include/iprt/circbuf.h @@ -0,0 +1,138 @@ +/** @file + * IPRT - Lock Free Circular Buffer + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_circbuf_h +#define ___iprt_circbuf_h + +#include <iprt/types.h> + +/** @defgroup grp_rt_circbuf RTCircBuf - Lock Free Circular Buffer + * @ingroup grp_rt + * + * Implementation of a lock free circular buffer which could be used in a multi + * threaded environment. Note that only the acquire, release and getter + * functions are threading aware. So don't use reset if the circular buffer is + * still in use. + * + * @{ + */ + +RT_C_DECLS_BEGIN + +/** Pointer to a circular buffer (abstract). */ +typedef struct RTCIRCBUF *PRTCIRCBUF; + +/** + * Create a circular buffer. + * + * @returns IPRT status code. + * + * @param ppBuf Where to store the buffer. + * @param cbSize The size of the new buffer. + */ +RTDECL(int) RTCircBufCreate(PRTCIRCBUF *ppBuf, size_t cbSize); + +/** + * Destroy the circular buffer. + * + * @param pBuf The buffer to destroy. NULL is ignored. + */ +RTDECL(void) RTCircBufDestroy(PRTCIRCBUF pBuf); + +/** + * Reset all position information in the circular buffer. + * + * @note This function is not multi threading aware. + * + * @param pBuf The buffer to reset. + */ +RTDECL(void) RTCircBufReset(PRTCIRCBUF pBuf); + +/** + * Returns the current free space of the buffer. + * + * @param pBuf The buffer to query. + */ +RTDECL(size_t) RTCircBufFree(PRTCIRCBUF pBuf); + +/** + * Returns the current used space of the buffer. + * + * @param pBuf The buffer to query. + */ +RTDECL(size_t) RTCircBufUsed(PRTCIRCBUF pBuf); + +/** + * Returns the size of the buffer. + * + * @param pBuf The buffer to query. + */ +RTDECL(size_t) RTCircBufSize(PRTCIRCBUF pBuf); + +RTDECL(bool) RTCircBufIsReading(PRTCIRCBUF pBuf); +RTDECL(bool) RTCircBufIsWriting(PRTCIRCBUF pBuf); + +/** + * Acquire a block of the circular buffer for reading. + * + * @param pBuf The buffer to acquire from. + * @param cbReqSize The requested size of the block. + * @param ppvStart The resulting memory pointer. + * @param pcbSize The resulting size of the memory pointer. + */ +RTDECL(void) RTCircBufAcquireReadBlock(PRTCIRCBUF pBuf, size_t cbReqSize, void **ppvStart, size_t *pcbSize); + +/** + * Release a block which was acquired by RTCircBufAcquireReadBlock. + * + * @param pBuf The buffer to acquire from. + * @param cbSize The size of the block. + */ +RTDECL(void) RTCircBufReleaseReadBlock(PRTCIRCBUF pBuf, size_t cbSize); + +/** + * Acquire a block of the circular buffer for writing. + * + * @param pBuf The buffer to acquire from. + * @param cbReqSize The requested size of the block. + * @param ppvStart The resulting memory pointer. + * @param pcbSize The resulting size of the memory pointer. + */ +RTDECL(void) RTCircBufAcquireWriteBlock(PRTCIRCBUF pBuf, size_t cbReqSize, void **ppvStart, size_t *pcbSize); + +/** + * Release a block which was acquired by RTCircBufAcquireWriteBlock. + * + * @param pBuf The buffer to acquire from. + * @param cbSize The size of the block. + */ +RTDECL(void) RTCircBufReleaseWriteBlock(PRTCIRCBUF pBuf, size_t cbSize); + +RT_C_DECLS_END + +/** @} */ + +#endif /* !___iprt_circbuf_h */ + diff --git a/include/iprt/condvar.h b/include/iprt/condvar.h new file mode 100644 index 00000000..98e5e2dc --- /dev/null +++ b/include/iprt/condvar.h @@ -0,0 +1,283 @@ +/** @file + * IPRT - Condition Variable. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_condvar_h +#define ___iprt_condvar_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) +# include <iprt/lockvalidator.h> +#endif + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_condvar RTCondVar - Condition Variable + * + * Condition variables combines mutex semaphore or critical sections with event + * semaphores. See @ref grp_rt_sems_mutex, @ref grp_rt_critsect, + * @ref grp_rt_sems_event and @ref grp_rt_sems_event_multi. + * + * @ingroup grp_rt + * @{ + */ + + +/** + * Create a condition variable. + * + * @returns iprt status code. + * @param phCondVar Where to store the handle to the newly created + * condition variable. + */ +RTDECL(int) RTConvVarCreate(PRTCONDVAR phCondVar); + +/** + * Create a condition variable. + * + * @returns iprt status code. + * @param phCondVar Where to store the handle to the newly created + * condition variable. + * @param fFlags Flags, any combination of the + * RTCONDVAR_FLAGS_XXX \#defines. + * @param hClass The class (no reference consumed). Since we + * don't do order checks on condition variables, + * the use of the class is limited to controlling + * the timeout threshold for deadlock detection. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(int) RTConvVarCreateEx(PRTCONDVAR phCondVar, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...); + +/** @name RTConvVarCreateEx flags + * @{ */ +/** Disables lock validation. */ +#define RTCONDVAR_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001) +/** @} */ + +/** + * Destroy a condition variable. + * + * @returns iprt status code. + * @param hCondVar Handle of the condition variable. NIL_RTCONDVAR + * is quietly ignored (VINF_SUCCESS). + */ +RTDECL(int) RTConvVarDestroy(RTCONDVAR hCondVar); + +/** + * Signal the condition variable, waking up exactly one thread. + * + * It is recommended that the caller holds the associated lock, but this is not + * strictly speaking necessary. + * + * If no threads are waiting on the condition variable, the call will have no + * effect on the variable. + * + * @returns iprt status code. + * @param hConvVar The condition variable to signal. + */ +RTDECL(int) RTConvVarSignal(RTCONDVAR hCondVar); + +/** + * Signal the condition variable, waking up all blocked threads. + * + * It is recommended that the caller holds the associated lock, but this is not + * strictly speaking necessary. + * + * If no threads are waiting on the condition variable, the call will have no + * effect on the variable. + * + * @returns iprt status code. + * @param hConvVar The condition variable to broadcast. + */ +RTDECL(int) RTConvVarBroadcast(RTCONDVAR hCondVar); + +/** + * Wait for the condition variable to be signaled, resume on interruption. + * + * This function will resume if the wait is interrupted by an async system event + * (like a unix signal) or similar. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param hConvVar The condition variable to wait on. + * @param hMtx The mutex to leave during the wait and which + * will be re-enter before returning. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait forever. + */ +RTDECL(int) RTConvVarMutexWait(RTCONDVAR hCondVar, RTSEMMUTEX hMtx, RTMSINTERVAL cMillies); + +/** + * Wait for the condition variable to be signaled, return on interruption. + * + * This function will not resume the wait if interrupted. + * + * @returns iprt status code. + * @param hConvVar The condition variable to wait on. + * @param hMtx The mutex to leave during the wait and which + * will be re-enter before returning. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait forever. + */ +RTDECL(int) RTConvVarMutexWaitNoResume(RTCONDVAR hCondVar, RTSEMMUTEX hMtx, RTMSINTERVAL cMillies); + +/** + * Wait for the condition variable to be signaled, resume on interruption. + * + * This function will resume if the wait is interrupted by an async system event + * (like a unix signal) or similar. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param hConvVar The condition variable to wait on. + * @param hRWSem The read/write semaphore to write-leave during + * the wait and which will be re-enter in write + * mode before returning. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait forever. + */ +RTDECL(int) RTConvVarRWWriteWait(RTCONDVAR hCondVar, RTSEMRW hRWSem, RTMSINTERVAL cMillies); + +/** + * Wait for the condition variable to be signaled, return on interruption. + * + * This function will not resume the wait if interrupted. + * + * @returns iprt status code. + * @param hConvVar The condition variable to wait on. + * @param hRWSem The read/write semaphore to write-leave during + * the wait and which will be re-enter in write + * mode before returning. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait forever. + */ +RTDECL(int) RTConvVarRWWriteWaitNoResume(RTCONDVAR hCondVar, RTSEMRW hRWSem, RTMSINTERVAL cMillies); + +/** + * Wait for the condition variable to be signaled, resume on interruption. + * + * This function will resume if the wait is interrupted by an async system event + * (like a unix signal) or similar. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param hConvVar The condition variable to wait on. + * @param hRWSem The read/write semaphore to read-leave during + * the wait and which will be re-enter in read mode + * before returning. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait forever. + */ +RTDECL(int) RTConvVarRWReadWait(RTCONDVAR hCondVar, RTSEMRW hRWSem, RTMSINTERVAL cMillies); + +/** + * Wait for the condition variable to be signaled, return on interruption. + * + * This function will not resume the wait if interrupted. + * + * @returns iprt status code. + * @param hConvVar The condition variable to wait on. + * @param hRWSem The read/write semaphore to read-leave during + * the wait and which will be re-enter in read mode + * before returning. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait forever. + */ +RTDECL(int) RTConvVarRWReadWaitNoResume(RTCONDVAR hCondVar, RTSEMRW hRWSem, RTMSINTERVAL cMillies); + +/** + * Wait for the condition variable to be signaled, resume on interruption. + * + * This function will resume if the wait is interrupted by an async system event + * (like a unix signal) or similar. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param hConvVar The condition variable to wait on. + * @param pCritSect The critical section to leave during the wait + * and which will be re-enter before returning. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait forever. + */ +RTDECL(int) RTConvVarCritSectWait(RTCONDVAR hCondVar, PRTCRITSECT pCritSect, RTMSINTERVAL cMillies); + +/** + * Wait for the condition variable to be signaled, return on interruption. + * + * This function will not resume the wait if interrupted. + * + * @returns iprt status code. + * @param hConvVar The condition variable to wait on. + * @param pCritSect The critical section to leave during the wait + * and which will be re-enter before returning. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait forever. + */ +RTDECL(int) RTConvVarCritSectWaitNoResume(RTCONDVAR hCondVar, PRTCRITSECT pCritSect, RTMSINTERVAL cMillies); + +/** + * Sets the signaller thread to one specific thread. + * + * This is only used for validating usage and deadlock detection. When used + * after calls to RTConvVarAddSignaller, the specified thread will be the only + * signalling thread. + * + * @param hConvVar The condition variable. + * @param hThread The thread that will signal it. Pass + * NIL_RTTHREAD to indicate that there is no + * special signalling thread. + */ +RTDECL(void) RTConvVarSetSignaller(RTCONDVAR hCondVar, RTTHREAD hThread); + +/** + * To add more signalling threads. + * + * First call RTCondVarSetSignaller then add further threads with this. + * + * @param hConvVar The condition variable. + * @param hThread The thread that will signal it. NIL_RTTHREAD is + * not accepted. + */ +RTDECL(void) RTConvVarAddSignaller(RTCONDVAR hCondVar, RTTHREAD hThread); + +/** + * To remove a signalling thread. + * + * Reverts work done by RTCondVarAddSignaller and RTCondVarSetSignaller. + * + * @param hConvVar The condition variable. + * @param hThread A previously added thread. + */ +RTDECL(void) RTConvVarRemoveSignaller(RTCONDVAR hCondVar, RTTHREAD hThread); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/coredumper.h b/include/iprt/coredumper.h new file mode 100644 index 00000000..6c748bbf --- /dev/null +++ b/include/iprt/coredumper.h @@ -0,0 +1,94 @@ +/** @file + * IPRT - Core Dumper. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_coredumper_h +#define ___iprt_coredumper_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_coredumper RTCoreDumper - Core Dumper. + * @ingroup grp_rt + * @{ + */ + +/** @name RTCoreDumperSetup flags + * @{ */ +/** Override system core dumper. Registers handlers for + * SIGSEGV/SIGTRAP/SIGBUS. */ +#define RTCOREDUMPER_FLAGS_REPLACE_SYSTEM_DUMP RT_BIT(0) +/** Allow taking live process dumps (without killing process). Registers handler + * for SIGUSR2. */ +#define RTCOREDUMPER_FLAGS_LIVE_CORE RT_BIT(1) +/** @} */ + +/** + * Take a core dump of the current process without terminating it. + * + * @returns IPRT status code. + * @param pszOutputFile Name of the core file. If NULL use the + * default naming scheme. + * @param fLiveCore When true, the process is not killed after + * taking a core. Otherwise it will be killed. This + * works in conjuction with the flags set during + * RTCoreDumperSetup(). + */ +RTDECL(int) RTCoreDumperTakeDump(const char *pszOutputFile, bool fLiveCore); + +/** + * Sets up and enables the core dumper. + * + * Installs signal / unhandled exception handlers for catching fatal errors + * that should result in a core dump. If you wish to install your own handlers + * you should do that after calling this function and make sure you pass on + * events you don't handle. + * + * This can be called multiple times to change the settings without needing to + * call RTCoreDumperDisable in between. + * + * @param pszOutputDir The directory to store the cores in. If NULL + * the current directory will be used. + * @param pszBaseName Base file name, no directory. If NULL the + * dumper will generate an appropriate name. + * @param fFlags Setup flags, 0 in NOT a valid flag, it must be + * one or more of RTCOREDUMPER_FLAGS_*. + */ +RTDECL(int) RTCoreDumperSetup(const char *pszOutputDir, uint32_t fFlags); + +/** + * Disables the core dumper, i.e. undoes what RTCoreDumperSetup did. + * + * @returns IPRT status code. + */ +RTDECL(int) RTCoreDumperDisable(void); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/cpp/Makefile.kup b/include/iprt/cpp/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/include/iprt/cpp/Makefile.kup diff --git a/include/iprt/cpp/autores.h b/include/iprt/cpp/autores.h new file mode 100644 index 00000000..0edad230 --- /dev/null +++ b/include/iprt/cpp/autores.h @@ -0,0 +1,203 @@ +/** @file + * IPRT - C++ Resource Management. + */ + +/* + * Copyright (C) 2008-2011 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. + */ + +#ifndef ___iprt_autores_h +#define ___iprt_autores_h + +#include <iprt/types.h> +#include <iprt/assert.h> +#include <iprt/cpp/utils.h> + + + +/** @defgroup grp_rt_cpp_autores C++ Resource Management + * @ingroup grp_rt_cpp + * @{ + */ + +/** + * A callable class template which returns the correct value against which an + * IPRT type must be compared to see if it is invalid. + * + * @warning This template *must* be specialised for the types it is to work with. + */ +template <class T> +inline T RTAutoResNil(void) +{ + AssertFatalMsgFailed(("Unspecialized template!\n")); + return (T)0; +} + +/** Specialisation of RTAutoResNil for RTFILE */ +template <> +inline RTFILE RTAutoResNil(void) +{ + return NIL_RTFILE; +} + +/** + * A function template which calls the correct destructor for an IPRT type. + * + * @warning This template *must* be specialised for the types it is to work with. + */ +template <class T> +inline void RTAutoResDestruct(T a_h) +{ + AssertFatalMsgFailed(("Unspecialized template!\n")); + NOREF(a_h); +} + +/** + * An auto pointer-type class for resources which take a C-style destructor + * (RTMemFree() or equivalent). + * + * The idea of this class is to manage resources which the current code is + * responsible for freeing. By wrapping the resource in an RTCAutoRes, you + * ensure that the resource will be freed when you leave the scope in which + * the RTCAutoRes is defined, unless you explicitly release the resource. + * + * A typical use case is when a function is allocating a number of resources. + * If any single allocation fails then all other resources must be freed. If + * all allocations succeed, then the resources should be returned to the + * caller. By placing all allocated resources in RTCAutoRes containers, you + * ensure that they will be freed on failure, and only have to take care of + * releasing them when you return them. + * + * @param T The type of the resource. + * @param Destruct The function to be used to free the resource. + * This parameter must be supplied if there is no + * specialisation of RTAutoDestruct available for @a T. + * @param NilRes The function returning the NIL value for T. Required. + * This parameter must be supplied if there is no + * specialisation of RTAutoResNil available for @a T. + * + * @note The class can not be initialised directly using assignment, due + * to the lack of a copy constructor. This is intentional. + */ +template <class T, void Destruct(T) = RTAutoResDestruct<T>, T NilRes(void) = RTAutoResNil<T> > +class RTCAutoRes + : public RTCNonCopyable +{ +protected: + /** The resource handle. */ + T m_hRes; + +public: + /** + * Constructor + * + * @param a_hRes The handle to resource to manage. Defaults to NIL. + */ + RTCAutoRes(T a_hRes = NilRes()) + : m_hRes(a_hRes) + { + } + + /** + * Destructor. + * + * This destroys any resource currently managed by the object. + */ + ~RTCAutoRes() + { + if (m_hRes != NilRes()) + Destruct(m_hRes); + } + + /** + * Assignment from a value. + * + * This destroys any resource currently managed by the object + * before taking on the new one. + * + * @param a_hRes The handle to the new resource. + */ + RTCAutoRes &operator=(T a_hRes) + { + if (m_hRes != NilRes()) + Destruct(m_hRes); + m_hRes = a_hRes; + return *this; + } + + /** + * Checks if the resource handle is NIL or not. + */ + bool operator!() + { + return m_hRes == NilRes(); + } + + /** + * Give up ownership the current resource, handing it to the caller. + * + * @returns The current resource handle. + * + * @note Nothing happens to the resource when the object goes out of scope. + */ + T release(void) + { + T Tmp = m_hRes; + m_hRes = NilRes(); + return Tmp; + } + + /** + * Deletes the current resources. + * + * @param a_hRes Handle to a new resource to manage. Defaults to NIL. + */ + void reset(T a_hRes = NilRes()) + { + if (a_hRes != m_hRes) + { + if (m_hRes != NilRes()) + Destruct(m_hRes); + m_hRes = a_hRes; + } + } + + /** + * Get the raw resource handle. + * + * Typically used passing the handle to some IPRT function while + * the object remains in scope. + * + * @returns The raw resource handle. + */ + T get(void) + { + return m_hRes; + } +}; + +/** @} */ + + +/* include after template definition */ +#include <iprt/mem.h> + +#endif + diff --git a/include/iprt/cpp/exception.h b/include/iprt/cpp/exception.h new file mode 100644 index 00000000..4fcbfb72 --- /dev/null +++ b/include/iprt/cpp/exception.h @@ -0,0 +1,95 @@ +/** @file + * IPRT - C++ Base Exceptions. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_cpp_exception_h +#define ___iprt_cpp_exception_h + +#include <iprt/cpp/ministring.h> +#include <exception> + +/** @defgroup grp_rt_cpp_exceptions C++ Exceptions + * @ingroup grp_rt_cpp + * @{ + */ + +/** + * Base exception class for IPRT, derived from std::exception. + * The XML exceptions are based on this. + */ +class RT_DECL_CLASS RTCError + : public std::exception +{ +public: + + RTCError(const char *pszMessage) + : m_strMsg(pszMessage) + { + } + + RTCError(const RTCString &a_rstrMessage) + : m_strMsg(a_rstrMessage) + { + } + + RTCError(const RTCError &a_rSrc) + : std::exception(a_rSrc), + m_strMsg(a_rSrc.what()) + { + } + + virtual ~RTCError() throw() + { + } + + void operator=(const RTCError &a_rSrc) + { + m_strMsg = a_rSrc.what(); + } + + void setWhat(const char *a_pszMessage) + { + m_strMsg = a_pszMessage; + } + + virtual const char *what() const throw() + { + return m_strMsg.c_str(); + } + +private: + /** + * Hidden default constructor making sure that the extended one above is + * always used. + */ + RTCError(); + + /** The exception message. */ + RTCString m_strMsg; +}; + +/** @} */ + +#endif + diff --git a/include/iprt/cpp/list.h b/include/iprt/cpp/list.h new file mode 100644 index 00000000..97c1a193 --- /dev/null +++ b/include/iprt/cpp/list.h @@ -0,0 +1,891 @@ +/** @file + * IPRT - Generic List Class. + */ + +/* + * Copyright (C) 2011 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. + */ + +#ifndef ___iprt_cpp_list_h +#define ___iprt_cpp_list_h + +#include <iprt/cpp/meta.h> +#include <iprt/mem.h> +#include <iprt/string.h> /* for memcpy */ + +#include <new> /* For std::bad_alloc */ + +/** @defgroup grp_rt_cpp_list C++ List support + * @ingroup grp_rt_cpp + * + * @brief Generic C++ list class support. + * + * This list classes manage any amount of data in a fast and easy to use way. + * They have no dependencies on STL, only on generic memory management methods + * of IRPT. This allows list handling in situations where the use of STL + * container classes is forbidden. + * + * Not all of the functionality of STL container classes is implemented. There + * are no iterators or any other high level access/modifier methods (e.g. + * std::algorithms). + * + * The implementation is array based which allows fast access to the items. + * Appending items is usually also fast, cause the internal array is + * preallocated. To minimize the memory overhead, native types (that is + * everything smaller then the size of void*) are directly saved in the array. + * If bigger types are used (e.g. RTCString) the internal array is an array of + * pointers to the objects. + * + * The size of the internal array will usually not shrink, but grow + * automatically. Only certain methods, like RTCList::clear or the "=" operator + * will reset any previously allocated memory. You can call + * RTCList::setCapacity for manual adjustment. If the size of an new list will + * be known, calling the constructor with the necessary capacity will speed up + * the insertion of the new items. + * + * For the full public interface these list classes offer see RTCListBase. + * + * There are some requirements for the types used which follow: + * -# They need a default and a copy constructor. + * -# Some methods (e.g. RTCList::contains) need an equal operator. + * -# If the type is some complex class (that is, having a constructor which + * allocates members on the heap) it has to be greater than sizeof(void*) to + * be used correctly. If this is not the case you can manually overwrite the + * list behavior. Just add T* as a second parameter to the list template if + * your class is called T. Another possibility is to specialize the list for + * your target class. See below for more information. + * + * The native types like int, bool, ptr, ..., are meeting this criteria, so + * they are save to use. + * + * Please note that the return type of some of the getter methods are slightly + * different depending on the list type. Native types return the item by value, + * items with a size greater than sizeof(void*) by reference. As native types + * saved directly in the internal array, returning a reference to them (and + * saving them in a reference as well) would make them invalid (or pointing to + * a wrong item) when the list is changed in the meanwhile. Returning a + * reference for bigger types isn't problematic and makes sure we get out the + * best speed of the list. The one exception to this rule is the index + * operator[]. This operator always return a reference to make it possible to + * use it as a lvalue. Its your responsibility to make sure the list isn't + * changed when using the value as reference returned by this operator. + * + * The list class is reentrant. For a thread-safe variant see RTCMTList. + * + * Implementation details: + * It is possible to specialize any type. This might be necessary to get the + * best speed out of the list. Examples are the 64-bit types, which use the + * native (no pointers) implementation even on a 32-bit host. Consult the + * source code for more details. + * + * Current specialized implementations: + * - int64_t: RTCList<int64_t> + * - uint64_t: RTCList<uint64_t> + * + * @{ + */ + +/** + * The guard definition. + */ +template <bool G> +class RTCListGuard; + +/** + * The default guard which does nothing. + */ +template <> +class RTCListGuard<false> +{ +public: + inline void enterRead() const {} + inline void leaveRead() const {} + inline void enterWrite() {} + inline void leaveWrite() {} + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); +}; + +/** + * General helper template for managing native values in RTCListBase. + */ +template <typename T1, typename T2> +class RTCListHelper +{ +public: + static inline void set(T2 *p, size_t i, const T1 &v) { p[i] = v; } + static inline T1 & at(T2 *p, size_t i) { return p[i]; } + static inline size_t find(T2 *p, const T1 &v, size_t cSize) + { + size_t i = 0; + while(i < cSize) + { + if (p[i] == v) + break; + ++i; + } + return i; + } + static inline void copyTo(T2 *p, T2 *const p1 , size_t iTo, size_t cSize) + { + if (cSize > 0) + memcpy(&p[iTo], &p1[0], sizeof(T1) * cSize); + } + static inline void erase(T2 *p, size_t /* i */) { /* Nothing to do here. */ } + static inline void eraseRange(T2 * /* p */, size_t /* cFrom */, size_t /* cSize */) { /* Nothing to do here. */ } +}; + +/** + * Specialized helper template for managing pointer values in RTCListBase. + */ +template <typename T1> +class RTCListHelper<T1, T1*> +{ +public: + static inline void set(T1 **p, size_t i, const T1 &v) { p[i] = new T1(v); } + static inline T1 & at(T1 **p, size_t i) { return *p[i]; } + static inline size_t find(T1 **p, const T1 &v, size_t cSize) + { + size_t i = 0; + while(i < cSize) + { + if (*p[i] == v) + break; + ++i; + } + return i; + } + static inline void copyTo(T1 **p, T1 **const p1 , size_t iTo, size_t cSize) + { + for (size_t i = 0; i < cSize; ++i) + p[iTo + i] = new T1(*p1[i]); + } + static inline void erase(T1 **p, size_t i) { delete p[i]; } + static inline void eraseRange(T1 **p, size_t cFrom, size_t cSize) + { + for (size_t i = cFrom; i < cFrom + cSize; ++i) + delete p[i]; + } +}; + +/** + * This is the base class for all other list classes. It implements the + * necessary list functionality in a type independent way and offers the public + * list interface to the user. + */ +template <class T, typename ITYPE, bool MT> +class RTCListBase +{ + /** + * Traits + * + * Defines the return type of most of the getter methods. If the internal + * used type is a pointer, we return a reference. If not we return by + * value. + */ + typedef typename RTCIfPtr<ITYPE, T&, T>::result GET_RTYPE; + typedef typename RTCIfPtr<ITYPE, const T&, T>::result GET_CRTYPE; + +public: + /** + * Creates a new list. + * + * This preallocates @a cCapacity elements within the list. + * + * @param cCapacitiy The initial capacity the list has. + * @throws std::bad_alloc + */ + RTCListBase(size_t cCapacity = DefaultCapacity) + : m_pArray(0) + , m_cSize(0) + , m_cCapacity(0) + { + if (cCapacity > 0) + realloc_grow(cCapacity); + } + + /** + * Creates a copy of another list. + * + * The other list will be fully copied and the capacity will be the same as + * the size of the other list. + * + * @param other The list to copy. + * @throws std::bad_alloc + */ + RTCListBase(const RTCListBase<T, ITYPE, MT>& other) + : m_pArray(0) + , m_cSize(0) + , m_cCapacity(0) + { + realloc_no_elements_clean(other.m_cSize); + RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); + m_cSize = other.m_cSize; + } + + /** + * Destructor. + */ + ~RTCListBase() + { + RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); + if (m_pArray) + RTMemFree(m_pArray); + } + + /** + * Sets a new capacity within the list. + * + * If the new capacity is bigger than the old size, it will be simply + * preallocated more space for the new items. If the new capacity is + * smaller than the previous size, items at the end of the list will be + * deleted. + * + * @param cCapacity The new capacity within the list. + * @throws std::bad_alloc + */ + void setCapacity(size_t cCapacity) + { + m_guard.enterWrite(); + realloc(cCapacity); + m_guard.leaveWrite(); + } + + /** + * Return the current capacity of the list. + * + * @return The actual capacity. + */ + size_t capacity() const { return m_cCapacity; } + + /** + * Check if an list contains any items. + * + * @return True if there is more than zero items, false otherwise. + */ + bool isEmpty() const { return m_cSize == 0; } + + /** + * Return the current count of elements within the list. + * + * @return The current element count. + */ + size_t size() const { return m_cSize; } + + /** + * Inserts an item to the list at position @a i. + * + * @param i The position of the new item. + * @param val The new item. + * @return a reference to this list. + * @throws std::bad_alloc + */ + RTCListBase<T, ITYPE, MT> &insert(size_t i, const T &val) + { + m_guard.enterWrite(); + if (m_cSize == m_cCapacity) + realloc_grow(m_cCapacity + DefaultCapacity); + memmove(&m_pArray[i + 1], &m_pArray[i], (m_cSize - i) * sizeof(ITYPE)); + RTCListHelper<T, ITYPE>::set(m_pArray, i, val); + ++m_cSize; + m_guard.leaveWrite(); + + return *this; + } + + /** + * Prepend an item to the list. + * + * @param val The new item. + * @return a reference to this list. + * @throws std::bad_alloc + */ + RTCListBase<T, ITYPE, MT> &prepend(const T &val) + { + return insert(0, val); + } + + /** + * Prepend a list of type T to the list. + * + * @param other The list to prepend. + * @return a reference to this list. + * @throws std::bad_alloc + */ + RTCListBase<T, ITYPE, MT> &prepend(const RTCListBase<T, ITYPE, MT> &other) + { + m_guard.enterWrite(); + if (m_cCapacity - m_cSize < other.m_cSize) + realloc_grow(m_cCapacity + (other.m_cSize - (m_cCapacity - m_cSize))); + memmove(&m_pArray[other.m_cSize], &m_pArray[0], m_cSize * sizeof(ITYPE)); + RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); + m_cSize += other.m_cSize; + m_guard.leaveWrite(); + + return *this; + } + + /** + * Append an item to the list. + * + * @param val The new item. + * @return a reference to this list. + * @throws std::bad_alloc + */ + RTCListBase<T, ITYPE, MT> &append(const T &val) + { + m_guard.enterWrite(); + if (m_cSize == m_cCapacity) + realloc_grow(m_cCapacity + DefaultCapacity); + RTCListHelper<T, ITYPE>::set(m_pArray, m_cSize, val); + ++m_cSize; + m_guard.leaveWrite(); + + return *this; + } + + /** + * Append a list of type T to the list. + * + * @param other The list to append. + * @return a reference to this list. + * @throws std::bad_alloc + */ + RTCListBase<T, ITYPE, MT> &append(const RTCListBase<T, ITYPE, MT> &other) + { + m_guard.enterWrite(); + if (RT_LIKELY(other.m_cSize > 0)) + { + if (m_cCapacity - m_cSize < other.m_cSize) + realloc_grow(m_cCapacity + (other.m_cSize - (m_cCapacity - m_cSize))); + RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, m_cSize, other.m_cSize); + m_cSize += other.m_cSize; + } + m_guard.leaveWrite(); + + return *this; + } + + /** + * Copy the items of the other list into this list. All previous items of + * this list are deleted. + * + * @param other The list to copy. + * @return a reference to this list. + */ + RTCListBase<T, ITYPE, MT> &operator=(const RTCListBase<T, ITYPE, MT>& other) + { + /* Prevent self assignment */ + if (RT_UNLIKELY(this == &other)) + return *this; + + m_guard.enterWrite(); + /* Delete all items. */ + RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); + /* Need we to realloc memory. */ + if (other.m_cSize != m_cCapacity) + realloc_no_elements_clean(other.m_cSize); + m_cSize = other.m_cSize; + /* Copy new items. */ + RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cSize); + m_guard.leaveWrite(); + + return *this; + } + + /** + * Replace an item in the list. + * + * @note No boundary checks are done. Make sure @a i is equal or greater zero + * and smaller than RTCList::size. + * + * @param i The position of the item to replace. + * @param val The new value. + * @return a reference to this list. + */ + RTCListBase<T, ITYPE, MT> &replace(size_t i, const T &val) + { + m_guard.enterWrite(); + RTCListHelper<T, ITYPE>::erase(m_pArray, i); + RTCListHelper<T, ITYPE>::set(m_pArray, i, val); + m_guard.leaveWrite(); + + return *this; + } + + /** + * Return the first item as constant object. + * + * @note No boundary checks are done. Make sure there is at least one + * element. + * + * @return The first item. + */ + GET_CRTYPE first() const + { + m_guard.enterRead(); + GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, 0); + m_guard.leaveRead(); + return res; + } + + /** + * Return the first item. + * + * @note No boundary checks are done. Make sure there is at least one + * element. + * + * @return The first item. + */ + GET_RTYPE first() + { + m_guard.enterRead(); + GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, 0); + m_guard.leaveRead(); + return res; + } + + /** + * Return the last item as constant object. + * + * @note No boundary checks are done. Make sure there is at least one + * element. + * + * @return The last item. + */ + GET_CRTYPE last() const + { + m_guard.enterRead(); + GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, m_cSize - 1); + m_guard.leaveRead(); + return res; + } + + /** + * Return the last item. + * + * @note No boundary checks are done. Make sure there is at least one + * element. + * + * @return The last item. + */ + GET_RTYPE last() + { + m_guard.enterRead(); + GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, m_cSize - 1); + m_guard.leaveRead(); + return res; + } + + /** + * Return the item at position @a i as constant object. + * + * @note No boundary checks are done. Make sure @a i is equal or greater zero + * and smaller than RTCList::size. + * + * @param i The position of the item to return. + * @return The item at position @a i. + */ + GET_CRTYPE at(size_t i) const + { + m_guard.enterRead(); + GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, i); + m_guard.leaveRead(); + return res; + } + + /** + * Return the item at position @a i. + * + * @note No boundary checks are done. Make sure @a i is equal or greater zero + * and smaller than RTCList::size. + * + * @param i The position of the item to return. + * @return The item at position @a i. + */ + GET_RTYPE at(size_t i) + { + m_guard.enterRead(); + GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, i); + m_guard.leaveRead(); + return res; + } + + /** + * Return the item at position @a i as mutable reference. + * + * @note No boundary checks are done. Make sure @a i is equal or greater zero + * and smaller than RTCList::size. + * + * @param i The position of the item to return. + * @return The item at position @a i. + */ + T &operator[](size_t i) + { + m_guard.enterRead(); + T &res = RTCListHelper<T, ITYPE>::at(m_pArray, i); + m_guard.leaveRead(); + return res; + } + + /** + * Return the item at position @a i. If @a i isn't valid within the list a + * default value is returned. + * + * @param i The position of the item to return. + * @return The item at position @a i. + */ + T value(size_t i) const + { + m_guard.enterRead(); + if (RT_UNLIKELY(i >= m_cSize)) + { + m_guard.leaveRead(); + return T(); + } + T res = RTCListHelper<T, ITYPE>::at(m_pArray, i); + m_guard.leaveRead(); + return res; + } + + /** + * Return the item at position @a i. If @a i isn't valid within the list + * @a defaultVal is returned. + * + * @param i The position of the item to return. + * @param defaultVal The value to return in case @a i is invalid. + * @return The item at position @a i. + */ + T value(size_t i, const T &defaultVal) const + { + m_guard.enterRead(); + if (RT_UNLIKELY(i >= m_cSize)) + { + m_guard.leaveRead(); + return defaultVal; + } + T res = RTCListHelper<T, ITYPE>::at(m_pArray, i); + m_guard.leaveRead(); + return res; + } + + /** + * Check if @a val is contained in the array. + * + * @param val The value to check for. + * @return true if it is found, false otherwise. + */ + bool contains(const T &val) const + { + m_guard.enterRead(); + bool res = RTCListHelper<T, ITYPE>::find(m_pArray, val, m_cSize) != m_cSize; + m_guard.leaveRead(); + return res; + } + + /** + * Remove the first item. + * + * @note No boundary checks are done. Make sure there is at least one + * element. + */ + void removeFirst() + { + removeAt(0); + } + + /** + * Remove the last item. + * + * @note No boundary checks are done. Make sure there is at least one + * element. + */ + void removeLast() + { + removeAt(m_cSize - 1); + } + + /** + * Remove the item at position @a i. + * + * @note No boundary checks are done. Make sure @a i is equal or greater zero + * and smaller than RTCList::size. + * + * @param i The position of the item to remove. + */ + void removeAt(size_t i) + { + m_guard.enterWrite(); + RTCListHelper<T, ITYPE>::erase(m_pArray, i); + /* Not last element? */ + if (i < m_cSize - 1) + memmove(&m_pArray[i], &m_pArray[i + 1], (m_cSize - i - 1) * sizeof(ITYPE)); + --m_cSize; + m_guard.leaveWrite(); + } + + /** + * Remove a range of items from the list. + * + * @note No boundary checks are done. Make sure @a iFrom is equal or + * greater zero and smaller than RTCList::size. @a iTo has to be + * greater than @a iFrom and equal or smaller than RTCList::size. + * + * @param iFrom The start position of the items to remove. + * @param iTo The end position of the items to remove (excluded). + */ + void removeRange(size_t iFrom, size_t iTo) + { + m_guard.enterWrite(); + RTCListHelper<T, ITYPE>::eraseRange(m_pArray, iFrom, iTo - iFrom); + /* Not last elements? */ + if (m_cSize - iTo > 0) + memmove(&m_pArray[iFrom], &m_pArray[iTo], (m_cSize - iTo) * sizeof(ITYPE)); + m_cSize -= iTo - iFrom; + m_guard.leaveWrite(); + } + + /** + * Delete all items in the list. + */ + void clear() + { + m_guard.enterWrite(); + /* Values cleanup */ + RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize); + if (m_cSize != DefaultCapacity) + realloc_no_elements_clean(DefaultCapacity); + m_cSize = 0; + m_guard.leaveWrite(); + } + + /** + * Return the raw array. For native types this is a pointer to continuous + * memory of the items. For pointer types this is a continuous memory of + * pointers to the items. + * + * @warning If you change anything in the underlaying list, this memory + * will very likely become invalid. So take care when using this + * method and better try to avoid using it. + * + * @returns the raw memory. + */ + ITYPE* raw() const + { + m_guard.enterRead(); + ITYPE* res = m_pArray; + m_guard.leaveRead(); + return res; + } + + RTCListBase<T, ITYPE, MT> &operator<<(const T &val) + { + return append(val); + } + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); + + /** + * The default capacity of the list. This is also used as grow factor. + */ + static const size_t DefaultCapacity; + +protected: + + /** + * Generic realloc, which does some kind of boundary checking. + */ + void realloc(size_t cNewSize) + { + /* Same size? */ + if (cNewSize == m_cCapacity) + return; + + /* If we get smaller we have to delete some of the objects at the end + of the list. */ + if ( cNewSize < m_cSize + && m_pArray) + RTCListHelper<T, ITYPE>::eraseRange(m_pArray, cNewSize, m_cSize - cNewSize); + realloc_no_elements_clean(cNewSize); + } + + void realloc_no_elements_clean(size_t cNewSize) + { + /* Same size? */ + if (cNewSize == m_cCapacity) + return; + + /* If we get smaller we have to delete some of the objects at the end + of the list. */ + if ( cNewSize < m_cSize + && m_pArray) + m_cSize -= m_cSize - cNewSize; + + /* If we get zero we delete the array it self. */ + if ( cNewSize == 0 + && m_pArray) + { + RTMemFree(m_pArray); + m_pArray = 0; + } + m_cCapacity = cNewSize; + + /* Resize the array. */ + if (cNewSize > 0) + { + m_pArray = static_cast<ITYPE*>(RTMemRealloc(m_pArray, sizeof(ITYPE) * cNewSize)); + if (!m_pArray) + { + /** @todo you leak memory. */ + m_cCapacity = 0; + m_cSize = 0; +#ifdef RT_EXCEPTIONS_ENABLED + throw std::bad_alloc(); +#endif + } + } + } + + /** + * Special realloc method which require that the array will grow. + * + * @note No boundary checks are done! + */ + void realloc_grow(size_t cNewSize) + { + /* Resize the array. */ + m_cCapacity = cNewSize; + m_pArray = static_cast<ITYPE*>(RTMemRealloc(m_pArray, sizeof(ITYPE) * cNewSize)); + if (!m_pArray) + { + /** @todo you leak memory. */ + m_cCapacity = 0; + m_cSize = 0; +#ifdef RT_EXCEPTIONS_ENABLED + throw std::bad_alloc(); +#endif + } + } + + /** The internal list array. */ + ITYPE *m_pArray; + /** The current count of items in use. */ + size_t m_cSize; + /** The current capacity of the internal array. */ + size_t m_cCapacity; + /** The guard used to serialize the access to the items. */ + RTCListGuard<MT> m_guard; +}; + +template <class T, typename ITYPE, bool MT> +const size_t RTCListBase<T, ITYPE, MT>::DefaultCapacity = 10; + +/** + * Template class which automatically determines the type of list to use. + * + * @see RTCListBase + */ +template <class T, typename ITYPE = typename RTCIf<(sizeof(T) > sizeof(void*)), T*, T>::result> +class RTCList : public RTCListBase<T, ITYPE, false> +{ + /* Traits */ + typedef RTCListBase<T, ITYPE, false> BASE; + +public: + /** + * Creates a new list. + * + * This preallocates @a cCapacity elements within the list. + * + * @param cCapacitiy The initial capacity the list has. + * @throws std::bad_alloc + */ + RTCList(size_t cCapacity = BASE::DefaultCapacity) + : BASE(cCapacity) {} + + RTCList(const BASE &other) + : BASE(other) {} + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); +}; + +/** + * Specialized class for using the native type list for unsigned 64-bit + * values even on a 32-bit host. + * + * @see RTCListBase + */ +template <> +class RTCList<uint64_t>: public RTCListBase<uint64_t, uint64_t, false> +{ + /* Traits */ + typedef RTCListBase<uint64_t, uint64_t, false> BASE; + +public: + /** + * Creates a new list. + * + * This preallocates @a cCapacity elements within the list. + * + * @param cCapacitiy The initial capacity the list has. + * @throws std::bad_alloc + */ + RTCList(size_t cCapacity = BASE::DefaultCapacity) + : BASE(cCapacity) {} + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); +}; + +/** + * Specialized class for using the native type list for signed 64-bit + * values even on a 32-bit host. + * + * @see RTCListBase + */ +template <> +class RTCList<int64_t>: public RTCListBase<int64_t, int64_t, false> +{ + /* Traits */ + typedef RTCListBase<int64_t, int64_t, false> BASE; + +public: + /** + * Creates a new list. + * + * This preallocates @a cCapacity elements within the list. + * + * @param cCapacitiy The initial capacity the list has. + * @throws std::bad_alloc + */ + RTCList(size_t cCapacity = BASE::DefaultCapacity) + : BASE(cCapacity) {} + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); +}; + +/** @} */ + +#endif /* !___iprt_cpp_list_h */ + diff --git a/include/iprt/cpp/lock.h b/include/iprt/cpp/lock.h new file mode 100644 index 00000000..1ea6c3cc --- /dev/null +++ b/include/iprt/cpp/lock.h @@ -0,0 +1,166 @@ +/** @file + * IPRT - Classes for Scope-based Locking. + */ + +/* + * Copyright (C) 2007-2011 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. + */ + +#ifndef ___iprt_cpp_lock_h +#define ___iprt_cpp_lock_h + +#include <iprt/critsect.h> +#ifdef RT_LOCK_STRICT +# include <iprt/lockvalidator.h> +#endif + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_cpp_lock C++ Scope-based Locking + * @ingroup grp_rt_cpp + * @{ + */ + +class RTCLock; + +/** + * The mutex lock. + * + * This is used as an object data member if the intention is to lock + * a single object. This can also be used statically, initialized in + * a global variable, for class wide purposes. + * + * This is best used together with RTCLock. + */ +class RTCLockMtx +{ +friend class RTCLock; + +private: + RTCRITSECT mMtx; + +public: + RTCLockMtx() + { +#ifdef RT_LOCK_STRICT_ORDER + RTCritSectInitEx(&mMtx, 0 /*fFlags*/, + RTLockValidatorClassCreateUnique(RT_SRC_POS, NULL), + RTLOCKVAL_SUB_CLASS_NONE, NULL); +#else + RTCritSectInit(&mMtx); +#endif + } + + /** Use to when creating locks that belongs in the same "class". */ + RTCLockMtx(RT_SRC_POS_DECL, uint32_t uSubClass = RTLOCKVAL_SUB_CLASS_NONE) + { +#ifdef RT_LOCK_STRICT_ORDER + RTCritSectInitEx(&mMtx, 0 /*fFlags*/, + RTLockValidatorClassForSrcPos(RT_SRC_POS_ARGS, NULL), + uSubClass, NULL); +#else + NOREF(uSubClass); + RTCritSectInit(&mMtx); + RT_SRC_POS_NOREF(); +#endif + } + + ~RTCLockMtx() + { + RTCritSectDelete(&mMtx); + } + + /* lock() and unlock() are private so that only friend RTCLock can access + them. */ +private: + inline void lock() + { + RTCritSectEnter(&mMtx); + } + + inline void unlock() + { + RTCritSectLeave(&mMtx); + } +}; + + +/** + * The stack object for automatic locking and unlocking. + * + * This is a helper class for automatic locks, to simplify requesting a + * RTCLockMtx and to not forget releasing it. To request a RTCLockMtx, simply + * create an instance of RTCLock on the stack and pass the mutex to it: + * + * @code + extern RTCLockMtx gMtx; // wherever this is + ... + if (...) + { + RTCLock lock(gMtx); + ... // do stuff + // when lock goes out of scope, destructor releases the mutex + } + @endcode + * + * You can also explicitly release the mutex by calling RTCLock::release(). + * This might be helpful if the lock doesn't go out of scope early enough + * for your mutex to be released. + */ +class RTCLock +{ +private: + /** Reference to the lock we're holding. */ + RTCLockMtx &m_rMtx; + /** Whether we're currently holding the lock of if it was already + * explictily released by the release() method. */ + bool m_fLocked; + +public: + RTCLock(RTCLockMtx &a_rMtx) + : m_rMtx(a_rMtx) + { + m_rMtx.lock(); + m_fLocked = true; + } + + ~RTCLock() + { + if (m_fLocked) + m_rMtx.unlock(); + } + + inline void release() + { + if (m_fLocked) + { + m_rMtx.unlock(); + m_fLocked = false; + } + } +}; + + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/cpp/mem.h b/include/iprt/cpp/mem.h new file mode 100644 index 00000000..66f6ab95 --- /dev/null +++ b/include/iprt/cpp/mem.h @@ -0,0 +1,271 @@ +/** @file + * IPRT - C++ Memory Resource Management. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_cpp_mem_h +#define ___iprt_cpp_mem_h + +#include <iprt/cpp/autores.h> +#include <iprt/assert.h> +#include <iprt/mem.h> +#include <iprt/string.h> /* for memset */ + +/** @defgroup grp_rt_cpp_autores_mem C++ Memory Resource Management + * @ingroup grp_rt_cpp_autores + * @{ + */ + +/** + * Template function wrapping RTMemFree to get the correct a_fnDestruct + * signature for RTCAutoRes. + * + * We can't use a more complex template here, because the g++ on RHEL 3 + * chokes on it with an internal compiler error. + * + * @tparam T The data type that's being managed. + * @param aMem Pointer to the memory that should be free. + */ +template <class T> +inline void RTCMemAutoDestructor(T *aMem) RT_NO_THROW +{ + RTMemFree(aMem); +} + + +/** + * RTCMemAutoPtr allocator which uses RTMemTmpAlloc(). + * + * @returns Allocated memory on success, NULL on failure. + * @param pvOld What to reallocate, shall always be NULL. + * @param cbNew The amount of memory to allocate (in bytes). + */ +inline void *RTCMemTmpAutoAllocator(void *pvOld, size_t cbNew) RT_NO_THROW +{ + AssertReturn(!pvOld, NULL); + return RTMemTmpAlloc(cbNew); +} + + +/** + * Template function wrapping RTMemTmpFree to get the correct a_fnDestruct + * signature for RTCAutoRes. + * + * We can't use a more complex template here, because the g++ on RHEL 3 + * chokes on it with an internal compiler error. + * + * @tparam T The data type that's being managed. + * @param aMem Pointer to the memory that should be free. + */ +template <class T> +inline void RTCMemTmpAutoDestructor(T *aMem) RT_NO_THROW +{ + RTMemTmpFree(aMem); +} + + +/** + * Template function wrapping RTMemEfFree to get the correct a_fnDestruct + * signature for RTCAutoRes. + * + * We can't use a more complex template here, because the g++ on RHEL 3 + * chokes on it with an internal compiler error. + * + * @tparam T The data type that's being managed. + * @param aMem Pointer to the memory that should be free. + */ +template <class T> +inline void RTCMemEfAutoFree(T *aMem) RT_NO_THROW +{ + RTMemEfFreeNP(aMem); +} + + +/** + * Template function wrapping NULL to get the correct NilRes signature + * for RTCAutoRes. + * + * @tparam T The data type that's being managed. + * @returns NULL with the right type. + */ +template <class T> +inline T *RTCMemAutoNil(void) RT_NO_THROW +{ + return (T *)(NULL); +} + + +/** + * An auto pointer-type template class for managing memory allocating + * via C APIs like RTMem (the default). + * + * The main purpose of this class is to automatically free memory that + * isn't explicitly used (release()'ed) when the object goes out of scope. + * + * As an additional service it can also make the allocations and + * reallocations for you if you like, but it can also take of memory + * you hand it. + * + * @tparam T The data type to manage allocations for. + * @tparam a_fnDestruct The function to be used to free the resource. + * This will default to RTMemFree. + * @tparam a_fnAllocator The function to be used to allocate or reallocate + * the managed memory. + * This is standard realloc() like stuff, so it's + * possible to support simple allocation without + * actually having to support reallocating memory if + * that's a problem. This will default to + * RTMemRealloc. + */ +template <class T, + void a_fnDestruct(T *) = RTCMemAutoDestructor<T>, +# if defined(RTMEM_WRAP_TO_EF_APIS) && !defined(RTMEM_NO_WRAP_TO_EF_APIS) + void *a_fnAllocator(void *, size_t, const char *) = RTMemEfReallocNP +# else + void *a_fnAllocator(void *, size_t, const char *) = RTMemReallocTag +# endif + > +class RTCMemAutoPtr + : public RTCAutoRes<T *, a_fnDestruct, RTCMemAutoNil<T> > +{ +public: + /** + * Constructor. + * + * @param aPtr Memory pointer to manage. Defaults to NULL. + */ + RTCMemAutoPtr(T *aPtr = NULL) + : RTCAutoRes<T *, a_fnDestruct, RTCMemAutoNil<T> >(aPtr) + { + } + + /** + * Constructor that allocates memory. + * + * @param a_cElements The number of elements (of the data type) to allocate. + * @param a_fZeroed Whether the memory should be memset with zeros after + * the allocation. Defaults to false. + */ + RTCMemAutoPtr(size_t a_cElements, bool a_fZeroed = false) + : RTCAutoRes<T *, a_fnDestruct, RTCMemAutoNil<T> >((T *)a_fnAllocator(NULL, a_cElements * sizeof(T), RTMEM_TAG)) + { + if (a_fZeroed && RT_LIKELY(this->get() != NULL)) + memset(this->get(), '\0', a_cElements * sizeof(T)); + } + + /** + * Free current memory and start managing aPtr. + * + * @param aPtr Memory pointer to manage. + */ + RTCMemAutoPtr &operator=(T *aPtr) + { + this->RTCAutoRes<T *, a_fnDestruct, RTCMemAutoNil<T> >::operator=(aPtr); + return *this; + } + + /** + * Dereference with * operator. + */ + T &operator*() + { + return *this->get(); + } + + /** + * Dereference with -> operator. + */ + T *operator->() + { + return this->get(); + } + + /** + * Accessed with the subscript operator ([]). + * + * @returns Reference to the element. + * @param a_i The element to access. + */ + T &operator[](size_t a_i) + { + return this->get()[a_i]; + } + + /** + * Allocates memory and start manage it. + * + * Any previously managed memory will be freed before making + * the new allocation. + * + * @returns Success indicator. + * @retval true if the new allocation succeeds. + * @retval false on failure, no memory is associated with the object. + * + * @param a_cElements The number of elements (of the data type) to allocate. + * This defaults to 1. + * @param a_fZeroed Whether the memory should be memset with zeros after + * the allocation. Defaults to false. + */ + bool alloc(size_t a_cElements = 1, bool a_fZeroed = false) + { + this->reset(NULL); + T *pNewMem = (T *)a_fnAllocator(NULL, a_cElements * sizeof(T), RTMEM_TAG); + if (a_fZeroed && RT_LIKELY(pNewMem != NULL)) + memset(pNewMem, '\0', a_cElements * sizeof(T)); + this->reset(pNewMem); + return pNewMem != NULL; + } + + /** + * Reallocate or allocates the memory resource. + * + * Free the old value if allocation fails. + * + * The content of any additional memory that was allocated is + * undefined when using the default allocator. + * + * @returns Success indicator. + * @retval true if the new allocation succeeds. + * @retval false on failure, no memory is associated with the object. + * + * @param a_cElements The new number of elements (of the data type) to + * allocate. The size of the allocation is the number of + * elements times the size of the data type - this is + * currently what's passed down to the a_fnAllocator. + * This defaults to 1. + */ + bool realloc(size_t a_cElements = 1) + { + T *aNewValue = (T *)a_fnAllocator(this->get(), a_cElements * sizeof(T), RTMEM_TAG); + if (RT_LIKELY(aNewValue != NULL)) + this->release(); + /* We want this both if aNewValue is non-NULL and if it is NULL. */ + this->reset(aNewValue); + return aNewValue != NULL; + } +}; + +/** @} */ + +#endif + diff --git a/include/iprt/cpp/meta.h b/include/iprt/cpp/meta.h new file mode 100644 index 00000000..81249d26 --- /dev/null +++ b/include/iprt/cpp/meta.h @@ -0,0 +1,110 @@ +/** @file + * IPRT - C++ Meta programming. + */ + +/* + * Copyright (C) 2011 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. + */ + +#ifndef ___iprt_cpp_meta_h +#define ___iprt_cpp_meta_h + +/** @defgroup grp_rt_cpp_meta C++ Meta programming utilities + * @ingroup grp_rt_cpp + * @{ + */ + +/** + * Check for a condition on compile time and dependent of the result TrueResult + * or FalseResult will be defined. + * + * @param Condition Condition to check. + * @param TrueResult Result when condition is true. + * @param FalseResult Result when condition is false + */ +template <bool Condition, typename TrueResult, typename FalseResult> +struct RTCIf; + +/** + * Check for a condition on compile time and dependent of the result TrueResult + * or FalseResult will be defined. + * + * True specialization of RTCIf. + * + * @param TrueResult Result when condition is true. + * @param FalseResult Result when condition is false + */ +template <typename TrueResult, typename FalseResult> +struct RTCIf<true, TrueResult, FalseResult> +{ + typedef TrueResult result; +}; + +/** + * Check for a condition on compile time and dependent of the result TrueResult + * or FalseResult will be defined. + * + * False specialization of RTCIf. + * + * @param TrueResult Result when condition is true. + * @param FalseResult Result when condition is false + */ +template <typename TrueResult, typename FalseResult> +struct RTCIf<false, TrueResult, FalseResult> +{ + typedef FalseResult result; +}; + +/** + * Check if @a T is a pointer or not at compile time and dependent of the + * result TrueResult or FalseResult will be defined. + * + * False version of RTCIfPtr. + * + * @param Condition Condition to check. + * @param TrueResult Result when condition is true. + * @param FalseResult Result when condition is false + */ +template <class T, typename TrueResult, typename FalseResult> +struct RTCIfPtr +{ + typedef FalseResult result; +}; + +/** + * Check if @a T is a pointer or not at compile time and dependent of the + * result TrueResult or FalseResult will be defined. + * + * True specialization of RTCIfPtr. + * + * @param Condition Condition to check. + * @param TrueResult Result when condition is true. + * @param FalseResult Result when condition is false + */ +template <class T, typename TrueResult, typename FalseResult> +struct RTCIfPtr<T*, TrueResult, FalseResult> +{ + typedef TrueResult result; +}; + +/** @} */ + +#endif /* !___iprt_cpp_meta_h */ + diff --git a/include/iprt/cpp/ministring.h b/include/iprt/cpp/ministring.h new file mode 100644 index 00000000..29c97409 --- /dev/null +++ b/include/iprt/cpp/ministring.h @@ -0,0 +1,1023 @@ +/** @file + * IPRT - C++ string class. + */ + +/* + * Copyright (C) 2007-2011 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. + */ + +#ifndef ___iprt_cpp_ministring_h +#define ___iprt_cpp_ministring_h + +#include <iprt/mem.h> +#include <iprt/string.h> +#include <iprt/stdarg.h> +#include <iprt/cpp/list.h> + +#include <new> + + +/** @defgroup grp_rt_cpp_string C++ String support + * @ingroup grp_rt_cpp + * @{ + */ + +/** @brief C++ string class. + * + * This is a C++ string class that does not depend on anything else except IPRT + * memory management functions. Semantics are like in std::string, except it + * can do a lot less. + * + * Note that RTCString does not differentiate between NULL strings + * and empty strings. In other words, RTCString("") and RTCString(NULL) + * behave the same. In both cases, RTCString allocates no memory, reports + * a zero length and zero allocated bytes for both, and returns an empty + * C string from c_str(). + * + * @note RTCString ASSUMES that all strings it deals with are valid UTF-8. + * The caller is responsible for not breaking this assumption. + */ +#ifdef VBOX + /** @remarks Much of the code in here used to be in com::Utf8Str so that + * com::Utf8Str can now derive from RTCString and only contain code + * that is COM-specific, such as com::Bstr conversions. Compared to + * the old Utf8Str though, RTCString always knows the length of its + * member string and the size of the buffer so it can use memcpy() + * instead of strdup(). + */ +#endif +class RT_DECL_CLASS RTCString +{ +public: + /** + * Creates an empty string that has no memory allocated. + */ + RTCString() + : m_psz(NULL), + m_cch(0), + m_cbAllocated(0) + { + } + + /** + * Creates a copy of another RTCString. + * + * This allocates s.length() + 1 bytes for the new instance, unless s is empty. + * + * @param a_rSrc The source string. + * + * @throws std::bad_alloc + */ + RTCString(const RTCString &a_rSrc) + { + copyFromN(a_rSrc.m_psz, a_rSrc.m_cch); + } + + /** + * Creates a copy of a C string. + * + * This allocates strlen(pcsz) + 1 bytes for the new instance, unless s is empty. + * + * @param pcsz The source string. + * + * @throws std::bad_alloc + */ + RTCString(const char *pcsz) + { + copyFromN(pcsz, pcsz ? strlen(pcsz) : 0); + } + + /** + * Create a partial copy of another RTCString. + * + * @param a_rSrc The source string. + * @param a_offSrc The byte offset into the source string. + * @param a_cchSrc The max number of chars (encoded UTF-8 bytes) + * to copy from the source string. + */ + RTCString(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc = npos) + { + if (a_offSrc < a_rSrc.m_cch) + copyFromN(&a_rSrc.m_psz[a_offSrc], RT_MIN(a_cchSrc, a_rSrc.m_cch - a_offSrc)); + else + { + m_psz = NULL; + m_cch = 0; + m_cbAllocated = 0; + } + } + + /** + * Create a partial copy of a C string. + * + * @param a_pszSrc The source string (UTF-8). + * @param a_cchSrc The max number of chars (encoded UTF-8 bytes) + * to copy from the source string. This must not + * be '0' as the compiler could easily mistake + * that for the va_list constructor. + */ + RTCString(const char *a_pszSrc, size_t a_cchSrc) + { + size_t cchMax = a_pszSrc ? RTStrNLen(a_pszSrc, a_cchSrc) : 0; + copyFromN(a_pszSrc, RT_MIN(a_cchSrc, cchMax)); + } + + /** + * Create a string containing @a a_cTimes repetitions of the character @a + * a_ch. + * + * @param a_cTimes The number of times the character is repeated. + * @param a_ch The character to fill the string with. + */ + RTCString(size_t a_cTimes, char a_ch) + : m_psz(NULL), + m_cch(0), + m_cbAllocated(0) + { + Assert((unsigned)a_ch < 0x80); + if (a_cTimes) + { + reserve(a_cTimes + 1); + memset(m_psz, a_ch, a_cTimes); + m_psz[a_cTimes] = '\0'; + m_cch = a_cTimes; + } + } + + /** + * Create a new string given the format string and its arguments. + * + * @param a_pszFormat Pointer to the format string (UTF-8), + * @see pg_rt_str_format. + * @param a_va Argument vector containing the arguments + * specified by the format string. + * @sa printfV + * @remarks Not part of std::string. + */ + RTCString(const char *a_pszFormat, va_list a_va) + : m_psz(NULL), + m_cch(0), + m_cbAllocated(0) + { + printfV(a_pszFormat, a_va); + } + + /** + * Destructor. + */ + virtual ~RTCString() + { + cleanup(); + } + + /** + * String length in bytes. + * + * Returns the length of the member string in bytes, which is equal to strlen(c_str()). + * In other words, this does not count unicode codepoints; use utf8length() for that. + * The byte length is always cached so calling this is cheap and requires no + * strlen() invocation. + * + * @returns m_cbLength. + */ + size_t length() const + { + return m_cch; + } + + /** + * String length in unicode codepoints. + * + * As opposed to length(), which returns the length in bytes, this counts + * the number of unicode codepoints. This is *not* cached so calling this + * is expensive. + * + * @returns Number of codepoints in the member string. + */ + size_t uniLength() const + { + return m_psz ? RTStrUniLen(m_psz) : 0; + } + + /** + * The allocated buffer size (in bytes). + * + * Returns the number of bytes allocated in the internal string buffer, which is + * at least length() + 1 if length() > 0; for an empty string, this returns 0. + * + * @returns m_cbAllocated. + */ + size_t capacity() const + { + return m_cbAllocated; + } + + /** + * Make sure at that least cb of buffer space is reserved. + * + * Requests that the contained memory buffer have at least cb bytes allocated. + * This may expand or shrink the string's storage, but will never truncate the + * contained string. In other words, cb will be ignored if it's smaller than + * length() + 1. + * + * @param cb New minimum size (in bytes) of member memory buffer. + * + * @throws std::bad_alloc On allocation error. The object is left unchanged. + */ + void reserve(size_t cb) + { + if ( cb != m_cbAllocated + && cb > m_cch + 1 + ) + { + int vrc = RTStrRealloc(&m_psz, cb); + if (RT_SUCCESS(vrc)) + m_cbAllocated = cb; +#ifdef RT_EXCEPTIONS_ENABLED + else + throw std::bad_alloc(); +#endif + } + } + + /** + * Deallocates all memory. + */ + inline void setNull() + { + cleanup(); + } + + RTMEMEF_NEW_AND_DELETE_OPERATORS(); + + /** + * Assigns a copy of pcsz to "this". + * + * @param pcsz The source string. + * + * @throws std::bad_alloc On allocation failure. The object is left describing + * a NULL string. + * + * @returns Reference to the object. + */ + RTCString &operator=(const char *pcsz) + { + if (m_psz != pcsz) + { + cleanup(); + copyFromN(pcsz, pcsz ? strlen(pcsz) : 0); + } + return *this; + } + + /** + * Assigns a copy of s to "this". + * + * @param s The source string. + * + * @throws std::bad_alloc On allocation failure. The object is left describing + * a NULL string. + * + * @returns Reference to the object. + */ + RTCString &operator=(const RTCString &s) + { + if (this != &s) + { + cleanup(); + copyFromN(s.m_psz, s.m_cch); + } + return *this; + } + + /** + * Assigns the output of the string format operation (RTStrPrintf). + * + * @param pszFormat Pointer to the format string, + * @see pg_rt_str_format. + * @param ... Ellipsis containing the arguments specified by + * the format string. + * + * @throws std::bad_alloc On allocation error. The object is left unchanged. + * + * @returns Reference to the object. + */ + RTCString &printf(const char *pszFormat, ...); + + /** + * Assigns the output of the string format operation (RTStrPrintfV). + * + * @param pszFormat Pointer to the format string, + * @see pg_rt_str_format. + * @param va Argument vector containing the arguments + * specified by the format string. + * + * @throws std::bad_alloc On allocation error. The object is left unchanged. + * + * @returns Reference to the object. + */ + RTCString &printfV(const char *pszFormat, va_list va); + + /** + * Appends the string "that" to "this". + * + * @param that The string to append. + * + * @throws std::bad_alloc On allocation error. The object is left unchanged. + * + * @returns Reference to the object. + */ + RTCString &append(const RTCString &that); + + /** + * Appends the string "that" to "this". + * + * @param pszThat The C string to append. + * + * @throws std::bad_alloc On allocation error. The object is left unchanged. + * + * @returns Reference to the object. + */ + RTCString &append(const char *pszThat); + + /** + * Appends the given character to "this". + * + * @param ch The character to append. + * + * @throws std::bad_alloc On allocation error. The object is left unchanged. + * + * @returns Reference to the object. + */ + RTCString &append(char ch); + + /** + * Appends the given unicode code point to "this". + * + * @param uc The unicode code point to append. + * + * @throws std::bad_alloc On allocation error. The object is left unchanged. + * + * @returns Reference to the object. + */ + RTCString &appendCodePoint(RTUNICP uc); + + /** + * Shortcut to append(), RTCString variant. + * + * @param that The string to append. + * + * @returns Reference to the object. + */ + RTCString &operator+=(const RTCString &that) + { + return append(that); + } + + /** + * Shortcut to append(), const char* variant. + * + * @param pszThat The C string to append. + * + * @returns Reference to the object. + */ + RTCString &operator+=(const char *pszThat) + { + return append(pszThat); + } + + /** + * Shortcut to append(), char variant. + * + * @param pszThat The character to append. + * + * @returns Reference to the object. + */ + RTCString &operator+=(char c) + { + return append(c); + } + + /** + * Converts the member string to upper case. + * + * @returns Reference to the object. + */ + RTCString &toUpper() + { + if (length()) + { + /* Folding an UTF-8 string may result in a shorter encoding (see + testcase), so recalculate the length afterwars. */ + ::RTStrToUpper(m_psz); + size_t cchNew = strlen(m_psz); + Assert(cchNew <= m_cch); + m_cch = cchNew; + } + return *this; + } + + /** + * Converts the member string to lower case. + * + * @returns Reference to the object. + */ + RTCString &toLower() + { + if (length()) + { + /* Folding an UTF-8 string may result in a shorter encoding (see + testcase), so recalculate the length afterwars. */ + ::RTStrToLower(m_psz); + size_t cchNew = strlen(m_psz); + Assert(cchNew <= m_cch); + m_cch = cchNew; + } + return *this; + } + + /** + * Index operator. + * + * Returns the byte at the given index, or a null byte if the index is not + * smaller than length(). This does _not_ count codepoints but simply points + * into the member C string. + * + * @param i The index into the string buffer. + * @returns char at the index or null. + */ + inline char operator[](size_t i) const + { + if (i < length()) + return m_psz[i]; + return '\0'; + } + + /** + * Returns the contained string as a C-style const char* pointer. + * This never returns NULL; if the string is empty, this returns a + * pointer to static null byte. + * + * @returns const pointer to C-style string. + */ + inline const char *c_str() const + { + return (m_psz) ? m_psz : ""; + } + + /** + * Returns a non-const raw pointer that allows to modify the string directly. + * As opposed to c_str() and raw(), this DOES return NULL for an empty string + * because we cannot return a non-const pointer to a static "" global. + * + * @warning + * -# Be sure not to modify data beyond the allocated memory! Call + * capacity() to find out how large that buffer is. + * -# After any operation that modifies the length of the string, + * you _must_ call RTCString::jolt(), or subsequent copy operations + * may go nowhere. Better not use mutableRaw() at all. + */ + char *mutableRaw() + { + return m_psz; + } + + /** + * Clean up after using mutableRaw. + * + * Intended to be called after something has messed with the internal string + * buffer (e.g. after using mutableRaw() or Utf8Str::asOutParam()). Resets the + * internal lengths correctly. Otherwise subsequent copy operations may go + * nowhere. + */ + void jolt() + { + if (m_psz) + { + m_cch = strlen(m_psz); + m_cbAllocated = m_cch + 1; /* (Required for the Utf8Str::asOutParam case) */ + } + else + { + m_cch = 0; + m_cbAllocated = 0; + } + } + + /** + * Returns @c true if the member string has no length. + * + * This is @c true for instances created from both NULL and "" input + * strings. + * + * This states nothing about how much memory might be allocated. + * + * @returns @c true if empty, @c false if not. + */ + bool isEmpty() const + { + return length() == 0; + } + + /** + * Returns @c false if the member string has no length. + * + * This is @c false for instances created from both NULL and "" input + * strings. + * + * This states nothing about how much memory might be allocated. + * + * @returns @c false if empty, @c true if not. + */ + bool isNotEmpty() const + { + return length() != 0; + } + + /** Case sensitivity selector. */ + enum CaseSensitivity + { + CaseSensitive, + CaseInsensitive + }; + + /** + * Compares the member string to a C-string. + * + * @param pcszThat The string to compare with. + * @param cs Whether comparison should be case-sensitive. + * @returns 0 if equal, negative if this is smaller than @a pcsz, positive + * if larger. + */ + int compare(const char *pcszThat, CaseSensitivity cs = CaseSensitive) const + { + /* This klugde is for m_cch=0 and m_psz=NULL. pcsz=NULL and psz="" + are treated the same way so that str.compare(str2.c_str()) works. */ + if (length() == 0) + return pcszThat == NULL || *pcszThat == '\0' ? 0 : -1; + + if (cs == CaseSensitive) + return ::RTStrCmp(m_psz, pcszThat); + return ::RTStrICmp(m_psz, pcszThat); + } + + /** + * Compares the member string to another RTCString. + * + * @param pcszThat The string to compare with. + * @param cs Whether comparison should be case-sensitive. + * @returns 0 if equal, negative if this is smaller than @a pcsz, positive + * if larger. + */ + int compare(const RTCString &that, CaseSensitivity cs = CaseSensitive) const + { + if (cs == CaseSensitive) + return ::RTStrCmp(m_psz, that.m_psz); + return ::RTStrICmp(m_psz, that.m_psz); + } + + /** + * Compares the two strings. + * + * @returns true if equal, false if not. + * @param that The string to compare with. + */ + bool equals(const RTCString &that) const + { + return that.length() == length() + && memcmp(that.m_psz, m_psz, length()) == 0; + } + + /** + * Compares the two strings. + * + * @returns true if equal, false if not. + * @param pszThat The string to compare with. + */ + bool equals(const char *pszThat) const + { + /* This klugde is for m_cch=0 and m_psz=NULL. pcsz=NULL and psz="" + are treated the same way so that str.equals(str2.c_str()) works. */ + if (length() == 0) + return pszThat == NULL || *pszThat == '\0'; + return RTStrCmp(pszThat, m_psz) == 0; + } + + /** + * Compares the two strings ignoring differences in case. + * + * @returns true if equal, false if not. + * @param that The string to compare with. + */ + bool equalsIgnoreCase(const RTCString &that) const + { + /* Unfolded upper and lower case characters may require different + amount of encoding space, so the length optimization doesn't work. */ + return RTStrICmp(that.m_psz, m_psz) == 0; + } + + /** + * Compares the two strings ignoring differences in case. + * + * @returns true if equal, false if not. + * @param pszThat The string to compare with. + */ + bool equalsIgnoreCase(const char *pszThat) const + { + /* This klugde is for m_cch=0 and m_psz=NULL. pcsz=NULL and psz="" + are treated the same way so that str.equalsIgnoreCase(str2.c_str()) works. */ + if (length() == 0) + return pszThat == NULL || *pszThat == '\0'; + return RTStrICmp(pszThat, m_psz) == 0; + } + + /** @name Comparison operators. + * @{ */ + bool operator==(const RTCString &that) const { return equals(that); } + bool operator!=(const RTCString &that) const { return !equals(that); } + bool operator<( const RTCString &that) const { return compare(that) < 0; } + bool operator>( const RTCString &that) const { return compare(that) > 0; } + + bool operator==(const char *pszThat) const { return equals(pszThat); } + bool operator!=(const char *pszThat) const { return !equals(pszThat); } + bool operator<( const char *pszThat) const { return compare(pszThat) < 0; } + bool operator>( const char *pszThat) const { return compare(pszThat) > 0; } + /** @} */ + + /** Max string offset value. + * + * When returned by a method, this indicates failure. When taken as input, + * typically a default, it means all the way to the string terminator. + */ + static const size_t npos; + + /** + * Find the given substring. + * + * Looks for pcszFind in "this" starting at "pos" and returns its position + * as a byte (not codepoint) offset, counting from the beginning of "this" at 0. + * + * @param pcszFind The substring to find. + * @param pos The (byte) offset into the string buffer to start + * searching. + * + * @returns 0 based position of pcszFind. npos if not found. + */ + size_t find(const char *pcszFind, size_t pos = 0) const; + + /** + * Replaces all occurences of cFind with cReplace in the member string. + * In order not to produce invalid UTF-8, the characters must be ASCII + * values less than 128; this is not verified. + * + * @param chFind Character to replace. Must be ASCII < 128. + * @param chReplace Character to replace cFind with. Must be ASCII < 128. + */ + void findReplace(char chFind, char chReplace); + + /** + * Count the occurences of the specified character in the string. + * + * @param ch What to search for. Must be ASCII < 128. + * @remarks QString::count + */ + size_t count(char ch) const; + + /** + * Count the occurences of the specified sub-string in the string. + * + * @param psz What to search for. + * @param cs Case sensitivity selector. + * @remarks QString::count + */ + size_t count(const char *psz, CaseSensitivity cs = CaseSensitive) const; + + /** + * Count the occurences of the specified sub-string in the string. + * + * @param pStr What to search for. + * @param cs Case sensitivity selector. + * @remarks QString::count + */ + size_t count(const RTCString *pStr, CaseSensitivity cs = CaseSensitive) const; + + /** + * Returns a substring of "this" as a new Utf8Str. + * + * Works exactly like its equivalent in std::string. With the default + * parameters "0" and "npos", this always copies the entire string. The + * "pos" and "n" arguments represent bytes; it is the caller's responsibility + * to ensure that the offsets do not copy invalid UTF-8 sequences. When + * used in conjunction with find() and length(), this will work. + * + * @param pos Index of first byte offset to copy from "this", counting from 0. + * @param n Number of bytes to copy, starting with the one at "pos". + * The copying will stop if the null terminator is encountered before + * n bytes have been copied. + */ + RTCString substr(size_t pos = 0, size_t n = npos) const + { + return RTCString(*this, pos, n); + } + + /** + * Returns a substring of "this" as a new Utf8Str. As opposed to substr(), + * this variant takes codepoint offsets instead of byte offsets. + * + * @param pos Index of first unicode codepoint to copy from + * "this", counting from 0. + * @param n Number of unicode codepoints to copy, starting with + * the one at "pos". The copying will stop if the null + * terminator is encountered before n codepoints have + * been copied. + */ + RTCString substrCP(size_t pos = 0, size_t n = npos) const; + + /** + * Returns true if "this" ends with "that". + * + * @param that Suffix to test for. + * @param cs Case sensitivity selector. + * @returns true if match, false if mismatch. + */ + bool endsWith(const RTCString &that, CaseSensitivity cs = CaseSensitive) const; + + /** + * Returns true if "this" begins with "that". + * @param that Prefix to test for. + * @param cs Case sensitivity selector. + * @returns true if match, false if mismatch. + */ + bool startsWith(const RTCString &that, CaseSensitivity cs = CaseSensitive) const; + + /** + * Returns true if "this" contains "that" (strstr). + * + * @param that Substring to look for. + * @param cs Case sensitivity selector. + * @returns true if match, false if mismatch. + */ + bool contains(const RTCString &that, CaseSensitivity cs = CaseSensitive) const; + + /** + * Attempts to convert the member string into a 32-bit integer. + * + * @returns 32-bit unsigned number on success. + * @returns 0 on failure. + */ + int32_t toInt32() const + { + return RTStrToInt32(m_psz); + } + + /** + * Attempts to convert the member string into an unsigned 32-bit integer. + * + * @returns 32-bit unsigned number on success. + * @returns 0 on failure. + */ + uint32_t toUInt32() const + { + return RTStrToUInt32(m_psz); + } + + /** + * Attempts to convert the member string into an 64-bit integer. + * + * @returns 64-bit unsigned number on success. + * @returns 0 on failure. + */ + int64_t toInt64() const + { + return RTStrToInt64(m_psz); + } + + /** + * Attempts to convert the member string into an unsigned 64-bit integer. + * + * @returns 64-bit unsigned number on success. + * @returns 0 on failure. + */ + uint64_t toUInt64() const + { + return RTStrToUInt64(m_psz); + } + + /** + * Attempts to convert the member string into an unsigned 64-bit integer. + * + * @param i Where to return the value on success. + * @returns IPRT error code, see RTStrToInt64. + */ + int toInt(uint64_t &i) const; + + /** + * Attempts to convert the member string into an unsigned 32-bit integer. + * + * @param i Where to return the value on success. + * @returns IPRT error code, see RTStrToInt32. + */ + int toInt(uint32_t &i) const; + + /** Splitting behavior regarding empty sections in the string. */ + enum SplitMode + { + KeepEmptyParts, /**< Empty parts are added as empty strings to the result list. */ + RemoveEmptyParts /**< Empty parts are skipped. */ + }; + + /** + * Splits a string separated by strSep into its parts. + * + * @param a_rstrSep The separator to search for. + * @param a_enmMode How should empty parts be handled. + * @returns separated strings as string list. + */ + RTCList<RTCString, RTCString *> split(const RTCString &a_rstrSep, + SplitMode a_enmMode = RemoveEmptyParts) const; + + /** + * Joins a list of strings together using the provided separator. + * + * @param a_rList The list to join. + * @param a_rstrSep The separator used for joining. + * @returns joined string. + */ + static RTCString join(const RTCList<RTCString, RTCString *> &a_rList, + const RTCString &a_rstrSep = ""); + +protected: + + /** + * Hide operator bool() to force people to use isEmpty() explicitly. + */ + operator bool() const; + + /** + * Destructor implementation, also used to clean up in operator=() before + * assigning a new string. + */ + void cleanup() + { + if (m_psz) + { + RTStrFree(m_psz); + m_psz = NULL; + m_cch = 0; + m_cbAllocated = 0; + } + } + + /** + * Protected internal helper to copy a string. + * + * This ignores the previous object state, so either call this from a + * constructor or call cleanup() first. copyFromN() unconditionally sets + * the members to a copy of the given other strings and makes no + * assumptions about previous contents. Can therefore be used both in copy + * constructors, when member variables have no defined value, and in + * assignments after having called cleanup(). + * + * @param pcszSrc The source string. + * @param cchSrc The number of chars (bytes) to copy from the + * source strings. RTSTR_MAX is NOT accepted. + * + * @throws std::bad_alloc On allocation failure. The object is left + * describing a NULL string. + */ + void copyFromN(const char *pcszSrc, size_t cchSrc) + { + if (cchSrc) + { + m_psz = RTStrAlloc(cchSrc + 1); + if (RT_LIKELY(m_psz)) + { + m_cch = cchSrc; + m_cbAllocated = cchSrc + 1; + memcpy(m_psz, pcszSrc, cchSrc); + m_psz[cchSrc] = '\0'; + } + else + { + m_cch = 0; + m_cbAllocated = 0; +#ifdef RT_EXCEPTIONS_ENABLED + throw std::bad_alloc(); +#endif + } + } + else + { + m_cch = 0; + m_cbAllocated = 0; + m_psz = NULL; + } + } + + static DECLCALLBACK(size_t) printfOutputCallback(void *pvArg, const char *pachChars, size_t cbChars); + + char *m_psz; /**< The string buffer. */ + size_t m_cch; /**< strlen(m_psz) - i.e. no terminator included. */ + size_t m_cbAllocated; /**< Size of buffer that m_psz points to; at least m_cbLength + 1. */ +}; + +/** @} */ + + +/** @addtogroup grp_rt_cpp_string + * @{ + */ + +/** + * Concatenate two strings. + * + * @param a_rstr1 String one. + * @param a_rstr2 String two. + * @returns the concatenate string. + * + * @relates RTCString + */ +RTDECL(const RTCString) operator+(const RTCString &a_rstr1, const RTCString &a_rstr2); + +/** + * Concatenate two strings. + * + * @param a_rstr1 String one. + * @param a_psz2 String two. + * @returns the concatenate string. + * + * @relates RTCString + */ +RTDECL(const RTCString) operator+(const RTCString &a_rstr1, const char *a_psz2); + +/** + * Concatenate two strings. + * + * @param a_psz1 String one. + * @param a_rstr2 String two. + * @returns the concatenate string. + * + * @relates RTCString + */ +RTDECL(const RTCString) operator+(const char *a_psz1, const RTCString &a_rstr2); + +/** + * Class with RTCString::printf as constructor for your convenience. + * + * Constructing a RTCString string object from a format string and a variable + * number of arguments can easily be confused with the other RTCString + * constructors, thus this child class. + * + * The usage of this class is like the following: + * @code + RTCStringFmt strName("program name = %s", argv[0]); + @endcode + */ +class RTCStringFmt : public RTCString +{ +public: + + /** + * Constructs a new string given the format string and the list of the + * arguments for the format string. + * + * @param a_pszFormat Pointer to the format string (UTF-8), + * @see pg_rt_str_format. + * @param ... Ellipsis containing the arguments specified by + * the format string. + */ + explicit RTCStringFmt(const char *a_pszFormat, ...) + { + va_list va; + va_start(va, a_pszFormat); + printfV(a_pszFormat, va); + va_end(va); + } + + RTMEMEF_NEW_AND_DELETE_OPERATORS(); + +protected: + RTCStringFmt() {} +}; + +/** @} */ + +#endif + diff --git a/include/iprt/cpp/mtlist.h b/include/iprt/cpp/mtlist.h new file mode 100644 index 00000000..eb4e587c --- /dev/null +++ b/include/iprt/cpp/mtlist.h @@ -0,0 +1,155 @@ +/** @file + * IPRT - Generic thread-safe list Class. + */ + +/* + * Copyright (C) 2011 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. + */ + +#ifndef ___iprt_cpp_mtlist_h +#define ___iprt_cpp_mtlist_h + +#include <iprt/cpp/list.h> + +#include <iprt/semaphore.h> + +/** @addtogroup grp_rt_cpp_list + * @{ + */ + +/** + * A guard class for thread-safe read/write access. + */ +template <> +class RTCListGuard<true> +{ +public: + RTCListGuard() { int rc = RTSemRWCreate(&m_hRWSem); AssertRC(rc); } + ~RTCListGuard() { RTSemRWDestroy(m_hRWSem); } + inline void enterRead() const { int rc = RTSemRWRequestRead(m_hRWSem, RT_INDEFINITE_WAIT); AssertRC(rc); } + inline void leaveRead() const { int rc = RTSemRWReleaseRead(m_hRWSem); AssertRC(rc); } + inline void enterWrite() { int rc = RTSemRWRequestWrite(m_hRWSem, RT_INDEFINITE_WAIT); AssertRC(rc); } + inline void leaveWrite() { int rc = RTSemRWReleaseWrite(m_hRWSem); AssertRC(rc); } + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); + +private: + mutable RTSEMRW m_hRWSem; +}; + +/** + * @brief Generic thread-safe list class. + * + * RTCMTList is a thread-safe implementation of the list class. It uses a + * read/write semaphore to serialize the access to the items. Several readers + * can simultaneous access different or the same item. If one thread is writing + * to an item, the other accessors are blocked until the write has finished. + * + * Although the access is guarded, the user has to make sure the list content + * is consistent when iterating over the list or doing any other kind of access + * which makes assumptions about the list content. For a finer control of access + * restrictions, use your own locking mechanism and the standard list + * implementation. + * + * @see RTCListBase + */ +template <class T, typename ITYPE = typename RTCIf<(sizeof(T) > sizeof(void*)), T*, T>::result> +class RTCMTList : public RTCListBase<T, ITYPE, true> +{ + /* Traits */ + typedef RTCListBase<T, ITYPE, true> BASE; + +public: + /** + * Creates a new list. + * + * This preallocates @a cCapacity elements within the list. + * + * @param cCapacitiy The initial capacity the list has. + * @throws std::bad_alloc + */ + RTCMTList(size_t cCapacity = BASE::DefaultCapacity) + : BASE(cCapacity) {} + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); +}; + +/** + * Specialized thread-safe list class for using the native type list for + * unsigned 64-bit values even on a 32-bit host. + * + * @see RTCListBase + */ +template <> +class RTCMTList<uint64_t>: public RTCListBase<uint64_t, uint64_t, true> +{ + /* Traits */ + typedef RTCListBase<uint64_t, uint64_t, true> BASE; + +public: + /** + * Creates a new list. + * + * This preallocates @a cCapacity elements within the list. + * + * @param cCapacitiy The initial capacity the list has. + * @throws std::bad_alloc + */ + RTCMTList(size_t cCapacity = BASE::DefaultCapacity) + : BASE(cCapacity) {} + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); +}; + +/** + * Specialized thread-safe list class for using the native type list for + * signed 64-bit values even on a 32-bit host. + * + * @see RTCListBase + */ +template <> +class RTCMTList<int64_t>: public RTCListBase<int64_t, int64_t, true> +{ + /* Traits */ + typedef RTCListBase<int64_t, int64_t, true> BASE; + +public: + /** + * Creates a new list. + * + * This preallocates @a cCapacity elements within the list. + * + * @param cCapacitiy The initial capacity the list has. + * @throws std::bad_alloc + */ + RTCMTList(size_t cCapacity = BASE::DefaultCapacity) + : BASE(cCapacity) {} + + /* Define our own new and delete. */ + RTMEMEF_NEW_AND_DELETE_OPERATORS(); +}; + +/** @} */ + +#endif /* !___iprt_cpp_mtlist_h */ + diff --git a/include/iprt/cpp/utils.h b/include/iprt/cpp/utils.h new file mode 100644 index 00000000..e5b269a0 --- /dev/null +++ b/include/iprt/cpp/utils.h @@ -0,0 +1,102 @@ +/** @file + * IPRT - C++ Utilities (useful templates, defines and such). + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_cpputils_h +#define ___iprt_cpputils_h + +/** @defgroup grp_rt_cpp IPRT C++ APIs */ + +/** @defgroup grp_rt_cpp_util C++ Utilities + * @ingroup grp_rt_cpp + * @{ + */ + +#define DPTR(CLASS) CLASS##Private *d = static_cast<CLASS##Private *>(d_ptr) +#define QPTR(CLASS) CLASS *q = static_cast<CLASS *>(q_ptr) + +/** + * A simple class used to prevent copying and assignment. + * + * Inherit from this class in order to prevent automatic generation + * of the copy constructor and assignment operator in your class. + * + * @addtogroup grp_rt_cpp_util + */ +class RTCNonCopyable +{ +protected: + RTCNonCopyable() {} + ~RTCNonCopyable() {} +private: + RTCNonCopyable(RTCNonCopyable const &); + RTCNonCopyable const &operator=(RTCNonCopyable const &); +}; + + +/** + * Shortcut to |const_cast<C &>()| that automatically derives the correct + * type (class) for the const_cast template's argument from its own argument. + * + * Can be used to temporarily cancel the |const| modifier on the left-hand side + * of assignment expressions, like this: + * @code + * const Class That; + * ... + * unconst(That) = SomeValue; + * @endcode + * + * @todo What to do about the prefix here? + */ +template <class C> +inline C &unconst(const C &that) +{ + return const_cast<C &>(that); +} + + +/** + * Shortcut to |const_cast<C *>()| that automatically derives the correct + * type (class) for the const_cast template's argument from its own argument. + * + * Can be used to temporarily cancel the |const| modifier on the left-hand side + * of assignment expressions, like this: + * @code + * const Class *pThat; + * ... + * unconst(pThat) = SomeValue; + * @endcode + * + * @todo What to do about the prefix here? + */ +template <class C> +inline C *unconst(const C *that) +{ + return const_cast<C *>(that); +} + +/** @} */ + +#endif + diff --git a/include/iprt/cpp/xml.h b/include/iprt/cpp/xml.h new file mode 100644 index 00000000..bb9f5a18 --- /dev/null +++ b/include/iprt/cpp/xml.h @@ -0,0 +1,748 @@ +/** @file + * IPRT - XML Helper APIs. + */ + +/* + * Copyright (C) 2007-2011 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. + */ + +#ifndef ___iprt_xml_h +#define ___iprt_xml_h + +#ifndef IN_RING3 +# error "There are no XML APIs available in Ring-0 Context!" +#endif + +#include <list> +#include <memory> + +#include <iprt/cpp/exception.h> + +/** @defgroup grp_rt_cpp_xml C++ XML support + * @ingroup grp_rt_cpp + * @{ + */ + +/* Forwards */ +typedef struct _xmlParserInput xmlParserInput; +typedef xmlParserInput *xmlParserInputPtr; +typedef struct _xmlParserCtxt xmlParserCtxt; +typedef xmlParserCtxt *xmlParserCtxtPtr; +typedef struct _xmlError xmlError; +typedef xmlError *xmlErrorPtr; + +typedef struct _xmlAttr xmlAttr; +typedef struct _xmlNode xmlNode; + +/** @} */ + +namespace xml +{ + +/** + * @addtogroup grp_rt_cpp_xml + * @{ + */ + +// Exceptions +////////////////////////////////////////////////////////////////////////////// + +class RT_DECL_CLASS LogicError : public RTCError +{ +public: + + LogicError(const char *aMsg = NULL) + : RTCError(aMsg) + {} + + LogicError(RT_SRC_POS_DECL); +}; + +class RT_DECL_CLASS RuntimeError : public RTCError +{ +public: + + RuntimeError(const char *aMsg = NULL) + : RTCError(aMsg) + {} +}; + +class RT_DECL_CLASS XmlError : public RuntimeError +{ +public: + XmlError(xmlErrorPtr aErr); + + static char* Format(xmlErrorPtr aErr); +}; + +// Logical errors +////////////////////////////////////////////////////////////////////////////// + +class RT_DECL_CLASS ENotImplemented : public LogicError +{ +public: + ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {} + ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} +}; + +class RT_DECL_CLASS EInvalidArg : public LogicError +{ +public: + EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {} + EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} +}; + +class RT_DECL_CLASS EDocumentNotEmpty : public LogicError +{ +public: + EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {} + EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} +}; + +class RT_DECL_CLASS ENodeIsNotElement : public LogicError +{ +public: + ENodeIsNotElement(const char *aMsg = NULL) : LogicError(aMsg) {} + ENodeIsNotElement(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} +}; + +// Runtime errors +////////////////////////////////////////////////////////////////////////////// + +class RT_DECL_CLASS EIPRTFailure : public RuntimeError +{ +public: + + EIPRTFailure(int aRC, const char *pcszContext, ...); + + int rc() const + { + return mRC; + } + +private: + int mRC; +}; + +/** + * The Stream class is a base class for I/O streams. + */ +class RT_DECL_CLASS Stream +{ +public: + + virtual ~Stream() {} + + virtual const char *uri() const = 0; + + /** + * Returns the current read/write position in the stream. The returned + * position is a zero-based byte offset from the beginning of the file. + * + * Throws ENotImplemented if this operation is not implemented for the + * given stream. + */ + virtual uint64_t pos() const = 0; + + /** + * Sets the current read/write position in the stream. + * + * @param aPos Zero-based byte offset from the beginning of the stream. + * + * Throws ENotImplemented if this operation is not implemented for the + * given stream. + */ + virtual void setPos (uint64_t aPos) = 0; +}; + +/** + * The Input class represents an input stream. + * + * This input stream is used to read the settings tree from. + * This is an abstract class that must be subclassed in order to fill it with + * useful functionality. + */ +class RT_DECL_CLASS Input : virtual public Stream +{ +public: + + /** + * Reads from the stream to the supplied buffer. + * + * @param aBuf Buffer to store read data to. + * @param aLen Buffer length. + * + * @return Number of bytes read. + */ + virtual int read (char *aBuf, int aLen) = 0; +}; + +/** + * + */ +class RT_DECL_CLASS Output : virtual public Stream +{ +public: + + /** + * Writes to the stream from the supplied buffer. + * + * @param aBuf Buffer to write data from. + * @param aLen Buffer length. + * + * @return Number of bytes written. + */ + virtual int write (const char *aBuf, int aLen) = 0; + + /** + * Truncates the stream from the current position and upto the end. + * The new file size will become exactly #pos() bytes. + * + * Throws ENotImplemented if this operation is not implemented for the + * given stream. + */ + virtual void truncate() = 0; +}; + + +////////////////////////////////////////////////////////////////////////////// + +/** + * The File class is a stream implementation that reads from and writes to + * regular files. + * + * The File class uses IPRT File API for file operations. Note that IPRT File + * API is not thread-safe. This means that if you pass the same RTFILE handle to + * different File instances that may be simultaneously used on different + * threads, you should care about serialization; otherwise you will get garbage + * when reading from or writing to such File instances. + */ +class RT_DECL_CLASS File : public Input, public Output +{ +public: + + /** + * Possible file access modes. + */ + enum Mode { Mode_Read, Mode_WriteCreate, Mode_Overwrite, Mode_ReadWrite }; + + /** + * Opens a file with the given name in the given mode. If @a aMode is Read + * or ReadWrite, the file must exist. If @a aMode is Write, the file must + * not exist. Otherwise, an EIPRTFailure excetion will be thrown. + * + * @param aMode File mode. + * @param aFileName File name. + * @param aFlushIt Whether to flush a writable file before closing it. + */ + File(Mode aMode, const char *aFileName, bool aFlushIt = false); + + /** + * Uses the given file handle to perform file operations. This file + * handle must be already open in necessary mode (read, or write, or mixed). + * + * The read/write position of the given handle will be reset to the + * beginning of the file on success. + * + * Note that the given file handle will not be automatically closed upon + * this object destruction. + * + * @note It you pass the same RTFILE handle to more than one File instance, + * please make sure you have provided serialization in case if these + * instasnces are to be simultaneously used by different threads. + * Otherwise you may get garbage when reading or writing. + * + * @param aHandle Open file handle. + * @param aFileName File name (for reference). + * @param aFlushIt Whether to flush a writable file before closing it. + */ + File(RTFILE aHandle, const char *aFileName = NULL, bool aFlushIt = false); + + /** + * Destroys the File object. If the object was created from a file name + * the corresponding file will be automatically closed. If the object was + * created from a file handle, it will remain open. + */ + virtual ~File(); + + const char *uri() const; + + uint64_t pos() const; + void setPos(uint64_t aPos); + + /** + * See Input::read(). If this method is called in wrong file mode, + * LogicError will be thrown. + */ + int read(char *aBuf, int aLen); + + /** + * See Output::write(). If this method is called in wrong file mode, + * LogicError will be thrown. + */ + int write(const char *aBuf, int aLen); + + /** + * See Output::truncate(). If this method is called in wrong file mode, + * LogicError will be thrown. + */ + void truncate(); + +private: + + /* Obscure class data */ + struct Data; + Data *m; + + /* auto_ptr data doesn't have proper copy semantics */ + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (File) +}; + +/** + * The MemoryBuf class represents a stream implementation that reads from the + * memory buffer. + */ +class RT_DECL_CLASS MemoryBuf : public Input +{ +public: + + MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL); + + virtual ~MemoryBuf(); + + const char *uri() const; + + int read(char *aBuf, int aLen); + uint64_t pos() const; + void setPos(uint64_t aPos); + +private: + /* Obscure class data */ + struct Data; + Data *m; + + /* auto_ptr data doesn't have proper copy semantics */ + DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(MemoryBuf) +}; + + +/* + * GlobalLock + * + * + */ + +typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI, + const char *aID, + xmlParserCtxt *aCtxt); +typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER; + +class RT_DECL_CLASS GlobalLock +{ +public: + GlobalLock(); + ~GlobalLock(); + + void setExternalEntityLoader(PFNEXTERNALENTITYLOADER pFunc); + + static xmlParserInput* callDefaultLoader(const char *aURI, + const char *aID, + xmlParserCtxt *aCtxt); + +private: + /* Obscure class data. */ + struct Data; + struct Data *m; +}; + +class ElementNode; +typedef std::list<const ElementNode*> ElementNodesList; + +class AttributeNode; + +class ContentNode; + +/** + * Node base class. Cannot be used directly, but ElementNode, ContentNode and + * AttributeNode derive from this. This does implement useful public methods though. + */ +class RT_DECL_CLASS Node +{ +public: + ~Node(); + + const char* getName() const; + bool nameEquals(const char *pcszNamespace, const char *pcsz) const; + bool nameEquals(const char *pcsz) const + { + return nameEquals(NULL, pcsz); + } + + const char* getValue() const; + bool copyValue(int32_t &i) const; + bool copyValue(uint32_t &i) const; + bool copyValue(int64_t &i) const; + bool copyValue(uint64_t &i) const; + + int getLineNumber() const; + + int isElement() const + { + return m_Type == IsElement; + } + +protected: + typedef enum {IsElement, IsAttribute, IsContent} EnumType; + + EnumType m_Type; + Node *m_pParent; + xmlNode *m_plibNode; // != NULL if this is an element or content node + xmlAttr *m_plibAttr; // != NULL if this is an attribute node + const char *m_pcszNamespacePrefix; // not always set + const char *m_pcszNamespaceHref; // full http:// spec + const char *m_pcszName; // element or attribute name, points either into plibNode or plibAttr; + // NULL if this is a content node + + // hide the default constructor so people use only our factory methods + Node(EnumType type, + Node *pParent, + xmlNode *plibNode, + xmlAttr *plibAttr); + Node(const Node &x); // no copying + + void buildChildren(const ElementNode &elmRoot); + + /* Obscure class data */ + struct Data; + Data *m; + + friend class AttributeNode; +}; + +/** + * Node subclass that represents an element. + * + * For elements, Node::getName() returns the element name, and Node::getValue() + * returns the text contents, if any. + * + * Since the Node constructor is private, one can create element nodes + * only through the following factory methods: + * + * -- Document::createRootElement() + * -- ElementNode::createChild() + */ +class RT_DECL_CLASS ElementNode : public Node +{ +public: + int getChildElements(ElementNodesList &children, + const char *pcszMatch = NULL) const; + + const ElementNode* findChildElement(const char *pcszNamespace, + const char *pcszMatch) const; + const ElementNode* findChildElement(const char *pcszMatch) const + { + return findChildElement(NULL, pcszMatch); + } + const ElementNode* findChildElementFromId(const char *pcszId) const; + + const AttributeNode* findAttribute(const char *pcszMatch) const; + bool getAttributeValue(const char *pcszMatch, const char *&ppcsz) const; + bool getAttributeValue(const char *pcszMatch, RTCString &str) const; + bool getAttributeValuePath(const char *pcszMatch, RTCString &str) const; + bool getAttributeValue(const char *pcszMatch, int32_t &i) const; + bool getAttributeValue(const char *pcszMatch, uint32_t &i) const; + bool getAttributeValue(const char *pcszMatch, int64_t &i) const; + bool getAttributeValue(const char *pcszMatch, uint64_t &i) const; + bool getAttributeValue(const char *pcszMatch, bool &f) const; + + ElementNode* createChild(const char *pcszElementName); + + ContentNode* addContent(const char *pcszContent); + ContentNode* addContent(const RTCString &strContent) + { + return addContent(strContent.c_str()); + } + + AttributeNode* setAttribute(const char *pcszName, const char *pcszValue); + AttributeNode* setAttribute(const char *pcszName, const RTCString &strValue) + { + return setAttribute(pcszName, strValue.c_str()); + } + AttributeNode* setAttributePath(const char *pcszName, const RTCString &strValue); + AttributeNode* setAttribute(const char *pcszName, int32_t i); + AttributeNode* setAttribute(const char *pcszName, uint32_t i); + AttributeNode* setAttribute(const char *pcszName, int64_t i); + AttributeNode* setAttribute(const char *pcszName, uint64_t i); + AttributeNode* setAttributeHex(const char *pcszName, uint32_t i); + AttributeNode* setAttribute(const char *pcszName, bool f); + +protected: + // hide the default constructor so people use only our factory methods + ElementNode(const ElementNode *pelmRoot, Node *pParent, xmlNode *plibNode); + ElementNode(const ElementNode &x); // no copying + + const ElementNode *m_pelmRoot; + + friend class Node; + friend class Document; + friend class XmlFileParser; +}; + +/** + * Node subclass that represents content (non-element text). + * + * Since the Node constructor is private, one can create new content nodes + * only through the following factory methods: + * + * -- ElementNode::addContent() + */ +class RT_DECL_CLASS ContentNode : public Node +{ +public: + +protected: + // hide the default constructor so people use only our factory methods + ContentNode(Node *pParent, xmlNode *plibNode); + ContentNode(const ContentNode &x); // no copying + + friend class Node; + friend class ElementNode; +}; + +/** + * Node subclass that represents an attribute of an element. + * + * For attributes, Node::getName() returns the attribute name, and Node::getValue() + * returns the attribute value, if any. + * + * Since the Node constructor is private, one can create new attribute nodes + * only through the following factory methods: + * + * -- ElementNode::setAttribute() + */ +class RT_DECL_CLASS AttributeNode : public Node +{ +public: + +protected: + // hide the default constructor so people use only our factory methods + AttributeNode(const ElementNode &elmRoot, + Node *pParent, + xmlAttr *plibAttr, + const char **ppcszKey); + AttributeNode(const AttributeNode &x); // no copying + + RTCString m_strKey; + + friend class Node; + friend class ElementNode; +}; + +/** + * Handy helper class with which one can loop through all or some children + * of a particular element. See NodesLoop::forAllNodes() for details. + */ +class RT_DECL_CLASS NodesLoop +{ +public: + NodesLoop(const ElementNode &node, const char *pcszMatch = NULL); + ~NodesLoop(); + const ElementNode* forAllNodes() const; + +private: + /* Obscure class data */ + struct Data; + Data *m; +}; + +/** + * The XML document class. An instance of this needs to be created by a user + * of the XML classes and then passed to + * + * -- XmlMemParser or XmlFileParser to read an XML document; those classes then + * fill the caller's Document with ElementNode, ContentNode and AttributeNode + * instances. The typical sequence then is: + * @code + Document doc; + XmlFileParser parser; + parser.read("file.xml", doc); + Element *pelmRoot = doc.getRootElement(); + @endcode + * + * -- XmlMemWriter or XmlFileWriter to write out an XML document after it has + * been created and filled. Example: + * + * @code + Document doc; + Element *pelmRoot = doc.createRootElement(); + // add children + xml::XmlFileWriter writer(doc); + writer.write("file.xml", true); + @endcode + */ +class RT_DECL_CLASS Document +{ +public: + Document(); + ~Document(); + + Document(const Document &x); + Document& operator=(const Document &x); + + const ElementNode* getRootElement() const; + ElementNode* getRootElement(); + + ElementNode* createRootElement(const char *pcszRootElementName, + const char *pcszComment = NULL); + +private: + friend class XmlMemParser; + friend class XmlFileParser; + friend class XmlMemWriter; + friend class XmlFileWriter; + + void refreshInternals(); + + /* Obscure class data */ + struct Data; + Data *m; +}; + +/* + * XmlParserBase + * + */ + +class RT_DECL_CLASS XmlParserBase +{ +protected: + XmlParserBase(); + ~XmlParserBase(); + + xmlParserCtxtPtr m_ctxt; +}; + +/* + * XmlMemParser + * + */ + +class RT_DECL_CLASS XmlMemParser : public XmlParserBase +{ +public: + XmlMemParser(); + ~XmlMemParser(); + + void read(const void* pvBuf, size_t cbSize, const RTCString &strFilename, Document &doc); +}; + +/* + * XmlFileParser + * + */ + +class RT_DECL_CLASS XmlFileParser : public XmlParserBase +{ +public: + XmlFileParser(); + ~XmlFileParser(); + + void read(const RTCString &strFilename, Document &doc); + +private: + /* Obscure class data */ + struct Data; + struct Data *m; + + static int ReadCallback(void *aCtxt, char *aBuf, int aLen); + static int CloseCallback (void *aCtxt); +}; + +/* + * XmlMemParser + * + */ + +class RT_DECL_CLASS XmlMemWriter +{ +public: + XmlMemWriter(); + ~XmlMemWriter(); + + void write(const Document &doc, void** ppvBuf, size_t *pcbSize); + +private: + void* m_pBuf; +}; + +/* + * XmlFileWriter + * + */ + +class RT_DECL_CLASS XmlFileWriter +{ +public: + XmlFileWriter(Document &doc); + ~XmlFileWriter(); + + /** + * Writes the XML document to the specified file. + * + * @param pcszFilename The name of the output file. + * @param fSafe If @c true, some extra safety precautions will be + * taken when writing the file: + * -# The file is written with a '-tmp' suffix. + * -# It is flushed to disk after writing. + * -# Any original file is renamed to '-prev'. + * -# The '-tmp' file is then renamed to the + * specified name. + * -# The directory changes are flushed to disk. + * The suffixes are available via s_pszTmpSuff and + * s_pszPrevSuff. + */ + void write(const char *pcszFilename, bool fSafe); + + static int WriteCallback(void *aCtxt, const char *aBuf, int aLen); + static int CloseCallback(void *aCtxt); + + /** The suffix used by XmlFileWriter::write() for the temporary file. */ + static const char * const s_pszTmpSuff; + /** The suffix used by XmlFileWriter::write() for the previous (backup) file. */ + static const char * const s_pszPrevSuff; + +private: + void writeInternal(const char *pcszFilename, bool fSafe); + + /* Obscure class data */ + struct Data; + Data *m; +}; + +#if defined(_MSC_VER) +#pragma warning (default:4251) +#endif + +/** @} */ + +} // end namespace xml + +#endif /* !___iprt_xml_h */ + diff --git a/include/iprt/cpuset.h b/include/iprt/cpuset.h new file mode 100644 index 00000000..0d1e1c51 --- /dev/null +++ b/include/iprt/cpuset.h @@ -0,0 +1,286 @@ +/** @file + * IPRT - CPU Set. + */ + +/* + * Copyright (C) 2008-2011 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. + */ + +#ifndef ___iprt_cpuset_h +#define ___iprt_cpuset_h + +#include <iprt/types.h> +#include <iprt/mp.h> /* RTMpCpuIdToSetIndex */ +#include <iprt/asm.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_cpuset RTCpuSet - CPU Set + * @ingroup grp_rt + * @{ + */ + + +/** + * Clear all CPUs. + * + * @returns pSet. + * @param pSet Pointer to the set. + */ +DECLINLINE(PRTCPUSET) RTCpuSetEmpty(PRTCPUSET pSet) +{ + unsigned i; + for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++) + pSet->bmSet[i] = 0; + return pSet; +} + + +/** + * Set all CPUs. + * + * @returns pSet. + * @param pSet Pointer to the set. + */ +DECLINLINE(PRTCPUSET) RTCpuSetFill(PRTCPUSET pSet) +{ + unsigned i; + for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++) + pSet->bmSet[i] = UINT64_MAX; + return pSet; +} + + +/** + * Adds a CPU given by its identifier to the set. + * + * @returns 0 on success, -1 if idCpu isn't valid. + * @param pSet Pointer to the set. + * @param idCpu The identifier of the CPU to add. + * @remarks The modification is atomic. + */ +DECLINLINE(int) RTCpuSetAdd(PRTCPUSET pSet, RTCPUID idCpu) +{ + int iCpu = RTMpCpuIdToSetIndex(idCpu); + if (RT_UNLIKELY(iCpu < 0)) + return -1; + ASMAtomicBitSet(pSet, iCpu); + return 0; +} + + +/** + * Adds a CPU given by its identifier to the set. + * + * @returns 0 on success, -1 if iCpu isn't valid. + * @param pSet Pointer to the set. + * @param iCpu The index of the CPU to add. + * @remarks The modification is atomic. + */ +DECLINLINE(int) RTCpuSetAddByIndex(PRTCPUSET pSet, int iCpu) +{ + if (RT_UNLIKELY((unsigned)iCpu >= RTCPUSET_MAX_CPUS)) + return -1; + ASMAtomicBitSet(pSet, iCpu); + return 0; +} + + +/** + * Removes a CPU given by its identifier from the set. + * + * @returns 0 on success, -1 if idCpu isn't valid. + * @param pSet Pointer to the set. + * @param idCpu The identifier of the CPU to delete. + * @remarks The modification is atomic. + */ +DECLINLINE(int) RTCpuSetDel(PRTCPUSET pSet, RTCPUID idCpu) +{ + int iCpu = RTMpCpuIdToSetIndex(idCpu); + if (RT_UNLIKELY(iCpu < 0)) + return -1; + ASMAtomicBitClear(pSet, iCpu); + return 0; +} + + +/** + * Removes a CPU given by its index from the set. + * + * @returns 0 on success, -1 if iCpu isn't valid. + * @param pSet Pointer to the set. + * @param iCpu The index of the CPU to delete. + * @remarks The modification is atomic. + */ +DECLINLINE(int) RTCpuSetDelByIndex(PRTCPUSET pSet, int iCpu) +{ + if (RT_UNLIKELY((unsigned)iCpu >= RTCPUSET_MAX_CPUS)) + return -1; + ASMAtomicBitClear(pSet, iCpu); + return 0; +} + + +/** + * Checks if a CPU given by its identifier is a member of the set. + * + * @returns true / false accordingly. + * @param pSet Pointer to the set. + * @param idCpu The identifier of the CPU to look for. + * @remarks The test is atomic. + */ +DECLINLINE(bool) RTCpuSetIsMember(PCRTCPUSET pSet, RTCPUID idCpu) +{ + int iCpu = RTMpCpuIdToSetIndex(idCpu); + if (RT_UNLIKELY(iCpu < 0)) + return false; + return ASMBitTest((volatile void *)pSet, iCpu); +} + + +/** + * Checks if a CPU given by its index is a member of the set. + * + * @returns true / false accordingly. + * @param pSet Pointer to the set. + * @param iCpu The index of the CPU in the set. + * @remarks The test is atomic. + */ +DECLINLINE(bool) RTCpuSetIsMemberByIndex(PCRTCPUSET pSet, int iCpu) +{ + if (RT_UNLIKELY((unsigned)iCpu >= RTCPUSET_MAX_CPUS)) + return false; + return ASMBitTest((volatile void *)pSet, iCpu); +} + + +/** + * Checks if the two sets match or not. + * + * @returns true / false accordingly. + * @param pSet1 The first set. + * @param pSet2 The second set. + */ +DECLINLINE(bool) RTCpuSetIsEqual(PCRTCPUSET pSet1, PCRTCPUSET pSet2) +{ + unsigned i; + for (i = 0; i < RT_ELEMENTS(pSet1->bmSet); i++) + if (pSet1->bmSet[i] != pSet2->bmSet[i]) + return false; + return true; +} + + +/** + * Converts the CPU set to a 64-bit mask. + * + * @returns The mask. + * @param pSet Pointer to the set. + * @remarks Use with extreme care as it may lose information! + */ +DECLINLINE(uint64_t) RTCpuSetToU64(PCRTCPUSET pSet) +{ + return pSet->bmSet[0]; +} + + +/** + * Initializes the CPU set from a 64-bit mask. + * + * @param pSet Pointer to the set. + * @param fMask The mask. + */ +DECLINLINE(PRTCPUSET) RTCpuSetFromU64(PRTCPUSET pSet, uint64_t fMask) +{ + unsigned i; + + pSet->bmSet[0] = fMask; + for (i = 1; i < RT_ELEMENTS(pSet->bmSet); i++) + pSet->bmSet[i] = 0; + + return pSet; +} + + +/** + * Count the CPUs in the set. + * + * @returns CPU count. + * @param pSet Pointer to the set. + */ +DECLINLINE(int) RTCpuSetCount(PCRTCPUSET pSet) +{ + int cCpus = 0; + unsigned i; + + for (i = 0; i < RT_ELEMENTS(pSet->bmSet); i++) + { + uint64_t u64 = pSet->bmSet[i]; + if (u64 != 0) + { + unsigned iCpu = 64; + while (iCpu-- > 0) + { + if (u64 & 1) + cCpus++; + u64 >>= 1; + } + } + } + return cCpus; +} + + +/** + * Get the highest set index. + * + * @returns The higest set index, -1 if all bits are clear. + * @param pSet Pointer to the set. + */ +DECLINLINE(int) RTCpuLastIndex(PCRTCPUSET pSet) +{ + unsigned i = RT_ELEMENTS(pSet->bmSet); + while (i-- > 0) + { + uint64_t u64 = pSet->bmSet[i]; + if (u64) + { + /* There are more efficient ways to do this in asm.h... */ + unsigned iBit; + for (iBit = 63; iBit > 0; iBit--) + { + if (u64 & RT_BIT_64(63)) + break; + u64 <<= 1; + } + return i * 64 + iBit; + } + } + return 0; +} + + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/crc.h b/include/iprt/crc.h new file mode 100644 index 00000000..82e3b11b --- /dev/null +++ b/include/iprt/crc.h @@ -0,0 +1,160 @@ +/** @file + * IPRT - CRCs and Checksums. + */ + +/* + * Copyright (C) 2006-2009 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. + */ + +#ifndef ___iprt_crc_h +#define ___iprt_crc_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_crc RTCrc - Checksums and CRCs. + * @ingroup grp_rt + * @{ + */ + + +/** @defgroup grp_rt_crc32 CRC-32 + * @{ */ +/** + * Calculate CRC-32 for a memory block. + * + * @returns CRC-32 for the memory block. + * @param pv Pointer to the memory block. + * @param cb Size of the memory block in bytes. + */ +RTDECL(uint32_t) RTCrc32(const void *pv, size_t cb); + +/** + * Start a multiblock CRC-32 calculation. + * + * @returns Start CRC-32. + */ +RTDECL(uint32_t) RTCrc32Start(void); + +/** + * Processes a multiblock of a CRC-32 calculation. + * + * @returns Intermediate CRC-32 value. + * @param uCRC32 Current CRC-32 intermediate value. + * @param pv The data block to process. + * @param cb The size of the data block in bytes. + */ +RTDECL(uint32_t) RTCrc32Process(uint32_t uCRC32, const void *pv, size_t cb); + +/** + * Complete a multiblock CRC-32 calculation. + * + * @returns CRC-32 value. + * @param uCRC32 Current CRC-32 intermediate value. + */ +RTDECL(uint32_t) RTCrc32Finish(uint32_t uCRC32); +/** @} */ + + +/** @defgroup grp_rt_crc64 CRC-64 Calculation + * @{ */ +/** + * Calculate CRC-64 for a memory block. + * + * @returns CRC-64 for the memory block. + * @param pv Pointer to the memory block. + * @param cb Size of the memory block in bytes. + */ +RTDECL(uint64_t) RTCrc64(const void *pv, size_t cb); + +/** + * Start a multiblock CRC-64 calculation. + * + * @returns Start CRC-64. + */ +RTDECL(uint64_t) RTCrc64Start(void); + +/** + * Processes a multiblock of a CRC-64 calculation. + * + * @returns Intermediate CRC-64 value. + * @param uCRC64 Current CRC-64 intermediate value. + * @param pv The data block to process. + * @param cb The size of the data block in bytes. + */ +RTDECL(uint64_t) RTCrc64Process(uint64_t uCRC64, const void *pv, size_t cb); + +/** + * Complete a multiblock CRC-64 calculation. + * + * @returns CRC-64 value. + * @param uCRC64 Current CRC-64 intermediate value. + */ +RTDECL(uint64_t) RTCrc64Finish(uint64_t uCRC64); +/** @} */ + + +/** @defgroup grp_rt_crc_adler32 Adler-32 + * @{ */ +/** + * Calculate Adler-32 for a memory block. + * + * @returns Adler-32 for the memory block. + * @param pv Pointer to the memory block. + * @param cb Size of the memory block in bytes. + */ +RTDECL(uint32_t) RTCrcAdler32(void const *pv, size_t cb); + +/** + * Start a multiblock Adler-32 calculation. + * + * @returns Start Adler-32. + */ +RTDECL(uint32_t) RTCrcAdler32Start(void); + +/** + * Processes a multiblock of a Adler-32 calculation. + * + * @returns Intermediate Adler-32 value. + * @param uCrc Current Adler-32 intermediate value. + * @param pv The data block to process. + * @param cb The size of the data block in bytes. + */ +RTDECL(uint32_t) RTCrcAdler32Process(uint32_t uCrc, void const *pv, size_t cb); + +/** + * Complete a multiblock Adler-32 calculation. + * + * @returns Adler-32 value. + * @param uCrc Current Adler-32 intermediate value. + */ +RTDECL(uint32_t) RTCrcAdler32Finish(uint32_t uCrc); + +/** @} */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/critsect.h b/include/iprt/critsect.h new file mode 100644 index 00000000..41bb65bd --- /dev/null +++ b/include/iprt/critsect.h @@ -0,0 +1,366 @@ +/** @file + * IPRT - Critical Sections. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_critsect_h +#define ___iprt_critsect_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/assert.h> +#ifdef IN_RING3 +# include <iprt/thread.h> +#endif +#ifdef RT_LOCK_STRICT_ORDER +# include <iprt/lockvalidator.h> +#endif + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_critsect RTCritSect - Critical Sections + * + * "Critical section" synchronization primitives can be used to + * protect a section of code or data to which access must be exclusive; + * only one thread can hold access to a critical section at one time. + * + * A critical section is a fast recursive write lock; if the critical + * section is not acquired, then entering it is fast (requires no system + * call). IPRT uses the Windows terminology here; on other platform, this + * might be called a "futex" or a "fast mutex". As opposed to IPRT + * "fast mutexes" (see @ref grp_rt_sems_fast_mutex ), critical sections + * are recursive. + * + * Use RTCritSectInit to initialize a critical section; use RTCritSectEnter + * and RTCritSectLeave to acquire and release access. + * + * For an overview of all types of synchronization primitives provided + * by IPRT (event, mutex/fast mutex/read-write mutex semaphores), see + * @ref grp_rt_sems . + * + * @ingroup grp_rt + * @{ + */ + +/** + * Critical section. + */ +typedef struct RTCRITSECT +{ + /** Magic used to validate the section state. + * RTCRITSECT_MAGIC is the value of an initialized & operational section. */ + volatile uint32_t u32Magic; + /** Number of lockers. + * -1 if the section is free. */ + volatile int32_t cLockers; + /** The owner thread. */ + volatile RTNATIVETHREAD NativeThreadOwner; + /** Number of nested enter operations performed. + * Greater or equal to 1 if owned, 0 when free. + */ + volatile int32_t cNestings; + /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */ + uint32_t fFlags; + /** The semaphore to block on. */ + RTSEMEVENT EventSem; + /** Lock validator record. Only used in strict builds. */ + R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec; + /** Alignmnet padding. */ + RTHCPTR Alignment; +} RTCRITSECT; +AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48); + +/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */ +#define RTCRITSECT_MAGIC UINT32_C(0x19790326) + +/** @name RTCritSectInitEx flags / RTCRITSECT::fFlags + * @{ */ +/** If set, nesting(/recursion) is not allowed. */ +#define RTCRITSECT_FLAGS_NO_NESTING UINT32_C(0x00000001) +/** Disables lock validation. */ +#define RTCRITSECT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000002) +/** Bootstrap hack for use with certain memory allocator locks only! */ +#define RTCRITSECT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004) +/** If set, the critical section becomes a dummy that doesn't serialize any + * threads. This flag can only be set at creation time. + * + * The intended use is avoiding lots of conditional code where some component + * might or might not require entering a critical section before access. */ +#define RTCRITSECT_FLAGS_NOP UINT32_C(0x00000008) +/** @} */ + +#ifdef IN_RING3 + +/** + * Initialize a critical section. + */ +RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect); + +/** + * Initialize a critical section. + * + * @returns iprt status code. + * @param pCritSect Pointer to the critical section structure. + * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS + * \#defines. + * @param hClass The class (no reference consumed). If NIL, no + * lock order validation will be performed on this + * lock. + * @param uSubClass The sub-class. This is used to define lock + * order within a class. RTLOCKVAL_SUB_CLASS_NONE + * is the recommended value here. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags, + RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...); + +/** + * Changes the lock validator sub-class of the critical section. + * + * It is recommended to try make sure that nobody is using this critical section + * while changing the value. + * + * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the + * lock validator isn't compiled in or either of the parameters are + * invalid. + * @param pCritSect The critical section. + * @param uSubClass The new sub-class value. + */ +RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass); + +/** + * Enter a critical section. + * + * @returns VINF_SUCCESS on success. + * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.) + * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting. + * @param pCritSect The critical section. + */ +RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect); + +/** + * Enter a critical section. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.) + * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting. + * + * @param pCritSect The critical section. + * @param uId Where we're entering the section. + * @param pszFile The source position - file. + * @param iLine The source position - line. + * @param pszFunction The source position - function. + */ +RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Try enter a critical section. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_BUSY if the critsect was owned. + * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.) + * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting. + * + * @param pCritSect The critical section. + */ +RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect); + +/** + * Try enter a critical section. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_BUSY if the critsect was owned. + * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.) + * @retval VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting. + * + * @param pCritSect The critical section. + * @param uId Where we're entering the section. + * @param pszFile The source position - file. + * @param iLine The source position - line. + * @param pszFunction The source position - function. + */ +RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Enter multiple critical sections. + * + * This function will enter ALL the specified critical sections before returning. + * + * @returns VINF_SUCCESS on success. + * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.) + * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting. + * @param cCritSects Number of critical sections in the array. + * @param papCritSects Array of critical section pointers. + * + * @remark Please note that this function will not necessarily come out favourable in a + * fight with other threads which are using the normal RTCritSectEnter() function. + * Therefore, avoid having to enter multiple critical sections! + */ +RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects); + +/** + * Enter multiple critical sections. + * + * This function will enter ALL the specified critical sections before returning. + * + * @returns VINF_SUCCESS on success. + * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.) + * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting. + * + * @param cCritSects Number of critical sections in the array. + * @param papCritSects Array of critical section pointers. + * @param uId Where we're entering the section. + * @param pszFile The source position - file. + * @param iLine The source position - line. + * @param pszFunction The source position - function. + * + * @remark See RTCritSectEnterMultiple(). + */ +RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Leave a critical section. + * + * @returns VINF_SUCCESS. + * @param pCritSect The critical section. + */ +RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect); + +/** + * Leave multiple critical sections. + * + * @returns VINF_SUCCESS. + * @param cCritSects Number of critical sections in the array. + * @param papCritSects Array of critical section pointers. + */ +RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects); + +/** + * Deletes a critical section. + * + * @returns VINF_SUCCESS. + * @param pCritSect The critical section. + */ +RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect); + +/** + * Checks the caller is the owner of the critical section. + * + * @returns true if owner. + * @returns false if not owner. + * @param pCritSect The critical section. + */ +DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect) +{ + return pCritSect->NativeThreadOwner == RTThreadNativeSelf(); +} + +#endif /* IN_RING3 */ + +/** + * Checks the section is owned by anyone. + * + * @returns true if owned. + * @returns false if not owned. + * @param pCritSect The critical section. + */ +DECLINLINE(bool) RTCritSectIsOwned(PCRTCRITSECT pCritSect) +{ + return pCritSect->NativeThreadOwner != NIL_RTNATIVETHREAD; +} + +/** + * Gets the thread id of the critical section owner. + * + * @returns Thread id of the owner thread if owned. + * @returns NIL_RTNATIVETHREAD is not owned. + * @param pCritSect The critical section. + */ +DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect) +{ + return pCritSect->NativeThreadOwner; +} + +/** + * Checks if a critical section is initialized or not. + * + * @returns true if initialized. + * @returns false if not initialized. + * @param pCritSect The critical section. + */ +DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect) +{ + return pCritSect->u32Magic == RTCRITSECT_MAGIC; +} + +/** + * Gets the recursion depth. + * + * @returns The recursion depth. + * @param pCritSect The Critical section + */ +DECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect) +{ + return pCritSect->cNestings; +} + +/** + * Gets the waiter count + * + * @returns The waiter count + * @param pCritSect The Critical section + */ +DECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect) +{ + return pCritSect->cLockers; +} + +/* Lock strict build: Remap the three enter calls to the debug versions. */ +#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING) +# ifdef ___iprt_asm_h +# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# else +# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS) +# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS) +# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), 0, RT_SRC_POS) +# endif +#endif + +/* Strict lock order: Automatically classify locks by init location. */ +#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTCRITSECT_WITHOUT_REMAPPING) &&!defined(RT_WITH_MANGLING) +# define RTCritSectInit(pCritSect) \ + RTCritSectInitEx((pCritSect), 0 /*fFlags*/, \ + RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \ + RTLOCKVAL_SUB_CLASS_NONE, NULL) +#endif + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/ctype.h b/include/iprt/ctype.h new file mode 100644 index 00000000..b491aa32 --- /dev/null +++ b/include/iprt/ctype.h @@ -0,0 +1,238 @@ +/** @file + * IPRT - Simple character type classiciation and conversion. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_ctype_h +#define ___iprt_ctype_h + +#include <iprt/types.h> + +/** @name C locale predicates and conversions. + * + * For most practical purposes, this can safely be used when parsing UTF-8 + * strings. Just keep in mind that we only deal with the first 127 chars and + * that full correctness is only archived using the non-existing RTLocIs* API. + * + * @remarks Use the marcros, not the inlined functions. + * + * @remarks ASSUMES the source code includes the basic ASCII chars. This is a + * general IPRT assumption. + * @{ */ +#define RT_C_IS_BLANK(ch) RTLocCIsBlank((ch)) +#define RT_C_IS_ALNUM(ch) RTLocCIsAlNum((ch)) +#define RT_C_IS_ALPHA(ch) RTLocCIsAlpha((ch)) +#define RT_C_IS_CNTRL(ch) RTLocCIsCntrl((ch)) +#define RT_C_IS_DIGIT(ch) RTLocCIsDigit((ch)) +#define RT_C_IS_LOWER(ch) RTLocCIsLower((ch)) +#define RT_C_IS_GRAPH(ch) RTLocCIsGraph((ch)) +#define RT_C_IS_ODIGIT(ch) RTLocCIsODigit((ch)) +#define RT_C_IS_PRINT(ch) RTLocCIsPrint((ch)) +#define RT_C_IS_PUNCT(ch) RTLocCIsPunct((ch)) +#define RT_C_IS_SPACE(ch) RTLocCIsSpace((ch)) +#define RT_C_IS_UPPER(ch) RTLocCIsUpper((ch)) +#define RT_C_IS_XDIGIT(ch) RTLocCIsXDigit((ch)) + +#define RT_C_TO_LOWER(ch) RTLocCToLower((ch)) +#define RT_C_TO_UPPER(ch) RTLocCToUpper((ch)) + +/** + * Checks for a blank character. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsBlank(int ch) +{ + return ch == 0x20 /* space */ + || ch == 0x09; /* horizontal tab */ +} + +/** + * Checks for a control character. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsCntrl(int ch) +{ + return (unsigned)ch < 32U /* 0..2f */ + || ch == 0x7f; +} + +/** + * Checks for a decimal digit. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsDigit(int ch) +{ + return (unsigned)ch - 0x30 < 10U; /* 30..39 */ +} + +/** + * Checks for a lower case character. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsLower(int ch) +{ + return (unsigned)ch - 0x61U < 26U; /* 61..7a */ +} + +/** + * Checks for an octal digit. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsODigit(int ch) +{ + return (unsigned)ch - 0x30 < 8U; /* 30..37 */ +} + +/** + * Checks for a printable character (whitespace included). + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsPrint(int ch) +{ + return (unsigned)ch - 0x20U < 95U; /* 20..7e */ +} + +/** + * Checks for punctuation (?). + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsPunct(int ch) +{ + return (unsigned)ch - 0x21U < 15U /* 21..2f */ + || (unsigned)ch - 0x2aU < 6U /* 2a..2f */ + || (unsigned)ch - 0x3aU < 7U /* 3a..40 */ + || (unsigned)ch - 0x5bU < 6U /* 5a..60 */ + || (unsigned)ch - 0x7bU < 4U /* 7b..7e */; +} + +/** + * Checks for a white-space character. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsSpace(int ch) +{ + return ch == 0x20 /* 20 (space) */ + || (unsigned)ch - 0x09U < 5U; /* 09..0d */ +} + +/** + * Checks for an upper case character. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsUpper(int ch) +{ + return (unsigned)ch - 0x41 < 26U; /* 41..5a */ +} + +/** + * Checks for a hexadecimal digit. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsXDigit(int ch) +{ + return (unsigned)ch - 0x30 < 10U /* 30..39 (0-9) */ + || (unsigned)ch - 0x41 < 6 /* 41..46 (A-F) */ + || (unsigned)ch - 0x61 < 6; /* 61..66 (a-f) */ +} + +/** + * Checks for an alphabetic character. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsAlpha(int ch) +{ + return RTLocCIsLower(ch) || RTLocCIsUpper(ch); +} + +/** + * Checks for an alphanumerical character. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsAlNum(int ch) +{ + return RTLocCIsDigit(ch) || RTLocCIsAlpha(ch); +} + +/** + * Checks for a printable character whitespace excluded. + * + * @returns true / false. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(bool) RTLocCIsGraph(int ch) +{ + return RTLocCIsPrint(ch) && !RTLocCIsBlank(ch); +} + + +/** + * Converts the character to lower case if applictable. + * + * @returns lower cased character or ch. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(int) RTLocCToLower(int ch) +{ + return RTLocCIsUpper(ch) ? (ch) + 0x20 : (ch); +} + +/** + * Converts the character to upper case if applictable. + * + * @returns upper cased character or ch. + * @param ch The character to test. + */ +DECL_FORCE_INLINE(int) RTLocCToUpper(int ch) +{ + return RTLocCIsLower(ch) ? (ch) - 0x20 : (ch); +} + + +/** @} */ + +#endif + diff --git a/include/iprt/dbg.h b/include/iprt/dbg.h new file mode 100644 index 00000000..04bea827 --- /dev/null +++ b/include/iprt/dbg.h @@ -0,0 +1,1273 @@ +/* $Id: dbg.h $ */ +/** @file + * IPRT - Debugging Routines. + */ + +/* + * Copyright (C) 2008-2009 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. + */ + +#ifndef ___iprt_dbg_h +#define ___iprt_dbg_h + +#include <iprt/types.h> +#include <iprt/stdarg.h> + +RT_C_DECLS_BEGIN + +# ifdef IN_RING3 + +/** @defgroup grp_rt_dbg RTDbg - Debugging Routines + * @ingroup grp_rt + * @{ + */ + + +/** Debug segment index. */ +typedef uint32_t RTDBGSEGIDX; +/** Pointer to a debug segment index. */ +typedef RTDBGSEGIDX *PRTDBGSEGIDX; +/** Pointer to a const debug segment index. */ +typedef RTDBGSEGIDX const *PCRTDBGSEGIDX; +/** NIL debug segment index. */ +#define NIL_RTDBGSEGIDX UINT32_C(0xffffffff) +/** The last normal segment index. */ +#define RTDBGSEGIDX_LAST UINT32_C(0xffffffef) +/** Special segment index that indicates that the offset is a relative + * virtual address (RVA). I.e. an offset from the start of the module. */ +#define RTDBGSEGIDX_RVA UINT32_C(0xfffffff0) +/** Special segment index that indicates that the offset is a absolute. */ +#define RTDBGSEGIDX_ABS UINT32_C(0xfffffff1) +/** The last valid special segment index. */ +#define RTDBGSEGIDX_SPECIAL_LAST RTDBGSEGIDX_ABS +/** The last valid special segment index. */ +#define RTDBGSEGIDX_SPECIAL_FIRST (RTDBGSEGIDX_LAST + 1U) + + +/** @name RTDBGSYMADDR_FLAGS_XXX + * Flags used when looking up a symbol by address. + * @{ */ +/** Less or equal address. (default) */ +#define RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL UINT32_C(0) +/** Greater or equal address. */ +#define RTDBGSYMADDR_FLAGS_GREATER_OR_EQUAL UINT32_C(1) +/** Mask of valid flags. */ +#define RTDBGSYMADDR_FLAGS_VALID_MASK UINT32_C(1) +/** @} */ + + +/** Max length (including '\\0') of a segment name. */ +#define RTDBG_SEGMENT_NAME_LENGTH (128 - 8 - 8 - 8 - 4 - 4) + +/** + * Debug module segment. + */ +typedef struct RTDBGSEGMENT +{ + /** The load address. + * RTUINTPTR_MAX if not applicable. */ + RTUINTPTR Address; + /** The image relative virtual address of the segment. + * RTUINTPTR_MAX if not applicable. */ + RTUINTPTR uRva; + /** The segment size. */ + RTUINTPTR cb; + /** The segment flags. (reserved) */ + uint32_t fFlags; + /** The segment index. */ + RTDBGSEGIDX iSeg; + /** Symbol name. */ + char szName[RTDBG_SEGMENT_NAME_LENGTH]; +} RTDBGSEGMENT; +/** Pointer to a debug module segment. */ +typedef RTDBGSEGMENT *PRTDBGSEGMENT; +/** Pointer to a const debug module segment. */ +typedef RTDBGSEGMENT const *PCRTDBGSEGMENT; + + + +/** Max length (including '\\0') of a symbol name. */ +#define RTDBG_SYMBOL_NAME_LENGTH (384 - 8 - 8 - 8 - 4 - 4 - 8) + +/** + * Debug symbol. + */ +typedef struct RTDBGSYMBOL +{ + /** Symbol value (address). + * This depends a bit who you ask. It will be the same as offSeg when you + * as RTDbgMod, but the mapping address if you ask RTDbgAs. */ + RTUINTPTR Value; + /** Symbol size. */ + RTUINTPTR cb; + /** Offset into the segment specified by iSeg. */ + RTUINTPTR offSeg; + /** Segment number. */ + RTDBGSEGIDX iSeg; + /** Symbol Flags. (reserved). */ + uint32_t fFlags; + /** Symbol ordinal. + * This is set to UINT32_MAX if the ordinals aren't supported. */ + uint32_t iOrdinal; + /** Symbol name. */ + char szName[RTDBG_SYMBOL_NAME_LENGTH]; +} RTDBGSYMBOL; +/** Pointer to debug symbol. */ +typedef RTDBGSYMBOL *PRTDBGSYMBOL; +/** Pointer to const debug symbol. */ +typedef const RTDBGSYMBOL *PCRTDBGSYMBOL; + +/** + * Allocate a new symbol structure. + * + * @returns Pointer to a new structure on success, NULL on failure. + */ +RTDECL(PRTDBGSYMBOL) RTDbgSymbolAlloc(void); + +/** + * Duplicates a symbol structure. + * + * @returns Pointer to duplicate on success, NULL on failure. + * + * @param pSymInfo The symbol info to duplicate. + */ +RTDECL(PRTDBGSYMBOL) RTDbgSymbolDup(PCRTDBGSYMBOL pSymInfo); + +/** + * Free a symbol structure previously allocated by a RTDbg method. + * + * @param pSymInfo The symbol info to free. NULL is ignored. + */ +RTDECL(void) RTDbgSymbolFree(PRTDBGSYMBOL pSymInfo); + + +/** Max length (including '\\0') of a debug info file name. */ +#define RTDBG_FILE_NAME_LENGTH (260) + + +/** + * Debug line number information. + */ +typedef struct RTDBGLINE +{ + /** Address. + * This depends a bit who you ask. It will be the same as offSeg when you + * as RTDbgMod, but the mapping address if you ask RTDbgAs. */ + RTUINTPTR Address; + /** Offset into the segment specified by iSeg. */ + RTUINTPTR offSeg; + /** Segment number. */ + RTDBGSEGIDX iSeg; + /** Line number. */ + uint32_t uLineNo; + /** Symbol ordinal. + * This is set to UINT32_MAX if the ordinals aren't supported. */ + uint32_t iOrdinal; + /** Filename. */ + char szFilename[RTDBG_FILE_NAME_LENGTH]; +} RTDBGLINE; +/** Pointer to debug line number. */ +typedef RTDBGLINE *PRTDBGLINE; +/** Pointer to const debug line number. */ +typedef const RTDBGLINE *PCRTDBGLINE; + +/** + * Allocate a new line number structure. + * + * @returns Pointer to a new structure on success, NULL on failure. + */ +RTDECL(PRTDBGLINE) RTDbgLineAlloc(void); + +/** + * Duplicates a line number structure. + * + * @returns Pointer to duplicate on success, NULL on failure. + * + * @param pLine The line number to duplicate. + */ +RTDECL(PRTDBGLINE) RTDbgLineDup(PCRTDBGLINE pLine); + +/** + * Free a line number structure previously allocated by a RTDbg method. + * + * @param pLine The line number to free. NULL is ignored. + */ +RTDECL(void) RTDbgLineFree(PRTDBGLINE pLine); + + +/** @defgroup grp_rt_dbgas RTDbgAs - Debug Address Space + * @{ + */ + +/** + * Creates an empty address space. + * + * @returns IPRT status code. + * + * @param phDbgAs Where to store the address space handle on success. + * @param FirstAddr The first address in the address space. + * @param LastAddr The last address in the address space. + * @param pszName The name of the address space. + */ +RTDECL(int) RTDbgAsCreate(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr, const char *pszName); + +/** + * Variant of RTDbgAsCreate that takes a name format string. + * + * @returns IPRT status code. + * + * @param phDbgAs Where to store the address space handle on success. + * @param FirstAddr The first address in the address space. + * @param LastAddr The last address in the address space. + * @param pszNameFmt The name format of the address space. + * @param va Format arguments. + */ +RTDECL(int) RTDbgAsCreateV(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr, const char *pszNameFmt, va_list va); + +/** + * Variant of RTDbgAsCreate that takes a name format string. + * + * @returns IPRT status code. + * + * @param phDbgAs Where to store the address space handle on success. + * @param FirstAddr The first address in the address space. + * @param LastAddr The last address in the address space. + * @param pszNameFmt The name format of the address space. + * @param ... Format arguments. + */ +RTDECL(int) RTDbgAsCreateF(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr, const char *pszNameFmt, ...); + +/** + * Retains a reference to the address space. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * + * @param hDbgAs The address space handle. + * + * @remarks Will not take any locks. + */ +RTDECL(uint32_t) RTDbgAsRetain(RTDBGAS hDbgAs); + +/** + * Release a reference to the address space. + * + * When the reference count reaches zero, the address space is destroyed. + * That means unlinking all the modules it currently contains, potentially + * causing some or all of them to be destroyed as they are managed by + * reference counting. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * + * @param hDbgAs The address space handle. The NIL handle is quietly + * ignored and 0 is returned. + * + * @remarks Will not take any locks. + */ +RTDECL(uint32_t) RTDbgAsRelease(RTDBGAS hDbgAs); + +/** + * Gets the name of an address space. + * + * @returns read only address space name. + * NULL if hDbgAs is invalid. + * + * @param hDbgAs The address space handle. + * + * @remarks Will not take any locks. + */ +RTDECL(const char *) RTDbgAsName(RTDBGAS hDbgAs); + +/** + * Gets the first address in an address space. + * + * @returns The address. + * 0 if hDbgAs is invalid. + * + * @param hDbgAs The address space handle. + * + * @remarks Will not take any locks. + */ +RTDECL(RTUINTPTR) RTDbgAsFirstAddr(RTDBGAS hDbgAs); + +/** + * Gets the last address in an address space. + * + * @returns The address. + * 0 if hDbgAs is invalid. + * + * @param hDbgAs The address space handle. + * + * @remarks Will not take any locks. + */ +RTDECL(RTUINTPTR) RTDbgAsLastAddr(RTDBGAS hDbgAs); + +/** + * Gets the number of modules in the address space. + * + * This can be used together with RTDbgAsModuleByIndex + * to enumerate the modules. + * + * @returns The number of modules. + * + * @param hDbgAs The address space handle. + * + * @remarks Will not take any locks. + */ +RTDECL(uint32_t) RTDbgAsModuleCount(RTDBGAS hDbgAs); + +/** @name Flags for RTDbgAsModuleLink and RTDbgAsModuleLinkSeg + * @{ */ +/** Replace all conflicting module. + * (The conflicting modules will be removed the address space and their + * references released.) */ +#define RTDBGASLINK_FLAGS_REPLACE RT_BIT_32(0) +/** Mask containing the valid flags. */ +#define RTDBGASLINK_FLAGS_VALID_MASK UINT32_C(0x00000001) +/** @} */ + +/** + * Links a module into the address space at the give address. + * + * The size of the mapping is determined using RTDbgModImageSize(). + * + * @returns IPRT status code. + * @retval VERR_OUT_OF_RANGE if the specified address will put the module + * outside the address space. + * @retval VERR_ADDRESS_CONFLICT if the mapping clashes with existing mappings. + * + * @param hDbgAs The address space handle. + * @param hDbgMod The module handle of the module to be linked in. + * @param ImageAddr The address to link the module at. + * @param fFlags See RTDBGASLINK_FLAGS_*. + */ +RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr, uint32_t fFlags); + +/** + * Links a segment into the address space at the give address. + * + * The size of the mapping is determined using RTDbgModSegmentSize(). + * + * @returns IPRT status code. + * @retval VERR_OUT_OF_RANGE if the specified address will put the module + * outside the address space. + * @retval VERR_ADDRESS_CONFLICT if the mapping clashes with existing mappings. + * + * @param hDbgAs The address space handle. + * @param hDbgMod The module handle. + * @param iSeg The segment number (0-based) of the segment to be + * linked in. + * @param SegAddr The address to link the segment at. + * @param fFlags See RTDBGASLINK_FLAGS_*. + */ +RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr, uint32_t fFlags); + +/** + * Unlinks all the mappings of a module from the address space. + * + * @returns IPRT status code. + * @retval VERR_NOT_FOUND if the module wasn't found. + * + * @param hDbgAs The address space handle. + * @param hDbgMod The module handle of the module to be unlinked. + */ +RTDECL(int) RTDbgAsModuleUnlink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod); + +/** + * Unlinks the mapping at the specified address. + * + * @returns IPRT status code. + * @retval VERR_NOT_FOUND if no module or segment is mapped at that address. + * + * @param hDbgAs The address space handle. + * @param Addr The address within the mapping to be unlinked. + */ +RTDECL(int) RTDbgAsModuleUnlinkByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr); + +/** + * Get a the handle of a module in the address space by is index. + * + * @returns A retained handle to the specified module. The caller must release + * the returned reference. + * NIL_RTDBGMOD if invalid index or handle. + * + * @param hDbgAs The address space handle. + * @param iModule The index of the module to get. + * + * @remarks The module indexes may change after calls to RTDbgAsModuleLink, + * RTDbgAsModuleLinkSeg, RTDbgAsModuleUnlink and + * RTDbgAsModuleUnlinkByAddr. + */ +RTDECL(RTDBGMOD) RTDbgAsModuleByIndex(RTDBGAS hDbgAs, uint32_t iModule); + +/** + * Queries mapping module information by handle. + * + * @returns IPRT status code. + * @retval VERR_NOT_FOUND if no mapping was found at the specified address. + * + * @param hDbgAs The address space handle. + * @param Addr Address within the mapping of the module or segment. + * @param phMod Where to the return the retained module handle. + * Optional. + * @param pAddr Where to return the base address of the mapping. + * Optional. + * @param piSeg Where to return the segment index. This is set to + * NIL if the entire module is mapped as a single + * mapping. Optional. + */ +RTDECL(int) RTDbgAsModuleByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTDBGMOD phMod, PRTUINTPTR pAddr, PRTDBGSEGIDX piSeg); + +/** + * Queries mapping module information by name. + * + * @returns IPRT status code. + * @retval VERR_NOT_FOUND if no mapping was found at the specified address. + * @retval VERR_OUT_OF_RANGE if the name index was out of range. + * + * @param hDbgAs The address space handle. + * @param pszName The module name. + * @param iName There can be more than one module by the same name + * in an address space. This argument indicates which + * is meant. (0 based) + * @param phMod Where to the return the retained module handle. + */ +RTDECL(int) RTDbgAsModuleByName(RTDBGAS hDbgAs, const char *pszName, uint32_t iName, PRTDBGMOD phMod); + +/** + * Information about a mapping. + * + * This is used by RTDbgAsModuleGetMapByIndex. + */ +typedef struct RTDBGASMAPINFO +{ + /** The mapping address. */ + RTUINTPTR Address; + /** The segment mapped there. + * This is NIL_RTDBGSEGIDX if the entire module image is mapped here. */ + RTDBGSEGIDX iSeg; +} RTDBGASMAPINFO; +/** Pointer to info about an address space mapping. */ +typedef RTDBGASMAPINFO *PRTDBGASMAPINFO; +/** Pointer to const info about an address space mapping. */ +typedef RTDBGASMAPINFO const *PCRTDBGASMAPINFO; + +/** + * Queries mapping information for a module given by index. + * + * @returns IRPT status code. + * @retval VERR_INVALID_HANDLE if hDbgAs is invalid. + * @retval VERR_OUT_OF_RANGE if the name index was out of range. + * @retval VINF_BUFFER_OVERFLOW if the array is too small and the returned + * information is incomplete. + * + * @param hDbgAs The address space handle. + * @param iModule The index of the module to get. + * @param paMappings Where to return the mapping information. The buffer + * size is given by *pcMappings. + * @param pcMappings IN: Size of the paMappings array. OUT: The number of + * entries returned. + * @param fFlags Flags for reserved for future use. MBZ. + * + * @remarks See remarks for RTDbgAsModuleByIndex regarding the volatility of the + * iModule parameter. + */ +RTDECL(int) RTDbgAsModuleQueryMapByIndex(RTDBGAS hDbgAs, uint32_t iModule, PRTDBGASMAPINFO paMappings, uint32_t *pcMappings, uint32_t fFlags); + +/** + * Adds a symbol to a module in the address space. + * + * @returns IPRT status code. See RTDbgModSymbolAdd for more specific ones. + * @retval VERR_INVALID_HANDLE if hDbgAs is invalid. + * @retval VERR_NOT_FOUND if no module was found at the specified address. + * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding + * custom symbols. + * + * @param hDbgAs The address space handle. + * @param pszSymbol The symbol name. + * @param Addr The address of the symbol. + * @param cb The size of the symbol. + * @param fFlags Symbol flags. + * @param piOrdinal Where to return the symbol ordinal on success. If + * the interpreter doesn't do ordinals, this will be set to + * UINT32_MAX. Optional + */ +RTDECL(int) RTDbgAsSymbolAdd(RTDBGAS hDbgAs, const char *pszSymbol, RTUINTPTR Addr, RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal); + +/** + * Query a symbol by address. + * + * @returns IPRT status code. See RTDbgModSymbolAddr for more specific ones. + * @retval VERR_INVALID_HANDLE if hDbgAs is invalid. + * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module. + * @retval VERR_INVALID_PARAMETER if incorrect flags. + * + * @param hDbgAs The address space handle. + * @param Addr The address which closest symbol is requested. + * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX. + * @param poffDisp Where to return the distance between the symbol + * and address. Optional. + * @param pSymbol Where to return the symbol info. + * @param phMod Where to return the module handle. Optional. + */ +RTDECL(int) RTDbgAsSymbolByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, uint32_t fFlags, + PRTINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod); + +/** + * Query a symbol by address. + * + * @returns IPRT status code. See RTDbgModSymbolAddrA for more specific ones. + * @retval VERR_INVALID_HANDLE if hDbgAs is invalid. + * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module. + * @retval VERR_INVALID_PARAMETER if incorrect flags. + * + * @param hDbgAs The address space handle. + * @param Addr The address which closest symbol is requested. + * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX. + * @param poffDisp Where to return the distance between the symbol + * and address. Optional. + * @param ppSymInfo Where to return the pointer to the allocated symbol + * info. Always set. Free with RTDbgSymbolFree. + * @param phMod Where to return the module handle. Optional. + */ +RTDECL(int) RTDbgAsSymbolByAddrA(RTDBGAS hDbgAs, RTUINTPTR Addr, uint32_t fFlags, + PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo, PRTDBGMOD phMod); + +/** + * Query a symbol by name. + * + * @returns IPRT status code. + * @retval VERR_SYMBOL_NOT_FOUND if not found. + * + * @param hDbgAs The address space handle. + * @param pszSymbol The symbol name. It is possible to limit the scope + * of the search by prefixing the symbol with a module + * name pattern followed by a bang (!) character. + * RTStrSimplePatternNMatch is used for the matching. + * @param pSymbol Where to return the symbol info. + * @param phMod Where to return the module handle. Optional. + */ +RTDECL(int) RTDbgAsSymbolByName(RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod); + +/** + * Query a symbol by name, allocating the returned symbol structure. + * + * @returns IPRT status code. + * @retval VERR_SYMBOL_NOT_FOUND if not found. + * + * @param hDbgAs The address space handle. + * @param pszSymbol The symbol name. See RTDbgAsSymbolByName for more. + * @param ppSymbol Where to return the pointer to the allocated + * symbol info. Always set. Free with RTDbgSymbolFree. + * @param phMod Where to return the module handle. Optional. + */ +RTDECL(int) RTDbgAsSymbolByNameA(RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL *ppSymbol, PRTDBGMOD phMod); + +/** + * Query a line number by address. + * + * @returns IPRT status code. See RTDbgModSymbolAddrA for more specific ones. + * @retval VERR_INVALID_HANDLE if hDbgAs is invalid. + * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module. + * + * @param hDbgAs The address space handle. + * @param Addr The address which closest symbol is requested. + * @param poffDisp Where to return the distance between the line + * number and address. + * @param pLine Where to return the line number information. + */ +RTDECL(int) RTDbgAs(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTINTPTR poffDisp, PRTDBGLINE pLine); + +/** + * Adds a line number to a module in the address space. + * + * @returns IPRT status code. See RTDbgModSymbolAdd for more specific ones. + * @retval VERR_INVALID_HANDLE if hDbgAs is invalid. + * @retval VERR_NOT_FOUND if no module was found at the specified address. + * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding + * custom symbols. + * + * @param hDbgAs The address space handle. + * @param pszFile The file name. + * @param uLineNo The line number. + * @param Addr The address of the symbol. + * @param piOrdinal Where to return the line number ordinal on success. + * If the interpreter doesn't do ordinals, this will be + * set to UINT32_MAX. Optional. + */ +RTDECL(int) RTDbgAsLineAdd(RTDBGAS hDbgAs, const char *pszFile, uint32_t uLineNo, RTUINTPTR Addr, uint32_t *piOrdinal); + + +/** + * Query a line number by address. + * + * @returns IPRT status code. See RTDbgModSymbolAddrA for more specific ones. + * @retval VERR_INVALID_HANDLE if hDbgAs is invalid. + * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module. + * + * @param hDbgAs The address space handle. + * @param Addr The address which closest symbol is requested. + * @param poffDisp Where to return the distance between the line + * number and address. + * @param pLine Where to return the line number information. + */ +RTDECL(int) RTDbgAsLineByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTINTPTR poffDisp, PRTDBGLINE pLine); + +/** + * Query a line number by address. + * + * @returns IPRT status code. See RTDbgModSymbolAddrA for more specific ones. + * @retval VERR_INVALID_HANDLE if hDbgAs is invalid. + * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module. + * + * @param hDbgAs The address space handle. + * @param Addr The address which closest symbol is requested. + * @param poffDisp Where to return the distance between the line + * number and address. + * @param ppLine Where to return the pointer to the allocated line + * number info. Always set. Free with RTDbgLineFree. + */ +RTDECL(int) RTDbgAsLineByAddrA(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTINTPTR poffDisp, PRTDBGLINE *ppLine); + +/** @todo Missing some bits here. */ + +/** @} */ + + +/** @defgroup grp_rt_dbgmod RTDbgMod - Debug Module Interpreter + * @{ + */ + +/** + * Creates a module based on the default debug info container. + * + * This can be used to manually load a module and its symbol. The primary user + * group is the debug info interpreters, which use this API to create an + * efficient debug info container behind the scenes and forward all queries to + * it once the info has been loaded. + * + * @returns IPRT status code. + * + * @param phDbgMod Where to return the module handle. + * @param pszName The name of the module (mandatory). + * @param cbSeg The size of initial segment. If zero, segments will + * have to be added manually using RTDbgModSegmentAdd. + * @param fFlags Flags reserved for future extensions, MBZ for now. + */ +RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cbSeg, uint32_t fFlags); + +RTDECL(int) RTDbgModCreateDeferred(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR cb, uint32_t fFlags); +RTDECL(int) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t fFlags); +RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR uSubtrahend, uint32_t fFlags); + + +/** + * Retains another reference to the module. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * + * @param hDbgMod The module handle. + * + * @remarks Will not take any locks. + */ +RTDECL(uint32_t) RTDbgModRetain(RTDBGMOD hDbgMod); + +/** + * Release a reference to the module. + * + * When the reference count reaches zero, the module is destroyed. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * + * @param hDbgMod The module handle. The NIL handle is quietly ignored + * and 0 is returned. + * + * @remarks Will not take any locks. + */ +RTDECL(uint32_t) RTDbgModRelease(RTDBGMOD hDbgMod); + +/** + * Gets the module name. + * + * @returns Pointer to a read only string containing the name. + * + * @param hDbgMod The module handle. + */ +RTDECL(const char *) RTDbgModName(RTDBGMOD hDbgMod); + +/** + * Converts an image relative address to a segment:offset address. + * + * @returns Segment index on success. + * NIL_RTDBGSEGIDX is returned if the module handle or the RVA are + * invalid. + * + * @param hDbgMod The module handle. + * @param uRva The image relative address to convert. + * @param poffSeg Where to return the segment offset. Optional. + */ +RTDECL(RTDBGSEGIDX) RTDbgModRvaToSegOff(RTDBGMOD hDbgMod, RTUINTPTR uRva, PRTUINTPTR poffSeg); + +/** + * Image size when mapped if segments are mapped adjacently. + * + * For ELF, PE, and Mach-O images this is (usually) a natural query, for LX and + * NE and such it's a bit odder and the answer may not make much sense for them. + * + * @returns Image mapped size. + * RTUINTPTR_MAX is returned if the handle is invalid. + * + * @param hDbgMod The module handle. + */ +RTDECL(RTUINTPTR) RTDbgModImageSize(RTDBGMOD hDbgMod); + +/** + * Gets the module tag value if any. + * + * @returns The tag. 0 if hDbgMod is invalid. + * + * @param hDbgMod The module handle. + */ +RTDECL(uint64_t) RTDbgModGetTag(RTDBGMOD hDbgMod); + +/** + * Tags or untags the module. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * + * @param hDbgMod The module handle. + * @param uTag The tag value. The convention is that 0 is no tag + * and any other value means it's tagged. It's adviced + * to use some kind of unique number like an address + * (global or string cache for instance) to avoid + * collisions with other users + */ +RTDECL(int) RTDbgModSetTag(RTDBGMOD hDbgMod, uint64_t uTag); + + +/** + * Adds a segment to the module. Optional feature. + * + * This method is intended used for manually constructing debug info for a + * module. The main usage is from other debug info interpreters that want to + * avoid writing a debug info database and instead uses the standard container + * behind the scenes. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if this feature isn't support by the debug info + * interpreter. This is a common return code. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_DBG_ADDRESS_WRAP if uRva+cb wraps around. + * @retval VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE if pszName is too short or long. + * @retval VERR_INVALID_PARAMETER if fFlags contains undefined flags. + * @retval VERR_DBG_SPECIAL_SEGMENT if *piSeg is a special segment. + * @retval VERR_DBG_INVALID_SEGMENT_INDEX if *piSeg doesn't meet expectations. + * + * @param hDbgMod The module handle. + * @param uRva The image relative address of the segment. + * @param cb The size of the segment. + * @param pszName The segment name. Does not normally need to be + * unique, although this is somewhat up to the + * debug interpreter to decide. + * @param fFlags Segment flags. Reserved for future used, MBZ. + * @param piSeg The segment index or NIL_RTDBGSEGIDX on input. + * The assigned segment index on successful return. + * Optional. + */ +RTDECL(int) RTDbgModSegmentAdd(RTDBGMOD hDbgMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, + uint32_t fFlags, PRTDBGSEGIDX piSeg); + +/** + * Gets the number of segments in the module. + * + * This is can be used to determine the range which can be passed to + * RTDbgModSegmentByIndex and derivates. + * + * @returns The segment relative address. + * NIL_RTDBGSEGIDX if the handle is invalid. + * + * @param hDbgMod The module handle. + */ +RTDECL(RTDBGSEGIDX) RTDbgModSegmentCount(RTDBGMOD hDbgMod); + +/** + * Query information about a segment. + * + * This can be used together with RTDbgModSegmentCount to enumerate segments. + * The index starts a 0 and stops one below RTDbgModSegmentCount. + * + * @returns IPRT status code. + * @retval VERR_DBG_INVALID_SEGMENT_INDEX if iSeg is too high. + * @retval VERR_DBG_SPECIAL_SEGMENT if iSeg indicates a special segment. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * + * @param hDbgMod The module handle. + * @param iSeg The segment index. No special segments. + * @param pSegInfo Where to return the segment info. The + * RTDBGSEGMENT::Address member will be set to + * RTUINTPTR_MAX or the load address used at link time. + */ +RTDECL(int) RTDbgModSegmentByIndex(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo); + +/** + * Gets the size of a segment. + * + * This is a just a wrapper around RTDbgModSegmentByIndex. + * + * @returns The segment size. + * RTUINTPTR_MAX is returned if either the handle and segment index are + * invalid. + * + * @param hDbgMod The module handle. + * @param iSeg The segment index. RTDBGSEGIDX_ABS is not allowed. + * If RTDBGSEGIDX_RVA is used, the functions returns + * the same value as RTDbgModImageSize. + */ +RTDECL(RTUINTPTR) RTDbgModSegmentSize(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg); + +/** + * Gets the image relative address of a segment. + * + * This is a just a wrapper around RTDbgModSegmentByIndex. + * + * @returns The segment relative address. + * RTUINTPTR_MAX is returned if either the handle and segment index are + * invalid. + * + * @param hDbgMod The module handle. + * @param iSeg The segment index. No special segment indexes + * allowed (asserted). + */ +RTDECL(RTUINTPTR) RTDbgModSegmentRva(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg); + + +/** + * Adds a line number to the module. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding + * custom symbols. This is a common place occurrence. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or + * short. + * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and + * it's not inside any of the segments defined by the module. + * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid. + * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the + * end of the segment. + * @retval VERR_DBG_ADDRESS_WRAP if off+cb wraps around. + * @retval VERR_INVALID_PARAMETER if the symbol flags sets undefined bits. + * + * @param hDbgMod The module handle. + * @param pszSymbol The symbol name. + * @param iSeg The segment index. + * @param off The segment offset. + * @param cb The size of the symbol. Can be zero, although this + * may depend somewhat on the debug interpreter. + * @param fFlags Symbol flags. Reserved for the future, MBZ. + * @param piOrdinal Where to return the symbol ordinal on success. If + * the interpreter doesn't do ordinals, this will be set to + * UINT32_MAX. Optional. + */ +RTDECL(int) RTDbgModSymbolAdd(RTDBGMOD hDbgMod, const char *pszSymbol, RTDBGSEGIDX iSeg, RTUINTPTR off, + RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal); + +/** + * Gets the symbol count. + * + * This can be used together wtih RTDbgModSymbolByOrdinal or + * RTDbgModSymbolByOrdinalA to enumerate all the symbols. + * + * @returns The number of symbols in the module. + * UINT32_MAX is returned if the module handle is invalid or some other + * error occurs. + * + * @param hDbgMod The module handle. + */ +RTDECL(uint32_t) RTDbgModSymbolCount(RTDBGMOD hDbgMod); + +/** + * Queries symbol information by ordinal number. + * + * @returns IPRT status code. + * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number. + * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported. + * + * @param hDbgMod The module handle. + * @param iOrdinal The symbol ordinal number. 0-based. The highest + * number is RTDbgModSymbolCount() - 1. + * @param pSymInfo Where to store the symbol information. + */ +RTDECL(int) RTDbgModSymbolByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo); + +/** + * Queries symbol information by ordinal number. + * + * @returns IPRT status code. + * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols. + * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported. + * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number. + * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails. + * + * @param hDbgMod The module handle. + * @param iOrdinal The symbol ordinal number. 0-based. The highest + * number is RTDbgModSymbolCount() - 1. + * @param ppSymInfo Where to store the pointer to the returned + * symbol information. Always set. Free with + * RTDbgSymbolFree. + */ +RTDECL(int) RTDbgModSymbolByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL *ppSymInfo); + +/** + * Queries symbol information by address. + * + * The returned symbol is what the debug info interpreter considers the symbol + * most applicable to the specified address. This usually means a symbol with an + * address equal or lower than the requested. + * + * @returns IPRT status code. + * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found. + * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and + * it's not inside any of the segments defined by the module. + * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid. + * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the + * end of the segment. + * @retval VERR_INVALID_PARAMETER if incorrect flags. + * + * @param hDbgMod The module handle. + * @param iSeg The segment number. + * @param off The offset into the segment. + * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX. + * @param poffDisp Where to store the distance between the + * specified address and the returned symbol. + * Optional. + * @param pSymInfo Where to store the symbol information. + */ +RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags, + PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo); + +/** + * Queries symbol information by address. + * + * The returned symbol is what the debug info interpreter considers the symbol + * most applicable to the specified address. This usually means a symbol with an + * address equal or lower than the requested. + * + * @returns IPRT status code. + * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found. + * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and + * it's not inside any of the segments defined by the module. + * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid. + * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the + * end of the segment. + * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails. + * @retval VERR_INVALID_PARAMETER if incorrect flags. + * + * @param hDbgMod The module handle. + * @param iSeg The segment index. + * @param off The offset into the segment. + * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX. + * @param poffDisp Where to store the distance between the + * specified address and the returned symbol. Optional. + * @param ppSymInfo Where to store the pointer to the returned + * symbol information. Always set. Free with + * RTDbgSymbolFree. + */ +RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags, + PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo); + +/** + * Queries symbol information by symbol name. + * + * @returns IPRT status code. + * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols. + * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found. + * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or + * short. + * + * @param hDbgMod The module handle. + * @param pszSymbol The symbol name. + * @param pSymInfo Where to store the symbol information. + */ +RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymInfo); + +/** + * Queries symbol information by symbol name. + * + * @returns IPRT status code. + * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols. + * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found. + * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or + * short. + * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails. + * + * @param hDbgMod The module handle. + * @param pszSymbol The symbol name. + * @param ppSymInfo Where to store the pointer to the returned + * symbol information. Always set. Free with + * RTDbgSymbolFree. + */ +RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymInfo); + +/** + * Adds a line number to the module. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding + * custom symbols. This should be consider a normal response. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_DBG_FILE_NAME_OUT_OF_RANGE if the file name is too longer or + * empty. + * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and + * it's not inside any of the segments defined by the module. + * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid. + * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the + * end of the segment. + * @retval VERR_INVALID_PARAMETER if the line number flags sets undefined bits. + * + * @param hDbgMod The module handle. + * @param pszFile The file name. + * @param uLineNo The line number. + * @param iSeg The segment index. + * @param off The segment offset. + * @param piOrdinal Where to return the line number ordinal on + * success. If the interpreter doesn't do ordinals, + * this will be set to UINT32_MAX. Optional. + */ +RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo, + RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t *piOrdinal); + +/** + * Gets the line number count. + * + * This can be used together wtih RTDbgModLineByOrdinal or RTDbgModSymbolByLineA + * to enumerate all the line number information. + * + * @returns The number of line numbers in the module. + * UINT32_MAX is returned if the module handle is invalid or some other + * error occurs. + * + * @param hDbgMod The module handle. + */ +RTDECL(uint32_t) RTDbgModLineCount(RTDBGMOD hDbgMod); + +/** + * Queries line number information by ordinal number. + * + * This can be used to enumerate the line numbers for the module. Use + * RTDbgModLineCount() to figure the end of the ordinals. + * + * @returns IPRT status code. + * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers. + * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that + * ordinal. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + + * @param hDbgMod The module handle. + * @param iOrdinal The line number ordinal number. + * @param pLineInfo Where to store the information about the line + * number. + */ +RTDECL(int) RTDbgModLineByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo); + +/** + * Queries line number information by ordinal number. + * + * This can be used to enumerate the line numbers for the module. Use + * RTDbgModLineCount() to figure the end of the ordinals. + * + * @returns IPRT status code. + * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers. + * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that + * ordinal. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails. + * + * @param hDbgMod The module handle. + * @param iOrdinal The line number ordinal number. + * @param ppLineInfo Where to store the pointer to the returned line + * number information. Always set. Free with + * RTDbgLineFree. + */ +RTDECL(int) RTDbgModLineByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE *ppLineInfo); + +/** + * Queries line number information by address. + * + * The returned line number is what the debug info interpreter considers the + * one most applicable to the specified address. This usually means a line + * number with an address equal or lower than the requested. + * + * @returns IPRT status code. + * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers. + * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and + * it's not inside any of the segments defined by the module. + * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid. + * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the + * end of the segment. + * + * @param hDbgMod The module handle. + * @param iSeg The segment number. + * @param off The offset into the segment. + * @param poffDisp Where to store the distance between the + * specified address and the returned symbol. + * Optional. + * @param pLineInfo Where to store the line number information. + */ +RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLineInfo); + +/** + * Queries line number information by address. + * + * The returned line number is what the debug info interpreter considers the + * one most applicable to the specified address. This usually means a line + * number with an address equal or lower than the requested. + * + * @returns IPRT status code. + * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers. + * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found. + * @retval VERR_INVALID_HANDLE if hDbgMod is invalid. + * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and + * it's not inside any of the segments defined by the module. + * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid. + * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the + * end of the segment. + * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails. + * + * @param hDbgMod The module handle. + * @param iSeg The segment number. + * @param off The offset into the segment. + * @param poffDisp Where to store the distance between the + * specified address and the returned symbol. + * Optional. + * @param ppLineInfo Where to store the pointer to the returned line + * number information. Always set. Free with + * RTDbgLineFree. + */ +RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLineInfo); +/** @} */ + +# endif /* IN_RING3 */ + + +/** @name Kernel Debug Info API + * + * This is a specialized API for obtaining symbols and structure information + * about the running kernel. It is relatively OS specific. Its purpose and + * operation is doesn't map all that well onto RTDbgMod, so a few dedicated + * functions was created for it. + * + * @{ */ + +/** Handle to the kernel debug info. */ +typedef struct RTDBGKRNLINFOINT *RTDBGKRNLINFO; +/** Pointer to a kernel debug info handle. */ +typedef RTDBGKRNLINFO *PRTDBGKRNLINFO; +/** Nil kernel debug info handle. */ +#define NIL_RTDBGKRNLINFO ((RTDBGKRNLINFO)0) + +/** + * Opens the kernel debug info. + * + * @returns IPRT status code. Can fail for any number of reasons. + * + * @param phKrnlInfo Where to return the kernel debug info handle on + * success. + * @param fFlags Flags reserved for future use. Must be zero. + */ +RTR0DECL(int) RTR0DbgKrnlInfoOpen(PRTDBGKRNLINFO phKrnlInfo, uint32_t fFlags); + +/** + * Retains a reference to the kernel debug info handle. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * @param hKrnlInfo The kernel info handle. + */ +RTR0DECL(uint32_t) RTR0DbgKrnlInfoRetain(RTDBGKRNLINFO hKrnlInfo); + + +/** + * Releases a reference to the kernel debug info handle, destroying it when the + * counter reaches zero. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * @param hKrnlInfo The kernel info handle. NIL_RTDBGKRNLINFO is + * quietly ignored. + */ +RTR0DECL(uint32_t) RTR0DbgKrnlInfoRelease(RTDBGKRNLINFO hKrnlInfo); + +/** + * Queries the offset (in bytes) of a member of a kernel structure. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and offset at @a poffMember. + * @retval VERR_NOT_FOUND if the structure or the member was not found. + * @retval VERR_INVALID_HANDLE if hKrnlInfo is bad. + * @retval VERR_INVALID_POINTER if any of the pointers are bad. + * + * @param hKrnlInfo The kernel info handle. + * @param pszStructure The structure name. + * @param pszMember The member name. + * @param poffMember Where to return the offset. + */ +RTR0DECL(int) RTR0DbgKrnlInfoQueryMember(RTDBGKRNLINFO hKrnlInfo, const char *pszStructure, + const char *pszMember, size_t *poffMember); + + +/** + * Queries the value (usually the address) of a kernel symbol. + * + * This may go looking for the symbol in other modules, in which case it will + * always check the kernel symbol table first. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and value at @a ppvSymbol. + * @retval VERR_SYMBOL_NOT_FOUND + * @retval VERR_INVALID_HANDLE if hKrnlInfo is bad. + * @retval VERR_INVALID_POINTER if any of the pointers are bad. + * + * @param hKrnlInfo The kernel info handle. + * @param pszModule Reserved for future extensions. Pass NULL. + * @param pszSymbol The C name of the symbol. + * @param ppvSymbol Where to return the symbol value, passing NULL is + * OK. This may be modified even on failure, in + * particular, it will be set to NULL when + * VERR_SYMBOL_NOT_FOUND is returned. + * + * @sa RTLdrGetSymbol. + */ +RTR0DECL(int) RTR0DbgKrnlInfoQuerySymbol(RTDBGKRNLINFO hKrnlInfo, const char *pszModule, + const char *pszSymbol, void **ppvSymbol); +/** @} */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/dir.h b/include/iprt/dir.h new file mode 100644 index 00000000..38d99aa3 --- /dev/null +++ b/include/iprt/dir.h @@ -0,0 +1,473 @@ +/** @file + * IPRT - Directory Manipulation. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_dir_h +#define ___iprt_dir_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/fs.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_dir RTDir - Directory Manipulation + * @ingroup grp_rt + * @{ + */ + +/** + * Check for the existence of a directory. + * + * All symbolic links will be attemped resolved. If that is undesirable, please + * use RTPathQueryInfo instead. + * + * @returns true if exist and is a directory. + * @returns false if not exists or isn't a directory. + * @param pszPath Path to the directory. + */ +RTDECL(bool) RTDirExists(const char *pszPath); + +/** @name RTDirCreate flags. + * @{ */ +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTDIRCREATE_FLAGS_NO_SYMLINKS RT_BIT(0) +/** @} */ + +/** + * Creates a directory. + * + * @returns iprt status code. + * @param pszPath Path to the directory to create. + * @param fMode The mode of the new directory. + * @param fCreate Create flags, RTDIRCREATE_FLAGS_*. + */ +RTDECL(int) RTDirCreate(const char *pszPath, RTFMODE fMode, uint32_t fCreate); + +/** + * Creates a directory including all parent directories in the path + * if they don't exist. + * + * @returns iprt status code. + * @param pszPath Path to the directory to create. + * @param fMode The mode of the new directories. + */ +RTDECL(int) RTDirCreateFullPath(const char *pszPath, RTFMODE fMode); + +/** + * Creates a new directory with a unique name using the given template. + * + * One or more trailing X'es in the template will be replaced by random alpha + * numeric characters until a RTDirCreate succeeds or we run out of patience. + * For instance: + * "/tmp/myprog-XXXXXX" + * + * As an alternative to trailing X'es, it + * is possible to put 3 or more X'es somewhere inside the directory name. In + * the following string only the last bunch of X'es will be modified: + * "/tmp/myprog-XXX-XXX.tmp" + * + * @returns iprt status code. + * @param pszTemplate The directory name template on input. The actual + * directory name on success. Empty string on failure. + * @param fMode The mode to create the directory with. Use 0700 + * unless you have reason not to. + */ +RTDECL(int) RTDirCreateTemp(char *pszTemplate, RTFMODE fMode); + +/** + * Secure version of @a RTDirCreateTemp with a fixed mode of 0700. + * + * This function behaves in the same way as @a RTDirCreateTemp with two + * additional points. Firstly the mode is fixed to 0700. Secondly it will + * fail if it is not possible to perform the operation securely. Possible + * reasons include that the directory could be removed by another unprivileged + * user before it is used (e.g. if is created in a non-sticky /tmp directory) + * or that the path contains symbolic links which another unprivileged user + * could manipulate; however the exact criteria will be specified on a + * platform-by-platform basis as platform support is added. + * @see RTPathIsSecure for the current list of criteria. + * @returns iprt status code. + * @returns VERR_NOT_SUPPORTED if the interface can not be supported on the + * current platform at this time. + * @returns VERR_INSECURE if the directory could not be created securely. + * @param pszTemplate The directory name template on input. The + * actual directory name on success. Empty string + * on failure. + */ +RTDECL(int) RTDirCreateTempSecure(char *pszTemplate); + +/** + * Creates a new directory with a unique name by appending a number. + * + * First it is tried to create the directory without any numbers appended. + * When this fails a number string is appended (starting with 1) separated by + * the optional separator. The numbers are zero padded. + * + * On success @a pszPath contains the path created. + * + * @returns iprt status code. + * @param pszPath Path to the directory to create. + * @param cbSize The size of pszPath. Needs enough space for holding the + * digits and the optional separator. + * @param fMode The mode of the new directory. + * @param cchDigits How many digits should the number maximal have. + * @param chSep The separator used between the path and the number. Can + * be zero. (optional) + */ +RTDECL(int) RTDirCreateUniqueNumbered(char *pszPath, size_t cbSize, RTFMODE fMode, signed int cchDigits, char chSep); + +/** + * Removes a directory if empty. + * + * @returns iprt status code. + * @param pszPath Path to the directory to remove. + */ +RTDECL(int) RTDirRemove(const char *pszPath); + +/** + * Removes a directory tree recursively. + * + * @returns iprt status code. + * @param pszPath Path to the directory to remove recursively. + * @param fFlags Flags, see RTDIRRMREC_F_XXX. + * + * @remarks This will not work on a root directory. + */ +RTDECL(int) RTDirRemoveRecursive(const char *pszPath, uint32_t fFlags); + +/** @name RTDirRemoveRecursive flags. + * @{ */ +/** Delete the content of the directory and the directory itself. */ +#define RTDIRRMREC_F_CONTENT_AND_DIR UINT32_C(0) +/** Only delete the content of the directory, omit the directory it self. */ +#define RTDIRRMREC_F_CONTENT_ONLY RT_BIT_32(0) +/** Mask of valid flags. */ +#define RTDIRRMREC_F_VALID_MASK UINT32_C(0x00000001) +/** @} */ + +/** + * Flushes the specified directory. + * + * This API is not implemented on all systems. On some systems it may be + * unnecessary if you've already flushed the file. If you really care for your + * data and is entering dangerous territories, it doesn't hurt calling it after + * flushing and closing the file. + * + * @returns IPRT status code. + * @retval VERR_NOT_IMPLEMENTED must be expected. + * @retval VERR_NOT_SUPPORTED must be expected. + * @param pszPath Path to the directory. + */ +RTDECL(int) RTDirFlush(const char *pszPath); + +/** + * Flushes the parent directory of the specified file. + * + * This is just a wrapper around RTDirFlush. + * + * @returns IPRT status code, see RTDirFlush for details. + * @param pszChild Path to the file which parent should be flushed. + */ +RTDECL(int) RTDirFlushParent(const char *pszChild); + + +/** Pointer to an open directory (sort of handle). */ +typedef struct RTDIR *PRTDIR; + + +/** + * Filter option for RTDirOpenFiltered(). + */ +typedef enum RTDIRFILTER +{ + /** The usual invalid 0 entry. */ + RTDIRFILTER_INVALID = 0, + /** No filter should be applied (and none was specified). */ + RTDIRFILTER_NONE, + /** The Windows NT filter. + * The following wildcard chars: *, ?, <, > and " + * The matching is done on the uppercased strings. */ + RTDIRFILTER_WINNT, + /** The UNIX filter. + * The following wildcard chars: *, ?, [..] + * The matching is done on exact case. */ + RTDIRFILTER_UNIX, + /** The UNIX filter, uppercased matching. + * Same as RTDIRFILTER_UNIX except that the strings are uppercased before comparing. */ + RTDIRFILTER_UNIX_UPCASED, + + /** The usual full 32-bit value. */ + RTDIRFILTER_32BIT_HACK = 0x7fffffff +} RTDIRFILTER; + + +/** + * Directory entry type. + * + * This is the RTFS_TYPE_MASK stuff shifted down 12 bits and + * identical to the BSD/LINUX ABI. + */ +typedef enum RTDIRENTRYTYPE +{ + /** Unknown type (DT_UNKNOWN). */ + RTDIRENTRYTYPE_UNKNOWN = 0, + /** Named pipe (fifo) (DT_FIFO). */ + RTDIRENTRYTYPE_FIFO = 001, + /** Character device (DT_CHR). */ + RTDIRENTRYTYPE_DEV_CHAR = 002, + /** Directory (DT_DIR). */ + RTDIRENTRYTYPE_DIRECTORY = 004, + /** Block device (DT_BLK). */ + RTDIRENTRYTYPE_DEV_BLOCK = 006, + /** Regular file (DT_REG). */ + RTDIRENTRYTYPE_FILE = 010, + /** Symbolic link (DT_LNK). */ + RTDIRENTRYTYPE_SYMLINK = 012, + /** Socket (DT_SOCK). */ + RTDIRENTRYTYPE_SOCKET = 014, + /** Whiteout (DT_WHT). */ + RTDIRENTRYTYPE_WHITEOUT = 016 +} RTDIRENTRYTYPE; + + +/** + * Directory entry. + * + * This is inspired by the POSIX interfaces. + */ +#pragma pack(1) +typedef struct RTDIRENTRY +{ + /** The unique identifier (within the file system) of this file system object (d_ino). + * + * Together with INodeIdDevice, this field can be used as a OS wide unique id + * when both their values are not 0. This field is 0 if the information is not + * available. */ + RTINODE INodeId; + /** The entry type. (d_type) + * RTDIRENTRYTYPE_UNKNOWN is a common return value here since not all file + * systems (or Unixes) stores the type of a directory entry and instead + * expects the user to use stat() to get it. So, when you see this you + * should use RTPathQueryInfo to get the type, or if if you're lazy, use + * RTDirReadEx. */ + RTDIRENTRYTYPE enmType; + /** The length of the filename, excluding the terminating nul character. */ + uint16_t cbName; + /** The filename. (no path) + * Using the pcbDirEntry parameter of RTDirRead makes this field variable in size. */ + char szName[260]; +} RTDIRENTRY; +#pragma pack() +/** Pointer to a directory entry. */ +typedef RTDIRENTRY *PRTDIRENTRY; + + +/** + * Directory entry with extended information. + * + * This is inspired by the PC interfaces. + */ +#pragma pack(1) +typedef struct RTDIRENTRYEX +{ + /** Full information about the object. */ + RTFSOBJINFO Info; + /** The length of the short field (number of RTUTF16 entries (not chars)). + * It is 16-bit for reasons of alignment. */ + uint16_t cwcShortName; + /** The short name for 8.3 compatibility. + * Empty string if not available. + * Since the length is a bit tricky for a UTF-8 encoded name, and since this + * is practically speaking only a windows thing, it is encoded as UCS-2. */ + RTUTF16 wszShortName[14]; + /** The length of the filename. */ + uint16_t cbName; + /** The filename. (no path) + * Using the pcbDirEntry parameter of RTDirReadEx makes this field variable in size. */ + char szName[260]; +} RTDIRENTRYEX; +#pragma pack() +/** Pointer to a directory entry. */ +typedef RTDIRENTRYEX *PRTDIRENTRYEX; + + +/** + * Opens a directory. + * + * @returns iprt status code. + * @param ppDir Where to store the open directory pointer. + * @param pszPath Path to the directory to open. + */ +RTDECL(int) RTDirOpen(PRTDIR *ppDir, const char *pszPath); + +/** @name RTDirOpenFiltered flags. + * @{ */ +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTDIROPEN_FLAGS_NO_SYMLINKS RT_BIT(0) +/** @} */ + +/** + * Opens a directory filtering the entries using dos style wildcards. + * + * @returns iprt status code. + * @param ppDir Where to store the open directory pointer. + * @param pszPath Path to the directory to search, this must include wildcards. + * @param enmFilter The kind of filter to apply. Setting this to RTDIRFILTER_NONE makes + * this function behave like RTDirOpen. + * @param fOpen Open flags, RTDIROPENFILTERED_FLAGS_*. + */ +RTDECL(int) RTDirOpenFiltered(PRTDIR *ppDir, const char *pszPath, RTDIRFILTER enmFilter, uint32_t fOpen); + +/** + * Closes a directory. + * + * @returns iprt status code. + * @param pDir Pointer to open directory returned by RTDirOpen() or RTDirOpenFiltered(). + */ +RTDECL(int) RTDirClose(PRTDIR pDir); + +/** + * Reads the next entry in the directory. + * + * @returns VINF_SUCCESS and data in pDirEntry on success. + * @returns VERR_NO_MORE_FILES when the end of the directory has been reached. + * @returns VERR_BUFFER_OVERFLOW if the buffer is too small to contain the filename. If + * pcbDirEntry is specified it will be updated with the required buffer size. + * @returns suitable iprt status code on other errors. + * + * @param pDir Pointer to the open directory. + * @param pDirEntry Where to store the information about the next + * directory entry on success. + * @param pcbDirEntry Optional parameter used for variable buffer size. + * + * On input the variable pointed to contains the size of the pDirEntry + * structure. This must be at least OFFSET(RTDIRENTRY, szName[2]) bytes. + * + * On successful output the field is updated to + * OFFSET(RTDIRENTRY, szName[pDirEntry->cbName + 1]). + * + * When the data doesn't fit in the buffer and VERR_BUFFER_OVERFLOW is + * returned, this field contains the required buffer size. + * + * The value is unchanged in all other cases. + */ +RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry); + +/** + * Reads the next entry in the directory returning extended information. + * + * @returns VINF_SUCCESS and data in pDirEntry on success. + * @returns VERR_NO_MORE_FILES when the end of the directory has been reached. + * @returns VERR_BUFFER_OVERFLOW if the buffer is too small to contain the filename. If + * pcbDirEntry is specified it will be updated with the required buffer size. + * @returns suitable iprt status code on other errors. + * + * @param pDir Pointer to the open directory. + * @param pDirEntry Where to store the information about the next + * directory entry on success. + * @param pcbDirEntry Optional parameter used for variable buffer size. + * + * On input the variable pointed to contains the size of the pDirEntry + * structure. This must be at least OFFSET(RTDIRENTRYEX, szName[2]) bytes. + * + * On successful output the field is updated to + * OFFSET(RTDIRENTRYEX, szName[pDirEntry->cbName + 1]). + * + * When the data doesn't fit in the buffer and VERR_BUFFER_OVERFLOW is + * returned, this field contains the required buffer size. + * + * The value is unchanged in all other cases. + * @param enmAdditionalAttribs + * Which set of additional attributes to request. + * Use RTFSOBJATTRADD_NOTHING if this doesn't matter. + * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK. + */ +RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags); + + +/** + * Renames a file. + * + * Identical to RTPathRename except that it will ensure that the source is a directory. + * + * @returns IPRT status code. + * @returns VERR_ALREADY_EXISTS if the destination file exists. + * + * @param pszSrc The path to the source file. + * @param pszDst The path to the destination file. + * This file will be created. + * @param fRename See RTPathRename. + */ +RTDECL(int) RTDirRename(const char *pszSrc, const char *pszDst, unsigned fRename); + + +/** + * Query information about an open directory. + * + * @returns iprt status code. + * + * @param pDir Pointer to the open directory. + * @param pObjInfo Object information structure to be filled on successful return. + * @param enmAdditionalAttribs Which set of additional attributes to request. + * Use RTFSOBJATTRADD_NOTHING if this doesn't matter. + */ +RTR3DECL(int) RTDirQueryInfo(PRTDIR pDir, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs); + + +/** + * Changes one or more of the timestamps associated of file system object. + * + * @returns iprt status code. + * @returns VERR_NOT_SUPPORTED is returned if the operation isn't supported by the OS. + * + * @param pDir Pointer to the open directory. + * @param pAccessTime Pointer to the new access time. NULL if not to be changed. + * @param pModificationTime Pointer to the new modifcation time. NULL if not to be changed. + * @param pChangeTime Pointer to the new change time. NULL if not to be changed. + * @param pBirthTime Pointer to the new time of birth. NULL if not to be changed. + * + * @remark The file system might not implement all these time attributes, + * the API will ignore the ones which aren't supported. + * + * @remark The file system might not implement the time resolution + * employed by this interface, the time will be chopped to fit. + * + * @remark The file system may update the change time even if it's + * not specified. + * + * @remark POSIX can only set Access & Modification and will always set both. + */ +RTR3DECL(int) RTDirSetTimes(PRTDIR pDir, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, + PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/dvm.h b/include/iprt/dvm.h new file mode 100644 index 00000000..f36a5f10 --- /dev/null +++ b/include/iprt/dvm.h @@ -0,0 +1,379 @@ +/** @file + * IPRT Disk Volume Management API (DVM). + */ + +/* + * Copyright (C) 2011 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. + */ + +#ifndef ___iprt_dvm_h +#define ___iprt_dvm_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + + +/** @defgroup grp_dvm IPRT Disk Volume Management + * @{ + */ + +/** + * Volume type. + * Comparable to the FS type in MBR partition maps + * or the partition type GUIDs in GPT tables. + */ +typedef enum RTDVMVOLTYPE +{ + /** Invalid. */ + RTDVMVOLTYPE_INVALID = 0, + /** Unknown. */ + RTDVMVOLTYPE_UNKNOWN, + /** Volume hosts a NTFS filesystem. */ + RTDVMVOLTYPE_NTFS, + /** Volume hosts a FAT16 filesystem. */ + RTDVMVOLTYPE_FAT16, + /** Volume hosts a FAT32 filesystem. */ + RTDVMVOLTYPE_FAT32, + /** Volume hosts a Linux swap. */ + RTDVMVOLTYPE_LINUX_SWAP, + /** Volume hosts a Linux filesystem. */ + RTDVMVOLTYPE_LINUX_NATIVE, + /** Volume hosts a Linux LVM. */ + RTDVMVOLTYPE_LINUX_LVM, + /** Volume hosts a Linux SoftRaid. */ + RTDVMVOLTYPE_LINUX_SOFTRAID, + /** Volume hosts a FreeBSD disklabel. */ + RTDVMVOLTYPE_FREEBSD, + /** Volume hosts a NetBSD disklabel. */ + RTDVMVOLTYPE_NETBSD, + /** Volume hosts a OpenBSD disklabel. */ + RTDVMVOLTYPE_OPENBSD, + /** Volume hosts a Mac OS X HFS or HFS+ filesystem. */ + RTDVMVOLTYPE_MAC_OSX_HFS, + /** Volume hosts a Solaris volume. */ + RTDVMVOLTYPE_SOLARIS, + /** End of the valid values. */ + RTDVMVOLTYPE_END, + /** Usual 32bit hack. */ + RTDVMVOLTYPE_32BIT_HACK = 0x7fffffff +} RTDVMVOLTYPE; + +/** @defgroup grp_dvm_flags Flags used by RTDvmCreate. + * @{ */ +/** DVM flags - Blocks are always marked as unused if the volume has + * no block status callback set. + * The default is to mark them as used. */ +#define DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED RT_BIT_32(0) +/** DVM flags - Space which is unused in the map will be marked as used + * when calling RTDvmMapQueryBlockStatus(). */ +#define DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED RT_BIT_32(1) +/** Mask of all valid flags. */ +#define DVM_FLAGS_MASK (DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED | DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED) +/** @} */ + + +/** @defgroup grp_dvm_vol_flags Volume flags used by DVMVolumeGetFlags. + * @{ */ +/** Volume flags - Volume is bootable. */ +#define DVMVOLUME_FLAGS_BOOTABLE RT_BIT_64(0) +/** Volume flags - Volume is active. */ +#define DVMVOLUME_FLAGS_ACTIVE RT_BIT_64(1) +/** @} */ + +/** A handle to a volume manager. */ +typedef struct RTDVMINTERNAL *RTDVM; +/** A pointer to a volume manager handle. */ +typedef RTDVM *PRTDVM; +/** NIL volume manager handle. */ +#define NIL_RTDVM ((RTDVM)~0) + +/** A handle to a volume in a volume map. */ +typedef struct RTDVMVOLUMEINTERNAL *RTDVMVOLUME; +/** A pointer to a volume handle. */ +typedef RTDVMVOLUME *PRTDVMVOLUME; +/** NIL volume handle. */ +#define NIL_RTDVMVOLUME ((RTDVMVOLUME)~0) + +/** + * Callback to read data from the underlying medium. + * + * @returns IPRT status code. + * @param pvUser Opaque user data passed on creation. + * @param off Offset to start reading from. + * @param pvBuf Where to store the read data. + * @param cbRead How many bytes to read. + */ +typedef DECLCALLBACK(int) FNDVMREAD(void *pvUser, uint64_t off, void *pvBuf, size_t cbRead); +/** Pointer to a read callback. */ +typedef FNDVMREAD *PFNDVMREAD; + +/** + * Callback to write data to the underlying medium. + * + * @returns IPRT status code. + * @param pvUser Opaque user data passed on creation. + * @param off Offset to start writing to. + * @param pvBuf The data to write. + * @param cbRead How many bytes to write. + */ +typedef DECLCALLBACK(int) FNDVMWRITE(void *pvUser, uint64_t off, const void *pvBuf, size_t cbWrite); +/** Pointer to a read callback. */ +typedef FNDVMWRITE *PFNDVMWRITE; + +/** + * Callback for querying the block allocation status of a volume. + * + * @returns IPRT status code. + * @param pvUser Opaque user data passed when setting the callback. + * @param off Offset relative to the start of the volume. + * @param cb Range to check in bytes. + * @param pfAllocated Where to store the allocation status on success. + */ +typedef DECLCALLBACK(int) FNDVMVOLUMEQUERYBLOCKSTATUS(void *pvUser, uint64_t off, + uint64_t cb, bool *pfAllocated); +/** Pointer to a query block allocation status callback. */ +typedef FNDVMVOLUMEQUERYBLOCKSTATUS *PFNDVMVOLUMEQUERYBLOCKSTATUS; + +/** + * Create a new volume manager. + * + * @returns IPRT status. + * @param phVolMgr Where to store the handle to the volume manager on + * success. + * @param pfnRead Read callback for the underlying + * disk/container/whatever. + * @param pfnWrite Write callback for the underlying + * disk/container/whatever. + * @param cbDisk Size of the underlying disk in bytes. + * @param cbSector Size of one sector in bytes. + * @param fFlags Combination of RTDVM_FLAGS_* + * @param pvUser Opaque user data passed to the callbacks. + */ +RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, PFNDVMREAD pfnRead, + PFNDVMWRITE pfnWrite, uint64_t cbDisk, + uint64_t cbSector, uint32_t fFlags, + void *pvUser); + +/** + * Retain a given volume manager. + * + * @returns New reference count on success, UINT32_MAX on failure. + * @param hVolMgr The volume manager to retain. + */ +RTDECL(uint32_t) RTDvmRetain(RTDVM hVolMgr); + +/** + * Releases a given volume manager. + * + * @returns New reference count on success (0 if closed), UINT32_MAX on failure. + * @param hVolMgr The volume manager to release. + */ +RTDECL(uint32_t) RTDvmRelease(RTDVM hVolMgr); + +/** + * Probes the underyling disk for the best volume manager format handler + * and opens it. + * + * @returns IPRT status code. + * @retval VERR_NOT_FOUND if no backend can handle the volume map on the disk. + * @param hVolMgr The volume manager handle. + */ +RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr); + +/** + * Initializes a new volume map using the given format handler. + * + * @returns IPRT status code. + * @param hVolMgr The volume manager handle. + * @param pszFmt The format to use for the new map. + */ +RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt); + +/** + * Gets the currently used format of the disk map. + * + * @returns Name of the format. + * @param hVolMgr The volume manager handle. + */ +RTDECL(const char *) RTDvmMapGetFormat(RTDVM hVolMgr); + +/** + * Gets the number of valid partitions in the map. + * + * @returns The number of valid volumes in the map or UINT32_MAX on failure. + * @param hVolMgr The volume manager handle. + */ +RTDECL(uint32_t) RTDvmMapGetValidVolumes(RTDVM hVolMgr); + +/** + * Gets the maximum number of partitions the map can hold. + * + * @returns The maximum number of volumes in the map or UINT32_MAX on failure. + * @param hVolMgr The volume manager handle. + */ +RTDECL(uint32_t) RTDvmMapGetMaxVolumes(RTDVM hVolMgr); + +/** + * Get the first valid volume from a map. + * + * @returns IPRT status code. + * @param hVolMgr The volume manager handle. + * @param phVol Where to store the handle to the first volume on + * success. Release with RTDvmVolumeRelease(). + */ +RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol); + +/** + * Get the first valid volume from a map. + * + * @returns IPRT status code. + * @param hVolMgr The volume manager handle. + * @param hVol Handle of the current volume. + * @param phVolNext Where to store the handle to the next volume on + * success. Release with RTDvmVolumeRelease(). + */ +RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext); + +/** + * Returns whether the given block on the disk is in use. + * + * @returns IPRT status code. + * @param hVolMgr The volume manager handler. + * @param off The start offset to check for. + * @param cb The range in bytes to check. + * @param pfAllocated Where to store the status on success. + * + * @remark This method will return true even if a part of the range is not in use. + */ +RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, + bool *pfAllocated); + +/** + * Retains a valid volume handle. + * + * @returns New reference count on success, UINT32_MAX on failure. + * @param hVol The volume to retain. + */ +RTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol); + +/** + * Releases a valid volume handle. + * + * @returns New reference count on success (0 if closed), UINT32_MAX on failure. + * @param hVol The volume to release. + */ +RTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol); + +/** + * Sets the callback to query the block allocation status for a volume. + * This overwrites any other callback set previously. + * + * @returns nothing. + * @param hVol The volume handle. + * @param pfnQueryBlockStatus The callback to set. Can be NULL to disable + * a previous callback. + * @param pvUser Opaque user data passed in the callback. + */ +RTDECL(void) RTDvmVolumeSetQueryBlockStatusCallback(RTDVMVOLUME hVol, + PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus, + void *pvUser); + +/** + * Get the size of a volume in bytes. + * + * @returns Size of the volume in bytes or 0 on failure. + * @param hVol The volume handle. + */ +RTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol); + +/** + * Gets the name of the volume if supported. + * + * @returns IPRT status code. + * @param hVol The volume handle. + * @param ppszVolName Where to store the name of the volume on success. + * The string must be freed with RTStrFree(). + */ +RTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName); + +/** + * Get the volume type of the volume if supported. + * + * @returns The volume type on success, DVMVOLTYPE_INVALID if hVol is invalid. + * @param hVol The volume handle. + */ +RTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol); + +/** + * Get the volume flags of the volume if supported. + * + * @returns The volume flags or UINT64_MAX on failure. + * @param hVol The volume handle. + */ +RTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol); + +/** + * Reads data from the given volume. + * + * @returns IPRT status code. + * @param hVol The volume handle. + * @param off Where to start reading from - 0 is the beginning of + * the volume. + * @param pvBuf Where to store the read data. + * @param cbRead How many bytes to read. + */ +RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead); + +/** + * Writes data to the given volume. + * + * @returns IPRT status code. + * @param hVol The volume handle. + * @param off Where to start writing to - 0 is the beginning of + * the volume. + * @param pvBuf The data to write. + * @param cbWrite How many bytes to write. + */ +RTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite); + +/** + * Returns the description of a given volume type. + * + * @returns The description of the type. + * @param enmVolType The volume type. + */ +RTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType); + +/** + * Creates an VFS file from a volume handle. + * + * @returns IPRT status code. + * @param hVol The volume handle. + * @param phVfsFileOut Where to store the VFS file handle on success. + */ +RTDECL(int) RTDvmVolumeCreateVfsFile(RTDVMVOLUME hVol, PRTVFSFILE phVfsFileOut); + +RT_C_DECLS_END + +/** @} */ + +#endif + diff --git a/include/iprt/env.h b/include/iprt/env.h new file mode 100644 index 00000000..64277d12 --- /dev/null +++ b/include/iprt/env.h @@ -0,0 +1,254 @@ +/** @file + * IPRT - Process Environment Strings. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_env_h +#define ___iprt_env_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_env RTEnv - Process Environment Strings + * @ingroup grp_rt + * @{ + */ + +#ifdef IN_RING3 + +/** Special handle that indicates the default process environment. */ +#define RTENV_DEFAULT ((RTENV)~(uintptr_t)0) + +/** + * Creates an empty environment block. + * + * @returns IPRT status code. Typical error is VERR_NO_MEMORY. + * + * @param pEnv Where to store the handle of the new environment block. + */ +RTDECL(int) RTEnvCreate(PRTENV pEnv); + +/** + * Creates an environment block and fill it with variables from the given + * environment array. + * + * @returns IPRT status code. + * @retval VWRN_ENV_NOT_FULLY_TRANSLATED may be returned when passing + * RTENV_DEFAULT and one or more of the environment variables have + * codeset incompatibilities. The problematic variables will be + * ignored and not included in the clone, thus the clone will have + * fewer variables. + * @retval VERR_NO_MEMORY + * @retval VERR_NO_STR_MEMORY + * @retval VERR_INVALID_HANDLE + * + * @param pEnv Where to store the handle of the new environment block. + * @param EnvToClone The environment to clone. + */ +RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone); + +/** + * Destroys an environment block. + * + * @returns IPRT status code. + * + * @param Env Environment block handle. + * Both RTENV_DEFAULT and NIL_RTENV are silently ignored. + */ +RTDECL(int) RTEnvDestroy(RTENV Env); + +/** + * Get the execve/spawnve/main envp. + * + * All returned strings are in the current process' codepage. + * This array is only valid until the next RTEnv call. + * + * @returns Pointer to the raw array of environment variables. + * @returns NULL if Env is NULL or invalid. + * + * @param Env Environment block handle. + */ +RTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env); + +/** + * Get a sorted, UTF-16 environment block for CreateProcess. + * + * @returns IPRT status code. + * + * @param hEnv Environment block handle. + * @param ppwszzBlock Where to return the environment block. This must be + * freed by calling RTEnvFreeUtf16Block. + */ +RTDECL(int) RTEnvQueryUtf16Block(RTENV hEnv, PRTUTF16 *ppwszzBlock); + +/** + * Frees an environment block returned by RTEnvGetUtf16Block(). + * + * @param pwszzBlock What RTEnvGetUtf16Block returned. NULL is ignored. + */ +RTDECL(void) RTEnvFreeUtf16Block(PRTUTF16 pwszzBlock); + +/** + * Checks if an environment variable exists in the default environment block. + * + * @returns IPRT status code. Typical error is VERR_NO_MEMORY. + * + * @param pszVar The environment variable name. + * @remark WARNING! The current implementation does not perform the appropriate + * codeset conversion. We'll figure this out when it becomes necessary. + */ +RTDECL(bool) RTEnvExist(const char *pszVar); + +/** + * Checks if an environment variable exists in a specific environment block. + * + * @returns IPRT status code. Typical error is VERR_NO_MEMORY. + * + * @param Env The environment handle. + * @param pszVar The environment variable name. + */ +RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar); + +/** + * Gets an environment variable from the default environment block. (getenv). + * + * The caller is responsible for ensuring that nobody changes the environment + * while it's using the returned string pointer! + * + * @returns Pointer to read only string on success, NULL if the variable wasn't found. + * + * @param pszVar The environment variable name. + * + * @remark WARNING! The current implementation does not perform the appropriate + * codeset conversion. We'll figure this out when it becomes necessary. + */ +RTDECL(const char *) RTEnvGet(const char *pszVar); + +/** + * Gets an environment variable in a specific environment block. + * + * @returns IPRT status code. + * @retval VERR_ENV_VAR_NOT_FOUND if the variable was not found. + * + * @param Env The environment handle. + * @param pszVar The environment variable name. + * @param pszValue Where to put the buffer. + * @param cbValue The size of the value buffer. + * @param pcchActual Returns the actual value string length. Optional. + */ +RTDECL(int) RTEnvGetEx(RTENV Env, const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual); + +/** + * Puts an variable=value string into the environment (putenv). + * + * @returns IPRT status code. Typical error is VERR_NO_MEMORY. + * + * @param pszVarEqualValue The variable '=' value string. If the value and '=' is + * omitted, the variable is removed from the environment. + * + * @remark Don't assume the value is copied. + * @remark WARNING! The current implementation does not perform the appropriate + * codeset conversion. We'll figure this out when it becomes necessary. + */ +RTDECL(int) RTEnvPut(const char *pszVarEqualValue); + +/** + * Puts a copy of the passed in 'variable=value' string into the environment block. + * + * @returns IPRT status code. Typical error is VERR_NO_MEMORY. + * + * @param Env Handle of the environment block. + * @param pszVarEqualValue The variable '=' value string. If the value and '=' is + * omitted, the variable is removed from the environment. + */ +RTDECL(int) RTEnvPutEx(RTENV Env, const char *pszVarEqualValue); + +/** + * Sets an environment variable (setenv(,,1)). + * + * @returns IPRT status code. Typical error is VERR_NO_MEMORY. + * + * @param pszVar The environment variable name. + * @param pszValue The environment variable value. + * + * @remark WARNING! The current implementation does not perform the appropriate + * codeset conversion. We'll figure this out when it becomes necessary. + */ +RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue); + +/** + * Sets an environment variable (setenv(,,1)). + * + * @returns IPRT status code. Typical error is VERR_NO_MEMORY. + * + * @param Env The environment handle. + * @param pszVar The environment variable name. + * @param pszValue The environment variable value. + */ +RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue); + +/** + * Removes an environment variable from the default environment block. + * + * @returns IPRT status code. + * @returns VINF_ENV_VAR_NOT_FOUND if the variable was not found. + * + * @param pszVar The environment variable name. + * + * @remark WARNING! The current implementation does not perform the appropriate + * codeset conversion. We'll figure this out when it becomes necessary. + */ +RTDECL(int) RTEnvUnset(const char *pszVar); + +/** + * Removes an environment variable from the specified environment block. + * + * @returns IPRT status code. + * @returns VINF_ENV_VAR_NOT_FOUND if the variable was not found. + * + * @param Env The environment handle. + * @param pszVar The environment variable name. + */ +RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar); + +/** + * Duplicates the value of a environment variable if it exists. + * + * @returns Pointer to a string containing the value, free it using RTStrFree. + * NULL if the variable was not found or we're out of memory. + * + * @param Env The environment handle. + * @param pszVar The environment variable name. + */ +RTDECL(char *) RTEnvDupEx(RTENV Env, const char *pszVar); + +#endif /* IN_RING3 */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/err.h b/include/iprt/err.h new file mode 100644 index 00000000..13b9914f --- /dev/null +++ b/include/iprt/err.h @@ -0,0 +1,1733 @@ +/** @file + * IPRT - Status Codes. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_err_h +#define ___iprt_err_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + + +/** @defgroup grp_rt_err RTErr - Status Codes + * @ingroup grp_rt + * + * The IPRT status codes are in two ranges: {0..999} and {22000..32766}. The + * IPRT users are free to use the range {1000..21999}. See RTERR_RANGE1_FIRST, + * RTERR_RANGE1_LAST, RTERR_RANGE2_FIRST, RTERR_RANGE2_LAST, RTERR_USER_FIRST + * and RTERR_USER_LAST. + * + * @{ + */ + +/** @defgroup grp_rt_err_hlp Status Code Helpers + * @ingroup grp_rt_err + * @{ + */ + +#ifdef __cplusplus +/** + * Strict type validation class. + * + * This is only really useful for type checking the arguments to RT_SUCCESS, + * RT_SUCCESS_NP, RT_FAILURE and RT_FAILURE_NP. The RTErrStrictType2 + * constructor is for integration with external status code strictness regimes. + */ +class RTErrStrictType +{ +protected: + int32_t m_rc; + +public: + /** + * Constructor for interaction with external status code strictness regimes. + * + * This is a special constructor for helping external return code validator + * classes interact cleanly with RT_SUCCESS, RT_SUCCESS_NP, RT_FAILURE and + * RT_FAILURE_NP while barring automatic cast to integer. + * + * @param rcObj IPRT status code object from an automatic cast. + */ + RTErrStrictType(RTErrStrictType2 const rcObj) + : m_rc(rcObj.getValue()) + { + } + + /** + * Integer constructor used by RT_SUCCESS_NP. + * + * @param rc IPRT style status code. + */ + RTErrStrictType(int32_t rc) + : m_rc(rc) + { + } + +#if 0 /** @todo figure where int32_t is long instead of int. */ + /** + * Integer constructor used by RT_SUCCESS_NP. + * + * @param rc IPRT style status code. + */ + RTErrStrictType(signed int rc) + : m_rc(rc) + { + } +#endif + + /** + * Test for success. + */ + bool success() const + { + return m_rc >= 0; + } + +private: + /** @name Try ban a number of wrong types. + * @{ */ + RTErrStrictType(uint8_t rc) : m_rc(-999) { NOREF(rc); } + RTErrStrictType(uint16_t rc) : m_rc(-999) { NOREF(rc); } + RTErrStrictType(uint32_t rc) : m_rc(-999) { NOREF(rc); } + RTErrStrictType(uint64_t rc) : m_rc(-999) { NOREF(rc); } + RTErrStrictType(int8_t rc) : m_rc(-999) { NOREF(rc); } + RTErrStrictType(int16_t rc) : m_rc(-999) { NOREF(rc); } + RTErrStrictType(int64_t rc) : m_rc(-999) { NOREF(rc); } + /** @todo fight long here - clashes with int32_t/int64_t on some platforms. */ + /** @} */ +}; +#endif /* __cplusplus */ + + +/** @def RTERR_STRICT_RC + * Indicates that RT_SUCCESS_NP, RT_SUCCESS, RT_FAILURE_NP and RT_FAILURE should + * make type enforcing at compile time. + * + * @remarks Only define this for C++ code. + */ +#if defined(__cplusplus) \ + && !defined(RTERR_STRICT_RC) \ + && ( defined(DOXYGEN_RUNNING) \ + || defined(DEBUG) \ + || defined(RT_STRICT) ) +# define RTERR_STRICT_RC 1 +#endif + + +/** @def RT_SUCCESS + * Check for success. We expect success in normal cases, that is the code path depending on + * this check is normally taken. To prevent any prediction use RT_SUCCESS_NP instead. + * + * @returns true if rc indicates success. + * @returns false if rc indicates failure. + * + * @param rc The iprt status code to test. + */ +#define RT_SUCCESS(rc) ( RT_LIKELY(RT_SUCCESS_NP(rc)) ) + +/** @def RT_SUCCESS_NP + * Check for success. Don't predict the result. + * + * @returns true if rc indicates success. + * @returns false if rc indicates failure. + * + * @param rc The iprt status code to test. + */ +#ifdef RTERR_STRICT_RC +# define RT_SUCCESS_NP(rc) ( RTErrStrictType(rc).success() ) +#else +# define RT_SUCCESS_NP(rc) ( (int)(rc) >= VINF_SUCCESS ) +#endif + +/** @def RT_FAILURE + * Check for failure. We don't expect in normal cases, that is the code path depending on + * this check is normally NOT taken. To prevent any prediction use RT_FAILURE_NP instead. + * + * @returns true if rc indicates failure. + * @returns false if rc indicates success. + * + * @param rc The iprt status code to test. + */ +#define RT_FAILURE(rc) ( RT_UNLIKELY(!RT_SUCCESS_NP(rc)) ) + +/** @def RT_FAILURE_NP + * Check for failure. Don't predict the result. + * + * @returns true if rc indicates failure. + * @returns false if rc indicates success. + * + * @param rc The iprt status code to test. + */ +#define RT_FAILURE_NP(rc) ( !RT_SUCCESS_NP(rc) ) + +RT_C_DECLS_BEGIN + +/** + * Converts a Darwin HRESULT error to an iprt status code. + * + * @returns iprt status code. + * @param iNativeCode HRESULT error code. + * @remark Darwin ring-3 only. + */ +RTDECL(int) RTErrConvertFromDarwinCOM(int32_t iNativeCode); + +/** + * Converts a Darwin IOReturn error to an iprt status code. + * + * @returns iprt status code. + * @param iNativeCode IOReturn error code. + * @remark Darwin only. + */ +RTDECL(int) RTErrConvertFromDarwinIO(int iNativeCode); + +/** + * Converts a Darwin kern_return_t error to an iprt status code. + * + * @returns iprt status code. + * @param iNativeCode kern_return_t error code. + * @remark Darwin only. + */ +RTDECL(int) RTErrConvertFromDarwinKern(int iNativeCode); + +/** + * Converts a Darwin error to an iprt status code. + * + * This will consult RTErrConvertFromDarwinKern, RTErrConvertFromDarwinIO + * and RTErrConvertFromDarwinCOM in this order. The latter is ring-3 only as it + * doesn't apply elsewhere. + * + * @returns iprt status code. + * @param iNativeCode Darwin error code. + * @remarks Darwin only. + * @remarks This is recommended over RTErrConvertFromDarwinKern and RTErrConvertFromDarwinIO + * since these are really just subsets of the same error space. + */ +RTDECL(int) RTErrConvertFromDarwin(int iNativeCode); + +/** + * Converts errno to iprt status code. + * + * @returns iprt status code. + * @param uNativeCode errno code. + */ +RTDECL(int) RTErrConvertFromErrno(unsigned uNativeCode); + +/** + * Converts a L4 errno to a iprt status code. + * + * @returns iprt status code. + * @param uNativeCode l4 errno. + * @remark L4 only. + */ +RTDECL(int) RTErrConvertFromL4Errno(unsigned uNativeCode); + +/** + * Converts NT status code to iprt status code. + * + * Needless to say, this is only available on NT and winXX targets. + * + * @returns iprt status code. + * @param lNativeCode NT status code. + * @remark Windows only. + */ +RTDECL(int) RTErrConvertFromNtStatus(long lNativeCode); + +/** + * Converts OS/2 error code to iprt status code. + * + * @returns iprt status code. + * @param uNativeCode OS/2 error code. + * @remark OS/2 only. + */ +RTDECL(int) RTErrConvertFromOS2(unsigned uNativeCode); + +/** + * Converts Win32 error code to iprt status code. + * + * @returns iprt status code. + * @param uNativeCode Win32 error code. + * @remark Windows only. + */ +RTDECL(int) RTErrConvertFromWin32(unsigned uNativeCode); + +/** + * Converts an iprt status code to a errno status code. + * + * @returns errno status code. + * @param iErr iprt status code. + */ +RTDECL(int) RTErrConvertToErrno(int iErr); + +#ifdef IN_RING3 + +/** + * iprt status code message. + */ +typedef struct RTSTATUSMSG +{ + /** Pointer to the short message string. */ + const char *pszMsgShort; + /** Pointer to the full message string. */ + const char *pszMsgFull; + /** Pointer to the define string. */ + const char *pszDefine; + /** Status code number. */ + int iCode; +} RTSTATUSMSG; +/** Pointer to iprt status code message. */ +typedef RTSTATUSMSG *PRTSTATUSMSG; +/** Pointer to const iprt status code message. */ +typedef const RTSTATUSMSG *PCRTSTATUSMSG; + +/** + * Get the message structure corresponding to a given iprt status code. + * + * @returns Pointer to read-only message description. + * @param rc The status code. + */ +RTDECL(PCRTSTATUSMSG) RTErrGet(int rc); + +/** + * Get the define corresponding to a given iprt status code. + * + * @returns Pointer to read-only string with the \#define identifier. + * @param rc The status code. + */ +#define RTErrGetDefine(rc) (RTErrGet(rc)->pszDefine) + +/** + * Get the short description corresponding to a given iprt status code. + * + * @returns Pointer to read-only string with the description. + * @param rc The status code. + */ +#define RTErrGetShort(rc) (RTErrGet(rc)->pszMsgShort) + +/** + * Get the full description corresponding to a given iprt status code. + * + * @returns Pointer to read-only string with the description. + * @param rc The status code. + */ +#define RTErrGetFull(rc) (RTErrGet(rc)->pszMsgFull) + +#ifdef RT_OS_WINDOWS +/** + * Windows error code message. + */ +typedef struct RTWINERRMSG +{ + /** Pointer to the full message string. */ + const char *pszMsgFull; + /** Pointer to the define string. */ + const char *pszDefine; + /** Error code number. */ + long iCode; +} RTWINERRMSG; +/** Pointer to Windows error code message. */ +typedef RTWINERRMSG *PRTWINERRMSG; +/** Pointer to const Windows error code message. */ +typedef const RTWINERRMSG *PCRTWINERRMSG; + +/** + * Get the message structure corresponding to a given Windows error code. + * + * @returns Pointer to read-only message description. + * @param rc The status code. + */ +RTDECL(PCRTWINERRMSG) RTErrWinGet(long rc); + +/** On windows COM errors are part of the Windows error database. */ +typedef RTWINERRMSG RTCOMERRMSG; + +#else /* !RT_OS_WINDOWS */ + +/** + * COM/XPCOM error code message. + */ +typedef struct RTCOMERRMSG +{ + /** Pointer to the full message string. */ + const char *pszMsgFull; + /** Pointer to the define string. */ + const char *pszDefine; + /** Error code number. */ + uint32_t iCode; +} RTCOMERRMSG; +#endif /* !RT_OS_WINDOWS */ +/** Pointer to a XPCOM/COM error code message. */ +typedef RTCOMERRMSG *PRTCOMERRMSG; +/** Pointer to const a XPCOM/COM error code message. */ +typedef const RTCOMERRMSG *PCRTCOMERRMSG; + +/** + * Get the message structure corresponding to a given COM/XPCOM error code. + * + * @returns Pointer to read-only message description. + * @param rc The status code. + */ +RTDECL(PCRTCOMERRMSG) RTErrCOMGet(uint32_t rc); + +#endif /* IN_RING3 */ + +/** @defgroup RTERRINFO_FLAGS_XXX RTERRINFO::fFlags + * @{ */ +/** Custom structure (the default). */ +#define RTERRINFO_FLAGS_T_CUSTOM UINT32_C(0) +/** Static structure (RTERRINFOSTATIC). */ +#define RTERRINFO_FLAGS_T_STATIC UINT32_C(1) +/** Allocated structure (RTErrInfoAlloc). */ +#define RTERRINFO_FLAGS_T_ALLOC UINT32_C(2) +/** Reserved type. */ +#define RTERRINFO_FLAGS_T_RESERVED UINT32_C(3) +/** Type mask. */ +#define RTERRINFO_FLAGS_T_MASK UINT32_C(3) +/** Error info is set. */ +#define RTERRINFO_FLAGS_SET RT_BIT_32(2) +/** Fixed flags (magic). */ +#define RTERRINFO_FLAGS_MAGIC UINT32_C(0xbabe0000) +/** The bit mask for the magic value. */ +#define RTERRINFO_FLAGS_MAGIC_MASK UINT32_C(0xffff0000) +/** @} */ + +/** + * Initializes an error info structure. + * + * @returns @a pErrInfo. + * @param pErrInfo The error info structure to init. + * @param pszMsg The message buffer. Must be at least one byte. + * @param cbMsg The size of the message buffer. + */ +DECLINLINE(PRTERRINFO) RTErrInfoInit(PRTERRINFO pErrInfo, char *pszMsg, size_t cbMsg) +{ + *pszMsg = '\0'; + + pErrInfo->fFlags = RTERRINFO_FLAGS_T_CUSTOM | RTERRINFO_FLAGS_MAGIC; + pErrInfo->rc = /*VINF_SUCCESS*/ 0; + pErrInfo->pszMsg = pszMsg; + pErrInfo->cbMsg = cbMsg; + pErrInfo->apvReserved[0] = NULL; + pErrInfo->apvReserved[1] = NULL; + + return pErrInfo; +} + +/** + * Initialize a static error info structure. + * + * @param pStaticErrInfo The static error info structure to init. + */ +DECLINLINE(void) RTErrInfoInitStatic(PRTERRINFOSTATIC pStaticErrInfo) +{ + RTErrInfoInit(&pStaticErrInfo->Core, pStaticErrInfo->szMsg, sizeof(pStaticErrInfo->szMsg)); + pStaticErrInfo->Core.fFlags = RTERRINFO_FLAGS_T_STATIC | RTERRINFO_FLAGS_MAGIC; +} + +/** + * Allocates a error info structure with a buffer at least the given size. + * + * @returns Pointer to an error info structure on success, NULL on failure. + * + * @param cbMsg The minimum message buffer size. Use 0 to get + * the default buffer size. + */ +RTDECL(PRTERRINFO) RTErrInfoAlloc(size_t cbMsg); + +/** + * Same as RTErrInfoAlloc, except that an IPRT status code is returned. + * + * @returns IPRT status code. + * + * @param cbMsg The minimum message buffer size. Use 0 to get + * the default buffer size. + * @param ppErrInfo Where to store the pointer to the allocated + * error info structure on success. This is + * always set to NULL. + */ +RTDECL(int) RTErrInfoAllocEx(size_t cbMsg, PRTERRINFO *ppErrInfo); + +/** + * Frees an error info structure allocated by RTErrInfoAlloc or + * RTErrInfoAllocEx. + * + * @param pErrInfo The error info structure. + */ +RTDECL(void) RTErrInfoFree(PRTERRINFO pErrInfo); + +/** + * Fills in the error info details. + * + * @returns @a rc. + * + * @param pErrInfo The error info structure to fill in. + * @param rc The status code to return. + * @param pszMsg The error message string. + */ +RTDECL(int) RTErrInfoSet(PRTERRINFO pErrInfo, int rc, const char *pszMsg); + +/** + * Fills in the error info details, with a sprintf style message. + * + * @returns @a rc. + * + * @param pErrInfo The error info structure to fill in. + * @param rc The status code to return. + * @param pszFormat The format string. + * @param ... The format arguments. + */ +RTDECL(int) RTErrInfoSetF(PRTERRINFO pErrInfo, int rc, const char *pszFormat, ...); + +/** + * Fills in the error info details, with a vsprintf style message. + * + * @returns @a rc. + * + * @param pErrInfo The error info structure to fill in. + * @param rc The status code to return. + * @param pszFormat The format string. + * @param va The format arguments. + */ +RTDECL(int) RTErrInfoSetV(PRTERRINFO pErrInfo, int rc, const char *pszFormat, va_list va); + +/** + * Checks if the error info is set. + * + * @returns true if set, false if not. + * @param pErrInfo The error info structure. NULL is OK. + */ +DECLINLINE(bool) RTErrInfoIsSet(PCRTERRINFO pErrInfo) +{ + if (!pErrInfo) + return false; + return (pErrInfo->fFlags & (RTERRINFO_FLAGS_MAGIC_MASK | RTERRINFO_FLAGS_SET)) + == (RTERRINFO_FLAGS_MAGIC | RTERRINFO_FLAGS_SET); +} + +/** + * Clears the error info structure. + * + * @param pErrInfo The error info structure. NULL is OK. + */ +DECLINLINE(void) RTErrInfoClear(PRTERRINFO pErrInfo) +{ + if (pErrInfo) + { + pErrInfo->fFlags &= ~RTERRINFO_FLAGS_SET; + pErrInfo->rc = /*VINF_SUCCESS*/0; + *pErrInfo->pszMsg = '\0'; + } +} + +/** + * Storage for error variables. + * + * @remarks Do NOT touch the members! They are platform specific and what's + * where may change at any time! + */ +typedef union RTERRVARS +{ + int8_t ai8Vars[32]; + int16_t ai16Vars[16]; + int32_t ai32Vars[8]; + int64_t ai64Vars[4]; +} RTERRVARS; +/** Pointer to an error variable storage union. */ +typedef RTERRVARS *PRTERRVARS; +/** Pointer to a const error variable storage union. */ +typedef RTERRVARS const *PCRTERRVARS; + +/** + * Saves the error variables. + * + * @returns @a pVars. + * @param pVars The variable storage union. + */ +RTDECL(PRTERRVARS) RTErrVarsSave(PRTERRVARS pVars); + +/** + * Restores the error variables. + * + * @param pVars The variable storage union. + */ +RTDECL(void) RTErrVarsRestore(PCRTERRVARS pVars); + +/** + * Checks if the first variable set equals the second. + * + * @returns true if they are equal, false if not. + * @param pVars1 The first variable storage union. + * @param pVars2 The second variable storage union. + */ +RTDECL(bool) RTErrVarsAreEqual(PCRTERRVARS pVars1, PCRTERRVARS pVars2); + +/** + * Checks if the (live) error variables have changed since we saved them. + * + * @returns @c true if they have changed, @c false if not. + * @param pVars The saved variables to compare the current state + * against. + */ +RTDECL(bool) RTErrVarsHaveChanged(PCRTERRVARS pVars); + +RT_C_DECLS_END + +/** @} */ + +/** @name Status Code Ranges + * @{ */ +/** The first status code in the primary IPRT range. */ +#define RTERR_RANGE1_FIRST 0 +/** The last status code in the primary IPRT range. */ +#define RTERR_RANGE1_LAST 999 + +/** The first status code in the secondary IPRT range. */ +#define RTERR_RANGE2_FIRST 22000 +/** The last status code in the secondary IPRT range. */ +#define RTERR_RANGE2_LAST 32766 + +/** The first status code in the user range. */ +#define RTERR_USER_FIRST 1000 +/** The last status code in the user range. */ +#define RTERR_USER_LAST 21999 +/** @} */ + + +/* SED-START */ + +/** @name Misc. Status Codes + * @{ + */ +/** Success. */ +#define VINF_SUCCESS 0 + +/** General failure - DON'T USE THIS!!! */ +#define VERR_GENERAL_FAILURE (-1) +/** Invalid parameter. */ +#define VERR_INVALID_PARAMETER (-2) +/** Invalid parameter. */ +#define VWRN_INVALID_PARAMETER 2 +/** Invalid magic or cookie. */ +#define VERR_INVALID_MAGIC (-3) +/** Invalid magic or cookie. */ +#define VWRN_INVALID_MAGIC 3 +/** Invalid loader handle. */ +#define VERR_INVALID_HANDLE (-4) +/** Invalid loader handle. */ +#define VWRN_INVALID_HANDLE 4 +/** Failed to lock the address range. */ +#define VERR_LOCK_FAILED (-5) +/** Invalid memory pointer. */ +#define VERR_INVALID_POINTER (-6) +/** Failed to patch the IDT. */ +#define VERR_IDT_FAILED (-7) +/** Memory allocation failed. */ +#define VERR_NO_MEMORY (-8) +/** Already loaded. */ +#define VERR_ALREADY_LOADED (-9) +/** Permission denied. */ +#define VERR_PERMISSION_DENIED (-10) +/** Permission denied. */ +#define VINF_PERMISSION_DENIED 10 +/** Version mismatch. */ +#define VERR_VERSION_MISMATCH (-11) +/** The request function is not implemented. */ +#define VERR_NOT_IMPLEMENTED (-12) + +/** Not equal. */ +#define VERR_NOT_EQUAL (-18) +/** The specified path does not point at a symbolic link. */ +#define VERR_NOT_SYMLINK (-19) +/** Failed to allocate temporary memory. */ +#define VERR_NO_TMP_MEMORY (-20) +/** Invalid file mode mask (RTFMODE). */ +#define VERR_INVALID_FMODE (-21) +/** Incorrect call order. */ +#define VERR_WRONG_ORDER (-22) +/** There is no TLS (thread local storage) available for storing the current thread. */ +#define VERR_NO_TLS_FOR_SELF (-23) +/** Failed to set the TLS (thread local storage) entry which points to our thread structure. */ +#define VERR_FAILED_TO_SET_SELF_TLS (-24) +/** Not able to allocate contiguous memory. */ +#define VERR_NO_CONT_MEMORY (-26) +/** No memory available for page table or page directory. */ +#define VERR_NO_PAGE_MEMORY (-27) +/** Already initialized. */ +#define VINF_ALREADY_INITIALIZED 28 +/** The specified thread is dead. */ +#define VERR_THREAD_IS_DEAD (-29) +/** The specified thread is not waitable. */ +#define VERR_THREAD_NOT_WAITABLE (-30) +/** Pagetable not present. */ +#define VERR_PAGE_TABLE_NOT_PRESENT (-31) +/** Invalid context. + * Typically an API was used by the wrong thread. */ +#define VERR_INVALID_CONTEXT (-32) +/** The per process timer is busy. */ +#define VERR_TIMER_BUSY (-33) +/** Address conflict. */ +#define VERR_ADDRESS_CONFLICT (-34) +/** Unresolved (unknown) host platform error. */ +#define VERR_UNRESOLVED_ERROR (-35) +/** Invalid function. */ +#define VERR_INVALID_FUNCTION (-36) +/** Not supported. */ +#define VERR_NOT_SUPPORTED (-37) +/** Not supported. */ +#define VINF_NOT_SUPPORTED 37 +/** Access denied. */ +#define VERR_ACCESS_DENIED (-38) +/** Call interrupted. */ +#define VERR_INTERRUPTED (-39) +/** Call interrupted. */ +#define VINF_INTERRUPTED 39 +/** Timeout. */ +#define VERR_TIMEOUT (-40) +/** Timeout. */ +#define VINF_TIMEOUT 40 +/** Buffer too small to save result. */ +#define VERR_BUFFER_OVERFLOW (-41) +/** Buffer too small to save result. */ +#define VINF_BUFFER_OVERFLOW 41 +/** Data size overflow. */ +#define VERR_TOO_MUCH_DATA (-42) +/** Max threads number reached. */ +#define VERR_MAX_THRDS_REACHED (-43) +/** Max process number reached. */ +#define VERR_MAX_PROCS_REACHED (-44) +/** The recipient process has refused the signal. */ +#define VERR_SIGNAL_REFUSED (-45) +/** A signal is already pending. */ +#define VERR_SIGNAL_PENDING (-46) +/** The signal being posted is not correct. */ +#define VERR_SIGNAL_INVALID (-47) +/** The state changed. + * This is a generic error message and needs a context to make sense. */ +#define VERR_STATE_CHANGED (-48) +/** Warning, the state changed. + * This is a generic error message and needs a context to make sense. */ +#define VWRN_STATE_CHANGED 48 +/** Error while parsing UUID string */ +#define VERR_INVALID_UUID_FORMAT (-49) +/** The specified process was not found. */ +#define VERR_PROCESS_NOT_FOUND (-50) +/** The process specified to a non-block wait had not exited. */ +#define VERR_PROCESS_RUNNING (-51) +/** Retry the operation. */ +#define VERR_TRY_AGAIN (-52) +/** Retry the operation. */ +#define VINF_TRY_AGAIN 52 +/** Generic parse error. */ +#define VERR_PARSE_ERROR (-53) +/** Value out of range. */ +#define VERR_OUT_OF_RANGE (-54) +/** A numeric conversion encountered a value which was too big for the target. */ +#define VERR_NUMBER_TOO_BIG (-55) +/** A numeric conversion encountered a value which was too big for the target. */ +#define VWRN_NUMBER_TOO_BIG 55 +/** The number begin converted (string) contained no digits. */ +#define VERR_NO_DIGITS (-56) +/** The number begin converted (string) contained no digits. */ +#define VWRN_NO_DIGITS 56 +/** Encountered a '-' during conversion to an unsigned value. */ +#define VERR_NEGATIVE_UNSIGNED (-57) +/** Encountered a '-' during conversion to an unsigned value. */ +#define VWRN_NEGATIVE_UNSIGNED 57 +/** Error while characters translation (unicode and so). */ +#define VERR_NO_TRANSLATION (-58) +/** Error while characters translation (unicode and so). */ +#define VWRN_NO_TRANSLATION 58 +/** Encountered unicode code point which is reserved for use as endian indicator (0xffff or 0xfffe). */ +#define VERR_CODE_POINT_ENDIAN_INDICATOR (-59) +/** Encountered unicode code point in the surrogate range (0xd800 to 0xdfff). */ +#define VERR_CODE_POINT_SURROGATE (-60) +/** A string claiming to be UTF-8 is incorrectly encoded. */ +#define VERR_INVALID_UTF8_ENCODING (-61) +/** Ad string claiming to be in UTF-16 is incorrectly encoded. */ +#define VERR_INVALID_UTF16_ENCODING (-62) +/** Encountered a unicode code point which cannot be represented as UTF-16. */ +#define VERR_CANT_RECODE_AS_UTF16 (-63) +/** Got an out of memory condition trying to allocate a string. */ +#define VERR_NO_STR_MEMORY (-64) +/** Got an out of memory condition trying to allocate a UTF-16 (/UCS-2) string. */ +#define VERR_NO_UTF16_MEMORY (-65) +/** Get an out of memory condition trying to allocate a code point array. */ +#define VERR_NO_CODE_POINT_MEMORY (-66) +/** Can't free the memory because it's used in mapping. */ +#define VERR_MEMORY_BUSY (-67) +/** The timer can't be started because it's already active. */ +#define VERR_TIMER_ACTIVE (-68) +/** The timer can't be stopped because i's already suspended. */ +#define VERR_TIMER_SUSPENDED (-69) +/** The operation was cancelled by the user (copy) or another thread (local ipc). */ +#define VERR_CANCELLED (-70) +/** Failed to initialize a memory object. + * Exactly what this means is OS specific. */ +#define VERR_MEMOBJ_INIT_FAILED (-71) +/** Out of memory condition when allocating memory with low physical backing. */ +#define VERR_NO_LOW_MEMORY (-72) +/** Out of memory condition when allocating physical memory (without mapping). */ +#define VERR_NO_PHYS_MEMORY (-73) +/** The address (virtual or physical) is too big. */ +#define VERR_ADDRESS_TOO_BIG (-74) +/** Failed to map a memory object. */ +#define VERR_MAP_FAILED (-75) +/** Trailing characters. */ +#define VERR_TRAILING_CHARS (-76) +/** Trailing characters. */ +#define VWRN_TRAILING_CHARS 76 +/** Trailing spaces. */ +#define VERR_TRAILING_SPACES (-77) +/** Trailing spaces. */ +#define VWRN_TRAILING_SPACES 77 +/** Generic not found error. */ +#define VERR_NOT_FOUND (-78) +/** Generic not found warning. */ +#define VWRN_NOT_FOUND 78 +/** Generic invalid state error. */ +#define VERR_INVALID_STATE (-79) +/** Generic invalid state warning. */ +#define VWRN_INVALID_STATE 79 +/** Generic out of resources error. */ +#define VERR_OUT_OF_RESOURCES (-80) +/** Generic out of resources warning. */ +#define VWRN_OUT_OF_RESOURCES 80 +/** No more handles available, too many open handles. */ +#define VERR_NO_MORE_HANDLES (-81) +/** Preemption is disabled. + * The requested operation can only be performed when preemption is enabled. */ +#define VERR_PREEMPT_DISABLED (-82) +/** End of string. */ +#define VERR_END_OF_STRING (-83) +/** End of string. */ +#define VINF_END_OF_STRING 83 +/** A page count is out of range. */ +#define VERR_PAGE_COUNT_OUT_OF_RANGE (-84) +/** Generic object destroyed status. */ +#define VERR_OBJECT_DESTROYED (-85) +/** Generic object was destroyed by the call status. */ +#define VINF_OBJECT_DESTROYED 85 +/** Generic dangling objects status. */ +#define VERR_DANGLING_OBJECTS (-86) +/** Generic dangling objects status. */ +#define VWRN_DANGLING_OBJECTS 86 +/** Invalid Base64 encoding. */ +#define VERR_INVALID_BASE64_ENCODING (-87) +/** Return instigated by a callback or similar. */ +#define VERR_CALLBACK_RETURN (-88) +/** Return instigated by a callback or similar. */ +#define VINF_CALLBACK_RETURN 88 +/** Authentication failure. */ +#define VERR_AUTHENTICATION_FAILURE (-89) +/** Not a power of two. */ +#define VERR_NOT_POWER_OF_TWO (-90) +/** Status code, typically given as a parameter, that isn't supposed to be used. */ +#define VERR_IGNORED (-91) +/** Concurrent access to the object is not allowed. */ +#define VERR_CONCURRENT_ACCESS (-92) +/** The caller does not have a reference to the object. + * This status is used when two threads is caught sharing the same object + * reference. */ +#define VERR_CALLER_NO_REFERENCE (-93) +/** Generic no change error. */ +#define VERR_NO_CHANGE (-95) +/** Generic no change info. */ +#define VINF_NO_CHANGE 95 +/** Out of memory condition when allocating executable memory. */ +#define VERR_NO_EXEC_MEMORY (-96) +/** The alignment is not supported. */ +#define VERR_UNSUPPORTED_ALIGNMENT (-97) +/** The alignment is not really supported, however we got lucky with this + * allocation. */ +#define VINF_UNSUPPORTED_ALIGNMENT 97 +/** Duplicate something. */ +#define VERR_DUPLICATE (-98) +/** Something is missing. */ +#define VERR_MISSING (-99) +/** An unexpected (/unknown) exception was caught. */ +#define VERR_UNEXPECTED_EXCEPTION (-22400) +/** Buffer underflow. */ +#define VERR_BUFFER_UNDERFLOW (-22401) +/** Buffer underflow. */ +#define VINF_BUFFER_UNDERFLOW 22401 +/** Uneven input. */ +#define VERR_UNEVEN_INPUT (-22402) +/** Something is not available or not working properly. */ +#define VERR_NOT_AVAILABLE (-22403) +/** @} */ + + +/** @name Common File/Disk/Pipe/etc Status Codes + * @{ + */ +/** Unresolved (unknown) file i/o error. */ +#define VERR_FILE_IO_ERROR (-100) +/** File/Device open failed. */ +#define VERR_OPEN_FAILED (-101) +/** File not found. */ +#define VERR_FILE_NOT_FOUND (-102) +/** Path not found. */ +#define VERR_PATH_NOT_FOUND (-103) +/** Invalid (malformed) file/path name. */ +#define VERR_INVALID_NAME (-104) +/** The object in question already exists. */ +#define VERR_ALREADY_EXISTS (-105) +/** The object in question already exists. */ +#define VWRN_ALREADY_EXISTS 105 +/** Too many open files. */ +#define VERR_TOO_MANY_OPEN_FILES (-106) +/** Seek error. */ +#define VERR_SEEK (-107) +/** Seek below file start. */ +#define VERR_NEGATIVE_SEEK (-108) +/** Trying to seek on device. */ +#define VERR_SEEK_ON_DEVICE (-109) +/** Reached the end of the file. */ +#define VERR_EOF (-110) +/** Reached the end of the file. */ +#define VINF_EOF 110 +/** Generic file read error. */ +#define VERR_READ_ERROR (-111) +/** Generic file write error. */ +#define VERR_WRITE_ERROR (-112) +/** Write protect error. */ +#define VERR_WRITE_PROTECT (-113) +/** Sharing violation, file is being used by another process. */ +#define VERR_SHARING_VIOLATION (-114) +/** Unable to lock a region of a file. */ +#define VERR_FILE_LOCK_FAILED (-115) +/** File access error, another process has locked a portion of the file. */ +#define VERR_FILE_LOCK_VIOLATION (-116) +/** File or directory can't be created. */ +#define VERR_CANT_CREATE (-117) +/** Directory can't be deleted. */ +#define VERR_CANT_DELETE_DIRECTORY (-118) +/** Can't move file to another disk. */ +#define VERR_NOT_SAME_DEVICE (-119) +/** The filename or extension is too long. */ +#define VERR_FILENAME_TOO_LONG (-120) +/** Media not present in drive. */ +#define VERR_MEDIA_NOT_PRESENT (-121) +/** The type of media was not recognized. Not formatted? */ +#define VERR_MEDIA_NOT_RECOGNIZED (-122) +/** Can't unlock - region was not locked. */ +#define VERR_FILE_NOT_LOCKED (-123) +/** Unrecoverable error: lock was lost. */ +#define VERR_FILE_LOCK_LOST (-124) +/** Can't delete directory with files. */ +#define VERR_DIR_NOT_EMPTY (-125) +/** A directory operation was attempted on a non-directory object. */ +#define VERR_NOT_A_DIRECTORY (-126) +/** A non-directory operation was attempted on a directory object. */ +#define VERR_IS_A_DIRECTORY (-127) +/** Tried to grow a file beyond the limit imposed by the process or the filesystem. */ +#define VERR_FILE_TOO_BIG (-128) +/** No pending request the aio context has to wait for completion. */ +#define VERR_FILE_AIO_NO_REQUEST (-129) +/** The request could not be canceled or prepared for another transfer + * because it is still in progress. */ +#define VERR_FILE_AIO_IN_PROGRESS (-130) +/** The request could not be canceled because it already completed. */ +#define VERR_FILE_AIO_COMPLETED (-131) +/** The I/O context couldn't be destroyed because there are still pending requests. */ +#define VERR_FILE_AIO_BUSY (-132) +/** The requests couldn't be submitted because that would exceed the capacity of the context. */ +#define VERR_FILE_AIO_LIMIT_EXCEEDED (-133) +/** The request was canceled. */ +#define VERR_FILE_AIO_CANCELED (-134) +/** The request wasn't submitted so it can't be canceled. */ +#define VERR_FILE_AIO_NOT_SUBMITTED (-135) +/** A request was not prepared and thus could not be submitted. */ +#define VERR_FILE_AIO_NOT_PREPARED (-136) +/** Not all requests could be submitted due to resource shortage. */ +#define VERR_FILE_AIO_INSUFFICIENT_RESSOURCES (-137) +/** Device or resource is busy. */ +#define VERR_RESOURCE_BUSY (-138) +/** A file operation was attempted on a non-file object. */ +#define VERR_NOT_A_FILE (-139) +/** A non-file operation was attempted on a file object. */ +#define VERR_IS_A_FILE (-140) +/** Unexpected filesystem object type. */ +#define VERR_UNEXPECTED_FS_OBJ_TYPE (-141) +/** A path does not start with a root specification. */ +#define VERR_PATH_DOES_NOT_START_WITH_ROOT (-142) +/** A path is relative, expected an absolute path. */ +#define VERR_PATH_IS_RELATIVE (-143) +/** A path is not relative (start with root), expected an relative path. */ +#define VERR_PATH_IS_NOT_RELATIVE (-144) +/** @} */ + + +/** @name Generic Filesystem I/O Status Codes + * @{ + */ +/** Unresolved (unknown) disk i/o error. */ +#define VERR_DISK_IO_ERROR (-150) +/** Invalid drive number. */ +#define VERR_INVALID_DRIVE (-151) +/** Disk is full. */ +#define VERR_DISK_FULL (-152) +/** Disk was changed. */ +#define VERR_DISK_CHANGE (-153) +/** Drive is locked. */ +#define VERR_DRIVE_LOCKED (-154) +/** The specified disk or diskette cannot be accessed. */ +#define VERR_DISK_INVALID_FORMAT (-155) +/** Too many symbolic links. */ +#define VERR_TOO_MANY_SYMLINKS (-156) +/** The OS does not support setting the time stamps on a symbolic link. */ +#define VERR_NS_SYMLINK_SET_TIME (-157) +/** The OS does not support changing the owner of a symbolic link. */ +#define VERR_NS_SYMLINK_CHANGE_OWNER (-158) +/** @} */ + + +/** @name Generic Directory Enumeration Status Codes + * @{ + */ +/** Unresolved (unknown) search error. */ +#define VERR_SEARCH_ERROR (-200) +/** No more files found. */ +#define VERR_NO_MORE_FILES (-201) +/** No more search handles available. */ +#define VERR_NO_MORE_SEARCH_HANDLES (-202) +/** RTDirReadEx() failed to retrieve the extra data which was requested. */ +#define VWRN_NO_DIRENT_INFO 203 +/** @} */ + + +/** @name Internal Processing Errors + * @{ + */ +/** Internal error - this should never happen. */ +#define VERR_INTERNAL_ERROR (-225) +/** Internal error no. 2. */ +#define VERR_INTERNAL_ERROR_2 (-226) +/** Internal error no. 3. */ +#define VERR_INTERNAL_ERROR_3 (-227) +/** Internal error no. 4. */ +#define VERR_INTERNAL_ERROR_4 (-228) +/** Internal error no. 5. */ +#define VERR_INTERNAL_ERROR_5 (-229) +/** Internal error: Unexpected status code. */ +#define VERR_IPE_UNEXPECTED_STATUS (-230) +/** Internal error: Unexpected status code. */ +#define VERR_IPE_UNEXPECTED_INFO_STATUS (-231) +/** Internal error: Unexpected status code. */ +#define VERR_IPE_UNEXPECTED_ERROR_STATUS (-232) +/** Internal error: Uninitialized status code. + * @remarks This is used by value elsewhere. */ +#define VERR_IPE_UNINITIALIZED_STATUS (-233) +/** Internal error: Supposedly unreachable default case in a switch. */ +#define VERR_IPE_NOT_REACHED_DEFAULT_CASE (-234) +/** @} */ + + +/** @name Generic Device I/O Status Codes + * @{ + */ +/** Unresolved (unknown) device i/o error. */ +#define VERR_DEV_IO_ERROR (-250) +/** Device i/o: Bad unit. */ +#define VERR_IO_BAD_UNIT (-251) +/** Device i/o: Not ready. */ +#define VERR_IO_NOT_READY (-252) +/** Device i/o: Bad command. */ +#define VERR_IO_BAD_COMMAND (-253) +/** Device i/o: CRC error. */ +#define VERR_IO_CRC (-254) +/** Device i/o: Bad length. */ +#define VERR_IO_BAD_LENGTH (-255) +/** Device i/o: Sector not found. */ +#define VERR_IO_SECTOR_NOT_FOUND (-256) +/** Device i/o: General failure. */ +#define VERR_IO_GEN_FAILURE (-257) +/** @} */ + + +/** @name Generic Pipe I/O Status Codes + * @{ + */ +/** Unresolved (unknown) pipe i/o error. */ +#define VERR_PIPE_IO_ERROR (-300) +/** Broken pipe. */ +#define VERR_BROKEN_PIPE (-301) +/** Bad pipe. */ +#define VERR_BAD_PIPE (-302) +/** Pipe is busy. */ +#define VERR_PIPE_BUSY (-303) +/** No data in pipe. */ +#define VERR_NO_DATA (-304) +/** Pipe is not connected. */ +#define VERR_PIPE_NOT_CONNECTED (-305) +/** More data available in pipe. */ +#define VERR_MORE_DATA (-306) +/** Expected read pipe, got a write pipe instead. */ +#define VERR_PIPE_NOT_READ (-307) +/** Expected write pipe, got a read pipe instead. */ +#define VERR_PIPE_NOT_WRITE (-308) +/** @} */ + + +/** @name Generic Semaphores Status Codes + * @{ + */ +/** Unresolved (unknown) semaphore error. */ +#define VERR_SEM_ERROR (-350) +/** Too many semaphores. */ +#define VERR_TOO_MANY_SEMAPHORES (-351) +/** Exclusive semaphore is owned by another process. */ +#define VERR_EXCL_SEM_ALREADY_OWNED (-352) +/** The semaphore is set and cannot be closed. */ +#define VERR_SEM_IS_SET (-353) +/** The semaphore cannot be set again. */ +#define VERR_TOO_MANY_SEM_REQUESTS (-354) +/** Attempt to release mutex not owned by caller. */ +#define VERR_NOT_OWNER (-355) +/** The semaphore has been opened too many times. */ +#define VERR_TOO_MANY_OPENS (-356) +/** The maximum posts for the event semaphore has been reached. */ +#define VERR_TOO_MANY_POSTS (-357) +/** The event semaphore has already been posted. */ +#define VERR_ALREADY_POSTED (-358) +/** The event semaphore has already been reset. */ +#define VERR_ALREADY_RESET (-359) +/** The semaphore is in use. */ +#define VERR_SEM_BUSY (-360) +/** The previous ownership of this semaphore has ended. */ +#define VERR_SEM_OWNER_DIED (-361) +/** Failed to open semaphore by name - not found. */ +#define VERR_SEM_NOT_FOUND (-362) +/** Semaphore destroyed while waiting. */ +#define VERR_SEM_DESTROYED (-363) +/** Nested ownership requests are not permitted for this semaphore type. */ +#define VERR_SEM_NESTED (-364) +/** The release call only release a semaphore nesting, i.e. the caller is still + * holding the semaphore. */ +#define VINF_SEM_NESTED (364) +/** Deadlock detected. */ +#define VERR_DEADLOCK (-365) +/** Ping-Pong listen or speak out of turn error. */ +#define VERR_SEM_OUT_OF_TURN (-366) +/** Tried to take a semaphore in a bad context. */ +#define VERR_SEM_BAD_CONTEXT (-367) +/** Don't spin for the semaphore, but it is safe to try grab it. */ +#define VINF_SEM_BAD_CONTEXT (367) +/** Wrong locking order detected. */ +#define VERR_SEM_LV_WRONG_ORDER (-368) +/** Wrong release order detected. */ +#define VERR_SEM_LV_WRONG_RELEASE_ORDER (-369) +/** Attempt to recursively enter a non-recurisve lock. */ +#define VERR_SEM_LV_NESTED (-370) +/** Invalid parameters passed to the lock validator. */ +#define VERR_SEM_LV_INVALID_PARAMETER (-371) +/** The lock validator detected a deadlock. */ +#define VERR_SEM_LV_DEADLOCK (-372) +/** The lock validator detected an existing deadlock. + * The deadlock was not caused by the current operation, but existed already. */ +#define VERR_SEM_LV_EXISTING_DEADLOCK (-373) +/** Not the lock owner according our records. */ +#define VERR_SEM_LV_NOT_OWNER (-374) +/** An illegal lock upgrade was attempted. */ +#define VERR_SEM_LV_ILLEGAL_UPGRADE (-375) +/** The thread is not a valid signaller of the event. */ +#define VERR_SEM_LV_NOT_SIGNALLER (-376) +/** Internal error in the lock validator or related components. */ +#define VERR_SEM_LV_INTERNAL_ERROR (-377) +/** @} */ + + +/** @name Generic Network I/O Status Codes + * @{ + */ +/** Unresolved (unknown) network error. */ +#define VERR_NET_IO_ERROR (-400) +/** The network is busy or is out of resources. */ +#define VERR_NET_OUT_OF_RESOURCES (-401) +/** Net host name not found. */ +#define VERR_NET_HOST_NOT_FOUND (-402) +/** Network path not found. */ +#define VERR_NET_PATH_NOT_FOUND (-403) +/** General network printing error. */ +#define VERR_NET_PRINT_ERROR (-404) +/** The machine is not on the network. */ +#define VERR_NET_NO_NETWORK (-405) +/** Name is not unique on the network. */ +#define VERR_NET_NOT_UNIQUE_NAME (-406) + +/* These are BSD networking error codes - numbers correspond, don't mess! */ +/** Operation in progress. */ +#define VERR_NET_IN_PROGRESS (-436) +/** Operation already in progress. */ +#define VERR_NET_ALREADY_IN_PROGRESS (-437) +/** Attempted socket operation with a non-socket handle. + * (This includes closed handles.) */ +#define VERR_NET_NOT_SOCKET (-438) +/** Destination address required. */ +#define VERR_NET_DEST_ADDRESS_REQUIRED (-439) +/** Message too long. */ +#define VERR_NET_MSG_SIZE (-440) +/** Protocol wrong type for socket. */ +#define VERR_NET_PROTOCOL_TYPE (-441) +/** Protocol not available. */ +#define VERR_NET_PROTOCOL_NOT_AVAILABLE (-442) +/** Protocol not supported. */ +#define VERR_NET_PROTOCOL_NOT_SUPPORTED (-443) +/** Socket type not supported. */ +#define VERR_NET_SOCKET_TYPE_NOT_SUPPORTED (-444) +/** Operation not supported. */ +#define VERR_NET_OPERATION_NOT_SUPPORTED (-445) +/** Protocol family not supported. */ +#define VERR_NET_PROTOCOL_FAMILY_NOT_SUPPORTED (-446) +/** Address family not supported by protocol family. */ +#define VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED (-447) +/** Address already in use. */ +#define VERR_NET_ADDRESS_IN_USE (-448) +/** Can't assign requested address. */ +#define VERR_NET_ADDRESS_NOT_AVAILABLE (-449) +/** Network is down. */ +#define VERR_NET_DOWN (-450) +/** Network is unreachable. */ +#define VERR_NET_UNREACHABLE (-451) +/** Network dropped connection on reset. */ +#define VERR_NET_CONNECTION_RESET (-452) +/** Software caused connection abort. */ +#define VERR_NET_CONNECTION_ABORTED (-453) +/** Connection reset by peer. */ +#define VERR_NET_CONNECTION_RESET_BY_PEER (-454) +/** No buffer space available. */ +#define VERR_NET_NO_BUFFER_SPACE (-455) +/** Socket is already connected. */ +#define VERR_NET_ALREADY_CONNECTED (-456) +/** Socket is not connected. */ +#define VERR_NET_NOT_CONNECTED (-457) +/** Can't send after socket shutdown. */ +#define VERR_NET_SHUTDOWN (-458) +/** Too many references: can't splice. */ +#define VERR_NET_TOO_MANY_REFERENCES (-459) +/** Too many references: can't splice. */ +#define VERR_NET_CONNECTION_TIMED_OUT (-460) +/** Connection refused. */ +#define VERR_NET_CONNECTION_REFUSED (-461) +/* ELOOP is not net. */ +/* ENAMETOOLONG is not net. */ +/** Host is down. */ +#define VERR_NET_HOST_DOWN (-464) +/** No route to host. */ +#define VERR_NET_HOST_UNREACHABLE (-465) +/** Protocol error. */ +#define VERR_NET_PROTOCOL_ERROR (-466) +/** Incomplete packet was submitted by guest. */ +#define VERR_NET_INCOMPLETE_TX_PACKET (-467) +/** @} */ + + +/** @name TCP Status Codes + * @{ + */ +/** Stop the TCP server. */ +#define VERR_TCP_SERVER_STOP (-500) +/** The server was stopped. */ +#define VINF_TCP_SERVER_STOP 500 +/** The TCP server was shut down using RTTcpServerShutdown. */ +#define VERR_TCP_SERVER_SHUTDOWN (-501) +/** The TCP server was destroyed. */ +#define VERR_TCP_SERVER_DESTROYED (-502) +/** The TCP server has no client associated with it. */ +#define VINF_TCP_SERVER_NO_CLIENT 503 +/** @} */ + + +/** @name UDP Status Codes + * @{ + */ +/** Stop the UDP server. */ +#define VERR_UDP_SERVER_STOP (-520) +/** The server was stopped. */ +#define VINF_UDP_SERVER_STOP 520 +/** The UDP server was shut down using RTUdpServerShutdown. */ +#define VERR_UDP_SERVER_SHUTDOWN (-521) +/** The UDP server was destroyed. */ +#define VERR_UDP_SERVER_DESTROYED (-522) +/** The UDP server has no client associated with it. */ +#define VINF_UDP_SERVER_NO_CLIENT 523 +/** @} */ + + +/** @name L4 Specific Status Codes + * @{ + */ +/** Invalid offset in an L4 dataspace */ +#define VERR_L4_INVALID_DS_OFFSET (-550) +/** IPC error */ +#define VERR_IPC (-551) +/** Item already used */ +#define VERR_RESOURCE_IN_USE (-552) +/** Source/destination not found */ +#define VERR_IPC_PROCESS_NOT_FOUND (-553) +/** Receive timeout */ +#define VERR_IPC_RECEIVE_TIMEOUT (-554) +/** Send timeout */ +#define VERR_IPC_SEND_TIMEOUT (-555) +/** Receive cancelled */ +#define VERR_IPC_RECEIVE_CANCELLED (-556) +/** Send cancelled */ +#define VERR_IPC_SEND_CANCELLED (-557) +/** Receive aborted */ +#define VERR_IPC_RECEIVE_ABORTED (-558) +/** Send aborted */ +#define VERR_IPC_SEND_ABORTED (-559) +/** Couldn't map pages during receive */ +#define VERR_IPC_RECEIVE_MAP_FAILED (-560) +/** Couldn't map pages during send */ +#define VERR_IPC_SEND_MAP_FAILED (-561) +/** Send pagefault timeout in receive */ +#define VERR_IPC_RECEIVE_SEND_PF_TIMEOUT (-562) +/** Send pagefault timeout in send */ +#define VERR_IPC_SEND_SEND_PF_TIMEOUT (-563) +/** (One) receive buffer was too small, or too few buffers */ +#define VINF_IPC_RECEIVE_MSG_CUT 564 +/** (One) send buffer was too small, or too few buffers */ +#define VINF_IPC_SEND_MSG_CUT 565 +/** Dataspace manager server not found */ +#define VERR_L4_DS_MANAGER_NOT_FOUND (-566) +/** @} */ + + +/** @name Loader Status Codes. + * @{ + */ +/** Invalid executable signature. */ +#define VERR_INVALID_EXE_SIGNATURE (-600) +/** The iprt loader recognized a ELF image, but doesn't support loading it. */ +#define VERR_ELF_EXE_NOT_SUPPORTED (-601) +/** The iprt loader recognized a PE image, but doesn't support loading it. */ +#define VERR_PE_EXE_NOT_SUPPORTED (-602) +/** The iprt loader recognized a LX image, but doesn't support loading it. */ +#define VERR_LX_EXE_NOT_SUPPORTED (-603) +/** The iprt loader recognized a LE image, but doesn't support loading it. */ +#define VERR_LE_EXE_NOT_SUPPORTED (-604) +/** The iprt loader recognized a NE image, but doesn't support loading it. */ +#define VERR_NE_EXE_NOT_SUPPORTED (-605) +/** The iprt loader recognized a MZ image, but doesn't support loading it. */ +#define VERR_MZ_EXE_NOT_SUPPORTED (-606) +/** The iprt loader recognized an a.out image, but doesn't support loading it. */ +#define VERR_AOUT_EXE_NOT_SUPPORTED (-607) +/** Bad executable. */ +#define VERR_BAD_EXE_FORMAT (-608) +/** Symbol (export) not found. */ +#define VERR_SYMBOL_NOT_FOUND (-609) +/** Module not found. */ +#define VERR_MODULE_NOT_FOUND (-610) +/** The loader resolved an external symbol to an address to big for the image format. */ +#define VERR_SYMBOL_VALUE_TOO_BIG (-611) +/** The image is too big. */ +#define VERR_IMAGE_TOO_BIG (-612) +/** The image base address is to high for this image type. */ +#define VERR_IMAGE_BASE_TOO_HIGH (-614) +/** Mismatching architecture. */ +#define VERR_LDR_ARCH_MISMATCH (-615) +/** Mismatch between IPRT and native loader. */ +#define VERR_LDR_MISMATCH_NATIVE (-616) +/** Failed to resolve an imported (external) symbol. */ +#define VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND (-617) +/** Generic loader failure. */ +#define VERR_LDR_GENERAL_FAILURE (-618) +/** Code signing error. */ +#define VERR_LDR_IMAGE_HASH (-619) +/** The PE loader encountered delayed imports, a feature which hasn't been implemented yet. */ +#define VERR_LDRPE_DELAY_IMPORT (-620) +/** The PE loader encountered a malformed certificate. */ +#define VERR_LDRPE_CERT_MALFORMED (-621) +/** The PE loader encountered a certificate with an unsupported type or structure revision. */ +#define VERR_LDRPE_CERT_UNSUPPORTED (-622) +/** The PE loader doesn't know how to deal with the global pointer data directory entry yet. */ +#define VERR_LDRPE_GLOBALPTR (-623) +/** The PE loader doesn't support the TLS data directory yet. */ +#define VERR_LDRPE_TLS (-624) +/** The PE loader doesn't grok the COM descriptor data directory entry. */ +#define VERR_LDRPE_COM_DESCRIPTOR (-625) +/** The PE loader encountered an unknown load config directory/header size. */ +#define VERR_LDRPE_LOAD_CONFIG_SIZE (-626) +/** The PE loader encountered a lock prefix table, a feature which hasn't been implemented yet. */ +#define VERR_LDRPE_LOCK_PREFIX_TABLE (-627) +/** The ELF loader doesn't handle foreign endianness. */ +#define VERR_LDRELF_ODD_ENDIAN (-630) +/** The ELF image is 'dynamic', the ELF loader can only deal with 'relocatable' images at present. */ +#define VERR_LDRELF_DYN (-631) +/** The ELF image is 'executable', the ELF loader can only deal with 'relocatable' images at present. */ +#define VERR_LDRELF_EXEC (-632) +/** The ELF image was created for an unsupported target machine type. */ +#define VERR_LDRELF_MACHINE (-633) +/** The ELF version is not supported. */ +#define VERR_LDRELF_VERSION (-634) +/** The ELF loader cannot handle multiple SYMTAB sections. */ +#define VERR_LDRELF_MULTIPLE_SYMTABS (-635) +/** The ELF loader encountered a relocation type which is not implemented. */ +#define VERR_LDRELF_RELOCATION_NOT_SUPPORTED (-636) +/** The ELF loader encountered a bad symbol index. */ +#define VERR_LDRELF_INVALID_SYMBOL_INDEX (-637) +/** The ELF loader encountered an invalid symbol name offset. */ +#define VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET (-638) +/** The ELF loader encountered an invalid relocation offset. */ +#define VERR_LDRELF_INVALID_RELOCATION_OFFSET (-639) +/** The ELF loader didn't find the symbol/string table for the image. */ +#define VERR_LDRELF_NO_SYMBOL_OR_NO_STRING_TABS (-640) +/** Invalid link address. */ +#define VERR_LDR_INVALID_LINK_ADDRESS (-647) +/** Invalid image relative virtual address. */ +#define VERR_LDR_INVALID_RVA (-648) +/** Invalid segment:offset address. */ +#define VERR_LDR_INVALID_SEG_OFFSET (-649) +/** @}*/ + +/** @name Debug Info Reader Status Codes. + * @{ + */ +/** The module contains no line number information. */ +#define VERR_DBG_NO_LINE_NUMBERS (-650) +/** The module contains no symbol information. */ +#define VERR_DBG_NO_SYMBOLS (-651) +/** The specified segment:offset address was invalid. Typically an attempt at + * addressing outside the segment boundary. */ +#define VERR_DBG_INVALID_ADDRESS (-652) +/** Invalid segment index. */ +#define VERR_DBG_INVALID_SEGMENT_INDEX (-653) +/** Invalid segment offset. */ +#define VERR_DBG_INVALID_SEGMENT_OFFSET (-654) +/** Invalid image relative virtual address. */ +#define VERR_DBG_INVALID_RVA (-655) +/** Invalid image relative virtual address. */ +#define VERR_DBG_SPECIAL_SEGMENT (-656) +/** Address conflict within a module/segment. + * Attempted to add a segment, symbol or line number that fully or partially + * overlaps with an existing one. */ +#define VERR_DBG_ADDRESS_CONFLICT (-657) +/** Duplicate symbol within the module. + * Attempted to add a symbol which name already exists within the module. */ +#define VERR_DBG_DUPLICATE_SYMBOL (-658) +/** The segment index specified when adding a new segment is already in use. */ +#define VERR_DBG_SEGMENT_INDEX_CONFLICT (-659) +/** No line number was found for the specified address/ordinal/whatever. */ +#define VERR_DBG_LINE_NOT_FOUND (-660) +/** The length of the symbol name is out of range. + * This means it is an empty string or that it's greater or equal to + * RTDBG_SYMBOL_NAME_LENGTH. */ +#define VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE (-661) +/** The length of the file name is out of range. + * This means it is an empty string or that it's greater or equal to + * RTDBG_FILE_NAME_LENGTH. */ +#define VERR_DBG_FILE_NAME_OUT_OF_RANGE (-662) +/** The length of the segment name is out of range. + * This means it is an empty string or that it is greater or equal to + * RTDBG_SEGMENT_NAME_LENGTH. */ +#define VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE (-663) +/** The specified address range wraps around. */ +#define VERR_DBG_ADDRESS_WRAP (-664) +/** The file is not a valid NM map file. */ +#define VERR_DBG_NOT_NM_MAP_FILE (-665) +/** The file is not a valid /proc/kallsyms file. */ +#define VERR_DBG_NOT_LINUX_KALLSYMS (-666) +/** No debug module interpreter matching the debug info. */ +#define VERR_DBG_NO_MATCHING_INTERPRETER (-667) +/** Bad DWARF line number header. */ +#define VERR_DWARF_BAD_LINE_NUMBER_HEADER (-668) +/** Unexpected end of DWARF unit. */ +#define VERR_DWARF_UNEXPECTED_END (-669) +/** DWARF LEB value overflows the decoder type. */ +#define VERR_DWARF_LEB_OVERFLOW (-670) +/** Bad DWARF extended line number opcode. */ +#define VERR_DWARF_BAD_LNE (-671) +/** Bad DWARF string. */ +#define VERR_DWARF_BAD_STRING (-672) +/** Bad DWARF position. */ +#define VERR_DWARF_BAD_POS (-673) +/** Bad DWARF info. */ +#define VERR_DWARF_BAD_INFO (-674) +/** Bad DWARF abbreviation data. */ +#define VERR_DWARF_BAD_ABBREV (-675) +/** A DWARF abbreviation was not found. */ +#define VERR_DWARF_ABBREV_NOT_FOUND (-676) +/** Encountered an unknown attribute form. */ +#define VERR_DWARF_UNKNOWN_FORM (-677) +/** Encountered an unexpected attribute form. */ +#define VERR_DWARF_UNEXPECTED_FORM (-678) +/** @} */ + +/** @name Request Packet Status Codes. + * @{ + */ +/** Invalid RT request type. + * For the RTReqAlloc() case, the caller just specified an illegal enmType. For + * all the other occurrences it means indicates corruption, broken logic, or stupid + * interface user. */ +#define VERR_RT_REQUEST_INVALID_TYPE (-700) +/** Invalid RT request state. + * The state of the request packet was not the expected and accepted one(s). Either + * the interface user screwed up, or we've got corruption/broken logic. */ +#define VERR_RT_REQUEST_STATE (-701) +/** Invalid RT request packet. + * One or more of the RT controlled packet members didn't contain the correct + * values. Some thing's broken. */ +#define VERR_RT_REQUEST_INVALID_PACKAGE (-702) +/** The status field has not been updated yet as the request is still + * pending completion. Someone queried the iStatus field before the request + * has been fully processed. */ +#define VERR_RT_REQUEST_STATUS_STILL_PENDING (-703) +/** The request has been freed, don't read the status now. + * Someone is reading the iStatus field of a freed request packet. */ +#define VERR_RT_REQUEST_STATUS_FREED (-704) +/** @} */ + +/** @name Environment Status Code + * @{ + */ +/** The specified environment variable was not found. (RTEnvGetEx) */ +#define VERR_ENV_VAR_NOT_FOUND (-750) +/** The specified environment variable was not found. (RTEnvUnsetEx) */ +#define VINF_ENV_VAR_NOT_FOUND (750) +/** Unable to translate all the variables in the default environment due to + * codeset issues (LANG / LC_ALL / LC_CTYPE). */ +#define VWRN_ENV_NOT_FULLY_TRANSLATED (751) +/** @} */ + +/** @name Multiprocessor Status Codes. + * @{ + */ +/** The specified cpu is offline. */ +#define VERR_CPU_OFFLINE (-800) +/** The specified cpu was not found. */ +#define VERR_CPU_NOT_FOUND (-801) +/** @} */ + +/** @name RTGetOpt status codes + * @{ */ +/** RTGetOpt: Command line option not recognized. */ +#define VERR_GETOPT_UNKNOWN_OPTION (-825) +/** RTGetOpt: Command line option needs argument. */ +#define VERR_GETOPT_REQUIRED_ARGUMENT_MISSING (-826) +/** RTGetOpt: Command line option has argument with bad format. */ +#define VERR_GETOPT_INVALID_ARGUMENT_FORMAT (-827) +/** RTGetOpt: Not an option. */ +#define VINF_GETOPT_NOT_OPTION 828 +/** RTGetOpt: Command line option needs an index. */ +#define VERR_GETOPT_INDEX_MISSING (-829) +/** @} */ + +/** @name RTCache status codes + * @{ */ +/** RTCache: cache is full. */ +#define VERR_CACHE_FULL (-850) +/** RTCache: cache is empty. */ +#define VERR_CACHE_EMPTY (-851) +/** @} */ + +/** @name RTMemCache status codes + * @{ */ +/** Reached the max cache size. */ +#define VERR_MEM_CACHE_MAX_SIZE (-855) +/** @} */ + +/** @name RTS3 status codes + * @{ */ +/** Access denied error. */ +#define VERR_S3_ACCESS_DENIED (-875) +/** The bucket/key wasn't found. */ +#define VERR_S3_NOT_FOUND (-876) +/** Bucket already exists. */ +#define VERR_S3_BUCKET_ALREADY_EXISTS (-877) +/** Can't delete bucket with keys. */ +#define VERR_S3_BUCKET_NOT_EMPTY (-878) +/** The current operation was canceled. */ +#define VERR_S3_CANCELED (-879) +/** @} */ + +/** @name RTManifest status codes + * @{ */ +/** A digest type used in the manifest file isn't supported. */ +#define VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE (-900) +/** An entry in the manifest file couldn't be interpreted correctly. */ +#define VERR_MANIFEST_WRONG_FILE_FORMAT (-901) +/** A digest doesn't match the corresponding file. */ +#define VERR_MANIFEST_DIGEST_MISMATCH (-902) +/** The file list doesn't match to the content of the manifest file. */ +#define VERR_MANIFEST_FILE_MISMATCH (-903) +/** The specified attribute (name) was not found in the manifest. */ +#define VERR_MANIFEST_ATTR_NOT_FOUND (-904) +/** The attribute type did not match. */ +#define VERR_MANIFEST_ATTR_TYPE_MISMATCH (-905) +/** No attribute of the specified types was found. */ +#define VERR_MANIFEST_ATTR_TYPE_NOT_FOUND (-906) +/** @} */ + +/** @name RTTar status codes + * @{ */ +/** The checksum of a tar header record doesn't match. */ +#define VERR_TAR_CHKSUM_MISMATCH (-925) +/** The tar end of file record was read. */ +#define VERR_TAR_END_OF_FILE (-926) +/** The tar file ended unexpectedly. */ +#define VERR_TAR_UNEXPECTED_EOS (-927) +/** The tar termination records was encountered without reaching the end of + * the input stream. */ +#define VERR_TAR_EOS_MORE_INPUT (-928) +/** A number tar header field was malformed. */ +#define VERR_TAR_BAD_NUM_FIELD (-929) +/** A numeric tar header field was not terminated correctly. */ +#define VERR_TAR_BAD_NUM_FIELD_TERM (-930) +/** A number tar header field was encoded using base-256 which this + * tar implementation currently does not support. */ +#define VERR_TAR_BASE_256_NOT_SUPPORTED (-931) +/** A number tar header field yielded a value too large for the internal + * variable of the tar interpreter. */ +#define VERR_TAR_NUM_VALUE_TOO_LARGE (-932) +/** The combined minor and major device number type is too small to hold the + * value stored in the tar header. */ +#define VERR_TAR_DEV_VALUE_TOO_LARGE (-933) +/** The mode field in a tar header is bad. */ +#define VERR_TAR_BAD_MODE_FIELD (-934) +/** The mode field should not include the type. */ +#define VERR_TAR_MODE_WITH_TYPE (-935) +/** The size field should be zero for links and symlinks. */ +#define VERR_TAR_SIZE_NOT_ZERO (-936) +/** Encountered an unknown type flag. */ +#define VERR_TAR_UNKNOWN_TYPE_FLAG (-937) +/** The tar header is all zeros. */ +#define VERR_TAR_ZERO_HEADER (-938) +/** Not a uniform standard tape v0.0 archive header. */ +#define VERR_TAR_NOT_USTAR_V00 (-939) +/** The name is empty. */ +#define VERR_TAR_EMPTY_NAME (-940) +/** A non-directory entry has a name ending with a slash. */ +#define VERR_TAR_NON_DIR_ENDS_WITH_SLASH (-941) +/** Encountered an unsupported portable archive exchange (pax) header. */ +#define VERR_TAR_UNSUPPORTED_PAX_TYPE (-942) +/** Encountered an unsupported Solaris Tar extension. */ +#define VERR_TAR_UNSUPPORTED_SOLARIS_HDR_TYPE (-943) +/** Encountered an unsupported GNU Tar extension. */ +#define VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE (-944) +/** Malformed checksum field in the tar header. */ +#define VERR_TAR_BAD_CHKSUM_FIELD (-945) +/** Malformed checksum field in the tar header. */ +#define VERR_TAR_MALFORMED_GNU_LONGXXXX (-946) +/** Too long name or link string. */ +#define VERR_TAR_NAME_TOO_LONG (-947) +/** @} */ + +/** @name RTPoll status codes + * @{ */ +/** The handle is not pollable. */ +#define VERR_POLL_HANDLE_NOT_POLLABLE (-950) +/** The handle ID is already present in the poll set. */ +#define VERR_POLL_HANDLE_ID_EXISTS (-951) +/** The handle ID was not found in the set. */ +#define VERR_POLL_HANDLE_ID_NOT_FOUND (-952) +/** The poll set is full. */ +#define VERR_POLL_SET_IS_FULL (-953) +/** @} */ + +/** @name RTZip status codes + * @{ */ +/** Generic zip error. */ +#define VERR_ZIP_ERROR (-22000) +/** The compressed data was corrupted. */ +#define VERR_ZIP_CORRUPTED (-22001) +/** Ran out of memory while compressing or uncompressing. */ +#define VERR_ZIP_NO_MEMORY (-22002) +/** The compression format version is unsupported. */ +#define VERR_ZIP_UNSUPPORTED_VERSION (-22003) +/** The compression method is unsupported. */ +#define VERR_ZIP_UNSUPPORTED_METHOD (-22004) +/** The compressed data started with a bad header. */ +#define VERR_ZIP_BAD_HEADER (-22005) +/** @} */ + +/** @name RTVfs status codes + * @{ */ +/** The VFS chain specification does not have a valid prefix. */ +#define VERR_VFS_CHAIN_NO_PREFIX (-22100) +/** The VFS chain specification is empty. */ +#define VERR_VFS_CHAIN_EMPTY (-22101) +/** Expected an element. */ +#define VERR_VFS_CHAIN_EXPECTED_ELEMENT (-22102) +/** The VFS object type is not known. */ +#define VERR_VFS_CHAIN_UNKNOWN_TYPE (-22103) +/** Expected a left paranthese. */ +#define VERR_VFS_CHAIN_EXPECTED_LEFT_PARENTHESES (-22104) +/** Expected a right paranthese. */ +#define VERR_VFS_CHAIN_EXPECTED_RIGHT_PARENTHESES (-22105) +/** Expected a provider name. */ +#define VERR_VFS_CHAIN_EXPECTED_PROVIDER_NAME (-22106) +/** Expected an action (> or |). */ +#define VERR_VFS_CHAIN_EXPECTED_ACTION (-22107) +/** Only one action element is currently supported. */ +#define VERR_VFS_CHAIN_MULTIPLE_ACTIONS (-22108) +/** Expected to find a driving action (>), but there is none. */ +#define VERR_VFS_CHAIN_NO_ACTION (-22109) +/** Expected pipe action. */ +#define VERR_VFS_CHAIN_EXPECTED_PIPE (-22110) +/** Unexpected action type. */ +#define VERR_VFS_CHAIN_UNEXPECTED_ACTION_TYPE (-22111) +/** @} */ + +/** @name RTDvm status codes + * @{ */ +/** The volume map doesn't contain any valid volume. */ +#define VERR_DVM_MAP_EMPTY (-22200) +/** There is no volume behind the current one. */ +#define VERR_DVM_MAP_NO_VOLUME (-22201) +/** @} */ + +/** @name Logger status codes + * @{ */ +/** The internal logger revision did not match. */ +#define VERR_LOG_REVISION_MISMATCH (-22300) +/** @} */ + +/* see above, 22400..22499 is used for misc codes! */ + +/** @name Logger status codes + * @{ */ +/** Power off is not supported by the hardware or the OS. */ +#define VERR_SYS_CANNOT_POWER_OFF (-22500) +/** The halt action was requested, but the OS may actually power + * off the machine. */ +#define VINF_SYS_MAY_POWER_OFF (22501) +/** Shutdown failed. */ +#define VERR_SYS_SHUTDOWN_FAILED (-22502) +/** @} */ + +/** @name Filesystem status codes + * @{ */ +/** Filesystem can't be opened because it is corrupt. */ +#define VERR_FILESYSTEM_CORRUPT (-22600) +/** @} */ + + +/* SED-END */ + +/** @} */ + +#endif + diff --git a/include/iprt/err.mac b/include/iprt/err.mac new file mode 100644 index 00000000..00e330cc --- /dev/null +++ b/include/iprt/err.mac @@ -0,0 +1,455 @@ +%define VINF_SUCCESS 0 +%define VERR_GENERAL_FAILURE (-1) +%define VERR_INVALID_PARAMETER (-2) +%define VWRN_INVALID_PARAMETER 2 +%define VERR_INVALID_MAGIC (-3) +%define VWRN_INVALID_MAGIC 3 +%define VERR_INVALID_HANDLE (-4) +%define VWRN_INVALID_HANDLE 4 +%define VERR_LOCK_FAILED (-5) +%define VERR_INVALID_POINTER (-6) +%define VERR_IDT_FAILED (-7) +%define VERR_NO_MEMORY (-8) +%define VERR_ALREADY_LOADED (-9) +%define VERR_PERMISSION_DENIED (-10) +%define VINF_PERMISSION_DENIED 10 +%define VERR_VERSION_MISMATCH (-11) +%define VERR_NOT_IMPLEMENTED (-12) +%define VERR_NOT_EQUAL (-18) +%define VERR_NOT_SYMLINK (-19) +%define VERR_NO_TMP_MEMORY (-20) +%define VERR_INVALID_FMODE (-21) +%define VERR_WRONG_ORDER (-22) +%define VERR_NO_TLS_FOR_SELF (-23) +%define VERR_FAILED_TO_SET_SELF_TLS (-24) +%define VERR_NO_CONT_MEMORY (-26) +%define VERR_NO_PAGE_MEMORY (-27) +%define VINF_ALREADY_INITIALIZED 28 +%define VERR_THREAD_IS_DEAD (-29) +%define VERR_THREAD_NOT_WAITABLE (-30) +%define VERR_PAGE_TABLE_NOT_PRESENT (-31) +%define VERR_INVALID_CONTEXT (-32) +%define VERR_TIMER_BUSY (-33) +%define VERR_ADDRESS_CONFLICT (-34) +%define VERR_UNRESOLVED_ERROR (-35) +%define VERR_INVALID_FUNCTION (-36) +%define VERR_NOT_SUPPORTED (-37) +%define VINF_NOT_SUPPORTED 37 +%define VERR_ACCESS_DENIED (-38) +%define VERR_INTERRUPTED (-39) +%define VINF_INTERRUPTED 39 +%define VERR_TIMEOUT (-40) +%define VINF_TIMEOUT 40 +%define VERR_BUFFER_OVERFLOW (-41) +%define VINF_BUFFER_OVERFLOW 41 +%define VERR_TOO_MUCH_DATA (-42) +%define VERR_MAX_THRDS_REACHED (-43) +%define VERR_MAX_PROCS_REACHED (-44) +%define VERR_SIGNAL_REFUSED (-45) +%define VERR_SIGNAL_PENDING (-46) +%define VERR_SIGNAL_INVALID (-47) +%define VERR_STATE_CHANGED (-48) +%define VWRN_STATE_CHANGED 48 +%define VERR_INVALID_UUID_FORMAT (-49) +%define VERR_PROCESS_NOT_FOUND (-50) +%define VERR_PROCESS_RUNNING (-51) +%define VERR_TRY_AGAIN (-52) +%define VINF_TRY_AGAIN 52 +%define VERR_PARSE_ERROR (-53) +%define VERR_OUT_OF_RANGE (-54) +%define VERR_NUMBER_TOO_BIG (-55) +%define VWRN_NUMBER_TOO_BIG 55 +%define VERR_NO_DIGITS (-56) +%define VWRN_NO_DIGITS 56 +%define VERR_NEGATIVE_UNSIGNED (-57) +%define VWRN_NEGATIVE_UNSIGNED 57 +%define VERR_NO_TRANSLATION (-58) +%define VWRN_NO_TRANSLATION 58 +%define VERR_CODE_POINT_ENDIAN_INDICATOR (-59) +%define VERR_CODE_POINT_SURROGATE (-60) +%define VERR_INVALID_UTF8_ENCODING (-61) +%define VERR_INVALID_UTF16_ENCODING (-62) +%define VERR_CANT_RECODE_AS_UTF16 (-63) +%define VERR_NO_STR_MEMORY (-64) +%define VERR_NO_UTF16_MEMORY (-65) +%define VERR_NO_CODE_POINT_MEMORY (-66) +%define VERR_MEMORY_BUSY (-67) +%define VERR_TIMER_ACTIVE (-68) +%define VERR_TIMER_SUSPENDED (-69) +%define VERR_CANCELLED (-70) +%define VERR_MEMOBJ_INIT_FAILED (-71) +%define VERR_NO_LOW_MEMORY (-72) +%define VERR_NO_PHYS_MEMORY (-73) +%define VERR_ADDRESS_TOO_BIG (-74) +%define VERR_MAP_FAILED (-75) +%define VERR_TRAILING_CHARS (-76) +%define VWRN_TRAILING_CHARS 76 +%define VERR_TRAILING_SPACES (-77) +%define VWRN_TRAILING_SPACES 77 +%define VERR_NOT_FOUND (-78) +%define VWRN_NOT_FOUND 78 +%define VERR_INVALID_STATE (-79) +%define VWRN_INVALID_STATE 79 +%define VERR_OUT_OF_RESOURCES (-80) +%define VWRN_OUT_OF_RESOURCES 80 +%define VERR_NO_MORE_HANDLES (-81) +%define VERR_PREEMPT_DISABLED (-82) +%define VERR_END_OF_STRING (-83) +%define VINF_END_OF_STRING 83 +%define VERR_PAGE_COUNT_OUT_OF_RANGE (-84) +%define VERR_OBJECT_DESTROYED (-85) +%define VINF_OBJECT_DESTROYED 85 +%define VERR_DANGLING_OBJECTS (-86) +%define VWRN_DANGLING_OBJECTS 86 +%define VERR_INVALID_BASE64_ENCODING (-87) +%define VERR_CALLBACK_RETURN (-88) +%define VINF_CALLBACK_RETURN 88 +%define VERR_AUTHENTICATION_FAILURE (-89) +%define VERR_NOT_POWER_OF_TWO (-90) +%define VERR_IGNORED (-91) +%define VERR_CONCURRENT_ACCESS (-92) +%define VERR_CALLER_NO_REFERENCE (-93) +%define VERR_NO_CHANGE (-95) +%define VINF_NO_CHANGE 95 +%define VERR_NO_EXEC_MEMORY (-96) +%define VERR_UNSUPPORTED_ALIGNMENT (-97) +%define VINF_UNSUPPORTED_ALIGNMENT 97 +%define VERR_DUPLICATE (-98) +%define VERR_MISSING (-99) +%define VERR_UNEXPECTED_EXCEPTION (-22400) +%define VERR_BUFFER_UNDERFLOW (-22401) +%define VINF_BUFFER_UNDERFLOW 22401 +%define VERR_UNEVEN_INPUT (-22402) +%define VERR_NOT_AVAILABLE (-22403) +%define VERR_FILE_IO_ERROR (-100) +%define VERR_OPEN_FAILED (-101) +%define VERR_FILE_NOT_FOUND (-102) +%define VERR_PATH_NOT_FOUND (-103) +%define VERR_INVALID_NAME (-104) +%define VERR_ALREADY_EXISTS (-105) +%define VWRN_ALREADY_EXISTS 105 +%define VERR_TOO_MANY_OPEN_FILES (-106) +%define VERR_SEEK (-107) +%define VERR_NEGATIVE_SEEK (-108) +%define VERR_SEEK_ON_DEVICE (-109) +%define VERR_EOF (-110) +%define VINF_EOF 110 +%define VERR_READ_ERROR (-111) +%define VERR_WRITE_ERROR (-112) +%define VERR_WRITE_PROTECT (-113) +%define VERR_SHARING_VIOLATION (-114) +%define VERR_FILE_LOCK_FAILED (-115) +%define VERR_FILE_LOCK_VIOLATION (-116) +%define VERR_CANT_CREATE (-117) +%define VERR_CANT_DELETE_DIRECTORY (-118) +%define VERR_NOT_SAME_DEVICE (-119) +%define VERR_FILENAME_TOO_LONG (-120) +%define VERR_MEDIA_NOT_PRESENT (-121) +%define VERR_MEDIA_NOT_RECOGNIZED (-122) +%define VERR_FILE_NOT_LOCKED (-123) +%define VERR_FILE_LOCK_LOST (-124) +%define VERR_DIR_NOT_EMPTY (-125) +%define VERR_NOT_A_DIRECTORY (-126) +%define VERR_IS_A_DIRECTORY (-127) +%define VERR_FILE_TOO_BIG (-128) +%define VERR_FILE_AIO_NO_REQUEST (-129) +%define VERR_FILE_AIO_IN_PROGRESS (-130) +%define VERR_FILE_AIO_COMPLETED (-131) +%define VERR_FILE_AIO_BUSY (-132) +%define VERR_FILE_AIO_LIMIT_EXCEEDED (-133) +%define VERR_FILE_AIO_CANCELED (-134) +%define VERR_FILE_AIO_NOT_SUBMITTED (-135) +%define VERR_FILE_AIO_NOT_PREPARED (-136) +%define VERR_FILE_AIO_INSUFFICIENT_RESSOURCES (-137) +%define VERR_RESOURCE_BUSY (-138) +%define VERR_NOT_A_FILE (-139) +%define VERR_IS_A_FILE (-140) +%define VERR_UNEXPECTED_FS_OBJ_TYPE (-141) +%define VERR_PATH_DOES_NOT_START_WITH_ROOT (-142) +%define VERR_PATH_IS_RELATIVE (-143) +%define VERR_PATH_IS_NOT_RELATIVE (-144) +%define VERR_DISK_IO_ERROR (-150) +%define VERR_INVALID_DRIVE (-151) +%define VERR_DISK_FULL (-152) +%define VERR_DISK_CHANGE (-153) +%define VERR_DRIVE_LOCKED (-154) +%define VERR_DISK_INVALID_FORMAT (-155) +%define VERR_TOO_MANY_SYMLINKS (-156) +%define VERR_NS_SYMLINK_SET_TIME (-157) +%define VERR_NS_SYMLINK_CHANGE_OWNER (-158) +%define VERR_SEARCH_ERROR (-200) +%define VERR_NO_MORE_FILES (-201) +%define VERR_NO_MORE_SEARCH_HANDLES (-202) +%define VWRN_NO_DIRENT_INFO 203 +%define VERR_INTERNAL_ERROR (-225) +%define VERR_INTERNAL_ERROR_2 (-226) +%define VERR_INTERNAL_ERROR_3 (-227) +%define VERR_INTERNAL_ERROR_4 (-228) +%define VERR_INTERNAL_ERROR_5 (-229) +%define VERR_IPE_UNEXPECTED_STATUS (-230) +%define VERR_IPE_UNEXPECTED_INFO_STATUS (-231) +%define VERR_IPE_UNEXPECTED_ERROR_STATUS (-232) +%define VERR_IPE_UNINITIALIZED_STATUS (-233) +%define VERR_IPE_NOT_REACHED_DEFAULT_CASE (-234) +%define VERR_DEV_IO_ERROR (-250) +%define VERR_IO_BAD_UNIT (-251) +%define VERR_IO_NOT_READY (-252) +%define VERR_IO_BAD_COMMAND (-253) +%define VERR_IO_CRC (-254) +%define VERR_IO_BAD_LENGTH (-255) +%define VERR_IO_SECTOR_NOT_FOUND (-256) +%define VERR_IO_GEN_FAILURE (-257) +%define VERR_PIPE_IO_ERROR (-300) +%define VERR_BROKEN_PIPE (-301) +%define VERR_BAD_PIPE (-302) +%define VERR_PIPE_BUSY (-303) +%define VERR_NO_DATA (-304) +%define VERR_PIPE_NOT_CONNECTED (-305) +%define VERR_MORE_DATA (-306) +%define VERR_PIPE_NOT_READ (-307) +%define VERR_PIPE_NOT_WRITE (-308) +%define VERR_SEM_ERROR (-350) +%define VERR_TOO_MANY_SEMAPHORES (-351) +%define VERR_EXCL_SEM_ALREADY_OWNED (-352) +%define VERR_SEM_IS_SET (-353) +%define VERR_TOO_MANY_SEM_REQUESTS (-354) +%define VERR_NOT_OWNER (-355) +%define VERR_TOO_MANY_OPENS (-356) +%define VERR_TOO_MANY_POSTS (-357) +%define VERR_ALREADY_POSTED (-358) +%define VERR_ALREADY_RESET (-359) +%define VERR_SEM_BUSY (-360) +%define VERR_SEM_OWNER_DIED (-361) +%define VERR_SEM_NOT_FOUND (-362) +%define VERR_SEM_DESTROYED (-363) +%define VERR_SEM_NESTED (-364) +%define VINF_SEM_NESTED (364) +%define VERR_DEADLOCK (-365) +%define VERR_SEM_OUT_OF_TURN (-366) +%define VERR_SEM_BAD_CONTEXT (-367) +%define VINF_SEM_BAD_CONTEXT (367) +%define VERR_SEM_LV_WRONG_ORDER (-368) +%define VERR_SEM_LV_WRONG_RELEASE_ORDER (-369) +%define VERR_SEM_LV_NESTED (-370) +%define VERR_SEM_LV_INVALID_PARAMETER (-371) +%define VERR_SEM_LV_DEADLOCK (-372) +%define VERR_SEM_LV_EXISTING_DEADLOCK (-373) +%define VERR_SEM_LV_NOT_OWNER (-374) +%define VERR_SEM_LV_ILLEGAL_UPGRADE (-375) +%define VERR_SEM_LV_NOT_SIGNALLER (-376) +%define VERR_SEM_LV_INTERNAL_ERROR (-377) +%define VERR_NET_IO_ERROR (-400) +%define VERR_NET_OUT_OF_RESOURCES (-401) +%define VERR_NET_HOST_NOT_FOUND (-402) +%define VERR_NET_PATH_NOT_FOUND (-403) +%define VERR_NET_PRINT_ERROR (-404) +%define VERR_NET_NO_NETWORK (-405) +%define VERR_NET_NOT_UNIQUE_NAME (-406) +%define VERR_NET_IN_PROGRESS (-436) +%define VERR_NET_ALREADY_IN_PROGRESS (-437) +%define VERR_NET_NOT_SOCKET (-438) +%define VERR_NET_DEST_ADDRESS_REQUIRED (-439) +%define VERR_NET_MSG_SIZE (-440) +%define VERR_NET_PROTOCOL_TYPE (-441) +%define VERR_NET_PROTOCOL_NOT_AVAILABLE (-442) +%define VERR_NET_PROTOCOL_NOT_SUPPORTED (-443) +%define VERR_NET_SOCKET_TYPE_NOT_SUPPORTED (-444) +%define VERR_NET_OPERATION_NOT_SUPPORTED (-445) +%define VERR_NET_PROTOCOL_FAMILY_NOT_SUPPORTED (-446) +%define VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED (-447) +%define VERR_NET_ADDRESS_IN_USE (-448) +%define VERR_NET_ADDRESS_NOT_AVAILABLE (-449) +%define VERR_NET_DOWN (-450) +%define VERR_NET_UNREACHABLE (-451) +%define VERR_NET_CONNECTION_RESET (-452) +%define VERR_NET_CONNECTION_ABORTED (-453) +%define VERR_NET_CONNECTION_RESET_BY_PEER (-454) +%define VERR_NET_NO_BUFFER_SPACE (-455) +%define VERR_NET_ALREADY_CONNECTED (-456) +%define VERR_NET_NOT_CONNECTED (-457) +%define VERR_NET_SHUTDOWN (-458) +%define VERR_NET_TOO_MANY_REFERENCES (-459) +%define VERR_NET_CONNECTION_TIMED_OUT (-460) +%define VERR_NET_CONNECTION_REFUSED (-461) +%define VERR_NET_HOST_DOWN (-464) +%define VERR_NET_HOST_UNREACHABLE (-465) +%define VERR_NET_PROTOCOL_ERROR (-466) +%define VERR_TCP_SERVER_STOP (-500) +%define VINF_TCP_SERVER_STOP 500 +%define VERR_TCP_SERVER_SHUTDOWN (-501) +%define VERR_TCP_SERVER_DESTROYED (-502) +%define VINF_TCP_SERVER_NO_CLIENT 503 +%define VERR_UDP_SERVER_STOP (-520) +%define VINF_UDP_SERVER_STOP 520 +%define VERR_UDP_SERVER_SHUTDOWN (-521) +%define VERR_UDP_SERVER_DESTROYED (-522) +%define VINF_UDP_SERVER_NO_CLIENT 523 +%define VERR_L4_INVALID_DS_OFFSET (-550) +%define VERR_IPC (-551) +%define VERR_RESOURCE_IN_USE (-552) +%define VERR_IPC_PROCESS_NOT_FOUND (-553) +%define VERR_IPC_RECEIVE_TIMEOUT (-554) +%define VERR_IPC_SEND_TIMEOUT (-555) +%define VERR_IPC_RECEIVE_CANCELLED (-556) +%define VERR_IPC_SEND_CANCELLED (-557) +%define VERR_IPC_RECEIVE_ABORTED (-558) +%define VERR_IPC_SEND_ABORTED (-559) +%define VERR_IPC_RECEIVE_MAP_FAILED (-560) +%define VERR_IPC_SEND_MAP_FAILED (-561) +%define VERR_IPC_RECEIVE_SEND_PF_TIMEOUT (-562) +%define VERR_IPC_SEND_SEND_PF_TIMEOUT (-563) +%define VINF_IPC_RECEIVE_MSG_CUT 564 +%define VINF_IPC_SEND_MSG_CUT 565 +%define VERR_L4_DS_MANAGER_NOT_FOUND (-566) +%define VERR_INVALID_EXE_SIGNATURE (-600) +%define VERR_ELF_EXE_NOT_SUPPORTED (-601) +%define VERR_PE_EXE_NOT_SUPPORTED (-602) +%define VERR_LX_EXE_NOT_SUPPORTED (-603) +%define VERR_LE_EXE_NOT_SUPPORTED (-604) +%define VERR_NE_EXE_NOT_SUPPORTED (-605) +%define VERR_MZ_EXE_NOT_SUPPORTED (-606) +%define VERR_AOUT_EXE_NOT_SUPPORTED (-607) +%define VERR_BAD_EXE_FORMAT (-608) +%define VERR_SYMBOL_NOT_FOUND (-609) +%define VERR_MODULE_NOT_FOUND (-610) +%define VERR_SYMBOL_VALUE_TOO_BIG (-611) +%define VERR_IMAGE_TOO_BIG (-612) +%define VERR_IMAGE_BASE_TOO_HIGH (-614) +%define VERR_LDR_ARCH_MISMATCH (-615) +%define VERR_LDR_MISMATCH_NATIVE (-616) +%define VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND (-617) +%define VERR_LDR_GENERAL_FAILURE (-618) +%define VERR_LDR_IMAGE_HASH (-619) +%define VERR_LDRPE_DELAY_IMPORT (-620) +%define VERR_LDRPE_CERT_MALFORMED (-621) +%define VERR_LDRPE_CERT_UNSUPPORTED (-622) +%define VERR_LDRPE_GLOBALPTR (-623) +%define VERR_LDRPE_TLS (-624) +%define VERR_LDRPE_COM_DESCRIPTOR (-625) +%define VERR_LDRPE_LOAD_CONFIG_SIZE (-626) +%define VERR_LDRPE_LOCK_PREFIX_TABLE (-627) +%define VERR_LDRELF_ODD_ENDIAN (-630) +%define VERR_LDRELF_DYN (-631) +%define VERR_LDRELF_EXEC (-632) +%define VERR_LDRELF_MACHINE (-633) +%define VERR_LDRELF_VERSION (-634) +%define VERR_LDRELF_MULTIPLE_SYMTABS (-635) +%define VERR_LDRELF_RELOCATION_NOT_SUPPORTED (-636) +%define VERR_LDRELF_INVALID_SYMBOL_INDEX (-637) +%define VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET (-638) +%define VERR_LDRELF_INVALID_RELOCATION_OFFSET (-639) +%define VERR_LDRELF_NO_SYMBOL_OR_NO_STRING_TABS (-640) +%define VERR_LDR_INVALID_LINK_ADDRESS (-647) +%define VERR_LDR_INVALID_RVA (-648) +%define VERR_LDR_INVALID_SEG_OFFSET (-649) +%define VERR_DBG_NO_LINE_NUMBERS (-650) +%define VERR_DBG_NO_SYMBOLS (-651) +%define VERR_DBG_INVALID_ADDRESS (-652) +%define VERR_DBG_INVALID_SEGMENT_INDEX (-653) +%define VERR_DBG_INVALID_SEGMENT_OFFSET (-654) +%define VERR_DBG_INVALID_RVA (-655) +%define VERR_DBG_SPECIAL_SEGMENT (-656) +%define VERR_DBG_ADDRESS_CONFLICT (-657) +%define VERR_DBG_DUPLICATE_SYMBOL (-658) +%define VERR_DBG_SEGMENT_INDEX_CONFLICT (-659) +%define VERR_DBG_LINE_NOT_FOUND (-660) +%define VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE (-661) +%define VERR_DBG_FILE_NAME_OUT_OF_RANGE (-662) +%define VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE (-663) +%define VERR_DBG_ADDRESS_WRAP (-664) +%define VERR_DBG_NOT_NM_MAP_FILE (-665) +%define VERR_DBG_NOT_LINUX_KALLSYMS (-666) +%define VERR_DBG_NO_MATCHING_INTERPRETER (-667) +%define VERR_DWARF_BAD_LINE_NUMBER_HEADER (-668) +%define VERR_DWARF_UNEXPECTED_END (-669) +%define VERR_DWARF_LEB_OVERFLOW (-670) +%define VERR_DWARF_BAD_LNE (-671) +%define VERR_DWARF_BAD_STRING (-672) +%define VERR_DWARF_BAD_POS (-673) +%define VERR_DWARF_BAD_INFO (-674) +%define VERR_DWARF_BAD_ABBREV (-675) +%define VERR_DWARF_ABBREV_NOT_FOUND (-676) +%define VERR_DWARF_UNKNOWN_FORM (-677) +%define VERR_DWARF_UNEXPECTED_FORM (-678) +%define VERR_RT_REQUEST_INVALID_TYPE (-700) +%define VERR_RT_REQUEST_STATE (-701) +%define VERR_RT_REQUEST_INVALID_PACKAGE (-702) +%define VERR_RT_REQUEST_STATUS_STILL_PENDING (-703) +%define VERR_RT_REQUEST_STATUS_FREED (-704) +%define VERR_ENV_VAR_NOT_FOUND (-750) +%define VINF_ENV_VAR_NOT_FOUND (750) +%define VWRN_ENV_NOT_FULLY_TRANSLATED (751) +%define VERR_CPU_OFFLINE (-800) +%define VERR_CPU_NOT_FOUND (-801) +%define VERR_GETOPT_UNKNOWN_OPTION (-825) +%define VERR_GETOPT_REQUIRED_ARGUMENT_MISSING (-826) +%define VERR_GETOPT_INVALID_ARGUMENT_FORMAT (-827) +%define VINF_GETOPT_NOT_OPTION 828 +%define VERR_GETOPT_INDEX_MISSING (-829) +%define VERR_CACHE_FULL (-850) +%define VERR_CACHE_EMPTY (-851) +%define VERR_MEM_CACHE_MAX_SIZE (-855) +%define VERR_S3_ACCESS_DENIED (-875) +%define VERR_S3_NOT_FOUND (-876) +%define VERR_S3_BUCKET_ALREADY_EXISTS (-877) +%define VERR_S3_BUCKET_NOT_EMPTY (-878) +%define VERR_S3_CANCELED (-879) +%define VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE (-900) +%define VERR_MANIFEST_WRONG_FILE_FORMAT (-901) +%define VERR_MANIFEST_DIGEST_MISMATCH (-902) +%define VERR_MANIFEST_FILE_MISMATCH (-903) +%define VERR_MANIFEST_ATTR_NOT_FOUND (-904) +%define VERR_MANIFEST_ATTR_TYPE_MISMATCH (-905) +%define VERR_MANIFEST_ATTR_TYPE_NOT_FOUND (-906) +%define VERR_TAR_CHKSUM_MISMATCH (-925) +%define VERR_TAR_END_OF_FILE (-926) +%define VERR_TAR_UNEXPECTED_EOS (-927) +%define VERR_TAR_EOS_MORE_INPUT (-928) +%define VERR_TAR_BAD_NUM_FIELD (-929) +%define VERR_TAR_BAD_NUM_FIELD_TERM (-930) +%define VERR_TAR_BASE_256_NOT_SUPPORTED (-931) +%define VERR_TAR_NUM_VALUE_TOO_LARGE (-932) +%define VERR_TAR_DEV_VALUE_TOO_LARGE (-933) +%define VERR_TAR_BAD_MODE_FIELD (-934) +%define VERR_TAR_MODE_WITH_TYPE (-935) +%define VERR_TAR_SIZE_NOT_ZERO (-936) +%define VERR_TAR_UNKNOWN_TYPE_FLAG (-937) +%define VERR_TAR_ZERO_HEADER (-938) +%define VERR_TAR_NOT_USTAR_V00 (-939) +%define VERR_TAR_EMPTY_NAME (-940) +%define VERR_TAR_NON_DIR_ENDS_WITH_SLASH (-941) +%define VERR_TAR_UNSUPPORTED_PAX_TYPE (-942) +%define VERR_TAR_UNSUPPORTED_SOLARIS_HDR_TYPE (-943) +%define VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE (-944) +%define VERR_TAR_BAD_CHKSUM_FIELD (-945) +%define VERR_TAR_MALFORMED_GNU_LONGXXXX (-946) +%define VERR_TAR_NAME_TOO_LONG (-947) +%define VERR_POLL_HANDLE_NOT_POLLABLE (-950) +%define VERR_POLL_HANDLE_ID_EXISTS (-951) +%define VERR_POLL_HANDLE_ID_NOT_FOUND (-952) +%define VERR_POLL_SET_IS_FULL (-953) +%define VERR_ZIP_ERROR (-22000) +%define VERR_ZIP_CORRUPTED (-22001) +%define VERR_ZIP_NO_MEMORY (-22002) +%define VERR_ZIP_UNSUPPORTED_VERSION (-22003) +%define VERR_ZIP_UNSUPPORTED_METHOD (-22004) +%define VERR_ZIP_BAD_HEADER (-22005) +%define VERR_VFS_CHAIN_NO_PREFIX (-22100) +%define VERR_VFS_CHAIN_EMPTY (-22101) +%define VERR_VFS_CHAIN_EXPECTED_ELEMENT (-22102) +%define VERR_VFS_CHAIN_UNKNOWN_TYPE (-22103) +%define VERR_VFS_CHAIN_EXPECTED_LEFT_PARENTHESES (-22104) +%define VERR_VFS_CHAIN_EXPECTED_RIGHT_PARENTHESES (-22105) +%define VERR_VFS_CHAIN_EXPECTED_PROVIDER_NAME (-22106) +%define VERR_VFS_CHAIN_EXPECTED_ACTION (-22107) +%define VERR_VFS_CHAIN_MULTIPLE_ACTIONS (-22108) +%define VERR_VFS_CHAIN_NO_ACTION (-22109) +%define VERR_VFS_CHAIN_EXPECTED_PIPE (-22110) +%define VERR_VFS_CHAIN_UNEXPECTED_ACTION_TYPE (-22111) +%define VERR_DVM_MAP_EMPTY (-22200) +%define VERR_DVM_MAP_NO_VOLUME (-22201) +%define VERR_LOG_REVISION_MISMATCH (-22300) +%define VERR_SYS_CANNOT_POWER_OFF (-22500) +%define VINF_SYS_MAY_POWER_OFF (22501) +%define VERR_SYS_SHUTDOWN_FAILED (-22502) +%define VERR_FILESYSTEM_CORRUPT (-22600) diff --git a/include/iprt/err.sed b/include/iprt/err.sed new file mode 100644 index 00000000..2271331c --- /dev/null +++ b/include/iprt/err.sed @@ -0,0 +1,45 @@ +## @file +# IPRT - SED script for converting VBox/err.h to .mac. +# + +# +# Copyright (C) 2006-2009 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. +# + +# Handle text inside the markers. +/SED-START/,/SED-END/{ + +# if (#define) goto defines +/^[[:space:]]*#[[:space:]]*define/b defines + +} + +# Everything else is deleted! +d +b end + +## +# Convert the defines +:defines +s/^[[:space:]]*#[[:space:]]*define[[:space:]]*\([[:alnum:]_]*\)[[:space:]]*\(.*\)[[:space:]]*$/%define \1 \2/ +b end + +# next expression +:end diff --git a/include/iprt/errno.h b/include/iprt/errno.h new file mode 100644 index 00000000..ee57065d --- /dev/null +++ b/include/iprt/errno.h @@ -0,0 +1,318 @@ +/** @file + * IPRT - errno.h wrapper. + */ + +/* + * Copyright (C) 2012 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. + */ + + +#ifndef ___iprt_errno_h___ +#define ___iprt_errno_h___ + +#ifndef IPRT_NO_CRT +# if defined(RT_OS_DARWIN) && defined(KERNEL) +# include <sys/errno.h> +# elif defined(RT_OS_LINUX) && defined(__KERNEL__) +# include <linux/errno.h> +# elif defined(RT_OS_FREEBSD) && defined(_KERNEL) +# include <sys/errno.h> +# else +# include <errno.h> +# endif +#endif + + +/* + * Supply missing errno values according to the current RT_OS_XXX definition. + * + * Note! These supplements are for making no-CRT mode, as well as making UNIXy + * code that makes used of odd errno defines internally, work smoothly. + * + * When adding more error codes, always check the following errno.h sources: + * - RT_OS_DARWIN: http://fxr.watson.org/fxr/source/bsd/sys/errno.h?v=xnu-1699.24.8 + * - RT_OS_FREEBSD: http://fxr.watson.org/fxr/source/sys/errno.h?v=DFBSD + * - RT_OS_NETBSD: http://fxr.watson.org/fxr/source/sys/errno.h?v=NETBSD + * - RT_OS_OPENBSD: http://fxr.watson.org/fxr/source/sys/errno.h?v=OPENBSD + * - RT_OS_OS2: http://svn.netlabs.org/libc/browser/trunk/libc/include/sys/errno.h + * - RT_OS_LINUX: http://fxr.watson.org/fxr/source/include/asm-generic/errno.h?v=linux-2.6 + * - RT_OS_SOLARIS: http://fxr.watson.org/fxr/source/common/sys/errno.h?v=OPENSOLARIS + * - RT_OS_WINDOWS: tools/win.x86/vcc/v8sp1/include/errno.h + */ + +#if defined(RT_OS_DARWIN) \ + || defined(RT_OS_FREEBSD) \ + || defined(RT_OS_NETBSD) \ + || defined(RT_OS_OPENBSD) \ + || defined(RT_OS_OS2) +# define RT_ERRNO_OS_BSD +#endif +#ifdef RT_OS_SOLARIS +# define RT_ERRNO_OS_SYSV_HARDCORE /* ?? */ +#endif + +/* The relatively similar part. */ +#ifndef EPERM +# define EPERM (1) +#endif +#ifndef ENOENT +# define ENOENT (2) +#endif +#ifndef ESRCH +# define ESRCH (3) +#endif +#ifndef EINTR +# define EINTR (4) +#endif +#ifndef EIO +# define EIO (5) +#endif +#ifndef ENXIO +# define ENXIO (6) +#endif +#ifndef E2BIG +# define E2BIG (7) +#endif +#ifndef ENOEXEC +# define ENOEXEC (8) +#endif +#ifndef EBADF +# define EBADF (9) +#endif +#ifndef ECHILD +# define ECHILD (10) +#endif +#ifndef EAGAIN +# if defined(RT_ERRNO_OS_BSD) +# define EAGAIN (35) +# else +# define EAGAIN (11) +# endif +#endif +#ifndef EWOULDBLOCK +# define EWOULDBLOCK EAGAIN +#endif +#ifndef EDEADLK +# if defined(RT_ERRNO_OS_BSD) +# define EDEADLK (11) +# elif defined(RT_OS_LINUX) +# define EDEADLK (35) +# elif defined(RT_OS_WINDOWS) +# define EDEADLK (36) +# else +# define EDEADLK (45) +# endif +#endif +#ifndef EDEADLOCK +# define EDEADLOCK EDEADLK +#endif +#ifndef ENOMEM +# define ENOMEM (12) +#endif +#ifndef EACCES +# define EACCES (13) +#endif +#ifndef EFAULT +# define EFAULT (14) +#endif +#ifndef ENOTBLK +# define ENOTBLK (15) +#endif +#ifndef EBUSY +# define EBUSY (16) +#endif +#ifndef EEXIST +# define EEXIST (17) +#endif +#ifndef EXDEV +# define EXDEV (18) +#endif +#ifndef ENODEV +# define ENODEV (19) +#endif +#ifndef ENOTDIR +# define ENOTDIR (20) +#endif +#ifndef EISDIR +# define EISDIR (21) +#endif +#ifndef EINVAL +# define EINVAL (22) +#endif +#ifndef ENFILE +# define ENFILE (23) +#endif +#ifndef EMFILE +# define EMFILE (24) +#endif +#ifndef ENOTTY +# define ENOTTY (25) +#endif +#ifndef ETXTBSY +# define ETXTBSY (26) +#endif +#ifndef EFBIG +# define EFBIG (27) +#endif +#ifndef ENOSPC +# define ENOSPC (28) +#endif +#ifndef ESPIPE +# define ESPIPE (29) +#endif +#ifndef EROFS +# define EROFS (30) +#endif +#ifndef EMLINK +# define EMLINK (31) +#endif +#ifndef EPIPE +# define EPIPE (32) +#endif +#ifndef EDOM +# define EDOM (33) +#endif +#ifndef ERANGE +# define ERANGE (34) +#endif + +/* 35 - also EAGAIN on BSD and EDEADLK on Linux. */ +#ifndef ENOMSG +# if defined(RT_OS_DARWIN) +# define ENOMSG (91) +# elif defined(RT_OS_FREEBSD) +# define ENOMSG (83) +# elif defined(RT_OS_LINUX) +# define ENOMSG (42) +# else +# define ENOMSG (35) +# endif +#endif + +/* 36 - Also EDEADLK on Windows. */ +#ifndef EIDRM +# if defined(RT_OS_DARWIN) +# define EIDRM (90) +# elif defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) +# define EIDRM (82) +# elif defined(RT_OS_OPENBSD) +# define EIDRM (89) +# elif defined(RT_OS_LINUX) +# define EIDRM (43) +# elif defined(RT_OS_WINDOWS) +# define EIDRM (600) +# else +# define EIDRM (36) +# endif +#endif +#ifndef EINPROGRESS +# if defined(RT_ERRNO_OS_BSD) +# define EINPROGRESS (36) +# elif defined(RT_OS_LINUX) +# define EINPROGRESS (115) +# else +# define EINPROGRESS (150) +# endif +#endif +#ifndef ENAMETOOLONG +# if defined(RT_ERRNO_OS_BSD) +# define ENAMETOOLONG (63) +# elif defined(RT_OS_LINUX) +# define ENAMETOOLONG (36) +# else +# define ENAMETOOLONG (78) +# endif +#endif + +/* 37 */ +#ifndef ECHRNG +# if defined(RT_ERRNO_OS_SYSV_HARDCORE) +# define ECHRNG (37) +# else +# define ECHRNG (599) +# endif +#endif +#ifndef ENOLCK +# if defined(RT_ERRNO_OS_BSD) +# define ENOLCK (77) +# elif defined(RT_OS_LINUX) +# define ENOLCK (37) +# else +# define ENOLCK (46) +# endif +#endif +#ifndef EALREADY +# if defined(RT_ERRNO_OS_BSD) +# define EALREADY (37) +# elif defined(RT_OS_LINUX) +# define EALREADY (114) +# else +# define EALREADY (149) +# endif +#endif + +/** @todo errno constants {37..44}. */ + +/* 45 - also EDEADLK on Solaris, EL2NSYNC on Linux. */ +#ifndef ENOTSUP +# if defined(RT_ERRNO_OS_BSD) +# define ENOTSUP (45) +# elif defined(RT_OS_LINUX) +# define ENOTSUP (95) +# else +# define ENOTSUP (48) +# endif +#endif +#ifndef EOPNOTSUPP +# if defined(RT_ERRNO_OS_BSD) +# define EOPNOTSUPP ENOTSUP +# elif defined(RT_OS_LINUX) +# define EOPNOTSUPP ENOTSUP +# else +# define EOPNOTSUPP (122) +# endif +#endif + +/** @todo errno constants {46..74}. */ + +/* 75 - note that Solaris has constant with value 75. */ +#ifndef EOVERFLOW +# if defined(RT_OS_OPENBSD) +# define EOVERFLOW (87) +# elif defined(RT_ERRNO_OS_BSD) +# define EOVERFLOW (84) +# elif defined(RT_OS_LINUX) +# define EOVERFLOW (75) +# else +# define EOVERFLOW (79) +# endif +#endif +#ifndef EPROGMISMATCH +# if defined(RT_ERRNO_OS_BSD) +# define EPROGMISMATCH (75) +# else +# define EPROGMISMATCH (598) +# endif +#endif + +/** @todo errno constants {76..}. */ + + +#endif diff --git a/include/iprt/file.h b/include/iprt/file.h new file mode 100644 index 00000000..3357ab23 --- /dev/null +++ b/include/iprt/file.h @@ -0,0 +1,1339 @@ +/** @file + * IPRT - File I/O. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_file_h +#define ___iprt_file_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> +#include <iprt/fs.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_fileio RTFile - File I/O + * @ingroup grp_rt + * @{ + */ + +/** Platform specific text line break. + * @deprecated Use text I/O streams and '\\n'. See iprt/stream.h. */ +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +# define RTFILE_LINEFEED "\r\n" +#else +# define RTFILE_LINEFEED "\n" +#endif + +/** Platform specific native standard input "handle". */ +#ifdef RT_OS_WINDOWS +# define RTFILE_NATIVE_STDIN ((uint32_t)-10) +#else +# define RTFILE_NATIVE_STDIN 0 +#endif + +/** Platform specific native standard out "handle". */ +#ifdef RT_OS_WINDOWS +# define RTFILE_NATIVE_STDOUT ((uint32_t)-11) +#else +# define RTFILE_NATIVE_STDOUT 1 +#endif + +/** Platform specific native standard error "handle". */ +#ifdef RT_OS_WINDOWS +# define RTFILE_NATIVE_STDERR ((uint32_t)-12) +#else +# define RTFILE_NATIVE_STDERR 2 +#endif + + +/** + * Checks if the specified file name exists and is a regular file. + * + * Symbolic links will be resolved. + * + * @returns true if it's a regular file, false if it isn't. + * @param pszPath The path to the file. + * + * @sa RTDirExists, RTPathExists, RTSymlinkExists. + */ +RTDECL(bool) RTFileExists(const char *pszPath); + +/** + * Queries the size of a file, given the path to it. + * + * Symbolic links will be resolved. + * + * @returns IPRT status code. + * @param pszPath The path to the file. + * @param pcbFile Where to return the file size (bytes). + * + * @sa RTFileGetSize, RTPathQueryInfoEx. + */ +RTDECL(int) RTFileQuerySize(const char *pszPath, uint64_t *pcbFile); + + +/** @name Open flags + * @{ */ +/** Open the file with read access. */ +#define RTFILE_O_READ UINT32_C(0x00000001) +/** Open the file with write access. */ +#define RTFILE_O_WRITE UINT32_C(0x00000002) +/** Open the file with read & write access. */ +#define RTFILE_O_READWRITE UINT32_C(0x00000003) +/** The file access mask. + * @remarks The value 0 is invalid. */ +#define RTFILE_O_ACCESS_MASK UINT32_C(0x00000003) + +/** Open file in APPEND mode, so all writes to the file handle will + * append data at the end of the file. + * @remarks It is ignored if write access is not requested, that is + * RTFILE_O_WRITE is not set. */ +#define RTFILE_O_APPEND UINT32_C(0x00000004) + /* UINT32_C(0x00000008) is unused atm. */ + +/** Sharing mode: deny none. */ +#define RTFILE_O_DENY_NONE UINT32_C(0x00000080) +/** Sharing mode: deny read. */ +#define RTFILE_O_DENY_READ UINT32_C(0x00000010) +/** Sharing mode: deny write. */ +#define RTFILE_O_DENY_WRITE UINT32_C(0x00000020) +/** Sharing mode: deny read and write. */ +#define RTFILE_O_DENY_READWRITE UINT32_C(0x00000030) +/** Sharing mode: deny all. */ +#define RTFILE_O_DENY_ALL RTFILE_O_DENY_READWRITE +/** Sharing mode: do NOT deny delete (NT). + * @remarks This might not be implemented on all platforms, and will be + * defaulted & ignored on those. + */ +#define RTFILE_O_DENY_NOT_DELETE UINT32_C(0x00000040) +/** Sharing mode mask. */ +#define RTFILE_O_DENY_MASK UINT32_C(0x000000f0) + +/** Action: Open an existing file (the default action). */ +#define RTFILE_O_OPEN UINT32_C(0x00000700) +/** Action: Create a new file or open an existing one. */ +#define RTFILE_O_OPEN_CREATE UINT32_C(0x00000100) +/** Action: Create a new a file. */ +#define RTFILE_O_CREATE UINT32_C(0x00000200) +/** Action: Create a new file or replace an existing one. */ +#define RTFILE_O_CREATE_REPLACE UINT32_C(0x00000300) +/** Action mask. */ +#define RTFILE_O_ACTION_MASK UINT32_C(0x00000700) + +/** Turns off indexing of files on Windows hosts, *CREATE* only. + * @remarks Window only. */ +#define RTFILE_O_NOT_CONTENT_INDEXED UINT32_C(0x00000800) +/** Truncate the file. + * @remarks This will not truncate files opened for read-only. + * @remarks The trunction doesn't have to be atomically, so anyone else opening + * the file may be racing us. The caller is responsible for not causing + * this race. */ +#define RTFILE_O_TRUNCATE UINT32_C(0x00001000) +/** Make the handle inheritable on RTProcessCreate(/exec). */ +#define RTFILE_O_INHERIT UINT32_C(0x00002000) +/** Open file in non-blocking mode - non-portable. + * @remarks This flag may not be supported on all platforms, in which case it's + * considered an invalid parameter. */ +#define RTFILE_O_NON_BLOCK UINT32_C(0x00004000) +/** Write through directly to disk. Workaround to avoid iSCSI + * initiator deadlocks on Windows hosts. + * @remarks This might not be implemented on all platforms, and will be ignored + * on those. */ +#define RTFILE_O_WRITE_THROUGH UINT32_C(0x00008000) + +/** Attribute access: Attributes can be read if the file is being opened with + * read access, and can be written with write access. */ +#define RTFILE_O_ACCESS_ATTR_DEFAULT UINT32_C(0x00000000) +/** Attribute access: Attributes can be read. + * @remarks Windows only. */ +#define RTFILE_O_ACCESS_ATTR_READ UINT32_C(0x00010000) +/** Attribute access: Attributes can be written. + * @remarks Windows only. */ +#define RTFILE_O_ACCESS_ATTR_WRITE UINT32_C(0x00020000) +/** Attribute access: Attributes can be both read & written. + * @remarks Windows only. */ +#define RTFILE_O_ACCESS_ATTR_READWRITE UINT32_C(0x00030000) +/** Attribute access: The file attributes access mask. + * @remarks Windows only. */ +#define RTFILE_O_ACCESS_ATTR_MASK UINT32_C(0x00030000) + +/** Open file for async I/O + * @remarks This flag may not be needed on all platforms, and will be ignored on + * those. */ +#define RTFILE_O_ASYNC_IO UINT32_C(0x00040000) + +/** Disables caching. + * + * Useful when using very big files which might bring the host I/O scheduler to + * its knees during high I/O load. + * + * @remarks This flag might impose restrictions + * on the buffer alignment, start offset and/or transfer size. + * + * On Linux the buffer needs to be aligned to the 512 sector + * boundary. + * + * On Windows the FILE_FLAG_NO_BUFFERING is used (see + * http://msdn.microsoft.com/en-us/library/cc644950(VS.85).aspx ). + * The buffer address, the transfer size and offset needs to be aligned + * to the sector size of the volume. Furthermore FILE_APPEND_DATA is + * disabled. To write beyond the size of file use RTFileSetSize prior + * writing the data to the file. + * + * This flag does not work on Solaris if the target filesystem is ZFS. + * RTFileOpen will return an error with that configuration. When used + * with UFS the same alginment restrictions apply like Linux and + * Windows. + * + * @remarks This might not be implemented on all platforms, and will be ignored + * on those. + */ +#define RTFILE_O_NO_CACHE UINT32_C(0x00080000) + +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTFILE_O_NO_SYMLINKS UINT32_C(0x20000000) + +/** Unix file mode mask for use when creating files. */ +#define RTFILE_O_CREATE_MODE_MASK UINT32_C(0x1ff00000) +/** The number of bits to shift to get the file mode mask. + * To extract it: (fFlags & RTFILE_O_CREATE_MODE_MASK) >> RTFILE_O_CREATE_MODE_SHIFT. + */ +#define RTFILE_O_CREATE_MODE_SHIFT 20 + + /* UINT32_C(0x40000000) + and UINT32_C(0x80000000) are unused atm. */ + +/** Mask of all valid flags. + * @remark This doesn't validate the access mode properly. + */ +#define RTFILE_O_VALID_MASK UINT32_C(0x3ffffff7) + +/** @} */ + + +#ifdef IN_RING3 +/** + * Force the use of open flags for all files opened after the setting is + * changed. The caller is responsible for not causing races with RTFileOpen(). + * + * @returns iprt status code. + * @param fOpenForAccess Access mode to which the set/mask settings apply. + * @param fSet Open flags to be forced set. + * @param fMask Open flags to be masked out. + */ +RTR3DECL(int) RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask); +#endif /* IN_RING3 */ + +/** + * Open a file. + * + * @returns iprt status code. + * @param pFile Where to store the handle to the opened file. + * @param pszFilename Path to the file which is to be opened. (UTF-8) + * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines. + * The ACCESS, ACTION and DENY flags are mandatory! + */ +RTDECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen); + +/** + * Open a file given as a format string. + * + * @returns iprt status code. + * @param pFile Where to store the handle to the opened file. + * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines. + * The ACCESS, ACTION and DENY flags are mandatory! + * @param pszFilenameFmt Format string givin the path to the file which is to + * be opened. (UTF-8) + * @param ... Arguments to the format string. + */ +RTDECL(int) RTFileOpenF(PRTFILE pFile, uint64_t fOpen, const char *pszFilenameFmt, ...); + +/** + * Open a file given as a format string. + * + * @returns iprt status code. + * @param pFile Where to store the handle to the opened file. + * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines. + * The ACCESS, ACTION and DENY flags are mandatory! + * @param pszFilenameFmt Format string givin the path to the file which is to + * be opened. (UTF-8) + * @param va Arguments to the format string. + */ +RTDECL(int) RTFileOpenV(PRTFILE pFile, uint64_t fOpen, const char *pszFilenameFmt, va_list va); + +/** + * Open the bit bucket (aka /dev/null or nul). + * + * @returns IPRT status code. + * @param phFile Where to store the handle to the opened file. + * @param fAccess The desired access only, i.e. read, write or both. + */ +RTDECL(int) RTFileOpenBitBucket(PRTFILE phFile, uint64_t fAccess); + +/** + * Close a file opened by RTFileOpen(). + * + * @returns iprt status code. + * @param File The file handle to close. + */ +RTDECL(int) RTFileClose(RTFILE File); + +/** + * Creates an IPRT file handle from a native one. + * + * @returns IPRT status code. + * @param pFile Where to store the IPRT file handle. + * @param uNative The native handle. + */ +RTDECL(int) RTFileFromNative(PRTFILE pFile, RTHCINTPTR uNative); + +/** + * Gets the native handle for an IPRT file handle. + * + * @return The native handle. + * @param File The IPRT file handle. + */ +RTDECL(RTHCINTPTR) RTFileToNative(RTFILE File); + +/** + * Delete a file. + * + * @returns iprt status code. + * @param pszFilename Path to the file which is to be deleted. (UTF-8) + * @todo This is a RTPath api! + */ +RTDECL(int) RTFileDelete(const char *pszFilename); + +/** @name Seek flags. + * @{ */ +/** Seek from the start of the file. */ +#define RTFILE_SEEK_BEGIN 0x00 +/** Seek from the current file position. */ +#define RTFILE_SEEK_CURRENT 0x01 +/** Seek from the end of the file. */ +#define RTFILE_SEEK_END 0x02 +/** @internal */ +#define RTFILE_SEEK_FIRST RTFILE_SEEK_BEGIN +/** @internal */ +#define RTFILE_SEEK_LAST RTFILE_SEEK_END +/** @} */ + + +/** + * Changes the read & write position in a file. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param offSeek Offset to seek. + * @param uMethod Seek method, i.e. one of the RTFILE_SEEK_* defines. + * @param poffActual Where to store the new file position. + * NULL is allowed. + */ +RTDECL(int) RTFileSeek(RTFILE File, int64_t offSeek, unsigned uMethod, uint64_t *poffActual); + +/** + * Read bytes from a file. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param pvBuf Where to put the bytes we read. + * @param cbToRead How much to read. + * @param *pcbRead How much we actually read . + * If NULL an error will be returned for a partial read. + */ +RTDECL(int) RTFileRead(RTFILE File, void *pvBuf, size_t cbToRead, size_t *pcbRead); + +/** + * Read bytes from a file at a given offset. + * This function may modify the file position. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param off Where to read. + * @param pvBuf Where to put the bytes we read. + * @param cbToRead How much to read. + * @param *pcbRead How much we actually read . + * If NULL an error will be returned for a partial read. + */ +RTDECL(int) RTFileReadAt(RTFILE File, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead); + +/** + * Write bytes to a file. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param pvBuf What to write. + * @param cbToWrite How much to write. + * @param *pcbWritten How much we actually wrote. + * If NULL an error will be returned for a partial write. + */ +RTDECL(int) RTFileWrite(RTFILE File, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten); + +/** + * Write bytes to a file at a given offset. + * This function may modify the file position. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param off Where to write. + * @param pvBuf What to write. + * @param cbToWrite How much to write. + * @param *pcbWritten How much we actually wrote. + * If NULL an error will be returned for a partial write. + */ +RTDECL(int) RTFileWriteAt(RTFILE File, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten); + +/** + * Flushes the buffers for the specified file. + * + * @returns iprt status code. + * @param File Handle to the file. + */ +RTDECL(int) RTFileFlush(RTFILE File); + +/** + * Set the size of the file. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param cbSize The new file size. + */ +RTDECL(int) RTFileSetSize(RTFILE File, uint64_t cbSize); + +/** + * Query the size of the file. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param pcbSize Where to store the filesize. + */ +RTDECL(int) RTFileGetSize(RTFILE File, uint64_t *pcbSize); + +/** + * Determine the maximum file size. + * + * @returns The max size of the file. + * -1 on failure, the file position is undefined. + * @param File Handle to the file. + * @see RTFileGetMaxSizeEx. + */ +RTDECL(RTFOFF) RTFileGetMaxSize(RTFILE File); + +/** + * Determine the maximum file size. + * + * @returns IPRT status code. + * @param File Handle to the file. + * @param pcbMax Where to store the max file size. + * @see RTFileGetMaxSize. + */ +RTDECL(int) RTFileGetMaxSizeEx(RTFILE File, PRTFOFF pcbMax); + +/** + * Determine the maximum file size depending on the file system the file is stored on. + * + * @returns The max size of the file. + * -1 on failure. + * @param File Handle to the file. + */ +RTDECL(RTFOFF) RTFileGetMaxSize(RTFILE File); + +/** + * Gets the current file position. + * + * @returns File offset. + * @returns ~0UUL on failure. + * @param File Handle to the file. + */ +RTDECL(uint64_t) RTFileTell(RTFILE File); + +/** + * Checks if the supplied handle is valid. + * + * @returns true if valid. + * @returns false if invalid. + * @param File The file handle + */ +RTDECL(bool) RTFileIsValid(RTFILE File); + +/** + * Copies a file. + * + * @returns VERR_ALREADY_EXISTS if the destination file exists. + * @returns VBox Status code. + * + * @param pszSrc The path to the source file. + * @param pszDst The path to the destination file. + * This file will be created. + */ +RTDECL(int) RTFileCopy(const char *pszSrc, const char *pszDst); + +/** + * Copies a file given the handles to both files. + * + * @returns VBox Status code. + * + * @param FileSrc The source file. The file position is unaltered. + * @param FileDst The destination file. + * On successful returns the file position is at the end of the file. + * On failures the file position and size is undefined. + */ +RTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst); + +/** Flags for RTFileCopyEx(). + * @{ */ +/** Do not use RTFILE_O_DENY_WRITE on the source file to allow for copying files opened for writing. */ +#define RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE RT_BIT(0) +/** Do not use RTFILE_O_DENY_WRITE on the target file. */ +#define RTFILECOPY_FLAGS_NO_DST_DENY_WRITE RT_BIT(1) +/** Do not use RTFILE_O_DENY_WRITE on either of the two files. */ +#define RTFILECOPY_FLAGS_NO_DENY_WRITE ( RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE | RTFILECOPY_FLAGS_NO_DST_DENY_WRITE ) +/** */ +#define RTFILECOPY_FLAGS_MASK UINT32_C(0x00000003) +/** @} */ + +/** + * Copies a file. + * + * @returns VERR_ALREADY_EXISTS if the destination file exists. + * @returns VBox Status code. + * + * @param pszSrc The path to the source file. + * @param pszDst The path to the destination file. + * This file will be created. + * @param fFlags Flags (RTFILECOPY_*). + * @param pfnProgress Pointer to callback function for reporting progress. + * @param pvUser User argument to pass to pfnProgress along with the completion percentage. + */ +RTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser); + +/** + * Copies a file given the handles to both files and + * provide progress callbacks. + * + * @returns IPRT status code. + * + * @param FileSrc The source file. The file position is unaltered. + * @param FileDst The destination file. + * On successful returns the file position is at the end of the file. + * On failures the file position and size is undefined. + * @param pfnProgress Pointer to callback function for reporting progress. + * @param pvUser User argument to pass to pfnProgress along with the completion percentage. + */ +RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser); + +/** + * Renames a file. + * + * Identical to RTPathRename except that it will ensure that the source is not a directory. + * + * @returns IPRT status code. + * @returns VERR_ALREADY_EXISTS if the destination file exists. + * + * @param pszSrc The path to the source file. + * @param pszDst The path to the destination file. + * This file will be created. + * @param fRename See RTPathRename. + */ +RTDECL(int) RTFileRename(const char *pszSrc, const char *pszDst, unsigned fRename); + + +/** @name RTFileMove flags (bit masks). + * @{ */ +/** Replace destination file if present. */ +#define RTFILEMOVE_FLAGS_REPLACE 0x1 +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTFILEMOVE_FLAGS_NO_SYMLINKS 0x2 +/** @} */ + +/** + * Moves a file. + * + * RTFileMove differs from RTFileRename in that it works across volumes. + * + * @returns IPRT status code. + * @returns VERR_ALREADY_EXISTS if the destination file exists. + * + * @param pszSrc The path to the source file. + * @param pszDst The path to the destination file. + * This file will be created. + * @param fMove A combination of the RTFILEMOVE_* flags. + */ +RTDECL(int) RTFileMove(const char *pszSrc, const char *pszDst, unsigned fMove); + + +/** + * Creates a new file with a unique name using the given template. + * + * One or more trailing X'es in the template will be replaced by random alpha + * numeric characters until a RTFileOpen with RTFILE_O_CREATE succeeds or we + * run out of patience. + * For instance: + * "/tmp/myprog-XXXXXX" + * + * As an alternative to trailing X'es, it is possible to put 3 or more X'es + * somewhere inside the file name. In the following string only the last + * bunch of X'es will be modified: + * "/tmp/myprog-XXX-XXX.tmp" + * + * @returns iprt status code. + * @param pszTemplate The file name template on input. The actual file + * name on success. Empty string on failure. + * @param fMode The mode to create the file with. Use 0600 unless + * you have reason not to. + */ +RTDECL(int) RTFileCreateTemp(char *pszTemplate, RTFMODE fMode); + +/** + * Secure version of @a RTFileCreateTemp with a fixed mode of 0600. + * + * This function behaves in the same way as @a RTFileCreateTemp with two + * additional points. Firstly the mode is fixed to 0600. Secondly it will + * fail if it is not possible to perform the operation securely. Possible + * reasons include that the file could be removed by another unprivileged + * user before it is used (e.g. if is created in a non-sticky /tmp directory) + * or that the path contains symbolic links which another unprivileged user + * could manipulate; however the exact criteria will be specified on a + * platform-by-platform basis as platform support is added. + * @see RTPathIsSecure for the current list of criteria. + * @returns iprt status code. + * @returns VERR_NOT_SUPPORTED if the interface can not be supported on the + * current platform at this time. + * @returns VERR_INSECURE if the file could not be created securely. + * @param pszTemplate The file name template on input. The actual + * file name on success. Empty string on failure. + */ +RTDECL(int) RTFileCreateTempSecure(char *pszTemplate); + + +/** @page pg_rt_filelock RT File locking API description + * + * File locking general rules: + * + * Region to lock or unlock can be located beyond the end of file, this can be used for + * growing files. + * Read (or Shared) locks can be acquired held by an unlimited number of processes at the + * same time, but a Write (or Exclusive) lock can only be acquired by one process, and + * cannot coexist with a Shared lock. To acquire a Read lock, a process must wait until + * there are no processes holding any Write locks. To acquire a Write lock, a process must + * wait until there are no processes holding either kind of lock. + * By default, RTFileLock and RTFileChangeLock calls returns error immediately if the lock + * can't be acquired due to conflict with other locks, however they can be called in wait mode. + * + * Differences in implementation: + * + * Win32, OS/2: Locking is mandatory, since locks are enforced by the operating system. + * I.e. when file region is locked in Read mode, any write in it will fail; in case of Write + * lock - region can be read and writed only by lock's owner. + * + * Win32: File size change (RTFileSetSize) is not controlled by locking at all (!) in the + * operation system. Also see comments to RTFileChangeLock API call. + * + * Linux/Posix: By default locks in Unixes are advisory. This means that cooperating processes + * may use locks to coordinate access to a file between themselves, but programs are also free + * to ignore locks and access the file in any way they choose to. + * + * Additional reading: + * http://en.wikipedia.org/wiki/File_locking + * http://unixhelp.ed.ac.uk/CGI/man-cgi?fcntl+2 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/lockfileex.asp + */ + +/** @name Lock flags (bit masks). + * @{ */ +/** Read access, can be shared with others. */ +#define RTFILE_LOCK_READ 0x00 +/** Write access, one at a time. */ +#define RTFILE_LOCK_WRITE 0x01 +/** Don't wait for other locks to be released. */ +#define RTFILE_LOCK_IMMEDIATELY 0x00 +/** Wait till conflicting locks have been released. */ +#define RTFILE_LOCK_WAIT 0x02 +/** Valid flags mask */ +#define RTFILE_LOCK_MASK 0x03 +/** @} */ + + +/** + * Locks a region of file for read (shared) or write (exclusive) access. + * + * @returns iprt status code. + * @returns VERR_FILE_LOCK_VIOLATION if lock can't be acquired. + * @param File Handle to the file. + * @param fLock Lock method and flags, see RTFILE_LOCK_* defines. + * @param offLock Offset of lock start. + * @param cbLock Length of region to lock, may overlap the end of file. + */ +RTDECL(int) RTFileLock(RTFILE File, unsigned fLock, int64_t offLock, uint64_t cbLock); + +/** + * Changes a lock type from read to write or from write to read. + * The region to type change must correspond exactly to an existing locked region. + * If change can't be done due to locking conflict and non-blocking mode is used, error is + * returned and lock keeps its state (see next warning). + * + * WARNING: win32 implementation of this call is not atomic, it transforms to a pair of + * calls RTFileUnlock and RTFileLock. Potentially the previously acquired lock can be + * lost, i.e. function is called in non-blocking mode, previous lock is freed, new lock can't + * be acquired, and old lock (previous state) can't be acquired back too. This situation + * may occurs _only_ if the other process is acquiring a _write_ lock in blocking mode or + * in race condition with the current call. + * In this very bad case special error code VERR_FILE_LOCK_LOST will be returned. + * + * @returns iprt status code. + * @returns VERR_FILE_NOT_LOCKED if region was not locked. + * @returns VERR_FILE_LOCK_VIOLATION if lock type can't be changed, lock remains its type. + * @returns VERR_FILE_LOCK_LOST if lock was lost, we haven't this lock anymore :( + * @param File Handle to the file. + * @param fLock Lock method and flags, see RTFILE_LOCK_* defines. + * @param offLock Offset of lock start. + * @param cbLock Length of region to lock, may overlap the end of file. + */ +RTDECL(int) RTFileChangeLock(RTFILE File, unsigned fLock, int64_t offLock, uint64_t cbLock); + +/** + * Unlocks previously locked region of file. + * The region to unlock must correspond exactly to an existing locked region. + * + * @returns iprt status code. + * @returns VERR_FILE_NOT_LOCKED if region was not locked. + * @param File Handle to the file. + * @param offLock Offset of lock start. + * @param cbLock Length of region to unlock, may overlap the end of file. + */ +RTDECL(int) RTFileUnlock(RTFILE File, int64_t offLock, uint64_t cbLock); + + +/** + * Query information about an open file. + * + * @returns iprt status code. + * + * @param File Handle to the file. + * @param pObjInfo Object information structure to be filled on successful return. + * @param enmAdditionalAttribs Which set of additional attributes to request. + * Use RTFSOBJATTRADD_NOTHING if this doesn't matter. + */ +RTDECL(int) RTFileQueryInfo(RTFILE File, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs); + +/** + * Changes one or more of the timestamps associated of file system object. + * + * @returns iprt status code. + * @retval VERR_NOT_SUPPORTED is returned if the operation isn't supported by + * the OS. + * + * @param File Handle to the file. + * @param pAccessTime Pointer to the new access time. NULL if not to be changed. + * @param pModificationTime Pointer to the new modifcation time. NULL if not to be changed. + * @param pChangeTime Pointer to the new change time. NULL if not to be changed. + * @param pBirthTime Pointer to the new time of birth. NULL if not to be changed. + * + * @remark The file system might not implement all these time attributes, + * the API will ignore the ones which aren't supported. + * + * @remark The file system might not implement the time resolution + * employed by this interface, the time will be chopped to fit. + * + * @remark The file system may update the change time even if it's + * not specified. + * + * @remark POSIX can only set Access & Modification and will always set both. + */ +RTDECL(int) RTFileSetTimes(RTFILE File, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, + PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime); + +/** + * Gets one or more of the timestamps associated of file system object. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param pAccessTime Where to store the access time. NULL is ok. + * @param pModificationTime Where to store the modifcation time. NULL is ok. + * @param pChangeTime Where to store the change time. NULL is ok. + * @param pBirthTime Where to store the time of birth. NULL is ok. + * + * @remark This is wrapper around RTFileQueryInfo() and exists to complement RTFileSetTimes(). + */ +RTDECL(int) RTFileGetTimes(RTFILE File, PRTTIMESPEC pAccessTime, PRTTIMESPEC pModificationTime, + PRTTIMESPEC pChangeTime, PRTTIMESPEC pBirthTime); + +/** + * Changes the mode flags of an open file. + * + * The API requires at least one of the mode flag sets (Unix/Dos) to + * be set. The type is ignored. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param fMode The new file mode, see @ref grp_rt_fs for details. + */ +RTDECL(int) RTFileSetMode(RTFILE File, RTFMODE fMode); + +/** + * Gets the mode flags of an open file. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param pfMode Where to store the file mode, see @ref grp_rt_fs for details. + * + * @remark This is wrapper around RTFileQueryInfo() + * and exists to complement RTFileSetMode(). + */ +RTDECL(int) RTFileGetMode(RTFILE File, uint32_t *pfMode); + +/** + * Changes the owner and/or group of an open file. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param uid The new file owner user id. Pass NIL_RTUID to leave + * this unchanged. + * @param gid The new group id. Pass NIL_RTGID to leave this + * unchanged. + */ +RTDECL(int) RTFileSetOwner(RTFILE File, uint32_t uid, uint32_t gid); + +/** + * Gets the owner and/or group of an open file. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param pUid Where to store the owner user id. NULL is ok. + * @param pGid Where to store the group id. NULL is ok. + * + * @remark This is wrapper around RTFileQueryInfo() and exists to complement RTFileGetOwner(). + */ +RTDECL(int) RTFileGetOwner(RTFILE File, uint32_t *pUid, uint32_t *pGid); + +/** + * Executes an IOCTL on a file descriptor. + * + * This function is currently only available in L4 and posix environments. + * Attemps at calling it from code shared with any other platforms will break things! + * + * The rational for defining this API is to simplify L4 porting of audio drivers, + * and to remove some of the assumptions on RTFILE being a file descriptor on + * platforms using the posix file implementation. + * + * @returns iprt status code. + * @param File Handle to the file. + * @param iRequest IOCTL request to carry out. + * @param pvData IOCTL data. + * @param cbData Size of the IOCTL data. + * @param piRet Return value of the IOCTL request. + */ +RTDECL(int) RTFileIoCtl(RTFILE File, unsigned long ulRequest, void *pvData, unsigned cbData, int *piRet); + +/** + * Query the sizes of a filesystem. + * + * @returns iprt status code. + * @retval VERR_NOT_SUPPORTED is returned if the operation isn't supported by + * the OS. + * + * @param hFile The file handle. + * @param pcbTotal Where to store the total filesystem space. (Optional) + * @param pcbFree Where to store the remaining free space in the filesystem. (Optional) + * @param pcbBlock Where to store the block size. (Optional) + * @param pcbSector Where to store the sector size. (Optional) + * + * @sa RTFsQuerySizes + */ +RTDECL(int) RTFileQueryFsSizes(RTFILE hFile, PRTFOFF pcbTotal, RTFOFF *pcbFree, + uint32_t *pcbBlock, uint32_t *pcbSector); + +/** + * Reads the file into memory. + * + * The caller must free the memory using RTFileReadAllFree(). + * + * @returns IPRT status code. + * @param pszFilename The name of the file. + * @param ppvFile Where to store the pointer to the memory on successful return. + * @param pcbFile Where to store the size of the returned memory. + * + * @remarks Note that this function may be implemented using memory mapping, which means + * that the file may remain open until RTFileReadAllFree() is called. It also + * means that the return memory may reflect the state of the file when it's + * accessed instead of when this call was done. So, in short, don't use this + * API for volatile files, then rather use the extended variant with a + * yet-to-be-defined flag. + */ +RTDECL(int) RTFileReadAll(const char *pszFilename, void **ppvFile, size_t *pcbFile); + +/** + * Reads the file into memory. + * + * The caller must free the memory using RTFileReadAllFree(). + * + * @returns IPRT status code. + * @param pszFilename The name of the file. + * @param off The offset to start reading at. + * @param cbMax The maximum number of bytes to read into memory. Specify RTFOFF_MAX + * to read to the end of the file. + * @param fFlags See RTFILE_RDALL_*. + * @param ppvFile Where to store the pointer to the memory on successful return. + * @param pcbFile Where to store the size of the returned memory. + * + * @remarks See the remarks for RTFileReadAll. + */ +RTDECL(int) RTFileReadAllEx(const char *pszFilename, RTFOFF off, RTFOFF cbMax, uint32_t fFlags, void **ppvFile, size_t *pcbFile); + +/** + * Reads the file into memory. + * + * The caller must free the memory using RTFileReadAllFree(). + * + * @returns IPRT status code. + * @param File The handle to the file. + * @param ppvFile Where to store the pointer to the memory on successful return. + * @param pcbFile Where to store the size of the returned memory. + * + * @remarks See the remarks for RTFileReadAll. + */ +RTDECL(int) RTFileReadAllByHandle(RTFILE File, void **ppvFile, size_t *pcbFile); + +/** + * Reads the file into memory. + * + * The caller must free the memory using RTFileReadAllFree(). + * + * @returns IPRT status code. + * @param File The handle to the file. + * @param off The offset to start reading at. + * @param cbMax The maximum number of bytes to read into memory. Specify RTFOFF_MAX + * to read to the end of the file. + * @param fFlags See RTFILE_RDALL_*. + * @param ppvFile Where to store the pointer to the memory on successful return. + * @param pcbFile Where to store the size of the returned memory. + * + * @remarks See the remarks for RTFileReadAll. + */ +RTDECL(int) RTFileReadAllByHandleEx(RTFILE File, RTFOFF off, RTFOFF cbMax, uint32_t fFlags, void **ppvFile, size_t *pcbFile); + +/** + * Frees the memory returned by one of the RTFileReadAll(), RTFileReadAllEx(), + * RTFileReadAllByHandle() and RTFileReadAllByHandleEx() functions. + * + * @param pvFile Pointer to the memory. + * @param cbFile The size of the memory. + */ +RTDECL(void) RTFileReadAllFree(void *pvFile, size_t cbFile); + +/** @name RTFileReadAllEx and RTFileReadAllHandleEx flags + * The open flags are ignored by RTFileReadAllHandleEx. + * @{ */ +#define RTFILE_RDALL_O_DENY_NONE RTFILE_O_DENY_NONE +#define RTFILE_RDALL_O_DENY_READ RTFILE_O_DENY_READ +#define RTFILE_RDALL_O_DENY_WRITE RTFILE_O_DENY_WRITE +#define RTFILE_RDALL_O_DENY_READWRITE RTFILE_O_DENY_READWRITE +#define RTFILE_RDALL_O_DENY_ALL RTFILE_O_DENY_ALL +#define RTFILE_RDALL_O_DENY_NOT_DELETE RTFILE_O_DENY_NOT_DELETE +#define RTFILE_RDALL_O_DENY_MASK RTFILE_O_DENY_MASK +/** Mask of valid flags. */ +#define RTFILE_RDALL_VALID_MASK RTFILE_RDALL_O_DENY_MASK +/** @} */ + + +#ifdef IN_RING3 + +/** @page pg_rt_asyncio RT File async I/O API + * + * File operations are usually blocking the calling thread until + * they completed making it impossible to let the thread do anything + * else in-between. + * The RT File async I/O API provides an easy and efficient way to + * access files asynchronously using the native facilities provided + * by each operating system. + * + * @section sec_rt_asyncio_objects Objects + * + * There are two objects used in this API. + * The first object is the request. A request contains every information + * needed two complete the file operation successfully like the start offset + * and pointer to the source or destination buffer. + * Requests are created with RTFileAioReqCreate() and destroyed with + * RTFileAioReqDestroy(). + * Because creating a request may require allocating various operating + * system dependent resources and may be quite expensive it is possible + * to use a request more than once to save CPU cycles. + * A request is constructed with either RTFileAioReqPrepareRead() + * which will set up a request to read from the given file or + * RTFileAioReqPrepareWrite() which will write to a given file. + * + * The second object is the context. A file is associated with a context + * and requests for this file may complete only on the context the file + * was associated with and not on the context given in RTFileAioCtxSubmit() + * (see below for further information). + * RTFileAioCtxWait() is used to wait for completion of requests which were + * associated with the context. While waiting for requests the thread can not + * respond to global state changes. That's why the API provides a way to let + * RTFileAioCtxWait() return immediately no matter how many requests + * have finished through RTFileAioCtxWakeup(). The return code is + * VERR_INTERRUPTED to let the thread know that he got interrupted. + * + * @section sec_rt_asyncio_request_states Request states + * + * Created: + * After a request was created with RTFileAioReqCreate() it is in the same state + * like it just completed successfully. RTFileAioReqGetRC() will return VINF_SUCCESS + * and a transfer size of 0. RTFileAioReqGetUser() will return NULL. The request can be + * destroyed RTFileAioReqDestroy(). It is also allowed to prepare a the request + * for a data transfer with the RTFileAioReqPrepare* methods. + * Calling any other method like RTFileAioCtxSubmit() will return VERR_FILE_AIO_NOT_PREPARED + * and RTFileAioReqCancel() returns VERR_FILE_AIO_NOT_SUBMITTED. + * + * Prepared: + * A request will enter this state if one of the RTFileAioReqPrepare* methods + * is called. In this state you can still destroy and retrieve the user data + * associated with the request but trying to cancel the request or getting + * the result of the operation will return VERR_FILE_AIO_NOT_SUBMITTED. + * + * Submitted: + * A prepared request can be submitted with RTFileAioCtxSubmit(). If the operation + * succeeds it is not allowed to touch the request or free any resources until + * it completed through RTFileAioCtxWait(). The only allowed method is RTFileAioReqCancel() + * which tries to cancel the request. The request will go into the completed state + * and RTFileAioReqGetRC() will return VERR_FILE_AIO_CANCELED. + * If the request completes not matter if successfully or with an error it will + * switch into the completed state. RTFileReqDestroy() fails if the given request + * is in this state. + * + * Completed: + * The request will be in this state after it completed and returned through + * RTFileAioCtxWait(). RTFileAioReqGetRC() returns the final result code + * and the number of bytes transferred. + * The request can be used for new data transfers. + * + * @section sec_rt_asyncio_threading Threading + * + * The API is a thin wrapper around the specific host OS APIs and therefore + * relies on the thread safety of the underlying API. + * The interesting functions with regards to thread safety are RTFileAioCtxSubmit() + * and RTFileAioCtxWait(). RTFileAioCtxWait() must not be called from different + * threads at the same time with the same context handle. The same applies to + * RTFileAioCtxSubmit(). However it is possible to submit new requests from a different + * thread while waiting for completed requests on another thread with RTFileAioCtxWait(). + * + * @section sec_rt_asyncio_implementations Differences in implementation + * + * Because the host APIs are quite different on every OS and every API has other limitations + * there are some things to consider to make the code as portable as possible. + * + * The first restriction at the moment is that every buffer has to be aligned to a 512 byte boundary. + * This limitation comes from the Linux io_* interface. To use the interface the file + * must be opened with O_DIRECT. This flag disables the kernel cache too which may + * degrade performance but is unfortunately the only way to make asynchronous + * I/O work till today (if O_DIRECT is omitted io_submit will revert to sychronous behavior + * and will return when the requests finished and when they are queued). + * It is mostly used by DBMS which do theire own caching. + * Furthermore there is no filesystem independent way to discover the restrictions at least + * for the 2.4 kernel series. Since 2.6 the 512 byte boundary seems to be used by all + * file systems. So Linus comment about this flag is comprehensible but Linux + * lacks an alternative at the moment. + * + * The next limitation applies only to Windows. Requests are not associated with the + * I/O context they are associated with but with the file the request is for. + * The file needs to be associated with exactly one I/O completion port and requests + * for this file will only arrive at that context after they completed and not on + * the context the request was submitted. + * To associate a file with a specific context RTFileAioCtxAssociateWithFile() is + * used. It is only implemented on Windows and does nothing on the other platforms. + * If the file needs to be associated with different context for some reason + * the file must be closed first. After it was opened again the new context + * can be associated with the other context. + * This can't be done by the API because there is no way to retrieve the flags + * the file was opened with. + */ + +/** + * Global limits for the AIO API. + */ +typedef struct RTFILEAIOLIMITS +{ + /** Global number of simultaneous outstanding requests allowed. + * RTFILEAIO_UNLIMITED_REQS means no limit. */ + uint32_t cReqsOutstandingMax; + /** The alignment data buffers need to have. + * 0 means no alignment restrictions. */ + uint32_t cbBufferAlignment; +} RTFILEAIOLIMITS; +/** A pointer to a AIO limits structure. */ +typedef RTFILEAIOLIMITS *PRTFILEAIOLIMITS; + +/** + * Returns the global limits for the AIO API. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the host does not support the async I/O API. + * + * @param pAioLimits Where to store the global limit information. + */ +RTDECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits); + +/** + * Creates an async I/O request handle. + * + * @returns IPRT status code. + * @param phReq Where to store the request handle. + */ +RTDECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq); + +/** + * Destroys an async I/O request handle. + * + * @returns IPRT status code. + * @retval VERR_FILE_AIO_IN_PROGRESS if the request is still in progress. + * + * @param hReq The request handle. + */ +RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq); + +/** + * Prepares an async read request. + * + * @returns IPRT status code. + * @retval VERR_FILE_AIO_IN_PROGRESS if the request is still in progress. + * + * @param hReq The request handle. + * @param hFile The file to read from. + * @param off The offset to start reading at. + * @param pvBuf Where to store the read bits. + * @param cbRead Number of bytes to read. + * @param pvUser Opaque user data associated with this request which + * can be retrieved with RTFileAioReqGetUser(). + */ +RTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void *pvBuf, size_t cbRead, void *pvUser); + +/** + * Prepares an async write request. + * + * @returns IPRT status code. + * @retval VERR_FILE_AIO_IN_PROGRESS if the request is still in progress. + * + * @param hReq The request handle. + * @param hFile The file to write to. + * @param off The offset to start writing at. + * @param pvBuf The bits to write. + * @param cbWrite Number of bytes to write. + * @param pvUser Opaque user data associated with this request which + * can be retrieved with RTFileAioReqGetUser(). + */ +RTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off, + void const *pvBuf, size_t cbWrite, void *pvUser); + +/** + * Prepares an async flush of all cached data associated with a file handle. + * + * @returns IPRT status code. + * @retval VERR_FILE_AIO_IN_PROGRESS if the request is still in progress. + * + * @param hReq The request handle. + * @param hFile The file to flush. + * @param pvUser Opaque user data associated with this request which + * can be retrieved with RTFileAioReqGetUser(). + * + * @remarks May also flush other caches on some platforms. + */ +RTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser); + +/** + * Gets the opaque user data associated with the given request. + * + * @returns Opaque user data. + * @retval NULL if the request hasn't been prepared yet. + * + * @param hReq The request handle. + */ +RTDECL(void *) RTFileAioReqGetUser(RTFILEAIOREQ hReq); + +/** + * Cancels a pending request. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS If the request was canceled. + * @retval VERR_FILE_AIO_NOT_SUBMITTED If the request wasn't submitted yet. + * @retval VERR_FILE_AIO_IN_PROGRESS If the request could not be canceled because it is already processed. + * @retval VERR_FILE_AIO_COMPLETED If the request could not be canceled because it already completed. + * + * @param hReq The request to cancel. + */ +RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq); + +/** + * Gets the status of a completed request. + * + * @returns The IPRT status code of the given request. + * @retval VERR_FILE_AIO_NOT_SUBMITTED if the request wasn't submitted yet. + * @retval VERR_FILE_AIO_CANCELED if the request was canceled. + * @retval VERR_FILE_AIO_IN_PROGRESS if the request isn't yet completed. + * + * @param hReq The request handle. + * @param pcbTransferred Where to store the number of bytes transferred. + * Optional since it is not relevant for all kinds of + * requests. + */ +RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransferred); + + + +/** + * Creates an async I/O context. + * + * @todo briefly explain what an async context is here or in the page + * above. + * + * @returns IPRT status code. + * @param phAioCtx Where to store the async I/O context handle. + * @param cAioReqsMax How many async I/O requests the context should be capable + * to handle. Pass RTFILEAIO_UNLIMITED_REQS if the + * context should support an unlimited number of + * requests. + */ +RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax); + +/** Unlimited number of requests. + * Used with RTFileAioCtxCreate and RTFileAioCtxGetMaxReqCount. */ +#define RTFILEAIO_UNLIMITED_REQS UINT32_MAX + +/** + * Destroys an async I/O context. + * + * @returns IPRT status code. + * @param hAioCtx The async I/O context handle. + */ +RTDECL(int) RTFileAioCtxDestroy(RTFILEAIOCTX hAioCtx); + +/** + * Get the maximum number of requests one aio context can handle. + * + * @returns Maximum number of tasks the context can handle. + * RTFILEAIO_UNLIMITED_REQS if there is no limit. + * + * @param hAioCtx The async I/O context handle. + * If NIL_RTAIOCONTEXT is passed the maximum value + * which can be passed to RTFileAioCtxCreate() + * is returned. + */ +RTDECL(uint32_t) RTFileAioCtxGetMaxReqCount(RTFILEAIOCTX hAioCtx); + +/** + * Associates a file with an async I/O context. + * Requests for this file will arrive at the completion port + * associated with the file. + * + * @returns IPRT status code. + * + * @param hAioCtx The async I/O context handle. + * @param hFile The file handle. + */ +RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile); + +/** + * Submits a set of requests to an async I/O context for processing. + * + * @returns IPRT status code. + * @returns VERR_FILE_AIO_INSUFFICIENT_RESSOURCES if the maximum number of + * simultaneous outstanding requests would be exceeded. + * + * @param hAioCtx The async I/O context handle. + * @param pahReqs Pointer to an array of request handles. + * @param cReqs The number of entries in the array. + * + * @remarks It is possible that some requests could be submitted successfully + * even if the method returns an error code. In that case RTFileAioReqGetRC() + * can be used to determine the status of a request. + * If it returns VERR_FILE_AIO_IN_PROGRESS it was submitted successfully. + * Any other error code may indicate why the request failed. + * VERR_FILE_AIO_NOT_SUBMITTED indicates that a request wasn't submitted + * probably because the previous request encountered an error. + * + * @remarks @a cReqs uses the type size_t while it really is a uint32_t, this is + * to avoid annoying warnings when using RT_ELEMENTS and similar + * macros. + */ +RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs); + +/** + * Waits for request completion. + * + * Only one thread at a time may call this API on a context. + * + * @returns IPRT status code. + * @retval VERR_INVALID_POINTER If pcReqs or/and pahReqs are invalid. + * @retval VERR_INVALID_HANDLE If hAioCtx is invalid. + * @retval VERR_OUT_OF_RANGE If cMinReqs is larger than cReqs. + * @retval VERR_INVALID_PARAMETER If cReqs is 0. + * @retval VERR_TIMEOUT If cMinReqs didn't complete before the + * timeout expired. + * @retval VERR_INTERRUPTED If the completion context was interrupted + * by RTFileAioCtxWakeup(). + * @retval VERR_FILE_AIO_NO_REQUEST If there are no pending request. + * + * @param hAioCtx The async I/O context handle to wait and get + * completed requests from. + * @param cMinReqs The minimum number of requests which have to + * complete before this function returns. + * @param cMillies The number of milliseconds to wait before returning + * VERR_TIMEOUT. Use RT_INDEFINITE_WAIT to wait + * forever. + * @param pahReqs Pointer to an array where the handles of the + * completed requests will be stored on success. + * @param cReqs The number of entries @a pahReqs can hold. + * @param pcReqs Where to store the number of returned (complete) + * requests. This will always be set. + * + * @remarks The wait will be resume if interrupted by a signal. An + * RTFileAioCtxWaitNoResume variant can be added later if it becomes + * necessary. + * + * @remarks @a cMinReqs and @a cReqs use the type size_t while they really are + * uint32_t's, this is to avoid annoying warnings when using + * RT_ELEMENTS and similar macros. + */ +RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL cMillies, + PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs); + +/** + * Forces any RTFileAioCtxWait() call on another thread to return immediately. + * + * @returns IPRT status code. + * + * @param hAioCtx The handle of the async I/O context to wakeup. + */ +RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx); + +#endif /* IN_RING3 */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/filesystem.h b/include/iprt/filesystem.h new file mode 100644 index 00000000..82ab146e --- /dev/null +++ b/include/iprt/filesystem.h @@ -0,0 +1,55 @@ +/** @file + * IPRT Filesystem API. + */ + +/* + * Copyright (C) 2012 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. + */ + +#ifndef ___iprt_filesystem_h +#define ___iprt_filesystem_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/vfs.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_filesystem IPRT Filesystem VFS + * @{ + */ + +/** + * Detect the filesystem in the image given by the VFS file handle + * and create a new VFS object. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the filesystem is not recognized. + * @param hVfsFile The file to use as the filesystem medium. + * @param phVfs Where to store the VFS handle on success. + */ +RTDECL(int) RTFilesystemVfsFromFile(RTVFSFILE hVfsFile, PRTVFS phVfs); + +/** @} */ + +RT_C_DECLS_END + +#endif /* !___iprt_filesystem_h */ + diff --git a/include/iprt/fs.h b/include/iprt/fs.h new file mode 100644 index 00000000..6ad2d2c5 --- /dev/null +++ b/include/iprt/fs.h @@ -0,0 +1,618 @@ +/** @file + * IPRT - Filesystem. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_fs_h +#define ___iprt_fs_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/time.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_fs RTFs - Filesystem and Volume + * @ingroup grp_rt + * @{ + */ + + +/** @name Filesystem Object Mode Flags. + * + * There are two sets of flags: the unix mode flags and the dos attributes. + * + * APIs returning mode flags will provide both sets. + * + * When specifying mode flags to any API at least one of them must be given. If + * one set is missing the API will synthesize it from the one given if it + * requires it. + * + * Both sets match their x86 ABIs, the DOS/NT one is simply shifted up 16 bits. + * The DOS/NT range is bits 16 to 31 inclusively. The Unix range is bits 0 to 15 + * (inclusively). + * + * @remarks These constants have been comitted to a binary format and must not + * be changed in any incompatible ways. + * + * @{ + */ + +/** Set user id on execution (S_ISUID). */ +#define RTFS_UNIX_ISUID 0004000U +/** Set group id on execution (S_ISGID). */ +#define RTFS_UNIX_ISGID 0002000U +/** Sticky bit (S_ISVTX / S_ISTXT). */ +#define RTFS_UNIX_ISTXT 0001000U + +/** Owner RWX mask (S_IRWXU). */ +#define RTFS_UNIX_IRWXU 0000700U +/** Owner readable (S_IRUSR). */ +#define RTFS_UNIX_IRUSR 0000400U +/** Owner writable (S_IWUSR). */ +#define RTFS_UNIX_IWUSR 0000200U +/** Owner executable (S_IXUSR). */ +#define RTFS_UNIX_IXUSR 0000100U + +/** Group RWX mask (S_IRWXG). */ +#define RTFS_UNIX_IRWXG 0000070U +/** Group readable (S_IRGRP). */ +#define RTFS_UNIX_IRGRP 0000040U +/** Group writable (S_IWGRP). */ +#define RTFS_UNIX_IWGRP 0000020U +/** Group executable (S_IXGRP). */ +#define RTFS_UNIX_IXGRP 0000010U + +/** Other RWX mask (S_IRWXO). */ +#define RTFS_UNIX_IRWXO 0000007U +/** Other readable (S_IROTH). */ +#define RTFS_UNIX_IROTH 0000004U +/** Other writable (S_IWOTH). */ +#define RTFS_UNIX_IWOTH 0000002U +/** Other executable (S_IXOTH). */ +#define RTFS_UNIX_IXOTH 0000001U + +/** Named pipe (fifo) (S_IFIFO). */ +#define RTFS_TYPE_FIFO 0010000U +/** Character device (S_IFCHR). */ +#define RTFS_TYPE_DEV_CHAR 0020000U +/** Directory (S_IFDIR). */ +#define RTFS_TYPE_DIRECTORY 0040000U +/** Block device (S_IFBLK). */ +#define RTFS_TYPE_DEV_BLOCK 0060000U +/** Regular file (S_IFREG). */ +#define RTFS_TYPE_FILE 0100000U +/** Symbolic link (S_IFLNK). */ +#define RTFS_TYPE_SYMLINK 0120000U +/** Socket (S_IFSOCK). */ +#define RTFS_TYPE_SOCKET 0140000U +/** Whiteout (S_IFWHT). */ +#define RTFS_TYPE_WHITEOUT 0160000U +/** Type mask (S_IFMT). */ +#define RTFS_TYPE_MASK 0170000U + +/** Unix attribute mask. */ +#define RTFS_UNIX_MASK 0xffffU +/** The mask of all the NT, OS/2 and DOS attributes. */ +#define RTFS_DOS_MASK (0x7fffU << RTFS_DOS_SHIFT) + +/** The shift value. */ +#define RTFS_DOS_SHIFT 16 +/** The mask of the OS/2 and DOS attributes. */ +#define RTFS_DOS_MASK_OS2 (0x003fU << RTFS_DOS_SHIFT) +/** The mask of the NT attributes. */ +#define RTFS_DOS_MASK_NT (0x7fffU << RTFS_DOS_SHIFT) + +/** Readonly object. */ +#define RTFS_DOS_READONLY (0x0001U << RTFS_DOS_SHIFT) +/** Hidden object. */ +#define RTFS_DOS_HIDDEN (0x0002U << RTFS_DOS_SHIFT) +/** System object. */ +#define RTFS_DOS_SYSTEM (0x0004U << RTFS_DOS_SHIFT) +/** Directory. */ +#define RTFS_DOS_DIRECTORY (0x0010U << RTFS_DOS_SHIFT) +/** Archived object. + * This bit is set by the filesystem after each modification of a file. */ +#define RTFS_DOS_ARCHIVED (0x0020U << RTFS_DOS_SHIFT) +/** Undocumented / Reserved, used to be the FAT volume label. */ +#define RTFS_DOS_NT_DEVICE (0x0040U << RTFS_DOS_SHIFT) +/** Normal object, no other attribute set (NT). */ +#define RTFS_DOS_NT_NORMAL (0x0080U << RTFS_DOS_SHIFT) +/** Temporary object (NT). */ +#define RTFS_DOS_NT_TEMPORARY (0x0100U << RTFS_DOS_SHIFT) +/** Sparse file (NT). */ +#define RTFS_DOS_NT_SPARSE_FILE (0x0200U << RTFS_DOS_SHIFT) +/** Reparse point (NT). */ +#define RTFS_DOS_NT_REPARSE_POINT (0x0400U << RTFS_DOS_SHIFT) +/** Compressed object (NT). + * For a directory, compression is the default for new files. */ +#define RTFS_DOS_NT_COMPRESSED (0x0800U << RTFS_DOS_SHIFT) +/** Physically offline data (NT). + * MSDN say, don't mess with this one. */ +#define RTFS_DOS_NT_OFFLINE (0x1000U << RTFS_DOS_SHIFT) +/** Not content indexed by the content indexing service (NT). */ +#define RTFS_DOS_NT_NOT_CONTENT_INDEXED (0x2000U << RTFS_DOS_SHIFT) +/** Encryped object (NT). + * For a directory, encrypted is the default for new files. */ +#define RTFS_DOS_NT_ENCRYPTED (0x4000U << RTFS_DOS_SHIFT) + +/** @} */ + + +/** @name Filesystem Object Type Predicates. + * @{ */ +/** Checks the mode flags indicate a named pipe (fifo) (S_ISFIFO). */ +#define RTFS_IS_FIFO(fMode) ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_FIFO ) +/** Checks the mode flags indicate a character device (S_ISCHR). */ +#define RTFS_IS_DEV_CHAR(fMode) ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_DEV_CHAR ) +/** Checks the mode flags indicate a directory (S_ISDIR). */ +#define RTFS_IS_DIRECTORY(fMode) ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_DIRECTORY ) +/** Checks the mode flags indicate a block device (S_ISBLK). */ +#define RTFS_IS_DEV_BLOCK(fMode) ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_DEV_BLOCK ) +/** Checks the mode flags indicate a regular file (S_ISREG). */ +#define RTFS_IS_FILE(fMode) ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_FILE ) +/** Checks the mode flags indicate a symbolic link (S_ISLNK). */ +#define RTFS_IS_SYMLINK(fMode) ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_SYMLINK ) +/** Checks the mode flags indicate a socket (S_ISSOCK). */ +#define RTFS_IS_SOCKET(fMode) ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_SOCKET ) +/** Checks the mode flags indicate a whiteout (S_ISWHT). */ +#define RTFS_IS_WHITEOUT(fMode) ( ((fMode) & RTFS_TYPE_MASK) == RTFS_TYPE_WHITEOUT ) +/** @} */ + + +/** + * Filesystem type IDs returned by RTFsQueryType. + * + * This enum is subject to changes and must not be used as part of any ABI or + * binary format (file, network, etc). + * + * @remarks When adding new entries, please update RTFsTypeName(). Also, try + * add them to the most natural group. + */ +typedef enum RTFSTYPE +{ + /** Unknown file system. */ + RTFSTYPE_UNKNOWN = 0, + + /** Universal Disk Format. */ + RTFSTYPE_UDF, + /** ISO 9660, aka Compact Disc File System (CDFS). */ + RTFSTYPE_ISO9660, + /** Filesystem in Userspace. */ + RTFSTYPE_FUSE, + /** VirtualBox shared folders. */ + RTFSTYPE_VBOXSHF, + + /* Linux: */ + RTFSTYPE_EXT, + RTFSTYPE_EXT2, + RTFSTYPE_EXT3, + RTFSTYPE_EXT4, + RTFSTYPE_XFS, + RTFSTYPE_CIFS, + RTFSTYPE_SMBFS, + RTFSTYPE_TMPFS, + RTFSTYPE_SYSFS, + RTFSTYPE_PROC, + RTFSTYPE_OCFS2, + + /* Windows: */ + /** New Technology File System. */ + RTFSTYPE_NTFS, + /** FAT12, FAT16 and FAT32 lumped into one basket. + * The partition size limit of FAT12 and FAT16 will be the factor + * limiting the file size (except, perhaps for the 64KB cluster case on + * non-Windows hosts). */ + RTFSTYPE_FAT, + + /* Solaris: */ + /** Zettabyte File System. */ + RTFSTYPE_ZFS, + /** Unix File System. */ + RTFSTYPE_UFS, + /** Network File System. */ + RTFSTYPE_NFS, + + /* Mac OS X: */ + /** Hierarchical File System. */ + RTFSTYPE_HFS, + /** @todo RTFSTYPE_HFS_PLUS? */ + RTFSTYPE_AUTOFS, + RTFSTYPE_DEVFS, + + /* *BSD: */ + + /* OS/2: */ + /** High Performance File System. */ + RTFSTYPE_HPFS, + /** Journaled File System (v2). */ + RTFSTYPE_JFS, + + /** The end of valid Filesystem types IDs. */ + RTFSTYPE_END, + /** The usual 32-bit type blow up. */ + RTFSTYPE_32BIT_HACK = 0x7fffffff +} RTFSTYPE; +/** Pointer to a Filesystem type ID. */ +typedef RTFSTYPE *PRTFSTYPE; + + +/** + * The available additional information in a RTFSOBJATTR object. + */ +typedef enum RTFSOBJATTRADD +{ + /** No additional information is available / requested. */ + RTFSOBJATTRADD_NOTHING = 1, + /** The additional unix attributes (RTFSOBJATTR::u::Unix) are available / + * requested. */ + RTFSOBJATTRADD_UNIX, + /** The additional unix attributes (RTFSOBJATTR::u::UnixOwner) are + * available / requested. */ + RTFSOBJATTRADD_UNIX_OWNER, + /** The additional unix attributes (RTFSOBJATTR::u::UnixGroup) are + * available / requested. */ + RTFSOBJATTRADD_UNIX_GROUP, + /** The additional extended attribute size (RTFSOBJATTR::u::EASize) is available / requested. */ + RTFSOBJATTRADD_EASIZE, + /** The last valid item (inclusive). + * The valid range is RTFSOBJATTRADD_NOTHING thru RTFSOBJATTRADD_LAST. */ + RTFSOBJATTRADD_LAST = RTFSOBJATTRADD_EASIZE, + + /** The usual 32-bit hack. */ + RTFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff +} RTFSOBJATTRADD; + +/** The number of bytes reserved for the additional attribute union. */ +#define RTFSOBJATTRUNION_MAX_SIZE 128 + +/** + * Additional Unix Attributes (RTFSOBJATTRADD_UNIX). + */ +typedef struct RTFSOBJATTRUNIX +{ + /** The user owning the filesystem object (st_uid). + * This field is NIL_UID if not supported. */ + RTUID uid; + + /** The group the filesystem object is assigned (st_gid). + * This field is NIL_GID if not supported. */ + RTGID gid; + + /** Number of hard links to this filesystem object (st_nlink). + * This field is 1 if the filesystem doesn't support hardlinking or + * the information isn't available. + */ + uint32_t cHardlinks; + + /** The device number of the device which this filesystem object resides on (st_dev). + * This field is 0 if this information is not available. */ + RTDEV INodeIdDevice; + + /** The unique identifier (within the filesystem) of this filesystem object (st_ino). + * Together with INodeIdDevice, this field can be used as a OS wide unique id + * when both their values are not 0. + * This field is 0 if the information is not available. */ + RTINODE INodeId; + + /** User flags (st_flags). + * This field is 0 if this information is not available. */ + uint32_t fFlags; + + /** The current generation number (st_gen). + * This field is 0 if this information is not available. */ + uint32_t GenerationId; + + /** The device number of a character or block device type object (st_rdev). + * This field is 0 if the file isn't of a character or block device type and + * when the OS doesn't subscribe to the major+minor device idenfication scheme. */ + RTDEV Device; +} RTFSOBJATTRUNIX; + + +/** + * Additional Unix Attributes (RTFSOBJATTRADD_UNIX_OWNER). + * + * @remarks This interface is mainly for TAR. + */ +typedef struct RTFSOBJATTRUNIXOWNER +{ + /** The user owning the filesystem object (st_uid). + * This field is NIL_UID if not supported. */ + RTUID uid; + /** The user name. + * Empty if not available or not supported, truncated if too long. */ + char szName[RTFSOBJATTRUNION_MAX_SIZE - sizeof(RTUID)]; +} RTFSOBJATTRUNIXOWNER; + + +/** + * Additional Unix Attributes (RTFSOBJATTRADD_UNIX_GROUP). + * + * @remarks This interface is mainly for TAR. + */ +typedef struct RTFSOBJATTRUNIXGROUP +{ + /** The user owning the filesystem object (st_uid). + * This field is NIL_GID if not supported. */ + RTGID gid; + /** The group name. + * Empty if not available or not supported, truncated if too long. */ + char szName[RTFSOBJATTRUNION_MAX_SIZE - sizeof(RTGID)]; +} RTFSOBJATTRUNIXGROUP; + + +/** + * Filesystem object attributes. + */ +typedef struct RTFSOBJATTR +{ + /** Mode flags (st_mode). RTFS_UNIX_*, RTFS_TYPE_*, and RTFS_DOS_*. */ + RTFMODE fMode; + + /** The additional attributes available. */ + RTFSOBJATTRADD enmAdditional; + + /** + * Additional attributes. + * + * Unless explicitly specified to an API, the API can provide additional + * data as it is provided by the underlying OS. + */ + union RTFSOBJATTRUNION + { + /** Additional Unix Attributes - RTFSOBJATTRADD_UNIX. */ + RTFSOBJATTRUNIX Unix; + /** Additional Unix Owner Attributes - RTFSOBJATTRADD_UNIX_OWNER. */ + RTFSOBJATTRUNIXOWNER UnixOwner; + /** Additional Unix Group Attributes - RTFSOBJATTRADD_UNIX_GROUP. */ + RTFSOBJATTRUNIXGROUP UnixGroup; + + /** + * Extended attribute size is available when RTFS_DOS_HAVE_EA_SIZE is set. + */ + struct RTFSOBJATTREASIZE + { + /** Size of EAs. */ + RTFOFF cb; + } EASize; + /** Reserved space. */ + uint8_t abReserveSpace[128]; + } u; +} RTFSOBJATTR; +/** Pointer to a filesystem object attributes structure. */ +typedef RTFSOBJATTR *PRTFSOBJATTR; +/** Pointer to a const filesystem object attributes structure. */ +typedef const RTFSOBJATTR *PCRTFSOBJATTR; + + +/** + * Filesystem object information structure. + * + * This is returned by the RTPathQueryInfo(), RTFileQueryInfo() and RTDirRead() APIs. + */ +typedef struct RTFSOBJINFO +{ + /** Logical size (st_size). + * For normal files this is the size of the file. + * For symbolic links, this is the length of the path name contained + * in the symbolic link. + * For other objects this fields needs to be specified. + */ + RTFOFF cbObject; + + /** Disk allocation size (st_blocks * DEV_BSIZE). */ + RTFOFF cbAllocated; + + /** Time of last access (st_atime). */ + RTTIMESPEC AccessTime; + + /** Time of last data modification (st_mtime). */ + RTTIMESPEC ModificationTime; + + /** Time of last status change (st_ctime). + * If not available this is set to ModificationTime. + */ + RTTIMESPEC ChangeTime; + + /** Time of file birth (st_birthtime). + * If not available this is set to ChangeTime. + */ + RTTIMESPEC BirthTime; + + /** Attributes. */ + RTFSOBJATTR Attr; + +} RTFSOBJINFO; +/** Pointer to a filesystem object information structure. */ +typedef RTFSOBJINFO *PRTFSOBJINFO; +/** Pointer to a const filesystem object information structure. */ +typedef const RTFSOBJINFO *PCRTFSOBJINFO; + + +#ifdef IN_RING3 + +/** + * Query the sizes of a filesystem. + * + * @returns iprt status code. + * @param pszFsPath Path within the mounted filesystem. + * @param pcbTotal Where to store the total filesystem space. (Optional) + * @param pcbFree Where to store the remaining free space in the filesystem. (Optional) + * @param pcbBlock Where to store the block size. (Optional) + * @param pcbSector Where to store the sector size. (Optional) + * + * @sa RTFileQueryFsSizes + */ +RTR3DECL(int) RTFsQuerySizes(const char *pszFsPath, PRTFOFF pcbTotal, RTFOFF *pcbFree, + uint32_t *pcbBlock, uint32_t *pcbSector); + +/** + * Query the mountpoint of a filesystem. + * + * @returns iprt status code. + * @returns VERR_BUFFER_OVERFLOW if cbMountpoint isn't enough. + * @param pszFsPath Path within the mounted filesystem. + * @param pszMountpoint Where to store the mountpoint path. + * @param cbMountpoint Size of the buffer pointed to by pszMountpoint. + */ +RTR3DECL(int) RTFsQueryMountpoint(const char *pszFsPath, char *pszMountpoint, size_t cbMountpoint); + +/** + * Query the label of a filesystem. + * + * @returns iprt status code. + * @returns VERR_BUFFER_OVERFLOW if cbLabel isn't enough. + * @param pszFsPath Path within the mounted filesystem. + * @param pszLabel Where to store the label. + * @param cbLabel Size of the buffer pointed to by pszLabel. + */ +RTR3DECL(int) RTFsQueryLabel(const char *pszFsPath, char *pszLabel, size_t cbLabel); + +/** + * Query the serial number of a filesystem. + * + * @returns iprt status code. + * @param pszFsPath Path within the mounted filesystem. + * @param pu32Serial Where to store the serial number. + */ +RTR3DECL(int) RTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial); + +/** + * Query the name of the filesystem driver. + * + * @returns iprt status code. + * @returns VERR_BUFFER_OVERFLOW if cbFsDriver isn't enough. + * @param pszFsPath Path within the mounted filesystem. + * @param pszFsDriver Where to store the filesystem driver name. + * @param cbFsDriver Size of the buffer pointed to by pszFsDriver. + */ +RTR3DECL(int) RTFsQueryDriver(const char *pszFsPath, char *pszFsDriver, size_t cbFsDriver); + +/** + * Query the name of the filesystem the file is located on. + * + * @returns iprt status code. + * @param pszFsPath Path within the mounted filesystem. It must exist. + * In case this is a symlink, the file it refers to is + * evaluated. + * @param penmType Where to store the filesystem type, this is always + * set. See RTFSTYPE for the values. + */ +RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType); + +#endif /* IN_RING3 */ + +/** + * Gets the name of a filesystem type. + * + * @returns Pointer to a read-only string containing the name. + * @param enmType A valid filesystem ID. If outside the valid range, + * the returned string will be pointing to a static + * memory buffer which will be changed on subsequent + * calls to this function by any thread. + */ +RTDECL(const char *) RTFsTypeName(RTFSTYPE enmType); + +/** + * Filesystem properties. + */ +typedef struct RTFSPROPERTIES +{ + /** The maximum size of a filesystem object name. + * This does not include the '\\0'. */ + uint32_t cbMaxComponent; + + /** True if the filesystem is remote. + * False if the filesystem is local. */ + bool fRemote; + + /** True if the filesystem is case sensitive. + * False if the filesystem is case insensitive. */ + bool fCaseSensitive; + + /** True if the filesystem is mounted read only. + * False if the filesystem is mounted read write. */ + bool fReadOnly; + + /** True if the filesystem can encode unicode object names. + * False if it can't. */ + bool fSupportsUnicode; + + /** True if the filesystem is compresses. + * False if it isn't or we don't know. */ + bool fCompressed; + + /** True if the filesystem compresses of individual files. + * False if it doesn't or we don't know. */ + bool fFileCompression; + + /** @todo more? */ +} RTFSPROPERTIES; +/** Pointer to a filesystem properties structure. */ +typedef RTFSPROPERTIES *PRTFSPROPERTIES; +/** Pointer to a const filesystem properties structure. */ +typedef RTFSPROPERTIES const *PCRTFSPROPERTIES; + +#ifdef IN_RING3 + +/** + * Query the properties of a mounted filesystem. + * + * @returns iprt status code. + * @param pszFsPath Path within the mounted filesystem. + * @param pProperties Where to store the properties. + */ +RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties); + + +/** + * Mountpoint enumerator callback. + * + * @returns iprt status code. Failure terminates the enumeration. + * @param pszMountpoint The mountpoint name. + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(int) FNRTFSMOUNTPOINTENUM(const char *pszMountpoint, void *pvUser); +/** Pointer to a FNRTFSMOUNTPOINTENUM(). */ +typedef FNRTFSMOUNTPOINTENUM *PFNRTFSMOUNTPOINTENUM; + +/** + * Enumerate mount points. + * + * @returns iprt status code. + * @param pfnCallback The callback function. + * @param pvUser The user argument to the callback. + */ +RTR3DECL(int) RTFsMountpointsEnum(PFNRTFSMOUNTPOINTENUM pfnCallback, void *pvUser); + + +#endif /* IN_RING3 */ + +/** @} */ + +RT_C_DECLS_END + +#endif /* !___iprt_fs_h */ + diff --git a/include/iprt/getopt.h b/include/iprt/getopt.h new file mode 100644 index 00000000..bf976cef --- /dev/null +++ b/include/iprt/getopt.h @@ -0,0 +1,447 @@ +/** @file + * IPRT - Command Line Parsing. + */ + +/* + * Copyright (C) 2007-2011 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. + */ + +#ifndef ___iprt_getopt_h +#define ___iprt_getopt_h + + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_getopt RTGetOpt - Command Line Parsing + * @ingroup grp_rt + * @{ + */ + +/** @name Values for RTGETOPTDEF::fFlags and the fFlags parameter of + * RTGetOptFetchValue. + * + * @remarks When neither of the RTGETOPT_FLAG_HEX, RTGETOPT_FLAG_OCT and RTGETOPT_FLAG_DEC + * flags are specified with a integer value format, RTGetOpt will default to + * decimal but recognize the 0x prefix when present. RTGetOpt will not look for + * for the octal prefix (0). + * @{ */ +/** Requires no extra argument. + * (Can be assumed to be 0 for ever.) */ +#define RTGETOPT_REQ_NOTHING 0 +/** A value is required or error will be returned. */ +#define RTGETOPT_REQ_STRING 1 +/** The value must be a valid signed 8-bit integer or an error will be returned. */ +#define RTGETOPT_REQ_INT8 2 +/** The value must be a valid unsigned 8-bit integer or an error will be returned. */ +#define RTGETOPT_REQ_UINT8 3 +/** The value must be a valid signed 16-bit integer or an error will be returned. */ +#define RTGETOPT_REQ_INT16 4 +/** The value must be a valid unsigned 16-bit integer or an error will be returned. */ +#define RTGETOPT_REQ_UINT16 5 +/** The value must be a valid signed 32-bit integer or an error will be returned. */ +#define RTGETOPT_REQ_INT32 6 +/** The value must be a valid unsigned 32-bit integer or an error will be returned. */ +#define RTGETOPT_REQ_UINT32 7 +/** The value must be a valid signed 64-bit integer or an error will be returned. */ +#define RTGETOPT_REQ_INT64 8 +/** The value must be a valid unsigned 64-bit integer or an error will be returned. */ +#define RTGETOPT_REQ_UINT64 9 +/** The value must be a valid IPv4 address. + * (Not a name, but 4 values in the 0..255 range with dots separating them). */ +#define RTGETOPT_REQ_IPV4ADDR 10 +#if 0 +/** The value must be a valid IPv4 CIDR. + * As with RTGETOPT_REQ_IPV4ADDR, no name. + * @todo Mix CIDR with types.h or/and net.h first and find a way to make the + * mask optional like with ifconfig. See RTCidrStrToIPv4. */ +#define RTGETOPT_REQ_IPV4CIDR 11 +#endif +/** The value must be a valid ethernet MAC address. */ +#define RTGETOPT_REQ_MACADDR 14 +/** The value must be a valid UUID. */ +#define RTGETOPT_REQ_UUID 15 +/** The value must be a string with value as "on" or "off". */ +#define RTGETOPT_REQ_BOOL_ONOFF 16 +/** Boolean option accepting a wide range of typical ways of + * expression true and false. */ +#define RTGETOPT_REQ_BOOL 17 +/** The mask of the valid required types. */ +#define RTGETOPT_REQ_MASK 31 +/** Treat the value as hexadecimal - only applicable with the RTGETOPT_REQ_*INT*. */ +#define RTGETOPT_FLAG_HEX RT_BIT(16) +/** Treat the value as octal - only applicable with the RTGETOPT_REQ_*INT*. */ +#define RTGETOPT_FLAG_OCT RT_BIT(17) +/** Treat the value as decimal - only applicable with the RTGETOPT_REQ_*INT*. */ +#define RTGETOPT_FLAG_DEC RT_BIT(18) +/** The index value is attached to the argument - only valid for long arguments. */ +#define RTGETOPT_FLAG_INDEX RT_BIT(19) +/** Treat the long option as case insensitive. */ +#define RTGETOPT_FLAG_ICASE RT_BIT(20) +/** Mask of valid bits - for validation. */ +#define RTGETOPT_VALID_MASK ( RTGETOPT_REQ_MASK \ + | RTGETOPT_FLAG_HEX \ + | RTGETOPT_FLAG_OCT \ + | RTGETOPT_FLAG_DEC \ + | RTGETOPT_FLAG_INDEX \ + | RTGETOPT_FLAG_ICASE) +/** @} */ + +/** + * An option definition. + */ +typedef struct RTGETOPTDEF +{ + /** The long option. + * This is optional */ + const char *pszLong; + /** The short option character. + * This doesn't have to be a character, it may also be a \#define or enum value if + * there isn't any short version of this option. Must be greater than 0. */ + int iShort; + /** The flags (RTGETOPT_*). */ + unsigned fFlags; +} RTGETOPTDEF; +/** Pointer to an option definition. */ +typedef RTGETOPTDEF *PRTGETOPTDEF; +/** Pointer to an const option definition. */ +typedef const RTGETOPTDEF *PCRTGETOPTDEF; + +/** + * Option argument union. + * + * What ends up here depends on argument format in the option definition. + * + * @remarks Integers will bet put in the \a i and \a u members and sign/zero extended + * according to the signedness indicated by the \a fFlags. So, you can choose + * use which ever of the integer members for accessing the value regardless + * of restrictions indicated in the \a fFlags. + */ +typedef union RTGETOPTUNION +{ + /** Pointer to the definition on failure or when the option doesn't take an argument. + * This can be NULL for some errors. */ + PCRTGETOPTDEF pDef; + /** A RTGETOPT_REQ_STRING option argument. */ + const char *psz; + + /** A RTGETOPT_REQ_INT8 option argument. */ + int8_t i8; + /** A RTGETOPT_REQ_UINT8 option argument . */ + uint8_t u8; + /** A RTGETOPT_REQ_INT16 option argument. */ + int16_t i16; + /** A RTGETOPT_REQ_UINT16 option argument . */ + uint16_t u16; + /** A RTGETOPT_REQ_INT16 option argument. */ + int32_t i32; + /** A RTGETOPT_REQ_UINT32 option argument . */ + uint32_t u32; + /** A RTGETOPT_REQ_INT64 option argument. */ + int64_t i64; + /** A RTGETOPT_REQ_UINT64 option argument. */ + uint64_t u64; +#ifdef ___iprt_net_h + /** A RTGETOPT_REQ_IPV4ADDR option argument. */ + RTNETADDRIPV4 IPv4Addr; +#endif + /** A RTGETOPT_REQ_MACADDR option argument. */ + RTMAC MacAddr; + /** A RTGETOPT_REQ_UUID option argument. */ + RTUUID Uuid; + /** A boolean flag. */ + bool f; +} RTGETOPTUNION; +/** Pointer to an option argument union. */ +typedef RTGETOPTUNION *PRTGETOPTUNION; +/** Pointer to a const option argument union. */ +typedef RTGETOPTUNION const *PCRTGETOPTUNION; + + +/** + * RTGetOpt state. + */ +typedef struct RTGETOPTSTATE +{ + /** The next argument. */ + int iNext; + /** Argument array. */ + char **argv; + /** Number of items in argv. */ + int argc; + /** Option definition array. */ + PCRTGETOPTDEF paOptions; + /** Number of items in paOptions. */ + size_t cOptions; + /** The next short option. + * (For parsing ls -latrT4 kind of option lists.) */ + const char *pszNextShort; + /** The option definition which matched. NULL otherwise. */ + PCRTGETOPTDEF pDef; + /** The index of an index option, otherwise UINT32_MAX. */ + uint32_t uIndex; + /** The flags passed to RTGetOptInit. */ + uint32_t fFlags; + /** Number of non-options that we're skipping during a sorted get. The value + * INT32_MAX is used to indicate that there are no more options. This is used + * to implement '--'. */ + int32_t cNonOptions; + + /* More members may be added later for dealing with new features. */ +} RTGETOPTSTATE; +/** Pointer to RTGetOpt state. */ +typedef RTGETOPTSTATE *PRTGETOPTSTATE; + + +/** + * Initialize the RTGetOpt state. + * + * The passed in argument vector may be sorted if fFlags indicates that this is + * desired (to be implemented). + * + * @returns VINF_SUCCESS, VERR_INVALID_PARAMETER or VERR_INVALID_POINTER. + * @param pState The state. + * + * @param argc Argument count, to be copied from what comes in with + * main(). + * @param argv Argument array, to be copied from what comes in with + * main(). This may end up being modified by the + * option/argument sorting. + * @param paOptions Array of RTGETOPTDEF structures, which must specify what + * options are understood by the program. + * @param cOptions Number of array items passed in with paOptions. + * @param iFirst The argument to start with (in argv). + * @param fFlags The flags, see RTGETOPTINIT_FLAGS_XXX. + */ +RTDECL(int) RTGetOptInit(PRTGETOPTSTATE pState, int argc, char **argv, + PCRTGETOPTDEF paOptions, size_t cOptions, + int iFirst, uint32_t fFlags); + +/** @name RTGetOptInit flags. + * @{ */ +/** Sort the arguments so that options comes first, then non-options. */ +#define RTGETOPTINIT_FLAGS_OPTS_FIRST RT_BIT_32(0) +/** Prevent add the standard version and help options: + * - "--help", "-h" and "-?" returns 'h'. + * - "--version" and "-V" return 'V'. + */ +#define RTGETOPTINIT_FLAGS_NO_STD_OPTS RT_BIT_32(1) +/** @} */ + +/** + * Command line argument parser, handling both long and short options and checking + * argument formats, if desired. + * + * This is to be called in a loop until it returns 0 (meaning that all options + * were parsed) or a negative value (meaning that an error occurred). How non-option + * arguments are dealt with depends on the flags passed to RTGetOptInit. The default + * (fFlags = 0) is to return VINF_GETOPT_NOT_OPTION with pValueUnion->psz pointing to + * the argument string. + * + * For example, for a program which takes the following options: + * + * --optwithstring (or -s) and a string argument; + * --optwithint (or -i) and a 32-bit signed integer argument; + * --verbose (or -v) with no arguments, + * + * code would look something like this: + * + * @code +int main(int argc, char **argv) +{ + int rc = RTR3Init(); + if (RT_FAILURE(rc)) + return RTMsgInitFailure(rc); + + static const RTGETOPTDEF s_aOptions[] = + { + { "--optwithstring", 's', RTGETOPT_REQ_STRING }, + { "--optwithint", 'i', RTGETOPT_REQ_INT32 }, + { "--verbose", 'v', 0 }, + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + // for options that require an argument, ValueUnion has received the value + switch (ch) + { + case 's': // --optwithstring or -s + // string argument, copy ValueUnion.psz + break; + + case 'i': // --optwithint or -i + // integer argument, copy ValueUnion.i32 + break; + + case 'v': // --verbose or -v + g_fOptVerbose = true; + break; + + case VINF_GETOPT_NOT_OPTION: + // handle non-option argument in ValueUnion.psz. + break; + + default: + return RTGetOptPrintError(ch, &ValueUnion); + } + } + + return RTEXITCODE_SUCCESS; +} + @endcode + * + * @returns 0 when done parsing. + * @returns the iShort value of the option. pState->pDef points to the option + * definition which matched. + * @returns IPRT error status on parse error. + * @returns VINF_GETOPT_NOT_OPTION when encountering a non-option argument and + * RTGETOPT_FLAG_SORT was not specified. pValueUnion->psz points to the + * argument string. + * @returns VERR_GETOPT_UNKNOWN_OPTION when encountering an unknown option. + * pValueUnion->psz points to the option string. + * @returns VERR_GETOPT_REQUIRED_ARGUMENT_MISSING and pValueUnion->pDef if + * a required argument (aka value) was missing for an option. + * @returns VERR_GETOPT_INVALID_ARGUMENT_FORMAT and pValueUnion->pDef if + * argument (aka value) conversion failed. + * + * @param pState The state previously initialized with RTGetOptInit. + * @param pValueUnion Union with value; in the event of an error, psz member + * points to erroneous parameter; otherwise, for options + * that require an argument, this contains the value of + * that argument, depending on the type that is required. + */ +RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion); + +/** + * Fetch a value. + * + * Used to retrive a value argument in a manner similar to what RTGetOpt does + * (@a fFlags -> @a pValueUnion). This can be used when handling + * VINF_GETOPT_NOT_OPTION, but is equally useful for decoding options that + * takes more than one value. + * + * @returns VINF_SUCCESS on success. + * @returns IPRT error status on parse error. + * @returns VERR_INVALID_PARAMETER if the flags are wrong. + * @returns VERR_GETOPT_UNKNOWN_OPTION when pState->pDef is null. + * @returns VERR_GETOPT_REQUIRED_ARGUMENT_MISSING if there are no more + * available arguments. pValueUnion->pDef is NULL. + * @returns VERR_GETOPT_INVALID_ARGUMENT_FORMAT and pValueUnion->pDef is + * unchanged if value conversion failed. + * + * @param pState The state previously initialized with RTGetOptInit. + * @param pValueUnion Union with value; in the event of an error, psz member + * points to erroneous parameter; otherwise, for options + * that require an argument, this contains the value of + * that argument, depending on the type that is required. + * @param fFlags What to get, that is RTGETOPT_REQ_XXX. + */ +RTDECL(int) RTGetOptFetchValue(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion, uint32_t fFlags); + +/** + * Print error messages for a RTGetOpt default case. + * + * Uses RTMsgError. + * + * @returns Suitable exit code. + * + * @param ch The RTGetOpt return value. + * @param pValueUnion The value union returned by RTGetOpt. + */ +RTDECL(RTEXITCODE) RTGetOptPrintError(int ch, PCRTGETOPTUNION pValueUnion); + +/** + * Parses the @a pszCmdLine string into an argv array. + * + * This is useful for converting a response file or similar to an argument + * vector that can be used with RTGetOptInit(). + * + * This function aims at following the bourn shell string quoting rules. + * + * @returns IPRT status code. + * + * @param ppapszArgv Where to return the argument vector. This must be + * freed by calling RTGetOptArgvFree. + * @param pcArgs Where to return the argument count. + * @param pszCmdLine The string to parse. + * @param pszSeparators String containing the argument separators. If NULL, + * then space, tab, line feed (\\n) and return (\\r) + * are used. + */ +RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *pszCmdLine, const char *pszSeparators); + +/** + * Frees and argument vector returned by RTGetOptStringToArgv. + * + * @param papszArgv Argument vector. NULL is fine. + */ +RTDECL(void) RTGetOptArgvFree(char **paArgv); + +/** + * Turns an argv array into a command line string. + * + * This is useful for calling CreateProcess on Windows, but can also be used for + * displaying an argv array. + * + * This function aims at following the bourn shell string quoting rules. + * + * @returns IPRT status code. + * + * @param ppszCmdLine Where to return the command line string. This must + * be freed by calling RTStrFree. + * @param papszArgs The argument vector to convert. + * @param fFlags A combination of the RTGETOPTARGV_CNV_XXX flags. + */ +RTDECL(int) RTGetOptArgvToString(char **ppszCmdLine, const char * const *papszArgv, uint32_t fFlags); + +/** @name RTGetOptArgvToString and RTGetOptArgvToUtf16String flags + * @{ */ +/** Quote strings according to the Microsoft CRT rules. */ +#define RTGETOPTARGV_CNV_QUOTE_MS_CRT UINT32_C(0) +/** Quote strings according to the Unix Bourne Shell. */ +#define RTGETOPTARGV_CNV_QUOTE_BOURNE_SH UINT32_C(1) +/** Mask for the quoting style. */ +#define RTGETOPTARGV_CNV_QUOTE_MASK UINT32_C(1) +/** @} */ + +/** + * Convenience wrapper around RTGetOpArgvToString and RTStrToUtf16. + * + * @returns IPRT status code. + * + * @param ppwszCmdLine Where to return the command line string. This must + * be freed by calling RTUtf16Free. + * @param papszArgs The argument vector to convert. + * @param fFlags A combination of the RTGETOPTARGV_CNV_XXX flags. + */ +RTDECL(int) RTGetOptArgvToUtf16String(PRTUTF16 *ppwszCmdLine, const char * const *papszArgv, uint32_t fFlags); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/handle.h b/include/iprt/handle.h new file mode 100644 index 00000000..2d06db10 --- /dev/null +++ b/include/iprt/handle.h @@ -0,0 +1,64 @@ +/** @file + * IPRT - Generic Handle Operations. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_handle_h +#define ___iprt_handle_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_handle RTHandle - Generic Handle Operations + * @ingroup grp_rt + * @{ + */ + +/** + * Closes or destroy a generic handle. + * + * @returns IPRT status code. + * @param ph Pointer to the generic handle. The structure handle + * will be set to NIL. A NULL pointer or a NIL handle + * will be quietly ignore (VINF_SUCCESS). + */ +RTDECL(int) RTHandleClose(PRTHANDLE ph); + +/** + * Gets one of the standard handles. + * + * @returns IPRT status code. + * @param enmStdHandle The standard handle. + * @param ph Pointer to the generic handle. This will contain + * the most appropriate IPRT handle on success. + */ +RTDECL(int) RTHandleGetStandard(RTHANDLESTD enmStdHandle, PRTHANDLE ph); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/handletable.h b/include/iprt/handletable.h new file mode 100644 index 00000000..0ade7412 --- /dev/null +++ b/include/iprt/handletable.h @@ -0,0 +1,243 @@ +/** @file + * IPRT - Handle Tables. + */ + +/* + * Copyright (C) 2008 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. + */ + +#ifndef ___iprt_handletable_h +#define ___iprt_handletable_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_handletable RTHandleTable - Handle Tables + * @ingroup grp_rt + * @{ + */ + +/** + * Callback for retaining an object during the lookup and free calls. + * + * This callback is executed when a handle is being looked up in one + * way or another from behind the handle table lock. This allows you + * to increase the reference (or some equivalent thing) during the + * handle lookup and thereby eliminate any race with anyone trying + * to free the handle. + * + * Note that there is no counterpart to this callback, so if you make + * use of this you'll have to release the object manually of course. + * + * Another use of this callback is to do some extra access checking. + * Use the return code to indicate whether the lookup should fail + * or not (no object is returned on faliure, naturally). + * + * @returns IPRT status code for the lookup (the caller won't see this). + * + * @param hHandleTable The handle table handle. + * @param pvObj The object which has been looked up. + * @param pvCtx The context argument if the handle table was created with the + * RTHANDLETABLE_FLAGS_CONTEXT set. Otherwise NULL. + * @param pvUser The user context argument specified when creating the table. + */ +typedef DECLCALLBACK(int) FNRTHANDLETABLERETAIN(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, void *pvUser); +/** Pointer to a FNHANDLETABLERETAIN. */ +typedef FNRTHANDLETABLERETAIN *PFNRTHANDLETABLERETAIN; + +/** + * Callback for deleting a left over object during RTHandleTableDestroy. + * + * @param hHandleTable The handle table handle. + * @param h The handle. + * @param pvObj The object. + * @param pvCtx The context argument if the handle table was created with the + * RTHANDLETABLE_FLAGS_CONTEXT set. Otherwise NULL. + * @param pvUser The user context argument specified when creating the table. + * + */ +typedef DECLCALLBACK(void) FNRTHANDLETABLEDELETE(RTHANDLETABLE hHandleTable, uint32_t h, void *pvObj, void *pvCtx, void *pvUser); +/** Pointer to a FNRTHANDLETABLEDELETE. */ +typedef FNRTHANDLETABLEDELETE *PFNRTHANDLETABLEDELETE; + + +/** @name RTHandleTableCreateEx flags + * @{ */ +/** Whether the handle table entries takes a context or not. + * + * This can be useful for associating a handle with for instance a process or + * similar in order to prevent anyone but the owner from using the handle. + * + * Setting this means you will have to use the WithCtx functions to do the + * handle management. */ +#define RTHANDLETABLE_FLAGS_CONTEXT RT_BIT_32(0) +/** Whether the handle table should take care of the serialization. + * If not specified the caller will have to take care of that. */ +#define RTHANDLETABLE_FLAGS_LOCKED RT_BIT_32(1) +/** The mask of valid flags. */ +#define RTHANDLETABLE_FLAGS_MASK UINT32_C(0x00000003) +/** @} */ + + +/** + * Creates a handle table. + * + * The handle table translates a 32-bit handle into an object pointer, + * optionally calling you back so you can retain the object without + * racing RTHandleTableFree. + * + * @returns IPRT status code and on success a handle table handle will be stored at the + * location phHandleTable points at. + * + * @param phHandleTable Where to store the handle table handle on success. + * @param fFlags Flags, see RTHANDLETABLE_FLAGS_*. + * @param uBase The handle base value. This is the value of the + * first handle to be returned. + * @param cMax The max number of handles. When exceeded the RTHandleTableAlloc + * or RTHandleTableAllocWithCtx calls will fail. Note that this + * number will be rounded up to a multiple of the sub-table size, + * or if it's too close to UINT32_MAX it will be rounded down. + * @param pfnRetain Optional retain callback that will be called from behind the + * lock (if any) during lookup. + * @param pvUser The user argument to the retain callback. + */ +RTDECL(int) RTHandleTableCreateEx(PRTHANDLETABLE phHandleTable, uint32_t fFlags, uint32_t uBase, uint32_t cMax, + PFNRTHANDLETABLERETAIN pfnRetain, void *pvUser); + +/** + * A simplified version of the RTHandleTableCreateEx API. + * + * It assumes a max of about 64K handles with 1 being the base. The table + * access will serialized (RTHANDLETABLE_FLAGS_LOCKED). + * + * @returns IPRT status code and *phHandleTable. + * + * @param phHandleTable Where to store the handle table handle on success. + */ +RTDECL(int) RTHandleTableCreate(PRTHANDLETABLE phHandleTable); + +/** + * Destroys a handle table. + * + * If any entries are still in used the pfnDelete callback will be invoked + * on each of them (if specfied) to allow to you clean things up. + * + * @returns IPRT status code + * + * @param hHandleTable The handle to the handle table. + * @param pfnDelete Function to be called back on each handle still in use. Optional. + * @param pvUser The user argument to pfnDelete. + */ +RTDECL(int) RTHandleTableDestroy(RTHANDLETABLE hHandleTable, PFNRTHANDLETABLEDELETE pfnDelete, void *pvUser); + +/** + * Allocates a handle from the handle table. + * + * @returns IPRT status code, almost any. + * @retval VINF_SUCCESS on success. + * @retval VERR_NO_MEMORY if we failed to extend the handle table. + * @retval VERR_NO_MORE_HANDLES if we're out of handles. + * + * @param hHandleTable The handle to the handle table. + * @param pvObj The object to associate with the new handle. + * This must be aligned on a 4 byte boundary. + * @param ph Where to return the handle on success. + * + * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation. + */ +RTDECL(int) RTHandleTableAlloc(RTHANDLETABLE hHandleTable, void *pvObj, uint32_t *ph); + +/** + * Looks up a handle. + * + * @returns The object pointer on success. NULL on failure. + * + * @param hHandleTable The handle to the handle table. + * @param h The handle to lookup. + * + * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation. + */ +RTDECL(void *) RTHandleTableLookup(RTHANDLETABLE hHandleTable, uint32_t h); + +/** + * Looks up and frees a handle. + * + * @returns The object pointer on success. NULL on failure. + * + * @param hHandleTable The handle to the handle table. + * @param h The handle to lookup. + * + * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation. + */ +RTDECL(void *) RTHandleTableFree(RTHANDLETABLE hHandleTable, uint32_t h); + +/** + * Allocates a handle from the handle table. + * + * @returns IPRT status code, almost any. + * @retval VINF_SUCCESS on success. + * @retval VERR_NO_MEMORY if we failed to extend the handle table. + * @retval VERR_NO_MORE_HANDLES if we're out of handles. + * + * @param hHandleTable The handle to the handle table. + * @param pvObj The object to associate with the new handle. + * This must be aligned on a 4 byte boundary. + * @param pvCtx The context to associate with the new handle. + * @param ph Where to return the handle on success. + * + * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation. + */ +RTDECL(int) RTHandleTableAllocWithCtx(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, uint32_t *ph); + +/** + * Looks up a handle. + * + * @returns The object pointer on success. NULL on failure. + * + * @param hHandleTable The handle to the handle table. + * @param h The handle to lookup. + * @param pvCtx The handle context, this must match what was given on allocation. + * + * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation. + */ +RTDECL(void *) RTHandleTableLookupWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx); + +/** + * Looks up and frees a handle. + * + * @returns The object pointer on success. NULL on failure. + * + * @param hHandleTable The handle to the handle table. + * @param h The handle to lookup. + * @param pvCtx The handle context, this must match what was given on allocation. + * + * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation. + */ +RTDECL(void *) RTHandleTableFreeWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx); + +/** @} */ + +RT_C_DECLS_END + + +#endif + diff --git a/include/iprt/heap.h b/include/iprt/heap.h new file mode 100644 index 00000000..f9e0c524 --- /dev/null +++ b/include/iprt/heap.h @@ -0,0 +1,356 @@ +/** @file + * IPRT - Heap Implementations + */ + +/* + * Copyright (C) 2006-2009 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. + */ + +#ifndef ___iprt_heap_h +#define ___iprt_heap_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_heap RTHeap - Heap Implementations + * @ingroup grp_rt + * @{ + */ + + +/** @defgroup grp_rt_heap_simple RTHeapSimple - Simple Heap + * @{ + */ + +/** + * Initializes the heap. + * + * @returns IPRT status code. + * @param pHeap Where to store the heap anchor block on success. + * @param pvMemory Pointer to the heap memory. + * @param cbMemory The size of the heap memory. + */ +RTDECL(int) RTHeapSimpleInit(PRTHEAPSIMPLE pHeap, void *pvMemory, size_t cbMemory); + +/** + * Merge two simple heaps into one. + * + * The requirement is of course that they next two each other memory wise. + * + * @returns IPRT status code. + * @param pHeap Where to store the handle to the merged heap on success. + * @param Heap1 Handle to the first heap. + * @param Heap2 Handle to the second heap. + * @remark This API isn't implemented yet. + */ +RTDECL(int) RTHeapSimpleMerge(PRTHEAPSIMPLE pHeap, RTHEAPSIMPLE Heap1, RTHEAPSIMPLE Heap2); + +/** + * Relocater the heap internal structures after copying it to a new location. + * + * This can be used when loading a saved heap. + * + * @returns IPRT status code. + * @param hHeap Heap handle that has already been adjusted by to the new + * location. That is to say, when calling + * RTHeapSimpleInit, the caller must note the offset of the + * returned heap handle into the heap memory. This offset + * must be used when calcuating the handle value for the + * new location. The offset may in some cases not be zero! + * @param offDelta The delta between the new and old location, i.e. what + * should be added to the internal pointers. + */ +RTDECL(int) RTHeapSimpleRelocate(RTHEAPSIMPLE hHeap, uintptr_t offDelta); + +/** + * Allocates memory from the specified simple heap. + * + * @returns Pointer to the allocated memory block on success. + * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.) + * + * @param Heap The heap to allocate the memory on. + * @param cb The requested heap block size. + * @param cbAlignment The requested heap block alignment. Pass 0 for default alignment. + * Must be a power of 2. + */ +RTDECL(void *) RTHeapSimpleAlloc(RTHEAPSIMPLE Heap, size_t cb, size_t cbAlignment); + +/** + * Allocates zeroed memory from the specified simple heap. + * + * @returns Pointer to the allocated memory block on success. + * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.) + * + * @param Heap The heap to allocate the memory on. + * @param cb The requested heap block size. + * @param cbAlignment The requested heap block alignment. Pass 0 for default alignment. + * Must be a power of 2. + */ +RTDECL(void *) RTHeapSimpleAllocZ(RTHEAPSIMPLE Heap, size_t cb, size_t cbAlignment); + +/** + * Reallocates / Allocates / Frees a heap block. + * + * @param Heap The heap. This is optional and will only be used for strict assertions. + * @param pv The heap block returned by RTHeapSimple. If NULL it behaves like RTHeapSimpleAlloc(). + * @param cbNew The new size of the heap block. If NULL it behaves like RTHeapSimpleFree(). + * @param cbAlignment The requested heap block alignment. Pass 0 for default alignment. + * Must be a power of 2. + * @remark This API isn't implemented yet. + */ +RTDECL(void *) RTHeapSimpleRealloc(RTHEAPSIMPLE Heap, void *pv, size_t cbNew, size_t cbAlignment); + +/** + * Reallocates / Allocates / Frees a heap block, zeroing any new bits. + * + * @param Heap The heap. This is optional and will only be used for strict assertions. + * @param pv The heap block returned by RTHeapSimple. If NULL it behaves like RTHeapSimpleAllocZ(). + * @param cbNew The new size of the heap block. If NULL it behaves like RTHeapSimpleFree(). + * @param cbAlignment The requested heap block alignment. Pass 0 for default alignment. + * Must be a power of 2. + * @remark This API isn't implemented yet. + */ +RTDECL(void *) RTHeapSimpleReallocZ(RTHEAPSIMPLE Heap, void *pv, size_t cbNew, size_t cbAlignment); + +/** + * Frees memory allocated from a simple heap. + * + * @param Heap The heap. This is optional and will only be used for strict assertions. + * @param pv The heap block returned by RTHeapSimple + */ +RTDECL(void) RTHeapSimpleFree(RTHEAPSIMPLE Heap, void *pv); + +/** + * Gets the size of the specified heap block. + * + * @returns The actual size of the heap block. + * @returns 0 if \a pv is NULL or it doesn't point to a valid heap block. An invalid \a pv + * can also cause traps or trigger assertions. + * @param Heap The heap. This is optional and will only be used for strict assertions. + * @param pv The heap block returned by RTHeapSimple + */ +RTDECL(size_t) RTHeapSimpleSize(RTHEAPSIMPLE Heap, void *pv); + +/** + * Gets the size of the heap. + * + * This size includes all the internal heap structures. So, even if the heap is + * empty the RTHeapSimpleGetFreeSize() will never reach the heap size returned + * by this function. + * + * @returns The heap size. + * @returns 0 if heap was safely detected as being bad. + * @param Heap The heap. + */ +RTDECL(size_t) RTHeapSimpleGetHeapSize(RTHEAPSIMPLE Heap); + +/** + * Returns the sum of all free heap blocks. + * + * This is the amount of memory you can theoretically allocate + * if you do allocations exactly matching the free blocks. + * + * @returns The size of the free blocks. + * @returns 0 if heap was safely detected as being bad. + * @param Heap The heap. + */ +RTDECL(size_t) RTHeapSimpleGetFreeSize(RTHEAPSIMPLE Heap); + +/** + * Printf like callbaclk function for RTHeapSimpleDump. + * @param pszFormat IPRT format string. + * @param ... Format arguments. + */ +typedef DECLCALLBACK(void) FNRTHEAPSIMPLEPRINTF(const char *pszFormat, ...); +/** Pointer to a FNRTHEAPSIMPLEPRINTF function. */ +typedef FNRTHEAPSIMPLEPRINTF *PFNRTHEAPSIMPLEPRINTF; + +/** + * Dumps the hypervisor heap. + * + * @param Heap The heap handle. + * @param pfnPrintf Printf like function that groks IPRT formatting. + */ +RTDECL(void) RTHeapSimpleDump(RTHEAPSIMPLE Heap, PFNRTHEAPSIMPLEPRINTF pfnPrintf); + +/** @} */ + + + +/** @defgroup grp_rt_heap_offset RTHeapOffset - Offset Based Heap + * + * This is a variation on the simple heap that doesn't use pointers internally + * and therefore can be saved and restored without any extra effort. + * + * @{ + */ + +/** + * Initializes the heap. + * + * @returns IPRT status code. + * @param phHeap Where to store the heap anchor block on success. + * @param pvMemory Pointer to the heap memory. + * @param cbMemory The size of the heap memory. + */ +RTDECL(int) RTHeapOffsetInit(PRTHEAPOFFSET phHeap, void *pvMemory, size_t cbMemory); + +/** + * Merge two simple heaps into one. + * + * The requirement is of course that they next two each other memory wise. + * + * @returns IPRT status code. + * @param phHeap Where to store the handle to the merged heap on success. + * @param hHeap1 Handle to the first heap. + * @param hHeap2 Handle to the second heap. + * @remark This API isn't implemented yet. + */ +RTDECL(int) RTHeapOffsetMerge(PRTHEAPOFFSET phHeap, RTHEAPOFFSET hHeap1, RTHEAPOFFSET hHeap2); + +/** + * Allocates memory from the specified simple heap. + * + * @returns Pointer to the allocated memory block on success. + * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.) + * + * @param hHeap The heap to allocate the memory on. + * @param cb The requested heap block size. + * @param cbAlignment The requested heap block alignment. Pass 0 for default alignment. + * Must be a power of 2. + */ +RTDECL(void *) RTHeapOffsetAlloc(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment); + +/** + * Allocates zeroed memory from the specified simple heap. + * + * @returns Pointer to the allocated memory block on success. + * @returns NULL if the request cannot be satisfied. (A VERR_NO_MEMORY condition.) + * + * @param hHeap The heap to allocate the memory on. + * @param cb The requested heap block size. + * @param cbAlignment The requested heap block alignment. Pass 0 for default + * alignment. Must be a power of 2. + */ +RTDECL(void *) RTHeapOffsetAllocZ(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment); + +/** + * Reallocates / Allocates / Frees a heap block. + * + * @param hHeap The heap handle. This is optional and will only be used + * for strict assertions. + * @param pv The heap block returned by RTHeapOffset. If NULL it + * behaves like RTHeapOffsetAlloc(). + * @param cbNew The new size of the heap block. If NULL it behaves like + * RTHeapOffsetFree(). + * @param cbAlignment The requested heap block alignment. Pass 0 for default + * alignment. Must be a power of 2. + * @remark This API isn't implemented yet. + */ +RTDECL(void *) RTHeapOffsetRealloc(RTHEAPOFFSET hHeap, void *pv, size_t cbNew, size_t cbAlignment); + +/** + * Reallocates / Allocates / Frees a heap block, zeroing any new bits. + * + * @param hHeap The heap handle. This is optional and will only be used + * for strict assertions. + * @param pv The heap block returned by RTHeapOffset. If NULL it + * behaves like RTHeapOffsetAllocZ(). + * @param cbNew The new size of the heap block. If NULL it behaves like + * RTHeapOffsetFree(). + * @param cbAlignment The requested heap block alignment. Pass 0 for default + * alignment. Must be a power of 2. + * @remark This API isn't implemented yet. + */ +RTDECL(void *) RTHeapOffsetReallocZ(RTHEAPOFFSET hHeap, void *pv, size_t cbNew, size_t cbAlignment); + +/** + * Frees memory allocated from a simple heap. + * + * @param hHeap The heap handle. This is optional and will only be used + * for strict assertions. + * @param pv The heap block returned by RTHeapOffset + */ +RTDECL(void) RTHeapOffsetFree(RTHEAPOFFSET hHeap, void *pv); + +/** + * Gets the size of the specified heap block. + * + * @returns The actual size of the heap block. + * @returns 0 if \a pv is NULL or it doesn't point to a valid heap block. An + * invalid \a pv can also cause traps or trigger assertions. + * + * @param hHeap The heap handle. This is optional and will only be used + * for strict assertions. + * @param pv The heap block returned by RTHeapOffset + */ +RTDECL(size_t) RTHeapOffsetSize(RTHEAPOFFSET hHeap, void *pv); + +/** + * Gets the size of the heap. + * + * This size includes all the internal heap structures. So, even if the heap is + * empty the RTHeapOffsetGetFreeSize() will never reach the heap size returned + * by this function. + * + * @returns The heap size. + * @returns 0 if heap was safely detected as being bad. + * @param hHeap The heap handle. + */ +RTDECL(size_t) RTHeapOffsetGetHeapSize(RTHEAPOFFSET hHeap); + +/** + * Returns the sum of all free heap blocks. + * + * This is the amount of memory you can theoretically allocate + * if you do allocations exactly matching the free blocks. + * + * @returns The size of the free blocks. + * @returns 0 if heap was safely detected as being bad. + * @param hHeap The heap handle. + */ +RTDECL(size_t) RTHeapOffsetGetFreeSize(RTHEAPOFFSET hHeap); + +/** + * Printf like callbaclk function for RTHeapOffsetDump. + * @param pszFormat IPRT format string. + * @param ... Format arguments. + */ +typedef DECLCALLBACK(void) FNRTHEAPOFFSETPRINTF(const char *pszFormat, ...); +/** Pointer to a FNRTHEAPOFFSETPRINTF function. */ +typedef FNRTHEAPOFFSETPRINTF *PFNRTHEAPOFFSETPRINTF; + +/** + * Dumps the hypervisor heap. + * + * @param hHeap The heap handle. + * @param pfnPrintf Printf like function that groks IPRT formatting. + */ +RTDECL(void) RTHeapOffsetDump(RTHEAPOFFSET hHeap, PFNRTHEAPOFFSETPRINTF pfnPrintf); + +/** @} */ + +/** @} */ +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/initterm.h b/include/iprt/initterm.h new file mode 100644 index 00000000..9fff94fc --- /dev/null +++ b/include/iprt/initterm.h @@ -0,0 +1,238 @@ +/** @file + * IPRT - Runtime Init/Term. + */ + +/* + * Copyright (C) 2006-2009 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. + */ + +#ifndef ___iprt_initterm_h +#define ___iprt_initterm_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt IPRT C/C++ APIs + * @{ + */ + +/** @defgroup grp_rt_initterm Init / Term + * @{ + */ + +#ifdef IN_RING3 +/** @name RTR3Init flags (RTR3INIT_XXX). + * @{ */ +/** Try initialize SUPLib. */ +#define RTR3INIT_FLAGS_SUPLIB RT_BIT(0) +/** Initializing IPRT from a DLL. */ +#define RTR3INIT_FLAGS_DLL RT_BIT(1) +/** @} */ + +/** @name RTR3InitEx version + * @{ */ +/** Version 1. */ +#define RTR3INIT_VER_1 UINT32_C(1) +/** The current version. */ +#define RTR3INIT_VER_CUR RTR3INIT_VER_1 +/** @} */ + +/** + * Initializes the runtime library. + * + * @returns iprt status code. + * @param fFlags Flags, see RTR3INIT_XXX. + */ +RTR3DECL(int) RTR3InitExeNoArguments(uint32_t fFlags); + +/** + * Initializes the runtime library. + * + * @returns iprt status code. + * @param cArgs Pointer to the argument count. + * @param ppapszArgs Pointer to the argument vector pointer. + * @param fFlags Flags, see RTR3INIT_XXX. + */ +RTR3DECL(int) RTR3InitExe(int cArgs, char ***papszArgs, uint32_t fFlags); + +/** + * Initializes the runtime library. + * + * @returns iprt status code. + * @param fFlags Flags, see RTR3INIT_XXX. + */ +RTR3DECL(int) RTR3InitDll(uint32_t fFlags); + +/** + * Initializes the runtime library and possibly also SUPLib too. + * + * Avoid this interface, it's not considered stable. + * + * @returns IPRT status code. + * @param iVersion The interface version. Must be 0 atm. + * @param fFlags Flags, see RTR3INIT_XXX. + * @param cArgs Pointer to the argument count. + * @param ppapszArgs Pointer to the argument vector pointer. NULL + * allowed if @a cArgs is 0. + * @param pszProgramPath The program path. Pass NULL if we're to figure it + * out ourselves. + */ +RTR3DECL(int) RTR3InitEx(uint32_t iVersion, uint32_t fFlags, int cArgs, char ***papszArgs, const char *pszProgramPath); + +/** + * Terminates the runtime library. + */ +RTR3DECL(void) RTR3Term(void); + +#endif /* IN_RING3 */ + + +#ifdef IN_RING0 +/** + * Initializes the ring-0 driver runtime library. + * + * @returns iprt status code. + * @param fReserved Flags reserved for the future. + */ +RTR0DECL(int) RTR0Init(unsigned fReserved); + +/** + * Terminates the ring-0 driver runtime library. + */ +RTR0DECL(void) RTR0Term(void); + +/** + * Forcibily terminates the ring-0 driver runtime library. + * + * This should be used when statically linking the IPRT. Module using dynamic + * linking shall use RTR0Term. If you're not sure, use RTR0Term! + */ +RTR0DECL(void) RTR0TermForced(void); +#endif + +#ifdef IN_RC +/** + * Initializes the raw-mode context runtime library. + * + * @returns iprt status code. + * + * @param u64ProgramStartNanoTS The startup timestamp. + */ +RTRCDECL(int) RTRCInit(uint64_t u64ProgramStartNanoTS); + +/** + * Terminates the raw-mode context runtime library. + */ +RTRCDECL(void) RTRCTerm(void); +#endif + + +/** + * Termination reason. + */ +typedef enum RTTERMREASON +{ + /** Normal exit. iStatus contains the exit code. */ + RTTERMREASON_EXIT = 1, + /** Any abnormal exit. iStatus is 0 and has no meaning. */ + RTTERMREASON_ABEND, + /** Killed by a signal. The iStatus contains the signal number. */ + RTTERMREASON_SIGNAL, + /** The IPRT module is being unloaded. iStatus is 0 and has no meaning. */ + RTTERMREASON_UNLOAD +} RTTERMREASON; + +/** Whether lazy clean up is Okay or not. + * When the process is exiting, it is a waste of time to for instance free heap + * memory or close open files. OTOH, when the runtime is unloaded from the + * process, it is important to release absolutely all resources to prevent + * resource leaks. */ +#define RTTERMREASON_IS_LAZY_CLEANUP_OK(enmReason) ((enmReason) != RTTERMREASON_UNLOAD) + + +/** + * IPRT termination callback function. + * + * @param enmReason The cause of the termination. + * @param iStatus The meaning of this depends on enmReason. + * @param pvUser User argument passed to RTTermRegisterCallback. + */ +typedef DECLCALLBACK(void) FNRTTERMCALLBACK(RTTERMREASON enmReason, int32_t iStatus, void *pvUser); +/** Pointer to an IPRT termination callback function. */ +typedef FNRTTERMCALLBACK *PFNRTTERMCALLBACK; + + +/** + * Registers a termination callback. + * + * This is intended for performing clean up during IPRT termination. Frequently + * paired with lazy initialization thru RTOnce. + * + * The callbacks are called in LIFO order. + * + * @returns IPRT status code. + * + * @param pfnCallback The callback function. + * @param pvUser The user argument for the callback. + * + * @remarks May need to acquire a fast mutex or critical section, so use with + * some care in ring-0 context. + * + * @remarks Be very careful using this from code that may be unloaded before + * IPRT terminates. Unlike some atexit and on_exit implementations, + * IPRT will not automatically unregister callbacks when a module gets + * unloaded. + */ +RTDECL(int) RTTermRegisterCallback(PFNRTTERMCALLBACK pfnCallback, void *pvUser); + +/** + * Deregister a termination callback. + * + * @returns VINF_SUCCESS if found, VERR_NOT_FOUND if the callback/pvUser pair + * wasn't found. + * + * @param pfnCallback The callback function. + * @param pvUser The user argument for the callback. + */ +RTDECL(int) RTTermDeregisterCallback(PFNRTTERMCALLBACK pfnCallback, void *pvUser); + +/** + * Runs the termination callback queue. + * + * Normally called by an internal IPRT termination function, but may also be + * called by external code immediately prior to terminating IPRT if it is in a + * better position to state the termination reason and/or status. + * + * @param enmReason The reason why it's called. + * @param iStatus The associated exit status or signal number. + */ +RTDECL(void) RTTermRunCallbacks(RTTERMREASON enmReason, int32_t iStatus); + +/** @} */ + +/** @} */ + +RT_C_DECLS_END + + +#endif + diff --git a/include/iprt/isofs.h b/include/iprt/isofs.h new file mode 100644 index 00000000..c7774cd9 --- /dev/null +++ b/include/iprt/isofs.h @@ -0,0 +1,225 @@ +/** @file + * IPRT - ISO 9660 file system handling. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_isofs_h +#define ___iprt_isofs_h + +#include <iprt/types.h> +#include <iprt/list.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_isofs RTIsoFs - ISO 9660 Filesystem + * @ingroup grp_rt + * @{ + */ + +#define RTISOFS_MAX_SYSTEM_ID 32 +#define RTISOFS_MAX_VOLUME_ID 32 +#define RTISOFS_MAX_PUBLISHER_ID 128 +#define RTISOFS_MAX_VOLUME_ID 32 +#define RTISOFS_MAX_VOLUMESET_ID 128 +#define RTISOFS_MAX_PREPARER_ID 128 +#define RTISOFS_MAX_APPLICATION_ID 128 +#define RTISOFS_MAX_STRING_LEN 255 + +/** Standard ID of volume descriptors. */ +#define RTISOFS_STANDARD_ID "CD001" + +/** Default sector size. */ +#define RTISOFS_SECTOR_SIZE 2048 + + +#pragma pack(1) +typedef struct RTISOFSDATESHORT +{ + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + int8_t gmt_offset; +} RTISOFSDATESHORT, *PRTISOFSDATESHORT; + +typedef struct RTISOFSDATELONG +{ + char year[4]; + char month[2]; + char day[2]; + char hour[2]; + char minute[2]; + char second[2]; + char hseconds[2]; + int8_t gmt_offset; +} RTISOFSDATELONG, *PRTISOFSDATELONG; + +/* Directory Record. */ +typedef struct RTISOFSDIRRECORD +{ + uint8_t record_length; + uint8_t extented_attr_length; + uint32_t extent_location; + uint32_t extent_location_big; + uint32_t extent_data_length; /* Number of bytes (file) / len (directory). */ + uint32_t extent_data_length_big; + RTISOFSDATESHORT date; + uint8_t flags; + uint8_t interleave_unit_size; + uint8_t interleave_gap_size; + uint16_t volume_sequence_number; + uint16_t volume_sequence_number_big; + uint8_t name_len; + /* Starting here there will be the actual directory entry name + * and a padding of 1 byte if name_len is odd. */ +} RTISOFSDIRRECORD, *PRTISOFSDIRRECORD; + +/* Primary Volume Descriptor. */ +typedef struct RTISOFSPRIVOLDESC +{ + uint8_t type; + char name_id[6]; + uint8_t version; + char system_id[RTISOFS_MAX_SYSTEM_ID]; + char volume_id[RTISOFS_MAX_VOLUME_ID]; + uint8_t unused2[8]; + uint32_t volume_space_size; /* Number of sectors, Little Endian. */ + uint32_t volume_space_size_big; /* Number of sectors Big Endian. */ + uint8_t unused3[32]; + uint16_t volume_set_size; + uint16_t volume_set_size_big; + uint16_t volume_sequence_number; + uint16_t volume_sequence_number_big; + uint16_t logical_block_size; /* 2048. */ + uint16_t logical_block_size_big; + uint32_t path_table_size; /* Size in bytes. */ + uint32_t path_table_size_big; /* Size in bytes. */ + uint32_t path_table_start_first; + uint32_t path_table_start_second; + uint32_t path_table_start_first_big; + uint32_t path_table_start_second_big; + RTISOFSDIRRECORD root_directory_record; + uint8_t directory_padding; + char volume_set_id[RTISOFS_MAX_VOLUMESET_ID]; + char publisher_id[RTISOFS_MAX_PUBLISHER_ID]; + char preparer_id[RTISOFS_MAX_PREPARER_ID]; + char application_id[RTISOFS_MAX_APPLICATION_ID]; + char copyright_file_id[37]; + char abstract_file_id[37]; + char bibliographic_file_id[37]; + RTISOFSDATELONG creation_date; + RTISOFSDATELONG modification_date; + RTISOFSDATELONG expiration_date; + RTISOFSDATELONG effective_date; + uint8_t file_structure_version; + uint8_t unused4[1]; + char application_data[512]; + uint8_t unused5[653]; +} RTISOFSPRIVOLDESC, *PRTISOFSPRIVOLDESC; + +typedef struct RTISOFSPATHTABLEHEADER +{ + uint8_t length; + uint8_t extended_attr_sectors; + /** Sector of starting directory table. */ + uint32_t sector_dir_table; + /** Index of parent directory (1 for the root). */ + uint16_t parent_index; + /* Starting here there will be the name of the directory, + * specified by length above. */ +} RTISOFSPATHTABLEHEADER, *PRTISOFSPATHTABLEHEADER; + +typedef struct RTISOFSPATHTABLEENTRY +{ + char *path; + char *path_full; + RTISOFSPATHTABLEHEADER header; + RTLISTNODE Node; +} RTISOFSPATHTABLEENTRY, *PRTISOFSPATHTABLEENTRY; + +typedef struct RTISOFSFILE +{ + RTFILE file; + RTLISTANCHOR listPaths; + RTISOFSPRIVOLDESC pvd; +} RTISOFSFILE, *PRTISOFSFILE; +#pragma pack() + + +#ifdef IN_RING3 +/** + * Opens an ISO file. + * + * The following limitations apply: + * - Fixed sector size (2048 bytes). + * - No extensions (Joliet, RockRidge etc.) support (yet). + * - Only primary volume descriptor (PVD) handled. + * + * @return IPRT status code. + * @param pFile Pointer to ISO handle. + * @param pszFileName Path to ISO file to open. + */ +RTR3DECL(int) RTIsoFsOpen(PRTISOFSFILE pFile, const char *pszFileName); + +/** + * Closes an ISO file. + * + * @param pFile Pointer to open ISO file returned by RTIsoFsOpen(). + */ +RTR3DECL(void) RTIsoFsClose(PRTISOFSFILE pFile); + +/** + * Retrieves the offset + length (both in bytes) of a given file + * stored in the ISO. + * @note According to the standard, a file cannot be larger than 2^32-1 bytes. + * Therefore using size_t / uint32_t is not a problem. + * + * @return IPRT status code. + * @param pFile Pointer to open ISO file returned by RTIsoFsOpen(). + * @param pszPath Path of file within the ISO to retrieve information for. + * @param pcbOffset Pointer to store the file's absolute offset within the ISO. + * @param pcbLength Pointer to store the file's size. + */ +RTR3DECL(int) RTIsoFsGetFileInfo(PRTISOFSFILE pFile, const char *pszPath, + uint32_t *pcbOffset, size_t *pcbLength); + +/** + * Extracts a file from an ISO to the given destination. + * + * @return IPRT status code. + * @param pFile Pointer to open ISO file returned by RTIsoFsOpen(). + * @param pszPath Path of file within the ISO to extract. + * @param pszDest Where to store the extracted file. + */ +RTR3DECL(int) RTIsoFsExtractFile(PRTISOFSFILE pFile, const char *pszSource, + const char *pszDest); +#endif /* IN_RING3 */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/ldr.h b/include/iprt/ldr.h new file mode 100644 index 00000000..9e036d83 --- /dev/null +++ b/include/iprt/ldr.h @@ -0,0 +1,559 @@ +/** @file + * IPRT - Loader. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_ldr_h +#define ___iprt_ldr_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + +/** @defgroup grp_ldr RTLdr - Loader + * @ingroup grp_rt + * @{ + */ + + +RT_C_DECLS_BEGIN + +/** Loader address (unsigned integer). */ +typedef RTUINTPTR RTLDRADDR; +/** Pointer to a loader address. */ +typedef RTLDRADDR *PRTLDRADDR; +/** Pointer to a const loader address. */ +typedef RTLDRADDR const *PCRTLDRADDR; +/** The max loader address value. */ +#define RTLDRADDR_MAX RTUINTPTR_MAX +/** NIL loader address value. */ +#define NIL_RTLDRADDR RTLDRADDR_MAX + + +/** + * Gets the default file suffix for DLL/SO/DYLIB/whatever. + * + * @returns The stuff (readonly). + */ +RTDECL(const char *) RTLdrGetSuff(void); + +/** + * Checks if a library is loadable or not. + * + * This may attempt load and unload the library. + * + * @returns true/false accordingly. + * @param pszFilename Image filename. + */ +RTDECL(bool) RTLdrIsLoadable(const char *pszFilename); + +/** + * Loads a dynamic load library (/shared object) image file using native + * OS facilities. + * + * The filename will be appended the default DLL/SO extension of + * the platform if it have been omitted. This means that it's not + * possible to load DLLs/SOs with no extension using this interface, + * but that's not a bad tradeoff. + * + * If no path is specified in the filename, the OS will usually search it's library + * path to find the image file. + * + * @returns iprt status code. + * @param pszFilename Image filename. + * @param phLdrMod Where to store the handle to the loader module. + */ +RTDECL(int) RTLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod); + +/** + * Loads a dynamic load library (/shared object) image file using native + * OS facilities. + * + * The filename will be appended the default DLL/SO extension of + * the platform if it have been omitted. This means that it's not + * possible to load DLLs/SOs with no extension using this interface, + * but that's not a bad tradeoff. + * + * If no path is specified in the filename, the OS will usually search it's library + * path to find the image file. + * + * @returns iprt status code. + * @param pszFilename Image filename. + * @param phLdrMod Where to store the handle to the loader module. + * @param fFlags See RTLDRLOAD_FLAGS_XXX. + * @param pErrInfo Where to return extended error information. Optional. + */ +RTDECL(int) RTLdrLoadEx(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo); + +/** @defgroup RTLDRLOAD_FLAGS_XXX RTLdrLoadEx flags. + * @{ */ +/** Symbols defined in this library are not made available to resolve + * references in subsequently loaded libraries (default). */ +#define RTLDRLOAD_FLAGS_LOCAL UINT32_C(0) +/** Symbols defined in this library will be made available for symbol + * resolution of subsequently loaded libraries. */ +#define RTLDRLOAD_FLAGS_GLOBAL RT_BIT_32(0) +/** The mask of valid flag bits. */ +#define RTLDRLOAD_FLAGS_VALID_MASK UINT32_C(0x00000001) +/** @} */ + +/** + * Loads a dynamic load library (/shared object) image file residing in the + * RTPathAppPrivateArch() directory. + * + * Suffix is not required. + * + * @returns iprt status code. + * @param pszFilename Image filename. No path. + * @param phLdrMod Where to store the handle to the loaded module. + */ +RTDECL(int) RTLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod); + +/** + * Image architecuture specifier for RTLdrOpenEx. + */ +typedef enum RTLDRARCH +{ + RTLDRARCH_INVALID = 0, + /** Whatever. */ + RTLDRARCH_WHATEVER, + /** The host architecture. */ + RTLDRARCH_HOST, + /** 32-bit x86. */ + RTLDRARCH_X86_32, + /** AMD64 (64-bit x86 if you like). */ + RTLDRARCH_AMD64, + /** End of the valid values. */ + RTLDRARCH_END, + /** Make sure the type is a full 32-bit. */ + RTLDRARCH_32BIT_HACK = 0x7fffffff +} RTLDRARCH; +/** Pointer to a RTLDRARCH. */ +typedef RTLDRARCH *PRTLDRARCH; + +/** + * Open a binary image file, extended version. + * + * @returns iprt status code. + * @param pszFilename Image filename. + * @param fFlags Reserved, MBZ. + * @param enmArch CPU architecture specifier for the image to be loaded. + * @param phLdrMod Where to store the handle to the loader module. + */ +RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod); + +/** + * Opens a binary image file using kLdr. + * + * @returns iprt status code. + * @param pszFilename Image filename. + * @param phLdrMod Where to store the handle to the loaded module. + * @param fFlags Reserved, MBZ. + * @param enmArch CPU architecture specifier for the image to be loaded. + * @remark Primarily for testing the loader. + */ +RTDECL(int) RTLdrOpenkLdr(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod); + +/** + * What to expect and do with the bits passed to RTLdrOpenBits(). + */ +typedef enum RTLDROPENBITS +{ + /** The usual invalid 0 entry. */ + RTLDROPENBITS_INVALID = 0, + /** The bits are readonly and will never be changed. */ + RTLDROPENBITS_READONLY, + /** The bits are going to be changed and the loader will have to duplicate them + * when opening the image. */ + RTLDROPENBITS_WRITABLE, + /** The bits are both the source and destination for the loader operation. + * This means that the loader may have to duplicate them prior to changing them. */ + RTLDROPENBITS_SRC_AND_DST, + /** The end of the valid enums. This entry marks the + * first invalid entry.. */ + RTLDROPENBITS_END, + RTLDROPENBITS_32BIT_HACK = 0x7fffffff +} RTLDROPENBITS; + +/** + * Open a binary image from in-memory bits. + * + * @returns iprt status code. + * @param pvBits The start of the raw-image. + * @param cbBits The size of the raw-image. + * @param enmBits What to expect from the pvBits. + * @param pszLogName What to call the raw-image when logging. + * For RTLdrLoad and RTLdrOpen the filename is used for this. + * @param phLdrMod Where to store the handle to the loader module. + */ +RTDECL(int) RTLdrOpenBits(const void *pvBits, size_t cbBits, RTLDROPENBITS enmBits, const char *pszLogName, PRTLDRMOD phLdrMod); + +/** + * Closes a loader module handle. + * + * The handle can be obtained using any of the RTLdrLoad(), RTLdrOpen() + * and RTLdrOpenBits() functions. + * + * @returns iprt status code. + * @param hLdrMod The loader module handle. + */ +RTDECL(int) RTLdrClose(RTLDRMOD hLdrMod); + +/** + * Gets the address of a named exported symbol. + * + * @returns iprt status code. + * @param hLdrMod The loader module handle. + * @param pszSymbol Symbol name. + * @param ppvValue Where to store the symbol value. Note that this is restricted to the + * pointer size used on the host! + */ +RTDECL(int) RTLdrGetSymbol(RTLDRMOD hLdrMod, const char *pszSymbol, void **ppvValue); + +/** + * Gets the address of a named exported symbol. + * + * This function differs from the plain one in that it can deal with + * both GC and HC address sizes, and that it can calculate the symbol + * value relative to any given base address. + * + * @returns iprt status code. + * @param hLdrMod The loader module handle. + * @param pvBits Optional pointer to the loaded image. + * Set this to NULL if no RTLdrGetBits() processed image bits are available. + * Not supported for RTLdrLoad() images. + * @param BaseAddress Image load address. + * Not supported for RTLdrLoad() images. + * @param pszSymbol Symbol name. + * @param pValue Where to store the symbol value. + */ +RTDECL(int) RTLdrGetSymbolEx(RTLDRMOD hLdrMod, const void *pvBits, RTLDRADDR BaseAddress, const char *pszSymbol, + PRTLDRADDR pValue); + +/** + * Gets the size of the loaded image. + * This is only supported for modules which has been opened using RTLdrOpen() and RTLdrOpenBits(). + * + * @returns image size (in bytes). + * @returns ~(size_t)0 on if not opened by RTLdrOpen(). + * @param hLdrMod Handle to the loader module. + * @remark Not supported for RTLdrLoad() images. + */ +RTDECL(size_t) RTLdrSize(RTLDRMOD hLdrMod); + +/** + * Resolve an external symbol during RTLdrGetBits(). + * + * @returns iprt status code. + * @param hLdrMod The loader module handle. + * @param pszModule Module name. + * @param pszSymbol Symbol name, NULL if uSymbol should be used. + * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used. + * @param pValue Where to store the symbol value (address). + * @param pvUser User argument. + */ +typedef DECLCALLBACK(int) RTLDRIMPORT(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, + PRTLDRADDR pValue, void *pvUser); +/** Pointer to a FNRTLDRIMPORT() callback function. */ +typedef RTLDRIMPORT *PFNRTLDRIMPORT; + +/** + * Loads the image into a buffer provided by the user and applies fixups + * for the given base address. + * + * @returns iprt status code. + * @param hLdrMod The load module handle. + * @param pvBits Where to put the bits. + * Must be as large as RTLdrSize() suggests. + * @param BaseAddress The base address. + * @param pfnGetImport Callback function for resolving imports one by one. + * @param pvUser User argument for the callback. + * @remark Not supported for RTLdrLoad() images. + */ +RTDECL(int) RTLdrGetBits(RTLDRMOD hLdrMod, void *pvBits, RTLDRADDR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser); + +/** + * Relocates bits after getting them. + * Useful for code which moves around a bit. + * + * @returns iprt status code. + * @param hLdrMod The loader module handle. + * @param pvBits Where the image bits are. + * Must have been passed to RTLdrGetBits(). + * @param NewBaseAddress The new base address. + * @param OldBaseAddress The old base address. + * @param pfnGetImport Callback function for resolving imports one by one. + * @param pvUser User argument for the callback. + * @remark Not supported for RTLdrLoad() images. + */ +RTDECL(int) RTLdrRelocate(RTLDRMOD hLdrMod, void *pvBits, RTLDRADDR NewBaseAddress, RTLDRADDR OldBaseAddress, + PFNRTLDRIMPORT pfnGetImport, void *pvUser); + +/** + * Enumeration callback function used by RTLdrEnumSymbols(). + * + * @returns iprt status code. Failure will stop the enumeration. + * @param hLdrMod The loader module handle. + * @param pszSymbol Symbol name. NULL if ordinal only. + * @param uSymbol Symbol ordinal, ~0 if not used. + * @param Value Symbol value. + * @param pvUser The user argument specified to RTLdrEnumSymbols(). + */ +typedef DECLCALLBACK(int) RTLDRENUMSYMS(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTLDRADDR Value, void *pvUser); +/** Pointer to a RTLDRENUMSYMS() callback function. */ +typedef RTLDRENUMSYMS *PFNRTLDRENUMSYMS; + +/** + * Enumerates all symbols in a module. + * + * @returns iprt status code. + * @param hLdrMod The loader module handle. + * @param fFlags Flags indicating what to return and such. + * @param pvBits Optional pointer to the loaded image. (RTLDR_ENUM_SYMBOL_FLAGS_*) + * Set this to NULL if no RTLdrGetBits() processed image bits are available. + * @param BaseAddress Image load address. + * @param pfnCallback Callback function. + * @param pvUser User argument for the callback. + * @remark Not supported for RTLdrLoad() images. + */ +RTDECL(int) RTLdrEnumSymbols(RTLDRMOD hLdrMod, unsigned fFlags, const void *pvBits, RTLDRADDR BaseAddress, PFNRTLDRENUMSYMS pfnCallback, void *pvUser); + +/** @name RTLdrEnumSymbols flags. + * @{ */ +/** Returns ALL kinds of symbols. The default is to only return public/exported symbols. */ +#define RTLDR_ENUM_SYMBOL_FLAGS_ALL RT_BIT(1) +/** @} */ + + +/** + * Debug info type (as far the loader can tell). + */ +typedef enum RTLDRDBGINFOTYPE +{ + /** The invalid 0 value. */ + RTLDRDBGINFOTYPE_INVALID = 0, + /** Unknown debug info format. */ + RTLDRDBGINFOTYPE_UNKNOWN, + /** Stabs. */ + RTLDRDBGINFOTYPE_STABS, + /** Debug With Arbitrary Record Format (DWARF). */ + RTLDRDBGINFOTYPE_DWARF, + /** Microsoft Codeview debug info. */ + RTLDRDBGINFOTYPE_CODEVIEW, + /** Watcom debug info. */ + RTLDRDBGINFOTYPE_WATCOM, + /** IBM High Level Language debug info.. */ + RTLDRDBGINFOTYPE_HLL, + /** The end of the valid debug info values (exclusive). */ + RTLDRDBGINFOTYPE_END, + /** Blow the type up to 32-bits. */ + RTLDRDBGINFOTYPE_32BIT_HACK = 0x7fffffff +} RTLDRDBGINFOTYPE; + +/** + * Debug info enumerator callback. + * + * @returns VINF_SUCCESS to continue the enumeration. Any other status code + * will cause RTLdrEnumDbgInfo to immediately return with that status. + * + * @param hLdrMod The module handle. + * @param iDbgInfo The debug info ordinal number / id. + * @param enmType The debug info type. + * @param iMajorVer The major version number of the debug info format. + * -1 if unknow - implies invalid iMinorVer. + * @param iMinorVer The minor version number of the debug info format. + * -1 when iMajorVer is -1. + * @param pszPartNm The name of the debug info part, NULL if not + * applicable. + * @param offFile The file offset *if* this type has one specific + * location in the executable image file. This is -1 + * if there isn't any specific file location. + * @param LinkAddress The link address of the debug info if it's + * loadable. NIL_RTLDRADDR if not loadable. + * @param cb The size of the debug information. -1 is used if + * this isn't applicable. + * @param pszExtFile This points to the name of an external file + * containing the debug info. This is NULL if there + * isn't any external file. + * @param pvUser The user parameter specified to RTLdrEnumDbgInfo. + */ +typedef DECLCALLBACK(int) FNRTLDRENUMDBG(RTLDRMOD hLdrMod, uint32_t iDbgInfo, RTLDRDBGINFOTYPE enmType, + uint16_t iMajorVer, uint16_t iMinorVer, const char *pszPartNm, + RTFOFF offFile, RTLDRADDR LinkAddress, RTLDRADDR cb, + const char *pszExtFile, void *pvUser); +/** Pointer to a debug info enumerator callback. */ +typedef FNRTLDRENUMDBG *PFNRTLDRENUMDBG; + +/** + * Enumerate the debug info contained in the executable image. + * + * @returns IPRT status code or whatever pfnCallback returns. + * + * @param hLdrMod The module handle. + * @param pvBits Optional pointer to bits returned by + * RTLdrGetBits(). This can be used by some module + * interpreters to reduce memory consumption. + * @param pfnCallback The callback function. + * @param pvUser The user argument. + */ +RTDECL(int) RTLdrEnumDbgInfo(RTLDRMOD hLdrMod, const void *pvBits, PFNRTLDRENUMDBG pfnCallback, void *pvUser); + + +/** + * Loader segment. + */ +typedef struct RTLDRSEG +{ + /** The segment name. (Might not be zero terminated!) */ + const char *pchName; + /** The length of the segment name. */ + uint32_t cchName; + /** The flat selector to use for the segment (i.e. data/code). + * Primarily a way for the user to specify selectors for the LX/LE and NE interpreters. */ + uint16_t SelFlat; + /** The 16-bit selector to use for the segment. + * Primarily a way for the user to specify selectors for the LX/LE and NE interpreters. */ + uint16_t Sel16bit; + /** Segment flags. */ + uint32_t fFlags; + /** The segment protection (RTMEM_PROT_XXX). */ + uint32_t fProt; + /** The size of the segment. */ + RTLDRADDR cb; + /** The required segment alignment. + * The to 0 if the segment isn't supposed to be mapped. */ + RTLDRADDR Alignment; + /** The link address. + * Set to NIL_RTLDRADDR if the segment isn't supposed to be mapped or if + * the image doesn't have link addresses. */ + RTLDRADDR LinkAddress; + /** File offset of the segment. + * Set to -1 if no file backing (like BSS). */ + RTFOFF offFile; + /** Size of the file bits of the segment. + * Set to -1 if no file backing (like BSS). */ + RTFOFF cbFile; + /** The relative virtual address when mapped. + * Set to NIL_RTLDRADDR if the segment isn't supposed to be mapped. */ + RTLDRADDR RVA; + /** The size of the segment including the alignment gap up to the next segment when mapped. + * This is set to NIL_RTLDRADDR if not implemented. */ + RTLDRADDR cbMapped; +} RTLDRSEG; +/** Pointer to a loader segment. */ +typedef RTLDRSEG *PRTLDRSEG; +/** Pointer to a read only loader segment. */ +typedef RTLDRSEG const *PCRTLDRSEG; + + +/** @name Segment flags + * @{ */ +/** The segment is 16-bit. When not set the default of the target architecture is assumed. */ +#define RTLDRSEG_FLAG_16BIT UINT32_C(1) +/** The segment requires a 16-bit selector alias. (OS/2) */ +#define RTLDRSEG_FLAG_OS2_ALIAS16 UINT32_C(2) +/** Conforming segment (x86 weirdness). (OS/2) */ +#define RTLDRSEG_FLAG_OS2_CONFORM UINT32_C(4) +/** IOPL (ring-2) segment. (OS/2) */ +#define RTLDRSEG_FLAG_OS2_IOPL UINT32_C(8) +/** @} */ + +/** + * Segment enumerator callback. + * + * @returns VINF_SUCCESS to continue the enumeration. Any other status code + * will cause RTLdrEnumSegments to immediately return with that + * status. + * + * @param hLdrMod The module handle. + * @param pSeg The segment information. + * @param pvUser The user parameter specified to RTLdrEnumSegments. + */ +typedef DECLCALLBACK(int) FNRTLDRENUMSEGS(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser); +/** Pointer to a segment enumerator callback. */ +typedef FNRTLDRENUMSEGS *PFNRTLDRENUMSEGS; + +/** + * Enumerate the debug info contained in the executable image. + * + * @returns IPRT status code or whatever pfnCallback returns. + * + * @param hLdrMod The module handle. + * @param pfnCallback The callback function. + * @param pvUser The user argument. + */ +RTDECL(int) RTLdrEnumSegments(RTLDRMOD hLdrMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser); + +/** + * Converts a link address to a segment:offset address. + * + * @returns IPRT status code. + * + * @param hLdrMod The module handle. + * @param LinkAddress The link address to convert. + * @param piSeg Where to return the segment index. + * @param poffSeg Where to return the segment offset. + */ +RTDECL(int) RTLdrLinkAddressToSegOffset(RTLDRMOD hLdrMod, RTLDRADDR LinkAddress, uint32_t *piSeg, PRTLDRADDR poffSeg); + +/** + * Converts a link address to an image relative virtual address (RVA). + * + * @returns IPRT status code. + * + * @param hLdrMod The module handle. + * @param LinkAddress The link address to convert. + * @param pRva Where to return the RVA. + */ +RTDECL(int) RTLdrLinkAddressToRva(RTLDRMOD hLdrMod, RTLDRADDR LinkAddress, PRTLDRADDR pRva); + +/** + * Converts an image relative virtual address (RVA) to a segment:offset. + * + * @returns IPRT status code. + * + * @param hLdrMod The module handle. + * @param Rva The link address to convert. + * @param piSeg Where to return the segment index. + * @param poffSeg Where to return the segment offset. + */ +RTDECL(int) RTLdrSegOffsetToRva(RTLDRMOD hLdrMod, uint32_t iSeg, RTLDRADDR offSeg, PRTLDRADDR pRva); + +/** + * Converts a segment:offset into an image relative virtual address (RVA). + * + * @returns IPRT status code. + * + * @param hLdrMod The module handle. + * @param iSeg The segment index. + * @param offSeg The segment offset. + * @param pRva Where to return the RVA. + */ +RTDECL(int) RTLdrRvaToSegOffset(RTLDRMOD hLdrMod, RTLDRADDR Rva, uint32_t *piSeg, PRTLDRADDR poffSeg); + +RT_C_DECLS_END + +/** @} */ + +#endif + diff --git a/include/iprt/linux/sysfs.h b/include/iprt/linux/sysfs.h new file mode 100644 index 00000000..27010af4 --- /dev/null +++ b/include/iprt/linux/sysfs.h @@ -0,0 +1,262 @@ +/* $Id: sysfs.h $ */ +/** @file + * IPRT - Linux sysfs access. + */ + +/* + * Copyright (C) 2008 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. + */ + +#ifndef ___iprt_linux_sysfs_h +#define ___iprt_linux_sysfs_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + +#include <sys/types.h> /* for dev_t */ + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_linux_sysfs RTLinuxSysfs - Linux sysfs + * @ingroup grp_rt + * @{ + */ + +/** + * Checks if a sysfs file (or directory, device, symlink, whatever) exists. + * + * @returns true / false, errno is preserved. + * @param pszFormat The name format, either absolute or relative to "/sys/". + * @param va The format args. + */ +RTDECL(bool) RTLinuxSysFsExistsV(const char *pszFormat, va_list va); + +/** + * Checks if a sysfs file (or directory, device, symlink, whatever) exists. + * + * @returns true / false, errno is preserved. + * @param pszFormat The name format, either absolute or relative to "/sys/". + * @param ... The format args. + */ +RTDECL(bool) RTLinuxSysFsExists(const char *pszFormat, ...); + +/** + * Opens a sysfs file. + * + * @returns The file descriptor. -1 and errno on failure. + * @param pszFormat The name format, either absolute or relative to "/sys/". + * @param va The format args. + */ +RTDECL(int) RTLinuxSysFsOpenV(const char *pszFormat, va_list va); + +/** + * Opens a sysfs file. + * + * @returns The file descriptor. -1 and errno on failure. + * @param pszFormat The name format, either absolute or relative to "/sys/". + * @param ... The format args. + */ +RTDECL(int) RTLinuxSysFsOpen(const char *pszFormat, ...); + +/** + * Closes a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV. + * + * @param fd File descriptor returned by RTLinuxSysFsOpen or + * RTLinuxSysFsOpenV. + */ +RTDECL(void) RTLinuxSysFsClose(int fd); + +/** + * Reads a string from a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV. + * + * @returns The number of bytes read. -1 and errno on failure. + * @param fd The file descriptor returned by RTLinuxSysFsOpen or RTLinuxSysFsOpenV. + * @param pszBuf Where to store the string. + * @param cchBuf The size of the buffer. Must be at least 2 bytes. + */ +RTDECL(ssize_t) RTLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf); + +/** + * Reads the remainder of a file opened with RTLinuxSysFsOpen or + * RTLinuxSysFsOpenV. + * + * @returns IPRT status code. + * @param fd The file descriptor returned by RTLinuxSysFsOpen or RTLinuxSysFsOpenV. + * @param pvBuf Where to store the bits from the file. + * @param cbBuf The size of the buffer. + * @param pcbRead Where to return the number of bytes read. Optional. + */ +RTDECL(int) RTLinuxSysFsReadFile(int fd, void *pvBuf, size_t cbBuf, size_t *pcbRead); + +/** + * Reads a number from a sysfs file. + * + * @returns 64-bit signed value on success, -1 and errno on failure. + * @param uBase The number base, 0 for autodetect. + * @param pszFormat The filename format, either absolute or relative to "/sys/". + * @param va Format args. + */ +RTDECL(int64_t) RTLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va); + +/** + * Reads a number from a sysfs file. + * + * @returns 64-bit signed value on success, -1 and errno on failure. + * @param uBase The number base, 0 for autodetect. + * @param pszFormat The filename format, either absolute or relative to "/sys/". + * @param ... Format args. + */ +RTDECL(int64_t) RTLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...); + +/** + * Reads a device number from a sysfs file. + * + * @returns device number on success, 0 and errno on failure. + * @param pszFormat The filename format, either absolute or relative to "/sys/". + * @param va Format args. + */ +RTDECL(dev_t) RTLinuxSysFsReadDevNumFileV(const char *pszFormat, va_list va); + +/** + * Reads a device number from a sysfs file. + * + * @returns device number on success, 0 and errno on failure. + * @param pszFormat The filename format, either absolute or relative to "/sys/". + * @param ... Format args. + */ +RTDECL(dev_t) RTLinuxSysFsReadDevNumFile(const char *pszFormat, ...); + +/** + * Reads a string from a sysfs file. If the file contains a newline, we only + * return the text up until there. + * + * @returns number of characters read on success, -1 and errno on failure. + * @param pszBuf Where to store the path element. Must be at least two + * characters, but a longer buffer would be advisable. + * @param cchBuf The size of the buffer pointed to by @a pszBuf. + * @param pszFormat The filename format, either absolute or relative to "/sys/". + * @param va Format args. + */ +RTDECL(ssize_t) RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va); + +/** + * Reads a string from a sysfs file. If the file contains a newline, we only + * return the text up until there. + * + * @returns number of characters read on success, -1 and errno on failure. + * @param pszBuf Where to store the path element. Must be at least two + * characters, but a longer buffer would be advisable. + * @param cchBuf The size of the buffer pointed to by @a pszBuf. + * @param pszFormat The filename format, either absolute or relative to "/sys/". + * @param ... Format args. + */ +RTDECL(ssize_t) RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, const char *pszFormat, ...); + +/** + * Reads the last element of the path of the file pointed to by the symbolic + * link specified. + * + * This is needed at least to get the name of the driver associated with a + * device, where pszFormat should be the "driver" link in the devices sysfs + * directory. + * + * @returns The length of the returned string on success, -1 and errno on + * failure. + * @param pszBuf Where to store the path element. Must be at least two + * characters, but a longer buffer would be advisable. + * @param cchBuf The size of the buffer pointed to by @a pszBuf. + * @param pszFormat The filename format, either absolute or relative to "/sys/". + * @param va Format args. + */ +RTDECL(ssize_t) RTLinuxSysFsGetLinkDestV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va); + +/** + * Reads the last element of the path of the file pointed to by the symbolic + * link specified. + * + * This is needed at least to get the name of the driver associated with a + * device, where pszFormat should be the "driver" link in the devices sysfs + * directory. + * + * @returns The length of the returned string on success, -1 and errno on + * failure. + * @param pszBuf Where to store the path element. Must be at least two + * characters, but a longer buffer would be advisable. + * @param cchBuf The size of the buffer pointed to by @a pszBuf. + * @param pszFormat The filename format, either absolute or relative to "/sys/". + * @param ... Format args. + */ +RTDECL(ssize_t) RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, const char *pszFormat, ...); + +/** + * Find the path of a device node under /dev, given then device number. + * + * This function will recursively search under /dev until it finds a device node + * matching @a devnum, and store the path into @a pszBuf. The caller may + * provide an expected path in pszSuggestion, which will be tried before + * searching, but due to the variance in Linux systems it can be hard to always + * correctly predict the path. + * + * @returns The length of the returned string on success, -1 and errno on + * failure. + * @returns -1 and ENOENT if no matching device node could be found. + * @param DevNum The device number to search for. + * @param fMode The type of device - only RTFS_TYPE_DEV_CHAR and + * RTFS_TYPE_DEV_BLOCK are valid values. + * @param pszBuf Where to store the path. + * @param cchBuf The size of the buffer. + * @param pszSuggestion The expected path format of the device node, either + * absolute or relative to "/dev". (Optional) + * @param va Format args. + */ +RTDECL(ssize_t) RTLinuxFindDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf, + const char *pszSuggestion, va_list va); + +/** + * Find the path of a device node under /dev, given the device number. + * + * This function will recursively search under /dev until it finds a device node + * matching @a devnum, and store the path into @a pszBuf. The caller may + * provide an expected path in pszSuggestion, which will be tried before + * searching, but due to the variance in Linux systems it can be hard to always + * correctly predict the path. + * + * @returns The length of the returned string on success, -1 and errno on + * failure. + * @returns -1 and ENOENT if no matching device node could be found. + * @param DevNum The device number to search for + * @param fMode The type of device - only RTFS_TYPE_DEV_CHAR and + * RTFS_TYPE_DEV_BLOCK are valid values + * @param pszBuf Where to store the path. + * @param cchBuf The size of the buffer. + * @param pszSuggestion The expected path format of the device node, either + * absolute or relative to "/dev". (Optional) + * @param ... Format args. + */ +RTDECL(ssize_t) RTLinuxFindDevicePath(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf, + const char *pszSuggestion, ...); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/list.h b/include/iprt/list.h new file mode 100644 index 00000000..1a4a4bc0 --- /dev/null +++ b/include/iprt/list.h @@ -0,0 +1,364 @@ +/** @file + * IPRT - Generic Doubly Linked List. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_list_h +#define ___iprt_list_h + +#include <iprt/types.h> + +/** @defgroup grp_rt_list RTList - Generic Doubly Linked List + * @ingroup grp_rt + * + * The list implementation is circular without any type wise distintion between + * the list and its nodes. This can be confusing since the list head usually + * resides in a different structure than the nodes, so care must be taken when + * walking the list. + * + * @{ + */ + +RT_C_DECLS_BEGIN + +/** + * A list node of a doubly linked list. + */ +typedef struct RTLISTNODE +{ + /** Pointer to the next list node. */ + struct RTLISTNODE *pNext; + /** Pointer to the previous list node. */ + struct RTLISTNODE *pPrev; +} RTLISTNODE; +/** Pointer to a list node. */ +typedef RTLISTNODE *PRTLISTNODE; +/** Pointer to a list node pointer. */ +typedef PRTLISTNODE *PPRTLISTNODE; + +/** The anchor (head/tail) of a doubly linked list. + * + * @remarks Please use this instead of RTLISTNODE to indicate a list + * head/tail. It makes the code so much easier to read. Also, + * always mention the actual list node type(s) in the comment. */ +typedef RTLISTNODE RTLISTANCHOR; +/** Pointer to a doubly linked list anchor. */ +typedef RTLISTANCHOR *PRTLISTANCHOR; + + +/** + * Initialize a list. + * + * @param pList Pointer to an unitialised list. + */ +DECLINLINE(void) RTListInit(PRTLISTNODE pList) +{ + pList->pNext = pList; + pList->pPrev = pList; +} + +/** + * Append a node to the end of the list. + * + * @param pList The list to append the node to. + * @param pNode The node to append. + */ +DECLINLINE(void) RTListAppend(PRTLISTNODE pList, PRTLISTNODE pNode) +{ + pList->pPrev->pNext = pNode; + pNode->pPrev = pList->pPrev; + pNode->pNext = pList; + pList->pPrev = pNode; +} + +/** + * Add a node as the first element of the list. + * + * @param pList The list to prepend the node to. + * @param pNode The node to prepend. + */ +DECLINLINE(void) RTListPrepend(PRTLISTNODE pList, PRTLISTNODE pNode) +{ + pList->pNext->pPrev = pNode; + pNode->pNext = pList->pNext; + pNode->pPrev = pList; + pList->pNext = pNode; +} + +/** + * Inserts a node after the specified one. + * + * @param pCurNode The current node. + * @param pNewNode The node to insert. + */ +DECLINLINE(void) RTListNodeInsertAfter(PRTLISTNODE pCurNode, PRTLISTNODE pNewNode) +{ + RTListPrepend(pCurNode, pNewNode); +} + +/** + * Inserts a node before the specified one. + * + * @param pCurNode The current node. + * @param pNewNode The node to insert. + */ +DECLINLINE(void) RTListNodeInsertBefore(PRTLISTNODE pCurNode, PRTLISTNODE pNewNode) +{ + RTListAppend(pCurNode, pNewNode); +} + +/** + * Remove a node from a list. + * + * @param pNode The node to remove. + */ +DECLINLINE(void) RTListNodeRemove(PRTLISTNODE pNode) +{ + PRTLISTNODE pPrev = pNode->pPrev; + PRTLISTNODE pNext = pNode->pNext; + + pPrev->pNext = pNext; + pNext->pPrev = pPrev; + + /* poison */ + pNode->pNext = NULL; + pNode->pPrev = NULL; +} + +/** + * Checks if a node is the last element in the list. + * + * @retval @c true if the node is the last element in the list. + * @retval @c false otherwise + * + * @param pList The list. + * @param pNode The node to check. + */ +#define RTListNodeIsLast(pList, pNode) ((pNode)->pNext == (pList)) + +/** + * Checks if a node is the first element in the list. + * + * @retval @c true if the node is the first element in the list. + * @retval @c false otherwise. + * + * @param pList The list. + * @param pNode The node to check. + */ +#define RTListNodeIsFirst(pList, pNode) ((pNode)->pPrev == (pList)) + +/** + * Checks if a type converted node is actually the dummy element (@a pList). + * + * @retval @c true if the node is the dummy element in the list. + * @retval @c false otherwise. + * + * @param pList The list. + * @param pNodeStruct The node structure to check. Typically + * something obtained from RTListNodeGetNext() or + * RTListNodeGetPrev(). This is NOT a PRTLISTNODE + * but something that contains a RTLISTNODE member! + * @param Type Structure the list node is a member of. + * @param Member The list node member. + */ +#define RTListNodeIsDummy(pList, pNode, Type, Member) \ + ( (pNode) == RT_FROM_MEMBER((pList), Type, Member) ) + +/** + * Checks if a list is empty. + * + * @retval @c true if the list is empty. + * @retval @c false otherwise. + * + * @param pList The list to check. + */ +#define RTListIsEmpty(pList) ((pList)->pPrev == (pList)) + +/** + * Returns the next node in the list. + * + * @returns The next node. + * + * @param pCurNode The current node. + * @param Type Structure the list node is a member of. + * @param Member The list node member. + */ +#define RTListNodeGetNext(pCurNode, Type, Member) \ + RT_FROM_MEMBER((pCurNode)->pNext, Type, Member) + +/** + * Returns the previous node in the list. + * + * @returns The previous node. + * + * @param pCurNode The current node. + * @param Type Structure the list node is a member of. + * @param Member The list node member. + */ +#define RTListNodeGetPrev(pCurNode, Type, Member) \ + RT_FROM_MEMBER((pCurNode)->pPrev, Type, Member) + +/** + * Returns the first element in the list (checks for empty list). + * + * @retval Pointer to the first list element. + * @retval NULL if the list is empty. + * + * @param pList List to get the first element from. + * @param Type Structure the list node is a member of. + * @param Member The list node member. + */ +#define RTListGetFirst(pList, Type, Member) \ + (!RTListIsEmpty(pList) ? RTListNodeGetNext(pList, Type, Member) : NULL) + +/** + * Returns the last element in the list (checks for empty list). + * + * @retval Pointer to the last list element. + * @retval NULL if the list is empty. + * + * @param pList List to get the last element from. + * @param Type Structure the list node is a member of. + * @param Member The list node member. + */ +#define RTListGetLast(pList, Type, Member) \ + (!RTListIsEmpty(pList) ? RTListNodeGetPrev(pList, Type, Member) : NULL) + +/** + * Returns the next node in the list or NULL if the end has been reached. + * + * @returns The next node or NULL. + * + * @param pList The list @a pCurNode is linked on. + * @param pCurNode The current node, of type @a Type. + * @param Type Structure the list node is a member of. + * @param Member The list node member. + */ +#define RTListGetNext(pList, pCurNode, Type, Member) \ + ( (pCurNode)->Member.pNext != (pList) ? RT_FROM_MEMBER((pCurNode)->Member.pNext, Type, Member) : NULL ) + +/** + * Returns the previous node in the list or NULL if the start has been reached. + * + * @returns The previous node or NULL. + * + * @param pList The list @a pCurNode is linked on. + * @param pCurNode The current node, of type @a Type. + * @param Type Structure the list node is a member of. + * @param Member The list node member. + */ +#define RTListGetPrev(pList, pCurNode, Type, Member) \ + ( (pCurNode)->Member.pPrev != (pList) ? RT_FROM_MEMBER((pCurNode)->Member.pPrev, Type, Member) : NULL ) + +/** + * Enumerate the list in head to tail order. + * + * @param pList List to enumerate. + * @param pIterator The iterator variable name. + * @param Type Structure the list node is a member of. + * @param Member The list node member name. + */ +#define RTListForEach(pList, pIterator, Type, Member) \ + for (pIterator = RTListNodeGetNext(pList, Type, Member); \ + !RTListNodeIsDummy(pList, pIterator, Type, Member); \ + pIterator = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member) ) + + +/** + * Enumerate the list in head to tail order, safe against removal of the + * current node. + * + * @param pList List to enumerate. + * @param pIterator The iterator variable name. + * @param pIterNext The name of the variable saving the pointer to + * the next element. + * @param Type Structure the list node is a member of. + * @param Member The list node member name. + */ +#define RTListForEachSafe(pList, pIterator, pIterNext, Type, Member) \ + for (pIterator = RTListNodeGetNext(pList, Type, Member), \ + pIterNext = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member); \ + !RTListNodeIsDummy(pList, pIterator, Type, Member); \ + pIterator = pIterNext, \ + pIterNext = RT_FROM_MEMBER((pIterator)->Member.pNext, Type, Member) ) + + +/** + * Enumerate the list in reverse order (tail to head). + * + * @param pList List to enumerate. + * @param pIterator The iterator variable name. + * @param Type Structure the list node is a member of. + * @param Member The list node member name. + */ +#define RTListForEachReverse(pList, pIterator, Type, Member) \ + for (pIterator = RTListNodeGetPrev(pList, Type, Member); \ + !RTListNodeIsDummy(pList, pIterator, Type, Member); \ + pIterator = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member) ) + + +/** + * Enumerate the list in reverse order (tail to head). + * + * @param pList List to enumerate. + * @param pIterator The iterator variable name. + * @param pIterPrev The name of the variable saving the pointer to + * the previous element. + * @param Type Structure the list node is a member of. + * @param Member The list node member name. + */ +#define RTListForEachReverseSafe(pList, pIterator, pIterPrev, Type, Member) \ + for (pIterator = RTListNodeGetPrev(pList, Type, Member), \ + pIterPrev = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member); \ + !RTListNodeIsDummy(pList, pIterator, Type, Member); \ + pIterator = pIterPrev, \ + pIterPrev = RT_FROM_MEMBER((pIterator)->Member.pPrev, Type, Member) ) + + +/** + * Move the given list to a new list header. + * + * @param pListDst The new list. + * @param pListSrc The list to move. + */ +DECLINLINE(void) RTListMove(PRTLISTNODE pListDst, PRTLISTNODE pListSrc) +{ + if (!RTListIsEmpty(pListSrc)) + { + pListDst->pNext = pListSrc->pNext; + pListDst->pPrev = pListSrc->pPrev; + + /* Adjust the first and last element links */ + pListDst->pNext->pPrev = pListDst; + pListDst->pPrev->pNext = pListDst; + + /* Finally remove the elements from the source list */ + RTListInit(pListSrc); + } +} + +RT_C_DECLS_END + +/** @} */ + +#endif diff --git a/include/iprt/localipc.h b/include/iprt/localipc.h new file mode 100644 index 00000000..0a887e42 --- /dev/null +++ b/include/iprt/localipc.h @@ -0,0 +1,274 @@ +/** @file + * IPRT - TCP/IP. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_tcp_h +#define ___iprt_tcp_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/thread.h> + +#ifdef IN_RING0 +# error "There are no RTFile APIs available Ring-0 Host Context!" +#endif + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_localipc RTLocalIpc - Local IPC + * @ingroup grp_rt + * @{ + */ + +/** Handle to a local IPC server instance. */ +typedef struct RTLOCALIPCSERVERINT *RTLOCALIPCSERVER; +/** Pointer to a local IPC server handle. */ +typedef RTLOCALIPCSERVER *PRTLOCALIPCSERVER; +/** Local IPC server handle nil value. */ +#define NIL_RTLOCALIPCSERVER ((RTLOCALIPCSERVER)0) + +/** Handle to a local ICP session instance. */ +typedef struct RTLOCALIPCSESSIONINT *RTLOCALIPCSESSION; +/** Pointer to a local ICP session handle. */ +typedef RTLOCALIPCSESSION *PRTLOCALIPCSESSION; +/** Local ICP session handle nil value. */ +#define NIL_RTLOCALIPCSESSION ((RTLOCALIPCSESSION)0) + + + +/** + * Create a local IPC server. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success and *phServer containing the instance handle. + * + * @param phServer Where to put the server instance handle. + * @param pszName The servier name. This must be unique and not + * include any special chars or slashes. It will + * be morphed into a unique platform specific + * identifier. + * @param fFlags Flags, see RTLOCALIPC_FLAGS_*. + */ +RTDECL(int) RTLocalIpcServerCreate(PRTLOCALIPCSERVER phServer, const char *pszName, uint32_t fFlags); + +/** @name RTLocalIpcServerCreate flags + * @{ */ +/** The server can handle multiple session. */ +#define RTLOCALIPC_FLAGS_MULTI_SESSION RT_BIT_32(0) +/** The mask of valid flags. */ +#define RTLOCALIPC_FLAGS_VALID_MASK UINT32_C(0x00000001) +/** @} */ + +/** + * Destroys a local IPC server. + * + * @returns IPRT status code. + * + * @param hServer The server handle. The nil value is quietly ignored (VINF_SUCCESS). + */ +RTDECL(int) RTLocalIpcServerDestroy(RTLOCALIPCSERVER hServer); + +/** + * Listen for clients. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success and *phClientSession containing the session handle. + * @retval VERR_CANCELLED if the listening was interrupted by RTLocalIpcServerCancel(). + * + * @param hServer The server handle. + * @param phClientSession Where to store the client session handle on success. + * + */ +RTDECL(int) RTLocalIpcServerListen(RTLOCALIPCSERVER hServer, PRTLOCALIPCSESSION phClientSession); + +/** + * Cancel the current or subsequent RTLocalIpcServerListen call. + * + * @returns IPRT status code. + * @param hServer The server handle. The nil value is quietly ignored (VINF_SUCCESS). + */ +RTDECL(int) RTLocalIpcServerCancel(RTLOCALIPCSERVER hServer); + + +/** + * Connects to a local IPC server. + * + * This is used a client process (or thread). + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success and *phSession holding the session handle. + * + * @param phSession Where to store the sesson handle on success. + * @param pszName The server name (see RTLocalIpcServerCreate for details). + * @param fFlags Flags. Current undefined, pass 0. + */ +RTDECL(int) RTLocalIpcSessionConnect(PRTLOCALIPCSESSION phSession, const char *pszName, uint32_t fFlags); + + +/** + * Closes the local IPC session. + * + * This can be used with sessions created by both RTLocalIpcSessionConnect + * and RTLocalIpcServerListen. + * + * @returns IPRT status code. + * + * @param hSession The session handle. The nil value is quietly ignored (VINF_SUCCESS). + */ +RTDECL(int) RTLocalIpcSessionClose(RTLOCALIPCSESSION hSession); + +/** + * Receive data from the other end of an local IPC session. + * + * This will block if there isn't any data. + * + * @returns IPRT status code. + * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel. + * + * @param hSession The session handle. + * @param pvBuffer Where to store the data. + * @param cbBuffer If pcbRead is non-NULL this indicates the maximum number of + * bytes to read. If pcbRead is NULL the this is the exact number + * of bytes to read. + * @param pcbRead Optional argument for indicating a partial read and returning + * the number of bytes actually read. + * This may return 0 on some implementations? + */ +RTDECL(int) RTLocalIpcSessionRead(RTLOCALIPCSESSION hSession, void *pvBuffer, size_t cbBuffer, size_t *pcbRead); + +/** + * Send data to the other end of an local IPC session. + * + * This may or may not block until the data is received by the other party, + * this is an implementation detail. If you want to make sure that the data + * has been received you should always call RTLocalIpcSessionFlush(). + * + * @returns IPRT status code. + * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel. + * + * @param hSession The session handle. + * @param pvBuffer The data to write. + * @param cbBuffer The number of bytes to write. + */ +RTDECL(int) RTLocalIpcSessionWrite(RTLOCALIPCSESSION hSession, const void *pvBuffer, size_t cbBuffer); + +/** + * Flush any buffered data and (perhaps) wait for the other party to receive it. + * + * The waiting for the other party to receive the data is + * implementation dependent. + * + * @returns IPRT status code. + * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel. + * + * @param hSession The session handle. + */ +RTDECL(int) RTLocalIpcSessionFlush(RTLOCALIPCSESSION hSession); + +/** + * Wait for data to become read for reading or for the + * session to be disconnected. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS when there is data to read. + * @retval VERR_TIMEOUT if no data became available within the specified period (@a cMillies) + * @retval VERR_BROKEN_PIPE if the session was disconnected. + * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel. + * + * @param hSession The session handle. + * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT + * to wait forever. + * + * @remark VERR_INTERRUPTED will not be returned. If this is desired at some later point + * add a RTLocalIpcSessionWaitForDataNoResume() variant like we're using elsewhere. + */ +RTDECL(int) RTLocalIpcSessionWaitForData(RTLOCALIPCSESSION hSession, uint32_t cMillies); + +/** + * Cancells a pending or subsequent operation. + * + * Not all methods are cancellable, only those which are specfied + * returning VERR_CANCELLED. The others are assumed to not be blocking + * for ever and ever. + * + * @returns IPRT status code. + * + * @param hSession The session handle. + */ +RTDECL(int) RTLocalIpcSessionCancel(RTLOCALIPCSESSION hSession); + +/** + * Query the process ID of the other party. + * + * This is an optional feature which may not be implemented, so don't + * depend on it and check for VERR_NOT_SUPPORTED. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and *pProcess on success. + * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel. + * @retval VERR_NOT_SUPPORTED and *pProcess = NIL_RTPROCESS if not supported. + * + * @param hSession The session handle. + * @param pProcess Where to store the process ID. + */ +RTDECL(int) RTLocalIpcSessionQueryProcess(RTLOCALIPCSESSION hSession, PRTPROCESS pProcess); + +/** + * Query the user ID of the other party. + * + * This is an optional feature which may not be implemented, so don't + * depend on it and check for VERR_NOT_SUPPORTED. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and *pUid on success. + * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel. + * @retval VERR_NOT_SUPPORTED and *pUid = NIL_RTUID if not supported. + * + * @param hSession The session handle. + * @param pUid Where to store the user ID on success. + */ +RTDECL(int) RTLocalIpcSessionQueryUserId(RTLOCALIPCSESSION hSession, PRTUID pUid); + +/** + * Query the group ID of the other party. + * + * This is an optional feature which may not be implemented, so don't + * depend on it and check for VERR_NOT_SUPPORTED. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and *pUid on success. + * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel. + * @retval VERR_NOT_SUPPORTED and *pGid = NIL_RTUID if not supported. + * + * @param hSession The session handle. + * @param pGid Where to store the group ID on success. + */ +RTDECL(int) RTLocalIpcSessionQueryGroupId(RTLOCALIPCSESSION hSession, PRTGID pGid); + +/** @} */ +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/lockvalidator.h b/include/iprt/lockvalidator.h new file mode 100644 index 00000000..7e0f08c1 --- /dev/null +++ b/include/iprt/lockvalidator.h @@ -0,0 +1,1062 @@ +/** @file + * IPRT - Lock Validator. + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_lockvalidator_h +#define ___iprt_lockvalidator_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/assert.h> +#include <iprt/thread.h> +#include <iprt/stdarg.h> + + +/** @defgroup grp_rtlockval RTLockValidator - Lock Validator + * @ingroup grp_rt + * @{ + */ + +RT_C_DECLS_BEGIN + +/** Pointer to a record union. + * @internal */ +typedef union RTLOCKVALRECUNION *PRTLOCKVALRECUNION; + +/** + * Source position. + */ +typedef struct RTLOCKVALSRCPOS +{ + /** The file where the lock was taken. */ + R3R0PTRTYPE(const char * volatile) pszFile; + /** The function where the lock was taken. */ + R3R0PTRTYPE(const char * volatile) pszFunction; + /** Some ID indicating where the lock was taken, typically an address. */ + RTHCUINTPTR volatile uId; + /** The line number in the file. */ + uint32_t volatile uLine; +#if HC_ARCH_BITS == 64 + uint32_t u32Padding; /**< Alignment padding. */ +#endif +} RTLOCKVALSRCPOS; +AssertCompileSize(RTLOCKVALSRCPOS, HC_ARCH_BITS == 32 ? 16 : 32); +/* The pointer types are defined in iprt/types.h. */ + +/** @def RTLOCKVALSRCPOS_INIT + * Initializer for a RTLOCKVALSRCPOS variable. + * + * @param pszFile The file name. Optional (NULL). + * @param uLine The line number in that file. Optional (0). + * @param pszFunction The function. Optional (NULL). + * @param uId Some location ID, normally the return address. + * Optional (NULL). + */ +#if HC_ARCH_BITS == 64 +# define RTLOCKVALSRCPOS_INIT(pszFile, uLine, pszFunction, uId) \ + { (pszFile), (pszFunction), (uId), (uLine), 0 } +#else +# define RTLOCKVALSRCPOS_INIT(pszFile, uLine, pszFunction, uId) \ + { (pszFile), (pszFunction), (uId), (uLine) } +#endif + +/** @def RTLOCKVALSRCPOS_INIT_DEBUG_API + * Initializer for a RTLOCKVALSRCPOS variable in a typicial debug API + * variant. Assumes RT_SRC_POS_DECL and RTHCUINTPTR uId as arguments. + */ +#define RTLOCKVALSRCPOS_INIT_DEBUG_API() \ + RTLOCKVALSRCPOS_INIT(pszFile, iLine, pszFunction, uId) + +/** @def RTLOCKVALSRCPOS_INIT_NORMAL_API + * Initializer for a RTLOCKVALSRCPOS variable in a normal API + * variant. Assumes iprt/asm.h is included. + */ +#define RTLOCKVALSRCPOS_INIT_NORMAL_API() \ + RTLOCKVALSRCPOS_INIT(__FILE__, __LINE__, __PRETTY_FUNCTION__, (uintptr_t)ASMReturnAddress()) + +/** @def RTLOCKVALSRCPOS_INIT_POS_NO_ID + * Initializer for a RTLOCKVALSRCPOS variable when no @c uId is present. + * Assumes iprt/asm.h is included. + */ +#define RTLOCKVALSRCPOS_INIT_POS_NO_ID() \ + RTLOCKVALSRCPOS_INIT(pszFile, iLine, pszFunction, (uintptr_t)ASMReturnAddress()) + +/** Pointer to a record of one ownership share. */ +typedef struct RTLOCKVALRECSHRD *PRTLOCKVALRECSHRD; + + +/** + * Lock validator record core. + */ +typedef struct RTLOCKVALRECORE +{ + /** The magic value indicating the record type. */ + uint32_t volatile u32Magic; +} RTLOCKVALRECCORE; +/** Pointer to a lock validator record core. */ +typedef RTLOCKVALRECCORE *PRTLOCKVALRECCORE; +/** Pointer to a const lock validator record core. */ +typedef RTLOCKVALRECCORE const *PCRTLOCKVALRECCORE; + + +/** + * Record recording the exclusive ownership of a lock. + * + * This is typically part of the per-lock data structure when compiling with + * the lock validator. + */ +typedef struct RTLOCKVALRECEXCL +{ + /** Record core with RTLOCKVALRECEXCL_MAGIC as the magic value. */ + RTLOCKVALRECCORE Core; + /** Whether it's enabled or not. */ + bool fEnabled; + /** Reserved. */ + bool afReserved[3]; + /** Source position where the lock was taken. */ + RTLOCKVALSRCPOS SrcPos; + /** The current owner thread. */ + RTTHREAD volatile hThread; + /** Pointer to the lock record below us. Only accessed by the owner. */ + R3R0PTRTYPE(PRTLOCKVALRECUNION) pDown; + /** Recursion count */ + uint32_t cRecursion; + /** The lock sub-class. */ + uint32_t volatile uSubClass; + /** The lock class. */ + RTLOCKVALCLASS hClass; + /** Pointer to the lock. */ + RTHCPTR hLock; + /** Pointer to the next sibling record. + * This is used to find the read side of a read-write lock. */ + R3R0PTRTYPE(PRTLOCKVALRECUNION) pSibling; + /** The lock name. + * @remarks The bytes beyond 32 are for better size alignment and can be + * taken and used for other purposes if it becomes necessary. */ + char szName[32 + (HC_ARCH_BITS == 32 ? 12 : 8)]; +} RTLOCKVALRECEXCL; +AssertCompileSize(RTLOCKVALRECEXCL, HC_ARCH_BITS == 32 ? 0x60 : 0x80); +/* The pointer type is defined in iprt/types.h. */ + +/** + * For recording the one ownership share. + */ +typedef struct RTLOCKVALRECSHRDOWN +{ + /** Record core with RTLOCKVALRECSHRDOWN_MAGIC as the magic value. */ + RTLOCKVALRECCORE Core; + /** Recursion count */ + uint16_t cRecursion; + /** Static (true) or dynamic (false) allocated record. */ + bool fStaticAlloc; + /** Reserved. */ + bool fReserved; + /** The current owner thread. */ + RTTHREAD volatile hThread; + /** Pointer to the lock record below us. Only accessed by the owner. */ + R3R0PTRTYPE(PRTLOCKVALRECUNION) pDown; + /** Pointer back to the shared record. */ + R3R0PTRTYPE(PRTLOCKVALRECSHRD) pSharedRec; +#if HC_ARCH_BITS == 32 + /** Reserved. */ + RTHCPTR pvReserved; +#endif + /** Source position where the lock was taken. */ + RTLOCKVALSRCPOS SrcPos; +} RTLOCKVALRECSHRDOWN; +AssertCompileSize(RTLOCKVALRECSHRDOWN, HC_ARCH_BITS == 32 ? 24 + 16 : 32 + 32); +/** Pointer to a RTLOCKVALRECSHRDOWN. */ +typedef RTLOCKVALRECSHRDOWN *PRTLOCKVALRECSHRDOWN; + +/** + * Record recording the shared ownership of a lock. + * + * This is typically part of the per-lock data structure when compiling with + * the lock validator. + */ +typedef struct RTLOCKVALRECSHRD +{ + /** Record core with RTLOCKVALRECSHRD_MAGIC as the magic value. */ + RTLOCKVALRECCORE Core; + /** The lock sub-class. */ + uint32_t volatile uSubClass; + /** The lock class. */ + RTLOCKVALCLASS hClass; + /** Pointer to the lock. */ + RTHCPTR hLock; + /** Pointer to the next sibling record. + * This is used to find the write side of a read-write lock. */ + R3R0PTRTYPE(PRTLOCKVALRECUNION) pSibling; + + /** The number of entries in the table. + * Updated before inserting and after removal. */ + uint32_t volatile cEntries; + /** The index of the last entry (approximately). */ + uint32_t volatile iLastEntry; + /** The max table size. */ + uint32_t volatile cAllocated; + /** Set if the table is being reallocated, clear if not. + * This is used together with rtLockValidatorSerializeDetectionEnter to make + * sure there is exactly one thread doing the reallocation and that nobody is + * using the table at that point. */ + bool volatile fReallocating; + /** Whether it's enabled or not. */ + bool fEnabled; + /** Set if event semaphore signaller, clear if read-write semaphore. */ + bool fSignaller; + /** Alignment padding. */ + bool fPadding; + /** Pointer to a table containing pointers to records of all the owners. */ + R3R0PTRTYPE(PRTLOCKVALRECSHRDOWN volatile *) papOwners; + + /** The lock name. + * @remarks The bytes beyond 32 are for better size alignment and can be + * taken and used for other purposes if it becomes necessary. */ + char szName[32 + (HC_ARCH_BITS == 32 ? 8 : 8)]; +} RTLOCKVALRECSHRD; +AssertCompileSize(RTLOCKVALRECSHRD, HC_ARCH_BITS == 32 ? 0x50 : 0x60); + + +/** + * Makes the two records siblings. + * + * @returns VINF_SUCCESS on success, VERR_SEM_LV_INVALID_PARAMETER if either of + * the records are invalid. + * @param pRec1 Record 1. + * @param pRec2 Record 2. + */ +RTDECL(int) RTLockValidatorRecMakeSiblings(PRTLOCKVALRECCORE pRec1, PRTLOCKVALRECCORE pRec2); + +/** + * Initialize a lock validator record. + * + * Use RTLockValidatorRecExclDelete to deinitialize it. + * + * @param pRec The record. + * @param hClass The class (no reference consumed). If NIL, the + * no lock order validation will be performed on + * this lock. + * @param uSubClass The sub-class. This is used to define lock + * order inside the same class. If you don't know, + * then pass RTLOCKVAL_SUB_CLASS_NONE. + * @param hLock The lock handle. + * @param fEnabled Pass @c false to explicitly disable lock + * validation, otherwise @c true. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(void) RTLockValidatorRecExclInit(PRTLOCKVALRECEXCL pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, + void *hLock, bool fEnabled, const char *pszNameFmt, ...); +/** + * Initialize a lock validator record. + * + * Use RTLockValidatorRecExclDelete to deinitialize it. + * + * @param pRec The record. + * @param hClass The class (no reference consumed). If NIL, the + * no lock order validation will be performed on + * this lock. + * @param uSubClass The sub-class. This is used to define lock + * order inside the same class. If you don't know, + * then pass RTLOCKVAL_SUB_CLASS_NONE. + * @param hLock The lock handle. + * @param fEnabled Pass @c false to explicitly disable lock + * validation, otherwise @c true. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param va Format string arguments. + */ +RTDECL(void) RTLockValidatorRecExclInitV(PRTLOCKVALRECEXCL pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, + void *hLock, bool fEnabled, const char *pszNameFmt, va_list va); +/** + * Uninitialize a lock validator record previously initialized by + * RTLockRecValidatorInit. + * + * @param pRec The record. Must be valid. + */ +RTDECL(void) RTLockValidatorRecExclDelete(PRTLOCKVALRECEXCL pRec); + +/** + * Create and initialize a lock validator record. + * + * Use RTLockValidatorRecExclDestroy to deinitialize and destroy the returned + * record. + * + * @return VINF_SUCCESS or VERR_NO_MEMORY. + * @param ppRec Where to return the record pointer. + * @param hClass The class (no reference consumed). If NIL, the + * no lock order validation will be performed on + * this lock. + * @param uSubClass The sub-class. This is used to define lock + * order inside the same class. If you don't know, + * then pass RTLOCKVAL_SUB_CLASS_NONE. + * @param hLock The lock handle. + * @param fEnabled Pass @c false to explicitly disable lock + * validation, otherwise @c true. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(int) RTLockValidatorRecExclCreate(PRTLOCKVALRECEXCL *ppRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, + void *hLock, bool fEnabled, const char *pszNameFmt, ...); + +/** + * Create and initialize a lock validator record. + * + * Use RTLockValidatorRecExclDestroy to deinitialize and destroy the returned + * record. + * + * @return VINF_SUCCESS or VERR_NO_MEMORY. + * @param ppRec Where to return the record pointer. + * @param hClass The class (no reference consumed). If NIL, the + * no lock order validation will be performed on + * this lock. + * @param uSubClass The sub-class. This is used to define lock + * order inside the same class. If you don't know, + * then pass RTLOCKVAL_SUB_CLASS_NONE. + * @param hLock The lock handle. + * @param fEnabled Pass @c false to explicitly disable lock + * validation, otherwise @c true. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param va Format string arguments. + */ +RTDECL(int) RTLockValidatorRecExclCreateV(PRTLOCKVALRECEXCL *ppRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, + void *hLock, bool fEnabled, const char *pszNameFmt, va_list va); + +/** + * Deinitialize and destroy a record created by RTLockValidatorRecExclCreate. + * + * @param ppRec Pointer to the record pointer. Will be set to + * NULL. + */ +RTDECL(void) RTLockValidatorRecExclDestroy(PRTLOCKVALRECEXCL *ppRec); + +/** + * Sets the sub-class of the record. + * + * It is recommended to try make sure that nobody is using this class while + * changing the value. + * + * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the + * lock validator isn't compiled in or either of the parameters are + * invalid. + * @param pRec The validator record. + * @param uSubClass The new sub-class value. + */ +RTDECL(uint32_t) RTLockValidatorRecExclSetSubClass(PRTLOCKVALRECEXCL pRec, uint32_t uSubClass); + +/** + * Record the specified thread as lock owner and increment the write lock count. + * + * This function is typically called after acquiring the lock. It accounts for + * recursions so it can be used instead of RTLockValidatorRecExclRecursion. Use + * RTLockValidatorRecExclReleaseOwner to reverse the effect. + * + * @param pRec The validator record. + * @param hThreadSelf The handle of the calling thread. If not known, + * pass NIL_RTTHREAD and we'll figure it out. + * @param pSrcPos The source position of the lock operation. + * @param fFirstRecursion Set if it is the first recursion, clear if not + * sure. + */ +RTDECL(void) RTLockValidatorRecExclSetOwner(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf, + PCRTLOCKVALSRCPOS pSrcPos, bool fFirstRecursion); + +/** + * Check the exit order and release (unset) the ownership. + * + * This is called by routines implementing releasing an exclusive lock, + * typically before getting down to the final lock releasing. Can be used for + * recursive releasing instead of RTLockValidatorRecExclUnwind. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong. Will have + * done all necessary whining and breakpointing before returning. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record. + * @param fFinalRecursion Set if it's the final recursion, clear if not + * sure. + */ +RTDECL(int) RTLockValidatorRecExclReleaseOwner(PRTLOCKVALRECEXCL pRec, bool fFinalRecursion); + +/** + * Clear the lock ownership and decrement the write lock count. + * + * This is only for special cases where we wish to drop lock validation + * recording. See RTLockValidatorRecExclCheckAndRelease. + * + * @param pRec The validator record. + */ +RTDECL(void) RTLockValidatorRecExclReleaseOwnerUnchecked(PRTLOCKVALRECEXCL pRec); + +/** + * Checks and records a lock recursion. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_NESTED if the semaphore class forbids recursion. Gone + * thru the motions. + * @retval VERR_SEM_LV_WRONG_ORDER if the locking order is wrong. Gone thru + * the motions. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record. + * @param pSrcPos The source position of the lock operation. + */ +RTDECL(int) RTLockValidatorRecExclRecursion(PRTLOCKVALRECEXCL pRec, PCRTLOCKVALSRCPOS pSrcPos); + +/** + * Checks and records a lock unwind (releasing one recursion). + * + * This should be coupled with called to RTLockValidatorRecExclRecursion. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the release order is wrong. Gone + * thru the motions. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record. + */ +RTDECL(int) RTLockValidatorRecExclUnwind(PRTLOCKVALRECEXCL pRec); + +/** + * Checks and records a mixed recursion. + * + * An example of a mixed recursion is a writer requesting read access to a + * SemRW. + * + * This should be coupled with called to RTLockValidatorRecExclUnwindMixed. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_NESTED if the semaphore class forbids recursion. Gone + * thru the motions. + * @retval VERR_SEM_LV_WRONG_ORDER if the locking order is wrong. Gone thru + * the motions. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record it to accounted it to. + * @param pRecMixed The validator record it came in on. + * @param pSrcPos The source position of the lock operation. + */ +RTDECL(int) RTLockValidatorRecExclRecursionMixed(PRTLOCKVALRECEXCL pRec, PRTLOCKVALRECCORE pRecMixed, PCRTLOCKVALSRCPOS pSrcPos); + +/** + * Checks and records the unwinding of a mixed recursion. + * + * This should be coupled with called to RTLockValidatorRecExclRecursionMixed. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the release order is wrong. Gone + * thru the motions. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record it was accounted to. + * @param pRecMixed The validator record it came in on. + */ +RTDECL(int) RTLockValidatorRecExclUnwindMixed(PRTLOCKVALRECEXCL pRec, PRTLOCKVALRECCORE pRecMixed); + +/** + * Check the exclusive locking order. + * + * This is called by routines implementing exclusive lock acquisition. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_WRONG_ORDER if the order is wrong. Will have done all + * necessary whining and breakpointing before returning. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record. + * @param hThreadSelf The handle of the calling thread. If not known, + * pass NIL_RTTHREAD and we'll figure it out. + * @param pSrcPos The source position of the lock operation. + * @param cMillies The timeout, in milliseconds. + */ +RTDECL(int) RTLockValidatorRecExclCheckOrder(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf, + PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies); + +/** + * Do deadlock detection before blocking on exclusive access to a lock and + * change the thread state. + * + * @retval VINF_SUCCESS - thread is in the specified sleep state. + * @retval VERR_SEM_LV_DEADLOCK if blocking would deadlock. Gone thru the + * motions. + * @retval VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is + * already the owner. Gone thru the motions. + * @retval VERR_SEM_LV_ILLEGAL_UPGRADE if it's a deadlock on the same lock. + * The caller must handle any legal upgrades without invoking this + * function (for now). + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record we're blocking on. + * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD! + * @param pSrcPos The source position of the lock operation. + * @param fRecursiveOk Whether it's ok to recurse. + * @param cMillies The timeout, in milliseconds. + * @param enmSleepState The sleep state to enter on successful return. + * @param fReallySleeping Is it really going to sleep now or not. Use + * false before calls to other IPRT synchronization + * methods. + */ +RTDECL(int) RTLockValidatorRecExclCheckBlocking(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf, + PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies, + RTTHREADSTATE enmSleepState, bool fReallySleeping); + +/** + * RTLockValidatorRecExclCheckOrder and RTLockValidatorRecExclCheckBlocking + * baked into one call. + * + * @returns Any of the statuses returned by the two APIs. + * @param pRec The validator record. + * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD! + * @param pSrcPos The source position of the lock operation. + * @param fRecursiveOk Whether it's ok to recurse. + * @param cMillies The timeout, in milliseconds. + * @param enmSleepState The sleep state to enter on successful return. + * @param fReallySleeping Is it really going to sleep now or not. Use + * false before calls to other IPRT synchronization + * methods. + */ +RTDECL(int) RTLockValidatorRecExclCheckOrderAndBlocking(PRTLOCKVALRECEXCL pRec, RTTHREAD hThreadSelf, + PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies, + RTTHREADSTATE enmSleepState, bool fReallySleeping); + +/** + * Initialize a lock validator record for a shared lock. + * + * Use RTLockValidatorRecSharedDelete to deinitialize it. + * + * @param pRec The shared lock record. + * @param hClass The class (no reference consumed). If NIL, the + * no lock order validation will be performed on + * this lock. + * @param uSubClass The sub-class. This is used to define lock + * order inside the same class. If you don't know, + * then pass RTLOCKVAL_SUB_CLASS_NONE. + * @param hLock The lock handle. + * @param fSignaller Set if event semaphore signaller logic should be + * applied to this record, clear if read-write + * semaphore logic should be used. + * @param fEnabled Pass @c false to explicitly disable lock + * validation, otherwise @c true. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(void) RTLockValidatorRecSharedInit(PRTLOCKVALRECSHRD pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, + void *hLock, bool fSignaller, bool fEnabled, const char *pszNameFmt, ...); +/** + * Initialize a lock validator record for a shared lock. + * + * Use RTLockValidatorRecSharedDelete to deinitialize it. + * + * @param pRec The shared lock record. + * @param hClass The class (no reference consumed). If NIL, the + * no lock order validation will be performed on + * this lock. + * @param uSubClass The sub-class. This is used to define lock + * order inside the same class. If you don't know, + * then pass RTLOCKVAL_SUB_CLASS_NONE. + * @param hLock The lock handle. + * @param fSignaller Set if event semaphore signaller logic should be + * applied to this record, clear if read-write + * semaphore logic should be used. + * @param fEnabled Pass @c false to explicitly disable lock + * validation, otherwise @c true. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param va Format string arguments. + */ +RTDECL(void) RTLockValidatorRecSharedInitV(PRTLOCKVALRECSHRD pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass, + void *hLock, bool fSignaller, bool fEnabled, const char *pszNameFmt, va_list va); +/** + * Uninitialize a lock validator record previously initialized by + * RTLockValidatorRecSharedInit. + * + * @param pRec The shared lock record. Must be valid. + */ +RTDECL(void) RTLockValidatorRecSharedDelete(PRTLOCKVALRECSHRD pRec); + +/** + * Sets the sub-class of the record. + * + * It is recommended to try make sure that nobody is using this class while + * changing the value. + * + * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the + * lock validator isn't compiled in or either of the parameters are + * invalid. + * @param pRec The validator record. + * @param uSubClass The new sub-class value. + */ +RTDECL(uint32_t) RTLockValidatorRecSharedSetSubClass(PRTLOCKVALRECSHRD pRec, uint32_t uSubClass); + +/** + * Check the shared locking order. + * + * This is called by routines implementing shared lock acquisition. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_WRONG_ORDER if the order is wrong. Will have done all + * necessary whining and breakpointing before returning. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record. + * @param hThreadSelf The handle of the calling thread. If not known, + * pass NIL_RTTHREAD and we'll figure it out. + * @param pSrcPos The source position of the lock operation. + */ +RTDECL(int) RTLockValidatorRecSharedCheckOrder(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf, + PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies); + +/** + * Do deadlock detection before blocking on shared access to a lock and change + * the thread state. + * + * @retval VINF_SUCCESS - thread is in the specified sleep state. + * @retval VERR_SEM_LV_DEADLOCK if blocking would deadlock. Gone thru the + * motions. + * @retval VERR_SEM_LV_NESTED if the semaphore isn't recursive and hThread is + * already the owner. Gone thru the motions. + * @retval VERR_SEM_LV_ILLEGAL_UPGRADE if it's a deadlock on the same lock. + * The caller must handle any legal upgrades without invoking this + * function (for now). + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record we're blocking on. + * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD! + * @param pSrcPos The source position of the lock operation. + * @param fRecursiveOk Whether it's ok to recurse. + * @param enmSleepState The sleep state to enter on successful return. + * @param fReallySleeping Is it really going to sleep now or not. Use + * false before calls to other IPRT synchronization + * methods. + */ +RTDECL(int) RTLockValidatorRecSharedCheckBlocking(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf, + PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies, + RTTHREADSTATE enmSleepState, bool fReallySleeping); + +/** + * RTLockValidatorRecSharedCheckOrder and RTLockValidatorRecSharedCheckBlocking + * baked into one call. + * + * @returns Any of the statuses returned by the two APIs. + * @param pRec The validator record. + * @param hThreadSelf The current thread. Shall not be NIL_RTTHREAD! + * @param pSrcPos The source position of the lock operation. + * @param fRecursiveOk Whether it's ok to recurse. + * @param enmSleepState The sleep state to enter on successful return. + * @param fReallySleeping Is it really going to sleep now or not. Use + * false before calls to other IPRT synchronization + * methods. + */ +RTDECL(int) RTLockValidatorRecSharedCheckOrderAndBlocking(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf, + PCRTLOCKVALSRCPOS pSrcPos, bool fRecursiveOk, RTMSINTERVAL cMillies, + RTTHREADSTATE enmSleepState, bool fReallySleeping); + +/** + * Removes all current owners and makes hThread the only owner. + * + * @param pRec The validator record. + * @param hThread The thread handle of the owner. NIL_RTTHREAD is + * an alias for the current thread. + * @param pSrcPos The source position of the lock operation. + */ +RTDECL(void) RTLockValidatorRecSharedResetOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos); + +/** + * Adds an owner to a shared locking record. + * + * Takes recursion into account. This function is typically called after + * acquiring the lock in shared mode. + * + * @param pRec The validator record. + * @param hThread The thread handle of the owner. NIL_RTTHREAD is + * an alias for the current thread. + * @param pSrcPos The source position of the lock operation. + */ +RTDECL(void) RTLockValidatorRecSharedAddOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread, PCRTLOCKVALSRCPOS pSrcPos); + +/** + * Removes an owner from a shared locking record. + * + * Takes recursion into account. This function is typically called before + * releasing the lock. + * + * @param pRec The validator record. + * @param hThread The thread handle of the owner. NIL_RTTHREAD is + * an alias for the current thread. + */ +RTDECL(void) RTLockValidatorRecSharedRemoveOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread); + +/** + * Checks if the specified thread is one of the owners. + * + * @returns true if it is, false if not. + * + * @param pRec The validator record. + * @param hThread The thread handle of the owner. NIL_RTTHREAD is + * an alias for the current thread. + */ +RTDECL(bool) RTLockValidatorRecSharedIsOwner(PRTLOCKVALRECSHRD pRec, RTTHREAD hThread); + +/** + * Check the exit order and release (unset) the shared ownership. + * + * This is called by routines implementing releasing the read/write lock. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_WRONG_RELEASE_ORDER if the order is wrong. Will have + * done all necessary whining and breakpointing before returning. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record. + * @param hThreadSelf The handle of the calling thread. NIL_RTTHREAD + * is an alias for the current thread. + */ +RTDECL(int) RTLockValidatorRecSharedCheckAndRelease(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf); + +/** + * Check the signaller of an event. + * + * This is called by routines implementing releasing the event semaphore (both + * kinds). + * + * @retval VINF_SUCCESS on success. + * @retval VERR_SEM_LV_NOT_SIGNALLER if the thread is not in the record. Will + * have done all necessary whining and breakpointing before returning. + * @retval VERR_SEM_LV_INVALID_PARAMETER if the input is invalid. + * + * @param pRec The validator record. + * @param hThreadSelf The handle of the calling thread. NIL_RTTHREAD + * is an alias for the current thread. + */ +RTDECL(int) RTLockValidatorRecSharedCheckSignaller(PRTLOCKVALRECSHRD pRec, RTTHREAD hThreadSelf); + +/** + * Gets the number of write locks and critical sections the specified + * thread owns. + * + * This number does not include any nested lock/critect entries. + * + * Note that it probably will return 0 for non-strict builds since + * release builds doesn't do unnecessary diagnostic counting like this. + * + * @returns Number of locks on success (0+) and VERR_INVALID_HANDLER on failure + * @param Thread The thread we're inquiring about. + * @remarks Will only work for strict builds. + */ +RTDECL(int32_t) RTLockValidatorWriteLockGetCount(RTTHREAD Thread); + +/** + * Works the THREADINT::cWriteLocks member, mostly internal. + * + * @param Thread The current thread. + */ +RTDECL(void) RTLockValidatorWriteLockInc(RTTHREAD Thread); + +/** + * Works the THREADINT::cWriteLocks member, mostly internal. + * + * @param Thread The current thread. + */ +RTDECL(void) RTLockValidatorWriteLockDec(RTTHREAD Thread); + +/** + * Gets the number of read locks the specified thread owns. + * + * Note that nesting read lock entry will be included in the + * total sum. And that it probably will return 0 for non-strict + * builds since release builds doesn't do unnecessary diagnostic + * counting like this. + * + * @returns Number of read locks on success (0+) and VERR_INVALID_HANDLER on failure + * @param Thread The thread we're inquiring about. + */ +RTDECL(int32_t) RTLockValidatorReadLockGetCount(RTTHREAD Thread); + +/** + * Works the THREADINT::cReadLocks member. + * + * @param Thread The current thread. + */ +RTDECL(void) RTLockValidatorReadLockInc(RTTHREAD Thread); + +/** + * Works the THREADINT::cReadLocks member. + * + * @param Thread The current thread. + */ +RTDECL(void) RTLockValidatorReadLockDec(RTTHREAD Thread); + +/** + * Query which lock the specified thread is waiting on. + * + * @returns The lock handle value or NULL. + * @param hThread The thread in question. + */ +RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread); + +/** + * Checks if the thread is running in the lock validator after it has entered a + * block state. + * + * @returns true if it is, false if it isn't. + * @param hThread The thread in question. + */ +RTDECL(bool) RTLockValidatorIsBlockedThreadInValidator(RTTHREAD hThread); + +/** + * Checks if the calling thread is holding a lock in the specified class. + * + * @returns true if it holds a lock in the specific class, false if it + * doesn't. + * + * @param hCurrentThread The current thread. Pass NIL_RTTHREAD if you're + * lazy. + * @param hClass The class. + */ +RTDECL(bool) RTLockValidatorHoldsLocksInClass(RTTHREAD hCurrentThread, RTLOCKVALCLASS hClass); + +/** + * Checks if the calling thread is holding a lock in the specified sub-class. + * + * @returns true if it holds a lock in the specific sub-class, false if it + * doesn't. + * + * @param hCurrentThread The current thread. Pass NIL_RTTHREAD if you're + * lazy. + * @param hClass The class. + * @param uSubClass The new sub-class value. + */ +RTDECL(bool) RTLockValidatorHoldsLocksInSubClass(RTTHREAD hCurrentThread, RTLOCKVALCLASS hClass, uint32_t uSubClass); + + + +/** + * Creates a new lock validator class, all properties specified. + * + * @returns IPRT status code + * @param phClass Where to return the class handle. + * @param pSrcPos The source position of the create call. + * @param fAutodidact Whether the class should be allowed to teach + * itself new locking order rules (true), or if the + * user will teach it all it needs to know (false). + * @param fRecursionOk Whether to allow lock recursion or not. + * @param fStrictReleaseOrder Enforce strict lock release order or not. + * @param cMsMinDeadlock Used to raise the sleep interval at which + * deadlock detection kicks in. Minimum is 1 ms, + * while RT_INDEFINITE_WAIT will disable it. + * @param cMsMinOrder Used to raise the sleep interval at which lock + * order validation kicks in. Minimum is 1 ms, + * while RT_INDEFINITE_WAIT will disable it. + * @param pszNameFmt Class name format string, optional (NULL). Max + * length is 32 bytes. + * @param ... Format string arguments. + * + * @remarks The properties can be modified after creation by the + * RTLockValidatorClassSet* methods. + */ +RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos, + bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder, + RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder, + const char *pszNameFmt, ...); + +/** + * Creates a new lock validator class, all properties specified. + * + * @returns IPRT status code + * @param phClass Where to return the class handle. + * @param pSrcPos The source position of the create call. + * @param fAutodidact Whether the class should be allowed to teach + * itself new locking order rules (true), or if the + * user will teach it all it needs to know (false). + * @param fRecursionOk Whether to allow lock recursion or not. + * @param fStrictReleaseOrder Enforce strict lock release order or not. + * @param cMsMinDeadlock Used to raise the sleep interval at which + * deadlock detection kicks in. Minimum is 1 ms, + * while RT_INDEFINITE_WAIT will disable it. + * @param cMsMinOrder Used to raise the sleep interval at which lock + * order validation kicks in. Minimum is 1 ms, + * while RT_INDEFINITE_WAIT will disable it. + * @param pszNameFmt Class name format string, optional (NULL). Max + * length is 32 bytes. + * @param va Format string arguments. + * + * @remarks The properties can be modified after creation by the + * RTLockValidatorClassSet* methods. + */ +RTDECL(int) RTLockValidatorClassCreateExV(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos, + bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder, + RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder, + const char *pszNameFmt, va_list va); + +/** + * Creates a new lock validator class. + * + * @returns IPRT status code + * @param phClass Where to return the class handle. + * @param fAutodidact Whether the class should be allowed to teach + * itself new locking order rules (true), or if the + * user will teach it all it needs to know (false). + * @param pszFile The source position of the call, file. + * @param iLine The source position of the call, line. + * @param pszFunction The source position of the call, function. + * @param pszNameFmt Class name format string, optional (NULL). Max + * length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(int) RTLockValidatorClassCreate(PRTLOCKVALCLASS phClass, bool fAutodidact, RT_SRC_POS_DECL, const char *pszNameFmt, ...); + +/** + * Creates a new lock validator class with a reference that is consumed by the + * first call to RTLockValidatorClassRetain. + * + * This is tailored for use in the parameter list of a semaphore constructor. + * + * @returns Class handle with a reference that is automatically consumed by the + * first retainer. NIL_RTLOCKVALCLASS if we run into trouble. + * + * @param pszFile The source position of the call, file. + * @param iLine The source position of the call, line. + * @param pszFunction The source position of the call, function. + * @param pszNameFmt Class name format string, optional (NULL). Max + * length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(RTLOCKVALCLASS) RTLockValidatorClassCreateUnique(RT_SRC_POS_DECL, const char *pszNameFmt, ...); + +/** + * Finds a class for the specified source position. + * + * @returns A handle to the class (not retained!) or NIL_RTLOCKVALCLASS. + * @param pSrcPos The source position. + */ +RTDECL(RTLOCKVALCLASS) RTLockValidatorClassFindForSrcPos(PRTLOCKVALSRCPOS pSrcPos); + +/** + * Finds or creates a class given the source position. + * + * @returns Class handle (not retained!) or NIL_RTLOCKVALCLASS. + * @param pszFile The source file. + * @param iLine The line in that source file. + * @param pszFunction The function name. + * @param pszNameFmt Class name format string, optional (NULL). Max + * length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(RTLOCKVALCLASS) RTLockValidatorClassForSrcPos(RT_SRC_POS_DECL, const char *pszNameFmt, ...); + +/** + * Retains a reference to a lock validator class. + * + * @returns New reference count; UINT32_MAX if the handle is invalid. + * @param hClass Handle to the class. + */ +RTDECL(uint32_t) RTLockValidatorClassRetain(RTLOCKVALCLASS hClass); + +/** + * Releases a reference to a lock validator class. + * + * @returns New reference count. 0 if hClass is NIL_RTLOCKVALCLASS. UINT32_MAX + * if the handle is invalid. + * @param hClass Handle to the class. + */ +RTDECL(uint32_t) RTLockValidatorClassRelease(RTLOCKVALCLASS hClass); + +/** + * Teaches the class @a hClass that locks in the class @a hPriorClass can be + * held when taking a lock of class @hClass + * + * @returns IPRT status. + * @param hClass Handle to the pupil class. + * @param hPriorClass Handle to the class that can be held prior to + * taking a lock in the pupil class. (No reference + * is consumed.) + */ +RTDECL(int) RTLockValidatorClassAddPriorClass(RTLOCKVALCLASS hClass, RTLOCKVALCLASS hPriorClass); + +/** + * Enables or disables the strict release order enforcing. + * + * @returns IPRT status. + * @param hClass Handle to the class to change. + * @param fEnable Enable it (true) or disable it (false). + */ +RTDECL(int) RTLockValidatorClassEnforceStrictReleaseOrder(RTLOCKVALCLASS hClass, bool fEnabled); + +/** + * Enables / disables the lock validator for new locks. + * + * @returns The old setting. + * @param fEnabled The new setting. + */ +RTDECL(bool) RTLockValidatorSetEnabled(bool fEnabled); + +/** + * Is the lock validator enabled? + * + * @returns True if enabled, false if not. + */ +RTDECL(bool) RTLockValidatorIsEnabled(void); + +/** + * Controls whether the lock validator should be quiet or noisy (default). + * + * @returns The old setting. + * @param fQuiet The new setting. + */ +RTDECL(bool) RTLockValidatorSetQuiet(bool fQuiet); + +/** + * Is the lock validator quiet or noisy? + * + * @returns True if it is quiet, false if noisy. + */ +RTDECL(bool) RTLockValidatorIsQuiet(void); + +/** + * Makes the lock validator panic (default) or not. + * + * @returns The old setting. + * @param fPanic The new setting. + */ +RTDECL(bool) RTLockValidatorSetMayPanic(bool fPanic); + +/** + * Can the lock validator cause panic. + * + * @returns True if it can, false if not. + */ +RTDECL(bool) RTLockValidatorMayPanic(void); + + +RT_C_DECLS_END + +/** @} */ + +#endif + diff --git a/include/iprt/log.h b/include/iprt/log.h new file mode 100644 index 00000000..cce17079 --- /dev/null +++ b/include/iprt/log.h @@ -0,0 +1,1984 @@ +/** @file + * IPRT - Logging. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_log_h +#define ___iprt_log_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_log RTLog - Logging + * @ingroup grp_rt + * @{ + */ + +/** + * IPRT Logging Groups. + * (Remember to update RT_LOGGROUP_NAMES!) + * + * @remark It should be pretty obvious, but just to have + * mentioned it, the values are sorted alphabetically (using the + * english alphabet) except for _DEFAULT which is always first. + * + * If anyone might be wondering what the alphabet looks like: + * a b c d e f g h i j k l m n o p q r s t u v w x y z + */ +typedef enum RTLOGGROUP +{ + /** Default logging group. */ + RTLOGGROUP_DEFAULT, + RTLOGGROUP_DBG, + RTLOGGROUP_DBG_DWARF, + RTLOGGROUP_DIR, + RTLOGGROUP_FILE, + RTLOGGROUP_FS, + RTLOGGROUP_LDR, + RTLOGGROUP_PATH, + RTLOGGROUP_PROCESS, + RTLOGGROUP_SYMLINK, + RTLOGGROUP_THREAD, + RTLOGGROUP_TIME, + RTLOGGROUP_TIMER, + RTLOGGROUP_ZIP = 31, + RTLOGGROUP_FIRST_USER = 32 +} RTLOGGROUP; + +/** @def RT_LOGGROUP_NAMES + * IPRT Logging group names. + * + * Must correspond 100% to RTLOGGROUP! + * Don't forget commas! + * + * @remark It should be pretty obvious, but just to have + * mentioned it, the values are sorted alphabetically (using the + * english alphabet) except for _DEFAULT which is always first. + * + * If anyone might be wondering what the alphabet looks like: + * a b c d e f g h i j k l m n o p q r s t u v w x y z + */ +#define RT_LOGGROUP_NAMES \ + "DEFAULT", \ + "RT_DBG", \ + "RT_DBG_DWARF", \ + "RT_DIR", \ + "RT_FILE", \ + "RT_FS", \ + "RT_LDR", \ + "RT_PATH", \ + "RT_PROCESS", \ + "RT_SYMLINK", \ + "RT_THREAD", \ + "RT_TIME", \ + "RT_TIMER", \ + "RT_13", \ + "RT_14", \ + "RT_15", \ + "RT_16", \ + "RT_17", \ + "RT_18", \ + "RT_19", \ + "RT_20", \ + "RT_21", \ + "RT_22", \ + "RT_23", \ + "RT_24", \ + "RT_25", \ + "RT_26", \ + "RT_27", \ + "RT_28", \ + "RT_29", \ + "RT_30", \ + "RT_ZIP" \ + + +/** @def LOG_GROUP + * Active logging group. + */ +#ifndef LOG_GROUP +# define LOG_GROUP RTLOGGROUP_DEFAULT +#endif + +/** @def LOG_INSTANCE + * Active logging instance. + */ +#ifndef LOG_INSTANCE +# define LOG_INSTANCE NULL +#endif + +/** @def LOG_REL_INSTANCE + * Active release logging instance. + */ +#ifndef LOG_REL_INSTANCE +# define LOG_REL_INSTANCE NULL +#endif + +/** @def LOG_FN_FMT + * You can use this to specify you desired way of printing __PRETTY_FUNCTION__ + * if you dislike the default one. + */ +#ifndef LOG_FN_FMT +# define LOG_FN_FMT "%Rfn" +#endif + +/** Logger structure. */ +#ifdef IN_RC +typedef struct RTLOGGERRC RTLOGGER; +#else +typedef struct RTLOGGER RTLOGGER; +#endif +/** Pointer to logger structure. */ +typedef RTLOGGER *PRTLOGGER; +/** Pointer to const logger structure. */ +typedef const RTLOGGER *PCRTLOGGER; + + +/** Guest context logger structure. */ +typedef struct RTLOGGERRC RTLOGGERRC; +/** Pointer to guest context logger structure. */ +typedef RTLOGGERRC *PRTLOGGERRC; +/** Pointer to const guest context logger structure. */ +typedef const RTLOGGERRC *PCRTLOGGERRC; + + +/** + * Logger phase. + * + * Used for signalling the log header/footer callback what to do. + */ +typedef enum RTLOGPHASE +{ + /** Begin of the logging. */ + RTLOGPHASE_BEGIN = 0, + /** End of the logging. */ + RTLOGPHASE_END, + /** Before rotating the log file. */ + RTLOGPHASE_PREROTATE, + /** After rotating the log file. */ + RTLOGPHASE_POSTROTATE, + /** 32-bit type blow up hack. */ + RTLOGPHASE_32BIT_HACK = 0x7fffffff +} RTLOGPHASE; + + +/** + * Logger function. + * + * @param pszFormat Format string. + * @param ... Optional arguments as specified in the format string. + */ +typedef DECLCALLBACK(void) FNRTLOGGER(const char *pszFormat, ...); +/** Pointer to logger function. */ +typedef FNRTLOGGER *PFNRTLOGGER; + +/** + * Flush function. + * + * @param pLogger Pointer to the logger instance which is to be flushed. + */ +typedef DECLCALLBACK(void) FNRTLOGFLUSH(PRTLOGGER pLogger); +/** Pointer to flush function. */ +typedef FNRTLOGFLUSH *PFNRTLOGFLUSH; + +/** + * Flush function. + * + * @param pLogger Pointer to the logger instance which is to be flushed. + */ +typedef DECLCALLBACK(void) FNRTLOGFLUSHGC(PRTLOGGERRC pLogger); +/** Pointer to logger function. */ +typedef RCPTRTYPE(FNRTLOGFLUSHGC *) PFNRTLOGFLUSHGC; + +/** + * Header/footer message callback. + * + * @param pLogger Pointer to the logger instance. + * @param pszFormat Format string. + * @param ... Optional arguments specified in the format string. + */ +typedef DECLCALLBACK(void) FNRTLOGPHASEMSG(PRTLOGGER pLogger, const char *pszFormat, ...); +/** Pointer to header/footer message callback function. */ +typedef FNRTLOGPHASEMSG *PFNRTLOGPHASEMSG; + +/** + * Log file header/footer callback. + * + * @param pLogger Pointer to the logger instance. + * @param enmLogPhase Indicates at what time the callback is invoked. + * @param pfnLogPhaseMsg Callback for writing the header/footer (RTLogPrintf + * and others are out of bounds). + */ +typedef DECLCALLBACK(void) FNRTLOGPHASE(PRTLOGGER pLogger, RTLOGPHASE enmLogPhase, PFNRTLOGPHASEMSG pfnLogPhaseMsg); +/** Pointer to log header/footer callback function. */ +typedef FNRTLOGPHASE *PFNRTLOGPHASE; + +/** + * Custom log prefix callback. + * + * + * @returns The number of chars written. + * + * @param pLogger Pointer to the logger instance. + * @param pchBuf Output buffer pointer. + * No need to terminate the output. + * @param cchBuf The size of the output buffer. + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(size_t) FNRTLOGPREFIX(PRTLOGGER pLogger, char *pchBuf, size_t cchBuf, void *pvUser); +/** Pointer to prefix callback function. */ +typedef FNRTLOGPREFIX *PFNRTLOGPREFIX; + + + +/** + * Logger instance structure for GC. + */ +struct RTLOGGERRC +{ + /** Pointer to temporary scratch buffer. + * This is used to format the log messages. */ + char achScratch[32768]; + /** Current scratch buffer position. */ + uint32_t offScratch; + /** This is set if a prefix is pending. */ + bool fPendingPrefix; + bool afAlignment[3]; + /** Pointer to the logger function. + * This is actually pointer to a wrapper which will push a pointer to the + * instance pointer onto the stack before jumping to the real logger function. + * A very unfortunate hack to work around the missing variadic macro support in C++. */ + RCPTRTYPE(PFNRTLOGGER) pfnLogger; + /** Pointer to the flush function. */ + PFNRTLOGFLUSHGC pfnFlush; + /** Magic number (RTLOGGERRC_MAGIC). */ + uint32_t u32Magic; + /** Logger instance flags - RTLOGFLAGS. */ + uint32_t fFlags; + /** Number of groups in the afGroups member. */ + uint32_t cGroups; + /** Group flags array - RTLOGGRPFLAGS. + * This member have variable length and may extend way beyond + * the declared size of 1 entry. */ + uint32_t afGroups[1]; +}; + +/** RTLOGGERRC::u32Magic value. (John Rogers Searle) */ +#define RTLOGGERRC_MAGIC 0x19320731 + + + +#ifndef IN_RC + +/** Pointer to internal logger bits. */ +typedef struct RTLOGGERINTERNAL *PRTLOGGERINTERNAL; + +/** + * Logger instance structure. + */ +struct RTLOGGER +{ + /** Pointer to temporary scratch buffer. + * This is used to format the log messages. */ + char achScratch[49152]; + /** Current scratch buffer position. */ + uint32_t offScratch; + /** Magic number. */ + uint32_t u32Magic; + /** Logger instance flags - RTLOGFLAGS. */ + uint32_t fFlags; + /** Destination flags - RTLOGDEST. */ + uint32_t fDestFlags; + /** Pointer to the internal bits of the logger. + * (The memory is allocated in the same block as RTLOGGER.) */ + PRTLOGGERINTERNAL pInt; + /** Pointer to the logger function (used in non-C99 mode only). + * + * This is actually pointer to a wrapper which will push a pointer to the + * instance pointer onto the stack before jumping to the real logger function. + * A very unfortunate hack to work around the missing variadic macro + * support in older C++/C standards. (The memory is allocated using + * RTMemExecAlloc(), except for agnostic R0 code.) */ + PFNRTLOGGER pfnLogger; + /** Number of groups in the afGroups and papszGroups members. */ + uint32_t cGroups; + /** Group flags array - RTLOGGRPFLAGS. + * This member have variable length and may extend way beyond + * the declared size of 1 entry. */ + uint32_t afGroups[1]; +}; + +/** RTLOGGER::u32Magic value. (Avram Noam Chomsky) */ +# define RTLOGGER_MAGIC UINT32_C(0x19281207) + +#endif /* !IN_RC */ + + +/** + * Logger flags. + */ +typedef enum RTLOGFLAGS +{ + /** The logger instance is disabled for normal output. */ + RTLOGFLAGS_DISABLED = 0x00000001, + /** The logger instance is using buffered output. */ + RTLOGFLAGS_BUFFERED = 0x00000002, + /** The logger instance expands LF to CR/LF. */ + RTLOGFLAGS_USECRLF = 0x00000010, + /** Append to the log destination where applicable. */ + RTLOGFLAGS_APPEND = 0x00000020, + /** Show relative timestamps with PREFIX_TSC and PREFIX_TS */ + RTLOGFLAGS_REL_TS = 0x00000040, + /** Show decimal timestamps with PREFIX_TSC and PREFIX_TS */ + RTLOGFLAGS_DECIMAL_TS = 0x00000080, + /** Open the file in write through mode. */ + RTLOGFLAGS_WRITE_THROUGH = 0x00000100, + /** Flush the file to disk when flushing the buffer. */ + RTLOGFLAGS_FLUSH = 0x00000200, + /** Restrict the number of log entries per group. */ + RTLOGFLAGS_RESTRICT_GROUPS = 0x00000400, + /** New lines should be prefixed with the write and read lock counts. */ + RTLOGFLAGS_PREFIX_LOCK_COUNTS = 0x00008000, + /** New lines should be prefixed with the CPU id (ApicID on intel/amd). */ + RTLOGFLAGS_PREFIX_CPUID = 0x00010000, + /** New lines should be prefixed with the native process id. */ + RTLOGFLAGS_PREFIX_PID = 0x00020000, + /** New lines should be prefixed with group flag number causing the output. */ + RTLOGFLAGS_PREFIX_FLAG_NO = 0x00040000, + /** New lines should be prefixed with group flag name causing the output. */ + RTLOGFLAGS_PREFIX_FLAG = 0x00080000, + /** New lines should be prefixed with group number. */ + RTLOGFLAGS_PREFIX_GROUP_NO = 0x00100000, + /** New lines should be prefixed with group name. */ + RTLOGFLAGS_PREFIX_GROUP = 0x00200000, + /** New lines should be prefixed with the native thread id. */ + RTLOGFLAGS_PREFIX_TID = 0x00400000, + /** New lines should be prefixed with thread name. */ + RTLOGFLAGS_PREFIX_THREAD = 0x00800000, + /** New lines should be prefixed with data from a custom callback. */ + RTLOGFLAGS_PREFIX_CUSTOM = 0x01000000, + /** New lines should be prefixed with formatted timestamp since program start. */ + RTLOGFLAGS_PREFIX_TIME_PROG = 0x04000000, + /** New lines should be prefixed with formatted timestamp (UCT). */ + RTLOGFLAGS_PREFIX_TIME = 0x08000000, + /** New lines should be prefixed with milliseconds since program start. */ + RTLOGFLAGS_PREFIX_MS_PROG = 0x10000000, + /** New lines should be prefixed with timestamp. */ + RTLOGFLAGS_PREFIX_TSC = 0x20000000, + /** New lines should be prefixed with timestamp. */ + RTLOGFLAGS_PREFIX_TS = 0x40000000, + /** The prefix mask. */ + RTLOGFLAGS_PREFIX_MASK = 0x7dff8000 +} RTLOGFLAGS; + +/** + * Logger per group flags. + */ +typedef enum RTLOGGRPFLAGS +{ + /** Enabled. */ + RTLOGGRPFLAGS_ENABLED = 0x00000001, + /** Level 1 logging. */ + RTLOGGRPFLAGS_LEVEL_1 = 0x00000002, + /** Level 2 logging. */ + RTLOGGRPFLAGS_LEVEL_2 = 0x00000004, + /** Level 3 logging. */ + RTLOGGRPFLAGS_LEVEL_3 = 0x00000008, + /** Level 4 logging. */ + RTLOGGRPFLAGS_LEVEL_4 = 0x00000010, + /** Level 5 logging. */ + RTLOGGRPFLAGS_LEVEL_5 = 0x00000020, + /** Level 6 logging. */ + RTLOGGRPFLAGS_LEVEL_6 = 0x00000040, + /** Flow logging. */ + RTLOGGRPFLAGS_FLOW = 0x00000080, + /** Restrict the number of log entries. */ + RTLOGGRPFLAGS_RESTRICT = 0x00000100, + + /** Lelik logging. */ + RTLOGGRPFLAGS_LELIK = 0x00010000, + /** Michael logging. */ + RTLOGGRPFLAGS_MICHAEL = 0x00020000, + /** sunlover logging. */ + RTLOGGRPFLAGS_SUNLOVER = 0x00040000, + /** Achim logging. */ + RTLOGGRPFLAGS_ACHIM = 0x00080000, + /** Sander logging. */ + RTLOGGRPFLAGS_SANDER = 0x00100000, + /** Klaus logging. */ + RTLOGGRPFLAGS_KLAUS = 0x00200000, + /** Frank logging. */ + RTLOGGRPFLAGS_FRANK = 0x00400000, + /** bird logging. */ + RTLOGGRPFLAGS_BIRD = 0x00800000, + /** aleksey logging. */ + RTLOGGRPFLAGS_ALEKSEY = 0x01000000, + /** dj logging. */ + RTLOGGRPFLAGS_DJ = 0x02000000, + /** NoName logging. */ + RTLOGGRPFLAGS_NONAME = 0x04000000 +} RTLOGGRPFLAGS; + +/** + * Logger destination type. + */ +typedef enum RTLOGDEST +{ + /** Log to file. */ + RTLOGDEST_FILE = 0x00000001, + /** Log to stdout. */ + RTLOGDEST_STDOUT = 0x00000002, + /** Log to stderr. */ + RTLOGDEST_STDERR = 0x00000004, + /** Log to debugger (win32 only). */ + RTLOGDEST_DEBUGGER = 0x00000008, + /** Log to com port. */ + RTLOGDEST_COM = 0x00000010, + /** Just a dummy flag to be used when no other flag applies. */ + RTLOGDEST_DUMMY = 0x20000000, + /** Log to a user defined output stream. */ + RTLOGDEST_USER = 0x40000000 +} RTLOGDEST; + + +RTDECL(void) RTLogPrintfEx(void *pvInstance, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...); + + +#ifdef DOXYGEN_RUNNING +# define LOG_DISABLED +# define LOG_ENABLED +# define LOG_ENABLE_FLOW +#endif + +/** @def LOG_DISABLED + * Use this compile time define to disable all logging macros. It can + * be overridden for each of the logging macros by the LOG_ENABLE* + * compile time defines. + */ + +/** @def LOG_ENABLED + * Use this compile time define to enable logging when not in debug mode + * or LOG_DISABLED is set. + * This will enabled Log() only. + */ + +/** @def LOG_ENABLE_FLOW + * Use this compile time define to enable flow logging when not in + * debug mode or LOG_DISABLED is defined. + * This will enable LogFlow() only. + */ + +/* + * Determine whether logging is enabled and forcefully normalize the indicators. + */ +#if (defined(DEBUG) || defined(LOG_ENABLED)) && !defined(LOG_DISABLED) +# undef LOG_DISABLED +# undef LOG_ENABLED +# define LOG_ENABLED +#else +# undef LOG_ENABLED +# undef LOG_DISABLED +# define LOG_DISABLED +#endif + + +/** @def LOG_USE_C99 + * Governs the use of variadic macros. + */ +#ifndef LOG_USE_C99 +# if defined(RT_ARCH_AMD64) || defined(RT_OS_DARWIN) || defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64) +# define LOG_USE_C99 +# endif +#endif + + +/** @def LogIt + * Write to specific logger if group enabled. + */ +#ifdef LOG_ENABLED +# if defined(LOG_USE_C99) +# define _LogRemoveParentheseis(...) __VA_ARGS__ +# define _LogIt(a_pvInst, a_fFlags, a_iGroup, ...) RTLogLoggerEx((PRTLOGGER)a_pvInst, a_fFlags, a_iGroup, __VA_ARGS__) +# define LogIt(a_pvInst, a_fFlags, a_iGroup, fmtargs) _LogIt(a_pvInst, a_fFlags, a_iGroup, _LogRemoveParentheseis fmtargs) +# define _LogItAlways(a_pvInst, a_fFlags, a_iGroup, ...) RTLogLoggerEx((PRTLOGGER)a_pvInst, a_fFlags, ~0U, __VA_ARGS__) +# define LogItAlways(a_pvInst, a_fFlags, a_iGroup, fmtargs) _LogItAlways(a_pvInst, a_fFlags, a_iGroup, _LogRemoveParentheseis fmtargs) + /** @todo invent a flag or something for skipping the group check so we can pass iGroup. LogItAlways. */ +# else +# define LogIt(a_pvInst, a_fFlags, a_iGroup, fmtargs) \ + do \ + { \ + register PRTLOGGER LogIt_pLogger = (PRTLOGGER)(a_pvInst) ? (PRTLOGGER)(a_pvInst) : RTLogDefaultInstance(); \ + if ( LogIt_pLogger \ + && !(LogIt_pLogger->fFlags & RTLOGFLAGS_DISABLED)) \ + { \ + register unsigned LogIt_fFlags = LogIt_pLogger->afGroups[(unsigned)(a_iGroup) < LogIt_pLogger->cGroups ? (unsigned)(a_iGroup) : 0]; \ + if ((LogIt_fFlags & ((a_fFlags) | RTLOGGRPFLAGS_ENABLED)) == ((a_fFlags) | RTLOGGRPFLAGS_ENABLED)) \ + LogIt_pLogger->pfnLogger fmtargs; \ + } \ + } while (0) +# define LogItAlways(a_pvInst, a_fFlags, a_iGroup, fmtargs) \ + do \ + { \ + register PRTLOGGER LogIt_pLogger = (PRTLOGGER)(a_pvInst) ? (PRTLOGGER)(a_pvInst) : RTLogDefaultInstance(); \ + if ( LogIt_pLogger \ + && !(LogIt_pLogger->fFlags & RTLOGFLAGS_DISABLED)) \ + LogIt_pLogger->pfnLogger fmtargs; \ + } while (0) +# endif +#else +# define LogIt(a_pvInst, a_fFlags, a_iGroup, fmtargs) do { } while (0) +# define LogItAlways(a_pvInst, a_fFlags, a_iGroup, fmtargs) do { } while (0) +# if defined(LOG_USE_C99) +# define _LogRemoveParentheseis(...) __VA_ARGS__ +# define _LogIt(a_pvInst, a_fFlags, a_iGroup, ...) do { } while (0) +# define _LogItAlways(a_pvInst, a_fFlags, a_iGroup, ...) do { } while (0) +# endif +#endif + + +/** @def Log + * Level 1 logging that works regardless of the group settings. + */ +#define LogAlways(a) LogItAlways(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a) + +/** @def Log + * Level 1 logging. + */ +#define Log(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a) + +/** @def Log2 + * Level 2 logging. + */ +#define Log2(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP, a) + +/** @def Log3 + * Level 3 logging. + */ +#define Log3(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP, a) + +/** @def Log4 + * Level 4 logging. + */ +#define Log4(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP, a) + +/** @def Log5 + * Level 5 logging. + */ +#define Log5(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP, a) + +/** @def Log6 + * Level 6 logging. + */ +#define Log6(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP, a) + +/** @def LogFlow + * Logging of execution flow. + */ +#define LogFlow(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, a) + +/** @def LogLelik + * lelik logging. + */ +#define LogLelik(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LELIK, LOG_GROUP, a) + + +/** @def LogMichael + * michael logging. + */ +#define LogMichael(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_MICHAEL, LOG_GROUP, a) + +/** @def LogSunlover + * sunlover logging. + */ +#define LogSunlover(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_SUNLOVER, LOG_GROUP, a) + +/** @def LogAchim + * Achim logging. + */ +#define LogAchim(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_ACHIM, LOG_GROUP, a) + +/** @def LogSander + * Sander logging. + */ +#define LogSander(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_SANDER, LOG_GROUP, a) + +/** @def LogKlaus + * klaus logging. + */ +#define LogKlaus(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_KLAUS, LOG_GROUP, a) + +/** @def LogFrank + * frank logging. + */ +#define LogFrank(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FRANK, LOG_GROUP, a) + +/** @def LogBird + * bird logging. + */ +#define LogBird(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_BIRD, LOG_GROUP, a) + +/** @def LogAleksey + * aleksey logging. + */ +#define LogAleksey(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_ALEKSEY, LOG_GROUP, a) + +/** @def LogDJ + * dj logging. + */ +#define LogDJ(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_DJ, LOG_GROUP, a) + +/** @def LogNoName + * NoName logging. + */ +#define LogNoName(a) LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_NONAME, LOG_GROUP, a) + +/** @def LogWarning + * The same as Log(), but prepents a <tt>"WARNING! "</tt> string to the message. + * + * @param a Custom log message in format <tt>("string\n" [, args])</tt>. + */ +#if defined(LOG_USE_C99) +# define LogWarning(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "WARNING! %M", _LogRemoveParentheseis a ) +#else +# define LogWarning(a) \ + do { Log(("WARNING! ")); Log(a); } while (0) +#endif + +/** @def LogTrace + * Macro to trace the execution flow: logs the file name, line number and + * function name. Can be easily searched for in log files using the + * ">>>>>" pattern (prepended to the beginning of each line). + */ +#define LogTrace() \ + LogFlow((">>>>> %s (%d): " LOG_FN_FMT "\n", __FILE__, __LINE__, __PRETTY_FUNCTION__)) + +/** @def LogTraceMsg + * The same as LogTrace but logs a custom log message right after the trace line. + * + * @param a Custom log message in format <tt>("string\n" [, args])</tt>. + */ +#ifdef LOG_USE_C99 +# define LogTraceMsg(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, ">>>>> %s (%d): " LOG_FN_FMT ": %M", __FILE__, __LINE__, __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogTraceMsg(a) \ + do { LogFlow((">>>>> %s (%d): " LOG_FN_FMT ": ", __FILE__, __LINE__, __PRETTY_FUNCTION__)); LogFlow(a); } while (0) +#endif + +/** @def LogFunc + * Level 1 logging inside C/C++ functions. + * + * Prepends the given log message with the function name followed by a + * semicolon and space. + * + * @param a Log message in format <tt>("string\n" [, args])</tt>. + */ +#ifdef LOG_USE_C99 +# define LogFunc(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogFunc(a) \ + do { Log((LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); Log(a); } while (0) +#endif + +/** @def LogThisFunc + * The same as LogFunc but for class functions (methods): the resulting log + * line is additionally prepended with a hex value of |this| pointer. + * + * @param a Log message in format <tt>("string\n" [, args])</tt>. + */ +#ifdef LOG_USE_C99 +# define LogThisFunc(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogThisFunc(a) \ + do { Log(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); Log(a); } while (0) +#endif + +/** @def LogFlowFunc + * Macro to log the execution flow inside C/C++ functions. + * + * Prepends the given log message with the function name followed by + * a semicolon and space. + * + * @param a Log message in format <tt>("string\n" [, args])</tt>. + */ +#ifdef LOG_USE_C99 +# define LogFlowFunc(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogFlowFunc(a) \ + do { LogFlow((LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); LogFlow(a); } while (0) +#endif + +/** @def LogWarningFunc + * The same as LogWarning(), but prepents the log message with the function name. + * + * @param a Log message in format <tt>("string\n" [, args])</tt>. + */ +#ifdef LOG_USE_C99 +# define LogWarningFunc(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": WARNING! %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogWarningFunc(a) \ + do { Log((LOG_FN_FMT ": WARNING! ", __PRETTY_FUNCTION__)); Log(a); } while (0) +#endif + +/** @def LogFlowThisFunc + * The same as LogFlowFunc but for class functions (methods): the resulting log + * line is additionally prepended with a hex value of |this| pointer. + * + * @param a Log message in format <tt>("string\n" [, args])</tt>. + */ +#ifdef LOG_USE_C99 +# define LogFlowThisFunc(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogFlowThisFunc(a) \ + do { LogFlow(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); LogFlow(a); } while (0) +#endif + +/** @def LogWarningThisFunc + * The same as LogWarningFunc() but for class functions (methods): the resulting + * log line is additionally prepended with a hex value of |this| pointer. + * + * @param a Log message in format <tt>("string\n" [, args])</tt>. + */ +#ifdef LOG_USE_C99 +# define LogWarningThisFunc(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": WARNING! %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogWarningThisFunc(a) \ + do { Log(("{%p} " LOG_FN_FMT ": WARNING! ", this, __PRETTY_FUNCTION__)); Log(a); } while (0) +#endif + +/** Shortcut to |LogFlowFunc ("ENTER\n")|, marks the beginnig of the function. */ +#define LogFlowFuncEnter() LogFlowFunc(("ENTER\n")) + +/** Shortcut to |LogFlowFunc ("LEAVE\n")|, marks the end of the function. */ +#define LogFlowFuncLeave() LogFlowFunc(("LEAVE\n")) + +/** Shortcut to |LogFlowFunc ("LEAVE: %Rrc\n")|, marks the end of the function. */ +#define LogFlowFuncLeaveRC(rc) LogFlowFunc(("LEAVE: %Rrc\n", (rc))) + +/** Shortcut to |LogFlowThisFunc ("ENTER\n")|, marks the beginnig of the function. */ +#define LogFlowThisFuncEnter() LogFlowThisFunc(("ENTER\n")) + +/** Shortcut to |LogFlowThisFunc ("LEAVE\n")|, marks the end of the function. */ +#define LogFlowThisFuncLeave() LogFlowThisFunc(("LEAVE\n")) + +/** @def LogObjRefCnt + * Helper macro to print the current reference count of the given COM object + * to the log file. + * + * @param pObj Pointer to the object in question (must be a pointer to an + * IUnknown subclass or simply define COM-style AddRef() and + * Release() methods) + * + * @note Use it only for temporary debugging. It leaves dummy code even if + * logging is disabled. + */ +#define LogObjRefCnt(pObj) \ + do { \ + int refc = (pObj)->AddRef(); \ + LogFlow((#pObj "{%p}.refCnt=%d\n", (pObj), refc - 1)); \ + (pObj)->Release(); \ + } while (0) + + +/** @def LogIsItEnabled + * Checks whether the specified logging group is enabled or not. + */ +#ifdef LOG_ENABLED +# define LogIsItEnabled(a_pvInst, a_fFlags, a_iGroup) \ + LogIsItEnabledInternal((a_pvInst), (unsigned)(a_iGroup), (unsigned)(a_fFlags)) +#else +# define LogIsItEnabled(a_pvInst, a_fFlags, a_iGroup) (false) +#endif + +/** @def LogIsEnabled + * Checks whether level 1 logging is enabled. + */ +#define LogIsEnabled() LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP) + +/** @def LogIs2Enabled + * Checks whether level 2 logging is enabled. + */ +#define LogIs2Enabled() LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP) + +/** @def LogIs3Enabled + * Checks whether level 3 logging is enabled. + */ +#define LogIs3Enabled() LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP) + +/** @def LogIs4Enabled + * Checks whether level 4 logging is enabled. + */ +#define LogIs4Enabled() LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP) + +/** @def LogIs5Enabled + * Checks whether level 5 logging is enabled. + */ +#define LogIs5Enabled() LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP) + +/** @def LogIs6Enabled + * Checks whether level 6 logging is enabled. + */ +#define LogIs6Enabled() LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP) + +/** @def LogIsFlowEnabled + * Checks whether execution flow logging is enabled. + */ +#define LogIsFlowEnabled() LogIsItEnabled(LOG_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP) + + +/** @name Passing Function Call Position When Logging. + * + * This is a little bit ugly as we have to omit the comma before the + * position parameters so that we don't inccur any overhead in non-logging + * builds (!defined(LOG_ENABLED). + * + * @{ */ +/** Source position for passing to a function call. */ +#ifdef LOG_ENABLED +# define RTLOG_COMMA_SRC_POS , __FILE__, __LINE__, __PRETTY_FUNCTION__ +#else +# define RTLOG_COMMA_SRC_POS RT_NOTHING +#endif +/** Source position declaration. */ +#ifdef LOG_ENABLED +# define RTLOG_COMMA_SRC_POS_DECL , const char *pszFile, unsigned iLine, const char *pszFunction +#else +# define RTLOG_COMMA_SRC_POS_DECL RT_NOTHING +#endif +/** Source position arguments. */ +#ifdef LOG_ENABLED +# define RTLOG_COMMA_SRC_POS_ARGS , pszFile, iLine, pszFunction +#else +# define RTLOG_COMMA_SRC_POS_ARGS RT_NOTHING +#endif +/** Applies NOREF() to the source position arguments. */ +#ifdef LOG_ENABLED +# define RTLOG_SRC_POS_NOREF() do { NOREF(pszFile); NOREF(iLine); NOREF(pszFunction); } while (0) +#else +# define RTLOG_SRC_POS_NOREF() do { } while (0) +#endif +/** @} */ + + + +/** @name Release Logging + * @{ + */ + +#ifdef DOXYGEN_RUNNING +# define RTLOG_REL_DISABLED +# define RTLOG_REL_ENABLED +#endif + +/** @def RTLOG_REL_DISABLED + * Use this compile time define to disable all release logging + * macros. + */ + +/** @def RTLOG_REL_ENABLED + * Use this compile time define to override RTLOG_REL_DISABLE. + */ + +/* + * Determine whether release logging is enabled and forcefully normalize the indicators. + */ +#if !defined(RTLOG_REL_DISABLED) || defined(RTLOG_REL_ENABLED) +# undef RTLOG_REL_DISABLED +# undef RTLOG_REL_ENABLED +# define RTLOG_REL_ENABLED +#else +# undef RTLOG_REL_ENABLED +# undef RTLOG_REL_DISABLED +# define RTLOG_REL_DISABLED +#endif + + +/** @def LogIt + * Write to specific logger if group enabled. + */ +#ifdef RTLOG_REL_ENABLED +# if defined(LOG_USE_C99) +# define _LogRelRemoveParentheseis(...) __VA_ARGS__ +# define _LogRelIt(a_pvInst, a_fFlags, a_iGroup, ...) \ + do \ + { \ + PRTLOGGER LogRelIt_pLogger = (PRTLOGGER)(a_pvInst) ? (PRTLOGGER)(a_pvInst) : RTLogRelDefaultInstance(); \ + if ( LogRelIt_pLogger \ + && !(LogRelIt_pLogger->fFlags & RTLOGFLAGS_DISABLED)) \ + RTLogLoggerEx(LogRelIt_pLogger, a_fFlags, a_iGroup, __VA_ARGS__); \ + _LogIt(LOG_INSTANCE, a_fFlags, a_iGroup, __VA_ARGS__); \ + } while (0) +# define LogRelIt(a_pvInst, a_fFlags, a_iGroup, fmtargs) _LogRelIt(a_pvInst, a_fFlags, a_iGroup, _LogRelRemoveParentheseis fmtargs) +# else +# define LogRelIt(a_pvInst, a_fFlags, a_iGroup, fmtargs) \ + do \ + { \ + PRTLOGGER LogRelIt_pLogger = (PRTLOGGER)(a_pvInst) ? (PRTLOGGER)(a_pvInst) : RTLogRelDefaultInstance(); \ + if ( LogRelIt_pLogger \ + && !(LogRelIt_pLogger->fFlags & RTLOGFLAGS_DISABLED)) \ + { \ + unsigned LogIt_fFlags = LogRelIt_pLogger->afGroups[(unsigned)(a_iGroup) < LogRelIt_pLogger->cGroups ? (unsigned)(a_iGroup) : 0]; \ + if ((LogIt_fFlags & ((a_fFlags) | RTLOGGRPFLAGS_ENABLED)) == ((a_fFlags) | RTLOGGRPFLAGS_ENABLED)) \ + LogRelIt_pLogger->pfnLogger fmtargs; \ + } \ + LogIt(LOG_INSTANCE, a_fFlags, a_iGroup, fmtargs); \ + } while (0) +# endif +#else /* !RTLOG_REL_ENABLED */ +# define LogRelIt(a_pvInst, a_fFlags, a_iGroup, fmtargs) do { } while (0) +# if defined(LOG_USE_C99) +# define _LogRelRemoveParentheseis(...) __VA_ARGS__ +# define _LogRelIt(a_pvInst, a_fFlags, a_iGroup, ...) do { } while (0) +# endif +#endif /* !RTLOG_REL_ENABLED */ + + +/** @def LogRel + * Level 1 logging. + */ +#define LogRel(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, a) + +/** @def LogRel2 + * Level 2 logging. + */ +#define LogRel2(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP, a) + +/** @def LogRel3 + * Level 3 logging. + */ +#define LogRel3(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP, a) + +/** @def LogRel4 + * Level 4 logging. + */ +#define LogRel4(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP, a) + +/** @def LogRel5 + * Level 5 logging. + */ +#define LogRel5(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP, a) + +/** @def LogRel6 + * Level 6 logging. + */ +#define LogRel6(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP, a) + +/** @def LogRelFlow + * Logging of execution flow. + */ +#define LogRelFlow(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, a) + +/** @def LogRelFunc + * Release logging. Prepends the given log message with the function name + * followed by a semicolon and space. + */ +#ifdef LOG_USE_C99 +# define LogRelFunc(a) \ + _LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +# define LogFunc(a) \ + _LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogRelFunc(a) \ + do { LogRel((LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); LogRel(a); } while (0) +#endif + +/** @def LogRelThisFunc + * The same as LogRelFunc but for class functions (methods): the resulting log + * line is additionally prepended with a hex value of |this| pointer. + */ +#ifdef LOG_USE_C99 +# define LogRelThisFunc(a) \ + _LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogRelThisFunc(a) \ + do { LogRel(("{%p} " LOG_FN_FMT ": ", this, __PRETTY_FUNCTION__)); LogRel(a); } while (0) +#endif + +/** @def LogRelFlowFunc + * Release logging. Macro to log the execution flow inside C/C++ functions. + * + * Prepends the given log message with the function name followed by + * a semicolon and space. + * + * @param a Log message in format <tt>("string\n" [, args])</tt>. + */ +#ifdef LOG_USE_C99 +# define LogRelFlowFunc(a) \ + _LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP, LOG_FN_FMT ": %M", __PRETTY_FUNCTION__, _LogRemoveParentheseis a ) +#else +# define LogRelFlowFunc(a) \ + do { LogRelFlow((LOG_FN_FMT ": ", __PRETTY_FUNCTION__)); LogRelFlow(a); } while (0) +#endif + +/** @def LogRelLelik + * lelik logging. + */ +#define LogRelLelik(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LELIK, LOG_GROUP, a) + +/** @def LogRelMichael + * michael logging. + */ +#define LogRelMichael(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_MICHAEL, LOG_GROUP, a) + +/** @def LogRelSunlover + * sunlover logging. + */ +#define LogRelSunlover(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_SUNLOVER, LOG_GROUP, a) + +/** @def LogRelAchim + * Achim logging. + */ +#define LogRelAchim(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_ACHIM, LOG_GROUP, a) + +/** @def LogRelSander + * Sander logging. + */ +#define LogRelSander(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_SANDER, LOG_GROUP, a) + +/** @def LogRelKlaus + * klaus logging. + */ +#define LogRelKlaus(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_KLAUS, LOG_GROUP, a) + +/** @def LogRelFrank + * frank logging. + */ +#define LogRelFrank(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_FRANK, LOG_GROUP, a) + +/** @def LogRelBird + * bird logging. + */ +#define LogRelBird(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_BIRD, LOG_GROUP, a) + +/** @def LogRelNoName + * NoName logging. + */ +#define LogRelNoName(a) LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_NONAME, LOG_GROUP, a) + + +/** @def LogRelIsItEnabled + * Checks whether the specified logging group is enabled or not. + */ +#define LogRelIsItEnabled(a_pvInst, a_fFlags, a_iGroup) \ + LogRelIsItEnabledInternal((a_pvInst), (unsigned)(a_iGroup), (unsigned)(a_fFlags)) + +/** @def LogRelIsEnabled + * Checks whether level 1 logging is enabled. + */ +#define LogRelIsEnabled() LogRelIsItEnabled(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP) + +/** @def LogRelIs2Enabled + * Checks whether level 2 logging is enabled. + */ +#define LogRelIs2Enabled() LogRelIsItEnabled(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_2, LOG_GROUP) + +/** @def LogRelIs3Enabled + * Checks whether level 3 logging is enabled. + */ +#define LogRelIs3Enabled() LogRelIsItEnabled(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_3, LOG_GROUP) + +/** @def LogRelIs4Enabled + * Checks whether level 4 logging is enabled. + */ +#define LogRelIs4Enabled() LogRelIsItEnabled(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_4, LOG_GROUP) + +/** @def LogRelIs5Enabled + * Checks whether level 5 logging is enabled. + */ +#define LogRelIs5Enabled() LogRelIsItEnabled(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_5, LOG_GROUP) + +/** @def LogRelIs6Enabled + * Checks whether level 6 logging is enabled. + */ +#define LogRelIs6Enabled() LogRelIsItEnabled(LOG_REL_INSTANCE, RTLOGGRPFLAGS_LEVEL_6, LOG_GROUP) + +/** @def LogRelIsFlowEnabled + * Checks whether execution flow logging is enabled. + */ +#define LogRelIsFlowEnabled() LogRelIsItEnabled(LOG_REL_INSTANCE, RTLOGGRPFLAGS_FLOW, LOG_GROUP) + + +#ifndef IN_RC +/** + * Sets the default release logger instance. + * + * @returns The old default instance. + * @param pLogger The new default release logger instance. + */ +RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger); +#endif /* !IN_RC */ + +/** + * Gets the default release logger instance. + * + * @returns Pointer to default release logger instance. + * @returns NULL if no default release logger instance available. + */ +RTDECL(PRTLOGGER) RTLogRelDefaultInstance(void); + +/** Internal worker function. + * Don't call directly, use the LogRelIsItEnabled macro! + */ +DECLINLINE(bool) LogRelIsItEnabledInternal(void *pvInst, unsigned iGroup, unsigned fFlags) +{ + register PRTLOGGER pLogger = (PRTLOGGER)pvInst ? (PRTLOGGER)pvInst : RTLogRelDefaultInstance(); + if ( pLogger + && !(pLogger->fFlags & RTLOGFLAGS_DISABLED)) + { + register unsigned fGrpFlags = pLogger->afGroups[(unsigned)iGroup < pLogger->cGroups ? (unsigned)iGroup : 0]; + if ((fGrpFlags & (fFlags | RTLOGGRPFLAGS_ENABLED)) == (fFlags | RTLOGGRPFLAGS_ENABLED)) + return true; + } + return false; +} + +/** + * Write to a logger instance, defaulting to the release one. + * + * This function will check whether the instance, group and flags makes up a + * logging kind which is currently enabled before writing anything to the log. + * + * @param pLogger Pointer to logger instance. + * @param fFlags The logging flags. + * @param iGroup The group. + * The value ~0U is reserved for compatibility with RTLogLogger[V] and is + * only for internal usage! + * @param pszFormat Format string. + * @param ... Format arguments. + * @remark This is a worker function for LogRelIt. + */ +RTDECL(void) RTLogRelLogger(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...); + +/** + * Write to a logger instance, defaulting to the release one. + * + * This function will check whether the instance, group and flags makes up a + * logging kind which is currently enabled before writing anything to the log. + * + * @param pLogger Pointer to logger instance. If NULL the default release instance is attempted. + * @param fFlags The logging flags. + * @param iGroup The group. + * The value ~0U is reserved for compatibility with RTLogLogger[V] and is + * only for internal usage! + * @param pszFormat Format string. + * @param args Format arguments. + */ +RTDECL(void) RTLogRelLoggerV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args); + +/** + * printf like function for writing to the default release log. + * + * @param pszFormat Printf like format string. + * @param ... Optional arguments as specified in pszFormat. + * + * @remark The API doesn't support formatting of floating point numbers at the moment. + */ +RTDECL(void) RTLogRelPrintf(const char *pszFormat, ...); + +/** + * vprintf like function for writing to the default release log. + * + * @param pszFormat Printf like format string. + * @param args Optional arguments as specified in pszFormat. + * + * @remark The API doesn't support formatting of floating point numbers at the moment. + */ +RTDECL(void) RTLogRelPrintfV(const char *pszFormat, va_list args); + +/** + * Changes the buffering setting of the default release logger. + * + * This can be used for optimizing longish logging sequences. + * + * @returns The old state. + * @param fBuffered The new state. + */ +RTDECL(bool) RTLogRelSetBuffering(bool fBuffered); + +/** @} */ + + + +/** @name COM port logging + * { + */ + +#ifdef DOXYGEN_RUNNING +# define LOG_TO_COM +# define LOG_NO_COM +#endif + +/** @def LOG_TO_COM + * Redirects the normal logging macros to the serial versions. + */ + +/** @def LOG_NO_COM + * Disables all LogCom* macros. + */ + +/** @def LogCom + * Generic logging to serial port. + */ +#if defined(LOG_ENABLED) && !defined(LOG_NO_COM) +# define LogCom(a) RTLogComPrintf a +#else +# define LogCom(a) do { } while (0) +#endif + +/** @def LogComFlow + * Logging to serial port of execution flow. + */ +#if defined(LOG_ENABLED) && defined(LOG_ENABLE_FLOW) && !defined(LOG_NO_COM) +# define LogComFlow(a) RTLogComPrintf a +#else +# define LogComFlow(a) do { } while (0) +#endif + +#ifdef LOG_TO_COM +# undef Log +# define Log(a) LogCom(a) +# undef LogFlow +# define LogFlow(a) LogComFlow(a) +#endif + +/** @} */ + + +/** @name Backdoor Logging + * @{ + */ + +#ifdef DOXYGEN_RUNNING +# define LOG_TO_BACKDOOR +# define LOG_NO_BACKDOOR +#endif + +/** @def LOG_TO_BACKDOOR + * Redirects the normal logging macros to the backdoor versions. + */ + +/** @def LOG_NO_BACKDOOR + * Disables all LogBackdoor* macros. + */ + +/** @def LogBackdoor + * Generic logging to the VBox backdoor via port I/O. + */ +#if defined(LOG_ENABLED) && !defined(LOG_NO_BACKDOOR) +# define LogBackdoor(a) RTLogBackdoorPrintf a +#else +# define LogBackdoor(a) do { } while (0) +#endif + +/** @def LogBackdoorFlow + * Logging of execution flow messages to the backdoor I/O port. + */ +#if defined(LOG_ENABLED) && !defined(LOG_NO_BACKDOOR) +# define LogBackdoorFlow(a) RTLogBackdoorPrintf a +#else +# define LogBackdoorFlow(a) do { } while (0) +#endif + +/** @def LogRelBackdoor + * Release logging to the VBox backdoor via port I/O. + */ +#if !defined(LOG_NO_BACKDOOR) +# define LogRelBackdoor(a) RTLogBackdoorPrintf a +#else +# define LogRelBackdoor(a) do { } while (0) +#endif + +#ifdef LOG_TO_BACKDOOR +# undef Log +# define Log(a) LogBackdoor(a) +# undef LogFlow +# define LogFlow(a) LogBackdoorFlow(a) +# undef LogRel +# define LogRel(a) LogRelBackdoor(a) +# if defined(LOG_USE_C99) +# undef _LogIt +# define _LogIt(a_pvInst, a_fFlags, a_iGroup, ...) LogBackdoor((__VA_ARGS__)) +# endif +#endif + +/** @} */ + + + +/** + * Gets the default logger instance, creating it if necessary. + * + * @returns Pointer to default logger instance. + * @returns NULL if no default logger instance available. + */ +RTDECL(PRTLOGGER) RTLogDefaultInstance(void); + +/** + * Gets the default logger instance. + * + * @returns Pointer to default logger instance. + * @returns NULL if no default logger instance available. + */ +RTDECL(PRTLOGGER) RTLogGetDefaultInstance(void); + +#ifndef IN_RC +/** + * Sets the default logger instance. + * + * @returns The old default instance. + * @param pLogger The new default logger instance. + */ +RTDECL(PRTLOGGER) RTLogSetDefaultInstance(PRTLOGGER pLogger); +#endif /* !IN_RC */ + +#ifdef IN_RING0 +/** + * Changes the default logger instance for the current thread. + * + * @returns IPRT status code. + * @param pLogger The logger instance. Pass NULL for deregistration. + * @param uKey Associated key for cleanup purposes. If pLogger is NULL, + * all instances with this key will be deregistered. So in + * order to only deregister the instance associated with the + * current thread use 0. + */ +RTDECL(int) RTLogSetDefaultInstanceThread(PRTLOGGER pLogger, uintptr_t uKey); +#endif /* IN_RING0 */ + + +#ifdef LOG_ENABLED +/** Internal worker function. + * Don't call directly, use the LogIsItEnabled macro! + */ +DECLINLINE(bool) LogIsItEnabledInternal(void *pvInst, unsigned iGroup, unsigned fFlags) +{ + register PRTLOGGER pLogger = (PRTLOGGER)pvInst ? (PRTLOGGER)pvInst : RTLogDefaultInstance(); + if ( pLogger + && !(pLogger->fFlags & RTLOGFLAGS_DISABLED)) + { + register unsigned fGrpFlags = pLogger->afGroups[(unsigned)iGroup < pLogger->cGroups ? (unsigned)iGroup : 0]; + if ((fGrpFlags & (fFlags | RTLOGGRPFLAGS_ENABLED)) == (fFlags | RTLOGGRPFLAGS_ENABLED)) + return true; + } + return false; +} +#endif + + +#ifndef IN_RC +/** + * Creates the default logger instance for a iprt users. + * + * Any user of the logging features will need to implement + * this or use the generic dummy. + * + * @returns Pointer to the logger instance. + */ +RTDECL(PRTLOGGER) RTLogDefaultInit(void); + +/** + * Create a logger instance. + * + * @returns iprt status code. + * + * @param ppLogger Where to store the logger instance. + * @param fFlags Logger instance flags, a combination of the + * RTLOGFLAGS_* values. + * @param pszGroupSettings The initial group settings. + * @param pszEnvVarBase Base name for the environment variables for + * this instance. + * @param cGroups Number of groups in the array. + * @param papszGroups Pointer to array of groups. This must stick + * around for the life of the logger instance. + * @param fDestFlags The destination flags. RTLOGDEST_FILE is ORed + * if pszFilenameFmt specified. + * @param pszFilenameFmt Log filename format string. Standard + * RTStrFormat(). + * @param ... Format arguments. + */ +RTDECL(int) RTLogCreate(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings, + const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups, + uint32_t fDestFlags, const char *pszFilenameFmt, ...); + +/** + * Create a logger instance. + * + * @returns iprt status code. + * + * @param ppLogger Where to store the logger instance. + * @param fFlags Logger instance flags, a combination of the + * RTLOGFLAGS_* values. + * @param pszGroupSettings The initial group settings. + * @param pszEnvVarBase Base name for the environment variables for + * this instance. + * @param cGroups Number of groups in the array. + * @param papszGroups Pointer to array of groups. This must stick + * around for the life of the logger instance. + * @param fDestFlags The destination flags. RTLOGDEST_FILE is ORed + * if pszFilenameFmt specified. + * @param pfnPhase Callback function for starting logging and for + * ending or starting a new file for log history + * rotation. NULL is OK. + * @param cHistory Number of old log files to keep when performing + * log history rotation. 0 means no history. + * @param cbHistoryFileMax Maximum size of log file when performing + * history rotation. 0 means no size limit. + * @param cSecsHistoryTimeSlot Maximum time interval per log file when + * performing history rotation, in seconds. + * 0 means time limit. + * @param pszErrorMsg A buffer which is filled with an error message if something fails. May be NULL. + * @param cchErrorMsg The size of the error message buffer. + * @param pszFilenameFmt Log filename format string. Standard RTStrFormat(). + * @param ... Format arguments. + */ +RTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings, + const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups, + uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory, + uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot, + char *pszErrorMsg, size_t cchErrorMsg, const char *pszFilenameFmt, ...); + +/** + * Create a logger instance. + * + * @returns iprt status code. + * + * @param ppLogger Where to store the logger instance. + * @param fFlags Logger instance flags, a combination of the + * RTLOGFLAGS_* values. + * @param pszGroupSettings The initial group settings. + * @param pszEnvVarBase Base name for the environment variables for + * this instance. + * @param cGroups Number of groups in the array. + * @param papszGroups Pointer to array of groups. This must stick + * around for the life of the logger instance. + * @param fDestFlags The destination flags. RTLOGDEST_FILE is ORed + * if pszFilenameFmt specified. + * @param pfnPhase Callback function for starting logging and for + * ending or starting a new file for log history + * rotation. + * @param cHistory Number of old log files to keep when performing + * log history rotation. 0 means no history. + * @param cbHistoryFileMax Maximum size of log file when performing + * history rotation. 0 means no size limit. + * @param cSecsHistoryTimeSlot Maximum time interval per log file when + * performing history rotation, in seconds. + * 0 means no time limit. + * @param pszErrorMsg A buffer which is filled with an error message + * if something fails. May be NULL. + * @param cchErrorMsg The size of the error message buffer. + * @param pszFilenameFmt Log filename format string. Standard + * RTStrFormat(). + * @param args Format arguments. + */ +RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings, + const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups, + uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory, + uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot, + char *pszErrorMsg, size_t cchErrorMsg, const char *pszFilenameFmt, va_list args); + +/** + * Create a logger instance for singled threaded ring-0 usage. + * + * @returns iprt status code. + * + * @param pLogger Where to create the logger instance. + * @param cbLogger The amount of memory available for the logger instance. + * @param pLoggerR0Ptr The ring-0 address corresponding to @a pLogger. + * @param pfnLoggerR0Ptr Pointer to logger wrapper function. + * @param pfnFlushR0Ptr Pointer to flush function. + * @param fFlags Logger instance flags, a combination of the RTLOGFLAGS_* values. + * @param fDestFlags The destination flags. + */ +RTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger, + RTR0PTR pLoggerR0Ptr, RTR0PTR pfnLoggerR0Ptr, RTR0PTR pfnFlushR0Ptr, + uint32_t fFlags, uint32_t fDestFlags); + +/** + * Calculates the minimum size of a ring-0 logger instance. + * + * @returns The minimum size. + * @param cGroups The number of groups. + * @param fFlags Relevant flags. + */ +RTDECL(size_t) RTLogCalcSizeForR0(uint32_t cGroups, uint32_t fFlags); + +/** + * Destroys a logger instance. + * + * The instance is flushed and all output destinations closed (where applicable). + * + * @returns iprt status code. + * @param pLogger The logger instance which close destroyed. NULL is fine. + */ +RTDECL(int) RTLogDestroy(PRTLOGGER pLogger); + +/** + * Create a logger instance clone for RC usage. + * + * @returns iprt status code. + * + * @param pLogger The logger instance to be cloned. + * @param pLoggerRC Where to create the RC logger instance. + * @param cbLoggerRC Amount of memory allocated to for the RC logger + * instance clone. + * @param pfnLoggerRCPtr Pointer to logger wrapper function for this + * instance (RC Ptr). + * @param pfnFlushRCPtr Pointer to flush function (RC Ptr). + * @param fFlags Logger instance flags, a combination of the RTLOGFLAGS_* values. + */ +RTDECL(int) RTLogCloneRC(PRTLOGGER pLogger, PRTLOGGERRC pLoggerRC, size_t cbLoggerRC, + RTRCPTR pfnLoggerRCPtr, RTRCPTR pfnFlushRCPtr, uint32_t fFlags); + +/** + * Flushes a RC logger instance to a R3 logger. + * + * @returns iprt status code. + * @param pLogger The R3 logger instance to flush pLoggerRC to. If NULL + * the default logger is used. + * @param pLoggerRC The RC logger instance to flush. + */ +RTDECL(void) RTLogFlushRC(PRTLOGGER pLogger, PRTLOGGERRC pLoggerRC); + +/** + * Flushes the buffer in one logger instance onto another logger. + * + * @returns iprt status code. + * + * @param pSrcLogger The logger instance to flush. + * @param pDstLogger The logger instance to flush onto. + * If NULL the default logger will be used. + */ +RTDECL(void) RTLogFlushToLogger(PRTLOGGER pSrcLogger, PRTLOGGER pDstLogger); + +/** + * Flushes a R0 logger instance to a R3 logger. + * + * @returns iprt status code. + * @param pLogger The R3 logger instance to flush pLoggerR0 to. If NULL + * the default logger is used. + * @param pLoggerR0 The R0 logger instance to flush. + */ +RTDECL(void) RTLogFlushR0(PRTLOGGER pLogger, PRTLOGGER pLoggerR0); + +/** + * Sets the custom prefix callback. + * + * @returns IPRT status code. + * @param pLogger The logger instance. + * @param pfnCallback The callback. + * @param pvUser The user argument for the callback. + * */ +RTDECL(int) RTLogSetCustomPrefixCallback(PRTLOGGER pLogger, PFNRTLOGPREFIX pfnCallback, void *pvUser); + +/** + * Same as RTLogSetCustomPrefixCallback for loggers created by + * RTLogCreateForR0. + * + * @returns IPRT status code. + * @param pLogger The logger instance. + * @param pLoggerR0Ptr The ring-0 address corresponding to @a pLogger. + * @param pfnCallbackR0Ptr The callback. + * @param pvUserR0Ptr The user argument for the callback. + * */ +RTDECL(int) RTLogSetCustomPrefixCallbackForR0(PRTLOGGER pLogger, RTR0PTR pLoggerR0Ptr, + RTR0PTR pfnCallbackR0Ptr, RTR0PTR pvUserR0Ptr); + +/** + * Copies the group settings and flags from logger instance to another. + * + * @returns IPRT status code. + * @param pDstLogger The destination logger instance. + * @param pDstLoggerR0Ptr The ring-0 address corresponding to @a pDstLogger. + * @param pSrcLogger The source logger instance. If NULL the default one is used. + * @param fFlagsOr OR mask for the flags. + * @param fFlagsAnd AND mask for the flags. + */ +RTDECL(int) RTLogCopyGroupsAndFlagsForR0(PRTLOGGER pDstLogger, RTR0PTR pDstLoggerR0Ptr, + PCRTLOGGER pSrcLogger, uint32_t fFlagsOr, uint32_t fFlagsAnd); + +/** + * Get the current log group settings as a string. + * + * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW. + * @param pLogger Logger instance (NULL for default logger). + * @param pszBuf The output buffer. + * @param cchBuf The size of the output buffer. Must be greater + * than zero. + */ +RTDECL(int) RTLogGetGroupSettings(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf); + +/** + * Updates the group settings for the logger instance using the specified + * specification string. + * + * @returns iprt status code. + * Failures can safely be ignored. + * @param pLogger Logger instance (NULL for default logger). + * @param pszValue Value to parse. + */ +RTDECL(int) RTLogGroupSettings(PRTLOGGER pLogger, const char *pszValue); +#endif /* !IN_RC */ + +/** + * Updates the flags for the logger instance using the specified + * specification string. + * + * @returns iprt status code. + * Failures can safely be ignored. + * @param pLogger Logger instance (NULL for default logger). + * @param pszValue Value to parse. + */ +RTDECL(int) RTLogFlags(PRTLOGGER pLogger, const char *pszValue); + +/** + * Changes the buffering setting of the specified logger. + * + * This can be used for optimizing longish logging sequences. + * + * @returns The old state. + * @param pLogger The logger instance (NULL is an alias for the + * default logger). + * @param fBuffered The new state. + */ +RTDECL(bool) RTLogSetBuffering(PRTLOGGER pLogger, bool fBuffered); + +/** + * Sets the max number of entries per group. + * + * @returns Old restriction. + * + * @param pLogger The logger instance (NULL is an alias for the + * default logger). + * @param cMaxEntriesPerGroup The max number of entries per group. + * + * @remarks Lowering the limit of an active logger may quietly mute groups. + * Raising it may reactive already muted groups. + */ +RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup); + +#ifndef IN_RC +/** + * Get the current log flags as a string. + * + * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW. + * @param pLogger Logger instance (NULL for default logger). + * @param pszBuf The output buffer. + * @param cchBuf The size of the output buffer. Must be greater + * than zero. + */ +RTDECL(int) RTLogGetFlags(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf); + +/** + * Updates the logger destination using the specified string. + * + * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW. + * @param pLogger Logger instance (NULL for default logger). + * @param pszValue The value to parse. + */ +RTDECL(int) RTLogDestinations(PRTLOGGER pLogger, char const *pszValue); + +/** + * Get the current log destinations as a string. + * + * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW. + * @param pLogger Logger instance (NULL for default logger). + * @param pszBuf The output buffer. + * @param cchBuf The size of the output buffer. Must be greater + * than 0. + */ +RTDECL(int) RTLogGetDestinations(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf); +#endif /* !IN_RC */ + +/** + * Flushes the specified logger. + * + * @param pLogger The logger instance to flush. + * If NULL the default instance is used. The default instance + * will not be initialized by this call. + */ +RTDECL(void) RTLogFlush(PRTLOGGER pLogger); + +/** + * Write to a logger instance. + * + * @param pLogger Pointer to logger instance. + * @param pvCallerRet Ignored. + * @param pszFormat Format string. + * @param ... Format arguments. + */ +RTDECL(void) RTLogLogger(PRTLOGGER pLogger, void *pvCallerRet, const char *pszFormat, ...); + +/** + * Write to a logger instance. + * + * @param pLogger Pointer to logger instance. + * @param pszFormat Format string. + * @param args Format arguments. + */ +RTDECL(void) RTLogLoggerV(PRTLOGGER pLogger, const char *pszFormat, va_list args); + +/** + * Write to a logger instance. + * + * This function will check whether the instance, group and flags makes up a + * logging kind which is currently enabled before writing anything to the log. + * + * @param pLogger Pointer to logger instance. If NULL the default logger instance will be attempted. + * @param fFlags The logging flags. + * @param iGroup The group. + * The value ~0U is reserved for compatibility with RTLogLogger[V] and is + * only for internal usage! + * @param pszFormat Format string. + * @param ... Format arguments. + * @remark This is a worker function of LogIt. + */ +RTDECL(void) RTLogLoggerEx(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...); + +/** + * Write to a logger instance. + * + * This function will check whether the instance, group and flags makes up a + * logging kind which is currently enabled before writing anything to the log. + * + * @param pLogger Pointer to logger instance. If NULL the default logger instance will be attempted. + * @param fFlags The logging flags. + * @param iGroup The group. + * The value ~0U is reserved for compatibility with RTLogLogger[V] and is + * only for internal usage! + * @param pszFormat Format string. + * @param args Format arguments. + */ +RTDECL(void) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args); + +/** + * printf like function for writing to the default log. + * + * @param pszFormat Printf like format string. + * @param ... Optional arguments as specified in pszFormat. + * + * @remark The API doesn't support formatting of floating point numbers at the moment. + */ +RTDECL(void) RTLogPrintf(const char *pszFormat, ...); + +/** + * vprintf like function for writing to the default log. + * + * @param pszFormat Printf like format string. + * @param args Optional arguments as specified in pszFormat. + * + * @remark The API doesn't support formatting of floating point numbers at the moment. + */ +RTDECL(void) RTLogPrintfV(const char *pszFormat, va_list args); + + +#ifndef DECLARED_FNRTSTROUTPUT /* duplicated in iprt/string.h */ +#define DECLARED_FNRTSTROUTPUT +/** + * Output callback. + * + * @returns number of bytes written. + * @param pvArg User argument. + * @param pachChars Pointer to an array of utf-8 characters. + * @param cbChars Number of bytes in the character array pointed to by pachChars. + */ +typedef DECLCALLBACK(size_t) FNRTSTROUTPUT(void *pvArg, const char *pachChars, size_t cbChars); +/** Pointer to callback function. */ +typedef FNRTSTROUTPUT *PFNRTSTROUTPUT; +#endif + +/** + * Partial vsprintf worker implementation. + * + * @returns number of bytes formatted. + * @param pfnOutput Output worker. + * Called in two ways. Normally with a string an it's length. + * For termination, it's called with NULL for string, 0 for length. + * @param pvArg Argument to output worker. + * @param pszFormat Format string. + * @param args Argument list. + */ +RTDECL(size_t) RTLogFormatV(PFNRTSTROUTPUT pfnOutput, void *pvArg, const char *pszFormat, va_list args); + +/** + * Write log buffer to COM port. + * + * @param pach Pointer to the buffer to write. + * @param cb Number of bytes to write. + */ +RTDECL(void) RTLogWriteCom(const char *pach, size_t cb); + +/** + * Prints a formatted string to the serial port used for logging. + * + * @returns Number of bytes written. + * @param pszFormat Format string. + * @param ... Optional arguments specified in the format string. + */ +RTDECL(size_t) RTLogComPrintf(const char *pszFormat, ...); + +/** + * Prints a formatted string to the serial port used for logging. + * + * @returns Number of bytes written. + * @param pszFormat Format string. + * @param args Optional arguments specified in the format string. + */ +RTDECL(size_t) RTLogComPrintfV(const char *pszFormat, va_list args); + + +#if 0 /* not implemented yet */ + +/** Indicates that the semaphores shall be used to notify the other + * part about buffer changes. */ +#define LOGHOOKBUFFER_FLAGS_SEMAPHORED 1 + +/** + * Log Hook Buffer. + * Use to communicate between the logger and a log consumer. + */ +typedef struct RTLOGHOOKBUFFER +{ + /** Write pointer. */ + volatile void *pvWrite; + /** Read pointer. */ + volatile void *pvRead; + /** Buffer start. */ + void *pvStart; + /** Buffer end (exclusive). */ + void *pvEnd; + /** Signaling semaphore used by the writer to wait on a full buffer. + * Only used when indicated in flags. */ + void *pvSemWriter; + /** Signaling semaphore used by the read to wait on an empty buffer. + * Only used when indicated in flags. */ + void *pvSemReader; + /** Buffer flags. Current reserved and set to zero. */ + volatile unsigned fFlags; +} RTLOGHOOKBUFFER; +/** Pointer to a log hook buffer. */ +typedef RTLOGHOOKBUFFER *PRTLOGHOOKBUFFER; + + +/** + * Register a logging hook. + * + * This type of logging hooks are expecting different threads acting + * producer and consumer. They share a circular buffer which have two + * pointers one for each end. When the buffer is full there are two + * alternatives (indicated by a buffer flag), either wait for the + * consumer to get it's job done, or to write a generic message saying + * buffer overflow. + * + * Since the waiting would need a signal semaphore, we'll skip that for now. + * + * @returns iprt status code. + * @param pBuffer Pointer to a logger hook buffer. + */ +RTDECL(int) RTLogRegisterHook(PRTLOGGER pLogger, PRTLOGHOOKBUFFER pBuffer); + +/** + * Deregister a logging hook registered with RTLogRegisterHook(). + * + * @returns iprt status code. + * @param pBuffer Pointer to a logger hook buffer. + */ +RTDECL(int) RTLogDeregisterHook(PRTLOGGER pLogger, PRTLOGHOOKBUFFER pBuffer); + +#endif /* not implemented yet */ + + + +/** + * Write log buffer to a debugger (RTLOGDEST_DEBUGGER). + * + * @param pach What to write. + * @param cb How much to write. + * @remark When linking statically, this function can be replaced by defining your own. + */ +RTDECL(void) RTLogWriteDebugger(const char *pach, size_t cb); + +/** + * Write log buffer to a user defined output stream (RTLOGDEST_USER). + * + * @param pach What to write. + * @param cb How much to write. + * @remark When linking statically, this function can be replaced by defining your own. + */ +RTDECL(void) RTLogWriteUser(const char *pach, size_t cb); + +/** + * Write log buffer to stdout (RTLOGDEST_STDOUT). + * + * @param pach What to write. + * @param cb How much to write. + * @remark When linking statically, this function can be replaced by defining your own. + */ +RTDECL(void) RTLogWriteStdOut(const char *pach, size_t cb); + +/** + * Write log buffer to stdout (RTLOGDEST_STDERR). + * + * @param pach What to write. + * @param cb How much to write. + * @remark When linking statically, this function can be replaced by defining your own. + */ +RTDECL(void) RTLogWriteStdErr(const char *pach, size_t cb); + +#ifdef VBOX + +/** + * Prints a formatted string to the backdoor port. + * + * @returns Number of bytes written. + * @param pszFormat Format string. + * @param ... Optional arguments specified in the format string. + */ +RTDECL(size_t) RTLogBackdoorPrintf(const char *pszFormat, ...); + +/** + * Prints a formatted string to the backdoor port. + * + * @returns Number of bytes written. + * @param pszFormat Format string. + * @param args Optional arguments specified in the format string. + */ +RTDECL(size_t) RTLogBackdoorPrintfV(const char *pszFormat, va_list args); + +#endif /* VBOX */ + +RT_C_DECLS_END + +/** @} */ + +#endif + diff --git a/include/iprt/mangling.h b/include/iprt/mangling.h new file mode 100644 index 00000000..cc8b4ec6 --- /dev/null +++ b/include/iprt/mangling.h @@ -0,0 +1,1796 @@ +/** @file + * IPRT - Symbol Mangling. + * + * This header is used to mangle public IPRT symbol to make it possible to have + * several IPRT version loaded into one symbol space at the same time. To + * enable symbol mangling you create a header which the compiler includes for + * every compilation unit (check out the -include option of gcc). Your header + * will define RT_MANGLER(name) and then include this header to set up the + * actual mappings. + */ + +/* + * Copyright (C) 2011-2012 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. + */ + +#ifndef ___iprt_mangling_h +#define ___iprt_mangling_h + +#ifndef RT_MANGLER +# error "RT_MANGLER is not defined." +#endif + +#ifndef DOXYGEN_RUNNING + +/** @def RT_WITH_MANGLING + * Indicates that we're mangling symbols. */ +# define RT_WITH_MANGLING + + +/* + * Stable functions (alphabetical order): + */ +# define ASMAtomicCmpXchgExU64 RT_MANGLER(ASMAtomicCmpXchgExU64) /* not-some-systems... */ +# define ASMAtomicCmpXchgExU64_EndProc RT_MANGLER(ASMAtomicCmpXchgExU64_EndProc) +# define ASMAtomicCmpXchgU64 RT_MANGLER(ASMAtomicCmpXchgU64) /* not-some-systems... */ +# define ASMAtomicCmpXchgU64_EndProc RT_MANGLER(ASMAtomicCmpXchgU64_EndProc) +# define ASMAtomicReadU64 RT_MANGLER(ASMAtomicReadU64) /* not-some-systems... */ +# define ASMAtomicReadU64_EndProc RT_MANGLER(ASMAtomicReadU64_EndProc) +# define ASMAtomicUoReadU64 RT_MANGLER(ASMAtomicUoReadU64) /* not-some-systems... */ +# define ASMAtomicUoReadU64_EndProc RT_MANGLER(ASMAtomicUoReadU64_EndProc) +# define ASMAtomicXchgU64 RT_MANGLER(ASMAtomicXchgU64) /* not-some-systems... */ +# define ASMAtomicXchgU64_EndProc RT_MANGLER(ASMAtomicXchgU64_EndProc) +# define RTAssertAreQuiet RT_MANGLER(RTAssertAreQuiet) +# define RTAssertMayPanic RT_MANGLER(RTAssertMayPanic) +# define RTAssertMsg1 RT_MANGLER(RTAssertMsg1) +# define RTAssertMsg1Weak RT_MANGLER(RTAssertMsg1Weak) +# define RTAssertMsg2 RT_MANGLER(RTAssertMsg2) +# define RTAssertMsg2Add RT_MANGLER(RTAssertMsg2Add) +# define RTAssertMsg2AddV RT_MANGLER(RTAssertMsg2AddV) +# define RTAssertMsg2AddWeak RT_MANGLER(RTAssertMsg2AddWeak) +# define RTAssertMsg2AddWeakV RT_MANGLER(RTAssertMsg2AddWeakV) +# define RTAssertMsg2V RT_MANGLER(RTAssertMsg2V) +# define RTAssertMsg2Weak RT_MANGLER(RTAssertMsg2Weak) +# define RTAssertMsg2WeakV RT_MANGLER(RTAssertMsg2WeakV) +# define RTAssertSetMayPanic RT_MANGLER(RTAssertSetMayPanic) +# define RTAssertSetQuiet RT_MANGLER(RTAssertSetQuiet) +# define RTAssertShouldPanic RT_MANGLER(RTAssertShouldPanic) +# define RTAvlGCPhysDestroy RT_MANGLER(RTAvlGCPhysDestroy) +# define RTAvlGCPhysDoWithAll RT_MANGLER(RTAvlGCPhysDoWithAll) +# define RTAvlGCPhysGet RT_MANGLER(RTAvlGCPhysGet) +# define RTAvlGCPhysGetBestFit RT_MANGLER(RTAvlGCPhysGetBestFit) +# define RTAvlGCPhysInsert RT_MANGLER(RTAvlGCPhysInsert) +# define RTAvlGCPhysRemove RT_MANGLER(RTAvlGCPhysRemove) +# define RTAvlGCPhysRemoveBestFit RT_MANGLER(RTAvlGCPhysRemoveBestFit) +# define RTAvlGCPtrDestroy RT_MANGLER(RTAvlGCPtrDestroy) +# define RTAvlGCPtrDoWithAll RT_MANGLER(RTAvlGCPtrDoWithAll) +# define RTAvlGCPtrGet RT_MANGLER(RTAvlGCPtrGet) +# define RTAvlGCPtrGetBestFit RT_MANGLER(RTAvlGCPtrGetBestFit) +# define RTAvlGCPtrInsert RT_MANGLER(RTAvlGCPtrInsert) +# define RTAvlGCPtrRemove RT_MANGLER(RTAvlGCPtrRemove) +# define RTAvlGCPtrRemoveBestFit RT_MANGLER(RTAvlGCPtrRemoveBestFit) +# define RTAvlHCPhysDestroy RT_MANGLER(RTAvlHCPhysDestroy) +# define RTAvlHCPhysDoWithAll RT_MANGLER(RTAvlHCPhysDoWithAll) +# define RTAvlHCPhysGet RT_MANGLER(RTAvlHCPhysGet) +# define RTAvlHCPhysGetBestFit RT_MANGLER(RTAvlHCPhysGetBestFit) +# define RTAvlHCPhysInsert RT_MANGLER(RTAvlHCPhysInsert) +# define RTAvlHCPhysRemove RT_MANGLER(RTAvlHCPhysRemove) +# define RTAvlHCPhysRemoveBestFit RT_MANGLER(RTAvlHCPhysRemoveBestFit) +# define RTAvllU32Destroy RT_MANGLER(RTAvllU32Destroy) +# define RTAvllU32DoWithAll RT_MANGLER(RTAvllU32DoWithAll) +# define RTAvllU32Get RT_MANGLER(RTAvllU32Get) +# define RTAvllU32GetBestFit RT_MANGLER(RTAvllU32GetBestFit) +# define RTAvllU32Insert RT_MANGLER(RTAvllU32Insert) +# define RTAvllU32Remove RT_MANGLER(RTAvllU32Remove) +# define RTAvllU32RemoveBestFit RT_MANGLER(RTAvllU32RemoveBestFit) +# define RTAvllU32RemoveNode RT_MANGLER(RTAvllU32RemoveNode) +# define RTAvloGCPhysDestroy RT_MANGLER(RTAvloGCPhysDestroy) +# define RTAvloGCPhysDoWithAll RT_MANGLER(RTAvloGCPhysDoWithAll) +# define RTAvloGCPhysGet RT_MANGLER(RTAvloGCPhysGet) +# define RTAvloGCPhysGetBestFit RT_MANGLER(RTAvloGCPhysGetBestFit) +# define RTAvloGCPhysInsert RT_MANGLER(RTAvloGCPhysInsert) +# define RTAvloGCPhysRemove RT_MANGLER(RTAvloGCPhysRemove) +# define RTAvloGCPhysRemoveBestFit RT_MANGLER(RTAvloGCPhysRemoveBestFit) +# define RTAvloGCPtrDestroy RT_MANGLER(RTAvloGCPtrDestroy) +# define RTAvloGCPtrDoWithAll RT_MANGLER(RTAvloGCPtrDoWithAll) +# define RTAvloGCPtrGet RT_MANGLER(RTAvloGCPtrGet) +# define RTAvloGCPtrGetBestFit RT_MANGLER(RTAvloGCPtrGetBestFit) +# define RTAvloGCPtrInsert RT_MANGLER(RTAvloGCPtrInsert) +# define RTAvloGCPtrRemove RT_MANGLER(RTAvloGCPtrRemove) +# define RTAvloGCPtrRemoveBestFit RT_MANGLER(RTAvloGCPtrRemoveBestFit) +# define RTAvloHCPhysDestroy RT_MANGLER(RTAvloHCPhysDestroy) +# define RTAvloHCPhysDoWithAll RT_MANGLER(RTAvloHCPhysDoWithAll) +# define RTAvloHCPhysGet RT_MANGLER(RTAvloHCPhysGet) +# define RTAvloHCPhysGetBestFit RT_MANGLER(RTAvloHCPhysGetBestFit) +# define RTAvloHCPhysInsert RT_MANGLER(RTAvloHCPhysInsert) +# define RTAvloHCPhysRemove RT_MANGLER(RTAvloHCPhysRemove) +# define RTAvloHCPhysRemoveBestFit RT_MANGLER(RTAvloHCPhysRemoveBestFit) +# define RTAvloIOPortDestroy RT_MANGLER(RTAvloIOPortDestroy) +# define RTAvloIOPortDoWithAll RT_MANGLER(RTAvloIOPortDoWithAll) +# define RTAvloIOPortGet RT_MANGLER(RTAvloIOPortGet) +# define RTAvloIOPortGetBestFit RT_MANGLER(RTAvloIOPortGetBestFit) +# define RTAvloIOPortInsert RT_MANGLER(RTAvloIOPortInsert) +# define RTAvloIOPortRemove RT_MANGLER(RTAvloIOPortRemove) +# define RTAvloIOPortRemoveBestFit RT_MANGLER(RTAvloIOPortRemoveBestFit) +# define RTAvloU32Destroy RT_MANGLER(RTAvloU32Destroy) +# define RTAvloU32DoWithAll RT_MANGLER(RTAvloU32DoWithAll) +# define RTAvloU32Get RT_MANGLER(RTAvloU32Get) +# define RTAvloU32GetBestFit RT_MANGLER(RTAvloU32GetBestFit) +# define RTAvloU32Insert RT_MANGLER(RTAvloU32Insert) +# define RTAvloU32Remove RT_MANGLER(RTAvloU32Remove) +# define RTAvloU32RemoveBestFit RT_MANGLER(RTAvloU32RemoveBestFit) +# define RTAvlPVDestroy RT_MANGLER(RTAvlPVDestroy) +# define RTAvlPVDoWithAll RT_MANGLER(RTAvlPVDoWithAll) +# define RTAvlPVGet RT_MANGLER(RTAvlPVGet) +# define RTAvlPVGetBestFit RT_MANGLER(RTAvlPVGetBestFit) +# define RTAvlPVInsert RT_MANGLER(RTAvlPVInsert) +# define RTAvlPVRemove RT_MANGLER(RTAvlPVRemove) +# define RTAvlPVRemoveBestFit RT_MANGLER(RTAvlPVRemoveBestFit) +# define RTAvlrFileOffsetDestroy RT_MANGLER(RTAvlrFileOffsetDestroy) +# define RTAvlrFileOffsetDoWithAll RT_MANGLER(RTAvlrFileOffsetDoWithAll) +# define RTAvlrFileOffsetGet RT_MANGLER(RTAvlrFileOffsetGet) +# define RTAvlrFileOffsetGetBestFit RT_MANGLER(RTAvlrFileOffsetGetBestFit) +# define RTAvlrFileOffsetGetLeft RT_MANGLER(RTAvlrFileOffsetGetLeft) +# define RTAvlrFileOffsetGetRight RT_MANGLER(RTAvlrFileOffsetGetRight) +# define RTAvlrFileOffsetGetRoot RT_MANGLER(RTAvlrFileOffsetGetRoot) +# define RTAvlrFileOffsetInsert RT_MANGLER(RTAvlrFileOffsetInsert) +# define RTAvlrFileOffsetRangeGet RT_MANGLER(RTAvlrFileOffsetRangeGet) +# define RTAvlrFileOffsetRangeRemove RT_MANGLER(RTAvlrFileOffsetRangeRemove) +# define RTAvlrFileOffsetRemove RT_MANGLER(RTAvlrFileOffsetRemove) +# define RTAvlrGCPtrDestroy RT_MANGLER(RTAvlrGCPtrDestroy) +# define RTAvlrGCPtrDoWithAll RT_MANGLER(RTAvlrGCPtrDoWithAll) +# define RTAvlrGCPtrGet RT_MANGLER(RTAvlrGCPtrGet) +# define RTAvlrGCPtrGetBestFit RT_MANGLER(RTAvlrGCPtrGetBestFit) +# define RTAvlrGCPtrGetLeft RT_MANGLER(RTAvlrGCPtrGetLeft) +# define RTAvlrGCPtrGetRight RT_MANGLER(RTAvlrGCPtrGetRight) +# define RTAvlrGCPtrGetRoot RT_MANGLER(RTAvlrGCPtrGetRoot) +# define RTAvlrGCPtrInsert RT_MANGLER(RTAvlrGCPtrInsert) +# define RTAvlrGCPtrRangeGet RT_MANGLER(RTAvlrGCPtrRangeGet) +# define RTAvlrGCPtrRangeRemove RT_MANGLER(RTAvlrGCPtrRangeRemove) +# define RTAvlrGCPtrRemove RT_MANGLER(RTAvlrGCPtrRemove) +# define RTAvlroGCPhysDestroy RT_MANGLER(RTAvlroGCPhysDestroy) +# define RTAvlroGCPhysDoWithAll RT_MANGLER(RTAvlroGCPhysDoWithAll) +# define RTAvlroGCPhysGet RT_MANGLER(RTAvlroGCPhysGet) +# define RTAvlroGCPhysGetBestFit RT_MANGLER(RTAvlroGCPhysGetBestFit) +# define RTAvlroGCPhysGetLeft RT_MANGLER(RTAvlroGCPhysGetLeft) +# define RTAvlroGCPhysGetRight RT_MANGLER(RTAvlroGCPhysGetRight) +# define RTAvlroGCPhysGetRoot RT_MANGLER(RTAvlroGCPhysGetRoot) +# define RTAvlroGCPhysInsert RT_MANGLER(RTAvlroGCPhysInsert) +# define RTAvlroGCPhysRangeGet RT_MANGLER(RTAvlroGCPhysRangeGet) +# define RTAvlroGCPhysRangeRemove RT_MANGLER(RTAvlroGCPhysRangeRemove) +# define RTAvlroGCPhysRemove RT_MANGLER(RTAvlroGCPhysRemove) +# define RTAvlroGCPtrDestroy RT_MANGLER(RTAvlroGCPtrDestroy) +# define RTAvlroGCPtrDoWithAll RT_MANGLER(RTAvlroGCPtrDoWithAll) +# define RTAvlroGCPtrGet RT_MANGLER(RTAvlroGCPtrGet) +# define RTAvlroGCPtrGetBestFit RT_MANGLER(RTAvlroGCPtrGetBestFit) +# define RTAvlroGCPtrGetLeft RT_MANGLER(RTAvlroGCPtrGetLeft) +# define RTAvlroGCPtrGetRight RT_MANGLER(RTAvlroGCPtrGetRight) +# define RTAvlroGCPtrGetRoot RT_MANGLER(RTAvlroGCPtrGetRoot) +# define RTAvlroGCPtrInsert RT_MANGLER(RTAvlroGCPtrInsert) +# define RTAvlroGCPtrRangeGet RT_MANGLER(RTAvlroGCPtrRangeGet) +# define RTAvlroGCPtrRangeRemove RT_MANGLER(RTAvlroGCPtrRangeRemove) +# define RTAvlroGCPtrRemove RT_MANGLER(RTAvlroGCPtrRemove) +# define RTAvlroIOPortDestroy RT_MANGLER(RTAvlroIOPortDestroy) +# define RTAvlroIOPortDoWithAll RT_MANGLER(RTAvlroIOPortDoWithAll) +# define RTAvlroIOPortGet RT_MANGLER(RTAvlroIOPortGet) +# define RTAvlroIOPortInsert RT_MANGLER(RTAvlroIOPortInsert) +# define RTAvlroIOPortRangeGet RT_MANGLER(RTAvlroIOPortRangeGet) +# define RTAvlroIOPortRangeRemove RT_MANGLER(RTAvlroIOPortRangeRemove) +# define RTAvlroIOPortRemove RT_MANGLER(RTAvlroIOPortRemove) +# define RTAvlrooGCPtrDestroy RT_MANGLER(RTAvlrooGCPtrDestroy) +# define RTAvlrooGCPtrDoWithAll RT_MANGLER(RTAvlrooGCPtrDoWithAll) +# define RTAvlrooGCPtrGet RT_MANGLER(RTAvlrooGCPtrGet) +# define RTAvlrooGCPtrGetBestFit RT_MANGLER(RTAvlrooGCPtrGetBestFit) +# define RTAvlrooGCPtrGetLeft RT_MANGLER(RTAvlrooGCPtrGetLeft) +# define RTAvlrooGCPtrGetNextEqual RT_MANGLER(RTAvlrooGCPtrGetNextEqual) +# define RTAvlrooGCPtrGetRight RT_MANGLER(RTAvlrooGCPtrGetRight) +# define RTAvlrooGCPtrGetRoot RT_MANGLER(RTAvlrooGCPtrGetRoot) +# define RTAvlrooGCPtrInsert RT_MANGLER(RTAvlrooGCPtrInsert) +# define RTAvlrooGCPtrRangeGet RT_MANGLER(RTAvlrooGCPtrRangeGet) +# define RTAvlrooGCPtrRangeRemove RT_MANGLER(RTAvlrooGCPtrRangeRemove) +# define RTAvlrooGCPtrRemove RT_MANGLER(RTAvlrooGCPtrRemove) +# define RTAvlrPVDestroy RT_MANGLER(RTAvlrPVDestroy) +# define RTAvlrPVDoWithAll RT_MANGLER(RTAvlrPVDoWithAll) +# define RTAvlrPVGet RT_MANGLER(RTAvlrPVGet) +# define RTAvlrPVGetBestFit RT_MANGLER(RTAvlrPVGetBestFit) +# define RTAvlrPVInsert RT_MANGLER(RTAvlrPVInsert) +# define RTAvlrPVRangeGet RT_MANGLER(RTAvlrPVRangeGet) +# define RTAvlrPVRangeRemove RT_MANGLER(RTAvlrPVRangeRemove) +# define RTAvlrPVRemove RT_MANGLER(RTAvlrPVRemove) +# define RTAvlrPVRemoveBestFit RT_MANGLER(RTAvlrPVRemoveBestFit) +# define RTAvlrU64Destroy RT_MANGLER(RTAvlrU64Destroy) +# define RTAvlrU64DoWithAll RT_MANGLER(RTAvlrU64DoWithAll) +# define RTAvlrU64Get RT_MANGLER(RTAvlrU64Get) +# define RTAvlrU64GetBestFit RT_MANGLER(RTAvlrU64GetBestFit) +# define RTAvlrU64Insert RT_MANGLER(RTAvlrU64Insert) +# define RTAvlrU64RangeGet RT_MANGLER(RTAvlrU64RangeGet) +# define RTAvlrU64RangeRemove RT_MANGLER(RTAvlrU64RangeRemove) +# define RTAvlrU64Remove RT_MANGLER(RTAvlrU64Remove) +# define RTAvlrU64RemoveBestFit RT_MANGLER(RTAvlrU64RemoveBestFit) +# define RTAvlrUIntPtrDestroy RT_MANGLER(RTAvlrUIntPtrDestroy) +# define RTAvlrUIntPtrDoWithAll RT_MANGLER(RTAvlrUIntPtrDoWithAll) +# define RTAvlrUIntPtrGet RT_MANGLER(RTAvlrUIntPtrGet) +# define RTAvlrUIntPtrGetBestFit RT_MANGLER(RTAvlrUIntPtrGetBestFit) +# define RTAvlrUIntPtrGetLeft RT_MANGLER(RTAvlrUIntPtrGetLeft) +# define RTAvlrUIntPtrGetRight RT_MANGLER(RTAvlrUIntPtrGetRight) +# define RTAvlrUIntPtrGetRoot RT_MANGLER(RTAvlrUIntPtrGetRoot) +# define RTAvlrUIntPtrInsert RT_MANGLER(RTAvlrUIntPtrInsert) +# define RTAvlrUIntPtrRangeGet RT_MANGLER(RTAvlrUIntPtrRangeGet) +# define RTAvlrUIntPtrRangeRemove RT_MANGLER(RTAvlrUIntPtrRangeRemove) +# define RTAvlrUIntPtrRemove RT_MANGLER(RTAvlrUIntPtrRemove) +# define RTAvlU32Destroy RT_MANGLER(RTAvlU32Destroy) +# define RTAvlU32DoWithAll RT_MANGLER(RTAvlU32DoWithAll) +# define RTAvlU32Get RT_MANGLER(RTAvlU32Get) +# define RTAvlU32GetBestFit RT_MANGLER(RTAvlU32GetBestFit) +# define RTAvlU32Insert RT_MANGLER(RTAvlU32Insert) +# define RTAvlU32Remove RT_MANGLER(RTAvlU32Remove) +# define RTAvlU32RemoveBestFit RT_MANGLER(RTAvlU32RemoveBestFit) +# define RTAvlUIntPtrDestroy RT_MANGLER(RTAvlUIntPtrDestroy) +# define RTAvlUIntPtrDoWithAll RT_MANGLER(RTAvlUIntPtrDoWithAll) +# define RTAvlUIntPtrGet RT_MANGLER(RTAvlUIntPtrGet) +# define RTAvlUIntPtrGetBestFit RT_MANGLER(RTAvlUIntPtrGetBestFit) +# define RTAvlUIntPtrGetLeft RT_MANGLER(RTAvlUIntPtrGetLeft) +# define RTAvlUIntPtrGetRight RT_MANGLER(RTAvlUIntPtrGetRight) +# define RTAvlUIntPtrGetRoot RT_MANGLER(RTAvlUIntPtrGetRoot) +# define RTAvlUIntPtrInsert RT_MANGLER(RTAvlUIntPtrInsert) +# define RTAvlUIntPtrRemove RT_MANGLER(RTAvlUIntPtrRemove) +# define RTAvlULDestroy RT_MANGLER(RTAvlULDestroy) +# define RTAvlULDoWithAll RT_MANGLER(RTAvlULDoWithAll) +# define RTAvlULGet RT_MANGLER(RTAvlULGet) +# define RTAvlULGetBestFit RT_MANGLER(RTAvlULGetBestFit) +# define RTAvlULInsert RT_MANGLER(RTAvlULInsert) +# define RTAvlULRemove RT_MANGLER(RTAvlULRemove) +# define RTAvlULRemoveBestFit RT_MANGLER(RTAvlULRemoveBestFit) +# define RTBase64Decode RT_MANGLER(RTBase64Decode) +# define RTBase64DecodedSize RT_MANGLER(RTBase64DecodedSize) +# define RTBase64Encode RT_MANGLER(RTBase64Encode) +# define RTBase64EncodedLength RT_MANGLER(RTBase64EncodedLength) +# define RTBldCfgCompiler RT_MANGLER(RTBldCfgCompiler) +# define RTBldCfgRevision RT_MANGLER(RTBldCfgRevision) +# define RTBldCfgRevisionStr RT_MANGLER(RTBldCfgRevisionStr) +# define RTBldCfgTarget RT_MANGLER(RTBldCfgTarget) +# define RTBldCfgTargetArch RT_MANGLER(RTBldCfgTargetArch) +# define RTBldCfgTargetDotArch RT_MANGLER(RTBldCfgTargetDotArch) +# define RTBldCfgType RT_MANGLER(RTBldCfgType) +# define RTBldCfgVersion RT_MANGLER(RTBldCfgVersion) +# define RTBldCfgVersionBuild RT_MANGLER(RTBldCfgVersionBuild) +# define RTBldCfgVersionMajor RT_MANGLER(RTBldCfgVersionMajor) +# define RTBldCfgVersionMinor RT_MANGLER(RTBldCfgVersionMinor) +# define RTCdromOpen RT_MANGLER(RTCdromOpen) +# define RTCdromRetain RT_MANGLER(RTCdromRetain) +# define RTCdromRelease RT_MANGLER(RTCdromRelease) +# define RTCdromQueryMountPoint RT_MANGLER(RTCdromQueryMountPoint) +# define RTCdromUnmount RT_MANGLER(RTCdromUnmount) +# define RTCdromEject RT_MANGLER(RTCdromEject) +# define RTCdromLock RT_MANGLER(RTCdromLock) +# define RTCdromUnlock RT_MANGLER(RTCdromUnlock) +# define RTCdromCount RT_MANGLER(RTCdromCount) +# define RTCdromOrdinalToName RT_MANGLER(RTCdromOrdinalToName) +# define RTCdromOpenByOrdinal RT_MANGLER(RTCdromOpenByOrdinal) +# define RTCidrStrToIPv4 RT_MANGLER(RTCidrStrToIPv4) +# define RTCircBufAcquireReadBlock RT_MANGLER(RTCircBufAcquireReadBlock) +# define RTCircBufAcquireWriteBlock RT_MANGLER(RTCircBufAcquireWriteBlock) +# define RTCircBufCreate RT_MANGLER(RTCircBufCreate) +# define RTCircBufDestroy RT_MANGLER(RTCircBufDestroy) +# define RTCircBufFree RT_MANGLER(RTCircBufFree) +# define RTCircBufIsReading RT_MANGLER(RTCircBufIsReading) +# define RTCircBufIsWriting RT_MANGLER(RTCircBufIsWriting) +# define RTCircBufReleaseReadBlock RT_MANGLER(RTCircBufReleaseReadBlock) +# define RTCircBufReleaseWriteBlock RT_MANGLER(RTCircBufReleaseWriteBlock) +# define RTCircBufReset RT_MANGLER(RTCircBufReset) +# define RTCircBufSize RT_MANGLER(RTCircBufSize) +# define RTCircBufUsed RT_MANGLER(RTCircBufUsed) +# define RTCoreDumperDisable RT_MANGLER(RTCoreDumperDisable) /* solaris */ +# define RTCoreDumperSetup RT_MANGLER(RTCoreDumperSetup) /* solaris */ +# define RTCoreDumperTakeDump RT_MANGLER(RTCoreDumperTakeDump) /* solaris */ +# define RTCrc32 RT_MANGLER(RTCrc32) +# define RTCrc32Finish RT_MANGLER(RTCrc32Finish) +# define RTCrc32Process RT_MANGLER(RTCrc32Process) +# define RTCrc32Start RT_MANGLER(RTCrc32Start) +# define RTCrc64 RT_MANGLER(RTCrc64) +# define RTCrc64Finish RT_MANGLER(RTCrc64Finish) +# define RTCrc64Process RT_MANGLER(RTCrc64Process) +# define RTCrc64Start RT_MANGLER(RTCrc64Start) +# define RTCrcAdler32 RT_MANGLER(RTCrcAdler32) +# define RTCrcAdler32Finish RT_MANGLER(RTCrcAdler32Finish) +# define RTCrcAdler32Process RT_MANGLER(RTCrcAdler32Process) +# define RTCrcAdler32Start RT_MANGLER(RTCrcAdler32Start) +# define RTCritSectDelete RT_MANGLER(RTCritSectDelete) +# define RTCritSectEnter RT_MANGLER(RTCritSectEnter) +# define RTCritSectEnterDebug RT_MANGLER(RTCritSectEnterDebug) +# define RTCritSectEnterMultiple RT_MANGLER(RTCritSectEnterMultiple) +# define RTCritSectEnterMultipleDebug RT_MANGLER(RTCritSectEnterMultipleDebug) +# define RTCritSectInit RT_MANGLER(RTCritSectInit) +# define RTCritSectInitEx RT_MANGLER(RTCritSectInitEx) +# define RTCritSectLeave RT_MANGLER(RTCritSectLeave) +# define RTCritSectLeaveMultiple RT_MANGLER(RTCritSectLeaveMultiple) +# define RTCritSectSetSubClass RT_MANGLER(RTCritSectSetSubClass) +# define RTCritSectTryEnter RT_MANGLER(RTCritSectTryEnter) +# define RTCritSectTryEnterDebug RT_MANGLER(RTCritSectTryEnterDebug) +# define RTDbgAsCreate RT_MANGLER(RTDbgAsCreate) +# define RTDbgAsCreateF RT_MANGLER(RTDbgAsCreateF) +# define RTDbgAsCreateV RT_MANGLER(RTDbgAsCreateV) +# define RTDbgAsFirstAddr RT_MANGLER(RTDbgAsFirstAddr) +# define RTDbgAsLastAddr RT_MANGLER(RTDbgAsLastAddr) +# define RTDbgAsLineAdd RT_MANGLER(RTDbgAsLineAdd) +# define RTDbgAsLineByAddr RT_MANGLER(RTDbgAsLineByAddr) +# define RTDbgAsLineByAddrA RT_MANGLER(RTDbgAsLineByAddrA) +# define RTDbgAsModuleByAddr RT_MANGLER(RTDbgAsModuleByAddr) +# define RTDbgAsModuleByIndex RT_MANGLER(RTDbgAsModuleByIndex) +# define RTDbgAsModuleByName RT_MANGLER(RTDbgAsModuleByName) +# define RTDbgAsModuleCount RT_MANGLER(RTDbgAsModuleCount) +# define RTDbgAsModuleLink RT_MANGLER(RTDbgAsModuleLink) +# define RTDbgAsModuleLinkSeg RT_MANGLER(RTDbgAsModuleLinkSeg) +# define RTDbgAsModuleQueryMapByIndex RT_MANGLER(RTDbgAsModuleQueryMapByIndex) +# define RTDbgAsModuleUnlink RT_MANGLER(RTDbgAsModuleUnlink) +# define RTDbgAsModuleUnlinkByAddr RT_MANGLER(RTDbgAsModuleUnlinkByAddr) +# define RTDbgAsName RT_MANGLER(RTDbgAsName) +# define RTDbgAsRelease RT_MANGLER(RTDbgAsRelease) +# define RTDbgAsRetain RT_MANGLER(RTDbgAsRetain) +# define RTDbgAsSymbolAdd RT_MANGLER(RTDbgAsSymbolAdd) +# define RTDbgAsSymbolByAddr RT_MANGLER(RTDbgAsSymbolByAddr) +# define RTDbgAsSymbolByAddrA RT_MANGLER(RTDbgAsSymbolByAddrA) +# define RTDbgAsSymbolByName RT_MANGLER(RTDbgAsSymbolByName) +# define RTDbgAsSymbolByNameA RT_MANGLER(RTDbgAsSymbolByNameA) +# define RTDbgLineAlloc RT_MANGLER(RTDbgLineAlloc) +# define RTDbgLineDup RT_MANGLER(RTDbgLineDup) +# define RTDbgLineFree RT_MANGLER(RTDbgLineFree) +# define RTDbgModCreate RT_MANGLER(RTDbgModCreate) +# define RTDbgModCreateDeferred RT_MANGLER(RTDbgModCreateDeferred) +# define RTDbgModCreateFromImage RT_MANGLER(RTDbgModCreateFromImage) +# define RTDbgModCreateFromMap RT_MANGLER(RTDbgModCreateFromMap) +# define RTDbgModGetTag RT_MANGLER(RTDbgModGetTag) +# define RTDbgModImageSize RT_MANGLER(RTDbgModImageSize) +# define RTDbgModLineAdd RT_MANGLER(RTDbgModLineAdd) +# define RTDbgModLineByAddr RT_MANGLER(RTDbgModLineByAddr) +# define RTDbgModLineByAddrA RT_MANGLER(RTDbgModLineByAddrA) +# define RTDbgModLineByOrdinal RT_MANGLER(RTDbgModLineByOrdinal) +# define RTDbgModLineByOrdinalA RT_MANGLER(RTDbgModLineByOrdinalA) +# define RTDbgModLineCount RT_MANGLER(RTDbgModLineCount) +# define RTDbgModName RT_MANGLER(RTDbgModName) +# define RTDbgModRelease RT_MANGLER(RTDbgModRelease) +# define RTDbgModRetain RT_MANGLER(RTDbgModRetain) +# define RTDbgModRvaToSegOff RT_MANGLER(RTDbgModRvaToSegOff) +# define RTDbgModSegmentAdd RT_MANGLER(RTDbgModSegmentAdd) +# define RTDbgModSegmentByIndex RT_MANGLER(RTDbgModSegmentByIndex) +# define RTDbgModSegmentCount RT_MANGLER(RTDbgModSegmentCount) +# define RTDbgModSegmentRva RT_MANGLER(RTDbgModSegmentRva) +# define RTDbgModSegmentSize RT_MANGLER(RTDbgModSegmentSize) +# define RTDbgModSetTag RT_MANGLER(RTDbgModSetTag) +# define RTDbgModSymbolAdd RT_MANGLER(RTDbgModSymbolAdd) +# define RTDbgModSymbolByAddr RT_MANGLER(RTDbgModSymbolByAddr) +# define RTDbgModSymbolByAddrA RT_MANGLER(RTDbgModSymbolByAddrA) +# define RTDbgModSymbolByName RT_MANGLER(RTDbgModSymbolByName) +# define RTDbgModSymbolByNameA RT_MANGLER(RTDbgModSymbolByNameA) +# define RTDbgModSymbolByOrdinal RT_MANGLER(RTDbgModSymbolByOrdinal) +# define RTDbgModSymbolByOrdinalA RT_MANGLER(RTDbgModSymbolByOrdinalA) +# define RTDbgModSymbolCount RT_MANGLER(RTDbgModSymbolCount) +# define RTDbgSymbolAlloc RT_MANGLER(RTDbgSymbolAlloc) +# define RTDbgSymbolDup RT_MANGLER(RTDbgSymbolDup) +# define RTDbgSymbolFree RT_MANGLER(RTDbgSymbolFree) +# define RTDirClose RT_MANGLER(RTDirClose) +# define RTDirCreate RT_MANGLER(RTDirCreate) +# define RTDirCreateFullPath RT_MANGLER(RTDirCreateFullPath) +# define RTDirCreateTemp RT_MANGLER(RTDirCreateTemp) +# define RTDirCreateTempSecure RT_MANGLER(RTDirCreateTempSecure) +# define RTDirCreateUniqueNumbered RT_MANGLER(RTDirCreateUniqueNumbered) +# define RTDirExists RT_MANGLER(RTDirExists) +# define RTDirFlush RT_MANGLER(RTDirFlush) +# define RTDirFlushParent RT_MANGLER(RTDirFlushParent) +# define RTDirOpen RT_MANGLER(RTDirOpen) +# define RTDirOpenFiltered RT_MANGLER(RTDirOpenFiltered) +# define RTDirQueryInfo RT_MANGLER(RTDirQueryInfo) +# define RTDirRead RT_MANGLER(RTDirRead) +# define RTDirReadEx RT_MANGLER(RTDirReadEx) +# define RTDirRemove RT_MANGLER(RTDirRemove) +# define RTDirRemoveRecursive RT_MANGLER(RTDirRemoveRecursive) +# define RTDirRename RT_MANGLER(RTDirRename) +# define RTDirSetTimes RT_MANGLER(RTDirSetTimes) +# define RTDvmCreate RT_MANGLER(RTDvmCreate) +# define RTDvmRetain RT_MANGLER(RTDvmRetain) +# define RTDvmRelease RT_MANGLER(RTDvmRelease) +# define RTDvmMapOpen RT_MANGLER(RTDvmMapOpen) +# define RTDvmMapInitialize RT_MANGLER(RTDvmMapInitialize) +# define RTDvmMapGetFormat RT_MANGLER(RTDvmMapGetFormat) +# define RTDvmMapGetValidVolumes RT_MANGLER(RTDvmMapGetValidVolumes) +# define RTDvmMapGetMaxVolumes RT_MANGLER(RTDvmMapGetMaxVolumes) +# define RTDvmMapQueryBlockStatus RT_MANGLER(RTDvmMapQueryBlockStatus) +# define RTDvmMapQueryFirstVolume RT_MANGLER(RTDvmMapQueryFirstVolume) +# define RTDvmMapQueryNextVolume RT_MANGLER(RTDvmMapQueryNextVolume) +# define RTDvmVolumeRetain RT_MANGLER(RTDvmVolumeRetain) +# define RTDvmVolumeRelease RT_MANGLER(RTDvmVolumeRelease) +# define RTDvmVolumeGetSize RT_MANGLER(RTDvmVolumeGetSize) +# define RTDvmVolumeQueryName RT_MANGLER(RTDvmVolumeQueryName) +# define RTDvmVolumeGetType RT_MANGLER(RTDvmVolumeGetType) +# define RTDvmVolumeGetFlags RT_MANGLER(RTDvmVolumeGetFlags) +# define RTDvmVolumeRead RT_MANGLER(RTDvmVolumeRead) +# define RTDvmVolumeWrite RT_MANGLER(RTDvmVolumeWrite) +# define RTDvmVolumeSetQueryBlockStatusCallback RT_MANGLER(RTDvmVolumeSetQueryBlockStatusCallback) +# define RTDvmVolumeTypeGetDescr RT_MANGLER(RTDvmVolumeTypeGetDescr) +# define RTDvmVolumeCreateVfsFile RT_MANGLER(RTDvmVolumeCreateVfsFile) +# define RTEnvClone RT_MANGLER(RTEnvClone) +# define RTEnvCreate RT_MANGLER(RTEnvCreate) +# define RTEnvDestroy RT_MANGLER(RTEnvDestroy) +# define RTEnvDupEx RT_MANGLER(RTEnvDupEx) +# define RTEnvExist RT_MANGLER(RTEnvExist) +# define RTEnvExistEx RT_MANGLER(RTEnvExistEx) +# define RTEnvFreeUtf16Block RT_MANGLER(RTEnvFreeUtf16Block) +# define RTEnvGet RT_MANGLER(RTEnvGet) +# define RTEnvGetEx RT_MANGLER(RTEnvGetEx) +# define RTEnvGetExecEnvP RT_MANGLER(RTEnvGetExecEnvP) +# define RTEnvPut RT_MANGLER(RTEnvPut) +# define RTEnvPutEx RT_MANGLER(RTEnvPutEx) +# define RTEnvQueryUtf16Block RT_MANGLER(RTEnvQueryUtf16Block) +# define RTEnvSet RT_MANGLER(RTEnvSet) +# define RTEnvSetEx RT_MANGLER(RTEnvSetEx) +# define RTEnvUnset RT_MANGLER(RTEnvUnset) +# define RTEnvUnsetEx RT_MANGLER(RTEnvUnsetEx) +# define RTErrCOMGet RT_MANGLER(RTErrCOMGet) +# define RTErrConvertFromErrno RT_MANGLER(RTErrConvertFromErrno) +# define RTErrConvertToErrno RT_MANGLER(RTErrConvertToErrno) +# define RTErrGet RT_MANGLER(RTErrGet) +# define RTErrInfoAlloc RT_MANGLER(RTErrInfoAlloc) +# define RTErrInfoAllocEx RT_MANGLER(RTErrInfoAllocEx) +# define RTErrInfoFree RT_MANGLER(RTErrInfoFree) +# define RTErrInfoSet RT_MANGLER(RTErrInfoSet) +# define RTErrInfoSetF RT_MANGLER(RTErrInfoSetF) +# define RTErrInfoSetV RT_MANGLER(RTErrInfoSetV) +# define RTErrVarsAreEqual RT_MANGLER(RTErrVarsAreEqual) +# define RTErrVarsHaveChanged RT_MANGLER(RTErrVarsHaveChanged) +# define RTErrVarsRestore RT_MANGLER(RTErrVarsRestore) +# define RTErrVarsSave RT_MANGLER(RTErrVarsSave) +# define RTFileAioCtxAssociateWithFile RT_MANGLER(RTFileAioCtxAssociateWithFile) +# define RTFileAioCtxCreate RT_MANGLER(RTFileAioCtxCreate) +# define RTFileAioCtxDestroy RT_MANGLER(RTFileAioCtxDestroy) +# define RTFileAioCtxGetMaxReqCount RT_MANGLER(RTFileAioCtxGetMaxReqCount) +# define RTFileAioCtxSubmit RT_MANGLER(RTFileAioCtxSubmit) +# define RTFileAioCtxWait RT_MANGLER(RTFileAioCtxWait) +# define RTFileAioCtxWakeup RT_MANGLER(RTFileAioCtxWakeup) +# define RTFileAioGetLimits RT_MANGLER(RTFileAioGetLimits) +# define RTFileAioReqCancel RT_MANGLER(RTFileAioReqCancel) +# define RTFileAioReqCreate RT_MANGLER(RTFileAioReqCreate) +# define RTFileAioReqDestroy RT_MANGLER(RTFileAioReqDestroy) +# define RTFileAioReqGetRC RT_MANGLER(RTFileAioReqGetRC) +# define RTFileAioReqGetUser RT_MANGLER(RTFileAioReqGetUser) +# define RTFileAioReqPrepareFlush RT_MANGLER(RTFileAioReqPrepareFlush) +# define RTFileAioReqPrepareRead RT_MANGLER(RTFileAioReqPrepareRead) +# define RTFileAioReqPrepareWrite RT_MANGLER(RTFileAioReqPrepareWrite) +# define RTFileChangeLock RT_MANGLER(RTFileChangeLock) +# define RTFileClose RT_MANGLER(RTFileClose) +# define RTFileCopy RT_MANGLER(RTFileCopy) +# define RTFileCopyByHandles RT_MANGLER(RTFileCopyByHandles) +# define RTFileCopyByHandlesEx RT_MANGLER(RTFileCopyByHandlesEx) +# define RTFileCopyEx RT_MANGLER(RTFileCopyEx) +# define RTFileCreateTemp RT_MANGLER(RTFileCreateTemp) +# define RTFileCreateTempSecure RT_MANGLER(RTFileCreateTempSecure) +# define RTFileDelete RT_MANGLER(RTFileDelete) +# define RTFileExists RT_MANGLER(RTFileExists) +# define RTFileFlush RT_MANGLER(RTFileFlush) +# define RTFileFromNative RT_MANGLER(RTFileFromNative) +# define RTFileGetMaxSize RT_MANGLER(RTFileGetMaxSize) +# define RTFileGetMaxSizeEx RT_MANGLER(RTFileGetMaxSizeEx) +# define RTFileGetSize RT_MANGLER(RTFileGetSize) +# define RTFileIoCtl RT_MANGLER(RTFileIoCtl) +# define RTFileIsValid RT_MANGLER(RTFileIsValid) +# define RTFileLock RT_MANGLER(RTFileLock) +# define RTFileMove RT_MANGLER(RTFileMove) +# define RTFileOpen RT_MANGLER(RTFileOpen) +# define RTFileOpenBitBucket RT_MANGLER(RTFileOpenBitBucket) +# define RTFileOpenF RT_MANGLER(RTFileOpenF) +# define RTFileOpenV RT_MANGLER(RTFileOpenV) +# define RTFileQueryFsSizes RT_MANGLER(RTFileQueryFsSizes) +# define RTFileQueryInfo RT_MANGLER(RTFileQueryInfo) +# define RTFileQuerySize RT_MANGLER(RTFileQuerySize) +# define RTFileRead RT_MANGLER(RTFileRead) +# define RTFileReadAll RT_MANGLER(RTFileReadAll) +# define RTFileReadAllByHandle RT_MANGLER(RTFileReadAllByHandle) +# define RTFileReadAllByHandleEx RT_MANGLER(RTFileReadAllByHandleEx) +# define RTFileReadAllEx RT_MANGLER(RTFileReadAllEx) +# define RTFileReadAllFree RT_MANGLER(RTFileReadAllFree) +# define RTFileReadAt RT_MANGLER(RTFileReadAt) +# define RTFileRename RT_MANGLER(RTFileRename) +# define RTFileSeek RT_MANGLER(RTFileSeek) +# define RTFileSetForceFlags RT_MANGLER(RTFileSetForceFlags) +# define RTFileSetMode RT_MANGLER(RTFileSetMode) +# define RTFileSetSize RT_MANGLER(RTFileSetSize) +# define RTFileSetTimes RT_MANGLER(RTFileSetTimes) +# define RTFileTell RT_MANGLER(RTFileTell) +# define RTFileToNative RT_MANGLER(RTFileToNative) +# define RTFileUnlock RT_MANGLER(RTFileUnlock) +# define RTFileWrite RT_MANGLER(RTFileWrite) +# define RTFileWriteAt RT_MANGLER(RTFileWriteAt) +# define RTFilesystemVfsFromFile RT_MANGLER(RTFilesystemVfsFromFile) +# define RTFsQueryProperties RT_MANGLER(RTFsQueryProperties) +# define RTFsQuerySerial RT_MANGLER(RTFsQuerySerial) +# define RTFsQuerySizes RT_MANGLER(RTFsQuerySizes) +# define RTFsQueryType RT_MANGLER(RTFsQueryType) +# define RTFsTypeName RT_MANGLER(RTFsTypeName) +# define RTGetOpt RT_MANGLER(RTGetOpt) +# define RTGetOptArgvFree RT_MANGLER(RTGetOptArgvFree) +# define RTGetOptArgvFromString RT_MANGLER(RTGetOptArgvFromString) +# define RTGetOptArgvToString RT_MANGLER(RTGetOptArgvToString) +# define RTGetOptArgvToUtf16String RT_MANGLER(RTGetOptArgvToUtf16String) +# define RTGetOptFetchValue RT_MANGLER(RTGetOptFetchValue) +# define RTGetOptInit RT_MANGLER(RTGetOptInit) +# define RTGetOptPrintError RT_MANGLER(RTGetOptPrintError) +# define RTHandleClose RT_MANGLER(RTHandleClose) +# define RTHandleGetStandard RT_MANGLER(RTHandleGetStandard) +# define RTHandleTableAlloc RT_MANGLER(RTHandleTableAlloc) +# define RTHandleTableAllocWithCtx RT_MANGLER(RTHandleTableAllocWithCtx) +# define RTHandleTableCreate RT_MANGLER(RTHandleTableCreate) +# define RTHandleTableCreateEx RT_MANGLER(RTHandleTableCreateEx) +# define RTHandleTableDestroy RT_MANGLER(RTHandleTableDestroy) +# define RTHandleTableFree RT_MANGLER(RTHandleTableFree) +# define RTHandleTableFreeWithCtx RT_MANGLER(RTHandleTableFreeWithCtx) +# define RTHandleTableLookup RT_MANGLER(RTHandleTableLookup) +# define RTHandleTableLookupWithCtx RT_MANGLER(RTHandleTableLookupWithCtx) +# define RTHeapOffsetAlloc RT_MANGLER(RTHeapOffsetAlloc) +# define RTHeapOffsetAllocZ RT_MANGLER(RTHeapOffsetAllocZ) +# define RTHeapOffsetDump RT_MANGLER(RTHeapOffsetDump) +# define RTHeapOffsetFree RT_MANGLER(RTHeapOffsetFree) +# define RTHeapOffsetGetFreeSize RT_MANGLER(RTHeapOffsetGetFreeSize) +# define RTHeapOffsetGetHeapSize RT_MANGLER(RTHeapOffsetGetHeapSize) +# define RTHeapOffsetInit RT_MANGLER(RTHeapOffsetInit) +# define RTHeapOffsetSize RT_MANGLER(RTHeapOffsetSize) +# define RTHeapSimpleAlloc RT_MANGLER(RTHeapSimpleAlloc) +# define RTHeapSimpleAllocZ RT_MANGLER(RTHeapSimpleAllocZ) +# define RTHeapSimpleDump RT_MANGLER(RTHeapSimpleDump) +# define RTHeapSimpleFree RT_MANGLER(RTHeapSimpleFree) +# define RTHeapSimpleGetFreeSize RT_MANGLER(RTHeapSimpleGetFreeSize) +# define RTHeapSimpleGetHeapSize RT_MANGLER(RTHeapSimpleGetHeapSize) +# define RTHeapSimpleInit RT_MANGLER(RTHeapSimpleInit) +# define RTHeapSimpleRelocate RT_MANGLER(RTHeapSimpleRelocate) +# define RTHeapSimpleSize RT_MANGLER(RTHeapSimpleSize) +# define RTIsoFsClose RT_MANGLER(RTIsoFsClose) +# define RTIsoFsExtractFile RT_MANGLER(RTIsoFsExtractFile) +# define RTIsoFsGetFileInfo RT_MANGLER(RTIsoFsGetFileInfo) +# define RTIsoFsOpen RT_MANGLER(RTIsoFsOpen) +# define RTLatin1CalcUtf16Len RT_MANGLER(RTLatin1CalcUtf16Len) +# define RTLatin1CalcUtf16LenEx RT_MANGLER(RTLatin1CalcUtf16LenEx) +# define RTLatin1CalcUtf8Len RT_MANGLER(RTLatin1CalcUtf8Len) +# define RTLatin1CalcUtf8LenEx RT_MANGLER(RTLatin1CalcUtf8LenEx) +# define RTLatin1ToUtf16ExTag RT_MANGLER(RTLatin1ToUtf16ExTag) +# define RTLatin1ToUtf16Tag RT_MANGLER(RTLatin1ToUtf16Tag) +# define RTLatin1ToUtf8ExTag RT_MANGLER(RTLatin1ToUtf8ExTag) +# define RTLatin1ToUtf8Tag RT_MANGLER(RTLatin1ToUtf8Tag) +# define RTLdrClose RT_MANGLER(RTLdrClose) +# define RTLdrEnumDbgInfo RT_MANGLER(RTLdrEnumDbgInfo) +# define RTLdrEnumSegments RT_MANGLER(RTLdrEnumSegments) +# define RTLdrEnumSymbols RT_MANGLER(RTLdrEnumSymbols) +# define RTLdrGetBits RT_MANGLER(RTLdrGetBits) +# define RTLdrGetSuff RT_MANGLER(RTLdrGetSuff) +# define RTLdrGetSymbol RT_MANGLER(RTLdrGetSymbol) +# define RTLdrGetSymbolEx RT_MANGLER(RTLdrGetSymbolEx) +# define RTLdrIsLoadable RT_MANGLER(RTLdrIsLoadable) +# define RTLdrLinkAddressToRva RT_MANGLER(RTLdrLinkAddressToRva) +# define RTLdrLinkAddressToSegOffset RT_MANGLER(RTLdrLinkAddressToSegOffset) +# define RTLdrLoad RT_MANGLER(RTLdrLoad) +# define RTLdrLoadAppPriv RT_MANGLER(RTLdrLoadAppPriv) +# define RTLdrLoadEx RT_MANGLER(RTLdrLoadEx) +# define RTLdrOpen RT_MANGLER(RTLdrOpen) +# define RTLdrOpenkLdr RT_MANGLER(RTLdrOpenkLdr) +# define RTLdrRelocate RT_MANGLER(RTLdrRelocate) +# define RTLdrRvaToSegOffset RT_MANGLER(RTLdrRvaToSegOffset) +# define RTLdrSegOffsetToRva RT_MANGLER(RTLdrSegOffsetToRva) +# define RTLdrSize RT_MANGLER(RTLdrSize) +# define RTLinuxFindDevicePath RT_MANGLER(RTLinuxFindDevicePath) +# define RTLinuxFindDevicePathV RT_MANGLER(RTLinuxFindDevicePathV) +# define RTLinuxSysFsClose RT_MANGLER(RTLinuxSysFsClose) +# define RTLinuxSysFsExists RT_MANGLER(RTLinuxSysFsExists) +# define RTLinuxSysFsExistsV RT_MANGLER(RTLinuxSysFsExistsV) +# define RTLinuxSysFsGetLinkDest RT_MANGLER(RTLinuxSysFsGetLinkDest) +# define RTLinuxSysFsGetLinkDestV RT_MANGLER(RTLinuxSysFsGetLinkDestV) +# define RTLinuxSysFsOpen RT_MANGLER(RTLinuxSysFsOpen) +# define RTLinuxSysFsOpenV RT_MANGLER(RTLinuxSysFsOpenV) +# define RTLinuxSysFsReadDevNumFile RT_MANGLER(RTLinuxSysFsReadDevNumFile) +# define RTLinuxSysFsReadDevNumFileV RT_MANGLER(RTLinuxSysFsReadDevNumFileV) +# define RTLinuxSysFsReadFile RT_MANGLER(RTLinuxSysFsReadFile) +# define RTLinuxSysFsReadIntFile RT_MANGLER(RTLinuxSysFsReadIntFile) +# define RTLinuxSysFsReadIntFileV RT_MANGLER(RTLinuxSysFsReadIntFileV) +# define RTLinuxSysFsReadStr RT_MANGLER(RTLinuxSysFsReadStr) +# define RTLinuxSysFsReadStrFile RT_MANGLER(RTLinuxSysFsReadStrFile) +# define RTLinuxSysFsReadStrFileV RT_MANGLER(RTLinuxSysFsReadStrFileV) +# define RTLockValidatorClassAddPriorClass RT_MANGLER(RTLockValidatorClassAddPriorClass) +# define RTLockValidatorClassCreate RT_MANGLER(RTLockValidatorClassCreate) +# define RTLockValidatorClassCreateEx RT_MANGLER(RTLockValidatorClassCreateEx) +# define RTLockValidatorClassCreateExV RT_MANGLER(RTLockValidatorClassCreateExV) +# define RTLockValidatorClassCreateUnique RT_MANGLER(RTLockValidatorClassCreateUnique) +# define RTLockValidatorClassEnforceStrictReleaseOrder RT_MANGLER(RTLockValidatorClassEnforceStrictReleaseOrder) +# define RTLockValidatorClassFindForSrcPos RT_MANGLER(RTLockValidatorClassFindForSrcPos) +# define RTLockValidatorClassForSrcPos RT_MANGLER(RTLockValidatorClassForSrcPos) +# define RTLockValidatorClassRelease RT_MANGLER(RTLockValidatorClassRelease) +# define RTLockValidatorClassRetain RT_MANGLER(RTLockValidatorClassRetain) +# define RTLockValidatorHoldsLocksInClass RT_MANGLER(RTLockValidatorHoldsLocksInClass) +# define RTLockValidatorHoldsLocksInSubClass RT_MANGLER(RTLockValidatorHoldsLocksInSubClass) +# define RTLockValidatorIsBlockedThreadInValidator RT_MANGLER(RTLockValidatorIsBlockedThreadInValidator) +# define RTLockValidatorIsEnabled RT_MANGLER(RTLockValidatorIsEnabled) +# define RTLockValidatorIsQuiet RT_MANGLER(RTLockValidatorIsQuiet) +# define RTLockValidatorMayPanic RT_MANGLER(RTLockValidatorMayPanic) +# define RTLockValidatorQueryBlocking RT_MANGLER(RTLockValidatorQueryBlocking) +# define RTLockValidatorReadLockDec RT_MANGLER(RTLockValidatorReadLockDec) +# define RTLockValidatorReadLockGetCount RT_MANGLER(RTLockValidatorReadLockGetCount) +# define RTLockValidatorReadLockInc RT_MANGLER(RTLockValidatorReadLockInc) +# define RTLockValidatorRecExclCheckBlocking RT_MANGLER(RTLockValidatorRecExclCheckBlocking) +# define RTLockValidatorRecExclCheckOrder RT_MANGLER(RTLockValidatorRecExclCheckOrder) +# define RTLockValidatorRecExclCheckOrderAndBlocking RT_MANGLER(RTLockValidatorRecExclCheckOrderAndBlocking) +# define RTLockValidatorRecExclCreate RT_MANGLER(RTLockValidatorRecExclCreate) +# define RTLockValidatorRecExclCreateV RT_MANGLER(RTLockValidatorRecExclCreateV) +# define RTLockValidatorRecExclDelete RT_MANGLER(RTLockValidatorRecExclDelete) +# define RTLockValidatorRecExclDestroy RT_MANGLER(RTLockValidatorRecExclDestroy) +# define RTLockValidatorRecExclInit RT_MANGLER(RTLockValidatorRecExclInit) +# define RTLockValidatorRecExclInitV RT_MANGLER(RTLockValidatorRecExclInitV) +# define RTLockValidatorRecExclRecursion RT_MANGLER(RTLockValidatorRecExclRecursion) +# define RTLockValidatorRecExclRecursionMixed RT_MANGLER(RTLockValidatorRecExclRecursionMixed) +# define RTLockValidatorRecExclReleaseOwner RT_MANGLER(RTLockValidatorRecExclReleaseOwner) +# define RTLockValidatorRecExclReleaseOwnerUnchecked RT_MANGLER(RTLockValidatorRecExclReleaseOwnerUnchecked) +# define RTLockValidatorRecExclSetOwner RT_MANGLER(RTLockValidatorRecExclSetOwner) +# define RTLockValidatorRecExclSetSubClass RT_MANGLER(RTLockValidatorRecExclSetSubClass) +# define RTLockValidatorRecExclUnwind RT_MANGLER(RTLockValidatorRecExclUnwind) +# define RTLockValidatorRecExclUnwindMixed RT_MANGLER(RTLockValidatorRecExclUnwindMixed) +# define RTLockValidatorRecMakeSiblings RT_MANGLER(RTLockValidatorRecMakeSiblings) +# define RTLockValidatorRecSharedAddOwner RT_MANGLER(RTLockValidatorRecSharedAddOwner) +# define RTLockValidatorRecSharedCheckAndRelease RT_MANGLER(RTLockValidatorRecSharedCheckAndRelease) +# define RTLockValidatorRecSharedCheckBlocking RT_MANGLER(RTLockValidatorRecSharedCheckBlocking) +# define RTLockValidatorRecSharedCheckOrder RT_MANGLER(RTLockValidatorRecSharedCheckOrder) +# define RTLockValidatorRecSharedCheckOrderAndBlocking RT_MANGLER(RTLockValidatorRecSharedCheckOrderAndBlocking) +# define RTLockValidatorRecSharedCheckSignaller RT_MANGLER(RTLockValidatorRecSharedCheckSignaller) +# define RTLockValidatorRecSharedDelete RT_MANGLER(RTLockValidatorRecSharedDelete) +# define RTLockValidatorRecSharedInit RT_MANGLER(RTLockValidatorRecSharedInit) +# define RTLockValidatorRecSharedInitV RT_MANGLER(RTLockValidatorRecSharedInitV) +# define RTLockValidatorRecSharedIsOwner RT_MANGLER(RTLockValidatorRecSharedIsOwner) +# define RTLockValidatorRecSharedRemoveOwner RT_MANGLER(RTLockValidatorRecSharedRemoveOwner) +# define RTLockValidatorRecSharedResetOwner RT_MANGLER(RTLockValidatorRecSharedResetOwner) +# define RTLockValidatorRecSharedSetSubClass RT_MANGLER(RTLockValidatorRecSharedSetSubClass) +# define RTLockValidatorSetEnabled RT_MANGLER(RTLockValidatorSetEnabled) +# define RTLockValidatorSetMayPanic RT_MANGLER(RTLockValidatorSetMayPanic) +# define RTLockValidatorSetQuiet RT_MANGLER(RTLockValidatorSetQuiet) +# define RTLockValidatorWriteLockDec RT_MANGLER(RTLockValidatorWriteLockDec) +# define RTLockValidatorWriteLockGetCount RT_MANGLER(RTLockValidatorWriteLockGetCount) +# define RTLockValidatorWriteLockInc RT_MANGLER(RTLockValidatorWriteLockInc) +# define RTLogBackdoorPrintf RT_MANGLER(RTLogBackdoorPrintf) /* r0drv-guest */ +# define RTLogBackdoorPrintfV RT_MANGLER(RTLogBackdoorPrintfV) /* r0drv-guest */ +# define RTLogCalcSizeForR0 RT_MANGLER(RTLogCalcSizeForR0) +# define RTLogCloneRC RT_MANGLER(RTLogCloneRC) +# define RTLogComPrintf RT_MANGLER(RTLogComPrintf) +# define RTLogComPrintfV RT_MANGLER(RTLogComPrintfV) +# define RTLogCopyGroupsAndFlagsForR0 RT_MANGLER(RTLogCopyGroupsAndFlagsForR0) +# define RTLogCreate RT_MANGLER(RTLogCreate) +# define RTLogCreateEx RT_MANGLER(RTLogCreateEx) +# define RTLogCreateExV RT_MANGLER(RTLogCreateExV) +# define RTLogCreateForR0 RT_MANGLER(RTLogCreateForR0) +# define RTLogDefaultInit RT_MANGLER(RTLogDefaultInit) +# define RTLogDefaultInstance RT_MANGLER(RTLogDefaultInstance) +# define RTLogDestinations RT_MANGLER(RTLogDestinations) +# define RTLogDestroy RT_MANGLER(RTLogDestroy) +# define RTLogFlags RT_MANGLER(RTLogFlags) +# define RTLogFlush RT_MANGLER(RTLogFlush) +# define RTLogFlushRC RT_MANGLER(RTLogFlushRC) +# define RTLogFlushR0 RT_MANGLER(RTLogFlushR0) +# define RTLogFlushToLogger RT_MANGLER(RTLogFlushToLogger) +# define RTLogFormatV RT_MANGLER(RTLogFormatV) +# define RTLogGetDefaultInstance RT_MANGLER(RTLogGetDefaultInstance) +# define RTLogGetDestinations RT_MANGLER(RTLogGetDestinations) +# define RTLogGetFlags RT_MANGLER(RTLogGetFlags) +# define RTLogGetGroupSettings RT_MANGLER(RTLogGetGroupSettings) +# define RTLogGroupSettings RT_MANGLER(RTLogGroupSettings) +# define RTLogLogger RT_MANGLER(RTLogLogger) +# define RTLogLoggerEx RT_MANGLER(RTLogLoggerEx) +# define RTLogLoggerExV RT_MANGLER(RTLogLoggerExV) +# define RTLogLoggerV RT_MANGLER(RTLogLoggerV) +# define RTLogPrintf RT_MANGLER(RTLogPrintf) +# define RTLogPrintfV RT_MANGLER(RTLogPrintfV) +# define RTLogRelDefaultInstance RT_MANGLER(RTLogRelDefaultInstance) +# define RTLogRelLogger RT_MANGLER(RTLogRelLogger) +# define RTLogRelLoggerV RT_MANGLER(RTLogRelLoggerV) +# define RTLogRelPrintf RT_MANGLER(RTLogRelPrintf) +# define RTLogRelPrintfV RT_MANGLER(RTLogRelPrintfV) +# define RTLogRelSetBuffering RT_MANGLER(RTLogRelSetBuffering) +# define RTLogRelSetDefaultInstance RT_MANGLER(RTLogRelSetDefaultInstance) +# define RTLogSetBuffering RT_MANGLER(RTLogSetBuffering) +# define RTLogSetCustomPrefixCallback RT_MANGLER(RTLogSetCustomPrefixCallback) +# define RTLogSetCustomPrefixCallbackForR0 RT_MANGLER(RTLogSetCustomPrefixCallbackForR0) +# define RTLogSetDefaultInstance RT_MANGLER(RTLogSetDefaultInstance) +# define RTLogSetDefaultInstanceThread RT_MANGLER(RTLogSetDefaultInstanceThread) /* r0drv */ +# define RTLogSetGroupLimit RT_MANGLER(RTLogSetGroupLimit) +# define RTLogWriteCom RT_MANGLER(RTLogWriteCom) +# define RTLogWriteCom RT_MANGLER(RTLogWriteCom) +# define RTLogWriteDebugger RT_MANGLER(RTLogWriteDebugger) +# define RTLogWriteStdErr RT_MANGLER(RTLogWriteStdErr) +# define RTLogWriteStdOut RT_MANGLER(RTLogWriteStdOut) +# define RTLogWriteUser RT_MANGLER(RTLogWriteUser) +# define RTManifestCreate RT_MANGLER(RTManifestCreate) +# define RTManifestDup RT_MANGLER(RTManifestDup) +# define RTManifestEntryAdd RT_MANGLER(RTManifestEntryAdd) +# define RTManifestEntryAddIoStream RT_MANGLER(RTManifestEntryAddIoStream) +# define RTManifestEntryAddPassthruIoStream RT_MANGLER(RTManifestEntryAddPassthruIoStream) +# define RTManifestEntryExists RT_MANGLER(RTManifestEntryExists) +# define RTManifestEntryRemove RT_MANGLER(RTManifestEntryRemove) +# define RTManifestEntryQueryAttr RT_MANGLER(RTManifestEntryQueryAttr) +# define RTManifestEntrySetAttr RT_MANGLER(RTManifestEntrySetAttr) +# define RTManifestEntryUnsetAttr RT_MANGLER(RTManifestEntryUnsetAttr) +# define RTManifestEquals RT_MANGLER(RTManifestEquals) +# define RTManifestEqualsEx RT_MANGLER(RTManifestEqualsEx) +# define RTManifestPtIosAddEntryNow RT_MANGLER(RTManifestPtIosAddEntryNow) +# define RTManifestQueryAttr RT_MANGLER(RTManifestQueryAttr) +# define RTManifestReadStandard RT_MANGLER(RTManifestReadStandard) +# define RTManifestReadStandardEx RT_MANGLER(RTManifestReadStandardEx) +# define RTManifestReadStandardFromFile RT_MANGLER(RTManifestReadStandardFromFile) +# define RTManifestRelease RT_MANGLER(RTManifestRelease) +# define RTManifestRetain RT_MANGLER(RTManifestRetain) +# define RTManifestSetAttr RT_MANGLER(RTManifestSetAttr) +# define RTManifestUnsetAttr RT_MANGLER(RTManifestUnsetAttr) +# define RTManifestVerify RT_MANGLER(RTManifestVerify) +# define RTManifestVerifyFiles RT_MANGLER(RTManifestVerifyFiles) +# define RTManifestVerifyFilesBuf RT_MANGLER(RTManifestVerifyFilesBuf) +# define RTManifestWriteFiles RT_MANGLER(RTManifestWriteFiles) +# define RTManifestWriteFilesBuf RT_MANGLER(RTManifestWriteFilesBuf) +# define RTManifestWriteStandard RT_MANGLER(RTManifestWriteStandard) +# define RTManifestWriteStandardToFile RT_MANGLER(RTManifestWriteStandardToFile) +# define RTMd5 RT_MANGLER(RTMd5) +# define RTMd5Final RT_MANGLER(RTMd5Final) +# define RTMd5FromString RT_MANGLER(RTMd5FromString) +# define RTMd5Init RT_MANGLER(RTMd5Init) +# define RTMd5ToString RT_MANGLER(RTMd5ToString) +# define RTMd5Update RT_MANGLER(RTMd5Update) +# define RTMemAllocExTag RT_MANGLER(RTMemAllocExTag) /* r0drv */ +# define RTMemAllocTag RT_MANGLER(RTMemAllocTag) +# define RTMemAllocVarTag RT_MANGLER(RTMemAllocVarTag) +# define RTMemAllocZTag RT_MANGLER(RTMemAllocZTag) +# define RTMemAllocZVarTag RT_MANGLER(RTMemAllocZVarTag) +# define RTMemCacheAlloc RT_MANGLER(RTMemCacheAlloc) +# define RTMemCacheAllocEx RT_MANGLER(RTMemCacheAllocEx) +# define RTMemCacheCreate RT_MANGLER(RTMemCacheCreate) +# define RTMemCacheDestroy RT_MANGLER(RTMemCacheDestroy) +# define RTMemCacheFree RT_MANGLER(RTMemCacheFree) +# define RTMemContAlloc RT_MANGLER(RTMemContAlloc) /* r0drv */ +# define RTMemContFree RT_MANGLER(RTMemContFree) /* r0drv */ +# define RTMemDump RT_MANGLER(RTMemDump) +# define RTMemDupExTag RT_MANGLER(RTMemDupExTag) +# define RTMemDupTag RT_MANGLER(RTMemDupTag) +# define RTMemEfAlloc RT_MANGLER(RTMemEfAlloc) +# define RTMemEfAllocNP RT_MANGLER(RTMemEfAllocNP) +# define RTMemEfAllocVar RT_MANGLER(RTMemEfAllocVar) +# define RTMemEfAllocVarNP RT_MANGLER(RTMemEfAllocVarNP) +# define RTMemEfAllocZ RT_MANGLER(RTMemEfAllocZ) +# define RTMemEfAllocZNP RT_MANGLER(RTMemEfAllocZNP) +# define RTMemEfAllocZVar RT_MANGLER(RTMemEfAllocZVar) +# define RTMemEfAllocZVarNP RT_MANGLER(RTMemEfAllocZVarNP) +# define RTMemEfDup RT_MANGLER(RTMemEfDup) +# define RTMemEfDupEx RT_MANGLER(RTMemEfDupEx) +# define RTMemEfDupExNP RT_MANGLER(RTMemEfDupExNP) +# define RTMemEfDupNP RT_MANGLER(RTMemEfDupNP) +# define RTMemEfFree RT_MANGLER(RTMemEfFree) +# define RTMemEfFreeNP RT_MANGLER(RTMemEfFreeNP) +# define RTMemEfRealloc RT_MANGLER(RTMemEfRealloc) +# define RTMemEfReallocNP RT_MANGLER(RTMemEfReallocNP) +# define RTMemEfTmpAlloc RT_MANGLER(RTMemEfTmpAlloc) +# define RTMemEfTmpAllocNP RT_MANGLER(RTMemEfTmpAllocNP) +# define RTMemEfTmpAllocZ RT_MANGLER(RTMemEfTmpAllocZ) +# define RTMemEfTmpAllocZNP RT_MANGLER(RTMemEfTmpAllocZNP) +# define RTMemEfTmpFree RT_MANGLER(RTMemEfTmpFree) +# define RTMemEfTmpFreeNP RT_MANGLER(RTMemEfTmpFreeNP) +# define RTMemExecAllocTag RT_MANGLER(RTMemExecAllocTag) +# define RTMemExecFree RT_MANGLER(RTMemExecFree) +# define RTMemFree RT_MANGLER(RTMemFree) +# define RTMemFreeEx RT_MANGLER(RTMemFreeEx) /* r0drv */ +# define RTMemPageAllocTag RT_MANGLER(RTMemPageAllocTag) +# define RTMemPageAllocZTag RT_MANGLER(RTMemPageAllocZTag) +# define RTMemPageFree RT_MANGLER(RTMemPageFree) +# define RTMemPoolAlloc RT_MANGLER(RTMemPoolAlloc) +# define RTMemPoolAllocZ RT_MANGLER(RTMemPoolAllocZ) +# define RTMemPoolCreate RT_MANGLER(RTMemPoolCreate) +# define RTMemPoolDestroy RT_MANGLER(RTMemPoolDestroy) +# define RTMemPoolDup RT_MANGLER(RTMemPoolDup) +# define RTMemPoolDupEx RT_MANGLER(RTMemPoolDupEx) +# define RTMemPoolFree RT_MANGLER(RTMemPoolFree) +# define RTMemPoolRealloc RT_MANGLER(RTMemPoolRealloc) +# define RTMemPoolRefCount RT_MANGLER(RTMemPoolRefCount) +# define RTMemPoolRelease RT_MANGLER(RTMemPoolRelease) +# define RTMemPoolRetain RT_MANGLER(RTMemPoolRetain) +# define RTMemProtect RT_MANGLER(RTMemProtect) +# define RTMemReallocTag RT_MANGLER(RTMemReallocTag) +# define RTMemTmpAllocTag RT_MANGLER(RTMemTmpAllocTag) +# define RTMemTmpAllocZTag RT_MANGLER(RTMemTmpAllocZTag) +# define RTMemTmpFree RT_MANGLER(RTMemTmpFree) +# define RTMemTrackerDumpAllToFile RT_MANGLER(RTMemTrackerDumpAllToFile) +# define RTMemTrackerDumpAllToLog RT_MANGLER(RTMemTrackerDumpAllToLog) +# define RTMemTrackerDumpAllToLogRel RT_MANGLER(RTMemTrackerDumpAllToLogRel) +# define RTMemTrackerDumpAllToStdErr RT_MANGLER(RTMemTrackerDumpAllToStdErr) +# define RTMemTrackerDumpAllToStdOut RT_MANGLER(RTMemTrackerDumpAllToStdOut) +# define RTMemTrackerDumpStatsToFile RT_MANGLER(RTMemTrackerDumpStatsToFile) +# define RTMemTrackerDumpStatsToLog RT_MANGLER(RTMemTrackerDumpStatsToLog) +# define RTMemTrackerDumpStatsToLogRel RT_MANGLER(RTMemTrackerDumpStatsToLogRel) +# define RTMemTrackerDumpStatsToStdErr RT_MANGLER(RTMemTrackerDumpStatsToStdErr) +# define RTMemTrackerDumpStatsToStdOut RT_MANGLER(RTMemTrackerDumpStatsToStdOut) +# define RTMemTrackerHdrAlloc RT_MANGLER(RTMemTrackerHdrAlloc) +# define RTMemTrackerHdrFree RT_MANGLER(RTMemTrackerHdrFree) +# define RTMemTrackerHdrReallocDone RT_MANGLER(RTMemTrackerHdrReallocDone) +# define RTMemTrackerHdrReallocPrep RT_MANGLER(RTMemTrackerHdrReallocPrep) +# define RTMemWipeThoroughly RT_MANGLER(RTMemWipeThoroughly) +# define RTMpCpuId RT_MANGLER(RTMpCpuId) +# define RTMpCpuIdFromSetIndex RT_MANGLER(RTMpCpuIdFromSetIndex) +# define RTMpCpuIdToSetIndex RT_MANGLER(RTMpCpuIdToSetIndex) +# define RTMpGetArraySize RT_MANGLER(RTMpGetArraySize) +# define RTMpGetCount RT_MANGLER(RTMpGetCount) +# define RTMpGetCurFrequency RT_MANGLER(RTMpGetCurFrequency) +# define RTMpGetDescription RT_MANGLER(RTMpGetDescription) +# define RTMpGetMaxCpuId RT_MANGLER(RTMpGetMaxCpuId) +# define RTMpGetMaxFrequency RT_MANGLER(RTMpGetMaxFrequency) +# define RTMpGetOnlineCount RT_MANGLER(RTMpGetOnlineCount) +# define RTMpGetOnlineSet RT_MANGLER(RTMpGetOnlineSet) +# define RTMpGetPresentCount RT_MANGLER(RTMpGetPresentCount) +# define RTMpGetPresentSet RT_MANGLER(RTMpGetPresentSet) +# define RTMpGetSet RT_MANGLER(RTMpGetSet) +# define RTMpIsCpuOnline RT_MANGLER(RTMpIsCpuOnline) +# define RTMpIsCpuPossible RT_MANGLER(RTMpIsCpuPossible) /* r0drv */ +# define RTMpIsCpuPresent RT_MANGLER(RTMpIsCpuPresent) +# define RTMpIsCpuWorkPending RT_MANGLER(RTMpIsCpuWorkPending) +# define RTMpNotificationDeregister RT_MANGLER(RTMpNotificationDeregister) /* r0drv */ +# define RTMpNotificationRegister RT_MANGLER(RTMpNotificationRegister) /* r0drv */ +# define RTMpOnAll RT_MANGLER(RTMpOnAll) /* r0drv */ +# define RTMpOnOthers RT_MANGLER(RTMpOnOthers) /* r0drv */ +# define RTMpOnSpecific RT_MANGLER(RTMpOnSpecific) /* r0drv */ +# define RTMpPokeCpu RT_MANGLER(RTMpPokeCpu) /* r0drv */ +# define RTMsgError RT_MANGLER(RTMsgError) +# define RTMsgErrorExit RT_MANGLER(RTMsgErrorExit) +# define RTMsgErrorExitV RT_MANGLER(RTMsgErrorExitV) +# define RTMsgErrorRc RT_MANGLER(RTMsgErrorRc) +# define RTMsgErrorRcV RT_MANGLER(RTMsgErrorRcV) +# define RTMsgErrorV RT_MANGLER(RTMsgErrorV) +# define RTMsgInfo RT_MANGLER(RTMsgInfo) +# define RTMsgInfoV RT_MANGLER(RTMsgInfoV) +# define RTMsgInitFailure RT_MANGLER(RTMsgInitFailure) +# define RTMsgSetProgName RT_MANGLER(RTMsgSetProgName) +# define RTMsgWarning RT_MANGLER(RTMsgWarning) +# define RTMsgWarningV RT_MANGLER(RTMsgWarningV) +# define RTNetIPv4AddDataChecksum RT_MANGLER(RTNetIPv4AddDataChecksum) +# define RTNetIPv4AddTCPChecksum RT_MANGLER(RTNetIPv4AddTCPChecksum) +# define RTNetIPv4AddUDPChecksum RT_MANGLER(RTNetIPv4AddUDPChecksum) +# define RTNetIPv4FinalizeChecksum RT_MANGLER(RTNetIPv4FinalizeChecksum) +# define RTNetIPv4HdrChecksum RT_MANGLER(RTNetIPv4HdrChecksum) +# define RTNetIPv4IsDHCPValid RT_MANGLER(RTNetIPv4IsDHCPValid) +# define RTNetIPv4IsHdrValid RT_MANGLER(RTNetIPv4IsHdrValid) +# define RTNetIPv4IsTCPSizeValid RT_MANGLER(RTNetIPv4IsTCPSizeValid) +# define RTNetIPv4IsTCPValid RT_MANGLER(RTNetIPv4IsTCPValid) +# define RTNetIPv4IsUDPSizeValid RT_MANGLER(RTNetIPv4IsUDPSizeValid) +# define RTNetIPv4IsUDPValid RT_MANGLER(RTNetIPv4IsUDPValid) +# define RTNetIPv4PseudoChecksum RT_MANGLER(RTNetIPv4PseudoChecksum) +# define RTNetIPv4PseudoChecksumBits RT_MANGLER(RTNetIPv4PseudoChecksumBits) +# define RTNetIPv4TCPChecksum RT_MANGLER(RTNetIPv4TCPChecksum) +# define RTNetIPv4UDPChecksum RT_MANGLER(RTNetIPv4UDPChecksum) +# define RTNetIPv6PseudoChecksum RT_MANGLER(RTNetIPv6PseudoChecksum) +# define RTNetIPv6PseudoChecksumBits RT_MANGLER(RTNetIPv6PseudoChecksumBits) +# define RTNetIPv6PseudoChecksumEx RT_MANGLER(RTNetIPv6PseudoChecksumEx) +# define RTNetTCPChecksum RT_MANGLER(RTNetTCPChecksum) +# define RTNetUDPChecksum RT_MANGLER(RTNetUDPChecksum) +# define RTNetIsIPv4AddrStr RT_MANGLER(RTNetIsIPv4AddrStr) +# define RTNetIsIPv6AddrStr RT_MANGLER(RTNetIsIPv6AddrStr) +# define RTOnceSlow RT_MANGLER(RTOnceSlow) +# define RTOnceReset RT_MANGLER(RTOnceReset) +# define RTPathAbs RT_MANGLER(RTPathAbs) +# define RTPathAbsDup RT_MANGLER(RTPathAbsDup) +# define RTPathAbsEx RT_MANGLER(RTPathAbsEx) +# define RTPathAbsExDup RT_MANGLER(RTPathAbsExDup) +# define RTPathAppDocs RT_MANGLER(RTPathAppDocs) +# define RTPathAppend RT_MANGLER(RTPathAppend) +# define RTPathAppendEx RT_MANGLER(RTPathAppendEx) +# define RTPathAppPrivateArch RT_MANGLER(RTPathAppPrivateArch) +# define RTPathAppPrivateArchTop RT_MANGLER(RTPathAppPrivateArchTop) +# define RTPathAppPrivateNoArch RT_MANGLER(RTPathAppPrivateNoArch) +# define RTPathChangeToDosSlashes RT_MANGLER(RTPathChangeToDosSlashes) +# define RTPathChangeToUnixSlashes RT_MANGLER(RTPathChangeToUnixSlashes) +# define RTPathCompare RT_MANGLER(RTPathCompare) +# define RTPathCopyComponents RT_MANGLER(RTPathCopyComponents) +# define RTPathCountComponents RT_MANGLER(RTPathCountComponents) +# define RTPathExecDir RT_MANGLER(RTPathExecDir) +# define RTPathExists RT_MANGLER(RTPathExists) +# define RTPathExistsEx RT_MANGLER(RTPathExistsEx) +# define RTPathExt RT_MANGLER(RTPathExt) +# define RTPathFilename RT_MANGLER(RTPathFilename) +# define RTPathGetCurrent RT_MANGLER(RTPathGetCurrent) +# define RTPathGetMode RT_MANGLER(RTPathGetMode) +# define RTPathHasExt RT_MANGLER(RTPathHasExt) +# define RTPathHasPath RT_MANGLER(RTPathHasPath) +# define RTPathJoin RT_MANGLER(RTPathJoin) +# define RTPathJoinA RT_MANGLER(RTPathJoinA) +# define RTPathJoinEx RT_MANGLER(RTPathJoinEx) +# define RTPathParse RT_MANGLER(RTPathParse) +# define RTPathQueryInfo RT_MANGLER(RTPathQueryInfo) +# define RTPathQueryInfoEx RT_MANGLER(RTPathQueryInfoEx) +# define RTPathReal RT_MANGLER(RTPathReal) +# define RTPathRealDup RT_MANGLER(RTPathRealDup) +# define RTPathRename RT_MANGLER(RTPathRename) +# define RTPathSetCurrent RT_MANGLER(RTPathSetCurrent) +# define RTPathSetMode RT_MANGLER(RTPathSetMode) /* not-win */ +# define RTPathSetOwner RT_MANGLER(RTPathSetOwner) /* not-win */ +# define RTPathSetOwnerEx RT_MANGLER(RTPathSetOwnerEx) /* not-win */ +# define RTPathSetTimes RT_MANGLER(RTPathSetTimes) +# define RTPathSetTimesEx RT_MANGLER(RTPathSetTimesEx) +# define RTPathSharedLibs RT_MANGLER(RTPathSharedLibs) +# define RTPathStartsWith RT_MANGLER(RTPathStartsWith) +# define RTPathStartsWithRoot RT_MANGLER(RTPathStartsWithRoot) +# define RTPathStripExt RT_MANGLER(RTPathStripExt) +# define RTPathStripFilename RT_MANGLER(RTPathStripFilename) +# define RTPathStripTrailingSlash RT_MANGLER(RTPathStripTrailingSlash) +# define RTPathTemp RT_MANGLER(RTPathTemp) +# define RTPathTraverseList RT_MANGLER(RTPathTraverseList) +# define RTPathUnlink RT_MANGLER(RTPathUnlink) +# define RTPathUserDocuments RT_MANGLER(RTPathUserDocuments) +# define RTPathUserHome RT_MANGLER(RTPathUserHome) +# define RTPipeClose RT_MANGLER(RTPipeClose) +# define RTPipeCreate RT_MANGLER(RTPipeCreate) +# define RTPipeFlush RT_MANGLER(RTPipeFlush) +# define RTPipeFromNative RT_MANGLER(RTPipeFromNative) +# define RTPipeQueryReadable RT_MANGLER(RTPipeQueryReadable) +# define RTPipeRead RT_MANGLER(RTPipeRead) +# define RTPipeReadBlocking RT_MANGLER(RTPipeReadBlocking) +# define RTPipeSelectOne RT_MANGLER(RTPipeSelectOne) +# define RTPipeToNative RT_MANGLER(RTPipeToNative) +# define RTPipeWrite RT_MANGLER(RTPipeWrite) +# define RTPipeWriteBlocking RT_MANGLER(RTPipeWriteBlocking) +# define RTPoll RT_MANGLER(RTPoll) +# define RTPollNoResume RT_MANGLER(RTPollNoResume) +# define RTPollSetAdd RT_MANGLER(RTPollSetAdd) +# define RTPollSetCreate RT_MANGLER(RTPollSetCreate) +# define RTPollSetDestroy RT_MANGLER(RTPollSetDestroy) +# define RTPollSetEventsChange RT_MANGLER(RTPollSetEventsChange) +# define RTPollSetGetCount RT_MANGLER(RTPollSetGetCount) +# define RTPollSetQueryHandle RT_MANGLER(RTPollSetQueryHandle) +# define RTPollSetRemove RT_MANGLER(RTPollSetRemove) +# define RTPowerNotificationDeregister RT_MANGLER(RTPowerNotificationDeregister) /* r0drv */ +# define RTPowerNotificationRegister RT_MANGLER(RTPowerNotificationRegister) /* r0drv */ +# define RTPowerSignalEvent RT_MANGLER(RTPowerSignalEvent) /* r0drv */ +# define RTPrintf RT_MANGLER(RTPrintf) +# define RTPrintfV RT_MANGLER(RTPrintfV) +# define RTProcCreate RT_MANGLER(RTProcCreate) +# define RTProcCreateEx RT_MANGLER(RTProcCreateEx) +# define RTProcDaemonize RT_MANGLER(RTProcDaemonize) +# define RTProcDaemonizeUsingFork RT_MANGLER(RTProcDaemonizeUsingFork) +# define RTProcGetAffinityMask RT_MANGLER(RTProcGetAffinityMask) +# define RTProcGetExecutablePath RT_MANGLER(RTProcGetExecutablePath) +# define RTProcGetPriority RT_MANGLER(RTProcGetPriority) +# define RTProcIsRunningByName RT_MANGLER(RTProcIsRunningByName) +# define RTProcQueryUsername RT_MANGLER(RTProcQueryUsername) +# define RTProcQueryUsernameA RT_MANGLER(RTProcQueryUsernameA) +# define RTProcSelf RT_MANGLER(RTProcSelf) +# define RTProcSetPriority RT_MANGLER(RTProcSetPriority) +# define RTProcShortName RT_MANGLER(RTProcShortName) +# define RTProcTerminate RT_MANGLER(RTProcTerminate) +# define RTProcWait RT_MANGLER(RTProcWait) +# define RTProcWaitNoResume RT_MANGLER(RTProcWaitNoResume) +# define RTR0AssertPanicSystem RT_MANGLER(RTR0AssertPanicSystem) /* r0drv */ +# define RTR0DbgKrnlInfoOpen RT_MANGLER(RTR0DbgKrnlInfoOpen) /* r0drv */ +# define RTR0DbgKrnlInfoQueryMember RT_MANGLER(RTR0DbgKrnlInfoQueryMember) /* r0drv */ +# define RTR0DbgKrnlInfoQuerySymbol RT_MANGLER(RTR0DbgKrnlInfoQuerySymbol) /* r0drv */ +# define RTR0DbgKrnlInfoRelease RT_MANGLER(RTR0DbgKrnlInfoRelease) /* r0drv */ +# define RTR0DbgKrnlInfoRetain RT_MANGLER(RTR0DbgKrnlInfoRetain) /* r0drv */ +# define RTR0Init RT_MANGLER(RTR0Init) /* r0drv */ +# define RTR0MemAreKrnlAndUsrDifferent RT_MANGLER(RTR0MemAreKrnlAndUsrDifferent) /* r0drv */ +# define RTR0MemExecDonate RT_MANGLER(RTR0MemExecDonate) /* r0drv */ +# define RTR0MemKernelIsValidAddr RT_MANGLER(RTR0MemKernelIsValidAddr) /* r0drv */ +# define RTR0MemObjAddress RT_MANGLER(RTR0MemObjAddress) /* r0drv */ +# define RTR0MemObjAddressR3 RT_MANGLER(RTR0MemObjAddressR3) /* r0drv */ +# define RTR0MemKernelCopyFrom RT_MANGLER(RTR0MemKernelCopyFrom) /* r0drv */ +# define RTR0MemKernelCopyTo RT_MANGLER(RTR0MemKernelCopyTo) /* r0drv */ +# define RTR0MemObjAllocContTag RT_MANGLER(RTR0MemObjAllocContTag) /* r0drv */ +# define RTR0MemObjAllocLowTag RT_MANGLER(RTR0MemObjAllocLowTag) /* r0drv */ +# define RTR0MemObjAllocPageTag RT_MANGLER(RTR0MemObjAllocPageTag) /* r0drv */ +# define RTR0MemObjAllocPhysExTag RT_MANGLER(RTR0MemObjAllocPhysExTag) /* r0drv */ +# define RTR0MemObjAllocPhysNCTag RT_MANGLER(RTR0MemObjAllocPhysNCTag) /* r0drv */ +# define RTR0MemObjAllocPhysTag RT_MANGLER(RTR0MemObjAllocPhysTag) /* r0drv */ +# define RTR0MemObjEnterPhysTag RT_MANGLER(RTR0MemObjEnterPhysTag) /* r0drv */ +# define RTR0MemObjFree RT_MANGLER(RTR0MemObjFree) /* r0drv */ +# define RTR0MemObjGetPagePhysAddr RT_MANGLER(RTR0MemObjGetPagePhysAddr) /* r0drv */ +# define RTR0MemObjIsMapping RT_MANGLER(RTR0MemObjIsMapping) /* r0drv */ +# define RTR0MemObjLockKernelTag RT_MANGLER(RTR0MemObjLockKernelTag) /* r0drv */ +# define RTR0MemObjLockUserTag RT_MANGLER(RTR0MemObjLockUserTag) /* r0drv */ +# define RTR0MemObjMapKernelExTag RT_MANGLER(RTR0MemObjMapKernelExTag) /* r0drv */ +# define RTR0MemObjMapKernelTag RT_MANGLER(RTR0MemObjMapKernelTag) /* r0drv */ +# define RTR0MemObjMapUserTag RT_MANGLER(RTR0MemObjMapUserTag) /* r0drv */ +# define RTR0MemObjProtect RT_MANGLER(RTR0MemObjProtect) /* r0drv */ +# define RTR0MemObjReserveKernelTag RT_MANGLER(RTR0MemObjReserveKernelTag) /* r0drv */ +# define RTR0MemObjReserveUserTag RT_MANGLER(RTR0MemObjReserveUserTag) /* r0drv */ +# define RTR0MemObjSize RT_MANGLER(RTR0MemObjSize) /* r0drv */ +# define RTR0MemUserCopyFrom RT_MANGLER(RTR0MemUserCopyFrom) /* r0drv */ +# define RTR0MemUserCopyTo RT_MANGLER(RTR0MemUserCopyTo) /* r0drv */ +# define RTR0MemUserIsValidAddr RT_MANGLER(RTR0MemUserIsValidAddr) /* r0drv */ +# define RTR0ProcHandleSelf RT_MANGLER(RTR0ProcHandleSelf) /* r0drv */ +# define RTR0Term RT_MANGLER(RTR0Term) /* r0drv */ +# define RTR0TermForced RT_MANGLER(RTR0TermForced) /* r0drv */ +# define RTR3InitDll RT_MANGLER(RTR3InitDll) +# define RTR3InitExe RT_MANGLER(RTR3InitExe) +# define RTR3InitExeNoArguments RT_MANGLER(RTR3InitExeNoArguments) +# define RTR3InitEx RT_MANGLER(RTR3InitEx) +# define rtR3MemAlloc RT_MANGLER(rtR3MemAlloc) +# define rtR3MemFree RT_MANGLER(rtR3MemFree) +# define rtR3MemRealloc RT_MANGLER(rtR3MemRealloc) +# define RTRCInit RT_MANGLER(RTRCInit) +# define RTRCTerm RT_MANGLER(RTRCTerm) +# define RTRandAdvBytes RT_MANGLER(RTRandAdvBytes) +# define RTRandAdvCreateParkMiller RT_MANGLER(RTRandAdvCreateParkMiller) +# define RTRandAdvCreateSystemFaster RT_MANGLER(RTRandAdvCreateSystemFaster) +# define RTRandAdvCreateSystemTruer RT_MANGLER(RTRandAdvCreateSystemTruer) +# define RTRandAdvDestroy RT_MANGLER(RTRandAdvDestroy) +# define RTRandAdvRestoreState RT_MANGLER(RTRandAdvRestoreState) +# define RTRandAdvS32 RT_MANGLER(RTRandAdvS32) +# define RTRandAdvS32Ex RT_MANGLER(RTRandAdvS32Ex) +# define RTRandAdvS64 RT_MANGLER(RTRandAdvS64) +# define RTRandAdvS64Ex RT_MANGLER(RTRandAdvS64Ex) +# define RTRandAdvSaveState RT_MANGLER(RTRandAdvSaveState) +# define RTRandAdvSeed RT_MANGLER(RTRandAdvSeed) +# define RTRandAdvU32 RT_MANGLER(RTRandAdvU32) +# define RTRandAdvU32Ex RT_MANGLER(RTRandAdvU32Ex) +# define RTRandAdvU64 RT_MANGLER(RTRandAdvU64) +# define RTRandAdvU64Ex RT_MANGLER(RTRandAdvU64Ex) +# define RTRandBytes RT_MANGLER(RTRandBytes) +# define RTRandS32 RT_MANGLER(RTRandS32) +# define RTRandS32Ex RT_MANGLER(RTRandS32Ex) +# define RTRandS64 RT_MANGLER(RTRandS64) +# define RTRandS64Ex RT_MANGLER(RTRandS64Ex) +# define RTRandU32 RT_MANGLER(RTRandU32) +# define RTRandU32Ex RT_MANGLER(RTRandU32Ex) +# define RTRandU64 RT_MANGLER(RTRandU64) +# define RTRandU64Ex RT_MANGLER(RTRandU64Ex) +# define RTReqPoolAlloc RT_MANGLER(RTReqPoolAlloc) +# define RTReqPoolCallEx RT_MANGLER(RTReqPoolCallEx) +# define RTReqPoolCallExV RT_MANGLER(RTReqPoolCallExV) +# define RTReqPoolCallWait RT_MANGLER(RTReqPoolCallWait) +# define RTReqPoolCallNoWait RT_MANGLER(RTReqPoolCallNoWait) +# define RTReqPoolCallVoidWait RT_MANGLER(RTReqPoolCallVoidWait) +# define RTReqPoolCallVoidNoWait RT_MANGLER(RTReqPoolCallVoidNoWait) +# define RTReqPoolCreate RT_MANGLER(RTReqPoolCreate) +# define RTReqPoolGetCfgVar RT_MANGLER(RTReqPoolGetCfgVar) +# define RTReqPoolGetStat RT_MANGLER(RTReqPoolGetStat) +# define RTReqPoolRetain RT_MANGLER(RTReqPoolRetain) +# define RTReqPoolRelease RT_MANGLER(RTReqPoolRelease) +# define RTReqPoolSetCfgVar RT_MANGLER(RTReqPoolSetCfgVar) +# define RTReqQueueAlloc RT_MANGLER(RTReqQueueAlloc) +# define RTReqQueueCall RT_MANGLER(RTReqQueueCall) +# define RTReqQueueCallEx RT_MANGLER(RTReqQueueCallEx) +# define RTReqQueueCallV RT_MANGLER(RTReqQueueCallV) +# define RTReqQueueCallVoid RT_MANGLER(RTReqQueueCallVoid) +# define RTReqQueueCreate RT_MANGLER(RTReqQueueCreate) +# define RTReqQueueDestroy RT_MANGLER(RTReqQueueDestroy) +# define RTReqQueueIsBusy RT_MANGLER(RTReqQueueIsBusy) +# define RTReqQueueProcess RT_MANGLER(RTReqQueueProcess) +# define RTReqSubmit RT_MANGLER(RTReqSubmit) +# define RTReqRelease RT_MANGLER(RTReqRelease) +# define RTReqRetain RT_MANGLER(RTReqRetain) +# define RTReqWait RT_MANGLER(RTReqWait) +# define RTReqGetStatus RT_MANGLER(RTReqGetStatus) +# define RTS3BucketsDestroy RT_MANGLER(RTS3BucketsDestroy) +# define RTS3Create RT_MANGLER(RTS3Create) +# define RTS3CreateBucket RT_MANGLER(RTS3CreateBucket) +# define RTS3DeleteBucket RT_MANGLER(RTS3DeleteBucket) +# define RTS3DeleteKey RT_MANGLER(RTS3DeleteKey) +# define RTS3Destroy RT_MANGLER(RTS3Destroy) +# define RTS3GetBucketKeys RT_MANGLER(RTS3GetBucketKeys) +# define RTS3GetBuckets RT_MANGLER(RTS3GetBuckets) +# define RTS3GetKey RT_MANGLER(RTS3GetKey) +# define RTS3KeysDestroy RT_MANGLER(RTS3KeysDestroy) +# define RTS3PutKey RT_MANGLER(RTS3PutKey) +# define RTS3SetProgressCallback RT_MANGLER(RTS3SetProgressCallback) +# define RTSemEventAddSignaller RT_MANGLER(RTSemEventAddSignaller) +# define RTSemEventCreate RT_MANGLER(RTSemEventCreate) +# define RTSemEventCreateEx RT_MANGLER(RTSemEventCreateEx) +# define RTSemEventDestroy RT_MANGLER(RTSemEventDestroy) +# define RTSemEventGetResolution RT_MANGLER(RTSemEventGetResolution) /* r0drv */ +# define RTSemEventMultiAddSignaller RT_MANGLER(RTSemEventMultiAddSignaller) +# define RTSemEventMultiCreate RT_MANGLER(RTSemEventMultiCreate) +# define RTSemEventMultiCreateEx RT_MANGLER(RTSemEventMultiCreateEx) +# define RTSemEventMultiDestroy RT_MANGLER(RTSemEventMultiDestroy) +# define RTSemEventMultiGetResolution RT_MANGLER(RTSemEventMultiGetResolution) /* r0drv */ +# define RTSemEventMultiRemoveSignaller RT_MANGLER(RTSemEventMultiRemoveSignaller) +# define RTSemEventMultiReset RT_MANGLER(RTSemEventMultiReset) +# define RTSemEventMultiSetSignaller RT_MANGLER(RTSemEventMultiSetSignaller) +# define RTSemEventMultiSignal RT_MANGLER(RTSemEventMultiSignal) +# define RTSemEventMultiWait RT_MANGLER(RTSemEventMultiWait) +# define RTSemEventMultiWaitEx RT_MANGLER(RTSemEventMultiWaitEx) +# define RTSemEventMultiWaitEx RT_MANGLER(RTSemEventMultiWaitEx) /* r0drv */ +# define RTSemEventMultiWaitExDebug RT_MANGLER(RTSemEventMultiWaitExDebug) +# define RTSemEventMultiWaitExDebug RT_MANGLER(RTSemEventMultiWaitExDebug) /* r0drv */ +# define RTSemEventMultiWaitNoResume RT_MANGLER(RTSemEventMultiWaitNoResume) +# define RTSemEventRemoveSignaller RT_MANGLER(RTSemEventRemoveSignaller) +# define RTSemEventSetSignaller RT_MANGLER(RTSemEventSetSignaller) +# define RTSemEventSignal RT_MANGLER(RTSemEventSignal) +# define RTSemEventWait RT_MANGLER(RTSemEventWait) +# define RTSemEventWaitEx RT_MANGLER(RTSemEventWaitEx) /* r0drv */ +# define RTSemEventWaitExDebug RT_MANGLER(RTSemEventWaitExDebug) /* r0drv */ +# define RTSemEventWaitNoResume RT_MANGLER(RTSemEventWaitNoResume) +# define RTSemFastMutexCreate RT_MANGLER(RTSemFastMutexCreate) +# define RTSemFastMutexDestroy RT_MANGLER(RTSemFastMutexDestroy) +# define RTSemFastMutexRelease RT_MANGLER(RTSemFastMutexRelease) +# define RTSemFastMutexRequest RT_MANGLER(RTSemFastMutexRequest) +# define RTSemMutexCreate RT_MANGLER(RTSemMutexCreate) +# define RTSemMutexCreateEx RT_MANGLER(RTSemMutexCreateEx) +# define RTSemMutexDestroy RT_MANGLER(RTSemMutexDestroy) +# define RTSemMutexIsOwned RT_MANGLER(RTSemMutexIsOwned) +# define RTSemMutexRelease RT_MANGLER(RTSemMutexRelease) +# define RTSemMutexRequest RT_MANGLER(RTSemMutexRequest) +# define RTSemMutexRequestDebug RT_MANGLER(RTSemMutexRequestDebug) +# define RTSemMutexRequestNoResume RT_MANGLER(RTSemMutexRequestNoResume) +# define RTSemMutexRequestNoResumeDebug RT_MANGLER(RTSemMutexRequestNoResumeDebug) +# define RTSemMutexSetSubClass RT_MANGLER(RTSemMutexSetSubClass) +# define RTSemPing RT_MANGLER(RTSemPing) +# define RTSemPingPongDelete RT_MANGLER(RTSemPingPongDelete) +# define RTSemPingPongInit RT_MANGLER(RTSemPingPongInit) +# define RTSemPingWait RT_MANGLER(RTSemPingWait) +# define RTSemPong RT_MANGLER(RTSemPong) +# define RTSemPongWait RT_MANGLER(RTSemPongWait) +# define RTSemRWCreate RT_MANGLER(RTSemRWCreate) +# define RTSemRWCreateEx RT_MANGLER(RTSemRWCreateEx) +# define RTSemRWDestroy RT_MANGLER(RTSemRWDestroy) +# define RTSemRWGetReadCount RT_MANGLER(RTSemRWGetReadCount) +# define RTSemRWGetWriteRecursion RT_MANGLER(RTSemRWGetWriteRecursion) +# define RTSemRWGetWriterReadRecursion RT_MANGLER(RTSemRWGetWriterReadRecursion) +# define RTSemRWIsReadOwner RT_MANGLER(RTSemRWIsReadOwner) +# define RTSemRWIsWriteOwner RT_MANGLER(RTSemRWIsWriteOwner) +# define RTSemRWReleaseRead RT_MANGLER(RTSemRWReleaseRead) +# define RTSemRWReleaseWrite RT_MANGLER(RTSemRWReleaseWrite) +# define RTSemRWRequestRead RT_MANGLER(RTSemRWRequestRead) +# define RTSemRWRequestReadDebug RT_MANGLER(RTSemRWRequestReadDebug) +# define RTSemRWRequestReadNoResume RT_MANGLER(RTSemRWRequestReadNoResume) +# define RTSemRWRequestReadNoResumeDebug RT_MANGLER(RTSemRWRequestReadNoResumeDebug) +# define RTSemRWRequestWrite RT_MANGLER(RTSemRWRequestWrite) +# define RTSemRWRequestWriteDebug RT_MANGLER(RTSemRWRequestWriteDebug) +# define RTSemRWRequestWriteNoResume RT_MANGLER(RTSemRWRequestWriteNoResume) +# define RTSemRWRequestWriteNoResumeDebug RT_MANGLER(RTSemRWRequestWriteNoResumeDebug) +# define RTSemRWSetSubClass RT_MANGLER(RTSemRWSetSubClass) +# define RTSemSpinMutexCreate RT_MANGLER(RTSemSpinMutexCreate) +# define RTSemSpinMutexDestroy RT_MANGLER(RTSemSpinMutexDestroy) +# define RTSemSpinMutexRelease RT_MANGLER(RTSemSpinMutexRelease) +# define RTSemSpinMutexRequest RT_MANGLER(RTSemSpinMutexRequest) +# define RTSemSpinMutexTryRequest RT_MANGLER(RTSemSpinMutexTryRequest) +# define RTSemXRoadsCreate RT_MANGLER(RTSemXRoadsCreate) +# define RTSemXRoadsDestroy RT_MANGLER(RTSemXRoadsDestroy) +# define RTSemXRoadsEWEnter RT_MANGLER(RTSemXRoadsEWEnter) +# define RTSemXRoadsEWLeave RT_MANGLER(RTSemXRoadsEWLeave) +# define RTSemXRoadsNSEnter RT_MANGLER(RTSemXRoadsNSEnter) +# define RTSemXRoadsNSLeave RT_MANGLER(RTSemXRoadsNSLeave) +# define RTSgBufAdvance RT_MANGLER(RTSgBufAdvance) +# define RTSgBufClone RT_MANGLER(RTSgBufClone) +# define RTSgBufCmp RT_MANGLER(RTSgBufCmp) +# define RTSgBufCmpEx RT_MANGLER(RTSgBufCmpEx) +# define RTSgBufCopy RT_MANGLER(RTSgBufCopy) +# define RTSgBufCopyFromBuf RT_MANGLER(RTSgBufCopyFromBuf) +# define RTSgBufCopyToBuf RT_MANGLER(RTSgBufCopyToBuf) +# define RTSgBufInit RT_MANGLER(RTSgBufInit) +# define RTSgBufReset RT_MANGLER(RTSgBufReset) +# define RTSgBufSegArrayCreate RT_MANGLER(RTSgBufSegArrayCreate) +# define RTSgBufSet RT_MANGLER(RTSgBufSet) +# define RTSgBufGetNextSegment RT_MANGLER(RTSgBufGetNextSegment) +# define RTSha1 RT_MANGLER(RTSha1) +# define RTSha1Digest RT_MANGLER(RTSha1Digest) +# define RTSha1DigestFromFile RT_MANGLER(RTSha1DigestFromFile) +# define RTSha1Final RT_MANGLER(RTSha1Final) +# define RTSha1FromString RT_MANGLER(RTSha1FromString) +# define RTSha1Init RT_MANGLER(RTSha1Init) +# define RTSha1ToString RT_MANGLER(RTSha1ToString) +# define RTSha1Update RT_MANGLER(RTSha1Update) +# define RTSha256 RT_MANGLER(RTSha256) +# define RTSha256Final RT_MANGLER(RTSha256Final) +# define RTSha256FromString RT_MANGLER(RTSha256FromString) +# define RTSha256Init RT_MANGLER(RTSha256Init) +# define RTSha256ToString RT_MANGLER(RTSha256ToString) +# define RTSha256Update RT_MANGLER(RTSha256Update) +# define RTSha512 RT_MANGLER(RTSha512) +# define RTSha512Final RT_MANGLER(RTSha512Final) +# define RTSha512FromString RT_MANGLER(RTSha512FromString) +# define RTSha512Init RT_MANGLER(RTSha512Init) +# define RTSha512ToString RT_MANGLER(RTSha512ToString) +# define RTSha512Update RT_MANGLER(RTSha512Update) +# define RTSocketClose RT_MANGLER(RTSocketClose) +# define RTSocketFromNative RT_MANGLER(RTSocketFromNative) +# define RTSocketQueryAddressStr RT_MANGLER(RTSocketQueryAddressStr) +# define RTSocketGetLocalAddress RT_MANGLER(RTSocketGetLocalAddress) +# define RTSocketGetPeerAddress RT_MANGLER(RTSocketGetPeerAddress) +# define RTSocketParseInetAddress RT_MANGLER(RTSocketParseInetAddress) +# define RTSocketRead RT_MANGLER(RTSocketRead) +# define RTSocketReadFrom RT_MANGLER(RTSocketReadFrom) +# define RTSocketReadNB RT_MANGLER(RTSocketReadNB) +# define RTSocketRelease RT_MANGLER(RTSocketRelease) +# define RTSocketRetain RT_MANGLER(RTSocketRetain) +# define RTSocketSelectOne RT_MANGLER(RTSocketSelectOne) +# define RTSocketSelectOneEx RT_MANGLER(RTSocketSelectOneEx) +# define RTSocketSetInheritance RT_MANGLER(RTSocketSetInheritance) +# define RTSocketSgWrite RT_MANGLER(RTSocketSgWrite) +# define RTSocketSgWriteL RT_MANGLER(RTSocketSgWriteL) +# define RTSocketSgWriteLNB RT_MANGLER(RTSocketSgWriteLNB) +# define RTSocketSgWriteLV RT_MANGLER(RTSocketSgWriteLV) +# define RTSocketSgWriteLVNB RT_MANGLER(RTSocketSgWriteLVNB) +# define RTSocketSgWriteNB RT_MANGLER(RTSocketSgWriteNB) +# define RTSocketShutdown RT_MANGLER(RTSocketShutdown) +# define RTSocketToNative RT_MANGLER(RTSocketToNative) +# define RTSocketWrite RT_MANGLER(RTSocketWrite) +# define RTSocketWriteNB RT_MANGLER(RTSocketWriteNB) +# define RTSocketWriteTo RT_MANGLER(RTSocketWriteTo) +# define RTSortApvIsSorted RT_MANGLER(RTSortApvIsSorted) +# define RTSortApvShell RT_MANGLER(RTSortApvShell) +# define RTSortIsSorted RT_MANGLER(RTSortIsSorted) +# define RTSpinlockAcquire RT_MANGLER(RTSpinlockAcquire) +# define RTSpinlockAcquireNoInts RT_MANGLER(RTSpinlockAcquireNoInts) +# define RTSpinlockCreate RT_MANGLER(RTSpinlockCreate) +# define RTSpinlockDestroy RT_MANGLER(RTSpinlockDestroy) +# define RTSpinlockRelease RT_MANGLER(RTSpinlockRelease) +# define RTSpinlockReleaseNoInts RT_MANGLER(RTSpinlockReleaseNoInts) +# define RTStrAAppendExNVTag RT_MANGLER(RTStrAAppendExNVTag) +# define RTStrAAppendNTag RT_MANGLER(RTStrAAppendNTag) +# define RTStrAAppendTag RT_MANGLER(RTStrAAppendTag) +# define RTStrAllocExTag RT_MANGLER(RTStrAllocExTag) +# define RTStrAllocTag RT_MANGLER(RTStrAllocTag) +# define RTStrAPrintf2VTag RT_MANGLER(RTStrAPrintf2VTag) +# define RTStrAPrintfVTag RT_MANGLER(RTStrAPrintfVTag) +# define RTStrATruncateTag RT_MANGLER(RTStrATruncateTag) +# define RTStrCacheCreate RT_MANGLER(RTStrCacheCreate) +# define RTStrCacheDestroy RT_MANGLER(RTStrCacheDestroy) +# define RTStrCacheEnter RT_MANGLER(RTStrCacheEnter) +# define RTStrCacheEnterN RT_MANGLER(RTStrCacheEnterN) +# define RTStrCacheLength RT_MANGLER(RTStrCacheLength) +# define RTStrCacheRelease RT_MANGLER(RTStrCacheRelease) +# define RTStrCacheRetain RT_MANGLER(RTStrCacheRetain) +# define RTStrCalcLatin1Len RT_MANGLER(RTStrCalcLatin1Len) +# define RTStrCalcLatin1LenEx RT_MANGLER(RTStrCalcLatin1LenEx) +# define RTStrCalcUtf16Len RT_MANGLER(RTStrCalcUtf16Len) +# define RTStrCalcUtf16LenEx RT_MANGLER(RTStrCalcUtf16LenEx) +# define RTStrCat RT_MANGLER(RTStrCat) +# define RTStrCatEx RT_MANGLER(RTStrCatEx) +# define RTStrCatP RT_MANGLER(RTStrCatP) +# define RTStrCatPEx RT_MANGLER(RTStrCatPEx) +# define RTStrCmp RT_MANGLER(RTStrCmp) +# define RTStrConvertHexBytes RT_MANGLER(RTStrConvertHexBytes) +# define RTStrCopy RT_MANGLER(RTStrCopy) +# define RTStrCopyEx RT_MANGLER(RTStrCopyEx) +# define RTStrCopyP RT_MANGLER(RTStrCopyP) +# define RTStrCopyPEx RT_MANGLER(RTStrCopyPEx) +# define RTStrCurrentCPToUtf8Tag RT_MANGLER(RTStrCurrentCPToUtf8Tag) +# define RTStrDupExTag RT_MANGLER(RTStrDupExTag) +# define RTStrDupNTag RT_MANGLER(RTStrDupNTag) +# define RTStrDupTag RT_MANGLER(RTStrDupTag) +# define RTStrFormat RT_MANGLER(RTStrFormat) +# define RTStrFormatNumber RT_MANGLER(RTStrFormatNumber) +# define RTStrFormatR80 RT_MANGLER(RTStrFormatR80) +# define RTStrFormatR80u2 RT_MANGLER(RTStrFormatR80u2) +# define RTStrFormatTypeDeregister RT_MANGLER(RTStrFormatTypeDeregister) +# define RTStrFormatTypeRegister RT_MANGLER(RTStrFormatTypeRegister) +# define RTStrFormatTypeSetUser RT_MANGLER(RTStrFormatTypeSetUser) +# define RTStrFormatU128 RT_MANGLER(RTStrFormatU128) +# define RTStrFormatU16 RT_MANGLER(RTStrFormatU16) +# define RTStrFormatU32 RT_MANGLER(RTStrFormatU32) +# define RTStrFormatU64 RT_MANGLER(RTStrFormatU64) +# define RTStrFormatU8 RT_MANGLER(RTStrFormatU8) +# define RTStrFormatV RT_MANGLER(RTStrFormatV) +# define RTStrFree RT_MANGLER(RTStrFree) +# define RTStrGetCpExInternal RT_MANGLER(RTStrGetCpExInternal) +# define RTStrGetCpInternal RT_MANGLER(RTStrGetCpInternal) +# define RTStrGetCpNExInternal RT_MANGLER(RTStrGetCpNExInternal) +# define RTStrHash1 RT_MANGLER(RTStrHash1) +# define RTStrHash1ExN RT_MANGLER(RTStrHash1ExN) +# define RTStrHash1ExNV RT_MANGLER(RTStrHash1ExNV) +# define RTStrHash1N RT_MANGLER(RTStrHash1N) +# define RTStrICmp RT_MANGLER(RTStrICmp) +# define RTStrIStr RT_MANGLER(RTStrIStr) +# define RTStrIsValidEncoding RT_MANGLER(RTStrIsValidEncoding) +# define RTStrmClearError RT_MANGLER(RTStrmClearError) +# define RTStrmClose RT_MANGLER(RTStrmClose) +# define RTStrmError RT_MANGLER(RTStrmError) +# define RTStrmFlush RT_MANGLER(RTStrmFlush) +# define RTStrmGetCh RT_MANGLER(RTStrmGetCh) +# define RTStrmGetLine RT_MANGLER(RTStrmGetLine) +# define RTStrmOpen RT_MANGLER(RTStrmOpen) +# define RTStrmOpenF RT_MANGLER(RTStrmOpenF) +# define RTStrmOpenFV RT_MANGLER(RTStrmOpenFV) +# define RTStrmPrintf RT_MANGLER(RTStrmPrintf) +# define RTStrmPrintfV RT_MANGLER(RTStrmPrintfV) +# define RTStrmPutCh RT_MANGLER(RTStrmPutCh) +# define RTStrmPutStr RT_MANGLER(RTStrmPutStr) +# define RTStrmReadEx RT_MANGLER(RTStrmReadEx) +# define RTStrmRewind RT_MANGLER(RTStrmRewind) +# define RTStrmSetMode RT_MANGLER(RTStrmSetMode) +# define RTStrmWriteEx RT_MANGLER(RTStrmWriteEx) +# define RTStrNCmp RT_MANGLER(RTStrNCmp) +# define RTStrNICmp RT_MANGLER(RTStrNICmp) +# define RTStrNLen RT_MANGLER(RTStrNLen) +# define RTStrNLenEx RT_MANGLER(RTStrNLenEx) +# define RTStrPrevCp RT_MANGLER(RTStrPrevCp) +# define RTStrPrintf RT_MANGLER(RTStrPrintf) +# define RTStrPrintfEx RT_MANGLER(RTStrPrintfEx) +# define RTStrPrintfExV RT_MANGLER(RTStrPrintfExV) +# define RTStrPrintfV RT_MANGLER(RTStrPrintfV) +# define RTStrPrintHexBytes RT_MANGLER(RTStrPrintHexBytes) +# define RTStrPurgeEncoding RT_MANGLER(RTStrPurgeEncoding) +# define RTStrPurgeComplementSet RT_MANGLER(RTStrPurgeComplementSet) +# define RTStrPutCpInternal RT_MANGLER(RTStrPutCpInternal) +# define RTStrReallocTag RT_MANGLER(RTStrReallocTag) +# define RTStrSimplePatternMatch RT_MANGLER(RTStrSimplePatternMatch) +# define RTStrSimplePatternMultiMatch RT_MANGLER(RTStrSimplePatternMultiMatch) +# define RTStrSimplePatternNMatch RT_MANGLER(RTStrSimplePatternNMatch) +# define RTStrSpaceDestroy RT_MANGLER(RTStrSpaceDestroy) +# define RTStrSpaceEnumerate RT_MANGLER(RTStrSpaceEnumerate) +# define RTStrSpaceGet RT_MANGLER(RTStrSpaceGet) +# define RTStrSpaceGetN RT_MANGLER(RTStrSpaceGetN) +# define RTStrSpaceInsert RT_MANGLER(RTStrSpaceInsert) +# define RTStrSpaceRemove RT_MANGLER(RTStrSpaceRemove) +# define RTStrStr RT_MANGLER(RTStrStr) +# define RTStrStrip RT_MANGLER(RTStrStrip) +# define RTStrStripL RT_MANGLER(RTStrStripL) +# define RTStrStripR RT_MANGLER(RTStrStripR) +# define RTStrToInt16 RT_MANGLER(RTStrToInt16) +# define RTStrToInt16Ex RT_MANGLER(RTStrToInt16Ex) +# define RTStrToInt16Full RT_MANGLER(RTStrToInt16Full) +# define RTStrToInt32 RT_MANGLER(RTStrToInt32) +# define RTStrToInt32Ex RT_MANGLER(RTStrToInt32Ex) +# define RTStrToInt32Full RT_MANGLER(RTStrToInt32Full) +# define RTStrToInt64 RT_MANGLER(RTStrToInt64) +# define RTStrToInt64Ex RT_MANGLER(RTStrToInt64Ex) +# define RTStrToInt64Full RT_MANGLER(RTStrToInt64Full) +# define RTStrToInt8 RT_MANGLER(RTStrToInt8) +# define RTStrToInt8Ex RT_MANGLER(RTStrToInt8Ex) +# define RTStrToInt8Full RT_MANGLER(RTStrToInt8Full) +# define RTStrToLatin1ExTag RT_MANGLER(RTStrToLatin1ExTag) +# define RTStrToLatin1Tag RT_MANGLER(RTStrToLatin1Tag) +# define RTStrToLower RT_MANGLER(RTStrToLower) +# define RTStrToUInt16 RT_MANGLER(RTStrToUInt16) +# define RTStrToUInt16Ex RT_MANGLER(RTStrToUInt16Ex) +# define RTStrToUInt16Full RT_MANGLER(RTStrToUInt16Full) +# define RTStrToUInt32 RT_MANGLER(RTStrToUInt32) +# define RTStrToUInt32Ex RT_MANGLER(RTStrToUInt32Ex) +# define RTStrToUInt32Full RT_MANGLER(RTStrToUInt32Full) +# define RTStrToUInt64 RT_MANGLER(RTStrToUInt64) +# define RTStrToUInt64Ex RT_MANGLER(RTStrToUInt64Ex) +# define RTStrToUInt64Full RT_MANGLER(RTStrToUInt64Full) +# define RTStrToUInt8 RT_MANGLER(RTStrToUInt8) +# define RTStrToUInt8Ex RT_MANGLER(RTStrToUInt8Ex) +# define RTStrToUInt8Full RT_MANGLER(RTStrToUInt8Full) +# define RTStrToUni RT_MANGLER(RTStrToUni) +# define RTStrToUniEx RT_MANGLER(RTStrToUniEx) +# define RTStrToUpper RT_MANGLER(RTStrToUpper) +# define RTStrToUtf16ExTag RT_MANGLER(RTStrToUtf16ExTag) +# define RTStrToUtf16Tag RT_MANGLER(RTStrToUtf16Tag) +# define RTStrUniLen RT_MANGLER(RTStrUniLen) +# define RTStrUniLenEx RT_MANGLER(RTStrUniLenEx) +# define RTStrUtf8ToCurrentCPTag RT_MANGLER(RTStrUtf8ToCurrentCPTag) +# define RTStrValidateEncoding RT_MANGLER(RTStrValidateEncoding) +# define RTStrValidateEncodingEx RT_MANGLER(RTStrValidateEncodingEx) +# define RTStrVersionCompare RT_MANGLER(RTStrVersionCompare) +# define RTSymlinkCreate RT_MANGLER(RTSymlinkCreate) +# define RTSymlinkDelete RT_MANGLER(RTSymlinkDelete) +# define RTSymlinkExists RT_MANGLER(RTSymlinkExists) +# define RTSymlinkIsDangling RT_MANGLER(RTSymlinkIsDangling) +# define RTSymlinkRead RT_MANGLER(RTSymlinkRead) +# define RTSymlinkReadA RT_MANGLER(RTSymlinkReadA) +# define RTSystemQueryAvailableRam RT_MANGLER(RTSystemQueryAvailableRam) +# define RTSystemQueryDmiString RT_MANGLER(RTSystemQueryDmiString) +# define RTSystemQueryOSInfo RT_MANGLER(RTSystemQueryOSInfo) +# define RTSystemQueryTotalRam RT_MANGLER(RTSystemQueryTotalRam) +# define RTSystemShutdown RT_MANGLER(RTSystemShutdown) +# define RTTarClose RT_MANGLER(RTTarClose) +# define RTTarCreate RT_MANGLER(RTTarCreate) +# define RTTarCurrentFile RT_MANGLER(RTTarCurrentFile) +# define RTTarExtractAll RT_MANGLER(RTTarExtractAll) +# define RTTarExtractFiles RT_MANGLER(RTTarExtractFiles) +# define RTTarExtractFileToBuf RT_MANGLER(RTTarExtractFileToBuf) +# define RTTarFileClose RT_MANGLER(RTTarFileClose) +# define RTTarFileExists RT_MANGLER(RTTarFileExists) +# define RTTarFileGetMode RT_MANGLER(RTTarFileGetMode) +# define RTTarFileGetOwner RT_MANGLER(RTTarFileGetOwner) +# define RTTarFileGetSize RT_MANGLER(RTTarFileGetSize) +# define RTTarFileGetTime RT_MANGLER(RTTarFileGetTime) +# define RTTarFileOpen RT_MANGLER(RTTarFileOpen) +# define RTTarFileOpenCurrentFile RT_MANGLER(RTTarFileOpenCurrentFile) +# define RTTarFileRead RT_MANGLER(RTTarFileRead) +# define RTTarFileReadAt RT_MANGLER(RTTarFileReadAt) +# define RTTarFileSeek RT_MANGLER(RTTarFileSeek) +# define RTTarFileSetMode RT_MANGLER(RTTarFileSetMode) +# define RTTarFileSetOwner RT_MANGLER(RTTarFileSetOwner) +# define RTTarFileSetSize RT_MANGLER(RTTarFileSetSize) +# define RTTarFileSetTime RT_MANGLER(RTTarFileSetTime) +# define RTTarFileTell RT_MANGLER(RTTarFileTell) +# define RTTarFileWrite RT_MANGLER(RTTarFileWrite) +# define RTTarFileWriteAt RT_MANGLER(RTTarFileWriteAt) +# define RTTarList RT_MANGLER(RTTarList) +# define RTTarOpen RT_MANGLER(RTTarOpen) +# define RTTarSeekNextFile RT_MANGLER(RTTarSeekNextFile) +# define RTTcpClientClose RT_MANGLER(RTTcpClientClose) +# define RTTcpClientCloseEx RT_MANGLER(RTTcpClientCloseEx) +# define RTTcpClientConnect RT_MANGLER(RTTcpClientConnect) +# define RTTcpFlush RT_MANGLER(RTTcpFlush) +# define RTTcpGetLocalAddress RT_MANGLER(RTTcpGetLocalAddress) +# define RTTcpGetPeerAddress RT_MANGLER(RTTcpGetPeerAddress) +# define RTTcpRead RT_MANGLER(RTTcpRead) +# define RTTcpReadNB RT_MANGLER(RTTcpReadNB) +# define RTTcpSelectOne RT_MANGLER(RTTcpSelectOne) +# define RTTcpSelectOneEx RT_MANGLER(RTTcpSelectOneEx) +# define RTTcpServerCreate RT_MANGLER(RTTcpServerCreate) +# define RTTcpServerCreateEx RT_MANGLER(RTTcpServerCreateEx) +# define RTTcpServerDestroy RT_MANGLER(RTTcpServerDestroy) +# define RTTcpServerDisconnectClient RT_MANGLER(RTTcpServerDisconnectClient) +# define RTTcpServerDisconnectClient2 RT_MANGLER(RTTcpServerDisconnectClient2) +# define RTTcpServerListen RT_MANGLER(RTTcpServerListen) +# define RTTcpServerListen2 RT_MANGLER(RTTcpServerListen2) +# define RTTcpServerShutdown RT_MANGLER(RTTcpServerShutdown) +# define RTTcpSetSendCoalescing RT_MANGLER(RTTcpSetSendCoalescing) +# define RTTcpSgWrite RT_MANGLER(RTTcpSgWrite) +# define RTTcpSgWriteL RT_MANGLER(RTTcpSgWriteL) +# define RTTcpSgWriteLNB RT_MANGLER(RTTcpSgWriteLNB) +# define RTTcpSgWriteLV RT_MANGLER(RTTcpSgWriteLV) +# define RTTcpSgWriteLVNB RT_MANGLER(RTTcpSgWriteLVNB) +# define RTTcpSgWriteNB RT_MANGLER(RTTcpSgWriteNB) +# define RTTcpWrite RT_MANGLER(RTTcpWrite) +# define RTTcpWriteNB RT_MANGLER(RTTcpWriteNB) +# define RTTermDeregisterCallback RT_MANGLER(RTTermDeregisterCallback) +# define RTTermRegisterCallback RT_MANGLER(RTTermRegisterCallback) +# define RTTermRunCallbacks RT_MANGLER(RTTermRunCallbacks) +# define RTTestBanner RT_MANGLER(RTTestBanner) +# define RTTestCreate RT_MANGLER(RTTestCreate) +# define RTTestDestroy RT_MANGLER(RTTestDestroy) +# define RTTestErrorCount RT_MANGLER(RTTestErrorCount) +# define RTTestErrorInc RT_MANGLER(RTTestErrorInc) +# define RTTestFailed RT_MANGLER(RTTestFailed) +# define RTTestFailedV RT_MANGLER(RTTestFailedV) +# define RTTestFailureDetails RT_MANGLER(RTTestFailureDetails) +# define RTTestFailureDetailsV RT_MANGLER(RTTestFailureDetailsV) +# define RTTestGuardedAlloc RT_MANGLER(RTTestGuardedAlloc) +# define RTTestGuardedAllocHead RT_MANGLER(RTTestGuardedAllocHead) +# define RTTestGuardedAllocTail RT_MANGLER(RTTestGuardedAllocTail) +# define RTTestGuardedFree RT_MANGLER(RTTestGuardedFree) +# define RTTestIErrorCount RT_MANGLER(RTTestIErrorCount) +# define RTTestIErrorInc RT_MANGLER(RTTestIErrorInc) +# define RTTestIFailed RT_MANGLER(RTTestIFailed) +# define RTTestIFailedRc RT_MANGLER(RTTestIFailedRc) +# define RTTestIFailedRcV RT_MANGLER(RTTestIFailedRcV) +# define RTTestIFailedV RT_MANGLER(RTTestIFailedV) +# define RTTestIFailureDetails RT_MANGLER(RTTestIFailureDetails) +# define RTTestIFailureDetailsV RT_MANGLER(RTTestIFailureDetailsV) +# define RTTestInitAndCreate RT_MANGLER(RTTestInitAndCreate) +# define RTTestIPassed RT_MANGLER(RTTestIPassed) +# define RTTestIPassedV RT_MANGLER(RTTestIPassedV) +# define RTTestIPrintf RT_MANGLER(RTTestIPrintf) +# define RTTestIPrintfV RT_MANGLER(RTTestIPrintfV) +# define RTTestISub RT_MANGLER(RTTestISub) +# define RTTestISubDone RT_MANGLER(RTTestISubDone) +# define RTTestISubF RT_MANGLER(RTTestISubF) +# define RTTestISubV RT_MANGLER(RTTestISubV) +# define RTTestIValue RT_MANGLER(RTTestIValue) +# define RTTestIValueF RT_MANGLER(RTTestIValueF) +# define RTTestIValueV RT_MANGLER(RTTestIValueV) +# define RTTestPassed RT_MANGLER(RTTestPassed) +# define RTTestPassedV RT_MANGLER(RTTestPassedV) +# define RTTestPrintf RT_MANGLER(RTTestPrintf) +# define RTTestPrintfNl RT_MANGLER(RTTestPrintfNl) +# define RTTestPrintfNlV RT_MANGLER(RTTestPrintfNlV) +# define RTTestPrintfV RT_MANGLER(RTTestPrintfV) +# define RTTestSetDefault RT_MANGLER(RTTestSetDefault) +# define RTTestSkipAndDestroy RT_MANGLER(RTTestSkipAndDestroy) +# define RTTestSkipAndDestroyV RT_MANGLER(RTTestSkipAndDestroyV) +# define RTTestSub RT_MANGLER(RTTestSub) +# define RTTestSubDone RT_MANGLER(RTTestSubDone) +# define RTTestSubF RT_MANGLER(RTTestSubF) +# define RTTestSubV RT_MANGLER(RTTestSubV) +# define RTTestSummaryAndDestroy RT_MANGLER(RTTestSummaryAndDestroy) +# define RTTestValue RT_MANGLER(RTTestValue) +# define RTTestValueF RT_MANGLER(RTTestValueF) +# define RTTestValueV RT_MANGLER(RTTestValueV) +# define RTThreadAdopt RT_MANGLER(RTThreadAdopt) +# define RTThreadBlocking RT_MANGLER(RTThreadBlocking) +# define RTThreadCreate RT_MANGLER(RTThreadCreate) +# define RTThreadCreateF RT_MANGLER(RTThreadCreateF) +# define RTThreadCreateV RT_MANGLER(RTThreadCreateV) +# define RTThreadFromNative RT_MANGLER(RTThreadFromNative) +# define RTThreadGetAffinity RT_MANGLER(RTThreadGetAffinity) +# define RTThreadGetExecutionTimeMilli RT_MANGLER(RTThreadGetExecutionTimeMilli) +# define RTThreadGetName RT_MANGLER(RTThreadGetName) +# define RTThreadGetNative RT_MANGLER(RTThreadGetNative) +# define RTThreadGetNativeState RT_MANGLER(RTThreadGetNativeState) +# define RTThreadGetReallySleeping RT_MANGLER(RTThreadGetReallySleeping) +# define RTThreadGetState RT_MANGLER(RTThreadGetState) +# define RTThreadGetType RT_MANGLER(RTThreadGetType) +# define RTThreadIsInInterrupt RT_MANGLER(RTThreadIsInInterrupt) /* r0drv */ +# define RTThreadIsInitialized RT_MANGLER(RTThreadIsInitialized) +# define RTThreadIsMain RT_MANGLER(RTThreadIsMain) +# define RTThreadIsSelfAlive RT_MANGLER(RTThreadIsSelfAlive) +# define RTThreadIsSelfKnown RT_MANGLER(RTThreadIsSelfKnown) +# define RTThreadNativeSelf RT_MANGLER(RTThreadNativeSelf) +# define RTThreadPoke RT_MANGLER(RTThreadPoke) /* not-win not-os2 */ +# define RTThreadPreemptDisable RT_MANGLER(RTThreadPreemptDisable) /* r0drv */ +# define RTThreadPreemptIsEnabled RT_MANGLER(RTThreadPreemptIsEnabled) /* r0drv */ +# define RTThreadPreemptIsPending RT_MANGLER(RTThreadPreemptIsPending) /* r0drv */ +# define RTThreadPreemptIsPendingTrusty RT_MANGLER(RTThreadPreemptIsPendingTrusty) /* r0drv */ +# define RTThreadPreemptIsPossible RT_MANGLER(RTThreadPreemptIsPossible) /* r0drv */ +# define RTThreadPreemptRestore RT_MANGLER(RTThreadPreemptRestore) /* r0drv */ +# define RTThreadSelf RT_MANGLER(RTThreadSelf) +# define RTThreadSelfAutoAdopt RT_MANGLER(RTThreadSelfAutoAdopt) +# define RTThreadSelfName RT_MANGLER(RTThreadSelfName) +# define RTThreadSetAffinity RT_MANGLER(RTThreadSetAffinity) +# define RTThreadSetAffinityToCpu RT_MANGLER(RTThreadSetAffinityToCpu) +# define RTThreadSetName RT_MANGLER(RTThreadSetName) +# define RTThreadSetType RT_MANGLER(RTThreadSetType) +# define RTThreadSleep RT_MANGLER(RTThreadSleep) +# define RTThreadSleepNoLog RT_MANGLER(RTThreadSleepNoLog) +# define RTThreadStateName RT_MANGLER(RTThreadStateName) +# define RTThreadUnblocked RT_MANGLER(RTThreadUnblocked) +# define RTThreadUserReset RT_MANGLER(RTThreadUserReset) +# define RTThreadUserSignal RT_MANGLER(RTThreadUserSignal) +# define RTThreadUserWait RT_MANGLER(RTThreadUserWait) +# define RTThreadUserWaitNoResume RT_MANGLER(RTThreadUserWaitNoResume) +# define RTThreadWait RT_MANGLER(RTThreadWait) +# define RTThreadWaitNoResume RT_MANGLER(RTThreadWaitNoResume) +# define RTThreadYield RT_MANGLER(RTThreadYield) +# define RTTimeDbgBad RT_MANGLER(RTTimeDbgBad) +# define RTTimeDbgExpired RT_MANGLER(RTTimeDbgExpired) +# define RTTimeDbgRaces RT_MANGLER(RTTimeDbgRaces) +# define RTTimeDbgSteps RT_MANGLER(RTTimeDbgSteps) +# define RTTimeExplode RT_MANGLER(RTTimeExplode) +# define RTTimeImplode RT_MANGLER(RTTimeImplode) +# define RTTimeIsLeapYear RT_MANGLER(RTTimeIsLeapYear) +# define RTTimeLocalDeltaNano RT_MANGLER(RTTimeLocalDeltaNano) +# define RTTimeLocalExplode RT_MANGLER(RTTimeLocalExplode) +# define RTTimeLocalNow RT_MANGLER(RTTimeLocalNow) +# define RTTimeMilliTS RT_MANGLER(RTTimeMilliTS) +# define RTTimeNanoTS RT_MANGLER(RTTimeNanoTS) +# define RTTimeNanoTSLegacyAsync RT_MANGLER(RTTimeNanoTSLegacyAsync) +# define RTTimeNanoTSLegacySync RT_MANGLER(RTTimeNanoTSLegacySync) +# define RTTimeNanoTSLFenceAsync RT_MANGLER(RTTimeNanoTSLFenceAsync) +# define RTTimeNanoTSLFenceSync RT_MANGLER(RTTimeNanoTSLFenceSync) +# define RTTimeNormalize RT_MANGLER(RTTimeNormalize) +# define RTTimeNow RT_MANGLER(RTTimeNow) +# define RTTimeProgramMicroTS RT_MANGLER(RTTimeProgramMicroTS) +# define RTTimeProgramMilliTS RT_MANGLER(RTTimeProgramMilliTS) +# define RTTimeProgramNanoTS RT_MANGLER(RTTimeProgramNanoTS) +# define RTTimeProgramSecTS RT_MANGLER(RTTimeProgramSecTS) +# define RTTimeProgramStartNanoTS RT_MANGLER(RTTimeProgramStartNanoTS) +# define RTTimerCanDoHighResolution RT_MANGLER(RTTimerCanDoHighResolution) +# define RTTimerChangeInterval RT_MANGLER(RTTimerChangeInterval) +# define RTTimerCreate RT_MANGLER(RTTimerCreate) +# define RTTimerCreateEx RT_MANGLER(RTTimerCreateEx) +# define RTTimerDestroy RT_MANGLER(RTTimerDestroy) +# define RTTimerGetSystemGranularity RT_MANGLER(RTTimerGetSystemGranularity) /* r0drv */ +# define RTTimerLRCreate RT_MANGLER(RTTimerLRCreate) +# define RTTimerLRCreateEx RT_MANGLER(RTTimerLRCreateEx) +# define RTTimerLRDestroy RT_MANGLER(RTTimerLRDestroy) +# define RTTimerLRStart RT_MANGLER(RTTimerLRStart) +# define RTTimerLRStop RT_MANGLER(RTTimerLRStop) +# define RTTimerLRChangeInterval RT_MANGLER(RTTimerLRChangeInterval) +# define RTTimerReleaseSystemGranularity RT_MANGLER(RTTimerReleaseSystemGranularity) /* r0drv */ +# define RTTimerRequestSystemGranularity RT_MANGLER(RTTimerRequestSystemGranularity) /* r0drv */ +# define RTTimerStart RT_MANGLER(RTTimerStart) +# define RTTimerStop RT_MANGLER(RTTimerStop) +# define RTTimeSet RT_MANGLER(RTTimeSet) +# define RTTimeSpecToString RT_MANGLER(RTTimeSpecToString) +# define RTTimeSystemMilliTS RT_MANGLER(RTTimeSystemMilliTS) +# define RTTimeSystemNanoTS RT_MANGLER(RTTimeSystemNanoTS) +# define RTTimeToString RT_MANGLER(RTTimeToString) +# define RTTlsAlloc RT_MANGLER(RTTlsAlloc) +# define RTTlsAllocEx RT_MANGLER(RTTlsAllocEx) +# define RTTlsFree RT_MANGLER(RTTlsFree) +# define RTTlsGet RT_MANGLER(RTTlsGet) +# define RTTlsGetEx RT_MANGLER(RTTlsGetEx) +# define RTTlsSet RT_MANGLER(RTTlsSet) +# define RTTraceBufAddMsg RT_MANGLER(RTTraceBufAddMsg) +# define RTTraceBufAddMsgEx RT_MANGLER(RTTraceBufAddMsgEx) +# define RTTraceBufAddMsgF RT_MANGLER(RTTraceBufAddMsgF) +# define RTTraceBufAddMsgV RT_MANGLER(RTTraceBufAddMsgV) +# define RTTraceBufAddPos RT_MANGLER(RTTraceBufAddPos) +# define RTTraceBufAddPosMsg RT_MANGLER(RTTraceBufAddPosMsg) +# define RTTraceBufAddPosMsgEx RT_MANGLER(RTTraceBufAddPosMsgEx) +# define RTTraceBufAddPosMsgF RT_MANGLER(RTTraceBufAddPosMsgF) +# define RTTraceBufAddPosMsgV RT_MANGLER(RTTraceBufAddPosMsgV) +# define RTTraceBufCarve RT_MANGLER(RTTraceBufCarve) +# define RTTraceBufCreate RT_MANGLER(RTTraceBufCreate) +# define RTTraceBufDisable RT_MANGLER(RTTraceBufDisable) +# define RTTraceBufDumpToAssert RT_MANGLER(RTTraceBufDumpToAssert) +# define RTTraceBufDumpToLog RT_MANGLER(RTTraceBufDumpToLog) +# define RTTraceBufEnable RT_MANGLER(RTTraceBufEnable) +# define RTTraceBufEnumEntries RT_MANGLER(RTTraceBufEnumEntries) +# define RTTraceBufGetEntryCount RT_MANGLER(RTTraceBufGetEntryCount) +# define RTTraceBufGetEntrySize RT_MANGLER(RTTraceBufGetEntrySize) +# define RTTraceBufRelease RT_MANGLER(RTTraceBufRelease) +# define RTTraceBufRetain RT_MANGLER(RTTraceBufRetain) +# define RTTraceGetDefaultBuf RT_MANGLER(RTTraceGetDefaultBuf) +# define RTTraceSetDefaultBuf RT_MANGLER(RTTraceSetDefaultBuf) +# define RTUdpRead RT_MANGLER(RTUdpRead) +# define RTUdpServerCreate RT_MANGLER(RTUdpServerCreate) +# define RTUdpServerCreateEx RT_MANGLER(RTUdpServerCreateEx) +# define RTUdpServerDestroy RT_MANGLER(RTUdpServerDestroy) +# define RTUdpServerListen RT_MANGLER(RTUdpServerListen) +# define RTUdpServerShutdown RT_MANGLER(RTUdpServerShutdown) +# define RTUdpWrite RT_MANGLER(RTUdpWrite) +# define RTUniFree RT_MANGLER(RTUniFree) +# define RTUriAuthority RT_MANGLER(RTUriAuthority) +# define RTUriCreate RT_MANGLER(RTUriCreate) +# define RTUriFileCreate RT_MANGLER(RTUriFileCreate) +# define RTUriFileNPath RT_MANGLER(RTUriFileNPath) +# define RTUriFilePath RT_MANGLER(RTUriFilePath) +# define RTUriFragment RT_MANGLER(RTUriFragment) +# define RTUriHasScheme RT_MANGLER(RTUriHasScheme) +# define RTUriPath RT_MANGLER(RTUriPath) +# define RTUriQuery RT_MANGLER(RTUriQuery) +# define RTUriScheme RT_MANGLER(RTUriScheme) +# define RTUtf16CalcLatin1Len RT_MANGLER(RTUtf16CalcLatin1Len) +# define RTUtf16CalcLatin1LenEx RT_MANGLER(RTUtf16CalcLatin1LenEx) +# define RTUtf16CalcUtf8Len RT_MANGLER(RTUtf16CalcUtf8Len) +# define RTUtf16CalcUtf8LenEx RT_MANGLER(RTUtf16CalcUtf8LenEx) +# define RTUtf16Cmp RT_MANGLER(RTUtf16Cmp) +# define RTUtf16DupExTag RT_MANGLER(RTUtf16DupExTag) +# define RTUtf16DupTag RT_MANGLER(RTUtf16DupTag) +# define RTUtf16Free RT_MANGLER(RTUtf16Free) +# define RTUtf16GetCpExInternal RT_MANGLER(RTUtf16GetCpExInternal) +# define RTUtf16GetCpInternal RT_MANGLER(RTUtf16GetCpInternal) +# define RTUtf16ICmp RT_MANGLER(RTUtf16ICmp) +# define RTUtf16Len RT_MANGLER(RTUtf16Len) +# define RTUtf16LocaleICmp RT_MANGLER(RTUtf16LocaleICmp) +# define RTUtf16PutCpInternal RT_MANGLER(RTUtf16PutCpInternal) +# define RTUtf16ToLatin1ExTag RT_MANGLER(RTUtf16ToLatin1ExTag) +# define RTUtf16ToLatin1Tag RT_MANGLER(RTUtf16ToLatin1Tag) +# define RTUtf16ToLower RT_MANGLER(RTUtf16ToLower) +# define RTUtf16ToUpper RT_MANGLER(RTUtf16ToUpper) +# define RTUtf16PurgeComplementSet RT_MANGLER(RTUtf16PurgeComplementSet) +# define RTUtf16ToUtf8ExTag RT_MANGLER(RTUtf16ToUtf8ExTag) +# define RTUtf16ToUtf8Tag RT_MANGLER(RTUtf16ToUtf8Tag) +# define RTUuidClear RT_MANGLER(RTUuidClear) +# define RTUuidCompare RT_MANGLER(RTUuidCompare) +# define RTUuidCompare2Strs RT_MANGLER(RTUuidCompare2Strs) +# define RTUuidCompareStr RT_MANGLER(RTUuidCompareStr) +# define RTUuidCreate RT_MANGLER(RTUuidCreate) +# define RTUuidFromStr RT_MANGLER(RTUuidFromStr) +# define RTUuidFromUtf16 RT_MANGLER(RTUuidFromUtf16) +# define RTUuidIsNull RT_MANGLER(RTUuidIsNull) +# define RTUuidToStr RT_MANGLER(RTUuidToStr) +# define RTUuidToUtf16 RT_MANGLER(RTUuidToUtf16) +# define RTVfsChainElementDeregisterProvider RT_MANGLER(RTVfsChainElementDeregisterProvider) +# define RTVfsChainElementRegisterProvider RT_MANGLER(RTVfsChainElementRegisterProvider) +# define RTVfsChainIsSpec RT_MANGLER(RTVfsChainIsSpec) +# define RTVfsChainOpenFile RT_MANGLER(RTVfsChainOpenFile) +# define RTVfsChainOpenIoStream RT_MANGLER(RTVfsChainOpenIoStream) +# define RTVfsChainSpecFree RT_MANGLER(RTVfsChainSpecFree) +# define RTVfsChainSpecParse RT_MANGLER(RTVfsChainSpecParse) +# define RTVfsDirRelease RT_MANGLER(RTVfsDirRelease) +# define RTVfsDirRetain RT_MANGLER(RTVfsDirRetain) +# define RTVfsFileFlush RT_MANGLER(RTVfsFileFlush) +# define RTVfsFileFromRTFile RT_MANGLER(RTVfsFileFromRTFile) +# define RTVfsFileGetSize RT_MANGLER(RTVfsFileGetSize) +# define RTVfsFileOpen RT_MANGLER(RTVfsFileOpen) +# define RTVfsFilePoll RT_MANGLER(RTVfsFilePoll) +# define RTVfsFileQueryInfo RT_MANGLER(RTVfsFileQueryInfo) +# define RTVfsFileRead RT_MANGLER(RTVfsFileRead) +# define RTVfsFileReadAt RT_MANGLER(RTVfsFileReadAt) +# define RTVfsFileRelease RT_MANGLER(RTVfsFileRelease) +# define RTVfsFileRetain RT_MANGLER(RTVfsFileRetain) +# define RTVfsFileSeek RT_MANGLER(RTVfsFileSeek) +# define RTVfsFileTell RT_MANGLER(RTVfsFileTell) +# define RTVfsFileToIoStream RT_MANGLER(RTVfsFileToIoStream) +# define RTVfsFileWrite RT_MANGLER(RTVfsFileWrite) +# define RTVfsFileWriteAt RT_MANGLER(RTVfsFileWriteAt) +# define RTVfsFsStrmNext RT_MANGLER(RTVfsFsStrmNext) +# define RTVfsFsStrmQueryInfo RT_MANGLER(RTVfsFsStrmQueryInfo) +# define RTVfsFsStrmRelease RT_MANGLER(RTVfsFsStrmRelease) +# define RTVfsFsStrmRetain RT_MANGLER(RTVfsFsStrmRetain) +# define RTVfsIoStreamToPrivate RT_MANGLER(RTVfsIoStreamToPrivate) +# define RTVfsIoStrmFlush RT_MANGLER(RTVfsIoStrmFlush) +# define RTVfsIoStrmFromRTFile RT_MANGLER(RTVfsIoStrmFromRTFile) +# define RTVfsIoStrmFromStdHandle RT_MANGLER(RTVfsIoStrmFromStdHandle) +# define RTVfsIoStrmIsAtEnd RT_MANGLER(RTVfsIoStrmIsAtEnd) +# define RTVfsIoStrmPoll RT_MANGLER(RTVfsIoStrmPoll) +# define RTVfsIoStrmQueryInfo RT_MANGLER(RTVfsIoStrmQueryInfo) +# define RTVfsIoStrmRead RT_MANGLER(RTVfsIoStrmRead) +# define RTVfsIoStrmReadAt RT_MANGLER(RTVfsIoStrmReadAt) +# define RTVfsIoStrmRelease RT_MANGLER(RTVfsIoStrmRelease) +# define RTVfsIoStrmRetain RT_MANGLER(RTVfsIoStrmRetain) +# define RTVfsIoStrmSgRead RT_MANGLER(RTVfsIoStrmSgRead) +# define RTVfsIoStrmSgWrite RT_MANGLER(RTVfsIoStrmSgWrite) +# define RTVfsIoStrmSkip RT_MANGLER(RTVfsIoStrmSkip) +# define RTVfsIoStrmTell RT_MANGLER(RTVfsIoStrmTell) +# define RTVfsIoStrmToFile RT_MANGLER(RTVfsIoStrmToFile) +# define RTVfsIoStrmValidateUtf8Encoding RT_MANGLER(RTVfsIoStrmValidateUtf8Encoding) +# define RTVfsIoStrmWrite RT_MANGLER(RTVfsIoStrmWrite) +# define RTVfsIoStrmWriteAt RT_MANGLER(RTVfsIoStrmWriteAt) +# define RTVfsIoStrmZeroFill RT_MANGLER(RTVfsIoStrmZeroFill) +# define RTVfsIsRangeInUse RT_MANGLER(RTVfsIsRangeInUse) +# define RTVfsLockAcquireReadSlow RT_MANGLER(RTVfsLockAcquireReadSlow) +# define RTVfsLockAcquireWriteSlow RT_MANGLER(RTVfsLockAcquireWriteSlow) +# define RTVfsLockRelease RT_MANGLER(RTVfsLockRelease) +# define RTVfsLockReleaseReadSlow RT_MANGLER(RTVfsLockReleaseReadSlow) +# define RTVfsLockReleaseWriteSlow RT_MANGLER(RTVfsLockReleaseWriteSlow) +# define RTVfsLockRetain RT_MANGLER(RTVfsLockRetain) +# define RTVfsMemorizeIoStreamAsFile RT_MANGLER(RTVfsMemorizeIoStreamAsFile) +# define RTVfsNew RT_MANGLER(RTVfsNew) +# define RTVfsNewBaseObj RT_MANGLER(RTVfsNewBaseObj) +# define RTVfsNewFile RT_MANGLER(RTVfsNewFile) +# define RTVfsNewFsStream RT_MANGLER(RTVfsNewFsStream) +# define RTVfsNewIoStream RT_MANGLER(RTVfsNewIoStream) +# define RTVfsNewSymlink RT_MANGLER(RTVfsNewSymlink) +# define RTVfsObjFromDir RT_MANGLER(RTVfsObjFromDir) +# define RTVfsObjFromFile RT_MANGLER(RTVfsObjFromFile) +# define RTVfsObjFromFsStream RT_MANGLER(RTVfsObjFromFsStream) +# define RTVfsObjFromIoStream RT_MANGLER(RTVfsObjFromIoStream) +# define RTVfsObjFromSymlink RT_MANGLER(RTVfsObjFromSymlink) +# define RTVfsObjFromVfs RT_MANGLER(RTVfsObjFromVfs) +# define RTVfsObjQueryInfo RT_MANGLER(RTVfsObjQueryInfo) +# define RTVfsObjRelease RT_MANGLER(RTVfsObjRelease) +# define RTVfsObjRetain RT_MANGLER(RTVfsObjRetain) +# define RTVfsObjToDir RT_MANGLER(RTVfsObjToDir) +# define RTVfsObjToFile RT_MANGLER(RTVfsObjToFile) +# define RTVfsObjToFsStream RT_MANGLER(RTVfsObjToFsStream) +# define RTVfsObjToIoStream RT_MANGLER(RTVfsObjToIoStream) +# define RTVfsObjToSymlink RT_MANGLER(RTVfsObjToSymlink) +# define RTVfsObjToVfs RT_MANGLER(RTVfsObjToVfs) +# define RTVfsParsePath RT_MANGLER(RTVfsParsePath) +# define RTVfsParsePathA RT_MANGLER(RTVfsParsePathA) +# define RTVfsParsePathAppend RT_MANGLER(RTVfsParsePathAppend) +# define RTVfsParsePathFree RT_MANGLER(RTVfsParsePathFree) +# define RTVfsRelease RT_MANGLER(RTVfsRelease) +# define RTVfsRetain RT_MANGLER(RTVfsRetain) +# define RTVfsSymlinkQueryInfo RT_MANGLER(RTVfsSymlinkQueryInfo) +# define RTVfsSymlinkRead RT_MANGLER(RTVfsSymlinkRead) +# define RTVfsSymlinkRelease RT_MANGLER(RTVfsSymlinkRelease) +# define RTVfsSymlinkRetain RT_MANGLER(RTVfsSymlinkRetain) +# define RTVfsSymlinkSetMode RT_MANGLER(RTVfsSymlinkSetMode) +# define RTVfsSymlinkSetOwner RT_MANGLER(RTVfsSymlinkSetOwner) +# define RTVfsSymlinkSetTimes RT_MANGLER(RTVfsSymlinkSetTimes) +# define RTVfsUtilDummyPollOne RT_MANGLER(RTVfsUtilDummyPollOne) +# define RTVfsUtilPumpIoStreams RT_MANGLER(RTVfsUtilPumpIoStreams) +# define RTZipBlockCompress RT_MANGLER(RTZipBlockCompress) +# define RTZipBlockDecompress RT_MANGLER(RTZipBlockDecompress) +# define RTZipCompCreate RT_MANGLER(RTZipCompCreate) +# define RTZipCompDestroy RT_MANGLER(RTZipCompDestroy) +# define RTZipCompFinish RT_MANGLER(RTZipCompFinish) +# define RTZipCompress RT_MANGLER(RTZipCompress) +# define RTZipDecompCreate RT_MANGLER(RTZipDecompCreate) +# define RTZipDecompDestroy RT_MANGLER(RTZipDecompDestroy) +# define RTZipDecompress RT_MANGLER(RTZipDecompress) +# define RTZipGzipDecompressIoStream RT_MANGLER(RTZipGzipDecompressIoStream) +# define RTZipTarCmd RT_MANGLER(RTZipTarCmd) +# define RTZipTarFsStreamFromIoStream RT_MANGLER(RTZipTarFsStreamFromIoStream) + +/* + * Stable variables (alphabetical order): + */ +# define g_apfnRTZlibDeps RT_MANGLER(g_apfnRTZlibDeps) /* os2 win solaris */ +# define g_aRTUniFlagsRanges RT_MANGLER(g_aRTUniFlagsRanges) +# define g_aRTUniLowerRanges RT_MANGLER(g_aRTUniLowerRanges) +# define g_aRTUniUpperRanges RT_MANGLER(g_aRTUniUpperRanges) +# define g_fRTAlignmentChecks RT_MANGLER(g_fRTAlignmentChecks) +# define g_hKrnlDbgInfo RT_MANGLER(g_hKrnlDbgInfo) /* solaris */ +# define g_pStdErr RT_MANGLER(g_pStdErr) +# define g_pStdIn RT_MANGLER(g_pStdIn) +# define g_pStdOut RT_MANGLER(g_pStdOut) +# define g_pszRTAssertExpr RT_MANGLER(g_pszRTAssertExpr) +# define g_pszRTAssertFile RT_MANGLER(g_pszRTAssertFile) +# define g_pszRTAssertFunction RT_MANGLER(g_pszRTAssertFunction) +# define g_szRTAssertMsg1 RT_MANGLER(g_szRTAssertMsg1) +# define g_szRTAssertMsg2 RT_MANGLER(g_szRTAssertMsg2) +# define g_u32RTAssertLine RT_MANGLER(g_u32RTAssertLine) + + + +/* + * Unstable functions (alphabetical order): + */ +/** @todo the list is incomplete! See the .def files + libraries. */ + + +/* + * Unstable variables (alphabetical order): + */ +/* none */ + +#endif /* !DOXYGEN_RUNNING */ + +#endif + diff --git a/include/iprt/manifest.h b/include/iprt/manifest.h new file mode 100644 index 00000000..f7092b2a --- /dev/null +++ b/include/iprt/manifest.h @@ -0,0 +1,523 @@ +/** @file + * IPRT - Manifest file handling. + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_manifest_h +#define ___iprt_manifest_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_manifest RTManifest - Manifest file creation and checking + * @ingroup grp_rt + * @{ + */ + +/** @name Manifest attribute types. + * The types can be ORed together to form a set. + * @{ */ +/** For use with other attributes. Representation unknown. */ +#define RTMANIFEST_ATTR_UNKNOWN 0 +/** The size of the content. Represented as a decimal number. */ +#define RTMANIFEST_ATTR_SIZE RT_BIT_32(0) +/** The MD5 of the content. Represented as a hex string. */ +#define RTMANIFEST_ATTR_MD5 RT_BIT_32(1) +/** The SHA-1 of the content. Represented as a hex string. */ +#define RTMANIFEST_ATTR_SHA1 RT_BIT_32(2) +/** The SHA-256 of the content. Represented as a hex string. */ +#define RTMANIFEST_ATTR_SHA256 RT_BIT_32(3) +/** The SHA-512 of the content. Represented as a hex string. */ +#define RTMANIFEST_ATTR_SHA512 RT_BIT_32(4) +/** The end of the valid values. */ +#define RTMANIFEST_ATTR_END RT_BIT_32(5) +/** Wildcard for use in queries. */ +#define RTMANIFEST_ATTR_ANY UINT32_C(0xffffffff) +/** @} */ + +/** @name Digest types. */ +typedef enum RTDIGESTTYPE +{ + /** CRC32 checksum */ + RTDIGESTTYPE_CRC32 = 1, + /** CRC64 checksum */ + RTDIGESTTYPE_CRC64, + /** MD5 checksum (unsafe!) */ + RTDIGESTTYPE_MD5, + /** SHA1 checksum (unsafe!) */ + RTDIGESTTYPE_SHA1, + /** SHA256 checksum */ + RTDIGESTTYPE_SHA256, + /** SHA512 checksum */ + RTDIGESTTYPE_SHA512 +} RTDIGESTTYPE; +/** @} */ + + +/** + * Creates an empty manifest. + * + * @returns IPRT status code. + * @param fFlags Flags, MBZ. + * @param phManifest Where to return the handle to the manifest. + */ +RTDECL(int) RTManifestCreate(uint32_t fFlags, PRTMANIFEST phManifest); + +/** + * Retains a reference to the manifest handle. + * + * @returns The new reference count, UINT32_MAX if the handle is invalid. + * @param hManifest The handle to retain. + */ +RTDECL(uint32_t) RTManifestRetain(RTMANIFEST hManifest); + +/** + * Releases a reference to the manifest handle. + * + * @returns The new reference count, 0 if free. UINT32_MAX is returned if the + * handle is invalid. + * @param hManifest The handle to release. + * NIL is quietly ignored (returns 0). + */ +RTDECL(uint32_t) RTManifestRelease(RTMANIFEST hManifest); + +/** + * Creates a duplicate of the specified manifest. + * + * @returns IPRT status code + * @param hManifestSrc The manifest to clone. + * @param phManifestDst Where to store the handle to the duplicate. + */ +RTDECL(int) RTManifestDup(RTMANIFEST hManifestSrc, PRTMANIFEST phManifestDst); + +/** + * Compares two manifests for equality. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if equal. + * @retval VERR_NOT_EQUAL if not equal. + * + * @param hManifest1 The first manifest. + * @param hManifest2 The second manifest. + * @param papszIgnoreEntries Entries to ignore. Ends with a NULL entry. + * @param papszIgnoreAttrs Attributes to ignore. Ends with a NULL entry. + * @param fFlags A combination of RTMANIFEST_EQUALS_XXX values. + * @param pszError Where to store the name of the mismatching + * entry, or as much of the name as there is room + * for. This is always set. Optional. + * @param cbError The size of the buffer pointed to by @a + * pszError. + */ +RTDECL(int) RTManifestEqualsEx(RTMANIFEST hManifest1, RTMANIFEST hManifest2, const char * const *papszIgnoreEntries, + const char * const *papszIgnoreAttr, uint32_t fFlags, char *pszError, size_t cbError); + +/** @defgroup RTMANIFEST_EQUALS_XXX RTManifestEqualsEx flags + * @{ */ +/** Ignore missing attributes if there is one or more to compare. */ +#define RTMANIFEST_EQUALS_IGN_MISSING_ATTRS RT_BIT_32(0) +/** Ignore attributes missing in the 1st manifest. + * @todo implement this */ +#define RTMANIFEST_EQUALS_IGN_MISSING_ATTRS_1ST RT_BIT_32(1) +/** Mask of valid flags. */ +#define RTMANIFEST_EQUALS_VALID_MASK UINT32_C(0x00000003) +/** @} */ + +/** + * Compares two manifests for equality. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if equal. + * @retval VERR_NOT_EQUAL if not equal. + * + * @param hManifest1 The first manifest. + * @param hManifest2 The second manifest. + */ +RTDECL(int) RTManifestEquals(RTMANIFEST hManifest1, RTMANIFEST hManifest2); + +/** + * Sets a manifest attribute. + * + * @returns IPRT status code. + * @param hManifest The manifest handle. + * @param pszAttr The attribute name. If this already exists, + * its value will be replaced. + * @param pszValue The value string. + * @param fType The attribute type, pass + * RTMANIFEST_ATTR_UNKNOWN if not known. + */ +RTDECL(int) RTManifestSetAttr(RTMANIFEST hManifest, const char *pszAttr, const char *pszValue, uint32_t fType); + +/** + * Unsets (removes) a manifest attribute if it exists. + * + * @returns IPRT status code. + * @retval VWRN_NOT_FOUND if not found. + * + * @param hManifest The manifest handle. + * @param pszAttr The attribute name. + */ +RTDECL(int) RTManifestUnsetAttr(RTMANIFEST hManifest, const char *pszAttr); + +/** + * Query a manifest entry attribute. + * + * @returns IPRT status code. + * @retval VERR_BUFFER_OVERFLOW if the value buffer is too small. The @a + * pszValue buffer will not be modified. + * @retval VERR_MANIFEST_ATTR_NOT_FOUND + * @retval VERR_MANIFEST_ATTR_TYPE_NOT_FOUND + * @retval VERR_MANIFEST_ATTR_TYPE_MISMATCH + * + * @param hManifest The manifest handle. + * @param pszEntry The entry name. + * @param pszAttr The attribute name. If NULL, it will be + * selected by @a fType alone. + * @param fType The attribute types the entry should match. Pass + * Pass RTMANIFEST_ATTR_ANY match any. If more + * than one is given, the first matching one is + * returned. + * @param pszValue Where to return value. + * @param cbValue The size of the buffer @a pszValue points to. + * @param pfType Where to return the attribute type value. + */ +RTDECL(int) RTManifestQueryAttr(RTMANIFEST hManifest, const char *pszAttr, uint32_t fType, + char *pszValue, size_t cbValue, uint32_t *pfType); + +/** + * Sets an attribute of a manifest entry. + * + * @returns IPRT status code. + * @param hManifest The manifest handle. + * @param pszEntry The entry name. This will automatically be + * added if there was no previous call to + * RTManifestEntryAdd for this name. See + * RTManifestEntryAdd for the entry name rules. + * @param pszAttr The attribute name. If this already exists, + * its value will be replaced. + * @param pszValue The value string. + * @param fType The attribute type, pass + * RTMANIFEST_ATTR_UNKNOWN if not known. + */ +RTDECL(int) RTManifestEntrySetAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr, + const char *pszValue, uint32_t fType); + +/** + * Unsets (removes) an attribute of a manifest entry if they both exist. + * + * @returns IPRT status code. + * @retval VWRN_NOT_FOUND if not found. + * + * @param hManifest The manifest handle. + * @param pszEntry The entry name. + * @param pszAttr The attribute name. + */ +RTDECL(int) RTManifestEntryUnsetAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr); + +/** + * Query a manifest entry attribute. + * + * @returns IPRT status code. + * @retval VERR_BUFFER_OVERFLOW if the value buffer is too small. The @a + * pszValue buffer will not be modified. + * @retval VERR_NOT_FOUND if the entry was not found. + * @retval VERR_MANIFEST_ATTR_NOT_FOUND + * @retval VERR_MANIFEST_ATTR_TYPE_NOT_FOUND + * @retval VERR_MANIFEST_ATTR_TYPE_MISMATCH + * + * @param hManifest The manifest handle. + * @param pszEntry The entry name. + * @param pszAttr The attribute name. If NULL, it will be + * selected by @a fType alone. + * @param fType The attribute types the entry should match. Pass + * Pass RTMANIFEST_ATTR_ANY match any. If more + * than one is given, the first matching one is + * returned. + * @param pszValue Where to return value. + * @param cbValue The size of the buffer @a pszValue points to. + * @param pfType Where to return the attribute type value. + */ +RTDECL(int) RTManifestEntryQueryAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr, uint32_t fType, + char *pszValue, size_t cbValue, uint32_t *pfType); + +/** + * Adds a new entry to a manifest. + * + * The entry name rules: + * - The entry name can contain any character defined by unicode, except + * control characters, ':', '(' and ')'. The exceptions are mainly there + * because of uncertainty around how various formats handles these. + * - It is considered case sensitive. + * - Forward (unix) and backward (dos) slashes are considered path + * separators and converted to forward slashes. + * + * @returns IPRT status code. + * @retval VWRN_ALREADY_EXISTS if the entry already exists. + * + * @param hManifest The manifest handle. + * @param pszEntry The entry name (UTF-8). + * + * @remarks Some manifest formats will not be able to store an entry without + * any attributes. So, this is just here in case it comes in handy + * when dealing with formats which can. + */ +RTDECL(int) RTManifestEntryAdd(RTMANIFEST hManifest, const char *pszEntry); + +/** + * Removes an entry. + * + * @returns IPRT status code. + * @param hManifest The manifest handle. + * @param pszEntry The entry name. + */ +RTDECL(int) RTManifestEntryRemove(RTMANIFEST hManifest, const char *pszEntry); + +/** + * Add an entry for an I/O stream using a passthru stream. + * + * The passthru I/O stream will hash all the data read from or written to the + * stream and automatically add an entry to the manifest with the desired + * attributes when it is released. Alternatively one can call + * RTManifestPtIosAddEntryNow() to have more control over exactly when this + * action is performed and which status it yields. + * + * @returns IPRT status code. + * @param hManifest The manifest to add the entry to. + * @param hVfsIos The I/O stream to pass thru to/from. + * @param pszEntry The entry name. + * @param fAttrs The attributes to create for this stream. + * @param fReadOrWrite Whether it's a read or write I/O stream. + * @param phVfsIosPassthru Where to return the new handle. + */ +RTDECL(int) RTManifestEntryAddPassthruIoStream(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, const char *pszEntry, + uint32_t fAttrs, bool fReadOrWrite, PRTVFSIOSTREAM phVfsIosPassthru); + +/** + * Adds the entry to the manifest right now. + * + * @returns IPRT status code. + * @param hVfsPtIos The manifest passthru I/O stream returned by + * RTManifestEntryAddPassthruIoStream(). + */ +RTDECL(int) RTManifestPtIosAddEntryNow(RTVFSIOSTREAM hVfsPtIos); + +/** + * Adds an entry for a file with the specified set of attributes. + * + * @returns IPRT status code. + * + * @param hManifest The manifest handle. + * @param hVfsIos The I/O stream handle of the entry. This will + * be processed to its end on successful return. + * (Must be positioned at the start to get + * the expected results.) + * @param pszEntry The entry name. + * @param fAttrs The attributes to create for this stream. See + * RTMANIFEST_ATTR_XXX. + */ +RTDECL(int) RTManifestEntryAddIoStream(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, const char *pszEntry, uint32_t fAttrs); + +/** + * Checks if there is a manifest entry by the given name. + * + * @returns true if there is, false if not or if the handle is invalid. + * @param hManifest The manifest handle. + * @param pszEntry The entry name. + */ +RTDECL(bool) RTManifestEntryExists(RTMANIFEST hManifest, const char *pszEntry); + +/** + * Reads in a "standard" manifest. + * + * This reads the format used by OVF, the distinfo in FreeBSD ports, and + * others. + * + * @returns IPRT status code. + * @param hManifest The handle to the manifest where to add the + * manifest that's read in. + * @param hVfsIos The I/O stream to read the manifest from. + */ +RTDECL(int) RTManifestReadStandard(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos); + +/** + * Reads in a "standard" manifest. + * + * This reads the format used by OVF, the distinfo in FreeBSD ports, and + * others. + * + * @returns IPRT status code. + * @param hManifest The handle to the manifest where to add the + * manifest that's read in. + * @param hVfsIos The I/O stream to read the manifest from. + * @param pszErr Where to return extended error info on failure. + * Optional. + * @param cbErr The size of the buffer @a pszErr points to. + */ +RTDECL(int) RTManifestReadStandardEx(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, char *pszErr, size_t cbErr); + +/** + * Reads in a "standard" manifest from the specified file. + * + * This reads the format used by OVF, the distinfo in FreeBSD ports, and + * others. + * + * @returns IPRT status code. + * @param hManifest The handle to the manifest where to add the + * manifest that's read in. + * @param pszFilename The name of the file to read in. + */ +RTDECL(int) RTManifestReadStandardFromFile(RTMANIFEST hManifest, const char *pszFilename); + +/** + * Writes a "standard" manifest. + * + * This writes the format used by OVF, the distinfo in FreeBSD ports, and + * others. + * + * @returns IPRT status code. + * @param hManifest The handle to the manifest to write. + * @param hVfsIos The I/O stream to read the manifest from. + */ +RTDECL(int) RTManifestWriteStandard(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos); + +/** + * Writes a "standard" manifest to the specified file. + * + * @returns IPRT status code. + * @param hManifest The handle to the manifest to write. + * @param pszFilename The name of the file. + */ +RTDECL(int) RTManifestWriteStandardToFile(RTMANIFEST hManifest, const char *pszFilename); + + + + + +/** + * Input structure for RTManifestVerify() which contains the filename & the + * SHA1/SHA256 digest. + */ +typedef struct RTMANIFESTTEST +{ + /** The filename. */ + const char *pszTestFile; + /** The SHA1/SHA256 digest of the file. */ + const char *pszTestDigest; +} RTMANIFESTTEST; +/** Pointer to the input structure. */ +typedef RTMANIFESTTEST* PRTMANIFESTTEST; + + +/** + * Verify the given SHA1 digests against the entries in the manifest file. + * + * Please note that not only the various digest have to match, but the + * filenames as well. If there are more or even less files listed in the + * manifest file than provided by paTests, VERR_MANIFEST_FILE_MISMATCH will be + * returned. + * + * @returns iprt status code. + * + * @param pszManifestFile Filename of the manifest file to verify. + * @param paTests Array of files & SHA1 sums. + * @param cTests Number of entries in paTests. + * @param piFailed A index to paTests in the + * VERR_MANIFEST_DIGEST_MISMATCH error case + * (optional). + */ +RTR3DECL(int) RTManifestVerify(const char *pszManifestFile, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed); + +/** + * This is analogous to function RTManifestVerify(), but calculates the SHA1 + * sums of the given files itself. + * + * @returns iprt status code. + * + * @param pszManifestFile Filename of the manifest file to verify. + * @param papszFiles Array of files to check SHA1 sums. + * @param cFiles Number of entries in papszFiles. + * @param piFailed A index to papszFiles in the + * VERR_MANIFEST_DIGEST_MISMATCH error case + * (optional). + * @param pfnProgressCallback optional callback for the progress indication + * @param pvUser user defined pointer for the callback + */ +RTR3DECL(int) RTManifestVerifyFiles(const char *pszManifestFile, const char * const *papszFiles, size_t cFiles, size_t *piFailed, + PFNRTPROGRESS pfnProgressCallback, void *pvUser); + +/** + * Creates a manifest file for a set of files. The manifest file contains SHA1 + * sums of every provided file and could be used to verify the data integrity + * of them. + * + * @returns iprt status code. + * + * @param pszManifestFile Filename of the manifest file to create. + * @param enmDigestType The digest type (RTDIGESTTYPE_*) + * @param papszFiles Array of files to create SHA1 sums for. + * @param cFiles Number of entries in papszFiles. + * @param pfnProgressCallback optional callback for the progress indication + * @param pvUser user defined pointer for the callback + */ +RTR3DECL(int) RTManifestWriteFiles(const char *pszManifestFile, RTDIGESTTYPE enmDigestType, + const char * const *papszFiles, size_t cFiles, + PFNRTPROGRESS pfnProgressCallback, void *pvUser); + +/** + * Verify the given SHA1 digests against the entries in the manifest file in + * memory. + * + * @returns iprt status code. + * + * @param pvBuf Pointer to memory buffer of the manifest file. + * @param cbSize Size of the memory buffer. + * @param paTests Array of file names and digests. + * @param cTest Number of entries in paTests. + * @param piFailed A index to paTests in the + * VERR_MANIFEST_DIGEST_MISMATCH error case + * (optional). + */ +RTR3DECL(int) RTManifestVerifyFilesBuf(void *pvBuf, size_t cbSize, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed); + +/** + * Creates a manifest file in memory for a set of files. The manifest file + * contains SHA1 sums of every provided file and could be used to verify the + * data integrity of them. + * + * @returns iprt status code. + * + * @param ppvBuf Pointer to resulting memory buffer. + * @param pcbSize Pointer for the size of the memory buffer. + * @param enmDigestType Which type of digest ("SHA1", "SHA256", ...) + * @param paFiles Array of file names and digests. + * @param cFiles Number of entries in paFiles. + */ +RTR3DECL(int) RTManifestWriteFilesBuf(void **ppvBuf, size_t *pcbSize, RTDIGESTTYPE enmDigestType, PRTMANIFESTTEST paFiles, size_t cFiles); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/md5.h b/include/iprt/md5.h new file mode 100644 index 00000000..e085abb6 --- /dev/null +++ b/include/iprt/md5.h @@ -0,0 +1,126 @@ +/** @file + * IPRT - Message-Digest algorithm 5. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_md5_h +#define ___iprt_md5_h + +#include <iprt/types.h> + +/** @defgroup grp_rt_md5 RTMd5 - Message-Digest algorithm 5 + * @ingroup grp_rt + * @{ + */ + +/** Size of a MD5 hash. */ +#define RTMD5_HASH_SIZE 16 +/** @deprecated Use RTMD5_HASH_SIZE. */ +#define RTMD5HASHSIZE RTMD5_HASH_SIZE +/** The length of a MD5 digest string. The terminator is not included. */ +#define RTMD5_DIGEST_LEN 32 +/** Size of a MD5 hash. + * @deprecated Use RTMD5_DIGEST_LEN */ +#define RTMD5_STRING_LEN RTMD5_DIGEST_LEN + +/** + * MD5 hash algorithm context. + */ +typedef struct RTMD5CONTEXT +{ + uint32_t in[16]; + uint32_t buf[4]; + uint32_t bits[2]; +} RTMD5CONTEXT; + +/** Pointer to MD5 hash algorithm context. */ +typedef RTMD5CONTEXT *PRTMD5CONTEXT; + +RT_C_DECLS_BEGIN + +/** + * Compute the MD5 hash of the data. + * + * @param pvBuf Pointer to data. + * @param cbBuf Length of data (in bytes). + * @param pabDigest Where to store the hash. + * (What's passed is a pointer to the caller's buffer.) + */ +RTDECL(void) RTMd5(const void *pvBuf, size_t cbBuf, uint8_t pabDigest[RTMD5HASHSIZE]); + +/** + * Initialize MD5 context. + * + * @param pCtx Pointer to the MD5 context to initialize. + */ +RTDECL(void) RTMd5Init(PRTMD5CONTEXT pCtx); + +/** + * Feed data into the MD5 computation. + * + * @param pCtx Pointer to the MD5 context. + * @param pvBuf Pointer to data. + * @param cbBuf Length of data (in bytes). + */ +RTDECL(void) RTMd5Update(PRTMD5CONTEXT pCtx, const void *pvBuf, size_t cbBuf); + +/** + * Compute the MD5 hash of the data. + * + * @param pabDigest Where to store the hash. + * (What's passed is a pointer to the caller's buffer.) + * @param pCtx Pointer to the MD5 context. + */ +RTDECL(void) RTMd5Final(uint8_t pabDigest[RTMD5HASHSIZE], PRTMD5CONTEXT pCtx); + +/** + * Converts a MD5 hash to a digest string. + * + * @returns IPRT status code. + * + * @param pabDigest The binary digest returned by RTMd5Final or RTMd5. + * @param pszDigest Where to return the stringified digest. + * @param cchDigest The size of the output buffer. Should be at least + * RTMD5_STRING_LEN + 1 bytes. + */ +RTDECL(int) RTMd5ToString(uint8_t const pabDigest[RTMD5_HASH_SIZE], char *pszDigest, size_t cchDigest); + +/** + * Converts a MD5 hash to a digest string. + * + * @returns IPRT status code. + * + * @param pszDigest The stringified digest. Leading and trailing spaces are + * ignored. + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(int) RTMd5FromString(char const *pszDigest, uint8_t pabDigest[RTMD5_HASH_SIZE]); + + +RT_C_DECLS_END + +/** @} */ + +#endif + diff --git a/include/iprt/mem.h b/include/iprt/mem.h new file mode 100644 index 00000000..883de0fe --- /dev/null +++ b/include/iprt/mem.h @@ -0,0 +1,924 @@ +/** @file + * IPRT - Memory Management and Manipulation. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_mem_h +#define ___iprt_mem_h + + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + +#ifdef IN_RC +# error "There are no RTMem APIs available Guest Context!" +#endif + + +/** @defgroup grp_rt_mem RTMem - Memory Management and Manipulation + * @ingroup grp_rt + * @{ + */ + +RT_C_DECLS_BEGIN + +/** @def RTMEM_ALIGNMENT + * The alignment of the memory blocks returned by RTMemAlloc(), RTMemAllocZ(), + * RTMemRealloc(), RTMemTmpAlloc() and RTMemTmpAllocZ() for allocations greater + * than RTMEM_ALIGNMENT. + * + * @note This alignment is not forced if the electric fence is active! + */ +#if defined(RT_OS_OS2) +# define RTMEM_ALIGNMENT 4 +#else +# define RTMEM_ALIGNMENT 8 +#endif + +/** @def RTMEM_TAG + * The default allocation tag used by the RTMem allocation APIs. + * + * When not defined before the inclusion of iprt/mem.h or iprt/memobj.h, this + * will default to the pointer to the current file name. The memory API will + * make of use of this as pointer to a volatile but read-only string. + * The alternative tag includes the line number for a more-detailed analysis. + */ +#ifndef RTMEM_TAG +# if 0 +# define RTMEM_TAG (__FILE__ ":" RT_XSTR(__LINE__)) +# else +# define RTMEM_TAG (__FILE__) +# endif +#endif + + +/** @name Allocate temporary memory. + * @{ */ +/** + * Allocates temporary memory with default tag. + * + * Temporary memory blocks are used for not too large memory blocks which + * are believed not to stick around for too long. Using this API instead + * of RTMemAlloc() not only gives the heap manager room for optimization + * but makes the code easier to read. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure, assertion raised in strict builds. + * @param cb Size in bytes of the memory block to allocated. + */ +#define RTMemTmpAlloc(cb) RTMemTmpAllocTag((cb), RTMEM_TAG) + +/** + * Allocates temporary memory with custom tag. + * + * Temporary memory blocks are used for not too large memory blocks which + * are believed not to stick around for too long. Using this API instead + * of RTMemAlloc() not only gives the heap manager room for optimization + * but makes the code easier to read. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure, assertion raised in strict builds. + * @param cb Size in bytes of the memory block to allocated. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemTmpAllocTag(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Allocates zero'd temporary memory with default tag. + * + * Same as RTMemTmpAlloc() but the memory will be zero'd. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure, assertion raised in strict builds. + * @param cb Size in bytes of the memory block to allocated. + */ +#define RTMemTmpAllocZ(cb) RTMemTmpAllocZTag((cb), RTMEM_TAG) + +/** + * Allocates zero'd temporary memory with custom tag. + * + * Same as RTMemTmpAlloc() but the memory will be zero'd. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure, assertion raised in strict builds. + * @param cb Size in bytes of the memory block to allocated. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemTmpAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Free temporary memory. + * + * @param pv Pointer to memory block. + */ +RTDECL(void) RTMemTmpFree(void *pv) RT_NO_THROW; + +/** @} */ + + +/** + * Allocates memory with default tag. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure, assertion raised in strict builds. + * @param cb Size in bytes of the memory block to allocated. + * @param pszTag Allocation tag used for statistics and such. + */ +#define RTMemAlloc(cb) RTMemAllocTag((cb), RTMEM_TAG) + +/** + * Allocates memory with custom tag. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure, assertion raised in strict builds. + * @param cb Size in bytes of the memory block to allocated. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemAllocTag(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Allocates zero'd memory with default tag. + * + * Instead of memset(pv, 0, sizeof()) use this when you want zero'd + * memory. This keeps the code smaller and the heap can skip the memset + * in about 0.42% of calls :-). + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param cb Size in bytes of the memory block to allocated. + */ +#define RTMemAllocZ(cb) RTMemAllocZTag((cb), RTMEM_TAG) + +/** + * Allocates zero'd memory with custom tag. + * + * Instead of memset(pv, 0, sizeof()) use this when you want zero'd + * memory. This keeps the code smaller and the heap can skip the memset + * in about 0.42% of calls :-). + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param cb Size in bytes of the memory block to allocated. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Wrapper around RTMemAlloc for automatically aligning variable sized + * allocations so that the various electric fence heaps works correctly. + * + * @returns See RTMemAlloc. + * @param cbUnaligned The unaligned size. + */ +#define RTMemAllocVar(cbUnaligned) RTMemAllocVarTag((cbUnaligned), RTMEM_TAG) + +/** + * Wrapper around RTMemAllocTag for automatically aligning variable sized + * allocations so that the various electric fence heaps works correctly. + * + * @returns See RTMemAlloc. + * @param cbUnaligned The unaligned size. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemAllocVarTag(size_t cbUnaligned, const char *pszTag) RT_NO_THROW; + +/** + * Wrapper around RTMemAllocZ for automatically aligning variable sized + * allocations so that the various electric fence heaps works correctly. + * + * @returns See RTMemAllocZ. + * @param cbUnaligned The unaligned size. + */ +#define RTMemAllocZVar(cbUnaligned) RTMemAllocZVarTag((cbUnaligned), RTMEM_TAG) + +/** + * Wrapper around RTMemAllocZTag for automatically aligning variable sized + * allocations so that the various electric fence heaps works correctly. + * + * @returns See RTMemAllocZ. + * @param cbUnaligned The unaligned size. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemAllocZVarTag(size_t cbUnaligned, const char *pszTag) RT_NO_THROW; + +/** + * Duplicates a chunk of memory into a new heap block (default tag). + * + * @returns New heap block with the duplicate data. + * @returns NULL if we're out of memory. + * @param pvSrc The memory to duplicate. + * @param cb The amount of memory to duplicate. + */ +#define RTMemDup(pvSrc, cb) RTMemDupTag((pvSrc), (cb), RTMEM_TAG) + +/** + * Duplicates a chunk of memory into a new heap block (custom tag). + * + * @returns New heap block with the duplicate data. + * @returns NULL if we're out of memory. + * @param pvSrc The memory to duplicate. + * @param cb The amount of memory to duplicate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemDupTag(const void *pvSrc, size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Duplicates a chunk of memory into a new heap block with some additional + * zeroed memory (default tag). + * + * @returns New heap block with the duplicate data. + * @returns NULL if we're out of memory. + * @param pvSrc The memory to duplicate. + * @param cbSrc The amount of memory to duplicate. + * @param cbExtra The amount of extra memory to allocate and zero. + */ +#define RTMemDupEx(pvSrc, cbSrc, cbExtra) RTMemDupExTag((pvSrc), (cbSrc), (cbExtra), RTMEM_TAG) + +/** + * Duplicates a chunk of memory into a new heap block with some additional + * zeroed memory (default tag). + * + * @returns New heap block with the duplicate data. + * @returns NULL if we're out of memory. + * @param pvSrc The memory to duplicate. + * @param cbSrc The amount of memory to duplicate. + * @param cbExtra The amount of extra memory to allocate and zero. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemDupExTag(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag) RT_NO_THROW; + +/** + * Reallocates memory with default tag. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param pvOld The memory block to reallocate. + * @param cbNew The new block size (in bytes). + */ +#define RTMemRealloc(pvOld, cbNew) RTMemReallocTag((pvOld), (cbNew), RTMEM_TAG) + +/** + * Reallocates memory with custom tag. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param pvOld The memory block to reallocate. + * @param cbNew The new block size (in bytes). + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemReallocTag(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW; + +/** + * Frees memory. + * + * @param pv Pointer to memory block. + */ +RTDECL(void) RTMemFree(void *pv) RT_NO_THROW; + + + +/** @def RTR0MemAllocEx and RTR0MemAllocExTag flags. + * @{ */ +/** The returned memory should be zeroed. */ +#define RTMEMALLOCEX_FLAGS_ZEROED RT_BIT(0) +/** It must be load code into the returned memory block and execute it. */ +#define RTMEMALLOCEX_FLAGS_EXEC RT_BIT(1) +/** Allocation from any context. + * Will return VERR_NOT_SUPPORTED if not supported. */ +#define RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC RT_BIT(2) +/** Allocate the memory such that it can be freed from any context. + * Will return VERR_NOT_SUPPORTED if not supported. */ +#define RTMEMALLOCEX_FLAGS_ANY_CTX_FREE RT_BIT(3) +/** Allocate and free from any context. + * Will return VERR_NOT_SUPPORTED if not supported. */ +#define RTMEMALLOCEX_FLAGS_ANY_CTX (RTMEMALLOCEX_FLAGS_ANY_CTX_ALLOC | RTMEMALLOCEX_FLAGS_ANY_CTX_FREE) +/** Mask of valid flags. */ +#define RTMEMALLOCEX_FLAGS_VALID_MASK UINT32_C(0x0000000f) +/** @} */ + +/** + * Extended heap allocation API, default tag. + * + * @returns IPRT status code. + * @retval VERR_NO_MEMORY if we're out of memory. + * @retval VERR_NO_EXEC_MEMORY if we're out of executable memory. + * @retval VERR_NOT_SUPPORTED if any of the specified flags are unsupported. + * + * @param cb The amount of memory to allocate. + * @param cbAlignment The alignment requirements. Use 0 to indicate + * default alignment. + * @param fFlags A combination of the RTMEMALLOCEX_FLAGS_XXX + * defines. + * @param ppv Where to return the memory. + */ +#define RTMemAllocEx(cb, cbAlignment, fFlags, ppv) RTMemAllocExTag((cb), (cbAlignment), (fFlags), RTMEM_TAG, (ppv)) + +/** + * Extended heap allocation API, custom tag. + * + * @returns IPRT status code. + * @retval VERR_NO_MEMORY if we're out of memory. + * @retval VERR_NO_EXEC_MEMORY if we're out of executable memory. + * @retval VERR_NOT_SUPPORTED if any of the specified flags are unsupported. + * + * @param cb The amount of memory to allocate. + * @param cbAlignment The alignment requirements. Use 0 to indicate + * default alignment. + * @param fFlags A combination of the RTMEMALLOCEX_FLAGS_XXX + * defines. + * @param pszTag The tag. + * @param ppv Where to return the memory. + */ +RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW; + +/** + * For freeing memory allocated by RTMemAllocEx or RTMemAllocExTag. + * + * @param pv What to free, NULL is fine. + * @param cb The amount of allocated memory. + */ +RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW; + + + +/** + * Allocates memory which may contain code (default tag). + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param cb Size in bytes of the memory block to allocate. + */ +#define RTMemExecAlloc(cb) RTMemExecAllocTag((cb), RTMEM_TAG) + +/** + * Allocates memory which may contain code (custom tag). + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param cb Size in bytes of the memory block to allocate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Free executable/read/write memory allocated by RTMemExecAlloc(). + * + * @param pv Pointer to memory block. + * @param cb The allocation size. + */ +RTDECL(void) RTMemExecFree(void *pv, size_t cb) RT_NO_THROW; + +#if defined(IN_RING0) && defined(RT_ARCH_AMD64) && defined(RT_OS_LINUX) +/** + * Donate read+write+execute memory to the exec heap. + * + * This API is specific to AMD64 and Linux/GNU. A kernel module that desires to + * use RTMemExecAlloc on AMD64 Linux/GNU will have to donate some statically + * allocated memory in the module if it wishes for GCC generated code to work. + * GCC can only generate modules that work in the address range ~2GB to ~0 + * currently. + * + * The API only accept one single donation. + * + * @returns IPRT status code. + * @param pvMemory Pointer to the memory block. + * @param cb The size of the memory block. + */ +RTR0DECL(int) RTR0MemExecDonate(void *pvMemory, size_t cb) RT_NO_THROW; +#endif /* R0+AMD64+LINUX */ + +/** + * Allocate page aligned memory with default tag. + * + * @returns Pointer to the allocated memory. + * @returns NULL if we're out of memory. + * @param cb Size of the memory block. Will be rounded up to page size. + */ +#define RTMemPageAlloc(cb) RTMemPageAllocTag((cb), RTMEM_TAG) + +/** + * Allocate page aligned memory with custom tag. + * + * @returns Pointer to the allocated memory. + * @returns NULL if we're out of memory. + * @param cb Size of the memory block. Will be rounded up to page size. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemPageAllocTag(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Allocate zero'd page aligned memory with default tag. + * + * @returns Pointer to the allocated memory. + * @returns NULL if we're out of memory. + * @param cb Size of the memory block. Will be rounded up to page size. + */ +#define RTMemPageAllocZ(cb) RTMemPageAllocZTag((cb), RTMEM_TAG) + +/** + * Allocate zero'd page aligned memory with custom tag. + * + * @returns Pointer to the allocated memory. + * @returns NULL if we're out of memory. + * @param cb Size of the memory block. Will be rounded up to page size. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemPageAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Free a memory block allocated with RTMemPageAlloc() or RTMemPageAllocZ(). + * + * @param pv Pointer to the block as it was returned by the allocation function. + * NULL will be ignored. + * @param cb The allocation size. Will be rounded up to page size. + * Ignored if @a pv is NULL. + */ +RTDECL(void) RTMemPageFree(void *pv, size_t cb) RT_NO_THROW; + +/** Page level protection flags for RTMemProtect(). + * @{ + */ +/** No access at all. */ +#define RTMEM_PROT_NONE 0 +/** Read access. */ +#define RTMEM_PROT_READ 1 +/** Write access. */ +#define RTMEM_PROT_WRITE 2 +/** Execute access. */ +#define RTMEM_PROT_EXEC 4 +/** @} */ + +/** + * Change the page level protection of a memory region. + * + * @returns iprt status code. + * @param pv Start of the region. Will be rounded down to nearest page boundary. + * @param cb Size of the region. Will be rounded up to the nearest page boundary. + * @param fProtect The new protection, a combination of the RTMEM_PROT_* defines. + */ +RTDECL(int) RTMemProtect(void *pv, size_t cb, unsigned fProtect) RT_NO_THROW; + +/** + * Goes thru some pains to make sure the specified memory block is thoroughly + * scrambled. + * + * @param pv The start of the memory block. + * @param cb The size of the memory block. + * @param cMinPasses The minimum number of passes to make. + */ +RTDECL(void) RTMemWipeThoroughly(void *pv, size_t cb, size_t cMinPasses) RT_NO_THROW; + +#ifdef IN_RING0 + +/** + * Allocates physical contiguous memory (below 4GB). + * The allocation is page aligned and the content is undefined. + * + * @returns Pointer to the memory block. This is page aligned. + * @param pPhys Where to store the physical address. + * @param cb The allocation size in bytes. This is always + * rounded up to PAGE_SIZE. + */ +RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) RT_NO_THROW; + +/** + * Frees memory allocated ysing RTMemContAlloc(). + * + * @param pv Pointer to return from RTMemContAlloc(). + * @param cb The cb parameter passed to RTMemContAlloc(). + */ +RTR0DECL(void) RTMemContFree(void *pv, size_t cb) RT_NO_THROW; + +/** + * Copy memory from an user mode buffer into a kernel buffer. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_ACCESS_DENIED on error. + * + * @param pvDst The kernel mode destination address. + * @param R3PtrSrc The user mode source address. + * @param cb The number of bytes to copy. + */ +RTR0DECL(int) RTR0MemUserCopyFrom(void *pvDst, RTR3PTR R3PtrSrc, size_t cb); + +/** + * Copy memory from a kernel buffer into a user mode one. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_ACCESS_DENIED on error. + * + * @param R3PtrDst The user mode destination address. + * @param pvSrc The kernel mode source address. + * @param cb The number of bytes to copy. + */ +RTR0DECL(int) RTR0MemUserCopyTo(RTR3PTR R3PtrDst, void const *pvSrc, size_t cb); + +/** + * Tests if the specified address is in the user addressable range. + * + * This function does not check whether the memory at that address is accessible + * or anything of that sort, only if the address it self is in the user mode + * range. + * + * @returns true if it's in the user addressable range. false if not. + * @param R3Ptr The user mode pointer to test. + * + * @remarks Some systems may have overlapping kernel and user address ranges. + * One prominent example of this is the x86 version of Mac OS X. Use + * RTR0MemAreKrnlAndUsrDifferent() to check. + */ +RTR0DECL(bool) RTR0MemUserIsValidAddr(RTR3PTR R3Ptr); + +/** + * Tests if the specified address is in the kernel mode range. + * + * This function does not check whether the memory at that address is accessible + * or anything of that sort, only if the address it self is in the kernel mode + * range. + * + * @returns true if it's in the kernel range. false if not. + * @param pv The alleged kernel mode pointer. + * + * @remarks Some systems may have overlapping kernel and user address ranges. + * One prominent example of this is the x86 version of Mac OS X. Use + * RTR0MemAreKrnlAndUsrDifferent() to check. + */ +RTR0DECL(bool) RTR0MemKernelIsValidAddr(void *pv); + +/** + * Are user mode and kernel mode address ranges distinctly different. + * + * This determines whether RTR0MemKernelIsValidAddr and RTR0MemUserIsValidAddr + * can be used for deciding whether some arbitrary address is a user mode or a + * kernel mode one. + * + * @returns true if they are, false if not. + */ +RTR0DECL(bool) RTR0MemAreKrnlAndUsrDifferent(void); + +/** + * Copy memory from an potentially unsafe kernel mode location and into a safe + * (kernel) buffer. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_ACCESS_DENIED on error. + * @retval VERR_NOT_SUPPORTED if not (yet) supported. + * + * @param pvDst The destination address (safe). + * @param pvSrc The source address (potentially unsafe). + * @param cb The number of bytes to copy. + */ +RTR0DECL(int) RTR0MemKernelCopyFrom(void *pvDst, void const *pvSrc, size_t cb); + +/** + * Copy from a safe (kernel) buffer and to a potentially unsafe kenrel mode + * location. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_ACCESS_DENIED on error. + * @retval VERR_NOT_SUPPORTED if not (yet) supported. + * + * @param pvDst The destination address (potentially unsafe). + * @param pvSrc The source address (safe). + * @param cb The number of bytes to copy. + */ +RTR0DECL(int) RTR0MemKernelCopyTo(void *pvDst, void const *pvSrc, size_t cb); + +#endif /* IN_RING0 */ + + +/** @name Electrical Fence Version of some APIs. + * @{ + */ + +/** + * Same as RTMemTmpAllocTag() except that it's fenced. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param cb Size in bytes of the memory block to allocate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfTmpAlloc(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemTmpAllocZTag() except that it's fenced. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param cb Size in bytes of the memory block to allocate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfTmpAllocZ(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemTmpFree() except that it's for fenced memory. + * + * @param pv Pointer to memory block. + */ +RTDECL(void) RTMemEfTmpFree(void *pv, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemAllocTag() except that it's fenced. + * + * @returns Pointer to the allocated memory. Free with RTMemEfFree(). + * @returns NULL on failure. + * @param cb Size in bytes of the memory block to allocate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfAlloc(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemAllocZTag() except that it's fenced. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param cb Size in bytes of the memory block to allocate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfAllocZ(size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemAllocVarTag() except that it's fenced. + * + * @returns Pointer to the allocated memory. Free with RTMemEfFree(). + * @returns NULL on failure. + * @param cbUnaligned Size in bytes of the memory block to allocate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfAllocVar(size_t cbUnaligned, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemAllocZVarTag() except that it's fenced. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param cbUnaligned Size in bytes of the memory block to allocate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfAllocZVar(size_t cbUnaligned, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemReallocTag() except that it's fenced. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * @param pvOld The memory block to reallocate. + * @param cbNew The new block size (in bytes). + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfRealloc(void *pvOld, size_t cbNew, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Free memory allocated by any of the RTMemEf* allocators. + * + * @param pv Pointer to memory block. + */ +RTDECL(void) RTMemEfFree(void *pv, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemDupTag() except that it's fenced. + * + * @returns New heap block with the duplicate data. + * @returns NULL if we're out of memory. + * @param pvSrc The memory to duplicate. + * @param cb The amount of memory to duplicate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfDup(const void *pvSrc, size_t cb, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** + * Same as RTMemEfDupExTag except that it's fenced. + * + * @returns New heap block with the duplicate data. + * @returns NULL if we're out of memory. + * @param pvSrc The memory to duplicate. + * @param cbSrc The amount of memory to duplicate. + * @param cbExtra The amount of extra memory to allocate and zero. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(void *) RTMemEfDupEx(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag, RT_SRC_POS_DECL) RT_NO_THROW; + +/** @def RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF + * Define RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF to enable electric fence new and + * delete operators for classes which uses the RTMEMEF_NEW_AND_DELETE_OPERATORS + * macro. + */ +/** @def RTMEMEF_NEW_AND_DELETE_OPERATORS + * Defines the electric fence new and delete operators for a class when + * RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF is define. + */ +#if defined(RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF) && !defined(RTMEM_NO_WRAP_SOME_NEW_AND_DELETE_TO_EF) +# if defined(RT_EXCEPTIONS_ENABLED) +# define RTMEMEF_NEW_AND_DELETE_OPERATORS() \ + void *operator new(size_t cb) RT_THROW(std::bad_alloc) \ + { \ + void *pv = RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \ + if (RT_UNLIKELY(!pv)) \ + throw std::bad_alloc(); \ + return pv; \ + } \ + void *operator new(size_t cb, const std::nothrow_t ¬hrow_constant) RT_NO_THROW \ + { \ + NOREF(nothrow_constant); \ + return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \ + } \ + void *operator new[](size_t cb) RT_THROW(std::bad_alloc) \ + { \ + void *pv = RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \ + if (RT_UNLIKELY(!pv)) \ + throw std::bad_alloc(); \ + return pv; \ + } \ + void *operator new[](size_t cb, const std::nothrow_t ¬hrow_constant) RT_NO_THROW \ + { \ + NOREF(nothrow_constant); \ + return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \ + } \ + \ + void operator delete(void *pv) RT_NO_THROW \ + { \ + RTMemEfFree(pv, RT_SRC_POS); \ + } \ + void operator delete(void *pv, const std::nothrow_t ¬hrow_constant) RT_NO_THROW \ + { \ + NOREF(nothrow_constant); \ + RTMemEfFree(pv, RT_SRC_POS); \ + } \ + void operator delete[](void *pv) RT_NO_THROW \ + { \ + RTMemEfFree(pv, RT_SRC_POS); \ + } \ + void operator delete[](void *pv, const std::nothrow_t ¬hrow_constant) RT_NO_THROW \ + { \ + NOREF(nothrow_constant); \ + RTMemEfFree(pv, RT_SRC_POS); \ + } \ + \ + typedef int UsingElectricNewAndDeleteOperators +# else +# define RTMEMEF_NEW_AND_DELETE_OPERATORS() \ + void *operator new(size_t cb) \ + { \ + return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \ + } \ + void *operator new(size_t cb, const std::nothrow_t ¬hrow_constant) \ + { \ + NOREF(nothrow_constant); \ + return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \ + } \ + void *operator new[](size_t cb) \ + { \ + return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \ + } \ + void *operator new[](size_t cb, const std::nothrow_t ¬hrow_constant) \ + { \ + NOREF(nothrow_constant); \ + return RTMemEfAlloc(cb, RTMEM_TAG, RT_SRC_POS); \ + } \ + \ + void operator delete(void *pv) \ + { \ + RTMemEfFree(pv, RT_SRC_POS); \ + } \ + void operator delete(void *pv, const std::nothrow_t ¬hrow_constant) \ + { \ + NOREF(nothrow_constant); \ + RTMemEfFree(pv, RT_SRC_POS); \ + } \ + void operator delete[](void *pv) \ + { \ + RTMemEfFree(pv, RT_SRC_POS); \ + } \ + void operator delete[](void *pv, const std::nothrow_t ¬hrow_constant) \ + { \ + NOREF(nothrow_constant); \ + RTMemEfFree(pv, RT_SRC_POS); \ + } \ + \ + typedef int UsingElectricNewAndDeleteOperators +# endif +#else +# define RTMEMEF_NEW_AND_DELETE_OPERATORS() \ + typedef int UsingDefaultNewAndDeleteOperators +#endif +#ifdef DOXYGEN_RUNNING +# define RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF +#endif + +/** @def RTMEM_WRAP_TO_EF_APIS + * Define RTMEM_WRAP_TO_EF_APIS to wrap RTMem APIs to RTMemEf APIs. + */ +#if defined(RTMEM_WRAP_TO_EF_APIS) && defined(IN_RING3) && !defined(RTMEM_NO_WRAP_TO_EF_APIS) +# define RTMemTmpAllocTag(cb, pszTag) RTMemEfTmpAlloc((cb), (pszTag), RT_SRC_POS) +# define RTMemTmpAllocZTag(cb, pszTag) RTMemEfTmpAllocZ((cb), (pszTag), RT_SRC_POS) +# define RTMemTmpFree(pv) RTMemEfTmpFree((pv), RT_SRC_POS) +# define RTMemAllocTag(cb, pszTag) RTMemEfAlloc((cb), (pszTag), RT_SRC_POS) +# define RTMemAllocZTag(cb, pszTag) RTMemEfAllocZ((cb), (pszTag), RT_SRC_POS) +# define RTMemAllocVarTag(cbUnaligned, pszTag) RTMemEfAllocVar((cbUnaligned), (pszTag), RT_SRC_POS) +# define RTMemAllocZVarTag(cbUnaligned, pszTag) RTMemEfAllocZVar((cbUnaligned), (pszTag), RT_SRC_POS) +# define RTMemReallocTag(pvOld, cbNew, pszTag) RTMemEfRealloc((pvOld), (cbNew), (pszTag), RT_SRC_POS) +# define RTMemFree(pv) RTMemEfFree((pv), RT_SRC_POS) +# define RTMemDupTag(pvSrc, cb, pszTag) RTMemEfDup((pvSrc), (cb), (pszTag), RT_SRC_POS) +# define RTMemDupExTag(pvSrc, cbSrc, cbExtra, pszTag) RTMemEfDupEx((pvSrc), (cbSrc), (cbExtra), (pszTag), RT_SRC_POS) +#endif +#ifdef DOXYGEN_RUNNING +# define RTMEM_WRAP_TO_EF_APIS +#endif + +/** + * Fenced drop-in replacement for RTMemTmpAllocTag. + * @copydoc RTMemTmpAllocTag + */ +RTDECL(void *) RTMemEfTmpAllocNP(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemTmpAllocZTag. + * @copydoc RTMemTmpAllocZTag + */ +RTDECL(void *) RTMemEfTmpAllocZNP(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemTmpFreeTag. + * @copydoc RTMemTmpFreeTag + */ +RTDECL(void) RTMemEfTmpFreeNP(void *pv) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemAllocTag. + * @copydoc RTMemAllocTag + */ +RTDECL(void *) RTMemEfAllocNP(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemAllocZTag. + * @copydoc RTMemAllocZTag + */ +RTDECL(void *) RTMemEfAllocZNP(size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemAllocVarTag + * @copydoc RTMemAllocVarTag + */ +RTDECL(void *) RTMemEfAllocVarNP(size_t cbUnaligned, const char *pszTag) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemAllocZVarTag. + * @copydoc RTMemAllocZVarTag + */ +RTDECL(void *) RTMemEfAllocZVarNP(size_t cbUnaligned, const char *pszTag) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemReallocTag. + * @copydoc RTMemReallocTag + */ +RTDECL(void *) RTMemEfReallocNP(void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemFree. + * @copydoc RTMemFree + */ +RTDECL(void) RTMemEfFreeNP(void *pv) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemDupExTag. + * @copydoc RTMemDupExTag + */ +RTDECL(void *) RTMemEfDupNP(const void *pvSrc, size_t cb, const char *pszTag) RT_NO_THROW; + +/** + * Fenced drop-in replacement for RTMemDupExTag. + * @copydoc RTMemDupExTag + */ +RTDECL(void *) RTMemEfDupExNP(const void *pvSrc, size_t cbSrc, size_t cbExtra, const char *pszTag) RT_NO_THROW; + +/** @} */ + +RT_C_DECLS_END + +/** @} */ + + +#endif + diff --git a/include/iprt/memcache.h b/include/iprt/memcache.h new file mode 100644 index 00000000..cad496b1 --- /dev/null +++ b/include/iprt/memcache.h @@ -0,0 +1,147 @@ +/** @file + * IPRT - Memory Object Allocation Cache. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_memcache_h +#define ___iprt_memcache_h + + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + + +/** @defgroup grp_rt_memcache RTMemCache - Memory Object Allocation Cache + * @ingroup grp_rt + * + * Optimized allocation, initialization, freeing and destruction of memory + * objects of the same kind and size. + * + * @{ + */ + +/** A memory cache handle. */ +typedef R3R0PTRTYPE(struct RTMEMCACHEINT *) RTMEMCACHE; +/** Pointer to a memory cache handle. */ +typedef RTMEMCACHE *PRTMEMCACHE; +/** Nil memory cache handle. */ +#define NIL_RTMEMCACHE ((RTMEMCACHE)0) + + +/** + * Object constructor. + * + * This is called for when an element is allocated for the first time. + * + * @returns IPRT status code. + * @param hMemCache The cache handle. + * @param pvObj The memory object that should be initialized. + * @param pvUser The user argument. + * + * @remarks No serialization is performed. + */ +typedef DECLCALLBACK(int) FNMEMCACHECTOR(RTMEMCACHE hMemCache, void *pvObj, void *pvUser); +/** Pointer to an object constructor for the memory cache. */ +typedef FNMEMCACHECTOR *PFNMEMCACHECTOR; + +/** + * Object destructor. + * + * This is called when we're shrinking or destroying the cache. + * + * @param hMemCache The cache handle. + * @param pvObj The memory object that should be initialized. + * @param pvUser The user argument. + * + * @remarks No serialization is performed. + */ +typedef DECLCALLBACK(void) FNMEMCACHEDTOR(RTMEMCACHE hMemCache, void *pvObj, void *pvUser); +/** Pointer to an object destructor for the memory cache. */ +typedef FNMEMCACHEDTOR *PFNMEMCACHEDTOR; + + +/** + * Create an allocation cache for fixed size memory objects. + * + * @returns IPRT status code. + * @param phMemCache Where to return the cache handle. + * @param cbObject The size of one memory object. + * @param cbAlignment The object alignment. This must be a power of + * two. The higest alignment is 64. If set to 0, + * a sensible alignment value will be derived from + * the object size. + * @param cMaxObjects The maximum cache size. Pass UINT32_MAX if unsure. + * @param pfnCtor Object constructor callback. Optional. + * @param pfnDtor Object destructor callback. Optional. + * @param pvUser User argument for the two callbacks. + * @param fFlags Flags reserved for future use. Must be zero. + */ +RTDECL(int) RTMemCacheCreate(PRTMEMCACHE phMemCache, size_t cbObject, size_t cbAlignment, uint32_t cMaxObjects, + PFNMEMCACHECTOR pfnCtor, PFNMEMCACHEDTOR pfnDtor, void *pvUser, uint32_t fFlags); + +/** + * Destroy a cache destroying and freeing allocated memory. + * + * @returns IPRT status code. + * @param hMemCache The cache handle. NIL is quietly (VINF_SUCCESS) + * ignored. + */ +RTDECL(int) RTMemCacheDestroy(RTMEMCACHE hMemCache); + +/** + * Allocate an object. + * + * @returns Pointer to the allocated cache object. + * @param hMemCache The cache handle. + */ +RTDECL(void *) RTMemCacheAlloc(RTMEMCACHE hMemCache); + +/** + * Allocate an object and return a proper status code. + * + * @returns IPRT status code. + * @retval VERR_MEM_CACHE_MAX_SIZE if we've reached maximum size (see + * RTMemCacheCreate). + * @retval VERR_NO_MEMORY if we failed to allocate more memory for the cache. + * + * @param hMemCache The cache handle. + * @param ppvObj Where to return the object. + */ +RTDECL(int) RTMemCacheAllocEx(RTMEMCACHE hMemCache, void **ppvObj); + +/** + * Free an object previously returned by RTMemCacheAlloc or RTMemCacheAllocEx. + * + * @param hMemCache The cache handle. + * @param pvObj The object to free. NULL is fine. + */ +RTDECL(void) RTMemCacheFree(RTMEMCACHE hMemCache, void *pvObj); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/memobj.h b/include/iprt/memobj.h new file mode 100644 index 00000000..3a3b7025 --- /dev/null +++ b/include/iprt/memobj.h @@ -0,0 +1,629 @@ +/** @file + * IPRT - Memory Objects (Ring-0). + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_memobj_h +#define ___iprt_memobj_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_memobj RTMemObj - Memory Object Manipulation (Ring-0) + * @ingroup grp_rt + * @{ + */ + +/** @def RTMEM_TAG + * The default allocation tag used by the RTMem allocation APIs. + * + * When not defined before the inclusion of iprt/memobj.h or iprt/mem.h, this + * will default to the pointer to the current file name. The memory API will + * make of use of this as pointer to a volatile but read-only string. + */ +#ifndef RTMEM_TAG +# define RTMEM_TAG (__FILE__) +#endif + +#ifdef IN_RING0 + +/** + * Checks if this is mapping or not. + * + * @returns true if it's a mapping, otherwise false. + * @param MemObj The ring-0 memory object handle. + */ +RTR0DECL(bool) RTR0MemObjIsMapping(RTR0MEMOBJ MemObj); + +/** + * Gets the address of a ring-0 memory object. + * + * @returns The address of the memory object. + * @returns NULL if the handle is invalid (asserts in strict builds) or if there isn't any mapping. + * @param MemObj The ring-0 memory object handle. + */ +RTR0DECL(void *) RTR0MemObjAddress(RTR0MEMOBJ MemObj); + +/** + * Gets the ring-3 address of a ring-0 memory object. + * + * This only applies to ring-0 memory object with ring-3 mappings of some kind, i.e. + * locked user memory, reserved user address space and user mappings. This API should + * not be used on any other objects. + * + * @returns The address of the memory object. + * @returns NIL_RTR3PTR if the handle is invalid or if it's not an object with a ring-3 mapping. + * Strict builds will assert in both cases. + * @param MemObj The ring-0 memory object handle. + */ +RTR0DECL(RTR3PTR) RTR0MemObjAddressR3(RTR0MEMOBJ MemObj); + +/** + * Gets the size of a ring-0 memory object. + * + * The returned value may differ from the one specified to the API creating the + * object because of alignment adjustments. The minimal alignment currently + * employed by any API is PAGE_SIZE, so the result can safely be shifted by + * PAGE_SHIFT to calculate a page count. + * + * @returns The object size. + * @returns 0 if the handle is invalid (asserts in strict builds) or if there isn't any mapping. + * @param MemObj The ring-0 memory object handle. + */ +RTR0DECL(size_t) RTR0MemObjSize(RTR0MEMOBJ MemObj); + +/** + * Get the physical address of an page in the memory object. + * + * @returns The physical address. + * @returns NIL_RTHCPHYS if the object doesn't contain fixed physical pages. + * @returns NIL_RTHCPHYS if the iPage is out of range. + * @returns NIL_RTHCPHYS if the object handle isn't valid. + * @param MemObj The ring-0 memory object handle. + * @param iPage The page number within the object. + */ +RTR0DECL(RTHCPHYS) RTR0MemObjGetPagePhysAddr(RTR0MEMOBJ MemObj, size_t iPage); + +/** + * Frees a ring-0 memory object. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if + * @param MemObj The ring-0 memory object to be freed. NULL is accepted. + * @param fFreeMappings Whether or not to free mappings of the object. + */ +RTR0DECL(int) RTR0MemObjFree(RTR0MEMOBJ MemObj, bool fFreeMappings); + +/** + * Allocates page aligned virtual kernel memory (default tag). + * + * The memory is taken from a non paged (= fixed physical memory backing) pool. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object. + */ +#define RTR0MemObjAllocPage(pMemObj, cb, fExecutable) \ + RTR0MemObjAllocPageTag((pMemObj), (cb), (fExecutable), RTMEM_TAG) + +/** + * Allocates page aligned virtual kernel memory (custom tag). + * + * The memory is taken from a non paged (= fixed physical memory backing) pool. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjAllocPageTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag); + +/** + * Allocates page aligned virtual kernel memory with physical backing below 4GB + * (default tag). + * + * The physical memory backing the allocation is fixed. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object. + */ +#define RTR0MemObjAllocLow(pMemObj, cb, fExecutable) \ + RTR0MemObjAllocLowTag((pMemObj), (cb), (fExecutable), RTMEM_TAG) + +/** + * Allocates page aligned virtual kernel memory with physical backing below 4GB + * (custom tag). + * + * The physical memory backing the allocation is fixed. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjAllocLowTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag); + +/** + * Allocates page aligned virtual kernel memory with contiguous physical backing + * below 4GB (default tag). + * + * The physical memory backing the allocation is fixed. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object. + */ +#define RTR0MemObjAllocCont(pMemObj, cb, fExecutable) \ + RTR0MemObjAllocContTag((pMemObj), (cb), (fExecutable), RTMEM_TAG) + +/** + * Allocates page aligned virtual kernel memory with contiguous physical backing + * below 4GB (custom tag). + * + * The physical memory backing the allocation is fixed. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjAllocContTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag); + +/** + * Locks a range of user virtual memory (default tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param R3Ptr User virtual address. This is rounded down to a page + * boundary. + * @param cb Number of bytes to lock. This is rounded up to + * nearest page boundary. + * @param fAccess The desired access, a combination of RTMEM_PROT_READ + * and RTMEM_PROT_WRITE. + * @param R0Process The process to lock pages in. NIL_R0PROCESS is an + * alias for the current one. + * + * @remarks RTR0MemGetAddressR3() and RTR0MemGetAddress() will return therounded + * down address. + * + * @remarks Linux: This API requires that the memory begin locked is in a memory + * mapping that is not required in any forked off child process. This + * is not intented as permanent restriction, feel free to help out + * lifting it. + */ +#define RTR0MemObjLockUser(pMemObj, R3Ptr, cb, fAccess, R0Process) \ + RTR0MemObjLockUserTag((pMemObj), (R3Ptr), (cb), (fAccess), (R0Process), RTMEM_TAG) + +/** + * Locks a range of user virtual memory (custom tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param R3Ptr User virtual address. This is rounded down to a page + * boundary. + * @param cb Number of bytes to lock. This is rounded up to + * nearest page boundary. + * @param fAccess The desired access, a combination of RTMEM_PROT_READ + * and RTMEM_PROT_WRITE. + * @param R0Process The process to lock pages in. NIL_R0PROCESS is an + * alias for the current one. + * @param pszTag Allocation tag used for statistics and such. + * + * @remarks RTR0MemGetAddressR3() and RTR0MemGetAddress() will return therounded + * down address. + * + * @remarks Linux: This API requires that the memory begin locked is in a memory + * mapping that is not required in any forked off child process. This + * is not intented as permanent restriction, feel free to help out + * lifting it. + */ +RTR0DECL(int) RTR0MemObjLockUserTag(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, + RTR0PROCESS R0Process, const char *pszTag); + +/** + * Locks a range of kernel virtual memory (default tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param pv Kernel virtual address. This is rounded down to a page boundary. + * @param cb Number of bytes to lock. This is rounded up to nearest page boundary. + * @param fAccess The desired access, a combination of RTMEM_PROT_READ + * and RTMEM_PROT_WRITE. + * + * @remark RTR0MemGetAddress() will return the rounded down address. + */ +#define RTR0MemObjLockKernel(pMemObj, pv, cb, fAccess) \ + RTR0MemObjLockKernelTag((pMemObj), (pv), (cb), (fAccess), RTMEM_TAG) + +/** + * Locks a range of kernel virtual memory (custom tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param pv Kernel virtual address. This is rounded down to a page boundary. + * @param cb Number of bytes to lock. This is rounded up to nearest page boundary. + * @param fAccess The desired access, a combination of RTMEM_PROT_READ + * and RTMEM_PROT_WRITE. + * @param pszTag Allocation tag used for statistics and such. + * + * @remark RTR0MemGetAddress() will return the rounded down address. + */ +RTR0DECL(int) RTR0MemObjLockKernelTag(PRTR0MEMOBJ pMemObj, void *pv, size_t cb, uint32_t fAccess, const char *pszTag); + +/** + * Allocates contiguous page aligned physical memory without (necessarily) any + * kernel mapping (default tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param PhysHighest The highest permitable address (inclusive). + * Pass NIL_RTHCPHYS if any address is acceptable. + */ +#define RTR0MemObjAllocPhys(pMemObj, cb, PhysHighest) \ + RTR0MemObjAllocPhysTag((pMemObj), (cb), (PhysHighest), RTMEM_TAG) + +/** + * Allocates contiguous page aligned physical memory without (necessarily) any + * kernel mapping (custom tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param PhysHighest The highest permitable address (inclusive). + * Pass NIL_RTHCPHYS if any address is acceptable. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjAllocPhysTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag); + +/** + * Allocates contiguous physical memory without (necessarily) any kernel mapping + * (default tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param PhysHighest The highest permitable address (inclusive). + * Pass NIL_RTHCPHYS if any address is acceptable. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M, _4M and _1G. + */ +#define RTR0MemObjAllocPhysEx(pMemObj, cb, PhysHighest, uAlignment) \ + RTR0MemObjAllocPhysExTag((pMemObj), (cb), (PhysHighest), (uAlignment), RTMEM_TAG) + +/** + * Allocates contiguous physical memory without (necessarily) any kernel mapping + * (custom tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param PhysHighest The highest permitable address (inclusive). + * Pass NIL_RTHCPHYS if any address is acceptable. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M, _4M and _1G. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjAllocPhysExTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment, const char *pszTag); + +/** + * Allocates non-contiguous page aligned physical memory without (necessarily) + * any kernel mapping (default tag). + * + * This API is for allocating huge amounts of pages and will return + * VERR_NOT_SUPPORTED if this cannot be implemented in a satisfactory + * manner. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if it's not possible to allocated unmapped + * physical memory on this platform. The caller should expect + * this error and have a fallback strategy for it. + * + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param PhysHighest The highest permitable address (inclusive). + * Pass NIL_RTHCPHYS if any address is acceptable. + */ +#define RTR0MemObjAllocPhysNC(pMemObj, cb, PhysHighest) \ + RTR0MemObjAllocPhysNCTag((pMemObj), (cb), (PhysHighest), RTMEM_TAG) + +/** + * Allocates non-contiguous page aligned physical memory without (necessarily) + * any kernel mapping (custom tag). + * + * This API is for allocating huge amounts of pages and will return + * VERR_NOT_SUPPORTED if this cannot be implemented in a satisfactory + * manner. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if it's not possible to allocated unmapped + * physical memory on this platform. The caller should expect + * this error and have a fallback strategy for it. + * + * @param pMemObj Where to store the ring-0 memory object handle. + * @param cb Number of bytes to allocate. This is rounded up to nearest page. + * @param PhysHighest The highest permitable address (inclusive). + * Pass NIL_RTHCPHYS if any address is acceptable. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjAllocPhysNCTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag); + +/** Memory cache policy for RTR0MemObjEnterPhys. + * @{ + */ +/** Default caching policy -- don't care. */ +#define RTMEM_CACHE_POLICY_DONT_CARE UINT32_C(0) +/** MMIO caching policy -- uncachable. */ +#define RTMEM_CACHE_POLICY_MMIO UINT32_C(1) +/** @} */ + +/** + * Creates a page aligned, contiguous, physical memory object (default tag). + * + * No physical memory is allocated, we trust you do know what you're doing. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param Phys The physical address to start at. This is rounded down to the + * nearest page boundary. + * @param cb The size of the object in bytes. This is rounded up to nearest page boundary. + * @param uCachePolicy One of the RTMEM_CACHE_XXX modes. + */ +#define RTR0MemObjEnterPhys(pMemObj, Phys, cb, uCachePolicy) \ + RTR0MemObjEnterPhysTag((pMemObj), (Phys), (cb), (uCachePolicy), RTMEM_TAG) + +/** + * Creates a page aligned, contiguous, physical memory object (custom tag). + * + * No physical memory is allocated, we trust you do know what you're doing. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param Phys The physical address to start at. This is rounded down to the + * nearest page boundary. + * @param cb The size of the object in bytes. This is rounded up to nearest page boundary. + * @param uCachePolicy One of the RTMEM_CACHE_XXX modes. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjEnterPhysTag(PRTR0MEMOBJ pMemObj, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy, const char *pszTag); + +/** + * Reserves kernel virtual address space (default tag). + * + * If this function fails with VERR_NOT_SUPPORTED, the idea is that you + * can use RTR0MemObjEnterPhys() + RTR0MemObjMapKernel() as a fallback if + * you have a safe physical address range to make use of... + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param pvFixed Requested address. (void *)-1 means any address. This must match the alignment. + * @param cb The number of bytes to reserve. This is rounded up to nearest page. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + */ +#define RTR0MemObjReserveKernel(pMemObj, pvFixed, cb, uAlignment) \ + RTR0MemObjReserveKernelTag((pMemObj), (pvFixed), (cb), (uAlignment), RTMEM_TAG) + +/** + * Reserves kernel virtual address space (custom tag). + * + * If this function fails with VERR_NOT_SUPPORTED, the idea is that you + * can use RTR0MemObjEnterPhys() + RTR0MemObjMapKernel() as a fallback if + * you have a safe physical address range to make use of... + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param pvFixed Requested address. (void *)-1 means any address. This must match the alignment. + * @param cb The number of bytes to reserve. This is rounded up to nearest page. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjReserveKernelTag(PRTR0MEMOBJ pMemObj, void *pvFixed, size_t cb, size_t uAlignment, const char *pszTag); + +/** + * Reserves user virtual address space in the current process (default tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param R3PtrFixed Requested address. (RTR3PTR)-1 means any address. This must match the alignment. + * @param cb The number of bytes to reserve. This is rounded up to nearest PAGE_SIZE. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param R0Process The process to reserve the memory in. NIL_R0PROCESS is an alias for the current one. + */ +#define RTR0MemObjReserveUser(pMemObj, R3PtrFixed, cb, uAlignment, R0Process) \ + RTR0MemObjReserveUserTag((pMemObj), (R3PtrFixed), (cb), (uAlignment), (R0Process), RTMEM_TAG) + +/** + * Reserves user virtual address space in the current process (custom tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle. + * @param R3PtrFixed Requested address. (RTR3PTR)-1 means any address. This must match the alignment. + * @param cb The number of bytes to reserve. This is rounded up to nearest PAGE_SIZE. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param R0Process The process to reserve the memory in. NIL_R0PROCESS is an alias for the current one. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjReserveUserTag(PRTR0MEMOBJ pMemObj, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, + RTR0PROCESS R0Process, const char *pszTag); + +/** + * Maps a memory object into kernel virtual address space (default tag). + * + * This is the same as calling RTR0MemObjMapKernelEx with cbSub and offSub set + * to zero. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle of the mapping object. + * @param MemObjToMap The object to be map. + * @param pvFixed Requested address. (void *)-1 means any address. This must match the alignment. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param fProt Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE). + */ +#define RTR0MemObjMapKernel(pMemObj, MemObjToMap, pvFixed, uAlignment, fProt) \ + RTR0MemObjMapKernelTag((pMemObj), (MemObjToMap), (pvFixed), (uAlignment), (fProt), RTMEM_TAG) + +/** + * Maps a memory object into kernel virtual address space (custom tag). + * + * This is the same as calling RTR0MemObjMapKernelEx with cbSub and offSub set + * to zero. + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle of the mapping object. + * @param MemObjToMap The object to be map. + * @param pvFixed Requested address. (void *)-1 means any address. This must match the alignment. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param fProt Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE). + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjMapKernelTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, + size_t uAlignment, unsigned fProt, const char *pszTag); + +/** + * Maps a memory object into kernel virtual address space (default tag). + * + * The ability to map subsections of the object into kernel space is currently + * not implemented on all platforms. All/Most of platforms supports mapping the + * whole object into kernel space. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if it's not possible to map a subsection of a + * memory object on this platform. When you hit this, try implement it. + * + * @param pMemObj Where to store the ring-0 memory object handle of the mapping object. + * @param MemObjToMap The object to be map. + * @param pvFixed Requested address. (void *)-1 means any address. This must match the alignment. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param fProt Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE). + * @param offSub Where in the object to start mapping. If non-zero + * the value must be page aligned and cbSub must be + * non-zero as well. + * @param cbSub The size of the part of the object to be mapped. If + * zero the entire object is mapped. The value must be + * page aligned. + */ +#define RTR0MemObjMapKernelEx(pMemObj, MemObjToMap, pvFixed, uAlignment, fProt, offSub, cbSub) \ + RTR0MemObjMapKernelExTag((pMemObj), (MemObjToMap), (pvFixed), (uAlignment), (fProt), (offSub), (cbSub), RTMEM_TAG) + +/** + * Maps a memory object into kernel virtual address space (custom tag). + * + * The ability to map subsections of the object into kernel space is currently + * not implemented on all platforms. All/Most of platforms supports mapping the + * whole object into kernel space. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if it's not possible to map a subsection of a + * memory object on this platform. When you hit this, try implement it. + * + * @param pMemObj Where to store the ring-0 memory object handle of the mapping object. + * @param MemObjToMap The object to be map. + * @param pvFixed Requested address. (void *)-1 means any address. This must match the alignment. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param fProt Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE). + * @param offSub Where in the object to start mapping. If non-zero + * the value must be page aligned and cbSub must be + * non-zero as well. + * @param cbSub The size of the part of the object to be mapped. If + * zero the entire object is mapped. The value must be + * page aligned. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjMapKernelExTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment, + unsigned fProt, size_t offSub, size_t cbSub, const char *pszTag); + +/** + * Maps a memory object into user virtual address space in the current process + * (default tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle of the mapping object. + * @param MemObjToMap The object to be map. + * @param R3PtrFixed Requested address. (RTR3PTR)-1 means any address. This must match the alignment. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param fProt Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE). + * @param R0Process The process to map the memory into. NIL_R0PROCESS is an alias for the current one. + */ +#define RTR0MemObjMapUser(pMemObj, MemObjToMap, R3PtrFixed, uAlignment, fProt, R0Process) \ + RTR0MemObjMapUserTag((pMemObj), (MemObjToMap), (R3PtrFixed), (uAlignment), (fProt), (R0Process), RTMEM_TAG) + +/** + * Maps a memory object into user virtual address space in the current process + * (custom tag). + * + * @returns IPRT status code. + * @param pMemObj Where to store the ring-0 memory object handle of the mapping object. + * @param MemObjToMap The object to be map. + * @param R3PtrFixed Requested address. (RTR3PTR)-1 means any address. This must match the alignment. + * @param uAlignment The alignment of the reserved memory. + * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M. + * @param fProt Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE). + * @param R0Process The process to map the memory into. NIL_R0PROCESS is an alias for the current one. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR0DECL(int) RTR0MemObjMapUserTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed, + size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process, const char *pszTag); + +/** + * Change the page level protection of one or more pages in a memory object. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the OS doesn't provide any way to manipulate + * page level protection. The caller must handle this status code + * gracefully. (Note that it may also occur if the implementation is + * missing, in which case just go ahead and implement it.) + * + * @param hMemObj Memory object handle. + * @param offSub Offset into the memory object. Must be page aligned. + * @param cbSub Number of bytes to change the protection of. Must be + * page aligned. + * @param fProt Combination of RTMEM_PROT_* flags. + */ +RTR0DECL(int) RTR0MemObjProtect(RTR0MEMOBJ hMemObj, size_t offSub, size_t cbSub, uint32_t fProt); + +#endif /* IN_RING0 */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/memory b/include/iprt/memory new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/include/iprt/memory diff --git a/include/iprt/mempool.h b/include/iprt/mempool.h new file mode 100644 index 00000000..6be563d3 --- /dev/null +++ b/include/iprt/mempool.h @@ -0,0 +1,165 @@ +/** @file + * IPRT - Memory Allocation Pool. + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_mempool_h +#define ___iprt_mempool_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** + * Creates a new memory pool. + * + * @returns IPRT status code. + * + * @param phMemPool Where to return the handle to the new memory + * pool. + * @param pszName The name of the pool (for debug purposes). + */ +RTDECL(int) RTMemPoolCreate(PRTMEMPOOL phMemPool, const char *pszName); + +/** + * Destroys the specified pool, freeing all the memory it contains. + * + * @returns IPRT status code. + * + * @param hMemPool The handle to the pool. The nil handle and + * RTMEMPOOL_DEFAULT are quietly ignored (retval + * VINF_SUCCESS). + */ +RTDECL(int) RTMemPoolDestroy(RTMEMPOOL hMemPool); + +/** + * Allocates memory. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * + * @param hMemPool Handle to the pool to allocate the memory from. + * @param cb Size in bytes of the memory block to allocated. + */ +RTDECL(void *) RTMemPoolAlloc(RTMEMPOOL hMemPool, size_t cb) RT_NO_THROW; + +/** + * Allocates zero'd memory. + * + * Instead of memset(pv, 0, sizeof()) use this when you want zero'd + * memory. This keeps the code smaller and the heap can skip the memset + * in about 0.42% of calls :-). + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * + * @param hMemPool Handle to the pool to allocate the memory from. + * @param cb Size in bytes of the memory block to allocated. + */ +RTDECL(void *) RTMemPoolAllocZ(RTMEMPOOL hMemPool, size_t cb) RT_NO_THROW; + +/** + * Duplicates a chunk of memory into a new heap block. + * + * @returns New heap block with the duplicate data. + * @returns NULL if we're out of memory. + * + * @param hMemPool Handle to the pool to allocate the memory from. + * @param pvSrc The memory to duplicate. + * @param cb The amount of memory to duplicate. + */ +RTDECL(void *) RTMemPoolDup(RTMEMPOOL hMemPool, const void *pvSrc, size_t cb) RT_NO_THROW; + +/** + * Duplicates a chunk of memory into a new heap block with some + * additional zeroed memory. + * + * @returns New heap block with the duplicate data. + * @returns NULL if we're out of memory. + * + * @param hMemPool Handle to the pool to allocate the memory from. + * @param pvSrc The memory to duplicate. + * @param cbSrc The amount of memory to duplicate. + * @param cbExtra The amount of extra memory to allocate and zero. + */ +RTDECL(void *) RTMemPoolDupEx(RTMEMPOOL hMemPool, const void *pvSrc, size_t cbSrc, size_t cbExtra) RT_NO_THROW; + +/** + * Reallocates memory. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. + * + * @param hMemPool Handle to the pool containing the old memory. + * @param pvOld The memory block to reallocate. + * @param cbNew The new block size (in bytes). + */ +RTDECL(void *) RTMemPoolRealloc(RTMEMPOOL hMemPool, void *pvOld, size_t cbNew) RT_NO_THROW; + +/** + * Frees memory allocated from a pool. + * + * @param hMemPool Handle to the pool containing the memory. Passing + * NIL here is fine, but it may come at a slight + * performance cost. + * @param pv Pointer to memory block. + * + * @remarks This is the same a RTMemPoolRelease but included here as a separate + * function to simplify code migration. + */ +RTDECL(void) RTMemPoolFree(RTMEMPOOL hMemPool, void *pv) RT_NO_THROW; + +/** + * Retains a reference to a memory block in a pool. + * + * @returns New reference count, UINT32_MAX on error (asserted). + * + * @param pv Pointer to memory block. + */ +RTDECL(uint32_t) RTMemPoolRetain(void *pv) RT_NO_THROW; + +/** + * Releases a reference to a memory block in a pool. + * + * @returns New reference count, UINT32_MAX on error (asserted). + * + * @param hMemPool Handle to the pool containing the memory. Passing + * NIL here is fine, but it may come at a slight + * performance cost. + * @param pv Pointer to memory block. + */ +RTDECL(uint32_t) RTMemPoolRelease(RTMEMPOOL hMemPool, void *pv) RT_NO_THROW; + +/** + * Get the current reference count. + * + * @returns The reference count, UINT32_MAX on error (asserted). + * @param pv Pointer to memory block. + */ +RTDECL(uint32_t) RTMemPoolRefCount(void *pv) RT_NO_THROW; + + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/memtracker.h b/include/iprt/memtracker.h new file mode 100644 index 00000000..5d557b20 --- /dev/null +++ b/include/iprt/memtracker.h @@ -0,0 +1,236 @@ +/** @file + * IPRT - Memory Tracker. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_memtracker_h +#define ___iprt_memtracker_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/list.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_memtracker RTMemTracker - Memory Allocation Tracker. + * @ingroup grp_rt + * @{ + */ + +/** + * The allocation/free method. + */ +typedef enum RTMEMTRACKERMETHOD +{ + RTMEMTRACKERMETHOD_INVALID = 0, + RTMEMTRACKERMETHOD_ALLOC, + RTMEMTRACKERMETHOD_ALLOCZ, + RTMEMTRACKERMETHOD_REALLOC_PREP, /**< Internal, don't use. */ + RTMEMTRACKERMETHOD_REALLOC_DONE, /**< Internal, don't use. */ + RTMEMTRACKERMETHOD_REALLOC_FAILED, /**< Internal, don't use. */ + RTMEMTRACKERMETHOD_FREE, + + RTMEMTRACKERMETHOD_NEW, + RTMEMTRACKERMETHOD_NEW_ARRAY, + RTMEMTRACKERMETHOD_DELETE, + RTMEMTRACKERMETHOD_DELETE_ARRAY, + RTMEMTRACKERMETHOD_END, + RTMEMTRACKERMETHOD_32BIT_HACK = 0x7fffffff +} RTMEMTRACKERMETHOD; + +/** Pointer to a tag structure. */ +typedef struct RTMEMTRACKERTAG *PRTMEMTRACKERTAG; + +/** Pointer to a user structure. */ +typedef struct RTMEMTRACKERUSER *PRTMEMTRACKERUSER; + +/** + * Memory Tracking Header for use with RTMemTrackerHdrAlloc, + * RTMemTrackerHdrReallocPrep, RTMemTrackerHdrReallocDone and + * RTMemTrackerHdrFree. + */ +typedef struct RTMEMTRACKERHDR +{ + /** Magic value / eye catcher (RTMEMTRACKERHDR_MAGIC). */ + size_t uMagic; + /** The allocation size, user data only. */ + size_t cbUser; + /** The list entry. */ + RTLISTNODE ListEntry; + /** Pointer to the user structure where this header is linked. */ + PRTMEMTRACKERUSER pUser; + /** Pointer to the per-tag structure. */ + PRTMEMTRACKERTAG pTag; + /** The tag string. */ + const char *pszTag; + /** Pointer to the user data we're tracking. */ + void *pvUser; +} RTMEMTRACKERHDR; +/** Pointer to a memory tracker header. */ +typedef RTMEMTRACKERHDR *PRTMEMTRACKERHDR; +/** Pointer to a const memory tracker header. */ +typedef RTMEMTRACKERHDR *PPRTMEMTRACKERHDR; + +/** Magic value for RTMEMTRACKERHDR::uMagic (Kelly Link). */ +#if ARCH_BITS == 64 +# define RTMEMTRACKERHDR_MAGIC UINT64_C(0x1907691919690719) +#else +# define RTMEMTRACKERHDR_MAGIC UINT32_C(0x19690719) +#endif +/** Magic number used when reallocated. */ +#if ARCH_BITS == 64 +# define RTMEMTRACKERHDR_MAGIC_REALLOC UINT64_C(0x0000691919690000) +#else +# define RTMEMTRACKERHDR_MAGIC_REALLOC UINT32_C(0x19690000) +#endif +/** Magic number used when freed. */ +#define RTMEMTRACKERHDR_MAGIC_FREE (~RTMEMTRACKERHDR_MAGIC) + + +/** + * Initializes the allocation header and links it to the relevant tag. + * + * @returns Pointer to the user data part. + * @param pv The header + user data block. This must be at + * least @a cb + sizeof(RTMEMTRACKERHDR). + * @param cbUser The user data size (bytes). + * @param pszTag The tag string. + * @param enmMethod The method that the user called. + */ +RTDECL(void *) RTMemTrackerHdrAlloc(void *pv, size_t cbUser, const char *pszTag, RTMEMTRACKERMETHOD enmMethod); + +/** + * Prepares for a realloc, i.e. invalidates the header. + * + * @returns Pointer to the user data part. + * @param pvOldUser Pointer to the old user data. + * @param cbOldUser The size of the old user data, 0 if not + * known. + * @param pszTag The tag string. + */ +RTDECL(void *) RTMemTrackerHdrReallocPrep(void *pvOldUser, size_t cbOldUser, const char *pszTag); + +/** + * Initializes the allocation header and links it to the relevant tag. + * + * @returns Pointer to the user data part. + * @param pvNew The new header + user data block. This must be + * at least @a cb + sizeof(RTMEMTRACKERHDR). If + * this is NULL, we assume the realloc() call + * failed. + * @param cbNewUser The user data size (bytes). + * @param pvOldUser Pointer to the old user data. This is only + * valid on failure of course and used to bail out + * in that case. Should not be NULL. + * @param pszTag The tag string. + */ +RTDECL(void *) RTMemTrackerHdrReallocDone(void *pvNew, size_t cbNewUser, void *pvOldUser, const char *pszTag); + + +/** + * Do the accounting on free. + * + * @returns @a pv. + * @param pvUser Pointer to the user data. + * @param cbUser The size of the user data, 0 if not known. + * @param pszTag The tag string. + * @param enmMethod The method that the user called. + */ +RTDECL(void *) RTMemTrackerHdrFree(void *pvUser, size_t cbUser, const char *pszTag, RTMEMTRACKERMETHOD enmMethod); + + +/** + * Dumps all the allocations and tag statistics to the log. + */ +RTDECL(void) RTMemTrackerDumpAllToLog(void); + +/** + * Dumps all the allocations and tag statistics to the release log. + */ +RTDECL(void) RTMemTrackerDumpAllToLogRel(void); + +/** + * Dumps all the allocations and tag statistics to standard out. + */ +RTDECL(void) RTMemTrackerDumpAllToStdOut(void); + +/** + * Dumps all the allocations and tag statistics to standard err. + */ +RTDECL(void) RTMemTrackerDumpAllToStdErr(void); + +/** + * Dumps all the allocations and tag statistics to the specified filename. + */ +RTDECL(void) RTMemTrackerDumpAllToFile(const char *pszFilename); + + +/** + * Dumps all the tag statistics to the log. + * + * @param fVerbose Whether to print all the stats or just the ones + * relevant to hunting leaks. + */ +RTDECL(void) RTMemTrackerDumpStatsToLog(bool fVerbose); + +/** + * Dumps all the tag statistics to the release log. + * + * @param fVerbose Whether to print all the stats or just the ones + * relevant to hunting leaks. + */ +RTDECL(void) RTMemTrackerDumpStatsToLogRel(bool fVerbose); + +/** + * Dumps all the tag statistics to standard out. + * + * @param fVerbose Whether to print all the stats or just the ones + * relevant to hunting leaks. + */ +RTDECL(void) RTMemTrackerDumpStatsToStdOut(bool fVerbose); + +/** + * Dumps all the tag statistics to standard err. + * + * @param fVerbose Whether to print all the stats or just the ones + * relevant to hunting leaks. + */ +RTDECL(void) RTMemTrackerDumpStatsToStdErr(bool fVerbose); + +/** + * Dumps all the tag statistics to the specified filename. + * + * @param fVerbose Whether to print all the stats or just the ones + * relevant to hunting leaks. + * @param pszFilename The name of the file to dump to. + */ +RTDECL(void) RTMemTrackerDumpStatsToFile(bool fVerbose, const char *pszFilename); + + + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/message.h b/include/iprt/message.h new file mode 100644 index 00000000..b70a79be --- /dev/null +++ b/include/iprt/message.h @@ -0,0 +1,198 @@ +/** @file + * IPRT - Message Formatting. + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_msg_h +#define ___iprt_msg_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_msg RTMsg - Message Formatting + * @ingroup grp_rt + * @{ + */ + +/** + * Sets the program name to use. + * + * @returns IPRT status code. + * @param pszFormat The program name format string. + * @param ... Format arguments. + */ +RTDECL(int) RTMsgSetProgName(const char *pszFormat, ...); + +/** + * Print error message to standard error. + * + * The message will be prefixed with the file name part of process image name + * (i.e. no path) and "error: ". If the message doesn't end with a new line, + * one will be added. The caller should call this with an empty string if + * unsure whether the cursor is currently position at the start of a new line. + * + * @returns IPRT status code. + * @param pszFormat The message format string. + * @param ... Format arguments. + */ +RTDECL(int) RTMsgError(const char *pszFormat, ...); + +/** + * Print error message to standard error. + * + * The message will be prefixed with the file name part of process image name + * (i.e. no path) and "error: ". If the message doesn't end with a new line, + * one will be added. The caller should call this with an empty string if + * unsure whether the cursor is currently position at the start of a new line. + * + * @returns IPRT status code. + * @param pszFormat The message format string. + * @param va Format arguments. + */ +RTDECL(int) RTMsgErrorV(const char *pszFormat, va_list va); + +/** + * Same as RTMsgError() except for the return value. + * + * @returns @a enmExitCode + * @param enmExitCode What to exit code to return. This is mainly for + * saving some vertical space in the source file. + * @param pszFormat The message format string. + * @param ... Format arguments. + */ +RTDECL(RTEXITCODE) RTMsgErrorExit(RTEXITCODE enmExitcode, const char *pszFormat, ...); + +/** + * Same as RTMsgErrorV() except for the return value. + * + * @returns @a enmExitCode + * @param enmExitCode What to exit code to return. This is mainly for + * saving some vertical space in the source file. + * @param pszFormat The message format string. + * @param va Format arguments. + */ +RTDECL(RTEXITCODE) RTMsgErrorExitV(RTEXITCODE enmExitCode, const char *pszFormat, va_list va); + +/** + * Same as RTMsgError() except for the return value. + * + * @returns @a rcRet + * @param rcRet What IPRT status to return. This is mainly for + * saving some vertical space in the source file. + * @param pszFormat The message format string. + * @param ... Format arguments. + */ +RTDECL(int) RTMsgErrorRc(int rc, const char *pszFormat, ...); + +/** + * Same as RTMsgErrorV() except for the return value. + * + * @returns @a rcRet + * @param rcRet What IPRT status to return. This is mainly for + * saving some vertical space in the source file. + * @param pszFormat The message format string. + * @param va Format arguments. + */ +RTDECL(int) RTMsgErrorRcV(int rc, const char *pszFormat, va_list va); + +/** + * Print an error message for a RTR3Init failure and suggest an exit code. + * + * @code + * + * int rc = RTR3Init(); + * if (RT_FAILURE(rc)) + * return RTMsgInitFailure(rc); + * + * @endcode + * + * @returns Appropriate exit code. + * @param rcRTR3Init The status code returned by RTR3Init. + */ +RTDECL(RTEXITCODE) RTMsgInitFailure(int rcRTR3Init); + +/** + * Print informational message to standard error. + * + * The message will be prefixed with the file name part of process image name + * (i.e. no path) and "warning: ". If the message doesn't end with a new line, + * one will be added. The caller should call this with an empty string if + * unsure whether the cursor is currently position at the start of a new line. + * + * @returns IPRT status code. + * @param pszFormat The message format string. + * @param ... Format arguments. + */ +RTDECL(int) RTMsgWarning(const char *pszFormat, ...); + +/** + * Print informational message to standard error. + * + * The message will be prefixed with the file name part of process image name + * (i.e. no path) and "warning: ". If the message doesn't end with a new line, + * one will be added. The caller should call this with an empty string if + * unsure whether the cursor is currently position at the start of a new line. + * + * @returns IPRT status code. + * @param pszFormat The message format string. + * @param va Format arguments. + */ +RTDECL(int) RTMsgWarningV(const char *pszFormat, va_list va); + +/** + * Print informational message to standard output. + * + * The message will be prefixed with the file name part of process image name + * (i.e. no path) and "info: ". If the message doesn't end with a new line, + * one will be added. The caller should call this with an empty string if + * unsure whether the cursor is currently position at the start of a new line. + * + * @returns IPRT status code. + * @param pszFormat The message format string. + * @param ... Format arguments. + */ +RTDECL(int) RTMsgInfo(const char *pszFormat, ...); + +/** + * Print informational message to standard output. + * + * The message will be prefixed with the file name part of process image name + * (i.e. no path) and "info: ". If the message doesn't end with a new line, + * one will be added. The caller should call this with an empty string if + * unsure whether the cursor is currently position at the start of a new line. + * + * @returns IPRT status code. + * @param pszFormat The message format string. + * @param va Format arguments. + */ +RTDECL(int) RTMsgInfoV(const char *pszFormat, va_list va); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/mp.h b/include/iprt/mp.h new file mode 100644 index 00000000..70c0bf5e --- /dev/null +++ b/include/iprt/mp.h @@ -0,0 +1,365 @@ +/** @file + * IPRT - Multiprocessor. + */ + +/* + * Copyright (C) 2008 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. + */ + +#ifndef ___iprt_mp_h +#define ___iprt_mp_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_mp RTMp - Multiprocessor + * @ingroup grp_rt + * @{ + */ + +/** + * Gets the identifier of the CPU executing the call. + * + * When called from a system mode where scheduling is active, like ring-3 or + * kernel mode with interrupts enabled on some systems, no assumptions should + * be made about the current CPU when the call returns. + * + * @returns CPU Id. + */ +RTDECL(RTCPUID) RTMpCpuId(void); + +/** + * Converts a CPU identifier to a CPU set index. + * + * This may or may not validate the presence of the CPU. + * + * @returns The CPU set index on success, -1 on failure. + * @param idCpu The identifier of the CPU. + */ +RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu); + +/** + * Converts a CPU set index to a a CPU identifier. + * + * This may or may not validate the presence of the CPU, so, use + * RTMpIsCpuPossible for that. + * + * @returns The corresponding CPU identifier, NIL_RTCPUID on failure. + * @param iCpu The CPU set index. + */ +RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu); + +/** + * Gets the max CPU identifier (inclusive). + * + * Intended for brute force enumerations, but use with + * care as it may be expensive. + * + * @returns The current higest CPU identifier value. + */ +RTDECL(RTCPUID) RTMpGetMaxCpuId(void); + +/** + * Gets the size of a CPU array that is indexed by CPU set index. + * + * This takes both online, offline and hot-plugged cpus into account. + * + * @returns Number of elements. + * + * @remarks Use RTMpCpuIdToSetIndex to convert a RTCPUID into an array index. + */ +RTDECL(uint32_t) RTMpGetArraySize(void); + +/** + * Checks if a CPU exists in the system or may possibly be hotplugged later. + * + * @returns true/false accordingly. + * @param idCpu The identifier of the CPU. + */ +RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu); + +/** + * Gets set of the CPUs present in the system plus any that may + * possibly be hotplugged later. + * + * @returns pSet. + * @param pSet Where to put the set. + */ +RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet); + +/** + * Get the count of CPUs present in the system plus any that may + * possibly be hotplugged later. + * + * @returns The count. + * @remarks Don't use this for CPU array sizing, use RTMpGetArraySize instead. + */ +RTDECL(RTCPUID) RTMpGetCount(void); + + +/** + * Gets set of the CPUs present that are currently online. + * + * @returns pSet. + * @param pSet Where to put the set. + */ +RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet); + +/** + * Get the count of CPUs that are currently online. + * + * @return The count. + */ +RTDECL(RTCPUID) RTMpGetOnlineCount(void); + +/** + * Checks if a CPU is online or not. + * + * @returns true/false accordingly. + * @param idCpu The identifier of the CPU. + */ +RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu); + + +/** + * Gets set of the CPUs present in the system. + * + * @returns pSet. + * @param pSet Where to put the set. + */ +RTDECL(PRTCPUSET) RTMpGetPresentSet(PRTCPUSET pSet); + +/** + * Get the count of CPUs that are present in the system. + * + * @return The count. + */ +RTDECL(RTCPUID) RTMpGetPresentCount(void); + +/** + * Checks if a CPU is present in the system. + * + * @returns true/false accordingly. + * @param idCpu The identifier of the CPU. + */ +RTDECL(bool) RTMpIsCpuPresent(RTCPUID idCpu); + + +/** + * Get the current frequency of a CPU. + * + * The CPU must be online. + * + * @returns The frequency as MHz. 0 if the CPU is offline + * or the information is not available. + * @param idCpu The identifier of the CPU. + */ +RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu); + +/** + * Get the maximum frequency of a CPU. + * + * The CPU must be online. + * + * @returns The frequency as MHz. 0 if the CPU is offline + * or the information is not available. + * @param idCpu The identifier of the CPU. + */ +RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu); + +/** + * Get the CPU description string. + * + * The CPU must be online. + * + * @returns IPRT status code. + * @param idCpu The identifier of the CPU. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + */ +RTDECL(int) RTMpGetDescription(RTCPUID idCpu, char *pszBuf, size_t cbBuf); + + +#ifdef IN_RING0 + +/** + * Check if there's work (DPCs on Windows) pending on the current CPU. + * + * @return true if there's pending work on the current CPU, false otherwise. + */ +RTDECL(bool) RTMpIsCpuWorkPending(void); + + +/** + * Worker function passed to RTMpOnAll, RTMpOnOthers and RTMpOnSpecific that + * is to be called on the target cpus. + * + * @param idCpu The identifier for the CPU the function is called on. + * @param pvUser1 The 1st user argument. + * @param pvUser2 The 2nd user argument. + */ +typedef DECLCALLBACK(void) FNRTMPWORKER(RTCPUID idCpu, void *pvUser1, void *pvUser2); +/** Pointer to a FNRTMPWORKER. */ +typedef FNRTMPWORKER *PFNRTMPWORKER; + +/** + * Executes a function on each (online) CPU in the system. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system. + * + * @param pfnWorker The worker function. + * @param pvUser1 The first user argument for the worker. + * @param pvUser2 The second user argument for the worker. + * + * @remarks The execution isn't in any way guaranteed to be simultaneous, + * it might even be serial (cpu by cpu). + */ +RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2); + +/** + * Executes a function on a all other (online) CPUs in the system. + * + * The caller must disable preemption prior to calling this API if the outcome + * is to make any sense. But do *not* disable interrupts. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system. + * + * @param pfnWorker The worker function. + * @param pvUser1 The first user argument for the worker. + * @param pvUser2 The second user argument for the worker. + * + * @remarks The execution isn't in any way guaranteed to be simultaneous, + * it might even be serial (cpu by cpu). + */ +RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2); + +/** + * Executes a function on a specific CPU in the system. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the system. + * @retval VERR_CPU_OFFLINE if the CPU is offline. + * @retval VERR_CPU_NOT_FOUND if the CPU wasn't found. + * + * @param idCpu The id of the CPU. + * @param pfnWorker The worker function. + * @param pvUser1 The first user argument for the worker. + * @param pvUser2 The second user argument for the worker. + */ +RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2); + +/** + * Pokes the specified CPU. + * + * This should cause the execution on the CPU to be interrupted and forcing it + * to enter kernel context. It is optimized version of a RTMpOnSpecific call + * with a worker which returns immediately. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if this kind of operation isn't supported by the + * system. The caller must not automatically assume that this API works + * when any of the RTMpOn* APIs works. This is because not all systems + * supports unicast MP events and this API will not be implemented as a + * broadcast. + * @retval VERR_CPU_OFFLINE if the CPU is offline. + * @retval VERR_CPU_NOT_FOUND if the CPU wasn't found. + * + * @param idCpu The id of the CPU to poke. + */ +RTDECL(int) RTMpPokeCpu(RTCPUID idCpu); + + +/** + * MP event, see FNRTMPNOTIFICATION. + */ +typedef enum RTMPEVENT +{ + /** The CPU goes online. */ + RTMPEVENT_ONLINE = 1, + /** The CPU goes offline. */ + RTMPEVENT_OFFLINE +} RTMPEVENT; + +/** + * Notification callback. + * + * The context this is called in differs a bit from platform to + * platform, so be careful while in here. + * + * @param idCpu The CPU this applies to. + * @param enmEvent The event. + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(void) FNRTMPNOTIFICATION(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser); +/** Pointer to a FNRTMPNOTIFICATION(). */ +typedef FNRTMPNOTIFICATION *PFNRTMPNOTIFICATION; + +/** + * Registers a notification callback for cpu events. + * + * On platforms which doesn't do cpu offline/online events this API + * will just be a no-op that pretends to work. + * + * @todo We'll be adding a flag to this soon to indicate whether the callback should be called on all + * CPUs that are currently online while it's being registered. This is to help avoid some race + * conditions (we'll hopefully be able to implement this on linux, solaris/win is no issue). + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_NO_MEMORY if a registration record cannot be allocated. + * @retval VERR_ALREADY_EXISTS if the pfnCallback and pvUser already exist + * in the callback list. + * + * @param pfnCallback The callback. + * @param pvUser The user argument to the callback function. + */ +RTDECL(int) RTMpNotificationRegister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser); + +/** + * This deregisters a notification callback registered via RTMpNotificationRegister(). + * + * The pfnCallback and pvUser arguments must be identical to the registration call + * of we won't find the right entry. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_NOT_FOUND if no matching entry was found. + * + * @param pfnCallback The callback. + * @param pvUser The user argument to the callback function. + */ +RTDECL(int) RTMpNotificationDeregister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser); + +#endif /* IN_RING0 */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/net.h b/include/iprt/net.h new file mode 100644 index 00000000..38e066b9 --- /dev/null +++ b/include/iprt/net.h @@ -0,0 +1,816 @@ +/** @file + * IPRT - Network Protocols. + */ + +/* + * Copyright (C) 2008-2012 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. + */ + +#ifndef ___iprt_net_h +#define ___iprt_net_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/assert.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_net RTNet - Network Protocols + * @ingroup grp_rt + * @{ + */ + +/** + * IPv4 address. + */ +typedef RTUINT32U RTNETADDRIPV4; +AssertCompileSize(RTNETADDRIPV4, 4); +/** Pointer to a IPv4 address. */ +typedef RTNETADDRIPV4 *PRTNETADDRIPV4; +/** Pointer to a const IPv4 address. */ +typedef RTNETADDRIPV4 const *PCRTNETADDRIPV4; + +/** + * Tests if the given string is an IPv4 address. + * + * @returns boolean. + * @param pszAddress String which may be an IPv4 address. + */ +RTDECL(bool) RTNetIsIPv4AddrStr(const char *pszAddress); + + +/** + * IPv6 address. + */ +typedef RTUINT128U RTNETADDRIPV6; +AssertCompileSize(RTNETADDRIPV6, 16); +/** Pointer to a IPv6 address. */ +typedef RTNETADDRIPV6 *PRTNETADDRIPV6; +/** Pointer to a const IPv6 address. */ +typedef RTNETADDRIPV6 const *PCRTNETADDRIPV6; + +/** + * Tests if the given string is a valid IPv6 address. + * + * @returns @c true if it is, @c false if not. + * @param pszAddress String which may be an IPv6 address. + */ +RTDECL(bool) RTNetIsIPv6AddrStr(const char *pszAddress); + + +/** + * IPX address. + */ +#pragma pack(1) +typedef struct RTNETADDRIPX +{ + /** The network ID. */ + uint32_t Network; + /** The node ID. (Defaults to the MAC address apparently.) */ + RTMAC Node; +} RTNETADDRIPX; +#pragma pack() +AssertCompileSize(RTNETADDRIPX, 4+6); +/** Pointer to an IPX address. */ +typedef RTNETADDRIPX *PRTNETADDRIPX; +/** Pointer to a const IPX address. */ +typedef RTNETADDRIPX const *PCRTNETADDRIPX; + +/** + * Network address union. + * + * @remarks The size of this structure may change in the future. + */ +typedef union RTNETADDRU +{ + /** 64-bit view. */ + uint64_t au64[2]; + /** 32-bit view. */ + uint32_t au32[4]; + /** 16-bit view. */ + uint16_t au16[8]; + /** 8-bit view. */ + uint8_t au8[16]; + /** IPv4 view. */ + RTNETADDRIPV4 IPv4; +#ifndef IPv6 /* Work around X11 and RDP defining IPv6 to 1. */ + /** IPv6 view. */ + RTNETADDRIPV6 IPv6; +#endif + /** IPX view. */ + RTNETADDRIPX Ipx; + /** MAC address view. */ + RTMAC Mac; +} RTNETADDRU; +AssertCompileSize(RTNETADDRU, 16); +/** Pointer to an address union. */ +typedef RTNETADDRU *PRTNETADDRU; +/** Pointer to a const address union. */ +typedef RTNETADDRU const *PCRTNETADDRU; + +/** + * Network address type. + * + * @remarks The value assignments may change in the future. + */ +typedef enum RTNETADDRTYPE +{ + /** The invalid 0 entry. */ + RTNETADDRTYPE_INVALID = 0, + /** IP version 4. */ + RTNETADDRTYPE_IPV4, + /** IP version 6. */ + RTNETADDRTYPE_IPV6, + /** IPX. */ + RTNETADDRTYPE_IPX, + /** MAC address. */ + RTNETADDRTYPE_MAC, + /** The end of the valid values. */ + RTNETADDRTYPE_END, + /** The usual 32-bit hack. */ + RTNETADDRTYPE_32_BIT_HACK = 0x7fffffff +} RTNETADDRTYPE; +/** Pointer to a network address type. */ +typedef RTNETADDRTYPE *PRTNETADDRTYPE; +/** Pointer to a const network address type. */ +typedef RTNETADDRTYPE const *PCRTNETADDRTYPE; + +/** + * Network address. + * + * @remarks The size and type values may change. + */ +typedef struct RTNETADDR +{ + /** The address union. */ + RTNETADDRU uAddr; + /** Indicates which view of @a u that is valid. */ + RTNETADDRTYPE enmType; + /** The port number for IPv4 and IPv6 addresses. This is set to + * RTNETADDR_NA_PORT if not applicable. */ + uint32_t uPort; +} RTNETADDR; +/** Pointer to a network address. */ +typedef RTNETADDR *PRTNETADDR; +/** Pointer to a const network address. */ +typedef RTNETADDR const *PCRTNETADDR; + +/** The not applicable value of RTNETADDR::uPort value use to inid. */ +#define RTNETADDR_PORT_NA UINT32_MAX + +/** + * Ethernet header. + */ +#pragma pack(1) +typedef struct RTNETETHERHDR +{ + RTMAC DstMac; + RTMAC SrcMac; + /** Ethernet frame type or frame size, depending on the kind of ethernet. + * This is big endian on the wire. */ + uint16_t EtherType; +} RTNETETHERHDR; +#pragma pack() +AssertCompileSize(RTNETETHERHDR, 14); +/** Pointer to an ethernet header. */ +typedef RTNETETHERHDR *PRTNETETHERHDR; +/** Pointer to a const ethernet header. */ +typedef RTNETETHERHDR const *PCRTNETETHERHDR; + +/** @name EtherType (RTNETETHERHDR::EtherType) + * @{ */ +#define RTNET_ETHERTYPE_IPV4 UINT16_C(0x0800) +#define RTNET_ETHERTYPE_ARP UINT16_C(0x0806) +#define RTNET_ETHERTYPE_IPV6 UINT16_C(0x86dd) +#define RTNET_ETHERTYPE_VLAN UINT16_C(0x8100) +#define RTNET_ETHERTYPE_IPX_1 UINT16_C(0x8037) +#define RTNET_ETHERTYPE_IPX_2 UINT16_C(0x8137) +#define RTNET_ETHERTYPE_IPX_3 UINT16_C(0x8138) +/** @} */ + + +/** + * IPv4 header. + * All is bigendian on the wire. + */ +#pragma pack(1) +typedef struct RTNETIPV4 +{ +#ifdef RT_BIG_ENDIAN + unsigned int ip_v : 4; + unsigned int ip_hl : 4; + unsigned int ip_tos : 8; + unsigned int ip_len : 16; +#else + /** 00:0 - Header length given as a 32-bit word count. */ + unsigned int ip_hl : 4; + /** 00:4 - Header version. */ + unsigned int ip_v : 4; + /** 01 - Type of service. */ + unsigned int ip_tos : 8; + /** 02 - Total length (header + data). */ + unsigned int ip_len : 16; +#endif + /** 04 - Packet idenficiation. */ + uint16_t ip_id; + /** 06 - Offset if fragmented. */ + uint16_t ip_off; + /** 08 - Time to live. */ + uint8_t ip_ttl; + /** 09 - Protocol. */ + uint8_t ip_p; + /** 0a - Header check sum. */ + uint16_t ip_sum; + /** 0c - Source address. */ + RTNETADDRIPV4 ip_src; + /** 10 - Destination address. */ + RTNETADDRIPV4 ip_dst; + /** 14 - Options (optional). */ + uint32_t ip_options[1]; +} RTNETIPV4; +#pragma pack() +AssertCompileSize(RTNETIPV4, 6 * 4); +/** Pointer to a IPv4 header. */ +typedef RTNETIPV4 *PRTNETIPV4; +/** Pointer to a const IPv4 header. */ +typedef RTNETIPV4 const *PCRTNETIPV4; + +/** The minimum IPv4 header length (in bytes). + * Up to and including RTNETIPV4::ip_dst. */ +#define RTNETIPV4_MIN_LEN (20) + + +/** @name IPv4 Protocol Numbers + * @{ */ +/** IPv4: ICMP */ +#define RTNETIPV4_PROT_ICMP (1) +/** IPv4: TCP */ +#define RTNETIPV4_PROT_TCP (6) +/** IPv4: UDP */ +#define RTNETIPV4_PROT_UDP (17) +/** @} */ + +/** @name Common IPv4 Port Assignments + * @{ + */ +/** Boostrap Protocol / DHCP) Server. */ +#define RTNETIPV4_PORT_BOOTPS (67) +/** Boostrap Protocol / DHCP) Client. */ +#define RTNETIPV4_PORT_BOOTPC (68) +/** @} */ + +/** @name IPv4 Flags + * @{ */ +/** IPv4: Don't fragment */ +#define RTNETIPV4_FLAGS_DF (0x4000) +/** IPv4: More fragments */ +#define RTNETIPV4_FLAGS_MF (0x2000) +/** @} */ + +RTDECL(uint16_t) RTNetIPv4HdrChecksum(PCRTNETIPV4 pIpHdr); +RTDECL(bool) RTNetIPv4IsHdrValid(PCRTNETIPV4 pIpHdr, size_t cbHdrMax, size_t cbPktMax, bool fChecksum); +RTDECL(uint32_t) RTNetIPv4PseudoChecksum(PCRTNETIPV4 pIpHdr); +RTDECL(uint32_t) RTNetIPv4PseudoChecksumBits(RTNETADDRIPV4 SrcAddr, RTNETADDRIPV4 DstAddr, uint8_t bProtocol, uint16_t cbPkt); +RTDECL(uint32_t) RTNetIPv4AddDataChecksum(void const *pvData, size_t cbData, uint32_t u32Sum, bool *pfOdd); +RTDECL(uint16_t) RTNetIPv4FinalizeChecksum(uint32_t u32Sum); + + +/** + * IPv6 header. + * All is bigendian on the wire. + */ +#pragma pack(1) +typedef struct RTNETIPV6 +{ + /** Version (4 bits), Traffic Class (8 bits) and Flow Lable (20 bits). + * @todo this is probably mislabeled - ip6_flow vs. ip6_vfc, fix later. */ + uint32_t ip6_vfc; + /** 04 - Payload length, including extension headers. */ + uint16_t ip6_plen; + /** 06 - Next header type (RTNETIPV4_PROT_XXX). */ + uint8_t ip6_nxt; + /** 07 - Hop limit. */ + uint8_t ip6_hlim; + /** xx - Source address. */ + RTNETADDRIPV6 ip6_src; + /** xx - Destination address. */ + RTNETADDRIPV6 ip6_dst; +} RTNETIPV6; +#pragma pack() +AssertCompileSize(RTNETIPV6, 8 + 16 + 16); +/** Pointer to a IPv6 header. */ +typedef RTNETIPV6 *PRTNETIPV6; +/** Pointer to a const IPv6 header. */ +typedef RTNETIPV6 const *PCRTNETIPV6; + +/** The minimum IPv6 header length (in bytes). + * Up to and including RTNETIPV6::ip6_dst. */ +#define RTNETIPV6_MIN_LEN (40) + +RTDECL(uint32_t) RTNetIPv6PseudoChecksum(PCRTNETIPV6 pIpHdr); +RTDECL(uint32_t) RTNetIPv6PseudoChecksumEx(PCRTNETIPV6 pIpHdr, uint8_t bProtocol, uint16_t cbPkt); +RTDECL(uint32_t) RTNetIPv6PseudoChecksumBits(PCRTNETADDRIPV6 pSrcAddr, PCRTNETADDRIPV6 pDstAddr, + uint8_t bProtocol, uint16_t cbPkt); + + +/** + * UDP header. + */ +#pragma pack(1) +typedef struct RTNETUDP +{ + /** The source port. */ + uint16_t uh_sport; + /** The destination port. */ + uint16_t uh_dport; + /** The length of the UDP header and associated data. */ + uint16_t uh_ulen; + /** The checksum of the pseudo header, the UDP header and the data. */ + uint16_t uh_sum; +} RTNETUDP; +#pragma pack() +AssertCompileSize(RTNETUDP, 8); +/** Pointer to an UDP header. */ +typedef RTNETUDP *PRTNETUDP; +/** Pointer to a const UDP header. */ +typedef RTNETUDP const *PCRTNETUDP; + +/** The minimum UDP packet length (in bytes). (RTNETUDP::uh_ulen) */ +#define RTNETUDP_MIN_LEN (8) + +RTDECL(uint16_t) RTNetUDPChecksum(uint32_t u32Sum, PCRTNETUDP pUdpHdr); +RTDECL(uint32_t) RTNetIPv4AddUDPChecksum(PCRTNETUDP pUdpHdr, uint32_t u32Sum); +RTDECL(uint16_t) RTNetIPv4UDPChecksum(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, void const *pvData); +RTDECL(bool) RTNetIPv4IsUDPSizeValid(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, size_t cbPktMax); +RTDECL(bool) RTNetIPv4IsUDPValid(PCRTNETIPV4 pIpHdr, PCRTNETUDP pUdpHdr, void const *pvData, size_t cbPktMax, bool fChecksum); + + +/** + * IPv4 BOOTP / DHCP packet. + */ +#pragma pack(1) +typedef struct RTNETBOOTP +{ + /** 00 - The packet opcode (RTNETBOOTP_OP_*). */ + uint8_t bp_op; + /** 01 - Hardware address type. Same as RTNETARPHDR::ar_htype. */ + uint8_t bp_htype; + /** 02 - Hardware address length. */ + uint8_t bp_hlen; + /** 03 - Gateway hops. */ + uint8_t bp_hops; + /** 04 - Transaction ID. */ + uint32_t bp_xid; + /** 08 - Seconds since boot started. */ + uint16_t bp_secs; + /** 0a - Unused (BOOTP) / Flags (DHCP) (RTNET_DHCP_FLAGS_*). */ + uint16_t bp_flags; + /** 0c - Client IPv4 address. */ + RTNETADDRIPV4 bp_ciaddr; + /** 10 - Your IPv4 address. */ + RTNETADDRIPV4 bp_yiaddr; + /** 14 - Server IPv4 address. */ + RTNETADDRIPV4 bp_siaddr; + /** 18 - Gateway IPv4 address. */ + RTNETADDRIPV4 bp_giaddr; + /** 1c - Client hardware address. */ + union + { + uint8_t au8[16]; + RTMAC Mac; + } bp_chaddr; + /** 2c - Server name. */ + uint8_t bp_sname[64]; + /** 6c - File name / more DHCP options. */ + uint8_t bp_file[128]; + /** ec - Vendor specific area (BOOTP) / Options (DHCP). + * @remark This is really 312 bytes in the DHCP version. */ + union + { + uint8_t au8[128]; + struct DHCP + { + /** ec - The DHCP cookie (RTNET_DHCP_COOKIE). */ + uint32_t dhcp_cookie; + /** f0 - The DHCP options. */ + uint8_t dhcp_opts[124]; + } Dhcp; + } bp_vend; + +} RTNETBOOTP; +#pragma pack() +AssertCompileSize(RTNETBOOTP, 0xec + 128); +/** Pointer to a BOOTP / DHCP packet. */ +typedef RTNETBOOTP *PRTNETBOOTP; +/** Pointer to a const BOOTP / DHCP packet. */ +typedef RTNETBOOTP const *PCRTNETBOOTP; + +/** Minimum BOOTP packet length. For quick validation, no standard thing really. */ +#define RTNETBOOTP_MIN_LEN 0xec +/** Minimum DHCP packet length. For quick validation, no standard thing really. */ +#define RTNETBOOTP_DHCP_MIN_LEN 0xf1 + +/** The normal size of the a DHCP packet (i.e. a RTNETBOOTP). + * Same as RTNET_DHCP_OPT_SIZE, just expressed differently. */ +#define RTNET_DHCP_NORMAL_SIZE (0xec + 4 + RTNET_DHCP_OPT_SIZE) +/** The normal size of RTNETBOOTP::bp_vend::Dhcp::dhcp_opts. */ +#define RTNET_DHCP_OPT_SIZE (312 - 4) + +/** @name BOOTP packet opcode values + * @{ */ +#define RTNETBOOTP_OP_REQUEST 1 +#define RTNETBOOTP_OP_REPLY 2 +/** @} */ + +/** @name DHCP flags (RTNETBOOTP::bp_flags) + * @{ */ +#define RTNET_DHCP_FLAGS_NO_BROADCAST UINT16_C(0x8000) /** @todo check test!!! */ +/** @} */ + +/** The DHCP cookie (network endian). */ +#define RTNET_DHCP_COOKIE UINT32_C(0x63825363) + +/** + * An IPv4 DHCP option header. + */ +typedef struct RTNETDHCPOPT +{ + /** 00 - The DHCP option. */ + uint8_t dhcp_opt; + /** 01 - The data length (excluding this header). */ + uint8_t dhcp_len; + /* 02 - The option data follows here, optional and of variable length. */ +} RTNETDHCPOPT; +AssertCompileSize(RTNETDHCPOPT, 2); +/** Pointer to a DHCP option header. */ +typedef RTNETDHCPOPT *PRTNETDHCPOPT; +/** Pointer to a const DHCP option header. */ +typedef RTNETDHCPOPT const *PCRTNETDHCPOPT; + +/** @name DHCP options + * @{ */ +/** 1 byte padding, this has no dhcp_len field. */ +#define RTNET_DHCP_OPT_PAD 0 + +/** The subnet mask. */ +#define RTNET_DHCP_OPT_SUBNET_MASK 1 +/** The time offset. */ +#define RTNET_DHCP_OPT_TIME_OFFSET 2 +/** The routers for the subnet. */ +#define RTNET_DHCP_OPT_ROUTERS 3 +/** Domain Name Server. */ +#define RTNET_DHCP_OPT_DNS 6 +/** Host name. */ +#define RTNET_DHCP_OPT_HOST_NAME 12 +/** Domain name. */ +#define RTNET_DHCP_OPT_DOMAIN_NAME 15 + +/** The requested address. */ +#define RTNET_DHCP_OPT_REQ_ADDR 50 +/** The lease time in seconds. */ +#define RTNET_DHCP_OPT_LEASE_TIME 51 +/** Option overload. + * Indicates that the bp_file and/or bp_sname holds contains DHCP options. */ +#define RTNET_DHCP_OPT_OPTION_OVERLOAD 52 +/** Have a 8-bit message type value as data, see RTNET_DHCP_MT_*. */ +#define RTNET_DHCP_OPT_MSG_TYPE 53 +/** Server ID. */ +#define RTNET_DHCP_OPT_SERVER_ID 54 +/** Parameter request list. */ +#define RTNET_DHCP_OPT_PARAM_REQ_LIST 55 +/** The maximum DHCP message size a client is willing to accept. */ +#define RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE 57 +/** Client ID. */ +#define RTNET_DHCP_OPT_CLIENT_ID 61 +/** TFTP server name. */ +#define RTNET_DHCP_OPT_TFTP_SERVER_NAME 66 +/** Bootfile name. */ +#define RTNET_DHCP_OPT_BOOTFILE_NAME 67 + +/** Marks the end of the DHCP options, this has no dhcp_len field. */ +#define RTNET_DHCP_OPT_END 255 +/** @} */ + +/** @name DHCP Message Types (option 53) + * @{ */ +#define RTNET_DHCP_MT_DISCOVER 1 +#define RTNET_DHCP_MT_OFFER 2 +#define RTNET_DHCP_MT_REQUEST 3 +#define RTNET_DHCP_MT_DECLINE 4 +#define RTNET_DHCP_MT_ACK 5 +#define RTNET_DHCP_MT_NAC 6 +#define RTNET_DHCP_MT_RELEASE 7 +#define RTNET_DHCP_MT_INFORM 8 +/** @} */ + +/** @name DHCP Flags + * @{ */ +#define RTNET_DHCP_FLAG_BROADCAST 0x8000 +/** @} */ + +RTDECL(bool) RTNetIPv4IsDHCPValid(PCRTNETUDP pUdpHdr, PCRTNETBOOTP pDhcp, size_t cbDhcp, uint8_t *pMsgType); + + +/** + * IPv4 DHCP packet. + * @deprecated Use RTNETBOOTP. + */ +#pragma pack(1) +typedef struct RTNETDHCP +{ + /** 00 - The packet opcode. */ + uint8_t Op; + /** Hardware address type. */ + uint8_t HType; + /** Hardware address length. */ + uint8_t HLen; + uint8_t Hops; + uint32_t XID; + uint16_t Secs; + uint16_t Flags; + /** Client IPv4 address. */ + RTNETADDRIPV4 CIAddr; + /** Your IPv4 address. */ + RTNETADDRIPV4 YIAddr; + /** Server IPv4 address. */ + RTNETADDRIPV4 SIAddr; + /** Gateway IPv4 address. */ + RTNETADDRIPV4 GIAddr; + /** Client hardware address. */ + uint8_t CHAddr[16]; + /** Server name. */ + uint8_t SName[64]; + uint8_t File[128]; + uint8_t abMagic[4]; + uint8_t DhcpOpt; + uint8_t DhcpLen; /* 1 */ + uint8_t DhcpReq; + uint8_t abOptions[57]; +} RTNETDHCP; +#pragma pack() +/** @todo AssertCompileSize(RTNETDHCP, ); */ +/** Pointer to a DHCP packet. */ +typedef RTNETDHCP *PRTNETDHCP; +/** Pointer to a const DHCP packet. */ +typedef RTNETDHCP const *PCRTNETDHCP; + + +/** + * TCP packet. + */ +#pragma pack(1) +typedef struct RTNETTCP +{ + /** 00 - The source port. */ + uint16_t th_sport; + /** 02 - The destination port. */ + uint16_t th_dport; + /** 04 - The sequence number. */ + uint32_t th_seq; + /** 08 - The acknowledgement number. */ + uint32_t th_ack; +#ifdef RT_BIG_ENDIAN + unsigned int th_win : 16; + unsigned int th_flags : 8; + unsigned int th_off : 4; + unsigned int th_x2 : 4; +#else + /** 0c:0 - Reserved. */ + unsigned int th_x2 : 4; + /** 0c:4 - The data offset given as a dword count from the start of this header. */ + unsigned int th_off : 4; + /** 0d - flags. */ + unsigned int th_flags : 8; + /** 0e - The window. */ + unsigned int th_win : 16; +#endif + /** 10 - The checksum of the pseudo header, the TCP header and the data. */ + uint16_t th_sum; + /** 12 - The urgent pointer. */ + uint16_t th_urp; + /* (options follows here and then the data (aka text).) */ +} RTNETTCP; +#pragma pack() +AssertCompileSize(RTNETTCP, 20); +/** Pointer to a TCP packet. */ +typedef RTNETTCP *PRTNETTCP; +/** Pointer to a const TCP packet. */ +typedef RTNETTCP const *PCRTNETTCP; + +/** The minimum TCP header length (in bytes). (RTNETTCP::th_off * 4) */ +#define RTNETTCP_MIN_LEN (20) + +/** @name TCP flags (RTNETTCP::th_flags) + * @{ */ +#define RTNETTCP_F_FIN 0x01 +#define RTNETTCP_F_SYN 0x02 +#define RTNETTCP_F_RST 0x04 +#define RTNETTCP_F_PSH 0x08 +#define RTNETTCP_F_ACK 0x10 +#define RTNETTCP_F_URG 0x20 +#define RTNETTCP_F_ECE 0x40 +#define RTNETTCP_F_CWR 0x80 +/** @} */ + +RTDECL(uint16_t) RTNetTCPChecksum(uint32_t u32Sum, PCRTNETTCP pTcpHdr, void const *pvData, size_t cbData); +RTDECL(uint32_t) RTNetIPv4AddTCPChecksum(PCRTNETTCP pTcpHdr, uint32_t u32Sum); +RTDECL(uint16_t) RTNetIPv4TCPChecksum(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, void const *pvData); +RTDECL(bool) RTNetIPv4IsTCPSizeValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, size_t cbPktMax); +RTDECL(bool) RTNetIPv4IsTCPValid(PCRTNETIPV4 pIpHdr, PCRTNETTCP pTcpHdr, size_t cbHdrMax, void const *pvData, + size_t cbPktMax, bool fChecksum); + + +/** + * IPv4 ICMP packet header. + */ +#pragma pack(1) +typedef struct RTNETICMPV4HDR +{ + /** 00 - The ICMP message type. */ + uint8_t icmp_type; + /** 01 - Type specific code that further qualifies the message. */ + uint8_t icmp_code; + /** 02 - Checksum of the ICMP message. */ + uint16_t icmp_cksum; +} RTNETICMPV4HDR; +#pragma pack() +AssertCompileSize(RTNETICMPV4HDR, 4); +/** Pointer to an ICMP packet header. */ +typedef RTNETICMPV4HDR *PRTNETICMPV4HDR; +/** Pointer to a const ICMP packet header. */ +typedef RTNETICMPV4HDR const *PCRTNETICMPV4HDR; + +/** @name ICMP (v4) message types. + * @{ */ +#define RTNETICMPV4_TYPE_ECHO_REPLY 0 +#define RTNETICMPV4_TYPE_ECHO_REQUEST 8 +#define RTNETICMPV4_TYPE_TRACEROUTE 30 +/** @} */ + +/** + * IPv4 ICMP ECHO Reply & Request packet. + */ +#pragma pack(1) +typedef struct RTNETICMPV4ECHO +{ + /** 00 - The ICMP header. */ + RTNETICMPV4HDR Hdr; + /** 04 - The identifier to help the requestor match up the reply. + * Can be 0. Typically fixed value. */ + uint16_t icmp_id; + /** 06 - The sequence number to help the requestor match up the reply. + * Can be 0. Typically incrementing between requests. */ + uint16_t icmp_seq; + /** 08 - Variable length data that is to be returned unmodified in the reply. */ + uint8_t icmp_data[1]; +} RTNETICMPV4ECHO; +#pragma pack() +AssertCompileSize(RTNETICMPV4ECHO, 9); +/** Pointer to an ICMP ECHO packet. */ +typedef RTNETICMPV4ECHO *PRTNETICMPV4ECHO; +/** Pointer to a const ICMP ECHO packet. */ +typedef RTNETICMPV4ECHO const *PCRTNETICMPV4ECHO; + +/** + * IPv4 ICMP TRACEROUTE packet. + * This is an reply to an IP packet with the traceroute option set. + */ +#pragma pack(1) +typedef struct RTNETICMPV4TRACEROUTE +{ + /** 00 - The ICMP header. */ + RTNETICMPV4HDR Hdr; + /** 04 - Identifier copied from the traceroute option's ID number. */ + uint16_t icmp_id; + /** 06 - Unused. (Possibly an icmp_seq?) */ + uint16_t icmp_void; + /** 08 - Outbound hop count. From the IP packet causing this message. */ + uint16_t icmp_ohc; + /** 0a - Return hop count. From the IP packet causing this message. */ + uint16_t icmp_rhc; + /** 0c - Output link speed, 0 if not known. */ + uint32_t icmp_speed; + /** 10 - Output link MTU, 0 if not known. */ + uint32_t icmp_mtu; +} RTNETICMPV4TRACEROUTE; +#pragma pack() +AssertCompileSize(RTNETICMPV4TRACEROUTE, 20); +/** Pointer to an ICMP TRACEROUTE packet. */ +typedef RTNETICMPV4TRACEROUTE *PRTNETICMPV4TRACEROUTE; +/** Pointer to a const ICMP TRACEROUTE packet. */ +typedef RTNETICMPV4TRACEROUTE const *PCRTNETICMPV4TRACEROUTE; + +/** @todo add more ICMPv4 as needed. */ + +/** + * IPv4 ICMP union packet. + */ +typedef union RTNETICMPV4 +{ + RTNETICMPV4HDR Hdr; + RTNETICMPV4ECHO Echo; + RTNETICMPV4TRACEROUTE Traceroute; +} RTNETICMPV4; +/** Pointer to an ICMP union packet. */ +typedef RTNETICMPV4 *PRTNETICMPV4; +/** Pointer to a const ICMP union packet. */ +typedef RTNETICMPV4 const *PCRTNETICMPV4; + + +/** @todo add ICMPv6 when needed. */ + + +/** + * Ethernet ARP header. + */ +#pragma pack(1) +typedef struct RTNETARPHDR +{ + /** The hardware type. */ + uint16_t ar_htype; + /** The protocol type (ethertype). */ + uint16_t ar_ptype; + /** The hardware address length. */ + uint8_t ar_hlen; + /** The protocol address length. */ + uint8_t ar_plen; + /** The operation. */ + uint16_t ar_oper; +} RTNETARPHDR; +#pragma pack() +AssertCompileSize(RTNETARPHDR, 8); +/** Pointer to an ethernet ARP header. */ +typedef RTNETARPHDR *PRTNETARPHDR; +/** Pointer to a const ethernet ARP header. */ +typedef RTNETARPHDR const *PCRTNETARPHDR; + +/** ARP hardware type - ethernet. */ +#define RTNET_ARP_ETHER UINT16_C(1) + +/** @name ARP operations + * @{ */ +#define RTNET_ARPOP_REQUEST UINT16_C(1) /**< Request hardware address given a protocol address (ARP). */ +#define RTNET_ARPOP_REPLY UINT16_C(2) +#define RTNET_ARPOP_REVREQUEST UINT16_C(3) /**< Request protocol address given a hardware address (RARP). */ +#define RTNET_ARPOP_REVREPLY UINT16_C(4) +#define RTNET_ARPOP_INVREQUEST UINT16_C(8) /**< Inverse ARP. */ +#define RTNET_ARPOP_INVREPLY UINT16_C(9) +/** Check if an ARP operation is a request or not. */ +#define RTNET_ARPOP_IS_REQUEST(Op) ((Op) & 1) +/** Check if an ARP operation is a reply or not. */ +#define RTNET_ARPOP_IS_REPLY(Op) (!RTNET_ARPOP_IS_REQUEST(Op)) +/** @} */ + + +/** + * Ethernet IPv4 + 6-byte MAC ARP request packet. + */ +#pragma pack(1) +typedef struct RTNETARPIPV4 +{ + /** ARP header. */ + RTNETARPHDR Hdr; + /** The sender hardware address. */ + RTMAC ar_sha; + /** The sender protocol address. */ + RTNETADDRIPV4 ar_spa; + /** The target hardware address. */ + RTMAC ar_tha; + /** The arget protocol address. */ + RTNETADDRIPV4 ar_tpa; +} RTNETARPIPV4; +#pragma pack() +AssertCompileSize(RTNETARPIPV4, 8+6+4+6+4); +/** Pointer to an ethernet IPv4+MAC ARP request packet. */ +typedef RTNETARPIPV4 *PRTNETARPIPV4; +/** Pointer to a const ethernet IPv4+MAC ARP request packet. */ +typedef RTNETARPIPV4 const *PCRTNETARPIPV4; + + +/** @todo RTNETNDP (IPv6)*/ + + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/nocrt/amd64/fenv.h b/include/iprt/nocrt/amd64/fenv.h new file mode 100644 index 00000000..002aa01f --- /dev/null +++ b/include/iprt/nocrt/amd64/fenv.h @@ -0,0 +1,232 @@ +/** @file + * IPRT / No-CRT - fenv.h, AMD64. + */ + +/* + * Copyright (C) 2006-2007 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. + * -------------------------------------------------------------------- + * + * This code is based on: + * + * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ___iprt_nocrt_amd64_fenv_h +#define ___iprt_nocrt_amd64_fenv_h + +#include <iprt/types.h> + +typedef struct { + struct { + uint32_t __control; + uint32_t __status; + uint32_t __tag; + char __other[16]; + } __x87; + uint32_t __mxcsr; +} fenv_t; + +typedef uint16_t fexcept_t; + +/* Exception flags */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* Rounding modes */ +#define FE_TONEAREST 0x0000 +#define FE_DOWNWARD 0x0400 +#define FE_UPWARD 0x0800 +#define FE_TOWARDZERO 0x0c00 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) + +/* + * As compared to the x87 control word, the SSE unit's control word + * has the rounding control bits offset by 3 and the exception mask + * bits offset by 7. + */ +#define _SSE_ROUND_SHIFT 3 +#define _SSE_EMASK_SHIFT 7 + +RT_C_DECLS_BEGIN + +/* Default floating-point environment */ +extern const fenv_t RT_NOCRT(__fe_dfl_env); +#define FE_DFL_ENV (&__fe_dfl_env) + +#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw)) +#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env)) +#define __fnclex() __asm __volatile("fnclex") +#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env))) +#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw))) +#define __fnstsw(__sw) __asm __volatile("fnstsw %0" : "=am" (*(__sw))) +#define __fwait() __asm __volatile("fwait") +#define __ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr)) +#define __stmxcsr(__csr) __asm __volatile("stmxcsr %0" : "=m" (*(__csr))) + +DECLINLINE(int) +feclearexcept(int __excepts) +{ + fenv_t __env; + + if (__excepts == FE_ALL_EXCEPT) { + __fnclex(); + } else { + __fnstenv(&__env.__x87); + __env.__x87.__status &= ~__excepts; + __fldenv(__env.__x87); + } + __stmxcsr(&__env.__mxcsr); + __env.__mxcsr &= ~__excepts; + __ldmxcsr(__env.__mxcsr); + return (0); +} + +DECLINLINE(int) +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + int __mxcsr, __status; + + __stmxcsr(&__mxcsr); + __fnstsw(&__status); + *__flagp = (__mxcsr | __status) & __excepts; + return (0); +} + +int RT_NOCRT(fesetexceptflag)(const fexcept_t *__flagp, int __excepts); +int RT_NOCRT(feraiseexcept)(int __excepts); + +DECLINLINE(int) +fetestexcept(int __excepts) +{ + int __mxcsr, __status; + + __stmxcsr(&__mxcsr); + __fnstsw(&__status); + return ((__status | __mxcsr) & __excepts); +} + +DECLINLINE(int) +fegetround(void) +{ + int __control; + + /* + * We assume that the x87 and the SSE unit agree on the + * rounding mode. Reading the control word on the x87 turns + * out to be about 5 times faster than reading it on the SSE + * unit on an Opteron 244. + */ + __fnstcw(&__control); + return (__control & _ROUND_MASK); +} + +DECLINLINE(int) +fesetround(int __round) +{ + int __mxcsr, __control; + + if (__round & ~_ROUND_MASK) + return (-1); + + __fnstcw(&__control); + __control &= ~_ROUND_MASK; + __control |= __round; + __fldcw(__control); + + __stmxcsr(&__mxcsr); + __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); + __mxcsr |= __round << _SSE_ROUND_SHIFT; + __ldmxcsr(__mxcsr); + + return (0); +} + +int RT_NOCRT(fegetenv)(fenv_t *__envp); +int RT_NOCRT(feholdexcept)(fenv_t *__envp); + +DECLINLINE(int) +fesetenv(const fenv_t *__envp) +{ + + __fldenv(__envp->__x87); + __ldmxcsr(__envp->__mxcsr); + return (0); +} + +int RT_NOCRT(feupdateenv)(const fenv_t *__envp); +int RT_NOCRT(feenableexcept)(int __mask); +int RT_NOCRT(fedisableexcept)(int __mask); + +DECLINLINE(int) +fegetexcept(void) +{ + int __control; + + /* + * We assume that the masks for the x87 and the SSE unit are + * the same. + */ + __fnstcw(&__control); + return (~__control & FE_ALL_EXCEPT); +} + +RT_C_DECLS_END + +#ifndef RT_WITHOUT_NOCRT_WRAPPERS +# define fesetexceptflag RT_NOCRT(fesetexceptflag) +# define feraiseexcept RT_NOCRT(feraiseexcept) +# define fegetenv RT_NOCRT(fegetenv) +# define feholdexcept RT_NOCRT(feholdexcept) +# define feupdateenv RT_NOCRT(feupdateenv) +# define feenableexcept RT_NOCRT(feenableexcept) +# define fedisableexcept RT_NOCRT(fedisableexcept) +# define __fe_dfl_env RT_NOCRT(__fe_dfl_env) +#endif + +#endif /* !__iprt_nocrt_amd64_fenv_h__ */ diff --git a/include/iprt/nocrt/amd64/math.h b/include/iprt/nocrt/amd64/math.h new file mode 100644 index 00000000..8d1e6536 --- /dev/null +++ b/include/iprt/nocrt/amd64/math.h @@ -0,0 +1,102 @@ +/** @file + * IPRT / No-CRT - math.h, AMD inlined functions. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_amd64_math_h +#define ___iprt_nocrt_amd64_math_h + +#include <iprt/asm.h> + + +#if RT_INLINE_ASM_GNU_STYLE && defined(__SSE__) + +DECLINLINE(long double) inline_atan2l(long double lrd1, long double lrd2) +{ + long double lrdResult; + __asm__ __volatile__("fpatan" + : "=t" (lrdResult) + : "u" (lrd1), + "0" (lrd2) + : "st(1)"); + return lrdResult; +} + +DECLINLINE(long double) inline_rintl(long double lrd) +{ + long double lrdResult; + __asm__ __volatile__("frndint" + : "=t" (lrdResult) + : "0" (lrd)); + return lrdResult; +} + +DECLINLINE(float) inline_rintf(float rf) +{ + return (float)inline_rintl(rf); +} + +DECLINLINE(double) inline_rint(double rd) +{ + return (double)inline_rintl(rd); +} + +DECLINLINE(long double) inline_sqrtl(long double lrd) +{ + long double lrdResult; + __asm__ __volatile__("fsqrt" + : "=t" (lrdResult) + : "0" (lrd)); + return lrdResult; +} + +DECLINLINE(float) inline_sqrtf(float rf) +{ + return (float)inline_sqrtl(rf); +} + +DECLINLINE(double) inline_sqrt(double rd) +{ + return (double)inline_sqrtl(rd); +} + + +# undef atan2l +# define atan2l(lrd1, lrd2) inline_atan2l(lrd1, lrd2) +# undef rint +# define rint(rd) inline_rint(rd) +# undef rintf +# define rintf(rf) inline_rintf(rf) +# undef rintl +# define rintl(lrd) inline_rintl(lrd) +# undef sqrt +# define sqrt(rd) inline_sqrt(rd) +# undef sqrtf +# define sqrtf(rf) inline_sqrtf(rf) +# undef sqrtl +# define sqrtl(lrd) inline_sqrtl(lrd) + +#endif /* RT_INLINE_ASM_GNU_STYLE */ + +#endif + diff --git a/include/iprt/nocrt/compiler/compiler.h b/include/iprt/nocrt/compiler/compiler.h new file mode 100644 index 00000000..ea9f8952 --- /dev/null +++ b/include/iprt/nocrt/compiler/compiler.h @@ -0,0 +1,37 @@ +/** @file + * IPRT / No-CRT - compiler specifics. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_compiler_compiler_h +#define ___iprt_nocrt_compiler_compiler_h + +#ifdef __GNUC__ +# include <iprt/nocrt/compiler/gcc.h> +#elif defined(_MSC_VER) +# include <iprt/nocrt/compiler/msc.h> +#else +# error "Unsupported compiler." +#endif + +#endif diff --git a/include/iprt/nocrt/compiler/gcc.h b/include/iprt/nocrt/compiler/gcc.h new file mode 100644 index 00000000..890448b3 --- /dev/null +++ b/include/iprt/nocrt/compiler/gcc.h @@ -0,0 +1,121 @@ +/** @file + * IPRT / No-CRT - GCC specifics. + * + * A quick hack for freebsd where there are no separate location + * for compiler specific headers like on linux, mingw, os2, ++. + * This file will be cleaned up later... + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_compiler_gcc_h +#define ___iprt_nocrt_compiler_gcc_h + + +/* stddef.h */ +#ifdef __PTRDIFF_TYPE__ +typedef __PTRDIFF_TYPE__ ptrdiff_t; +#elif ARCH_BITS == 32 +typedef int32_t ptrdiff_t; +#elif ARCH_BITS == 64 +typedef int64_t ptrdiff_t; +#else +# error "ARCH_BITS is undefined or incorrect." +#endif +#define _PTRDIFF_T_DECLARED + +#ifdef __SIZE_TYPE__ +typedef __SIZE_TYPE__ size_t; +#elif ARCH_BITS == 32 +typedef uint32_t size_t; +#elif ARCH_BITS == 64 +typedef uint64_t size_t; +#else +# error "ARCH_BITS is undefined or incorrect." +#endif +#define _SIZE_T_DECLARED + +#ifndef __cplusplus +# ifdef __WCHAR_TYPE__ +typedef __WCHAR_TYPE__ wchar_t; +# elif defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +typedef uint16_t wchar_t; +# else +typedef int wchar_t; +# endif +# define _WCHAR_T_DECLARED +#endif + +#ifdef __WINT_TYPE__ +typedef __WINT_TYPE__ wint_t; +#else +typedef unsigned int wint_t; +#endif +#define _WINT_T_DECLARED + +#ifndef NULL +# ifdef __cplusplus +# define NULL 0 +# else +# define NULL ((void *)0) +# endif +#endif + + +#ifndef offsetof +# if defined(__cplusplus) && defined(__offsetof__) +# define offsetof(type, memb) + (__offsetof__ (reinterpret_cast<size_t>(&reinterpret_cast<const volatile char &>(static_cast<type *>(0)->memb))) ) +# else +# define offsetof(type, memb) ((size_t)&((type *)0)->memb) +# endif +#endif + + +/* sys/types.h */ +#ifdef __SSIZE_TYPE__ +typedef __SSIZE_TYPE__ ssize_t; +#elif ARCH_BITS == 32 +typedef int32_t ssize_t; +#elif ARCH_BITS == 64 +typedef int64_t ssize_t; +#else +# define ARCH_BITS 123123 +# error "ARCH_BITS is undefined or incorrect." +#endif +#define _SSIZE_T_DECLARED + + +/* stdarg.h */ +typedef __builtin_va_list va_list; +#if __GNUC__ == 3 \ + && __GNUC_MINOR__ == 2 +# define va_start(va, arg) __builtin_stdarg_start(va, arg) +#else +# define va_start(va, arg) __builtin_va_start(va, arg) +#endif +#define va_end(va) __builtin_va_end(va) +#define va_arg(va, type) __builtin_va_arg(va, type) +#define va_copy(dst, src) __builtin_va_copy(dst, src) + + +#endif diff --git a/include/iprt/nocrt/compiler/msc.h b/include/iprt/nocrt/compiler/msc.h new file mode 100644 index 00000000..1fbb3a14 --- /dev/null +++ b/include/iprt/nocrt/compiler/msc.h @@ -0,0 +1,45 @@ +/** @file + * IPRT / No-CRT - MSC specifics. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_compiler_msc_h +#define ___iprt_nocrt_compiler_msc_h + + +/* stddef.h */ +#if !defined(_MT) && !defined(_DLL) && _MSC_VER < 1400 +# define errno msvcrt_errno +#endif +#include <../include/stddef.h> +#undef errno + +#undef ssize_t +typedef intptr_t ssize_t; + + +/* stdarg.h */ +#include <../include/stdarg.h> + +#endif + diff --git a/include/iprt/nocrt/fenv.h b/include/iprt/nocrt/fenv.h new file mode 100644 index 00000000..32d8163c --- /dev/null +++ b/include/iprt/nocrt/fenv.h @@ -0,0 +1,38 @@ +/** @file + * IPRT / No-CRT - fenv.h wrapper. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_fenv_h +#define ___iprt_nocrt_fenv_h + +#include <iprt/cdefs.h> +#ifdef RT_ARCH_AMD64 +# include <iprt/nocrt/amd64/fenv.h> +#elif defined(RT_ARCH_X86) +# include <iprt/nocrt/x86/fenv.h> +#else +# error "IPRT: no fenv.h available for this platform, or the platform define is missing!" +#endif + +#endif diff --git a/include/iprt/nocrt/inttypes.h b/include/iprt/nocrt/inttypes.h new file mode 100644 index 00000000..dc42dbb4 --- /dev/null +++ b/include/iprt/nocrt/inttypes.h @@ -0,0 +1,42 @@ +/** @file + * IPRT / No-CRT - Our minimal inttypes.h. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_inttypes_h +#define ___iprt_nocrt_inttypes_h + +#include <iprt/types.h> + +#define PRId32 "RI32" +#define PRIx32 "RX32" +#define PRIu32 "RU32" +#define PRIo32 huh? anyone using this? great! + +#define PRId64 "RI64" +#define PRIx64 "RX64" +#define PRIu64 "RU64" +#define PRIo64 huh? anyone using this? great! + +#endif + diff --git a/include/iprt/nocrt/limits.h b/include/iprt/nocrt/limits.h new file mode 100644 index 00000000..047f9644 --- /dev/null +++ b/include/iprt/nocrt/limits.h @@ -0,0 +1,86 @@ +/** @file + * IPRT / No-CRT - Our own limits header. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_limits_h +#define ___iprt_nocrt_limits_h + +#include <iprt/types.h> + +#define CHAR_BIT 8 +#define SCHAR_MAX 0x7f +#define SCHAR_MIN (-0x7f - 1) +#define UCHAR_MAX 0xff +#if 1 /* ASSUMES: signed char */ +# define CHAR_MAX SCHAR_MAX +# define CHAR_MIN SCHAR_MIN +#else +# define CHAR_MAX UCHAR_MAX +# define CHAR_MIN 0 +#endif + +#define WORD_BIT 16 +#define USHRT_MAX 0xffff +#define SHRT_MAX 0x7fff +#define SHRT_MIN (-0x7fff - 1) + +/* ASSUMES 32-bit int */ +#define UINT_MAX 0xffffffffU +#define INT_MAX 0x7fffffff +#define INT_MIN (-0x7fffffff - 1) + +#if defined(RT_ARCH_X86) || defined(RT_OS_WINDOWS) || defined(RT_ARCH_SPARC) +# define LONG_BIT 32 +# define ULONG_MAX 0xffffffffU +# define LONG_MAX 0x7fffffff +# define LONG_MIN (-0x7fffffff - 1) +#elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_SPARC64) +# define LONG_BIT 64 +# define ULONG_MAX UINT64_C(0xffffffffffffffff) +# define LONG_MAX INT64_C(0x7fffffffffffffff) +# define LONG_MIN (INT64_C(-0x7fffffffffffffff) - 1) +#else +# error "PORTME" +#endif + +#define LLONG_BIT 64 +#define ULLONG_MAX UINT64_C(0xffffffffffffffff) +#define LLONG_MAX INT64_C(0x7fffffffffffffff) +#define LLONG_MIN (INT64_C(-0x7fffffffffffffff) - 1) + +#if ARCH_BITS == 32 +# define SIZE_T_MAX 0xffffffffU +# define SSIZE_MAX 0x7fffffff +#elif ARCH_BITS == 64 +# define SIZE_T_MAX UINT64_C(0xffffffffffffffff) +# define SSIZE_MAX INT64_C(0x7fffffffffffffff) +#else +# error "huh?" +#endif + +/*#define OFF_MAX __OFF_MAX +#define OFF_MIN __OFF_MIN*/ + +#endif + diff --git a/include/iprt/nocrt/math.h b/include/iprt/nocrt/math.h new file mode 100644 index 00000000..da37c5f6 --- /dev/null +++ b/include/iprt/nocrt/math.h @@ -0,0 +1,823 @@ +/** @file + * IPRT / No-CRT - math.h. + */ + +/* + * Copyright (C) 2006-2007 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. + * -------------------------------------------------------------------- + * + * This code is based on: + * + * from: @(#)fdlibm.h 5.1 93/09/24 + * $FreeBSD: src/lib/msun/src/math.h,v 1.61 2005/04/16 21:12:47 das Exp $ + * FreeBSD HEAD 2005-06-xx + * + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#ifndef ___iprt_nocrt_math_h +#define ___iprt_nocrt_math_h + +#if !defined(__GNUC__) /* && !defined(__YOUR_COMPILER__) */ +# error "IPRT: Adjust this header for your compiler" +#endif + +#include <iprt/types.h> +/*#include <machine/_limits.h>*/ + +/* from sys/cdefs.h */ +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +#define __GNUC_PREREQ__(ma, mi) \ + (__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)) +#else +#define __GNUC_PREREQ__(ma, mi) 0 +#endif +#define __pure2 + + +/* + * ANSI/POSIX + */ +extern const union __infinity_un { + unsigned char __uc[8]; + double __ud; +} RT_NOCRT(__infinity); + +extern const union __nan_un { + unsigned char __uc[sizeof(float)]; + float __uf; +} RT_NOCRT(__nan); + +#if __GNUC_PREREQ__(3, 3) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800) +#define __MATH_BUILTIN_CONSTANTS +#endif + +#if __GNUC_PREREQ__(3, 0) && !defined(__INTEL_COMPILER) +#define __MATH_BUILTIN_RELOPS +#endif + +#ifdef __MATH_BUILTIN_CONSTANTS +#define HUGE_VAL __builtin_huge_val() +#else +#define HUGE_VAL (RT_NOCRT(__infinity).__ud) +#endif + +#if 1/* __ISO_C_VISIBLE >= 1999*/ +#define FP_ILOGB0 (-__INT_MAX) +#define FP_ILOGBNAN __INT_MAX + +#ifdef __MATH_BUILTIN_CONSTANTS +#define HUGE_VALF __builtin_huge_valf() +#define HUGE_VALL __builtin_huge_vall() +#define INFINITY __builtin_inf() +#define NAN __builtin_nan("") +#else +#define HUGE_VALF (float)HUGE_VAL +#define HUGE_VALL (long double)HUGE_VAL +#define INFINITY HUGE_VALF +#define NAN (__nan.__uf) +#endif /* __MATH_BUILTIN_CONSTANTS */ + +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 +#define math_errhandling MATH_ERREXCEPT + +/* XXX We need a <machine/math.h>. */ +#if defined(__ia64__) || defined(__sparc64__) +#define FP_FAST_FMA +#endif +#ifdef __ia64__ +#define FP_FAST_FMAL +#endif +#define FP_FAST_FMAF + +/* Symbolic constants to classify floating point numbers. */ +#define FP_INFINITE 0x01 +#define FP_NAN 0x02 +#define FP_NORMAL 0x04 +#define FP_SUBNORMAL 0x08 +#define FP_ZERO 0x10 +#define fpclassify(x) \ + ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__fpclassifyf)(x) \ + : (sizeof (x) == sizeof (double)) ? RT_NOCRT(__fpclassifyd)(x) \ + : RT_NOCRT(__fpclassifyl)(x)) + +#define isfinite(x) \ + ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__isfinitef)(x) \ + : (sizeof (x) == sizeof (double)) ? RT_NOCRT(__isfinite)(x) \ + : RT_NOCRT(__isfinitel)(x)) +#define isinf(x) \ + ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__isinff)(x) \ + : (sizeof (x) == sizeof (double)) ? isinf(x) \ + : RT_NOCRT(__isinfl)(x)) +#define isnan(x) \ + ((sizeof (x) == sizeof (float)) ? isnanf(x) \ + : (sizeof (x) == sizeof (double)) ? isnan(x) \ + : RT_NOCRT(__isnanl)(x)) +#define isnormal(x) \ + ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__isnormalf)(x) \ + : (sizeof (x) == sizeof (double)) ? RT_NOCRT(__isnormal)(x) \ + : RT_NOCRT(__isnormall)(x)) + +#ifdef __MATH_BUILTIN_RELOPS +#define isgreater(x, y) __builtin_isgreater((x), (y)) +#define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y)) +#define isless(x, y) __builtin_isless((x), (y)) +#define islessequal(x, y) __builtin_islessequal((x), (y)) +#define islessgreater(x, y) __builtin_islessgreater((x), (y)) +#define isunordered(x, y) __builtin_isunordered((x), (y)) +#else +#define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y)) +#define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y)) +#define isless(x, y) (!isunordered((x), (y)) && (x) < (y)) +#define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y)) +#define islessgreater(x, y) (!isunordered((x), (y)) && \ + ((x) > (y) || (y) > (x))) +#define isunordered(x, y) (isnan(x) || isnan(y)) +#endif /* __MATH_BUILTIN_RELOPS */ + +#define signbit(x) \ + ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__signbitf)(x) \ + : (sizeof (x) == sizeof (double)) ? RT_NOCRT(__signbit)(x) \ + : RT_NOCRT(__signbitl)(x)) + +typedef double double_t; +typedef float float_t; +#endif /* __ISO_C_VISIBLE >= 1999 */ + +/* + * XOPEN/SVID + */ +#if 1/* __BSD_VISIBLE || __XSI_VISIBLE*/ +#define M_E 2.7182818284590452354 /* e */ +#define M_LOG2E 1.4426950408889634074 /* log 2e */ +#define M_LOG10E 0.43429448190325182765 /* log 10e */ +#define M_LN2 0.69314718055994530942 /* log e2 */ +#define M_LN10 2.30258509299404568402 /* log e10 */ +#define M_PI 3.14159265358979323846 /* pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ + +#define MAXFLOAT ((float)3.40282346638528860e+38) +extern int RT_NOCRT(signgam); +#endif /* __BSD_VISIBLE || __XSI_VISIBLE */ + +#if 1/* __BSD_VISIBLE*/ +#if 0 +/* Old value from 4.4BSD-Lite math.h; this is probably better. */ +#define HUGE HUGE_VAL +#else +#define HUGE MAXFLOAT +#endif +#endif /* __BSD_VISIBLE */ + +/* + * Most of these functions depend on the rounding mode and have the side + * effect of raising floating-point exceptions, so they are not declared + * as __pure2. In C99, FENV_ACCESS affects the purity of these functions. + */ +RT_C_DECLS_BEGIN +/* + * ANSI/POSIX + */ +int RT_NOCRT(__fpclassifyd)(double) __pure2; +int RT_NOCRT(__fpclassifyf)(float) __pure2; +int RT_NOCRT(__fpclassifyl)(long double) __pure2; +int RT_NOCRT(__isfinitef)(float) __pure2; +int RT_NOCRT(__isfinite)(double) __pure2; +int RT_NOCRT(__isfinitel)(long double) __pure2; +int RT_NOCRT(__isinff)(float) __pure2; +int RT_NOCRT(__isinfl)(long double) __pure2; +int RT_NOCRT(__isnanl)(long double) __pure2; +int RT_NOCRT(__isnormalf)(float) __pure2; +int RT_NOCRT(__isnormal)(double) __pure2; +int RT_NOCRT(__isnormall)(long double) __pure2; +int RT_NOCRT(__signbit)(double) __pure2; +int RT_NOCRT(__signbitf)(float) __pure2; +int RT_NOCRT(__signbitl)(long double) __pure2; + +double RT_NOCRT(acos)(double); +double RT_NOCRT(asin)(double); +double RT_NOCRT(atan)(double); +double RT_NOCRT(atan2)(double, double); +double RT_NOCRT(cos)(double); +double RT_NOCRT(sin)(double); +double RT_NOCRT(tan)(double); + +double RT_NOCRT(cosh)(double); +double RT_NOCRT(sinh)(double); +double RT_NOCRT(tanh)(double); + +double RT_NOCRT(exp)(double); +double RT_NOCRT(frexp)(double, int *); /* fundamentally !__pure2 */ +double RT_NOCRT(ldexp)(double, int); +double RT_NOCRT(log)(double); +double RT_NOCRT(log10)(double); +double RT_NOCRT(modf)(double, double *); /* fundamentally !__pure2 */ + +double RT_NOCRT(pow)(double, double); +double RT_NOCRT(sqrt)(double); + +double RT_NOCRT(ceil)(double); +double RT_NOCRT(fabs)(double) __pure2; +double RT_NOCRT(floor)(double); +double RT_NOCRT(fmod)(double, double); + +/* + * These functions are not in C90. + */ +#if 1 /*__BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE*/ +double RT_NOCRT(acosh)(double); +double RT_NOCRT(asinh)(double); +double RT_NOCRT(atanh)(double); +double RT_NOCRT(cbrt)(double); +double RT_NOCRT(erf)(double); +double RT_NOCRT(erfc)(double); +double RT_NOCRT(exp2)(double); +double RT_NOCRT(expm1)(double); +double RT_NOCRT(fma)(double, double, double); +double RT_NOCRT(hypot)(double, double); +int RT_NOCRT(ilogb)(double) __pure2; +/*int isinf(double) __pure2;*/ +/*int isnan(double) __pure2;*/ +double RT_NOCRT(lgamma)(double); +long long RT_NOCRT(llrint)(double); +long long RT_NOCRT(llround)(double); +double RT_NOCRT(log1p)(double); +double RT_NOCRT(logb)(double); +long RT_NOCRT(lrint)(double); +long RT_NOCRT(lround)(double); +double RT_NOCRT(nextafter)(double, double); +double RT_NOCRT(remainder)(double, double); +double RT_NOCRT(remquo)(double, double, int *); +double RT_NOCRT(rint)(double); +#endif /* __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE */ + +#if 1/* __BSD_VISIBLE || __XSI_VISIBLE*/ +double RT_NOCRT(j0)(double); +double RT_NOCRT(j1)(double); +double RT_NOCRT(jn)(int, double); +double RT_NOCRT(scalb)(double, double); +double RT_NOCRT(y0)(double); +double RT_NOCRT(y1)(double); +double RT_NOCRT(yn)(int, double); + +#if 1/* __XSI_VISIBLE <= 500 || __BSD_VISIBLE*/ +double RT_NOCRT(gamma)(double); +#endif +#endif /* __BSD_VISIBLE || __XSI_VISIBLE */ + +#if 1/* __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999*/ +double RT_NOCRT(copysign)(double, double) __pure2; +double RT_NOCRT(fdim)(double, double); +double RT_NOCRT(fmax)(double, double) __pure2; +double RT_NOCRT(fmin)(double, double) __pure2; +double RT_NOCRT(nearbyint)(double); +double RT_NOCRT(round)(double); +double RT_NOCRT(scalbln)(double, long); +double RT_NOCRT(scalbn)(double, int); +double RT_NOCRT(tgamma)(double); +double RT_NOCRT(trunc)(double); +#endif + +/* + * BSD math library entry points + */ +#if 1/* __BSD_VISIBLE*/ +double RT_NOCRT(drem)(double, double); +int RT_NOCRT(finite)(double) __pure2; +int RT_NOCRT(isnanf)(float) __pure2; + +/* + * Reentrant version of gamma & lgamma; passes signgam back by reference + * as the second argument; user must allocate space for signgam. + */ +double RT_NOCRT(gamma_r)(double, int *); +double RT_NOCRT(lgamma_r)(double, int *); + +/* + * IEEE Test Vector + */ +double RT_NOCRT(significand)(double); +#endif /* __BSD_VISIBLE */ + +/* float versions of ANSI/POSIX functions */ +#if 1/* __ISO_C_VISIBLE >= 1999*/ +float RT_NOCRT(acosf)(float); +float RT_NOCRT(asinf)(float); +float RT_NOCRT(atanf)(float); +float RT_NOCRT(atan2f)(float, float); +float RT_NOCRT(cosf)(float); +float RT_NOCRT(sinf)(float); +float RT_NOCRT(tanf)(float); + +float RT_NOCRT(coshf)(float); +float RT_NOCRT(sinhf)(float); +float RT_NOCRT(tanhf)(float); + +float RT_NOCRT(exp2f)(float); +float RT_NOCRT(expf)(float); +float RT_NOCRT(expm1f)(float); +float RT_NOCRT(frexpf)(float, int *); /* fundamentally !__pure2 */ +int RT_NOCRT(ilogbf)(float) __pure2; +float RT_NOCRT(ldexpf)(float, int); +float RT_NOCRT(log10f)(float); +float RT_NOCRT(log1pf)(float); +float RT_NOCRT(logf)(float); +float RT_NOCRT(modff)(float, float *); /* fundamentally !__pure2 */ + +float RT_NOCRT(powf)(float, float); +float RT_NOCRT(sqrtf)(float); + +float RT_NOCRT(ceilf)(float); +float RT_NOCRT(fabsf)(float) __pure2; +float RT_NOCRT(floorf)(float); +float RT_NOCRT(fmodf)(float, float); +float RT_NOCRT(roundf)(float); + +float RT_NOCRT(erff)(float); +float RT_NOCRT(erfcf)(float); +float RT_NOCRT(hypotf)(float, float); +float RT_NOCRT(lgammaf)(float); + +float RT_NOCRT(acoshf)(float); +float RT_NOCRT(asinhf)(float); +float RT_NOCRT(atanhf)(float); +float RT_NOCRT(cbrtf)(float); +float RT_NOCRT(logbf)(float); +float RT_NOCRT(copysignf)(float, float) __pure2; +long long RT_NOCRT(llrintf)(float); +long long RT_NOCRT(llroundf)(float); +long RT_NOCRT(lrintf)(float); +long RT_NOCRT(lroundf)(float); +float RT_NOCRT(nearbyintf)(float); +float RT_NOCRT(nextafterf)(float, float); +float RT_NOCRT(remainderf)(float, float); +float RT_NOCRT(remquof)(float, float, int *); +float RT_NOCRT(rintf)(float); +float RT_NOCRT(scalblnf)(float, long); +float RT_NOCRT(scalbnf)(float, int); +float RT_NOCRT(truncf)(float); + +float RT_NOCRT(fdimf)(float, float); +float RT_NOCRT(fmaf)(float, float, float); +float RT_NOCRT(fmaxf)(float, float) __pure2; +float RT_NOCRT(fminf)(float, float) __pure2; +#endif + +/* + * float versions of BSD math library entry points + */ +#if 1/* __BSD_VISIBLE*/ +float RT_NOCRT(dremf)(float, float); +int RT_NOCRT(finitef)(float) __pure2; +float RT_NOCRT(gammaf)(float); +float RT_NOCRT(j0f)(float); +float RT_NOCRT(j1f)(float); +float RT_NOCRT(jnf)(int, float); +float RT_NOCRT(scalbf)(float, float); +float RT_NOCRT(y0f)(float); +float RT_NOCRT(y1f)(float); +float RT_NOCRT(ynf)(int, float); + +/* + * Float versions of reentrant version of gamma & lgamma; passes + * signgam back by reference as the second argument; user must + * allocate space for signgam. + */ +float RT_NOCRT(gammaf_r)(float, int *); +float RT_NOCRT(lgammaf_r)(float, int *); + +/* + * float version of IEEE Test Vector + */ +float RT_NOCRT(significandf)(float); +#endif /* __BSD_VISIBLE */ + +/* + * long double versions of ISO/POSIX math functions + */ +#if 1/* __ISO_C_VISIBLE >= 1999*/ +#if 1 /* bird: we've got these */ +long double RT_NOCRT(acoshl)(long double); +long double RT_NOCRT(acosl)(long double); +long double RT_NOCRT(asinhl)(long double); +long double RT_NOCRT(asinl)(long double); +long double RT_NOCRT(atan2l)(long double, long double); +long double RT_NOCRT(atanhl)(long double); +long double RT_NOCRT(atanl)(long double); +long double RT_NOCRT(cbrtl)(long double); +#endif +long double RT_NOCRT(ceill)(long double); +long double RT_NOCRT(copysignl)(long double, long double) __pure2; +#if 1 /* bird */ +long double RT_NOCRT(coshl)(long double); +long double RT_NOCRT(cosl)(long double); +long double RT_NOCRT(erfcl)(long double); +long double RT_NOCRT(erfl)(long double); +long double RT_NOCRT(exp2l)(long double); +long double RT_NOCRT(expl)(long double); +long double RT_NOCRT(expm1l)(long double); +#endif +long double RT_NOCRT(fabsl)(long double) __pure2; +long double RT_NOCRT(fdiml)(long double, long double); +long double RT_NOCRT(floorl)(long double); +long double RT_NOCRT(fmal)(long double, long double, long double); +long double RT_NOCRT(fmaxl)(long double, long double) __pure2; +long double RT_NOCRT(fminl)(long double, long double) __pure2; +#if 1 /* bird */ +long double RT_NOCRT(fmodl)(long double, long double); +#endif +long double RT_NOCRT(frexpl)(long double value, int *); /* fundamentally !__pure2 */ +#if 1 /* bird */ +long double RT_NOCRT(hypotl)(long double, long double); +#endif +int RT_NOCRT(ilogbl)(long double) __pure2; +long double RT_NOCRT(ldexpl)(long double, int); +#if 1 /* bird */ +long double RT_NOCRT(lgammal)(long double); +long long RT_NOCRT(llrintl)(long double); +#endif +long long RT_NOCRT(llroundl)(long double); +#if 1 /* bird */ +long double RT_NOCRT(log10l)(long double); +long double RT_NOCRT(log1pl)(long double); +long double RT_NOCRT(log2l)(long double); +long double RT_NOCRT(logbl)(long double); +long double RT_NOCRT(logl)(long double); +long RT_NOCRT(lrintl)(long double); +#endif +long RT_NOCRT(lroundl)(long double); +#if 1 /* bird */ +long double RT_NOCRT(modfl)(long double, long double *); /* fundamentally !__pure2 */ +long double RT_NOCRT(nanl)(const char *) __pure2; +long double RT_NOCRT(nearbyintl)(long double); +#endif +long double RT_NOCRT(nextafterl)(long double, long double); +double RT_NOCRT(nexttoward)(double, long double); +float RT_NOCRT(nexttowardf)(float, long double); +long double RT_NOCRT(nexttowardl)(long double, long double); +#if 1 /* bird */ +long double RT_NOCRT(powl)(long double, long double); +long double RT_NOCRT(remainderl)(long double, long double); +long double RT_NOCRT(remquol)(long double, long double, int *); +long double RT_NOCRT(rintl)(long double); +#endif +long double RT_NOCRT(roundl)(long double); +long double RT_NOCRT(scalblnl)(long double, long); +long double RT_NOCRT(scalbnl)(long double, int); +#if 1 /* bird: we 've got most of these. */ +long double RT_NOCRT(sinhl)(long double); +long double RT_NOCRT(sinl)(long double); +long double RT_NOCRT(sqrtl)(long double); +long double RT_NOCRT(tanhl)(long double); +long double RT_NOCRT(tanl)(long double); +long double RT_NOCRT(tgammal)(long double); +#endif +long double RT_NOCRT(truncl)(long double); + +/* bird: these were missing, gcc apparently inlines them. */ +double RT_NOCRT(nan)(const char *); +float RT_NOCRT(nanf)(const char *); + +#endif /* __ISO_C_VISIBLE >= 1999 */ + +#if 1/*def __USE_GNU*/ +/* + * In GLIBC there are long variants of the XOPEN/SVID constant + * block some pages ago. We need this to get the math tests going. + */ +#define M_El 2.7182818284590452353602874713526625L +#define M_LOG2El 1.4426950408889634073599246810018921L +#define M_LOG10El 0.4342944819032518276511289189166051L +#define M_LN2l 0.6931471805599453094172321214581766L +#define M_LN10l 2.3025850929940456840179914546843642L +#define M_PIl 3.1415926535897932384626433832795029L +#define M_PI_2l 1.5707963267948966192313216916397514L +#define M_PI_4l 0.7853981633974483096156608458198757L +#define M_1_PIl 0.3183098861837906715377675267450287L +#define M_2_PIl 0.6366197723675813430755350534900574L +#define M_2_SQRTPIl 1.1283791670955125738961589031215452L +#define M_SQRT2l 1.4142135623730950488016887242096981L +#define M_SQRT1_2l 0.7071067811865475244008443621048490L +#endif + +#if 1/*def __USE_GNU*/ + +void RT_NOCRT(sincos)(double, double *, double *); +void RT_NOCRT(sincosf)(float, float *, float *); +void RT_NOCRT(sincosl)(long double, long double *, long double *); +float RT_NOCRT(exp10f)(float); +double RT_NOCRT(exp10)(double); +long double RT_NOCRT(exp10l)(long double); +float RT_NOCRT(log2f)(float); +double RT_NOCRT(log2)(double); +long double RT_NOCRT(log2l)(long double); +float RT_NOCRT(tgammaf)(float); +long double RT_NOCRT(significandl)(long double); +long double RT_NOCRT(j0l)(long double); +long double RT_NOCRT(j1l)(long double); +long double RT_NOCRT(jnl)(int, long double); +long double RT_NOCRT(scalbl)(long double, long double); +long double RT_NOCRT(y0l)(long double); +long double RT_NOCRT(y1l)(long double); +long double RT_NOCRT(ynl)(int, long double); +long double RT_NOCRT(lgammal_r)(long double,int *); +long double RT_NOCRT(gammal)(long double); +#endif +RT_C_DECLS_END + + + +#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES) +/* sed -e "/#/d" -e "/RT_NOCRT/!d" -e "s/^.*RT_NOCRT(\([a-z0-9_]*\)).*$/# define \1 RT_NOCRT(\1)/" */ +# define __infinity RT_NOCRT(__infinity) +# define __nan RT_NOCRT(__nan) +# define __fpclassifyf RT_NOCRT(__fpclassifyf) +# define __fpclassifyd RT_NOCRT(__fpclassifyd) +# define __fpclassifyl RT_NOCRT(__fpclassifyl) +# define __isfinitef RT_NOCRT(__isfinitef) +# define __isfinite RT_NOCRT(__isfinite) +# define __isfinitel RT_NOCRT(__isfinitel) +# define __isinff RT_NOCRT(__isinff) +# define __isinfl RT_NOCRT(__isinfl) +# define __isnanl RT_NOCRT(__isnanl) +# define __isnormalf RT_NOCRT(__isnormalf) +# define __isnormal RT_NOCRT(__isnormal) +# define __isnormall RT_NOCRT(__isnormall) +# define __signbitf RT_NOCRT(__signbitf) +# define __signbit RT_NOCRT(__signbit) +# define __signbitl RT_NOCRT(__signbitl) +# define signgam RT_NOCRT(signgam) +# define __fpclassifyd RT_NOCRT(__fpclassifyd) +# define __fpclassifyf RT_NOCRT(__fpclassifyf) +# define __fpclassifyl RT_NOCRT(__fpclassifyl) +# define __isfinitef RT_NOCRT(__isfinitef) +# define __isfinite RT_NOCRT(__isfinite) +# define __isfinitel RT_NOCRT(__isfinitel) +# define __isinff RT_NOCRT(__isinff) +# define __isinfl RT_NOCRT(__isinfl) +# define __isnanl RT_NOCRT(__isnanl) +# define __isnormalf RT_NOCRT(__isnormalf) +# define __isnormal RT_NOCRT(__isnormal) +# define __isnormall RT_NOCRT(__isnormall) +# define __signbit RT_NOCRT(__signbit) +# define __signbitf RT_NOCRT(__signbitf) +# define __signbitl RT_NOCRT(__signbitl) +# define acos RT_NOCRT(acos) +# define asin RT_NOCRT(asin) +# define atan RT_NOCRT(atan) +# define atan2 RT_NOCRT(atan2) +# define cos RT_NOCRT(cos) +# define sin RT_NOCRT(sin) +# define tan RT_NOCRT(tan) +# define cosh RT_NOCRT(cosh) +# define sinh RT_NOCRT(sinh) +# define tanh RT_NOCRT(tanh) +# define exp RT_NOCRT(exp) +# define frexp RT_NOCRT(frexp) +# define ldexp RT_NOCRT(ldexp) +# define log RT_NOCRT(log) +# define log10 RT_NOCRT(log10) +# define modf RT_NOCRT(modf) +# define pow RT_NOCRT(pow) +# define sqrt RT_NOCRT(sqrt) +# define ceil RT_NOCRT(ceil) +# define fabs RT_NOCRT(fabs) +# define floor RT_NOCRT(floor) +# define fmod RT_NOCRT(fmod) +# define acosh RT_NOCRT(acosh) +# define asinh RT_NOCRT(asinh) +# define atanh RT_NOCRT(atanh) +# define cbrt RT_NOCRT(cbrt) +# define erf RT_NOCRT(erf) +# define erfc RT_NOCRT(erfc) +# define exp2 RT_NOCRT(exp2) +# define expm1 RT_NOCRT(expm1) +# define fma RT_NOCRT(fma) +# define hypot RT_NOCRT(hypot) +# define ilogb RT_NOCRT(ilogb) +# define lgamma RT_NOCRT(lgamma) +# define llrint RT_NOCRT(llrint) +# define llround RT_NOCRT(llround) +# define log1p RT_NOCRT(log1p) +# define logb RT_NOCRT(logb) +# define lrint RT_NOCRT(lrint) +# define lround RT_NOCRT(lround) +# define nextafter RT_NOCRT(nextafter) +# define remainder RT_NOCRT(remainder) +# define remquo RT_NOCRT(remquo) +# define rint RT_NOCRT(rint) +# define j0 RT_NOCRT(j0) +# define j1 RT_NOCRT(j1) +# define jn RT_NOCRT(jn) +# define scalb RT_NOCRT(scalb) +# define y0 RT_NOCRT(y0) +# define y1 RT_NOCRT(y1) +# define yn RT_NOCRT(yn) +# define gamma RT_NOCRT(gamma) +# define copysign RT_NOCRT(copysign) +# define fdim RT_NOCRT(fdim) +# define fmax RT_NOCRT(fmax) +# define fmin RT_NOCRT(fmin) +# define nearbyint RT_NOCRT(nearbyint) +# define round RT_NOCRT(round) +# define scalbln RT_NOCRT(scalbln) +# define scalbn RT_NOCRT(scalbn) +# define tgamma RT_NOCRT(tgamma) +# define trunc RT_NOCRT(trunc) +# define drem RT_NOCRT(drem) +# define finite RT_NOCRT(finite) +# define isnanf RT_NOCRT(isnanf) +# define gamma_r RT_NOCRT(gamma_r) +# define lgamma_r RT_NOCRT(lgamma_r) +# define significand RT_NOCRT(significand) +# define acosf RT_NOCRT(acosf) +# define asinf RT_NOCRT(asinf) +# define atanf RT_NOCRT(atanf) +# define atan2f RT_NOCRT(atan2f) +# define cosf RT_NOCRT(cosf) +# define sinf RT_NOCRT(sinf) +# define tanf RT_NOCRT(tanf) +# define coshf RT_NOCRT(coshf) +# define sinhf RT_NOCRT(sinhf) +# define tanhf RT_NOCRT(tanhf) +# define exp2f RT_NOCRT(exp2f) +# define expf RT_NOCRT(expf) +# define expm1f RT_NOCRT(expm1f) +# define frexpf RT_NOCRT(frexpf) +# define ilogbf RT_NOCRT(ilogbf) +# define ldexpf RT_NOCRT(ldexpf) +# define log10f RT_NOCRT(log10f) +# define log1pf RT_NOCRT(log1pf) +# define logf RT_NOCRT(logf) +# define modff RT_NOCRT(modff) +# define powf RT_NOCRT(powf) +# define sqrtf RT_NOCRT(sqrtf) +# define ceilf RT_NOCRT(ceilf) +# define fabsf RT_NOCRT(fabsf) +# define floorf RT_NOCRT(floorf) +# define fmodf RT_NOCRT(fmodf) +# define roundf RT_NOCRT(roundf) +# define erff RT_NOCRT(erff) +# define erfcf RT_NOCRT(erfcf) +# define hypotf RT_NOCRT(hypotf) +# define lgammaf RT_NOCRT(lgammaf) +# define acoshf RT_NOCRT(acoshf) +# define asinhf RT_NOCRT(asinhf) +# define atanhf RT_NOCRT(atanhf) +# define cbrtf RT_NOCRT(cbrtf) +# define logbf RT_NOCRT(logbf) +# define copysignf RT_NOCRT(copysignf) +# define llrintf RT_NOCRT(llrintf) +# define llroundf RT_NOCRT(llroundf) +# define lrintf RT_NOCRT(lrintf) +# define lroundf RT_NOCRT(lroundf) +# define nearbyintf RT_NOCRT(nearbyintf) +# define nextafterf RT_NOCRT(nextafterf) +# define remainderf RT_NOCRT(remainderf) +# define remquof RT_NOCRT(remquof) +# define rintf RT_NOCRT(rintf) +# define scalblnf RT_NOCRT(scalblnf) +# define scalbnf RT_NOCRT(scalbnf) +# define truncf RT_NOCRT(truncf) +# define fdimf RT_NOCRT(fdimf) +# define fmaf RT_NOCRT(fmaf) +# define fmaxf RT_NOCRT(fmaxf) +# define fminf RT_NOCRT(fminf) +# define dremf RT_NOCRT(dremf) +# define finitef RT_NOCRT(finitef) +# define gammaf RT_NOCRT(gammaf) +# define j0f RT_NOCRT(j0f) +# define j1f RT_NOCRT(j1f) +# define jnf RT_NOCRT(jnf) +# define scalbf RT_NOCRT(scalbf) +# define y0f RT_NOCRT(y0f) +# define y1f RT_NOCRT(y1f) +# define ynf RT_NOCRT(ynf) +# define gammaf_r RT_NOCRT(gammaf_r) +# define lgammaf_r RT_NOCRT(lgammaf_r) +# define significandf RT_NOCRT(significandf) +# define acoshl RT_NOCRT(acoshl) +# define acosl RT_NOCRT(acosl) +# define asinhl RT_NOCRT(asinhl) +# define asinl RT_NOCRT(asinl) +# define atan2l RT_NOCRT(atan2l) +# define atanhl RT_NOCRT(atanhl) +# define atanl RT_NOCRT(atanl) +# define cbrtl RT_NOCRT(cbrtl) +# define ceill RT_NOCRT(ceill) +# define copysignl RT_NOCRT(copysignl) +# define coshl RT_NOCRT(coshl) +# define cosl RT_NOCRT(cosl) +# define erfcl RT_NOCRT(erfcl) +# define erfl RT_NOCRT(erfl) +# define exp2l RT_NOCRT(exp2l) +# define expl RT_NOCRT(expl) +# define expm1l RT_NOCRT(expm1l) +# define fabsl RT_NOCRT(fabsl) +# define fdiml RT_NOCRT(fdiml) +# define floorl RT_NOCRT(floorl) +# define fmal RT_NOCRT(fmal) +# define fmaxl RT_NOCRT(fmaxl) +# define fminl RT_NOCRT(fminl) +# define fmodl RT_NOCRT(fmodl) +# define frexpl RT_NOCRT(frexpl) +# define hypotl RT_NOCRT(hypotl) +# define ilogbl RT_NOCRT(ilogbl) +# define ldexpl RT_NOCRT(ldexpl) +# define lgammal RT_NOCRT(lgammal) +# define llrintl RT_NOCRT(llrintl) +# define llroundl RT_NOCRT(llroundl) +# define log10l RT_NOCRT(log10l) +# define log1pl RT_NOCRT(log1pl) +# define log2l RT_NOCRT(log2l) +# define logbl RT_NOCRT(logbl) +# define logl RT_NOCRT(logl) +# define lrintl RT_NOCRT(lrintl) +# define lroundl RT_NOCRT(lroundl) +# define modfl RT_NOCRT(modfl) +# define nanl RT_NOCRT(nanl) +# define nearbyintl RT_NOCRT(nearbyintl) +# define nextafterl RT_NOCRT(nextafterl) +# define nexttoward RT_NOCRT(nexttoward) +# define nexttowardf RT_NOCRT(nexttowardf) +# define nexttowardl RT_NOCRT(nexttowardl) +# define powl RT_NOCRT(powl) +# define remainderl RT_NOCRT(remainderl) +# define remquol RT_NOCRT(remquol) +# define rintl RT_NOCRT(rintl) +# define roundl RT_NOCRT(roundl) +# define scalblnl RT_NOCRT(scalblnl) +# define scalbnl RT_NOCRT(scalbnl) +# define sinhl RT_NOCRT(sinhl) +# define sinl RT_NOCRT(sinl) +# define sqrtl RT_NOCRT(sqrtl) +# define tanhl RT_NOCRT(tanhl) +# define tanl RT_NOCRT(tanl) +# define tgammal RT_NOCRT(tgammal) +# define truncl RT_NOCRT(truncl) +# define nan RT_NOCRT(nan) +# define nanf RT_NOCRT(nanf) +# define sincos RT_NOCRT(sincos) +# define sincosf RT_NOCRT(sincosf) +# define sincosl RT_NOCRT(sincosl) +# define exp10f RT_NOCRT(exp10f) +# define exp10 RT_NOCRT(exp10) +# define exp10l RT_NOCRT(exp10l) +# define log2f RT_NOCRT(log2f) +# define log2 RT_NOCRT(log2) +# define log2l RT_NOCRT(log2l) +# define tgammaf RT_NOCRT(tgammaf) +# define significandl RT_NOCRT(significandl) +# define j0l RT_NOCRT(j0l) +# define j1l RT_NOCRT(j1l) +# define jnl RT_NOCRT(jnl) +# define scalbl RT_NOCRT(scalbl) +# define y0l RT_NOCRT(y0l) +# define y1l RT_NOCRT(y1l) +# define ynl RT_NOCRT(ynl) +# define lgammal_r RT_NOCRT(lgammal_r) +# define gammal RT_NOCRT(gammal) +#endif + +/* + * Include inlined implementations. + */ +#ifdef RT_ARCH_AMD64 +# include <iprt/nocrt/amd64/math.h> +#elif defined(RT_ARCH_X86) +# include <iprt/nocrt/x86/math.h> +#endif + +#endif + diff --git a/include/iprt/nocrt/setjmp.h b/include/iprt/nocrt/setjmp.h new file mode 100644 index 00000000..c7c7aaf0 --- /dev/null +++ b/include/iprt/nocrt/setjmp.h @@ -0,0 +1,55 @@ +/** @file + * IPRT / No-CRT - Our own setjmp header. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_setjmp_h +#define ___iprt_nocrt_setjmp_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +#ifdef RT_ARCH_AMD64 +# ifdef RT_OS_WINDOWS /* Also saves rsi, rdi and xmm6-xmm15. */ +typedef uint64_t RT_NOCRT(jmp_buf)[10 + (2*10)]; +# else +typedef uint64_t RT_NOCRT(jmp_buf)[8]; +# endif +#else +typedef uint32_t RT_NOCRT(jmp_buf)[6+2]; +#endif + +extern int RT_NOCRT(setjmp)(RT_NOCRT(jmp_buf)); +extern int RT_NOCRT(longjmp)(RT_NOCRT(jmp_buf), int); + +#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES) +# define jmp_buf RT_NOCRT(jmp_buf) +# define setjmp RT_NOCRT(setjmp) +# define longjmp RT_NOCRT(longjmp) +#endif + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/nocrt/stdarg.h b/include/iprt/nocrt/stdarg.h new file mode 100644 index 00000000..daa6e0a7 --- /dev/null +++ b/include/iprt/nocrt/stdarg.h @@ -0,0 +1,27 @@ +/** @file + * IPRT / No-CRT - stdarg.h (-> iprt/stdarg.h). + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#include <iprt/stdarg.h> + diff --git a/include/iprt/nocrt/stddef.h b/include/iprt/nocrt/stddef.h new file mode 100644 index 00000000..8487c26e --- /dev/null +++ b/include/iprt/nocrt/stddef.h @@ -0,0 +1,27 @@ +/** @file + * IPRT / No-CRT - stddef.h (-> iprt/types.h). + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#include <iprt/types.h> + diff --git a/include/iprt/nocrt/stdlib.h b/include/iprt/nocrt/stdlib.h new file mode 100644 index 00000000..9bfc1d2f --- /dev/null +++ b/include/iprt/nocrt/stdlib.h @@ -0,0 +1,36 @@ +/** @file + * IPRT / No-CRT - Our minimal stdlib.h. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_stdlib_h +#define ___iprt_nocrt_stdlib_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + + +RT_C_DECLS_END + +#endif diff --git a/include/iprt/nocrt/string.h b/include/iprt/nocrt/string.h new file mode 100644 index 00000000..2ed2f72d --- /dev/null +++ b/include/iprt/nocrt/string.h @@ -0,0 +1,80 @@ +/** @file + * IPRT / No-CRT - string.h. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_string_h +#define ___iprt_nocrt_string_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +void * RT_NOCRT(memchr)(const void *pv, int ch, size_t cb); +int RT_NOCRT(memcmp)(const void *pv1, const void *pv2, size_t cb); +void * RT_NOCRT(memcpy)(void *pvDst, const void *pvSrc, size_t cb); +void * RT_NOCRT(mempcpy)(void *pvDst, const void *pvSrc, size_t cb); +void * RT_NOCRT(memmove)(void *pvDst, const void *pvSrc, size_t cb); +void * RT_NOCRT(memset)(void *pvDst, int ch, size_t cb); + +char * RT_NOCRT(strcat)(char *pszDst, const char *pszSrc); +char * RT_NOCRT(strncat)(char *pszDst, const char *pszSrc, size_t cch); +char * RT_NOCRT(strchr)(const char *psz, int ch); +int RT_NOCRT(strcmp)(const char *psz1, const char *psz2); +int RT_NOCRT(strncmp)(const char *psz1, const char *psz2, size_t cch); +int RT_NOCRT(stricmp)(const char *psz1, const char *psz2); +int RT_NOCRT(strnicmp)(const char *psz1, const char *psz2, size_t cch); +char * RT_NOCRT(strcpy)(char *pszDst, const char *pszSrc); +char * RT_NOCRT(strncpy)(char *pszDst, const char *pszSrc, size_t cch); +char * RT_NOCRT(strcat)(char *pszDst, const char *pszSrc); +char * RT_NOCRT(strncat)(char *pszDst, const char *pszSrc, size_t cch); +size_t RT_NOCRT(strlen)(const char *psz); +size_t RT_NOCRT(strnlen)(const char *psz, size_t cch); +char * RT_NOCRT(strstr)(const char *psz, const char *pszSub); + +#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES) +# define memchr RT_NOCRT(memchr) +# define memcmp RT_NOCRT(memcmp) +# define memcpy RT_NOCRT(memcpy) +# define mempcpy RT_NOCRT(mempcpy) +# define memmove RT_NOCRT(memmove) +# define memset RT_NOCRT(memset) +# define strcat RT_NOCRT(strcat) +# define strncat RT_NOCRT(strncat) +# define strchr RT_NOCRT(strchr) +# define strcmp RT_NOCRT(strcmp) +# define strncmp RT_NOCRT(strncmp) +# define stricmp RT_NOCRT(stricmp) +# define strnicmp RT_NOCRT(strnicmp) +# define strcpy RT_NOCRT(strcpy) +# define strncpy RT_NOCRT(strncpy) +# define strcat RT_NOCRT(strcat) +# define strncat RT_NOCRT(strncat) +# define strlen RT_NOCRT(strlen) +# define strnlen RT_NOCRT(strnlen) +# define strstr RT_NOCRT(strstr) +#endif + +RT_C_DECLS_END + +#endif diff --git a/include/iprt/nocrt/x86/fenv.h b/include/iprt/nocrt/x86/fenv.h new file mode 100644 index 00000000..3a3db7da --- /dev/null +++ b/include/iprt/nocrt/x86/fenv.h @@ -0,0 +1,274 @@ +/** @file + * IPRT / No-CRT - fenv.h, X86. + */ + +/* + * Copyright (C) 2006-2007 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. + * -------------------------------------------------------------------- + * + * This code is based on: + * + * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/msun/i387/fenv.h,v 1.4 2005/03/17 22:21:46 das Exp $ + */ + +#ifndef ___iprt_nocrt_x86_fenv_h +#define ___iprt_nocrt_x86_fenv_h + +#include <iprt/types.h> + +/* + * To preserve binary compatibility with FreeBSD 5.3, we pack the + * mxcsr into some reserved fields, rather than changing sizeof(fenv_t). + */ +typedef struct { + uint16_t __control; + uint16_t __mxcsr_hi; + uint16_t __status; + uint16_t __mxcsr_lo; + uint32_t __tag; + char __other[16]; +} fenv_t; + +#define __get_mxcsr(env) (((env).__mxcsr_hi << 16) | \ + ((env).__mxcsr_lo)) +#define __set_mxcsr(env, x) do { \ + (env).__mxcsr_hi = (uint32_t)(x) >> 16; \ + (env).__mxcsr_lo = (uint16_t)(x); \ +} while (0) + +typedef uint16_t fexcept_t; + +/* Exception flags */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 +#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ + FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) + +/* Rounding modes */ +#define FE_TONEAREST 0x0000 +#define FE_DOWNWARD 0x0400 +#define FE_UPWARD 0x0800 +#define FE_TOWARDZERO 0x0c00 +#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ + FE_UPWARD | FE_TOWARDZERO) + +/* + * As compared to the x87 control word, the SSE unit's control word + * has the rounding control bits offset by 3 and the exception mask + * bits offset by 7. + */ +#define _SSE_ROUND_SHIFT 3 +#define _SSE_EMASK_SHIFT 7 + +/* After testing for SSE support once, we cache the result in __has_sse. */ +enum __sse_support { __SSE_YES, __SSE_NO, __SSE_UNK }; +extern enum __sse_support RT_NOCRT(__has_sse); +int RT_NOCRT(__test_sse)(void); +#ifdef __SSE__ +#define __HAS_SSE() 1 +#else +#define __HAS_SSE() (RT_NOCRT(__has_sse) == __SSE_YES || \ + (RT_NOCRT(__has_sse) == __SSE_UNK && RT_NOCRT(__test_sse)())) +#endif + +RT_C_DECLS_BEGIN + +/* Default floating-point environment */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw)) +#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env)) +#define __fnclex() __asm __volatile("fnclex") +#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env))) +#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw))) +#define __fnstsw(__sw) __asm __volatile("fnstsw %0" : "=am" (*(__sw))) +#define __fwait() __asm __volatile("fwait") +#define __ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr)) +#define __stmxcsr(__csr) __asm __volatile("stmxcsr %0" : "=m" (*(__csr))) + +DECLINLINE(int) +feclearexcept(int __excepts) +{ + fenv_t __env; + int __mxcsr; + + if (__excepts == FE_ALL_EXCEPT) { + __fnclex(); + } else { + __fnstenv(&__env); + __env.__status &= ~__excepts; + __fldenv(__env); + } + if (__HAS_SSE()) { + __stmxcsr(&__mxcsr); + __mxcsr &= ~__excepts; + __ldmxcsr(__mxcsr); + } + return (0); +} + +DECLINLINE(int) +fegetexceptflag(fexcept_t *__flagp, int __excepts) +{ + int __mxcsr, __status; + + __fnstsw(&__status); + if (__HAS_SSE()) + __stmxcsr(&__mxcsr); + else + __mxcsr = 0; + *__flagp = (__mxcsr | __status) & __excepts; + return (0); +} + +int RT_NOCRT(fesetexceptflag)(const fexcept_t *__flagp, int __excepts); +int RT_NOCRT(feraiseexcept)(int __excepts); + +DECLINLINE(int) +fetestexcept(int __excepts) +{ + int __mxcsr, __status; + + __fnstsw(&__status); + if (__HAS_SSE()) + __stmxcsr(&__mxcsr); + else + __mxcsr = 0; + return ((__status | __mxcsr) & __excepts); +} + +DECLINLINE(int) +fegetround(void) +{ + int __control; + + /* + * We assume that the x87 and the SSE unit agree on the + * rounding mode. Reading the control word on the x87 turns + * out to be about 5 times faster than reading it on the SSE + * unit on an Opteron 244. + */ + __fnstcw(&__control); + return (__control & _ROUND_MASK); +} + +DECLINLINE(int) +fesetround(int __round) +{ + int __mxcsr, __control; + + if (__round & ~_ROUND_MASK) + return (-1); + + __fnstcw(&__control); + __control &= ~_ROUND_MASK; + __control |= __round; + __fldcw(__control); + + if (__HAS_SSE()) { + __stmxcsr(&__mxcsr); + __mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT); + __mxcsr |= __round << _SSE_ROUND_SHIFT; + __ldmxcsr(__mxcsr); + } + + return (0); +} + +int RT_NOCRT(fegetenv)(fenv_t *__envp); +int RT_NOCRT(feholdexcept)(fenv_t *__envp); + +DECLINLINE(int) +fesetenv(const fenv_t *__envp) +{ + fenv_t __env = *__envp; + int __mxcsr; + + __mxcsr = __get_mxcsr(__env); + __set_mxcsr(__env, 0xffffffff); + __fldenv(__env); + if (__HAS_SSE()) + __ldmxcsr(__mxcsr); + return (0); +} + +int RT_NOCRT(feupdateenv)(const fenv_t *__envp); +int RT_NOCRT(feenableexcept)(int __mask); +int RT_NOCRT(fedisableexcept)(int __mask); + +DECLINLINE(int) +fegetexcept(void) +{ + int __control; + + /* + * We assume that the masks for the x87 and the SSE unit are + * the same. + */ + __fnstcw(&__control); + return (~__control & FE_ALL_EXCEPT); +} + +RT_C_DECLS_END + +#ifndef RT_WIHTOUT_NOCRT_WRAPPERS +# define __has_sse RT_NOCRT(__has_sse) +# define __test_sse RT_NOCRT(__test_sse) +# define __test_sse RT_NOCRT(__test_sse) +# define fesetexceptflag RT_NOCRT(fesetexceptflag) +# define feraiseexcept RT_NOCRT(feraiseexcept) +# define fegetenv RT_NOCRT(fegetenv) +# define feholdexcept RT_NOCRT(feholdexcept) +# define feupdateenv RT_NOCRT(feupdateenv) +# define feenableexcept RT_NOCRT(feenableexcept) +# define fedisableexcept RT_NOCRT(fedisableexcept) +#endif + +#endif /* !__iprt_nocrt_x86_fenv_h__ */ + diff --git a/include/iprt/nocrt/x86/math.h b/include/iprt/nocrt/x86/math.h new file mode 100644 index 00000000..1d5dbed4 --- /dev/null +++ b/include/iprt/nocrt/x86/math.h @@ -0,0 +1,101 @@ +/** @file + * IPRT / No-CRT - math.h, x86 inlined functions. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_nocrt_x86_math_h +#define ___iprt_nocrt_x86_math_h + +#include <iprt/asm.h> + +#if RT_INLINE_ASM_GNU_STYLE + +DECLINLINE(long double) inline_atan2l(long double lrd1, long double lrd2) +{ + long double lrdResult; + __asm__ __volatile__("fpatan" + : "=t" (lrdResult) + : "u" (lrd1), + "0" (lrd2) + : "st(1)"); + return lrdResult; +} + +DECLINLINE(long double) inline_rintl(long double lrd) +{ + long double lrdResult; + __asm__ __volatile__("frndint" + : "=t" (lrdResult) + : "0" (lrd)); + return lrdResult; +} + +DECLINLINE(float) inline_rintf(float rf) +{ + return (float)inline_rintl(rf); +} + +DECLINLINE(double) inline_rint(double rd) +{ + return (double)inline_rintl(rd); +} + +DECLINLINE(long double) inline_sqrtl(long double lrd) +{ + long double lrdResult; + __asm__ __volatile__("fsqrt" + : "=t" (lrdResult) + : "0" (lrd)); + return lrdResult; +} + +DECLINLINE(float) inline_sqrtf(float rf) +{ + return (float)inline_sqrtl(rf); +} + +DECLINLINE(double) inline_sqrt(double rd) +{ + return (double)inline_sqrtl(rd); +} + + +# undef atan2l +# define atan2l(lrd1, lrd2) inline_atan2l(lrd1, lrd2) +# undef rint +# define rint(rd) inline_rint(rd) +# undef rintf +# define rintf(rf) inline_rintf(rf) +# undef rintl +# define rintl(lrd) inline_rintl(lrd) +# undef sqrt +# define sqrt(rd) inline_sqrt(rd) +# undef sqrtf +# define sqrtf(rf) inline_sqrtf(rf) +# undef sqrtl +# define sqrtl(lrd) inline_sqrtl(lrd) + +#endif /* RT_INLINE_ASM_GNU_STYLE */ + +#endif + diff --git a/include/iprt/ntwrap.mac b/include/iprt/ntwrap.mac new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/include/iprt/ntwrap.mac diff --git a/include/iprt/once.h b/include/iprt/once.h new file mode 100644 index 00000000..31afb739 --- /dev/null +++ b/include/iprt/once.h @@ -0,0 +1,162 @@ +/** @file + * IPRT - Execute Once. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_once_h +#define ___iprt_once_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/asm.h> +#include <iprt/err.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_once RTOnce - Execute Once + * @ingroup grp_rt + * @{ + */ + +/** + * Execute once structure. + * + * This is typically a global variable that is statically initialized + * by RTONCE_INITIALIZER. + */ +typedef struct RTONCE +{ + /** Event semaphore that the other guys are blocking on. */ + RTSEMEVENTMULTI volatile hEventMulti; + /** Reference counter for hEventMulti. */ + int32_t volatile cEventRefs; + /** -1 when uninitialized, 1 when initializing (busy) and 2 when done. */ + int32_t volatile iState; + /** The return code of pfnOnce. */ + int32_t volatile rc; +} RTONCE; +/** Pointer to a execute once struct. */ +typedef RTONCE *PRTONCE; + +/** + * The execute once statemachine. + */ +typedef enum RTONCESTATE +{ + /** RTOnce() has not been called. + * Next: NO_SEM */ + RTONCESTATE_UNINITIALIZED = 1, + /** RTOnce() is busy, no race. + * Next: CREATING_SEM, DONE */ + RTONCESTATE_BUSY_NO_SEM, + /** More than one RTOnce() caller is busy. + * Next: BUSY_HAVE_SEM, BUSY_SPIN, DONE_CREATING_SEM, DONE */ + RTONCESTATE_BUSY_CREATING_SEM, + /** More than one RTOnce() caller, the first is busy, the others are + * waiting. + * Next: DONE */ + RTONCESTATE_BUSY_HAVE_SEM, + /** More than one RTOnce() caller, the first is busy, the others failed to + * create a semaphore and are spinning. + * Next: DONE */ + RTONCESTATE_BUSY_SPIN, + /** More than one RTOnce() caller, the first has completed, the others + * are busy creating the semaphore. + * Next: DONE_HAVE_SEM */ + RTONCESTATE_DONE_CREATING_SEM, + /** More than one RTOnce() caller, the first is busy grabbing the + * semaphore, while the others are waiting. + * Next: DONE */ + RTONCESTATE_DONE_HAVE_SEM, + /** The execute once stuff has completed. */ + RTONCESTATE_DONE = 16 +} RTONCESTATE; + +/** Static initializer for RTONCE variables. */ +#define RTONCE_INITIALIZER { NIL_RTSEMEVENTMULTI, 0, RTONCESTATE_UNINITIALIZED, VERR_INTERNAL_ERROR } + + +/** + * Callback that gets executed once. + * + * @returns IPRT style status code, RTOnce returns this. + * + * @param pvUser1 The first user parameter. + * @param pvUser2 The second user parameter. + */ +typedef DECLCALLBACK(int32_t) FNRTONCE(void *pvUser1, void *pvUser2); +/** Pointer to a FNRTONCE. */ +typedef FNRTONCE *PFNRTONCE; + +/** + * Serializes execution of the pfnOnce function, making sure it's + * executed exactly once and that nobody returns from RTOnce before + * it has executed successfully. + * + * @returns IPRT like status code returned by pfnOnce. + * + * @param pOnce Pointer to the execute once variable. + * @param pfnOnce The function to executed once. + * @param pvUser1 The first user parameter for pfnOnce. + * @param pvUser2 The second user parameter for pfnOnce. + */ +RTDECL(int) RTOnceSlow(PRTONCE pOnce, PFNRTONCE pfnOnce, void *pvUser1, void *pvUser2); + +/** + * Serializes execution of the pfnOnce function, making sure it's + * executed exactly once and that nobody returns from RTOnce before + * it has executed successfully. + * + * @returns IPRT like status code returned by pfnOnce. + * + * @param pOnce Pointer to the execute once variable. + * @param pfnOnce The function to executed once. + * @param pvUser1 The first user parameter for pfnOnce. + * @param pvUser2 The second user parameter for pfnOnce. + */ +DECLINLINE(int) RTOnce(PRTONCE pOnce, PFNRTONCE pfnOnce, void *pvUser1, void *pvUser2) +{ + int32_t iState = ASMAtomicUoReadS32(&pOnce->iState); + if (RT_LIKELY( iState == RTONCESTATE_DONE + || iState == RTONCESTATE_DONE_CREATING_SEM + || iState == RTONCESTATE_DONE_HAVE_SEM )) + return ASMAtomicUoReadS32(&pOnce->rc); + return RTOnceSlow(pOnce, pfnOnce, pvUser1, pvUser2); +} + +/** + * Resets an execute once variable. + * + * The caller is responsible for making sure there are no concurrent accesses to + * the execute once variable. + * + * @param pOnce Pointer to the execute once variable. + */ +RTDECL(void) RTOnceReset(PRTONCE pOnce); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/param.h b/include/iprt/param.h new file mode 100644 index 00000000..0e95e52d --- /dev/null +++ b/include/iprt/param.h @@ -0,0 +1,131 @@ +/** @file + * IPRT - Parameter Definitions. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_param_h +#define ___iprt_param_h + +/** @todo Much of the PAGE_* stuff here is obsolete and highly risky to have around. + * As for component configs (MM_*), either we gather all in here or we move those bits away! */ + +/** @defgroup grp_rt_param System Parameter Definitions + * @ingroup grp_rt_cdefs + * @{ + */ + +/* Undefine PAGE_SIZE and PAGE_SHIFT to avoid unnecessary noice when clashing + * with system headers. Include system headers before / after iprt depending + * on which you wish to take precedence. */ +#undef PAGE_SIZE +#undef PAGE_SHIFT + +/* Undefine PAGE_OFFSET_MASK to avoid the conflict with the-linux-kernel.h */ +#undef PAGE_OFFSET_MASK + +/** + * i386 Page size. + */ +#if defined(RT_ARCH_SPARC64) +# define PAGE_SIZE 8192 +#else +# define PAGE_SIZE 4096 +#endif + +/** + * i386 Page shift. + * This is used to convert between size (in bytes) and page count. + */ +#if defined(RT_ARCH_SPARC64) +# define PAGE_SHIFT 13 +#else +# define PAGE_SHIFT 12 +#endif + +/** + * i386 Page offset mask. + * + * Do NOT one-complement this for whatever purpose. You may get a 32-bit const when you want a 64-bit one. + * Use PAGE_BASE_MASK, PAGE_BASE_GC_MASK, PAGE_BASE_HC_MASK, PAGE_ADDRESS() or X86_PTE_PAE_PG_MASK. + */ +#if defined(RT_ARCH_SPARC64) +# define PAGE_OFFSET_MASK 0x1fff +#else +# define PAGE_OFFSET_MASK 0xfff +#endif + +/** + * Page address mask for the guest context POINTERS. + * @remark Physical addresses are always masked using X86_PTE_PAE_PG_MASK! + */ +#define PAGE_BASE_GC_MASK (~(RTGCUINTPTR)PAGE_OFFSET_MASK) + +/** + * Page address mask for the host context POINTERS. + * @remark Physical addresses are always masked using X86_PTE_PAE_PG_MASK! + */ +#define PAGE_BASE_HC_MASK (~(RTHCUINTPTR)PAGE_OFFSET_MASK) + +/** + * Page address mask for the both context POINTERS. + * + * Be careful when using this since it may be a size too big! + * @remark Physical addresses are always masked using X86_PTE_PAE_PG_MASK! + */ +#define PAGE_BASE_MASK (~(RTUINTPTR)PAGE_OFFSET_MASK) + +/** + * Get the page aligned address of a POINTER in the CURRENT context. + * + * @returns Page aligned address (it's an uintptr_t). + * @param pv The virtual address to align. + * + * @remarks Physical addresses are always masked using X86_PTE_PAE_PG_MASK! + * @remarks This only works with POINTERS in the current context. + * Do NOT use on guest address or physical address! + */ +#define PAGE_ADDRESS(pv) ((uintptr_t)(pv) & ~(uintptr_t)PAGE_OFFSET_MASK) + +/** + * Get the page aligned address of a physical address + * + * @returns Page aligned address (it's an RTHCPHYS or RTGCPHYS). + * @param Phys The physical address to align. + */ +#define PHYS_PAGE_ADDRESS(Phys) ((Phys) & X86_PTE_PAE_PG_MASK) + +/** + * Host max path (the reasonable value). + * @remarks defined both by iprt/param.h and iprt/path.h. + */ +#if !defined(___iprt_path_h) || defined(DOXYGEN_RUNNING) +# define RTPATH_MAX (4096 + 4) /* (PATH_MAX + 1) on linux w/ some alignment */ +#endif + +/** @} */ + + +/** @} */ + +#endif + diff --git a/include/iprt/path.h b/include/iprt/path.h new file mode 100644 index 00000000..7e51f87d --- /dev/null +++ b/include/iprt/path.h @@ -0,0 +1,942 @@ +/** @file + * IPRT - Path Manipulation. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_path_h +#define ___iprt_path_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#ifdef IN_RING3 +# include <iprt/fs.h> +#endif + + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_path RTPath - Path Manipulation + * @ingroup grp_rt + * @{ + */ + +/** + * Host max path (the reasonable value). + * @remarks defined both by iprt/param.h and iprt/path.h. + */ +#if !defined(___iprt_param_h) || defined(DOXYGEN_RUNNING) +# define RTPATH_MAX (4096 + 4) /* (PATH_MAX + 1) on linux w/ some alignment */ +#endif + +/** @def RTPATH_SLASH + * The preferred slash character. + * + * @remark IPRT will always accept unix slashes. So, normally you would + * never have to use this define. + */ +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +# define RTPATH_SLASH '\\' +#else +# define RTPATH_SLASH '/' +#endif + +/** @deprecated Use '/'! */ +#define RTPATH_DELIMITER RTPATH_SLASH + + +/** @def RTPATH_SLASH_STR + * The preferred slash character as a string, handy for concatenations + * with other strings. + * + * @remark IPRT will always accept unix slashes. So, normally you would + * never have to use this define. + */ +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +# define RTPATH_SLASH_STR "\\" +#else +# define RTPATH_SLASH_STR "/" +#endif + + +/** @def RTPATH_IS_SLASH + * Checks if a character is a slash. + * + * @returns true if it's a slash and false if not. + * @returns @param ch Char to check. + */ +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +# define RTPATH_IS_SLASH(ch) ( (ch) == '\\' || (ch) == '/' ) +#else +# define RTPATH_IS_SLASH(ch) ( (ch) == '/' ) +#endif + + +/** @def RTPATH_IS_VOLSEP + * Checks if a character marks the end of the volume specification. + * + * @remark This is sufficient for the drive letter concept on PC. + * However it might be insufficient on other platforms + * and even on PC a UNC volume spec won't be detected this way. + * Use the RTPath@<too be created@>() instead. + * + * @returns true if it is and false if it isn't. + * @returns @param ch Char to check. + */ +#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) +# define RTPATH_IS_VOLSEP(ch) ( (ch) == ':' ) +#else +# define RTPATH_IS_VOLSEP(ch) (false) +#endif + + +/** @def RTPATH_IS_SEP + * Checks if a character is path component separator + * + * @returns true if it is and false if it isn't. + * @returns @param ch Char to check. + * @ + */ +#define RTPATH_IS_SEP(ch) ( RTPATH_IS_SLASH(ch) || RTPATH_IS_VOLSEP(ch) ) + + +/** @name Generic RTPath flags + * @{ */ +/** Last component: Work on the link. */ +#define RTPATH_F_ON_LINK RT_BIT_32(0) +/** Last component: Follow if link. */ +#define RTPATH_F_FOLLOW_LINK RT_BIT_32(1) +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTPATH_F_NO_SYMLINKS RT_BIT_32(2) +/** @} */ + + +/** Validates a flags parameter containing RTPATH_F_*. + * @remarks The parameters will be referenced multiple times. */ +#define RTPATH_F_IS_VALID(fFlags, fIgnore) \ + ( ((fFlags) & ~(uint32_t)((fIgnore)|RTPATH_F_NO_SYMLINKS)) == RTPATH_F_ON_LINK \ + || ((fFlags) & ~(uint32_t)((fIgnore)|RTPATH_F_NO_SYMLINKS)) == RTPATH_F_FOLLOW_LINK ) + + +/** + * Checks if the path exists. + * + * Symbolic links will all be attempted resolved and broken links means false. + * + * @returns true if it exists and false if it doesn't. + * @param pszPath The path to check. + */ +RTDECL(bool) RTPathExists(const char *pszPath); + +/** + * Checks if the path exists. + * + * @returns true if it exists and false if it doesn't. + * @param pszPath The path to check. + * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK. + */ +RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags); + +/** + * Sets the current working directory of the process. + * + * @returns IPRT status code. + * @param pszPath The path to the new working directory. + */ +RTDECL(int) RTPathSetCurrent(const char *pszPath); + +/** + * Gets the current working directory of the process. + * + * @returns IPRT status code. + * @param pszPath Where to store the path. + * @param cchPath The size of the buffer pszPath points to. + */ +RTDECL(int) RTPathGetCurrent(char *pszPath, size_t cchPath); + +/** + * Get the real path (no symlinks, no . or .. components), must exist. + * + * @returns iprt status code. + * @param pszPath The path to resolve. + * @param pszRealPath Where to store the real path. + * @param cchRealPath Size of the buffer. + */ +RTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, size_t cchRealPath); + +/** + * Same as RTPathReal only the result is RTStrDup()'ed. + * + * @returns Pointer to real path. Use RTStrFree() to free this string. + * @returns NULL if RTPathReal() or RTStrDup() fails. + * @param pszPath The path to resolve. + */ +RTDECL(char *) RTPathRealDup(const char *pszPath); + +/** + * Get the absolute path (starts from root, no . or .. components), doesn't have + * to exist. Note that this method is designed to never perform actual file + * system access, therefore symlinks are not resolved. + * + * @returns iprt status code. + * @param pszPath The path to resolve. + * @param pszAbsPath Where to store the absolute path. + * @param cchAbsPath Size of the buffer. + */ +RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cchAbsPath); + +/** + * Same as RTPathAbs only the result is RTStrDup()'ed. + * + * @returns Pointer to the absolute path. Use RTStrFree() to free this string. + * @returns NULL if RTPathAbs() or RTStrDup() fails. + * @param pszPath The path to resolve. + */ +RTDECL(char *) RTPathAbsDup(const char *pszPath); + +/** + * Get the absolute path (no symlinks, no . or .. components), assuming the + * given base path as the current directory. The resulting path doesn't have + * to exist. + * + * @returns iprt status code. + * @param pszBase The base path to act like a current directory. + * When NULL, the actual cwd is used (i.e. the call + * is equivalent to RTPathAbs(pszPath, ...). + * @param pszPath The path to resolve. + * @param pszAbsPath Where to store the absolute path. + * @param cchAbsPath Size of the buffer. + */ +RTDECL(int) RTPathAbsEx(const char *pszBase, const char *pszPath, char *pszAbsPath, size_t cchAbsPath); + +/** + * Same as RTPathAbsEx only the result is RTStrDup()'ed. + * + * @returns Pointer to the absolute path. Use RTStrFree() to free this string. + * @returns NULL if RTPathAbsEx() or RTStrDup() fails. + * @param pszBase The base path to act like a current directory. + * When NULL, the actual cwd is used (i.e. the call + * is equivalent to RTPathAbs(pszPath, ...). + * @param pszPath The path to resolve. + */ +RTDECL(char *) RTPathAbsExDup(const char *pszBase, const char *pszPath); + +/** + * Strips the filename from a path. Truncates the given string in-place by overwriting the + * last path separator character with a null byte in a platform-neutral way. + * + * @param pszPath Path from which filename should be extracted, will be truncated. + * If the string contains no path separator, it will be changed to a "." string. + */ +RTDECL(void) RTPathStripFilename(char *pszPath); + +/** + * Strips the extension from a path. + * + * @param pszPath Path which extension should be stripped. + */ +RTDECL(void) RTPathStripExt(char *pszPath); + +/** + * Strips the trailing slashes of a path name. + * + * Won't strip root slashes. + * + * @returns The new length of pszPath. + * @param pszPath Path to strip. + */ +RTDECL(size_t) RTPathStripTrailingSlash(char *pszPath); + +/** + * Changes all the slashes in the specified path to DOS style. + * + * Unless @a fForce is set, nothing will be done when on a UNIX flavored system + * since paths wont work with DOS style slashes there. + * + * @returns @a pszPath. + * @param pszPath The path to modify. + * @param fForce Whether to force the conversion on non-DOS OSes. + */ +RTDECL(char *) RTPathChangeToDosSlashes(char *pszPath, bool fForce); + +/** + * Changes all the slashes in the specified path to unix style. + * + * Unless @a fForce is set, nothing will be done when on a UNIX flavored system + * since paths wont work with DOS style slashes there. + * + * @returns @a pszPath. + * @param pszPath The path to modify. + * @param fForce Whether to force the conversion on non-DOS OSes. + */ +RTDECL(char *) RTPathChangeToUnixSlashes(char *pszPath, bool fForce); + +/** + * Parses a path. + * + * It figures the length of the directory component, the offset of + * the file name and the location of the suffix dot. + * + * @returns The path length. + * + * @param pszPath Path to find filename in. + * @param pcchDir Where to put the length of the directory component. If + * no directory, this will be 0. Optional. + * @param poffName Where to store the filename offset. + * If empty string or if it's ending with a slash this + * will be set to -1. Optional. + * @param poffSuff Where to store the suffix offset (the last dot). + * If empty string or if it's ending with a slash this + * will be set to -1. Optional. + */ +RTDECL(size_t) RTPathParse(const char *pszPath, size_t *pcchDir, ssize_t *poffName, ssize_t *poffSuff); + +/** + * Finds the filename in a path. + * + * @returns Pointer to filename within pszPath. + * @returns NULL if no filename (i.e. empty string or ends with a slash). + * @param pszPath Path to find filename in. + */ +RTDECL(char *) RTPathFilename(const char *pszPath); + +/** + * Finds the extension part of in a path. + * + * @returns Pointer to extension within pszPath. + * @returns NULL if no extension. + * @param pszPath Path to find extension in. + */ +RTDECL(char *) RTPathExt(const char *pszPath); + +/** + * Checks if a path has an extension. + * + * @returns true if extension present. + * @returns false if no extension. + * @param pszPath Path to check. + */ +RTDECL(bool) RTPathHasExt(const char *pszPath); +/** Misspelled, don't use. */ +#define RTPathHaveExt RTPathHasExt + +/** + * Checks if a path includes more than a filename. + * + * @returns true if path present. + * @returns false if no path. + * @param pszPath Path to check. + */ +RTDECL(bool) RTPathHasPath(const char *pszPath); +/** Misspelled, don't use. */ +#define RTPathHavePath RTPathHasPath + +/** + * Checks if the path starts with a root specifier or not. + * + * @returns @c true if it starts with root, @c false if not. + * + * @param pszPath Path to check. + */ +RTDECL(bool) RTPathStartsWithRoot(const char *pszPath); + +/** + * Counts the components in the specified path. + * + * An empty string has zero components. A lone root slash is considered have + * one. The paths "/init" and "/bin/" are considered having two components. An + * UNC share specifier like "\\myserver\share" will be considered as one single + * component. + * + * @returns The number of path components. + * @param pszPath The path to parse. + */ +RTDECL(size_t) RTPathCountComponents(const char *pszPath); + +/** + * Copies the specified number of path components from @a pszSrc and into @a + * pszDst. + * + * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW. In the latter case the buffer + * is not touched. + * + * @param pszDst The destination buffer. + * @param cbDst The size of the destination buffer. + * @param pszSrc The source path. + * @param cComponents The number of components to copy from @a pszSrc. + */ +RTDECL(int) RTPathCopyComponents(char *pszDst, size_t cbDst, const char *pszSrc, size_t cComponents); + +/** + * Compares two paths. + * + * The comparison takes platform-dependent details into account, + * such as: + * <ul> + * <li>On DOS-like platforms, both separator chars (|\| and |/|) are considered + * to be equal. + * <li>On platforms with case-insensitive file systems, mismatching characters + * are uppercased and compared again. + * </ul> + * + * @returns @< 0 if the first path less than the second path. + * @returns 0 if the first path identical to the second path. + * @returns @> 0 if the first path greater than the second path. + * + * @param pszPath1 Path to compare (must be an absolute path). + * @param pszPath2 Path to compare (must be an absolute path). + * + * @remarks File system details are currently ignored. This means that you won't + * get case-insensitive compares on unix systems when a path goes into a + * case-insensitive filesystem like FAT, HPFS, HFS, NTFS, JFS, or + * similar. For NT, OS/2 and similar you'll won't get case-sensitive + * compares on a case-sensitive file system. + */ +RTDECL(int) RTPathCompare(const char *pszPath1, const char *pszPath2); + +/** + * Checks if a path starts with the given parent path. + * + * This means that either the path and the parent path matches completely, or + * that the path is to some file or directory residing in the tree given by the + * parent directory. + * + * The path comparison takes platform-dependent details into account, + * see RTPathCompare() for details. + * + * @returns |true| when \a pszPath starts with \a pszParentPath (or when they + * are identical), or |false| otherwise. + * + * @param pszPath Path to check, must be an absolute path. + * @param pszParentPath Parent path, must be an absolute path. + * No trailing directory slash! + * + * @remarks This API doesn't currently handle root directory compares in a + * manner consistent with the other APIs. RTPathStartsWith(pszSomePath, + * "/") will not work if pszSomePath isn't "/". + */ +RTDECL(bool) RTPathStartsWith(const char *pszPath, const char *pszParentPath); + +/** + * Appends one partial path to another. + * + * The main purpose of this function is to deal correctly with the slashes when + * concatenating the two partial paths. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the result is too big to fit within + * cbPathDst bytes. No changes has been made. + * @retval VERR_INVALID_PARAMETER if the string pointed to by pszPath is longer + * than cbPathDst-1 bytes (failed to find terminator). Asserted. + * + * @param pszPath The path to append pszAppend to. This serves as both + * input and output. This can be empty, in which case + * pszAppend is just copied over. + * @param cbPathDst The size of the buffer pszPath points to, terminator + * included. This should NOT be strlen(pszPath). + * @param pszAppend The partial path to append to pszPath. This can be + * NULL, in which case nothing is done. + * + * @remarks See the RTPathAppendEx remarks. + */ +RTDECL(int) RTPathAppend(char *pszPath, size_t cbPathDst, const char *pszAppend); + +/** + * Appends one partial path to another. + * + * The main purpose of this function is to deal correctly with the slashes when + * concatenating the two partial paths. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the result is too big to fit within + * cbPathDst bytes. No changes has been made. + * @retval VERR_INVALID_PARAMETER if the string pointed to by pszPath is longer + * than cbPathDst-1 bytes (failed to find terminator). Asserted. + * + * @param pszPath The path to append pszAppend to. This serves as both + * input and output. This can be empty, in which case + * pszAppend is just copied over. + * @param cbPathDst The size of the buffer pszPath points to, terminator + * included. This should NOT be strlen(pszPath). + * @param pszAppend The partial path to append to pszPath. This can be + * NULL, in which case nothing is done. + * @param cchAppendMax The maximum number or characters to take from @a + * pszAppend. RTSTR_MAX is fine. + * + * @remarks On OS/2, Window and similar systems, concatenating a drive letter + * specifier with a slash prefixed path will result in an absolute + * path. Meaning, RTPathAppend(strcpy(szBuf, "C:"), sizeof(szBuf), + * "/bar") will result in "C:/bar". (This follows directly from the + * behavior when pszPath is empty.) + * + * On the other hand, when joining a drive letter specifier with a + * partial path that does not start with a slash, the result is not an + * absolute path. Meaning, RTPathAppend(strcpy(szBuf, "C:"), + * sizeof(szBuf), "bar") will result in "C:bar". + */ +RTDECL(int) RTPathAppendEx(char *pszPath, size_t cbPathDst, const char *pszAppend, size_t cchAppendMax); + +/** + * Like RTPathAppend, but with the base path as a separate argument instead of + * in the path buffer. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the result is too big to fit within + * cbPathDst bytes. + * @retval VERR_INVALID_PARAMETER if the string pointed to by pszPath is longer + * than cbPathDst-1 bytes (failed to find terminator). Asserted. + * + * @param pszPathDst Where to store the resulting path. + * @param cbPathDst The size of the buffer pszPathDst points to, + * terminator included. + * @param pszPathSrc The base path to copy into @a pszPathDst before + * appending @a pszAppend. + * @param pszAppend The partial path to append to pszPathSrc. This can + * be NULL, in which case nothing is done. + * + */ +RTDECL(int) RTPathJoin(char *pszPathDst, size_t cbPathDst, const char *pszPathSrc, + const char *pszAppend); + +/** + * Same as RTPathJoin, except that the output buffer is allocated. + * + * @returns Buffer containing the joined up path, call RTStrFree to free. NULL + * on allocation failure. + * @param pszPathSrc The base path to copy into @a pszPathDst before + * appending @a pszAppend. + * @param pszAppend The partial path to append to pszPathSrc. This can + * be NULL, in which case nothing is done. + * + */ +RTDECL(char *) RTPathJoinA(const char *pszPathSrc, const char *pszAppend); + +/** + * Extended version of RTPathJoin, both inputs can be specified as substrings. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the result is too big to fit within + * cbPathDst bytes. + * @retval VERR_INVALID_PARAMETER if the string pointed to by pszPath is longer + * than cbPathDst-1 bytes (failed to find terminator). Asserted. + * + * @param pszPathDst Where to store the resulting path. + * @param cbPathDst The size of the buffer pszPathDst points to, + * terminator included. + * @param pszPathSrc The base path to copy into @a pszPathDst before + * appending @a pszAppend. + * @param cchPathSrcMax The maximum number of bytes to copy from @a + * pszPathSrc. RTSTR_MAX is find. + * @param pszAppend The partial path to append to pszPathSrc. This can + * be NULL, in which case nothing is done. + * @param cchAppendMax The maximum number of bytes to copy from @a + * pszAppend. RTSTR_MAX is find. + * + */ +RTDECL(int) RTPathJoinEx(char *pszPathDst, size_t cbPathDst, + const char *pszPathSrc, size_t cchPathSrcMax, + const char *pszAppend, size_t cchAppendMax); + +/** + * Callback for RTPathTraverseList that's called for each element. + * + * @returns IPRT style status code. Return VERR_TRY_AGAIN to continue, any other + * value will abort the traversing and be returned to the caller. + * + * @param pchPath Pointer to the start of the current path. This is + * not null terminated. + * @param cchPath The length of the path. + * @param pvUser1 The first user parameter. + * @param pvUser2 The second user parameter. + */ +typedef DECLCALLBACK(int) FNRTPATHTRAVERSER(char const *pchPath, size_t cchPath, void *pvUser1, void *pvUser2); +/** Pointer to a FNRTPATHTRAVERSER. */ +typedef FNRTPATHTRAVERSER *PFNRTPATHTRAVERSER; + +/** + * Traverses a string that can contain multiple paths separated by a special + * character. + * + * @returns IPRT style status code from the callback or VERR_END_OF_STRING if + * the callback returned VERR_TRY_AGAIN for all paths in the string. + * + * @param pszPathList The string to traverse. + * @param chSep The separator character. Using the null terminator + * is fine, but the result will simply be that there + * will only be one callback for the entire string + * (save any leading white space). + * @param pfnCallback The callback. + * @param pvUser1 First user argument for the callback. + * @param pvUser2 Second user argument for the callback. + */ +RTDECL(int) RTPathTraverseList(const char *pszPathList, char chSep, PFNRTPATHTRAVERSER pfnCallback, void *pvUser1, void *pvUser2); + + +#ifdef IN_RING3 + +/** + * Gets the path to the directory containing the executable. + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathExecDir(char *pszPath, size_t cchPath); + +/** + * Gets the user home directory. + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath); + +/** + * Gets the user documents directory. + * + * The returned path isn't guarantied to exist. + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathUserDocuments(char *pszPath, size_t cchPath); + +/** + * Gets the directory of shared libraries. + * + * This is not the same as RTPathAppPrivateArch() as Linux depends all shared + * libraries in a common global directory where ld.so can find them. + * + * Linux: /usr/lib + * Solaris: /opt/@<application@>/@<arch>@ or something + * Windows: @<program files directory@>/@<application@> + * Old path: same as RTPathExecDir() + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathSharedLibs(char *pszPath, size_t cchPath); + +/** + * Gets the directory for architecture-independent application data, for + * example NLS files, module sources, ... + * + * Linux: /usr/shared/@<application@> + * Solaris: /opt/@<application@> + * Windows: @<program files directory@>/@<application@> + * Old path: same as RTPathExecDir() + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathAppPrivateNoArch(char *pszPath, size_t cchPath); + +/** + * Gets the directory for architecture-dependent application data, for + * example modules which can be loaded at runtime. + * + * Linux: /usr/lib/@<application@> + * Solaris: /opt/@<application@>/@<arch>@ or something + * Windows: @<program files directory@>/@<application@> + * Old path: same as RTPathExecDir() + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathAppPrivateArch(char *pszPath, size_t cchPath); + +/** + * Gets the toplevel directory for architecture-dependent application data. + * + * This differs from RTPathAppPrivateArch on Solaris only where it will work + * around the /opt/@<application@>/amd64 and /opt/@<application@>/i386 multi + * architecture installation style. + * + * Linux: /usr/lib/@<application@> + * Solaris: /opt/@<application@> + * Windows: @<program files directory@>/@<application@> + * Old path: same as RTPathExecDir() + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathAppPrivateArchTop(char *pszPath, size_t cchPath); + +/** + * Gets the directory for documentation. + * + * Linux: /usr/share/doc/@<application@> + * Solaris: /opt/@<application@> + * Windows: @<program files directory@>/@<application@> + * Old path: same as RTPathExecDir() + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathAppDocs(char *pszPath, size_t cchPath); + +/** + * Gets the temporary directory path. + * + * @returns iprt status code. + * @param pszPath Buffer where to store the path. + * @param cchPath Buffer size in bytes. + */ +RTDECL(int) RTPathTemp(char *pszPath, size_t cchPath); + +/** + * Query information about a file system object. + * + * This API will resolve NOT symbolic links in the last component (just like + * unix lstat()). + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if the object exists, information returned. + * @retval VERR_PATH_NOT_FOUND if any but the last component in the specified + * path was not found or was not a directory. + * @retval VERR_FILE_NOT_FOUND if the object does not exist (but path to the + * parent directory exists). + * + * @param pszPath Path to the file system object. + * @param pObjInfo Object information structure to be filled on successful + * return. + * @param enmAdditionalAttribs + * Which set of additional attributes to request. + * Use RTFSOBJATTRADD_NOTHING if this doesn't matter. + */ +RTR3DECL(int) RTPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs); + +/** + * Query information about a file system object. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if the object exists, information returned. + * @retval VERR_PATH_NOT_FOUND if any but the last component in the specified + * path was not found or was not a directory. + * @retval VERR_FILE_NOT_FOUND if the object does not exist (but path to the + * parent directory exists). + * + * @param pszPath Path to the file system object. + * @param pObjInfo Object information structure to be filled on successful return. + * @param enmAdditionalAttribs + * Which set of additional attributes to request. + * Use RTFSOBJATTRADD_NOTHING if this doesn't matter. + * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK. + */ +RTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags); + +/** + * Changes the mode flags of a file system object. + * + * The API requires at least one of the mode flag sets (Unix/Dos) to + * be set. The type is ignored. + * + * This API will resolve symbolic links in the last component since + * mode isn't important for symbolic links. + * + * @returns iprt status code. + * @param pszPath Path to the file system object. + * @param fMode The new file mode, see @ref grp_rt_fs for details. + */ +RTR3DECL(int) RTPathSetMode(const char *pszPath, RTFMODE fMode); + +/** + * Gets the mode flags of a file system object. + * + * @returns iprt status code. + * @param pszPath Path to the file system object. + * @param pfMode Where to store the file mode, see @ref grp_rt_fs for details. + * + * @remark This is wrapper around RTPathQueryInfoEx(RTPATH_F_FOLLOW_LINK) and + * exists to complement RTPathSetMode(). + */ +RTR3DECL(int) RTPathGetMode(const char *pszPath, PRTFMODE pfMode); + +/** + * Changes one or more of the timestamps associated of file system object. + * + * This API will not resolve symbolic links in the last component (just + * like unix lutimes()). + * + * @returns iprt status code. + * @param pszPath Path to the file system object. + * @param pAccessTime Pointer to the new access time. + * @param pModificationTime Pointer to the new modification time. + * @param pChangeTime Pointer to the new change time. NULL if not to be changed. + * @param pBirthTime Pointer to the new time of birth. NULL if not to be changed. + * + * @remark The file system might not implement all these time attributes, + * the API will ignore the ones which aren't supported. + * + * @remark The file system might not implement the time resolution + * employed by this interface, the time will be chopped to fit. + * + * @remark The file system may update the change time even if it's + * not specified. + * + * @remark POSIX can only set Access & Modification and will always set both. + */ +RTR3DECL(int) RTPathSetTimes(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, + PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime); + +/** + * Changes one or more of the timestamps associated of file system object. + * + * @returns iprt status code. + * @param pszPath Path to the file system object. + * @param pAccessTime Pointer to the new access time. + * @param pModificationTime Pointer to the new modification time. + * @param pChangeTime Pointer to the new change time. NULL if not to be changed. + * @param pBirthTime Pointer to the new time of birth. NULL if not to be changed. + * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK. + * + * @remark The file system might not implement all these time attributes, + * the API will ignore the ones which aren't supported. + * + * @remark The file system might not implement the time resolution + * employed by this interface, the time will be chopped to fit. + * + * @remark The file system may update the change time even if it's + * not specified. + * + * @remark POSIX can only set Access & Modification and will always set both. + */ +RTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, + PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags); + +/** + * Gets one or more of the timestamps associated of file system object. + * + * @returns iprt status code. + * @param pszPath Path to the file system object. + * @param pAccessTime Where to store the access time. NULL is ok. + * @param pModificationTime Where to store the modification time. NULL is ok. + * @param pChangeTime Where to store the change time. NULL is ok. + * @param pBirthTime Where to store the creation time. NULL is ok. + * + * @remark This is wrapper around RTPathQueryInfo() and exists to complement + * RTPathSetTimes(). If the last component is a symbolic link, it will + * not be resolved. + */ +RTR3DECL(int) RTPathGetTimes(const char *pszPath, PRTTIMESPEC pAccessTime, PRTTIMESPEC pModificationTime, + PRTTIMESPEC pChangeTime, PRTTIMESPEC pBirthTime); + +/** + * Changes the owner and/or group of a file system object. + * + * This API will not resolve symbolic links in the last component (just + * like unix lchown()). + * + * @returns iprt status code. + * @param pszPath Path to the file system object. + * @param uid The new file owner user id. Pass NIL_RTUID to leave + * this unchanged. + * @param gid The new group id. Pass NIL_RTGUID to leave this + * unchanged. + */ +RTR3DECL(int) RTPathSetOwner(const char *pszPath, uint32_t uid, uint32_t gid); + +/** + * Changes the owner and/or group of a file system object. + * + * @returns iprt status code. + * @param pszPath Path to the file system object. + * @param uid The new file owner user id. Pass NIL_RTUID to leave + * this unchanged. + * @param gid The new group id. Pass NIL_RTGID to leave this + * unchanged. + * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK. + */ +RTR3DECL(int) RTPathSetOwnerEx(const char *pszPath, uint32_t uid, uint32_t gid, uint32_t fFlags); + +/** + * Gets the owner and/or group of a file system object. + * + * @returns iprt status code. + * @param pszPath Path to the file system object. + * @param pUid Where to store the owner user id. NULL is ok. + * @param pGid Where to store the group id. NULL is ok. + * + * @remark This is wrapper around RTPathQueryInfo() and exists to complement + * RTPathGetOwner(). If the last component is a symbolic link, it will + * not be resolved. + */ +RTR3DECL(int) RTPathGetOwner(const char *pszPath, uint32_t *pUid, uint32_t *pGid); + + +/** @name RTPathRename, RTDirRename & RTFileRename flags. + * @{ */ +/** Do not replace anything. */ +#define RTPATHRENAME_FLAGS_NO_REPLACE UINT32_C(0) +/** This will replace attempt any target which isn't a directory. */ +#define RTPATHRENAME_FLAGS_REPLACE RT_BIT(0) +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTPATHRENAME_FLAGS_NO_SYMLINKS RT_BIT(1) +/** @} */ + +/** + * Renames a path within a filesystem. + * + * This will rename symbolic links. If RTPATHRENAME_FLAGS_REPLACE is used and + * pszDst is a symbolic link, it will be replaced and not its target. + * + * @returns IPRT status code. + * @param pszSrc The source path. + * @param pszDst The destination path. + * @param fRename Rename flags, RTPATHRENAME_FLAGS_*. + */ +RTR3DECL(int) RTPathRename(const char *pszSrc, const char *pszDst, unsigned fRename); + +/** @name RTPathUnlink flags. + * @{ */ +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTPATHUNLINK_FLAGS_NO_SYMLINKS RT_BIT(0) +/** @} */ + +/** + * Removes the last component of the path. + * + * @returns IPRT status code. + * @param pszPath The path. + * @param fUnlink Unlink flags, RTPATHUNLINK_FLAGS_*. + */ +RTR3DECL(int) RTPathUnlink(const char *pszPath, uint32_t fUnlink); + +#endif /* IN_RING3 */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/pipe.h b/include/iprt/pipe.h new file mode 100644 index 00000000..11715c88 --- /dev/null +++ b/include/iprt/pipe.h @@ -0,0 +1,226 @@ +/** @file + * IPRT - Anonymous Pipes. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_pipe_h +#define ___iprt_pipe_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_pipe RTPipe - Anonymous Pipes + * @ingroup grp_rt + * @{ + */ + +/** + * Create an anonymous pipe. + * + * @returns IPRT status code. + * @param phPipeRead Where to return the read end of the pipe. + * @param phPipeWrite Where to return the write end of the pipe. + * @param fFlags A combination of RTPIPE_C_XXX defines. + */ +RTDECL(int) RTPipeCreate(PRTPIPE phPipeRead, PRTPIPE phPipeWrite, uint32_t fFlags); + +/** @name RTPipeCreate flags. + * @{ */ +/** Mark the read end as inheritable. */ +#define RTPIPE_C_INHERIT_READ RT_BIT(0) +/** Mark the write end as inheritable. */ +#define RTPIPE_C_INHERIT_WRITE RT_BIT(1) +/** Mask of valid flags. */ +#define RTPIPE_C_VALID_MASK UINT32_C(0x00000003) +/** @} */ + +/** + * Closes one end of a pipe created by RTPipeCreate. + * + * @returns IPRT status code. + * @param hPipe The pipe end to close. + */ +RTDECL(int) RTPipeClose(RTPIPE hPipe); + +/** + * Creates an IPRT pipe handle from a native one. + * + * Do NOT use the native handle after passing it to this function, IPRT owns it + * and might even have closed in some cases (in order to gain some query + * information access on Windows). + * + * @returns IPRT status code. + * @param phPipe Where to return the pipe handle. + * @param hNativePipe The native pipe handle. + * @param fFlags Pipe flags, RTPIPE_N_XXX. + */ +RTDECL(int) RTPipeFromNative(PRTPIPE phPipe, RTHCINTPTR hNativePipe, uint32_t fFlags); + +/** @name RTPipeFromNative flags. + * @{ */ +/** The read end. */ +#define RTPIPE_N_READ RT_BIT(0) +/** The write end. */ +#define RTPIPE_N_WRITE RT_BIT(1) +/** Make sure the pipe is inheritable if set and not inheritable when clear. */ +#define RTPIPE_N_INHERIT RT_BIT(2) +/** Mask of valid flags. */ +#define RTPIPE_N_VALID_MASK UINT32_C(0x00000007) +/** @} */ + +/** + * Gets the native handle for an IPRT pipe handle. + * + * This is mainly for passing a pipe to a child and then closing the parent + * handle. IPRT also uses it internally to implement RTProcCreatEx and + * RTPollSetAdd on some platforms. Do NOT expect sane API behavior if used + * for any other purpose. + * + * @returns The native handle. -1 on failure. + * @param hPipe The IPRT pipe handle. + */ +RTDECL(RTHCINTPTR) RTPipeToNative(RTPIPE hPipe); + +/** + * Read bytes from a pipe, non-blocking. + * + * @returns IPRT status code. + * @retval VERR_WRONG_ORDER if racing a call to RTPipeReadBlocking. + * @retval VERR_BROKEN_PIPE if the remote party has disconnected and we've read + * all the buffered data. + * @retval VINF_TRY_AGAIN if no data was available. @a *pcbRead will be set to + * 0. + * @retval VERR_ACCESS_DENIED if it's a write pipe. + * + * @param hPipe The IPRT pipe handle to read from. + * @param pvBuf Where to put the bytes we read. + * @param cbToRead How much to read. Must be greater than 0. + * @param pcbRead Where to return the number of bytes that has been + * read (mandatory). This is 0 if there is no more + * bytes to read. + * @sa RTPipeReadBlocking. + */ +RTDECL(int) RTPipeRead(RTPIPE hPipe, void *pvBuf, size_t cbToRead, size_t *pcbRead); + +/** + * Read bytes from a pipe, blocking. + * + * @returns IPRT status code. + * @retval VERR_WRONG_ORDER if racing a call to RTPipeRead. + * @retval VERR_BROKEN_PIPE if the remote party has disconnected and we've read + * all the buffered data. + * @retval VERR_ACCESS_DENIED if it's a write pipe. + * + * @param hPipe The IPRT pipe handle to read from. + * @param pvBuf Where to put the bytes we read. + * @param cbToRead How much to read. + * @param pcbRead Where to return the number of bytes that has been + * read. Optional. + */ +RTDECL(int) RTPipeReadBlocking(RTPIPE hPipe, void *pvBuf, size_t cbToRead, size_t *pcbRead); + +/** + * Write bytes to a pipe, non-blocking. + * + * @returns IPRT status code. + * @retval VERR_WRONG_ORDER if racing a call to RTPipeWriteBlocking. + * @retval VERR_BROKEN_PIPE if the remote party has disconnected. Does not + * trigger when @a cbToWrite is 0. + * @retval VINF_TRY_AGAIN if no data was written. @a *pcbWritten will be set + * to 0. + * @retval VERR_ACCESS_DENIED if it's a read pipe. + * + * @param hPipe The IPRT pipe handle to write to. + * @param pvBuf What to write. + * @param cbToWrite How much to write. + * @param pcbWritten How many bytes we wrote, mandatory. The return can + * be 0. + */ +RTDECL(int) RTPipeWrite(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten); + +/** + * Write bytes to a pipe, blocking. + * + * @returns IPRT status code. + * @retval VERR_WRONG_ORDER if racing a call to RTPipeWrite. + * @retval VERR_BROKEN_PIPE if the remote party has disconnected. Does not + * trigger when @a cbToWrite is 0. + * @retval VERR_ACCESS_DENIED if it's a read pipe. + * + * @param hPipe The IPRT pipe handle to write to. + * @param pvBuf What to write. + * @param cbToWrite How much to write. + * @param pcbWritten How many bytes we wrote, optional. If NULL then all + * bytes will be written. + */ +RTDECL(int) RTPipeWriteBlocking(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten); + +/** + * Flushes the buffers for the specified pipe and making sure the other party + * reads them. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if not supported by the OS. + * @retval VERR_BROKEN_PIPE if the remote party has disconnected. + * @retval VERR_ACCESS_DENIED if it's a read pipe. + * + * @param hPipe The IPRT pipe handle to flush. + */ +RTDECL(int) RTPipeFlush(RTPIPE hPipe); + +/** + * Checks if the pipe is ready for reading or writing (depending on the pipe + * end). + * + * @returns IPRT status code. + * @retval VERR_TIMEOUT if the timeout was reached before the pipe was ready + * for reading/writing. + * @retval VERR_NOT_SUPPORTED if not supported by the OS? + * + * @param hPipe The IPRT pipe handle to select on. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait for ever. + */ +RTDECL(int) RTPipeSelectOne(RTPIPE hPipe, RTMSINTERVAL cMillies); + +/** + * Queries the number of bytes immediately available for reading. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if not supported by the OS. The caller shall + * handle this case. + * + * @param hPipe The IPRT read pipe handle. + * @param pcbReadable Where to return the number of bytes that is ready + * to be read. + */ +RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/poll.h b/include/iprt/poll.h new file mode 100644 index 00000000..33da9c31 --- /dev/null +++ b/include/iprt/poll.h @@ -0,0 +1,243 @@ +/** @file + * IPRT - Polling I/O Handles. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_poll_h +#define ___iprt_poll_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_poll RTPoll - Polling I/O Handles + * @ingroup grp_rt + * @{ + */ + +/** @name Poll events + * @{ */ +/** Readable without blocking. */ +#define RTPOLL_EVT_READ RT_BIT_32(0) +/** Writable without blocking. */ +#define RTPOLL_EVT_WRITE RT_BIT_32(1) +/** Error condition, hangup, exception or similar. */ +#define RTPOLL_EVT_ERROR RT_BIT_32(2) +/** Mask of the valid bits. */ +#define RTPOLL_EVT_VALID_MASK UINT32_C(0x00000007) +/** @} */ + +/** + * Polls on the specified poll set until an event occurs on one of the handles + * or the timeout expires. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if an event occurred on a handle. Note that these + * @retval VERR_INVALID_HANDLE if @a hPollSet is invalid. + * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The + * user is responsible for ensuring single threaded access. + * @retval VERR_TIMEOUT if @a cMillies ellapsed without any events. + * @retval VERR_DEADLOCK if @a cMillies is set to RT_INDEFINITE_WAIT and there + * are no valid handles in the set. + * + * @param hPollSet The set to poll on. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait for ever. + * @param pfEvents Where to return details about the events that + * occurred. Optional. + * @param pid Where to return the ID associated with the + * handle when calling RTPollSetAdd. Optional. + * + * @sa RTPollNoResume + * + * @remarks The caller is responsible for ensuring + */ +RTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid); + +/** + * Same as RTPoll except that it will return when interrupted. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if an event occurred on a handle. Note that these + * @retval VERR_INVALID_HANDLE if @a hPollSet is invalid. + * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The + * user is responsible for ensuring single threaded access. + * @retval VERR_TIMEOUT if @a cMillies ellapsed without any events. + * @retval VERR_DEADLOCK if @a cMillies is set to RT_INDEFINITE_WAIT and there + * are no valid handles in the set. + * @retval VERR_INTERRUPTED if a signal or other asynchronous event interrupted + * the polling. + * + * @param hPollSet The set to poll on. + * @param cMillies Number of milliseconds to wait. Use + * RT_INDEFINITE_WAIT to wait for ever. + * @param pfEvents Where to return details about the events that + * occurred. Optional. + * @param pid Where to return the ID associated with the + * handle when calling RTPollSetAdd. Optional. + */ +RTDECL(int) RTPollNoResume(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid); + +/** + * Creates a poll set with no members. + * + * @returns IPRT status code. + * @param phPollSet Where to return the poll set handle. + */ +RTDECL(int) RTPollSetCreate(PRTPOLLSET phPollSet); + +/** + * Destroys a poll set. + * + * @returns IPRT status code. + * @param hPollSet The poll set to destroy. NIL_POLLSET is quietly + * ignored (VINF_SUCCESS). + */ +RTDECL(int) RTPollSetDestroy(RTPOLLSET hPollSet); + +/** + * Adds a generic handle to the poll set. + * + * @returns IPRT status code + * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The + * user is responsible for ensuring single threaded access. + * @retval VERR_POLL_HANDLE_NOT_POLLABLE if the specified handle is not + * pollable. + * @retval VERR_POLL_HANDLE_ID_EXISTS if the handle ID is already in use in the + * set. + * + * @param hPollSet The poll set to modify. + * @param pHandle The handle to add. NIL handles are quietly + * ignored. + * @param fEvents Which events to poll for. + * @param id The handle ID. + */ +RTDECL(int) RTPollSetAdd(RTPOLLSET hPollSet, PCRTHANDLE pHandle, uint32_t fEvents, uint32_t id); + +/** + * Removes a generic handle from the poll set. + * + * @returns IPRT status code + * @retval VERR_INVALID_HANDLE if @a hPollSet not valid. + * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The + * user is responsible for ensuring single threaded access. + * @retval VERR_POLL_HANDLE_ID_NOT_FOUND if @a id doesn't resolve to a valid + * handle. + * + * @param hPollSet The poll set to modify. + * @param id The handle ID of the handle that should be + * removed. + */ +RTDECL(int) RTPollSetRemove(RTPOLLSET hPollSet, uint32_t id); + + +/** + * Query a handle in the poll set by it's ID. + * + * @returns IPRT status code + * @retval VINF_SUCCESS if the handle was found. @a *pHandle is set. + * @retval VERR_INVALID_HANDLE if @a hPollSet is invalid. + * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The + * user is responsible for ensuring single threaded access. + * @retval VERR_POLL_HANDLE_ID_NOT_FOUND if there is no handle with that ID. + * + * @param hPollSet The poll set to query. + * @param id The ID of the handle. + * @param pHandle Where to return the handle details. Optional. + */ +RTDECL(int) RTPollSetQueryHandle(RTPOLLSET hPollSet, uint32_t id, PRTHANDLE pHandle); + +/** + * Gets the number of handles in the set. + * + * @retval The handle count. + * @retval UINT32_MAX if @a hPollSet is invalid or there is concurrent access. + * + * @param hPollSet The poll set. + */ +RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet); + +/** + * Modifies the events to poll for for the given id. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if @a hPollSet not valid. + * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The + * user is responsible for ensuring single threaded access. + * @retval VERR_POLL_HANDLE_ID_NOT_FOUND if @a id doesn't resolve to a valid + * handle. + * + * @param hPollSet The poll set to modify. + * @param id The handle ID to change the events for. + * @param fEvents Which events to poll for. + */ +RTDECL(int) RTPollSetEventsChange(RTPOLLSET hPollSet, uint32_t id, uint32_t fEvents); + +/** + * Adds a pipe handle to the set. + * + * @returns See RTPollSetAdd. + * + * @param hPollSet The poll set. + * @param hPipe The pipe handle. + * @param fEvents Which events to poll for. + * @param id The handle ID. + * + * @todo Maybe we could figure out what to poll for depending on the kind of + * pipe we're dealing with. + */ +DECLINLINE(int) RTPollSetAddPipe(RTPOLLSET hPollSet, RTPIPE hPipe, uint32_t fEvents, uint32_t id) +{ + RTHANDLE Handle; + Handle.enmType = RTHANDLETYPE_PIPE; + Handle.u.uInt = 0; + Handle.u.hPipe = hPipe; + return RTPollSetAdd(hPollSet, &Handle, fEvents, id); +} + +/** + * Adds a socket handle to the set. + * + * @returns See RTPollSetAdd. + * + * @param hPollSet The poll set. + * @param hSocket The socket handle. + * @param fEvents Which events to poll for. + * @param id The handle ID. + */ +DECLINLINE(int) RTPollSetAddSocket(RTPOLLSET hPollSet, RTSOCKET hSocket, uint32_t fEvents, uint32_t id) +{ + RTHANDLE Handle; + Handle.enmType = RTHANDLETYPE_SOCKET; + Handle.u.uInt = 0; + Handle.u.hSocket = hSocket; + return RTPollSetAdd(hPollSet, &Handle, fEvents, id); +} + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/power.h b/include/iprt/power.h new file mode 100644 index 00000000..7a290734 --- /dev/null +++ b/include/iprt/power.h @@ -0,0 +1,112 @@ +/** @file + * IPRT - Power management. + */ + +/* + * Copyright (C) 2008 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. + */ + +#ifndef ___iprt_power_h +#define ___iprt_power_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_power RTPower - Power management + * @ingroup grp_rt + * @{ + */ + +#ifdef IN_RING0 + +/** + * MP event, see FNRTPOWERNOTIFICATION. + */ +typedef enum RTPOWEREVENT +{ + /** The system will go into suspend mode. */ + RTPOWEREVENT_SUSPEND = 1, + /** The system has resumed. */ + RTPOWEREVENT_RESUME +} RTPOWEREVENT; + +/** + * Notification callback. + * + * The context this is called in differs a bit from platform to + * platform, so be careful while in here. + * + * @param enmEvent The event. + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(void) FNRTPOWERNOTIFICATION(RTPOWEREVENT enmEvent, void *pvUser); +/** Pointer to a FNRTPOWERNOTIFICATION(). */ +typedef FNRTPOWERNOTIFICATION *PFNRTPOWERNOTIFICATION; + +/** + * Registers a notification callback for power events. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_NO_MEMORY if a registration record cannot be allocated. + * @retval VERR_ALREADY_EXISTS if the pfnCallback and pvUser already exist + * in the callback list. + * + * @param pfnCallback The callback. + * @param pvUser The user argument to the callback function. + */ +RTDECL(int) RTPowerNotificationRegister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser); + +/** + * This deregisters a notification callback registered via RTPowerNotificationRegister(). + * + * The pfnCallback and pvUser arguments must be identical to the registration call + * of we won't find the right entry. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_NOT_FOUND if no matching entry was found. + * + * @param pfnCallback The callback. + * @param pvUser The user argument to the callback function. + */ +RTDECL(int) RTPowerNotificationDeregister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser); + +/** + * This calls all registered power management callback handlers registered via RTPowerNotificationRegister(). + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * + * @param enmEvent Power Management event + */ +RTDECL(int) RTPowerSignalEvent(RTPOWEREVENT enmEvent); + +#endif /* IN_RING0 */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/process.h b/include/iprt/process.h new file mode 100644 index 00000000..b359e8ad --- /dev/null +++ b/include/iprt/process.h @@ -0,0 +1,398 @@ +/** @file + * IPRT - Process Management. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_process_h +#define ___iprt_process_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_process RTProc - Process Management + * @ingroup grp_rt + * @{ + */ + + +/** + * Process priority. + * + * The process priority is used to select how scheduling properties + * are assigned to the different thread types (see THREADTYPE). + * + * In addition to using the policy assigned to the process at startup (DEFAULT) + * it is possible to change the process priority at runtime. This allows for + * a GUI, resource manager or admin to adjust the general priority of a task + * without upsetting the fine-tuned priority of the threads within. + */ +typedef enum RTPROCPRIORITY +{ + /** Invalid priority. */ + RTPROCPRIORITY_INVALID = 0, + /** Default priority. + * Derive the scheduling policy from the priority of the RTR3Init() + * and RTProcSetPriority() callers and the rights the process have + * to alter its own priority. + */ + RTPROCPRIORITY_DEFAULT, + /** Flat priority. + * Assumes a scheduling policy which puts the process at the default priority + * and with all thread at the same priority. + */ + RTPROCPRIORITY_FLAT, + /** Low priority. + * Assumes a scheduling policy which puts the process mostly below the + * default priority of the host OS. + */ + RTPROCPRIORITY_LOW, + /** Normal priority. + * Assume a scheduling policy which shares the CPU resources fairly with + * other processes running with the default priority of the host OS. + */ + RTPROCPRIORITY_NORMAL, + /** High priority. + * Assumes a scheduling policy which puts the task above the default + * priority of the host OS. This policy might easily cause other tasks + * in the system to starve. + */ + RTPROCPRIORITY_HIGH, + /** Last priority, used for validation. */ + RTPROCPRIORITY_LAST +} RTPROCPRIORITY; + + +/** + * Get the current process identifier. + * + * @returns Process identifier. + */ +RTDECL(RTPROCESS) RTProcSelf(void); + + +#ifdef IN_RING0 +/** + * Get the current process handle. + * + * @returns Ring-0 process handle. + */ +RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void); +#endif + + +#ifdef IN_RING3 + +/** + * Attempts to alter the priority of the current process. + * + * @returns iprt status code. + * @param enmPriority The new priority. + */ +RTR3DECL(int) RTProcSetPriority(RTPROCPRIORITY enmPriority); + +/** + * Gets the current priority of this process. + * + * @returns The priority (see RTPROCPRIORITY). + */ +RTR3DECL(RTPROCPRIORITY) RTProcGetPriority(void); + +/** + * Create a child process. + * + * @returns iprt status code. + * @param pszExec Executable image to use to create the child process. + * @param papszArgs Pointer to an array of arguments to the child. The array terminated by an entry containing NULL. + * @param Env Handle to the environment block for the child. + * @param fFlags Flags, one of the RTPROC_FLAGS_* defines. + * @param pProcess Where to store the process identifier on successful return. + * The content is not changed on failure. NULL is allowed. + */ +RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess); + + +/** + * Create a child process. + * + * @returns IPRT status code. + * + * @param pszExec Executable image to use to create the child process. + * @param papszArgs Pointer to an array of arguments to the child. The + * array terminated by an entry containing NULL. + * @param hEnv Handle to the environment block for the child. Pass + * RTENV_DEFAULT to use the environment of the current + * process. + * @param fFlags Flags, one of the RTPROC_FLAGS_* defines. + * @param phStdIn The standard in handle to assign the new process. Pass + * NULL to use the same as the current process. If the + * handle is NIL, we'll close the standard input of the + * guest. + * @param phStdOut The standard out handle to assign the new process. Pass + * NULL to use the same as the current process. If the + * handle is NIL, we'll close the standard output of the + * guest. + * @param phStdErr The standard error handle to assign the new process. Pass + * NULL to use the same as the current process. If the + * handle is NIL, we'll close the standard error of the + * guest. + * @param pszAsUser User to run the process as. Pass NULL to use the same + * user as the current process. + * Windows: Use user@domain format to specify a domain. + * @param pszPassword Password to use to authenticate @a pszAsUser. Must be + * NULL wif pszAsUser is NULL. Whether this is actually + * used or not depends on the platform. + * @param phProcess Where to store the process handle on successful return. + * The content is not changed on failure. NULL is allowed. + * + * @remarks The handles does not have to be created as inheritable, but it + * doesn't hurt if they are as it may avoid race conditions on some + * platforms. + * + * @remarks The as-user feature isn't supported/implemented on all platforms and + * will cause a-yet-to-be-determined-error-status on these. + */ +RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags, + PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser, + const char *pszPassword, PRTPROCESS phProcess); + +/** @name RTProcCreate and RTProcCreateEx flags + * @{ */ +/** Detach the child process from the parents process tree and process group, + * session or/and console (depends on the platform what's done applicable). + * + * The new process will not be a direct decendent of the parent and it will not + * be possible to wait for it, i.e. @a phProcess shall be NULL. */ +#define RTPROC_FLAGS_DETACHED RT_BIT(0) +/** Don't show the started process. + * This is a window (and maybe OS/2) concept, do not use on other platforms. */ +#define RTPROC_FLAGS_HIDDEN RT_BIT(1) +/** Use special code path for starting child processes from a service (daemon). + * This is a windows concept for dealing with the so called "Session 0" + * isolation which was introduced with Windows Vista. Do not use on other + * platforms. */ +#define RTPROC_FLAGS_SERVICE RT_BIT(2) +/** Suppress changing the process contract id for the child process + * on Solaris. Without this flag the contract id is always changed, as that's + * the more frequently used case. */ +#define RTPROC_FLAGS_SAME_CONTRACT RT_BIT(3) +/** Do not load user profile data when executing a process. + * This bit at the moment only is valid on Windows. */ +#define RTPROC_FLAGS_NO_PROFILE RT_BIT(4) +/** Create process without a console window. + * This is a Windows (and OS/2) concept, do not use on other platforms. */ +#define RTPROC_FLAGS_NO_WINDOW RT_BIT(5) +/** Search the PATH for the executable. */ +#define RTPROC_FLAGS_SEARCH_PATH RT_BIT(6) + +/** @} */ + + +/** + * Process exit reason. + */ +typedef enum RTPROCEXITREASON +{ + /** Normal exit. iStatus contains the exit code. */ + RTPROCEXITREASON_NORMAL = 1, + /** Any abnormal exit. iStatus is undefined. */ + RTPROCEXITREASON_ABEND, + /** Killed by a signal. The iStatus field contains the signal number. */ + RTPROCEXITREASON_SIGNAL +} RTPROCEXITREASON; + +/** + * Process exit status. + */ +typedef struct RTPROCSTATUS +{ + /** The process exit status if the exit was a normal one. */ + int iStatus; + /** The reason the process terminated. */ + RTPROCEXITREASON enmReason; +} RTPROCSTATUS; +/** Pointer to a process exit status structure. */ +typedef RTPROCSTATUS *PRTPROCSTATUS; +/** Pointer to a const process exit status structure. */ +typedef const RTPROCSTATUS *PCRTPROCSTATUS; + + +/** Flags for RTProcWait(). + * @{ */ +/** Block indefinitly waiting for the process to exit. */ +#define RTPROCWAIT_FLAGS_BLOCK 0 +/** Don't block, just check if the process have exited. */ +#define RTPROCWAIT_FLAGS_NOBLOCK 1 +/** @} */ + +/** + * Waits for a process, resumes on interruption. + * + * @returns VINF_SUCCESS when the status code for the process was collected and + * put in *pProcStatus. + * @returns VERR_PROCESS_NOT_FOUND if the specified process wasn't found. + * @returns VERR_PROCESS_RUNNING when the RTPROCWAIT_FLAGS_NOBLOCK and the + * process haven't exited yet. + * + * @param Process The process to wait for. + * @param fFlags The wait flags, any of the RTPROCWAIT_FLAGS_ \#defines. + * @param pProcStatus Where to store the exit status on success. + * Optional. + */ +RTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus); + +/** + * Waits for a process, returns on interruption. + * + * @returns VINF_SUCCESS when the status code for the process was collected and + * put in *pProcStatus. + * @returns VERR_PROCESS_NOT_FOUND if the specified process wasn't found. + * @returns VERR_PROCESS_RUNNING when the RTPROCWAIT_FLAGS_NOBLOCK and the + * process haven't exited yet. + * @returns VERR_INTERRUPTED when the wait was interrupted by the arrival of a + * signal or other async event. + * + * @param Process The process to wait for. + * @param fFlags The wait flags, any of the RTPROCWAIT_FLAGS_ \#defines. + * @param pProcStatus Where to store the exit status on success. + * Optional. + */ +RTR3DECL(int) RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus); + +/** + * Terminates (kills) a running process. + * + * @returns IPRT status code. + * @param Process The process to terminate. + */ +RTR3DECL(int) RTProcTerminate(RTPROCESS Process); + +/** + * Gets the processor affinity mask of the current process. + * + * @returns The affinity mask. + */ +RTR3DECL(uint64_t) RTProcGetAffinityMask(void); + +/** + * Gets the short process name. + * + * @returns Pointer to read-only name string. + */ +RTR3DECL(const char *) RTProcShortName(void); + +/** + * Gets the path to the executable image of the current process. + * + * @returns pszExecPath on success. NULL on buffer overflow or other errors. + * + * @param pszExecPath Where to store the path. + * @param cbExecPath The size of the buffer. + */ +RTR3DECL(char *) RTProcGetExecutablePath(char *pszExecPath, size_t cbExecPath); + +/** + * Daemonize the current process, making it a background process. + * + * The way this work is that it will spawn a detached / backgrounded / + * daemonized / call-it-what-you-want process that isn't a direct child of the + * current process. The spawned will have the same arguments a the caller, + * except that the @a pszDaemonizedOpt is appended to prevent that the new + * process calls this API again. + * + * The new process will have the standard handles directed to/from the + * bitbucket. + * + * @returns IPRT status code. On success it is normal for the caller to exit + * the process by returning from main(). + * + * @param papszArgs The argument vector of the calling process. + * @param pszDaemonized The daemonized option. This is appended to the end + * of the parameter list of the daemonized process. + */ +RTR3DECL(int) RTProcDaemonize(const char * const *papszArgs, const char *pszDaemonizedOpt); + +/** + * Daemonize the current process, making it a background process. The current + * process will exit if daemonizing is successful. + * + * @returns IPRT status code. On success it will only return in the child + * process, the parent will exit. On failure, it will return in the + * parent process and no child has been spawned. + * + * @param fNoChDir Pass false to change working directory to "/". + * @param fNoClose Pass false to redirect standard file streams to the null device. + * @param pszPidfile Path to a file to write the process id of the daemon + * process to. Daemonizing will fail if this file already + * exists or cannot be written. May be NULL. + */ +RTR3DECL(int) RTProcDaemonizeUsingFork(bool fNoChDir, bool fNoClose, const char *pszPidfile); + +/** + * Check if the given process is running on the system. + * + * This check is case sensitive on most systems, except for Windows, OS/2 and + * Darwin. + * + * @returns true if the process is running & false otherwise. + * @param pszName Process name to search for. If no path is given only the + * filename part of the running process set will be + * matched. If a path is specified, the full path will be + * matched. + */ +RTR3DECL(bool) RTProcIsRunningByName(const char *pszName); + +/** + * Query the username of the given process. + * + * @returns IPRT status code. + * @retval VERR_BUFFER_OVERFLOW if the given buffer size is to small for the username. + * @param hProcess The process handle to query the username for. + * @param pszUser Where to store the user name on success. + * @param cbUser The size of the user name buffer. + * @param pcbUser Where to store the username length on success + * or the required buffer size if VERR_BUFFER_OVERFLOW + * is returned. + */ +RTR3DECL(int) RTProcQueryUsername(RTPROCESS hProcess, char *pszUser, size_t cbUser, + size_t *pcbUser); + +/** + * Query the username of the given process allocating the string for the username. + * + * @returns IPRT status code. + * @param hProcess The process handle to query the username for. + * @param ppszUser Where to store the pointer to the string containing + * the username on success. Free with RTStrFree(). + */ +RTR3DECL(int) RTProcQueryUsernameA(RTPROCESS hProcess, char **ppszUser); + +#endif /* IN_RING3 */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/rand.h b/include/iprt/rand.h new file mode 100644 index 00000000..f9fa5b80 --- /dev/null +++ b/include/iprt/rand.h @@ -0,0 +1,317 @@ +/** @file + * IPRT - Random Numbers and Byte Streams. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_rand_h +#define ___iprt_rand_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_rand RTRand - Random Numbers and Byte Streams + * @ingroup grp_rt + * @{ + */ + +/** + * Fills a buffer with random bytes. + * + * @param pv Where to store the random bytes. + * @param cb Number of bytes to generate. + */ +RTDECL(void) RTRandBytes(void *pv, size_t cb) RT_NO_THROW; + +/** + * Generate a 32-bit signed random number in the set [i32First..i32Last]. + * + * @returns The random number. + * @param i32First First number in the set. + * @param i32Last Last number in the set. + */ +RTDECL(int32_t) RTRandS32Ex(int32_t i32First, int32_t i32Last) RT_NO_THROW; + +/** + * Generate a 32-bit signed random number. + * + * @returns The random number. + */ +RTDECL(int32_t) RTRandS32(void) RT_NO_THROW; + +/** + * Generate a 32-bit unsigned random number in the set [u32First..u32Last]. + * + * @returns The random number. + * @param u32First First number in the set. + * @param u32Last Last number in the set. + */ +RTDECL(uint32_t) RTRandU32Ex(uint32_t u32First, uint32_t u32Last) RT_NO_THROW; + +/** + * Generate a 32-bit unsigned random number. + * + * @returns The random number. + */ +RTDECL(uint32_t) RTRandU32(void) RT_NO_THROW; + +/** + * Generate a 64-bit signed random number in the set [i64First..i64Last]. + * + * @returns The random number. + * @param i64First First number in the set. + * @param i64Last Last number in the set. + */ +RTDECL(int64_t) RTRandS64Ex(int64_t i64First, int64_t i64Last) RT_NO_THROW; + +/** + * Generate a 64-bit signed random number. + * + * @returns The random number. + */ +RTDECL(int64_t) RTRandS64(void) RT_NO_THROW; + +/** + * Generate a 64-bit unsigned random number in the set [u64First..u64Last]. + * + * @returns The random number. + * @param u64First First number in the set. + * @param u64Last Last number in the set. + */ +RTDECL(uint64_t) RTRandU64Ex(uint64_t u64First, uint64_t u64Last) RT_NO_THROW; + +/** + * Generate a 64-bit unsigned random number. + * + * @returns The random number. + */ +RTDECL(uint64_t) RTRandU64(void) RT_NO_THROW; + + +/** + * Create an instance of the default random number generator. + * + * @returns IPRT status code. + * @param phRand Where to return the handle to the new random number + * generator. + */ +RTDECL(int) RTRandAdvCreate(PRTRAND phRand) RT_NO_THROW; + +/** + * Create an instance of the default pseudo random number generator. + * + * @returns IPRT status code. + * @param phRand Where to store the handle to the generator. + */ +RTDECL(int) RTRandAdvCreatePseudo(PRTRAND phRand) RT_NO_THROW; + +/** + * Create an instance of the Park-Miller pseudo random number generator. + * + * @returns IPRT status code. + * @param phRand Where to store the handle to the generator. + */ +RTDECL(int) RTRandAdvCreateParkMiller(PRTRAND phRand) RT_NO_THROW; + +/** + * Create an instance of the faster random number generator for the OS. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED on platforms which doesn't have this feature. + * @retval VERR_FILE_NOT_FOUND on system where the random generator hasn't + * been installed or configured correctly. + * @retval VERR_PATH_NOT_FOUND for the same reasons as VERR_FILE_NOT_FOUND. + * + * @param phRand Where to store the handle to the generator. + * + * @remarks Think /dev/urandom. + */ +RTDECL(int) RTRandAdvCreateSystemFaster(PRTRAND phRand) RT_NO_THROW; + +/** + * Create an instance of the truer random number generator for the OS. + * + * Don't use this unless you seriously need good random numbers because most + * systems will have will have problems producing sufficient entropy for this + * and you'll end up blocking while it accumulates. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED on platforms which doesn't have this feature. + * @retval VERR_FILE_NOT_FOUND on system where the random generator hasn't + * been installed or configured correctly. + * @retval VERR_PATH_NOT_FOUND for the same reasons as VERR_FILE_NOT_FOUND. + * + * @param phRand Where to store the handle to the generator. + * + * @remarks Think /dev/random. + */ +RTDECL(int) RTRandAdvCreateSystemTruer(PRTRAND phRand) RT_NO_THROW; + +/** + * Destroys a random number generator. + * + * @returns IPRT status code. + * @param hRand Handle to the random number generator. + */ +RTDECL(int) RTRandAdvDestroy(RTRAND hRand) RT_NO_THROW; + +/** + * Generic method for seeding of a random number generator. + * + * The different generators may have specialized methods for + * seeding, use one of those if you desire better control + * over the result. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if it isn't a pseudo generator. + * + * @param hRand Handle to the random number generator. + * @param u64Seed Seed. + */ +RTDECL(int) RTRandAdvSeed(RTRAND hRand, uint64_t u64Seed) RT_NO_THROW; + +/** + * Save the current state of a pseudo generator. + * + * This can be use to save the state so it can later be resumed at the same + * position. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. *pcbState contains the length of the + * returned string and pszState contains the state string. + * @retval VERR_BUFFER_OVERFLOW if the supplied buffer is too small. *pcbState + * will contain the necessary buffer size. + * @retval VERR_NOT_SUPPORTED by non-psuedo generators. + * + * @param hRand Handle to the random number generator. + * @param pszState Where to store the state. The returned string will be + * null terminated and printable. + * @param pcbState The size of the buffer pszState points to on input, the + * size required / used on return (including the + * terminator, thus the 'cb' instead of 'cch'). + */ +RTDECL(int) RTRandAdvSaveState(RTRAND hRand, char *pszState, size_t *pcbState) RT_NO_THROW; + +/** + * Restores the state of a pseudo generator. + * + * The state must have been obtained using RTRandAdvGetState. + * + * @returns IPRT status code. + * @retval VERR_PARSE_ERROR if the state string is malformed. + * @retval VERR_NOT_SUPPORTED by non-psuedo generators. + * + * @param hRand Handle to the random number generator. + * @param pszState The state to load. + */ +RTDECL(int) RTRandAdvRestoreState(RTRAND hRand, char const *pszState) RT_NO_THROW; + +/** + * Fills a buffer with random bytes. + * + * @param hRand Handle to the random number generator. + * @param pv Where to store the random bytes. + * @param cb Number of bytes to generate. + */ +RTDECL(void) RTRandAdvBytes(RTRAND hRand, void *pv, size_t cb) RT_NO_THROW; + +/** + * Generate a 32-bit signed random number in the set [i32First..i32Last]. + * + * @returns The random number. + * @param hRand Handle to the random number generator. + * @param i32First First number in the set. + * @param i32Last Last number in the set. + */ +RTDECL(int32_t) RTRandAdvS32Ex(RTRAND hRand, int32_t i32First, int32_t i32Last) RT_NO_THROW; + +/** + * Generate a 32-bit signed random number. + * + * @returns The random number. + * @param hRand Handle to the random number generator. + */ +RTDECL(int32_t) RTRandAdvS32(RTRAND hRand) RT_NO_THROW; + +/** + * Generate a 32-bit unsigned random number in the set [u32First..u32Last]. + * + * @returns The random number. + * @param hRand Handle to the random number generator. + * @param u32First First number in the set. + * @param u32Last Last number in the set. + */ +RTDECL(uint32_t) RTRandAdvU32Ex(RTRAND hRand, uint32_t u32First, uint32_t u32Last) RT_NO_THROW; + +/** + * Generate a 32-bit unsigned random number. + * + * @returns The random number. + * @param hRand Handle to the random number generator. + */ +RTDECL(uint32_t) RTRandAdvU32(RTRAND hRand) RT_NO_THROW; + +/** + * Generate a 64-bit signed random number in the set [i64First..i64Last]. + * + * @returns The random number. + * @param hRand Handle to the random number generator. + * @param i64First First number in the set. + * @param i64Last Last number in the set. + */ +RTDECL(int64_t) RTRandAdvS64Ex(RTRAND hRand, int64_t i64First, int64_t i64Last) RT_NO_THROW; + +/** + * Generate a 64-bit signed random number. + * + * @returns The random number. + */ +RTDECL(int64_t) RTRandAdvS64(RTRAND hRand) RT_NO_THROW; + +/** + * Generate a 64-bit unsigned random number in the set [u64First..u64Last]. + * + * @returns The random number. + * @param hRand Handle to the random number generator. + * @param u64First First number in the set. + * @param u64Last Last number in the set. + */ +RTDECL(uint64_t) RTRandAdvU64Ex(RTRAND hRand, uint64_t u64First, uint64_t u64Last) RT_NO_THROW; + +/** + * Generate a 64-bit unsigned random number. + * + * @returns The random number. + * @param hRand Handle to the random number generator. + */ +RTDECL(uint64_t) RTRandAdvU64(RTRAND hRand) RT_NO_THROW; + + +/** @} */ + +RT_C_DECLS_END + + +#endif + diff --git a/include/iprt/req.h b/include/iprt/req.h new file mode 100644 index 00000000..ea5abb63 --- /dev/null +++ b/include/iprt/req.h @@ -0,0 +1,598 @@ +/** @file + * IPRT - Request Queue & Pool. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_req_h +#define ___iprt_req_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +#include <iprt/stdarg.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_req RTReq - Request Queue & Pool. + * @ingroup grp_rt + * @{ + */ + +/** Request queue handle. */ +typedef struct RTREQQUEUEINT *RTREQQUEUE; +/** Pointer to a request queue handle. */ +typedef RTREQQUEUE *PRTREQQUEUE; +/** NIL request queue handle. */ +#define NIL_RTREQQUEUE ((RTREQQUEUE)0) + +/** Request thread pool handle. */ +typedef struct RTREQPOOLINT *RTREQPOOL; +/** Poiner to a request thread pool handle. */ +typedef RTREQPOOL *PRTREQPOOL; +/** NIL request pool handle. */ +#define NIL_RTREQPOOL ((RTREQPOOL)0) + + +/** + * Request type. + */ +typedef enum RTREQTYPE +{ + /** Invalid request. */ + RTREQTYPE_INVALID = 0, + /** RT: Internal. */ + RTREQTYPE_INTERNAL, + /** Maximum request type (exclusive). Used for validation. */ + RTREQTYPE_MAX +} RTREQTYPE; + +/** + * Request flags. + */ +typedef enum RTREQFLAGS +{ + /** The request returns a iprt status code. */ + RTREQFLAGS_IPRT_STATUS = 0, + /** The request is a void request and have no status code. */ + RTREQFLAGS_VOID = 1, + /** Return type mask. */ + RTREQFLAGS_RETURN_MASK = 1, + /** Caller does not wait on the packet, Queue process thread will free it. */ + RTREQFLAGS_NO_WAIT = 2 +} RTREQFLAGS; + + +/** A request packet. */ +typedef struct RTREQ RTREQ; +/** Pointer to an RT request packet. */ +typedef RTREQ *PRTREQ; +/** Nil request handle. */ +#define NIL_RTREQ ((PRTREQ)0) + + +#ifdef IN_RING3 + +/** + * Create a request packet queue + * + * @returns iprt status code. + * @param phQueue Where to store the request queue handle. + */ +RTDECL(int) RTReqQueueCreate(PRTREQQUEUE phQueue); + +/** + * Destroy a request packet queue + * + * @returns iprt status code. + * @param hQueue The request queue. + */ +RTDECL(int) RTReqQueueDestroy(RTREQQUEUE hQueue); + +/** + * Process one or more request packets + * + * @returns iprt status code. + * @returns VERR_TIMEOUT if cMillies was reached without the packet being added. + * + * @param hQueue The request queue. + * @param cMillies Number of milliseconds to wait for a pending request. + * Use RT_INDEFINITE_WAIT to only wait till one is added. + */ +RTDECL(int) RTReqQueueProcess(RTREQQUEUE hQueue, RTMSINTERVAL cMillies); + +/** + * Allocate and queue a call request. + * + * If it's desired to poll on the completion of the request set cMillies + * to 0 and use RTReqWait() to check for completion. In the other case + * use RT_INDEFINITE_WAIT. + * The returned request packet must be freed using RTReqRelease(). + * + * @returns iprt statuscode. + * Will not return VERR_INTERRUPTED. + * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed. + * + * @param hQueue The request queue. + * @param ppReq Where to store the pointer to the request. + * This will be NULL or a valid request pointer not matter what happens. + * @param cMillies Number of milliseconds to wait for the request to + * be completed. Use RT_INDEFINITE_WAIT to only + * wait till it's completed. + * @param pfnFunction Pointer to the function to call. + * @param cArgs Number of arguments following in the ellipsis. + * @param ... Function arguments. + * + * @remarks See remarks on RTReqQueueCallV. + */ +RTDECL(int) RTReqQueueCall(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, PFNRT pfnFunction, unsigned cArgs, ...); + +/** + * Allocate and queue a call request to a void function. + * + * If it's desired to poll on the completion of the request set cMillies + * to 0 and use RTReqWait() to check for completion. In the other case + * use RT_INDEFINITE_WAIT. + * The returned request packet must be freed using RTReqRelease(). + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed. + * + * @param hQueue The request queue. + * @param ppReq Where to store the pointer to the request. + * This will be NULL or a valid request pointer not matter what happens. + * @param cMillies Number of milliseconds to wait for the request to + * be completed. Use RT_INDEFINITE_WAIT to only + * wait till it's completed. + * @param pfnFunction Pointer to the function to call. + * @param cArgs Number of arguments following in the ellipsis. + * @param ... Function arguments. + * + * @remarks See remarks on RTReqQueueCallV. + */ +RTDECL(int) RTReqQueueCallVoid(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, PFNRT pfnFunction, unsigned cArgs, ...); + +/** + * Allocate and queue a call request to a void function. + * + * If it's desired to poll on the completion of the request set cMillies + * to 0 and use RTReqWait() to check for completion. In the other case + * use RT_INDEFINITE_WAIT. + * The returned request packet must be freed using RTReqRelease(). + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed. + * + * @param hQueue The request queue. + * @param ppReq Where to store the pointer to the request. + * This will be NULL or a valid request pointer not matter what happens, unless fFlags + * contains RTREQFLAGS_NO_WAIT when it will be optional and always NULL. + * @param cMillies Number of milliseconds to wait for the request to + * be completed. Use RT_INDEFINITE_WAIT to only + * wait till it's completed. + * @param fFlags A combination of the RTREQFLAGS values. + * @param pfnFunction Pointer to the function to call. + * @param cArgs Number of arguments following in the ellipsis. + * @param ... Function arguments. + * + * @remarks See remarks on RTReqQueueCallV. + */ +RTDECL(int) RTReqQueueCallEx(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...); + +/** + * Allocate and queue a call request. + * + * If it's desired to poll on the completion of the request set cMillies + * to 0 and use RTReqWait() to check for completion. In the other case + * use RT_INDEFINITE_WAIT. + * The returned request packet must be freed using RTReqRelease(). + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed. + * + * @param hQueue The request queue. + * @param ppReq Where to store the pointer to the request. + * This will be NULL or a valid request pointer not matter what happens, unless fFlags + * contains RTREQFLAGS_NO_WAIT when it will be optional and always NULL. + * @param cMillies Number of milliseconds to wait for the request to + * be completed. Use RT_INDEFINITE_WAIT to only + * wait till it's completed. + * @param fFlags A combination of the RTREQFLAGS values. + * @param pfnFunction Pointer to the function to call. + * @param cArgs Number of arguments following in the ellipsis. + * @param Args Variable argument vector. + * + * @remarks Caveats: + * - Do not pass anything which is larger than an uintptr_t. + * - 64-bit integers are larger than uintptr_t on 32-bit hosts. + * Pass integers > 32-bit by reference (pointers). + * - Don't use NULL since it should be the integer 0 in C++ and may + * therefore end up with garbage in the bits 63:32 on 64-bit + * hosts because 'int' is 32-bit. + * Use (void *)NULL or (uintptr_t)0 instead of NULL. + */ +RTDECL(int) RTReqQueueCallV(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args); + +/** + * Checks if the queue is busy or not. + * + * The caller is responsible for dealing with any concurrent submitts. + * + * @returns true if busy, false if idle. + * @param hQueue The queue. + */ +RTDECL(bool) RTReqQueueIsBusy(RTREQQUEUE hQueue); + +/** + * Allocates a request packet. + * + * The caller allocates a request packet, fills in the request data + * union and queues the request. + * + * @returns iprt status code. + * + * @param hQueue The request queue. + * @param enmType Package type. + * @param phReq Where to store the handle to the new request. + */ +RTDECL(int) RTReqQueueAlloc(RTREQQUEUE hQueue, RTREQTYPE enmType, PRTREQ *phReq); + + +/** + * Creates a request thread pool. + * + * The core configuration is given as parameters, finer pool tuning can be + * achieved via RTReqPoolSetCfgVar. + * + * @returns IPRT status code. + * @param cMaxThreads The maximum number of worker threads. + * UINT32_MAX is an alias for the highest + * allowed thread count. + * @param cMsMinIdle The number of milliseconds a worker + * thread needs to be idle before it is + * considered for shutdown. The value + * RT_INDEFINITE_WAIT disables automatic + * idle thread shutdown. + * @param cThreadsPushBackThreshold At which worker thread count the push + * back should kick in. + * @param cMsMaxPushBack The max number of milliseconds to push + * back a submitter. UINT32_MAX is an + * alias for the highest allowed push back. + * @param pszName The pool name. Keep it short as it is + * used for naming worker threads. + * @param phPool Where to return the pool handle. + */ +RTDECL(int) RTReqPoolCreate(uint32_t cMaxThreads, RTMSINTERVAL cMsMinIdle, + uint32_t cThreadsPushBackThreshold, uint32_t cMsMaxPushBack, + const char *pszName, PRTREQPOOL phPool); + +/** + * Retainsa reference to a request thread pool. + * + * @returns The new reference count, UINT32_MAX on invalid handle (asserted). + * @param hPool The request thread pool handle. + */ +RTDECL(uint32_t) RTReqPoolRetain(RTREQPOOL hPool); + +/** + * Releases a reference to the request thread pool. + * + * When the reference count reaches zero, the request will be pooled for reuse. + * + * @returns The new reference count, UINT32_MAX on invalid handle (asserted). + * @param hPool The request thread pool handle. + */ +RTDECL(uint32_t) RTReqPoolRelease(RTREQPOOL hPool); + +/** + * Request thread pool configuration variable. + */ +typedef enum RTREQPOOLCFGVAR +{ + /** Invalid zero value. */ + RTREQPOOLCFGVAR_INVALID = 0, + /** The desired RTTHREADTYPE of the worker threads. */ + RTREQPOOLCFGVAR_THREAD_TYPE, + /** The minimum number of threads to keep handy once spawned. */ + RTREQPOOLCFGVAR_MIN_THREADS, + /** The maximum number of thread to start. */ + RTREQPOOLCFGVAR_MAX_THREADS, + /** The minimum number of milliseconds a worker thread needs to be idle + * before we consider shutting it down. The other shutdown criteria + * being set by RTREQPOOLCFGVAR_MIN_THREADS. The value + * RT_INDEFINITE_WAIT can be used to disable shutting down idle threads. */ + RTREQPOOLCFGVAR_MS_MIN_IDLE, + /** The sleep period, in milliseoncds, to employ when idling. The value + * RT_INDEFINITE_WAIT can be used to disable shutting down idle threads. */ + RTREQPOOLCFGVAR_MS_IDLE_SLEEP, + /** The number of threads at which to start pushing back. The value + * UINT64_MAX is an alias for the current upper thread count limit, i.e. + * disabling push back. The value 0 (zero) is an alias for the current + * lower thread count, a good value to start pushing back at. The value + * must otherwise be within */ + RTREQPOOLCFGVAR_PUSH_BACK_THRESHOLD, + /** The minimum push back time in milliseconds. */ + RTREQPOOLCFGVAR_PUSH_BACK_MIN_MS, + /** The maximum push back time in milliseconds. */ + RTREQPOOLCFGVAR_PUSH_BACK_MAX_MS, + /** The maximum number of free requests to keep handy for recycling. */ + RTREQPOOLCFGVAR_MAX_FREE_REQUESTS, + /** The end of the range of valid config variables. */ + RTREQPOOLCFGVAR_END, + /** Blow the type up to 32-bits. */ + RTREQPOOLCFGVAR_32BIT_HACK = 0x7fffffff +} RTREQPOOLCFGVAR; + + +/** + * Sets a config variable for a request thread pool. + * + * @returns IPRT status code. + * @param hPool The pool handle. + * @param enmVar The variable to set. + * @param uValue The new value. + */ +RTDECL(int) RTReqPoolSetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar, uint64_t uValue); + +/** + * Gets a config variable for a request thread pool. + * + * @returns The value, UINT64_MAX on invalid parameters. + * @param hPool The pool handle. + * @param enmVar The variable to query. + */ +RTDECL(uint64_t) RTReqPoolGetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar); + +/** + * Request thread pool statistics value names. + */ +typedef enum RTREQPOOLSTAT +{ + /** The invalid zero value, as per tradition. */ + RTREQPOOLSTAT_INVALID = 0, + /** The current number of worker threads. */ + RTREQPOOLSTAT_THREADS, + /** The number of threads that have been created. */ + RTREQPOOLSTAT_THREADS_CREATED, + /** The total number of requests that have been processed. */ + RTREQPOOLSTAT_REQUESTS_PROCESSED, + /** The total number of requests that have been submitted. */ + RTREQPOOLSTAT_REQUESTS_SUBMITTED, + /** the current number of pending (waiting) requests. */ + RTREQPOOLSTAT_REQUESTS_PENDING, + /** The current number of active (executing) requests. */ + RTREQPOOLSTAT_REQUESTS_ACTIVE, + /** The current number of free (recycled) requests. */ + RTREQPOOLSTAT_REQUESTS_FREE, + /** Total time the requests took to process. */ + RTREQPOOLSTAT_NS_TOTAL_REQ_PROCESSING, + /** Total time the requests had to wait in the queue before being + * scheduled. */ + RTREQPOOLSTAT_NS_TOTAL_REQ_QUEUED, + /** Average time the requests took to process. */ + RTREQPOOLSTAT_NS_AVERAGE_REQ_PROCESSING, + /** Average time the requests had to wait in the queue before being + * scheduled. */ + RTREQPOOLSTAT_NS_AVERAGE_REQ_QUEUED, + /** The end of the valid statistics value names. */ + RTREQPOOLSTAT_END, + /** Blow the type up to 32-bit. */ + RTREQPOOLSTAT_32BIT_HACK = 0x7fffffff +} RTREQPOOLSTAT; + +/** + * Read a statistics value from the request thread pool. + * + * @returns The value, UINT64_MAX if an invalid parameter was given. + * @param hPool The request thread pool handle. + * @param enmStat The statistics value to get. + */ +RTDECL(uint64_t) RTReqPoolGetStat(RTREQPOOL hPool, RTREQPOOLSTAT enmStat); + +/** + * Allocates a request packet. + * + * This is mostly for internal use, please use the convenience methods. + * + * @returns iprt status code. + * + * @param hPool The request thread pool handle. + * @param enmType Package type. + * @param phReq Where to store the handle to the new request. + */ +RTDECL(int) RTReqPoolAlloc(RTREQPOOL hPool, RTREQTYPE enmType, PRTREQ *phReq); + +/** + * Call a function on a worker thread. + * + * @returns IPRT status code. + * @param hPool The request thread pool handle. + * @param cMillies The number of milliseconds to wait for the request + * to be processed. + * @param phReq Where to return the request. Can be NULL if the + * RTREQFLAGS_NO_WAIT flag is used. + * @param fFlags A combination of RTREQFLAGS values. + * @param pfnFunction The function to be called. Must be declared by a + * DECL macro because of calling conventions. + * @param cArgs The number of arguments in the ellipsis. + * @param ... Arguments. + * + * @remarks The function better avoid taking uint64_t and structs as part of the + * arguments (use pointers to these instead). In general anything + * that's larger than an uintptr_t is problematic. + */ +RTDECL(int) RTReqPoolCallEx( RTREQPOOL hPool, RTMSINTERVAL cMillies, PRTREQ *phReq, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...); + + +/** + * Call a function on a worker thread. + * + * @returns IPRT status code. + * @param hPool The request thread pool handle. + * @param cMillies The number of milliseconds to wait for the request + * to be processed. + * @param phReq Where to return the request. Can be NULL if the + * RTREQFLAGS_NO_WAIT flag is used. + * @param fFlags A combination of RTREQFLAGS values. + * @param pfnFunction The function to be called. Must be declared by a + * DECL macro because of calling conventions. + * @param cArgs The number of arguments in the variable argument + * list. + * @param va Arguments. + * @remarks See remarks on RTReqPoolCallEx. + */ +RTDECL(int) RTReqPoolCallExV(RTREQPOOL hPool, RTMSINTERVAL cMillies, PRTREQ *phReq, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list va); + +/** + * Call a function on a worker thread, wait for it to return. + * + * @returns IPRT status code returned by @a pfnFunction or request pool error. + * @param hPool The request thread pool handle. + * @param pfnFunction The function to be called. Must be declared by a + * DECL macro because of calling conventions. The + * function must return an int value compatible with + * the IPRT status code convention. + * @param cArgs The number of arguments in the elipsis. + * @param ... Arguments. + * @remarks See remarks on RTReqPoolCallEx. + */ +RTDECL(int) RTReqPoolCallWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...); + +/** + * Call a function on a worker thread, don't wait for it to return. + * + * @returns IPRT status code. + * @param hPool The request thread pool handle. + * @param pfnFunction The function to be called. Must be declared by a + * DECL macro because of calling conventions. The + * function should return an int value compatible with + * the IPRT status code convention, thought it's not + * all that important as it's thrown away. + * @param cArgs The number of arguments in the elipsis. + * @param ... Arguments. + * @remarks See remarks on RTReqPoolCallEx. + */ +RTDECL(int) RTReqPoolCallNoWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...); + +/** + * Call a void function on a worker thread. + * + * @returns IPRT status code. + * @param hPool The request thread pool handle. + * @param pfnFunction The function to be called. Must be declared by a + * DECL macro because of calling conventions. The + * function is taken to return void. + * @param cArgs The number of arguments in the elipsis. + * @param ... Arguments. + * @remarks See remarks on RTReqPoolCallEx. + */ +RTDECL(int) RTReqPoolCallVoidWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...); + +/** + * Call a void function on a worker thread, don't wait for it to return. + * + * @returns IPRT status code. + * @param hPool The request thread pool handle. + * @param pfnFunction The function to be called. Must be declared by a + * DECL macro because of calling conventions. The + * function is taken to return void. + * @param cArgs The number of arguments in the elipsis. + * @param ... Arguments. + * @remarks See remarks on RTReqPoolCallEx. + */ +RTDECL(int) RTReqPoolCallVoidNoWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...); + + +/** + * Retainsa reference to a request. + * + * @returns The new reference count, UINT32_MAX on invalid handle (asserted). + * @param hReq The request handle. + */ +RTDECL(uint32_t) RTReqRetain(PRTREQ hReq); + +/** + * Releases a reference to the request. + * + * When the reference count reaches zero, the request will be pooled for reuse. + * + * @returns The new reference count, UINT32_MAX on invalid handle (asserted). + * @param hReq Package to release. + */ +RTDECL(uint32_t) RTReqRelease(PRTREQ hReq); + +/** + * Queue a request. + * + * The quest must be allocated using RTReqQueueAlloc() or RTReqPoolAlloc() and + * contain all the required data. + * + * If it's desired to poll on the completion of the request set cMillies + * to 0 and use RTReqWait() to check for completion. In the other case + * use RT_INDEFINITE_WAIT. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed. + * + * @param pReq The request to queue. + * @param cMillies Number of milliseconds to wait for the request to + * be completed. Use RT_INDEFINITE_WAIT to only + * wait till it's completed. + */ +RTDECL(int) RTReqSubmit(PRTREQ pReq, RTMSINTERVAL cMillies); + + +/** + * Wait for a request to be completed. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed. + * + * @param pReq The request to wait for. + * @param cMillies Number of milliseconds to wait. + * Use RT_INDEFINITE_WAIT to only wait till it's completed. + */ +RTDECL(int) RTReqWait(PRTREQ pReq, RTMSINTERVAL cMillies); + +/** + * Get the status of the request. + * + * @returns Status code in the IPRT tradition. + * + * @param pReq The request. + */ +RTDECL(int) RTReqGetStatus(PRTREQ pReq); + +#endif /* IN_RING3 */ + + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/runtime-loader.h b/include/iprt/runtime-loader.h new file mode 100644 index 00000000..81ba40e6 --- /dev/null +++ b/include/iprt/runtime-loader.h @@ -0,0 +1,179 @@ +/** @file + * IPRT - Runtime Loader Generation. + */ + +/* + * Copyright (C) 2008-2010 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. + */ + +#include <iprt/types.h> +#ifdef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS +# include <iprt/ldr.h> +# include <iprt/log.h> +# include <iprt/once.h> +#endif + +/** @defgroup grp_rt_runtime_loader Runtime Loader Generation + * @ingroup grp_rt + * + * How to use this loader generator + * + * This loader generator can be used to generate stub code for loading a shared + * library and its functions at runtime, or for generating a header file with + * the declaration of the loader function and optionally declarations for the + * functions loaded. It should be included in a header file or a C source + * file, after defining certain macros which it makes use of. + * + * To generate the C source code for function proxy stubs and the library + * loader function, you should define the following macros in your source file + * before including this header: + * + * RT_RUNTIME_LOADER_LIB_NAME - the file name of the library to load + * RT_RUNTIME_LOADER_FUNCTION - the name of the loader function + * RT_RUNTIME_LOADER_INSERT_SYMBOLS - a macro containing the names of the + * functions to be loaded, defined in the + * following pattern: + * @code + * #define RT_RUNTIME_LOADER_INSERT_SYMBOLS \ + * RT_PROXY_STUB(func_name, ret_type, (long_param_list), (short_param_list)) \ + * RT_PROXY_STUB(func_name2, ret_type2, (long_param_list2), (short_param_list2)) \ + * ... + * @endcode + * + * where long_param_list is a parameter list for declaring the function of the + * form (type1 arg1, type2 arg2, ...) and short_param_list for calling it, of + * the form (arg1, arg2, ...). + * + * To generate the header file, you should define RT_RUNTIME_LOADER_FUNCTION + * and if you wish to generate declarations for the functions you should + * additionally define RT_RUNTIME_LOADER_INSERT_SYMBOLS as above and + * RT_RUNTIME_LOADER_GENERATE_DECLS (without a value) before including this + * file. + * + * @{ + */ +/** @todo this is far too complicated. A script for generating the files would + * probably be preferable. + * + * bird> An alternative is to generate assembly jump wrappers, this only + * requires the symbol names and prefix. I've done this ages ago when we forked + * the EMX/GCC toolchain on OS/2... It's a wee bit more annoying in x86 PIC/PIE + * mode, but nothing that cannot be dealt with. + */ +/** @todo r=bird: The use of RTR3DECL here is an unresolved issue. */ +/** @todo r=bird: The lack of RT_C_DECLS_BEGIN/END is an unresolved issue. Here + * we'll get into trouble if we use the same symbol names as the + * original! */ +/** @todo r=bird: The prefix usage here is very confused: RT_RUNTIME_LOADER_XXX, + * RT_PROXY_STUB, etc. */ + +#ifdef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS + +/* The following are the symbols which we need from the library. */ +# define RT_PROXY_STUB(function, rettype, signature, shortsig) \ + void (*function ## _fn)(void); \ + RTR3DECL(rettype) function signature \ + { return ( (rettype (*) signature) function ## _fn ) shortsig; } + +RT_RUNTIME_LOADER_INSERT_SYMBOLS + +# undef RT_PROXY_STUB + +/* Now comes a table of functions to be loaded from the library. */ +typedef struct +{ + const char *pszName; + void (**ppfn)(void); +} RTLDRSHAREDFUNC; + +# define RT_PROXY_STUB(s, dummy1, dummy2, dummy3 ) { #s , & s ## _fn } , +static RTLDRSHAREDFUNC g_aSharedFuncs[] = +{ + RT_RUNTIME_LOADER_INSERT_SYMBOLS + { NULL, NULL } +}; +# undef RT_PROXY_STUB + +/** + * The function which does the actual work for RT_RUNTIME_LOADER_FUNCTION, + * serialised for thread safety. + */ +static DECLCALLBACK(int) rtldrLoadOnce(void *, void *) +{ + RTLDRMOD hLib; + int rc; + + LogFlowFunc(("\n")); + rc = RTLdrLoad(RT_RUNTIME_LOADER_LIB_NAME, &hLib); + for (unsigned i = 0; RT_SUCCESS(rc) && g_aSharedFuncs[i].pszName != NULL; ++i) + rc = RTLdrGetSymbol(hLib, g_aSharedFuncs[i].pszName, (void **)g_aSharedFuncs[i].ppfn); + LogFlowFunc(("rc = %Rrc\n", rc)); + + return rc; +} + +/** + * Load the shared library RT_RUNTIME_LOADER_LIB_NAME and resolve the symbols + * pointed to by RT_RUNTIME_LOADER_INSERT_SYMBOLS. + * + * May safely be called from multiple threads and will not return until the + * library is loaded or has failed to load. + * + * @returns IPRT status code. + */ +RTR3DECL(int) RT_RUNTIME_LOADER_FUNCTION(void) +{ + static RTONCE s_Once = RTONCE_INITIALIZER; + int rc; + + LogFlowFunc(("\n")); + rc = RTOnce(&s_Once, rtldrLoadOnce, NULL, NULL); + LogFlowFunc(("rc = %Rrc\n", rc)); + + return rc; +} + +#elif defined(RT_RUNTIME_LOADER_GENERATE_HEADER) +# ifdef RT_RUNTIME_LOADER_GENERATE_DECLS +/* Declarations of the functions that we need from + * RT_RUNTIME_LOADER_LIB_NAME */ +# define RT_PROXY_STUB(function, rettype, signature, shortsig) \ + RTR3DECL(rettype) ( function ) signature ; + +RT_RUNTIME_LOADER_INSERT_SYMBOLS + +# undef RT_PROXY_STUB +# endif /* RT_RUNTIME_LOADER_GENERATE_DECLS */ + +/** + * Try to dynamically load the library. This function should be called before + * attempting to use any of the library functions. It is safe to call this + * function multiple times. + * + * @returns iprt status code + */ +RTR3DECL(int) RT_RUNTIME_LOADER_FUNCTION(void); + +#else +# error "One of RT_RUNTIME_LOADER_GENERATE_HEADER or RT_RUNTIME_LOADER_GENERATE_BODY_STUBS must be defined when including this file" +#endif + +/** @} */ + diff --git a/include/iprt/runtime.h b/include/iprt/runtime.h new file mode 100644 index 00000000..b70bfd1b --- /dev/null +++ b/include/iprt/runtime.h @@ -0,0 +1,86 @@ +/** @file + * IPRT - Include Everything. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_runtime_h +#define ___iprt_runtime_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/param.h> +#include <iprt/initterm.h> + +#if !defined(IN_RC) && !defined(IN_RING0_AGNOSTIC) +# include <iprt/alloca.h> +#endif +#include <iprt/asm.h> +#include <iprt/assert.h> +#include <iprt/avl.h> +#include <iprt/crc.h> +#include <iprt/critsect.h> +#include <iprt/dir.h> +#include <iprt/err.h> +#ifndef IN_RC +# include <iprt/file.h> +# include <iprt/fs.h> +#endif +#include <iprt/getopt.h> +#include <iprt/ldr.h> +#include <iprt/log.h> +#include <iprt/md5.h> +#ifndef IN_RC +# include <iprt/mem.h> +# include <iprt/mp.h> +#endif +#include <iprt/path.h> +#include <iprt/semaphore.h> +#include <iprt/spinlock.h> +#include <iprt/stdarg.h> +#include <iprt/string.h> +#include <iprt/system.h> +#include <iprt/table.h> +#ifndef IN_RC +# include <iprt/thread.h> +#endif +#include <iprt/time.h> +#include <iprt/timer.h> +#include <iprt/uni.h> +#include <iprt/uuid.h> +#include <iprt/zip.h> + +#ifdef IN_RING3 +# include <iprt/stream.h> +# include <iprt/tcp.h> +# include <iprt/ctype.h> +# include <iprt/alloca.h> /** @todo iprt/alloca.h should be made available in R0 and GC too! */ +# include <iprt/process.h> /** @todo iprt/process.h should be made available in R0 too (partly). */ +#endif + +#ifdef IN_RING0 +# include <iprt/memobj.h> +#endif + + +#endif + diff --git a/include/iprt/s3.h b/include/iprt/s3.h new file mode 100644 index 00000000..2c200d5a --- /dev/null +++ b/include/iprt/s3.h @@ -0,0 +1,270 @@ +/* $Id: s3.h $ */ +/** @file + * IPRT - Simple Storage Service (S3) Communication API. + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_s3_h +#define ___iprt_s3_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_s3 RTS3 - Simple Storage Service (S3) Communication API + * @ingroup grp_rt + * @{ + */ + +/** @todo the following three definitions may move the iprt/types.h later. */ +/** RTS3 interface handle. */ +typedef R3PTRTYPE(struct RTS3INTERNAL *) RTS3; +/** Pointer to a RTS3 interface handle. */ +typedef RTS3 *PRTS3; +/** Nil RTS3 interface handle. */ +#define NIL_RTS3 ((RTS3)0) + + +/** + * S3 progress callback. + * + * @returns Reserved, must be 0. + * + * @param uPercent The process completion percentage. + * @param pvUser The user parameter given to RTS3SetProgressCallback. + */ +typedef DECLCALLBACK(int) FNRTS3PROGRESS(unsigned uPercent, void *pvUser); +/** Pointer to a S3 progress callback. */ +typedef FNRTS3PROGRESS *PFNRTS3PROGRESS; + + +/** Pointer to an S3 bucket entry. */ +typedef struct RTS3BUCKETENTRY *PRTS3BUCKETENTRY; +/** Pointer to a const S3 bucket entry. */ +typedef struct RTS3BUCKETENTRY const *PCRTS3BUCKETENTRY; +/** + * RTS3 bucket entry. + * + * Represent a bucket of the S3 storage server. Bucket entries are chained as a + * doubly linked list using the pPrev & pNext member. + * + * @todo Consider making the entire list const unless there are plans for + * more APIs using this structure which requires the caller to create + * or modify it. + */ +typedef struct RTS3BUCKETENTRY +{ + /** The previous element. */ + PRTS3BUCKETENTRY pPrev; + /** The next element. */ + PRTS3BUCKETENTRY pNext; + + /** The name of the bucket. */ + char const *pszName; + /** The creation date of the bucket as string. */ + char const *pszCreationDate; +} RTS3BUCKETENTRY; + + +/** Pointer to an S3 key entry. */ +typedef struct RTS3KEYENTRY *PRTS3KEYENTRY; +/** Pointer to a const S3 key entry. */ +typedef struct RTS3KEYENTRY const *PCRTS3KEYENTRY; +/** + * RTS3 key entry. + * + * Represent a key of the S3 storage server. Key entries are chained as a doubly + * linked list using the pPrev & pNext member. + * + * @todo Consider making the entire list const unless there are plans for + * more APIs using this structure which requires the caller to create + * or modify it. + */ +typedef struct RTS3KEYENTRY +{ + /** The previous element. */ + PRTS3KEYENTRY pPrev; + /** The next element. */ + PRTS3KEYENTRY pNext; + + /** The name of the key. */ + char const *pszName; + /** The date this key was last modified as string. */ + char const *pszLastModified; + /** The size of the file behind this key in bytes. */ + uint64_t cbFile; +} RTS3KEYENTRY; + + +/** + * Creates a RTS3 interface handle. + * + * @returns iprt status code. + * + * @param phS3 Where to store the RTS3 handle. + * @param pszAccessKey The access key for the S3 storage server. + * @param pszSecretKey The secret access key for the S3 storage server. + * @param pszBaseUrl The base URL of the S3 storage server. + * @param pszUserAgent An optional user agent string used in the HTTP + * communication. + */ +RTR3DECL(int) RTS3Create(PRTS3 phS3, const char *pszAccessKey, const char *pszSecretKey, const char *pszBaseUrl, const char *pszUserAgent); + +/** + * Destroys a RTS3 interface handle. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + */ +RTR3DECL(void) RTS3Destroy(RTS3 hS3); + +/** + * Sets an optional progress callback. + * + * This callback function will be called when the completion percentage of an S3 + * operation changes. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + * @param pfnProgressCB The pointer to the progress function. + * @param pvUser The pvUser arg of FNRTS3PROGRESS. + */ +RTR3DECL(void) RTS3SetProgressCallback(RTS3 hS3, PFNRTS3PROGRESS pfnProgressCB, void *pvUser); + +/** + * Gets a list of all available buckets on the S3 storage server. + * + * You have to delete ppBuckets after usage with RTS3BucketsDestroy. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + * @param ppBuckets Where to store the pointer to the head of the + * returned bucket list. Consider the entire list + * read-only. + */ +RTR3DECL(int) RTS3GetBuckets(RTS3 hS3, PCRTS3BUCKETENTRY *ppBuckets); + +/** + * Destroys the bucket list returned by RTS3GetBuckets. + * + * @returns iprt status code. + * + * @param pBuckets Pointer to the first bucket entry. + */ +RTR3DECL(int) RTS3BucketsDestroy(PCRTS3BUCKETENTRY pBuckets); + +/** + * Creates a new bucket on the S3 storage server. + * + * This name have to be unique over all accounts on the S3 storage server. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + * @param pszBucketName Name of the new bucket. + */ +RTR3DECL(int) RTS3CreateBucket(RTS3 hS3, const char *pszBucketName); + +/** + * Deletes a bucket on the S3 storage server. + * + * The bucket must be empty. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + * @param pszBucketName Name of the bucket to delete. + */ +RTR3DECL(int) RTS3DeleteBucket(RTS3 hS3, const char *pszBucketName); + +/** + * Gets a list of all available keys in a bucket on the S3 storage server. + * + * You have to delete ppKeys after usage with RTS3KeysDestroy. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + * @param pszBucketName Name of the bucket to delete. + * @param ppKeys Where to store the pointer to the head of the + * returned key list. Consider the entire list + * read-only. + */ +RTR3DECL(int) RTS3GetBucketKeys(RTS3 hS3, const char *pszBucketName, PCRTS3KEYENTRY *ppKeys); + +/** + * Delete the key list returned by RTS3GetBucketKeys. + * + * @returns iprt status code. + * + * @param pKeys Pointer to the first key entry. + */ +RTR3DECL(int) RTS3KeysDestroy(PCRTS3KEYENTRY pKeys); + +/** + * Deletes a key in a bucket on the S3 storage server. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + * @param pszBucketName Name of the bucket contains pszKeyName. + * @param pszKeyName Name of the key to delete. + */ +RTR3DECL(int) RTS3DeleteKey(RTS3 hS3, const char *pszBucketName, const char *pszKeyName); + +/** + * Downloads a key from a bucket into a file. + * + * The file must not exists. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + * @param pszBucketName Name of the bucket that contains pszKeyName. + * @param pszKeyName Name of the key to download. + * @param pszFilename Name of the file to store the downloaded key as. + */ +RTR3DECL(int) RTS3GetKey(RTS3 hS3, const char *pszBucketName, const char *pszKeyName, const char *pszFilename); + +/** + * Uploads the content of a file into a key in the specified bucked. + * + * @returns iprt status code. + * + * @param hS3 Handle to the RTS3 interface. + * @param pszBucketName Name of the bucket where the new key should be + * created. + * @param pszKeyName Name of the new key. + * @param pszFilename Name of the file to upload the content of. + */ +RTR3DECL(int) RTS3PutKey(RTS3 hS3, const char *pszBucketName, const char *pszKeyName, const char *pszFilename); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/semaphore.h b/include/iprt/semaphore.h new file mode 100644 index 00000000..0eba39c7 --- /dev/null +++ b/include/iprt/semaphore.h @@ -0,0 +1,1441 @@ +/** @file + * IPRT - Semaphore. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_semaphore_h +#define ___iprt_semaphore_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) +# include <iprt/lockvalidator.h> +#endif + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_sems RTSem - Semaphores + * + * This module implements all kinds of event and mutex semaphores; in addition + * to these, IPRT implements "critical sections", which are fast recursive + * mutexes (see @ref grp_rt_critsect ). C++ users may find @ref grp_rt_cpp_lock + * interesting. + * + * @ingroup grp_rt + * @{ + */ + + +/** @name Generic Semaphore Wait Flags. + * + * @remarks Exactly one of RTSEMWAIT_FLAGS_RELATIVE and + * RTSEMWAIT_FLAGS_ABSOLUTE must be set, unless + * RTSEMWAIT_FLAGS_INDEFINITE is used. + * + * Exactly one of RTSEMWAIT_FLAGS_NANOSECS and + * RTSEMWAIT_FLAGS_MILLISECS must be set, unless + * RTSEMWAIT_FLAGS_INDEFINITE is used. + * + * Exactly one of RTSEMWAIT_FLAGS_RESUME and RTSEMWAIT_FLAGS_NORESUME + * must be set. + * + * The interruptible vs resume stuff is ring-0 vs ring-3 semantics. + * + * @{ */ +/** The timeout is relative. */ +#define RTSEMWAIT_FLAGS_RELATIVE RT_BIT_32(0) +/** The timeout is absolute. */ +#define RTSEMWAIT_FLAGS_ABSOLUTE RT_BIT_32(1) +/** The timeout is specified in nanoseconds. */ +#define RTSEMWAIT_FLAGS_NANOSECS RT_BIT_32(2) +/** The timeout is specified in milliseconds. */ +#define RTSEMWAIT_FLAGS_MILLISECS RT_BIT_32(3) +/** Indefinite wait. + * The relative/absolute and nano-/millisecond flags are ignored. */ +#define RTSEMWAIT_FLAGS_INDEFINITE RT_BIT_32(4) +/** Mask covering the time related bits. */ +#define RTSEMWAIT_FLAGS_TIME_MASK UINT32_C(0x0000001f) + +/** Interruptible wait. */ +#define RTSEMWAIT_FLAGS_INTERRUPTIBLE RT_BIT_32(5) +/** No automatic resume, same as interruptible. */ +#define RTSEMWAIT_FLAGS_NORESUME RTSEMWAIT_FLAGS_INTERRUPTIBLE +/** Uninterruptible wait. */ +#define RTSEMWAIT_FLAGS_UNINTERRUPTIBLE RT_BIT_32(6) +/** Resume on interrupt, same as uninterruptible. */ +#define RTSEMWAIT_FLAGS_RESUME RTSEMWAIT_FLAGS_UNINTERRUPTIBLE + +/** Macro for validate the flags. */ +#define RTSEMWAIT_FLAGS_ARE_VALID(fFlags) \ + ( !((fFlags) & UINT32_C(0xffffff80)) \ + && ( ((fFlags) & RTSEMWAIT_FLAGS_INDEFINITE) \ + ? ( (((fFlags) & UINT32_C(0x20))) ^ (((fFlags) >> 1) & UINT32_C(0x20)) ) == UINT32_C(0x20) \ + : ( (((fFlags) & UINT32_C(0x25))) ^ (((fFlags) >> 1) & UINT32_C(0x25)) ) == UINT32_C(0x25) )) +/** @} */ + + + +/** @defgroup grp_rt_sems_event RTSemEvent - Single Release Event Semaphores + * + * Event semaphores can be used for inter-thread communication when one thread + * wants to notify another thread that something happened. A thread can block + * ("wait") on an event semaphore until it is signalled by another thread; see + * RTSemEventCreate, RTSemEventSignal and RTSemEventWait. + * + * @{ */ + +/** + * Create an event semaphore. + * + * @returns iprt status code. + * @param phEventSem Where to store the handle to the newly created + * event semaphore. + */ +RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem); + +/** + * Create an event semaphore. + * + * @returns iprt status code. + * @param phEventSem Where to store the handle to the newly created + * event semaphore. + * @param fFlags Flags, any combination of the + * RTSEMEVENT_FLAGS_XXX \#defines. + * @param hClass The class (no reference consumed). Since we + * don't do order checks on event semaphores, the + * use of the class is limited to controlling the + * timeout threshold for deadlock detection. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...); + +/** @name RTSemMutexCreateEx flags + * @{ */ +/** Disables lock validation. */ +#define RTSEMEVENT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001) +/** Bootstrap hack for use with certain memory allocator locks only! */ +#define RTSEMEVENT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004) +/** @} */ + +/** + * Destroy an event semaphore. + * + * @returns iprt status code. + * @param hEventSem Handle of the event semaphore. NIL_RTSEMEVENT + * is quietly ignored (VINF_SUCCESS). + */ +RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem); + +/** + * Signal an event semaphore. + * + * The event semaphore will be signaled and automatically reset after exactly + * one thread have successfully returned from RTSemEventWait() after + * waiting/polling on that semaphore. + * + * @returns iprt status code. + * @param hEventSem The event semaphore to signal. + * + * @remarks ring-0: This works when preemption is disabled. However it is + * system specific whether it works in interrupt context or with + * interrupts disabled. + */ +RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem); + +/** + * Wait for the event semaphore to be signaled, resume on interruption. + * + * This function will resume if the wait is interrupted by an async system event + * (like a unix signal) or similar. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param hEventSem The event semaphore to wait on. + * @param cMillies Number of milliseconds to wait. + */ +RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies); + +/** + * Wait for the event semaphore to be signaled, return on interruption. + * + * This function will not resume the wait if interrupted. + * + * @returns iprt status code. + * @param hEventSem The event semaphore to wait on. + * @param cMillies Number of milliseconds to wait. + */ +RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies); + +/** + * Extended API for waiting on an event semaphore to be signaled. + * + * @returns IPRT status code. + * @param hEventSem The event semaphore to wait on. + * @param fFlags Combination of RTSEMWAIT_FLAGS_XXX. + * @param uTimeout The timeout, ignored if + * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags. + * Whether this is absolute or relative, + * milliseconds or nanoseconds depends on the @a + * fFlags value. Do not pass RT_INDEFINITE_WAIT + * here, use RTSEMWAIT_FLAGS_INDEFINITE instead. + */ +RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout); + +/** + * Debug version of RTSemEventWaitEx that tracks the location. + * + * @returns IPRT status code, see RTSemEventWaitEx. + * @param hEventSem The event semaphore to wait on. + * @param fFlags See RTSemEventWaitEx. + * @param uTimeout See RTSemEventWaitEx. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Gets the best timeout resolution that RTSemEventWaitEx can do. + * + * @returns The resolution in nanoseconds. + */ +RTDECL(uint32_t) RTSemEventGetResolution(void); + +/** + * Sets the signaller thread to one specific thread. + * + * This is only used for validating usage and deadlock detection. When used + * after calls to RTSemEventAddSignaller, the specified thread will be the only + * signalling thread. + * + * @param hEventSem The event semaphore. + * @param hThread The thread that will signal it. Pass + * NIL_RTTHREAD to indicate that there is no + * special signalling thread. + */ +RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread); + +/** + * To add more signalling threads. + * + * First call RTSemEventSetSignaller then add further threads with this. + * + * @param hEventSem The event semaphore. + * @param hThread The thread that will signal it. NIL_RTTHREAD is + * not accepted. + */ +RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread); + +/** + * To remove a signalling thread. + * + * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller. + * + * @param hEventSem The event semaphore. + * @param hThread A previously added thread. + */ +RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread); + +/** @} */ + + +/** @defgroup grp_rt_sems_event_multi RTSemEventMulti - Multiple Release Event Semaphores + * + * A variant of @ref grp_rt_sems_event where all threads will be unblocked when + * signalling the semaphore. + * + * @{ */ + +/** + * Creates a multiple release event semaphore. + * + * @returns iprt status code. + * @param phEventMultiSem Where to store the handle to the newly created + * multiple release event semaphore. + */ +RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem); + +/** + * Creates a multiple release event semaphore. + * + * @returns iprt status code. + * @param phEventMultiSem Where to store the handle to the newly created + * multiple release event semaphore. + * @param fFlags Flags, any combination of the + * RTSEMEVENTMULTI_FLAGS_XXX \#defines. + * @param hClass The class (no reference consumed). Since we + * don't do order checks on event semaphores, the + * use of the class is limited to controlling the + * timeout threshold for deadlock detection. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass, + const char *pszNameFmt, ...); + +/** @name RTSemMutexCreateEx flags + * @{ */ +/** Disables lock validation. */ +#define RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001) +/** @} */ + +/** + * Destroy an event multi semaphore. + * + * @returns iprt status code. + * @param hEventMultiSem The multiple release event semaphore. NIL is + * quietly ignored (VINF_SUCCESS). + */ +RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem); + +/** + * Signal an event multi semaphore. + * + * @returns iprt status code. + * @param hEventMultiSem The multiple release event semaphore. + * + * @remarks ring-0: This works when preemption is disabled. However it is + * system specific whether it works in interrupt context or with + * interrupts disabled. + */ +RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem); + +/** + * Resets an event multi semaphore to non-signaled state. + * + * @returns iprt status code. + * @param hEventMultiSem The multiple release event semaphore. + */ +RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem); + +/** + * Wait for the event multi semaphore to be signaled, resume on interruption. + * + * This function will resume if the wait is interrupted by an async + * system event (like a unix signal) or similar. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param hEventMultiSem The multiple release event semaphore. + * @param cMillies Number of milliseconds to wait. + */ +RTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies); + +/** + * Wait for the event multi semaphore to be signaled, return on interruption. + * + * This function will not resume the wait if interrupted. + * + * @returns iprt status code. + * @param hEventMultiSem The multiple release event semaphore. + * @param cMillies Number of milliseconds to wait. + * @todo Rename to RTSemEventMultiWaitIntr since it is mainly for + * ring-0 consumption. + */ +RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, RTMSINTERVAL cMillies); + +/** + * Extended API for waiting on an event semaphore to be signaled. + * + * @returns IPRT status code. + * @param hEventMultiSem The multiple release event semaphore to wait + * on. + * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX. + * @param uTimeout The timeout, ignored if + * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags. + * Whether this is absolute or relative, + * milliseconds or nanoseconds depends on the @a + * fFlags value. Do not pass RT_INDEFINITE_WAIT + * here, use RTSEMWAIT_FLAGS_INDEFINITE instead. + */ +RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout); + +/** + * Debug version of RTSemEventMultiWaitEx that tracks the location. + + * @returns IPRT status code, see RTSemEventMultiWaitEx. + * @param hEventMultiSem The multiple release event semaphore handle. + * @param fFlags See RTSemEventMultiWaitEx. + * @param uTimeout See RTSemEventMultiWaitEx. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Gets the best timeout resolution that RTSemEventMultiWaitEx can do. + * + * @returns The resolution in nanoseconds. + */ +RTDECL(uint32_t) RTSemEventMultiGetResolution(void); + +/** + * Sets the signaller thread to one specific thread. + * + * This is only used for validating usage and deadlock detection. When used + * after calls to RTSemEventAddSignaller, the specified thread will be the only + * signalling thread. + * + * @param hEventMultiSem The multiple release event semaphore. + * @param hThread The thread that will signal it. Pass + * NIL_RTTHREAD to indicate that there is no + * special signalling thread. + */ +RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread); + +/** + * To add more signalling threads. + * + * First call RTSemEventSetSignaller then add further threads with this. + * + * @param hEventMultiSem The multiple release event semaphore. + * @param hThread The thread that will signal it. NIL_RTTHREAD is + * not accepted. + */ +RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread); + +/** + * To remove a signalling thread. + * + * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller. + * + * @param hEventMultiSem The multiple release event semaphore. + * @param hThread A previously added thread. + */ +RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread); + +/** @} */ + + +/** @defgroup grp_rt_sems_mutex RTSemMutex - Mutex semaphores. + * + * Mutex semaphores protect a section of code or data to which access must be + * exclusive. Only one thread can hold access to a critical section at one + * time. See RTSemMutexCreate, RTSemMutexRequest and RTSemMutexRelease. + * + * @remarks These are less efficient than "fast mutexes" and "critical + * sections", which IPRT implements as well; see @ref + * grp_rt_sems_fast_mutex and @ref grp_rt_critsect . + * + * @{ */ + +/** + * Create a mutex semaphore. + * + * @returns iprt status code. + * @param phMutexSem Where to store the mutex semaphore handle. + */ +RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem); + +/** + * Creates a read/write semaphore. + * + * @returns iprt status code. + * @param phRWSem Where to store the handle to the newly created + * RW semaphore. + * @param fFlags Flags, any combination of the + * RTSEMMUTEX_FLAGS_XXX \#defines. + * @param hClass The class (no reference consumed). If NIL, no + * lock order validation will be performed on this + * lock. + * @param uSubClass The sub-class. This is used to define lock + * order within a class. RTLOCKVAL_SUB_CLASS_NONE + * is the recommended value here. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags, + RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...); + +/** @name RTSemMutexCreateEx flags + * @{ */ +/** Disables lock validation. */ +#define RTSEMMUTEX_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001) +/** @} */ + + +/** + * Destroy a mutex semaphore. + * + * @returns iprt status code. + * @param hMutexSem The mutex semaphore to destroy. NIL is quietly + * ignored (VINF_SUCCESS). + */ +RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX hMutexSem); + +/** + * Changes the lock validator sub-class of the mutex semaphore. + * + * It is recommended to try make sure that nobody is using this semaphore while + * changing the value. + * + * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the + * lock validator isn't compiled in or either of the parameters are + * invalid. + * @param hMutexSem The handle to the mutex semaphore. + * @param uSubClass The new sub-class value. + */ +RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass); + +/** + * Request ownership of a mutex semaphore, resume on interruption. + * + * This function will resume if the wait is interrupted by an async + * system event (like a unix signal) or similar. + * + * The same thread may request a mutex semaphore multiple times, + * a nested counter is kept to make sure it's released on the right + * RTSemMutexRelease() call. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param hMutexSem The mutex semaphore to request ownership over. + * @param cMillies The number of milliseconds to wait. + */ +RTDECL(int) RTSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies); + +/** + * Request ownership of a mutex semaphore, return on interruption. + * + * This function will not resume the wait if interrupted. + * + * The same thread may request a mutex semaphore multiple times, + * a nested counter is kept to make sure it's released on the right + * RTSemMutexRelease() call. + * + * @returns iprt status code. + * @param hMutexSem The mutex semaphore to request ownership over. + * @param cMillies The number of milliseconds to wait. + */ +RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies); + +/** + * Debug version of RTSemMutexRequest that tracks the location. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param hMutexSem The mutex semaphore to request ownership over. + * @param cMillies The number of milliseconds to wait. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Debug version of RTSemMutexRequestNoResume that tracks the location. + * + * @returns iprt status code. + * @param hMutexSem The mutex semaphore to request ownership over. + * @param cMillies The number of milliseconds to wait. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Request ownership of a mutex semaphore, extended edition. + * + * The same thread may request a mutex semaphore multiple times, + * a nested counter is kept to make sure it's released on the right + * RTSemMutexRelease() call. + * + * @returns iprt status code. + * @param hMutexSem The mutex semaphore to request ownership over. + * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX. + * @param uTimeout The timeout, ignored if + * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags. + * Whether this is absolute or relative, + * milliseconds or nanoseconds depends on the @a + * fFlags value. Do not pass RT_INDEFINITE_WAIT + * here, use RTSEMWAIT_FLAGS_INDEFINITE instead. + */ +RTDECL(int) RTSemMutexRequestEx(RTSEMMUTEX hMutexSem, uint32_t fFlags, uint64_t uTimeout); + +/** + * Debug version of RTSemMutexRequestEx that tracks the location. + * + * @returns iprt status code. + * @param hMutexSem The mutex semaphore to request ownership over. + * @param fFlags See RTSemMutexRequestEx. + * @param uTimeout See RTSemMutexRequestEx. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemMutexRequestExDebug(RTSEMMUTEX hMutexSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Release the ownership of a mutex semaphore. + * + * @returns iprt status code. + * @param hMutexSem The mutex to release the ownership of. It goes + * without saying the the calling thread must own + * it. + */ +RTDECL(int) RTSemMutexRelease(RTSEMMUTEX hMutexSem); + +/** + * Checks if the mutex semaphore is owned or not. + * + * @returns true if owned, false if not. + * @param hMutexSem The mutex semaphore. + */ +RTDECL(bool) RTSemMutexIsOwned(RTSEMMUTEX hMutexSem); + +/* Strict build: Remap the two request calls to the debug versions. */ +#if defined(RT_STRICT) && !defined(RTSEMMUTEX_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING) +# ifdef ___iprt_asm_h +# define RTSemMutexRequest(hMutexSem, cMillies) RTSemMutexRequestDebug((hMutexSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define RTSemMutexRequestNoResume(hMutexSem, cMillies) RTSemMutexRequestNoResumeDebug((hMutexSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define RTSemMutexRequestEx(hMutexSem, fFlags, uTimeout) RTSemMutexRequestExDebug((hMutexSem), (fFlags), (uTimeout), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# else +# define RTSemMutexRequest(hMutexSem, cMillies) RTSemMutexRequestDebug((hMutexSem), (cMillies), 0, RT_SRC_POS) +# define RTSemMutexRequestNoResume(hMutexSem, cMillies) RTSemMutexRequestNoResumeDebug((hMutexSem), (cMillies), 0, RT_SRC_POS) +# define RTSemMutexRequestEx(hMutexSem, fFlags, uTimeout) RTSemMutexRequestExDebug((hMutexSem), (fFlags), (uTimeout), 0, RT_SRC_POS) +# endif +#endif + +/* Strict lock order: Automatically classify locks by init location. */ +#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTSEMMUTEX_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING) +# define RTSemMutexCreate(phMutexSem) \ + RTSemMutexCreateEx((phMutexSem), 0 /*fFlags*/, \ + RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \ + RTLOCKVAL_SUB_CLASS_NONE, NULL) +#endif + +/** @} */ + + +/** @defgroup grp_rt_sems_fast_mutex RTSemFastMutex - Fast Mutex Semaphores + * + * Fast mutexes work like regular mutexes in that they allow only a single + * thread access to a critical piece of code or data. As opposed to mutexes, + * they require no syscall if the fast mutex is not held (like critical + * sections). Unlike critical sections however, they are *not* recursive. + * + * @remarks The fast mutexes has sideeffects on IRQL on Windows hosts. So use + * with care and test on windows with driver verifier. + * + * @{ */ + +/** + * Create a fast mutex semaphore. + * + * @returns iprt status code. + * @param phFastMtx Where to store the handle to the newly created + * fast mutex semaphore. + * + * @remarks Fast mutex semaphores are not recursive. + */ +RTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx); + +/** + * Destroy a fast mutex semaphore. + * + * @returns iprt status code. + * @param hFastMtx Handle to the fast mutex semaphore. NIL is + * quietly ignored (VINF_SUCCESS). + */ +RTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx); + +/** + * Request ownership of a fast mutex semaphore. + * + * The same thread may request a mutex semaphore multiple times, + * a nested counter is kept to make sure it's released on the right + * RTSemMutexRelease() call. + * + * @returns iprt status code. + * @param hFastMtx Handle to the fast mutex semaphore. + */ +RTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx); + +/** + * Release the ownership of a fast mutex semaphore. + * + * @returns iprt status code. + * @param hFastMtx Handle to the fast mutex semaphore. It goes + * without saying the the calling thread must own + * it. + */ +RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx); + +/** @} */ + + +/** @defgroup grp_rt_sems_spin_mutex RTSemSpinMutex - Spinning Mutex Semaphores + * + * A very adaptive variant of mutex semaphore that is tailored for the ring-0 + * logger. + * + * @{ */ + +/** + * Creates a spinning mutex semaphore. + * + * @returns iprt status code. + * @retval VERR_INVALID_PARAMETER on invalid flags. + * @retval VERR_NO_MEMORY if out of memory for the semaphore structure and + * handle. + * + * @param phSpinMtx Where to return the handle to the create semaphore. + * @param fFlags Flags, see RTSEMSPINMUTEX_FLAGS_XXX. + */ +RTDECL(int) RTSemSpinMutexCreate(PRTSEMSPINMUTEX phSpinMtx, uint32_t fFlags); + +/** @name RTSemSpinMutexCreate flags. + * @{ */ +/** Always take the semaphore in a IRQ safe way. + * (In plain words: always disable interrupts.) */ +#define RTSEMSPINMUTEX_FLAGS_IRQ_SAFE RT_BIT_32(0) +/** Mask of valid flags. */ +#define RTSEMSPINMUTEX_FLAGS_VALID_MASK UINT32_C(0x00000001) +/** @} */ + +/** + * Destroys a spinning mutex semaphore. + * + * @returns iprt status code. + * @retval VERR_INVALID_HANDLE (or crash) if the handle is invalid. (NIL will + * not cause this status.) + * + * @param hSpinMtx The semaphore handle. NIL_RTSEMSPINMUTEX is ignored + * quietly (VINF_SUCCESS). + */ +RTDECL(int) RTSemSpinMutexDestroy(RTSEMSPINMUTEX hSpinMtx); + +/** + * Request the spinning mutex semaphore. + * + * This may block if the context we're called in allows this. If not it will + * spin. If called in an interrupt context, we will only spin if the current + * owner isn't interrupted. Also, on some systems it is not always possible to + * wake up blocking threads in all contexts, so, which will either be indicated + * by returning VERR_SEM_BAD_CONTEXT or by temporarily switching the semaphore + * into pure spinlock state. + * + * Preemption will be disabled upon return. IRQs may also be disabled. + * + * @returns iprt status code. + * @retval VERR_SEM_BAD_CONTEXT if the context it's called in isn't suitable + * for releasing it if someone is sleeping on it. + * @retval VERR_SEM_DESTROYED if destroyed. + * @retval VERR_SEM_NESTED if held by the caller. Asserted. + * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted + * + * @param hSpinMtx The semaphore handle. + */ +RTDECL(int) RTSemSpinMutexRequest(RTSEMSPINMUTEX hSpinMtx); + +/** + * Like RTSemSpinMutexRequest but it won't block or spin if the semaphore is + * held by someone else. + * + * @returns iprt status code. + * @retval VERR_SEM_BUSY if held by someone else. + * @retval VERR_SEM_DESTROYED if destroyed. + * @retval VERR_SEM_NESTED if held by the caller. Asserted. + * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted + * + * @param hSpinMtx The semaphore handle. + */ +RTDECL(int) RTSemSpinMutexTryRequest(RTSEMSPINMUTEX hSpinMtx); + +/** + * Releases the semaphore previously acquired by RTSemSpinMutexRequest or + * RTSemSpinMutexTryRequest. + * + * @returns iprt status code. + * @retval VERR_SEM_DESTROYED if destroyed. + * @retval VERR_NOT_OWNER if not owner. Asserted. + * @retval VERR_INVALID_HANDLE if the handle is invalid. Asserted. + * + * @param hSpinMtx The semaphore handle. + */ +RTDECL(int) RTSemSpinMutexRelease(RTSEMSPINMUTEX hSpinMtx); + +/** @} */ + + +/** @defgroup grp_rt_sem_rw RTSemRW - Read / Write Semaphores + * + * Read/write semaphores are a fancier version of mutexes in that they grant + * read access to the protected data to several threads at the same time but + * allow only one writer at a time. This can make code scale better at the + * expense of slightly more overhead in mutex management. + * + * @{ */ + +/** + * Creates a read/write semaphore. + * + * @returns iprt status code. + * @param phRWSem Where to store the handle to the newly created + * RW semaphore. + */ +RTDECL(int) RTSemRWCreate(PRTSEMRW phRWSem); + +/** + * Creates a read/write semaphore. + * + * @returns iprt status code. + * @param phRWSem Where to store the handle to the newly created + * RW semaphore. + * @param fFlags Flags, any combination of the RTSEMRW_FLAGS_XXX + * \#defines. + * @param hClass The class (no reference consumed). If NIL, no + * lock order validation will be performed on this + * lock. + * @param uSubClass The sub-class. This is used to define lock + * order within a class. RTLOCKVAL_SUB_CLASS_NONE + * is the recommended value here. + * @param pszNameFmt Name format string for the lock validator, + * optional (NULL). Max length is 32 bytes. + * @param ... Format string arguments. + */ +RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags, + RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...); + +/** @name RTSemRWCreateEx flags + * @{ */ +/** Disables lock validation. */ +#define RTSEMRW_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001) +/** @} */ + +/** + * Destroys a read/write semaphore. + * + * @returns iprt status code. + * @param hRWSem Handle to the read/write semaphore. NIL is + * quietly ignored (VINF_SUCCESS). + */ +RTDECL(int) RTSemRWDestroy(RTSEMRW hRWSem); + +/** + * Changes the lock validator sub-class of the read/write semaphore. + * + * It is recommended to try make sure that nobody is using this semaphore while + * changing the value. + * + * @returns The old sub-class. RTLOCKVAL_SUB_CLASS_INVALID is returns if the + * lock validator isn't compiled in or either of the parameters are + * invalid. + * @param hRWSem Handle to the read/write semaphore. + * @param uSubClass The new sub-class value. + */ +RTDECL(uint32_t) RTSemRWSetSubClass(RTSEMRW hRWSem, uint32_t uSubClass); + +/** + * Request read access to a read/write semaphore, resume on interruption + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INTERRUPT if the wait was interrupted. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param cMillies The number of milliseconds to wait. + */ +RTDECL(int) RTSemRWRequestRead(RTSEMRW hRWSem, RTMSINTERVAL cMillies); + +/** + * Request read access to a read/write semaphore, return on interruption + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INTERRUPT if the wait was interrupted. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param cMillies The number of milliseconds to wait. + */ +RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies); + +/** + * Debug version of RTSemRWRequestRead that tracks the location. + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INTERRUPT if the wait was interrupted. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param cMillies The number of milliseconds to wait. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemRWRequestReadDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Debug version of RTSemRWRequestWriteNoResume that tracks the location. + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INTERRUPT if the wait was interrupted. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param cMillies The number of milliseconds to wait. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Request read access to a read/write semaphore, extended edition. + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INTERRUPT if the wait was interrupted. + * @retval VERR_TIMEOUT if the wait timed out. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX. + * @param uTimeout The timeout, ignored if + * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags. + * Whether this is absolute or relative, + * milliseconds or nanoseconds depends on the @a + * fFlags value. Do not pass RT_INDEFINITE_WAIT + * here, use RTSEMWAIT_FLAGS_INDEFINITE instead. + */ +RTDECL(int) RTSemRWRequestReadEx(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout); + + +/** + * Debug version of RTSemRWRequestReadEx that tracks the location. + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INTERRUPT if the wait was interrupted. + * @retval VERR_TIMEOUT if the wait timed out. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param fFlags See RTSemRWRequestReadEx. + * @param uTimeout See RTSemRWRequestReadEx. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemRWRequestReadExDebug(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Release read access to a read/write semaphore. + * + * @returns iprt status code. + * @param hRWSem Handle to the read/write semaphore. It goes + * without saying that caller must own read + * privileges to the semaphore. + */ +RTDECL(int) RTSemRWReleaseRead(RTSEMRW hRWSem); + +/** + * Request write access to a read/write semaphore, resume on interruption. + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_DEADLOCK if the caller owned the read lock. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param cMillies The number of milliseconds to wait. + */ +RTDECL(int) RTSemRWRequestWrite(RTSEMRW hRWSem, RTMSINTERVAL cMillies); + +/** + * Request write access to a read/write semaphore, return on interruption. + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INTERRUPT if the wait was interrupted. + * @retval VERR_DEADLOCK if the caller owned the read lock. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param cMillies The number of milliseconds to wait. + */ +RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW hRWSem, RTMSINTERVAL cMillies); + +/** + * Debug version of RTSemRWRequestWrite that tracks the location. + * + * @returns IPRT status code, see RTSemRWRequestWrite. + * @param hRWSem Handle to the read/write semaphore. + * @param cMillies The number of milliseconds to wait. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Debug version of RTSemRWRequestWriteNoResume that tracks the location. + * + * @returns IPRT status code, see RTSemRWRequestWriteNoResume. + * @param hRWSem Handle to the read/write semaphore. + * @param cMillies The number of milliseconds to wait. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW hRWSem, RTMSINTERVAL cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Request write access to a read/write semaphore, extended edition. + * + * @returns iprt status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INTERRUPTED if the wait was interrupted. + * @retval VERR_TIMEOUT if the wait timed out. + * @retval VERR_DEADLOCK if the caller owned the read lock. Do not depend on + * this as it is implementation specific. + * @retval VERR_INVALID_HANDLE if hRWSem is invalid. + * + * @param hRWSem Handle to the read/write semaphore. + * @param fFlags Combination of the RTSEMWAIT_FLAGS_XXX. + * @param uTimeout The timeout, ignored if + * RTSEMWAIT_FLAGS_INDEFINITE is set in @a flags. + * Whether this is absolute or relative, + * milliseconds or nanoseconds depends on the @a + * fFlags value. Do not pass RT_INDEFINITE_WAIT + * here, use RTSEMWAIT_FLAGS_INDEFINITE instead. + */ +RTDECL(int) RTSemRWRequestWriteEx(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout); + +/** + * Debug version of RTSemRWRequestWriteEx that tracks the location. + * + * @returns IPRT status code, see RTSemRWRequestWriteEx. + * @param hRWSem Handle to the read/write semaphore. + * @param fFlags See RTSemRWRequestWriteEx. + * @param uTimeout See RTSemRWRequestWriteEx. + * @param uId Some kind of locking location ID. Typically a + * return address up the stack. Optional (0). + * @param pszFile The file where the lock is being acquired from. + * Optional. + * @param iLine The line number in that file. Optional (0). + * @param pszFunction The function where the lock is being acquired + * from. Optional. + */ +RTDECL(int) RTSemRWRequestWriteExDebug(RTSEMRW hRWSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL); + +/** + * Release write access to a read/write semaphore. + * + * @returns iprt status code. + * @param hRWSem Handle to the read/write semaphore. Goes + * without saying that caller must have write + * access to the semaphore. + */ +RTDECL(int) RTSemRWReleaseWrite(RTSEMRW hRWSem); + +/** + * Checks if the caller is the exclusive semaphore owner. + * + * @returns true / false accoringly. + * @param hRWSem Handle to the read/write semaphore. + */ +RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW hRWSem); + +/** + * Checks if the caller is one of the read owners of the semaphore. + * + * @note !CAUTION! This API doesn't work reliably if lock validation isn't + * enabled. Meaning, the answer is not trustworhty unless + * RT_LOCK_STRICT or RTSEMRW_STRICT was defined at build time. Also, + * make sure you do not use RTSEMRW_FLAGS_NO_LOCK_VAL when creating + * the semaphore. And finally, if you used a locking class, don't + * disable deadlock detection by setting cMsMinDeadlock to + * RT_INDEFINITE_WAIT. + * + * In short, only use this for assertions. + * + * @returns true if reader, false if not. + * @param hRWSem Handle to the read/write semaphore. + * @param fWannaHear What you'd like to hear when lock validation is + * not available. (For avoiding asserting all over + * the place.) + */ +RTDECL(bool) RTSemRWIsReadOwner(RTSEMRW hRWSem, bool fWannaHear); + +/** + * Gets the write recursion count. + * + * @returns The write recursion count (0 if bad semaphore handle). + * @param hRWSem Handle to the read/write semaphore. + */ +RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW hRWSem); + +/** + * Gets the read recursion count of the current writer. + * + * @returns The read recursion count (0 if bad semaphore handle). + * @param hRWSem Handle to the read/write semaphore. + */ +RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW hRWSem); + +/** + * Gets the current number of reads. + * + * This includes all read recursions, so it might be higher than the number of + * read owners. It does not include reads done by the current writer. + * + * @returns The read count (0 if bad semaphore handle). + * @param hRWSem Handle to the read/write semaphore. + */ +RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW hRWSem); + +/* Strict build: Remap the four request calls to the debug versions. */ +#if defined(RT_STRICT) && !defined(RTSEMRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING) +# ifdef ___iprt_asm_h +# define RTSemRWRequestRead(hRWSem, cMillies) RTSemRWRequestReadDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define RTSemRWRequestReadNoResume(hRWSem, cMillies) RTSemRWRequestReadNoResumeDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define RTSemRWRequestWrite(hRWSem, cMillies) RTSemRWRequestWriteDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define RTSemRWRequestWriteNoResume(hRWSem, cMillies) RTSemRWRequestWriteNoResumeDebug((hRWSem), (cMillies), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# define RTSemRWRequestWriteEx(hRWSem, fFlags, uTimeout) RTSemRWRequestWriteExDebug((hRWSem), (fFlags), (uTimeout), (uintptr_t)ASMReturnAddress(), RT_SRC_POS) +# else +# define RTSemRWRequestRead(hRWSem, cMillies) RTSemRWRequestReadDebug((hRWSem), (cMillies), 0, RT_SRC_POS) +# define RTSemRWRequestReadNoResume(hRWSem, cMillies) RTSemRWRequestReadNoResumeDebug((hRWSem), (cMillies), 0, RT_SRC_POS) +# define RTSemRWRequestWrite(hRWSem, cMillies) RTSemRWRequestWriteDebug((hRWSem), (cMillies), 0, RT_SRC_POS) +# define RTSemRWRequestWriteNoResume(hRWSem, cMillies) RTSemRWRequestWriteNoResumeDebug((hRWSem), (cMillies), 0, RT_SRC_POS) +# define RTSemRWRequestWriteEx(hRWSem, fFlags, uTimeout) RTSemRWRequestWriteExDebug((hRWSem), (fFlags), (uTimeout), 0, RT_SRC_POS) +# endif +#endif + +/* Strict lock order: Automatically classify locks by init location. */ +#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3) && !defined(RTSEMRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING) +# define RTSemRWCreate(phSemRW) \ + RTSemRWCreateEx((phSemRW), 0 /*fFlags*/, \ + RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \ + RTLOCKVAL_SUB_CLASS_NONE, NULL) +#endif + +/** @} */ + + +/** @defgroup grp_rt_sems_pingpong RTSemPingPong - Ping-Pong Construct + * + * Serialization of a two way communication. + * + * @{ */ + +/** + * Ping-pong speaker + */ +typedef enum RTPINGPONGSPEAKER +{ + /** Not initialized. */ + RTPINGPONGSPEAKER_UNINITIALIZE = 0, + /** Ping is speaking, Pong is waiting. */ + RTPINGPONGSPEAKER_PING, + /** Pong is signaled, Ping is waiting. */ + RTPINGPONGSPEAKER_PONG_SIGNALED, + /** Pong is speaking, Ping is waiting. */ + RTPINGPONGSPEAKER_PONG, + /** Ping is signaled, Pong is waiting. */ + RTPINGPONGSPEAKER_PING_SIGNALED, + /** Hack to ensure that it's at least 32-bits wide. */ + RTPINGPONGSPEAKER_HACK = 0x7fffffff +} RTPINGPONGSPEAKER; + +/** + * Ping-Pong construct. + * + * Two threads, one saying Ping and the other saying Pong. The construct + * makes sure they don't speak out of turn and that they can wait and poll + * on the conversation. + */ +typedef struct RTPINGPONG +{ + /** The semaphore the Ping thread waits on. */ + RTSEMEVENT Ping; + /** The semaphore the Pong thread waits on. */ + RTSEMEVENT Pong; + /** The current speaker. */ + volatile RTPINGPONGSPEAKER enmSpeaker; +#if HC_ARCH_BITS == 64 + /** Padding the structure to become a multiple of sizeof(RTHCPTR). */ + uint32_t u32Padding; +#endif +} RTPINGPONG; +/** Pointer to Ping-Pong construct. */ +typedef RTPINGPONG *PRTPINGPONG; + +/** + * Init a Ping-Pong construct. + * + * @returns iprt status code. + * @param pPP Pointer to the ping-pong structure which needs initialization. + */ +RTDECL(int) RTSemPingPongInit(PRTPINGPONG pPP); + +/** + * Deletes a Ping-Pong construct. + * + * @returns iprt status code. + * @param pPP Pointer to the ping-pong structure which is to be destroyed. + * (I.e. put into uninitialized state.) + */ +RTDECL(int) RTSemPingPongDelete(PRTPINGPONG pPP); + +/** + * Signals the pong thread in a ping-pong construct. (I.e. sends ping.) + * This is called by the ping thread. + * + * @returns iprt status code. + * @param pPP Pointer to the ping-pong structure to ping. + */ +RTDECL(int) RTSemPing(PRTPINGPONG pPP); + +/** + * Signals the ping thread in a ping-pong construct. (I.e. sends pong.) + * This is called by the pong thread. + * + * @returns iprt status code. + * @param pPP Pointer to the ping-pong structure to pong. + */ +RTDECL(int) RTSemPong(PRTPINGPONG pPP); + +/** + * Wait function for the ping thread. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param pPP Pointer to the ping-pong structure to wait on. + * @param cMillies Number of milliseconds to wait. + */ +RTDECL(int) RTSemPingWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies); + +/** + * Wait function for the pong thread. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param pPP Pointer to the ping-pong structure to wait on. + * @param cMillies Number of milliseconds to wait. + */ +RTDECL(int) RTSemPongWait(PRTPINGPONG pPP, RTMSINTERVAL cMillies); + + +/** + * Checks if the pong thread is speaking. + * + * @returns true / false. + * @param pPP Pointer to the ping-pong structure. + * @remark This is NOT the same as !RTSemPongIsSpeaker(). + */ +DECLINLINE(bool) RTSemPingIsSpeaker(PRTPINGPONG pPP) +{ + RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker; + return enmSpeaker == RTPINGPONGSPEAKER_PING; +} + + +/** + * Checks if the pong thread is speaking. + * + * @returns true / false. + * @param pPP Pointer to the ping-pong structure. + * @remark This is NOT the same as !RTSemPingIsSpeaker(). + */ +DECLINLINE(bool) RTSemPongIsSpeaker(PRTPINGPONG pPP) +{ + RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker; + return enmSpeaker == RTPINGPONGSPEAKER_PONG; +} + + +/** + * Checks whether the ping thread should wait. + * + * @returns true / false. + * @param pPP Pointer to the ping-pong structure. + * @remark This is NOT the same as !RTSemPongShouldWait(). + */ +DECLINLINE(bool) RTSemPingShouldWait(PRTPINGPONG pPP) +{ + RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker; + return enmSpeaker == RTPINGPONGSPEAKER_PONG + || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED + || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED; +} + + +/** + * Checks whether the pong thread should wait. + * + * @returns true / false. + * @param pPP Pointer to the ping-pong structure. + * @remark This is NOT the same as !RTSemPingShouldWait(). + */ +DECLINLINE(bool) RTSemPongShouldWait(PRTPINGPONG pPP) +{ + RTPINGPONGSPEAKER enmSpeaker = pPP->enmSpeaker; + return enmSpeaker == RTPINGPONGSPEAKER_PING + || enmSpeaker == RTPINGPONGSPEAKER_PING_SIGNALED + || enmSpeaker == RTPINGPONGSPEAKER_PONG_SIGNALED; +} + +/** @} */ + + +/** @defgroup grp_rt_sems_xroads RTSemXRoads - Crossroads + * + * The crossroads semaphore is intended to prevent two classes of incompatible + * events from occurring simultaneously, like south/north bound traffic and + * west/east bound traffic at a 4-way junction. + * + * @remarks In order to simplify the implementation, the current flow is always + * given priority. So, it won't work at all well when busy! + * + * @remarks "XRoads" is used as a name because it is briefer than "crossroads" + * and it slightly stresses that is a 4 way crossing to the users of + * American English. + * @{ + */ + +/** + * Creates a crossroads semaphore. + * + * @returns IPRT status code. + * + * @param phXRoads Where to return the handle to the newly created + * crossroads semaphore. + */ +RTDECL(int) RTSemXRoadsCreate(PRTSEMXROADS phXRoads); + +/** + * Destroys a crossroads semaphore. + * + * @returns IPRT status code. + * + * @param hXRoads Handle to the crossroads semaphore that is to be + * destroyed. NIL_RTSEMXROADS is quitetly ignored + * (VINF_SUCCESS). + */ +RTDECL(int) RTSemXRoadsDestroy(RTSEMXROADS hXRoads); + +/** + * Enter the crossroads from the south or north. + * + * (Coupled with RTSemXRoadsNSLeave.) + * + * @returns IPRT status code. + * @param hXRoads Handle to the crossroads semaphore. + */ +RTDECL(int) RTSemXRoadsNSEnter(RTSEMXROADS hXRoads); + +/** + * Leave the crossroads to the north or south. + * + * (Coupled with RTSemXRoadsNSEnter.) + * + * @returns IPRT status code. + * @param hXRoads Handle to the crossroads semaphore. + */ +RTDECL(int) RTSemXRoadsNSLeave(RTSEMXROADS hXRoads); + +/** + * Leave the crossroads from the east or west. + * + * (Coupled with RTSemXRoadsEWLeave.) + * + * @returns IPRT status code. + * @param hXRoads Handle to the crossroads semaphore. + */ +RTDECL(int) RTSemXRoadsEWEnter(RTSEMXROADS hXRoads); + +/** + * Leave the crossroads to the west or east. + * + * (Coupled with RTSemXRoadsEWEnter.) + * + * @returns IPRT status code. + * @param hXRoads Handle to the crossroads semaphore. + */ +RTDECL(int) RTSemXRoadsEWLeave(RTSEMXROADS hXRoads); + +/** @} */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/sg.h b/include/iprt/sg.h new file mode 100644 index 00000000..d515de8b --- /dev/null +++ b/include/iprt/sg.h @@ -0,0 +1,278 @@ +/** @file + * IPRT - S/G buffer handling. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_sg_h +#define ___iprt_sg_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** + * A S/G entry. + */ +typedef struct RTSGSEG +{ + /** Pointer to the segment buffer. */ + void *pvSeg; + /** Size of the segment buffer. */ + size_t cbSeg; +} RTSGSEG; +/** Pointer to a S/G entry. */ +typedef RTSGSEG *PRTSGSEG; +/** Pointer to a const S/G entry. */ +typedef const RTSGSEG *PCRTSGSEG; +/** Pointer to a S/G entry pointer. */ +typedef PRTSGSEG *PPRTSGSEG; + +/** + * A S/G buffer. + * + * The members should be treated as private. + */ +typedef struct RTSGBUF +{ + /** Pointer to the scatter/gather array. */ + PCRTSGSEG paSegs; + /** Number of segments. */ + unsigned cSegs; + /** Current segment we are in. */ + unsigned idxSeg; + /** Pointer to the current segment start. */ + void *pvSegCur; + /** Number of bytes left in the current buffer. */ + size_t cbSegLeft; +} RTSGBUF; +/** Pointer to a S/G entry. */ +typedef RTSGBUF *PRTSGBUF; +/** Pointer to a const S/G entry. */ +typedef const RTSGBUF *PCRTSGBUF; +/** Pointer to a S/G entry pointer. */ +typedef PRTSGBUF *PPRTSGBUF; + +/** + * Initialize a S/G buffer structure. + * + * @returns nothing. + * @param pSgBuf Pointer to the S/G buffer to initialize. + * @param paSegs Pointer to the start of the segment array. + * @param cSegs Number of segments in the array. + */ +RTDECL(void) RTSgBufInit(PRTSGBUF pSgBuf, PCRTSGSEG paSegs, size_t cSegs); + +/** + * Resets the internal buffer position of the S/G buffer to the beginning. + * + * @returns nothing. + * @param pSgBuf The S/G buffer to reset. + */ +RTDECL(void) RTSgBufReset(PRTSGBUF pSgBuf); + +/** + * Clones a given S/G buffer. + * + * @returns nothing. + * @param pSgBufNew The new S/G buffer to clone to. + * @param pSgBufOld The source S/G buffer to clone from. + * + * @note This is only a shallow copy. Both S/G buffers will point to the + * same segment array. + */ +RTDECL(void) RTSgBufClone(PRTSGBUF pSgBufNew, PCRTSGBUF pSgBufOld); + +/** + * Returns the next segment in the S/G buffer or NULL if no segment is left. + * + * @returns Pointer to the next segment in the S/G buffer. + * @param pSgBuf The S/G buffer. + * @param pcbSeg Where to store the size of the returned segment. + * Holds the number of bytes requested initially or 0 to + * indicate that the size doesn't matter. + * This may contain fewer bytes on success if the current segment + * is smaller than the amount of bytes requested. + * + * @note This operation advances the internal buffer pointer of both S/G buffers. + */ +RTDECL(void *) RTSgBufGetNextSegment(PRTSGBUF pSgBuf, size_t *pcbSeg); + +/** + * Copy data between two S/G buffers. + * + * @returns The number of bytes copied. + * @param pSgBufDst The destination S/G buffer. + * @param pSgBufSrc The source S/G buffer. + * @param cbCopy Number of bytes to copy. + * + * @note This operation advances the internal buffer pointer of both S/G buffers. + */ +RTDECL(size_t) RTSgBufCopy(PRTSGBUF pSgBufDst, PRTSGBUF pSgBufSrc, size_t cbCopy); + +/** + * Compares the content of two S/G buffers. + * + * @returns Whatever memcmp returns. + * @param pSgBuf1 First S/G buffer. + * @param pSgBuf2 Second S/G buffer. + * @param cbCmp How many bytes to compare. + * + * @note This operation doesn't change the internal position of the S/G buffers. + */ +RTDECL(int) RTSgBufCmp(PCRTSGBUF pSgBuf1, PCRTSGBUF pSgBuf2, size_t cbCmp); + +/** + * Compares the content of two S/G buffers - advanced version. + * + * @returns Whatever memcmp returns. + * @param pSgBuf1 First S/G buffer. + * @param pSgBuf2 Second S/G buffer. + * @param cbCmp How many bytes to compare. + * @param pcbOff Where to store the offset of the first different byte + * in the buffer starting from the position of the S/G + * buffer before this call. + * @param fAdvance Flag whether the internal buffer position should be advanced. + * + */ +RTDECL(int) RTSgBufCmpEx(PRTSGBUF pSgBuf1, PRTSGBUF pSgBuf2, size_t cbCmp, + size_t *pcbOff, bool fAdvance); + +/** + * Fills an S/G buf with a constant byte. + * + * @returns The number of actually filled bytes. + * Can be less than than cbSet if the end of the S/G buffer was reached. + * @param pSgBuf The S/G buffer. + * @param ubFill The byte to fill the buffer with. + * @param cbSet How many bytes to set. + * + * @note This operation advances the internal buffer pointer of the S/G buffer. + */ +RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t ubFill, size_t cbSet); + +/** + * Copies data from an S/G buffer into a given non scattered buffer. + * + * @returns Number of bytes copied. + * @param pSgBuf The S/G buffer to copy from. + * @param pvBuf Buffer to copy the data into. + * @param cbCopy How many bytes to copy. + * + * @note This operation advances the internal buffer pointer of the S/G buffer. + */ +RTDECL(size_t) RTSgBufCopyToBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy); + +/** + * Copies data from a non scattered buffer into an S/G buffer. + * + * @returns Number of bytes copied. + * @param pSgBuf The S/G buffer to copy to. + * @param pvBuf Buffer to copy the data into. + * @param cbCopy How many bytes to copy. + * + * @note This operation advances the internal buffer pointer of the S/G buffer. + */ +RTDECL(size_t) RTSgBufCopyFromBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy); + +/** + * Advances the internal buffer pointer. + * + * @returns Number of bytes the pointer was moved forward. + * @param pSgBuf The S/G buffer. + * @param cbAdvance Number of bytes to move forward. + */ +RTDECL(size_t) RTSgBufAdvance(PRTSGBUF pSgBuf, size_t cbAdvance); + +/** + * Constructs a new segment array starting from the current position + * and describing the given number of bytes. + * + * @returns Number of bytes the array describes. + * @param pSgBuf The S/G buffer. + * @param paSeg The uninitialized segment array. + * If NULL pcSeg will contain the number of segments needed + * to describe the requested amount of data. + * @param pcSeg The number of segments the given array has. + * This will hold the actual number of entries needed upon return. + * @param cbData Number of bytes the new array should describe. + * + * @note This operation advances the internal buffer pointer of the S/G buffer if paSeg is not NULL. + */ +RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSeg, size_t cbData); + +/** + * Maps the given S/G buffer to a segment array of another type (for example to + * iovec on POSIX or WSABUF on Windows). + * + * @param paMapped Where to store the pointer to the start of the native + * array or NULL. The memory needs to be freed with + * RTMemTmpFree(). + * @param pSgBuf The S/G buffer to map. + * @param Struct Struct used as the destination. + * @param pvBufField Name of the field holding the pointer to a buffer. + * @param TypeBufPtr Type of the buffer pointer. + * @param cbBufField Name of the field holding the size of the buffer. + * @param TypeBufSize Type of the field for the buffer size. + * @param cSegsMapped Where to store the number of segments the native array + * has. + * + * @note This operation maps the whole S/G buffer starting at the current + * internal position. The internal buffer position is unchanged by + * this operation. + * + * @remark Usage is a bit ugly but saves a few lines of duplicated code + * somewhere else and makes it possible to keep the S/G buffer members + * private without going through RTSgBufSegArrayCreate() first. + */ +#define RTSgBufMapToNative(paMapped, pSgBuf, Struct, pvBufField, TypeBufPtr, cbBufField, TypeBufSize, cSegsMapped) \ + do \ + { \ + AssertCompileMemberSize(Struct, pvBufField, RT_SIZEOFMEMB(RTSGSEG, pvSeg)); \ + /*AssertCompile(RT_SIZEOFMEMB(Struct, cbBufField) >= RT_SIZEOFMEMB(RTSGSEG, cbSeg));*/ \ + (cSegsMapped) = (pSgBuf)->cSegs - (pSgBuf)->idxSeg; \ + \ + /* We need room for at least one segment. */ \ + if ((pSgBuf)->cSegs == (pSgBuf)->idxSeg) \ + (cSegsMapped)++; \ + \ + (paMapped) = (Struct *)RTMemTmpAllocZ((cSegsMapped) * sizeof(Struct)); \ + if ((paMapped)) \ + { \ + /* The first buffer is special because we could be in the middle of a segment. */ \ + (paMapped)[0].pvBufField = (TypeBufPtr)(pSgBuf)->pvSegCur; \ + (paMapped)[0].cbBufField = (TypeBufSize)(pSgBuf)->cbSegLeft; \ + \ + for (unsigned i = 1; i < (cSegsMapped); i++) \ + { \ + (paMapped)[i].pvBufField = (TypeBufPtr)(pSgBuf)->paSegs[(pSgBuf)->idxSeg + i].pvSeg; \ + (paMapped)[i].cbBufField = (TypeBufSize)(pSgBuf)->paSegs[(pSgBuf)->idxSeg + i].cbSeg; \ + } \ + } \ + } while (0) + +RT_C_DECLS_END + +/** @} */ + +#endif + diff --git a/include/iprt/sha.h b/include/iprt/sha.h new file mode 100644 index 00000000..046ca813 --- /dev/null +++ b/include/iprt/sha.h @@ -0,0 +1,302 @@ +/** @file + * IPRT - SHA1 digest creation + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_sha_h +#define ___iprt_sha_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_sha RTSha - SHA Family of Hash Functions + * @ingroup grp_rt + * @{ + */ + +/** The size of a SHA-1 hash. */ +#define RTSHA1_HASH_SIZE 20 +/** The length of a SHA-1 digest string. The terminator is not included. */ +#define RTSHA1_DIGEST_LEN 40 + +/** + * SHA-1 context. + */ +typedef union RTSHA1CONTEXT +{ + uint8_t abPadding[ARCH_BITS == 32 ? 96 : 128]; +#ifdef RT_SHA1_PRIVATE_CONTEXT + SHA_CTX Private; +#endif +} RTSHA1CONTEXT; +/** Pointer to an SHA-1 context. */ +typedef RTSHA1CONTEXT *PRTSHA1CONTEXT; + +/** + * Compute the SHA-1 hash of the data. + * + * @param pvBuf Pointer to the data. + * @param cbBuf The amount of data (in bytes). + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(void) RTSha1(const void *pvBuf, size_t cbBuf, uint8_t pabDigest[RTSHA1_HASH_SIZE]); + +/** + * Initializes the SHA-1 context. + * + * @param pCtx Pointer to the SHA-1 context. + */ +RTDECL(void) RTSha1Init(PRTSHA1CONTEXT pCtx); + +/** + * Feed data into the SHA-1 computation. + * + * @param pCtx Pointer to the SHA-1 context. + * @param pvBuf Pointer to the data. + * @param cbBuf The length of the data (in bytes). + */ +RTDECL(void) RTSha1Update(PRTSHA1CONTEXT pCtx, const void *pvBuf, size_t cbBuf); + +/** + * Compute the SHA-1 hash of the data. + * + * @param pCtx Pointer to the SHA-1 context. + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(void) RTSha1Final(PRTSHA1CONTEXT pCtx, uint8_t pabDigest[RTSHA1_HASH_SIZE]); + +/** + * Converts a SHA-1 hash to a digest string. + * + * @returns IPRT status code. + * + * @param pabDigest The binary digest returned by RTSha1Final or RTSha1. + * @param pszDigest Where to return the stringified digest. + * @param cchDigest The size of the output buffer. Should be at least + * RTSHA1_DIGEST_LEN + 1 bytes. + */ +RTDECL(int) RTSha1ToString(uint8_t const pabDigest[RTSHA1_HASH_SIZE], char *pszDigest, size_t cchDigest); + +/** + * Converts a SHA-1 hash to a digest string. + * + * @returns IPRT status code. + * + * @param pszDigest The stringified digest. Leading and trailing spaces are + * ignored. + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(int) RTSha1FromString(char const *pszDigest, uint8_t pabDigest[RTSHA1_HASH_SIZE]); + +/** + * Creates a SHA1 digest for the given memory buffer. + * + * @returns iprt status code. + * + * @param pvBuf Memory buffer to create a SHA1 digest for. + * @param cbBuf The amount of data (in bytes). + * @param ppszDigest On success the SHA1 digest. + * @param pfnProgressCallback optional callback for the progress indication + * @param pvUser user defined pointer for the callback + */ +RTR3DECL(int) RTSha1Digest(void* pvBuf, size_t cbBuf, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser); + +/** + * Creates a SHA1 digest for the given file. + * + * @returns iprt status code. + * + * @param pszFile Filename to create a SHA1 digest for. + * @param ppszDigest On success the SHA1 digest. + * @param pfnProgressCallback optional callback for the progress indication + * @param pvUser user defined pointer for the callback + */ +RTR3DECL(int) RTSha1DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser); + + +/** The size of a SHA-256 hash. */ +#define RTSHA256_HASH_SIZE 32 +/** The length of a SHA-256 digest string. The terminator is not included. */ +#define RTSHA256_DIGEST_LEN 64 + +/** + * SHA-256 context. + */ +typedef union RTSHA256CONTEXT +{ + uint8_t abPadding[ARCH_BITS == 32 ? 112 : 160]; +#ifdef RT_SHA256_PRIVATE_CONTEXT + SHA256_CTX Private; +#endif +} RTSHA256CONTEXT; +/** Pointer to an SHA-256 context. */ +typedef RTSHA256CONTEXT *PRTSHA256CONTEXT; + +/** + * Compute the SHA-256 hash of the data. + * + * @param pvBuf Pointer to the data. + * @param cbBuf The amount of data (in bytes). + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(void) RTSha256(const void *pvBuf, size_t cbBuf, uint8_t pabDigest[RTSHA256_HASH_SIZE]); + +/** + * Initializes the SHA-256 context. + * + * @param pCtx Pointer to the SHA-256 context. + */ +RTDECL(void) RTSha256Init(PRTSHA256CONTEXT pCtx); + +/** + * Feed data into the SHA-256 computation. + * + * @param pCtx Pointer to the SHA-256 context. + * @param pvBuf Pointer to the data. + * @param cbBuf The length of the data (in bytes). + */ +RTDECL(void) RTSha256Update(PRTSHA256CONTEXT pCtx, const void *pvBuf, size_t cbBuf); + +/** + * Compute the SHA-256 hash of the data. + * + * @param pCtx Pointer to the SHA-256 context. + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(void) RTSha256Final(PRTSHA256CONTEXT pCtx, uint8_t pabDigest[RTSHA256_HASH_SIZE]); + +/** + * Converts a SHA-256 hash to a digest string. + * + * @returns IPRT status code. + * + * @param pabDigest The binary digest returned by RTSha256Final or RTSha256. + * @param pszDigest Where to return the stringified digest. + * @param cchDigest The size of the output buffer. Should be at least + * RTSHA256_DIGEST_LEN + 1 bytes. + */ +RTDECL(int) RTSha256ToString(uint8_t const pabDigest[RTSHA256_HASH_SIZE], char *pszDigest, size_t cchDigest); + +/** + * Converts a SHA-256 hash to a digest string. + * + * @returns IPRT status code. + * + * @param pszDigest The stringified digest. Leading and trailing spaces are + * ignored. + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(int) RTSha256FromString(char const *pszDigest, uint8_t pabDigest[RTSHA256_HASH_SIZE]); + + + +/** The size of a SHA-512 hash. */ +#define RTSHA512_HASH_SIZE 64 +/** The length of a SHA-512 digest string. The terminator is not included. */ +#define RTSHA512_DIGEST_LEN 128 + +/** + * SHA-512 context. + */ +typedef union RTSHA512CONTEXT +{ + uint8_t abPadding[ARCH_BITS == 32 ? 216 : 256]; +#ifdef RT_SHA512_PRIVATE_CONTEXT + SHA512_CTX Private; +#endif +} RTSHA512CONTEXT; +/** Pointer to an SHA-512 context. */ +typedef RTSHA512CONTEXT *PRTSHA512CONTEXT; + +/** + * Compute the SHA-512 hash of the data. + * + * @param pvBuf Pointer to the data. + * @param cbBuf The amount of data (in bytes). + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(void) RTSha512(const void *pvBuf, size_t cbBuf, uint8_t pabDigest[RTSHA512_HASH_SIZE]); + +/** + * Initializes the SHA-512 context. + * + * @param pCtx Pointer to the SHA-512 context. + */ +RTDECL(void) RTSha512Init(PRTSHA512CONTEXT pCtx); + +/** + * Feed data into the SHA-512 computation. + * + * @param pCtx Pointer to the SHA-512 context. + * @param pvBuf Pointer to the data. + * @param cbBuf The length of the data (in bytes). + */ +RTDECL(void) RTSha512Update(PRTSHA512CONTEXT pCtx, const void *pvBuf, size_t cbBuf); + +/** + * Compute the SHA-512 hash of the data. + * + * @param pCtx Pointer to the SHA-512 context. + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(void) RTSha512Final(PRTSHA512CONTEXT pCtx, uint8_t pabDigest[RTSHA512_HASH_SIZE]); + +/** + * Converts a SHA-512 hash to a digest string. + * + * @returns IPRT status code. + * + * @param pabDigest The binary digest returned by RTSha512Final or RTSha512. + * @param pszDigest Where to return the stringified digest. + * @param cchDigest The size of the output buffer. Should be at least + * RTSHA512_DIGEST_LEN + 1 bytes. + */ +RTDECL(int) RTSha512ToString(uint8_t const pabDigest[RTSHA512_HASH_SIZE], char *pszDigest, size_t cchDigest); + +/** + * Converts a SHA-512 hash to a digest string. + * + * @returns IPRT status code. + * + * @param pszDigest The stringified digest. Leading and trailing spaces are + * ignored. + * @param pabDigest Where to store the hash. (What is passed is a pointer to + * the caller's buffer.) + */ +RTDECL(int) RTSha512FromString(char const *pszDigest, uint8_t pabDigest[RTSHA512_HASH_SIZE]); + +/** @} */ + +RT_C_DECLS_END + +#endif /* ___iprt_sha1_h */ + diff --git a/include/iprt/socket.h b/include/iprt/socket.h new file mode 100644 index 00000000..0b577c5b --- /dev/null +++ b/include/iprt/socket.h @@ -0,0 +1,399 @@ +/** @file + * IPRT - Network Sockets. + */ + +/* + * Copyright (C) 2006-2012 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. + */ + +#ifndef ___iprt_socket_h +#define ___iprt_socket_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/thread.h> +#include <iprt/net.h> +#include <iprt/sg.h> + +#ifdef IN_RING0 +# error "There are no RTSocket APIs available Ring-0 Host Context!" +#endif + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_tcp RTSocket - Network Sockets + * @ingroup grp_rt + * @{ + */ + +/** + * Retains a reference to the socket handle. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * + * @param hSocket The socket handle. + */ +RTDECL(uint32_t) RTSocketRetain(RTSOCKET hSocket); + +/** + * Release a reference to the socket handle. + * + * When the reference count reaches zero, the socket handle is shut down and + * destroyed. This will not be graceful shutdown, use the protocol specific + * close method if this is desired. + * + * @returns New reference count, UINT32_MAX on invalid handle (asserted). + * + * @param hSocket The socket handle. The NIL handle is quietly + * ignored and 0 is returned. + */ +RTDECL(uint32_t) RTSocketRelease(RTSOCKET hSocket); + +/** + * Shuts down the socket, close it and then release one handle reference. + * + * This is slightly different from RTSocketRelease which will first do the + * shutting down and closing when the reference count reaches zero. + * + * @returns IPRT status code. + * @param hSocket The socket handle. NIL is ignored. + * + * @remarks This will not perform a graceful shutdown of the socket, it will + * just destroy it. Use the protocol specific close method if this is + * desired. + */ +RTDECL(int) RTSocketClose(RTSOCKET hSocket); + +/** + * Creates an IPRT socket handle from a native one. + * + * Do NOT use the native handle after passing it to this function, IPRT owns it + * and might even have closed upon a successful return. + * + * @returns IPRT status code. + * @param phSocket Where to store the IPRT socket handle. + * @param uNative The native handle. + */ +RTDECL(int) RTSocketFromNative(PRTSOCKET phSocket, RTHCINTPTR uNative); + +/** + * Gets the native socket handle. + * + * @returns The native socket handle or RTHCUINTPTR_MAX if not invalid. + * @param hSocket The socket handle. + */ +RTDECL(RTHCUINTPTR) RTSocketToNative(RTSOCKET hSocket); + +/** + * Helper that ensures the correct inheritability of a socket. + * + * We're currently ignoring failures. + * + * @returns IPRT status code + * @param hSocket The socket handle. + * @param fInheritable The desired inheritability state. + */ +RTDECL(int) RTSocketSetInheritance(RTSOCKET hSocket, bool fInheritable); + +/** + * Parse Internet style addresses, getting a generic IPRT network address. + * + * @returns IPRT status code + * @param pszAddress Name or IP address. NULL or empty string (no + * spaces) is taken to mean INADDR_ANY, which is + * meaningful when binding a server socket for + * instance. + * @param uPort Port number (host byte order). + * @param pAddr Where to return the generic IPRT network address. + */ +RTDECL(int) RTSocketParseInetAddress(const char *pszAddress, unsigned uPort, PRTNETADDR pAddr); + +/** + * Try resolve a host name, returning the first matching address. + * + * @returns IPRT status code. + * @param pszHost Name or IP address to look up. + * @param pszAddress Where to return the stringified address. + * @param pcbAddress Input: The size of the @a pszResult buffer. + * Output: size of the returned string. This is set on + * VERR_BUFFER_OVERFLOW and most other error statuses. + * @param penmAddrType Input: Which kind of address to return. Valid values + * are: + * - RTNETADDRTYPE_IPV4 -> lookup AF_INET. + * - RTNETADDRTYPE_IPV6 -> lookup AF_INET6. + * - RTNETADDRTYPE_INVALID/NULL -> lookup anything. + * Output: The type of address that is being returned. + * Not modified on failure. + */ +RTDECL(int) RTSocketQueryAddressStr(const char *pszHost, char *pszAddress, size_t *pcbAddress, PRTNETADDRTYPE penmAddrType); + +/** + * Receive data from a socket. + * + * @returns IPRT status code. + * @param hSocket The socket handle. + * @param pvBuffer Where to put the data we read. + * @param cbBuffer Read buffer size. + * @param pcbRead Number of bytes read. If NULL the entire buffer + * will be filled upon successful return. If not NULL a + * partial read can be done successfully. + */ +RTDECL(int) RTSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead); + +/** + * Receive data from a socket, including sender address. Mainly useful + * for datagram sockets. + * + * @returns IPRT status code. + * @param hSocket The socket handle. + * @param pvBuffer Where to put the data we read. + * @param cbBuffer Read buffer size. + * @param pcbRead Number of bytes read. Must be non-NULL. + * @param pSrcAddr Pointer to sender address buffer. May be NULL. + */ +RTDECL(int) RTSocketReadFrom(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr); + +/** + * Send data to a socket. + * + * @returns IPRT status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param hSocket The socket handle. + * @param pvBuffer Buffer to write data to socket. + * @param cbBuffer How much to write. + */ +RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer); + +/** + * Send data to a socket, including destination address. Mainly useful + * for datagram sockets. + * + * @returns IPRT status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param hSocket The socket handle. + * @param pvBuffer Buffer to write data to socket. + * @param cbBuffer How much to write. + * @param pDstAddr Pointer to destination address. May be NULL. + */ +RTDECL(int) RTSocketWriteTo(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pDstAddr); + +/** + * Checks if the socket is ready for reading (for I/O multiplexing). + * + * @returns IPRT status code. + * @param hSocket The socket handle. + * @param cMillies Number of milliseconds to wait for the socket. Use + * RT_INDEFINITE_WAIT to wait for ever. + */ +RTDECL(int) RTSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies); + +/** @name Select events + * @{ */ +/** Readable without blocking. */ +#define RTSOCKET_EVT_READ RT_BIT_32(0) +/** Writable without blocking. */ +#define RTSOCKET_EVT_WRITE RT_BIT_32(1) +/** Error condition, hangup, exception or similar. */ +#define RTSOCKET_EVT_ERROR RT_BIT_32(2) +/** Mask of the valid bits. */ +#define RTSOCKET_EVT_VALID_MASK UINT32_C(0x00000007) +/** @} */ + +/** + * Socket I/O multiplexing + * Checks if the socket is ready for one of the given events. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + * @param fEvents Event mask to wait for. + * @param pfEvents Where to store the event mask on return. + * @param cMillies Number of milliseconds to wait for the socket. + * Use RT_INDEFINITE_WAIT to wait for ever. + */ +RTR3DECL(int) RTSocketSelectOneEx(RTSOCKET Sock, uint32_t fEvents, uint32_t *pfEvents, + RTMSINTERVAL cMillies); + +/** + * Shuts down one or both directions of communciation. + * + * @returns IPRT status code. + * @param hSocket The socket handle. + * @param fRead Whether to shutdown our read direction. + * @param fWrite Whether to shutdown our write direction. + */ +RTDECL(int) RTSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite); + +/** + * Gets the address of the local side. + * + * @returns IPRT status code. + * @param Sock Socket descriptor. + * @param pAddr Where to store the local address on success. + */ +RTDECL(int) RTSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr); + +/** + * Gets the address of the other party. + * + * @returns IPRT status code. + * @param Sock Socket descriptor. + * @param pAddr Where to store the peer address on success. + */ +RTDECL(int) RTSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr); + +/** + * Send data from a scatter/gather buffer to a socket. + * + * @returns IPRT status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param hSocket The socket handle. + * @param pSgBuf Scatter/gather buffer to write data to socket. + */ +RTDECL(int) RTSocketSgWrite(RTSOCKET hSocket, PCRTSGBUF pSgBuf); + +/** + * Send data from multiple buffers to a socket. + * + * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls + * for lazy coders. The "L" in the function name is short for "list" just like + * in the execl libc API. + * + * @returns IPRT status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param hSocket The socket handle. + * @param cSegs The number of data segments in the following + * ellipsis. + * @param ... Pairs of buffer pointers (void const *) and buffer + * sizes (size_t). Make 101% sure the pointer is + * really size_t. + */ +RTDECL(int) RTSocketSgWriteL(RTSOCKET hSocket, size_t cSegs, ...); + +/** + * Send data from multiple buffers to a socket. + * + * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls + * for lazy coders. The "L" in the function name is short for "list" just like + * in the execl libc API. + * + * @returns IPRT status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param hSocket The socket handle. + * @param cSegs The number of data segments in the following + * argument list. + * @param va Pairs of buffer pointers (void const *) and buffer + * sizes (size_t). Make 101% sure the pointer is + * really size_t. + */ +RTDECL(int) RTSocketSgWriteLV(RTSOCKET hSocket, size_t cSegs, va_list va); + +/** + * Receive data from a socket. + * + * This version doesn't block if there is no data on the socket. + * + * @returns IPRT status code. + * + * @param hSocket The socket handle. + * @param pvBuffer Where to put the data we read. + * @param cbBuffer Read buffer size. + * @param pcbRead Number of bytes read. + */ +RTDECL(int) RTSocketReadNB(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead); + +/** + * Send data to a socket. + * + * This version doesn't block if there is not enough room for the message. + * + * @returns IPRT status code. + * + * @param hSocket The socket handle. + * @param pvBuffer Buffer to write data to socket. + * @param cbBuffer How much to write. + * @param pcbWritten Number of bytes written. + */ +RTDECL(int) RTSocketWriteNB(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten); + +/** + * Send data from a scatter/gather buffer to a socket. + * + * This version doesn't block if there is not enough room for the message. + * + * @returns iprt status code. + * + * @param Sock Socket descriptor. + * @param pSgBuf Scatter/gather buffer to write data to socket. + * @param pcbWritten Number of bytes written. + */ +RTR3DECL(int) RTSocketSgWriteNB(RTSOCKET Sock, PCRTSGBUF pSgBuf, size_t *pcbWritten); + + +/** + * Send data from multiple buffers to a socket. + * + * This version doesn't block if there is not enough room for the message. + * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls + * for lazy coders. The "L" in the function name is short for "list" just like + * in the execl libc API. + * + * @returns IPRT status code. + * + * @param hSocket The socket handle. + * @param cSegs The number of data segments in the following + * ellipsis. + * @param pcbWritten Number of bytes written. + * @param ... Pairs of buffer pointers (void const *) and buffer + * sizes (size_t). Make 101% sure the pointer is + * really size_t. + */ +RTR3DECL(int) RTSocketSgWriteLNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, ...); + +/** + * Send data from multiple buffers to a socket. + * + * This version doesn't block if there is not enough room for the message. + * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls + * for lazy coders. The "L" in the function name is short for "list" just like + * in the execl libc API. + * + * @returns IPRT status code. + * + * @param hSocket The socket handle. + * @param cSegs The number of data segments in the following + * argument list. + * @param pcbWritten Number of bytes written. + * @param va Pairs of buffer pointers (void const *) and buffer + * sizes (size_t). Make 101% sure the pointer is + * really size_t. + */ +RTR3DECL(int) RTSocketSgWriteLVNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, va_list va); + +/** @} */ +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/solaris/kmoddeps.mac b/include/iprt/solaris/kmoddeps.mac new file mode 100644 index 00000000..6b8a4003 --- /dev/null +++ b/include/iprt/solaris/kmoddeps.mac @@ -0,0 +1,183 @@ +; $Id: kmoddeps.mac $ +;; @file +; Assembly macros for generating Solaris kernel module dependencies +; + +; +; Copyright (C) 2012 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. +; + +; Solaris kernel modules use non-standard ELF constructions to express inter- +; module dependencies, namely a DT_NEEDED tag inside a relocatable ELF file. +; The Solaris linker can generate these automatically; since yasm can't +; produce an ELF file which quite fits Solaris's requirements we create one +; manually using flat binary output format. In order to save unnecessary +; repetition, this file defines macros for the repetitive bits which can be +; reused by the actual dependency objects. Certainly not the nicest way to +; get the effect we want, but probably a reasonable compromise between +; cleanness and required effort. +; + +%ifdef RT_ARCH_AMD64 + +BITS 64 +;; +; Native word size +%define DNAT dq + +;; +; ELF machine number for the current architecture. +%define EM_CUR 62 ; EM_X86_64 + +;; +; ELF header class for the current architecture. +%define CLASS 2 + +%else + +BITS 32 +%define DNAT dd +%define EM_CUR 3 ; EM_386 +%define CLASS 1 + +%endif + +;; +; ELF file header, section tables and shared string table for the dependency +; object. +%macro kmoddeps_header 0 +elf_hdr: ; elfxx_hdr structure + db 7fh, "ELF" ; e_ident + db CLASS, 1, 1 ; e_ident + times 9 db 0 ; padding + dw 1 ; e_type ET_REL + dw EM_CUR ; e_machine + dd 1 ; e_version EV_CURRENT + DNAT 0 ; e_entry + DNAT 0 ; e_phoff + DNAT sect_hdr - $$ ; e_shoff + dd 0 ; e_flags + dw elf_hsize ; e_ehsize + dw 0 ; e_phentsize + dw 0 ; e_phnum + dw sect_hsize ; e_shentsize + dw 4 ; e_shnum + dw 1 ; e_shstrndx section .shstrtab +elf_hsize equ $ - elf_hdr + +sect_hdr: ; elfxx_shdr structure + times sect_hsize db 0 ; undefined section + +sect_hdr1: + dd str_shstrtab ; sh_name .shstrtab + dd 3 ; sh_type SHT_STRTAB + DNAT 20h ; sh_flags SHF_STRINGS + DNAT 0 ; sh_addr + DNAT shstrtab - $$ ; sh_offset + DNAT shstrtab_size ; sh_size + dd 0 ; sh_link + dd 0 ; sh_info + DNAT 1 ; sh_addralign + DNAT 0 ; sh_entsize +sect_hsize equ $ - sect_hdr1 + + dd str_dynstr ; sh_name .dynstr + dd 3 ; sh_type SHT_STRTAB + DNAT 20h ; sh_flags SHF_STRINGS + DNAT 0 ; sh_addr + DNAT dynstr - $$ ; sh_offset + DNAT dynstr_size ; sh_size + dd 0 ; sh_link + dd 0 ; sh_info + DNAT 1 ; sh_addralign + DNAT 0 ; sh_entsize + + dd str_dynamic ; sh_name .dynamic + dd 6 ; sh_type SHT_DYNAMIC + DNAT 1 ; sh_flags SHF_WRITE + DNAT 0 ; sh_addr + DNAT dynamic - $$ ; sh_offset + DNAT dynamic_size ; sh_size + dd 2 ; sh_link .dynstr + dd 0 ; sh_info + DNAT 8 ; sh_addralign + DNAT 0 ; sh_entsize + +shstrtab: +str_shstrtab equ $ - shstrtab + db ".shstrtab", 0 +str_dynstr equ $ - shstrtab + db ".dynstr", 0 +str_dynamic equ $ - shstrtab + db ".dynamic", 0 +shstrtab_size equ $ - shstrtab +%endmacro ; kmoddeps_header + +;; +; Start of the .dynstr section for the dependency object. +%macro kmoddeps_dynstr_start 0 +dynstr: + db 0 +%endmacro + +;; +; A .dynstr string entry for the dependency object. +; The parameters are a symbolic name for the string and the string itself. +%macro kmoddeps_dynstr_string 2 +dynstr_name_%1 equ $ - dynstr + db %2, 0 +%endmacro + +;; +; End of the .dynstr section for the dependency object. +%macro kmoddeps_dynstr_end 0 +dynstr_size equ $ - dynstr +%endmacro + +;; +; Start of the .dynamic section for the dependency object. +%macro kmoddeps_dynamic_start 0 +dynamic: +%endmacro + +;; +; A .dynamic DT_NEEDED entry for the dependency object. +; The parameter is a symbolic string name previously defined using +; @a kmoddeps_dynstr_string. +%macro kmoddeps_dynamic_needed 1 + DNAT 1 ; DT_NEEDED + DNAT dynstr_name_%1 +%endmacro + +;; +; End of the .dynamic section for the dependency object. +%macro kmoddeps_dynamic_end 0 + DNAT 1ah ; DT_FLAGS + DNAT 4 ; TEXTREL + DNAT 6ffffffbh ; DT_FLAGS1 + DNAT 0 + DNAT 601900h ; SUNW_STRPAD + DNAT 200h + DNAT 601b00h ; SUNW_LDMACH + DNAT 62 ; EM_X86_64 + times 22 DNAT 0 ; padding +dynamic_size equ $ - dynamic +%endmacro ; kmoddeps_dynamic_end + diff --git a/include/iprt/sort.h b/include/iprt/sort.h new file mode 100644 index 00000000..dd4e93e5 --- /dev/null +++ b/include/iprt/sort.h @@ -0,0 +1,128 @@ +/** @file + * IPRT - Sorting. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_sort_h +#define ___iprt_sort_h + +#include <iprt/types.h> + +/** @defgroup grp_rt_sort RTSort - Sorting Algorithms + * @ingroup grp_rt + * @{ */ + +RT_C_DECLS_BEGIN + +/** + * Callback for comparing two array elements. + * + * @retval 0 if equal. + * @retval -1 if @a pvElement1 comes before @a pvElement2. + * @retval 1 if @a pvElement1 comes after @a pvElement2. + * + * @param pvElement1 The 1st element. + * @param pvElement2 The 2nd element. + * @param pvUser The user argument passed to the sorting function. + */ +typedef DECLCALLBACK(int) FNRTSORTCMP(void const *pvElement1, void const *pvElement2, void *pvUser); +/** Pointer to a compare function. */ +typedef FNRTSORTCMP *PFNRTSORTCMP; + +/** + * Sorter function for an array of variable sized elementes. + * + * @param papvArray The array to sort. + * @param cElements The number of elements in the array. + * @param cbElements The size of an array element. + * @param pfnCmp Callback function comparing two elements. + * @param pvUser User argument for the callback. + */ +typedef DECLCALLBACK(void) FNRTSORT(void *pvArray, size_t cElements, size_t cbElement, PFNRTSORTCMP pfnCmp, void *pvUser); +/** Pointer to a sorter function for an array of variable sized elements. */ +typedef FNRTSORT *PFNRTSORT; + +/** + * Pointer array sorter function. + * + * @param papvArray The array to sort. + * @param cElements The number of elements in the array. + * @param pfnCmp Callback function comparing two elements. + * @param pvUser User argument for the callback. + */ +typedef DECLCALLBACK(void) FNRTSORTAPV(void **papvArray, size_t cElements, PFNRTSORTCMP pfnCmp, void *pvUser); +/** Pointer to a pointer array sorter function. */ +typedef FNRTSORTAPV *PFNRTSORTAPV; + +/** + * Shell sort an array of variable sized elementes. + * + * @param papvArray The array to sort. + * @param cElements The number of elements in the array. + * @param cbElements The size of an array element. + * @param pfnCmp Callback function comparing two elements. + * @param pvUser User argument for the callback. + */ +RTDECL(void) RTSortShell(void *pvArray, size_t cElements, size_t cbElement, PFNRTSORTCMP pfnCmp, void *pvUser); + +/** + * Same as RTSortShell but speciallized for an array containing element + * pointers. + * + * @param papvArray The array to sort. + * @param cElements The number of elements in the array. + * @param pfnCmp Callback function comparing two elements. + * @param pvUser User argument for the callback. + */ +RTDECL(void) RTSortApvShell(void **papvArray, size_t cElements, PFNRTSORTCMP pfnCmp, void *pvUser); + +/** + * Checks if an array of variable sized elementes is sorted. + * + * @returns true if it is sorted, false if it isn't. + * @param papvArray The array to check. + * @param cElements The number of elements in the array. + * @param cbElements The size of an array element. + * @param pfnCmp Callback function comparing two elements. + * @param pvUser User argument for the callback. + */ +RTDECL(bool) RTSortIsSorted(void const *pvArray, size_t cElements, size_t cbElement, PFNRTSORTCMP pfnCmp, void *pvUser); + +/** + * Same as RTSortShell but speciallized for an array containing element + * pointers. + * + * @returns true if it is sorted, false if it isn't. + * @param papvArray The array to check. + * @param cElements The number of elements in the array. + * @param pfnCmp Callback function comparing two elements. + * @param pvUser User argument for the callback. + */ +RTDECL(bool) RTSortApvIsSorted(void const * const *papvArray, size_t cElements, PFNRTSORTCMP pfnCmp, void *pvUser); + +RT_C_DECLS_END + +/** @} */ + +#endif + diff --git a/include/iprt/spinlock.h b/include/iprt/spinlock.h new file mode 100644 index 00000000..2c36a0fd --- /dev/null +++ b/include/iprt/spinlock.h @@ -0,0 +1,97 @@ +/** @file + * IPRT - Spinlocks. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_spinlock_h +#define ___iprt_spinlock_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + + +/** @defgroup grp_rt_spinlock RTSpinlock - Spinlocks + * @ingroup grp_rt + * @{ + */ + +/** + * Creates a spinlock. + * + * @returns iprt status code. + * @param pSpinlock Where to store the spinlock handle. + * @param fFlags Creation flags, see RTSPINLOCK_FLAGS_XXX. + * @param pszName Spinlock name, for debugging purposes. String lifetime + * must be the same as the lock as it won't be copied. + */ +RTDECL(int) RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char *pszName); + +/** @name RTSPINLOCK_FLAGS_XXX + * @{ */ +/** Disable interrupts when taking the spinlock, making it interrupt safe + * (sans NMI of course). + * + * This is generally the safest option, though it isn't really required unless + * the data being protect is also accessed from interrupt handler context. */ +#define RTSPINLOCK_FLAGS_INTERRUPT_SAFE RT_BIT(1) +/** No need to disable interrupts, the protect code/data is not used by + * interrupt handlers. */ +#define RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE RT_BIT(2) +/** @} */ + +/** + * Destroys a spinlock created by RTSpinlockCreate(). + * + * @returns iprt status code. + * @param Spinlock Spinlock returned by RTSpinlockCreate(). + */ +RTDECL(int) RTSpinlockDestroy(RTSPINLOCK Spinlock); + +/** + * Acquires the spinlock. + * + * @param Spinlock The spinlock to acquire. + * @param pTmp Where to save the state. + */ +RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock); + +/** + * Releases the spinlock. + * + * @param Spinlock The spinlock to acquire. + * @param pTmp The state to restore. (This better be the same as for the RTSpinlockAcquire() call!) + */ +RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock); + +/* Temporarily, only for checking the spinlock creation flags. */ +RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock); + + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/stdarg.h b/include/iprt/stdarg.h new file mode 100644 index 00000000..4b93fb01 --- /dev/null +++ b/include/iprt/stdarg.h @@ -0,0 +1,54 @@ +/** @file + * IPRT - stdarg.h wrapper. + */ + +/* + * Copyright (C) 2006-2012 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. + */ + +#ifndef ___iprt_stdarg_h +#define ___iprt_stdarg_h + +#ifdef IPRT_NO_CRT +# include <iprt/types.h> +# include <iprt/nocrt/compiler/compiler.h> +#else +# include <iprt/cdefs.h> +# if defined(RT_OS_FREEBSD) && defined(_KERNEL) +# include <machine/stdarg.h> +# elif defined(RT_OS_SOLARIS) && defined(_KERNEL) && defined(__GNUC__) +# include <stdarg.h> +# if __GNUC__ >= 4 /* System headers refers to __builtin_stdarg_start. */ +# define __builtin_stdarg_start __builtin_va_start +# endif +# else +# include <stdarg.h> +# endif +#endif + +/* + * MSC doesn't implement va_copy. + */ +#ifndef va_copy +# define va_copy(dst, src) do { (dst) = (src); } while (0) /** @todo check AMD64 */ +#endif + +#endif + diff --git a/include/iprt/stdint.h b/include/iprt/stdint.h new file mode 100644 index 00000000..59c2d726 --- /dev/null +++ b/include/iprt/stdint.h @@ -0,0 +1,244 @@ +/** @file + * IPRT - stdint.h wrapper (for backlevel compilers like MSC). + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef __iprt_stdint_h +#define __iprt_stdint_h + +#include <iprt/cdefs.h> + + +/* + * Use the stdint.h on systems that have one. + */ +#if !(defined(RT_OS_LINUX) && defined(__KERNEL__)) \ + && !(defined(RT_OS_FREEBSD) && defined(_KERNEL)) \ + && !defined(_MSC_VER) \ + && !defined(__IBMC__) \ + && !defined(__IBMCPP__) \ + && !defined(IPRT_NO_CRT) \ + && !defined(IPRT_DONT_USE_SYSTEM_STDINT_H) \ + && !defined(DOXYGEN_RUNNING) + +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +# endif +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +# endif +# include <stdint.h> + +# if defined(RT_OS_DARWIN) && defined(KERNEL) && defined(RT_ARCH_AMD64) + /* + * Kludge to fix the incorrect 32-bit constant macros in + * Kernel.framework/Headers/stdin.h. uint32_t and int32_t are + * int not long as these macros use, which is significant when + * targeting AMD64. (10a222) + */ +# undef INT32_C +# define INT32_C(Value) (Value) +# undef UINT32_C +# define UINT32_C(Value) (Value ## U) +# endif /* 64-bit darwin kludge. */ + +#elif defined(RT_OS_FREEBSD) && defined(_KERNEL) + +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +# endif +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +# endif +# include <sys/stdint.h> + +#else /* No system stdint.h */ + +/* + * Define the types we use. + * The linux kernel defines all these in linux/types.h, so skip it. + */ +# if !(defined(RT_OS_LINUX) && defined(__KERNEL__)) \ + || defined(IPRT_NO_CRT) \ + || defined(IPRT_DONT_USE_SYSTEM_STDINT_H) \ + || defined(DOXGEN_RUNNING) + + /* Simplify the [u]int64_t type detection mess. */ +# undef IPRT_STDINT_USE_STRUCT_FOR_64_BIT_TYPES +# ifdef __IBMCPP__ +# if __IBMCPP__ < 350 && (defined(__WINDOWS__) || defined(_AIX) || defined(__OS2__)) +# defined IPRT_STDINT_USE_STRUCT_FOR_64_BIT_TYPES +# endif +# endif +# ifdef __IBMC__ +# if __IBMC__ < 350 && (defined(__WINDOWS__) || defined(_AIX) || defined(__OS2__)) +# defined IPRT_STDINT_USE_STRUCT_FOR_64_BIT_TYPES +# endif +# endif + + /* x-bit types */ +# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64) +# if !defined(_INT8_T_DECLARED) && !defined(_INT8_T) +typedef signed char int8_t; +# endif +# if !defined(_UINT8_T_DECLARED) && !defined(_UINT8_T) +typedef unsigned char uint8_t; +# endif +# if !defined(_INT16_T_DECLARED) && !defined(_INT16_T) +typedef signed short int16_t; +# endif +# if !defined(_UINT16_T_DECLARED) && !defined(_UINT16_T) +typedef unsigned short uint16_t; +# endif +# if !defined(_INT32_T_DECLARED) && !defined(_INT32_T) +typedef signed int int32_t; +# endif +# if !defined(_UINT32_T_DECLARED) && !defined(_UINT32_T) +typedef unsigned int uint32_t; +# endif +# if defined(_MSC_VER) +# if !defined(_INT64_T_DECLARED) && !defined(_INT64_T) +typedef signed _int64 int64_t; +# endif +# if !defined(_UINT64_T_DECLARED) && !defined(_UINT64_T) +typedef unsigned _int64 uint64_t; +# endif +# elif defined(IPRT_STDINT_USE_STRUCT_FOR_64_BIT_TYPES) +# if !defined(_INT64_T_DECLARED) && !defined(_INT64_T) +typedef struct { uint32_t lo; int32_t hi; } int64_t; +# endif +# if !defined(_UINT64_T_DECLARED) && !defined(_UINT64_T) +typedef struct { uint32_t lo; uint32_t hi; } uint64_t; +# endif +# else /* Use long long for 64-bit types */ +# if !defined(_INT64_T_DECLARED) && !defined(_INT64_T) +typedef signed long long int64_t; +# endif +# if !defined(_UINT64_T_DECLARED) && !defined(_UINT64_T) +typedef unsigned long long uint64_t; +# endif +# endif + + /* max integer types */ +# if !defined(_INTMAX_T_DECLARED) && !defined(_INTMAX_T) +typedef int64_t intmax_t; +# endif +# if !defined(_UINTMAX_T_DECLARED) && !defined(_UINTMAX_T) +typedef uint64_t uintmax_t; +# endif + +# else +# error "PORTME: Add architecture. Don't forget to check the [U]INTx_C() and [U]INTMAX_MIN/MAX macros." +# endif + +# endif /* !linux kernel or stuff */ + + /* pointer <-> integer types */ +# if !defined(_MSC_VER) || defined(DOXYGEN_RUNNING) +# if ARCH_BITS == 32 \ + || defined(RT_OS_LINUX) \ + || defined(RT_OS_FREEBSD) +# if !defined(_INTPTR_T_DECLARED) && !defined(_INTPTR_T) +typedef signed long intptr_t; +# endif +# if !defined(_UINTPTR_T_DECLARED) && !defined(_UINTPTR_T) +typedef unsigned long uintptr_t; +# endif +# else +# if !defined(_INTPTR_T_DECLARED) && !defined(_INTPTR_T) +typedef int64_t intptr_t; +# endif +# if !defined(_UINTPTR_T_DECLARED) && !defined(_UINTPTR_T) +typedef uint64_t uintptr_t; +# endif +# endif +# endif /* !_MSC_VER */ + +#endif /* no system stdint.h */ + + +/* + * Make sure the [U]INTx_C(c) macros are present. + * For In C++ source the system stdint.h may have skipped these if it was + * included before we managed to define __STDC_CONSTANT_MACROS. (Kludge alert!) + */ +#if !defined(INT8_C) \ + || !defined(INT16_C) \ + || !defined(INT32_C) \ + || !defined(INT64_C) \ + || !defined(INTMAX_C) \ + || !defined(UINT8_C) \ + || !defined(UINT16_C) \ + || !defined(UINT32_C) \ + || !defined(UINT64_C) \ + || !defined(UINTMAX_C) +# define INT8_C(Value) (Value) +# define INT16_C(Value) (Value) +# define INT32_C(Value) (Value) +# define INT64_C(Value) (Value ## LL) +# define UINT8_C(Value) (Value) +# define UINT16_C(Value) (Value) +# define UINT32_C(Value) (Value ## U) +# define UINT64_C(Value) (Value ## ULL) +# define INTMAX_C(Value) INT64_C(Value) +# define UINTMAX_C(Value) UINT64_C(Value) +#endif + + +/* + * Make sure the INTx_MIN and [U]INTx_MAX macros are present. + * For In C++ source the system stdint.h may have skipped these if it was + * included before we managed to define __STDC_LIMIT_MACROS. (Kludge alert!) + */ +#if !defined(INT8_MIN) \ + || !defined(INT16_MIN) \ + || !defined(INT32_MIN) \ + || !defined(INT64_MIN) \ + || !defined(INT8_MAX) \ + || !defined(INT16_MAX) \ + || !defined(INT32_MAX) \ + || !defined(INT64_MAX) \ + || !defined(UINT8_MAX) \ + || !defined(UINT16_MAX) \ + || !defined(UINT32_MAX) \ + || !defined(UINT64_MAX) +# define INT8_MIN (INT8_C(-0x7f) - 1) +# define INT16_MIN (INT16_C(-0x7fff) - 1) +# define INT32_MIN (INT32_C(-0x7fffffff) - 1) +# define INT64_MIN (INT64_C(-0x7fffffffffffffff) - 1) +# define INT8_MAX INT8_C(0x7f) +# define INT16_MAX INT16_C(0x7fff) +# define INT32_MAX INT32_C(0x7fffffff) +# define INT64_MAX INT64_C(0x7fffffffffffffff) +# define UINT8_MAX UINT8_C(0xff) +# define UINT16_MAX UINT16_C(0xffff) +# define UINT32_MAX UINT32_C(0xffffffff) +# define UINT64_MAX UINT64_C(0xffffffffffffffff) + +# define INTMAX_MIN INT64_MIN +# define INTMAX_MAX INT64_MAX +# define UINTMAX_MAX UINT64_MAX +#endif + +#endif + diff --git a/include/iprt/strcache.h b/include/iprt/strcache.h new file mode 100644 index 00000000..d3883483 --- /dev/null +++ b/include/iprt/strcache.h @@ -0,0 +1,121 @@ +/* $Id: strcache.h $ */ +/** @file + * IPRT - String Cache, stub implementation. + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_strcache_h +#define ___iprt_strcache_h + +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + + +/** + * Create a new string cache. + * + * @returns IPRT status code + * + * @param phStrCache Where to return the string cache handle. + * @param pszName The name of the cache (for debug purposes). + */ +RTDECL(int) RTStrCacheCreate(PRTSTRCACHE phStrCache, const char *pszName); + + +/** + * Destroys a string cache. + * + * This will cause all strings in the cache to be released and thus become + * invalid. + * + * @returns IPRT status. + * + * @param hStrCache Handle to the string cache. The nil and default + * handles are ignored quietly (VINF_SUCCESS). + */ +RTDECL(int) RTStrCacheDestroy(RTSTRCACHE hStrCache); + + +/** + * Enters a string into the cache. + * + * @returns Pointer to a read-only copy of the string. + * + * @param hStrCache Handle to the string cache. + * @param pchString Pointer to a string. This does not need to be + * zero terminated, but must not contain any zero + * characters. + * @param cchString The number of characters (bytes) to enter. + * + * @remarks It is implementation dependent whether the returned string pointer + * differs when entering the same string twice. + */ +RTDECL(const char *) RTStrCacheEnterN(RTSTRCACHE hStrCache, const char *pchString, size_t cchString); + +/** + * Enters a string into the cache. + * + * @returns Pointer to a read-only copy of the string. + * + * @param hStrCache Handle to the string cache. + * @param psz Pointer to a zero terminated string. + * + * @remarks See RTStrCacheEnterN. + */ +RTDECL(const char *) RTStrCacheEnter(RTSTRCACHE hStrCache, const char *psz); + + +/** + * Retains a reference to a string. + * + * @returns The new reference count. UINT32_MAX is returned if the string + * pointer is invalid. + */ +RTDECL(uint32_t) RTStrCacheRetain(const char *psz); + +/** + * Releases a reference to a string. + * + * @returns The new reference count. + * UINT32_MAX is returned if the string pointer is invalid. + * + * @param hStrCache Handle to the string cache. Passing NIL is ok, + * but this may come a performance hit. + * @param psz Pointer to a cached string. + */ +RTDECL(uint32_t) RTStrCacheRelease(RTSTRCACHE hStrCache, const char *psz); + +/** + * Gets the string length of a cache entry. + * + * @returns The string length. 0 if the string is invalid (asserted). + * + * @param psz Pointer to a cached string. + */ +RTDECL(size_t) RTStrCacheLength(const char *psz); + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/stream.h b/include/iprt/stream.h new file mode 100644 index 00000000..e8ac0d08 --- /dev/null +++ b/include/iprt/stream.h @@ -0,0 +1,292 @@ +/** @file + * IPRT - I/O Stream. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_stream_h +#define ___iprt_stream_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_stream RTStrm - File Streams + * @ingroup grp_rt + * @{ + */ + +/** Pointer to a stream. */ +typedef struct RTSTREAM *PRTSTREAM; + +/** Pointer to the standard input stream. */ +extern RTDATADECL(PRTSTREAM) g_pStdIn; + +/** Pointer to the standard error stream. */ +extern RTDATADECL(PRTSTREAM) g_pStdErr; + +/** Pointer to the standard output stream. */ +extern RTDATADECL(PRTSTREAM) g_pStdOut; + + +/** + * Opens a file stream. + * + * @returns iprt status code. + * @param pszFilename Path to the file to open. + * @param pszMode The open mode. See fopen() standard. + * Format: <a|r|w>[+][b|t] + * @param ppStream Where to store the opened stream. + */ +RTR3DECL(int) RTStrmOpen(const char *pszFilename, const char *pszMode, PRTSTREAM *ppStream); + +/** + * Opens a file stream. + * + * @returns iprt status code. + * @param pszMode The open mode. See fopen() standard. + * Format: <a|r|w>[+][b|t] + * @param ppStream Where to store the opened stream. + * @param pszFilenameFmt Filename path format string. + * @param args Arguments to the format string. + */ +RTR3DECL(int) RTStrmOpenFV(const char *pszMode, PRTSTREAM *ppStream, const char *pszFilenameFmt, va_list args); + +/** + * Opens a file stream. + * + * @returns iprt status code. + * @param pszMode The open mode. See fopen() standard. + * Format: <a|r|w>[+][b|t] + * @param ppStream Where to store the opened stream. + * @param pszFilenameFmt Filename path format string. + * @param ... Arguments to the format string. + */ +RTR3DECL(int) RTStrmOpenF(const char *pszMode, PRTSTREAM *ppStream, const char *pszFilenameFmt, ...); + +/** + * Closes the specified stream. + * + * @returns iprt status code. + * @param pStream The stream to close. + */ +RTR3DECL(int) RTStrmClose(PRTSTREAM pStream); + +/** + * Get the pending error of the stream. + * + * @returns iprt status code. of the stream. + * @param pStream The stream. + */ +RTR3DECL(int) RTStrmError(PRTSTREAM pStream); + +/** + * Clears stream error condition. + * + * All stream operations save RTStrmClose and this will fail + * while an error is asserted on the stream + * + * @returns iprt status code. + * @param pStream The stream. + */ +RTR3DECL(int) RTStrmClearError(PRTSTREAM pStream); + +/** + * Changes the stream mode. + * + * @returns iprt status code. + * @param pStream The stream. + * @param fBinary The desired binary (@c true) / text mode (@c false). + * Pass -1 to leave it unchanged. + * @param fCurrentCodeSet Whether converting the stream from UTF-8 to the + * current code set is desired (@c true) or not (@c + * false). Pass -1 to leave this property unchanged. + */ +RTR3DECL(int) RTStrmSetMode(PRTSTREAM pStream, int fBinary, int fCurrentCodeSet); + +/** + * Rewinds the stream. + * + * Stream errors will be reset on success. + * + * @returns IPRT status code. + * + * @param pStream The stream. + * + * @remarks Not all streams are rewindable and that behavior is currently + * undefined for those. + */ +RTR3DECL(int) RTStrmRewind(PRTSTREAM pStream); + +/** + * Reads from a file stream. + * + * @returns iprt status code. + * @param pStream The stream. + * @param pvBuf Where to put the read bits. + * Must be cbRead bytes or more. + * @param cbRead Number of bytes to read. + * @param pcbRead Where to store the number of bytes actually read. + * If NULL cbRead bytes are read or an error is returned. + */ +RTR3DECL(int) RTStrmReadEx(PRTSTREAM pStream, void *pvBuf, size_t cbRead, size_t *pcbRead); + +/** + * Writes to a file stream. + * + * @returns iprt status code. + * @param pStream The stream. + * @param pvBuf Where to get the bits to write from. + * @param cbWrite Number of bytes to write. + * @param pcbWritten Where to store the number of bytes actually written. + * If NULL cbWrite bytes are written or an error is returned. + */ +RTR3DECL(int) RTStrmWriteEx(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite, size_t *pcbWritten); + +/** + * Reads from a file stream. + * + * @returns iprt status code. + * @param pStream The stream. + * @param pvBuf Where to put the read bits. + * Must be cbRead bytes or more. + * @param cbRead Number of bytes to read. + */ +DECLINLINE(int) RTStrmRead(PRTSTREAM pStream, void *pvBuf, size_t cbRead) +{ + return RTStrmReadEx(pStream, pvBuf, cbRead, NULL); +} + +/** + * Writes to a file stream. + * + * @returns iprt status code. + * @param pStream The stream. + * @param pvBuf Where to get the bits to write from. + * @param cbWrite Number of bytes to write. + */ +DECLINLINE(int) RTStrmWrite(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite) +{ + return RTStrmWriteEx(pStream, pvBuf, cbWrite, NULL); +} + +/** + * Reads a character from a file stream. + * + * @returns The char as an unsigned char cast to int. + * @returns -1 on failure. + * @param pStream The stream. + */ +RTR3DECL(int) RTStrmGetCh(PRTSTREAM pStream); + +/** + * Writes a character to a file stream. + * + * @returns iprt status code. + * @param pStream The stream. + * @param ch The char to write. + */ +RTR3DECL(int) RTStrmPutCh(PRTSTREAM pStream, int ch); + +/** + * Writes a string to a file stream. + * + * @returns iprt status code. + * @param pStream The stream. + * @param pszString The string to write. + * No newlines or anything is appended or prepended. + * The terminating '\\0' is not written, of course. + */ +RTR3DECL(int) RTStrmPutStr(PRTSTREAM pStream, const char *pszString); + +/** + * Reads a line from a file stream. + * + * A line ends with a '\\n', '\\r\\n', '\\0' or the end of the file. + * + * @returns iprt status code. + * @retval VINF_BUFFER_OVERFLOW if the buffer wasn't big enough to read an + * entire line. + * @retval VERR_BUFFER_OVERFLOW if a lone '\\r' was encountered at the end of + * the buffer and we ended up dropping the following character. + * + * @param pStream The stream. + * @param pszString Where to store the line. + * The line will *NOT* contain any '\\n'. + * @param cbString The size of the string buffer. + */ +RTR3DECL(int) RTStrmGetLine(PRTSTREAM pStream, char *pszString, size_t cbString); + +/** + * Flushes a stream. + * + * @returns iprt status code. + * @param pStream The stream to flush. + */ +RTR3DECL(int) RTStrmFlush(PRTSTREAM pStream); + +/** + * Prints a formatted string to the specified stream. + * + * @returns Number of bytes printed. + * @param pStream The stream to print to. + * @param pszFormat Runtime format string. + * @param ... Arguments specified by pszFormat. + */ +RTR3DECL(int) RTStrmPrintf(PRTSTREAM pStream, const char *pszFormat, ...); + +/** + * Prints a formatted string to the specified stream. + * + * @returns Number of bytes printed. + * @param pStream The stream to print to. + * @param pszFormat Runtime format string. + * @param args Arguments specified by pszFormat. + */ +RTR3DECL(int) RTStrmPrintfV(PRTSTREAM pStream, const char *pszFormat, va_list args); + +/** + * Prints a formatted string to the standard output stream (g_pStdOut). + * + * @returns Number of bytes printed. + * @param pszFormat Runtime format string. + * @param ... Arguments specified by pszFormat. + */ +RTR3DECL(int) RTPrintf(const char *pszFormat, ...); + +/** + * Prints a formatted string to the standard output stream (g_pStdOut). + * + * @returns Number of bytes printed. + * @param pszFormat Runtime format string. + * @param args Arguments specified by pszFormat. + */ +RTR3DECL(int) RTPrintfV(const char *pszFormat, va_list args); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/string.h b/include/iprt/string.h new file mode 100644 index 00000000..1f52c75d --- /dev/null +++ b/include/iprt/string.h @@ -0,0 +1,3868 @@ +/** @file + * IPRT - String Manipulation. + */ + +/* + * Copyright (C) 2006-2012 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. + */ + +#ifndef ___iprt_string_h +#define ___iprt_string_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/assert.h> +#include <iprt/stdarg.h> +#include <iprt/err.h> /* for VINF_SUCCESS */ +#if defined(RT_OS_LINUX) && defined(__KERNEL__) + RT_C_DECLS_BEGIN +# include <linux/string.h> + RT_C_DECLS_END + +#elif defined(IN_XF86_MODULE) && !defined(NO_ANSIC) + RT_C_DECLS_BEGIN +# include "xf86_ansic.h" + RT_C_DECLS_END + +#elif defined(RT_OS_FREEBSD) && defined(_KERNEL) + RT_C_DECLS_BEGIN + /** @todo + * XXX: Very ugly hack to get things build on recent FreeBSD builds. They have + * memchr now and we need to include param.h to get __FreeBSD_version and make + * memchr available based on the version below or we can't compile the kernel + * module on older versions anymore. + * + * But including param.h here opens Pandora's box because we clash with a few + * defines namely PVM and PAGE_SIZE. We can safely undefine PVM here but not + * PAGE_SIZE because this results in build errors sooner or later. Luckily this + * define is in a header included by param.h (machine/param.h). We define the + * guards here to prevent inclusion of it if PAGE_SIZE was defined already. + * + * @todo aeichner: Search for an elegant solution and cleanup this mess ASAP! + */ +# ifdef PAGE_SIZE +# define _AMD64_INCLUDE_PARAM_H_ +# define _I386_INCLUDE_PARAM_H_ +# define _MACHINE_PARAM_H_ +# endif +# include <sys/param.h> /* __FreeBSD_version */ +# undef PVM +# include <sys/libkern.h> + /* + * No memmove on versions < 7.2 + * Defining a macro using bcopy here + */ +# define memmove(dst, src, size) bcopy(src, dst, size) + RT_C_DECLS_END + +#elif defined(RT_OS_SOLARIS) && defined(_KERNEL) + /* + * Same case as with FreeBSD kernel: + * The string.h stuff clashes with sys/system.h + * ffs = find first set bit. + */ +# define ffs ffs_string_h +# include <string.h> +# undef ffs +# undef strpbrk + +#else +# include <string.h> +#endif + +/* + * Supply prototypes for standard string functions provided by + * IPRT instead of the operating environment. + */ +#if defined(RT_OS_DARWIN) && defined(KERNEL) +RT_C_DECLS_BEGIN +void *memchr(const void *pv, int ch, size_t cb); +char *strpbrk(const char *pszStr, const char *pszChars); +RT_C_DECLS_END +#endif + +#if defined(RT_OS_FREEBSD) && defined(_KERNEL) +RT_C_DECLS_BEGIN +#if __FreeBSD_version < 900000 +void *memchr(const void *pv, int ch, size_t cb); +#endif +char *strpbrk(const char *pszStr, const char *pszChars); +RT_C_DECLS_END +#endif + +/** @def RT_USE_RTC_3629 + * When defined the UTF-8 range will stop at 0x10ffff. If not defined, the + * range stops at 0x7fffffff. + * @remarks Must be defined both when building and using the IPRT. */ +#ifdef DOXYGEN_RUNNING +# define RT_USE_RTC_3629 +#endif + + +/** + * Byte zero the specified object. + * + * This will use sizeof(Obj) to figure the size and will call memset, bzero + * or some compiler intrinsic to perform the actual zeroing. + * + * @param Obj The object to zero. Make sure to dereference pointers. + * + * @remarks Because the macro may use memset it has been placed in string.h + * instead of cdefs.h to avoid build issues because someone forgot + * to include this header. + * + * @ingroup grp_rt_cdefs + */ +#define RT_ZERO(Obj) RT_BZERO(&(Obj), sizeof(Obj)) + +/** + * Byte zero the specified memory area. + * + * This will call memset, bzero or some compiler intrinsic to clear the + * specified bytes of memory. + * + * @param pv Pointer to the memory. + * @param cb The number of bytes to clear. Please, don't pass 0. + * + * @remarks Because the macro may use memset it has been placed in string.h + * instead of cdefs.h to avoid build issues because someone forgot + * to include this header. + * + * @ingroup grp_rt_cdefs + */ +#define RT_BZERO(pv, cb) do { memset((pv), 0, cb); } while (0) + + + +/** @defgroup grp_rt_str RTStr - String Manipulation + * Mostly UTF-8 related helpers where the standard string functions won't do. + * @ingroup grp_rt + * @{ + */ + +RT_C_DECLS_BEGIN + + +/** + * The maximum string length. + */ +#define RTSTR_MAX (~(size_t)0) + + +/** @def RTMEM_TAG + * The default allocation tag used by the RTStr allocation APIs. + * + * When not defined before the inclusion of iprt/string.h, this will default to + * the pointer to the current file name. The string API will make of use of + * this as pointer to a volatile but read-only string. + */ +#ifndef RTSTR_TAG +# define RTSTR_TAG (__FILE__) +#endif + + +#ifdef IN_RING3 + +/** + * Allocates tmp buffer with default tag, translates pszString from UTF8 to + * current codepage. + * + * @returns iprt status code. + * @param ppszString Receives pointer of allocated native CP string. + * The returned pointer must be freed using RTStrFree(). + * @param pszString UTF-8 string to convert. + */ +#define RTStrUtf8ToCurrentCP(ppszString, pszString) RTStrUtf8ToCurrentCPTag((ppszString), (pszString), RTSTR_TAG) + +/** + * Allocates tmp buffer with custom tag, translates pszString from UTF8 to + * current codepage. + * + * @returns iprt status code. + * @param ppszString Receives pointer of allocated native CP string. + * The returned pointer must be freed using + * RTStrFree()., const char *pszTag + * @param pszString UTF-8 string to convert. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR3DECL(int) RTStrUtf8ToCurrentCPTag(char **ppszString, const char *pszString, const char *pszTag); + +/** + * Allocates tmp buffer, translates pszString from current codepage to UTF-8. + * + * @returns iprt status code. + * @param ppszString Receives pointer of allocated UTF-8 string. + * The returned pointer must be freed using RTStrFree(). + * @param pszString Native string to convert. + */ +#define RTStrCurrentCPToUtf8(ppszString, pszString) RTStrCurrentCPToUtf8Tag((ppszString), (pszString), RTSTR_TAG) + +/** + * Allocates tmp buffer, translates pszString from current codepage to UTF-8. + * + * @returns iprt status code. + * @param ppszString Receives pointer of allocated UTF-8 string. + * The returned pointer must be freed using RTStrFree(). + * @param pszString Native string to convert. + * @param pszTag Allocation tag used for statistics and such. + */ +RTR3DECL(int) RTStrCurrentCPToUtf8Tag(char **ppszString, const char *pszString, const char *pszTag); + +#endif /* IN_RING3 */ + +/** + * Free string allocated by any of the non-UCS-2 string functions. + * + * @returns iprt status code. + * @param pszString Pointer to buffer with string to free. + * NULL is accepted. + */ +RTDECL(void) RTStrFree(char *pszString); + +/** + * Allocates a new copy of the given UTF-8 string (default tag). + * + * @returns Pointer to the allocated UTF-8 string. + * @param pszString UTF-8 string to duplicate. + */ +#define RTStrDup(pszString) RTStrDupTag((pszString), RTSTR_TAG) + +/** + * Allocates a new copy of the given UTF-8 string (custom tag). + * + * @returns Pointer to the allocated UTF-8 string. + * @param pszString UTF-8 string to duplicate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(char *) RTStrDupTag(const char *pszString, const char *pszTag); + +/** + * Allocates a new copy of the given UTF-8 string (default tag). + * + * @returns iprt status code. + * @param ppszString Receives pointer of the allocated UTF-8 string. + * The returned pointer must be freed using RTStrFree(). + * @param pszString UTF-8 string to duplicate. + */ +#define RTStrDupEx(ppszString, pszString) RTStrDupExTag((ppszString), (pszString), RTSTR_TAG) + +/** + * Allocates a new copy of the given UTF-8 string (custom tag). + * + * @returns iprt status code. + * @param ppszString Receives pointer of the allocated UTF-8 string. + * The returned pointer must be freed using RTStrFree(). + * @param pszString UTF-8 string to duplicate. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrDupExTag(char **ppszString, const char *pszString, const char *pszTag); + +/** + * Allocates a new copy of the given UTF-8 substring (default tag). + * + * @returns Pointer to the allocated UTF-8 substring. + * @param pszString UTF-8 string to duplicate. + * @param cchMax The max number of chars to duplicate, not counting + * the terminator. + */ +#define RTStrDupN(pszString, cchMax) RTStrDupNTag((pszString), (cchMax), RTSTR_TAG) + +/** + * Allocates a new copy of the given UTF-8 substring (custom tag). + * + * @returns Pointer to the allocated UTF-8 substring. + * @param pszString UTF-8 string to duplicate. + * @param cchMax The max number of chars to duplicate, not counting + * the terminator. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(char *) RTStrDupNTag(const char *pszString, size_t cchMax, const char *pszTag); + +/** + * Appends a string onto an existing IPRT allocated string (default tag). + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string pointer. The string + * pointer must either be NULL or point to a string + * returned by an IPRT string API. (In/Out) + * @param pszAppend The string to append. NULL and empty strings + * are quietly ignored. + */ +#define RTStrAAppend(ppsz, pszAppend) RTStrAAppendTag((ppsz), (pszAppend), RTSTR_TAG) + +/** + * Appends a string onto an existing IPRT allocated string (custom tag). + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string pointer. The string + * pointer must either be NULL or point to a string + * returned by an IPRT string API. (In/Out) + * @param pszAppend The string to append. NULL and empty strings + * are quietly ignored. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrAAppendTag(char **ppsz, const char *pszAppend, const char *pszTag); + +/** + * Appends N bytes from a strings onto an existing IPRT allocated string + * (default tag). + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string pointer. The string + * pointer must either be NULL or point to a string + * returned by an IPRT string API. (In/Out) + * @param pszAppend The string to append. Can be NULL if cchAppend + * is NULL. + * @param cchAppend The number of chars (not code points) to append + * from pszAppend. Must not be more than + * @a pszAppend contains, except for the special + * value RTSTR_MAX that can be used to indicate all + * of @a pszAppend without having to strlen it. + */ +#define RTStrAAppendN(ppsz, pszAppend, cchAppend) RTStrAAppendNTag((ppsz), (pszAppend), (cchAppend), RTSTR_TAG) + +/** + * Appends N bytes from a strings onto an existing IPRT allocated string (custom + * tag). + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string pointer. The string + * pointer must either be NULL or point to a string + * returned by an IPRT string API. (In/Out) + * @param pszAppend The string to append. Can be NULL if cchAppend + * is NULL. + * @param cchAppend The number of chars (not code points) to append + * from pszAppend. Must not be more than + * @a pszAppend contains, except for the special + * value RTSTR_MAX that can be used to indicate all + * of @a pszAppend without having to strlen it. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrAAppendNTag(char **ppsz, const char *pszAppend, size_t cchAppend, const char *pszTag); + +/** + * Appends one or more strings onto an existing IPRT allocated string. + * + * This is a very flexible and efficient alternative to using RTStrAPrintf to + * combine several strings together. + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string pointer. The string + * pointer must either be NULL or point to a string + * returned by an IPRT string API. (In/Out) + * @param cPairs The number of string / length pairs in the + * @a va. + * @param va List of string (const char *) and length + * (size_t) pairs. The strings will be appended to + * the string in the first argument. + */ +#define RTStrAAppendExNV(ppsz, cPairs, va) RTStrAAppendExNVTag((ppsz), (cPairs), (va), RTSTR_TAG) + +/** + * Appends one or more strings onto an existing IPRT allocated string. + * + * This is a very flexible and efficient alternative to using RTStrAPrintf to + * combine several strings together. + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string pointer. The string + * pointer must either be NULL or point to a string + * returned by an IPRT string API. (In/Out) + * @param cPairs The number of string / length pairs in the + * @a va. + * @param va List of string (const char *) and length + * (size_t) pairs. The strings will be appended to + * the string in the first argument. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrAAppendExNVTag(char **ppsz, size_t cPairs, va_list va, const char *pszTag); + +/** + * Appends one or more strings onto an existing IPRT allocated string + * (untagged). + * + * This is a very flexible and efficient alternative to using RTStrAPrintf to + * combine several strings together. + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string pointer. The string + * pointer must either be NULL or point to a string + * returned by an IPRT string API. (In/Out) + * @param cPairs The number of string / length pairs in the + * ellipsis. + * @param ... List of string (const char *) and length + * (size_t) pairs. The strings will be appended to + * the string in the first argument. + */ +DECLINLINE(int) RTStrAAppendExN(char **ppsz, size_t cPairs, ...) +{ + int rc; + va_list va; + va_start(va, cPairs); + rc = RTStrAAppendExNVTag(ppsz, cPairs, va, RTSTR_TAG); + va_end(va); + return rc; +} + +/** + * Appends one or more strings onto an existing IPRT allocated string (custom + * tag). + * + * This is a very flexible and efficient alternative to using RTStrAPrintf to + * combine several strings together. + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string pointer. The string + * pointer must either be NULL or point to a string + * returned by an IPRT string API. (In/Out) + * @param pszTag Allocation tag used for statistics and such. + * @param cPairs The number of string / length pairs in the + * ellipsis. + * @param ... List of string (const char *) and length + * (size_t) pairs. The strings will be appended to + * the string in the first argument. + */ +DECLINLINE(int) RTStrAAppendExNTag(char **ppsz, const char *pszTag, size_t cPairs, ...) +{ + int rc; + va_list va; + va_start(va, cPairs); + rc = RTStrAAppendExNVTag(ppsz, cPairs, va, pszTag); + va_end(va); + return rc; +} + +/** + * Truncates an IPRT allocated string (default tag). + * + * @retval VINF_SUCCESS. + * @retval VERR_OUT_OF_RANGE if cchNew is too long. Nothing is done. + * + * @param ppsz Pointer to the string pointer. The string + * pointer can be NULL if @a cchNew is 0, no change + * is made then. If we actually reallocate the + * string, the string pointer might be changed by + * this call. (In/Out) + * @param cchNew The new string length (excluding the + * terminator). The string must be at least this + * long or we'll return VERR_OUT_OF_RANGE and + * assert on you. + */ +#define RTStrATruncate(ppsz, cchNew) RTStrATruncateTag((ppsz), (cchNew), RTSTR_TAG) + +/** + * Truncates an IPRT allocated string. + * + * @retval VINF_SUCCESS. + * @retval VERR_OUT_OF_RANGE if cchNew is too long. Nothing is done. + * + * @param ppsz Pointer to the string pointer. The string + * pointer can be NULL if @a cchNew is 0, no change + * is made then. If we actually reallocate the + * string, the string pointer might be changed by + * this call. (In/Out) + * @param cchNew The new string length (excluding the + * terminator). The string must be at least this + * long or we'll return VERR_OUT_OF_RANGE and + * assert on you. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrATruncateTag(char **ppsz, size_t cchNew, const char *pszTag); + +/** + * Allocates memory for string storage (default tag). + * + * You should normally not use this function, except if there is some very + * custom string handling you need doing that isn't covered by any of the other + * APIs. + * + * @returns Pointer to the allocated string. The first byte is always set + * to the string terminator char, the contents of the remainder of the + * memory is undefined. The string must be freed by calling RTStrFree. + * + * NULL is returned if the allocation failed. Please translate this to + * VERR_NO_STR_MEMORY and not VERR_NO_MEMORY. Also consider + * RTStrAllocEx if an IPRT status code is required. + * + * @param cb How many bytes to allocate. If this is zero, we + * will allocate a terminator byte anyway. + */ +#define RTStrAlloc(cb) RTStrAllocTag((cb), RTSTR_TAG) + +/** + * Allocates memory for string storage (custom tag). + * + * You should normally not use this function, except if there is some very + * custom string handling you need doing that isn't covered by any of the other + * APIs. + * + * @returns Pointer to the allocated string. The first byte is always set + * to the string terminator char, the contents of the remainder of the + * memory is undefined. The string must be freed by calling RTStrFree. + * + * NULL is returned if the allocation failed. Please translate this to + * VERR_NO_STR_MEMORY and not VERR_NO_MEMORY. Also consider + * RTStrAllocEx if an IPRT status code is required. + * + * @param cb How many bytes to allocate. If this is zero, we + * will allocate a terminator byte anyway. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(char *) RTStrAllocTag(size_t cb, const char *pszTag); + +/** + * Allocates memory for string storage, with status code (default tag). + * + * You should normally not use this function, except if there is some very + * custom string handling you need doing that isn't covered by any of the other + * APIs. + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY + * + * @param ppsz Where to return the allocated string. This will + * be set to NULL on failure. On success, the + * returned memory will always start with a + * terminator char so that it is considered a valid + * C string, the contents of rest of the memory is + * undefined. + * @param cb How many bytes to allocate. If this is zero, we + * will allocate a terminator byte anyway. + */ +#define RTStrAllocEx(ppsz, cb) RTStrAllocExTag((ppsz), (cb), RTSTR_TAG) + +/** + * Allocates memory for string storage, with status code (custom tag). + * + * You should normally not use this function, except if there is some very + * custom string handling you need doing that isn't covered by any of the other + * APIs. + * + * @retval VINF_SUCCESS + * @retval VERR_NO_STR_MEMORY + * + * @param ppsz Where to return the allocated string. This will + * be set to NULL on failure. On success, the + * returned memory will always start with a + * terminator char so that it is considered a valid + * C string, the contents of rest of the memory is + * undefined. + * @param cb How many bytes to allocate. If this is zero, we + * will allocate a terminator byte anyway. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrAllocExTag(char **ppsz, size_t cb, const char *pszTag); + +/** + * Reallocates the specified string (default tag). + * + * You should normally not have use this function, except perhaps to truncate a + * really long string you've got from some IPRT string API, but then you should + * use RTStrATruncate. + * + * @returns VINF_SUCCESS. + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string variable containing the + * input and output string. + * + * When not freeing the string, the result will + * always have the last byte set to the terminator + * character so that when used for string + * truncation the result will be a valid C string + * (your job to keep it a valid UTF-8 string). + * + * When the input string is NULL and we're supposed + * to reallocate, the returned string will also + * have the first byte set to the terminator char + * so it will be a valid C string. + * + * @param cbNew When @a cbNew is zero, we'll behave like + * RTStrFree and @a *ppsz will be set to NULL. + * + * When not zero, this will be the new size of the + * memory backing the string, i.e. it includes the + * terminator char. + */ +#define RTStrRealloc(ppsz, cbNew) RTStrReallocTag((ppsz), (cbNew), RTSTR_TAG) + +/** + * Reallocates the specified string (custom tag). + * + * You should normally not have use this function, except perhaps to truncate a + * really long string you've got from some IPRT string API, but then you should + * use RTStrATruncate. + * + * @returns VINF_SUCCESS. + * @retval VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz + * remains unchanged. + * + * @param ppsz Pointer to the string variable containing the + * input and output string. + * + * When not freeing the string, the result will + * always have the last byte set to the terminator + * character so that when used for string + * truncation the result will be a valid C string + * (your job to keep it a valid UTF-8 string). + * + * When the input string is NULL and we're supposed + * to reallocate, the returned string will also + * have the first byte set to the terminator char + * so it will be a valid C string. + * + * @param cbNew When @a cbNew is zero, we'll behave like + * RTStrFree and @a *ppsz will be set to NULL. + * + * When not zero, this will be the new size of the + * memory backing the string, i.e. it includes the + * terminator char. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrReallocTag(char **ppsz, size_t cbNew, const char *pszTag); + +/** + * Validates the UTF-8 encoding of the string. + * + * @returns iprt status code. + * @param psz The string. + */ +RTDECL(int) RTStrValidateEncoding(const char *psz); + +/** @name Flags for RTStrValidateEncodingEx + */ +/** Check that the string is zero terminated within the given size. + * VERR_BUFFER_OVERFLOW will be returned if the check fails. */ +#define RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED RT_BIT_32(0) +/** @} */ + +/** + * Validates the UTF-8 encoding of the string. + * + * @returns iprt status code. + * @param psz The string. + * @param cch The max string length. Use RTSTR_MAX to process the entire string. + * @param fFlags Reserved for future. Pass 0. + */ +RTDECL(int) RTStrValidateEncodingEx(const char *psz, size_t cch, uint32_t fFlags); + +/** + * Checks if the UTF-8 encoding is valid. + * + * @returns true / false. + * @param psz The string. + */ +RTDECL(bool) RTStrIsValidEncoding(const char *psz); + +/** + * Purge all bad UTF-8 encoding in the string, replacing it with '?'. + * + * @returns The number of bad characters (0 if nothing was done). + * @param psz The string to purge. + */ +RTDECL(size_t) RTStrPurgeEncoding(char *psz); + +/** + * Sanitise a (valid) UTF-8 string by replacing all characters outside a white + * list in-place by an ASCII replacement character. Multi-byte characters will + * be replaced byte by byte. + * + * @returns The number of code points replaced, or a negative value if the + * string is not correctly encoded. In this last case the string + * may be partially processed. + * @param psz The string to sanitise. + * @param puszValidSets A zero-terminated array of pairs of Unicode points. + * Each pair is the start and end point of a range, + * and the union of these ranges forms the white list. + * @param chReplacement The ASCII replacement character. + */ +RTDECL(ssize_t) RTStrPurgeComplementSet(char *psz, PCRTUNICP puszValidSet, char chReplacement); + +/** + * Gets the number of code points the string is made up of, excluding + * the terminator. + * + * + * @returns Number of code points (RTUNICP). + * @returns 0 if the string was incorrectly encoded. + * @param psz The string. + */ +RTDECL(size_t) RTStrUniLen(const char *psz); + +/** + * Gets the number of code points the string is made up of, excluding + * the terminator. + * + * This function will validate the string, and incorrectly encoded UTF-8 + * strings will be rejected. + * + * @returns iprt status code. + * @param psz The string. + * @param cch The max string length. Use RTSTR_MAX to process the entire string. + * @param pcuc Where to store the code point count. + * This is undefined on failure. + */ +RTDECL(int) RTStrUniLenEx(const char *psz, size_t cch, size_t *pcuc); + +/** + * Translate a UTF-8 string into an unicode string (i.e. RTUNICPs), allocating the string buffer. + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param ppUniString Receives pointer to the allocated unicode string. + * The returned string must be freed using RTUniFree(). + */ +RTDECL(int) RTStrToUni(const char *pszString, PRTUNICP *ppUniString); + +/** + * Translates pszString from UTF-8 to an array of code points, allocating the result + * array if requested. + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param cchString The maximum size in chars (the type) to convert. The conversion stop + * when it reaches cchString or the string terminator ('\\0'). + * Use RTSTR_MAX to translate the entire string. + * @param ppaCps If cCps is non-zero, this must either be pointing to pointer to + * a buffer of the specified size, or pointer to a NULL pointer. + * If *ppusz is NULL or cCps is zero a buffer of at least cCps items + * will be allocated to hold the translated string. + * If a buffer was requested it must be freed using RTUtf16Free(). + * @param cCps The number of code points in the unicode string. This includes the terminator. + * @param pcCps Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + */ +RTDECL(int) RTStrToUniEx(const char *pszString, size_t cchString, PRTUNICP *ppaCps, size_t cCps, size_t *pcCps); + +/** + * Calculates the length of the string in RTUTF16 items. + * + * This function will validate the string, and incorrectly encoded UTF-8 + * strings will be rejected. The primary purpose of this function is to + * help allocate buffers for RTStrToUtf16Ex of the correct size. For most + * other purposes RTStrCalcUtf16LenEx() should be used. + * + * @returns Number of RTUTF16 items. + * @returns 0 if the string was incorrectly encoded. + * @param psz The string. + */ +RTDECL(size_t) RTStrCalcUtf16Len(const char *psz); + +/** + * Calculates the length of the string in RTUTF16 items. + * + * This function will validate the string, and incorrectly encoded UTF-8 + * strings will be rejected. + * + * @returns iprt status code. + * @param psz The string. + * @param cch The max string length. Use RTSTR_MAX to process the entire string. + * @param pcwc Where to store the string length. Optional. + * This is undefined on failure. + */ +RTDECL(int) RTStrCalcUtf16LenEx(const char *psz, size_t cch, size_t *pcwc); + +/** + * Translate a UTF-8 string into a UTF-16 allocating the result buffer (default + * tag). + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param ppwszString Receives pointer to the allocated UTF-16 string. + * The returned string must be freed using RTUtf16Free(). + */ +#define RTStrToUtf16(pszString, ppwszString) RTStrToUtf16Tag((pszString), (ppwszString), RTSTR_TAG) + +/** + * Translate a UTF-8 string into a UTF-16 allocating the result buffer (custom + * tag). + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param ppwszString Receives pointer to the allocated UTF-16 string. + * The returned string must be freed using RTUtf16Free(). + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrToUtf16Tag(const char *pszString, PRTUTF16 *ppwszString, const char *pszTag); + +/** + * Translates pszString from UTF-8 to UTF-16, allocating the result buffer if requested. + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param cchString The maximum size in chars (the type) to convert. The conversion stop + * when it reaches cchString or the string terminator ('\\0'). + * Use RTSTR_MAX to translate the entire string. + * @param ppwsz If cwc is non-zero, this must either be pointing to pointer to + * a buffer of the specified size, or pointer to a NULL pointer. + * If *ppwsz is NULL or cwc is zero a buffer of at least cwc items + * will be allocated to hold the translated string. + * If a buffer was requested it must be freed using RTUtf16Free(). + * @param cwc The buffer size in RTUTF16s. This includes the terminator. + * @param pcwc Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + */ +#define RTStrToUtf16Ex(pszString, cchString, ppwsz, cwc, pcwc) \ + RTStrToUtf16ExTag((pszString), (cchString), (ppwsz), (cwc), (pcwc), RTSTR_TAG) + +/** + * Translates pszString from UTF-8 to UTF-16, allocating the result buffer if + * requested (custom tag). + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param cchString The maximum size in chars (the type) to convert. The conversion stop + * when it reaches cchString or the string terminator ('\\0'). + * Use RTSTR_MAX to translate the entire string. + * @param ppwsz If cwc is non-zero, this must either be pointing to pointer to + * a buffer of the specified size, or pointer to a NULL pointer. + * If *ppwsz is NULL or cwc is zero a buffer of at least cwc items + * will be allocated to hold the translated string. + * If a buffer was requested it must be freed using RTUtf16Free(). + * @param cwc The buffer size in RTUTF16s. This includes the terminator. + * @param pcwc Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrToUtf16ExTag(const char *pszString, size_t cchString, PRTUTF16 *ppwsz, size_t cwc, size_t *pcwc, const char *pszTag); + + +/** + * Calculates the length of the string in Latin-1 characters. + * + * This function will validate the string, and incorrectly encoded UTF-8 + * strings as well as string with codepoints outside the latin-1 range will be + * rejected. The primary purpose of this function is to help allocate buffers + * for RTStrToLatin1Ex of the correct size. For most other purposes + * RTStrCalcLatin1LenEx() should be used. + * + * @returns Number of Latin-1 characters. + * @returns 0 if the string was incorrectly encoded. + * @param psz The string. + */ +RTDECL(size_t) RTStrCalcLatin1Len(const char *psz); + +/** + * Calculates the length of the string in Latin-1 characters. + * + * This function will validate the string, and incorrectly encoded UTF-8 + * strings as well as string with codepoints outside the latin-1 range will be + * rejected. + * + * @returns iprt status code. + * @param psz The string. + * @param cch The max string length. Use RTSTR_MAX to process the + * entire string. + * @param pcch Where to store the string length. Optional. + * This is undefined on failure. + */ +RTDECL(int) RTStrCalcLatin1LenEx(const char *psz, size_t cch, size_t *pcwc); + +/** + * Translate a UTF-8 string into a Latin-1 allocating the result buffer (default + * tag). + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param ppszString Receives pointer to the allocated Latin-1 string. + * The returned string must be freed using RTStrFree(). + */ +#define RTStrToLatin1(pszString, ppszString) RTStrToLatin1Tag((pszString), (ppszString), RTSTR_TAG) + +/** + * Translate a UTF-8 string into a Latin-1 allocating the result buffer (custom + * tag). + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param ppszString Receives pointer to the allocated Latin-1 string. + * The returned string must be freed using RTStrFree(). + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrToLatin1Tag(const char *pszString, char **ppszString, const char *pszTag); + +/** + * Translates pszString from UTF-8 to Latin-1, allocating the result buffer if requested. + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param cchString The maximum size in chars (the type) to convert. + * The conversion stop when it reaches cchString or + * the string terminator ('\\0'). Use RTSTR_MAX to + * translate the entire string. + * @param ppsz If cch is non-zero, this must either be pointing to + * pointer to a buffer of the specified size, or + * pointer to a NULL pointer. If *ppsz is NULL or cch + * is zero a buffer of at least cch items will be + * allocated to hold the translated string. If a + * buffer was requested it must be freed using + * RTStrFree(). + * @param cch The buffer size in bytes. This includes the + * terminator. + * @param pcch Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + */ +#define RTStrToLatin1Ex(pszString, cchString, ppsz, cch, pcch) \ + RTStrToLatin1ExTag((pszString), (cchString), (ppsz), (cch), (pcch), RTSTR_TAG) + +/** + * Translates pszString from UTF-8 to Latin1, allocating the result buffer if + * requested (custom tag). + * + * @returns iprt status code. + * @param pszString UTF-8 string to convert. + * @param cchString The maximum size in chars (the type) to convert. + * The conversion stop when it reaches cchString or + * the string terminator ('\\0'). Use RTSTR_MAX to + * translate the entire string. + * @param ppsz If cch is non-zero, this must either be pointing to + * pointer to a buffer of the specified size, or + * pointer to a NULL pointer. If *ppsz is NULL or cch + * is zero a buffer of at least cch items will be + * allocated to hold the translated string. If a + * buffer was requested it must be freed using + * RTStrFree(). + * @param cch The buffer size in bytes. This includes the + * terminator. + * @param pcch Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrToLatin1ExTag(const char *pszString, size_t cchString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag); + + +/** + * Translate a Latin1 string into a UTF-8 allocating the result buffer (default + * tag). + * + * @returns iprt status code. + * @param pszString Latin1 string to convert. + * @param ppszString Receives pointer of allocated UTF-8 string on + * success, and is always set to NULL on failure. + * The returned pointer must be freed using RTStrFree(). + */ +#define RTLatin1ToUtf8(pszString, ppszString) RTLatin1ToUtf8Tag((pszString), (ppszString), RTSTR_TAG) + +/** + * Translate a Latin-1 string into a UTF-8 allocating the result buffer. + * + * @returns iprt status code. + * @param pszString Latin-1 string to convert. + * @param ppszString Receives pointer of allocated UTF-8 string on + * success, and is always set to NULL on failure. + * The returned pointer must be freed using RTStrFree(). + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTLatin1ToUtf8Tag(const char *pszString, char **ppszString, const char *pszTag); + +/** + * Translates Latin-1 to UTF-8 using buffer provided by the caller or a fittingly + * sized buffer allocated by the function (default tag). + * + * @returns iprt status code. + * @param pszString The Latin-1 string to convert. + * @param cchString The number of Latin-1 characters to translate from + * pszString. The translation will stop when reaching + * cchString or the terminator ('\\0'). Use RTSTR_MAX + * to translate the entire string. + * @param ppsz If cch is non-zero, this must either be pointing to + * a pointer to a buffer of the specified size, or + * pointer to a NULL pointer. If *ppsz is NULL or cch + * is zero a buffer of at least cch chars will be + * allocated to hold the translated string. If a + * buffer was requested it must be freed using + * RTStrFree(). + * @param cch The buffer size in chars (the type). This includes the terminator. + * @param pcch Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + */ +#define RTLatin1ToUtf8Ex(pszString, cchString, ppsz, cch, pcch) \ + RTLatin1ToUtf8ExTag((pszString), (cchString), (ppsz), (cch), (pcch), RTSTR_TAG) + +/** + * Translates Latin1 to UTF-8 using buffer provided by the caller or a fittingly + * sized buffer allocated by the function (custom tag). + * + * @returns iprt status code. + * @param pszString The Latin1 string to convert. + * @param cchString The number of Latin1 characters to translate from + * pwszString. The translation will stop when + * reaching cchString or the terminator ('\\0'). Use + * RTSTR_MAX to translate the entire string. + * @param ppsz If cch is non-zero, this must either be pointing to + * a pointer to a buffer of the specified size, or + * pointer to a NULL pointer. If *ppsz is NULL or cch + * is zero a buffer of at least cch chars will be + * allocated to hold the translated string. If a + * buffer was requested it must be freed using + * RTStrFree(). + * @param cch The buffer size in chars (the type). This includes + * the terminator. + * @param pcch Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTLatin1ToUtf8ExTag(const char *pszString, size_t cchString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag); + +/** + * Calculates the length of the Latin-1 string in UTF-8 chars (bytes). + * + * The primary purpose of this function is to help allocate buffers for + * RTLatin1ToUtf8() of the correct size. For most other purposes + * RTLatin1ToUtf8Ex() should be used. + * + * @returns Number of chars (bytes). + * @returns 0 if the string was incorrectly encoded. + * @param psz The Latin-1 string. + */ +RTDECL(size_t) RTLatin1CalcUtf8Len(const char *psz); + +/** + * Calculates the length of the Latin-1 string in UTF-8 chars (bytes). + * + * @returns iprt status code. + * @param psz The string. + * @param cch The max string length. Use RTSTR_MAX to process the entire string. + * @param pcch Where to store the string length (in bytes). Optional. + * This is undefined on failure. + */ +RTDECL(int) RTLatin1CalcUtf8LenEx(const char *psz, size_t cch, size_t *pcch); + +/** + * Get the unicode code point at the given string position. + * + * @returns unicode code point. + * @returns RTUNICP_INVALID if the encoding is invalid. + * @param psz The string. + */ +RTDECL(RTUNICP) RTStrGetCpInternal(const char *psz); + +/** + * Get the unicode code point at the given string position. + * + * @returns iprt status code + * @returns VERR_INVALID_UTF8_ENCODING if the encoding is invalid. + * @param ppsz The string cursor. + * This is advanced one character forward on failure. + * @param pCp Where to store the unicode code point. + * Stores RTUNICP_INVALID if the encoding is invalid. + */ +RTDECL(int) RTStrGetCpExInternal(const char **ppsz, PRTUNICP pCp); + +/** + * Get the unicode code point at the given string position for a string of a + * given length. + * + * @returns iprt status code + * @retval VERR_INVALID_UTF8_ENCODING if the encoding is invalid. + * @retval VERR_END_OF_STRING if *pcch is 0. *pCp is set to RTUNICP_INVALID. + * + * @param ppsz The string. + * @param pcch Pointer to the length of the string. This will be + * decremented by the size of the code point. + * @param pCp Where to store the unicode code point. + * Stores RTUNICP_INVALID if the encoding is invalid. + */ +RTDECL(int) RTStrGetCpNExInternal(const char **ppsz, size_t *pcch, PRTUNICP pCp); + +/** + * Put the unicode code point at the given string position + * and return the pointer to the char following it. + * + * This function will not consider anything at or following the + * buffer area pointed to by psz. It is therefore not suitable for + * inserting code points into a string, only appending/overwriting. + * + * @returns pointer to the char following the written code point. + * @param psz The string. + * @param CodePoint The code point to write. + * This should not be RTUNICP_INVALID or any other + * character out of the UTF-8 range. + * + * @remark This is a worker function for RTStrPutCp(). + * + */ +RTDECL(char *) RTStrPutCpInternal(char *psz, RTUNICP CodePoint); + +/** + * Get the unicode code point at the given string position. + * + * @returns unicode code point. + * @returns RTUNICP_INVALID if the encoding is invalid. + * @param psz The string. + * + * @remark We optimize this operation by using an inline function for + * the most frequent and simplest sequence, the rest is + * handled by RTStrGetCpInternal(). + */ +DECLINLINE(RTUNICP) RTStrGetCp(const char *psz) +{ + const unsigned char uch = *(const unsigned char *)psz; + if (!(uch & RT_BIT(7))) + return uch; + return RTStrGetCpInternal(psz); +} + +/** + * Get the unicode code point at the given string position. + * + * @returns iprt status code. + * @param ppsz Pointer to the string pointer. This will be updated to + * point to the char following the current code point. + * This is advanced one character forward on failure. + * @param pCp Where to store the code point. + * RTUNICP_INVALID is stored here on failure. + * + * @remark We optimize this operation by using an inline function for + * the most frequent and simplest sequence, the rest is + * handled by RTStrGetCpExInternal(). + */ +DECLINLINE(int) RTStrGetCpEx(const char **ppsz, PRTUNICP pCp) +{ + const unsigned char uch = **(const unsigned char **)ppsz; + if (!(uch & RT_BIT(7))) + { + (*ppsz)++; + *pCp = uch; + return VINF_SUCCESS; + } + return RTStrGetCpExInternal(ppsz, pCp); +} + +/** + * Get the unicode code point at the given string position for a string of a + * given maximum length. + * + * @returns iprt status code. + * @retval VERR_INVALID_UTF8_ENCODING if the encoding is invalid. + * @retval VERR_END_OF_STRING if *pcch is 0. *pCp is set to RTUNICP_INVALID. + * + * @param ppsz Pointer to the string pointer. This will be updated to + * point to the char following the current code point. + * @param pcch Pointer to the maximum string length. This will be + * decremented by the size of the code point found. + * @param pCp Where to store the code point. + * RTUNICP_INVALID is stored here on failure. + * + * @remark We optimize this operation by using an inline function for + * the most frequent and simplest sequence, the rest is + * handled by RTStrGetCpNExInternal(). + */ +DECLINLINE(int) RTStrGetCpNEx(const char **ppsz, size_t *pcch, PRTUNICP pCp) +{ + if (RT_LIKELY(*pcch != 0)) + { + const unsigned char uch = **(const unsigned char **)ppsz; + if (!(uch & RT_BIT(7))) + { + (*ppsz)++; + (*pcch)--; + *pCp = uch; + return VINF_SUCCESS; + } + } + return RTStrGetCpNExInternal(ppsz, pcch, pCp); +} + +/** + * Get the UTF-8 size in characters of a given Unicode code point. + * + * The code point is expected to be a valid Unicode one, but not necessarily in + * the range supported by UTF-8. + * + * @returns The number of chars (bytes) required to encode the code point, or + * zero if there is no UTF-8 encoding. + * @param CodePoint The unicode code point. + */ +DECLINLINE(size_t) RTStrCpSize(RTUNICP CodePoint) +{ + if (CodePoint < 0x00000080) + return 1; + if (CodePoint < 0x00000800) + return 2; + if (CodePoint < 0x00010000) + return 3; +#ifdef RT_USE_RTC_3629 + if (CodePoint < 0x00011000) + return 4; +#else + if (CodePoint < 0x00200000) + return 4; + if (CodePoint < 0x04000000) + return 5; + if (CodePoint < 0x7fffffff) + return 6; +#endif + return 0; +} + +/** + * Put the unicode code point at the given string position + * and return the pointer to the char following it. + * + * This function will not consider anything at or following the + * buffer area pointed to by psz. It is therefore not suitable for + * inserting code points into a string, only appending/overwriting. + * + * @returns pointer to the char following the written code point. + * @param psz The string. + * @param CodePoint The code point to write. + * This should not be RTUNICP_INVALID or any other + * character out of the UTF-8 range. + * + * @remark We optimize this operation by using an inline function for + * the most frequent and simplest sequence, the rest is + * handled by RTStrPutCpInternal(). + */ +DECLINLINE(char *) RTStrPutCp(char *psz, RTUNICP CodePoint) +{ + if (CodePoint < 0x80) + { + *psz++ = (unsigned char)CodePoint; + return psz; + } + return RTStrPutCpInternal(psz, CodePoint); +} + +/** + * Skips ahead, past the current code point. + * + * @returns Pointer to the char after the current code point. + * @param psz Pointer to the current code point. + * @remark This will not move the next valid code point, only past the current one. + */ +DECLINLINE(char *) RTStrNextCp(const char *psz) +{ + RTUNICP Cp; + RTStrGetCpEx(&psz, &Cp); + return (char *)psz; +} + +/** + * Skips back to the previous code point. + * + * @returns Pointer to the char before the current code point. + * @returns pszStart on failure. + * @param pszStart Pointer to the start of the string. + * @param psz Pointer to the current code point. + */ +RTDECL(char *) RTStrPrevCp(const char *pszStart, const char *psz); + +/** + * Get the unicode code point at the given string position. + * + * @returns unicode code point. + * @returns RTUNICP_INVALID if the encoding is invalid. + * @param psz The string. + */ +DECLINLINE(RTUNICP) RTLatin1GetCp(const char *psz) +{ + return *(const unsigned char *)psz; +} + +/** + * Get the unicode code point at the given string position. + * + * @returns iprt status code. + * @param ppsz Pointer to the string pointer. This will be updated to + * point to the char following the current code point. + * This is advanced one character forward on failure. + * @param pCp Where to store the code point. + * RTUNICP_INVALID is stored here on failure. + * + * @remark We optimize this operation by using an inline function for + * the most frequent and simplest sequence, the rest is + * handled by RTStrGetCpExInternal(). + */ +DECLINLINE(int) RTLatin1GetCpEx(const char **ppsz, PRTUNICP pCp) +{ + const unsigned char uch = **(const unsigned char **)ppsz; + (*ppsz)++; + *pCp = uch; + return VINF_SUCCESS; +} + +/** + * Get the unicode code point at the given string position for a string of a + * given maximum length. + * + * @returns iprt status code. + * @retval VERR_END_OF_STRING if *pcch is 0. *pCp is set to RTUNICP_INVALID. + * + * @param ppsz Pointer to the string pointer. This will be updated to + * point to the char following the current code point. + * @param pcch Pointer to the maximum string length. This will be + * decremented by the size of the code point found. + * @param pCp Where to store the code point. + * RTUNICP_INVALID is stored here on failure. + */ +DECLINLINE(int) RTLatin1GetCpNEx(const char **ppsz, size_t *pcch, PRTUNICP pCp) +{ + if (RT_LIKELY(*pcch != 0)) + { + const unsigned char uch = **(const unsigned char **)ppsz; + (*ppsz)++; + (*pcch)--; + *pCp = uch; + return VINF_SUCCESS; + } + *pCp = RTUNICP_INVALID; + return VERR_END_OF_STRING; +} + +/** + * Get the Latin-1 size in characters of a given Unicode code point. + * + * The code point is expected to be a valid Unicode one, but not necessarily in + * the range supported by Latin-1. + * + * @returns the size in characters, or zero if there is no Latin-1 encoding + */ +DECLINLINE(size_t) RTLatin1CpSize(RTUNICP CodePoint) +{ + if (CodePoint < 0x100) + return 1; + return 0; +} + +/** + * Put the unicode code point at the given string position + * and return the pointer to the char following it. + * + * This function will not consider anything at or following the + * buffer area pointed to by psz. It is therefore not suitable for + * inserting code points into a string, only appending/overwriting. + * + * @returns pointer to the char following the written code point. + * @param psz The string. + * @param CodePoint The code point to write. + * This should not be RTUNICP_INVALID or any other + * character out of the Latin-1 range. + */ +DECLINLINE(char *) RTLatin1PutCp(char *psz, RTUNICP CodePoint) +{ + AssertReturn(CodePoint < 0x100, NULL); + *psz++ = (unsigned char)CodePoint; + return psz; +} + +/** + * Skips ahead, past the current code point. + * + * @returns Pointer to the char after the current code point. + * @param psz Pointer to the current code point. + * @remark This will not move the next valid code point, only past the current one. + */ +DECLINLINE(char *) RTLatin1NextCp(const char *psz) +{ + psz++; + return (char *)psz; +} + +/** + * Skips back to the previous code point. + * + * @returns Pointer to the char before the current code point. + * @returns pszStart on failure. + * @param pszStart Pointer to the start of the string. + * @param psz Pointer to the current code point. + */ +DECLINLINE(char *) RTLatin1PrevCp(const char *psz) +{ + psz--; + return (char *)psz; +} + + +/** @page pg_rt_str_format The IPRT Format Strings + * + * IPRT implements most of the commonly used format types and flags with the + * exception of floating point which is completely missing. In addition IPRT + * provides a number of IPRT specific format types for the IPRT typedefs and + * other useful things. Note that several of these extensions are similar to + * \%p and doesn't care much if you try add formating flags/width/precision. + * + * + * Group 0a, The commonly used format types: + * - \%s - Takes a pointer to a zero terminated string (UTF-8) and + * prints it with the optionally adjustment (width, -) and + * length restriction (precision). + * - \%ls - Same as \%s except that the input is UTF-16 (output UTF-8). + * - \%Ls - Same as \%s except that the input is UCS-32 (output UTF-8). + * - \%S - Same as \%s, used to convert to current codeset but this is + * now done by the streams code. Deprecated, use \%s. + * - \%lS - Ditto. Deprecated, use \%ls. + * - \%LS - Ditto. Deprecated, use \%Ls. + * - \%c - Takes a char and prints it. + * - \%d - Takes a signed integer and prints it as decimal. Thousand + * separator (\'), zero padding (0), adjustment (-+), width, + * precision + * - \%i - Same as \%d. + * - \%u - Takes an unsigned integer and prints it as decimal. Thousand + * separator (\'), zero padding (0), adjustment (-+), width, + * precision + * - \%x - Takes an unsigned integer and prints it as lowercased + * hexadecimal. The special hash (\#) flag causes a '0x' + * prefixed to be printed. Zero padding (0), adjustment (-+), + * width, precision. + * - \%X - Same as \%x except that it is uppercased. + * - \%o - Takes an unsigned (?) integer and prints it as octal. Zero + * padding (0), adjustment (-+), width, precision. + * - \%p - Takes a pointer (void technically) and prints it. Zero + * padding (0), adjustment (-+), width, precision. + * + * The \%d, \%i, \%u, \%x, \%X and \%o format types support the following + * argument type specifiers: + * - \%ll - long long (uint64_t). + * - \%L - long long (uint64_t). + * - \%l - long (uint32_t, uint64_t) + * - \%h - short (int16_t). + * - \%hh - char (int8_t). + * - \%H - char (int8_t). + * - \%z - size_t. + * - \%j - intmax_t (int64_t). + * - \%t - ptrdiff_t. + * The type in parentheses is typical sizes, however when printing those types + * you are better off using the special group 2 format types below (\%RX32 and + * such). + * + * + * Group 0b, IPRT format tricks: + * - %M - Replaces the format string, takes a string pointer. + * - %N - Nested formatting, takes a pointer to a format string + * followed by the pointer to a va_list variable. The va_list + * variable will not be modified and the caller must do va_end() + * on it. Make sure the va_list variable is NOT in a parameter + * list or some gcc versions/targets may get it all wrong. + * + * + * Group 1, the basic runtime typedefs (excluding those which obviously are + * pointer): + * - \%RTbool - Takes a bool value and prints 'true', 'false', or '!%d!'. + * - \%RTfile - Takes a #RTFILE value. + * - \%RTfmode - Takes a #RTFMODE value. + * - \%RTfoff - Takes a #RTFOFF value. + * - \%RTfp16 - Takes a #RTFAR16 value. + * - \%RTfp32 - Takes a #RTFAR32 value. + * - \%RTfp64 - Takes a #RTFAR64 value. + * - \%RTgid - Takes a #RTGID value. + * - \%RTino - Takes a #RTINODE value. + * - \%RTint - Takes a #RTINT value. + * - \%RTiop - Takes a #RTIOPORT value. + * - \%RTldrm - Takes a #RTLDRMOD value. + * - \%RTmac - Takes a #PCRTMAC pointer. + * - \%RTnaddr - Takes a #PCRTNETADDR value. + * - \%RTnaipv4 - Takes a #RTNETADDRIPV4 value. + * - \%RTnaipv6 - Takes a #PCRTNETADDRIPV6 value. + * - \%RTnthrd - Takes a #RTNATIVETHREAD value. + * - \%RTnthrd - Takes a #RTNATIVETHREAD value. + * - \%RTproc - Takes a #RTPROCESS value. + * - \%RTptr - Takes a #RTINTPTR or #RTUINTPTR value (but not void *). + * - \%RTreg - Takes a #RTCCUINTREG value. + * - \%RTsel - Takes a #RTSEL value. + * - \%RTsem - Takes a #RTSEMEVENT, #RTSEMEVENTMULTI, #RTSEMMUTEX, #RTSEMFASTMUTEX, or #RTSEMRW value. + * - \%RTsock - Takes a #RTSOCKET value. + * - \%RTthrd - Takes a #RTTHREAD value. + * - \%RTuid - Takes a #RTUID value. + * - \%RTuint - Takes a #RTUINT value. + * - \%RTunicp - Takes a #RTUNICP value. + * - \%RTutf16 - Takes a #RTUTF16 value. + * - \%RTuuid - Takes a #PCRTUUID and will print the UUID as a string. + * - \%RTxuint - Takes a #RTUINT or #RTINT value, formatting it as hex. + * - \%RGi - Takes a #RTGCINT value. + * - \%RGp - Takes a #RTGCPHYS value. + * - \%RGr - Takes a #RTGCUINTREG value. + * - \%RGu - Takes a #RTGCUINT value. + * - \%RGv - Takes a #RTGCPTR, #RTGCINTPTR or #RTGCUINTPTR value. + * - \%RGx - Takes a #RTGCUINT or #RTGCINT value, formatting it as hex. + * - \%RHi - Takes a #RTHCINT value. + * - \%RHp - Takes a #RTHCPHYS value. + * - \%RHr - Takes a #RTHCUINTREG value. + * - \%RHu - Takes a #RTHCUINT value. + * - \%RHv - Takes a #RTHCPTR, #RTHCINTPTR or #RTHCUINTPTR value. + * - \%RHx - Takes a #RTHCUINT or #RTHCINT value, formatting it as hex. + * - \%RRv - Takes a #RTRCPTR, #RTRCINTPTR or #RTRCUINTPTR value. + * - \%RCi - Takes a #RTINT value. + * - \%RCp - Takes a #RTCCPHYS value. + * - \%RCr - Takes a #RTCCUINTREG value. + * - \%RCu - Takes a #RTUINT value. + * - \%RCv - Takes a #uintptr_t, #intptr_t, void * value. + * - \%RCx - Takes a #RTUINT or #RTINT value, formatting it as hex. + * + * + * Group 2, the generic integer types which are prefered over relying on what + * bit-count a 'long', 'short', or 'long long' has on a platform. This are + * highly prefered for the [u]intXX_t kind of types: + * - \%RI[8|16|32|64] - Signed integer value of the specifed bit count. + * - \%RU[8|16|32|64] - Unsigned integer value of the specifed bit count. + * - \%RX[8|16|32|64] - Hexadecimal integer value of the specifed bit count. + * + * + * Group 3, hex dumpers and other complex stuff which requires more than simple + * formatting: + * - \%Rhxd - Takes a pointer to the memory which is to be dumped in typical + * hex format. Use the precision to specify the length, and the width to + * set the number of bytes per line. Default width and precision is 16. + * - \%Rhxs - Takes a pointer to the memory to be displayed as a hex string, + * i.e. a series of space separated bytes formatted as two digit hex value. + * Use the precision to specify the length. Default length is 16 bytes. + * The width, if specified, is ignored. + * - \%Rrc - Takes an integer iprt status code as argument. Will insert the + * status code define corresponding to the iprt status code. + * - \%Rrs - Takes an integer iprt status code as argument. Will insert the + * short description of the specified status code. + * - \%Rrf - Takes an integer iprt status code as argument. Will insert the + * full description of the specified status code. + * - \%Rra - Takes an integer iprt status code as argument. Will insert the + * status code define + full description. + * - \%Rwc - Takes a long Windows error code as argument. Will insert the status + * code define corresponding to the Windows error code. + * - \%Rwf - Takes a long Windows error code as argument. Will insert the + * full description of the specified status code. + * - \%Rwa - Takes a long Windows error code as argument. Will insert the + * error code define + full description. + * + * - \%Rhrc - Takes a COM/XPCOM status code as argument. Will insert the status + * code define corresponding to the Windows error code. + * - \%Rhrf - Takes a COM/XPCOM status code as argument. Will insert the + * full description of the specified status code. + * - \%Rhra - Takes a COM/XPCOM error code as argument. Will insert the + * error code define + full description. + * + * - \%Rfn - Pretty printing of a function or method. It drops the + * return code and parameter list. + * - \%Rbn - Prints the base name. For dropping the path in + * order to save space when printing a path name. + * + * On other platforms, \%Rw? simply prints the argument in a form of 0xXXXXXXXX. + * + * + * Group 4, structure dumpers: + * - \%RDtimespec - Takes a PCRTTIMESPEC. + * + * + * Group 5, XML / HTML escapers: + * - \%RMas - Takes a string pointer (const char *) and outputs + * it as an attribute value with the proper escaping. + * This typically ends up in double quotes. + * + * - \%RMes - Takes a string pointer (const char *) and outputs + * it as an element with the necessary escaping. + * + * Group 6, CPU Architecture Register dumpers: + * - \%RAx86[reg] - Takes a 64-bit register value if the register is + * 64-bit or smaller. Check the code wrt which + * registers are implemented. + * + */ + +#ifndef DECLARED_FNRTSTROUTPUT /* duplicated in iprt/log.h */ +# define DECLARED_FNRTSTROUTPUT +/** + * Output callback. + * + * @returns number of bytes written. + * @param pvArg User argument. + * @param pachChars Pointer to an array of utf-8 characters. + * @param cbChars Number of bytes in the character array pointed to by pachChars. + */ +typedef DECLCALLBACK(size_t) FNRTSTROUTPUT(void *pvArg, const char *pachChars, size_t cbChars); +/** Pointer to callback function. */ +typedef FNRTSTROUTPUT *PFNRTSTROUTPUT; +#endif + +/** Format flag. + * These are used by RTStrFormat extensions and RTStrFormatNumber, mind + * that not all flags makes sense to both of the functions. + * @{ */ +#define RTSTR_F_CAPITAL 0x0001 +#define RTSTR_F_LEFT 0x0002 +#define RTSTR_F_ZEROPAD 0x0004 +#define RTSTR_F_SPECIAL 0x0008 +#define RTSTR_F_VALSIGNED 0x0010 +#define RTSTR_F_PLUS 0x0020 +#define RTSTR_F_BLANK 0x0040 +#define RTSTR_F_WIDTH 0x0080 +#define RTSTR_F_PRECISION 0x0100 +#define RTSTR_F_THOUSAND_SEP 0x0200 + +#define RTSTR_F_BIT_MASK 0xf800 +#define RTSTR_F_8BIT 0x0800 +#define RTSTR_F_16BIT 0x1000 +#define RTSTR_F_32BIT 0x2000 +#define RTSTR_F_64BIT 0x4000 +#define RTSTR_F_128BIT 0x8000 +/** @} */ + +/** @def RTSTR_GET_BIT_FLAG + * Gets the bit flag for the specified type. + */ +#define RTSTR_GET_BIT_FLAG(type) \ + ( sizeof(type) * 8 == 32 ? RTSTR_F_32BIT \ + : sizeof(type) * 8 == 64 ? RTSTR_F_64BIT \ + : sizeof(type) * 8 == 16 ? RTSTR_F_16BIT \ + : sizeof(type) * 8 == 8 ? RTSTR_F_8BIT \ + : sizeof(type) * 8 == 128 ? RTSTR_F_128BIT \ + : 0) + + +/** + * Callback to format non-standard format specifiers. + * + * @returns The number of bytes formatted. + * @param pvArg Formatter argument. + * @param pfnOutput Pointer to output function. + * @param pvArgOutput Argument for the output function. + * @param ppszFormat Pointer to the format string pointer. Advance this till the char + * after the format specifier. + * @param pArgs Pointer to the argument list. Use this to fetch the arguments. + * @param cchWidth Format Width. -1 if not specified. + * @param cchPrecision Format Precision. -1 if not specified. + * @param fFlags Flags (RTSTR_NTFS_*). + * @param chArgSize The argument size specifier, 'l' or 'L'. + */ +typedef DECLCALLBACK(size_t) FNSTRFORMAT(void *pvArg, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, + const char **ppszFormat, va_list *pArgs, int cchWidth, + int cchPrecision, unsigned fFlags, char chArgSize); +/** Pointer to a FNSTRFORMAT() function. */ +typedef FNSTRFORMAT *PFNSTRFORMAT; + + +/** + * Partial implementation of a printf like formatter. + * It doesn't do everything correct, and there is no floating point support. + * However, it supports custom formats by the means of a format callback. + * + * @returns number of bytes formatted. + * @param pfnOutput Output worker. + * Called in two ways. Normally with a string and its length. + * For termination, it's called with NULL for string, 0 for length. + * @param pvArgOutput Argument to the output worker. + * @param pfnFormat Custom format worker. + * @param pvArgFormat Argument to the format worker. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param InArgs Argument list. + */ +RTDECL(size_t) RTStrFormatV(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PFNSTRFORMAT pfnFormat, void *pvArgFormat, const char *pszFormat, va_list InArgs); + +/** + * Partial implementation of a printf like formatter. + * It doesn't do everything correct, and there is no floating point support. + * However, it supports custom formats by the means of a format callback. + * + * @returns number of bytes formatted. + * @param pfnOutput Output worker. + * Called in two ways. Normally with a string and its length. + * For termination, it's called with NULL for string, 0 for length. + * @param pvArgOutput Argument to the output worker. + * @param pfnFormat Custom format worker. + * @param pvArgFormat Argument to the format worker. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param ... Argument list. + */ +RTDECL(size_t) RTStrFormat(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, PFNSTRFORMAT pfnFormat, void *pvArgFormat, const char *pszFormat, ...); + +/** + * Formats an integer number according to the parameters. + * + * @returns Length of the formatted number. + * @param psz Pointer to output string buffer of sufficient size. + * @param u64Value Value to format. + * @param uiBase Number representation base. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags, RTSTR_F_XXX. + */ +RTDECL(int) RTStrFormatNumber(char *psz, uint64_t u64Value, unsigned int uiBase, signed int cchWidth, signed int cchPrecision, unsigned int fFlags); + +/** + * Formats an unsigned 8-bit number. + * + * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param u8Value The value to format. + * @param uiBase Number representation base. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags, RTSTR_F_XXX. + */ +RTDECL(ssize_t) RTStrFormatU8(char *pszBuf, size_t cbBuf, uint8_t u8Value, unsigned int uiBase, + signed int cchWidth, signed int cchPrecision, uint32_t fFlags); + +/** + * Formats an unsigned 16-bit number. + * + * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param u16Value The value to format. + * @param uiBase Number representation base. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags, RTSTR_F_XXX. + */ +RTDECL(ssize_t) RTStrFormatU16(char *pszBuf, size_t cbBuf, uint16_t u16Value, unsigned int uiBase, + signed int cchWidth, signed int cchPrecision, uint32_t fFlags); + +/** + * Formats an unsigned 32-bit number. + * + * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param u32Value The value to format. + * @param uiBase Number representation base. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags, RTSTR_F_XXX. + */ +RTDECL(ssize_t) RTStrFormatU32(char *pszBuf, size_t cbBuf, uint32_t u32Value, unsigned int uiBase, + signed int cchWidth, signed int cchPrecision, uint32_t fFlags); + +/** + * Formats an unsigned 64-bit number. + * + * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param u64Value The value to format. + * @param uiBase Number representation base. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags, RTSTR_F_XXX. + */ +RTDECL(ssize_t) RTStrFormatU64(char *pszBuf, size_t cbBuf, uint64_t u64Value, unsigned int uiBase, + signed int cchWidth, signed int cchPrecision, uint32_t fFlags); + +/** + * Formats an unsigned 128-bit number. + * + * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param pu128Value The value to format. + * @param uiBase Number representation base. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags, RTSTR_F_XXX. + */ +RTDECL(ssize_t) RTStrFormatU128(char *pszBuf, size_t cbBuf, PCRTUINT128U pu128Value, unsigned int uiBase, + signed int cchWidth, signed int cchPrecision, uint32_t fFlags); + +/** + * Formats an 80-bit extended floating point number. + * + * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param pr80Value The value to format. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags, RTSTR_F_XXX. + */ +RTDECL(ssize_t) RTStrFormatR80(char *pszBuf, size_t cbBuf, PCRTFLOAT80U pr80Value, signed int cchWidth, + signed int cchPrecision, uint32_t fFlags); + +/** + * Formats an 80-bit extended floating point number, version 2. + * + * @returns The length of the formatted number or VERR_BUFFER_OVERFLOW. + * @param pszBuf The output buffer. + * @param cbBuf The size of the output buffer. + * @param pr80Value The value to format. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags, RTSTR_F_XXX. + */ +RTDECL(ssize_t) RTStrFormatR80u2(char *pszBuf, size_t cbBuf, PCRTFLOAT80U2 pr80Value, signed int cchWidth, + signed int cchPrecision, uint32_t fFlags); + + + +/** + * Callback for formatting a type. + * + * This is registered using the RTStrFormatTypeRegister function and will + * be called during string formatting to handle the specified %R[type]. + * The argument for this format type is assumed to be a pointer and it's + * passed in the @a pvValue argument. + * + * @returns Length of the formatted output. + * @param pfnOutput Output worker. + * @param pvArgOutput Argument to the output worker. + * @param pszType The type name. + * @param pvValue The argument value. + * @param cchWidth Width. + * @param cchPrecision Precision. + * @param fFlags Flags (NTFS_*). + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(size_t) FNRTSTRFORMATTYPE(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, + const char *pszType, void const *pvValue, + int cchWidth, int cchPrecision, unsigned fFlags, + void *pvUser); +/** Pointer to a FNRTSTRFORMATTYPE. */ +typedef FNRTSTRFORMATTYPE *PFNRTSTRFORMATTYPE; + + +/** + * Register a format handler for a type. + * + * The format handler is used to handle '%R[type]' format types, where the argument + * in the vector is a pointer value (a bit restrictive, but keeps it simple). + * + * The caller must ensure that no other thread will be making use of any of + * the dynamic formatting type facilities simultaneously with this call. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_ALREADY_EXISTS if the type has already been registered. + * @retval VERR_TOO_MANY_OPEN_FILES if all the type slots has been allocated already. + * + * @param pszType The type name. + * @param pfnHandler The handler address. See FNRTSTRFORMATTYPE for details. + * @param pvUser The user argument to pass to the handler. See RTStrFormatTypeSetUser + * for how to update this later. + */ +RTDECL(int) RTStrFormatTypeRegister(const char *pszType, PFNRTSTRFORMATTYPE pfnHandler, void *pvUser); + +/** + * Deregisters a format type. + * + * The caller must ensure that no other thread will be making use of any of + * the dynamic formatting type facilities simultaneously with this call. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_FILE_NOT_FOUND if not found. + * + * @param pszType The type to deregister. + */ +RTDECL(int) RTStrFormatTypeDeregister(const char *pszType); + +/** + * Sets the user argument for a type. + * + * This can be used if a user argument needs relocating in GC. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_FILE_NOT_FOUND if not found. + * + * @param pszType The type to update. + * @param pvUser The new user argument value. + */ +RTDECL(int) RTStrFormatTypeSetUser(const char *pszType, void *pvUser); + + +/** + * String printf. + * + * @returns The length of the returned string (in pszBuffer) excluding the + * terminator. + * @param pszBuffer Output buffer. + * @param cchBuffer Size of the output buffer. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param args The format argument. + */ +RTDECL(size_t) RTStrPrintfV(char *pszBuffer, size_t cchBuffer, const char *pszFormat, va_list args); + +/** + * String printf. + * + * @returns The length of the returned string (in pszBuffer) excluding the + * terminator. + * @param pszBuffer Output buffer. + * @param cchBuffer Size of the output buffer. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param ... The format argument. + */ +RTDECL(size_t) RTStrPrintf(char *pszBuffer, size_t cchBuffer, const char *pszFormat, ...); + + +/** + * String printf with custom formatting. + * + * @returns The length of the returned string (in pszBuffer) excluding the + * terminator. + * @param pfnFormat Pointer to handler function for the custom formats. + * @param pvArg Argument to the pfnFormat function. + * @param pszBuffer Output buffer. + * @param cchBuffer Size of the output buffer. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param args The format argument. + */ +RTDECL(size_t) RTStrPrintfExV(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer, const char *pszFormat, va_list args); + +/** + * String printf with custom formatting. + * + * @returns The length of the returned string (in pszBuffer) excluding the + * terminator. + * @param pfnFormat Pointer to handler function for the custom formats. + * @param pvArg Argument to the pfnFormat function. + * @param pszBuffer Output buffer. + * @param cchBuffer Size of the output buffer. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param ... The format argument. + */ +RTDECL(size_t) RTStrPrintfEx(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer, const char *pszFormat, ...); + + +/** + * Allocating string printf (default tag). + * + * @returns The length of the string in the returned *ppszBuffer excluding the + * terminator. + * @returns -1 on failure. + * @param ppszBuffer Where to store the pointer to the allocated output buffer. + * The buffer should be freed using RTStrFree(). + * On failure *ppszBuffer will be set to NULL. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param args The format argument. + */ +#define RTStrAPrintfV(ppszBuffer, pszFormat, args) RTStrAPrintfVTag((ppszBuffer), (pszFormat), (args), RTSTR_TAG) + +/** + * Allocating string printf (custom tag). + * + * @returns The length of the string in the returned *ppszBuffer excluding the + * terminator. + * @returns -1 on failure. + * @param ppszBuffer Where to store the pointer to the allocated output buffer. + * The buffer should be freed using RTStrFree(). + * On failure *ppszBuffer will be set to NULL. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param args The format argument. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTStrAPrintfVTag(char **ppszBuffer, const char *pszFormat, va_list args, const char *pszTag); + +/** + * Allocating string printf. + * + * @returns The length of the string in the returned *ppszBuffer excluding the + * terminator. + * @returns -1 on failure. + * @param ppszBuffer Where to store the pointer to the allocated output buffer. + * The buffer should be freed using RTStrFree(). + * On failure *ppszBuffer will be set to NULL. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param ... The format argument. + */ +DECLINLINE(int) RTStrAPrintf(char **ppszBuffer, const char *pszFormat, ...) +{ + int cbRet; + va_list va; + va_start(va, pszFormat); + cbRet = RTStrAPrintfVTag(ppszBuffer, pszFormat, va, RTSTR_TAG); + va_end(va); + return cbRet; +} + +/** + * Allocating string printf (custom tag). + * + * @returns The length of the string in the returned *ppszBuffer excluding the + * terminator. + * @returns -1 on failure. + * @param ppszBuffer Where to store the pointer to the allocated output buffer. + * The buffer should be freed using RTStrFree(). + * On failure *ppszBuffer will be set to NULL. + * @param pszTag Allocation tag used for statistics and such. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param ... The format argument. + */ +DECLINLINE(int) RTStrAPrintfTag(char **ppszBuffer, const char *pszTag, const char *pszFormat, ...) +{ + int cbRet; + va_list va; + va_start(va, pszFormat); + cbRet = RTStrAPrintfVTag(ppszBuffer, pszFormat, va, pszTag); + va_end(va); + return cbRet; +} + +/** + * Allocating string printf, version 2. + * + * @returns Formatted string. Use RTStrFree() to free it. NULL when out of + * memory. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param args The format argument. + */ +#define RTStrAPrintf2V(pszFormat, args) RTStrAPrintf2VTag((pszFormat), (args), RTSTR_TAG) + +/** + * Allocating string printf, version 2. + * + * @returns Formatted string. Use RTStrFree() to free it. NULL when out of + * memory. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param args The format argument. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(char *) RTStrAPrintf2VTag(const char *pszFormat, va_list args, const char *pszTag); + +/** + * Allocating string printf, version 2 (default tag). + * + * @returns Formatted string. Use RTStrFree() to free it. NULL when out of + * memory. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param ... The format argument. + */ +DECLINLINE(char *) RTStrAPrintf2(const char *pszFormat, ...) +{ + char *pszRet; + va_list va; + va_start(va, pszFormat); + pszRet = RTStrAPrintf2VTag(pszFormat, va, RTSTR_TAG); + va_end(va); + return pszRet; +} + +/** + * Allocating string printf, version 2 (custom tag). + * + * @returns Formatted string. Use RTStrFree() to free it. NULL when out of + * memory. + * @param pszTag Allocation tag used for statistics and such. + * @param pszFormat Pointer to the format string, @see pg_rt_str_format. + * @param ... The format argument. + */ +DECLINLINE(char *) RTStrAPrintf2Tag(const char *pszTag, const char *pszFormat, ...) +{ + char *pszRet; + va_list va; + va_start(va, pszFormat); + pszRet = RTStrAPrintf2VTag(pszFormat, va, pszTag); + va_end(va); + return pszRet; +} + +/** + * Strips blankspaces from both ends of the string. + * + * @returns Pointer to first non-blank char in the string. + * @param psz The string to strip. + */ +RTDECL(char *) RTStrStrip(char *psz); + +/** + * Strips blankspaces from the start of the string. + * + * @returns Pointer to first non-blank char in the string. + * @param psz The string to strip. + */ +RTDECL(char *) RTStrStripL(const char *psz); + +/** + * Strips blankspaces from the end of the string. + * + * @returns psz. + * @param psz The string to strip. + */ +RTDECL(char *) RTStrStripR(char *psz); + +/** + * String copy with overflow handling. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the destination buffer is too small. The + * buffer will contain as much of the string as it can hold, fully + * terminated. + * + * @param pszDst The destination buffer. + * @param cbDst The size of the destination buffer (in bytes). + * @param pszSrc The source string. NULL is not OK. + */ +RTDECL(int) RTStrCopy(char *pszDst, size_t cbDst, const char *pszSrc); + +/** + * String copy with overflow handling. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the destination buffer is too small. The + * buffer will contain as much of the string as it can hold, fully + * terminated. + * + * @param pszDst The destination buffer. + * @param cbDst The size of the destination buffer (in bytes). + * @param pszSrc The source string. NULL is not OK. + * @param cchSrcMax The maximum number of chars (not code points) to + * copy from the source string, not counting the + * terminator as usual. + */ +RTDECL(int) RTStrCopyEx(char *pszDst, size_t cbDst, const char *pszSrc, size_t cchSrcMax); + +/** + * String copy with overflow handling and buffer advancing. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the destination buffer is too small. The + * buffer will contain as much of the string as it can hold, fully + * terminated. + * + * @param ppszDst Pointer to the destination buffer pointer. + * This will be advanced to the end of the copied + * bytes (points at the terminator). This is also + * updated on overflow. + * @param pcbDst Pointer to the destination buffer size + * variable. This will be updated in accord with + * the buffer pointer. + * @param pszSrc The source string. NULL is not OK. + */ +RTDECL(int) RTStrCopyP(char **ppszDst, size_t *pcbDst, const char *pszSrc); + +/** + * String copy with overflow handling. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the destination buffer is too small. The + * buffer will contain as much of the string as it can hold, fully + * terminated. + * + * @param ppszDst Pointer to the destination buffer pointer. + * This will be advanced to the end of the copied + * bytes (points at the terminator). This is also + * updated on overflow. + * @param pcbDst Pointer to the destination buffer size + * variable. This will be updated in accord with + * the buffer pointer. + * @param pszSrc The source string. NULL is not OK. + * @param cchSrcMax The maximum number of chars (not code points) to + * copy from the source string, not counting the + * terminator as usual. + */ +RTDECL(int) RTStrCopyPEx(char **ppszDst, size_t *pcbDst, const char *pszSrc, size_t cchSrcMax); + +/** + * String concatenation with overflow handling. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the destination buffer is too small. The + * buffer will contain as much of the string as it can hold, fully + * terminated. + * + * @param pszDst The destination buffer. + * @param cbDst The size of the destination buffer (in bytes). + * @param pszSrc The source string. NULL is not OK. + */ +RTDECL(int) RTStrCat(char *pszDst, size_t cbDst, const char *pszSrc); + +/** + * String concatenation with overflow handling. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the destination buffer is too small. The + * buffer will contain as much of the string as it can hold, fully + * terminated. + * + * @param pszDst The destination buffer. + * @param cbDst The size of the destination buffer (in bytes). + * @param pszSrc The source string. NULL is not OK. + * @param cchSrcMax The maximum number of chars (not code points) to + * copy from the source string, not counting the + * terminator as usual. + */ +RTDECL(int) RTStrCatEx(char *pszDst, size_t cbDst, const char *pszSrc, size_t cchSrcMax); + +/** + * String concatenation with overflow handling. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the destination buffer is too small. The + * buffer will contain as much of the string as it can hold, fully + * terminated. + * + * @param ppszDst Pointer to the destination buffer pointer. + * This will be advanced to the end of the copied + * bytes (points at the terminator). This is also + * updated on overflow. + * @param pcbDst Pointer to the destination buffer size + * variable. This will be updated in accord with + * the buffer pointer. + * @param pszSrc The source string. NULL is not OK. + */ +RTDECL(int) RTStrCatP(char **ppszDst, size_t *pcbDst, const char *pszSrc); + +/** + * String concatenation with overflow handling and buffer advancing. + * + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the destination buffer is too small. The + * buffer will contain as much of the string as it can hold, fully + * terminated. + * + * @param ppszDst Pointer to the destination buffer pointer. + * This will be advanced to the end of the copied + * bytes (points at the terminator). This is also + * updated on overflow. + * @param pcbDst Pointer to the destination buffer size + * variable. This will be updated in accord with + * the buffer pointer. + * @param pszSrc The source string. NULL is not OK. + * @param cchSrcMax The maximum number of chars (not code points) to + * copy from the source string, not counting the + * terminator as usual. + */ +RTDECL(int) RTStrCatPEx(char **ppszDst, size_t *pcbDst, const char *pszSrc, size_t cchSrcMax); + +/** + * Performs a case sensitive string compare between two UTF-8 strings. + * + * Encoding errors are ignored by the current implementation. So, the only + * difference between this and the CRT strcmp function is the handling of + * NULL arguments. + * + * @returns < 0 if the first string less than the second string. + * @returns 0 if the first string identical to the second string. + * @returns > 0 if the first string greater than the second string. + * @param psz1 First UTF-8 string. Null is allowed. + * @param psz2 Second UTF-8 string. Null is allowed. + */ +RTDECL(int) RTStrCmp(const char *psz1, const char *psz2); + +/** + * Performs a case sensitive string compare between two UTF-8 strings, given + * a maximum string length. + * + * Encoding errors are ignored by the current implementation. So, the only + * difference between this and the CRT strncmp function is the handling of + * NULL arguments. + * + * @returns < 0 if the first string less than the second string. + * @returns 0 if the first string identical to the second string. + * @returns > 0 if the first string greater than the second string. + * @param psz1 First UTF-8 string. Null is allowed. + * @param psz2 Second UTF-8 string. Null is allowed. + * @param cchMax The maximum string length + */ +RTDECL(int) RTStrNCmp(const char *psz1, const char *psz2, size_t cchMax); + +/** + * Performs a case insensitive string compare between two UTF-8 strings. + * + * This is a simplified compare, as only the simplified lower/upper case folding + * specified by the unicode specs are used. It does not consider character pairs + * as they are used in some languages, just simple upper & lower case compares. + * + * The result is the difference between the mismatching codepoints after they + * both have been lower cased. + * + * If the string encoding is invalid the function will assert (strict builds) + * and use RTStrCmp for the remainder of the string. + * + * @returns < 0 if the first string less than the second string. + * @returns 0 if the first string identical to the second string. + * @returns > 0 if the first string greater than the second string. + * @param psz1 First UTF-8 string. Null is allowed. + * @param psz2 Second UTF-8 string. Null is allowed. + */ +RTDECL(int) RTStrICmp(const char *psz1, const char *psz2); + +/** + * Performs a case insensitive string compare between two UTF-8 strings, given a + * maximum string length. + * + * This is a simplified compare, as only the simplified lower/upper case folding + * specified by the unicode specs are used. It does not consider character pairs + * as they are used in some languages, just simple upper & lower case compares. + * + * The result is the difference between the mismatching codepoints after they + * both have been lower cased. + * + * If the string encoding is invalid the function will assert (strict builds) + * and use RTStrCmp for the remainder of the string. + * + * @returns < 0 if the first string less than the second string. + * @returns 0 if the first string identical to the second string. + * @returns > 0 if the first string greater than the second string. + * @param psz1 First UTF-8 string. Null is allowed. + * @param psz2 Second UTF-8 string. Null is allowed. + * @param cchMax Maximum string length + */ +RTDECL(int) RTStrNICmp(const char *psz1, const char *psz2, size_t cchMax); + +/** + * Locates a case sensitive substring. + * + * If any of the two strings are NULL, then NULL is returned. If the needle is + * an empty string, then the haystack is returned (i.e. matches anything). + * + * @returns Pointer to the first occurrence of the substring if found, NULL if + * not. + * + * @param pszHaystack The string to search. + * @param pszNeedle The substring to search for. + * + * @remarks The difference between this and strstr is the handling of NULL + * pointers. + */ +RTDECL(char *) RTStrStr(const char *pszHaystack, const char *pszNeedle); + +/** + * Locates a case insensitive substring. + * + * If any of the two strings are NULL, then NULL is returned. If the needle is + * an empty string, then the haystack is returned (i.e. matches anything). + * + * @returns Pointer to the first occurrence of the substring if found, NULL if + * not. + * + * @param pszHaystack The string to search. + * @param pszNeedle The substring to search for. + * + */ +RTDECL(char *) RTStrIStr(const char *pszHaystack, const char *pszNeedle); + +/** + * Converts the string to lower case. + * + * @returns Pointer to the converted string. + * @param psz The string to convert. + */ +RTDECL(char *) RTStrToLower(char *psz); + +/** + * Converts the string to upper case. + * + * @returns Pointer to the converted string. + * @param psz The string to convert. + */ +RTDECL(char *) RTStrToUpper(char *psz); + +/** + * Find the length of a zero-terminated byte string, given + * a max string length. + * + * See also RTStrNLenEx. + * + * @returns The string length or cbMax. The returned length does not include + * the zero terminator if it was found. + * + * @param pszString The string. + * @param cchMax The max string length. + */ +RTDECL(size_t) RTStrNLen(const char *pszString, size_t cchMax); + +/** + * Find the length of a zero-terminated byte string, given + * a max string length. + * + * See also RTStrNLen. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if the string has a length less than cchMax. + * @retval VERR_BUFFER_OVERFLOW if the end of the string wasn't found + * before cchMax was reached. + * + * @param pszString The string. + * @param cchMax The max string length. + * @param pcch Where to store the string length excluding the + * terminator. This is set to cchMax if the terminator + * isn't found. + */ +RTDECL(int) RTStrNLenEx(const char *pszString, size_t cchMax, size_t *pcch); + +RT_C_DECLS_END + +/** The maximum size argument of a memchr call. */ +#define RTSTR_MEMCHR_MAX ((~(size_t)0 >> 1) - 15) + +/** + * Find the zero terminator in a string with a limited length. + * + * @returns Pointer to the zero terminator. + * @returns NULL if the zero terminator was not found. + * + * @param pszString The string. + * @param cchMax The max string length. RTSTR_MAX is fine. + */ +#if defined(__cplusplus) && !defined(DOXYGEN_RUNNING) +DECLINLINE(char const *) RTStrEnd(char const *pszString, size_t cchMax) +{ + /* Avoid potential issues with memchr seen in glibc. + * See sysdeps/x86_64/memchr.S in glibc versions older than 2.11 */ + while (cchMax > RTSTR_MEMCHR_MAX) + { + char const *pszRet = (char const *)memchr(pszString, '\0', RTSTR_MEMCHR_MAX); + if (RT_LIKELY(pszRet)) + return pszRet; + pszString += RTSTR_MEMCHR_MAX; + cchMax -= RTSTR_MEMCHR_MAX; + } + return (char const *)memchr(pszString, '\0', cchMax); +} + +DECLINLINE(char *) RTStrEnd(char *pszString, size_t cchMax) +#else +DECLINLINE(char *) RTStrEnd(const char *pszString, size_t cchMax) +#endif +{ + /* Avoid potential issues with memchr seen in glibc. + * See sysdeps/x86_64/memchr.S in glibc versions older than 2.11 */ + while (cchMax > RTSTR_MEMCHR_MAX) + { + char *pszRet = (char *)memchr(pszString, '\0', RTSTR_MEMCHR_MAX); + if (RT_LIKELY(pszRet)) + return pszRet; + pszString += RTSTR_MEMCHR_MAX; + cchMax -= RTSTR_MEMCHR_MAX; + } + return (char *)memchr(pszString, '\0', cchMax); +} + +RT_C_DECLS_BEGIN + +/** + * Matches a simple string pattern. + * + * @returns true if the string matches the pattern, otherwise false. + * + * @param pszPattern The pattern. Special chars are '*' and '?', where the + * asterisk matches zero or more characters and question + * mark matches exactly one character. + * @param pszString The string to match against the pattern. + */ +RTDECL(bool) RTStrSimplePatternMatch(const char *pszPattern, const char *pszString); + +/** + * Matches a simple string pattern, neither which needs to be zero terminated. + * + * This is identical to RTStrSimplePatternMatch except that you can optionally + * specify the length of both the pattern and the string. The function will + * stop when it hits a string terminator or either of the lengths. + * + * @returns true if the string matches the pattern, otherwise false. + * + * @param pszPattern The pattern. Special chars are '*' and '?', where the + * asterisk matches zero or more characters and question + * mark matches exactly one character. + * @param cchPattern The pattern length. Pass RTSTR_MAX if you don't know the + * length and wish to stop at the string terminator. + * @param pszString The string to match against the pattern. + * @param cchString The string length. Pass RTSTR_MAX if you don't know the + * length and wish to match up to the string terminator. + */ +RTDECL(bool) RTStrSimplePatternNMatch(const char *pszPattern, size_t cchPattern, + const char *pszString, size_t cchString); + +/** + * Matches multiple patterns against a string. + * + * The patterns are separated by the pipe character (|). + * + * @returns true if the string matches the pattern, otherwise false. + * + * @param pszPatterns The patterns. + * @param cchPatterns The lengths of the patterns to use. Pass RTSTR_MAX to + * stop at the terminator. + * @param pszString The string to match against the pattern. + * @param cchString The string length. Pass RTSTR_MAX stop stop at the + * terminator. + * @param poffPattern Offset into the patterns string of the patttern that + * matched. If no match, this will be set to RTSTR_MAX. + * This is optional, NULL is fine. + */ +RTDECL(bool) RTStrSimplePatternMultiMatch(const char *pszPatterns, size_t cchPatterns, + const char *pszString, size_t cchString, + size_t *poffPattern); + +/** + * Compares two version strings RTStrICmp fashion. + * + * The version string is split up into sections at punctuation, spaces, + * underscores, dashes and plus signs. The sections are then split up into + * numeric and string sub-sections. Finally, the sub-sections are compared + * in a numeric or case insesntivie fashion depending on what they are. + * + * The following strings are considered to be equal: "1.0.0", "1.00.0", "1.0", + * "1". These aren't: "1.0.0r993", "1.0", "1.0r993", "1.0_Beta3", "1.1" + * + * @returns < 0 if the first string less than the second string. + * @returns 0 if the first string identical to the second string. + * @returns > 0 if the first string greater than the second string. + * + * @param pszVer1 First version string to compare. + * @param pszVer2 Second version string to compare first version with. + */ +RTDECL(int) RTStrVersionCompare(const char *pszVer1, const char *pszVer2); + + +/** @defgroup rt_str_conv String To/From Number Conversions + * @ingroup grp_rt_str + * @{ */ + +/** + * Converts a string representation of a number to a 64-bit unsigned number. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_NEGATIVE_UNSIGNED + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param ppszNext Where to store the pointer to the first char following the number. (Optional) + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pu64 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint64_t *pu64); + +/** + * Converts a string representation of a number to a 64-bit unsigned number, + * making sure the full string is converted. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_NEGATIVE_UNSIGNED + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * @retval VERR_TRAILING_SPACES + * @retval VERR_TRAILING_CHARS + * + * @param pszValue Pointer to the string value. + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pu64 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBase, uint64_t *pu64); + +/** + * Converts a string representation of a number to a 64-bit unsigned number. + * The base is guessed. + * + * @returns 64-bit unsigned number on success. + * @returns 0 on failure. + * @param pszValue Pointer to the string value. + */ +RTDECL(uint64_t) RTStrToUInt64(const char *pszValue); + +/** + * Converts a string representation of a number to a 32-bit unsigned number. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_NEGATIVE_UNSIGNED + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param ppszNext Where to store the pointer to the first char following the number. (Optional) + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pu32 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32); + +/** + * Converts a string representation of a number to a 32-bit unsigned number, + * making sure the full string is converted. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_NEGATIVE_UNSIGNED + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * @retval VERR_TRAILING_SPACES + * @retval VERR_TRAILING_CHARS + * + * @param pszValue Pointer to the string value. + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pu32 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBase, uint32_t *pu32); + +/** + * Converts a string representation of a number to a 64-bit unsigned number. + * The base is guessed. + * + * @returns 32-bit unsigned number on success. + * @returns 0 on failure. + * @param pszValue Pointer to the string value. + */ +RTDECL(uint32_t) RTStrToUInt32(const char *pszValue); + +/** + * Converts a string representation of a number to a 16-bit unsigned number. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_NEGATIVE_UNSIGNED + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param ppszNext Where to store the pointer to the first char following the number. (Optional) + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pu16 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint16_t *pu16); + +/** + * Converts a string representation of a number to a 16-bit unsigned number, + * making sure the full string is converted. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_NEGATIVE_UNSIGNED + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * @retval VERR_TRAILING_SPACES + * @retval VERR_TRAILING_CHARS + * + * @param pszValue Pointer to the string value. + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pu16 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBase, uint16_t *pu16); + +/** + * Converts a string representation of a number to a 16-bit unsigned number. + * The base is guessed. + * + * @returns 16-bit unsigned number on success. + * @returns 0 on failure. + * @param pszValue Pointer to the string value. + */ +RTDECL(uint16_t) RTStrToUInt16(const char *pszValue); + +/** + * Converts a string representation of a number to a 8-bit unsigned number. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_NEGATIVE_UNSIGNED + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param ppszNext Where to store the pointer to the first char following the number. (Optional) + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pu8 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint8_t *pu8); + +/** + * Converts a string representation of a number to a 8-bit unsigned number, + * making sure the full string is converted. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_NEGATIVE_UNSIGNED + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * @retval VERR_TRAILING_SPACES + * @retval VERR_TRAILING_CHARS + * + * @param pszValue Pointer to the string value. + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pu8 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBase, uint8_t *pu8); + +/** + * Converts a string representation of a number to a 8-bit unsigned number. + * The base is guessed. + * + * @returns 8-bit unsigned number on success. + * @returns 0 on failure. + * @param pszValue Pointer to the string value. + */ +RTDECL(uint8_t) RTStrToUInt8(const char *pszValue); + +/** + * Converts a string representation of a number to a 64-bit signed number. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param ppszNext Where to store the pointer to the first char following the number. (Optional) + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pi64 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, int64_t *pi64); + +/** + * Converts a string representation of a number to a 64-bit signed number, + * making sure the full string is converted. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VINF_SUCCESS + * @retval VERR_TRAILING_CHARS + * @retval VERR_TRAILING_SPACES + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pi64 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBase, int64_t *pi64); + +/** + * Converts a string representation of a number to a 64-bit signed number. + * The base is guessed. + * + * @returns 64-bit signed number on success. + * @returns 0 on failure. + * @param pszValue Pointer to the string value. + */ +RTDECL(int64_t) RTStrToInt64(const char *pszValue); + +/** + * Converts a string representation of a number to a 32-bit signed number. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param ppszNext Where to store the pointer to the first char following the number. (Optional) + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pi32 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, int32_t *pi32); + +/** + * Converts a string representation of a number to a 32-bit signed number, + * making sure the full string is converted. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VINF_SUCCESS + * @retval VERR_TRAILING_CHARS + * @retval VERR_TRAILING_SPACES + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pi32 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBase, int32_t *pi32); + +/** + * Converts a string representation of a number to a 32-bit signed number. + * The base is guessed. + * + * @returns 32-bit signed number on success. + * @returns 0 on failure. + * @param pszValue Pointer to the string value. + */ +RTDECL(int32_t) RTStrToInt32(const char *pszValue); + +/** + * Converts a string representation of a number to a 16-bit signed number. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param ppszNext Where to store the pointer to the first char following the number. (Optional) + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pi16 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, int16_t *pi16); + +/** + * Converts a string representation of a number to a 16-bit signed number, + * making sure the full string is converted. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VINF_SUCCESS + * @retval VERR_TRAILING_CHARS + * @retval VERR_TRAILING_SPACES + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pi16 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBase, int16_t *pi16); + +/** + * Converts a string representation of a number to a 16-bit signed number. + * The base is guessed. + * + * @returns 16-bit signed number on success. + * @returns 0 on failure. + * @param pszValue Pointer to the string value. + */ +RTDECL(int16_t) RTStrToInt16(const char *pszValue); + +/** + * Converts a string representation of a number to a 8-bit signed number. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * @retval VINF_SUCCESS + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param ppszNext Where to store the pointer to the first char following the number. (Optional) + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pi8 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, int8_t *pi8); + +/** + * Converts a string representation of a number to a 8-bit signed number, + * making sure the full string is converted. + * + * @returns iprt status code. + * Warnings are used to indicate conversion problems. + * @retval VWRN_NUMBER_TOO_BIG + * @retval VINF_SUCCESS + * @retval VERR_TRAILING_CHARS + * @retval VERR_TRAILING_SPACES + * @retval VERR_NO_DIGITS + * + * @param pszValue Pointer to the string value. + * @param uBase The base of the representation used. + * If 0 the function will look for known prefixes before defaulting to 10. + * @param pi8 Where to store the converted number. (optional) + */ +RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBase, int8_t *pi8); + +/** + * Converts a string representation of a number to a 8-bit signed number. + * The base is guessed. + * + * @returns 8-bit signed number on success. + * @returns 0 on failure. + * @param pszValue Pointer to the string value. + */ +RTDECL(int8_t) RTStrToInt8(const char *pszValue); + +/** + * Formats a buffer stream as hex bytes. + * + * The default is no separating spaces or line breaks or anything. + * + * @returns IPRT status code. + * @retval VERR_INVALID_POINTER if any of the pointers are wrong. + * @retval VERR_BUFFER_OVERFLOW if the buffer is insufficent to hold the bytes. + * + * @param pszBuf Output string buffer. + * @param cchBuf The size of the output buffer. + * @param pv Pointer to the bytes to stringify. + * @param cb The number of bytes to stringify. + * @param fFlags Must be zero, reserved for future use. + */ +RTDECL(int) RTStrPrintHexBytes(char *pszBuf, size_t cchBuf, void const *pv, size_t cb, uint32_t fFlags); + +/** + * Converts a string of hex bytes back into binary data. + * + * @returns IPRT status code. + * @retval VERR_INVALID_POINTER if any of the pointers are wrong. + * @retval VERR_BUFFER_OVERFLOW if the string contains too many hex bytes. + * @retval VERR_BUFFER_UNDERFLOW if there aren't enough hex bytes to fill up + * the output buffer. + * @retval VERR_UNEVEN_INPUT if the input contains a half byte. + * @retval VERR_NO_DIGITS + * @retval VWRN_TRAILING_CHARS + * @retval VWRN_TRAILING_SPACES + * + * @param pszHex The string containing the hex bytes. + * @param pv Output buffer. + * @param cb The size of the output buffer. + * @param fFlags Must be zero, reserved for future use. + */ +RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags); + +/** @} */ + + +/** @defgroup rt_str_space Unique String Space + * @ingroup grp_rt_str + * @{ + */ + +/** Pointer to a string name space container node core. */ +typedef struct RTSTRSPACECORE *PRTSTRSPACECORE; +/** Pointer to a pointer to a string name space container node core. */ +typedef PRTSTRSPACECORE *PPRTSTRSPACECORE; + +/** + * String name space container node core. + */ +typedef struct RTSTRSPACECORE +{ + /** Hash key. Don't touch. */ + uint32_t Key; + /** Pointer to the left leaf node. Don't touch. */ + PRTSTRSPACECORE pLeft; + /** Pointer to the left right node. Don't touch. */ + PRTSTRSPACECORE pRight; + /** Pointer to the list of string with the same key. Don't touch. */ + PRTSTRSPACECORE pList; + /** Height of this tree: max(heigth(left), heigth(right)) + 1. Don't touch */ + unsigned char uchHeight; + /** The string length. Read only! */ + size_t cchString; + /** Pointer to the string. Read only! */ + const char *pszString; +} RTSTRSPACECORE; + +/** String space. (Initialize with NULL.) */ +typedef PRTSTRSPACECORE RTSTRSPACE; +/** Pointer to a string space. */ +typedef PPRTSTRSPACECORE PRTSTRSPACE; + + +/** + * Inserts a string into a unique string space. + * + * @returns true on success. + * @returns false if the string collided with an existing string. + * @param pStrSpace The space to insert it into. + * @param pStr The string node. + */ +RTDECL(bool) RTStrSpaceInsert(PRTSTRSPACE pStrSpace, PRTSTRSPACECORE pStr); + +/** + * Removes a string from a unique string space. + * + * @returns Pointer to the removed string node. + * @returns NULL if the string was not found in the string space. + * @param pStrSpace The space to remove it from. + * @param pszString The string to remove. + */ +RTDECL(PRTSTRSPACECORE) RTStrSpaceRemove(PRTSTRSPACE pStrSpace, const char *pszString); + +/** + * Gets a string from a unique string space. + * + * @returns Pointer to the string node. + * @returns NULL if the string was not found in the string space. + * @param pStrSpace The space to get it from. + * @param pszString The string to get. + */ +RTDECL(PRTSTRSPACECORE) RTStrSpaceGet(PRTSTRSPACE pStrSpace, const char *pszString); + +/** + * Gets a string from a unique string space. + * + * @returns Pointer to the string node. + * @returns NULL if the string was not found in the string space. + * @param pStrSpace The space to get it from. + * @param pszString The string to get. + * @param cchMax The max string length to evaluate. Passing + * RTSTR_MAX is ok and makes it behave just like + * RTStrSpaceGet. + */ +RTDECL(PRTSTRSPACECORE) RTStrSpaceGetN(PRTSTRSPACE pStrSpace, const char *pszString, size_t cchMax); + +/** + * Callback function for RTStrSpaceEnumerate() and RTStrSpaceDestroy(). + * + * @returns 0 on continue. + * @returns Non-zero to aborts the operation. + * @param pStr The string node + * @param pvUser The user specified argument. + */ +typedef DECLCALLBACK(int) FNRTSTRSPACECALLBACK(PRTSTRSPACECORE pStr, void *pvUser); +/** Pointer to callback function for RTStrSpaceEnumerate() and RTStrSpaceDestroy(). */ +typedef FNRTSTRSPACECALLBACK *PFNRTSTRSPACECALLBACK; + +/** + * Destroys the string space. + * + * The caller supplies a callback which will be called for each of the string + * nodes in for freeing their memory and other resources. + * + * @returns 0 or what ever non-zero return value pfnCallback returned + * when aborting the destruction. + * @param pStrSpace The space to destroy. + * @param pfnCallback The callback. + * @param pvUser The user argument. + */ +RTDECL(int) RTStrSpaceDestroy(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser); + +/** + * Enumerates the string space. + * The caller supplies a callback which will be called for each of + * the string nodes. + * + * @returns 0 or what ever non-zero return value pfnCallback returned + * when aborting the destruction. + * @param pStrSpace The space to enumerate. + * @param pfnCallback The callback. + * @param pvUser The user argument. + */ +RTDECL(int) RTStrSpaceEnumerate(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser); + +/** @} */ + + +/** @defgroup rt_str_hash Sting hashing + * @ingroup grp_rt_str + * @{ */ + +/** + * Hashes the given string using algorithm \#1. + * + * @returns String hash. + * @param pszString The string to hash. + */ +RTDECL(uint32_t) RTStrHash1(const char *pszString); + +/** + * Hashes the given string using algorithm \#1. + * + * @returns String hash. + * @param pszString The string to hash. + * @param cchString The max length to hash. Hashing will stop if the + * terminator character is encountered first. Passing + * RTSTR_MAX is fine. + */ +RTDECL(uint32_t) RTStrHash1N(const char *pszString, size_t cchString); + +/** + * Hashes the given strings as if they were concatenated using algorithm \#1. + * + * @returns String hash. + * @param cPairs The number of string / length pairs in the + * ellipsis. + * @param ... List of string (const char *) and length + * (size_t) pairs. Passing RTSTR_MAX as the size is + * fine. + */ +RTDECL(uint32_t) RTStrHash1ExN(size_t cPairs, ...); + +/** + * Hashes the given strings as if they were concatenated using algorithm \#1. + * + * @returns String hash. + * @param cPairs The number of string / length pairs in the @a va. + * @param va List of string (const char *) and length + * (size_t) pairs. Passing RTSTR_MAX as the size is + * fine. + */ +RTDECL(uint32_t) RTStrHash1ExNV(size_t cPairs, va_list va); + +/** @} */ + + +/** @defgroup rt_str_utf16 UTF-16 String Manipulation + * @ingroup grp_rt_str + * @{ + */ + +/** + * Free a UTF-16 string allocated by RTStrToUtf16(), RTStrToUtf16Ex(), + * RTLatin1ToUtf16(), RTLatin1ToUtf16Ex(), RTUtf16Dup() or RTUtf16DupEx(). + * + * @returns iprt status code. + * @param pwszString The UTF-16 string to free. NULL is accepted. + */ +RTDECL(void) RTUtf16Free(PRTUTF16 pwszString); + +/** + * Allocates a new copy of the specified UTF-16 string (default tag). + * + * @returns Pointer to the allocated string copy. Use RTUtf16Free() to free it. + * @returns NULL when out of memory. + * @param pwszString UTF-16 string to duplicate. + * @remark This function will not make any attempt to validate the encoding. + */ +#define RTUtf16Dup(pwszString) RTUtf16DupTag((pwszString), RTSTR_TAG) + +/** + * Allocates a new copy of the specified UTF-16 string (custom tag). + * + * @returns Pointer to the allocated string copy. Use RTUtf16Free() to free it. + * @returns NULL when out of memory. + * @param pwszString UTF-16 string to duplicate. + * @param pszTag Allocation tag used for statistics and such. + * @remark This function will not make any attempt to validate the encoding. + */ +RTDECL(PRTUTF16) RTUtf16DupTag(PCRTUTF16 pwszString, const char *pszTag); + +/** + * Allocates a new copy of the specified UTF-16 string (default tag). + * + * @returns iprt status code. + * @param ppwszString Receives pointer of the allocated UTF-16 string. + * The returned pointer must be freed using RTUtf16Free(). + * @param pwszString UTF-16 string to duplicate. + * @param cwcExtra Number of extra RTUTF16 items to allocate. + * @remark This function will not make any attempt to validate the encoding. + */ +#define RTUtf16DupEx(ppwszString, pwszString, cwcExtra) \ + RTUtf16DupExTag((ppwszString), (pwszString), (cwcExtra), RTSTR_TAG) + +/** + * Allocates a new copy of the specified UTF-16 string (custom tag). + * + * @returns iprt status code. + * @param ppwszString Receives pointer of the allocated UTF-16 string. + * The returned pointer must be freed using RTUtf16Free(). + * @param pwszString UTF-16 string to duplicate. + * @param cwcExtra Number of extra RTUTF16 items to allocate. + * @param pszTag Allocation tag used for statistics and such. + * @remark This function will not make any attempt to validate the encoding. + */ +RTDECL(int) RTUtf16DupExTag(PRTUTF16 *ppwszString, PCRTUTF16 pwszString, size_t cwcExtra, const char *pszTag); + +/** + * Returns the length of a UTF-16 string in UTF-16 characters + * without trailing '\\0'. + * + * Surrogate pairs counts as two UTF-16 characters here. Use RTUtf16CpCnt() + * to get the exact number of code points in the string. + * + * @returns The number of RTUTF16 items in the string. + * @param pwszString Pointer the UTF-16 string. + * @remark This function will not make any attempt to validate the encoding. + */ +RTDECL(size_t) RTUtf16Len(PCRTUTF16 pwszString); + +/** + * Performs a case sensitive string compare between two UTF-16 strings. + * + * @returns < 0 if the first string less than the second string.s + * @returns 0 if the first string identical to the second string. + * @returns > 0 if the first string greater than the second string. + * @param pwsz1 First UTF-16 string. Null is allowed. + * @param pwsz2 Second UTF-16 string. Null is allowed. + * @remark This function will not make any attempt to validate the encoding. + */ +RTDECL(int) RTUtf16Cmp(register PCRTUTF16 pwsz1, register PCRTUTF16 pwsz2); + +/** + * Performs a case insensitive string compare between two UTF-16 strings. + * + * This is a simplified compare, as only the simplified lower/upper case folding + * specified by the unicode specs are used. It does not consider character pairs + * as they are used in some languages, just simple upper & lower case compares. + * + * @returns < 0 if the first string less than the second string. + * @returns 0 if the first string identical to the second string. + * @returns > 0 if the first string greater than the second string. + * @param pwsz1 First UTF-16 string. Null is allowed. + * @param pwsz2 Second UTF-16 string. Null is allowed. + */ +RTDECL(int) RTUtf16ICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2); + +/** + * Performs a case insensitive string compare between two UTF-16 strings + * using the current locale of the process (if applicable). + * + * This differs from RTUtf16ICmp() in that it will try, if a locale with the + * required data is available, to do a correct case-insensitive compare. It + * follows that it is more complex and thereby likely to be more expensive. + * + * @returns < 0 if the first string less than the second string. + * @returns 0 if the first string identical to the second string. + * @returns > 0 if the first string greater than the second string. + * @param pwsz1 First UTF-16 string. Null is allowed. + * @param pwsz2 Second UTF-16 string. Null is allowed. + */ +RTDECL(int) RTUtf16LocaleICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2); + +/** + * Folds a UTF-16 string to lowercase. + * + * This is a very simple folding; is uses the simple lowercase + * code point, it is not related to any locale just the most common + * lowercase codepoint setup by the unicode specs, and it will not + * create new surrogate pairs or remove existing ones. + * + * @returns Pointer to the passed in string. + * @param pwsz The string to fold. + */ +RTDECL(PRTUTF16) RTUtf16ToLower(PRTUTF16 pwsz); + +/** + * Folds a UTF-16 string to uppercase. + * + * This is a very simple folding; is uses the simple uppercase + * code point, it is not related to any locale just the most common + * uppercase codepoint setup by the unicode specs, and it will not + * create new surrogate pairs or remove existing ones. + * + * @returns Pointer to the passed in string. + * @param pwsz The string to fold. + */ +RTDECL(PRTUTF16) RTUtf16ToUpper(PRTUTF16 pwsz); + +/** + * Sanitise a (valid) UTF-16 string by replacing all characters outside a white + * list in-place by an ASCII replacement character. Multi-byte characters will + * be replaced byte by byte. + * + * @returns The number of code points replaced, or a negative value if the + * string is not correctly encoded. In this last case the string + * may be partially processed. + * @param pwsz The string to sanitise. + * @param puszValidSets A zero-terminated array of pairs of Unicode points. + * Each pair is the start and end point of a range, + * and the union of these ranges forms the white list. + * @param chReplacement The ASCII replacement character. + */ +RTDECL(ssize_t) RTUtf16PurgeComplementSet(PRTUTF16 pwsz, PCRTUNICP puszValidSet, char chReplacement); + +/** + * Translate a UTF-16 string into a UTF-8 allocating the result buffer (default + * tag). + * + * @returns iprt status code. + * @param pwszString UTF-16 string to convert. + * @param ppszString Receives pointer of allocated UTF-8 string on + * success, and is always set to NULL on failure. + * The returned pointer must be freed using RTStrFree(). + */ +#define RTUtf16ToUtf8(pwszString, ppszString) RTUtf16ToUtf8Tag((pwszString), (ppszString), RTSTR_TAG) + +/** + * Translate a UTF-16 string into a UTF-8 allocating the result buffer. + * + * @returns iprt status code. + * @param pwszString UTF-16 string to convert. + * @param ppszString Receives pointer of allocated UTF-8 string on + * success, and is always set to NULL on failure. + * The returned pointer must be freed using RTStrFree(). + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTUtf16ToUtf8Tag(PCRTUTF16 pwszString, char **ppszString, const char *pszTag); + +/** + * Translates UTF-16 to UTF-8 using buffer provided by the caller or a fittingly + * sized buffer allocated by the function (default tag). + * + * @returns iprt status code. + * @param pwszString The UTF-16 string to convert. + * @param cwcString The number of RTUTF16 items to translate from pwszString. + * The translation will stop when reaching cwcString or the terminator ('\\0'). + * Use RTSTR_MAX to translate the entire string. + * @param ppsz If cch is non-zero, this must either be pointing to a pointer to + * a buffer of the specified size, or pointer to a NULL pointer. + * If *ppsz is NULL or cch is zero a buffer of at least cch chars + * will be allocated to hold the translated string. + * If a buffer was requested it must be freed using RTStrFree(). + * @param cch The buffer size in chars (the type). This includes the terminator. + * @param pcch Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + */ +#define RTUtf16ToUtf8Ex(pwszString, cwcString, ppsz, cch, pcch) \ + RTUtf16ToUtf8ExTag((pwszString), (cwcString), (ppsz), (cch), (pcch), RTSTR_TAG) + +/** + * Translates UTF-16 to UTF-8 using buffer provided by the caller or a fittingly + * sized buffer allocated by the function (custom tag). + * + * @returns iprt status code. + * @param pwszString The UTF-16 string to convert. + * @param cwcString The number of RTUTF16 items to translate from pwszString. + * The translation will stop when reaching cwcString or the terminator ('\\0'). + * Use RTSTR_MAX to translate the entire string. + * @param ppsz If cch is non-zero, this must either be pointing to a pointer to + * a buffer of the specified size, or pointer to a NULL pointer. + * If *ppsz is NULL or cch is zero a buffer of at least cch chars + * will be allocated to hold the translated string. + * If a buffer was requested it must be freed using RTStrFree(). + * @param cch The buffer size in chars (the type). This includes the terminator. + * @param pcch Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTUtf16ToUtf8ExTag(PCRTUTF16 pwszString, size_t cwcString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag); + +/** + * Calculates the length of the UTF-16 string in UTF-8 chars (bytes). + * + * This function will validate the string, and incorrectly encoded UTF-16 + * strings will be rejected. The primary purpose of this function is to + * help allocate buffers for RTUtf16ToUtf8() of the correct size. For most + * other purposes RTUtf16ToUtf8Ex() should be used. + * + * @returns Number of char (bytes). + * @returns 0 if the string was incorrectly encoded. + * @param pwsz The UTF-16 string. + */ +RTDECL(size_t) RTUtf16CalcUtf8Len(PCRTUTF16 pwsz); + +/** + * Calculates the length of the UTF-16 string in UTF-8 chars (bytes). + * + * This function will validate the string, and incorrectly encoded UTF-16 + * strings will be rejected. + * + * @returns iprt status code. + * @param pwsz The string. + * @param cwc The max string length. Use RTSTR_MAX to process the entire string. + * @param pcch Where to store the string length (in bytes). Optional. + * This is undefined on failure. + */ +RTDECL(int) RTUtf16CalcUtf8LenEx(PCRTUTF16 pwsz, size_t cwc, size_t *pcch); + +/** + * Translate a UTF-16 string into a Latin-1 (ISO-8859-1) allocating the result + * buffer (default tag). + * + * @returns iprt status code. + * @param pwszString UTF-16 string to convert. + * @param ppszString Receives pointer of allocated Latin1 string on + * success, and is always set to NULL on failure. + * The returned pointer must be freed using RTStrFree(). + */ +#define RTUtf16ToLatin1(pwszString, ppszString) RTUtf16ToLatin1Tag((pwszString), (ppszString), RTSTR_TAG) + +/** + * Translate a UTF-16 string into a Latin-1 (ISO-8859-1) allocating the result + * buffer (custom tag). + * + * @returns iprt status code. + * @param pwszString UTF-16 string to convert. + * @param ppszString Receives pointer of allocated Latin1 string on + * success, and is always set to NULL on failure. + * The returned pointer must be freed using RTStrFree(). + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTUtf16ToLatin1Tag(PCRTUTF16 pwszString, char **ppszString, const char *pszTag); + +/** + * Translates UTF-16 to Latin-1 (ISO-8859-1) using buffer provided by the caller + * or a fittingly sized buffer allocated by the function (default tag). + * + * @returns iprt status code. + * @param pwszString The UTF-16 string to convert. + * @param cwcString The number of RTUTF16 items to translate from + * pwszString. The translation will stop when reaching + * cwcString or the terminator ('\\0'). Use RTSTR_MAX + * to translate the entire string. + * @param ppsz Pointer to the pointer to the Latin-1 string. The + * buffer can optionally be preallocated by the caller. + * + * If cch is zero, *ppsz is undefined. + * + * If cch is non-zero and *ppsz is not NULL, then this + * will be used as the output buffer. + * VERR_BUFFER_OVERFLOW will be returned if this is + * insufficient. + * + * If cch is zero or *ppsz is NULL, then a buffer of + * sufficient size is allocated. cch can be used to + * specify a minimum size of this buffer. Use + * RTUtf16Free() to free the result. + * + * @param cch The buffer size in chars (the type). This includes + * the terminator. + * @param pcch Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + */ +#define RTUtf16ToLatin1Ex(pwszString, cwcString, ppsz, cch, pcch) \ + RTUtf16ToLatin1ExTag((pwszString), (cwcString), (ppsz), (cch), (pcch), RTSTR_TAG) + +/** + * Translates UTF-16 to Latin-1 (ISO-8859-1) using buffer provided by the caller + * or a fittingly sized buffer allocated by the function (custom tag). + * + * @returns iprt status code. + * @param pwszString The UTF-16 string to convert. + * @param cwcString The number of RTUTF16 items to translate from + * pwszString. The translation will stop when reaching + * cwcString or the terminator ('\\0'). Use RTSTR_MAX + * to translate the entire string. + * @param ppsz Pointer to the pointer to the Latin-1 string. The + * buffer can optionally be preallocated by the caller. + * + * If cch is zero, *ppsz is undefined. + * + * If cch is non-zero and *ppsz is not NULL, then this + * will be used as the output buffer. + * VERR_BUFFER_OVERFLOW will be returned if this is + * insufficient. + * + * If cch is zero or *ppsz is NULL, then a buffer of + * sufficient size is allocated. cch can be used to + * specify a minimum size of this buffer. Use + * RTUtf16Free() to free the result. + * + * @param cch The buffer size in chars (the type). This includes + * the terminator. + * @param pcch Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTUtf16ToLatin1ExTag(PCRTUTF16 pwszString, size_t cwcString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag); + +/** + * Calculates the length of the UTF-16 string in Latin-1 (ISO-8859-1) chars. + * + * This function will validate the string, and incorrectly encoded UTF-16 + * strings will be rejected. The primary purpose of this function is to + * help allocate buffers for RTUtf16ToLatin1() of the correct size. For most + * other purposes RTUtf16ToLatin1Ex() should be used. + * + * @returns Number of char (bytes). + * @returns 0 if the string was incorrectly encoded. + * @param pwsz The UTF-16 string. + */ +RTDECL(size_t) RTUtf16CalcLatin1Len(PCRTUTF16 pwsz); + +/** + * Calculates the length of the UTF-16 string in Latin-1 (ISO-8859-1) chars. + * + * This function will validate the string, and incorrectly encoded UTF-16 + * strings will be rejected. + * + * @returns iprt status code. + * @param pwsz The string. + * @param cwc The max string length. Use RTSTR_MAX to process the + * entire string. + * @param pcch Where to store the string length (in bytes). Optional. + * This is undefined on failure. + */ +RTDECL(int) RTUtf16CalcLatin1LenEx(PCRTUTF16 pwsz, size_t cwc, size_t *pcch); + +/** + * Get the unicode code point at the given string position. + * + * @returns unicode code point. + * @returns RTUNICP_INVALID if the encoding is invalid. + * @param pwsz The string. + * + * @remark This is an internal worker for RTUtf16GetCp(). + */ +RTDECL(RTUNICP) RTUtf16GetCpInternal(PCRTUTF16 pwsz); + +/** + * Get the unicode code point at the given string position. + * + * @returns iprt status code. + * @param ppwsz Pointer to the string pointer. This will be updated to + * point to the char following the current code point. + * @param pCp Where to store the code point. + * RTUNICP_INVALID is stored here on failure. + * + * @remark This is an internal worker for RTUtf16GetCpEx(). + */ +RTDECL(int) RTUtf16GetCpExInternal(PCRTUTF16 *ppwsz, PRTUNICP pCp); + +/** + * Put the unicode code point at the given string position + * and return the pointer to the char following it. + * + * This function will not consider anything at or following the + * buffer area pointed to by pwsz. It is therefore not suitable for + * inserting code points into a string, only appending/overwriting. + * + * @returns pointer to the char following the written code point. + * @param pwsz The string. + * @param CodePoint The code point to write. + * This should not be RTUNICP_INVALID or any other + * character out of the UTF-16 range. + * + * @remark This is an internal worker for RTUtf16GetCpEx(). + */ +RTDECL(PRTUTF16) RTUtf16PutCpInternal(PRTUTF16 pwsz, RTUNICP CodePoint); + +/** + * Get the unicode code point at the given string position. + * + * @returns unicode code point. + * @returns RTUNICP_INVALID if the encoding is invalid. + * @param pwsz The string. + * + * @remark We optimize this operation by using an inline function for + * everything which isn't a surrogate pair or an endian indicator. + */ +DECLINLINE(RTUNICP) RTUtf16GetCp(PCRTUTF16 pwsz) +{ + const RTUTF16 wc = *pwsz; + if (wc < 0xd800 || (wc > 0xdfff && wc < 0xfffe)) + return wc; + return RTUtf16GetCpInternal(pwsz); +} + +/** + * Get the unicode code point at the given string position. + * + * @returns iprt status code. + * @param ppwsz Pointer to the string pointer. This will be updated to + * point to the char following the current code point. + * @param pCp Where to store the code point. + * RTUNICP_INVALID is stored here on failure. + * + * @remark We optimize this operation by using an inline function for + * everything which isn't a surrogate pair or and endian indicator. + */ +DECLINLINE(int) RTUtf16GetCpEx(PCRTUTF16 *ppwsz, PRTUNICP pCp) +{ + const RTUTF16 wc = **ppwsz; + if (wc < 0xd800 || (wc > 0xdfff && wc < 0xfffe)) + { + (*ppwsz)++; + *pCp = wc; + return VINF_SUCCESS; + } + return RTUtf16GetCpExInternal(ppwsz, pCp); +} + +/** + * Put the unicode code point at the given string position + * and return the pointer to the char following it. + * + * This function will not consider anything at or following the + * buffer area pointed to by pwsz. It is therefore not suitable for + * inserting code points into a string, only appending/overwriting. + * + * @returns pointer to the char following the written code point. + * @param pwsz The string. + * @param CodePoint The code point to write. + * This should not be RTUNICP_INVALID or any other + * character out of the UTF-16 range. + * + * @remark We optimize this operation by using an inline function for + * everything which isn't a surrogate pair or and endian indicator. + */ +DECLINLINE(PRTUTF16) RTUtf16PutCp(PRTUTF16 pwsz, RTUNICP CodePoint) +{ + if (CodePoint < 0xd800 || (CodePoint > 0xd800 && CodePoint < 0xfffe)) + { + *pwsz++ = (RTUTF16)CodePoint; + return pwsz; + } + return RTUtf16PutCpInternal(pwsz, CodePoint); +} + +/** + * Skips ahead, past the current code point. + * + * @returns Pointer to the char after the current code point. + * @param pwsz Pointer to the current code point. + * @remark This will not move the next valid code point, only past the current one. + */ +DECLINLINE(PRTUTF16) RTUtf16NextCp(PCRTUTF16 pwsz) +{ + RTUNICP Cp; + RTUtf16GetCpEx(&pwsz, &Cp); + return (PRTUTF16)pwsz; +} + +/** + * Skips backwards, to the previous code point. + * + * @returns Pointer to the char after the current code point. + * @param pwszStart Pointer to the start of the string. + * @param pwsz Pointer to the current code point. + */ +RTDECL(PRTUTF16) RTUtf16PrevCp(PCRTUTF16 pwszStart, PCRTUTF16 pwsz); + + +/** + * Checks if the UTF-16 char is the high surrogate char (i.e. + * the 1st char in the pair). + * + * @returns true if it is. + * @returns false if it isn't. + * @param wc The character to investigate. + */ +DECLINLINE(bool) RTUtf16IsHighSurrogate(RTUTF16 wc) +{ + return wc >= 0xd800 && wc <= 0xdbff; +} + +/** + * Checks if the UTF-16 char is the low surrogate char (i.e. + * the 2nd char in the pair). + * + * @returns true if it is. + * @returns false if it isn't. + * @param wc The character to investigate. + */ +DECLINLINE(bool) RTUtf16IsLowSurrogate(RTUTF16 wc) +{ + return wc >= 0xdc00 && wc <= 0xdfff; +} + + +/** + * Checks if the two UTF-16 chars form a valid surrogate pair. + * + * @returns true if they do. + * @returns false if they doesn't. + * @param wcHigh The high (1st) character. + * @param wcLow The low (2nd) character. + */ +DECLINLINE(bool) RTUtf16IsSurrogatePair(RTUTF16 wcHigh, RTUTF16 wcLow) +{ + return RTUtf16IsHighSurrogate(wcHigh) + && RTUtf16IsLowSurrogate(wcLow); +} + +/** @} */ + + +/** @defgroup rt_str_latin1 Latin-1 (ISO-8859-1) String Manipulation + * @ingroup grp_rt_str + * @{ + */ + +/** + * Calculates the length of the Latin-1 (ISO-8859-1) string in RTUTF16 items. + * + * @returns Number of RTUTF16 items. + * @param psz The Latin-1 string. + */ +RTDECL(size_t) RTLatin1CalcUtf16Len(const char *psz); + +/** + * Calculates the length of the Latin-1 (ISO-8859-1) string in RTUTF16 items. + * + * @returns iprt status code. + * @param psz The Latin-1 string. + * @param cch The max string length. Use RTSTR_MAX to process the + * entire string. + * @param pcwc Where to store the string length. Optional. + * This is undefined on failure. + */ +RTDECL(int) RTLatin1CalcUtf16LenEx(const char *psz, size_t cch, size_t *pcwc); + +/** + * Translate a Latin-1 (ISO-8859-1) string into a UTF-16 allocating the result + * buffer (default tag). + * + * @returns iprt status code. + * @param pszString The Latin-1 string to convert. + * @param ppwszString Receives pointer to the allocated UTF-16 string. The + * returned string must be freed using RTUtf16Free(). + */ +#define RTLatin1ToUtf16(pszString, ppwszString) RTLatin1ToUtf16Tag((pszString), (ppwszString), RTSTR_TAG) + +/** + * Translate a Latin-1 (ISO-8859-1) string into a UTF-16 allocating the result + * buffer (custom tag). + * + * @returns iprt status code. + * @param pszString The Latin-1 string to convert. + * @param ppwszString Receives pointer to the allocated UTF-16 string. The + * returned string must be freed using RTUtf16Free(). + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTLatin1ToUtf16Tag(const char *pszString, PRTUTF16 *ppwszString, const char *pszTag); + +/** + * Translates pszString from Latin-1 (ISO-8859-1) to UTF-16, allocating the + * result buffer if requested (default tag). + * + * @returns iprt status code. + * @param pszString The Latin-1 string to convert. + * @param cchString The maximum size in chars (the type) to convert. + * The conversion stops when it reaches cchString or + * the string terminator ('\\0'). + * Use RTSTR_MAX to translate the entire string. + * @param ppwsz If cwc is non-zero, this must either be pointing + * to pointer to a buffer of the specified size, or + * pointer to a NULL pointer. + * If *ppwsz is NULL or cwc is zero a buffer of at + * least cwc items will be allocated to hold the + * translated string. If a buffer was requested it + * must be freed using RTUtf16Free(). + * @param cwc The buffer size in RTUTF16s. This includes the + * terminator. + * @param pcwc Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + */ +#define RTLatin1ToUtf16Ex(pszString, cchString, ppwsz, cwc, pcwc) \ + RTLatin1ToUtf16ExTag((pszString), (cchString), (ppwsz), (cwc), (pcwc), RTSTR_TAG) + +/** + * Translates pszString from Latin-1 (ISO-8859-1) to UTF-16, allocating the + * result buffer if requested. + * + * @returns iprt status code. + * @param pszString The Latin-1 string to convert. + * @param cchString The maximum size in chars (the type) to convert. + * The conversion stops when it reaches cchString or + * the string terminator ('\\0'). + * Use RTSTR_MAX to translate the entire string. + * @param ppwsz If cwc is non-zero, this must either be pointing + * to pointer to a buffer of the specified size, or + * pointer to a NULL pointer. + * If *ppwsz is NULL or cwc is zero a buffer of at + * least cwc items will be allocated to hold the + * translated string. If a buffer was requested it + * must be freed using RTUtf16Free(). + * @param cwc The buffer size in RTUTF16s. This includes the + * terminator. + * @param pcwc Where to store the length of the translated string, + * excluding the terminator. (Optional) + * + * This may be set under some error conditions, + * however, only for VERR_BUFFER_OVERFLOW and + * VERR_NO_STR_MEMORY will it contain a valid string + * length that can be used to resize the buffer. + * @param pszTag Allocation tag used for statistics and such. + */ +RTDECL(int) RTLatin1ToUtf16ExTag(const char *pszString, size_t cchString, + PRTUTF16 *ppwsz, size_t cwc, size_t *pcwc, const char *pszTag); + +/** @} */ + + +RT_C_DECLS_END + +/** @} */ + +#endif + diff --git a/include/iprt/symlink.h b/include/iprt/symlink.h new file mode 100644 index 00000000..85edf1ad --- /dev/null +++ b/include/iprt/symlink.h @@ -0,0 +1,176 @@ +/** @file + * IPRT - Symbolic Link Manipulation. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_symlink_h +#define ___iprt_symlink_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_symlink RTSymlink - Symbolic Link Manipulation + * @ingroup grp_rt + * + * For querying and changing symlink info (mode, ownership, etc) please refer + * to the @ref grp_rt_path "RTPath" API: RTPathQueryInfoEx, RTPathSetOwnerEx, + * RTPathSetModeEx and RTPathSetTimesEx. + * + * @{ + */ + +/** + * Checks if the specified path exists and is a symlink. + * + * @returns true if it's a symlink, false if it isn't. + * @param pszSymlink The path to the symlink. + * + * @sa RTDirExists, RTPathExists, RTSymlinkExists. + */ +RTDECL(bool) RTSymlinkExists(const char *pszSymlink); + +/** + * Checks if this is a dangling link or not. + * + * If the target of @a pszSymlink is a symbolic link, this may return false if + * that or any subsequent links are dangling. + * + * @returns true if it's dangling, false if it isn't. + * @param pszSymlink The path to the symlink. + */ +RTDECL(bool) RTSymlinkIsDangling(const char *pszSymlink); + +/** + * RTSymlinkCreate link type argument. + */ +typedef enum RTSYMLINKTYPE +{ + /** Invalid value. */ + RTSYMLINKTYPE_INVALID = 0, + /** The link targets a directory. */ + RTSYMLINKTYPE_DIR, + /** The link targets a file (or whatever else). */ + RTSYMLINKTYPE_FILE, + /** It is not known what is being targeted. + * @remarks The RTSymlinkCreate API may probe the target to try figure + * out what is being targeted. */ + RTSYMLINKTYPE_UNKNOWN, + /** The end of the valid type values. */ + RTSYMLINKTYPE_END, + /** Blow the type up to 32-bit. */ + RTSYMLINKTYPE_32BIT_HACK = 0x7fffffff +} RTSYMLINKTYPE; + +/** @name RTSymlinkCreate flags. + * @{ */ +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTSYMLINKCREATE_FLAGS_NO_SYMLINKS RT_BIT(0) +/** @} */ + +/** + * Creates a symbolic link (@a pszSymlink) targeting @a pszTarget. + * + * @returns IPRT status code. + * + * @param pszSymlink The name of the symbolic link. + * @param pszTarget The path to the symbolic link target. This is + * relative to @a pszSymlink or an absolute path. + * @param enmType The symbolic link type. For Windows compatability + * it is very important to set this correctly. When + * RTSYMLINKTYPE_UNKNOWN is used, the API will try + * make a guess and may attempt query information + * about @a pszTarget in the process. + * @param fCreate Create flags, RTSYMLINKCREATE_FLAGS_*. + */ +RTDECL(int) RTSymlinkCreate(const char *pszSymlink, const char *pszTarget, + RTSYMLINKTYPE enmType, uint32_t fCreate); + +/** @name RTSymlinkDelete flags. + * @{ */ +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTSYMLINKDELETE_FLAGS_NO_SYMLINKS RT_BIT(0) +/** @} */ + +/** + * Deletes the specified symbolic link. + * + * This will try to refuse deleting non-symlinks, however there are usually + * races in the implementation of this check so no guarantees can be are made. + * + * @returns IPRT status code. + * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link. + * + * @param pszSymlink The symbolic link that should be removed. + * @param fDelete Delete flags, RTSYMLINKDELETE_FLAGS_*. + */ +RTDECL(int) RTSymlinkDelete(const char *pszSymlink, uint32_t fDelete); + +/** @name RTSymlinkRead flags. + * @{ */ +/** Don't allow symbolic links as part of the path. + * @remarks this flag is currently not implemented and will be ignored. */ +#define RTSYMLINKREAD_FLAGS_NO_SYMLINKS RT_BIT(0) +/** @} */ + +/** + * Read the symlink target. + * + * @returns IPRT status code. + * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link. + * @retval VERR_BUFFER_OVERFLOW if the link is larger than @a cbTarget. The + * buffer will contain what all we managed to read, fully terminated + * if @a cbTarget > 0. + * + * @param pszSymlink The symbolic link that should be read. + * @param pszTarget The target buffer. + * @param cbTarget The size of the target buffer. + * @param fRead Read flags, RTSYMLINKREAD_FLAGS_*. + */ +RTDECL(int) RTSymlinkRead(const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead); + +/** + * Read the symlink target into an API allocated buffer. + * + * This API eliminates the race involved in determining the right buffer size. + * + * @returns IPRT status code. + * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link. + * + * @param pszSymlink The symbolic link that should be read. + * @param ppszTarget Where to return the target string. Free the string + * by calling RTStrFree. + */ +RTDECL(int) RTSymlinkReadA(const char *pszSymlink, char **ppszTarget); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/system.h b/include/iprt/system.h new file mode 100644 index 00000000..e7083e27 --- /dev/null +++ b/include/iprt/system.h @@ -0,0 +1,250 @@ +/** @file + * IPRT - System Information. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_system_h +#define ___iprt_system_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_system RTSystem - System Information + * @ingroup grp_rt + * @{ + */ + +/** + * Info level for RTSystemGetOSInfo(). + */ +typedef enum RTSYSOSINFO +{ + RTSYSOSINFO_INVALID = 0, /**< The usual invalid entry. */ + RTSYSOSINFO_PRODUCT, /**< OS product name. (uname -o) */ + RTSYSOSINFO_RELEASE, /**< OS release. (uname -r) */ + RTSYSOSINFO_VERSION, /**< OS version, optional. (uname -v) */ + RTSYSOSINFO_SERVICE_PACK, /**< Service/fix pack level, optional. */ + RTSYSOSINFO_END /**< End of the valid info levels. */ +} RTSYSOSINFO; + + +/** + * Queries information about the OS. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_INVALID_PARAMETER if enmInfo is invalid. + * @retval VERR_INVALID_POINTER if pszInfoStr is invalid. + * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer will + * contain the chopped off result in this case, provided cchInfo isn't 0. + * @retval VERR_NOT_SUPPORTED if the info level isn't implemented. The buffer will + * contain an empty string. + * + * @param enmInfo The OS info level. + * @param pszInfo Where to store the result. + * @param cchInfo The size of the output buffer. + */ +RTDECL(int) RTSystemQueryOSInfo(RTSYSOSINFO enmInfo, char *pszInfo, size_t cchInfo); + +/** + * Queries the total amount of RAM in the system. + * + * This figure does not given any information about how much memory is + * currently available. Use RTSystemQueryAvailableRam instead. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and *pcb on sucess. + * @retval VERR_ACCESS_DENIED if the information isn't accessible to the + * caller. + * + * @param pcb Where to store the result (in bytes). + */ +RTDECL(int) RTSystemQueryTotalRam(uint64_t *pcb); + +/** + * Queries the total amount of RAM accessible to the system. + * + * This figure should not include memory that is installed but not used, + * nor memory that will be slow to bring online. The definition of 'slow' + * here is slower than swapping out a MB of pages to disk. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and *pcb on success. + * @retval VERR_ACCESS_DENIED if the information isn't accessible to the + * caller. + * + * @param pcb Where to store the result (in bytes). + */ +RTDECL(int) RTSystemQueryAvailableRam(uint64_t *pcb); + +/** + * Queries the amount of RAM that is currently locked down or in some other + * way made impossible to virtualize within reasonably short time. + * + * The purposes of this API is, when combined with RTSystemQueryTotalRam, to + * be able to determine an absolute max limit for how much fixed memory it is + * (theoretically) possible to allocate (or lock down). + * + * The kind memory covered by this function includes: + * - locked (wired) memory - like for instance RTR0MemObjLockUser + * and RTR0MemObjLockKernel makes, + * - kernel pools and heaps - like for instance the ring-0 variant + * of RTMemAlloc taps into, + * - fixed (not pageable) kernel allocations - like for instance + * all the RTR0MemObjAlloc* functions makes, + * - any similar memory that isn't easily swapped out, discarded, + * or flushed to disk. + * + * This works against the value returned by RTSystemQueryTotalRam, and + * the value reported by this function can never be larger than what a + * call to RTSystemQueryTotalRam returns. + * + * The short time term here is relative to swapping to disk like in + * RTSystemQueryTotalRam. This could mean that (part of) the dirty buffers + * in the dynamic I/O cache could be included in the total. If the dynamic + * I/O cache isn't likely to either flush buffers when the load increases + * and put them back into normal circulation, they should be included in + * the memory accounted for here. + * + * @retval VINF_SUCCESS and *pcb on success. + * @retval VERR_NOT_SUPPORTED if the information isn't available on the + * system in general. The caller must handle this scenario. + * @retval VERR_ACCESS_DENIED if the information isn't accessible to the + * caller. + * + * @param pcb Where to store the result (in bytes). + * + * @remarks This function could've been inverted and called + * RTSystemQueryAvailableRam, but that might give impression that + * it would be possible to allocate the amount of memory it + * indicates for a single purpose, something which would be very + * improbable on most systems. + * + * @remarks We might have to add another output parameter to this function + * that indicates if some of the memory kinds listed above cannot + * be accounted for on the system and therefore is not include in + * the returned amount. + */ +RTDECL(int) RTSystemQueryUnavailableRam(uint64_t *pcb); + + +/** + * The DMI strings. + */ +typedef enum RTSYSDMISTR +{ + /** Invalid zero entry. */ + RTSYSDMISTR_INVALID = 0, + /** The product name. */ + RTSYSDMISTR_PRODUCT_NAME, + /** The product version. */ + RTSYSDMISTR_PRODUCT_VERSION, + /** The product UUID. */ + RTSYSDMISTR_PRODUCT_UUID, + /** The product serial. */ + RTSYSDMISTR_PRODUCT_SERIAL, + /** The system manufacturer. */ + RTSYSDMISTR_MANUFACTURER, + /** The end of the valid strings. */ + RTSYSDMISTR_END, + /** The usual 32-bit hack. */ + RTSYSDMISTR_32_BIT_HACK = 0x7fffffff +} RTSYSDMISTR; + +/** + * Queries a DMI string. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS on success. + * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer will + * contain the chopped off result in this case, provided cbBuf isn't 0. + * @retval VERR_ACCESS_DENIED if the information isn't accessible to the + * caller. + * @retval VERR_NOT_SUPPORTED if the information isn't available on the system + * in general. The caller must expect this status code and deal with + * it. + * + * @param enmString Which string to query. + * @param pszBuf Where to store the string. This is always + * terminated, even on error. + * @param cbBuf The buffer size. + */ +RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t cbBuf); + +/** @name Flags for RTSystemReboot and RTSystemShutdown. + * @{ */ +/** Reboot the system after shutdown. */ +#define RTSYSTEM_SHUTDOWN_REBOOT UINT32_C(0) +/** Reboot the system after shutdown. + * The call may return VINF_SYS_MAY_POWER_OFF if the OS / + * hardware combination may power off instead of halting. */ +#define RTSYSTEM_SHUTDOWN_HALT UINT32_C(1) +/** Power off the system after shutdown. + * This may be equvivalent to a RTSYSTEM_SHUTDOWN_HALT on systems where we + * cannot figure out whether the hardware/OS implements the actual powering + * off. If we can figure out that it's not supported, an + * VERR_SYS_CANNOT_POWER_OFF error is raised. */ +#define RTSYSTEM_SHUTDOWN_POWER_OFF UINT32_C(2) +/** Power off the system after shutdown, or halt it if that's not possible. */ +#define RTSYSTEM_SHUTDOWN_POWER_OFF_HALT UINT32_C(3) +/** The shutdown action mask. */ +#define RTSYSTEM_SHUTDOWN_ACTION_MASK UINT32_C(3) +/** Unplanned shutdown/reboot. */ +#define RTSYSTEM_SHUTDOWN_UNPLANNED UINT32_C(0) +/** Planned shutdown/reboot. */ +#define RTSYSTEM_SHUTDOWN_PLANNED RT_BIT_32(2) +/** Force the system to shutdown/reboot regardless of objecting application + * or other stuff. This flag might not be realized on all systems. */ +#define RTSYSTEM_SHUTDOWN_FORCE RT_BIT_32(3) +/** Parameter validation mask. */ +#define RTSYSTEM_SHUTDOWN_VALID_MASK UINT32_C(0x0000000f) +/** @} */ + +/** + * Shuts down the system. + * + * @returns IPRT status code on failure, on success it may or may not return + * depending on the OS. + * @retval VINF_SUCCESS + * @retval VINF_SYS_MAY_POWER_OFF + * @retval VERR_SYS_SHUTDOWN_FAILED + * @retval VERR_SYS_CANNOT_POWER_OFF + * + * @param cMsDelay The delay before the actual reboot. If this is + * not supported by the OS, an immediate reboot + * will be performed. + * @param fFlags Shutdown flags, see RTSYSTEM_SHUTDOWN_XXX. + * @param pszLogMsg Message for the log and users about why we're + * shutting down. + */ +RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char *pszLogMsg); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/table.h b/include/iprt/table.h new file mode 100644 index 00000000..70023979 --- /dev/null +++ b/include/iprt/table.h @@ -0,0 +1,713 @@ +/** @file + * IPRT - Abstract Table/Trees. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_table_h +#define ___iprt_table_h + +#include <iprt/types.h> + +/** @defgroup grp_rt_tab RTTab - Generic Tree and Table Interface. + * @ingroup grp_rt + * @{ + */ + +RT_C_DECLS_BEGIN + +/** Pointer to an allocator. */ +typedef struct RTTABALLOCATOR *PRTTABALLOCATOR; + +/** + * Allocates memory. + * + * @returns Pointer to the allocated memory. + * @returns NULL on failure. (don't throw!) + * @param pAllocator The allocator structure. + * @param cb The number of bytes to allocate. (Never 0.) + */ +typedef DECLCALLBACK(void *) FNRTTABALLOC(PRTTABALLOCATOR pAllocator, size_t cb); +/** Pointer to a FNRTTABALLOC() function. */ +typedef FNRTTABALLOC *PFNRTTABALLOC; + +/** + * Frees memory. + * + * @param pAllocator The allocator structure. + * @param pv The memory to free. (can be NULL) + */ +typedef DECLCALLBACK(void *) FNRTTABFREE(PRTTABALLOCATOR pAllocator, void *pv); +/** Pointer to a FNRTTABFREE() function. */ +typedef FNRTTABFREE *PFNRTTABFREE; + +/** + * The allocator structure. + * (Hint: use this as like 'base class' for your custom allocators.) + */ +typedef struct RTTABALLOCATOR +{ + /** The allocation function. */ + PFNRTTABALLOC pfnAlloc; + /** The free function. */ + PFNRTTABFREE pfnFree; +} RTTABALLOCATOR; + +/** + * Gets the default allocator. + * + * @returns Pointer to the default allocator. + */ +RTDECL(RTTABALLOCATOR) RTTabDefaultAllocator(void); + + +/** + * Compares two table items. + * + * @returns 0 if equal + * @returns <0 if pvItem1 is less than pvItem2 (pvItem2 is then greater than pvItem1). + * @returns >0 if pvItem1 is less than pvItem2 (pvItem1 is then greater than pvItem2). + * + * @param pvItem1 The first item. + * @param pvItem2 The second item. + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(int) FNRTTABCOMP(const void *pvItem1, const void *pvItem2, void *pvUser); +/** Pointer to a FNRTTABCOMP() function. */ +typedef FNRTTABCOMP *PFNRTTABCOMP; + +/** + * Duplicates a table item. + * This is used when duplicating or copying a table. + * + * @returns Pointer to the copy. + * @returns NULL on failure. + * + * @param pvItem The item to copy. + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(void *) FNRTTABDUPLICATE(const void *pvItem, void *pvUser); +/** Pointer to a FNRTTABDUPLICATE() function. */ +typedef FNRTTABDUPLICATE *PFNRTTABDUPLICATE; + +/** + * Callback function for doing something with an item. + * + * What exactly we're doing is specific to the context of the call. + * + * @param pvItem The item. + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(void) FNRTTABCALLBACK(const void *pvItem, void *pvUser); +/** Pointer to a FNRTTABCALLBACK() function. */ +typedef FNRTTABCALLBACK *PFNRTTABCALLBACK; + + +/** Pointer to const table operations. */ +typedef const struct RTTABOPS *PCRTTABOPS; +/** Pointer to a table. */ +typedef struct RTTAB *PRTTAB; +/** Pointer to a const table. */ +typedef const struct RTTAB *PCRTTAB; +/** Pointer to a traverser. */ +typedef struct RTTABTRAVERSER *PRTTABTRAVERSER; +/** Pointer to a const traverser. */ +typedef const struct RTTABTRAVERSER *PCRTTABTRAVERSER; +/** Pointer to a traverser core. */ +typedef struct RTTABTRAVERSERCORE *PRTTABTRAVERSERCORE; +/** Pointer to a const traverser core. */ +typedef const struct RTTABTRAVERSERCORE *PCRTTABTRAVERSERCORE; + + +/** + * Table operations. + */ +typedef struct RTTABOPS +{ + /** + * Create a table. + * + * @returns Pointer to the new table. + * @returns NULL if we're out of memory or some other resource. + * @param pOps The table operations. + * @param fCreateFlags The table type specific creation flags. + * @param pAllocator Custom allocator. Pass NULL for the default allocator. + * @param pfnComp The comparision function. + */ + DECLCALLBACKMEMBER(PRTTAB, pfnCreate)(PCRTTABOPS pOps, unsigned fCreateFlags, PRTTABALLOCATOR pAllocator, PFNRTTABCOMP pfnComp); + + /** + * Duplicates a table to a table of the same type. + * + * @returns Pointer to the new table. + * @returns NULL if we're out of memory or some other resource. + * @param pTab The table to duplicate. + * @param pfnDuplicate Pointer to the item duplication function. If NULL the new table will + * be referencing the same data as the old one. + * @param pfnNewCB Callback which is called for all the items in the new table. Optional. + * @param pAllocator Custom allocator. Pass NULL to use the same allocator as pTab. + */ + DECLCALLBACKMEMBER(PRTTAB, pfnDuplicate)(PCRTTAB pTab, PFNRTTABDUPLICATE pfnDuplicate, PFNRTTABCALLBACK pfnNewCB, PRTTABALLOCATOR pAllocator); + + /** + * Destroys a table. + * + * @param pTab The table to destroy. + */ + DECLCALLBACKMEMBER(void, pfnDestroy)(PRTTAB pTab); + + /** + * Inserts an item into the table, if a matching item is encountered + * the pointer to the pointer to it will be returned. + * + * @returns Pointer to the item pointer in the table. + * This can be used to replace existing items (don't break anything, dude). + * @returns NULL if we failed to allocate memory for the new node. + * @param pTab The table. + * @param pvItem The item which will be inserted if an matching item was not found in the table. + */ + DECLCALLBACKMEMBER(void **, pfnProbe)(PRTTAB pTab, void *pvItem); + + /** + * Inserts an item into the table, fail if a matching item exists. + * + * @returns NULL on success and allocation failure. + * @returns Pointer to the matching item. + * @param pTab The table. + * @param pvItem The item which is to be inserted. + */ + DECLCALLBACKMEMBER(void *, pfnInsert)(PRTTAB pTab, void *pvItem); + + /** + * Inserts an item into the table, if a matching item is encountered + * it will be replaced and returned. + * + * @returns NULL if inserted and allocation failure. + * @returns Pointer to the replaced item. + * @param pTab The table. + * @param pvItem The item which is to be inserted. + */ + DECLCALLBACKMEMBER(void *, pfnReplace)(PRTTAB pTab, void *pvItem); + + /** + * Removes an item from the table if found. + * + * @returns Pointer to the removed item. + * @returns NULL if no item matched pvItem. + * @param pTab The table. + * @param pvItem The item which is to be inserted. + */ + DECLCALLBACKMEMBER(void *, pfnRemove)(PRTTAB pTab, const void *pvItem); + + /** + * Finds an item in the table. + * + * @returns Pointer to the item it found. + * @returns NULL if no item matched pvItem. + * @param pTab The table. + * @param pvItem The item which is to be inserted. + */ + DECLCALLBACKMEMBER(void *, pfnFind)(PRTTAB pTab, const void *pvItem); + + /** + * Initializes a traverser to the NULL item. + * + * The NULL item is an imaginary table item before the first and after + * the last items in the table. + * + * @returns Pointer to the traverser positioned at the NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + */ + DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravInit)(PRTTAB pTab, PRTTABTRAVERSER pTravNew); + + /** + * Initializes a traverser to the first item in the table. + * + * If the table is empty, the traverser will be positioned at the NULL item + * like with RTTabTravInit(). + * + * @returns Pointer to the traverser positioned at the first item or NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + */ + DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravFirst)(PRTTAB pTab, PRTTABTRAVERSER pTravNew); + + /** + * Initializes a traverser to the last item in the table. + * + * If the table is empty, the traverser will be positioned at the NULL item + * like with RTTabTravInit(). + * + * @returns Pointer to the traverser positioned at the last item or NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + */ + DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravLast)(PRTTAB pTab, PRTTABTRAVERSER pTravNew); + + /** + * Initializes a traverser to an item matching the given one. + * + * If the item isn't found, the traverser will be positioned at the NULL item + * like with RTTabTravInit(). + * + * @returns Pointer to the traverser positioned at the matching item or NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + * @param pvItem The item to find the match to. + */ + DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravFind)(PRTTAB pTab, PRTTABTRAVERSER pTravNew, const void *pvItem); + + /** + * Initializes a traverser to the inserted item. + * + * If there already exists an item in the tree matching pvItem, the traverser + * is positioned at that item like with RTTabTravFind(). + * + * If the insert operation failes because of an out of memory condition, the + * traverser will be positioned at the NULL item like with RTTabTravInit(). + * + * @returns Pointer to the traverser positioned at the inserted, existing or NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + * @param pvItem The item to be inserted. + */ + DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravInsert)(PRTTAB pTab, PRTTABTRAVERSER pTravNew, void *pvItem); + + /** + * Duplicates a traverser. + * + * @returns The pointer to the duplicate. + * @returns NULL on allocation failure. + * + * @param pTrav The traverser to duplicate. + * @param pTravNew Pointer to a preallocated structure. Optional. + */ + DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravDuplicate)(PRTTABTRAVERSERCORE pTrav, PCRTTABTRAVERSER pTravNew); + + /** + * Frees a traverser. + * + * This can safely be called even if the traverser structure + * wasn't dynamically allocated or the constructor failed. + * + * @param pTrav The traverser which is to be free. + */ + DECLCALLBACKMEMBER(void, pfnTravFree)(PRTTABTRAVERSERCORE pTrav); + + /** + * Gets the current item. + * + * @returns The current item. (NULL indicates the imaginary NULL item.) + * @param pTrav The traverser. + */ + DECLCALLBACKMEMBER(void *, pfnTravCur)(PCRTTABTRAVERSERCORE pTrav); + + /** + * Advances to the next item. + * + * @returns The new current item. (NULL indicates the imaginary NULL item.) + * @param pTrav The traverser. + */ + DECLCALLBACKMEMBER(void *, pfnTravNext)(PRTTABTRAVERSERCORE pTrav); + + /** + * Advances to the previous item. + * + * @returns The new current item. (NULL indicates the imaginary NULL item.) + * @param pTrav The traverser. + */ + DECLCALLBACKMEMBER(void *, pfnTravPrev)(PRTTABTRAVERSERCORE pTrav); + + /** + * Replaces the current item. + * + * This has the same restrictions as RTTabProbe(), e.g. it's not permitted to + * break the order of the table. + * + * @returns The replaced item. + * @returns NULL if the current item is the NULL item. The traverser + * and table remains unchanged. + * @param pTrav The traverser. + * @param pvItem The item to be inserted. + */ + DECLCALLBACKMEMBER(void *, pfnTravReplace)(PRTTABTRAVERSERCORE pTrav, void *pvItem); + + /** The type of table type. */ + const char *pszType; +} RTTABOPS; + +/** + * A table. + */ +typedef struct RTTAB +{ + /** The table operations. */ + PCRTTABOPS pOps; + /** The function for comparing table items. */ + PFNRTTABCOMP pfnComp; + /** The number of items in the table. */ + RTUINT cItems; + /** The table generation number. + * This must be updated whenever the table changes. */ + RTUINT idGeneration; +} RTTAB; + + +/** + * Create a table. + * + * @returns Pointer to the new table. + * @returns NULL if we're out of memory or some other resource. + * @param pOps The table operations. + * @param fCreateFlags The table type specific creation flags. + * @param pAllocator Custom allocator. Pass NULL for the default allocator. + * @param pfnComp The comparision function. + */ +DECLINLINE(PRTTAB) RTTabCreate(PCRTTABOPS pOps, unsigned fCreateFlags, PRTTABALLOCATOR pAllocator, PFNRTTABCOMP pfnComp) +{ + return pOps->pfnCreate(pOps, fCreateFlags, pAllocator, pfnComp); +} + +/** + * Duplicates a table to a table of the same type. + * + * @returns Pointer to the new table. + * @returns NULL if we're out of memory or some other resource. + * @param pTab The table to duplicate. + * @param pfnDuplicate Pointer to the item duplication function. If NULL the new table will + * be referencing the same data as the old one. + * @param pfnNewCB Callback which is called for all the items in the new table. Optional. + * @param pAllocator Custom allocator. Pass NULL to use the same allocator as pTab. + */ +DECLINLINE(PRTTAB) RTTabDuplicate(PCRTTAB pTab, PFNRTTABDUPLICATE pfnDuplicate, PFNRTTABCALLBACK pfnNewCB, PRTTABALLOCATOR pAllocator) +{ + return pTab->pOps->pfnDuplicate(pTab, pfnDuplicate, pfnNewCB, pAllocator); +} + +/** + * Destroys a table. + * + * @param pTab The table to destroy. + */ +DECLINLINE(void) RTTabDestroy(PRTTAB pTab) +{ + pTab->pOps->pfnDestroy(pTab); +} + +/** + * Count the item in the table. + * + * @returns Number of items in the table. + * @param pTab The table to count. + */ +DECLINLINE(RTUINT) RTTabCount(PRTTAB pTab) +{ + return pTab->cItems; +} + +/** + * Inserts an item into the table, if a matching item is encountered + * the pointer to the pointer to it will be returned. + * + * @returns Pointer to the item pointer in the table. + * This can be used to replace existing items (don't break anything, dude). + * @returns NULL if we failed to allocate memory for the new node. + * @param pTab The table. + * @param pvItem The item which will be inserted if an matching item was not found in the table. + */ +DECLINLINE(void **) RTTabProbe(PRTTAB pTab, void *pvItem) +{ + return pTab->pOps->pfnProbe(pTab, pvItem); +} + +/** + * Inserts an item into the table, fail if a matching item exists. + * + * @returns NULL on success and allocation failure. + * @returns Pointer to the matching item. + * @param pTab The table. + * @param pvItem The item which is to be inserted. + */ +DECLINLINE(void *) RTTabInsert(PRTTAB pTab, void *pvItem) +{ + return pTab->pOps->pfnInsert(pTab, pvItem); +} + +/** + * Inserts an item into the table, if a matching item is encountered + * it will be replaced and returned. + * + * @returns NULL if inserted and allocation failure. + * @returns Pointer to the replaced item. + * @param pTab The table. + * @param pvItem The item which is to be inserted. + */ +DECLINLINE(void *) RTTabReplace(PRTTAB pTab, void *pvItem) +{ + return pTab->pOps->pfnReplace(pTab, pvItem); +} + +/** + * Removes an item from the table if found. + * + * @returns Pointer to the removed item. + * @returns NULL if no item matched pvItem. + * @param pTab The table. + * @param pvItem The item which is to be inserted. + */ +DECLINLINE(void *) RTTabRemove(PRTTAB pTab, const void *pvItem) +{ + return pTab->pOps->pfnRemove(pTab, pvItem); +} + +/** + * Finds an item in the table. + * + * @returns Pointer to the item it found. + * @returns NULL if no item matched pvItem. + * @param pTab The table. + * @param pvItem The item to find the match to. + */ +DECLINLINE(void *) RTTabFind(PRTTAB pTab, const void *pvItem) +{ + return pTab->pOps->pfnFind(pTab, pvItem); +} + + +/** + * Common traverser core. + */ +typedef struct RTTABTRAVERSERCORE +{ + /** The table being traversed. */ + PRTTAB pTab; + /** Indicates that this traverser was allocated. */ + bool fAllocated; + /** The table generation id this traverser was last updated for. + * This is used to catch up with table changes. */ + RTUINT idGeneration; +} RTTABTRAVERSERCORE; + +/** + * Generic traverser structure. + * + * Tree implementations will use the tree specific part by mapping + * this structure onto their own internal traverser structure. + * + * @remark It would be better to use alloca() for allocating the structure, + * OTOH this is simpler for the user. + */ +typedef struct RTTABTRAVERSER +{ + /** The common core of the traverser data. */ + RTTABTRAVERSERCORE Core; + /** The tree specific data. */ + void *apvTreeSpecific[32]; +} RTTABTRAVERSER; + + +/** + * Initializes a traverser to the NULL item. + * + * The NULL item is an imaginary table item before the first and after + * the last items in the table. + * + * @returns Pointer to the traverser positioned at the NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + */ +DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravInit(PRTTAB pTab, PRTTABTRAVERSER pTravNew) +{ + return pTab->pOps->pfnTravInit(pTab, pTravNew); +} + +/** + * Initializes a traverser to the first item in the table. + * + * If the table is empty, the traverser will be positioned at the NULL item + * like with RTTabTravInit(). + * + * @returns Pointer to the traverser positioned at the first item or NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + */ +DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravFirst(PRTTAB pTab, PRTTABTRAVERSER pTravNew) +{ + return pTab->pOps->pfnTravFirst(pTab, pTravNew); +} + +/** + * Initializes a traverser to the last item in the table. + * + * If the table is empty, the traverser will be positioned at the NULL item + * like with RTTabTravInit(). + * + * @returns Pointer to the traverser positioned at the last item or NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + */ +DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravLast(PRTTAB pTab, PRTTABTRAVERSER pTravNew) +{ + return pTab->pOps->pfnTravLast(pTab, pTravNew); +} + +/** + * Initializes a traverser to an item matching the given one. + * + * If the item isn't found, the traverser will be positioned at the NULL item + * like with RTTabTravInit(). + * + * @returns Pointer to the traverser positioned at the matching item or NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + * @param pvItem The item to find the match to. + */ +DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravFind(PRTTAB pTab, PRTTABTRAVERSER pTravNew, const void *pvItem) +{ + return pTab->pOps->pfnTravFind(pTab, pTravNew, pvItem); +} + +/** + * Initializes a traverser to the inserted item. + * + * If there already exists an item in the tree matching pvItem, the traverser + * is positioned at that item like with RTTabTravFind(). + * + * If the insert operation failes because of an out of memory condition, the + * traverser will be positioned at the NULL item like with RTTabTravInit(). + * + * @returns Pointer to the traverser positioned at the inserted, existing or NULL item. + * @returns NULL on failure to allocate the traverser. + * + * @param pTab The table. + * @param pTravNew Pointer to a preallocated structure. Optional. + * @param pvItem The item to be inserted. + */ +DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravInsert(PRTTAB pTab, PRTTABTRAVERSER pTravNew, void *pvItem) +{ + return pTab->pOps->pfnTravInsert(pTab, pTravNew, pvItem); +} + +/** + * Duplicates a traverser. + * + * @returns The pointer to the duplicate. + * @returns NULL on allocation failure. + * + * @param pTrav The traverser to duplicate. + * @param pTravNew Pointer to a preallocated structure. Optional. + */ +DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravDuplicate(PRTTABTRAVERSERCORE pTrav, PCRTTABTRAVERSER pTravNew) +{ + if (pTrav) + return pTrav->pTab->pOps->pfnTravDuplicate(pTrav, pTravNew); + return NULL; +} + +/** + * Frees a traverser. + * + * This can safely be called even if the traverser structure + * wasn't dynamically allocated or the constructor failed. + * + * @param pTrav The traverser which is to be free. + */ +DECLINLINE(void) RTTabTravFree(PRTTABTRAVERSERCORE pTrav) +{ + if (pTrav && pTrav->fAllocated) + pTrav->pTab->pOps->pfnTravFree(pTrav); +} + +/** + * Gets the current item. + * + * @returns The current item. (NULL indicates the imaginary NULL item.) + * @param pTrav The traverser. + */ +DECLINLINE(void *) RTTabTravCur(PCRTTABTRAVERSERCORE pTrav) +{ + return pTrav->pTab->pOps->pfnTravCur(pTrav); +} + +/** + * Advances to the next item. + * + * @returns The new current item. (NULL indicates the imaginary NULL item.) + * @param pTrav The traverser. + */ +DECLINLINE(void *) RTTabTravNext(PRTTABTRAVERSERCORE pTrav) +{ + return pTrav->pTab->pOps->pfnTravNext(pTrav); +} + +/** + * Advances to the previous item. + * + * @returns The new current item. (NULL indicates the imaginary NULL item.) + * @param pTrav The traverser. + */ +DECLINLINE(void *) RTTabTravPrev(PRTTABTRAVERSERCORE pTrav) +{ + return pTrav->pTab->pOps->pfnTravPrev(pTrav); +} + +/** + * Replaces the current item. + * + * This has the same restrictions as RTTabProbe(), e.g. it's not permitted to + * break the order of the table. + * + * @returns The replaced item. + * @returns NULL if the current item is the NULL item. The traverser + * and table remains unchanged. + * @param pTrav The traverser. + * @param pvItem The item to be inserted. + */ +DECLINLINE(void *) RTTabTravReplace(PRTTABTRAVERSERCORE pTrav, void *pvItem) +{ + return pTrav->pTab->pOps->pfnTravReplace(pTrav, pvItem); +} + +RT_C_DECLS_END + +/** @} */ + +#endif diff --git a/include/iprt/tar.h b/include/iprt/tar.h new file mode 100644 index 00000000..96fad7a6 --- /dev/null +++ b/include/iprt/tar.h @@ -0,0 +1,456 @@ +/** @file + * IPRT - Tar archive I/O. + */ + +/* + * Copyright (C) 2009-2010 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. + */ + +#ifndef ___iprt_tar_h +#define ___iprt_tar_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/time.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_tar RTTar - Tar archive I/O + * @ingroup grp_rt + * @{ + */ + +/** A tar handle */ +typedef R3PTRTYPE(struct RTTARINTERNAL *) RTTAR; +/** Pointer to a RTTAR interface handle. */ +typedef RTTAR *PRTTAR; +/** Nil RTTAR interface handle. */ +#define NIL_RTTAR ((RTTAR)0) + +/** A tar file handle */ +typedef R3PTRTYPE(struct RTTARFILEINTERNAL *) RTTARFILE; +/** Pointer to a RTTARFILE interface handle. */ +typedef RTTARFILE *PRTTARFILE; +/** Nil RTTARFILE interface handle. */ +#define NIL_RTTARFILE ((RTTARFILE)0) + +/** + * Opens a Tar archive. + * + * Use the mask to specify the access type. In create mode the target file + * have not to exists. + * + * @returns IPRT status code. + * + * @param phTar Where to store the RTTAR handle. + * @param pszTarname The file name of the tar archive to open. + * @param fMode Open flags, i.e a combination of the RTFILE_O_* defines. + * The ACCESS, ACTION and DENY flags are mandatory! + * @param fStream Open the file in stream mode. Within this mode no + * seeking is allowed. Use this together with + * RTTarFileCurrent, RTTarFileOpenCurrent, + * RTTarFileSeekNextFile and the read method to + * sequential read a tar file. Currently ignored with + * RTFILE_O_WRITE. + */ +RTR3DECL(int) RTTarOpen(PRTTAR phTar, const char *pszTarname, uint32_t fMode, bool fStream); + +#if 0 +/** + * Opens a Tar archive by handle. + * + * Use the mask to specify the access type. In create mode the target file + * have not to exists. + * + * @returns IPRT status code. + * + * @param phTar Where to store the RTTAR handle. + * @param hFile The file handle of the tar file. This is expected + * to be a regular file at the moment. + * @param fStream Open the file in stream mode. Within this mode no + * seeking is allowed. Use this together with + * RTTarFileCurrent, RTTarFileOpenCurrent, + * RTTarFileSeekNextFile and the read method to + * sequential read a tar file. Currently ignored with + * RTFILE_O_WRITE. + */ +RTR3DECL(int) RTTarOpenByHandle(PRTTAR phTar, RTFILE hFile, uint32_t fMode, bool fStream); +#endif + +/** + * Close the Tar archive. + * + * @returns IPRT status code. + * + * @param hTar Handle to the RTTAR interface. + */ +RTR3DECL(int) RTTarClose(RTTAR hTar); + +/** + * Open a file in the Tar archive. + * + * @returns IPRT status code. + * + * @param hTar The handle of the tar archive. + * @param phFile Where to store the handle to the opened file. + * @param pszFilename Path to the file which is to be opened. (UTF-8) + * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines. + * The ACCESS, ACTION flags are mandatory! DENY flags + * are currently not supported. + * + * @remarks Write mode means append mode only. It is not possible to make + * changes to existing files. + * + * @remarks Currently it is not possible to open more than one file in write + * mode. Although open more than one file in read only mode (even when + * one file is opened in write mode) is always possible. + */ +RTR3DECL(int) RTTarFileOpen(RTTAR hTar, PRTTARFILE phFile, const char *pszFilename, uint32_t fOpen); + +/** + * Close the file opened by RTTarFileOpen. + * + * @returns IPRT status code. + * + * @param hFile The file handle to close. + */ +RTR3DECL(int) RTTarFileClose(RTTARFILE hFile); + +/** + * Changes the read & write position in a file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param offSeek Offset to seek. + * @param uMethod Seek method, i.e. one of the RTFILE_SEEK_* defines. + * @param poffActual Where to store the new file position. + * NULL is allowed. + */ +RTR3DECL(int) RTTarFileSeek(RTTARFILE hFile, uint64_t offSeek, unsigned uMethod, uint64_t *poffActual); + +/** + * Gets the current file position. + * + * @returns File offset. + * @returns UINT64_MAX on failure. + * + * @param hFile Handle to the file. + */ +RTR3DECL(uint64_t) RTTarFileTell(RTTARFILE hFile); + +/** + * Read bytes from a file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param pvBuf Where to put the bytes we read. + * @param cbToRead How much to read. + * @param *pcbRead How much we actually read . + * If NULL an error will be returned for a partial read. + */ +RTR3DECL(int) RTTarFileRead(RTTARFILE hFile, void *pvBuf, size_t cbToRead, size_t *pcbRead); + +/** + * Read bytes from a file at a given offset. + * This function may modify the file position. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param off Where to read. + * @param pvBuf Where to put the bytes we read. + * @param cbToRead How much to read. + * @param *pcbRead How much we actually read . + * If NULL an error will be returned for a partial read. + */ +RTR3DECL(int) RTTarFileReadAt(RTTARFILE hFile, uint64_t off, void *pvBuf, size_t cbToRead, size_t *pcbRead); + +/** + * Write bytes to a file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param pvBuf What to write. + * @param cbToWrite How much to write. + * @param *pcbWritten How much we actually wrote. + * If NULL an error will be returned for a partial write. + */ +RTR3DECL(int) RTTarFileWrite(RTTARFILE hFile, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten); + +/** + * Write bytes to a file at a given offset. + * This function may modify the file position. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param off Where to write. + * @param pvBuf What to write. + * @param cbToWrite How much to write. + * @param *pcbWritten How much we actually wrote. + * If NULL an error will be returned for a partial write. + */ +RTR3DECL(int) RTTarFileWriteAt(RTTARFILE hFile, uint64_t off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten); + +/** + * Query the size of the file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param pcbSize Where to store the filesize. + */ +RTR3DECL(int) RTTarFileGetSize(RTTARFILE hFile, uint64_t *pcbSize); + +/** + * Set the size of the file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param cbSize The new file size. + */ +RTR3DECL(int) RTTarFileSetSize(RTTARFILE hFile, uint64_t cbSize); + +/** + * Gets the mode flags of an open file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param pfMode Where to store the file mode, see @ref grp_rt_fs for details. + */ +RTR3DECL(int) RTTarFileGetMode(RTTARFILE hFile, uint32_t *pfMode); + +/** + * Changes the mode flags of an open file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param fMode The new file mode, see @ref grp_rt_fs for details. + */ +RTR3DECL(int) RTTarFileSetMode(RTTARFILE hFile, uint32_t fMode); + +/** + * Gets the modification timestamp of the file. + * + * @returns IPRT status code. + * + * @param pFile Handle to the file. + * @param pTime Where to store the time. + */ +RTR3DECL(int) RTTarFileGetTime(RTTARFILE hFile, PRTTIMESPEC pTime); + +/** + * Sets the modification timestamp of the file. + * + * @returns IPRT status code. + * + * @param pFile Handle to the file. + * @param pTime The time to store. + */ +RTR3DECL(int) RTTarFileSetTime(RTTARFILE hFile, PRTTIMESPEC pTime); + +/** + * Gets the owner and/or group of an open file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param pUid Where to store the owner user id. NULL is ok. + * @param pGid Where to store the group id. NULL is ok. + */ +RTR3DECL(int) RTTarFileGetOwner(RTTARFILE hFile, uint32_t *pUid, uint32_t *pGid); + +/** + * Changes the owner and/or group of an open file. + * + * @returns IPRT status code. + * + * @param hFile Handle to the file. + * @param uid The new file owner user id. Use -1 (or ~0) to leave this unchanged. + * @param gid The new group id. Use -1 (or ~0) to leave this unchanged. + */ +RTR3DECL(int) RTTarFileSetOwner(RTTARFILE hFile, uint32_t uid, uint32_t gid); + +/****************************************************************************** + * Convenience Functions * + ******************************************************************************/ + +/** + * Check if the specified file exists in the Tar archive. + * + * (The matching is case sensitive.) + * + * @note Currently only regular files are supported. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS when the file exists in the Tar archive. + * @retval VERR_FILE_NOT_FOUND when the file not exists in the Tar archive. + * + * @param pszTarFile Tar file to check. + * @param pszFile Filename to check for. + * + * @todo This is predicate function which SHALL return bool! + */ +RTR3DECL(int) RTTarFileExists(const char *pszTarFile, const char *pszFile); + +/** + * Create a file list from a Tar archive. + * + * @note Currently only regular files are supported. + * + * @returns IPRT status code. + * + * @param pszTarFile Tar file to list files from. + * @param ppapszFiles On success an array with array with the filenames is + * returned. The names must be freed with RTStrFree and + * the array with RTMemFree. + * @param pcFiles On success the number of entries in ppapszFiles. + */ +RTR3DECL(int) RTTarList(const char *pszTarFile, char ***ppapszFiles, size_t *pcFiles); + +/** + * Extract a file from a Tar archive into a memory buffer. + * + * The caller is responsible for the deletion of the returned memory buffer. + * + * (The matching is case sensitive.) + * + * @note Currently only regular files are supported. Also some of the header + * fields are not used (uid, gid, uname, gname, mtime). + * + * @returns IPRT status code. + * + * @param pszTarFile Tar file to extract files from. + * @param ppBuf The buffer which will held the extracted data. + * @param pcbSize The size (in bytes) of ppBuf after successful + * extraction. + * @param pszFile The file to extract. + * @param pfnProgressCallback Progress callback function. Optional. + * @param pvUser User defined data for the progress + * callback. Optional. + */ +RTR3DECL(int) RTTarExtractFileToBuf(const char *pszTarFile, void **ppvBuf, size_t *pcbSize, const char *pszFile, + PFNRTPROGRESS pfnProgressCallback, void *pvUser); + +/** + * Extract a set of files from a Tar archive. + * + * Also note that this function is atomic. If an error occurs all previously + * extracted files will be deleted. + * + * (The matching is case sensitive.) + * + * @note Currently only regular files are supported. Also some of the header + * fields are not used (uid, gid, uname, gname, mtime). + * + * @returns IPRT status code. + * + * @param pszTarFile Tar file to extract files from. + * @param pszOutputDir Where to store the extracted files. Must exist. + * @param papszFiles Which files should be extracted. + * @param cFiles The number of files in papszFiles. + * @param pfnProgressCallback Progress callback function. Optional. + * @param pvUser User defined data for the progress + * callback. Optional. + */ +RTR3DECL(int) RTTarExtractFiles(const char *pszTarFile, const char *pszOutputDir, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser); + +/** + * Extract all files of the archive. + * + * @note Currently only regular files are supported. Also some of the header + * fields are not used (uid, gid, uname, gname, mtime). + * + * @returns IPRT status code. + * + * @param pszTarFile Tar file to extract the files from. + * @param pszOutputDir Where to store the extracted files. Must exist. + * @param pfnProgressCallback Progress callback function. Optional. + * @param pvUser User defined data for the progress + * callback. Optional. + */ +RTR3DECL(int) RTTarExtractAll(const char *pszTarFile, const char *pszOutputDir, PFNRTPROGRESS pfnProgressCallback, void *pvUser); + +/** + * Create a Tar archive out of the given files. + * + * @note Currently only regular files are supported. + * + * @returns IPRT status code. + * + * @param pszTarFile Where to create the Tar archive. + * @param papszFiles Which files should be included. + * @param cFiles The number of files in papszFiles. + * @param pfnProgressCallback Progress callback function. Optional. + * @param pvUser User defined data for the progress + * callback. Optional. + */ +RTR3DECL(int) RTTarCreate(const char *pszTarFile, const char * const *papszFiles, size_t cFiles, PFNRTPROGRESS pfnProgressCallback, void *pvUser); + +/****************************************************************************** + * Streaming Functions * + ******************************************************************************/ + +/** + * Return the filename where RTTar currently stays at. + * + * @returns IPRT status code. + * + * @param hTar Handle to the RTTAR interface. + * @param ppszFilename On success the filename. + */ +RTR3DECL(int) RTTarCurrentFile(RTTAR hTar, char **ppszFilename); + +/** + * Jumps to the next file from the current RTTar position. + * + * @returns IPRT status code. + * + * @param hTar Handle to the RTTAR interface. + */ +RTR3DECL(int) RTTarSeekNextFile(RTTAR hTar); + +/** + * Opens the file where RTTar currently stays at. + * + * @returns IPRT status code. + * + * @param hTar Handle to the RTTAR interface. + * @param phFile Where to store the handle to the opened file. + * @param ppszFilename On success the filename. + * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines. + * The ACCESS, ACTION flags are mandatory! Currently + * only RTFILE_O_OPEN | RTFILE_O_READ is supported. + */ +RTR3DECL(int) RTTarFileOpenCurrentFile(RTTAR hTar, PRTTARFILE phFile, char **ppszFilename, uint32_t fOpen); + + +/** @} */ + +RT_C_DECLS_END + +#endif /* ___iprt_tar_h */ + diff --git a/include/iprt/tcp.h b/include/iprt/tcp.h new file mode 100644 index 00000000..32d7de45 --- /dev/null +++ b/include/iprt/tcp.h @@ -0,0 +1,443 @@ +/** @file + * IPRT - TCP/IP. + */ + +/* + * Copyright (C) 2006-2010 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. + */ + +#ifndef ___iprt_tcp_h +#define ___iprt_tcp_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/thread.h> +#include <iprt/net.h> +#include <iprt/sg.h> +#include <iprt/socket.h> + +#ifdef IN_RING0 +# error "There are no RTFile APIs available Ring-0 Host Context!" +#endif + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_tcp RTTcp - TCP/IP + * @ingroup grp_rt + * @{ + */ + + +/** + * Serve a TCP Server connection. + * + * @returns iprt status code. + * @returns VERR_TCP_SERVER_STOP to terminate the server loop forcing + * the RTTcpCreateServer() call to return. + * @param Sock The socket which the client is connected to. + * The call will close this socket. + * @param pvUser User argument. + */ +typedef DECLCALLBACK(int) FNRTTCPSERVE(RTSOCKET Sock, void *pvUser); +/** Pointer to a RTTCPSERVE(). */ +typedef FNRTTCPSERVE *PFNRTTCPSERVE; + +/** + * Create single connection at a time TCP Server in a separate thread. + * + * The thread will loop accepting connections and call pfnServe for + * each of the incoming connections in turn. The pfnServe function can + * return VERR_TCP_SERVER_STOP too terminate this loop. RTTcpServerDestroy() + * should be used to terminate the server. + * + * @returns iprt status code. + * @param pszAddress The address for creating a listening socket. + * If NULL or empty string the server is bound to all interfaces. + * @param uPort The port for creating a listening socket. + * @param enmType The thread type. + * @param pszThrdName The name of the worker thread. + * @param pfnServe The function which will serve a new client connection. + * @param pvUser User argument passed to pfnServe. + * @param ppServer Where to store the serverhandle. + */ +RTR3DECL(int) RTTcpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName, + PFNRTTCPSERVE pfnServe, void *pvUser, PPRTTCPSERVER ppServer); + +/** + * Create single connection at a time TCP Server. + * The caller must call RTTcpServerListen() to actually start the server. + * + * @returns iprt status code. + * @param pszAddress The address for creating a listening socket. + * If NULL the server is bound to all interfaces. + * @param uPort The port for creating a listening socket. + * @param ppServer Where to store the serverhandle. + */ +RTR3DECL(int) RTTcpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTTCPSERVER ppServer); + +/** + * Closes down and frees a TCP Server. + * This will also terminate any open connections to the server. + * + * @returns iprt status code. + * @param pServer Handle to the server. + */ +RTR3DECL(int) RTTcpServerDestroy(PRTTCPSERVER pServer); + +/** + * Listen for incoming connections. + * + * The function will loop accepting connections and call pfnServe for + * each of the incoming connections in turn. The pfnServe function can + * return VERR_TCP_SERVER_STOP too terminate this loop. A stopped server + * can only be destroyed. + * + * @returns iprt status code. + * @param pServer The server handle as returned from RTTcpServerCreateEx(). + * @param pfnServe The function which will serve a new client connection. + * @param pvUser User argument passed to pfnServe. + */ +RTR3DECL(int) RTTcpServerListen(PRTTCPSERVER pServer, PFNRTTCPSERVE pfnServe, void *pvUser); + +/** + * Listen and accept one incoming connection. + * + * This is an alternative to RTTcpServerListen for the use the callbacks are not + * possible. + * + * @returns IPRT status code. + * @retval VERR_TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown. + * @retval VERR_INTERRUPTED if the listening was interrupted. + * + * @param pServer The server handle as returned from RTTcpServerCreateEx(). + * @param phClientSocket Where to return the socket handle to the client + * connection (on success only). This must be closed + * by calling RTTcpServerDisconnectClient2(). + */ +RTR3DECL(int) RTTcpServerListen2(PRTTCPSERVER pServer, PRTSOCKET phClientSocket); + +/** + * Terminate the open connection to the server. + * + * @returns iprt status code. + * @param pServer Handle to the server. + */ +RTR3DECL(int) RTTcpServerDisconnectClient(PRTTCPSERVER pServer); + +/** + * Terminates an open client connect when using RTTcpListen2 + * + * @returns IPRT status code. + * @param hClientSocket The client socket handle. This will be invalid upon + * return, whether successful or not. NIL is quietly + * ignored (VINF_SUCCESS). + */ +RTR3DECL(int) RTTcpServerDisconnectClient2(RTSOCKET hClientSocket); + +/** + * Shuts down the server, leaving client connections open. + * + * @returns IPRT status code. + * @param pServer Handle to the server. + */ +RTR3DECL(int) RTTcpServerShutdown(PRTTCPSERVER pServer); + +/** + * Connect (as a client) to a TCP Server. + * + * @returns iprt status code. + * @param pszAddress The address to connect to. + * @param uPort The port to connect to. + * @param pSock Where to store the handle to the established connection. + */ +RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock); + +/** + * Close a socket returned by RTTcpClientConnect(). + * + * @returns iprt status code. + * @param Sock Socket descriptor. + */ +RTR3DECL(int) RTTcpClientClose(RTSOCKET Sock); + +/** + * Close a socket returned by RTTcpClientConnect(). + * + * @returns iprt status code. + * @param hSocket The socket handle. + * @param fGracefulShutdown If true, try do a graceful shutdown of the + * outgoing pipe and draining any lingering input. + * This is sometimes better for the server side. + * If false, just close the connection without + * further ado. + */ +RTR3DECL(int) RTTcpClientCloseEx(RTSOCKET Sock, bool fGracefulShutdown); + +/** + * Receive data from a socket. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + * @param pvBuffer Where to put the data we read. + * @param cbBuffer Read buffer size. + * @param pcbRead Number of bytes read. + * If NULL the entire buffer will be filled upon successful return. + * If not NULL a partial read can be done successfully. + */ +RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead); + +/** + * Send data to a socket. + * + * @returns iprt status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param Sock Socket descriptor. + * @param pvBuffer Buffer to write data to socket. + * @param cbBuffer How much to write. + */ +RTR3DECL(int) RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer); + +/** + * Flush socket write buffers. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + */ +RTR3DECL(int) RTTcpFlush(RTSOCKET Sock); + +/** + * Enables or disables delaying sends to coalesce packets. + * + * The TCP/IP stack usually uses the Nagle algorithm (RFC 896) to implement the + * coalescing. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + * @param fEnable When set to true enables coalescing. + */ +RTR3DECL(int) RTTcpSetSendCoalescing(RTSOCKET Sock, bool fEnable); + +/** + * Socket I/O multiplexing. + * Checks if the socket is ready for reading. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + * @param cMillies Number of milliseconds to wait for the socket. + * Use RT_INDEFINITE_WAIT to wait for ever. + */ +RTR3DECL(int) RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies); + +/** + * Socket I/O multiplexing + * Checks if the socket is ready for one of the given events. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + * @param fEvents Event mask to wait for. + * Use the RTSOCKET_EVT_* defines. + * @param pfEvents Where to store the event mask on return. + * @param cMillies Number of milliseconds to wait for the socket. + * Use RT_INDEFINITE_WAIT to wait for ever. + */ +RTR3DECL(int) RTTcpSelectOneEx(RTSOCKET Sock, uint32_t fEvents, uint32_t *pfEvents, + RTMSINTERVAL cMillies); + +#if 0 /* skipping these for now - RTTcpServer* handles this. */ +/** + * Listen for connection on a socket. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + * @param cBackLog The maximum length the queue of pending connections + * may grow to. + */ +RTR3DECL(int) RTTcpListen(RTSOCKET Sock, int cBackLog); + +/** + * Accept a connection on a socket. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + * @param uPort The port for accepting connection. + * @param pSockAccepted Where to store the handle to the accepted connection. + */ +RTR3DECL(int) RTTcpAccept(RTSOCKET Sock, unsigned uPort, PRTSOCKET pSockAccepted); + +#endif + +/** + * Gets the address of the local side. + * + * @returns IPRT status code. + * @param Sock Socket descriptor. + * @param pAddr Where to store the local address on success. + */ +RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr); + +/** + * Gets the address of the other party. + * + * @returns IPRT status code. + * @param Sock Socket descriptor. + * @param pAddr Where to store the peer address on success. + */ +RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr); + +/** + * Send data from a scatter/gather buffer to a socket. + * + * @returns iprt status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param Sock Socket descriptor. + * @param pSgBuf Scatter/gather buffer to write data to socket. + */ +RTR3DECL(int) RTTcpSgWrite(RTSOCKET Sock, PCRTSGBUF pSgBuf); + + +/** + * Send data from multiple buffers to a socket. + * + * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls + * for lazy coders. The "L" in the function name is short for "list" just like + * in the execl libc API. + * + * @returns IPRT status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param hSocket The socket handle. + * @param cSegs The number of data segments in the following + * ellipsis. + * @param ... Pairs of buffer pointers (void const *) and buffer + * sizes (size_t). Make 101% sure the pointer is + * really size_t. + */ +RTR3DECL(int) RTTcpSgWriteL(RTSOCKET hSocket, size_t cSegs, ...); + +/** + * Send data from multiple buffers to a socket. + * + * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls + * for lazy coders. The "L" in the function name is short for "list" just like + * in the execl libc API. + * + * @returns IPRT status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param hSocket The socket handle. + * @param cSegs The number of data segments in the following + * argument list. + * @param va Pairs of buffer pointers (void const *) and buffer + * sizes (size_t). Make 101% sure the pointer is + * really size_t. + */ +RTR3DECL(int) RTTcpSgWriteLV(RTSOCKET hSocket, size_t cSegs, va_list va); + +/** + * Receive data from a socket. + * + * This version doesn't block if there is no data on the socket. + * + * @returns IPRT status code. + * + * @param Sock Socket descriptor. + * @param pvBuffer Where to put the data we read. + * @param cbBuffer Read buffer size. + * @param pcbRead Number of bytes read. + */ +RTR3DECL(int) RTTcpReadNB(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead); + +/** + * Send data to a socket. + * + * This version doesn't block if there is not enough room for the message. + * + * @returns IPRT status code. + * + * @param Sock Socket descriptor. + * @param pvBuffer Buffer to write data to socket. + * @param cbBuffer How much to write. + * @param pcbWritten Number of bytes written. + */ +RTR3DECL(int) RTTcpWriteNB(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten); + +/** + * Send data from a scatter/gather buffer to a socket. + * + * This version doesn't block if there is not enough room for the message. + * + * @returns iprt status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param Sock Socket descriptor. + * @param pSgBuf Scatter/gather buffer to write data to socket. + * @param pcbWritten Number of bytes written. + */ +RTR3DECL(int) RTTcpSgWriteNB(RTSOCKET Sock, PCRTSGBUF pSgBuf, size_t *pcbWritten); + + +/** + * Send data from multiple buffers to a socket. + * + * This version doesn't block if there is not enough room for the message. + * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls + * for lazy coders. The "L" in the function name is short for "list" just like + * in the execl libc API. + * + * @returns IPRT status code. + * + * @param hSocket The socket handle. + * @param cSegs The number of data segments in the following + * ellipsis. + * @param pcbWritten Number of bytes written. + * @param ... Pairs of buffer pointers (void const *) and buffer + * sizes (size_t). Make 101% sure the pointer is + * really size_t. + */ +RTR3DECL(int) RTTcpSgWriteLNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, ...); + +/** + * Send data from multiple buffers to a socket. + * + * This version doesn't block if there is not enough room for the message. + * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls + * for lazy coders. The "L" in the function name is short for "list" just like + * in the execl libc API. + * + * @returns IPRT status code. + * + * @param hSocket The socket handle. + * @param cSegs The number of data segments in the following + * argument list. + * @param pcbWritten Number of bytes written. + * @param va Pairs of buffer pointers (void const *) and buffer + * sizes (size_t). Make 101% sure the pointer is + * really size_t. + */ +RTR3DECL(int) RTTcpSgWriteLVNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, va_list va); + +/** @} */ +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/test.h b/include/iprt/test.h new file mode 100644 index 00000000..c004ab4f --- /dev/null +++ b/include/iprt/test.h @@ -0,0 +1,1200 @@ +/** @file + * IPRT - Testcase Framework. + */ + +/* + * Copyright (C) 2009 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. + */ + +#ifndef ___iprt_test_h +#define ___iprt_test_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_test RTTest - Testcase Framework. + * @ingroup grp_rt + * @{ + */ + +/** A test handle. */ +typedef struct RTTESTINT *RTTEST; +/** A pointer to a test handle. */ +typedef RTTEST *PRTTEST; +/** A const pointer to a test handle. */ +typedef RTTEST const *PCRTTEST; + +/** A NIL Test handle. */ +#define NIL_RTTEST ((RTTEST)0) + +/** + * Test message importance level. + */ +typedef enum RTTESTLVL +{ + /** Invalid 0. */ + RTTESTLVL_INVALID = 0, + /** Message should always be printed. */ + RTTESTLVL_ALWAYS, + /** Failure message. */ + RTTESTLVL_FAILURE, + /** Sub-test banner. */ + RTTESTLVL_SUB_TEST, + /** Info message. */ + RTTESTLVL_INFO, + /** Debug message. */ + RTTESTLVL_DEBUG, + /** The last (invalid). */ + RTTESTLVL_END +} RTTESTLVL; + + +/** + * Creates a test instance. + * + * @returns IPRT status code. + * @param pszTest The test name. + * @param phTest Where to store the test instance handle. + */ +RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest); + +/** + * Initializes IPRT and creates a test instance. + * + * Typical usage is: + * @code + int main(int argc, char **argv) + { + RTTEST hTest; + int rc = RTTestInitAndCreate("tstSomething", &hTest); + if (rc) + return rc; + ... + } + @endcode + * + * @returns RTEXITCODE_SUCCESS on success. On failure an error message is + * printed and a suitable exit code is return. + * + * @param pszTest The test name. + * @param phTest Where to store the test instance handle. + */ +RTR3DECL(RTEXITCODE) RTTestInitAndCreate(const char *pszTest, PRTTEST phTest); + +/** + * Destroys a test instance previously created by RTTestCreate. + * + * @returns IPRT status code. + * @param hTest The test handle. NIL_RTTEST is ignored. + */ +RTR3DECL(int) RTTestDestroy(RTTEST hTest); + +/** + * Changes the default test instance for the calling thread. + * + * @returns IPRT status code. + * + * @param hNewDefaultTest The new default test. NIL_RTTEST is fine. + * @param phOldTest Where to store the old test handle. Optional. + */ +RTR3DECL(int) RTTestSetDefault(RTTEST hNewDefaultTest, PRTTEST phOldTest); + +/** + * Allocate a block of guarded memory. + * + * @returns IPRT status code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param cb The amount of memory to allocate. + * @param cbAlign The alignment of the returned block. + * @param fHead Head or tail optimized guard. + * @param ppvUser Where to return the pointer to the block. + */ +RTR3DECL(int) RTTestGuardedAlloc(RTTEST hTest, size_t cb, uint32_t cbAlign, bool fHead, void **ppvUser); + +/** + * Allocates a block of guarded memory where the guarded is immediately after + * the user memory. + * + * @returns Pointer to the allocated memory. NULL on failure. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param cb The amount of memory to allocate. + */ +RTR3DECL(void *) RTTestGuardedAllocTail(RTTEST hTest, size_t cb); + +/** + * Allocates a block of guarded memory where the guarded is right in front of + * the user memory. + * + * @returns Pointer to the allocated memory. NULL on failure. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param cb The amount of memory to allocate. + */ +RTR3DECL(void *) RTTestGuardedAllocHead(RTTEST hTest, size_t cb); + +/** + * Frees a block of guarded memory. + * + * @returns IPRT status code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pv The memory. NULL is ignored. + */ +RTR3DECL(int) RTTestGuardedFree(RTTEST hTest, void *pv); + +/** + * Test vprintf making sure the output starts on a new line. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param enmLevel Message importance level. + * @param pszFormat The message. + * @param va Arguments. + */ +RTR3DECL(int) RTTestPrintfNlV(RTTEST hTest, RTTESTLVL enmLevel, const char *pszFormat, va_list va); + +/** + * Test printf making sure the output starts on a new line. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param enmLevel Message importance level. + * @param pszFormat The message. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestPrintfNl(RTTEST hTest, RTTESTLVL enmLevel, const char *pszFormat, ...); + +/** + * Test vprintf, makes sure lines are prefixed and so forth. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param enmLevel Message importance level. + * @param pszFormat The message. + * @param va Arguments. + */ +RTR3DECL(int) RTTestPrintfV(RTTEST hTest, RTTESTLVL enmLevel, const char *pszFormat, va_list va); + +/** + * Test printf, makes sure lines are prefixed and so forth. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param enmLevel Message importance level. + * @param pszFormat The message. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestPrintf(RTTEST hTest, RTTESTLVL enmLevel, const char *pszFormat, ...); + +/** + * Prints the test banner. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + */ +RTR3DECL(int) RTTestBanner(RTTEST hTest); + +/** + * Summaries the test, destroys the test instance and return an exit code. + * + * @returns Test program exit code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + */ +RTR3DECL(RTEXITCODE) RTTestSummaryAndDestroy(RTTEST hTest); + +/** + * Skips the test, destroys the test instance and return an exit code. + * + * @returns Test program exit code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszReasonFmt Text explaining why, optional (NULL). + * @param va Arguments for the reason format string. + */ +RTR3DECL(RTEXITCODE) RTTestSkipAndDestroyV(RTTEST hTest, const char *pszReasonFmt, va_list va); + +/** + * Skips the test, destroys the test instance and return an exit code. + * + * @returns Test program exit code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszReasonFmt Text explaining why, optional (NULL). + * @param ... Arguments for the reason format string. + */ +RTR3DECL(RTEXITCODE) RTTestSkipAndDestroy(RTTEST hTest, const char *pszReasonFmt, ...); + +/** + * Starts a sub-test. + * + * This will perform an implicit RTTestSubDone() call if that has not been done + * since the last RTTestSub call. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszSubTest The sub-test name. + */ +RTR3DECL(int) RTTestSub(RTTEST hTest, const char *pszSubTest); + +/** + * Format string version of RTTestSub. + * + * See RTTestSub for details. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszSubTestFmt The sub-test name format string. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestSubF(RTTEST hTest, const char *pszSubTestFmt, ...); + +/** + * Format string version of RTTestSub. + * + * See RTTestSub for details. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszSubTestFmt The sub-test name format string. + * @param va Arguments. + */ +RTR3DECL(int) RTTestSubV(RTTEST hTest, const char *pszSubTestFmt, va_list va); + +/** + * Completes a sub-test. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + */ +RTR3DECL(int) RTTestSubDone(RTTEST hTest); + +/** + * Prints an extended PASSED message, optional. + * + * This does not conclude the sub-test, it could be used to report the passing + * of a sub-sub-to-the-power-of-N-test. + * + * @returns IPRT status code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszFormat The message. No trailing newline. + * @param va The arguments. + */ +RTR3DECL(int) RTTestPassedV(RTTEST hTest, const char *pszFormat, va_list va); + +/** + * Prints an extended PASSED message, optional. + * + * This does not conclude the sub-test, it could be used to report the passing + * of a sub-sub-to-the-power-of-N-test. + * + * @returns IPRT status code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszFormat The message. No trailing newline. + * @param ... The arguments. + */ +RTR3DECL(int) RTTestPassed(RTTEST hTest, const char *pszFormat, ...); + +/** + * Value units. + */ +typedef enum RTTESTUNIT +{ + /** The usual invalid value. */ + RTTESTUNIT_INVALID = 0, + /** Percentage. */ + RTTESTUNIT_PCT, + /** Bytes. */ + RTTESTUNIT_BYTES, + /** Bytes per second. */ + RTTESTUNIT_BYTES_PER_SEC, + /** Kilobytes. */ + RTTESTUNIT_KILOBYTES, + /** Kilobytes per second. */ + RTTESTUNIT_KILOBYTES_PER_SEC, + /** Megabytes. */ + RTTESTUNIT_MEGABYTES, + /** Megabytes per second. */ + RTTESTUNIT_MEGABYTES_PER_SEC, + /** Packets. */ + RTTESTUNIT_PACKETS, + /** Packets per second. */ + RTTESTUNIT_PACKETS_PER_SEC, + /** Frames. */ + RTTESTUNIT_FRAMES, + /** Frames per second. */ + RTTESTUNIT_FRAMES_PER_SEC, + /** Occurrences. */ + RTTESTUNIT_OCCURRENCES, + /** Occurrences per second. */ + RTTESTUNIT_OCCURRENCES_PER_SEC, + /** Calls. */ + RTTESTUNIT_CALLS, + /** Calls per second. */ + RTTESTUNIT_CALLS_PER_SEC, + /** Round trips. */ + RTTESTUNIT_ROUND_TRIP, + /** Seconds. */ + RTTESTUNIT_SECS, + /** Milliseconds. */ + RTTESTUNIT_MS, + /** Nanoseconds. */ + RTTESTUNIT_NS, + /** Nanoseconds per call. */ + RTTESTUNIT_NS_PER_CALL, + /** Nanoseconds per frame. */ + RTTESTUNIT_NS_PER_FRAME, + /** Nanoseconds per occurrence. */ + RTTESTUNIT_NS_PER_OCCURRENCE, + /** Nanoseconds per frame. */ + RTTESTUNIT_NS_PER_PACKET, + /** Nanoseconds per round trip. */ + RTTESTUNIT_NS_PER_ROUND_TRIP, + /** The end of valid units. */ + RTTESTUNIT_END +} RTTESTUNIT; + +/** + * Report a named test result value. + * + * This is typically used for benchmarking but can be used for other purposes + * like reporting limits of some implementation. The value gets associated with + * the current sub test, the name must be unique within the sub test. + * + * @returns IPRT status code. + * + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszName The value name. + * @param u64Value The value. + * @param enmUnit The value unit. + */ +RTR3DECL(int) RTTestValue(RTTEST hTest, const char *pszName, uint64_t u64Value, RTTESTUNIT enmUnit); + +/** + * Same as RTTestValue, except that the name is now a format string. + * + * @returns IPRT status code. + * + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param u64Value The value. + * @param enmUnit The value unit. + * @param pszNameFmt The value name format string. + * @param ... String arguments. + */ +RTR3DECL(int) RTTestValueF(RTTEST hTest, uint64_t u64Value, RTTESTUNIT enmUnit, const char *pszNameFmt, ...); + +/** + * Same as RTTestValue, except that the name is now a format string. + * + * @returns IPRT status code. + * + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param u64Value The value. + * @param enmUnit The value unit. + * @param pszNameFmt The value name format string. + * @param va_list String arguments. + */ +RTR3DECL(int) RTTestValueV(RTTEST hTest, uint64_t u64Value, RTTESTUNIT enmUnit, const char *pszNameFmt, va_list va); + +/** + * Increments the error counter. + * + * @returns IPRT status code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + */ +RTR3DECL(int) RTTestErrorInc(RTTEST hTest); + +/** + * Get the current error count. + * + * @returns The error counter, UINT32_MAX if no valid test handle. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + */ +RTR3DECL(uint32_t) RTTestErrorCount(RTTEST hTest); + +/** + * Increments the error counter and prints a failure message. + * + * @returns IPRT status code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszFormat The message. No trailing newline. + * @param va The arguments. + */ +RTR3DECL(int) RTTestFailedV(RTTEST hTest, const char *pszFormat, va_list va); + +/** + * Increments the error counter and prints a failure message. + * + * @returns IPRT status code. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszFormat The message. No trailing newline. + * @param ... The arguments. + */ +RTR3DECL(int) RTTestFailed(RTTEST hTest, const char *pszFormat, ...); + +/** + * Same as RTTestPrintfV with RTTESTLVL_FAILURE. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszFormat The message. + * @param va Arguments. + */ +RTR3DECL(int) RTTestFailureDetailsV(RTTEST hTest, const char *pszFormat, va_list va); + +/** + * Same as RTTestPrintf with RTTESTLVL_FAILURE. + * + * @returns Number of chars printed. + * @param hTest The test handle. If NIL_RTTEST we'll use the one + * associated with the calling thread. + * @param pszFormat The message. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestFailureDetails(RTTEST hTest, const char *pszFormat, ...); + + +/** @def RTTEST_CHECK + * Check whether a boolean expression holds true. + * + * If the expression is false, call RTTestFailed giving the line number and expression. + * + * @param hTest The test handle. + * @param expr The expression to evaluate. + */ +#define RTTEST_CHECK(hTest, expr) \ + do { if (!(expr)) { \ + RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \ + } \ + } while (0) +/** @def RTTEST_CHECK_RET + * Check whether a boolean expression holds true, returns on false. + * + * If the expression is false, call RTTestFailed giving the line number and + * expression, then return @a rcRet. + * + * @param hTest The test handle. + * @param expr The expression to evaluate. + * @param rcRet What to return on failure. + */ +#define RTTEST_CHECK_RET(hTest, expr, rcRet) \ + do { if (!(expr)) { \ + RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \ + return (rcRet); \ + } \ + } while (0) +/** @def RTTEST_CHECK_RETV + * Check whether a boolean expression holds true, returns void on false. + * + * If the expression is false, call RTTestFailed giving the line number and + * expression, then return void. + * + * @param hTest The test handle. + * @param expr The expression to evaluate. + */ +#define RTTEST_CHECK_RETV(hTest, expr) \ + do { if (!(expr)) { \ + RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \ + return; \ + } \ + } while (0) +/** @def RTTEST_CHECK_BREAK + * Check whether a boolean expression holds true. + * + * If the expression is false, call RTTestFailed giving the line number and + * expression, then break. + * + * @param hTest The test handle. + * @param expr The expression to evaluate. + */ +#define RTTEST_CHECK_BREAK(hTest, expr) \ + if (!(expr)) { \ + RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \ + break; \ + } else do {} while (0) + + +/** @def RTTEST_CHECK_MSG + * Check whether a boolean expression holds true. + * + * If the expression is false, call RTTestFailed giving the line number and expression. + * + * @param hTest The test handle. + * @param expr The expression to evaluate. + * @param DetailsArgs Argument list for RTTestFailureDetails, including + * parenthesis. + */ +#define RTTEST_CHECK_MSG(hTest, expr, DetailsArgs) \ + do { if (!(expr)) { \ + RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \ + RTTestFailureDetails DetailsArgs; \ + } \ + } while (0) +/** @def RTTEST_CHECK_MSG_RET + * Check whether a boolean expression holds true, returns on false. + * + * If the expression is false, call RTTestFailed giving the line number and expression. + * + * @param hTest The test handle. + * @param expr The expression to evaluate. + * @param DetailsArgs Argument list for RTTestFailureDetails, including + * parenthesis. + * @param rcRet What to return on failure. + */ +#define RTTEST_CHECK_MSG_RET(hTest, expr, DetailsArgs, rcRet) \ + do { if (!(expr)) { \ + RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \ + RTTestFailureDetails DetailsArgs; \ + return (rcRet); \ + } \ + } while (0) +/** @def RTTEST_CHECK_MSG_RET + * Check whether a boolean expression holds true, returns void on false. + * + * If the expression is false, call RTTestFailed giving the line number and expression. + * + * @param hTest The test handle. + * @param expr The expression to evaluate. + * @param DetailsArgs Argument list for RTTestFailureDetails, including + * parenthesis. + */ +#define RTTEST_CHECK_MSG_RETV(hTest, expr, DetailsArgs) \ + do { if (!(expr)) { \ + RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \ + RTTestFailureDetails DetailsArgs; \ + return; \ + } \ + } while (0) + + +/** @def RTTEST_CHECK_RC + * Check whether an expression returns a specific IPRT style status code. + * + * If a different status code is return, call RTTestFailed giving the line + * number, expression, actual and expected status codes. + * + * @param hTest The test handle. + * @param rcExpr The expression resulting in an IPRT status code. + * @param rcExpect The expected return code. This may be referenced + * more than once by the macro. + */ +#define RTTEST_CHECK_RC(hTest, rcExpr, rcExpect) \ + do { \ + int rcCheck = (rcExpr); \ + if (rcCheck != (rcExpect)) { \ + RTTestFailed((hTest), "line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \ + } \ + } while (0) +/** @def RTTEST_CHECK_RC_RET + * Check whether an expression returns a specific IPRT style status code. + * + * If a different status code is return, call RTTestFailed giving the line + * number, expression, actual and expected status codes, then return. + * + * @param hTest The test handle. + * @param rcExpr The expression resulting in an IPRT status code. + * This will be assigned to a local rcCheck variable + * that can be used as return value. + * @param rcExpect The expected return code. This may be referenced + * more than once by the macro. + * @param rcRet The return code. + */ +#define RTTEST_CHECK_RC_RET(hTest, rcExpr, rcExpect, rcRet) \ + do { \ + int rcCheck = (rcExpr); \ + if (rcCheck != (rcExpect)) { \ + RTTestFailed((hTest), "line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \ + return (rcRet); \ + } \ + } while (0) +/** @def RTTEST_CHECK_RC_RETV + * Check whether an expression returns a specific IPRT style status code. + * + * If a different status code is return, call RTTestFailed giving the line + * number, expression, actual and expected status codes, then return. + * + * @param hTest The test handle. + * @param rcExpr The expression resulting in an IPRT status code. + * @param rcExpect The expected return code. This may be referenced + * more than once by the macro. + */ +#define RTTEST_CHECK_RC_RETV(hTest, rcExpr, rcExpect) \ + do { \ + int rcCheck = (rcExpr); \ + if (rcCheck != (rcExpect)) { \ + RTTestFailed((hTest), "line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \ + return; \ + } \ + } while (0) +/** @def RTTEST_CHECK_RC_BREAK + * Check whether an expression returns a specific IPRT style status code. + * + * If a different status code is return, call RTTestFailed giving the line + * number, expression, actual and expected status codes, then break. + * + * @param hTest The test handle. + * @param rcExpr The expression resulting in an IPRT status code. + * @param rcExpect The expected return code. This may be referenced + * more than once by the macro. + */ +#define RTTEST_CHECK_RC_BREAK(hTest, rcExpr, rcExpect) \ + if (1) { \ + int rcCheck = (rcExpr); \ + if (rcCheck != (rcExpect)) { \ + RTTestFailed((hTest), "line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \ + break; \ + } \ + } else do {} while (0) + + +/** @def RTTEST_CHECK_RC_OK + * Check whether a IPRT style status code indicates success. + * + * If the status indicates failure, call RTTestFailed giving the line number, + * expression and status code. + * + * @param hTest The test handle. + * @param rcExpr The expression resulting in an IPRT status code. + */ +#define RTTEST_CHECK_RC_OK(hTest, rcExpr) \ + do { \ + int rcCheck = (rcExpr); \ + if (RT_FAILURE(rcCheck)) { \ + RTTestFailed((hTest), "line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \ + } \ + } while (0) +/** @def RTTEST_CHECK_RC_OK_RET + * Check whether a IPRT style status code indicates success. + * + * If the status indicates failure, call RTTestFailed giving the line number, + * expression and status code, then return with the specified value. + * + * @param hTest The test handle. + * @param rcExpr The expression resulting in an IPRT status code. + * This will be assigned to a local rcCheck variable + * that can be used as return value. + * @param rcRet The return code. + */ +#define RTTEST_CHECK_RC_OK_RET(hTest, rcExpr, rcRet) \ + do { \ + int rcCheck = (rcExpr); \ + if (RT_FAILURE(rcCheck)) { \ + RTTestFailed((hTest), "line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \ + return (rcRet); \ + } \ + } while (0) +/** @def RTTEST_CHECK_RC_OK_RETV + * Check whether a IPRT style status code indicates success. + * + * If the status indicates failure, call RTTestFailed giving the line number, + * expression and status code, then return. + * + * @param hTest The test handle. + * @param rcExpr The expression resulting in an IPRT status code. + */ +#define RTTEST_CHECK_RC_OK_RETV(hTest, rcExpr) \ + do { \ + int rcCheck = (rcExpr); \ + if (RT_FAILURE(rcCheck)) { \ + RTTestFailed((hTest), "line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \ + return; \ + } \ + } while (0) + + + + +/** @name Implicit Test Handle API Variation + * The test handle is retrieved from the test TLS entry of the calling thread. + * @{ + */ + +/** + * Test vprintf, makes sure lines are prefixed and so forth. + * + * @returns Number of chars printed. + * @param enmLevel Message importance level. + * @param pszFormat The message. + * @param va Arguments. + */ +RTR3DECL(int) RTTestIPrintfV(RTTESTLVL enmLevel, const char *pszFormat, va_list va); + +/** + * Test printf, makes sure lines are prefixed and so forth. + * + * @returns Number of chars printed. + * @param enmLevel Message importance level. + * @param pszFormat The message. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestIPrintf(RTTESTLVL enmLevel, const char *pszFormat, ...); + +/** + * Starts a sub-test. + * + * This will perform an implicit RTTestSubDone() call if that has not been done + * since the last RTTestSub call. + * + * @returns Number of chars printed. + * @param pszSubTest The sub-test name. + */ +RTR3DECL(int) RTTestISub(const char *pszSubTest); + +/** + * Format string version of RTTestSub. + * + * See RTTestSub for details. + * + * @returns Number of chars printed. + * @param pszSubTestFmt The sub-test name format string. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestISubF(const char *pszSubTestFmt, ...); + +/** + * Format string version of RTTestSub. + * + * See RTTestSub for details. + * + * @returns Number of chars printed. + * @param pszSubTestFmt The sub-test name format string. + * @param va Arguments. + */ +RTR3DECL(int) RTTestISubV(const char *pszSubTestFmt, va_list va); + +/** + * Completes a sub-test. + * + * @returns Number of chars printed. + */ +RTR3DECL(int) RTTestISubDone(void); + +/** + * Prints an extended PASSED message, optional. + * + * This does not conclude the sub-test, it could be used to report the passing + * of a sub-sub-to-the-power-of-N-test. + * + * @returns IPRT status code. + * @param pszFormat The message. No trailing newline. + * @param va The arguments. + */ +RTR3DECL(int) RTTestIPassedV(const char *pszFormat, va_list va); + +/** + * Prints an extended PASSED message, optional. + * + * This does not conclude the sub-test, it could be used to report the passing + * of a sub-sub-to-the-power-of-N-test. + * + * @returns IPRT status code. + * @param pszFormat The message. No trailing newline. + * @param ... The arguments. + */ +RTR3DECL(int) RTTestIPassed(const char *pszFormat, ...); + +/** + * Report a named test result value. + * + * This is typically used for benchmarking but can be used for other purposes + * like reporting limits of some implementation. The value gets associated with + * the current sub test, the name must be unique within the sub test. + * + * @returns IPRT status code. + * + * @param pszName The value name. + * @param u64Value The value. + * @param enmUnit The value unit. + */ +RTR3DECL(int) RTTestIValue(const char *pszName, uint64_t u64Value, RTTESTUNIT enmUnit); + +/** + * Same as RTTestValue, except that the name is now a format string. + * + * @returns IPRT status code. + * + * @param u64Value The value. + * @param enmUnit The value unit. + * @param pszNameFmt The value name format string. + * @param ... String arguments. + */ +RTR3DECL(int) RTTestIValueF(uint64_t u64Value, RTTESTUNIT enmUnit, const char *pszNameFmt, ...); + +/** + * Same as RTTestValue, except that the name is now a format string. + * + * @returns IPRT status code. + * + * @param u64Value The value. + * @param enmUnit The value unit. + * @param pszNameFmt The value name format string. + * @param va_list String arguments. + */ +RTR3DECL(int) RTTestIValueV(uint64_t u64Value, RTTESTUNIT enmUnit, const char *pszNameFmt, va_list va); + +/** + * Increments the error counter. + * + * @returns IPRT status code. + */ +RTR3DECL(int) RTTestIErrorInc(void); + +/** + * Get the current error count. + * + * @returns The error counter, UINT32_MAX if no valid test handle. + */ +RTR3DECL(uint32_t) RTTestIErrorCount(void); + +/** + * Increments the error counter and prints a failure message. + * + * @returns IPRT status code. + * @param pszFormat The message. No trailing newline. + * @param va The arguments. + */ +RTR3DECL(int) RTTestIFailedV(const char *pszFormat, va_list va); + +/** + * Increments the error counter and prints a failure message. + * + * @returns IPRT status code. + * @param pszFormat The message. No trailing newline. + * @param ... The arguments. + */ +RTR3DECL(int) RTTestIFailed(const char *pszFormat, ...); + +/** + * Increments the error counter, prints a failure message and returns the + * specified status code. + * + * This is mainly a convenience method for saving vertical space in the source + * code. + * + * @returns @a rcRet + * @param rcRet The IPRT status code to return. + * @param pszFormat The message. No trailing newline. + * @param va The arguments. + */ +RTR3DECL(int) RTTestIFailedRcV(int rcRet, const char *pszFormat, va_list va); + +/** + * Increments the error counter, prints a failure message and returns the + * specified status code. + * + * This is mainly a convenience method for saving vertical space in the source + * code. + * + * @returns @a rcRet + * @param rcRet The IPRT status code to return. + * @param pszFormat The message. No trailing newline. + * @param ... The arguments. + */ +RTR3DECL(int) RTTestIFailedRc(int rcRet, const char *pszFormat, ...); + +/** + * Same as RTTestIPrintfV with RTTESTLVL_FAILURE. + * + * @returns Number of chars printed. + * @param pszFormat The message. + * @param va Arguments. + */ +RTR3DECL(int) RTTestIFailureDetailsV(const char *pszFormat, va_list va); + +/** + * Same as RTTestIPrintf with RTTESTLVL_FAILURE. + * + * @returns Number of chars printed. + * @param pszFormat The message. + * @param ... Arguments. + */ +RTR3DECL(int) RTTestIFailureDetails(const char *pszFormat, ...); + + +/** @def RTTESTI_CHECK + * Check whether a boolean expression holds true. + * + * If the expression is false, call RTTestIFailed giving the line number and + * expression. + * + * @param expr The expression to evaluate. + */ +#define RTTESTI_CHECK(expr) \ + do { if (!(expr)) { \ + RTTestIFailed("line %u: %s", __LINE__, #expr); \ + } \ + } while (0) +/** @def RTTESTI_CHECK_RET + * Check whether a boolean expression holds true, returns on false. + * + * If the expression is false, call RTTestIFailed giving the line number and + * expression, then return @a rcRet. + * + * @param expr The expression to evaluate. + * @param rcRet What to return on failure. + */ +#define RTTESTI_CHECK_RET(expr, rcRet) \ + do { if (!(expr)) { \ + RTTestIFailed("line %u: %s", __LINE__, #expr); \ + return (rcRet); \ + } \ + } while (0) +/** @def RTTESTI_CHECK_RETV + * Check whether a boolean expression holds true, returns void on false. + * + * If the expression is false, call RTTestIFailed giving the line number and + * expression, then return void. + * + * @param expr The expression to evaluate. + */ +#define RTTESTI_CHECK_RETV(expr) \ + do { if (!(expr)) { \ + RTTestIFailed("line %u: %s", __LINE__, #expr); \ + return; \ + } \ + } while (0) +/** @def RTTESTI_CHECK_RETV + * Check whether a boolean expression holds true, returns void on false. + * + * If the expression is false, call RTTestIFailed giving the line number and + * expression, then break. + * + * @param expr The expression to evaluate. + */ +#define RTTESTI_CHECK_BREAK(expr) \ + if (!(expr)) { \ + RTTestIFailed("line %u: %s", __LINE__, #expr); \ + break; \ + } do {} while (0) + + +/** @def RTTESTI_CHECK_MSG + * Check whether a boolean expression holds true. + * + * If the expression is false, call RTTestIFailed giving the line number and + * expression. + * + * @param expr The expression to evaluate. + * @param DetailsArgs Argument list for RTTestIFailureDetails, including + * parenthesis. + */ +#define RTTESTI_CHECK_MSG(expr, DetailsArgs) \ + do { if (!(expr)) { \ + RTTestIFailed("line %u: %s", __LINE__, #expr); \ + RTTestIFailureDetails DetailsArgs; \ + } \ + } while (0) +/** @def RTTESTI_CHECK_MSG_RET + * Check whether a boolean expression holds true, returns on false. + * + * If the expression is false, call RTTestIFailed giving the line number and + * expression. + * + * @param expr The expression to evaluate. + * @param DetailsArgs Argument list for RTTestIFailureDetails, including + * parenthesis. + * @param rcRet What to return on failure. + */ +#define RTTESTI_CHECK_MSG_RET(expr, DetailsArgs, rcRet) \ + do { if (!(expr)) { \ + RTTestIFailed("line %u: %s", __LINE__, #expr); \ + RTTestIFailureDetails DetailsArgs; \ + return (rcRet); \ + } \ + } while (0) +/** @def RTTESTI_CHECK_MSG_RET + * Check whether a boolean expression holds true, returns void on false. + * + * If the expression is false, call RTTestIFailed giving the line number and + * expression. + * + * @param expr The expression to evaluate. + * @param DetailsArgs Argument list for RTTestIFailureDetails, including + * parenthesis. + */ +#define RTTESTI_CHECK_MSG_RETV(expr, DetailsArgs) \ + do { if (!(expr)) { \ + RTTestIFailed("line %u: %s", __LINE__, #expr); \ + RTTestIFailureDetails DetailsArgs; \ + return; \ + } \ + } while (0) + + +/** @def RTTESTI_CHECK_RC + * Check whether an expression returns a specific IPRT style status code. + * + * If a different status code is return, call RTTestIFailed giving the line + * number, expression, actual and expected status codes. + * + * @param rcExpr The expression resulting in an IPRT status code. + * @param rcExpect The expected return code. This may be referenced + * more than once by the macro. + */ +#define RTTESTI_CHECK_RC(rcExpr, rcExpect) \ + do { \ + int rcCheck = (rcExpr); \ + if (rcCheck != (rcExpect)) { \ + RTTestIFailed("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \ + } \ + } while (0) +/** @def RTTESTI_CHECK_RC_RET + * Check whether an expression returns a specific IPRT style status code. + * + * If a different status code is return, call RTTestIFailed giving the line + * number, expression, actual and expected status codes, then return. + * + * @param rcExpr The expression resulting in an IPRT status code. + * This will be assigned to a local rcCheck variable + * that can be used as return value. + * @param rcExpect The expected return code. This may be referenced + * more than once by the macro. + * @param rcRet The return code. + */ +#define RTTESTI_CHECK_RC_RET(rcExpr, rcExpect, rcRet) \ + do { \ + int rcCheck = (rcExpr); \ + if (rcCheck != (rcExpect)) { \ + RTTestIFailed("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \ + return (rcRet); \ + } \ + } while (0) +/** @def RTTESTI_CHECK_RC_RETV + * Check whether an expression returns a specific IPRT style status code. + * + * If a different status code is return, call RTTestIFailed giving the line + * number, expression, actual and expected status codes, then return. + * + * @param rcExpr The expression resulting in an IPRT status code. + * @param rcExpect The expected return code. This may be referenced + * more than once by the macro. + */ +#define RTTESTI_CHECK_RC_RETV(rcExpr, rcExpect) \ + do { \ + int rcCheck = (rcExpr); \ + if (rcCheck != (rcExpect)) { \ + RTTestIFailed("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \ + return; \ + } \ + } while (0) +/** @def RTTESTI_CHECK_RC_BREAK + * Check whether an expression returns a specific IPRT style status code. + * + * If a different status code is return, call RTTestIFailed giving the line + * number, expression, actual and expected status codes, then break. + * + * @param rcExpr The expression resulting in an IPRT status code. + * @param rcExpect The expected return code. This may be referenced + * more than once by the macro. + */ +#define RTTESTI_CHECK_RC_BREAK(rcExpr, rcExpect) \ + if (1) { \ + int rcCheck = (rcExpr); \ + if (rcCheck != (rcExpect)) { \ + RTTestIFailed("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \ + break; \ + } \ + } else do {} while (0) + + +/** @def RTTESTI_CHECK_RC_OK + * Check whether a IPRT style status code indicates success. + * + * If the status indicates failure, call RTTestIFailed giving the line number, + * expression and status code. + * + * @param rcExpr The expression resulting in an IPRT status code. + */ +#define RTTESTI_CHECK_RC_OK(rcExpr) \ + do { \ + int rcCheck = (rcExpr); \ + if (RT_FAILURE(rcCheck)) { \ + RTTestIFailed("line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \ + } \ + } while (0) +/** @def RTTESTI_CHECK_RC_OK_RET + * Check whether a IPRT style status code indicates success. + * + * If the status indicates failure, call RTTestIFailed giving the line number, + * expression and status code, then return with the specified value. + * + * @param rcExpr The expression resulting in an IPRT status code. + * This will be assigned to a local rcCheck variable + * that can be used as return value. + * @param rcRet The return code. + */ +#define RTTESTI_CHECK_RC_OK_RET(rcExpr, rcRet) \ + do { \ + int rcCheck = (rcExpr); \ + if (RT_FAILURE(rcCheck)) { \ + RTTestIFailed("line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \ + return (rcRet); \ + } \ + } while (0) +/** @def RTTESTI_CHECK_RC_OK_RETV + * Check whether a IPRT style status code indicates success. + * + * If the status indicates failure, call RTTestIFailed giving the line number, + * expression and status code, then return. + * + * @param rcExpr The expression resulting in an IPRT status code. + */ +#define RTTESTI_CHECK_RC_OK_RETV(rcExpr) \ + do { \ + int rcCheck = (rcExpr); \ + if (RT_FAILURE(rcCheck)) { \ + RTTestIFailed("line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \ + return; \ + } \ + } while (0) + +/** @} */ + + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/thread.h b/include/iprt/thread.h new file mode 100644 index 00000000..6bd63b99 --- /dev/null +++ b/include/iprt/thread.h @@ -0,0 +1,832 @@ +/** @file + * IPRT - Threads. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_thread_h +#define ___iprt_thread_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_thread RTThread - Thread Management + * @ingroup grp_rt + * @{ + */ + +/** + * The thread state. + */ +typedef enum RTTHREADSTATE +{ + /** The usual invalid 0 value. */ + RTTHREADSTATE_INVALID = 0, + /** The thread is being initialized. */ + RTTHREADSTATE_INITIALIZING, + /** The thread has terminated */ + RTTHREADSTATE_TERMINATED, + /** Probably running. */ + RTTHREADSTATE_RUNNING, + + /** Waiting on a critical section. */ + RTTHREADSTATE_CRITSECT, + /** Waiting on a event semaphore. */ + RTTHREADSTATE_EVENT, + /** Waiting on a event multiple wakeup semaphore. */ + RTTHREADSTATE_EVENT_MULTI, + /** Waiting on a fast mutex. */ + RTTHREADSTATE_FAST_MUTEX, + /** Waiting on a mutex. */ + RTTHREADSTATE_MUTEX, + /** Waiting on a read write semaphore, read (shared) access. */ + RTTHREADSTATE_RW_READ, + /** Waiting on a read write semaphore, write (exclusive) access. */ + RTTHREADSTATE_RW_WRITE, + /** The thread is sleeping. */ + RTTHREADSTATE_SLEEP, + /** Waiting on a spin mutex. */ + RTTHREADSTATE_SPIN_MUTEX, + /** End of the thread states. */ + RTTHREADSTATE_END, + + /** The usual 32-bit size hack. */ + RTTHREADSTATE_32BIT_HACK = 0x7fffffff +} RTTHREADSTATE; + +/** Checks if a thread state indicates that the thread is sleeping. */ +#define RTTHREAD_IS_SLEEPING(enmState) ((enmState) >= RTTHREADSTATE_CRITSECT) + +/** + * Thread types. + * Besides identifying the purpose of the thread, the thread type is + * used to select the scheduling properties. + * + * The types in are placed in a rough order of ascending priority. + */ +typedef enum RTTHREADTYPE +{ + /** Invalid type. */ + RTTHREADTYPE_INVALID = 0, + /** Infrequent poller thread. + * This type of thread will sleep for the most of the time, and do + * infrequent polls on resources at 0.5 sec or higher intervals. + */ + RTTHREADTYPE_INFREQUENT_POLLER, + /** Main heavy worker thread. + * Thread of this type is driving asynchronous tasks in the Main + * API which takes a long time and might involve a bit of CPU. Like + * for instance creating a fixed sized VDI. + */ + RTTHREADTYPE_MAIN_HEAVY_WORKER, + /** The emulation thread type. + * While being a thread with very high workload it still is vital + * that it gets scheduled frequently. When possible all other thread + * types except DEFAULT and GUI should interrupt this one ASAP when + * they become ready. + */ + RTTHREADTYPE_EMULATION, + /** The default thread type. + * Since it doesn't say much about the purpose of the thread + * nothing special is normally done to the scheduling. This type + * should be avoided. + * The main thread is registered with default type during RTR3Init() + * and that's what the default process priority is derived from. + */ + RTTHREADTYPE_DEFAULT, + /** The GUI thread type + * The GUI normally have a low workload but is frequently scheduled + * to handle events. When possible the scheduler should not leave + * threads of this kind waiting for too long (~50ms). + */ + RTTHREADTYPE_GUI, + /** Main worker thread. + * Thread of this type is driving asynchronous tasks in the Main API. + * In most cases this means little work an a lot of waiting. + */ + RTTHREADTYPE_MAIN_WORKER, + /** VRDP I/O thread. + * These threads are I/O threads in the RDP server will hang around + * waiting for data, process it and pass it on. + */ + RTTHREADTYPE_VRDP_IO, + /** The debugger type. + * Threads involved in servicing the debugger. It must remain + * responsive even when things are running wild in. + */ + RTTHREADTYPE_DEBUGGER, + /** Message pump thread. + * Thread pumping messages from one thread/process to another + * thread/process. The workload is very small, most of the time + * it's blocked waiting for messages to be procduced or processed. + * This type of thread will be favored after I/O threads. + */ + RTTHREADTYPE_MSG_PUMP, + /** The I/O thread type. + * Doing I/O means shuffling data, waiting for request to arrive and + * for them to complete. The thread should be favored when competing + * with any other threads except timer threads. + */ + RTTHREADTYPE_IO, + /** The timer thread type. + * A timer thread is mostly waiting for the timer to tick + * and then perform a little bit of work. Accuracy is important here, + * so the thread should be favoured over all threads. If premention can + * be configured at thread level, it could be made very short. + */ + RTTHREADTYPE_TIMER, + /** Only used for validation. */ + RTTHREADTYPE_END +} RTTHREADTYPE; + + +#ifndef IN_RC + +/** + * Checks if the IPRT thread component has been initialized. + * + * This is used to avoid calling into RTThread before the runtime has been + * initialized. + * + * @returns @c true if it's initialized, @c false if not. + */ +RTDECL(bool) RTThreadIsInitialized(void); + +/** + * Get the thread handle of the current thread. + * + * @returns Thread handle. + */ +RTDECL(RTTHREAD) RTThreadSelf(void); + +/** + * Get the native thread handle of the current thread. + * + * @returns Native thread handle. + */ +RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void); + +/** + * Millisecond granular sleep function. + * + * @returns VINF_SUCCESS on success. + * @returns VERR_INTERRUPTED if a signal or other asynchronous stuff happened + * which interrupt the peaceful sleep. + * @param cMillies Number of milliseconds to sleep. + * 0 milliseconds means yielding the timeslice - deprecated! + * @remark See RTThreadNanoSleep() for sleeping for smaller periods of time. + */ +RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies); + +/** + * Millisecond granular sleep function, no logger calls. + * + * Same as RTThreadSleep, except it will never call into the IPRT logger. It + * can therefore safely be used in places where the logger is off limits, like + * at termination or init time. The electric fence heap is one consumer of + * this API. + * + * @returns VINF_SUCCESS on success. + * @returns VERR_INTERRUPTED if a signal or other asynchronous stuff happened + * which interrupt the peaceful sleep. + * @param cMillies Number of milliseconds to sleep. + * 0 milliseconds means yielding the timeslice - deprecated! + */ +RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies); + +/** + * Yields the CPU. + * + * @returns true if we yielded. + * @returns false if it's probable that we didn't yield. + */ +RTDECL(bool) RTThreadYield(void); + + + +/** + * Thread function. + * + * @returns 0 on success. + * @param ThreadSelf Thread handle to this thread. + * @param pvUser User argument. + */ +typedef DECLCALLBACK(int) FNRTTHREAD(RTTHREAD ThreadSelf, void *pvUser); +/** Pointer to a FNRTTHREAD(). */ +typedef FNRTTHREAD *PFNRTTHREAD; + +/** + * Thread creation flags. + */ +typedef enum RTTHREADFLAGS +{ + /** This flag is used to keep the thread structure around so it can + * be waited on after termination. @sa RTThreadWait and + * RTThreadWaitNoResume. Not required for RTThreadUserWait and friends! + */ + RTTHREADFLAGS_WAITABLE = RT_BIT(0), + /** The bit number corresponding to the RTTHREADFLAGS_WAITABLE mask. */ + RTTHREADFLAGS_WAITABLE_BIT = 0, + + /** Mask of valid flags, use for validation. */ + RTTHREADFLAGS_MASK = RT_BIT(0) +} RTTHREADFLAGS; + + +/** + * Create a new thread. + * + * @returns iprt status code. + * @param pThread Where to store the thread handle to the new thread. (optional) + * @param pfnThread The thread function. + * @param pvUser User argument. + * @param cbStack The size of the stack for the new thread. + * Use 0 for the default stack size. + * @param enmType The thread type. Used for deciding scheduling attributes + * of the thread. + * @param fFlags Flags of the RTTHREADFLAGS type (ORed together). + * @param pszName Thread name. + * + * @remark When called in Ring-0, this API will create a new kernel thread and not a thread in + * the context of the calling process. + */ +RTDECL(int) RTThreadCreate(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack, + RTTHREADTYPE enmType, unsigned fFlags, const char *pszName); + +/** + * Create a new thread. + * + * Same as RTThreadCreate except the name is given in the RTStrPrintfV form. + * + * @returns iprt status code. + * @param pThread See RTThreadCreate. + * @param pfnThread See RTThreadCreate. + * @param pvUser See RTThreadCreate. + * @param cbStack See RTThreadCreate. + * @param enmType See RTThreadCreate. + * @param fFlags See RTThreadCreate. + * @param pszName Thread name format. + * @param va Format arguments. + */ +RTDECL(int) RTThreadCreateV(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack, + RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, va_list va); + +/** + * Create a new thread. + * + * Same as RTThreadCreate except the name is given in the RTStrPrintf form. + * + * @returns iprt status code. + * @param pThread See RTThreadCreate. + * @param pfnThread See RTThreadCreate. + * @param pvUser See RTThreadCreate. + * @param cbStack See RTThreadCreate. + * @param enmType See RTThreadCreate. + * @param fFlags See RTThreadCreate. + * @param pszName Thread name format. + * @param ... Format arguments. + */ +RTDECL(int) RTThreadCreateF(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack, + RTTHREADTYPE enmType, uint32_t fFlags, const char *pszNameFmt, ...); + +/** + * Gets the native thread id of a IPRT thread. + * + * @returns The native thread id. + * @param Thread The IPRT thread. + */ +RTDECL(RTNATIVETHREAD) RTThreadGetNative(RTTHREAD Thread); + +/** + * Gets the IPRT thread of a native thread. + * + * @returns The IPRT thread handle + * @returns NIL_RTTHREAD if not a thread known to IPRT. + * @param NativeThread The native thread handle/id. + */ +RTDECL(RTTHREAD) RTThreadFromNative(RTNATIVETHREAD NativeThread); + +/** + * Changes the type of the specified thread. + * + * @returns iprt status code. + * @param Thread The thread which type should be changed. + * @param enmType The new thread type. + * @remark In Ring-0 it only works if Thread == RTThreadSelf(). + */ +RTDECL(int) RTThreadSetType(RTTHREAD Thread, RTTHREADTYPE enmType); + +/** + * Wait for the thread to terminate, resume on interruption. + * + * @returns iprt status code. + * Will not return VERR_INTERRUPTED. + * @param Thread The thread to wait for. + * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for + * an indefinite wait. + * @param prc Where to store the return code of the thread. Optional. + */ +RTDECL(int) RTThreadWait(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc); + +/** + * Wait for the thread to terminate, return on interruption. + * + * @returns iprt status code. + * @param Thread The thread to wait for. + * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for + * an indefinite wait. + * @param prc Where to store the return code of the thread. Optional. + */ +RTDECL(int) RTThreadWaitNoResume(RTTHREAD Thread, RTMSINTERVAL cMillies, int *prc); + +/** + * Gets the name of the current thread thread. + * + * @returns Pointer to readonly name string. + * @returns NULL on failure. + */ +RTDECL(const char *) RTThreadSelfName(void); + +/** + * Gets the name of a thread. + * + * @returns Pointer to readonly name string. + * @returns NULL on failure. + * @param Thread Thread handle of the thread to query the name of. + */ +RTDECL(const char *) RTThreadGetName(RTTHREAD Thread); + +/** + * Gets the type of the specified thread. + * + * @returns The thread type. + * @returns RTTHREADTYPE_INVALID if the thread handle is invalid. + * @param Thread The thread in question. + */ +RTDECL(RTTHREADTYPE) RTThreadGetType(RTTHREAD Thread); + +/** + * Sets the name of a thread. + * + * @returns iprt status code. + * @param Thread Thread handle of the thread to query the name of. + * @param pszName The thread name. + */ +RTDECL(int) RTThreadSetName(RTTHREAD Thread, const char *pszName); + +/** + * Checks if the specified thread is the main thread. + * + * @returns true if it is, false if it isn't. + * + * @param hThread The thread handle. + */ +RTDECL(bool) RTThreadIsMain(RTTHREAD hThread); + +/** + * Checks if the calling thread is known to IPRT. + * + * @returns @c true if it is, @c false if it isn't. + */ +RTDECL(bool) RTThreadIsSelfKnown(void); + +/** + * Checks if the calling thread is know to IPRT and is alive. + * + * @returns @c true if it is, @c false if it isn't. + */ +RTDECL(bool) RTThreadIsSelfAlive(void); + +/** + * Checks if the calling thread is known to IPRT. + * + * @returns @c true if it is, @c false if it isn't. + */ +RTDECL(bool) RTThreadIsOperational(void); + +/** + * Signal the user event. + * + * @returns iprt status code. + */ +RTDECL(int) RTThreadUserSignal(RTTHREAD Thread); + +/** + * Wait for the user event. + * + * @returns iprt status code. + * @param Thread The thread to wait for. + * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for + * an indefinite wait. + */ +RTDECL(int) RTThreadUserWait(RTTHREAD Thread, RTMSINTERVAL cMillies); + +/** + * Wait for the user event, return on interruption. + * + * @returns iprt status code. + * @param Thread The thread to wait for. + * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT for + * an indefinite wait. + */ +RTDECL(int) RTThreadUserWaitNoResume(RTTHREAD Thread, RTMSINTERVAL cMillies); + +/** + * Reset the user event. + * + * @returns iprt status code. + * @param Thread The thread to reset. + */ +RTDECL(int) RTThreadUserReset(RTTHREAD Thread); + +/** + * Pokes the thread. + * + * This will signal the thread, attempting to interrupt whatever it's currently + * doing. This is *NOT* implemented on all platforms and may cause unresolved + * symbols during linking or VERR_NOT_IMPLEMENTED at runtime. + * + * @returns IPRT status code. + * + * @param hThread The thread to poke. This must not be the + * calling thread. + */ +RTDECL(int) RTThreadPoke(RTTHREAD hThread); + +# ifdef IN_RING0 + +/** + * Check if preemption is currently enabled or not for the current thread. + * + * @note This may return true even on systems where preemption isn't + * possible. In that case, it means no call to RTThreadPreemptDisable + * has been made and interrupts are still enabled. + * + * @returns true if preemption is enabled, false if preemetion is disabled. + * @param hThread Must be NIL_RTTHREAD for now. + */ +RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread); + +/** + * Check if preemption is pending for the current thread. + * + * This function should be called regularly when executing larger portions of + * code with preemption disabled. + * + * @returns true if pending, false if not. + * @param hThread Must be NIL_RTTHREAD for now. + */ +RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread); + +/** + * Is RTThreadPreemptIsPending reliable? + * + * @returns true if reliable, false if not. + */ +RTDECL(bool) RTThreadPreemptIsPendingTrusty(void); + +/** + * Is preemption possible on this system. + * + * @returns true if possible, false if not. + */ +RTDECL(bool) RTThreadPreemptIsPossible(void); + +/** + * Preemption state saved by RTThreadPreemptDisable and used by + * RTThreadPreemptRestore to restore the previous state. + */ +typedef struct RTTHREADPREEMPTSTATE +{ + /** In debug builds this will be used to check for cpu migration. */ + RTCPUID idCpu; +# ifdef RT_OS_WINDOWS + /** The old IRQL. Don't touch! */ + unsigned char uchOldIrql; + /** Reserved, MBZ. */ + uint8_t bReserved1; + /** Reserved, MBZ. */ + uint8_t bReserved2; + /** Reserved, MBZ. */ + uint8_t bReserved3; +# define RTTHREADPREEMPTSTATE_INITIALIZER { NIL_RTCPUID, 255, 0, 0, 0 } +# elif defined(RT_OS_SOLARIS) + /** The Old PIL. Don't touch! */ + uint32_t uOldPil; +# define RTTHREADPREEMPTSTATE_INITIALIZER { NIL_RTCPUID, UINT32_MAX } +# else + /** Reserved, MBZ. */ + uint32_t u32Reserved; +# define RTTHREADPREEMPTSTATE_INITIALIZER { NIL_RTCPUID, 0 } +# endif +} RTTHREADPREEMPTSTATE; +/** Pointer to a preemption state. */ +typedef RTTHREADPREEMPTSTATE *PRTTHREADPREEMPTSTATE; + +/** + * Disable preemption. + * + * A call to this function must be matched by exactly one call to + * RTThreadPreemptRestore(). + * + * @param pState Where to store the preemption state. + */ +RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState); + +/** + * Restores the preemption state, undoing a previous call to + * RTThreadPreemptDisable. + * + * A call to this function must be matching a previous call to + * RTThreadPreemptDisable. + * + * @param pState The state return by RTThreadPreemptDisable. + */ +RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState); + +/** + * Check if the thread is executing in interrupt context. + * + * @returns true if in interrupt context, false if not. + * @param hThread Must be NIL_RTTHREAD for now. + */ +RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread); + +# endif /* IN_RING0 */ + + +# ifdef IN_RING3 + +/** + * Adopts a non-IPRT thread. + * + * @returns IPRT status code. + * @param enmType The thread type. + * @param fFlags The thread flags. RTTHREADFLAGS_WAITABLE is not currently allowed. + * @param pszName The thread name. Optional + * @param pThread Where to store the thread handle. Optional. + */ +RTDECL(int) RTThreadAdopt(RTTHREADTYPE enmType, unsigned fFlags, const char *pszName, PRTTHREAD pThread); + +/** + * Get the thread handle of the current thread, automatically adopting alien + * threads. + * + * @returns Thread handle. + */ +RTDECL(RTTHREAD) RTThreadSelfAutoAdopt(void); + +/** + * Gets the affinity mask of the current thread. + * + * @returns IPRT status code. + * @param pCpuSet Where to return the CPU affienty set of the calling + * thread. + */ +RTR3DECL(int) RTThreadGetAffinity(PRTCPUSET pCpuSet); + +/** + * Sets the affinity mask of the current thread. + * + * @returns iprt status code. + * @param pCpuSet The set of CPUs this thread can run on. NULL means + * all CPUs. + */ +RTR3DECL(int) RTThreadSetAffinity(PCRTCPUSET pCpuSet); + +/** + * Binds the thread to one specific CPU. + * + * @returns iprt status code. + * @param idCpu The ID of the CPU to bind this thread to. Use + * NIL_RTCPUID to unbind it. + */ +RTR3DECL(int) RTThreadSetAffinityToCpu(RTCPUID idCpu); + +/** + * Unblocks a thread. + * + * This function is paired with RTThreadBlocking and RTThreadBlockingDebug. + * + * @param hThread The current thread. + * @param enmCurState The current state, used to check for nested blocking. + * The new state will be running. + */ +RTDECL(void) RTThreadUnblocked(RTTHREAD hThread, RTTHREADSTATE enmCurState); + +/** + * Change the thread state to blocking. + * + * @param hThread The current thread. + * @param enmState The sleep state. + * @param fReallySleeping Really going to sleep now. Use false before calls + * to other IPRT synchronization methods. + */ +RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState, bool fReallySleeping); + +/** + * Get the current thread state. + * + * A thread that is reported as sleeping may actually still be running inside + * the lock validator or/and in the code of some other IPRT synchronization + * primitive. Use RTThreadGetReallySleeping + * + * @returns The thread state. + * @param hThread The thread. + */ +RTDECL(RTTHREADSTATE) RTThreadGetState(RTTHREAD hThread); + +/** + * Checks if the thread is really sleeping or not. + * + * @returns RTTHREADSTATE_RUNNING if not really sleeping, otherwise the state it + * is sleeping in. + * @param hThread The thread. + */ +RTDECL(RTTHREADSTATE) RTThreadGetReallySleeping(RTTHREAD hThread); + +/** + * Translate a thread state into a string. + * + * @returns Pointer to a read-only string containing the state name. + * @param enmState The state. + */ +RTDECL(const char *) RTThreadStateName(RTTHREADSTATE enmState); + + +/** + * Native thread states returned by RTThreadNativeState. + */ +typedef enum RTTHREADNATIVESTATE +{ + /** Invalid thread handle. */ + RTTHREADNATIVESTATE_INVALID = 0, + /** Unable to determine the thread state. */ + RTTHREADNATIVESTATE_UNKNOWN, + /** The thread is running. */ + RTTHREADNATIVESTATE_RUNNING, + /** The thread is blocked. */ + RTTHREADNATIVESTATE_BLOCKED, + /** The thread is suspended / stopped. */ + RTTHREADNATIVESTATE_SUSPENDED, + /** The thread has terminated. */ + RTTHREADNATIVESTATE_TERMINATED, + /** Make sure it's a 32-bit type. */ + RTTHREADNATIVESTATE_32BIT_HACK = 0x7fffffff +} RTTHREADNATIVESTATE; + + +/** + * Get the native state of a thread. + * + * @returns Native state. + * @param hThread The thread handle. + * + * @remarks Not yet implemented on all systems, so have a backup plan for + * RTTHREADNATIVESTATE_UNKNOWN. + */ +RTDECL(RTTHREADNATIVESTATE) RTThreadGetNativeState(RTTHREAD hThread); + + +/** + * Get the execution times of the specified thread + * + * @returns IPRT status code. + * @param pKernelTime Kernel execution time in ms (out) + * @param pUserTime User execution time in ms (out) + * + */ +RTR3DECL(int) RTThreadGetExecutionTimeMilli(uint64_t *pKernelTime, uint64_t *pUserTime); + +/** @name Thread Local Storage + * @{ + */ +/** + * Thread termination callback for destroying a non-zero TLS entry. + * + * @remarks It is not permitable to use any RTTls APIs at this time. Doing so + * may lead to endless loops, crashes, and other bad stuff. + * + * @param pvValue The current value. + */ +typedef DECLCALLBACK(void) FNRTTLSDTOR(void *pvValue); +/** Pointer to a FNRTTLSDTOR. */ +typedef FNRTTLSDTOR *PFNRTTLSDTOR; + +/** + * Allocates a TLS entry (index). + * + * Example code: + * @code + RTTLS g_iTls = NIL_RTTLS; + + ... + + // once for the process, allocate the TLS index + if (g_iTls == NIL_RTTLS) + g_iTls = RTTlsAlloc(); + + // set the thread-local value. + RTTlsSet(g_iTls, pMyData); + + ... + + // get the thread-local value + PMYDATA pMyData = (PMYDATA)RTTlsGet(g_iTls); + + @endcode + * + * @returns the index of the allocated TLS entry. + * @returns NIL_RTTLS on failure. + */ +RTR3DECL(RTTLS) RTTlsAlloc(void); + +/** + * Variant of RTTlsAlloc that returns a status code. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if pfnDestructor is non-NULL and the platform + * doesn't support this feature. + * + * @param piTls Where to store the index of the allocated TLS entry. + * This is set to NIL_RTTLS on failure. + * @param pfnDestructor Optional callback function for cleaning up on + * thread termination. WARNING! This feature may not + * be implemented everywhere. + */ +RTR3DECL(int) RTTlsAllocEx(PRTTLS piTls, PFNRTTLSDTOR pfnDestructor); + +/** + * Frees a TLS entry. + * + * @returns IPRT status code. + * @param iTls The index of the TLS entry. + */ +RTR3DECL(int) RTTlsFree(RTTLS iTls); + +/** + * Get the (thread-local) value stored in a TLS entry. + * + * @returns value in given TLS entry. + * @retval NULL if RTTlsSet() has not yet been called on this thread, or if the + * TLS index is invalid. + * + * @param iTls The index of the TLS entry. + */ +RTR3DECL(void *) RTTlsGet(RTTLS iTls); + +/** + * Get the value stored in a TLS entry. + * + * @returns IPRT status code. + * @param iTls The index of the TLS entry. + * @param ppvValue Where to store the value. The value will be NULL if + * RTTlsSet has not yet been called on this thread. + */ +RTR3DECL(int) RTTlsGetEx(RTTLS iTls, void **ppvValue); + +/** + * Set the value stored in an allocated TLS entry. + * + * @returns IPRT status. + * @param iTls The index of the TLS entry. + * @param pvValue The value to store. + * + * @remarks Note that NULL is considered a special value. + */ +RTR3DECL(int) RTTlsSet(RTTLS iTls, void *pvValue); + +/** @} */ + +# endif /* IN_RING3 */ +# endif /* !IN_RC */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/time.h b/include/iprt/time.h new file mode 100644 index 00000000..7a94dcd7 --- /dev/null +++ b/include/iprt/time.h @@ -0,0 +1,941 @@ +/** @file + * IPRT - Time. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_time_h +#define ___iprt_time_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_time RTTime - Time + * @ingroup grp_rt + * @{ + */ + +/** Time Specification. + * + * Use the inline RTTimeSpecGet/Set to operate on structure this so we + * can easily change the representation if required later. + * + * The current representation is in nanoseconds relative to the unix epoch + * (1970-01-01 00:00:00 UTC). This gives us an approximate span from + * 1678 to 2262 without sacrificing the resolution offered by the various + * host OSes (BSD & LINUX 1ns, NT 100ns). + */ +typedef struct RTTIMESPEC +{ + /** Nanoseconds since epoch. + * The name is intentially too long to be comfortable to use because you should be + * using inline helpers! */ + int64_t i64NanosecondsRelativeToUnixEpoch; +} RTTIMESPEC; + + +/** @name RTTIMESPEC methods + * @{ */ + +/** + * Gets the time as nanoseconds relative to the unix epoch. + * + * @returns Nanoseconds relative to unix epoch. + * @param pTime The time spec to interpret. + */ +DECLINLINE(int64_t) RTTimeSpecGetNano(PCRTTIMESPEC pTime) +{ + return pTime->i64NanosecondsRelativeToUnixEpoch; +} + + +/** + * Sets the time give by nanoseconds relative to the unix epoch. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Nano The new time in nanoseconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNano(PRTTIMESPEC pTime, int64_t i64Nano) +{ + pTime->i64NanosecondsRelativeToUnixEpoch = i64Nano; + return pTime; +} + + +/** + * Gets the time as microseconds relative to the unix epoch. + * + * @returns microseconds relative to unix epoch. + * @param pTime The time spec to interpret. + */ +DECLINLINE(int64_t) RTTimeSpecGetMicro(PCRTTIMESPEC pTime) +{ + return pTime->i64NanosecondsRelativeToUnixEpoch / 1000; +} + + +/** + * Sets the time given by microseconds relative to the unix epoch. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Micro The new time in microsecond. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetMicro(PRTTIMESPEC pTime, int64_t i64Micro) +{ + pTime->i64NanosecondsRelativeToUnixEpoch = i64Micro * 1000; + return pTime; +} + + +/** + * Gets the time as milliseconds relative to the unix epoch. + * + * @returns milliseconds relative to unix epoch. + * @param pTime The time spec to interpret. + */ +DECLINLINE(int64_t) RTTimeSpecGetMilli(PCRTTIMESPEC pTime) +{ + return pTime->i64NanosecondsRelativeToUnixEpoch / 1000000; +} + + +/** + * Sets the time given by milliseconds relative to the unix epoch. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Milli The new time in milliseconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetMilli(PRTTIMESPEC pTime, int64_t i64Milli) +{ + pTime->i64NanosecondsRelativeToUnixEpoch = i64Milli * 1000000; + return pTime; +} + + +/** + * Gets the time as seconds relative to the unix epoch. + * + * @returns seconds relative to unix epoch. + * @param pTime The time spec to interpret. + */ +DECLINLINE(int64_t) RTTimeSpecGetSeconds(PCRTTIMESPEC pTime) +{ + return pTime->i64NanosecondsRelativeToUnixEpoch / 1000000000; +} + + +/** + * Sets the time given by seconds relative to the unix epoch. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Seconds The new time in seconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetSeconds(PRTTIMESPEC pTime, int64_t i64Seconds) +{ + pTime->i64NanosecondsRelativeToUnixEpoch = i64Seconds * 1000000000; + return pTime; +} + + +/** + * Makes the time spec absolute like abs() does (i.e. a positive value). + * + * @returns pTime. + * @param pTime The time spec to modify. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecAbsolute(PRTTIMESPEC pTime) +{ + if (pTime->i64NanosecondsRelativeToUnixEpoch < 0) + pTime->i64NanosecondsRelativeToUnixEpoch = -pTime->i64NanosecondsRelativeToUnixEpoch; + return pTime; +} + + +/** + * Negates the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecNegate(PRTTIMESPEC pTime) +{ + pTime->i64NanosecondsRelativeToUnixEpoch = -pTime->i64NanosecondsRelativeToUnixEpoch; + return pTime; +} + + +/** + * Adds a time period to the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param pTimeAdd The time spec to add to pTime. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecAdd(PRTTIMESPEC pTime, PCRTTIMESPEC pTimeAdd) +{ + pTime->i64NanosecondsRelativeToUnixEpoch += pTimeAdd->i64NanosecondsRelativeToUnixEpoch; + return pTime; +} + + +/** + * Adds a time period give as nanoseconds from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Nano The time period in nanoseconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecAddNano(PRTTIMESPEC pTime, int64_t i64Nano) +{ + pTime->i64NanosecondsRelativeToUnixEpoch += i64Nano; + return pTime; +} + + +/** + * Adds a time period give as microseconds from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Micro The time period in microseconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecAddMicro(PRTTIMESPEC pTime, int64_t i64Micro) +{ + pTime->i64NanosecondsRelativeToUnixEpoch += i64Micro * 1000; + return pTime; +} + + +/** + * Adds a time period give as milliseconds from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Milli The time period in milliseconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecAddMilli(PRTTIMESPEC pTime, int64_t i64Milli) +{ + pTime->i64NanosecondsRelativeToUnixEpoch += i64Milli * 1000000; + return pTime; +} + + +/** + * Adds a time period give as seconds from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Seconds The time period in seconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecAddSeconds(PRTTIMESPEC pTime, int64_t i64Seconds) +{ + pTime->i64NanosecondsRelativeToUnixEpoch += i64Seconds * 1000000000; + return pTime; +} + + +/** + * Subtracts a time period from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param pTimeSub The time spec to subtract from pTime. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSub(PRTTIMESPEC pTime, PCRTTIMESPEC pTimeSub) +{ + pTime->i64NanosecondsRelativeToUnixEpoch -= pTimeSub->i64NanosecondsRelativeToUnixEpoch; + return pTime; +} + + +/** + * Subtracts a time period give as nanoseconds from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Nano The time period in nanoseconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSubNano(PRTTIMESPEC pTime, int64_t i64Nano) +{ + pTime->i64NanosecondsRelativeToUnixEpoch -= i64Nano; + return pTime; +} + + +/** + * Subtracts a time period give as microseconds from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Micro The time period in microseconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSubMicro(PRTTIMESPEC pTime, int64_t i64Micro) +{ + pTime->i64NanosecondsRelativeToUnixEpoch -= i64Micro * 1000; + return pTime; +} + + +/** + * Subtracts a time period give as milliseconds from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Milli The time period in milliseconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSubMilli(PRTTIMESPEC pTime, int64_t i64Milli) +{ + pTime->i64NanosecondsRelativeToUnixEpoch -= i64Milli * 1000000; + return pTime; +} + + +/** + * Subtracts a time period give as seconds from the time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Seconds The time period in seconds. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSubSeconds(PRTTIMESPEC pTime, int64_t i64Seconds) +{ + pTime->i64NanosecondsRelativeToUnixEpoch -= i64Seconds * 100000000; + return pTime; +} + + +/* PORTME: Add struct timeval guard macro here. */ +#if defined(RTTIME_INCL_TIMEVAL) || defined(_STRUCT_TIMEVAL) || defined(_SYS__TIMEVAL_H_) || defined(_SYS_TIME_H) || defined(_TIMEVAL) || defined(_LINUX_TIME_H) +/** + * Gets the time as POSIX timeval. + * + * @returns pTime. + * @param pTime The time spec to interpret. + * @param pTimeval Where to store the time as POSIX timeval. + */ +DECLINLINE(struct timeval *) RTTimeSpecGetTimeval(PCRTTIMESPEC pTime, struct timeval *pTimeval) +{ + int64_t i64 = RTTimeSpecGetMicro(pTime); + int32_t i32Micro = (int32_t)(i64 % 1000000); + i64 /= 1000000; + if (i32Micro < 0) + { + i32Micro += 1000000; + i64--; + } + pTimeval->tv_sec = (time_t)i64; + pTimeval->tv_usec = i32Micro; + return pTimeval; +} + +/** + * Sets the time as POSIX timeval. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param pTimeval Pointer to the POSIX timeval struct with the new time. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetTimeval(PRTTIMESPEC pTime, const struct timeval *pTimeval) +{ + return RTTimeSpecAddMicro(RTTimeSpecSetSeconds(pTime, pTimeval->tv_sec), pTimeval->tv_usec); +} +#endif /* various ways of detecting struct timeval */ + + +/* PORTME: Add struct timespec guard macro here. */ +#if defined(RTTIME_INCL_TIMESPEC) || defined(_STRUCT_TIMESPEC) || defined(_SYS__TIMESPEC_H_) || defined(TIMEVAL_TO_TIMESPEC) || defined(_TIMESPEC) +/** + * Gets the time as POSIX timespec. + * + * @returns pTime. + * @param pTime The time spec to interpret. + * @param pTimespec Where to store the time as POSIX timespec. + */ +DECLINLINE(struct timespec *) RTTimeSpecGetTimespec(PCRTTIMESPEC pTime, struct timespec *pTimespec) +{ + int64_t i64 = RTTimeSpecGetNano(pTime); + int32_t i32Nano = (int32_t)(i64 % 1000000000); + i64 /= 1000000000; + if (i32Nano < 0) + { + i32Nano += 1000000000; + i64--; + } + pTimespec->tv_sec = (time_t)i64; + pTimespec->tv_nsec = i32Nano; + return pTimespec; +} + +/** + * Sets the time as POSIX timespec. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param pTimespec Pointer to the POSIX timespec struct with the new time. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetTimespec(PRTTIMESPEC pTime, const struct timespec *pTimespec) +{ + return RTTimeSpecAddNano(RTTimeSpecSetSeconds(pTime, pTimespec->tv_sec), pTimespec->tv_nsec); +} +#endif /* various ways of detecting struct timespec */ + + + +/** The offset of the unix epoch and the base for NT time (in 100ns units). + * Nt time starts at 1601-01-01 00:00:00. */ +#define RTTIME_NT_TIME_OFFSET_UNIX (116444736000000000LL) + + +/** + * Gets the time as NT time. + * + * @returns Nt time. + * @param pTime The time spec to interpret. + */ +DECLINLINE(uint64_t) RTTimeSpecGetNtTime(PCRTTIMESPEC pTime) +{ + return pTime->i64NanosecondsRelativeToUnixEpoch / 100 + + RTTIME_NT_TIME_OFFSET_UNIX; +} + + +/** + * Sets the time given by Nt time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param u64NtTime The new time in Nt time. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNtTime(PRTTIMESPEC pTime, uint64_t u64NtTime) +{ + pTime->i64NanosecondsRelativeToUnixEpoch = + ((int64_t)u64NtTime - RTTIME_NT_TIME_OFFSET_UNIX) * 100; + return pTime; +} + + +#ifdef _FILETIME_ +/** + * Gets the time as NT file time. + * + * @returns pFileTime. + * @param pTime The time spec to interpret. + * @param pFileTime Pointer to NT filetime structure. + */ +DECLINLINE(PFILETIME) RTTimeSpecGetNtFileTime(PCRTTIMESPEC pTime, PFILETIME pFileTime) +{ + *((uint64_t *)pFileTime) = RTTimeSpecGetNtTime(pTime); + return pFileTime; +} + +/** + * Sets the time as NT file time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param pFileTime Where to store the time as Nt file time. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNtFileTime(PRTTIMESPEC pTime, const FILETIME *pFileTime) +{ + return RTTimeSpecSetNtTime(pTime, *(const uint64_t *)pFileTime); +} +#endif + + +/** The offset to the start of DOS time. + * DOS time starts 1980-01-01 00:00:00. */ +#define RTTIME_OFFSET_DOS_TIME (315532800000000000LL) + + +/** + * Gets the time as seconds relative to the start of dos time. + * + * @returns seconds relative to the start of dos time. + * @param pTime The time spec to interpret. + */ +DECLINLINE(int64_t) RTTimeSpecGetDosSeconds(PCRTTIMESPEC pTime) +{ + return (pTime->i64NanosecondsRelativeToUnixEpoch - RTTIME_OFFSET_DOS_TIME) + / 1000000000; +} + + +/** + * Sets the time given by seconds relative to the start of dos time. + * + * @returns pTime. + * @param pTime The time spec to modify. + * @param i64Seconds The new time in seconds relative to the start of dos time. + */ +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetDosSeconds(PRTTIMESPEC pTime, int64_t i64Seconds) +{ + pTime->i64NanosecondsRelativeToUnixEpoch = i64Seconds * 1000000000 + + RTTIME_OFFSET_DOS_TIME; + return pTime; +} + + +/** + * Compare two time specs. + * + * @returns true they are equal. + * @returns false they are not equal. + * @param pTime1 The 1st time spec. + * @param pTime2 The 2nd time spec. + */ +DECLINLINE(bool) RTTimeSpecIsEqual(PCRTTIMESPEC pTime1, PCRTTIMESPEC pTime2) +{ + return pTime1->i64NanosecondsRelativeToUnixEpoch == pTime2->i64NanosecondsRelativeToUnixEpoch; +} + +/** + * Converts a time spec to a ISO date string. + * + * @returns psz on success. + * @returns NULL on buffer underflow. + * @param pTime The time spec. + * @param psz Where to store the string. + * @param cb The size of the buffer. + */ +RTDECL(char *) RTTimeSpecToString(PCRTTIMESPEC pTime, char *psz, size_t cb); + +/** @} */ + + +/** + * Exploded time. + */ +#pragma pack(1) +typedef struct RTTIME +{ + /** The year number. */ + int32_t i32Year; + /** The month of the year (1-12). January is 1. */ + uint8_t u8Month; + /** The day of the week (0-6). Monday is 0. */ + uint8_t u8WeekDay; + /** The day of the year (1-366). January the 1st is 1. */ + uint16_t u16YearDay; + /** The day of the month (1-31). */ + uint8_t u8MonthDay; + /** Hour of the day (0-23). */ + uint8_t u8Hour; + /** The minute of the hour (0-59). */ + uint8_t u8Minute; + /** The second of the minute (0-60). + * (u32Nanosecond / 1000000) */ + uint8_t u8Second; + /** The nanoseconds of the second (0-999999999). */ + uint32_t u32Nanosecond; + /** Flags, of the RTTIME_FLAGS_* \#defines. */ + uint32_t fFlags; + /** UCT time offset in minutes (-840-840). + * @remarks The implementation of RTTimeLocal* isn't quite there yet, so this might not be 100% correct. */ + int32_t offUTC; +} RTTIME; +#pragma pack() +/** Pointer to a exploded time structure. */ +typedef RTTIME *PRTTIME; +/** Pointer to a const exploded time structure. */ +typedef const RTTIME *PCRTTIME; + +/** @name RTTIME::fFlags values. + * @{ */ +/** Set if the time is UTC. If clear the time local time. */ +#define RTTIME_FLAGS_TYPE_MASK 3 +/** the time is UTC time. */ +#define RTTIME_FLAGS_TYPE_UTC 2 +/** The time is local time. */ +#define RTTIME_FLAGS_TYPE_LOCAL 3 + +/** Set if the time is local and daylight saving time is in effect. + * Not bit is not valid if RTTIME_FLAGS_NO_DST_DATA is set. */ +#define RTTIME_FLAGS_DST RT_BIT(4) +/** Set if the time is local and there is no data available on daylight saving time. */ +#define RTTIME_FLAGS_NO_DST_DATA RT_BIT(5) +/** Set if the year is a leap year. + * This is mutual exclusiv with RTTIME_FLAGS_COMMON_YEAR. */ +#define RTTIME_FLAGS_LEAP_YEAR RT_BIT(6) +/** Set if the year is a common year. + * This is mutual exclusiv with RTTIME_FLAGS_LEAP_YEAR. */ +#define RTTIME_FLAGS_COMMON_YEAR RT_BIT(7) +/** The mask of valid flags. */ +#define RTTIME_FLAGS_MASK UINT32_C(0xff) +/** @} */ + + +/** + * Gets the current system time (UTC). + * + * @returns pTime. + * @param pTime Where to store the time. + */ +RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime); + +/** + * Sets the system time. + * + * @returns IPRT status code + * @param pTime The new system time (UTC). + * + * @remarks This will usually fail because changing the wall time is usually + * requires extra privileges. + */ +RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime); + +/** + * Explodes a time spec (UTC). + * + * @returns pTime. + * @param pTime Where to store the exploded time. + * @param pTimeSpec The time spec to exploded. + */ +RTDECL(PRTTIME) RTTimeExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec); + +/** + * Implodes exploded time to a time spec (UTC). + * + * @returns pTime on success. + * @returns NULL if the pTime data is invalid. + * @param pTimeSpec Where to store the imploded UTC time. + * If pTime specifies a time which outside the range, maximum or + * minimum values will be returned. + * @param pTime Pointer to the exploded time to implode. + * The fields u8Month, u8WeekDay and u8MonthDay are not used, + * and all the other fields are expected to be within their + * bounds. Use RTTimeNormalize() to calculate u16YearDay and + * normalize the ranges of the fields. + */ +RTDECL(PRTTIMESPEC) RTTimeImplode(PRTTIMESPEC pTimeSpec, PCRTTIME pTime); + +/** + * Normalizes the fields of a time structure. + * + * It is possible to calculate year-day from month/day and vice + * versa. If you adjust any of of these, make sure to zero the + * other so you make it clear which of the fields to use. If + * it's ambiguous, the year-day field is used (and you get + * assertions in debug builds). + * + * All the time fields and the year-day or month/day fields will + * be adjusted for overflows. (Since all fields are unsigned, there + * is no underflows.) It is possible to exploit this for simple + * date math, though the recommended way of doing that to implode + * the time into a timespec and do the math on that. + * + * @returns pTime on success. + * @returns NULL if the data is invalid. + * + * @param pTime The time structure to normalize. + * + * @remarks This function doesn't work with local time, only with UTC time. + */ +RTDECL(PRTTIME) RTTimeNormalize(PRTTIME pTime); + +/** + * Gets the current local system time. + * + * @returns pTime. + * @param pTime Where to store the local time. + */ +RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime); + +/** + * Gets the delta between UTC and local time. + * + * @code + * RTTIMESPEC LocalTime; + * RTTimeSpecAddNano(RTTimeNow(&LocalTime), RTTimeLocalDeltaNano()); + * @endcode + * + * @returns Returns the nanosecond delta between UTC and local time. + */ +RTDECL(int64_t) RTTimeLocalDeltaNano(void); + +/** + * Explodes a time spec to the localized timezone. + * + * @returns pTime. + * @param pTime Where to store the exploded time. + * @param pTimeSpec The time spec to exploded (UTC). + */ +RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec); + +/** + * Normalizes the fields of a time structure containing local time. + * + * See RTTimeNormalize for details. + * + * @returns pTime on success. + * @returns NULL if the data is invalid. + * @param pTime The time structure to normalize. + */ +RTDECL(PRTTIME) RTTimeLocalNormalize(PRTTIME pTime); + +/** + * Converts a time spec to a ISO date string. + * + * @returns psz on success. + * @returns NULL on buffer underflow. + * @param pTime The time. Caller should've normalized this. + * @param psz Where to store the string. + * @param cb The size of the buffer. + */ +RTDECL(char *) RTTimeToString(PCRTTIME pTime, char *psz, size_t cb); + +/** + * Checks if a year is a leap year or not. + * + * @returns true if it's a leap year. + * @returns false if it's a common year. + * @param i32Year The year in question. + */ +RTDECL(bool) RTTimeIsLeapYear(int32_t i32Year); + +/** + * Gets the current nanosecond timestamp. + * + * @returns nanosecond timestamp. + */ +RTDECL(uint64_t) RTTimeNanoTS(void); + +/** + * Gets the current millisecond timestamp. + * + * @returns millisecond timestamp. + */ +RTDECL(uint64_t) RTTimeMilliTS(void); + +/** + * Debugging the time api. + * + * @returns the number of 1ns steps which has been applied by RTTimeNanoTS(). + */ +RTDECL(uint32_t) RTTimeDbgSteps(void); + +/** + * Debugging the time api. + * + * @returns the number of times the TSC interval expired RTTimeNanoTS(). + */ +RTDECL(uint32_t) RTTimeDbgExpired(void); + +/** + * Debugging the time api. + * + * @returns the number of bad previous values encountered by RTTimeNanoTS(). + */ +RTDECL(uint32_t) RTTimeDbgBad(void); + +/** + * Debugging the time api. + * + * @returns the number of update races in RTTimeNanoTS(). + */ +RTDECL(uint32_t) RTTimeDbgRaces(void); + +/** @name RTTimeNanoTS GIP worker functions, for TM. + * @{ */ +/** Pointer to a RTTIMENANOTSDATA structure. */ +typedef struct RTTIMENANOTSDATA *PRTTIMENANOTSDATA; + +/** + * Nanosecond timestamp data. + * + * This is used to keep track of statistics and callback so IPRT + * and TM (VirtualBox) can share code. + * + * @remark Keep this in sync with the assembly version in timesupA.asm. + */ +typedef struct RTTIMENANOTSDATA +{ + /** Where the previous timestamp is stored. + * This is maintained to ensure that time doesn't go backwards or anything. */ + uint64_t volatile *pu64Prev; + + /** + * Helper function that's used by the assembly routines when something goes bust. + * + * @param pData Pointer to this structure. + * @param u64NanoTS The calculated nano ts. + * @param u64DeltaPrev The delta relative to the previously returned timestamp. + * @param u64PrevNanoTS The previously returned timestamp (as it was read it). + */ + DECLCALLBACKMEMBER(void, pfnBad)(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS); + + /** + * Callback for when rediscovery is required. + * + * @returns Nanosecond timestamp. + * @param pData Pointer to this structure. + */ + DECLCALLBACKMEMBER(uint64_t, pfnRediscover)(PRTTIMENANOTSDATA pData); + + /** Just a dummy alignment member. */ + void *pvDummy; + + /** Number of 1ns steps because of overshooting the period. */ + uint32_t c1nsSteps; + /** The number of times the interval expired (overflow). */ + uint32_t cExpired; + /** Number of "bad" previous values. */ + uint32_t cBadPrev; + /** The number of update races. */ + uint32_t cUpdateRaces; +} RTTIMENANOTSDATA; + +#ifndef IN_RING3 +/** + * The Ring-3 layout of the RTTIMENANOTSDATA structure. + */ +typedef struct RTTIMENANOTSDATAR3 +{ + R3PTRTYPE(uint64_t volatile *) pu64Prev; + DECLR3CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS)); + DECLR3CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData)); + RTR3PTR pvDummy; + uint32_t c1nsSteps; + uint32_t cExpired; + uint32_t cBadPrev; + uint32_t cUpdateRaces; +} RTTIMENANOTSDATAR3; +#else +typedef RTTIMENANOTSDATA RTTIMENANOTSDATAR3; +#endif + +#ifndef IN_RING0 +/** + * The Ring-3 layout of the RTTIMENANOTSDATA structure. + */ +typedef struct RTTIMENANOTSDATAR0 +{ + R0PTRTYPE(uint64_t volatile *) pu64Prev; + DECLR0CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS)); + DECLR0CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData)); + RTR0PTR pvDummy; + uint32_t c1nsSteps; + uint32_t cExpired; + uint32_t cBadPrev; + uint32_t cUpdateRaces; +} RTTIMENANOTSDATAR0; +#else +typedef RTTIMENANOTSDATA RTTIMENANOTSDATAR0; +#endif + +#ifndef IN_RC +/** + * The RC layout of the RTTIMENANOTSDATA structure. + */ +typedef struct RTTIMENANOTSDATARC +{ + RCPTRTYPE(uint64_t volatile *) pu64Prev; + DECLRCCALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS)); + DECLRCCALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData)); + RCPTRTYPE(void *) pvDummy; + uint32_t c1nsSteps; + uint32_t cExpired; + uint32_t cBadPrev; + uint32_t cUpdateRaces; +} RTTIMENANOTSDATARC; +#else +typedef RTTIMENANOTSDATA RTTIMENANOTSDATARC; +#endif + +/** Internal RTTimeNanoTS worker (assembly). */ +typedef DECLCALLBACK(uint64_t) FNTIMENANOTSINTERNAL(PRTTIMENANOTSDATA pData); +/** Pointer to an internal RTTimeNanoTS worker (assembly). */ +typedef FNTIMENANOTSINTERNAL *PFNTIMENANOTSINTERNAL; + +RTDECL(uint64_t) RTTimeNanoTSLegacySync(PRTTIMENANOTSDATA pData); +RTDECL(uint64_t) RTTimeNanoTSLegacyAsync(PRTTIMENANOTSDATA pData); +RTDECL(uint64_t) RTTimeNanoTSLFenceSync(PRTTIMENANOTSDATA pData); +RTDECL(uint64_t) RTTimeNanoTSLFenceAsync(PRTTIMENANOTSDATA pData); +/** @} */ + + +/** + * Gets the current nanosecond timestamp. + * + * This differs from RTTimeNanoTS in that it will use system APIs and not do any + * resolution or performance optimizations. + * + * @returns nanosecond timestamp. + */ +RTDECL(uint64_t) RTTimeSystemNanoTS(void); + +/** + * Gets the current millisecond timestamp. + * + * This differs from RTTimeNanoTS in that it will use system APIs and not do any + * resolution or performance optimizations. + * + * @returns millisecond timestamp. + */ +RTDECL(uint64_t) RTTimeSystemMilliTS(void); + +/** + * Get the nanosecond timestamp relative to program startup. + * + * @returns Timestamp relative to program startup. + */ +RTDECL(uint64_t) RTTimeProgramNanoTS(void); + +/** + * Get the microsecond timestamp relative to program startup. + * + * @returns Timestamp relative to program startup. + */ +RTDECL(uint64_t) RTTimeProgramMicroTS(void); + +/** + * Get the millisecond timestamp relative to program startup. + * + * @returns Timestamp relative to program startup. + */ +RTDECL(uint64_t) RTTimeProgramMilliTS(void); + +/** + * Get the second timestamp relative to program startup. + * + * @returns Timestamp relative to program startup. + */ +RTDECL(uint32_t) RTTimeProgramSecTS(void); + +/** + * Get the RTTimeNanoTS() of when the program started. + * + * @returns Program startup timestamp. + */ +RTDECL(uint64_t) RTTimeProgramStartNanoTS(void); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/timer.h b/include/iprt/timer.h new file mode 100644 index 00000000..54e63a7a --- /dev/null +++ b/include/iprt/timer.h @@ -0,0 +1,379 @@ +/** @file + * IPRT - Timer. + */ + +/* + * Copyright (C) 2006-2012 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. + */ + +#ifndef ___iprt_timer_h +#define ___iprt_timer_h + + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_timer RTTimer - Timer + * + * The IPRT timer API provides a simple abstraction of recurring and one-shot callback timers. + * + * Because of the great variation in the native APIs and the quality of + * the service delivered by those native APIs, the timers are operated + * on at best effort basis. + * + * All the ring-3 implementations are naturally at the mercy of the scheduler, + * which means that the callback rate might vary quite a bit and we might skip + * ticks. Many systems have a restriction that a process can only have one + * timer. IPRT currently makes no efforts at multiplexing timers in those kind + * of situations and will simply fail if you try to create more than one timer. + * + * Things are generally better in ring-0. The implementations will use interrupt + * time callbacks wherever available, and if not, resort to a high priority + * kernel thread. + * + * @ingroup grp_rt + * @{ + */ + + +/** Timer handle. */ +typedef struct RTTIMER *PRTTIMER; + +/** + * Timer callback function. + * + * The context this call is made in varies with different platforms and + * kernel / user mode IPRT. + * + * In kernel mode a timer callback should not waste time, it shouldn't + * waste stack and it should be prepared that some APIs might not work + * correctly because of weird OS restrictions in this context that we + * haven't discovered and avoided yet. Please fix those APIs so they + * at least avoid panics and weird behaviour. + * + * @param pTimer Timer handle. + * @param pvUser User argument. + * @param iTick The current timer tick. This is always 1 on the first + * callback after the timer was started. For omni timers + * this will be 1 when a cpu comes back online. + */ +typedef DECLCALLBACK(void) FNRTTIMER(PRTTIMER pTimer, void *pvUser, uint64_t iTick); +/** Pointer to FNRTTIMER() function. */ +typedef FNRTTIMER *PFNRTTIMER; + + +/** + * Create a recurring timer. + * + * @returns iprt status code. + * @param ppTimer Where to store the timer handle. + * @param uMilliesInterval Milliseconds between the timer ticks. + * This is rounded up to the system granularity. + * @param pfnTimer Callback function which shall be scheduled for execution + * on every timer tick. + * @param pvUser User argument for the callback. + * @see RTTimerCreateEx, RTTimerStart, RTTimerStop, RTTimerChangeInterval, + * RTTimerDestroy, RTTimerGetSystemGranularity + */ +RTDECL(int) RTTimerCreate(PRTTIMER *ppTimer, unsigned uMilliesInterval, PFNRTTIMER pfnTimer, void *pvUser); + +/** + * Create a suspended timer. + * + * @returns iprt status code. + * @retval VERR_NOT_SUPPORTED if an unsupported flag was specfied. + * @retval VERR_CPU_NOT_FOUND if the specified CPU + * + * @param ppTimer Where to store the timer handle. + * @param u64NanoInterval The interval between timer ticks specified in nanoseconds if it's + * a recurring timer. This is rounded to the fit the system timer granularity. + * For one shot timers, pass 0. + * @param fFlags Timer flags. + * @param pfnTimer Callback function which shall be scheduled for execution + * on every timer tick. + * @param pvUser User argument for the callback. + * @see RTTimerStart, RTTimerStop, RTTimerChangeInterval, RTTimerDestroy, + * RTTimerGetSystemGranularity, RTTimerCanDoHighResolution + */ +RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser); + +/** @name RTTimerCreateEx flags + * @{ */ +/** Any CPU is fine. (Must be 0.) */ +#define RTTIMER_FLAGS_CPU_ANY UINT32_C(0) +/** One specific CPU */ +#define RTTIMER_FLAGS_CPU_SPECIFIC RT_BIT(8) +/** Omni timer, run on all online CPUs. + * @remarks The timer callback isn't necessarily running at the time same time on each CPU. */ +#define RTTIMER_FLAGS_CPU_ALL ( RTTIMER_FLAGS_CPU_MASK | RTTIMER_FLAGS_CPU_SPECIFIC ) +/** CPU mask. */ +#define RTTIMER_FLAGS_CPU_MASK UINT32_C(0xff) +/** Desire a high resolution timer that works with RTTimerChangeInterval and + * isn't subject to RTTimerGetSystemGranularity rounding. + * @remarks This is quietly ignored if the feature isn't supported. */ +#define RTTIMER_FLAGS_HIGH_RES RT_BIT(9) +/** Convert a CPU set index (0-based) to RTTimerCreateEx flags. + * This will automatically OR in the RTTIMER_FLAGS_CPU_SPECIFIC flag. */ +#define RTTIMER_FLAGS_CPU(iCpu) ( (iCpu) | RTTIMER_FLAGS_CPU_SPECIFIC ) +/** Macro that validates the flags. */ +#define RTTIMER_FLAGS_ARE_VALID(fFlags) \ + ( !((fFlags) & ~((fFlags) & RTTIMER_FLAGS_CPU_SPECIFIC ? UINT32_C(0x3ff) : UINT32_C(0x300))) ) +/** @} */ + +/** + * Stops and destroys a running timer. + * + * @returns iprt status code. + * @param pTimer Timer to stop and destroy. NULL is ok. + */ +RTDECL(int) RTTimerDestroy(PRTTIMER pTimer); + +/** + * Starts a suspended timer. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if pTimer isn't valid. + * @retval VERR_TIMER_ACTIVE if the timer isn't suspended. + * @retval VERR_CPU_OFFLINE if the CPU the timer was created to run on is not + * online (this include the case where it's not present in the + * system). + * + * @param pTimer The timer to activate. + * @param u64First The RTTimeSystemNanoTS() for when the timer should start + * firing (relative). If 0 is specified, the timer will + * fire ASAP. + * @remarks When RTTimerCanDoHighResolution returns true, this API is + * callable with preemption disabled in ring-0. + * @see RTTimerStop + */ +RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First); + +/** + * Stops an active timer. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if pTimer isn't valid. + * @retval VERR_TIMER_SUSPENDED if the timer isn't active. + * @retval VERR_NOT_SUPPORTED if the IPRT implementation doesn't support + * stopping a timer. + * + * @param pTimer The timer to suspend. + * @remarks Can be called from the timer callback function to stop it. + * @see RTTimerStart + */ +RTDECL(int) RTTimerStop(PRTTIMER pTimer); + +/** + * Changes the interval of a periodic timer. + * + * If the timer is active, it is implementation dependent whether the change + * takes place immediately or after the next tick. To get defined behavior, + * stop the timer before calling this API. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if pTimer isn't valid. + * @retval VERR_NOT_SUPPORTED if not supported. + * + * @param pTimer The timer to activate. + * @param u64NanoInterval The interval between timer ticks specified in + * nanoseconds. This is rounded to the fit the + * system timer granularity. + * @remarks Callable from the timer callback. Callable with preemption + * disabled in ring-0. + */ +RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval); + +/** + * Gets the (current) timer granularity of the system. + * + * @returns The timer granularity of the system in nanoseconds. + * @see RTTimerRequestSystemGranularity + */ +RTDECL(uint32_t) RTTimerGetSystemGranularity(void); + +/** + * Requests a specific system timer granularity. + * + * Successfull calls to this API must be coupled with the exact same number of + * calls to RTTimerReleaseSystemGranularity() in order to undo any changes made. + * + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the requested value isn't supported by the host platform + * or if the host platform doesn't support modifying the system timer granularity. + * @retval VERR_PERMISSION_DENIED if the caller doesn't have the necessary privilege to + * modify the system timer granularity. + * + * @param u32Request The requested system timer granularity in nanoseconds. + * @param pu32Granted Where to store the granted system granularity. This is the value + * that should be passed to RTTimerReleaseSystemGranularity(). It + * is what RTTimerGetSystemGranularity() would return immediately + * after the change was made. + * + * The value differ from the request in two ways; rounding and + * scale. Meaning if your request is for 10.000.000 you might + * be granted 10.000.055 or 1.000.000. + * @see RTTimerReleaseSystemGranularity, RTTimerGetSystemGranularity + */ +RTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted); + +/** + * Releases a system timer granularity grant acquired by RTTimerRequestSystemGranularity(). + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the host platform doesn't have any way of modifying + * the system timer granularity. + * @retval VERR_WRONG_ORDER if nobody call RTTimerRequestSystemGranularity() with the + * given grant value. + * @param u32Granted The granted system granularity. + * @see RTTimerRequestSystemGranularity + */ +RTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted); + +/** + * Checks if the system support high resolution timers. + * + * The kind of support we are checking for is the kind of dynamically + * reprogrammable timers employed by recent Solaris and Linux kernels. It also + * implies that we can specify microsecond (or even better maybe) intervals + * without getting into trouble. + * + * @returns true if supported, false it not. + * + * @remarks Returning true also means RTTimerChangeInterval must be implemented + * and RTTimerStart be callable with preemption disabled. + */ +RTDECL(bool) RTTimerCanDoHighResolution(void); + + +/** + * Timer callback function for low res timers. + * + * This is identical to FNRTTIMER except for the first parameter, so + * see FNRTTIMER for details. + * + * @param hTimerLR The low resolution timer handle. + * @param pvUser User argument. + * @param iTick The current timer tick. This is always 1 on the first + * callback after the timer was started. Will jump if we've + * skipped ticks when lagging behind. + */ +typedef DECLCALLBACK(void) FNRTTIMERLR(RTTIMERLR hTimerLR, void *pvUser, uint64_t iTick); +/** Pointer to FNRTTIMER() function. */ +typedef FNRTTIMERLR *PFNRTTIMERLR; + + +/** + * Create a recurring low resolution timer. + * + * @returns iprt status code. + * @param phTimerLR Where to store the timer handle. + * @param uMilliesInterval Milliseconds between the timer ticks, at least 100 ms. + * If higher resolution is required use the other API. + * @param pfnTimer Callback function which shall be scheduled for execution + * on every timer tick. + * @param pvUser User argument for the callback. + * @see RTTimerLRCreateEx, RTTimerLRDestroy, RTTimerLRStop + */ +RTDECL(int) RTTimerLRCreate(PRTTIMERLR phTimerLR, uint32_t uMilliesInterval, PFNRTTIMERLR pfnTimer, void *pvUser); + +/** + * Create a suspended low resolution timer. + * + * @returns iprt status code. + * @retval VERR_NOT_SUPPORTED if an unsupported flag was specfied. + * + * @param phTimerLR Where to store the timer handle. + * @param u64NanoInterval The interval between timer ticks specified in nanoseconds if it's + * a recurring timer, the minimum for is 100000000 ns. + * For one shot timers, pass 0. + * @param fFlags Timer flags. Same as RTTimerCreateEx. + * @param pfnTimer Callback function which shall be scheduled for execution + * on every timer tick. + * @param pvUser User argument for the callback. + * @see RTTimerLRStart, RTTimerLRStop, RTTimerLRDestroy + */ +RTDECL(int) RTTimerLRCreateEx(PRTTIMERLR phTimerLR, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMERLR pfnTimer, void *pvUser); + +/** + * Stops and destroys a running low resolution timer. + * + * @returns iprt status code. + * @param hTimerLR The low resolution timer to stop and destroy. + * NIL_RTTIMERLR is accepted. + */ +RTDECL(int) RTTimerLRDestroy(RTTIMERLR hTimerLR); + +/** + * Starts a low resolution timer. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if pTimer isn't valid. + * @retval VERR_TIMER_ACTIVE if the timer isn't suspended. + * + * @param hTimerLR The low resolution timer to activate. + * @param u64First The RTTimeSystemNanoTS() for when the timer should start + * firing (relative), the minimum is 100000000 ns. + * If 0 is specified, the timer will fire ASAP. + * + * @see RTTimerLRStop + */ +RTDECL(int) RTTimerLRStart(RTTIMERLR hTimerLR, uint64_t u64First); + +/** + * Stops an active low resolution timer. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if pTimer isn't valid. + * @retval VERR_TIMER_SUSPENDED if the timer isn't active. + * @retval VERR_NOT_SUPPORTED if the IPRT implementation doesn't support stopping a timer. + * + * @param hTimerLR The low resolution timer to suspend. + * + * @see RTTimerLRStart + */ +RTDECL(int) RTTimerLRStop(RTTIMERLR hTimerLR); + +/** + * Changes the interval of a low resolution timer. + * + * If the timer is active, the next tick will occure immediately just like with + * RTTimerLRStart() when u64First parameter is zero. + * + * @returns IPRT status code. + * @retval VERR_INVALID_HANDLE if pTimer isn't valid. + * @retval VERR_NOT_SUPPORTED if not supported. + * + * @param hTimerLR The low resolution timer to update. + * @param u64NanoInterval The interval between timer ticks specified in + * nanoseconds. This is rounded to the fit the + * system timer granularity. + * @remarks Callable from the timer callback. + */ +RTDECL(int) RTTimerLRChangeInterval(RTTIMERLR hTimerLR, uint64_t u64NanoInterval); + +/** @} */ + +RT_C_DECLS_END + +#endif diff --git a/include/iprt/trace.h b/include/iprt/trace.h new file mode 100644 index 00000000..263c715b --- /dev/null +++ b/include/iprt/trace.h @@ -0,0 +1,215 @@ +/** @file + * IPRT - Tracing. + */ + +/* + * Copyright (C) 2011 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. + */ + +#ifndef ___iprt_trace_h +#define ___iprt_trace_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/stdarg.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_trace RTTrace - Tracing + * @ingroup grp_rt + * + * The tracing facility is somewhat similar to a stripped down logger that + * outputs to a circular buffer. Part of the idea here is that it can the + * overhead is much smaller and that it can be done without involving any + * locking or other thing that could throw off timing. + * + * @{ + */ + + +#ifdef DOXYGEN_RUNNING +# define RTTRACE_DISABLED +# define RTTRACE_ENABLED +#endif + +/** @def RTTRACE_DISABLED + * Use this compile time define to disable all tracing macros. This trumps + * RTTRACE_ENABLED. + */ + +/** @def RTTRACE_ENABLED + * Use this compile time define to enable tracing when not in debug mode + */ + +/* + * Determine whether tracing is enabled and forcefully normalize the indicators. + */ +#if (defined(DEBUG) || defined(RTTRACE_ENABLED)) && !defined(RTTRACE_DISABLED) +# undef RTTRACE_DISABLED +# undef RTTRACE_ENABLED +# define RTTRACE_ENABLED +#else +# undef RTTRACE_DISABLED +# undef RTTRACE_ENABLED +# define RTTRACE_DISABLED +#endif + + +/** @name RTTRACEBUF_FLAGS_XXX - RTTraceBufCarve and RTTraceBufCreate flags. + * @{ */ +/** Free the memory block on release using RTMemFree(). */ +#define RTTRACEBUF_FLAGS_FREE_ME RT_BIT_32(0) +/** Whether the trace buffer is disabled or enabled. */ +#define RTTRACEBUF_FLAGS_DISABLED RT_BIT_32(RTTRACEBUF_FLAGS_DISABLED_BIT) +/** The bit number corresponding to the RTTRACEBUF_FLAGS_DISABLED mask. */ +#define RTTRACEBUF_FLAGS_DISABLED_BIT 1 +/** Mask of the valid flags. */ +#define RTTRACEBUF_FLAGS_MASK UINT32_C(0x00000003) +/** @} */ + + +RTDECL(int) RTTraceBufCreate(PRTTRACEBUF hTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags); +RTDECL(int) RTTraceBufCarve(PRTTRACEBUF hTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags, + void *pvBlock, size_t *pcbBlock); +RTDECL(uint32_t) RTTraceBufRetain(RTTRACEBUF hTraceBuf); +RTDECL(uint32_t) RTTraceBufRelease(RTTRACEBUF hTraceBuf); +RTDECL(int) RTTraceBufDumpToLog(RTTRACEBUF hTraceBuf); +RTDECL(int) RTTraceBufDumpToAssert(RTTRACEBUF hTraceBuf); + +/** + * Trace buffer callback for processing one entry. + * + * Used by RTTraceBufEnumEntries. + * + * @returns IPRT status code. Any status code but VINF_SUCCESS will abort the + * enumeration and be returned by RTTraceBufEnumEntries. + * @param hTraceBuf The trace buffer handle. + * @param iEntry The entry number. + * @param NanoTS The timestamp of the entry. + * @param idCpu The ID of the CPU which added the entry. + * @param pszMsg The message text. + * @param pvUser The user argument. + */ +typedef DECLCALLBACK(int) FNRTTRACEBUFCALLBACK(RTTRACEBUF hTraceBuf, uint32_t iEntry, uint64_t NanoTS, + RTCPUID idCpu, const char *pszMsg, void *pvUser); +/** Pointer to trace buffer enumeration callback function. */ +typedef FNRTTRACEBUFCALLBACK *PFNRTTRACEBUFCALLBACK; + +/** + * Enumerates the used trace buffer entries, calling @a pfnCallback for each. + * + * @returns IPRT status code. Should the callback (@a pfnCallback) return + * anything other than VINF_SUCCESS, then the enumeration will be + * aborted and the status code will be returned by this function. + * @retval VINF_SUCCESS + * @retval VERR_INVALID_HANDLE + * @retval VERR_INVALID_PARAMETER + * @retval VERR_INVALID_POINTER + * + * @param hTraceBuf The trace buffer handle. Special handles are + * accepted. + * @param pfnCallback The callback to call for each entry. + * @param pvUser The user argument for the callback. + */ +RTDECL(int) RTTraceBufEnumEntries(RTTRACEBUF hTraceBuf, PFNRTTRACEBUFCALLBACK pfnCallback, void *pvUser); + +/** + * Gets the entry size used by the specified trace buffer. + * + * @returns The size on success, 0 if the handle is invalid. + * + * @param hTraceBuf The trace buffer handle. Special handles are + * accepted. + */ +RTDECL(uint32_t) RTTraceBufGetEntrySize(RTTRACEBUF hTraceBuf); + +/** + * Gets the number of entries in the specified trace buffer. + * + * @returns The entry count on success, 0 if the handle is invalid. + * + * @param hTraceBuf The trace buffer handle. Special handles are + * accepted. + */ +RTDECL(uint32_t) RTTraceBufGetEntryCount(RTTRACEBUF hTraceBuf); + + +/** + * Disables tracing. + * + * @returns @c true if tracing was enabled prior to this call, @c false if + * disabled already. + * + * @param hTraceBuf The trace buffer handle. Special handles are + * accepted. + */ +RTDECL(bool) RTTraceBufDisable(RTTRACEBUF hTraceBuf); + +/** + * Enables tracing. + * + * @returns @c true if tracing was enabled prior to this call, @c false if + * disabled already. + * + * @param hTraceBuf The trace buffer handle. Special handles are + * accepted. + */ +RTDECL(bool) RTTraceBufEnable(RTTRACEBUF hTraceBuf); + + +RTDECL(int) RTTraceBufAddMsg( RTTRACEBUF hTraceBuf, const char *pszMsg); +RTDECL(int) RTTraceBufAddMsgF( RTTRACEBUF hTraceBuf, const char *pszMsgFmt, ...); +RTDECL(int) RTTraceBufAddMsgV( RTTRACEBUF hTraceBuf, const char *pszMsgFmt, va_list va); +RTDECL(int) RTTraceBufAddMsgEx( RTTRACEBUF hTraceBuf, const char *pszMsg, size_t cbMaxMsg); + +RTDECL(int) RTTraceBufAddPos( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL); +RTDECL(int) RTTraceBufAddPosMsg( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg); +RTDECL(int) RTTraceBufAddPosMsgEx( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg, size_t cbMaxMsg); +RTDECL(int) RTTraceBufAddPosMsgF( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, ...); +RTDECL(int) RTTraceBufAddPosMsgV( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, va_list va); + + +RTDECL(int) RTTraceSetDefaultBuf(RTTRACEBUF hTraceBuf); +RTDECL(RTTRACEBUF) RTTraceGetDefaultBuf(void); + + +/** @def RTTRACE_BUF + * The trace buffer used by the macros. + */ +#ifndef RTTRACE_BUF +# define RTTRACE_BUF NULL +#endif + +/** + * Record the current source position. + */ +#ifdef RTTRACE_ENABLED +# define RTTRACE_POS() do { RTTraceBufAddPos(RTTRACE_BUF, RT_SRC_POS); } while (0) +#else +# define RTTRACE_POS() do { } while (0) +#endif + + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/types.h b/include/iprt/types.h new file mode 100644 index 00000000..e841dea5 --- /dev/null +++ b/include/iprt/types.h @@ -0,0 +1,2371 @@ +/** @file + * IPRT - Types. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_types_h +#define ___iprt_types_h + +#include <iprt/cdefs.h> +#include <iprt/stdint.h> + +/* + * Include standard C types. + */ +#ifndef IPRT_NO_CRT + +# if defined(IN_XF86_MODULE) && !defined(NO_ANSIC) + /* + * Kludge for xfree86 modules: size_t and other types are redefined. + */ +RT_C_DECLS_BEGIN +# include "xf86_ansic.h" +# undef NULL +RT_C_DECLS_END + +# elif defined(RT_OS_DARWIN) && defined(KERNEL) + /* + * Kludge for the darwin kernel: + * stddef.h is missing IIRC. + */ +# ifndef _PTRDIFF_T +# define _PTRDIFF_T + typedef __darwin_ptrdiff_t ptrdiff_t; +# endif +# include <sys/types.h> + +# elif defined(RT_OS_FREEBSD) && defined(_KERNEL) + /* + * Kludge for the FreeBSD kernel: + * stddef.h and sys/types.h have slightly different offsetof definitions + * when compiling in kernel mode. This is just to make GCC shut up. + */ +# ifndef _STDDEF_H_ +# undef offsetof +# endif +# include <sys/stddef.h> +# ifndef _SYS_TYPES_H_ +# undef offsetof +# endif +# include <sys/types.h> +# ifndef offsetof +# error "offsetof is not defined..." +# endif + +# elif defined(RT_OS_FREEBSD) && HC_ARCH_BITS == 64 && defined(RT_ARCH_X86) + /* + * Kludge for compiling 32-bit code on a 64-bit FreeBSD: + * FreeBSD declares uint64_t and int64_t wrong (long unsigned and long int + * though they need to be long long unsigned and long long int). These + * defines conflict with our decleration in stdint.h. Adding the defines + * below omits the definitions in the system header. + */ +# include <stddef.h> +# define _UINT64_T_DECLARED +# define _INT64_T_DECLARED +# define _UINTPTR_T_DECLARED +# define _INTPTR_T_DECLARED +# include <sys/types.h> + +# elif defined(RT_OS_LINUX) && defined(__KERNEL__) + /* + * Kludge for the linux kernel: + * 1. sys/types.h doesn't mix with the kernel. + * 2. Starting with 2.6.19, linux/types.h typedefs bool and linux/stddef.h + * declares false and true as enum values. + * 3. Starting with 2.6.24, linux/types.h typedefs uintptr_t. + * We work around these issues here and nowhere else. + */ +# include <stddef.h> +# if defined(__cplusplus) + typedef bool _Bool; +# endif +# define bool linux_bool +# define true linux_true +# define false linux_false +# define uintptr_t linux_uintptr_t +# include <linux/version.h> +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) +# include <generated/autoconf.h> +# else +# ifndef AUTOCONF_INCLUDED +# include <linux/autoconf.h> +# endif +# endif +# include <linux/compiler.h> +# if defined(__cplusplus) + /* + * Starting with 3.3, <linux/compiler-gcc.h> appends 'notrace' (which + * expands to __attribute__((no_instrument_function))) to inline, + * __inline and __inline__. Revert that. + */ +# undef inline +# define inline inline +# undef __inline__ +# define __inline__ __inline__ +# undef __inline +# define __inline __inline +# endif +# include <linux/types.h> +# include <linux/stddef.h> + /* + * Starting with 3.4, <linux/stddef.h> defines NULL as '((void*)0)' which + * does not work for C++ code. + */ +# undef NULL +# undef uintptr_t +# ifdef __GNUC__ +# if (__GNUC__ * 100 + __GNUC_MINOR__) <= 400 + /* + * <linux/compiler-gcc{3,4}.h> does + * #define __inline__ __inline__ __attribute__((always_inline)) + * in some older Linux kernels. Forcing inlining will fail for some RTStrA* + * functions with gcc <= 4.0 due to passing variable argument lists. + */ +# undef __inline__ +# define __inline__ __inline__ +# endif +# endif +# undef false +# undef true +# undef bool +# else +# include <stddef.h> +# include <sys/types.h> +# endif + + +/* Define any types missing from sys/types.h on windows. */ +# ifdef _MSC_VER +# undef ssize_t + typedef intptr_t ssize_t; +# endif + +#else /* no crt */ +# include <iprt/nocrt/compiler/compiler.h> +#endif /* no crt */ + +/** @def NULL + * NULL pointer. + */ +#ifndef NULL +# ifdef __cplusplus +# define NULL 0 +# else +# define NULL ((void*)0) +# endif +#endif + + + +/** @defgroup grp_rt_types IPRT Base Types + * @{ + */ + +/* define wchar_t, we don't wanna include all the wcsstuff to get this. */ +#ifdef _MSC_VER +# ifndef _WCHAR_T_DEFINED + typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +# endif +#endif +#ifdef __GNUC__ +/** @todo wchar_t on GNUC */ +#endif + +/* + * C doesn't have bool. + */ +#ifndef __cplusplus +# if defined(__GNUC__) +# if defined(RT_OS_LINUX) && __GNUC__ < 3 +typedef uint8_t bool; +# elif defined(RT_OS_FREEBSD) +# ifndef __bool_true_false_are_defined +typedef _Bool bool; +# endif +# else +# if defined(RT_OS_DARWIN) && defined(_STDBOOL_H) +# undef bool +# endif +typedef _Bool bool; +# endif +# else +typedef unsigned char bool; +# endif +# ifndef true +# define true (1) +# endif +# ifndef false +# define false (0) +# endif +#endif + +/** + * 128-bit unsigned integer. + */ +#if defined(__GNUC__) && defined(RT_ARCH_AMD64) +typedef __uint128_t uint128_t; +#else +typedef struct uint128_s +{ +# ifdef RT_BIG_ENDIAN + uint64_t Hi; + uint64_t Lo; +# else + uint64_t Lo; + uint64_t Hi; +# endif +} uint128_t; +#endif + + +/** + * 128-bit signed integer. + */ +#if defined(__GNUC__) && defined(RT_ARCH_AMD64) +typedef __int128_t int128_t; +#else +typedef struct int128_s +{ +# ifdef RT_BIG_ENDIAN + int64_t Hi; + uint64_t Lo; +# else + uint64_t Lo; + int64_t Hi; +# endif +} int128_t; +#endif + + +/** + * 16-bit unsigned integer union. + */ +typedef union RTUINT16U +{ + /** natural view. */ + uint16_t u; + + /** 16-bit view. */ + uint16_t au16[1]; + /** 8-bit view. */ + uint8_t au8[2]; + /** 16-bit hi/lo view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint8_t Hi; + uint8_t Lo; +#else + uint8_t Lo; + uint8_t Hi; +#endif + } s; +} RTUINT16U; +/** Pointer to a 16-bit unsigned integer union. */ +typedef RTUINT16U *PRTUINT16U; +/** Pointer to a const 32-bit unsigned integer union. */ +typedef const RTUINT16U *PCRTUINT16U; + + +/** + * 32-bit unsigned integer union. + */ +typedef union RTUINT32U +{ + /** natural view. */ + uint32_t u; + /** Hi/Low view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint16_t Hi; + uint16_t Lo; +#else + uint16_t Lo; + uint16_t Hi; +#endif + } s; + /** Word view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint16_t w1; + uint16_t w0; +#else + uint16_t w0; + uint16_t w1; +#endif + } Words; + + /** 32-bit view. */ + uint32_t au32[1]; + /** 16-bit view. */ + uint16_t au16[2]; + /** 8-bit view. */ + uint8_t au8[4]; +} RTUINT32U; +/** Pointer to a 32-bit unsigned integer union. */ +typedef RTUINT32U *PRTUINT32U; +/** Pointer to a const 32-bit unsigned integer union. */ +typedef const RTUINT32U *PCRTUINT32U; + + +/** + * 64-bit unsigned integer union. + */ +typedef union RTUINT64U +{ + /** Natural view. */ + uint64_t u; + /** Hi/Low view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint32_t Hi; + uint32_t Lo; +#else + uint32_t Lo; + uint32_t Hi; +#endif + } s; + /** Double-Word view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint32_t dw1; + uint32_t dw0; +#else + uint32_t dw0; + uint32_t dw1; +#endif + } DWords; + /** Word view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint16_t w3; + uint16_t w2; + uint16_t w1; + uint16_t w0; +#else + uint16_t w0; + uint16_t w1; + uint16_t w2; + uint16_t w3; +#endif + } Words; + + /** 64-bit view. */ + uint64_t au64[1]; + /** 32-bit view. */ + uint32_t au32[2]; + /** 16-bit view. */ + uint16_t au16[4]; + /** 8-bit view. */ + uint8_t au8[8]; +} RTUINT64U; +/** Pointer to a 64-bit unsigned integer union. */ +typedef RTUINT64U *PRTUINT64U; +/** Pointer to a const 64-bit unsigned integer union. */ +typedef const RTUINT64U *PCRTUINT64U; + + +/** + * 128-bit unsigned integer union. + */ +typedef union RTUINT128U +{ + /** Natural view. + * WARNING! This member depends on the compiler supporting 128-bit stuff. */ + uint128_t u; + /** Hi/Low view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint64_t Hi; + uint64_t Lo; +#else + uint64_t Lo; + uint64_t Hi; +#endif + } s; + /** Quad-Word view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint64_t qw1; + uint64_t qw0; +#else + uint64_t qw0; + uint64_t qw1; +#endif + } QWords; + /** Double-Word view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint32_t dw3; + uint32_t dw2; + uint32_t dw1; + uint32_t dw0; +#else + uint32_t dw0; + uint32_t dw1; + uint32_t dw2; + uint32_t dw3; +#endif + } DWords; + /** Word view. */ + struct + { +#ifdef RT_BIG_ENDIAN + uint16_t w7; + uint16_t w6; + uint16_t w5; + uint16_t w4; + uint16_t w3; + uint16_t w2; + uint16_t w1; + uint16_t w0; +#else + uint16_t w0; + uint16_t w1; + uint16_t w2; + uint16_t w3; + uint16_t w4; + uint16_t w5; + uint16_t w6; + uint16_t w7; +#endif + } Words; + + /** 64-bit view. */ + uint64_t au64[2]; + /** 32-bit view. */ + uint32_t au32[4]; + /** 16-bit view. */ + uint16_t au16[8]; + /** 8-bit view. */ + uint8_t au8[16]; +} RTUINT128U; +/** Pointer to a 64-bit unsigned integer union. */ +typedef RTUINT128U *PRTUINT128U; +/** Pointer to a const 64-bit unsigned integer union. */ +typedef const RTUINT128U *PCRTUINT128U; + + +/** + * Double precision floating point format (64-bit). + */ +typedef union RTFLOAT64U +{ +#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) + /** Double view. */ + double rd; +#endif + /** Format using regular bitfields. */ + struct + { +# ifdef RT_BIG_ENDIAN + /** The sign indicator. */ + uint32_t fSign : 1; + /** The exponent (offseted by 1023). */ + uint32_t uExponent : 11; + /** The fraction, bits 32 thru 51. */ + uint32_t u20FractionHigh : 20; + /** The fraction, bits 0 thru 31. */ + uint32_t u32FractionLow; +# else + /** The fraction, bits 0 thru 31. */ + uint32_t u32FractionLow; + /** The fraction, bits 32 thru 51. */ + uint32_t u20FractionHigh : 20; + /** The exponent (offseted by 1023). */ + uint32_t uExponent : 11; + /** The sign indicator. */ + uint32_t fSign : 1; +# endif + } s; + +#ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS + /** Format using 64-bit bitfields. */ + RT_GCC_EXTENSION struct + { +# ifdef RT_BIG_ENDIAN + /** The sign indicator. */ + RT_GCC_EXTENSION uint64_t fSign : 1; + /** The exponent (offseted by 1023). */ + RT_GCC_EXTENSION uint64_t uExponent : 11; + /** The fraction. */ + RT_GCC_EXTENSION uint64_t uFraction : 52; +# else + /** The fraction. */ + RT_GCC_EXTENSION uint64_t uFraction : 52; + /** The exponent (offseted by 1023). */ + RT_GCC_EXTENSION uint64_t uExponent : 11; + /** The sign indicator. */ + RT_GCC_EXTENSION uint64_t fSign : 1; +# endif + } s64; +#endif + + /** 64-bit view. */ + uint64_t au64[1]; + /** 32-bit view. */ + uint32_t au32[2]; + /** 16-bit view. */ + uint16_t au16[4]; + /** 8-bit view. */ + uint8_t au8[8]; +} RTFLOAT64U; +/** Pointer to a double precision floating point format union. */ +typedef RTFLOAT64U *PRTFLOAT64U; +/** Pointer to a const double precision floating point format union. */ +typedef const RTFLOAT64U *PCRTFLOAT64U; + + +/** + * Extended Double precision floating point format (80-bit). + */ +#pragma pack(1) +typedef union RTFLOAT80U +{ + /** Format using bitfields. */ + RT_GCC_EXTENSION struct + { +# ifdef RT_BIG_ENDIAN + /** The sign indicator. */ + RT_GCC_EXTENSION uint16_t fSign : 1; + /** The exponent (offseted by 16383). */ + RT_GCC_EXTENSION uint16_t uExponent : 15; + /** The mantissa. */ + uint64_t u64Mantissa; +# else + /** The mantissa. */ + uint64_t u64Mantissa; + /** The exponent (offseted by 16383). */ + RT_GCC_EXTENSION uint16_t uExponent : 15; + /** The sign indicator. */ + RT_GCC_EXTENSION uint16_t fSign : 1; +# endif + } s; + + /** 64-bit view. */ + uint64_t au64[1]; + /** 32-bit view. */ + uint32_t au32[2]; + /** 16-bit view. */ + uint16_t au16[5]; + /** 8-bit view. */ + uint8_t au8[10]; +} RTFLOAT80U; +#pragma pack() +/** Pointer to a extended precision floating point format union. */ +typedef RTFLOAT80U *PRTFLOAT80U; +/** Pointer to a const extended precision floating point format union. */ +typedef const RTFLOAT80U *PCRTFLOAT80U; + + +/** + * A variant of RTFLOAT80U that may be larger than 80-bits depending on how the + * compiler implements long double. + */ +#pragma pack(1) +typedef union RTFLOAT80U2 +{ +#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE + /** Long double view. */ + long double lrd; +#endif + /** Format using bitfields. */ + RT_GCC_EXTENSION struct + { +#ifdef RT_BIG_ENDIAN + /** The sign indicator. */ + RT_GCC_EXTENSION uint16_t fSign : 1; + /** The exponent (offseted by 16383). */ + RT_GCC_EXTENSION uint16_t uExponent : 15; + /** The mantissa. */ + uint64_t u64Mantissa; +#else + /** The mantissa. */ + uint64_t u64Mantissa; + /** The exponent (offseted by 16383). */ + RT_GCC_EXTENSION uint16_t uExponent : 15; + /** The sign indicator. */ + RT_GCC_EXTENSION uint16_t fSign : 1; +#endif + } s; + + /** Bitfield exposing the J bit and the fraction. */ + RT_GCC_EXTENSION struct + { +#ifdef RT_BIG_ENDIAN + /** The sign indicator. */ + RT_GCC_EXTENSION uint16_t fSign : 1; + /** The exponent (offseted by 16383). */ + RT_GCC_EXTENSION uint16_t uExponent : 15; + /** The J bit, aka the integer bit. */ + uint32_t fInteger; + /** The fraction, bits 32 thru 62. */ + uint32_t u31FractionHigh : 31; + /** The fraction, bits 0 thru 31. */ + uint32_t u32FractionLow : 32; +#else + /** The fraction, bits 0 thru 31. */ + uint32_t u32FractionLow : 32; + /** The fraction, bits 32 thru 62. */ + uint32_t u31FractionHigh : 31; + /** The J bit, aka the integer bit. */ + uint32_t fInteger; + /** The exponent (offseted by 16383). */ + RT_GCC_EXTENSION uint16_t uExponent : 15; + /** The sign indicator. */ + RT_GCC_EXTENSION uint16_t fSign : 1; +#endif + } sj; + +#ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS + /** 64-bit bitfields exposing the J bit and the fraction. */ + RT_GCC_EXTENSION struct + { +# ifdef RT_BIG_ENDIAN + /** The sign indicator. */ + RT_GCC_EXTENSION uint16_t fSign : 1; + /** The exponent (offseted by 16383). */ + RT_GCC_EXTENSION uint16_t uExponent : 15; + /** The J bit, aka the integer bit. */ + RT_GCC_EXTENSION uint64_t fInteger : 1; + /** The fraction. */ + RT_GCC_EXTENSION uint64_t u63Fraction : 63; +# else + /** The fraction. */ + RT_GCC_EXTENSION uint64_t u63Fraction : 63; + /** The J bit, aka the integer bit. */ + RT_GCC_EXTENSION uint64_t fInteger : 1; + /** The exponent (offseted by 16383). */ + RT_GCC_EXTENSION uint16_t uExponent : 15; + /** The sign indicator. */ + RT_GCC_EXTENSION uint16_t fSign : 1; +# endif + } sj64; +#endif + + /** 64-bit view. */ + uint64_t au64[1]; + /** 32-bit view. */ + uint32_t au32[2]; + /** 16-bit view. */ + uint16_t au16[5]; + /** 8-bit view. */ + uint8_t au8[10]; +} RTFLOAT80U2; +#pragma pack() +/** Pointer to a extended precision floating point format union, 2nd + * variant. */ +typedef RTFLOAT80U2 *PRTFLOAT80U2; +/** Pointer to a const extended precision floating point format union, 2nd + * variant. */ +typedef const RTFLOAT80U2 *PCRTFLOAT80U2; + + +/** Generic function type. + * @see PFNRT + */ +typedef DECLCALLBACK(void) FNRT(void); + +/** Generic function pointer. + * With -pedantic, gcc-4 complains when casting a function to a data object, for + * example: + * + * @code + * void foo(void) + * { + * } + * + * void *bar = (void *)foo; + * @endcode + * + * The compiler would warn with "ISO C++ forbids casting between + * pointer-to-function and pointer-to-object". The purpose of this warning is + * not to bother the programmer but to point out that he is probably doing + * something dangerous, assigning a pointer to executable code to a data object. + */ +typedef FNRT *PFNRT; + +/** Millisecond interval. */ +typedef uint32_t RTMSINTERVAL; +/** Pointer to a millisecond interval. */ +typedef RTMSINTERVAL *PRTMSINTERVAL; +/** Pointer to a const millisecond interval. */ +typedef const RTMSINTERVAL *PCRTMSINTERVAL; + +/** Pointer to a time spec structure. */ +typedef struct RTTIMESPEC *PRTTIMESPEC; +/** Pointer to a const time spec structure. */ +typedef const struct RTTIMESPEC *PCRTTIMESPEC; + +/** + * Generic pointer union. + */ +typedef union RTPTRUNION +{ + /** Pointer into the void... */ + void *pv; + /** Pointer to a 8-bit unsigned value. */ + uint8_t *pu8; + /** Pointer to a 16-bit unsigned value. */ + uint16_t *pu16; + /** Pointer to a 32-bit unsigned value. */ + uint32_t *pu32; + /** Pointer to a 64-bit unsigned value. */ + uint64_t *pu64; +} RTPTRUNION; +/** Pointer to a pointer union. */ +typedef RTPTRUNION *PRTPTRUNION; + +/** + * Generic const pointer union. + */ +typedef union RTCPTRUNION +{ + /** Pointer into the void... */ + void const *pv; + /** Pointer to a 8-bit unsigned value. */ + uint8_t const *pu8; + /** Pointer to a 16-bit unsigned value. */ + uint16_t const *pu16; + /** Pointer to a 32-bit unsigned value. */ + uint32_t const *pu32; + /** Pointer to a 64-bit unsigned value. */ + uint64_t const *pu64; +} RTCPTRUNION; +/** Pointer to a const pointer union. */ +typedef RTCPTRUNION *PRTCPTRUNION; + +/** + * Generic volatile pointer union. + */ +typedef union RTVPTRUNION +{ + /** Pointer into the void... */ + void volatile *pv; + /** Pointer to a 8-bit unsigned value. */ + uint8_t volatile *pu8; + /** Pointer to a 16-bit unsigned value. */ + uint16_t volatile *pu16; + /** Pointer to a 32-bit unsigned value. */ + uint32_t volatile *pu32; + /** Pointer to a 64-bit unsigned value. */ + uint64_t volatile *pu64; +} RTVPTRUNION; +/** Pointer to a const pointer union. */ +typedef RTVPTRUNION *PRTVPTRUNION; + +/** + * Generic const volatile pointer union. + */ +typedef union RTCVPTRUNION +{ + /** Pointer into the void... */ + void const volatile *pv; + /** Pointer to a 8-bit unsigned value. */ + uint8_t const volatile *pu8; + /** Pointer to a 16-bit unsigned value. */ + uint16_t const volatile *pu16; + /** Pointer to a 32-bit unsigned value. */ + uint32_t const volatile *pu32; + /** Pointer to a 64-bit unsigned value. */ + uint64_t const volatile *pu64; +} RTCVPTRUNION; +/** Pointer to a const pointer union. */ +typedef RTCVPTRUNION *PRTCVPTRUNION; + + +/** @defgroup grp_rt_types_both Common Guest and Host Context Basic Types + * @ingroup grp_rt_types + * @{ + */ + +/** Signed integer which can contain both GC and HC pointers. */ +#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) +typedef int32_t RTINTPTR; +#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64) +typedef int64_t RTINTPTR; +#else +# error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values. +#endif +/** Pointer to signed integer which can contain both GC and HC pointers. */ +typedef RTINTPTR *PRTINTPTR; +/** Pointer const to signed integer which can contain both GC and HC pointers. */ +typedef const RTINTPTR *PCRTINTPTR; +/** The maximum value the RTINTPTR type can hold. */ +#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) +# define RTINTPTR_MAX INT32_MAX +#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64) +# define RTINTPTR_MAX INT64_MAX +#else +# error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values. +#endif +/** The minimum value the RTINTPTR type can hold. */ +#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) +# define RTINTPTR_MIN INT32_MIN +#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64) +# define RTINTPTR_MIN INT64_MIN +#else +# error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values. +#endif + +/** Unsigned integer which can contain both GC and HC pointers. */ +#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) +typedef uint32_t RTUINTPTR; +#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64) +typedef uint64_t RTUINTPTR; +#else +# error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values. +#endif +/** Pointer to unsigned integer which can contain both GC and HC pointers. */ +typedef RTUINTPTR *PRTUINTPTR; +/** Pointer const to unsigned integer which can contain both GC and HC pointers. */ +typedef const RTUINTPTR *PCRTUINTPTR; +/** The maximum value the RTUINTPTR type can hold. */ +#if (HC_ARCH_BITS == 32 && GC_ARCH_BITS == 32) +# define RTUINTPTR_MAX UINT32_MAX +#elif (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64) +# define RTUINTPTR_MAX UINT64_MAX +#else +# error Unsupported HC_ARCH_BITS and/or GC_ARCH_BITS values. +#endif + +/** Signed integer. */ +typedef int32_t RTINT; +/** Pointer to signed integer. */ +typedef RTINT *PRTINT; +/** Pointer to const signed integer. */ +typedef const RTINT *PCRTINT; + +/** Unsigned integer. */ +typedef uint32_t RTUINT; +/** Pointer to unsigned integer. */ +typedef RTUINT *PRTUINT; +/** Pointer to const unsigned integer. */ +typedef const RTUINT *PCRTUINT; + +/** A file offset / size (off_t). */ +typedef int64_t RTFOFF; +/** Pointer to a file offset / size. */ +typedef RTFOFF *PRTFOFF; +/** The max value for RTFOFF. */ +#define RTFOFF_MAX INT64_MAX +/** The min value for RTFOFF. */ +#define RTFOFF_MIN INT64_MIN + +/** File mode (see iprt/fs.h). */ +typedef uint32_t RTFMODE; +/** Pointer to file mode. */ +typedef RTFMODE *PRTFMODE; + +/** Device unix number. */ +typedef uint32_t RTDEV; +/** Pointer to a device unix number. */ +typedef RTDEV *PRTDEV; + +/** @name RTDEV Macros + * @{ */ +/** + * Our makedev macro. + * @returns RTDEV + * @param uMajor The major device number. + * @param uMinor The minor device number. + */ +#define RTDEV_MAKE(uMajor, uMinor) ((RTDEV)( ((RTDEV)(uMajor) << 24) | (uMinor & UINT32_C(0x00ffffff)) )) +/** + * Get the major device node number from an RTDEV type. + * @returns The major device number of @a uDev + * @param uDev The device number. + */ +#define RTDEV_MAJOR(uDev) ((uDev) >> 24) +/** + * Get the minor device node number from an RTDEV type. + * @returns The minor device number of @a uDev + * @param uDev The device number. + */ +#define RTDEV_MINOR(uDev) ((uDev) & UINT32_C(0x00ffffff)) +/** @} */ + +/** i-node number. */ +typedef uint64_t RTINODE; +/** Pointer to a i-node number. */ +typedef RTINODE *PRTINODE; + +/** User id. */ +typedef uint32_t RTUID; +/** Pointer to a user id. */ +typedef RTUID *PRTUID; +/** NIL user id. + * @todo check this for portability! */ +#define NIL_RTUID (~(RTUID)0) + +/** Group id. */ +typedef uint32_t RTGID; +/** Pointer to a group id. */ +typedef RTGID *PRTGID; +/** NIL group id. + * @todo check this for portability! */ +#define NIL_RTGID (~(RTGID)0) + +/** I/O Port. */ +typedef uint16_t RTIOPORT; +/** Pointer to I/O Port. */ +typedef RTIOPORT *PRTIOPORT; +/** Pointer to const I/O Port. */ +typedef const RTIOPORT *PCRTIOPORT; + +/** Selector. */ +typedef uint16_t RTSEL; +/** Pointer to selector. */ +typedef RTSEL *PRTSEL; +/** Pointer to const selector. */ +typedef const RTSEL *PCRTSEL; +/** Max selector value. */ +#define RTSEL_MAX UINT16_MAX + +/** Far 16-bit pointer. */ +#pragma pack(1) +typedef struct RTFAR16 +{ + uint16_t off; + RTSEL sel; +} RTFAR16; +#pragma pack() +/** Pointer to Far 16-bit pointer. */ +typedef RTFAR16 *PRTFAR16; +/** Pointer to const Far 16-bit pointer. */ +typedef const RTFAR16 *PCRTFAR16; + +/** Far 32-bit pointer. */ +#pragma pack(1) +typedef struct RTFAR32 +{ + uint32_t off; + RTSEL sel; +} RTFAR32; +#pragma pack() +/** Pointer to Far 32-bit pointer. */ +typedef RTFAR32 *PRTFAR32; +/** Pointer to const Far 32-bit pointer. */ +typedef const RTFAR32 *PCRTFAR32; + +/** Far 64-bit pointer. */ +#pragma pack(1) +typedef struct RTFAR64 +{ + uint64_t off; + RTSEL sel; +} RTFAR64; +#pragma pack() +/** Pointer to Far 64-bit pointer. */ +typedef RTFAR64 *PRTFAR64; +/** Pointer to const Far 64-bit pointer. */ +typedef const RTFAR64 *PCRTFAR64; + +/** @} */ + + +/** @defgroup grp_rt_types_hc Host Context Basic Types + * @ingroup grp_rt_types + * @{ + */ + +/** HC Natural signed integer. + * @deprecated silly type. */ +typedef int32_t RTHCINT; +/** Pointer to HC Natural signed integer. + * @deprecated silly type. */ +typedef RTHCINT *PRTHCINT; +/** Pointer to const HC Natural signed integer. + * @deprecated silly type. */ +typedef const RTHCINT *PCRTHCINT; + +/** HC Natural unsigned integer. + * @deprecated silly type. */ +typedef uint32_t RTHCUINT; +/** Pointer to HC Natural unsigned integer. + * @deprecated silly type. */ +typedef RTHCUINT *PRTHCUINT; +/** Pointer to const HC Natural unsigned integer. + * @deprecated silly type. */ +typedef const RTHCUINT *PCRTHCUINT; + + +/** Signed integer which can contain a HC pointer. */ +#if HC_ARCH_BITS == 32 +typedef int32_t RTHCINTPTR; +#elif HC_ARCH_BITS == 64 +typedef int64_t RTHCINTPTR; +#else +# error Unsupported HC_ARCH_BITS value. +#endif +/** Pointer to signed integer which can contain a HC pointer. */ +typedef RTHCINTPTR *PRTHCINTPTR; +/** Pointer to const signed integer which can contain a HC pointer. */ +typedef const RTHCINTPTR *PCRTHCINTPTR; +/** Max RTHCINTPTR value. */ +#if HC_ARCH_BITS == 32 +# define RTHCINTPTR_MAX INT32_MAX +#else +# define RTHCINTPTR_MAX INT64_MAX +#endif +/** Min RTHCINTPTR value. */ +#if HC_ARCH_BITS == 32 +# define RTHCINTPTR_MIN INT32_MIN +#else +# define RTHCINTPTR_MIN INT64_MIN +#endif + +/** Signed integer which can contain a HC ring-3 pointer. */ +#if R3_ARCH_BITS == 32 +typedef int32_t RTR3INTPTR; +#elif R3_ARCH_BITS == 64 +typedef int64_t RTR3INTPTR; +#else +# error Unsupported R3_ARCH_BITS value. +#endif +/** Pointer to signed integer which can contain a HC ring-3 pointer. */ +typedef RTR3INTPTR *PRTR3INTPTR; +/** Pointer to const signed integer which can contain a HC ring-3 pointer. */ +typedef const RTR3INTPTR *PCRTR3INTPTR; +/** Max RTR3INTPTR value. */ +#if R3_ARCH_BITS == 32 +# define RTR3INTPTR_MAX INT32_MAX +#else +# define RTR3INTPTR_MAX INT64_MAX +#endif +/** Min RTR3INTPTR value. */ +#if R3_ARCH_BITS == 32 +# define RTR3INTPTR_MIN INT32_MIN +#else +# define RTR3INTPTR_MIN INT64_MIN +#endif + +/** Signed integer which can contain a HC ring-0 pointer. */ +#if R0_ARCH_BITS == 32 +typedef int32_t RTR0INTPTR; +#elif R0_ARCH_BITS == 64 +typedef int64_t RTR0INTPTR; +#else +# error Unsupported R0_ARCH_BITS value. +#endif +/** Pointer to signed integer which can contain a HC ring-0 pointer. */ +typedef RTR0INTPTR *PRTR0INTPTR; +/** Pointer to const signed integer which can contain a HC ring-0 pointer. */ +typedef const RTR0INTPTR *PCRTR0INTPTR; +/** Max RTR0INTPTR value. */ +#if R0_ARCH_BITS == 32 +# define RTR0INTPTR_MAX INT32_MAX +#else +# define RTR0INTPTR_MAX INT64_MAX +#endif +/** Min RTHCINTPTR value. */ +#if R0_ARCH_BITS == 32 +# define RTR0INTPTR_MIN INT32_MIN +#else +# define RTR0INTPTR_MIN INT64_MIN +#endif + + +/** Unsigned integer which can contain a HC pointer. */ +#if HC_ARCH_BITS == 32 +typedef uint32_t RTHCUINTPTR; +#elif HC_ARCH_BITS == 64 +typedef uint64_t RTHCUINTPTR; +#else +# error Unsupported HC_ARCH_BITS value. +#endif +/** Pointer to unsigned integer which can contain a HC pointer. */ +typedef RTHCUINTPTR *PRTHCUINTPTR; +/** Pointer to unsigned integer which can contain a HC pointer. */ +typedef const RTHCUINTPTR *PCRTHCUINTPTR; +/** Max RTHCUINTTPR value. */ +#if HC_ARCH_BITS == 32 +# define RTHCUINTPTR_MAX UINT32_MAX +#else +# define RTHCUINTPTR_MAX UINT64_MAX +#endif + +/** Unsigned integer which can contain a HC ring-3 pointer. */ +#if R3_ARCH_BITS == 32 +typedef uint32_t RTR3UINTPTR; +#elif R3_ARCH_BITS == 64 +typedef uint64_t RTR3UINTPTR; +#else +# error Unsupported R3_ARCH_BITS value. +#endif +/** Pointer to unsigned integer which can contain a HC ring-3 pointer. */ +typedef RTR3UINTPTR *PRTR3UINTPTR; +/** Pointer to unsigned integer which can contain a HC ring-3 pointer. */ +typedef const RTR3UINTPTR *PCRTR3UINTPTR; +/** Max RTHCUINTTPR value. */ +#if R3_ARCH_BITS == 32 +# define RTR3UINTPTR_MAX UINT32_MAX +#else +# define RTR3UINTPTR_MAX UINT64_MAX +#endif + +/** Unsigned integer which can contain a HC ring-0 pointer. */ +#if R0_ARCH_BITS == 32 +typedef uint32_t RTR0UINTPTR; +#elif R0_ARCH_BITS == 64 +typedef uint64_t RTR0UINTPTR; +#else +# error Unsupported R0_ARCH_BITS value. +#endif +/** Pointer to unsigned integer which can contain a HC ring-0 pointer. */ +typedef RTR0UINTPTR *PRTR0UINTPTR; +/** Pointer to unsigned integer which can contain a HC ring-0 pointer. */ +typedef const RTR0UINTPTR *PCRTR0UINTPTR; +/** Max RTR0UINTTPR value. */ +#if HC_ARCH_BITS == 32 +# define RTR0UINTPTR_MAX UINT32_MAX +#else +# define RTR0UINTPTR_MAX UINT64_MAX +#endif + + +/** Host Physical Memory Address. */ +typedef uint64_t RTHCPHYS; +/** Pointer to Host Physical Memory Address. */ +typedef RTHCPHYS *PRTHCPHYS; +/** Pointer to const Host Physical Memory Address. */ +typedef const RTHCPHYS *PCRTHCPHYS; +/** @def NIL_RTHCPHYS + * NIL HC Physical Address. + * NIL_RTHCPHYS is used to signal an invalid physical address, similar + * to the NULL pointer. + */ +#define NIL_RTHCPHYS (~(RTHCPHYS)0) +/** Max RTHCPHYS value. */ +#define RTHCPHYS_MAX UINT64_MAX + + +/** HC pointer. */ +#ifndef IN_RC +typedef void * RTHCPTR; +#else +typedef RTHCUINTPTR RTHCPTR; +#endif +/** Pointer to HC pointer. */ +typedef RTHCPTR *PRTHCPTR; +/** Pointer to const HC pointer. */ +typedef const RTHCPTR *PCRTHCPTR; +/** @def NIL_RTHCPTR + * NIL HC pointer. + */ +#define NIL_RTHCPTR ((RTHCPTR)0) +/** Max RTHCPTR value. */ +#define RTHCPTR_MAX ((RTHCPTR)RTHCUINTPTR_MAX) + + +/** HC ring-3 pointer. */ +#ifdef IN_RING3 +typedef void * RTR3PTR; +#else +typedef RTR3UINTPTR RTR3PTR; +#endif +/** Pointer to HC ring-3 pointer. */ +typedef RTR3PTR *PRTR3PTR; +/** Pointer to const HC ring-3 pointer. */ +typedef const RTR3PTR *PCRTR3PTR; +/** @def NIL_RTR3PTR + * NIL HC ring-3 pointer. + */ +#ifndef IN_RING3 +# define NIL_RTR3PTR ((RTR3PTR)0) +#else +# define NIL_RTR3PTR (NULL) +#endif +/** Max RTR3PTR value. */ +#define RTR3PTR_MAX ((RTR3PTR)RTR3UINTPTR_MAX) + +/** HC ring-0 pointer. */ +#ifdef IN_RING0 +typedef void * RTR0PTR; +#else +typedef RTR0UINTPTR RTR0PTR; +#endif +/** Pointer to HC ring-0 pointer. */ +typedef RTR0PTR *PRTR0PTR; +/** Pointer to const HC ring-0 pointer. */ +typedef const RTR0PTR *PCRTR0PTR; +/** @def NIL_RTR0PTR + * NIL HC ring-0 pointer. + */ +#ifndef IN_RING0 +# define NIL_RTR0PTR ((RTR0PTR)0) +#else +# define NIL_RTR0PTR (NULL) +#endif +/** Max RTR3PTR value. */ +#define RTR0PTR_MAX ((RTR0PTR)RTR0UINTPTR_MAX) + + +/** Unsigned integer register in the host context. */ +#if HC_ARCH_BITS == 32 +typedef uint32_t RTHCUINTREG; +#elif HC_ARCH_BITS == 64 +typedef uint64_t RTHCUINTREG; +#else +# error "Unsupported HC_ARCH_BITS!" +#endif +/** Pointer to an unsigned integer register in the host context. */ +typedef RTHCUINTREG *PRTHCUINTREG; +/** Pointer to a const unsigned integer register in the host context. */ +typedef const RTHCUINTREG *PCRTHCUINTREG; + +/** Unsigned integer register in the host ring-3 context. */ +#if R3_ARCH_BITS == 32 +typedef uint32_t RTR3UINTREG; +#elif R3_ARCH_BITS == 64 +typedef uint64_t RTR3UINTREG; +#else +# error "Unsupported R3_ARCH_BITS!" +#endif +/** Pointer to an unsigned integer register in the host ring-3 context. */ +typedef RTR3UINTREG *PRTR3UINTREG; +/** Pointer to a const unsigned integer register in the host ring-3 context. */ +typedef const RTR3UINTREG *PCRTR3UINTREG; + +/** Unsigned integer register in the host ring-3 context. */ +#if R0_ARCH_BITS == 32 +typedef uint32_t RTR0UINTREG; +#elif R0_ARCH_BITS == 64 +typedef uint64_t RTR0UINTREG; +#else +# error "Unsupported R3_ARCH_BITS!" +#endif +/** Pointer to an unsigned integer register in the host ring-3 context. */ +typedef RTR0UINTREG *PRTR0UINTREG; +/** Pointer to a const unsigned integer register in the host ring-3 context. */ +typedef const RTR0UINTREG *PCRTR0UINTREG; + +/** @} */ + + +/** @defgroup grp_rt_types_gc Guest Context Basic Types + * @ingroup grp_rt_types + * @{ + */ + +/** Natural signed integer in the GC. + * @deprecated silly type. */ +#if GC_ARCH_BITS == 32 +typedef int32_t RTGCINT; +#elif GC_ARCH_BITS == 64 /** @todo this isn't right, natural int is 32-bit, see RTHCINT. */ +typedef int64_t RTGCINT; +#endif +/** Pointer to natural signed integer in GC. + * @deprecated silly type. */ +typedef RTGCINT *PRTGCINT; +/** Pointer to const natural signed integer in GC. + * @deprecated silly type. */ +typedef const RTGCINT *PCRTGCINT; + +/** Natural unsigned integer in the GC. + * @deprecated silly type. */ +#if GC_ARCH_BITS == 32 +typedef uint32_t RTGCUINT; +#elif GC_ARCH_BITS == 64 /** @todo this isn't right, natural int is 32-bit, see RTHCUINT. */ +typedef uint64_t RTGCUINT; +#endif +/** Pointer to natural unsigned integer in GC. + * @deprecated silly type. */ +typedef RTGCUINT *PRTGCUINT; +/** Pointer to const natural unsigned integer in GC. + * @deprecated silly type. */ +typedef const RTGCUINT *PCRTGCUINT; + +/** Signed integer which can contain a GC pointer. */ +#if GC_ARCH_BITS == 32 +typedef int32_t RTGCINTPTR; +#elif GC_ARCH_BITS == 64 +typedef int64_t RTGCINTPTR; +#endif +/** Pointer to signed integer which can contain a GC pointer. */ +typedef RTGCINTPTR *PRTGCINTPTR; +/** Pointer to const signed integer which can contain a GC pointer. */ +typedef const RTGCINTPTR *PCRTGCINTPTR; + +/** Unsigned integer which can contain a GC pointer. */ +#if GC_ARCH_BITS == 32 +typedef uint32_t RTGCUINTPTR; +#elif GC_ARCH_BITS == 64 +typedef uint64_t RTGCUINTPTR; +#else +# error Unsupported GC_ARCH_BITS value. +#endif +/** Pointer to unsigned integer which can contain a GC pointer. */ +typedef RTGCUINTPTR *PRTGCUINTPTR; +/** Pointer to unsigned integer which can contain a GC pointer. */ +typedef const RTGCUINTPTR *PCRTGCUINTPTR; + +/** Unsigned integer which can contain a 32 bits GC pointer. */ +typedef uint32_t RTGCUINTPTR32; +/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */ +typedef RTGCUINTPTR32 *PRTGCUINTPTR32; +/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */ +typedef const RTGCUINTPTR32 *PCRTGCUINTPTR32; + +/** Unsigned integer which can contain a 64 bits GC pointer. */ +typedef uint64_t RTGCUINTPTR64; +/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */ +typedef RTGCUINTPTR64 *PRTGCUINTPTR64; +/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */ +typedef const RTGCUINTPTR64 *PCRTGCUINTPTR64; + +/** Guest Physical Memory Address.*/ +typedef uint64_t RTGCPHYS; +/** Pointer to Guest Physical Memory Address. */ +typedef RTGCPHYS *PRTGCPHYS; +/** Pointer to const Guest Physical Memory Address. */ +typedef const RTGCPHYS *PCRTGCPHYS; +/** @def NIL_RTGCPHYS + * NIL GC Physical Address. + * NIL_RTGCPHYS is used to signal an invalid physical address, similar + * to the NULL pointer. Note that this value may actually be valid in + * some contexts. + */ +#define NIL_RTGCPHYS (~(RTGCPHYS)0U) +/** Max guest physical memory address value. */ +#define RTGCPHYS_MAX UINT64_MAX + + +/** Guest Physical Memory Address; limited to 32 bits.*/ +typedef uint32_t RTGCPHYS32; +/** Pointer to Guest Physical Memory Address. */ +typedef RTGCPHYS32 *PRTGCPHYS32; +/** Pointer to const Guest Physical Memory Address. */ +typedef const RTGCPHYS32 *PCRTGCPHYS32; +/** @def NIL_RTGCPHYS32 + * NIL GC Physical Address. + * NIL_RTGCPHYS32 is used to signal an invalid physical address, similar + * to the NULL pointer. Note that this value may actually be valid in + * some contexts. + */ +#define NIL_RTGCPHYS32 (~(RTGCPHYS32)0) + + +/** Guest Physical Memory Address; limited to 64 bits.*/ +typedef uint64_t RTGCPHYS64; +/** Pointer to Guest Physical Memory Address. */ +typedef RTGCPHYS64 *PRTGCPHYS64; +/** Pointer to const Guest Physical Memory Address. */ +typedef const RTGCPHYS64 *PCRTGCPHYS64; +/** @def NIL_RTGCPHYS64 + * NIL GC Physical Address. + * NIL_RTGCPHYS64 is used to signal an invalid physical address, similar + * to the NULL pointer. Note that this value may actually be valid in + * some contexts. + */ +#define NIL_RTGCPHYS64 (~(RTGCPHYS64)0) + +/** Guest context pointer, 32 bits. + * Keep in mind that this type is an unsigned integer in + * HC and void pointer in GC. + */ +typedef RTGCUINTPTR32 RTGCPTR32; +/** Pointer to a guest context pointer. */ +typedef RTGCPTR32 *PRTGCPTR32; +/** Pointer to a const guest context pointer. */ +typedef const RTGCPTR32 *PCRTGCPTR32; +/** @def NIL_RTGCPTR32 + * NIL GC pointer. + */ +#define NIL_RTGCPTR32 ((RTGCPTR32)0) + +/** Guest context pointer, 64 bits. + */ +typedef RTGCUINTPTR64 RTGCPTR64; +/** Pointer to a guest context pointer. */ +typedef RTGCPTR64 *PRTGCPTR64; +/** Pointer to a const guest context pointer. */ +typedef const RTGCPTR64 *PCRTGCPTR64; +/** @def NIL_RTGCPTR64 + * NIL GC pointer. + */ +#define NIL_RTGCPTR64 ((RTGCPTR64)0) + +/** Guest context pointer. + * Keep in mind that this type is an unsigned integer in + * HC and void pointer in GC. + */ +#if GC_ARCH_BITS == 64 +typedef RTGCPTR64 RTGCPTR; +/** Pointer to a guest context pointer. */ +typedef PRTGCPTR64 PRTGCPTR; +/** Pointer to a const guest context pointer. */ +typedef PCRTGCPTR64 PCRTGCPTR; +/** @def NIL_RTGCPTR + * NIL GC pointer. + */ +# define NIL_RTGCPTR NIL_RTGCPTR64 +/** Max RTGCPTR value. */ +# define RTGCPTR_MAX UINT64_MAX +#elif GC_ARCH_BITS == 32 +typedef RTGCPTR32 RTGCPTR; +/** Pointer to a guest context pointer. */ +typedef PRTGCPTR32 PRTGCPTR; +/** Pointer to a const guest context pointer. */ +typedef PCRTGCPTR32 PCRTGCPTR; +/** @def NIL_RTGCPTR + * NIL GC pointer. + */ +# define NIL_RTGCPTR NIL_RTGCPTR32 +/** Max RTGCPTR value. */ +# define RTGCPTR_MAX UINT32_MAX +#else +# error "Unsupported GC_ARCH_BITS!" +#endif + +/** Unsigned integer register in the guest context. */ +typedef uint32_t RTGCUINTREG32; +/** Pointer to an unsigned integer register in the guest context. */ +typedef RTGCUINTREG32 *PRTGCUINTREG32; +/** Pointer to a const unsigned integer register in the guest context. */ +typedef const RTGCUINTREG32 *PCRTGCUINTREG32; + +typedef uint64_t RTGCUINTREG64; +/** Pointer to an unsigned integer register in the guest context. */ +typedef RTGCUINTREG64 *PRTGCUINTREG64; +/** Pointer to a const unsigned integer register in the guest context. */ +typedef const RTGCUINTREG64 *PCRTGCUINTREG64; + +#if GC_ARCH_BITS == 64 +typedef RTGCUINTREG64 RTGCUINTREG; +#elif GC_ARCH_BITS == 32 +typedef RTGCUINTREG32 RTGCUINTREG; +#else +# error "Unsupported GC_ARCH_BITS!" +#endif +/** Pointer to an unsigned integer register in the guest context. */ +typedef RTGCUINTREG *PRTGCUINTREG; +/** Pointer to a const unsigned integer register in the guest context. */ +typedef const RTGCUINTREG *PCRTGCUINTREG; + +/** @} */ + +/** @defgroup grp_rt_types_rc Raw mode Context Basic Types + * @ingroup grp_rt_types + * @{ + */ + +/** Raw mode context pointer; a 32 bits guest context pointer. + * Keep in mind that this type is an unsigned integer in + * HC and void pointer in RC. + */ +#ifdef IN_RC +typedef void * RTRCPTR; +#else +typedef uint32_t RTRCPTR; +#endif +/** Pointer to a raw mode context pointer. */ +typedef RTRCPTR *PRTRCPTR; +/** Pointer to a const raw mode context pointer. */ +typedef const RTRCPTR *PCRTRCPTR; +/** @def NIL_RTGCPTR + * NIL RC pointer. + */ +#ifndef IN_RC +# define NIL_RTRCPTR ((RTRCPTR)0) +#else +# define NIL_RTRCPTR (NULL) +#endif +/** @def RTRCPTR_MAX + * The maximum value a RTRCPTR can have. Mostly used as INVALID value. + */ +#define RTRCPTR_MAX ((RTRCPTR)UINT32_MAX) + +/** Raw mode context pointer, unsigned integer variant. */ +typedef int32_t RTRCINTPTR; +/** @def RTRCUINTPTR_MAX + * The maximum value a RTRCUINPTR can have. + */ +#define RTRCUINTPTR_MAX ((RTRCUINTPTR)UINT32_MAX) + +/** Raw mode context pointer, signed integer variant. */ +typedef uint32_t RTRCUINTPTR; +/** @def RTRCINTPTR_MIN + * The minimum value a RTRCINPTR can have. + */ +#define RTRCINTPTR_MIN ((RTRCINTPTR)INT32_MIN) +/** @def RTRCINTPTR_MAX + * The maximum value a RTRCINPTR can have. + */ +#define RTRCINTPTR_MAX ((RTRCINTPTR)INT32_MAX) + +/** @} */ + + +/** @defgroup grp_rt_types_cc Current Context Basic Types + * @ingroup grp_rt_types + * @{ + */ + +/** Current Context Physical Memory Address.*/ +#ifdef IN_RC +typedef RTGCPHYS RTCCPHYS; +#else +typedef RTHCPHYS RTCCPHYS; +#endif +/** Pointer to Current Context Physical Memory Address. */ +typedef RTCCPHYS *PRTCCPHYS; +/** Pointer to const Current Context Physical Memory Address. */ +typedef const RTCCPHYS *PCRTCCPHYS; +/** @def NIL_RTCCPHYS + * NIL CC Physical Address. + * NIL_RTCCPHYS is used to signal an invalid physical address, similar + * to the NULL pointer. + */ +#ifdef IN_RC +# define NIL_RTCCPHYS NIL_RTGCPHYS +#else +# define NIL_RTCCPHYS NIL_RTHCPHYS +#endif + +/** Unsigned integer register in the current context. */ +#if ARCH_BITS == 32 +typedef uint32_t RTCCUINTREG; +#elif ARCH_BITS == 64 +typedef uint64_t RTCCUINTREG; +#else +# error "Unsupported ARCH_BITS!" +#endif +/** Pointer to an unsigned integer register in the current context. */ +typedef RTCCUINTREG *PRTCCUINTREG; +/** Pointer to a const unsigned integer register in the current context. */ +typedef RTCCUINTREG const *PCRTCCUINTREG; + +/** Signed integer register in the current context. */ +#if ARCH_BITS == 32 +typedef int32_t RTCCINTREG; +#elif ARCH_BITS == 64 +typedef int64_t RTCCINTREG; +#endif +/** Pointer to a signed integer register in the current context. */ +typedef RTCCINTREG *PRTCCINTREG; +/** Pointer to a const signed integer register in the current context. */ +typedef RTCCINTREG const *PCRTCCINTREG; + +/** @} */ + + +/** Pointer to a critical section. */ +typedef struct RTCRITSECT *PRTCRITSECT; +/** Pointer to a const critical section. */ +typedef const struct RTCRITSECT *PCRTCRITSECT; + + +/** Condition variable handle. */ +typedef R3PTRTYPE(struct RTCONDVARINTERNAL *) RTCONDVAR; +/** Pointer to a condition variable handle. */ +typedef RTCONDVAR *PRTCONDVAR; +/** Nil condition variable handle. */ +#define NIL_RTCONDVAR 0 + +/** File handle. */ +typedef R3R0PTRTYPE(struct RTFILEINT *) RTFILE; +/** Pointer to file handle. */ +typedef RTFILE *PRTFILE; +/** Nil file handle. */ +#define NIL_RTFILE ((RTFILE)~(RTHCINTPTR)0) + +/** Async I/O request handle. */ +typedef R3PTRTYPE(struct RTFILEAIOREQINTERNAL *) RTFILEAIOREQ; +/** Pointer to an async I/O request handle. */ +typedef RTFILEAIOREQ *PRTFILEAIOREQ; +/** Nil request handle. */ +#define NIL_RTFILEAIOREQ 0 + +/** Async I/O completion context handle. */ +typedef R3PTRTYPE(struct RTFILEAIOCTXINTERNAL *) RTFILEAIOCTX; +/** Pointer to an async I/O completion context handle. */ +typedef RTFILEAIOCTX *PRTFILEAIOCTX; +/** Nil context handle. */ +#define NIL_RTFILEAIOCTX 0 + +/** Loader module handle. */ +typedef R3PTRTYPE(struct RTLDRMODINTERNAL *) RTLDRMOD; +/** Pointer to a loader module handle. */ +typedef RTLDRMOD *PRTLDRMOD; +/** Nil loader module handle. */ +#define NIL_RTLDRMOD 0 + +/** Lock validator class handle. */ +typedef R3R0PTRTYPE(struct RTLOCKVALCLASSINT *) RTLOCKVALCLASS; +/** Pointer to a lock validator class handle. */ +typedef RTLOCKVALCLASS *PRTLOCKVALCLASS; +/** Nil lock validator class handle. */ +#define NIL_RTLOCKVALCLASS ((RTLOCKVALCLASS)0) + +/** Ring-0 memory object handle. */ +typedef R0PTRTYPE(struct RTR0MEMOBJINTERNAL *) RTR0MEMOBJ; +/** Pointer to a Ring-0 memory object handle. */ +typedef RTR0MEMOBJ *PRTR0MEMOBJ; +/** Nil ring-0 memory object handle. */ +#define NIL_RTR0MEMOBJ 0 + +/** Native thread handle. */ +typedef RTHCUINTPTR RTNATIVETHREAD; +/** Pointer to an native thread handle. */ +typedef RTNATIVETHREAD *PRTNATIVETHREAD; +/** Nil native thread handle. */ +#define NIL_RTNATIVETHREAD (~(RTNATIVETHREAD)0) + +/** Pipe handle. */ +typedef R3R0PTRTYPE(struct RTPIPEINTERNAL *) RTPIPE; +/** Pointer to a pipe handle. */ +typedef RTPIPE *PRTPIPE; +/** Nil pipe handle. + * @remarks This is not 0 because of UNIX and OS/2 handle values. Take care! */ +#define NIL_RTPIPE ((RTPIPE)RTHCUINTPTR_MAX) + +/** @typedef RTPOLLSET + * Poll set handle. */ +typedef R3R0PTRTYPE(struct RTPOLLSETINTERNAL *) RTPOLLSET; +/** Pointer to a poll set handle. */ +typedef RTPOLLSET *PRTPOLLSET; +/** Nil poll set handle handle. */ +#define NIL_RTPOLLSET ((RTPOLLSET)0) + +/** Process identifier. */ +typedef uint32_t RTPROCESS; +/** Pointer to a process identifier. */ +typedef RTPROCESS *PRTPROCESS; +/** Nil process identifier. */ +#define NIL_RTPROCESS (~(RTPROCESS)0) + +/** Process ring-0 handle. */ +typedef RTR0UINTPTR RTR0PROCESS; +/** Pointer to a ring-0 process handle. */ +typedef RTR0PROCESS *PRTR0PROCESS; +/** Nil ring-0 process handle. */ +#define NIL_RTR0PROCESS (~(RTR0PROCESS)0) + +/** @typedef RTSEMEVENT + * Event Semaphore handle. */ +typedef R3R0PTRTYPE(struct RTSEMEVENTINTERNAL *) RTSEMEVENT; +/** Pointer to an event semaphore handle. */ +typedef RTSEMEVENT *PRTSEMEVENT; +/** Nil event semaphore handle. */ +#define NIL_RTSEMEVENT 0 + +/** @typedef RTSEMEVENTMULTI + * Event Multiple Release Semaphore handle. */ +typedef R3R0PTRTYPE(struct RTSEMEVENTMULTIINTERNAL *) RTSEMEVENTMULTI; +/** Pointer to an event multiple release semaphore handle. */ +typedef RTSEMEVENTMULTI *PRTSEMEVENTMULTI; +/** Nil multiple release event semaphore handle. */ +#define NIL_RTSEMEVENTMULTI 0 + +/** @typedef RTSEMFASTMUTEX + * Fast mutex Semaphore handle. */ +typedef R3R0PTRTYPE(struct RTSEMFASTMUTEXINTERNAL *) RTSEMFASTMUTEX; +/** Pointer to a fast mutex semaphore handle. */ +typedef RTSEMFASTMUTEX *PRTSEMFASTMUTEX; +/** Nil fast mutex semaphore handle. */ +#define NIL_RTSEMFASTMUTEX 0 + +/** @typedef RTSEMMUTEX + * Mutex Semaphore handle. */ +typedef R3R0PTRTYPE(struct RTSEMMUTEXINTERNAL *) RTSEMMUTEX; +/** Pointer to a mutex semaphore handle. */ +typedef RTSEMMUTEX *PRTSEMMUTEX; +/** Nil mutex semaphore handle. */ +#define NIL_RTSEMMUTEX 0 + +/** @typedef RTSEMSPINMUTEX + * Spinning mutex Semaphore handle. */ +typedef R3R0PTRTYPE(struct RTSEMSPINMUTEXINTERNAL *) RTSEMSPINMUTEX; +/** Pointer to a spinning mutex semaphore handle. */ +typedef RTSEMSPINMUTEX *PRTSEMSPINMUTEX; +/** Nil spinning mutex semaphore handle. */ +#define NIL_RTSEMSPINMUTEX 0 + +/** @typedef RTSEMRW + * Read/Write Semaphore handle. */ +typedef R3R0PTRTYPE(struct RTSEMRWINTERNAL *) RTSEMRW; +/** Pointer to a read/write semaphore handle. */ +typedef RTSEMRW *PRTSEMRW; +/** Nil read/write semaphore handle. */ +#define NIL_RTSEMRW 0 + +/** @typedef RTSEMXROADS + * Crossroads semaphore handle. */ +typedef R3R0PTRTYPE(struct RTSEMXROADSINTERNAL *) RTSEMXROADS; +/** Pointer to a crossroads semaphore handle. */ +typedef RTSEMXROADS *PRTSEMXROADS; +/** Nil crossroads semaphore handle. */ +#define NIL_RTSEMXROADS ((RTSEMXROADS)0) + +/** Spinlock handle. */ +typedef R3R0PTRTYPE(struct RTSPINLOCKINTERNAL *) RTSPINLOCK; +/** Pointer to a spinlock handle. */ +typedef RTSPINLOCK *PRTSPINLOCK; +/** Nil spinlock handle. */ +#define NIL_RTSPINLOCK 0 + +/** Socket handle. */ +typedef R3R0PTRTYPE(struct RTSOCKETINT *) RTSOCKET; +/** Pointer to socket handle. */ +typedef RTSOCKET *PRTSOCKET; +/** Nil socket handle. */ +#define NIL_RTSOCKET ((RTSOCKET)0) + +/** Pointer to a RTTCPSERVER handle. */ +typedef struct RTTCPSERVER *PRTTCPSERVER; +/** Pointer to a RTTCPSERVER handle. */ +typedef PRTTCPSERVER *PPRTTCPSERVER; +/** Nil RTTCPSERVER handle. */ +#define NIL_RTTCPSERVER ((PRTTCPSERVER)0) + +/** Pointer to a RTUDPSERVER handle. */ +typedef struct RTUDPSERVER *PRTUDPSERVER; +/** Pointer to a RTUDPSERVER handle. */ +typedef PRTUDPSERVER *PPRTUDPSERVER; +/** Nil RTUDPSERVER handle. */ +#define NIL_RTUDPSERVER ((PRTUDPSERVER)0) + +/** Thread handle.*/ +typedef R3R0PTRTYPE(struct RTTHREADINT *) RTTHREAD; +/** Pointer to thread handle. */ +typedef RTTHREAD *PRTTHREAD; +/** Nil thread handle. */ +#define NIL_RTTHREAD 0 + +/** A TLS index. */ +typedef RTHCINTPTR RTTLS; +/** Pointer to a TLS index. */ +typedef RTTLS *PRTTLS; +/** Pointer to a const TLS index. */ +typedef RTTLS const *PCRTTLS; +/** NIL TLS index value. */ +#define NIL_RTTLS ((RTTLS)-1) + +/** Trace buffer handle. + * @remarks This is not a R3/R0 type like most other handles! + */ +typedef struct RTTRACEBUFINT *RTTRACEBUF; +/** Poiner to a trace buffer handle. */ +typedef RTTRACEBUF *PRTTRACEBUF; +/** Nil trace buffer handle. */ +#define NIL_RTTRACEBUF ((RTTRACEBUF)0) +/** The handle of the default trace buffer. + * This can be used with any of the RTTraceBufAdd APIs. */ +#define RTTRACEBUF_DEFAULT ((RTTRACEBUF)-2) + +/** Handle to a simple heap. */ +typedef R3R0PTRTYPE(struct RTHEAPSIMPLEINTERNAL *) RTHEAPSIMPLE; +/** Pointer to a handle to a simple heap. */ +typedef RTHEAPSIMPLE *PRTHEAPSIMPLE; +/** NIL simple heap handle. */ +#define NIL_RTHEAPSIMPLE ((RTHEAPSIMPLE)0) + +/** Handle to an offset based heap. */ +typedef R3R0PTRTYPE(struct RTHEAPOFFSETINTERNAL *) RTHEAPOFFSET; +/** Pointer to a handle to an offset based heap. */ +typedef RTHEAPOFFSET *PRTHEAPOFFSET; +/** NIL offset based heap handle. */ +#define NIL_RTHEAPOFFSET ((RTHEAPOFFSET)0) + +/** Handle to an environment block. */ +typedef R3PTRTYPE(struct RTENVINTERNAL *) RTENV; +/** Pointer to a handle to an environment block. */ +typedef RTENV *PRTENV; +/** NIL simple heap handle. */ +#define NIL_RTENV ((RTENV)0) + +/** A CPU identifier. + * @remarks This doesn't have to correspond to the APIC ID (intel/amd). Nor + * does it have to correspond to the bits in the affinity mask, at + * least not until we've sorted out Windows NT. */ +typedef uint32_t RTCPUID; +/** Pointer to a CPU identifier. */ +typedef RTCPUID *PRTCPUID; +/** Pointer to a const CPU identifier. */ +typedef RTCPUID const *PCRTCPUID; +/** Nil CPU Id. */ +#define NIL_RTCPUID ((RTCPUID)~0) + +/** The maximum number of CPUs a set can contain and IPRT is able + * to reference. (Should be max of support arch/platforms.) + * @remarks Must be a multiple of 64 (see RTCPUSET). */ +#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64) +# define RTCPUSET_MAX_CPUS 256 +#elif defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64) +# define RTCPUSET_MAX_CPUS 1024 +#else +# define RTCPUSET_MAX_CPUS 64 +#endif +/** A CPU set. + * @note Treat this as an opaque type and always use RTCpuSet* for + * manupulating it. */ +typedef struct RTCPUSET +{ + /** The bitmap. */ + uint64_t bmSet[RTCPUSET_MAX_CPUS / 64]; +} RTCPUSET; +/** Pointer to a CPU set. */ +typedef RTCPUSET *PRTCPUSET; +/** Pointer to a const CPU set. */ +typedef RTCPUSET const *PCRTCPUSET; + +/** A handle table handle. */ +typedef R3R0PTRTYPE(struct RTHANDLETABLEINT *) RTHANDLETABLE; +/** A pointer to a handle table handle. */ +typedef RTHANDLETABLE *PRTHANDLETABLE; +/** @def NIL_RTHANDLETABLE + * NIL handle table handle. */ +#define NIL_RTHANDLETABLE ((RTHANDLETABLE)0) + +/** A handle to a low resolution timer. */ +typedef R3R0PTRTYPE(struct RTTIMERLRINT *) RTTIMERLR; +/** A pointer to a low resolution timer handle. */ +typedef RTTIMERLR *PRTTIMERLR; +/** @def NIL_RTTIMERLR + * NIL low resolution timer handle value. */ +#define NIL_RTTIMERLR ((RTTIMERLR)0) + +/** Handle to a random number generator. */ +typedef R3R0PTRTYPE(struct RTRANDINT *) RTRAND; +/** Pointer to a random number generator handle. */ +typedef RTRAND *PRTRAND; +/** NIL random number genrator handle value. */ +#define NIL_RTRAND ((RTRAND)0) + +/** Debug address space handle. */ +typedef R3R0PTRTYPE(struct RTDBGASINT *) RTDBGAS; +/** Pointer to a debug address space handle. */ +typedef RTDBGAS *PRTDBGAS; +/** NIL debug address space handle. */ +#define NIL_RTDBGAS ((RTDBGAS)0) + +/** Debug module handle. */ +typedef R3R0PTRTYPE(struct RTDBGMODINT *) RTDBGMOD; +/** Pointer to a debug module handle. */ +typedef RTDBGMOD *PRTDBGMOD; +/** NIL debug module handle. */ +#define NIL_RTDBGMOD ((RTDBGMOD)0) + +/** Manifest handle. */ +typedef struct RTMANIFESTINT *RTMANIFEST; +/** Pointer to a manifest handle. */ +typedef RTMANIFEST *PRTMANIFEST; +/** NIL manifest handle. */ +#define NIL_RTMANIFEST ((RTMANIFEST)~(uintptr_t)0) + +/** Memory pool handle. */ +typedef R3R0PTRTYPE(struct RTMEMPOOLINT *) RTMEMPOOL; +/** Pointer to a memory pool handle. */ +typedef RTMEMPOOL *PRTMEMPOOL; +/** NIL memory pool handle. */ +#define NIL_RTMEMPOOL ((RTMEMPOOL)0) +/** The default memory pool handle. */ +#define RTMEMPOOL_DEFAULT ((RTMEMPOOL)-2) + +/** String cache handle. */ +typedef R3R0PTRTYPE(struct RTSTRCACHEINT *) RTSTRCACHE; +/** Pointer to a string cache handle. */ +typedef RTSTRCACHE *PRTSTRCACHE; +/** NIL string cache handle. */ +#define NIL_RTSTRCACHE ((RTSTRCACHE)0) +/** The default string cache handle. */ +#define RTSTRCACHE_DEFAULT ((RTSTRCACHE)-2) + + +/** Virtual Filesystem handle. */ +typedef struct RTVFSINTERNAL *RTVFS; +/** Pointer to a VFS handle. */ +typedef RTVFS *PRTVFS; +/** A NIL VFS handle. */ +#define NIL_RTVFS ((RTVFS)~(uintptr_t)0) + +/** Virtual Filesystem base object handle. */ +typedef struct RTVFSOBJINTERNAL *RTVFSOBJ; +/** Pointer to a VFS base object handle. */ +typedef RTVFSOBJ *PRTVFSOBJ; +/** A NIL VFS base object handle. */ +#define NIL_RTVFSOBJ ((RTVFSOBJ)~(uintptr_t)0) + +/** Virtual Filesystem directory handle. */ +typedef struct RTVFSDIRINTERNAL *RTVFSDIR; +/** Pointer to a VFS directory handle. */ +typedef RTVFSDIR *PRTVFSDIR; +/** A NIL VFS directory handle. */ +#define NIL_RTVFSDIR ((RTVFSDIR)~(uintptr_t)0) + +/** Virtual Filesystem filesystem stream handle. */ +typedef struct RTVFSFSSTREAMINTERNAL *RTVFSFSSTREAM; +/** Pointer to a VFS filesystem stream handle. */ +typedef RTVFSFSSTREAM *PRTVFSFSSTREAM; +/** A NIL VFS filesystem stream handle. */ +#define NIL_RTVFSFSSTREAM ((RTVFSFSSTREAM)~(uintptr_t)0) + +/** Virtual Filesystem I/O stream handle. */ +typedef struct RTVFSIOSTREAMINTERNAL *RTVFSIOSTREAM; +/** Pointer to a VFS I/O stream handle. */ +typedef RTVFSIOSTREAM *PRTVFSIOSTREAM; +/** A NIL VFS I/O stream handle. */ +#define NIL_RTVFSIOSTREAM ((RTVFSIOSTREAM)~(uintptr_t)0) + +/** Virtual Filesystem file handle. */ +typedef struct RTVFSFILEINTERNAL *RTVFSFILE; +/** Pointer to a VFS file handle. */ +typedef RTVFSFILE *PRTVFSFILE; +/** A NIL VFS file handle. */ +#define NIL_RTVFSFILE ((RTVFSFILE)~(uintptr_t)0) + +/** Virtual Filesystem symbolic link handle. */ +typedef struct RTVFSSYMLINKINTERNAL *RTVFSSYMLINK; +/** Pointer to a VFS symbolic link handle. */ +typedef RTVFSSYMLINK *PRTVFSSYMLINK; +/** A NIL VFS symbolic link handle. */ +#define NIL_RTVFSSYMLINK ((RTVFSSYMLINK)~(uintptr_t)0) + + +/** + * Handle type. + * + * This is usually used together with RTHANDLEUNION. + */ +typedef enum RTHANDLETYPE +{ + /** The invalid zero value. */ + RTHANDLETYPE_INVALID = 0, + /** File handle. */ + RTHANDLETYPE_FILE, + /** Pipe handle */ + RTHANDLETYPE_PIPE, + /** Socket handle. */ + RTHANDLETYPE_SOCKET, + /** Thread handle. */ + RTHANDLETYPE_THREAD, + /** The end of the valid values. */ + RTHANDLETYPE_END, + /** The 32-bit type blow up. */ + RTHANDLETYPE_32BIT_HACK = 0x7fffffff +} RTHANDLETYPE; +/** Pointer to a handle type. */ +typedef RTHANDLETYPE *PRTHANDLETYPE; + +/** + * Handle union. + * + * This is usually used together with RTHANDLETYPE or as RTHANDLE. + */ +typedef union RTHANDLEUNION +{ + RTFILE hFile; /**< File handle. */ + RTPIPE hPipe; /**< Pipe handle. */ + RTSOCKET hSocket; /**< Socket handle. */ + RTTHREAD hThread; /**< Thread handle. */ + /** Generic integer handle value. + * Note that RTFILE is not yet pointer sized, so accessing it via this member + * isn't necessarily safe or fully portable. */ + RTHCUINTPTR uInt; +} RTHANDLEUNION; +/** Pointer to a handle union. */ +typedef RTHANDLEUNION *PRTHANDLEUNION; +/** Pointer to a const handle union. */ +typedef RTHANDLEUNION const *PCRTHANDLEUNION; + +/** + * Generic handle. + */ +typedef struct RTHANDLE +{ + /** The handle type. */ + RTHANDLETYPE enmType; + /** The handle value. */ + RTHANDLEUNION u; +} RTHANDLE; +/** Pointer to a generic handle. */ +typedef RTHANDLE *PRTHANDLE; +/** Pointer to a const generic handle. */ +typedef RTHANDLE const *PCRTHANDLE; + + +/** + * Standard handles. + * + * @remarks These have the correct file descriptor values for unixy systems and + * can be used directly in code specific to those platforms. + */ +typedef enum RTHANDLESTD +{ + /** Invalid standard handle. */ + RTHANDLESTD_INVALID = -1, + /** The standard input handle. */ + RTHANDLESTD_INPUT = 0, + /** The standard output handle. */ + RTHANDLESTD_OUTPUT, + /** The standard error handle. */ + RTHANDLESTD_ERROR, + /** The typical 32-bit type hack. */ + RTHANDLESTD_32BIT_HACK = 0x7fffffff +} RTHANDLESTD; + + +/** + * Error info. + * + * See RTErrInfo*. + */ +typedef struct RTERRINFO +{ + /** Flags, see RTERRINFO_FLAGS_XXX. */ + uint32_t fFlags; + /** The status code. */ + int32_t rc; + /** The size of the message */ + size_t cbMsg; + /** The error buffer. */ + char *pszMsg; + /** Reserved for future use. */ + void *apvReserved[2]; +} RTERRINFO; +/** Pointer to an error info structure. */ +typedef RTERRINFO *PRTERRINFO; +/** Pointer to a const error info structure. */ +typedef RTERRINFO const *PCRTERRINFO; + +/** + * Static error info structure, see RTErrInfoInitStatic. + */ +typedef struct RTERRINFOSTATIC +{ + /** The core error info. */ + RTERRINFO Core; + /** The static message buffer. */ + char szMsg[3072]; +} RTERRINFOSTATIC; +/** Pointer to a error info buffer. */ +typedef RTERRINFOSTATIC *PRTERRINFOSTATIC; +/** Pointer to a const static error info buffer. */ +typedef RTERRINFOSTATIC const *PCRTERRINFOSTATIC; + + +/** + * UUID data type. + * + * See RTUuid*. + * + * @remarks IPRT defines that the first three integers in the @c Gen struct + * interpretation are in little endian representation. This is + * different to many other UUID implementation, and requires + * conversion if you need to achieve consistent results. + */ +typedef union RTUUID +{ + /** 8-bit view. */ + uint8_t au8[16]; + /** 16-bit view. */ + uint16_t au16[8]; + /** 32-bit view. */ + uint32_t au32[4]; + /** 64-bit view. */ + uint64_t au64[2]; + /** The way the UUID is declared by the DCE specification. */ + struct + { + uint32_t u32TimeLow; + uint16_t u16TimeMid; + uint16_t u16TimeHiAndVersion; + uint8_t u8ClockSeqHiAndReserved; + uint8_t u8ClockSeqLow; + uint8_t au8Node[6]; + } Gen; +} RTUUID; +/** Pointer to UUID data. */ +typedef RTUUID *PRTUUID; +/** Pointer to readonly UUID data. */ +typedef const RTUUID *PCRTUUID; + +/** UUID string maximum length. */ +#define RTUUID_STR_LENGTH 37 + + +/** Compression handle. */ +typedef struct RTZIPCOMP *PRTZIPCOMP; +/** Decompressor handle. */ +typedef struct RTZIPDECOMP *PRTZIPDECOMP; + + +/** + * Unicode Code Point. + */ +typedef uint32_t RTUNICP; +/** Pointer to an Unicode Code Point. */ +typedef RTUNICP *PRTUNICP; +/** Pointer to an Unicode Code Point. */ +typedef const RTUNICP *PCRTUNICP; +/** Max value a RTUNICP type can hold. */ +#define RTUNICP_MAX ( ~(RTUNICP)0 ) +/** Invalid code point. + * This is returned when encountered invalid encodings or invalid + * unicode code points. */ +#define RTUNICP_INVALID ( UINT32_C(0xfffffffe) ) + + +/** + * UTF-16 character. + * @remark wchar_t is not usable since it's compiler defined. + * @remark When we use the term character we're not talking about unicode code point, but + * the basic unit of the string encoding. Thus cwc - count of wide chars - means + * count of RTUTF16; cuc - count of unicode chars - means count of RTUNICP; + * and cch means count of the typedef 'char', which is assumed to be an octet. + */ +typedef uint16_t RTUTF16; +/** Pointer to a UTF-16 character. */ +typedef RTUTF16 *PRTUTF16; +/** Pointer to a const UTF-16 character. */ +typedef const RTUTF16 *PCRTUTF16; + + +/** + * Wait for ever if we have to. + */ +#define RT_INDEFINITE_WAIT (~0U) + + +/** + * Generic process callback. + * + * @returns VBox status code. Failure will cancel the operation. + * @param uPercentage The percentage of the operation which has been completed. + * @param pvUser The user specified argument. + */ +typedef DECLCALLBACK(int) FNRTPROGRESS(unsigned uPrecentage, void *pvUser); +/** Pointer to a generic progress callback function, FNRTPROCESS(). */ +typedef FNRTPROGRESS *PFNRTPROGRESS; + + +/** + * A point in a two dimentional coordinate system. + */ +typedef struct RTPOINT +{ + /** X coordinate. */ + int32_t x; + /** Y coordinate. */ + int32_t y; +} RTPOINT; +/** Pointer to a point. */ +typedef RTPOINT *PRTPOINT; +/** Pointer to a const point. */ +typedef const RTPOINT *PCRTPOINT; + + +/** + * Rectangle data type, double point. + */ +typedef struct RTRECT +{ + /** left X coordinate. */ + int32_t xLeft; + /** top Y coordinate. */ + int32_t yTop; + /** right X coordinate. (exclusive) */ + int32_t xRight; + /** bottom Y coordinate. (exclusive) */ + int32_t yBottom; +} RTRECT; +/** Pointer to a double point rectangle. */ +typedef RTRECT *PRTRECT; +/** Pointer to a const double point rectangle. */ +typedef const RTRECT *PCRTRECT; + + +/** + * Rectangle data type, point + size. + */ +typedef struct RTRECT2 +{ + /** X coordinate. + * Unless stated otherwise, this is the top left corner. */ + int32_t x; + /** Y coordinate. + * Unless stated otherwise, this is the top left corner. */ + int32_t y; + /** The width. + * Unless stated otherwise, this is to the right of (x,y) and will not + * be a negative number. */ + int32_t cx; + /** The height. + * Unless stated otherwise, this is down from (x,y) and will not be a + * negative number. */ + int32_t cy; +} RTRECT2; +/** Pointer to a point + size rectangle. */ +typedef RTRECT2 *PRTRECT2; +/** Pointer to a const point + size rectangle. */ +typedef const RTRECT2 *PCRTRECT2; + + +/** + * The size of a rectangle. + */ +typedef struct RTRECTSIZE +{ + /** The width (along the x-axis). */ + uint32_t cx; + /** The height (along the y-axis). */ + uint32_t cy; +} RTRECTSIZE; +/** Pointer to a rectangle size. */ +typedef RTRECTSIZE *PRTRECTSIZE; +/** Pointer to a const rectangle size. */ +typedef const RTRECTSIZE *PCRTRECTSIZE; + + +/** + * Ethernet MAC address. + * + * The first 24 bits make up the Organisationally Unique Identifier (OUI), + * where the first bit (little endian) indicates multicast (set) / unicast, + * and the second bit indicates locally (set) / global administered. If all + * bits are set, it's a broadcast. + */ +typedef union RTMAC +{ + /** @todo add a bitfield view of this stuff. */ + /** 8-bit view. */ + uint8_t au8[6]; + /** 16-bit view. */ + uint16_t au16[3]; +} RTMAC; +/** Pointer to a MAC address. */ +typedef RTMAC *PRTMAC; +/** Pointer to a readonly MAC address. */ +typedef const RTMAC *PCRTMAC; + + +/** Pointer to a lock validator record. + * The structure definition is found in iprt/lockvalidator.h. */ +typedef struct RTLOCKVALRECEXCL *PRTLOCKVALRECEXCL; +/** Pointer to a lock validator source poisition. + * The structure definition is found in iprt/lockvalidator.h. */ +typedef struct RTLOCKVALSRCPOS *PRTLOCKVALSRCPOS; +/** Pointer to a const lock validator source poisition. + * The structure definition is found in iprt/lockvalidator.h. */ +typedef struct RTLOCKVALSRCPOS const *PCRTLOCKVALSRCPOS; + +/** @name Special sub-class values. + * The range 16..UINT32_MAX is available to the user, the range 0..15 is + * reserved for the lock validator. In the user range the locks can only be + * taking in ascending order. + * @{ */ +/** Invalid value. */ +#define RTLOCKVAL_SUB_CLASS_INVALID UINT32_C(0) +/** Not allowed to be taken with any other locks in the same class. + * This is the recommended value. */ +#define RTLOCKVAL_SUB_CLASS_NONE UINT32_C(1) +/** Any order is allowed within the class. */ +#define RTLOCKVAL_SUB_CLASS_ANY UINT32_C(2) +/** The first user value. */ +#define RTLOCKVAL_SUB_CLASS_USER UINT32_C(16) +/** @} */ + + +/** + * Process exit codes. + */ +typedef enum RTEXITCODE +{ + /** Success. */ + RTEXITCODE_SUCCESS = 0, + /** General failure. */ + RTEXITCODE_FAILURE = 1, + /** Invalid arguments. */ + RTEXITCODE_SYNTAX = 2, + /** Initialization failure (usually IPRT, but could be used for other + * components as well). */ + RTEXITCODE_INIT = 3, + /** Test skipped. */ + RTEXITCODE_SKIPPED = 4, + /** The end of valid exit codes. */ + RTEXITCODE_END, + /** The usual 32-bit type hack. */ + RTEXITCODE_32BIT_HACK = 0x7fffffff +} RTEXITCODE; + +/** + * Range descriptor. + */ +typedef struct RTRANGE +{ + /** Start offset. */ + uint64_t offStart; + /** Range size. */ + size_t cbRange; +} RTRANGE; +/** Pointer to a range descriptor. */ +typedef RTRANGE *PRTRANGE; +/** Pointer to a readonly range descriptor. */ +typedef const RTRANGE *PCRTRANGE; + +#ifdef __cplusplus +/** + * Strict type validation helper class. + * + * See RTErrStrictType and RT_SUCCESS_NP. + */ +class RTErrStrictType2 +{ +protected: + /** The status code. */ + int32_t m_rc; + +public: + /** + * Constructor. + * @param rc IPRT style status code. + */ + RTErrStrictType2(int32_t rc) : m_rc(rc) + { + } + + /** + * Get the status code. + * @returns IPRT style status code. + */ + int32_t getValue() const + { + return m_rc; + } +}; +#endif /* __cplusplus */ +/** @} */ + +#endif + diff --git a/include/iprt/udp.h b/include/iprt/udp.h new file mode 100644 index 00000000..543d73d6 --- /dev/null +++ b/include/iprt/udp.h @@ -0,0 +1,155 @@ +/** @file + * IPRT - UDP/IP. + */ + +/* + * Copyright (C) 2006-2011 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. + */ + +#ifndef ___iprt_udp_h +#define ___iprt_udp_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/thread.h> +#include <iprt/net.h> +#include <iprt/sg.h> +#include <iprt/socket.h> + +#ifdef IN_RING0 +# error "There are no RTFile APIs available Ring-0 Host Context!" +#endif + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_udp RTUdp - UDP/IP + * @ingroup grp_rt + * @{ + */ + + +/** + * Handle incoming UDP datagrams. + * + * @returns iprt status code. + * @returns VERR_UDP_SERVER_STOP to terminate the server loop forcing + * the RTUdpCreateServer() call to return. + * @param Sock The socket on which the datagram needs to be received. + * @param pvUser User argument. + */ +typedef DECLCALLBACK(int) FNRTUDPSERVE(RTSOCKET Sock, void *pvUser); +/** Pointer to a RTUDPSERVE(). */ +typedef FNRTUDPSERVE *PFNRTUDPSERVE; + +/** + * Create single datagram at a time UDP Server in a separate thread. + * + * The thread will loop accepting datagrams and call pfnServe for + * each of the incoming datagrams in turn. The pfnServe function can + * return VERR_UDP_SERVER_STOP too terminate this loop. RTUdpServerDestroy() + * should be used to terminate the server. + * + * @returns iprt status code. + * @param pszAddress The address for creating a datagram socket. + * If NULL or empty string the server is bound to all interfaces. + * @param uPort The port for creating a datagram socket. + * @param enmType The thread type. + * @param pszThrdName The name of the worker thread. + * @param pfnServe The function which will handle incoming datagrams. + * @param pvUser User argument passed to pfnServe. + * @param ppServer Where to store the serverhandle. + */ +RTR3DECL(int) RTUdpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName, + PFNRTUDPSERVE pfnServe, void *pvUser, PPRTUDPSERVER ppServer); + +/** + * Create single datagram at a time UDP Server. + * The caller must call RTUdpServerReceive() to actually start the server. + * + * @returns iprt status code. + * @param pszAddress The address for creating a datagram socket. + * If NULL the server is bound to all interfaces. + * @param uPort The port for creating a datagram socket. + * @param ppServer Where to store the serverhandle. + */ +RTR3DECL(int) RTUdpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTUDPSERVER ppServer); + +/** + * Shuts down the server. + * + * @returns IPRT status code. + * @param pServer Handle to the server. + */ +RTR3DECL(int) RTUdpServerShutdown(PRTUDPSERVER pServer); + +/** + * Closes down and frees a UDP Server. + * + * @returns iprt status code. + * @param pServer Handle to the server. + */ +RTR3DECL(int) RTUdpServerDestroy(PRTUDPSERVER pServer); + +/** + * Listen for incoming datagrams. + * + * The function will loop waiting for datagrams and call pfnServe for + * each of the incoming datagrams in turn. The pfnServe function can + * return VERR_UDP_SERVER_STOP too terminate this loop. A stopped server + * can only be destroyed. + * + * @returns iprt status code. + * @param pServer The server handle as returned from RTUdpServerCreateEx(). + * @param pfnServe The function which will handle incoming datagrams. + * @param pvUser User argument passed to pfnServe. + */ +RTR3DECL(int) RTUdpServerListen(PRTUDPSERVER pServer, PFNRTUDPSERVE pfnServe, void *pvUser); + +/** + * Receive data from a socket. + * + * @returns iprt status code. + * @param Sock Socket descriptor. + * @param pvBuffer Where to put the data we read. + * @param cbBuffer Read buffer size. + * @param pcbRead Number of bytes read. Must be non-NULL. + */ +RTR3DECL(int) RTUdpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr); + +/** + * Send data to a socket. + * + * @returns iprt status code. + * @retval VERR_INTERRUPTED if interrupted before anything was written. + * + * @param pServer Handle to the server. + * @param pvBuffer Buffer to write data to socket. + * @param cbBuffer How much to write. + * @param pDstAddr Destination address. + */ +RTR3DECL(int) RTUdpWrite(PRTUDPSERVER pServer, const void *pvBuffer, + size_t cbBuffer, PCRTNETADDR pDstAddr); + +/** @} */ +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/uint128.h b/include/iprt/uint128.h new file mode 100644 index 00000000..d5df1c4a --- /dev/null +++ b/include/iprt/uint128.h @@ -0,0 +1,698 @@ +/** @file + * IPRT - RTUINT128U & uint128_t methods. + */ + +/* + * Copyright (C) 2011 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. + */ + +#ifndef ___iprt_uint128_h +#define ___iprt_uint128_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/err.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_once RTUInt128 - 128-bit Unsigned Integer Methods + * @ingroup grp_rt + * @{ + */ + + +/** + * Test if a 128-bit unsigned integer value is zero. + * + * @returns true if they are, false if they aren't. + * @param pValue The input and output value. + */ +DECLINLINE(bool) RTUInt128IsZero(PRTUINT128U pValue) +{ +#if ARCH_BITS >= 64 + return pValue->s.Hi == 0 + && pValue->s.Lo == 0; +#else + return pValue->DWords.dw0 == 0 + && pValue->DWords.dw1 == 0 + && pValue->DWords.dw2 == 0 + && pValue->DWords.dw3 == 0; +#endif +} + + +/** + * Set a 128-bit unsigned integer value to zero. + * + * @returns pResult + * @param pResult The result variable. + */ +DECLINLINE(PRTUINT128U) RTUInt128SetZero(PRTUINT128U pResult) +{ +#if ARCH_BITS >= 64 + pResult->s.Hi = 0; + pResult->s.Lo = 0; +#else + pResult->DWords.dw0 = 0; + pResult->DWords.dw1 = 0; + pResult->DWords.dw2 = 0; + pResult->DWords.dw3 = 0; +#endif + return pResult; +} + + +/** + * Set a 128-bit unsigned integer value to the maximum value. + * + * @returns pResult + * @param pResult The result variable. + */ +DECLINLINE(PRTUINT128U) RTUInt128SetMax(PRTUINT128U pResult) +{ +#if ARCH_BITS >= 64 + pResult->s.Hi = UINT64_MAX; + pResult->s.Lo = UINT64_MAX; +#else + pResult->DWords.dw0 = UINT32_MAX; + pResult->DWords.dw1 = UINT32_MAX; + pResult->DWords.dw2 = UINT32_MAX; + pResult->DWords.dw3 = UINT32_MAX; +#endif + return pResult; +} + + +RTDECL(PRTUINT128U) RTUInt128Add(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128Sub(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128Div(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128Mod(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128And(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128Or( PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128Xor(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128ShiftLeft( PRTUINT128U pResult, PCRTUINT128U pValue, int cBits); +RTDECL(PRTUINT128U) RTUInt128ShiftRight(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits); +RTDECL(PRTUINT128U) RTUInt128BooleanNot(PRTUINT128U pResult, PCRTUINT128U pValue); +RTDECL(PRTUINT128U) RTUInt128BitwiseNot(PRTUINT128U pResult, PCRTUINT128U pValue); + + +/** + * Assigns one 128-bit unsigned integer value to another. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue The value to assign. + */ +DECLINLINE(PRTUINT128U) RTUInt128Assign(PRTUINT128U pResult, PCRTUINT128U pValue) +{ +#if ARCH_BITS >= 64 + pResult->s.Hi = pValue->s.Hi; + pResult->s.Lo = pValue->s.Lo; +#else + pResult->DWords.dw0 = pValue->DWords.dw0; + pResult->DWords.dw1 = pValue->DWords.dw1; + pResult->DWords.dw2 = pValue->DWords.dw2; + pResult->DWords.dw3 = pValue->DWords.dw3; +#endif + return pResult; +} + + +/** + * Assigns a boolean value to 128-bit unsigned integer. + * + * @returns pResult + * @param pResult The result variable. + * @param fValue The boolean value. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignBoolean(PRTUINT128U pValueResult, bool fValue) +{ +#if ARCH_BITS >= 64 + pValueResult->s.Lo = fValue; + pValueResult->s.Hi = 0; +#else + pValueResult->DWords.dw0 = fValue; + pValueResult->DWords.dw1 = 0; + pValueResult->DWords.dw2 = 0; + pValueResult->DWords.dw3 = 0; +#endif + return pValueResult; +} + + +/** + * Assigns a 8-bit unsigned integer value to 128-bit unsigned integer. + * + * @returns pResult + * @param pResult The result variable. + * @param u8Value The 8-bit unsigned integer value. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignU8(PRTUINT128U pValueResult, uint8_t u8Value) +{ +#if ARCH_BITS >= 64 + pValueResult->s.Lo = u8Value; + pValueResult->s.Hi = 0; +#else + pValueResult->DWords.dw0 = u8Value; + pValueResult->DWords.dw1 = 0; + pValueResult->DWords.dw2 = 0; + pValueResult->DWords.dw3 = 0; +#endif + return pValueResult; +} + + +/** + * Assigns a 16-bit unsigned integer value to 128-bit unsigned integer. + * + * @returns pResult + * @param pResult The result variable. + * @param u16Value The 16-bit unsigned integer value. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignU16(PRTUINT128U pValueResult, uint16_t u16Value) +{ +#if ARCH_BITS >= 64 + pValueResult->s.Lo = u16Value; + pValueResult->s.Hi = 0; +#else + pValueResult->DWords.dw0 = u16Value; + pValueResult->DWords.dw1 = 0; + pValueResult->DWords.dw2 = 0; + pValueResult->DWords.dw3 = 0; +#endif + return pValueResult; +} + + +/** + * Assigns a 16-bit unsigned integer value to 128-bit unsigned integer. + * + * @returns pResult + * @param pResult The result variable. + * @param u32Value The 32-bit unsigned integer value. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignU32(PRTUINT128U pValueResult, uint32_t u32Value) +{ +#if ARCH_BITS >= 64 + pValueResult->s.Lo = u32Value; + pValueResult->s.Hi = 0; +#else + pValueResult->DWords.dw0 = u32Value; + pValueResult->DWords.dw1 = 0; + pValueResult->DWords.dw2 = 0; + pValueResult->DWords.dw3 = 0; +#endif + return pValueResult; +} + + +/** + * Assigns a 64-bit unsigned integer value to 128-bit unsigned integer. + * + * @returns pResult + * @param pResult The result variable. + * @param u32Value The 32-bit unsigned integer value. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignU64(PRTUINT128U pValueResult, uint64_t u64Value) +{ + pValueResult->s.Lo = u64Value; + pValueResult->s.Hi = 0; + return pValueResult; +} + + +RTDECL(PRTUINT128U) RTUInt128AssignAdd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128AssignSub(PRTUINT128U pValue1Result, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128AssignDiv(PRTUINT128U pValue1Result, PCRTUINT128U pValue2); +RTDECL(PRTUINT128U) RTUInt128AssignMod(PRTUINT128U pValue1Result, PCRTUINT128U pValue2); + + +/** + * Performs a bitwise AND of two 128-bit unsigned integer values and assigned + * the result to the first one. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignAnd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2) +{ +#if ARCH_BITS >= 64 + pValue1Result->s.Hi &= pValue2->s.Hi; + pValue1Result->s.Lo &= pValue2->s.Lo; +#else + pValue1Result->DWords.dw0 &= pValue2->DWords.dw0; + pValue1Result->DWords.dw1 &= pValue2->DWords.dw1; + pValue1Result->DWords.dw2 &= pValue2->DWords.dw2; + pValue1Result->DWords.dw3 &= pValue2->DWords.dw3; +#endif + return pValue1Result; +} + + +/** + * Performs a bitwise AND of a 128-bit unsigned integer value and a mask made + * up of the first N bits, assigning the result to the the 128-bit value. + * + * @returns pValueResult. + * @param pValueResult The value and result. + * @param cBits The number of bits to AND (counting from the first + * bit). + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignAndNFirstBits(PRTUINT128U pValueResult, unsigned cBits) +{ + if (cBits <= 64) + { + if (cBits != 64) + pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1); + pValueResult->s.Hi = 0; + } + else if (cBits < 128) + pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1); +/** @todo #if ARCH_BITS >= 64 */ + return pValueResult; +} + + +/** + * Performs a bitwise OR of two 128-bit unsigned integer values and assigned + * the result to the first one. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignOr(PRTUINT128U pValue1Result, PCRTUINT128U pValue2) +{ +#if ARCH_BITS >= 64 + pValue1Result->s.Hi |= pValue2->s.Hi; + pValue1Result->s.Lo |= pValue2->s.Lo; +#else + pValue1Result->DWords.dw0 |= pValue2->DWords.dw0; + pValue1Result->DWords.dw1 |= pValue2->DWords.dw1; + pValue1Result->DWords.dw2 |= pValue2->DWords.dw2; + pValue1Result->DWords.dw3 |= pValue2->DWords.dw3; +#endif + return pValue1Result; +} + + +/** + * Performs a bitwise XOR of two 128-bit unsigned integer values and assigned + * the result to the first one. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignXor(PRTUINT128U pValue1Result, PCRTUINT128U pValue2) +{ +#if ARCH_BITS >= 64 + pValue1Result->s.Hi ^= pValue2->s.Hi; + pValue1Result->s.Lo ^= pValue2->s.Lo; +#else + pValue1Result->DWords.dw0 ^= pValue2->DWords.dw0; + pValue1Result->DWords.dw1 ^= pValue2->DWords.dw1; + pValue1Result->DWords.dw2 ^= pValue2->DWords.dw2; + pValue1Result->DWords.dw3 ^= pValue2->DWords.dw3; +#endif + return pValue1Result; +} + + +/** + * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning + * the result to it. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param cBits The number of bits to shift. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignShiftLeft(PRTUINT128U pValueResult, int cBits) +{ + RTUINT128U const InVal = *pValueResult; +/** @todo #if ARCH_BITS >= 64 */ + if (cBits > 0) + { + /* (left shift) */ + if (cBits >= 128) + RTUInt128SetZero(pValueResult); + else if (cBits >= 64) + { + pValueResult->s.Lo = 0; + pValueResult->s.Hi = InVal.s.Lo << (cBits - 64); + } + else + { + pValueResult->s.Hi = InVal.s.Hi << cBits; + pValueResult->s.Hi |= InVal.s.Lo >> (64 - cBits); + pValueResult->s.Lo = InVal.s.Lo << cBits; + } + } + else if (cBits < 0) + { + /* (right shift) */ + cBits = -cBits; + if (cBits >= 128) + RTUInt128SetZero(pValueResult); + else if (cBits >= 64) + { + pValueResult->s.Hi = 0; + pValueResult->s.Lo = InVal.s.Hi >> (cBits - 64); + } + else + { + pValueResult->s.Lo = InVal.s.Lo >> cBits; + pValueResult->s.Lo |= InVal.s.Hi << (64 - cBits); + pValueResult->s.Hi = InVal.s.Hi >> cBits; + } + } + return pValueResult; +} + + +/** + * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning + * the result to it. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param cBits The number of bits to shift. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignShiftRight(PRTUINT128U pValueResult, int cBits) +{ + return RTUInt128AssignShiftLeft(pValueResult, -cBits); +} + + +/** + * Performs a bitwise NOT on a 128-bit unsigned integer value, assigning the + * result to it. + * + * @returns pValueResult + * @param pValueResult The value and result. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignBitwiseNot(PRTUINT128U pValueResult) +{ +#if ARCH_BITS >= 64 + pValueResult->s.Hi = ~pValueResult->s.Hi; + pValueResult->s.Lo = ~pValueResult->s.Lo; +#else + pValueResult->DWords.dw0 = ~pValueResult->DWords.dw0; + pValueResult->DWords.dw1 = ~pValueResult->DWords.dw1; + pValueResult->DWords.dw2 = ~pValueResult->DWords.dw2; + pValueResult->DWords.dw3 = ~pValueResult->DWords.dw3; +#endif + return pValueResult; +} + + +/** + * Performs a boolean NOT on a 128-bit unsigned integer value, assigning the + * result to it. + * + * @returns pValueResult + * @param pValueResult The value and result. + */ +DECLINLINE(PRTUINT128U) RTUInt128AssignBooleanNot(PRTUINT128U pValueResult) +{ + return RTUInt128AssignBoolean(pValueResult, RTUInt128IsZero(pValueResult)); +} + + +/** + * Compares two 128-bit unsigned integer values. + * + * @retval 0 if equal. + * @retval -1 if the first value is smaller than the second. + * @retval 1 if the first value is larger than the second. + * + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(int) RTUInt128Compare(PCRTUINT128U pValue1, PCRTUINT128U pValue2) +{ +#if ARCH_BITS >= 64 + if (pValue1->s.Hi != pValue2->s.Hi) + return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1; + if (pValue1->s.Lo != pValue2->s.Lo) + return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1; + return 0; +#else + if (pValue1->DWords.dw0 != pValue2->DWords.dw0) + return pValue1->DWords.dw0 > pValue2->DWords.dw0 ? 1 : -1; + if (pValue1->DWords.dw1 != pValue2->DWords.dw1) + return pValue1->DWords.dw1 > pValue2->DWords.dw1 ? 1 : -1; + if (pValue1->DWords.dw2 != pValue2->DWords.dw2) + return pValue1->DWords.dw2 > pValue2->DWords.dw2 ? 1 : -1; + if (pValue1->DWords.dw3 != pValue2->DWords.dw3) + return pValue1->DWords.dw3 > pValue2->DWords.dw3 ? 1 : -1; + return 0; +#endif +} + + +/** + * Tests if two 128-bit unsigned integer values not equal. + * + * @returns true if equal, false if not equal. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(bool) RTUInt128IsEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2) +{ +#if ARCH_BITS >= 64 + return pValue1->s.Hi == pValue2->s.Hi + && pValue1->s.Lo == pValue2->s.Lo; +#else + return pValue1->DWords.dw0 == pValue2->DWords.dw0 + && pValue1->DWords.dw1 == pValue2->DWords.dw1 + && pValue1->DWords.dw2 == pValue2->DWords.dw2 + && pValue1->DWords.dw3 == pValue2->DWords.dw3; +#endif +} + + +/** + * Tests if two 128-bit unsigned integer values are not equal. + * + * @returns true if not equal, false if equal. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(bool) RTUInt128IsNotEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2) +{ + return !RTUInt128IsEqual(pValue1, pValue2); +} + + +/** + * Sets a bit in a 128-bit unsigned integer type. + * + * @returns pValueResult. + * @param pValueResult The input and output value. + * @param iBit The bit to set. + */ +DECLINLINE(PRTUINT128U) RTUInt128BitSet(PRTUINT128U pValueResult, unsigned iBit) +{ + if (iBit < 64) + { +#if ARCH_BITS >= 64 + pValueResult->s.Lo |= RT_BIT_64(iBit); +#else + if (iBit < 32) + pValueResult->DWords.dw0 |= RT_BIT_32(iBit); + else + pValueResult->DWords.dw1 |= RT_BIT_32(iBit - 32); +#endif + } + else if (iBit < 128) + { +#if ARCH_BITS >= 64 + pValueResult->s.Hi |= RT_BIT_64(iBit - 64); +#else + if (iBit < 96) + pValueResult->DWords.dw2 |= RT_BIT_32(iBit - 64); + else + pValueResult->DWords.dw3 |= RT_BIT_32(iBit - 96); +#endif + } + return pValueResult; +} + + +/** + * Sets a bit in a 128-bit unsigned integer type. + * + * @returns pValueResult. + * @param pValueResult The input and output value. + * @param iBit The bit to set. + */ +DECLINLINE(PRTUINT128U) RTUInt128BitClear(PRTUINT128U pValueResult, unsigned iBit) +{ + if (iBit < 64) + { +#if ARCH_BITS >= 64 + pValueResult->s.Lo &= ~RT_BIT_64(iBit); +#else + if (iBit < 32) + pValueResult->DWords.dw0 &= ~RT_BIT_32(iBit); + else + pValueResult->DWords.dw1 &= ~RT_BIT_32(iBit - 32); +#endif + } + else if (iBit < 128) + { +#if ARCH_BITS >= 64 + pValueResult->s.Hi &= ~RT_BIT_64(iBit - 64); +#else + if (iBit < 96) + pValueResult->DWords.dw2 &= ~RT_BIT_32(iBit - 64); + else + pValueResult->DWords.dw3 &= ~RT_BIT_32(iBit - 96); +#endif + } + return pValueResult; +} + + +/** + * Tests if a bit in a 128-bit unsigned integer value is set. + * + * @returns pValueResult. + * @param pValueResult The input and output value. + * @param iBit The bit to test. + */ +DECLINLINE(bool) RTUInt128BitTest(PRTUINT128U pValueResult, unsigned iBit) +{ + bool fRc; + if (iBit < 64) + { +#if ARCH_BITS >= 64 + fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_64(iBit)); +#else + if (iBit < 32) + fRc = RT_BOOL(pValueResult->DWords.dw0 & RT_BIT_32(iBit)); + else + fRc = RT_BOOL(pValueResult->DWords.dw1 & RT_BIT_32(iBit - 32)); +#endif + } + else if (iBit < 128) + { +#if ARCH_BITS >= 64 + fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_64(iBit - 64)); +#else + if (iBit < 96) + fRc = RT_BOOL(pValueResult->DWords.dw2 & RT_BIT_32(iBit - 64)); + else + fRc = RT_BOOL(pValueResult->DWords.dw3 & RT_BIT_32(iBit - 96)); +#endif + } + else + fRc = false; + return fRc; +} + + +/** + * Set a range of bits a 128-bit unsigned integer value. + * + * @returns pValueResult. + * @param pValueResult The input and output value. + * @param iFirstBit The first bit to test. + * @param cBits The number of bits to set. + */ +DECLINLINE(PRTUINT128U) RTUInt128BitSetRange(PRTUINT128U pValueResult, unsigned iFirstBit, unsigned cBits) +{ + /* bounds check & fix. */ + if (iFirstBit < 128) + { + if (iFirstBit + cBits > 128) + cBits = 128 - iFirstBit; + +#if ARCH_BITS >= 64 + if (iFirstBit + cBits < 64) + pValueResult->s.Lo |= (RT_BIT_64(cBits) - 1) << iFirstBit; + else if (iFirstBit + cBits < 128 && iFirstBit >= 64) + pValueResult->s.Hi |= (RT_BIT_64(cBits) - 1) << (iFirstBit - 64); + else +#else + if (iFirstBit + cBits < 32) + pValueResult->DWords.dw0 |= (RT_BIT_32(cBits) - 1) << iFirstBit; + else if (iFirstBit + cBits < 64 && iFirstBit >= 32) + pValueResult->DWords.dw1 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32); + else if (iFirstBit + cBits < 96 && iFirstBit >= 64) + pValueResult->DWords.dw2 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 64); + else if (iFirstBit + cBits < 128 && iFirstBit >= 96) + pValueResult->DWords.dw3 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 96); + else +#endif + while (cBits-- > 0) + RTUInt128BitSet(pValueResult, iFirstBit++); + } + return pValueResult; +} + + +/** + * Test if all the bits of a 128-bit unsigned integer value are set. + * + * @returns true if they are, false if they aren't. + * @param pValue The input and output value. + */ +DECLINLINE(bool) RTUInt128BitAreAllSet(PRTUINT128U pValue) +{ +#if ARCH_BITS >= 64 + return pValue->s.Hi == UINT64_MAX + && pValue->s.Lo == UINT64_MAX; +#else + return pValue->DWords.dw0 == UINT32_MAX + && pValue->DWords.dw1 == UINT32_MAX + && pValue->DWords.dw2 == UINT32_MAX + && pValue->DWords.dw3 == UINT32_MAX; +#endif +} + + +/** + * Test if all the bits of a 128-bit unsigned integer value are clear. + * + * @returns true if they are, false if they aren't. + * @param pValue The input and output value. + */ +DECLINLINE(bool) RTUInt128BitAreAllClear(PRTUINT128U pValue) +{ +#if ARCH_BITS >= 64 + return pValue->s.Hi == 0 + && pValue->s.Lo == 0; +#else + return pValue->DWords.dw0 == 0 + && pValue->DWords.dw1 == 0 + && pValue->DWords.dw2 == 0 + && pValue->DWords.dw3 == 0; +#endif +} + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/uni.h b/include/iprt/uni.h new file mode 100644 index 00000000..6f0c23ec --- /dev/null +++ b/include/iprt/uni.h @@ -0,0 +1,397 @@ +/** @file + * IPRT - Unicode Code Points. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_uni_h +#define ___iprt_uni_h + +/** @defgroup grp_rt_uni RTUniCp - Unicode Code Points + * @ingroup grp_rt + * @{ + */ + +/** @def RTUNI_USE_WCTYPE + * Define RTUNI_USE_WCTYPE to not use the IPRT unicode data but the + * data which the C runtime library provides. */ +#ifdef DOXYGEN_RUNNING +# define RTUNI_USE_WCTYPE +#endif + +#include <iprt/types.h> +#ifdef RTUNI_USE_WCTYPE +# include <wctype.h> +#endif + +RT_C_DECLS_BEGIN + + + +#ifndef RTUNI_USE_WCTYPE +/** + * A unicode flags range. + * @internal + */ +typedef struct RTUNIFLAGSRANGE +{ + /** The first code point of the range. */ + RTUNICP BeginCP; + /** The last + 1 code point of the range. */ + RTUNICP EndCP; + /** Pointer to the array of case folded code points. */ + const uint8_t *pafFlags; +} RTUNIFLAGSRANGE; +/** Pointer to a flags range. + * @internal */ +typedef RTUNIFLAGSRANGE *PRTUNIFLAGSRANGE; +/** Pointer to a const flags range. + * @internal */ +typedef const RTUNIFLAGSRANGE *PCRTUNIFLAGSRANGE; + +/** + * A unicode case folded range. + * @internal + */ +typedef struct RTUNICASERANGE +{ + /** The first code point of the range. */ + RTUNICP BeginCP; + /** The last + 1 code point of the range. */ + RTUNICP EndCP; + /** Pointer to the array of case folded code points. */ + PCRTUNICP paFoldedCPs; +} RTUNICASERANGE; +/** Pointer to a case folded range. + * @internal */ +typedef RTUNICASERANGE *PRTUNICASERANGE; +/** Pointer to a const case folded range. + * @internal */ +typedef const RTUNICASERANGE *PCRTUNICASERANGE; + +/** @name Unicode Code Point Flags. + * @internal + * @{ */ +#define RTUNI_UPPER RT_BIT(0) +#define RTUNI_LOWER RT_BIT(1) +#define RTUNI_ALPHA RT_BIT(2) +#define RTUNI_XDIGIT RT_BIT(3) +#define RTUNI_DDIGIT RT_BIT(4) +#define RTUNI_WSPACE RT_BIT(5) +/*#define RTUNI_BSPACE RT_BIT(6) - later */ +/** When set, the codepoint requires further checking wrt NFC and NFD + * normalization. I.e. set when either of QC_NFD and QC_NFC are not Y. */ +#define RTUNI_QC_NFX RT_BIT(7) +/** @} */ + + +/** + * Array of flags ranges. + * @internal + */ +extern RTDATADECL(const RTUNIFLAGSRANGE) g_aRTUniFlagsRanges[]; + +/** + * Gets the flags for a unicode code point. + * + * @returns The flag mask. (RTUNI_*) + * @param CodePoint The unicode code point. + * @internal + */ +DECLINLINE(RTUNICP) rtUniCpFlags(RTUNICP CodePoint) +{ + PCRTUNIFLAGSRANGE pCur = &g_aRTUniFlagsRanges[0]; + do + { + if (pCur->EndCP > CodePoint) + { + if (pCur->BeginCP <= CodePoint) + return pCur->pafFlags[CodePoint - pCur->BeginCP]; + break; + } + pCur++; + } while (pCur->EndCP != RTUNICP_MAX); + return 0; +} + + +/** + * Checks if a unicode code point is upper case. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsUpper(RTUNICP CodePoint) +{ + return (rtUniCpFlags(CodePoint) & RTUNI_UPPER) != 0; +} + + +/** + * Checks if a unicode code point is lower case. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsLower(RTUNICP CodePoint) +{ + return (rtUniCpFlags(CodePoint) & RTUNI_LOWER) != 0; +} + + +/** + * Checks if a unicode code point is alphabetic. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsAlphabetic(RTUNICP CodePoint) +{ + return (rtUniCpFlags(CodePoint) & RTUNI_ALPHA) != 0; +} + + +/** + * Checks if a unicode code point is a decimal digit. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsDecDigit(RTUNICP CodePoint) +{ + return (rtUniCpFlags(CodePoint) & RTUNI_DDIGIT) != 0; +} + + +/** + * Checks if a unicode code point is a hexadecimal digit. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsHexDigit(RTUNICP CodePoint) +{ + return (rtUniCpFlags(CodePoint) & RTUNI_XDIGIT) != 0; +} + + +/** + * Checks if a unicode code point is white space. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsSpace(RTUNICP CodePoint) +{ + return (rtUniCpFlags(CodePoint) & RTUNI_WSPACE) != 0; +} + + + +/** + * Array of uppercase ranges. + * @internal + */ +extern RTDATADECL(const RTUNICASERANGE) g_aRTUniUpperRanges[]; + +/** + * Array of lowercase ranges. + * @internal + */ +extern RTDATADECL(const RTUNICASERANGE) g_aRTUniLowerRanges[]; + + +/** + * Folds a unicode code point using the specified range array. + * + * @returns FOlded code point. + * @param CodePoint The unicode code point to fold. + * @param pCur The case folding range to use. + */ +DECLINLINE(RTUNICP) rtUniCpFold(RTUNICP CodePoint, PCRTUNICASERANGE pCur) +{ + do + { + if (pCur->EndCP > CodePoint) + { + if (pCur->BeginCP <= CodePoint) + CodePoint = pCur->paFoldedCPs[CodePoint - pCur->BeginCP]; + break; + } + pCur++; + } while (pCur->EndCP != RTUNICP_MAX); + return CodePoint; +} + + +/** + * Folds a unicode code point to upper case. + * + * @returns Folded code point. + * @param CodePoint The unicode code point to fold. + */ +DECLINLINE(RTUNICP) RTUniCpToUpper(RTUNICP CodePoint) +{ + return rtUniCpFold(CodePoint, &g_aRTUniUpperRanges[0]); +} + + +/** + * Folds a unicode code point to lower case. + * + * @returns Folded code point. + * @param CodePoint The unicode code point to fold. + */ +DECLINLINE(RTUNICP) RTUniCpToLower(RTUNICP CodePoint) +{ + return rtUniCpFold(CodePoint, &g_aRTUniLowerRanges[0]); +} + + +#else /* RTUNI_USE_WCTYPE */ + + +/** + * Checks if a unicode code point is upper case. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsUpper(RTUNICP CodePoint) +{ + return !!iswupper(CodePoint); +} + + +/** + * Checks if a unicode code point is lower case. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsLower(RTUNICP CodePoint) +{ + return !!iswlower(CodePoint); +} + + +/** + * Checks if a unicode code point is alphabetic. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsAlphabetic(RTUNICP CodePoint) +{ + return !!iswalpha(CodePoint); +} + + +/** + * Checks if a unicode code point is a decimal digit. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsDecDigit(RTUNICP CodePoint) +{ + return !!iswdigit(CodePoint); +} + + +/** + * Checks if a unicode code point is a hexadecimal digit. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsHexDigit(RTUNICP CodePoint) +{ + return !!iswxdigit(CodePoint); +} + + +/** + * Checks if a unicode code point is white space. + * + * @returns true if it is. + * @returns false if it isn't. + * @param CodePoint The code point. + */ +DECLINLINE(bool) RTUniCpIsSpace(RTUNICP CodePoint) +{ + return !!iswspace(CodePoint); +} + + +/** + * Folds a unicode code point to upper case. + * + * @returns Folded code point. + * @param CodePoint The unicode code point to fold. + */ +DECLINLINE(RTUNICP) RTUniCpToUpper(RTUNICP CodePoint) +{ + return towupper(CodePoint); +} + + +/** + * Folds a unicode code point to lower case. + * + * @returns Folded code point. + * @param CodePoint The unicode code point to fold. + */ +DECLINLINE(RTUNICP) RTUniCpToLower(RTUNICP CodePoint) +{ + return towlower(CodePoint); +} + + +#endif /* RTUNI_USE_WCTYPE */ + + +/** + * Frees a unicode string. + * + * @param pusz The string to free. + */ +RTDECL(void) RTUniFree(PRTUNICP pusz); + + +RT_C_DECLS_END +/** @} */ + + +#endif + diff --git a/include/iprt/uri.h b/include/iprt/uri.h new file mode 100644 index 00000000..5696e5ae --- /dev/null +++ b/include/iprt/uri.h @@ -0,0 +1,157 @@ +/** @file + * IPRT - Uniform Resource Identifier handling. + */ + +/* + * Copyright (C) 2011 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. + */ + +#ifndef ___iprt_uri_h +#define ___iprt_uri_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_uri RTUri - Uri parsing and creation + * URI parsing and creation based on RFC 3986. + * See http://datatracker.ietf.org/doc/rfc3986/ for the full specification. + * @note Currently it isn't the full specification implemented. + * @note Currently only some generic URI support and a minimum File(file:) URI + * support is implemented. Other specific scheme support, like html:, ldap:, + * data:, ..., is missing. + * @see grp_rt_uri_file + * @ingroup grp_rt + * @{ + */ + +/** + * Creates a generic URI. + * + * @returns the new URI on success, NULL otherwise. + * @param pszScheme The URI scheme. + * @param pszAuthority The authority part of the URI (optional). + * @param pszPath The path part of the URI (optional). + * @param pszQuery The query part of the URI (optional). + * @param pszFragment The fragment part of the URI (optional). + */ +RTR3DECL(char *) RTUriCreate(const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery, const char *pszFragment); + +/** + * Check an string for a specific URI scheme. + * + * @returns true if the scheme match, false if not. + * @param pszUri The URI to check. + * @param pszScheme The scheme to compare with. + */ +RTR3DECL(bool) RTUriHasScheme(const char *pszUri, const char *pszScheme); + +/** + * Extract the scheme out of an URI. + * + * @returns the scheme if the URI is valid, NULL otherwise. + * @param pszUri The URI to extract from. + */ +RTR3DECL(char *) RTUriScheme(const char *pszUri); + +/** + * Extract the authority out of an URI. + * + * @returns the authority if the URI contains one, NULL otherwise. + * @param pszUri The URI to extract from. + */ +RTR3DECL(char *) RTUriAuthority(const char *pszUri); + +/** + * Extract the path out of an URI. + * + * @returns the path if the URI contains one, NULL otherwise. + * @param pszUri The URI to extract from. + */ +RTR3DECL(char *) RTUriPath(const char *pszUri); + +/** + * Extract the query out of an URI. + * + * @returns the query if the URI contains one, NULL otherwise. + * @param pszUri The URI to extract from. + */ +RTR3DECL(char *) RTUriQuery(const char *pszUri); + +/** + * Extract the fragment out of an URI. + * + * @returns the fragment if the URI contains one, NULL otherwise. + * @param pszUri The URI to extract from. + */ +RTR3DECL(char *) RTUriFragment(const char *pszUri); + +/** @defgroup grp_rt_uri_file RTUriFile - Uri file parsing and creation + * Adds file: scheme support to the generic RTUri interface. This is partly + * documented in http://datatracker.ietf.org/doc/rfc1738/. + * @ingroup grp_rt_uri + * @{ + */ + +/** Auto detect in which format a path is returned. */ +#define URI_FILE_FORMAT_AUTO UINT32_C(0) +/** Return a path in UNIX format style. */ +#define URI_FILE_FORMAT_UNIX UINT32_C(1) +/** Return a path in Windows format style. */ +#define URI_FILE_FORMAT_WIN UINT32_C(2) + +/** + * Creates a file URI. + * + * @see RTUriCreate + * + * @returns the new URI on success, NULL otherwise. + * @param pszPath The path of the URI. + */ +RTR3DECL(char *) RTUriFileCreate(const char *pszPath); + +/** + * Returns the file path encoded in the URI. + * + * @returns the path if the URI contains one, NULL otherwise. + * @param pszUri The URI to extract from. + * @param uFormat In which format should the path returned. + */ +RTR3DECL(char *) RTUriFilePath(const char *pszUri, uint32_t uFormat); + +/** + * Returns the file path encoded in the URI, given a max string length. + * + * @returns the path if the URI contains one, NULL otherwise. + * @param pszUri The URI to extract from. + * @param uFormat In which format should the path returned. + * @param cbMax The max string length to inspect. + */ +RTR3DECL(char *) RTUriFileNPath(const char *pszUri, uint32_t uFormat, size_t cchMax); + +/** @} */ + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/uuid.h b/include/iprt/uuid.h new file mode 100644 index 00000000..94604e2b --- /dev/null +++ b/include/iprt/uuid.h @@ -0,0 +1,185 @@ +/** @file + * IPRT - Universal Unique Identifiers (UUID). + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_uuid_h +#define ___iprt_uuid_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_uuid RTUuid - Universally Unique Identifiers + * @ingroup grp_rt + * @{ + */ + +/** + * Generates new UUID value. + * + * @note IPRT uses little endian byte ordering in the UUID integer fields. If + * you want to pass IPRT UUIDs in binary representation to other UUID libraries + * and expect to get exactly the same string representation as in IPRT, you + * need to convert the first three integer fields (one 32 bit value, two 16 bit + * values) separately to big endian (also called network byte order). + * + * @sa RTUUID::Gen + * + * @returns iprt status code. + * @param pUuid Where to store generated uuid. + */ +RTDECL(int) RTUuidCreate(PRTUUID pUuid); + +/** + * Makes null UUID value. + * + * @returns iprt status code. + * @param pUuid Where to store generated null uuid. + */ +RTDECL(int) RTUuidClear(PRTUUID pUuid); + +/** + * Checks if UUID is null. + * + * @returns true if UUID is null. + * @param pUuid uuid to check. + */ +RTDECL(bool) RTUuidIsNull(PCRTUUID pUuid); + +/** + * Compares two UUID values. + * + * @returns 0 if eq, < 0 or > 0. + * @param pUuid1 First value to compare. NULL is treated like if + * RTUuidIsNull() return true. + * @param pUuid2 Second value to compare. NULL is treated like if + * RTUuidIsNull() return true. + */ +RTDECL(int) RTUuidCompare(PCRTUUID pUuid1, PCRTUUID pUuid2); + +/** + * Compares a UUID value with a UUID string. + * + * @note IPRT uses little endian byte ordering in the UUID integer fields. If + * you want to pass IPRT UUIDs in binary representation to other UUID libraries + * and expect to get exactly the same string representation as in IPRT, you need + * to convert the first three integer fields (one 32 bit value, two 16 bit + * values) separately to big endian (also called network byte order). + * Correspondingly, if you want to get the right result with UUIDs which are in + * big endian format, you need to convert them before using this function. + * + * @sa RTUUID::Gen + * + * @returns 0 if eq, < 0 or > 0. + * @param pUuid1 First value to compare. NULL is not allowed. + * @param pszString2 The 2nd UUID in string form. NULL or malformed + * string is not permitted. + */ +RTDECL(int) RTUuidCompareStr(PCRTUUID pUuid1, const char *pszString2); + +/** + * Compares two UUID strings. + * + * @returns 0 if eq, < 0 or > 0. + * @param pszString1 The 1st UUID in string from. NULL or malformed + * string is not permitted. + * @param pszString2 The 2nd UUID in string form. NULL or malformed + * string is not permitted. + */ +RTDECL(int) RTUuidCompare2Strs(const char *pszString1, const char *pszString2); + +/** + * Converts binary UUID to its string representation. + * + * @note IPRT uses little endian byte ordering in the UUID integer fields. If + * you want to pass IPRT UUIDs in binary representation to other UUID libraries + * and expect to get exactly the same string representation as in IPRT, you + * need to convert the first three integer fields (one 32 bit value, two 16 bit + * values) separately to big endian (also called network byte order). + * Correspondingly, if you want to get the right result with UUIDs which are in + * big endian format, you need to convert them before using this function. + * + * @sa RTUUID::Gen + * + * @returns iprt status code. + * @param pUuid Uuid to convert. + * @param pszString Where to store result string. + * @param cchString pszString buffer length, must be >= RTUUID_STR_LENGTH. + */ +RTDECL(int) RTUuidToStr(PCRTUUID pUuid, char *pszString, size_t cchString); + +/** + * Converts UUID from its string representation to binary format. + * + * @note IPRT uses little endian byte ordering in the UUID integer fields. If + * you want to pass IPRT UUIDs in binary representation to other UUID libraries + * and expect to get exactly the same string representation as in IPRT, you + * need to convert the first three integer fields (one 32 bit value, two 16 bit + * values) separately to big endian (also called network byte order). + * Correspondingly, if you want to get the right result with UUIDs which are in + * big endian format, you need to convert them before using this function. + * + * @sa RTUUID::Gen + * + * @returns iprt status code. + * @param pUuid Where to store result Uuid. + * @param pszString String with UUID text data. + */ +RTDECL(int) RTUuidFromStr(PRTUUID pUuid, const char *pszString); + +/** + * Converts binary UUID to its UTF-16 string representation. + * + * @note See note in RTUuidToStr. + * + * @sa RTUUID::Gen + * + * @returns iprt status code. + * @param pUuid Uuid to convert. + * @param pwszString Where to store result string. + * @param cwcString pszString buffer length, must be >= + * RTUUID_STR_LENGTH. + */ +RTDECL(int) RTUuidToUtf16(PCRTUUID pUuid, PRTUTF16 pwszString, size_t cwcString); + +/** + * Converts UUID from its UTF-16 string representation to binary format. + * + * @note See note in RTUuidFromStr. + * + * @sa RTUUID::Gen + * + * @returns iprt status code. + * @param pUuid Where to store result Uuid. + * @param pwszString String with UUID text data. + */ +RTDECL(int) RTUuidFromUtf16(PRTUUID pUuid, PCRTUTF16 pwszString); + +/** @} */ + +RT_C_DECLS_END + +#endif + diff --git a/include/iprt/vector.h b/include/iprt/vector.h new file mode 100644 index 00000000..797fe192 --- /dev/null +++ b/include/iprt/vector.h @@ -0,0 +1,375 @@ +/** @file + * IPRT - Vector + * STL-inspired vector implementation in C + */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @todo the right Doxygen tag here + * This file defines a set of macros which provide a functionality and an + * interface roughly similar to the C++ STL vector container. To create a + * vector of a particular type one must first explicitly instantiate such a + * vector in the source file, e.g. + * RTVEC_DECL(TopLevels, Window *) + * without a semi-colon. This macro will define a structure (struct TopLevels) + * which contains a dynamically resizeable array of Window * elements. It + * will also define a number of inline methods for manipulating the structure, + * such as + * Window *TopLevelsPushBack(struct TopLevels *) + * which adds a new element to the end of the array and returns it, optionally + * reallocating the array if there is not enough space for the new element. + * (This particular method prototype differs from the STL equivalent - + * push_back - more than most of the other methods). + * + * To create a vector, one simply needs to declare the structure, in this case + * struct TopLevels = RTVEC_INITIALIZER; + * + * There are various other macros for declaring vectors with different + * allocators (e.g. RTVEC_DECL_ALLOCATOR) or with clean-up functions + * (e.g. RTVEC_DECL_DELETE). See the descriptions of the generic methods and + * the declarator macros below. + * + * One particular use of vectors is to assemble an array of a particular type + * in heap memory without knowing - or counting - the number of elements in + * advance. To do this, add the elements onto the array using PushBack, then + * extract the array from the vector using the (non-STL) Detach method. + * + * @note functions in this file are inline to prevent warnings about + * unused static functions. I assume that in this day and age a + * compiler makes its own decisions about whether to actually + * inline a function. + * @note since vector structures must be explicitly instanciated unlike the + * C++ vector template, care must be taken not to instanciate a + * particular type twice, e.g. once in a header and once in a code file. + * Only using vectors in code files and keeping them out of interfaces + * (or passing them as anonymously) makes it easier to take care of this. + */ +#ifndef ___iprt_vector_h +# define ___iprt_vector_h + +/******************************************************************************* +* Header Files * +*******************************************************************************/ + +#include <iprt/assert.h> +#include <iprt/cdefs.h> +#include <iprt/err.h> +#include <iprt/mem.h> /** @todo Should the caller include this if they need + * it? */ + + +/** + * Generic vector structure + */ +/** @todo perhaps we should include an additional member for a parameter to + * three-argument reallocators, so that we can support e.g. mempools? */ +#define RTVEC_DECL_STRUCT(name, type) \ +struct name \ +{ \ + /** The number of elements in the vector */ \ + size_t mcElements; \ + /** The current capacity of the vector */ \ + size_t mcCapacity; \ + /** The elements themselves */ \ + type *mpElements; \ +}; + +/** Initialiser for an empty vector structure */ +#define RTVEC_INITIALIZER { 0, 0, NULL } + +/** The unit by which the vector capacity is increased */ +#define RTVECIMPL_ALLOC_UNIT 16 + +/** + * Generic method - get the size of a vector + */ +/** @todo What is the correct way to do doxygen for this sort of macro? */ +#define RTVEC_DECLFN_SIZE(name, type) \ +DECLINLINE(size_t) name ## Size(struct name *pVec) \ +{ \ + return(pVec->mcElements); \ +} + +/** + * Generic method - expand a vector + */ +#define RTVEC_DECLFN_RESERVE(name, type, pfnRealloc) \ +DECLINLINE(int) name ## Reserve(struct name *pVec, size_t cNewCapacity) \ +{ \ + void *pvNew; \ + \ + if (cNewCapacity <= pVec->mcCapacity) \ + return VINF_SUCCESS; \ + pvNew = pfnRealloc(pVec->mpElements, cNewCapacity * sizeof(type)); \ + if (!pvNew) \ + return VERR_NO_MEMORY; \ + pVec->mcCapacity = cNewCapacity; \ + pVec->mpElements = (type *)pvNew; \ + return VINF_SUCCESS; \ +} + +/** + * Generic method - return a pointer to the first element in the vector. + */ +#define RTVEC_DECLFN_BEGIN(name, type) \ +DECLINLINE(type *) name ## Begin(struct name *pVec) \ +{ \ + return(pVec->mpElements); \ +} + +/** + * Generic method - return a pointer to one past the last element in the + * vector. + */ +#define RTVEC_DECLFN_END(name, type) \ +DECLINLINE(type *) name ## End(struct name *pVec) \ +{ \ + return(&pVec->mpElements[pVec->mcElements]); \ +} + +/** + * Generic method - add a new, uninitialised element onto a vector and return + * it. + * @note this method differs from the STL equivalent by letting the caller + * post-initialise the new element rather than copying it from its + * argument. + */ +#define RTVEC_DECLFN_PUSHBACK(name, type) \ +DECLINLINE(type *) name ## PushBack(struct name *pVec) \ +{ \ + Assert(pVec->mcElements <= pVec->mcCapacity); \ + if ( pVec->mcElements == pVec->mcCapacity \ + && RT_FAILURE(name ## Reserve(pVec, pVec->mcCapacity \ + + RTVECIMPL_ALLOC_UNIT))) \ + return NULL; \ + ++pVec->mcElements; \ + return &pVec->mpElements[pVec->mcElements - 1]; \ +} + +/** + * Generic method - drop the last element from the vector. + */ +#define RTVEC_DECLFN_POPBACK(name) \ +DECLINLINE(void) name ## PopBack(struct name *pVec) \ +{ \ + Assert(pVec->mcElements <= pVec->mcCapacity); \ + --pVec->mcElements; \ +} + +/** + * Generic method - drop the last element from the vector, calling a clean-up + * method first. + * + * By taking an adapter function for the element to be dropped as an + * additional macro parameter we can support clean-up by pointer + * (pfnAdapter maps T* -> T*) or by value (maps T* -> T). pfnAdapter takes + * one argument of type @a type * and must return whatever type pfnDelete + * expects. + */ +/** @todo find a better name for pfnAdapter? */ +#define RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete, pfnAdapter) \ +DECLINLINE(void) name ## PopBack(struct name *pVec) \ +{ \ + Assert(pVec->mcElements <= pVec->mcCapacity); \ + --pVec->mcElements; \ + pfnDelete(pfnAdapter(&pVec->mpElements[pVec->mcElements])); \ +} + +/** + * Generic method - reset a vector to empty. + * @note This function does not free any memory + */ +#define RTVEC_DECLFN_CLEAR(name) \ +DECLINLINE(void) name ## Clear(struct name *pVec) \ +{ \ + Assert(pVec->mcElements <= pVec->mcCapacity); \ + pVec->mcElements = 0; \ +} + +/** + * Generic method - reset a vector to empty, calling a clean-up method on each + * element first. + * @note See @a RTVEC_DECLFN_POPBACK_DELETE for an explanation of pfnAdapter + * @note This function does not free any memory + * @note The cleanup function is currently called on the elements from first + * to last. The testcase expects this. + */ +#define RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete, pfnAdapter) \ +DECLINLINE(void) name ## Clear(struct name *pVec) \ +{ \ + size_t i; \ + \ + Assert(pVec->mcElements <= pVec->mcCapacity); \ + for (i = 0; i < pVec->mcElements; ++i) \ + pfnDelete(pfnAdapter(&pVec->mpElements[i])); \ + pVec->mcElements = 0; \ +} + +/** + * Generic method - detach the array contained inside a vector and reset the + * vector to empty. + * @note This function does not free any memory + */ +#define RTVEC_DECLFN_DETACH(name, type) \ +DECLINLINE(type *) name ## Detach(struct name *pVec) \ +{ \ + type *pArray = pVec->mpElements; \ + \ + Assert(pVec->mcElements <= pVec->mcCapacity); \ + pVec->mcElements = 0; \ + pVec->mpElements = NULL; \ + pVec->mcCapacity = 0; \ + return pArray; \ +} + +/** Common declarations for all vector types */ +#define RTVEC_DECL_COMMON(name, type, pfnRealloc) \ + RTVEC_DECL_STRUCT(name, type) \ + RTVEC_DECLFN_SIZE(name, type) \ + RTVEC_DECLFN_RESERVE(name, type, pfnRealloc) \ + RTVEC_DECLFN_BEGIN(name, type) \ + RTVEC_DECLFN_END(name, type) \ + RTVEC_DECLFN_PUSHBACK(name, type) \ + RTVEC_DECLFN_DETACH(name, type) + +/** + * Declarator macro - declare a vector type + * @param name the name of the C struct type describing the vector as + * well as the prefix of the functions for manipulating it + * @param type the type of the objects contained in the vector + * @param pfnRealloc the memory reallocation function used for expanding the + * vector + */ +#define RTVEC_DECL_ALLOCATOR(name, type, pfnRealloc) \ + RTVEC_DECL_COMMON(name, type, pfnRealloc) \ + RTVEC_DECLFN_POPBACK(name) \ + RTVEC_DECLFN_CLEAR(name) + +/** + * Generic method - inline id mapping delete adapter function - see the + * explanation of pfnAdapter in @a RTVEC_DECLFN_POPBACK_DELETE. + */ +#define RTVEC_DECLFN_DELETE_ADAPTER_ID(name, type) \ +DECLINLINE(type *) name ## DeleteAdapterId(type *arg) \ +{ \ + return arg; \ +} + +/** + * Generic method - inline pointer-to-value mapping delete adapter function - + * see the explanation of pfnAdapter in @a RTVEC_DECLFN_POPBACK_DELETE. + */ +#define RTVEC_DECLFN_DELETE_ADAPTER_TO_VALUE(name, type) \ +DECLINLINE(type) name ## DeleteAdapterToValue(type *arg) \ +{ \ + return *arg; \ +} + +/** + * Declarator macro - declare a vector type with a cleanup callback to be used + * when elements are dropped from the vector. The callback takes a pointer to + * @a type, + * NOT a value of type @a type. + * @param name the name of the C struct type describing the vector as + * well as the prefix of the functions for manipulating it + * @param type the type of the objects contained in the vector + * @param pfnRealloc the memory reallocation function used for expanding the + * vector + * @param pfnDelete the cleanup callback function - signature + * void pfnDelete(type *) + */ +#define RTVEC_DECL_ALLOCATOR_DELETE(name, type, pfnRealloc, pfnDelete) \ + RTVEC_DECL_COMMON(name, type, pfnRealloc) \ + RTVEC_DECLFN_DELETE_ADAPTER_ID(name, type) \ + RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete, \ + name ## DeleteAdapterId) \ + RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete, name ## DeleteAdapterId) + +/** + * Declarator macro - declare a vector type with a cleanup callback to be used + * when elements are dropped from the vector. The callback takes a parameter + * of type @a type, NOT a pointer to @a type. + * @param name the name of the C struct type describing the vector as + * well as the prefix of the functions for manipulating it + * @param type the type of the objects contained in the vector + * @param pfnRealloc the memory reallocation function used for expanding the + * vector + * @param pfnDelete the cleanup callback function - signature + * void pfnDelete(type) + */ +#define RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE(name, type, pfnRealloc, \ + pfnDelete) \ + RTVEC_DECL_COMMON(name, type, pfnRealloc) \ + RTVEC_DECLFN_DELETE_ADAPTER_TO_VALUE(name, type) \ + RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete, \ + name ## DeleteAdapterToValue) \ + RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete, \ + name ## DeleteAdapterToValue) + +/** + * Inline wrapper around RTMemRealloc macro to get a function usable as a + * callback. + */ +DECLINLINE(void *) rtvecReallocDefTag(void *pv, size_t cbNew) +{ + return RTMemRealloc(pv, cbNew); +} + +/** + * Declarator macro - declare a vector type (see @a RTVEC_DECL_ALLOCATOR) + * using RTMemRealloc as a memory allocator + * @param name the name of the C struct type describing the vector as + * well as the prefix of the functions for manipulating it + * @param type the type of the objects contained in the vector + */ +#define RTVEC_DECL(name, type) \ + RTVEC_DECL_ALLOCATOR(name, type, rtvecReallocDefTag) + +/** + * Declarator macro - declare a vector type with a cleanup by pointer callback + * (see @a RTVEC_DECL_ALLOCATOR_DELETE) using RTMemRealloc as a memory + * allocator + * @param name the name of the C struct type describing the vector as + * well as the prefix of the functions for manipulating it + * @param type the type of the objects contained in the vector + * @param pfnDelete the cleanup callback function - signature + * void pfnDelete(type *) + */ +#define RTVEC_DECL_DELETE(name, type, pfnDelete) \ + RTVEC_DECL_ALLOCATOR_DELETE(name, type, rtvecReallocDefTag, pfnDelete) + +/** + * Declarator macro - declare a vector type with a cleanup by value callback + * (see @a RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE) using RTMemRealloc as a memory + * allocator + * @param name the name of the C struct type describing the vector as + * well as the prefix of the functions for manipulating it + * @param type the type of the objects contained in the vector + * @param pfnDelete the cleanup callback function - signature + * void pfnDelete(type) + */ +#define RTVEC_DECL_DELETE_BY_VALUE(name, type, pfnDelete) \ + RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE(name, type, rtvecReallocDefTag, \ + pfnDelete) + +#endif /* ___iprt_vector_h */ diff --git a/include/iprt/vfs.h b/include/iprt/vfs.h new file mode 100644 index 00000000..6eefa01d --- /dev/null +++ b/include/iprt/vfs.h @@ -0,0 +1,934 @@ +/** @file + * IPRT - Virtual Filesystem. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_vfs_h +#define ___iprt_vfs_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/dir.h> +#include <iprt/fs.h> +#include <iprt/handle.h> +#include <iprt/symlink.h> +#include <iprt/sg.h> +#include <iprt/time.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_vfs RTVfs - Virtual Filesystem + * @ingroup grp_rt + * + * The virtual filesystem APIs are intended to make it possible to work on + * container files, file system sub-trees, file system overlays and other custom + * filesystem configurations. It also makes it possible to create filters, like + * automatically gunzipping a tar.gz file before feeding it to the RTTar API for + * unpacking - or wise versa. + * + * The virtual filesystem APIs are intended to mirror the RTDir, RTFile, RTPath + * and RTFs APIs pretty closely so that rewriting a piece of code to work with + * it should be easy. However there are some differences to the way the APIs + * works and the user should heed the documentation. The differences are + * usually motivated by simplification and in some case to make the VFS more + * flexible. + * + * @{ + */ + +/** + * The object type. + */ +typedef enum RTVFSOBJTYPE +{ + /** Invalid type. */ + RTVFSOBJTYPE_INVALID = 0, + /** Pure base object. + * This is returned by the filesystem stream to represent directories, + * devices, fifos and similar that needs to be created. */ + RTVFSOBJTYPE_BASE, + /** Virtual filesystem. */ + RTVFSOBJTYPE_VFS, + /** Filesystem stream. */ + RTVFSOBJTYPE_FS_STREAM, + /** Pure I/O stream. */ + RTVFSOBJTYPE_IO_STREAM, + /** Directory. */ + RTVFSOBJTYPE_DIR, + /** File. */ + RTVFSOBJTYPE_FILE, + /** Symbolic link. */ + RTVFSOBJTYPE_SYMLINK, + /** End of valid object types. */ + RTVFSOBJTYPE_END, + /** Pure I/O stream. */ + RTVFSOBJTYPE_32BIT_HACK = 0x7fffffff +} RTVFSOBJTYPE; +/** Pointer to a VFS object type. */ +typedef RTVFSOBJTYPE *PRTVFSOBJTYPE; + + + +/** @name RTVfsCreate flags + * @{ */ +/** Whether the file system is read-only. */ +#define RTVFS_C_READONLY RT_BIT(0) +/** Whether we the VFS should be thread safe (i.e. automaticaly employ + * locks). */ +#define RTVFS_C_THREAD_SAFE RT_BIT(1) +/** @} */ + +/** + * Creates an empty virtual filesystem. + * + * @returns IPRT status code. + * @param pszName Name, for logging and such. + * @param fFlags Flags, MBZ. + * @param phVfs Where to return the VFS handle. Release the returned + * reference by calling RTVfsRelease. + */ +RTDECL(int) RTVfsCreate(const char *pszName, uint32_t fFlags, PRTVFS phVfs); +RTDECL(uint32_t) RTVfsRetain(RTVFS phVfs); +RTDECL(uint32_t) RTVfsRelease(RTVFS phVfs); +RTDECL(int) RTVfsAttach(RTVFS hVfs, const char *pszMountPoint, uint32_t fFlags, RTVFS hVfsAttach); +RTDECL(int) RTVfsDetach(RTVFS hVfs, const char *pszMountPoint, RTVFS hVfsToDetach, PRTVFS *phVfsDetached); +RTDECL(uint32_t) RTVfsGetAttachmentCount(RTVFS hVfs); +RTDECL(int) RTVfsGetAttachment(RTVFS hVfs, uint32_t iOrdinal, PRTVFS *phVfsAttached, uint32_t *pfFlags, + char *pszMountPoint, size_t cbMountPoint); + +/** + * Checks whether a given range is in use by the virtual filesystem. + * + * @returns IPRT status code. + * @param hVfs VFS handle. + * @param off Start offset to check. + * @param cb Number of bytes to check. + * @param pfUsed Where to store the result. + */ +RTDECL(int) RTVfsIsRangeInUse(RTVFS hVfs, uint64_t off, size_t cb, + bool *pfUsed); + +/** @defgroup grp_vfs_dir VFS Base Object API + * @{ + */ + +/** + * Retains a reference to the VFS base object handle. + * + * @returns New reference count on success, UINT32_MAX on failure. + * @param hVfsObj The VFS base object handle. + */ +RTDECL(uint32_t) RTVfsObjRetain(RTVFSOBJ hVfsObj); + +/** + * Releases a reference to the VFS base handle. + * + * @returns New reference count on success (0 if closed), UINT32_MAX on failure. + * @param hVfsObj The VFS base object handle. + */ +RTDECL(uint32_t) RTVfsObjRelease(RTVFSOBJ hVfsObj); + +/** + * Query information about the object. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the @a enmAddAttr value is not handled by the + * implementation. + * + * @param hVfsObj The VFS object handle. + * @param pObjInfo Where to return the info. + * @param enmAddAttr Which additional attributes should be retrieved. + * @sa RTVfsIoStrmQueryInfo, RTVfsFileQueryInfo, RTFileQueryInfo, + * RTPathQueryInfo + */ +RTDECL(int) RTVfsObjQueryInfo(RTVFSOBJ hVfsObj, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr); + + +/** + * Converts a VFS base object handle to a VFS handle. + * + * @returns Referenced handle on success, NIL on failure. + * @param hVfsObj The VFS base object handle. + */ +RTDECL(RTVFS) RTVfsObjToVfs(RTVFSOBJ hVfsObj); + +/** + * Converts a VFS base object handle to a VFS filesystem stream handle. + * + * @returns Referenced handle on success, NIL on failure. + * @param hVfsObj The VFS base object handle. + */ +RTDECL(RTVFSFSSTREAM) RTVfsObjToFsStream(RTVFSOBJ hVfsObj); + +/** + * Converts a VFS base object handle to a VFS directory handle. + * + * @returns Referenced handle on success, NIL on failure. + * @param hVfsObj The VFS base object handle. + */ +RTDECL(RTVFSDIR) RTVfsObjToDir(RTVFSOBJ hVfsObj); + +/** + * Converts a VFS base object handle to a VFS I/O stream handle. + * + * @returns Referenced handle on success, NIL on failure. + * @param hVfsObj The VFS base object handle. + */ +RTDECL(RTVFSIOSTREAM) RTVfsObjToIoStream(RTVFSOBJ hVfsObj); + +/** + * Converts a VFS base object handle to a VFS file handle. + * + * @returns Referenced handle on success, NIL on failure. + * @param hVfsObj The VFS base object handle. + */ +RTDECL(RTVFSFILE) RTVfsObjToFile(RTVFSOBJ hVfsObj); + +/** + * Converts a VFS base object handle to a VFS symbolic link handle. + * + * @returns Referenced handle on success, NIL on failure. + * @param hVfsObj The VFS base object handle. + */ +RTDECL(RTVFSSYMLINK) RTVfsObjToSymlink(RTVFSOBJ hVfsObj); + + +/** + * Converts a VFS handle to a VFS base object handle. + * + * @returns Referenced handle on success, NIL if the input handle was invalid. + * @param hVfs The VFS handle. + */ +RTDECL(RTVFSOBJ) RTVfsObjFromVfs(RTVFS hVfs); + +/** + * Converts a VFS filesystem stream handle to a VFS base object handle. + * + * @returns Referenced handle on success, NIL if the input handle was invalid. + * @param hVfsFSs The VFS filesystem stream handle. + */ +RTDECL(RTVFSOBJ) RTVfsObjFromFsStream(RTVFSFSSTREAM hVfsFss); + +/** + * Converts a VFS directory handle to a VFS base object handle. + * + * @returns Referenced handle on success, NIL if the input handle was invalid. + * @param hVfsDir The VFS directory handle. + */ +RTDECL(RTVFSOBJ) RTVfsObjFromDir(RTVFSDIR hVfsDir); + +/** + * Converts a VFS I/O stream handle to a VFS base object handle. + * + * @returns Referenced handle on success, NIL if the input handle was invalid. + * @param hVfsIos The VFS I/O stream handle. + */ +RTDECL(RTVFSOBJ) RTVfsObjFromIoStream(RTVFSIOSTREAM hVfsIos); + +/** + * Converts a VFS file handle to a VFS base object handle. + * + * @returns Referenced handle on success, NIL if the input handle was invalid. + * @param hVfsFile The VFS file handle. + */ +RTDECL(RTVFSOBJ) RTVfsObjFromFile(RTVFSFILE hVfsFile); + +/** + * Converts a VFS symbolic link handle to a VFS base object handle. + * + * @returns Referenced handle on success, NIL if the input handle was invalid. + * @param hVfsSym The VFS symbolic link handle. + */ +RTDECL(RTVFSOBJ) RTVfsObjFromSymlink(RTVFSSYMLINK hVfsSym); + +/** @} */ + + +/** @defgroup grp_vfs_fsstream VFS Filesystem Stream API + * + * Filesystem streams are for tar, cpio and similar. Any virtual filesystem can + * be turned into a filesystem stream using RTVfsFsStrmFromVfs. + * + * @{ + */ + +RTDECL(uint32_t) RTVfsFsStrmRetain(RTVFSFSSTREAM hVfsFss); +RTDECL(uint32_t) RTVfsFsStrmRelease(RTVFSFSSTREAM hVfsFss); +RTDECL(int) RTVfsFsStrmQueryInfo(RTVFSFSSTREAM hVfsFss, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr); + +/** + * Gets the next object in the stream. + * + * This call may affect the stream posision of a previously returned object. + * + * The type of object returned here typically boils down to three types: + * - I/O streams (representing files), + * - symbolic links + * - base object + * The base objects represent anything not convered by the two other, i.e. + * directories, device nodes, fifos, sockets and whatnot. The details can be + * queried using RTVfsObjQueryInfo. + * + * That said, absolutely any object except for filesystem stream objects can be + * returned by this call. Any generic code is adviced to just deal with it all. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if a new object was retrieved. + * @retval VERR_EOF when there are no more objects. + * + * @param pvThis The implementation specific directory data. + * @param ppszName Where to return the object name. Must be freed by + * calling RTStrFree. + * @param penmType Where to return the object type. + * @param hVfsObj Where to return the object handle (referenced). + * This must be cast to the desired type before use. + */ +RTDECL(int) RTVfsFsStrmNext(RTVFSFSSTREAM hVfsFss, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj); + +/** @} */ + + +/** @defgroup grp_vfs_dir VFS Directory API + * @{ + */ + +/** + * Retains a reference to the VFS directory handle. + * + * @returns New reference count on success, UINT32_MAX on failure. + * @param hVfsDir The VFS directory handle. + */ +RTDECL(uint32_t) RTVfsDirRetain(RTVFSDIR hVfsDir); + +/** + * Releases a reference to the VFS directory handle. + * + * @returns New reference count on success (0 if closed), UINT32_MAX on failure. + * @param hVfsIos The VFS directory handle. + */ +RTDECL(uint32_t) RTVfsDirRelease(RTVFSDIR hVfsDir); + +/** @} */ + + +/** @defgroup grp_vfs_iostream VFS Symbolic Link API + * + * @remarks The TAR VFS and filesystem stream uses symbolic links for + * describing hard links as well. The users must use RTFS_IS_SYMLINK + * to check if it is a real symlink in those cases. + * + * @remarks Any VFS which is backed by a real file system may be subject to + * races with other processes or threads, so the user may get + * unexpected errors when this happends. This is a bit host specific, + * i.e. it might be prevent on windows if we care. + * + * @{ + */ + + +/** + * Retains a reference to the VFS symbolic link handle. + * + * @returns New reference count on success, UINT32_MAX on failure. + * @param hVfsSym The VFS symbolic link handle. + */ +RTDECL(uint32_t) RTVfsSymlinkRetain(RTVFSSYMLINK hVfsSym); + +/** + * Releases a reference to the VFS symbolic link handle. + * + * @returns New reference count on success (0 if closed), UINT32_MAX on failure. + * @param hVfsSym The VFS symbolic link handle. + */ +RTDECL(uint32_t) RTVfsSymlinkRelease(RTVFSSYMLINK hVfsSym); + +/** + * Query information about the symbolic link. + * + * @returns IPRT status code. + * @param hVfsSym The VFS symbolic link handle. + * @param pObjInfo Where to return the info. + * @param enmAddAttr Which additional attributes should be retrieved. + * + * @sa RTFileQueryInfo, RTPathQueryInfo, RTPathQueryInfoEx + */ +RTDECL(int) RTVfsSymlinkQueryInfo(RTVFSSYMLINK hVfsSym, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr); + +/** + * Set the unix style owner and group. + * + * @returns IPRT status code. + * @param hVfsSym The VFS symbolic link handle. + * @param fMode The new mode bits. + * @param fMask The mask indicating which bits we are changing. + * @sa RTFileSetMode, RTPathSetMode + */ +RTDECL(int) RTVfsSymlinkSetMode(RTVFSSYMLINK hVfsSym, RTFMODE fMode, RTFMODE fMask); + +/** + * Set the timestamps associated with the object. + * + * @returns IPRT status code. + * @param hVfsSym The VFS symbolic link handle. + * @param pAccessTime Pointer to the new access time. NULL if not + * to be changed. + * @param pModificationTime Pointer to the new modifcation time. NULL if + * not to be changed. + * @param pChangeTime Pointer to the new change time. NULL if not to be + * changed. + * @param pBirthTime Pointer to the new time of birth. NULL if not to be + * changed. + * @remarks See RTFileSetTimes for restrictions and behavior imposed by the + * host OS or underlying VFS provider. + * @sa RTFileSetTimes, RTPathSetTimes + */ +RTDECL(int) RTVfsSymlinkSetTimes(RTVFSSYMLINK hVfsSym, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, + PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime); + +/** + * Set the unix style owner and group. + * + * @returns IPRT status code. + * @param hVfsSym The VFS symbolic link handle. + * @param uid The user ID of the new owner. NIL_RTUID if + * unchanged. + * @param gid The group ID of the new owner group. NIL_RTGID if + * unchanged. + * @sa RTFileSetOwner, RTPathSetOwner. + */ +RTDECL(int) RTVfsSymlinkSetOwner(RTVFSSYMLINK hVfsSym, RTUID uid, RTGID gid); + +/** + * Read the symbolic link target. + * + * @returns IPRT status code. + * @param hVfsSym The VFS symbolic link handle. + * @param pszTarget The target buffer. + * @param cbTarget The size of the target buffer. + * @sa RTSymlinkRead + */ +RTDECL(int) RTVfsSymlinkRead(RTVFSSYMLINK hVfsSym, char *pszTarget, size_t cbTarget); + +/** @} */ + + + +/** @defgroup grp_vfs_iostream VFS I/O Stream API + * @{ + */ + +/** + * Create a VFS I/O stream handle from a standard IPRT file handle (RTFILE). + * + * @returns IPRT status code. + * @param hFile The standard IPRT file handle. + * @param fOpen The flags the handle was opened with. Pass 0 to + * have these detected. + * @param fLeaveOpen Whether to leave the handle open when the VFS file + * is released, or to close it (@c false). + * @param phVfsIos Where to return the VFS I/O stream handle. + */ +RTDECL(int) RTVfsIoStrmFromRTFile(RTFILE hFile, uint64_t fOpen, bool fLeaveOpen, PRTVFSIOSTREAM phVfsIos); + +/** + * Create a VFS I/O stream handle from one of the standard handles. + * + * @returns IPRT status code. + * @param enmStdHandle The standard IPRT file handle. + * @param fOpen The flags the handle was opened with. Pass 0 to + * have these detected. + * @param fLeaveOpen Whether to leave the handle open when the VFS file + * is released, or to close it (@c false). + * @param phVfsIos Where to return the VFS I/O stream handle. + */ +RTDECL(int) RTVfsIoStrmFromStdHandle(RTHANDLESTD enmStdHandle, uint64_t fOpen, bool fLeaveOpen, + PRTVFSIOSTREAM phVfsIos); + +/** + * Retains a reference to the VFS I/O stream handle. + * + * @returns New reference count on success, UINT32_MAX on failure. + * @param hVfsIos The VFS I/O stream handle. + */ +RTDECL(uint32_t) RTVfsIoStrmRetain(RTVFSIOSTREAM hVfsIos); + +/** + * Releases a reference to the VFS I/O stream handle. + * + * @returns New reference count on success (0 if closed), UINT32_MAX on failure. + * @param hVfsIos The VFS I/O stream handle. + */ +RTDECL(uint32_t) RTVfsIoStrmRelease(RTVFSIOSTREAM hVfsIos); + +/** + * Convert the VFS I/O stream handle to a VFS file handle. + * + * @returns The VFS file handle on success, this must be released. + * NIL_RTVFSFILE if the I/O stream handle is invalid. + * @param hVfsIos The VFS I/O stream handle. + * @sa RTVfsFileToIoStream + */ +RTDECL(RTVFSFILE) RTVfsIoStrmToFile(RTVFSIOSTREAM hVfsIos); + +/** + * Query information about the I/O stream. + * + * @returns IPRT status code. + * @param hVfsIos The VFS I/O stream handle. + * @param pObjInfo Where to return the info. + * @param enmAddAttr Which additional attributes should be retrieved. + * @sa RTFileQueryInfo + */ +RTDECL(int) RTVfsIoStrmQueryInfo(RTVFSIOSTREAM hVfsIos, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr); + +/** + * Read bytes from the I/O stream. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and the number of bytes read written to @a pcbRead. + * @retval VINF_TRY_AGAIN if @a fBlocking is @c false, @a pcbRead is not NULL, + * and no data was available. @a *pcbRead will be set to 0. + * @retval VINF_EOF when trying to read __beyond__ the end of the stream and + * @a pcbRead is not NULL (it will be set to the number of bytes read, + * or 0 if the end of the stream was reached before this call). + * When the last byte of the read request is the last byte in the + * stream, this status code will not be used. However, VINF_EOF is + * returned when attempting to read 0 bytes while standing at the end + * of the stream. + * @retval VERR_EOF when trying to read __beyond__ the end of the stream and + * @a pcbRead is NULL. + * @retval VERR_ACCESS_DENIED if the stream is not readable. + * + * @param hVfsIos The VFS I/O stream handle. + * @param pvBuf Where to store the read bytes. + * @param cbToRead The number of bytes to read. + * @param fBlocking Whether the call is blocking (@c true) or not. If + * not, the @a pcbRead parameter must not be NULL. + * @param pcbRead Where to always store the number of bytes actually + * read. This can be NULL if @a fBlocking is true. + * @sa RTVfsFileRead, RTFileRead, RTPipeRead, RTPipeReadBlocking, + * RTSocketRead + */ +RTDECL(int) RTVfsIoStrmRead(RTVFSIOSTREAM hVfsIos, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead); +RTDECL(int) RTVfsIoStrmReadAt(RTVFSIOSTREAM hVfsIos, RTFOFF off, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead); + +/** + * Write bytes to the I/O stream. + * + * @returns IPRT status code. + * @retval VERR_ACCESS_DENIED if the stream is not writable. + * + * @param hVfsIos The VFS I/O stream handle. + * @param pvBuf The bytes to write. + * @param cbToWrite The number of bytes to write. + * @param fBlocking Whether the call is blocking (@c true) or not. If + * not, the @a pcbWritten parameter must not be NULL. + * @param pcbRead Where to always store the number of bytes actually + * written. This can be NULL if @a fBlocking is true. + * @sa RTVfsFileWrite, RTFileWrite, RTPipeWrite, RTPipeWriteBlocking, + * RTSocketWrite + */ +RTDECL(int) RTVfsIoStrmWrite(RTVFSIOSTREAM hVfsIos, const void *pvBuf, size_t cbToWrite, bool fBlocking, size_t *pcbWritten); +RTDECL(int) RTVfsIoStrmWriteAt(RTVFSIOSTREAM hVfsIos, RTFOFF off, const void *pvBuf, size_t cbToWrite, bool fBlocking, size_t *pcbWritten); + +/** + * Reads bytes from the I/O stream into a scatter buffer. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and the number of bytes read written to @a pcbRead. + * @retval VINF_TRY_AGAIN if @a fBlocking is @c false, @a pcbRead is not NULL, + * and no data was available. @a *pcbRead will be set to 0. + * @retval VINF_EOF when trying to read __beyond__ the end of the stream and + * @a pcbRead is not NULL (it will be set to the number of bytes read, + * or 0 if the end of the stream was reached before this call). + * When the last byte of the read request is the last byte in the + * stream, this status code will not be used. However, VINF_EOF is + * returned when attempting to read 0 bytes while standing at the end + * of the stream. + * @retval VERR_EOF when trying to read __beyond__ the end of the stream and + * @a pcbRead is NULL. + * @retval VERR_ACCESS_DENIED if the stream is not readable. + * + * @param hVfsIos The VFS I/O stream handle. + * @param pSgBuf Pointer to a scatter buffer descriptor. The number + * of bytes described by the segments is what will be + * attemted read. + * @param fBlocking Whether the call is blocking (@c true) or not. If + * not, the @a pcbRead parameter must not be NULL. + * @param pcbRead Where to always store the number of bytes actually + * read. This can be NULL if @a fBlocking is true. + * @sa RTFileSgRead, RTSocketSgRead, RTPipeRead, RTPipeReadBlocking + */ +RTDECL(int) RTVfsIoStrmSgRead(RTVFSIOSTREAM hVfsIos, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead); + +/** + * Write bytes to the I/O stream from a gather buffer. + * + * @returns IPRT status code. + * @retval VERR_ACCESS_DENIED if the stream is not writable. + * + * @param hVfsIos The VFS I/O stream handle. + * @param pSgBuf Pointer to a gather buffer descriptor. The number + * of bytes described by the segments is what will be + * attemted written. + * @param fBlocking Whether the call is blocking (@c true) or not. If + * not, the @a pcbWritten parameter must not be NULL. + * @param pcbRead Where to always store the number of bytes actually + * written. This can be NULL if @a fBlocking is true. + * @sa RTFileSgWrite, RTSocketSgWrite + */ +RTDECL(int) RTVfsIoStrmSgWrite(RTVFSIOSTREAM hVfsIos, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten); + +/** + * Flush any buffered data to the I/O stream. + * + * @returns IPRT status code. + * @param hVfsIos The VFS I/O stream handle. + * @sa RTVfsFileFlush, RTFileFlush, RTPipeFlush + */ +RTDECL(int) RTVfsIoStrmFlush(RTVFSIOSTREAM hVfsIos); + +/** + * Poll for events. + * + * @returns IPRT status code. + * @param hVfsIos The VFS I/O stream handle. + * @param fEvents The events to poll for (RTPOLL_EVT_XXX). + * @param cMillies How long to wait for event to eventuate. + * @param fIntr Whether the wait is interruptible and can return + * VERR_INTERRUPTED (@c true) or if this condition + * should be hidden from the caller (@c false). + * @param pfRetEvents Where to return the event mask. + * @sa RTVfsFilePoll, RTPollSetAdd, RTPoll, RTPollNoResume. + */ +RTDECL(int) RTVfsIoStrmPoll(RTVFSIOSTREAM hVfsIos, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, + uint32_t *pfRetEvents); +/** + * Tells the current I/O stream position. + * + * @returns Zero or higher - where to return the I/O stream offset. Values + * below zero are IPRT status codes (VERR_XXX). + * @param hVfsIos The VFS I/O stream handle. + * @sa RTFileTell + */ +RTDECL(RTFOFF) RTVfsIoStrmTell(RTVFSIOSTREAM hVfsIos); + +/** + * Skips @a cb ahead in the stream. + * + * @returns IPRT status code. + * @param hVfsIos The VFS I/O stream handle. + * @param cb The number bytes to skip. + */ +RTDECL(int) RTVfsIoStrmSkip(RTVFSIOSTREAM hVfsIos, RTFOFF cb); + +/** + * Fills the stream with @a cb zeros. + * + * @returns IPRT status code. + * @param hVfsIos The VFS I/O stream handle. + * @param cb The number of zero bytes to insert. + */ +RTDECL(int) RTVfsIoStrmZeroFill(RTVFSIOSTREAM hVfsIos, RTFOFF cb); + +/** + * Checks if we're at the end of the I/O stream. + * + * @returns true if at EOS, otherwise false. + * @param hVfsIos The VFS I/O stream handle. + */ +RTDECL(bool) RTVfsIoStrmIsAtEnd(RTVFSIOSTREAM hVfsIos); + +/** + * Process the rest of the stream, checking if it's all valid UTF-8 encoding. + * + * @returns VBox status cod.e + * + * @param hVfsIos The VFS I/O stream handle. + * @param fFlags Flags governing the validation, see + * RTVFS_VALIDATE_UTF8_XXX. + * @param poffError Where to return the error offset. Optional. + */ +RTDECL(int) RTVfsIoStrmValidateUtf8Encoding(RTVFSIOSTREAM hVfsIos, uint32_t fFlags, PRTFOFF poffError); + +/** @defgroup RTVFS_VALIDATE_UTF8_XXX RTVfsIoStrmValidateUtf8Encoding flags. + * @{ */ +/** The text must not contain any null terminator codepoints. */ +#define RTVFS_VALIDATE_UTF8_NO_NULL RT_BIT_32(0) +/** The codepoints must be in the range covered by RTC-3629. */ +#define RTVFS_VALIDATE_UTF8_BY_RTC_3629 RT_BIT_32(1) +/** Mask of valid flags. */ +#define RTVFS_VALIDATE_UTF8_VALID_MASK UINT32_C(0x00000003) +/** @} */ + +/** @} */ + + +/** @defgroup grp_vfs_file VFS File API + * @{ + */ +RTDECL(int) RTVfsFileOpen(RTVFS hVfs, const char *pszFilename, uint64_t fOpen, PRTVFSFILE phVfsFile); + +/** + * Create a VFS file handle from a standard IPRT file handle (RTFILE). + * + * @returns IPRT status code. + * @param hFile The standard IPRT file handle. + * @param fOpen The flags the handle was opened with. Pass 0 to + * have these detected. + * @param fLeaveOpen Whether to leave the handle open when the VFS file + * is released, or to close it (@c false). + * @param phVfsFile Where to return the VFS file handle. + */ +RTDECL(int) RTVfsFileFromRTFile(RTFILE hFile, uint64_t fOpen, bool fLeaveOpen, PRTVFSFILE phVfsFile); +RTDECL(RTHCUINTPTR) RTVfsFileToNative(RTFILE hVfsFile); + +/** + * Convert the VFS file handle to a VFS I/O stream handle. + * + * @returns The VFS I/O stream handle on success, this must be released. + * NIL_RTVFSIOSTREAM if the file handle is invalid. + * @param hVfsFile The VFS file handle. + * @sa RTVfsIoStrmToFile + */ +RTDECL(RTVFSIOSTREAM) RTVfsFileToIoStream(RTVFSFILE hVfsFile); + +/** + * Retains a reference to the VFS file handle. + * + * @returns New reference count on success, UINT32_MAX on failure. + * @param hVfsFile The VFS file handle. + */ +RTDECL(uint32_t) RTVfsFileRetain(RTVFSFILE hVfsFile); + +/** + * Releases a reference to the VFS file handle. + * + * @returns New reference count on success (0 if closed), UINT32_MAX on failure. + * @param hVfsFile The VFS file handle. + */ +RTDECL(uint32_t) RTVfsFileRelease(RTVFSFILE hVfsFile); + +/** + * Query information about the object. + * + * @returns IPRT status code. + * @retval VERR_NOT_SUPPORTED if the @a enmAddAttr value is not handled by the + * implementation. + * + * @param hVfsObj The VFS object handle. + * @param pObjInfo Where to return the info. + * @param enmAddAttr Which additional attributes should be retrieved. + * @sa RTVfsObjQueryInfo, RTVfsFsStrmQueryInfo, RTVfsDirQueryInfo, + * RTVfsIoStrmQueryInfo, RTVfsFileQueryInfo, RTFileQueryInfo, + * RTPathQueryInfo. + */ +RTDECL(int) RTVfsFileQueryInfo(RTVFSFILE hVfsFile, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr); + +/** + * Read bytes from the file at the current position. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS and the number of bytes read written to @a pcbRead. + * @retval VINF_TRY_AGAIN if @a fBlocking is @c false, @a pcbRead is not NULL, + * and no data was available. @a *pcbRead will be set to 0. + * @retval VINF_EOF when trying to read __beyond__ the end of the file and + * @a pcbRead is not NULL (it will be set to the number of bytes read, + * or 0 if the end of the file was reached before this call). + * When the last byte of the read request is the last byte in the + * file, this status code will not be used. However, VINF_EOF is + * returned when attempting to read 0 bytes while standing at the end + * of the file. + * @retval VERR_EOF when trying to read __beyond__ the end of the file and + * @a pcbRead is NULL. + * @retval VERR_ACCESS_DENIED if the file is not readable. + * + * @param hVfsFile The VFS file handle. + * @param pvBuf Where to store the read bytes. + * @param cbToRead The number of bytes to read. + * @param fBlocking Whether the call is blocking (@c true) or not. If + * not, the @a pcbRead parameter must not be NULL. + * @param pcbRead Where to always store the number of bytes actually + * read. This can be NULL if @a fBlocking is true. + * @sa RTVfsIoStrmRead, RTFileRead, RTPipeRead, RTPipeReadBlocking, + * RTSocketRead + */ +RTDECL(int) RTVfsFileRead(RTVFSFILE hVfsFile, void *pvBuf, size_t cbToRead, size_t *pcbRead); +RTDECL(int) RTVfsFileReadAt(RTVFSFILE hVfsFile, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead); + +/** + * Write bytes to the file at the current position. + * + * @returns IPRT status code. + * @retval VERR_ACCESS_DENIED if the file is not writable. + * + * @param hVfsFile The VFS file handle. + * @param pvBuf The bytes to write. + * @param cbToWrite The number of bytes to write. + * @param fBlocking Whether the call is blocking (@c true) or not. If + * not, the @a pcbWritten parameter must not be NULL. + * @param pcbRead Where to always store the number of bytes actually + * written. This can be NULL if @a fBlocking is true. + * @sa RTVfsIoStrmRead, RTFileWrite, RTPipeWrite, RTPipeWriteBlocking, + * RTSocketWrite + */ +RTDECL(int) RTVfsFileWrite(RTVFSFILE hVfsFile, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten); +RTDECL(int) RTVfsFileWriteAt(RTVFSFILE hVfsFile, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten); + +/** + * Flush any buffered data to the file. + * + * @returns IPRT status code. + * @param hVfsFile The VFS file handle. + * @sa RTVfsIoStrmFlush, RTFileFlush, RTPipeFlush + */ +RTDECL(int) RTVfsFileFlush(RTVFSFILE hVfsFile); + +/** + * Poll for events. + * + * @returns IPRT status code. + * @param hVfsFile The VFS file handle. + * @param fEvents The events to poll for (RTPOLL_EVT_XXX). + * @param cMillies How long to wait for event to eventuate. + * @param fIntr Whether the wait is interruptible and can return + * VERR_INTERRUPTED (@c true) or if this condition + * should be hidden from the caller (@c false). + * @param pfRetEvents Where to return the event mask. + * @sa RTVfsIoStrmPoll, RTPollSetAdd, RTPoll, RTPollNoResume. + */ +RTDECL(RTFOFF) RTVfsFilePoll(RTVFSFILE hVfsFile, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, + uint32_t *pfRetEvents); + +/** + * Tells the current file position. + * + * @returns Zero or higher - where to return the file offset. Values + * below zero are IPRT status codes (VERR_XXX). + * @param hVfsFile The VFS file handle. + * @sa RTFileTell, RTVfsIoStrmTell. + */ +RTDECL(RTFOFF) RTVfsFileTell(RTVFSFILE hVfsFile); + +/** + * Changes the current read/write position of a file. + * + * @returns IPRT status code. + * + * @param hVfsFile The VFS file handle. + * @param offSeek The seek offset. + * @param uMethod The seek emthod. + * @param poffActual Where to optionally return the new file offset. + * + * @sa RTFileSeek + */ +RTDECL(int) RTVfsFileSeek(RTVFSFILE hVfsFile, RTFOFF offSeek, uint32_t uMethod, uint64_t *poffActual); + +RTDECL(int) RTVfsFileSetSize(RTVFSFILE hVfsFile, uint64_t cbSize); +RTDECL(int) RTVfsFileGetSize(RTVFSFILE hVfsFile, uint64_t *pcbSize); +RTDECL(RTFOFF) RTVfsFileGetMaxSize(RTVFSFILE hVfsFile); +RTDECL(int) RTVfsFileGetMaxSizeEx(RTVFSFILE hVfsFile, PRTFOFF pcbMax); + +/** @} */ + + +/** @defgroup grp_vfs_misc VFS Miscellaneous + * @{ + */ + +/** + * Memorizes the I/O stream as a file backed by memory. + * + * @returns VBox status code. + * + * @param hVfsIos The VFS I/O stream to memorize. This will be read + * to the end on success, on failure its position is + * undefined. + * @param fFlags A combination of RTFILE_O_READ and RTFILE_O_WRITE. + * @param phVfsFile Where to return the handle to the memory file on + * success. + */ +RTDECL(int) RTVfsMemorizeIoStreamAsFile(RTVFSIOSTREAM hVfsIos, uint32_t fFlags, PRTVFSFILE phVfsFile); + + +/** + * Pumps data from one I/O stream to another. + * + * The data is read in chunks from @a hVfsIosSrc and written to @a hVfsIosDst + * until @hVfsIosSrc indicates end of stream. + * + * @returns IPRT status code + * + * @param hVfsIosSrc The input stream. + * @param hVfsIosDst The output stream. + * @param cbBufHint Hints at a good temporary buffer size, pass 0 if + * clueless. + */ +RTDECL(int) RTVfsUtilPumpIoStreams(RTVFSIOSTREAM hVfsIosSrc, RTVFSIOSTREAM hVfsIosDst, size_t cbBufHint); + +/** @} */ + + +/** @defgroup grp_rt_vfs_chain VFS Chains + * + * VFS chains is for doing pipe like things with VFS objects from the command + * line. Imagine you want to cat the readme.gz of an ISO you could do + * something like: + * RTCat :iprtvfs:vfs(isofs,./mycd.iso)|ios(open,readme.gz)|ios(gunzip) + * or + * RTCat :iprtvfs:ios(isofs,./mycd.iso,/readme.gz)|ios(gunzip) + * + * The "isofs", "open" and "gunzip" bits in the above examples are chain + * element providers registered with IPRT. See RTVFSCHAINELEMENTREG for how + * these works. + * + * @{ */ + +/** The path prefix used to identify an VFS chain specification. */ +#define RTVFSCHAIN_SPEC_PREFIX ":iprtvfs:" + +RTDECL(int) RTVfsChainOpenVfs( const char *pszSpec, PRTVFS phVfs, const char **ppszError); +RTDECL(int) RTVfsChainOpenFsStream( const char *pszSpec, PRTVFSFSSTREAM phVfsFss, const char **ppszError); +RTDECL(int) RTVfsChainOpenDir( const char *pszSpec, uint64_t fOpen, PRTVFSDIR phVfsDir, const char **ppszError); +RTDECL(int) RTVfsChainOpenFile( const char *pszSpec, uint64_t fOpen, PRTVFSFILE phVfsFile, const char **ppszError); +RTDECL(int) RTVfsChainOpenSymlink( const char *pszSpec, PRTVFSSYMLINK phVfsSym, const char **ppszError); +RTDECL(int) RTVfsChainOpenIoStream( const char *pszSpec, uint64_t fOpen, PRTVFSIOSTREAM phVfsIos, const char **ppszError); + +/** + * Tests if the given string is a chain specification or not. + * + * @returns true if it is, false if it isn't. + * @param pszSpec The alleged chain spec. + */ +RTDECL(bool) RTVfsChainIsSpec(const char *pszSpec); + +/** @} */ + + +/** @} */ + +RT_C_DECLS_END + +#endif /* !___iprt_vfs_h */ + diff --git a/include/iprt/vfslowlevel.h b/include/iprt/vfslowlevel.h new file mode 100644 index 00000000..d5208cf4 --- /dev/null +++ b/include/iprt/vfslowlevel.h @@ -0,0 +1,1236 @@ +/** @file + * IPRT - Virtual Filesystem. + */ + +/* + * Copyright (C) 2010 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. + */ + +#ifndef ___iprt_vfslowlevel_h +#define ___iprt_vfslowlevel_h + +#include <iprt/vfs.h> +#include <iprt/err.h> +#include <iprt/list.h> +#include <iprt/param.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_vfs_lowlevel RTVfs - Low-level Interface. + * @ingroup grp_rt_vfs + * @{ + */ + + +/** @name VFS Lock Abstraction + * @todo This should be moved somewhere else as it is of general use. + * @{ */ + +/** + * VFS lock types. + */ +typedef enum RTVFSLOCKTYPE +{ + /** Invalid lock type. */ + RTVFSLOCKTYPE_INVALID = 0, + /** Read write semaphore. */ + RTVFSLOCKTYPE_RW, + /** Fast mutex semaphore (critical section in ring-3). */ + RTVFSLOCKTYPE_FASTMUTEX, + /** Full fledged mutex semaphore. */ + RTVFSLOCKTYPE_MUTEX, + /** The end of valid lock types. */ + RTVFSLOCKTYPE_END, + /** The customary 32-bit type hack. */ + RTVFSLOCKTYPE_32BIT_HACK = 0x7fffffff +} RTVFSLOCKTYPE; + +/** VFS lock handle. */ +typedef struct RTVFSLOCKINTERNAL *RTVFSLOCK; +/** Pointer to a VFS lock handle. */ +typedef RTVFSLOCK *PRTVFSLOCK; +/** Nil VFS lock handle. */ +#define NIL_RTVFSLOCK ((RTVFSLOCK)~(uintptr_t)0) + +/** Special handle value for creating a new read/write semaphore based lock. */ +#define RTVFSLOCK_CREATE_RW ((RTVFSLOCK)~(uintptr_t)1) +/** Special handle value for creating a new fast mutex semaphore based lock. */ +#define RTVFSLOCK_CREATE_FASTMUTEX ((RTVFSLOCK)~(uintptr_t)2) +/** Special handle value for creating a new mutex semaphore based lock. */ +#define RTVFSLOCK_CREATE_MUTEX ((RTVFSLOCK)~(uintptr_t)3) + +/** + * Retains a reference to the VFS lock handle. + * + * @returns New reference count on success, UINT32_MAX on failure. + * @param hLock The VFS lock handle. + */ +RTDECL(uint32_t) RTVfsLockRetain(RTVFSLOCK hLock); + +/** + * Releases a reference to the VFS lock handle. + * + * @returns New reference count on success (0 if closed), UINT32_MAX on failure. + * @param hLock The VFS lock handle. + */ +RTDECL(uint32_t) RTVfsLockRelease(RTVFSLOCK hLock); + +/** + * Gets the lock type. + * + * @returns The lock type on success, RTVFSLOCKTYPE_INVALID if the handle is + * not valid. + * @param hLock The lock handle. + */ +RTDECL(RTVFSLOCKTYPE) RTVfsLockGetType(RTVFSLOCK hLock); + + + +RTDECL(void) RTVfsLockAcquireReadSlow(RTVFSLOCK hLock); +RTDECL(void) RTVfsLockReleaseReadSlow(RTVFSLOCK hLock); +RTDECL(void) RTVfsLockAcquireWriteSlow(RTVFSLOCK hLock); +RTDECL(void) RTVfsLockReleaseWriteSlow(RTVFSLOCK hLock); + +/** + * Acquire a read lock. + * + * @param hLock The lock handle, can be NIL. + */ +DECLINLINE(void) RTVfsLockAcquireRead(RTVFSLOCK hLock) +{ + if (hLock != NIL_RTVFSLOCK) + RTVfsLockAcquireReadSlow(hLock); +} + + +/** + * Release a read lock. + * + * @param hLock The lock handle, can be NIL. + */ +DECLINLINE(void) RTVfsLockReleaseRead(RTVFSLOCK hLock) +{ + if (hLock != NIL_RTVFSLOCK) + RTVfsLockReleaseReadSlow(hLock); +} + + +/** + * Acquire a write lock. + * + * @param hLock The lock handle, can be NIL. + */ +DECLINLINE(void) RTVfsLockAcquireWrite(RTVFSLOCK hLock) +{ + if (hLock != NIL_RTVFSLOCK) + RTVfsLockAcquireWriteSlow(hLock); +} + + +/** + * Release a write lock. + * + * @param hLock The lock handle, can be NIL. + */ +DECLINLINE(void) RTVfsLockReleaseWrite(RTVFSLOCK hLock) +{ + if (hLock != NIL_RTVFSLOCK) + RTVfsLockReleaseWriteSlow(hLock); +} + +/** @} */ + +/** + * The VFS operations. + */ +typedef struct RTVFSOPS +{ + /** The structure version (RTVFSOPS_VERSION). */ + uint32_t uVersion; + /** The virtual file system feature mask. */ + uint32_t fFeatures; + /** The name of the operations. */ + const char *pszName; + + /** + * Destructor. + * + * @param pvThis The implementation specific data. + */ + DECLCALLBACKMEMBER(void, pfnDestroy)(void *pvThis); + + /** + * Opens the root directory. + * + * @returns IPRT status code. + * @param pvThis The implementation specific data. + * @param phVfsDir Where to return the handle to the root directory. + */ + DECLCALLBACKMEMBER(int, pfnOpenRoot)(void *pvThis, PRTVFSDIR phVfsDir); + + /** + * Checks whether a given range in the underlying medium + * is in use by the virtual filesystem. + * + * @returns IPRT status code. + * @param pvThis The implementation specific data. + * @param off Start offset to check. + * @param cb Number of bytes to check. + * @param pfUsed Where to store whether the given range is in use. + */ + DECLCALLBACKMEMBER(int, pfnIsRangeInUse)(void *pvThis, RTFOFF off, size_t cb, + bool *pfUsed); + + /** @todo There will be more methods here to optimize opening and + * querying. */ + +#if 0 + /** + * Optional entry point for optimizing path traversal within the file system. + * + * @returns IPRT status code. + * @param pvThis The implementation specific data. + * @param pszPath The path to resolve. + * @param poffPath The current path offset on input, what we've + * traversed to on successful return. + * @param phVfs??? Return handle to what we've traversed. + * @param p??? Return other stuff... + */ + DECLCALLBACKMEMBER(int, pfnTraverse)(void *pvThis, const char *pszPath, size_t *poffPath, PRTVFS??? phVfs?, ???* p???); +#endif + + /** Marks the end of the structure (RTVFSOPS_VERSION). */ + uintptr_t uEndMarker; +} RTVFSOPS; +/** Pointer to constant VFS operations. */ +typedef RTVFSOPS const *PCRTVFSOPS; + +/** The RTVFSOPS structure version. */ +#define RTVFSOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x0f,1,0) + +/** @name RTVFSOPS::fFeatures + * @{ */ +/** The VFS supports attaching other systems. */ +#define RTVFSOPS_FEAT_ATTACH RT_BIT_32(0) +/** @} */ + +/** + * Creates a new VFS handle. + * + * @returns IPRT status code + * @param pVfs Ops The VFS operations. + * @param cbInstance The size of the instance data. + * @param hVfs The VFS handle to associate this VFS with. + * NIL_VFS is ok. + * @param hLock Handle to a custom lock to be used with the new + * object. The reference is consumed. NIL and + * special lock handles are fine. + * @param phVfs Where to return the new handle. + * @param ppvInstance Where to return the pointer to the instance data + * (size is @a cbInstance). + */ +RTDECL(int) RTVfsNew(PCRTVFSOPS pVfsOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock, + PRTVFS phVfs, void **ppvInstance); + +/** + * The basis for all virtual file system objects except RTVFS. + */ +typedef struct RTVFSOBJOPS +{ + /** The structure version (RTVFSOBJOPS_VERSION). */ + uint32_t uVersion; + /** The object type for type introspection. */ + RTVFSOBJTYPE enmType; + /** The name of the operations. */ + const char *pszName; + + /** + * Close the object. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + */ + DECLCALLBACKMEMBER(int, pfnClose)(void *pvThis); + + /** + * Get information about the file. + * + * @returns IPRT status code. See RTVfsObjQueryInfo. + * @param pvThis The implementation specific file data. + * @param pObjInfo Where to return the object info on success. + * @param enmAddAttr Which set of additional attributes to request. + * @sa RTVfsObjQueryInfo, RTFileQueryInfo, RTPathQueryInfo + */ + DECLCALLBACKMEMBER(int, pfnQueryInfo)(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr); + + /** Marks the end of the structure (RTVFSOBJOPS_VERSION). */ + uintptr_t uEndMarker; +} RTVFSOBJOPS; +/** Pointer to constant VFS object operations. */ +typedef RTVFSOBJOPS const *PCRTVFSOBJOPS; + +/** The RTVFSOBJOPS structure version. */ +#define RTVFSOBJOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x1f,1,0) + + +/** + * Creates a new VFS base object handle. + * + * @returns IPRT status code + * @param pObjOps The base object operations. + * @param cbInstance The size of the instance data. + * @param hVfs The VFS handle to associate this base object + * with. NIL_VFS is ok. + * @param hLock Handle to a custom lock to be used with the new + * object. The reference is consumed. NIL and + * special lock handles are fine. + * @param phVfsFss Where to return the new handle. + * @param ppvInstance Where to return the pointer to the instance data + * (size is @a cbInstance). + */ +RTDECL(int) RTVfsNewBaseObj(PCRTVFSOBJOPS pObjOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock, + PRTVFSOBJ phVfsObj, void **ppvInstance); + + +/** + * Additional operations for setting object attributes. + */ +typedef struct RTVFSOBJSETOPS +{ + /** The structure version (RTVFSOBJSETOPS_VERSION). */ + uint32_t uVersion; + /** The offset to the RTVFSOBJOPS structure. */ + int32_t offObjOps; + + /** + * Set the unix style owner and group. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param fMode The new mode bits. + * @param fMask The mask indicating which bits we are + * changing. + * @sa RTFileSetMode + */ + DECLCALLBACKMEMBER(int, pfnSetMode)(void *pvThis, RTFMODE fMode, RTFMODE fMask); + + /** + * Set the timestamps associated with the object. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param pAccessTime Pointer to the new access time. NULL if not + * to be changed. + * @param pModificationTime Pointer to the new modifcation time. NULL if + * not to be changed. + * @param pChangeTime Pointer to the new change time. NULL if not + * to be changed. + * @param pBirthTime Pointer to the new time of birth. NULL if + * not to be changed. + * @remarks See RTFileSetTimes for restrictions and behavior imposed by the + * host OS or underlying VFS provider. + * @sa RTFileSetTimes + */ + DECLCALLBACKMEMBER(int, pfnSetTimes)(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, + PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime); + + /** + * Set the unix style owner and group. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param uid The user ID of the new owner. NIL_RTUID if + * unchanged. + * @param gid The group ID of the new owner group. NIL_RTGID if + * unchanged. + * @sa RTFileSetOwner + */ + DECLCALLBACKMEMBER(int, pfnSetOwner)(void *pvThis, RTUID uid, RTGID gid); + + /** Marks the end of the structure (RTVFSOBJSETOPS_VERSION). */ + uintptr_t uEndMarker; +} RTVFSOBJSETOPS; +/** Pointer to const object attribute setter operations. */ +typedef RTVFSOBJSETOPS const *PCRTVFSOBJSETOPS; + +/** The RTVFSOBJSETOPS structure version. */ +#define RTVFSOBJSETOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x2f,1,0) + + +/** + * The filesystem stream operations. + * + * @extends RTVFSOBJOPS + */ +typedef struct RTVFSFSSTREAMOPS +{ + /** The basic object operation. */ + RTVFSOBJOPS Obj; + /** The structure version (RTVFSFSSTREAMOPS_VERSION). */ + uint32_t uVersion; + /** Reserved field, MBZ. */ + uint32_t fReserved; + + /** + * Gets the next object in the stream. + * + * @returns IPRT status code. + * @retval VINF_SUCCESS if a new object was retrieved. + * @retval VERR_EOF when there are no more objects. + * @param pvThis The implementation specific directory data. + * @param ppszName Where to return the object name. Must be freed by + * calling RTStrFree. + * @param penmType Where to return the object type. + * @param hVfsObj Where to return the object handle (referenced). + * This must be cast to the desired type before use. + * @sa RTVfsFsStrmNext + */ + DECLCALLBACKMEMBER(int, pfnNext)(void *pvThis, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj); + + /** Marks the end of the structure (RTVFSFSSTREAMOPS_VERSION). */ + uintptr_t uEndMarker; +} RTVFSFSSTREAMOPS; +/** Pointer to const object attribute setter operations. */ +typedef RTVFSFSSTREAMOPS const *PCRTVFSFSSTREAMOPS; + +/** The RTVFSFSSTREAMOPS structure version. */ +#define RTVFSFSSTREAMOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x3f,1,0) + + +/** + * Creates a new VFS filesystem stream handle. + * + * @returns IPRT status code + * @param pFsStreamOps The filesystem stream operations. + * @param cbInstance The size of the instance data. + * @param hVfs The VFS handle to associate this filesystem + * stream with. NIL_VFS is ok. + * @param hLock Handle to a custom lock to be used with the new + * object. The reference is consumed. NIL and + * special lock handles are fine. + * @param phVfsFss Where to return the new handle. + * @param ppvInstance Where to return the pointer to the instance data + * (size is @a cbInstance). + */ +RTDECL(int) RTVfsNewFsStream(PCRTVFSFSSTREAMOPS pFsStreamOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock, + PRTVFSFSSTREAM phVfsFss, void **ppvInstance); + + +/** + * The directory operations. + * + * @extends RTVFSOBJOPS + * @extends RTVFSOBJSETOPS + */ +typedef struct RTVFSDIROPS +{ + /** The basic object operation. */ + RTVFSOBJOPS Obj; + /** The structure version (RTVFSDIROPS_VERSION). */ + uint32_t uVersion; + /** Reserved field, MBZ. */ + uint32_t fReserved; + /** The object setter operations. */ + RTVFSOBJSETOPS ObjSet; + + /** + * Opens a directory entry for traversal purposes. + * + * Method which sole purpose is helping the path traversal. Only one of + * the three output variables will be set, the others will left untouched + * (caller sets them to NIL). + * + * @returns IPRT status code. + * @retval VERR_PATH_NOT_FOUND if @a pszEntry was not found. + * @param pvThis The implementation specific directory data. + * @param pszEntry The name of the directory entry to remove. + * @param phVfsDir If not NULL and it is a directory, open it and + * return the handle here. + * @param phVfsSymlink If not NULL and it is a symbolic link, open it + * and return the handle here. + * @param phVfsMounted If not NULL and it is a mounted VFS directory, + * reference it and return the handle here. + * @todo Should com dir, symlinks and mount points using some common + * ancestor "class". + */ + DECLCALLBACKMEMBER(int, pfnTraversalOpen)(void *pvThis, const char *pszEntry, PRTVFSDIR phVfsDir, + PRTVFSSYMLINK phVfsSymlink, PRTVFS phVfsMounted); + + /** + * Open or create a file. + * + * @returns IPRT status code. + * @param pvThis The implementation specific directory data. + * @param pszFilename The name of the immediate file to open or create. + * @param fOpen The open flags (RTFILE_O_XXX). + * @param phVfsFile Where to return the thandle to the opened file. + * @sa RTFileOpen. + */ + DECLCALLBACKMEMBER(int, pfnOpenFile)(void *pvThis, const char *pszFilename, uint32_t fOpen, PRTVFSFILE phVfsFile); + + /** + * Open an existing subdirectory. + * + * @returns IPRT status code. + * @param pvThis The implementation specific directory data. + * @param pszSubDir The name of the immediate subdirectory to open. + * @param phVfsDir Where to return the handle to the opened directory. + * @sa RTDirOpen. + */ + DECLCALLBACKMEMBER(int, pfnOpenDir)(void *pvThis, const char *pszSubDir, PRTVFSDIR phVfsDir); + + /** + * Creates a new subdirectory. + * + * @returns IPRT status code. + * @param pvThis The implementation specific directory data. + * @param pszSubDir The name of the immediate subdirectory to create. + * @param fMode The mode mask of the new directory. + * @param phVfsDir Where to optionally return the handle to the newly + * create directory. + * @sa RTDirCreate. + */ + DECLCALLBACKMEMBER(int, pfnCreateDir)(void *pvThis, const char *pszSubDir, RTFMODE fMode, PRTVFSDIR phVfsDir); + + /** + * Opens an existing symbolic link. + * + * @returns IPRT status code. + * @param pvThis The implementation specific directory data. + * @param pszSymlink The name of the immediate symbolic link to open. + * @param phVfsSymlink Where to optionally return the handle to the + * newly create symbolic link. + * @sa RTSymlinkCreate. + */ + DECLCALLBACKMEMBER(int, pfnOpenSymlink)(void *pvThis, const char *pszSymlink, PRTVFSSYMLINK phVfsSymlink); + + /** + * Creates a new symbolic link. + * + * @returns IPRT status code. + * @param pvThis The implementation specific directory data. + * @param pszSymlink The name of the immediate symbolic link to create. + * @param pszTarget The symbolic link target. + * @param enmType The symbolic link type. + * @param phVfsSymlink Where to optionally return the handle to the + * newly create symbolic link. + * @sa RTSymlinkCreate. + */ + DECLCALLBACKMEMBER(int, pfnCreateSymlink)(void *pvThis, const char *pszSymlink, const char *pszTarget, + RTSYMLINKTYPE enmType, PRTVFSSYMLINK phVfsSymlink); + + /** + * Removes a directory entry. + * + * @returns IPRT status code. + * @param pvThis The implementation specific directory data. + * @param pszEntry The name of the directory entry to remove. + * @param fType If non-zero, this restricts the type of the entry to + * the object type indicated by the mask + * (RTFS_TYPE_XXX). + * @sa RTFileRemove, RTDirRemove, RTSymlinkRemove. + */ + DECLCALLBACKMEMBER(int, pfnUnlinkEntry)(void *pvThis, const char *pszEntry, RTFMODE fType, PRTVFSDIR phVfsDir); + + /** + * Rewind the directory stream so that the next read returns the first + * entry. + * + * @returns IPRT status code. + * @param pvThis The implementation specific directory data. + */ + DECLCALLBACKMEMBER(int, pfnRewindDir)(void *pvThis); + + /** + * Rewind the directory stream so that the next read returns the first + * entry. + * + * @returns IPRT status code. + * @param pvThis The implementation specific directory data. + * @param pDirEntry Output buffer. + * @param pcbDirEntry Complicated, see RTDirReadEx. + * @param enmAddAttr Which set of additional attributes to request. + * @sa RTDirReadEx + */ + DECLCALLBACKMEMBER(int, pfnReadDir)(void *pvThis, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAddAttr); + + /** Marks the end of the structure (RTVFSDIROPS_VERSION). */ + uintptr_t uEndMarker; +} RTVFSDIROPS; +/** Pointer to const directory operations. */ +typedef RTVFSDIROPS const *PCRTVFSDIROPS; +/** The RTVFSDIROPS structure version. */ +#define RTVFSDIROPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x4f,1,0) + + +/** + * The symbolic link operations. + * + * @extends RTVFSOBJOPS + * @extends RTVFSOBJSETOPS + */ +typedef struct RTVFSSYMLINKOPS +{ + /** The basic object operation. */ + RTVFSOBJOPS Obj; + /** The structure version (RTVFSSYMLINKOPS_VERSION). */ + uint32_t uVersion; + /** Reserved field, MBZ. */ + uint32_t fReserved; + /** The object setter operations. */ + RTVFSOBJSETOPS ObjSet; + + /** + * Read the symbolic link target. + * + * @returns IPRT status code. + * @param pvThis The implementation specific symbolic link data. + * @param pszTarget The target buffer. + * @param cbTarget The size of the target buffer. + * @sa RTSymlinkRead + */ + DECLCALLBACKMEMBER(int, pfnRead)(void *pvThis, char *pszTarget, size_t cbTarget); + + /** Marks the end of the structure (RTVFSSYMLINKOPS_VERSION). */ + uintptr_t uEndMarker; +} RTVFSSYMLINKOPS; +/** Pointer to const symbolic link operations. */ +typedef RTVFSSYMLINKOPS const *PCRTVFSSYMLINKOPS; +/** The RTVFSSYMLINKOPS structure version. */ +#define RTVFSSYMLINKOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x5f,1,0) + + +/** + * Creates a new VFS symlink handle. + * + * @returns IPRT status code + * @param pSymlinkOps The symlink operations. + * @param cbInstance The size of the instance data. + * @param hVfs The VFS handle to associate this symlink object + * with. NIL_VFS is ok. + * @param hLock Handle to a custom lock to be used with the new + * object. The reference is consumed. NIL and + * special lock handles are fine. + * @param phVfsSym Where to return the new handle. + * @param ppvInstance Where to return the pointer to the instance data + * (size is @a cbInstance). + */ +RTDECL(int) RTVfsNewSymlink(PCRTVFSSYMLINKOPS pSymlinkOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock, + PRTVFSSYMLINK phVfsSym, void **ppvInstance); + + +/** + * The basis for all I/O objects (files, pipes, sockets, devices, ++). + * + * @extends RTVFSOBJOPS + */ +typedef struct RTVFSIOSTREAMOPS +{ + /** The basic object operation. */ + RTVFSOBJOPS Obj; + /** The structure version (RTVFSIOSTREAMOPS_VERSION). */ + uint32_t uVersion; + /** Feature field. */ + uint32_t fFeatures; + + /** + * Reads from the file/stream. + * + * @returns IPRT status code. See RTVfsIoStrmRead. + * @param pvThis The implementation specific file data. + * @param off Where to read at, -1 for the current position. + * @param pSgBuf Gather buffer describing the bytes that are to be + * written. + * @param fBlocking If @c true, the call is blocking, if @c false it + * should not block. + * @param pcbRead Where return the number of bytes actually read. + * This is set it 0 by the caller. If NULL, try read + * all and fail if incomplete. + * @sa RTVfsIoStrmRead, RTVfsIoStrmSgRead, RTVfsFileRead, + * RTVfsFileReadAt, RTFileRead, RTFileReadAt. + */ + DECLCALLBACKMEMBER(int, pfnRead)(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead); + + /** + * Writes to the file/stream. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param off Where to start wrinting, -1 for the current + * position. + * @param pSgBuf Gather buffers describing the bytes that are to be + * written. + * @param fBlocking If @c true, the call is blocking, if @c false it + * should not block. + * @param pcbWritten Where to return the number of bytes actually + * written. This is set it 0 by the caller. If + * NULL, try write it all and fail if incomplete. + * @sa RTFileWrite, RTFileWriteAt. + */ + DECLCALLBACKMEMBER(int, pfnWrite)(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten); + + /** + * Flushes any pending data writes to the stream. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @sa RTFileFlush. + */ + DECLCALLBACKMEMBER(int, pfnFlush)(void *pvThis); + + /** + * Poll for events. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param fEvents The events to poll for (RTPOLL_EVT_XXX). + * @param cMillies How long to wait for event to eventuate. + * @param fIntr Whether the wait is interruptible and can return + * VERR_INTERRUPTED (@c true) or if this condition + * should be hidden from the caller (@c false). + * @param pfRetEvents Where to return the event mask. + * @sa RTPollSetAdd, RTPoll, RTPollNoResume. + */ + DECLCALLBACKMEMBER(int, pfnPollOne)(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, + uint32_t *pfRetEvents); + + /** + * Tells the current file/stream position. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param poffActual Where to return the actual offset. + * @sa RTFileTell + */ + DECLCALLBACKMEMBER(int, pfnTell)(void *pvThis, PRTFOFF poffActual); + + /** + * Skips @a cb ahead in the stream. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param cb The number bytes to skip. + * @remarks This is optional and can be NULL. + */ + DECLCALLBACKMEMBER(int, pfnSkip)(void *pvThis, RTFOFF cb); + + /** + * Fills the stream with @a cb zeros. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param cb The number of zero bytes to insert. + * @remarks This is optional and can be NULL. + */ + DECLCALLBACKMEMBER(int, pfnZeroFill)(void *pvThis, RTFOFF cb); + + /** Marks the end of the structure (RTVFSIOSTREAMOPS_VERSION). */ + uintptr_t uEndMarker; +} RTVFSIOSTREAMOPS; +/** Pointer to const I/O stream operations. */ +typedef RTVFSIOSTREAMOPS const *PCRTVFSIOSTREAMOPS; + +/** The RTVFSIOSTREAMOPS structure version. */ +#define RTVFSIOSTREAMOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x6f,1,0) + +/** @name RTVFSIOSTREAMOPS::fFeatures + * @{ */ +/** No scatter gather lists, thank you. */ +#define RTVFSIOSTREAMOPS_FEAT_NO_SG RT_BIT_32(0) +/** Mask of the valid I/O stream feature flags. */ +#define RTVFSIOSTREAMOPS_FEAT_VALID_MASK UINT32_C(0x00000001) +/** @} */ + + +/** + * Creates a new VFS I/O stream handle. + * + * @returns IPRT status code + * @param pIoStreamOps The I/O stream operations. + * @param cbInstance The size of the instance data. + * @param fOpen The open flags. The minimum is the access mask. + * @param hVfs The VFS handle to associate this I/O stream + * with. NIL_VFS is ok. + * @param hLock Handle to a custom lock to be used with the new + * object. The reference is consumed. NIL and + * special lock handles are fine. + * @param phVfsIos Where to return the new handle. + * @param ppvInstance Where to return the pointer to the instance data + * (size is @a cbInstance). + */ +RTDECL(int) RTVfsNewIoStream(PCRTVFSIOSTREAMOPS pIoStreamOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTVFSLOCK hLock, + PRTVFSIOSTREAM phVfsIos, void **ppvInstance); + + +/** + * Gets the private data of an I/O stream. + * + * @returns Pointer to the private data. NULL if the handle is invalid in some + * way. + * @param hVfsIos The I/O stream handle. + * @param pIoStreamOps The I/O stream operations. This servers as a + * sort of password. + */ +RTDECL(void *) RTVfsIoStreamToPrivate(RTVFSIOSTREAM hVfsIos, PCRTVFSIOSTREAMOPS pIoStreamOps); + + +/** + * The file operations. + * + * @extends RTVFSIOSTREAMOPS + * @extends RTVFSOBJSETOPS + */ +typedef struct RTVFSFILEOPS +{ + /** The I/O stream and basis object operations. */ + RTVFSIOSTREAMOPS Stream; + /** The structure version (RTVFSFILEOPS_VERSION). */ + uint32_t uVersion; + /** Reserved field, MBZ. */ + uint32_t fReserved; + /** The object setter operations. */ + RTVFSOBJSETOPS ObjSet; + + /** + * Changes the current file position. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param offSeek The offset to seek. + * @param uMethod The seek method, i.e. what the seek is relative to. + * @param poffActual Where to return the actual offset. + * @sa RTFileSeek + */ + DECLCALLBACKMEMBER(int, pfnSeek)(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual); + + /** + * Get the current file/stream size. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param pcbFile Where to store the current file size. + * @sa RTFileGetSize + */ + DECLCALLBACKMEMBER(int, pfnQuerySize)(void *pvThis, uint64_t *pcbFile); + + /** @todo There will be more methods here. */ + + /** Marks the end of the structure (RTVFSFILEOPS_VERSION). */ + uintptr_t uEndMarker; +} RTVFSFILEOPS; +/** Pointer to const file operations. */ +typedef RTVFSFILEOPS const *PCRTVFSFILEOPS; + +/** The RTVFSFILEOPS structure version. */ +#define RTVFSFILEOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x7f,1,0) + +/** + * Creates a new VFS file handle. + * + * @returns IPRT status code + * @param pFileOps The file operations. + * @param cbInstance The size of the instance data. + * @param fOpen The open flags. The minimum is the access mask. + * @param hVfs The VFS handle to associate this file with. + * NIL_VFS is ok. + * @param hLock Handle to a custom lock to be used with the new + * object. The reference is consumed. NIL and + * special lock handles are fine. + * @param phVfsFile Where to return the new handle. + * @param ppvInstance Where to return the pointer to the instance data + * (size is @a cbInstance). + */ +RTDECL(int) RTVfsNewFile(PCRTVFSFILEOPS pFileOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTVFSLOCK hLock, + PRTVFSFILE phVfsFile, void **ppvInstance); + + +/** @defgroup grp_rt_vfs_ll_util VFS Utility APIs + * @{ */ + +/** + * Parsed path. + */ +typedef struct RTVFSPARSEDPATH +{ + /** The length of the path in szCopy. */ + uint16_t cch; + /** The number of path components. */ + uint16_t cComponents; + /** Set if the path ends with slash, indicating that it's a directory + * reference and not a file reference. The slash has been removed from + * the copy. */ + bool fDirSlash; + /** The offset where each path component starts, i.e. the char after the + * slash. The array has cComponents + 1 entries, where the final one is + * cch + 1 so that one can always terminate the current component by + * szPath[aoffComponent[i] - 1] = '\0'. */ + uint16_t aoffComponents[RTPATH_MAX / 2 + 1]; + /** A normalized copy of the path. + * Reserve some extra space so we can be more relaxed about overflow + * checks and terminator paddings, especially when recursing. */ + char szPath[RTPATH_MAX]; +} RTVFSPARSEDPATH; +/** Pointer to a parsed path. */ +typedef RTVFSPARSEDPATH *PRTVFSPARSEDPATH; + +/** The max accepted path length. + * This must be a few chars shorter than RTVFSPARSEDPATH::szPath because we + * use two terminators and wish be a little bit lazy with checking. */ +#define RTVFSPARSEDPATH_MAX (RTPATH_MAX - 4) + +/** + * Appends @a pszPath (relative) to the already parsed path @a pPath. + * + * @retval VINF_SUCCESS + * @retval VERR_FILENAME_TOO_LONG + * @retval VERR_INTERNAL_ERROR_4 + * @param pPath The parsed path to append @a pszPath onto. + * This is both input and output. + * @param pszPath The path to append. This must be relative. + * @param piRestartComp The component to restart parsing at. This is + * input/output. The input does not have to be + * within the valid range. Optional. + */ +RTDECL(int) RTVfsParsePathAppend(PRTVFSPARSEDPATH pPath, const char *pszPath, uint16_t *piRestartComp); + +/** + * Parses a path. + * + * @retval VINF_SUCCESS + * @retval VERR_FILENAME_TOO_LONG + * @param pPath Where to store the parsed path. + * @param pszPath The path to parse. Absolute or relative to @a + * pszCwd. + * @param pszCwd The current working directory. Must be + * absolute. + */ +RTDECL(int) RTVfsParsePath(PRTVFSPARSEDPATH pPath, const char *pszPath, const char *pszCwd); + +/** + * Same as RTVfsParsePath except that it allocates a temporary buffer. + * + * @retval VINF_SUCCESS + * @retval VERR_NO_TMP_MEMORY + * @retval VERR_FILENAME_TOO_LONG + * @param pszPath The path to parse. Absolute or relative to @a + * pszCwd. + * @param pszCwd The current working directory. Must be + * absolute. + * @param ppPath Where to store the pointer to the allocated + * buffer containing the parsed path. This must + * be freed by calling RTVfsParsePathFree. NULL + * will be stored on failured. + */ +RTDECL(int) RTVfsParsePathA(const char *pszPath, const char *pszCwd, PRTVFSPARSEDPATH *ppPath); + +/** + * Frees a buffer returned by RTVfsParsePathA. + * + * @param pPath The parsed path buffer to free. NULL is fine. + */ +RTDECL(void) RTVfsParsePathFree(PRTVFSPARSEDPATH pPath); + +/** + * Dummy implementation of RTVFSIOSTREAMOPS::pfnPollOne. + * + * This handles the case where there is no chance any events my be raised and + * all that is required is to wait according to the parameters. + * + * @returns IPRT status code. + * @param pvThis The implementation specific file data. + * @param fEvents The events to poll for (RTPOLL_EVT_XXX). + * @param cMillies How long to wait for event to eventuate. + * @param fIntr Whether the wait is interruptible and can return + * VERR_INTERRUPTED (@c true) or if this condition + * should be hidden from the caller (@c false). + * @param pfRetEvents Where to return the event mask. + * @sa RTVFSIOSTREAMOPS::pfnPollOne, RTPollSetAdd, RTPoll, RTPollNoResume. + */ +RTDECL(int) RTVfsUtilDummyPollOne(uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, uint32_t *pfRetEvents); + +/** @} */ + + +/** @defgroup grp_rt_vfs_lowlevel_chain VFS Chains + * @ref grp_rt_vfs_chain + * @{ + */ + + +/** + * Chain element input actions. + */ +typedef enum RTVFSCHAINACTION +{ + /** Invalid action. */ + RTVFSCHAINACTION_INVALID = 0, + /** No action (start of the chain). */ + RTVFSCHAINACTION_NONE, + /** Passive filtering (expressed by pipe symbol). */ + RTVFSCHAINACTION_PASSIVE, + /** Push filtering (expressed by redirection-out symbol). */ + RTVFSCHAINACTION_PUSH, + /** The end of the valid actions. */ + RTVFSCHAINACTION_END, + /** Make sure it's a 32-bit type. */ + RTVFSCHAINACTION_32BIT_HACK = 0x7fffffff +} RTVFSCHAINACTION; + + +/** + * VFS chain element specification. + */ +typedef struct RTVFSCHAINELEMSPEC +{ + /** The provider name. */ + char *pszProvider; + /** The input type. */ + RTVFSOBJTYPE enmTypeIn; + /** The output type. */ + RTVFSOBJTYPE enmTypeOut; + /** The action to take (or not). */ + RTVFSCHAINACTION enmAction; + /** The number of arguments. */ + uint32_t cArgs; + /** Arguments. */ + char **papszArgs; +} RTVFSCHAINELEMSPEC; +/** Pointer to a chain element specification. */ +typedef RTVFSCHAINELEMSPEC *PRTVFSCHAINELEMSPEC; +/** Pointer to a const chain element specification. */ +typedef RTVFSCHAINELEMSPEC const *PCRTVFSCHAINELEMSPEC; + + +/** + * Parsed VFS chain specification. + */ +typedef struct RTVFSCHAINSPEC +{ + /** The action element, UINT32_MAX if none. + * Currently we only support one action element (RTVFSCHAINACTION_PASSIVE + * is not considered). */ + uint32_t iActionElement; + /** The number of elements. */ + uint32_t cElements; + /** The elements. */ + PRTVFSCHAINELEMSPEC paElements; +} RTVFSCHAINSPEC; +/** Pointer to a parsed VFS chain specification. */ +typedef RTVFSCHAINSPEC *PRTVFSCHAINSPEC; +/** Pointer to a const, parsed VFS chain specification. */ +typedef RTVFSCHAINSPEC const *PCRTVFSCHAINSPEC; + + +/** + * A chain element provider registration record. + */ +typedef struct RTVFSCHAINELEMENTREG +{ + /** The version (RTVFSCHAINELEMENTREG_VERSION). */ + uint32_t uVersion; + /** Reserved, MBZ. */ + uint32_t fReserved; + /** The provider name (unique). */ + const char *pszName; + /** For chaining the providers. */ + RTLISTNODE ListEntry; + + /** + * Create a VFS from the given chain element specficiation. + * + * @returns IPRT status code. + * @param pSpec The chain element specification. + * @param phVfs Where to returned the VFS handle. + */ + DECLCALLBACKMEMBER(int, pfnOpenVfs)( PCRTVFSCHAINELEMSPEC pSpec, PRTVFS phVfs); + + /** + * Open a directory from the given chain element specficiation. + * + * @returns IPRT status code. + * @param pSpec The chain element specification. + * @param phVfsDir Where to returned the directory handle. + */ + DECLCALLBACKMEMBER(int, pfnOpenDir)( PCRTVFSCHAINELEMSPEC pSpec, PRTVFSDIR phVfsDir); + + /** + * Open a file from the given chain element specficiation. + * + * @returns IPRT status code. + * @param pSpec The chain element specification. + * @param fOpen The open flag. Can be zero and the + * specification may modify it. + * @param phVfsFile Where to returned the file handle. + */ + DECLCALLBACKMEMBER(int, pfnOpenFile)( PCRTVFSCHAINELEMSPEC pSpec, uint32_t fOpen, PRTVFSFILE phVfsFile); + + /** + * Open a symlink from the given chain element specficiation. + * + * @returns IPRT status code. + * @param pSpec The chain element specification. + * @param phVfsSym Where to returned the symlink handle. + */ + DECLCALLBACKMEMBER(int, pfnOpenSymlink)( PCRTVFSCHAINELEMSPEC pSpec, PRTVFSSYMLINK phVfsSym); + + /** + * Open a I/O stream from the given chain element specficiation. + * + * @returns IPRT status code. + * @param pSpec The chain element specification. + * @param fOpen The open flag. Can be zero and the + * specification may modify it. + * @param phVfsIos Where to returned the I/O stream handle. + */ + DECLCALLBACKMEMBER(int, pfnOpenIoStream)(PCRTVFSCHAINELEMSPEC pSpec, uint32_t fOpen, PRTVFSIOSTREAM phVfsIos); + + /** + * Open a filesystem stream from the given chain element specficiation. + * + * @returns IPRT status code. + * @param pSpec The chain element specification. + * @param phVfsFss Where to returned the filesystem stream handle. + */ + DECLCALLBACKMEMBER(int, pfnOpenFsStream)(PCRTVFSCHAINELEMSPEC pSpec, PRTVFSFSSTREAM phVfsFss); + + /** End marker (RTVFSCHAINELEMENTREG_VERSION). */ + uintptr_t uEndMarker; +} RTVFSCHAINELEMENTREG; +/** Pointer to a VFS chain element registration record. */ +typedef RTVFSCHAINELEMENTREG *PRTVFSCHAINELEMENTREG; +/** Pointer to a const VFS chain element registration record. */ +typedef RTVFSCHAINELEMENTREG const *PCRTVFSCHAINELEMENTREG; + +/** The VFS chain element registration record version number. */ +#define RTVFSCHAINELEMENTREG_VERSION RT_MAKE_U32_FROM_U8(0xff, 0x7f, 1, 0) + + +/** + * Parses the specification. + * + * @returns IPRT status code. + * @param pszSpec The specification string to parse. + * @param fFlags Flags, see RTVFSCHAIN_PF_XXX. + * @param enmLeadingAction The only allowed leading action type. + * @param enmTrailingAction The only allowed trailing action type. + * @param ppSpec Where to return the pointer to the parsed + * specification. This must be freed by calling + * RTVfsChainSpecFree. Will always be set (unless + * invalid parameters.) + * @param ppszError On failure, this will point at the error + * location in @a pszSpec. Optional. + */ +RTDECL(int) RTVfsChainSpecParse(const char *pszSpec, uint32_t fFlags, RTVFSCHAINACTION enmLeadingAction, + RTVFSCHAINACTION enmTrailingAction, + PRTVFSCHAINSPEC *ppSpec, const char **ppszError); + +/** @name RTVfsChainSpecParse + * @{ */ +/** No real action is permitted, i.e. only passive filtering (aka pipe). */ +#define RTVFSCHAIN_PF_NO_REAL_ACTION RT_BIT_32(0) +/** The specified leading action is optional. */ +#define RTVFSCHAIN_PF_LEADING_ACTION_OPTIONAL RT_BIT_32(1) +/** The specified trailing action is optional. */ +#define RTVFSCHAIN_PF_TRAILING_ACTION_OPTIONAL RT_BIT_32(2) +/** Mask of valid flags. */ +#define RTVFSCHAIN_PF_VALID_MASK UINT32_C(0x00000007) +/** @}*/ + +/** + * Frees a parsed chain specification. + * + * @param pSpec What RTVfsChainSpecParse returned. NULL is + * quietly ignored. + */ +RTDECL(void) RTVfsChainSpecFree(PRTVFSCHAINSPEC pSpec); + +/** + * Registers a chain element provider. + * + * @returns IPRT status code + * @param pRegRec The registration record. + * @param fFromCtor Indicates where we're called from. + */ +RTDECL(int) RTVfsChainElementRegisterProvider(PRTVFSCHAINELEMENTREG pRegRec, bool fFromCtor); + +/** + * Deregisters a chain element provider. + * + * @returns IPRT status code + * @param pRegRec The registration record. + * @param fFromDtor Indicates where we're called from. + */ +RTDECL(int) RTVfsChainElementDeregisterProvider(PRTVFSCHAINELEMENTREG pRegRec, bool fFromDtor); + + +/** @def RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER + * Automatically registers a chain element provider using a global constructor + * and destructor hack. + * + * @param pRegRec Pointer to the registration record. + * @param name Some unique variable name prefix. + */ + +#ifdef __cplusplus +/** + * Class used for registering a VFS chain element provider. + */ +class RTVfsChainElementAutoRegisterHack +{ +private: + /** The registration record, NULL if registration failed. */ + PRTVFSCHAINELEMENTREG m_pRegRec; + +public: + RTVfsChainElementAutoRegisterHack(PRTVFSCHAINELEMENTREG a_pRegRec) + : m_pRegRec(a_pRegRec) + { + int rc = RTVfsChainElementRegisterProvider(m_pRegRec, true); + if (RT_FAILURE(rc)) + m_pRegRec = NULL; + } + + ~RTVfsChainElementAutoRegisterHack() + { + RTVfsChainElementDeregisterProvider(m_pRegRec, true); + m_pRegRec = NULL; + } +}; + +# define RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(pRegRec, name) \ + static RTVfsChainElementAutoRegisterHack name ## AutoRegistrationHack(pRegRec) + +#else +# define RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(pRegRec, name) \ + extern void *name ## AutoRegistrationHack = \ + &Sorry_but_RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER_does_not_work_in_c_source_files +#endif + + +/** @} */ + + +/** @} */ + +RT_C_DECLS_END + +#endif /* !___iprt_vfslowlevel_h */ + diff --git a/include/iprt/x86.h b/include/iprt/x86.h new file mode 100644 index 00000000..22b0b952 --- /dev/null +++ b/include/iprt/x86.h @@ -0,0 +1,3194 @@ +/** @file + * IPRT - X86 and AMD64 Structures and Definitions. + * + * @note x86.mac is generated from this file by running 'kmk incs' in the root. + */ + +/* + * Copyright (C) 2006-2012 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. + */ + +#ifndef ___iprt_x86_h +#define ___iprt_x86_h + +#ifndef VBOX_FOR_DTRACE_LIB +# include <iprt/types.h> +# include <iprt/assert.h> +#else +# pragma D depends_on library vbox-types.d +#endif + +/* Workaround for Solaris sys/regset.h defining CS, DS */ +#ifdef RT_OS_SOLARIS +# undef CS +# undef DS +#endif + +/** @defgroup grp_rt_x86 x86 Types and Definitions + * @ingroup grp_rt + * @{ + */ + +#ifndef VBOX_FOR_DTRACE_LIB +/** + * EFLAGS Bits. + */ +typedef struct X86EFLAGSBITS +{ + /** Bit 0 - CF - Carry flag - Status flag. */ + unsigned u1CF : 1; + /** Bit 1 - 1 - Reserved flag. */ + unsigned u1Reserved0 : 1; + /** Bit 2 - PF - Parity flag - Status flag. */ + unsigned u1PF : 1; + /** Bit 3 - 0 - Reserved flag. */ + unsigned u1Reserved1 : 1; + /** Bit 4 - AF - Auxiliary carry flag - Status flag. */ + unsigned u1AF : 1; + /** Bit 5 - 0 - Reserved flag. */ + unsigned u1Reserved2 : 1; + /** Bit 6 - ZF - Zero flag - Status flag. */ + unsigned u1ZF : 1; + /** Bit 7 - SF - Signed flag - Status flag. */ + unsigned u1SF : 1; + /** Bit 8 - TF - Trap flag - System flag. */ + unsigned u1TF : 1; + /** Bit 9 - IF - Interrupt flag - System flag. */ + unsigned u1IF : 1; + /** Bit 10 - DF - Direction flag - Control flag. */ + unsigned u1DF : 1; + /** Bit 11 - OF - Overflow flag - Status flag. */ + unsigned u1OF : 1; + /** Bit 12-13 - IOPL - I/O prvilege level flag - System flag. */ + unsigned u2IOPL : 2; + /** Bit 14 - NT - Nested task flag - System flag. */ + unsigned u1NT : 1; + /** Bit 15 - 0 - Reserved flag. */ + unsigned u1Reserved3 : 1; + /** Bit 16 - RF - Resume flag - System flag. */ + unsigned u1RF : 1; + /** Bit 17 - VM - Virtual 8086 mode - System flag. */ + unsigned u1VM : 1; + /** Bit 18 - AC - Alignment check flag - System flag. Works with CR0.AM. */ + unsigned u1AC : 1; + /** Bit 19 - VIF - Virtual interrupt flag - System flag. */ + unsigned u1VIF : 1; + /** Bit 20 - VIP - Virtual interrupt pending flag - System flag. */ + unsigned u1VIP : 1; + /** Bit 21 - ID - CPUID flag - System flag. If this responds to flipping CPUID is supported. */ + unsigned u1ID : 1; + /** Bit 22-31 - 0 - Reserved flag. */ + unsigned u10Reserved4 : 10; +} X86EFLAGSBITS; +/** Pointer to EFLAGS bits. */ +typedef X86EFLAGSBITS *PX86EFLAGSBITS; +/** Pointer to const EFLAGS bits. */ +typedef const X86EFLAGSBITS *PCX86EFLAGSBITS; +#endif /* !VBOX_FOR_DTRACE_LIB */ + +/** + * EFLAGS. + */ +typedef union X86EFLAGS +{ + /** The plain unsigned view. */ + uint32_t u; +#ifndef VBOX_FOR_DTRACE_LIB + /** The bitfield view. */ + X86EFLAGSBITS Bits; +#endif + /** The 8-bit view. */ + uint8_t au8[4]; + /** The 16-bit view. */ + uint16_t au16[2]; + /** The 32-bit view. */ + uint32_t au32[1]; + /** The 32-bit view. */ + uint32_t u32; +} X86EFLAGS; +/** Pointer to EFLAGS. */ +typedef X86EFLAGS *PX86EFLAGS; +/** Pointer to const EFLAGS. */ +typedef const X86EFLAGS *PCX86EFLAGS; + +/** + * RFLAGS (32 upper bits are reserved). + */ +typedef union X86RFLAGS +{ + /** The plain unsigned view. */ + uint64_t u; +#ifndef VBOX_FOR_DTRACE_LIB + /** The bitfield view. */ + X86EFLAGSBITS Bits; +#endif + /** The 8-bit view. */ + uint8_t au8[8]; + /** The 16-bit view. */ + uint16_t au16[4]; + /** The 32-bit view. */ + uint32_t au32[2]; + /** The 64-bit view. */ + uint64_t au64[1]; + /** The 64-bit view. */ + uint64_t u64; +} X86RFLAGS; +/** Pointer to RFLAGS. */ +typedef X86RFLAGS *PX86RFLAGS; +/** Pointer to const RFLAGS. */ +typedef const X86RFLAGS *PCX86RFLAGS; + + +/** @name EFLAGS + * @{ + */ +/** Bit 0 - CF - Carry flag - Status flag. */ +#define X86_EFL_CF RT_BIT(0) +/** Bit 1 - Reserved, reads as 1. */ +#define X86_EFL_1 RT_BIT(1) +/** Bit 2 - PF - Parity flag - Status flag. */ +#define X86_EFL_PF RT_BIT(2) +/** Bit 4 - AF - Auxiliary carry flag - Status flag. */ +#define X86_EFL_AF RT_BIT(4) +/** Bit 6 - ZF - Zero flag - Status flag. */ +#define X86_EFL_ZF RT_BIT(6) +/** Bit 7 - SF - Signed flag - Status flag. */ +#define X86_EFL_SF RT_BIT(7) +/** Bit 8 - TF - Trap flag - System flag. */ +#define X86_EFL_TF RT_BIT(8) +/** Bit 9 - IF - Interrupt flag - System flag. */ +#define X86_EFL_IF RT_BIT(9) +/** Bit 10 - DF - Direction flag - Control flag. */ +#define X86_EFL_DF RT_BIT(10) +/** Bit 11 - OF - Overflow flag - Status flag. */ +#define X86_EFL_OF RT_BIT(11) +/** Bit 12-13 - IOPL - I/O prvilege level flag - System flag. */ +#define X86_EFL_IOPL (RT_BIT(12) | RT_BIT(13)) +/** Bit 14 - NT - Nested task flag - System flag. */ +#define X86_EFL_NT RT_BIT(14) +/** Bit 16 - RF - Resume flag - System flag. */ +#define X86_EFL_RF RT_BIT(16) +/** Bit 17 - VM - Virtual 8086 mode - System flag. */ +#define X86_EFL_VM RT_BIT(17) +/** Bit 18 - AC - Alignment check flag - System flag. Works with CR0.AM. */ +#define X86_EFL_AC RT_BIT(18) +/** Bit 19 - VIF - Virtual interrupt flag - System flag. */ +#define X86_EFL_VIF RT_BIT(19) +/** Bit 20 - VIP - Virtual interrupt pending flag - System flag. */ +#define X86_EFL_VIP RT_BIT(20) +/** Bit 21 - ID - CPUID flag - System flag. If this responds to flipping CPUID is supported. */ +#define X86_EFL_ID RT_BIT(21) +/** IOPL shift. */ +#define X86_EFL_IOPL_SHIFT 12 +/** The the IOPL level from the flags. */ +#define X86_EFL_GET_IOPL(efl) (((efl) >> X86_EFL_IOPL_SHIFT) & 3) +/** Bits restored by popf */ +#define X86_EFL_POPF_BITS (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT | X86_EFL_AC | X86_EFL_ID) +/** @} */ + + +/** CPUID Feature information - ECX. + * CPUID query with EAX=1. + */ +#ifndef VBOX_FOR_DTRACE_LIB +typedef struct X86CPUIDFEATECX +{ + /** Bit 0 - SSE3 - Supports SSE3 or not. */ + unsigned u1SSE3 : 1; + /** Bit 1 - PCLMULQDQ. */ + unsigned u1PCLMULQDQ : 1; + /** Bit 2 - DS Area 64-bit layout. */ + unsigned u1DTE64 : 1; + /** Bit 3 - MONITOR - Supports MONITOR/MWAIT. */ + unsigned u1Monitor : 1; + /** Bit 4 - CPL-DS - CPL Qualified Debug Store. */ + unsigned u1CPLDS : 1; + /** Bit 5 - VMX - Virtual Machine Technology. */ + unsigned u1VMX : 1; + /** Bit 6 - SMX: Safer Mode Extensions. */ + unsigned u1SMX : 1; + /** Bit 7 - EST - Enh. SpeedStep Tech. */ + unsigned u1EST : 1; + /** Bit 8 - TM2 - Terminal Monitor 2. */ + unsigned u1TM2 : 1; + /** Bit 9 - SSSE3 - Supplemental Streaming SIMD Extensions 3. */ + unsigned u1SSSE3 : 1; + /** Bit 10 - CNTX-ID - L1 Context ID. */ + unsigned u1CNTXID : 1; + /** Bit 11 - Reserved. */ + unsigned u1Reserved1 : 1; + /** Bit 12 - FMA. */ + unsigned u1FMA : 1; + /** Bit 13 - CX16 - CMPXCHG16B. */ + unsigned u1CX16 : 1; + /** Bit 14 - xTPR Update Control. Processor supports changing IA32_MISC_ENABLES[bit 23]. */ + unsigned u1TPRUpdate : 1; + /** Bit 15 - PDCM - Perf/Debug Capability MSR. */ + unsigned u1PDCM : 1; + /** Bit 16 - Reserved. */ + unsigned u1Reserved2 : 1; + /** Bit 17 - PCID - Process-context identifiers. */ + unsigned u1PCID : 1; + /** Bit 18 - Direct Cache Access. */ + unsigned u1DCA : 1; + /** Bit 19 - SSE4_1 - Supports SSE4_1 or not. */ + unsigned u1SSE4_1 : 1; + /** Bit 20 - SSE4_2 - Supports SSE4_2 or not. */ + unsigned u1SSE4_2 : 1; + /** Bit 21 - x2APIC. */ + unsigned u1x2APIC : 1; + /** Bit 22 - MOVBE - Supports MOVBE. */ + unsigned u1MOVBE : 1; + /** Bit 23 - POPCNT - Supports POPCNT. */ + unsigned u1POPCNT : 1; + /** Bit 24 - TSC-Deadline. */ + unsigned u1TSCDEADLINE : 1; + /** Bit 25 - AES. */ + unsigned u1AES : 1; + /** Bit 26 - XSAVE - Supports XSAVE. */ + unsigned u1XSAVE : 1; + /** Bit 27 - OSXSAVE - Supports OSXSAVE. */ + unsigned u1OSXSAVE : 1; + /** Bit 28 - AVX - Supports AVX instruction extensions. */ + unsigned u1AVX : 1; + /** Bit 29 - 30 - Reserved */ + unsigned u2Reserved3 : 2; + /** Bit 31 - Hypervisor present (we're a guest). */ + unsigned u1HVP : 1; +} X86CPUIDFEATECX; +#else /* VBOX_FOR_DTRACE_LIB */ +typedef uint32_t X86CPUIDFEATECX; +#endif /* VBOX_FOR_DTRACE_LIB */ +/** Pointer to CPUID Feature Information - ECX. */ +typedef X86CPUIDFEATECX *PX86CPUIDFEATECX; +/** Pointer to const CPUID Feature Information - ECX. */ +typedef const X86CPUIDFEATECX *PCX86CPUIDFEATECX; + + +/** CPUID Feature Information - EDX. + * CPUID query with EAX=1. + */ +#ifndef VBOX_FOR_DTRACE_LIB /* DTrace different (brain-dead from a C pov) bitfield implementation */ +typedef struct X86CPUIDFEATEDX +{ + /** Bit 0 - FPU - x87 FPU on Chip. */ + unsigned u1FPU : 1; + /** Bit 1 - VME - Virtual 8086 Mode Enhancements. */ + unsigned u1VME : 1; + /** Bit 2 - DE - Debugging extensions. */ + unsigned u1DE : 1; + /** Bit 3 - PSE - Page Size Extension. */ + unsigned u1PSE : 1; + /** Bit 4 - TSC - Time Stamp Counter. */ + unsigned u1TSC : 1; + /** Bit 5 - MSR - Model Specific Registers RDMSR and WRMSR Instructions. */ + unsigned u1MSR : 1; + /** Bit 6 - PAE - Physical Address Extension. */ + unsigned u1PAE : 1; + /** Bit 7 - MCE - Machine Check Exception. */ + unsigned u1MCE : 1; + /** Bit 8 - CX8 - CMPXCHG8B instruction. */ + unsigned u1CX8 : 1; + /** Bit 9 - APIC - APIC On-Chip. */ + unsigned u1APIC : 1; + /** Bit 10 - Reserved. */ + unsigned u1Reserved1 : 1; + /** Bit 11 - SEP - SYSENTER and SYSEXIT. */ + unsigned u1SEP : 1; + /** Bit 12 - MTRR - Memory Type Range Registers. */ + unsigned u1MTRR : 1; + /** Bit 13 - PGE - PTE Global Bit. */ + unsigned u1PGE : 1; + /** Bit 14 - MCA - Machine Check Architecture. */ + unsigned u1MCA : 1; + /** Bit 15 - CMOV - Conditional Move Instructions. */ + unsigned u1CMOV : 1; + /** Bit 16 - PAT - Page Attribute Table. */ + unsigned u1PAT : 1; + /** Bit 17 - PSE-36 - 36-bit Page Size Extention. */ + unsigned u1PSE36 : 1; + /** Bit 18 - PSN - Processor Serial Number. */ + unsigned u1PSN : 1; + /** Bit 19 - CLFSH - CLFLUSH Instruction. */ + unsigned u1CLFSH : 1; + /** Bit 20 - Reserved. */ + unsigned u1Reserved2 : 1; + /** Bit 21 - DS - Debug Store. */ + unsigned u1DS : 1; + /** Bit 22 - ACPI - Thermal Monitor and Software Controlled Clock Facilities. */ + unsigned u1ACPI : 1; + /** Bit 23 - MMX - Intel MMX 'Technology'. */ + unsigned u1MMX : 1; + /** Bit 24 - FXSR - FXSAVE and FXRSTOR Instructions. */ + unsigned u1FXSR : 1; + /** Bit 25 - SSE - SSE Support. */ + unsigned u1SSE : 1; + /** Bit 26 - SSE2 - SSE2 Support. */ + unsigned u1SSE2 : 1; + /** Bit 27 - SS - Self Snoop. */ + unsigned u1SS : 1; + /** Bit 28 - HTT - Hyper-Threading Technology. */ + unsigned u1HTT : 1; + /** Bit 29 - TM - Thermal Monitor. */ + unsigned u1TM : 1; + /** Bit 30 - Reserved - . */ + unsigned u1Reserved3 : 1; + /** Bit 31 - PBE - Pending Break Enabled. */ + unsigned u1PBE : 1; +} X86CPUIDFEATEDX; +#else /* VBOX_FOR_DTRACE_LIB */ +typedef uint32_t X86CPUIDFEATEDX; +#endif /* VBOX_FOR_DTRACE_LIB */ +/** Pointer to CPUID Feature Information - EDX. */ +typedef X86CPUIDFEATEDX *PX86CPUIDFEATEDX; +/** Pointer to const CPUID Feature Information - EDX. */ +typedef const X86CPUIDFEATEDX *PCX86CPUIDFEATEDX; + +/** @name CPUID Vendor information. + * CPUID query with EAX=0. + * @{ + */ +#define X86_CPUID_VENDOR_INTEL_EBX 0x756e6547 /* Genu */ +#define X86_CPUID_VENDOR_INTEL_ECX 0x6c65746e /* ntel */ +#define X86_CPUID_VENDOR_INTEL_EDX 0x49656e69 /* ineI */ + +#define X86_CPUID_VENDOR_AMD_EBX 0x68747541 /* Auth */ +#define X86_CPUID_VENDOR_AMD_ECX 0x444d4163 /* cAMD */ +#define X86_CPUID_VENDOR_AMD_EDX 0x69746e65 /* enti */ + +#define X86_CPUID_VENDOR_VIA_EBX 0x746e6543 /* Cent */ +#define X86_CPUID_VENDOR_VIA_ECX 0x736c7561 /* auls */ +#define X86_CPUID_VENDOR_VIA_EDX 0x48727561 /* aurH */ +/** @} */ + + +/** @name CPUID Feature information. + * CPUID query with EAX=1. + * @{ + */ +/** ECX Bit 0 - SSE3 - Supports SSE3 or not. */ +#define X86_CPUID_FEATURE_ECX_SSE3 RT_BIT(0) +/** ECX Bit 1 - PCLMUL - PCLMULQDQ support (for AES-GCM). */ +#define X86_CPUID_FEATURE_ECX_PCLMUL RT_BIT(1) +/** ECX Bit 2 - DTES64 - DS Area 64-bit Layout. */ +#define X86_CPUID_FEATURE_ECX_DTES64 RT_BIT(2) +/** ECX Bit 3 - MONITOR - Supports MONITOR/MWAIT. */ +#define X86_CPUID_FEATURE_ECX_MONITOR RT_BIT(3) +/** ECX Bit 4 - CPL-DS - CPL Qualified Debug Store. */ +#define X86_CPUID_FEATURE_ECX_CPLDS RT_BIT(4) +/** ECX Bit 5 - VMX - Virtual Machine Technology. */ +#define X86_CPUID_FEATURE_ECX_VMX RT_BIT(5) +/** ECX Bit 6 - SMX - Safer Mode Extensions. */ +#define X86_CPUID_FEATURE_ECX_SMX RT_BIT(6) +/** ECX Bit 7 - EST - Enh. SpeedStep Tech. */ +#define X86_CPUID_FEATURE_ECX_EST RT_BIT(7) +/** ECX Bit 8 - TM2 - Terminal Monitor 2. */ +#define X86_CPUID_FEATURE_ECX_TM2 RT_BIT(8) +/** ECX Bit 9 - SSSE3 - Supplemental Streaming SIMD Extensions 3. */ +#define X86_CPUID_FEATURE_ECX_SSSE3 RT_BIT(9) +/** ECX Bit 10 - CNTX-ID - L1 Context ID. */ +#define X86_CPUID_FEATURE_ECX_CNTXID RT_BIT(10) +/** ECX Bit 12 - FMA. */ +#define X86_CPUID_FEATURE_ECX_FMA RT_BIT(12) +/** ECX Bit 13 - CX16 - CMPXCHG16B. */ +#define X86_CPUID_FEATURE_ECX_CX16 RT_BIT(13) +/** ECX Bit 14 - xTPR Update Control. Processor supports changing IA32_MISC_ENABLES[bit 23]. */ +#define X86_CPUID_FEATURE_ECX_TPRUPDATE RT_BIT(14) +/** ECX Bit 15 - PDCM - Perf/Debug Capability MSR. */ +#define X86_CPUID_FEATURE_ECX_PDCM RT_BIT(15) +/** ECX Bit 17 - PCID - Process-context identifiers. */ +#define X86_CPUID_FEATURE_ECX_PCID RT_BIT(17) +/** ECX Bit 18 - DCA - Direct Cache Access. */ +#define X86_CPUID_FEATURE_ECX_DCA RT_BIT(18) +/** ECX Bit 19 - SSE4_1 - Supports SSE4_1 or not. */ +#define X86_CPUID_FEATURE_ECX_SSE4_1 RT_BIT(19) +/** ECX Bit 20 - SSE4_2 - Supports SSE4_2 or not. */ +#define X86_CPUID_FEATURE_ECX_SSE4_2 RT_BIT(20) +/** ECX Bit 21 - x2APIC support. */ +#define X86_CPUID_FEATURE_ECX_X2APIC RT_BIT(21) +/** ECX Bit 22 - MOVBE instruction. */ +#define X86_CPUID_FEATURE_ECX_MOVBE RT_BIT(22) +/** ECX Bit 23 - POPCNT instruction. */ +#define X86_CPUID_FEATURE_ECX_POPCNT RT_BIT(23) +/** ECX Bir 24 - TSC-Deadline. */ +#define X86_CPUID_FEATURE_ECX_TSCDEADL RT_BIT(24) +/** ECX Bit 25 - AES instructions. */ +#define X86_CPUID_FEATURE_ECX_AES RT_BIT(25) +/** ECX Bit 26 - XSAVE instruction. */ +#define X86_CPUID_FEATURE_ECX_XSAVE RT_BIT(26) +/** ECX Bit 27 - OSXSAVE instruction. */ +#define X86_CPUID_FEATURE_ECX_OSXSAVE RT_BIT(27) +/** ECX Bit 28 - AVX. */ +#define X86_CPUID_FEATURE_ECX_AVX RT_BIT(28) +/** ECX Bit 31 - Hypervisor Present (software only). */ +#define X86_CPUID_FEATURE_ECX_HVP RT_BIT(31) + + +/** Bit 0 - FPU - x87 FPU on Chip. */ +#define X86_CPUID_FEATURE_EDX_FPU RT_BIT(0) +/** Bit 1 - VME - Virtual 8086 Mode Enhancements. */ +#define X86_CPUID_FEATURE_EDX_VME RT_BIT(1) +/** Bit 2 - DE - Debugging extensions. */ +#define X86_CPUID_FEATURE_EDX_DE RT_BIT(2) +/** Bit 3 - PSE - Page Size Extension. */ +#define X86_CPUID_FEATURE_EDX_PSE RT_BIT(3) +/** Bit 4 - TSC - Time Stamp Counter. */ +#define X86_CPUID_FEATURE_EDX_TSC RT_BIT(4) +/** Bit 5 - MSR - Model Specific Registers RDMSR and WRMSR Instructions. */ +#define X86_CPUID_FEATURE_EDX_MSR RT_BIT(5) +/** Bit 6 - PAE - Physical Address Extension. */ +#define X86_CPUID_FEATURE_EDX_PAE RT_BIT(6) +/** Bit 7 - MCE - Machine Check Exception. */ +#define X86_CPUID_FEATURE_EDX_MCE RT_BIT(7) +/** Bit 8 - CX8 - CMPXCHG8B instruction. */ +#define X86_CPUID_FEATURE_EDX_CX8 RT_BIT(8) +/** Bit 9 - APIC - APIC On-Chip. */ +#define X86_CPUID_FEATURE_EDX_APIC RT_BIT(9) +/** Bit 11 - SEP - SYSENTER and SYSEXIT Present. */ +#define X86_CPUID_FEATURE_EDX_SEP RT_BIT(11) +/** Bit 12 - MTRR - Memory Type Range Registers. */ +#define X86_CPUID_FEATURE_EDX_MTRR RT_BIT(12) +/** Bit 13 - PGE - PTE Global Bit. */ +#define X86_CPUID_FEATURE_EDX_PGE RT_BIT(13) +/** Bit 14 - MCA - Machine Check Architecture. */ +#define X86_CPUID_FEATURE_EDX_MCA RT_BIT(14) +/** Bit 15 - CMOV - Conditional Move Instructions. */ +#define X86_CPUID_FEATURE_EDX_CMOV RT_BIT(15) +/** Bit 16 - PAT - Page Attribute Table. */ +#define X86_CPUID_FEATURE_EDX_PAT RT_BIT(16) +/** Bit 17 - PSE-36 - 36-bit Page Size Extention. */ +#define X86_CPUID_FEATURE_EDX_PSE36 RT_BIT(17) +/** Bit 18 - PSN - Processor Serial Number. */ +#define X86_CPUID_FEATURE_EDX_PSN RT_BIT(18) +/** Bit 19 - CLFSH - CLFLUSH Instruction. */ +#define X86_CPUID_FEATURE_EDX_CLFSH RT_BIT(19) +/** Bit 21 - DS - Debug Store. */ +#define X86_CPUID_FEATURE_EDX_DS RT_BIT(21) +/** Bit 22 - ACPI - Termal Monitor and Software Controlled Clock Facilities. */ +#define X86_CPUID_FEATURE_EDX_ACPI RT_BIT(22) +/** Bit 23 - MMX - Intel MMX Technology. */ +#define X86_CPUID_FEATURE_EDX_MMX RT_BIT(23) +/** Bit 24 - FXSR - FXSAVE and FXRSTOR Instructions. */ +#define X86_CPUID_FEATURE_EDX_FXSR RT_BIT(24) +/** Bit 25 - SSE - SSE Support. */ +#define X86_CPUID_FEATURE_EDX_SSE RT_BIT(25) +/** Bit 26 - SSE2 - SSE2 Support. */ +#define X86_CPUID_FEATURE_EDX_SSE2 RT_BIT(26) +/** Bit 27 - SS - Self Snoop. */ +#define X86_CPUID_FEATURE_EDX_SS RT_BIT(27) +/** Bit 28 - HTT - Hyper-Threading Technology. */ +#define X86_CPUID_FEATURE_EDX_HTT RT_BIT(28) +/** Bit 29 - TM - Therm. Monitor. */ +#define X86_CPUID_FEATURE_EDX_TM RT_BIT(29) +/** Bit 31 - PBE - Pending Break Enabled. */ +#define X86_CPUID_FEATURE_EDX_PBE RT_BIT(31) +/** @} */ + +/** @name CPUID mwait/monitor information. + * CPUID query with EAX=5. + * @{ + */ +/** ECX Bit 0 - MWAITEXT - Supports mwait/monitor extensions or not. */ +#define X86_CPUID_MWAIT_ECX_EXT RT_BIT(0) +/** ECX Bit 1 - MWAITBREAK - Break mwait for external interrupt even if EFLAGS.IF=0. */ +#define X86_CPUID_MWAIT_ECX_BREAKIRQIF0 RT_BIT(1) +/** @} */ + + +/** @name CPUID Extended Feature information. + * CPUID query with EAX=0x80000001. + * @{ + */ +/** ECX Bit 0 - LAHF/SAHF support in 64-bit mode. */ +#define X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF RT_BIT(0) + +/** EDX Bit 11 - SYSCALL/SYSRET. */ +#define X86_CPUID_EXT_FEATURE_EDX_SYSCALL RT_BIT(11) +/** EDX Bit 20 - No-Execute/Execute-Disable. */ +#define X86_CPUID_EXT_FEATURE_EDX_NX RT_BIT(20) +/** EDX Bit 26 - 1 GB large page. */ +#define X86_CPUID_EXT_FEATURE_EDX_PAGE1GB RT_BIT(26) +/** EDX Bit 27 - RDTSCP. */ +#define X86_CPUID_EXT_FEATURE_EDX_RDTSCP RT_BIT(27) +/** EDX Bit 29 - AMD Long Mode/Intel-64 Instructions. */ +#define X86_CPUID_EXT_FEATURE_EDX_LONG_MODE RT_BIT(29) +/** @}*/ + +/** @name CPUID AMD Feature information. + * CPUID query with EAX=0x80000001. + * @{ + */ +/** Bit 0 - FPU - x87 FPU on Chip. */ +#define X86_CPUID_AMD_FEATURE_EDX_FPU RT_BIT(0) +/** Bit 1 - VME - Virtual 8086 Mode Enhancements. */ +#define X86_CPUID_AMD_FEATURE_EDX_VME RT_BIT(1) +/** Bit 2 - DE - Debugging extensions. */ +#define X86_CPUID_AMD_FEATURE_EDX_DE RT_BIT(2) +/** Bit 3 - PSE - Page Size Extension. */ +#define X86_CPUID_AMD_FEATURE_EDX_PSE RT_BIT(3) +/** Bit 4 - TSC - Time Stamp Counter. */ +#define X86_CPUID_AMD_FEATURE_EDX_TSC RT_BIT(4) +/** Bit 5 - MSR - K86 Model Specific Registers RDMSR and WRMSR Instructions. */ +#define X86_CPUID_AMD_FEATURE_EDX_MSR RT_BIT(5) +/** Bit 6 - PAE - Physical Address Extension. */ +#define X86_CPUID_AMD_FEATURE_EDX_PAE RT_BIT(6) +/** Bit 7 - MCE - Machine Check Exception. */ +#define X86_CPUID_AMD_FEATURE_EDX_MCE RT_BIT(7) +/** Bit 8 - CX8 - CMPXCHG8B instruction. */ +#define X86_CPUID_AMD_FEATURE_EDX_CX8 RT_BIT(8) +/** Bit 9 - APIC - APIC On-Chip. */ +#define X86_CPUID_AMD_FEATURE_EDX_APIC RT_BIT(9) +/** Bit 12 - MTRR - Memory Type Range Registers. */ +#define X86_CPUID_AMD_FEATURE_EDX_MTRR RT_BIT(12) +/** Bit 13 - PGE - PTE Global Bit. */ +#define X86_CPUID_AMD_FEATURE_EDX_PGE RT_BIT(13) +/** Bit 14 - MCA - Machine Check Architecture. */ +#define X86_CPUID_AMD_FEATURE_EDX_MCA RT_BIT(14) +/** Bit 15 - CMOV - Conditional Move Instructions. */ +#define X86_CPUID_AMD_FEATURE_EDX_CMOV RT_BIT(15) +/** Bit 16 - PAT - Page Attribute Table. */ +#define X86_CPUID_AMD_FEATURE_EDX_PAT RT_BIT(16) +/** Bit 17 - PSE-36 - 36-bit Page Size Extention. */ +#define X86_CPUID_AMD_FEATURE_EDX_PSE36 RT_BIT(17) +/** Bit 22 - AXMMX - AMD Extensions to MMX Instructions. */ +#define X86_CPUID_AMD_FEATURE_EDX_AXMMX RT_BIT(22) +/** Bit 23 - MMX - Intel MMX Technology. */ +#define X86_CPUID_AMD_FEATURE_EDX_MMX RT_BIT(23) +/** Bit 24 - FXSR - FXSAVE and FXRSTOR Instructions. */ +#define X86_CPUID_AMD_FEATURE_EDX_FXSR RT_BIT(24) +/** Bit 25 - FFXSR - AMD fast FXSAVE and FXRSTOR Instructions. */ +#define X86_CPUID_AMD_FEATURE_EDX_FFXSR RT_BIT(25) +/** Bit 30 - 3DNOWEXT - AMD Extensions to 3DNow. */ +#define X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX RT_BIT(30) +/** Bit 31 - 3DNOW - AMD 3DNow. */ +#define X86_CPUID_AMD_FEATURE_EDX_3DNOW RT_BIT(31) + +/** Bit 1 - CMPL - Core multi-processing legacy mode. */ +#define X86_CPUID_AMD_FEATURE_ECX_CMPL RT_BIT(1) +/** Bit 2 - SVM - AMD VM extensions. */ +#define X86_CPUID_AMD_FEATURE_ECX_SVM RT_BIT(2) +/** Bit 3 - EXTAPIC - AMD extended APIC registers starting at 0x400. */ +#define X86_CPUID_AMD_FEATURE_ECX_EXT_APIC RT_BIT(3) +/** Bit 4 - CR8L - AMD LOCK MOV CR0 means MOV CR8. */ +#define X86_CPUID_AMD_FEATURE_ECX_CR8L RT_BIT(4) +/** Bit 5 - ABM - AMD Advanced bit manipulation. LZCNT instruction support. */ +#define X86_CPUID_AMD_FEATURE_ECX_ABM RT_BIT(5) +/** Bit 6 - SSE4A - AMD EXTRQ, INSERTQ, MOVNTSS, and MOVNTSD instruction support. */ +#define X86_CPUID_AMD_FEATURE_ECX_SSE4A RT_BIT(6) +/** Bit 7 - MISALIGNSSE - AMD Misaligned SSE mode. */ +#define X86_CPUID_AMD_FEATURE_ECX_MISALNSSE RT_BIT(7) +/** Bit 8 - 3DNOWPRF - AMD PREFETCH and PREFETCHW instruction support. */ +#define X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF RT_BIT(8) +/** Bit 9 - OSVW - AMD OS visible workaround. */ +#define X86_CPUID_AMD_FEATURE_ECX_OSVW RT_BIT(9) +/** Bit 10 - IBS - Instruct based sampling. */ +#define X86_CPUID_AMD_FEATURE_ECX_IBS RT_BIT(10) +/** Bit 11 - SSE5 - SSE5 instruction support. */ +#define X86_CPUID_AMD_FEATURE_ECX_SSE5 RT_BIT(11) +/** Bit 12 - SKINIT - AMD SKINIT: SKINIT, STGI, and DEV support. */ +#define X86_CPUID_AMD_FEATURE_ECX_SKINIT RT_BIT(12) +/** Bit 13 - WDT - AMD Watchdog timer support. */ +#define X86_CPUID_AMD_FEATURE_ECX_WDT RT_BIT(13) + +/** @} */ + + +/** @name CPUID AMD Feature information. + * CPUID query with EAX=0x80000007. + * @{ + */ +/** Bit 0 - TS - Temperature Sensor. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_TS RT_BIT(0) +/** Bit 1 - FID - Frequency ID Control. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_FID RT_BIT(1) +/** Bit 2 - VID - Voltage ID Control. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_VID RT_BIT(2) +/** Bit 3 - TTP - THERMTRIP. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_TTP RT_BIT(3) +/** Bit 4 - TM - Hardware Thermal Control. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_TM RT_BIT(4) +/** Bit 5 - STC - Software Thermal Control. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_STC RT_BIT(5) +/** Bit 6 - MC - 100 Mhz Multiplier Control. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_MC RT_BIT(6) +/** Bit 7 - HWPSTATE - Hardware P-State Control. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_HWPSTATE RT_BIT(7) +/** Bit 8 - TSCINVAR - TSC Invariant. */ +#define X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR RT_BIT(8) +/** @} */ + + +/** @name CR0 + * @{ */ +/** Bit 0 - PE - Protection Enabled */ +#define X86_CR0_PE RT_BIT(0) +#define X86_CR0_PROTECTION_ENABLE RT_BIT(0) +/** Bit 1 - MP - Monitor Coprocessor */ +#define X86_CR0_MP RT_BIT(1) +#define X86_CR0_MONITOR_COPROCESSOR RT_BIT(1) +/** Bit 2 - EM - Emulation. */ +#define X86_CR0_EM RT_BIT(2) +#define X86_CR0_EMULATE_FPU RT_BIT(2) +/** Bit 3 - TS - Task Switch. */ +#define X86_CR0_TS RT_BIT(3) +#define X86_CR0_TASK_SWITCH RT_BIT(3) +/** Bit 4 - ET - Extension flag. ('hardcoded' to 1) */ +#define X86_CR0_ET RT_BIT(4) +#define X86_CR0_EXTENSION_TYPE RT_BIT(4) +/** Bit 5 - NE - Numeric error. */ +#define X86_CR0_NE RT_BIT(5) +#define X86_CR0_NUMERIC_ERROR RT_BIT(5) +/** Bit 16 - WP - Write Protect. */ +#define X86_CR0_WP RT_BIT(16) +#define X86_CR0_WRITE_PROTECT RT_BIT(16) +/** Bit 18 - AM - Alignment Mask. */ +#define X86_CR0_AM RT_BIT(18) +#define X86_CR0_ALIGMENT_MASK RT_BIT(18) +/** Bit 29 - NW - Not Write-though. */ +#define X86_CR0_NW RT_BIT(29) +#define X86_CR0_NOT_WRITE_THROUGH RT_BIT(29) +/** Bit 30 - WP - Cache Disable. */ +#define X86_CR0_CD RT_BIT(30) +#define X86_CR0_CACHE_DISABLE RT_BIT(30) +/** Bit 31 - PG - Paging. */ +#define X86_CR0_PG RT_BIT(31) +#define X86_CR0_PAGING RT_BIT(31) +/** @} */ + + +/** @name CR3 + * @{ */ +/** Bit 3 - PWT - Page-level Writes Transparent. */ +#define X86_CR3_PWT RT_BIT(3) +/** Bit 4 - PCD - Page-level Cache Disable. */ +#define X86_CR3_PCD RT_BIT(4) +/** Bits 12-31 - - Page directory page number. */ +#define X86_CR3_PAGE_MASK (0xfffff000) +/** Bits 5-31 - - PAE Page directory page number. */ +#define X86_CR3_PAE_PAGE_MASK (0xffffffe0) +/** Bits 12-51 - - AMD64 Page directory page number. */ +#define X86_CR3_AMD64_PAGE_MASK UINT64_C(0x000ffffffffff000) +/** @} */ + + +/** @name CR4 + * @{ */ +/** Bit 0 - VME - Virtual-8086 Mode Extensions. */ +#define X86_CR4_VME RT_BIT(0) +/** Bit 1 - PVI - Protected-Mode Virtual Interrupts. */ +#define X86_CR4_PVI RT_BIT(1) +/** Bit 2 - TSD - Time Stamp Disable. */ +#define X86_CR4_TSD RT_BIT(2) +/** Bit 3 - DE - Debugging Extensions. */ +#define X86_CR4_DE RT_BIT(3) +/** Bit 4 - PSE - Page Size Extension. */ +#define X86_CR4_PSE RT_BIT(4) +/** Bit 5 - PAE - Physical Address Extension. */ +#define X86_CR4_PAE RT_BIT(5) +/** Bit 6 - MCE - Machine-Check Enable. */ +#define X86_CR4_MCE RT_BIT(6) +/** Bit 7 - PGE - Page Global Enable. */ +#define X86_CR4_PGE RT_BIT(7) +/** Bit 8 - PCE - Performance-Monitoring Counter Enable. */ +#define X86_CR4_PCE RT_BIT(8) +/** Bit 9 - OSFSXR - Operating System Support for FXSAVE and FXRSTORE instruction. */ +#define X86_CR4_OSFSXR RT_BIT(9) +/** Bit 10 - OSXMMEEXCPT - Operating System Support for Unmasked SIMD Floating-Point Exceptions. */ +#define X86_CR4_OSXMMEEXCPT RT_BIT(10) +/** Bit 13 - VMXE - VMX mode is enabled. */ +#define X86_CR4_VMXE RT_BIT(13) +/** Bit 14 - SMXE - Safer Mode Extensions Enabled. */ +#define X86_CR4_SMXE RT_BIT(14) +/** Bit 17 - PCIDE - Process-Context Identifiers Enabled. */ +#define X86_CR4_PCIDE RT_BIT(17) +/** Bit 18 - OSXSAVE - Operating System Support for XSAVE and processor + * extended states. */ +#define X86_CR4_OSXSAVE RT_BIT(18) +/** Bit 20 - SMEP - Supervisor-mode Execution Prevention enabled. */ +#define X86_CR4_SMEP RT_BIT(20) +/** @} */ + + +/** @name DR6 + * @{ */ +/** Bit 0 - B0 - Breakpoint 0 condition detected. */ +#define X86_DR6_B0 RT_BIT(0) +/** Bit 1 - B1 - Breakpoint 1 condition detected. */ +#define X86_DR6_B1 RT_BIT(1) +/** Bit 2 - B2 - Breakpoint 2 condition detected. */ +#define X86_DR6_B2 RT_BIT(2) +/** Bit 3 - B3 - Breakpoint 3 condition detected. */ +#define X86_DR6_B3 RT_BIT(3) +/** Bit 13 - BD - Debug register access detected. Corresponds to the X86_DR7_GD bit. */ +#define X86_DR6_BD RT_BIT(13) +/** Bit 14 - BS - Single step */ +#define X86_DR6_BS RT_BIT(14) +/** Bit 15 - BT - Task switch. (TSS T bit.) */ +#define X86_DR6_BT RT_BIT(15) +/** Value of DR6 after powerup/reset. */ +#define X86_DR6_INIT_VAL UINT64_C(0xFFFF0FF0) +/** @} */ + + +/** @name DR7 + * @{ */ +/** Bit 0 - L0 - Local breakpoint enable. Cleared on task switch. */ +#define X86_DR7_L0 RT_BIT(0) +/** Bit 1 - G0 - Global breakpoint enable. Not cleared on task switch. */ +#define X86_DR7_G0 RT_BIT(1) +/** Bit 2 - L1 - Local breakpoint enable. Cleared on task switch. */ +#define X86_DR7_L1 RT_BIT(2) +/** Bit 3 - G1 - Global breakpoint enable. Not cleared on task switch. */ +#define X86_DR7_G1 RT_BIT(3) +/** Bit 4 - L2 - Local breakpoint enable. Cleared on task switch. */ +#define X86_DR7_L2 RT_BIT(4) +/** Bit 5 - G2 - Global breakpoint enable. Not cleared on task switch. */ +#define X86_DR7_G2 RT_BIT(5) +/** Bit 6 - L3 - Local breakpoint enable. Cleared on task switch. */ +#define X86_DR7_L3 RT_BIT(6) +/** Bit 7 - G3 - Global breakpoint enable. Not cleared on task switch. */ +#define X86_DR7_G3 RT_BIT(7) +/** Bit 8 - LE - Local breakpoint exact. (Not supported (read ignored) by P6 and later.) */ +#define X86_DR7_LE RT_BIT(8) +/** Bit 9 - GE - Local breakpoint exact. (Not supported (read ignored) by P6 and later.) */ +#define X86_DR7_GE RT_BIT(9) + +/** Bit 13 - GD - General detect enable. Enables emulators to get exceptions when + * any DR register is accessed. */ +#define X86_DR7_GD RT_BIT(13) +/** Bit 16 & 17 - R/W0 - Read write field 0. Values X86_DR7_RW_*. */ +#define X86_DR7_RW0_MASK (3 << 16) +/** Bit 18 & 19 - LEN0 - Length field 0. Values X86_DR7_LEN_*. */ +#define X86_DR7_LEN0_MASK (3 << 18) +/** Bit 20 & 21 - R/W1 - Read write field 0. Values X86_DR7_RW_*. */ +#define X86_DR7_RW1_MASK (3 << 20) +/** Bit 22 & 23 - LEN1 - Length field 0. Values X86_DR7_LEN_*. */ +#define X86_DR7_LEN1_MASK (3 << 22) +/** Bit 24 & 25 - R/W2 - Read write field 0. Values X86_DR7_RW_*. */ +#define X86_DR7_RW2_MASK (3 << 24) +/** Bit 26 & 27 - LEN2 - Length field 0. Values X86_DR7_LEN_*. */ +#define X86_DR7_LEN2_MASK (3 << 26) +/** Bit 28 & 29 - R/W3 - Read write field 0. Values X86_DR7_RW_*. */ +#define X86_DR7_RW3_MASK (3 << 28) +/** Bit 30 & 31 - LEN3 - Length field 0. Values X86_DR7_LEN_*. */ +#define X86_DR7_LEN3_MASK (3 << 30) + +/** Bits which must be 1s. */ +#define X86_DR7_MB1_MASK (RT_BIT(10)) + +/** Calcs the L bit of Nth breakpoint. + * @param iBp The breakpoint number [0..3]. + */ +#define X86_DR7_L(iBp) ( UINT32_C(1) << (iBp * 2) ) + +/** Calcs the G bit of Nth breakpoint. + * @param iBp The breakpoint number [0..3]. + */ +#define X86_DR7_G(iBp) ( UINT32_C(1) << (iBp * 2 + 1) ) + +/** @name Read/Write values. + * @{ */ +/** Break on instruction fetch only. */ +#define X86_DR7_RW_EO 0U +/** Break on write only. */ +#define X86_DR7_RW_WO 1U +/** Break on I/O read/write. This is only defined if CR4.DE is set. */ +#define X86_DR7_RW_IO 2U +/** Break on read or write (but not instruction fetches). */ +#define X86_DR7_RW_RW 3U +/** @} */ + +/** Shifts a X86_DR7_RW_* value to its right place. + * @param iBp The breakpoint number [0..3]. + * @param fRw One of the X86_DR7_RW_* value. + */ +#define X86_DR7_RW(iBp, fRw) ( (fRw) << ((iBp) * 4 + 16) ) + +/** @name Length values. + * @{ */ +#define X86_DR7_LEN_BYTE 0U +#define X86_DR7_LEN_WORD 1U +#define X86_DR7_LEN_QWORD 2U /**< AMD64 long mode only. */ +#define X86_DR7_LEN_DWORD 3U +/** @} */ + +/** Shifts a X86_DR7_LEN_* value to its right place. + * @param iBp The breakpoint number [0..3]. + * @param cb One of the X86_DR7_LEN_* values. + */ +#define X86_DR7_LEN(iBp, cb) ( (cb) << ((iBp) * 4 + 18) ) + +/** Fetch the breakpoint length bits from the DR7 value. + * @param uDR7 DR7 value + * @param iBp The breakpoint number [0..3]. + */ +#define X86_DR7_GET_LEN(uDR7, iBp) ( ( (uDR7) >> ((iBp) * 4 + 18) ) & 0x3U) + +/** Mask used to check if any breakpoints are enabled. */ +#define X86_DR7_ENABLED_MASK (RT_BIT(0) | RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7)) + +/** Mask used to check if any io breakpoints are set. */ +#define X86_DR7_IO_ENABLED_MASK (X86_DR7_RW(0, X86_DR7_RW_IO) | X86_DR7_RW(1, X86_DR7_RW_IO) | X86_DR7_RW(2, X86_DR7_RW_IO) | X86_DR7_RW(3, X86_DR7_RW_IO)) + +/** Value of DR7 after powerup/reset. */ +#define X86_DR7_INIT_VAL 0x400 +/** @} */ + + +/** @name Machine Specific Registers + * @{ + */ + +/** Time Stamp Counter. */ +#define MSR_IA32_TSC 0x10 + +#define MSR_IA32_PLATFORM_ID 0x17 + +#ifndef MSR_IA32_APICBASE /* qemu cpu.h kludge */ +#define MSR_IA32_APICBASE 0x1b +#endif + +/** CPU Feature control. */ +#define MSR_IA32_FEATURE_CONTROL 0x3A +#define MSR_IA32_FEATURE_CONTROL_LOCK RT_BIT(0) +#define MSR_IA32_FEATURE_CONTROL_VMXON RT_BIT(2) + +/** BIOS update trigger (microcode update). */ +#define MSR_IA32_BIOS_UPDT_TRIG 0x79 + +/** BIOS update signature (microcode). */ +#define MSR_IA32_BIOS_SIGN_ID 0x8B + +/** General performance counter no. 0. */ +#define MSR_IA32_PMC0 0xC1 +/** General performance counter no. 1. */ +#define MSR_IA32_PMC1 0xC2 +/** General performance counter no. 2. */ +#define MSR_IA32_PMC2 0xC3 +/** General performance counter no. 3. */ +#define MSR_IA32_PMC3 0xC4 + +/** Nehalem power control. */ +#define MSR_IA32_PLATFORM_INFO 0xCE + +/** Get FSB clock status (Intel-specific). */ +#define MSR_IA32_FSB_CLOCK_STS 0xCD + +/** MTRR Capabilities. */ +#define MSR_IA32_MTRR_CAP 0xFE + + +#ifndef MSR_IA32_SYSENTER_CS /* qemu cpu.h kludge */ +/** SYSENTER_CS - the R0 CS, indirectly giving R0 SS, R3 CS and R3 DS. + * R0 SS == CS + 8 + * R3 CS == CS + 16 + * R3 SS == CS + 24 + */ +#define MSR_IA32_SYSENTER_CS 0x174 +/** SYSENTER_ESP - the R0 ESP. */ +#define MSR_IA32_SYSENTER_ESP 0x175 +/** SYSENTER_EIP - the R0 EIP. */ +#define MSR_IA32_SYSENTER_EIP 0x176 +#endif + +/** Machine Check Global Capabilities Register. */ +#define MSR_IA32_MCP_CAP 0x179 +/** Machine Check Global Status Register. */ +#define MSR_IA32_MCP_STATUS 0x17A +/** Machine Check Global Control Register. */ +#define MSR_IA32_MCP_CTRL 0x17B + +/** Trace/Profile Resource Control (R/W) */ +#define MSR_IA32_DEBUGCTL 0x1D9 + +/** Page Attribute Table. */ +#define MSR_IA32_CR_PAT 0x277 + +/** Performance counter MSRs. (Intel only) */ +#define MSR_IA32_PERFEVTSEL0 0x186 +#define MSR_IA32_PERFEVTSEL1 0x187 +#define MSR_IA32_FLEX_RATIO 0x194 +#define MSR_IA32_PERF_STATUS 0x198 +#define MSR_IA32_PERF_CTL 0x199 +#define MSR_IA32_THERM_STATUS 0x19c + +/** Enable misc. processor features (R/W). */ +#define MSR_IA32_MISC_ENABLE 0x1A0 +/** Enable fast-strings feature (for REP MOVS and REP STORS). */ +#define MSR_IA32_MISC_ENABLE_FAST_STRINGS RT_BIT(0) +/** Automatic Thermal Control Circuit Enable (R/W). */ +#define MSR_IA32_MISC_ENABLE_TCC RT_BIT(3) +/** Performance Monitoring Available (R). */ +#define MSR_IA32_MISC_ENABLE_PERF_MON RT_BIT(7) +/** Branch Trace Storage Unavailable (R/O). */ +#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL RT_BIT(11) +/** Precise Event Based Sampling (PEBS) Unavailable (R/O). */ +#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL RT_BIT(12) +/** Enhanced Intel SpeedStep Technology Enable (R/W). */ +#define MSR_IA32_MISC_ENABLE_SST_ENABLE RT_BIT(16) +/** If MONITOR/MWAIT is supported (R/W). */ +#define MSR_IA32_MISC_ENABLE_MONITOR RT_BIT(18) +/** Limit CPUID Maxval to 3 leafs (R/W). */ +#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID RT_BIT(22) +/** When set to 1, xTPR messages are disabled (R/W). */ +#define MSR_IA32_MISC_ENABLE_XTPR_MSG_DISABLE RT_BIT(23) +/** When set to 1, the Execute Disable Bit feature (XD Bit) is disabled (R/W). */ +#define MSR_IA32_MISC_ENABLE_XD_DISABLE RT_BIT(34) + +#define IA32_MTRR_PHYSBASE0 0x200 +#define IA32_MTRR_PHYSMASK0 0x201 +#define IA32_MTRR_PHYSBASE1 0x202 +#define IA32_MTRR_PHYSMASK1 0x203 +#define IA32_MTRR_PHYSBASE2 0x204 +#define IA32_MTRR_PHYSMASK2 0x205 +#define IA32_MTRR_PHYSBASE3 0x206 +#define IA32_MTRR_PHYSMASK3 0x207 +#define IA32_MTRR_PHYSBASE4 0x208 +#define IA32_MTRR_PHYSMASK4 0x209 +#define IA32_MTRR_PHYSBASE5 0x20a +#define IA32_MTRR_PHYSMASK5 0x20b +#define IA32_MTRR_PHYSBASE6 0x20c +#define IA32_MTRR_PHYSMASK6 0x20d +#define IA32_MTRR_PHYSBASE7 0x20e +#define IA32_MTRR_PHYSMASK7 0x20f +#define IA32_MTRR_PHYSBASE8 0x210 +#define IA32_MTRR_PHYSMASK8 0x211 +#define IA32_MTRR_PHYSBASE9 0x212 +#define IA32_MTRR_PHYSMASK9 0x213 + +/** Fixed range MTRRs. + * @{ */ +#define IA32_MTRR_FIX64K_00000 0x250 +#define IA32_MTRR_FIX16K_80000 0x258 +#define IA32_MTRR_FIX16K_A0000 0x259 +#define IA32_MTRR_FIX4K_C0000 0x268 +#define IA32_MTRR_FIX4K_C8000 0x269 +#define IA32_MTRR_FIX4K_D0000 0x26a +#define IA32_MTRR_FIX4K_D8000 0x26b +#define IA32_MTRR_FIX4K_E0000 0x26c +#define IA32_MTRR_FIX4K_E8000 0x26d +#define IA32_MTRR_FIX4K_F0000 0x26e +#define IA32_MTRR_FIX4K_F8000 0x26f +/** @} */ + +/** MTRR Default Range. */ +#define MSR_IA32_MTRR_DEF_TYPE 0x2FF + +#define MSR_IA32_MC0_CTL 0x400 +#define MSR_IA32_MC0_STATUS 0x401 + +/** Basic VMX information. */ +#define MSR_IA32_VMX_BASIC_INFO 0x480 +/** Allowed settings for pin-based VM execution controls */ +#define MSR_IA32_VMX_PINBASED_CTLS 0x481 +/** Allowed settings for proc-based VM execution controls */ +#define MSR_IA32_VMX_PROCBASED_CTLS 0x482 +/** Allowed settings for the VMX exit controls. */ +#define MSR_IA32_VMX_EXIT_CTLS 0x483 +/** Allowed settings for the VMX entry controls. */ +#define MSR_IA32_VMX_ENTRY_CTLS 0x484 +/** Misc VMX info. */ +#define MSR_IA32_VMX_MISC 0x485 +/** Fixed cleared bits in CR0. */ +#define MSR_IA32_VMX_CR0_FIXED0 0x486 +/** Fixed set bits in CR0. */ +#define MSR_IA32_VMX_CR0_FIXED1 0x487 +/** Fixed cleared bits in CR4. */ +#define MSR_IA32_VMX_CR4_FIXED0 0x488 +/** Fixed set bits in CR4. */ +#define MSR_IA32_VMX_CR4_FIXED1 0x489 +/** Information for enumerating fields in the VMCS. */ +#define MSR_IA32_VMX_VMCS_ENUM 0x48A +/** Allowed settings for secondary proc-based VM execution controls */ +#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48B +/** EPT capabilities. */ +#define MSR_IA32_VMX_EPT_CAPS 0x48C +/** DS Save Area (R/W). */ +#define MSR_IA32_DS_AREA 0x600 +/** X2APIC MSR ranges. */ +#define MSR_IA32_APIC_START 0x800 +#define MSR_IA32_APIC_END 0x900 + +/** K6 EFER - Extended Feature Enable Register. */ +#define MSR_K6_EFER 0xc0000080 +/** @todo document EFER */ +/** Bit 0 - SCE - System call extensions (SYSCALL / SYSRET). (R/W) */ +#define MSR_K6_EFER_SCE RT_BIT(0) +/** Bit 8 - LME - Long mode enabled. (R/W) */ +#define MSR_K6_EFER_LME RT_BIT(8) +/** Bit 10 - LMA - Long mode active. (R) */ +#define MSR_K6_EFER_LMA RT_BIT(10) +/** Bit 11 - NXE - No-Execute Page Protection Enabled. (R/W) */ +#define MSR_K6_EFER_NXE RT_BIT(11) +/** Bit 12 - SVME - Secure VM Extension Enabled. (R/W) */ +#define MSR_K6_EFER_SVME RT_BIT(12) +/** Bit 13 - LMSLE - Long Mode Segment Limit Enable. (R/W?) */ +#define MSR_K6_EFER_LMSLE RT_BIT(13) +/** Bit 14 - FFXSR - Fast FXSAVE / FXRSTOR (skip XMM*). (R/W) */ +#define MSR_K6_EFER_FFXSR RT_BIT(14) +/** K6 STAR - SYSCALL/RET targets. */ +#define MSR_K6_STAR 0xc0000081 +/** Shift value for getting the SYSRET CS and SS value. */ +#define MSR_K6_STAR_SYSRET_CS_SS_SHIFT 48 +/** Shift value for getting the SYSCALL CS and SS value. */ +#define MSR_K6_STAR_SYSCALL_CS_SS_SHIFT 32 +/** Selector mask for use after shifting. */ +#define MSR_K6_STAR_SEL_MASK 0xffff +/** The mask which give the SYSCALL EIP. */ +#define MSR_K6_STAR_SYSCALL_EIP_MASK 0xffffffff +/** K6 WHCR - Write Handling Control Register. */ +#define MSR_K6_WHCR 0xc0000082 +/** K6 UWCCR - UC/WC Cacheability Control Register. */ +#define MSR_K6_UWCCR 0xc0000085 +/** K6 PSOR - Processor State Observability Register. */ +#define MSR_K6_PSOR 0xc0000087 +/** K6 PFIR - Page Flush/Invalidate Register. */ +#define MSR_K6_PFIR 0xc0000088 + +/** Performance counter MSRs. (AMD only) */ +#define MSR_K7_EVNTSEL0 0xc0010000 +#define MSR_K7_EVNTSEL1 0xc0010001 +#define MSR_K7_EVNTSEL2 0xc0010002 +#define MSR_K7_EVNTSEL3 0xc0010003 +#define MSR_K7_PERFCTR0 0xc0010004 +#define MSR_K7_PERFCTR1 0xc0010005 +#define MSR_K7_PERFCTR2 0xc0010006 +#define MSR_K7_PERFCTR3 0xc0010007 + +/** K8 LSTAR - Long mode SYSCALL target (RIP). */ +#define MSR_K8_LSTAR 0xc0000082 +/** K8 CSTAR - Compatibility mode SYSCALL target (RIP). */ +#define MSR_K8_CSTAR 0xc0000083 +/** K8 SF_MASK - SYSCALL flag mask. (aka SFMASK) */ +#define MSR_K8_SF_MASK 0xc0000084 +/** K8 FS.base - The 64-bit base FS register. */ +#define MSR_K8_FS_BASE 0xc0000100 +/** K8 GS.base - The 64-bit base GS register. */ +#define MSR_K8_GS_BASE 0xc0000101 +/** K8 KernelGSbase - Used with SWAPGS. */ +#define MSR_K8_KERNEL_GS_BASE 0xc0000102 +/** K8 TSC_AUX - Used with RDTSCP. */ +#define MSR_K8_TSC_AUX 0xc0000103 +#define MSR_K8_SYSCFG 0xc0010010 +#define MSR_K8_HWCR 0xc0010015 +#define MSR_K8_IORRBASE0 0xc0010016 +#define MSR_K8_IORRMASK0 0xc0010017 +#define MSR_K8_IORRBASE1 0xc0010018 +#define MSR_K8_IORRMASK1 0xc0010019 +#define MSR_K8_TOP_MEM1 0xc001001a +#define MSR_K8_TOP_MEM2 0xc001001d +#define MSR_K8_VM_CR 0xc0010114 +#define MSR_K8_VM_CR_SVM_DISABLE RT_BIT(4) + +#define MSR_K8_IGNNE 0xc0010115 +#define MSR_K8_SMM_CTL 0xc0010116 +/** SVM - VM_HSAVE_PA - Physical address for saving and restoring + * host state during world switch. + */ +#define MSR_K8_VM_HSAVE_PA 0xc0010117 + +/** @} */ + + +/** @name Page Table / Directory / Directory Pointers / L4. + * @{ + */ + +/** Page table/directory entry as an unsigned integer. */ +typedef uint32_t X86PGUINT; +/** Pointer to a page table/directory table entry as an unsigned integer. */ +typedef X86PGUINT *PX86PGUINT; +/** Pointer to an const page table/directory table entry as an unsigned integer. */ +typedef X86PGUINT const *PCX86PGUINT; + +/** Number of entries in a 32-bit PT/PD. */ +#define X86_PG_ENTRIES 1024 + + +/** PAE page table/page directory/pdpt/l4/l5 entry as an unsigned integer. */ +typedef uint64_t X86PGPAEUINT; +/** Pointer to a PAE page table/page directory/pdpt/l4/l5 entry as an unsigned integer. */ +typedef X86PGPAEUINT *PX86PGPAEUINT; +/** Pointer to an const PAE page table/page directory/pdpt/l4/l5 entry as an unsigned integer. */ +typedef X86PGPAEUINT const *PCX86PGPAEUINT; + +/** Number of entries in a PAE PT/PD. */ +#define X86_PG_PAE_ENTRIES 512 +/** Number of entries in a PAE PDPT. */ +#define X86_PG_PAE_PDPE_ENTRIES 4 + +/** Number of entries in an AMD64 PT/PD/PDPT/L4/L5. */ +#define X86_PG_AMD64_ENTRIES X86_PG_PAE_ENTRIES +/** Number of entries in an AMD64 PDPT. + * Just for complementing X86_PG_PAE_PDPE_ENTRIES, using X86_PG_AMD64_ENTRIES for this is fine too. */ +#define X86_PG_AMD64_PDPE_ENTRIES X86_PG_AMD64_ENTRIES + +/** The size of a 4KB page. */ +#define X86_PAGE_4K_SIZE _4K +/** The page shift of a 4KB page. */ +#define X86_PAGE_4K_SHIFT 12 +/** The 4KB page offset mask. */ +#define X86_PAGE_4K_OFFSET_MASK 0xfff +/** The 4KB page base mask for virtual addresses. */ +#define X86_PAGE_4K_BASE_MASK 0xfffffffffffff000ULL +/** The 4KB page base mask for virtual addresses - 32bit version. */ +#define X86_PAGE_4K_BASE_MASK_32 0xfffff000U + +/** The size of a 2MB page. */ +#define X86_PAGE_2M_SIZE _2M +/** The page shift of a 2MB page. */ +#define X86_PAGE_2M_SHIFT 21 +/** The 2MB page offset mask. */ +#define X86_PAGE_2M_OFFSET_MASK 0x001fffff +/** The 2MB page base mask for virtual addresses. */ +#define X86_PAGE_2M_BASE_MASK 0xffffffffffe00000ULL +/** The 2MB page base mask for virtual addresses - 32bit version. */ +#define X86_PAGE_2M_BASE_MASK_32 0xffe00000U + +/** The size of a 4MB page. */ +#define X86_PAGE_4M_SIZE _4M +/** The page shift of a 4MB page. */ +#define X86_PAGE_4M_SHIFT 22 +/** The 4MB page offset mask. */ +#define X86_PAGE_4M_OFFSET_MASK 0x003fffff +/** The 4MB page base mask for virtual addresses. */ +#define X86_PAGE_4M_BASE_MASK 0xffffffffffc00000ULL +/** The 4MB page base mask for virtual addresses - 32bit version. */ +#define X86_PAGE_4M_BASE_MASK_32 0xffc00000U + + + +/** @name Page Table Entry + * @{ + */ +/** Bit 0 - P - Present bit. */ +#define X86_PTE_BIT_P 0 +/** Bit 1 - R/W - Read (clear) / Write (set) bit. */ +#define X86_PTE_BIT_RW 1 +/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. */ +#define X86_PTE_BIT_US 2 +/** Bit 3 - PWT - Page level write thru bit. */ +#define X86_PTE_BIT_PWT 3 +/** Bit 4 - PCD - Page level cache disable bit. */ +#define X86_PTE_BIT_PCD 4 +/** Bit 5 - A - Access bit. */ +#define X86_PTE_BIT_A 5 +/** Bit 6 - D - Dirty bit. */ +#define X86_PTE_BIT_D 6 +/** Bit 7 - PAT - Page Attribute Table index bit. Reserved and 0 if not supported. */ +#define X86_PTE_BIT_PAT 7 +/** Bit 8 - G - Global flag. */ +#define X86_PTE_BIT_G 8 + +/** Bit 0 - P - Present bit mask. */ +#define X86_PTE_P RT_BIT(0) +/** Bit 1 - R/W - Read (clear) / Write (set) bit mask. */ +#define X86_PTE_RW RT_BIT(1) +/** Bit 2 - U/S - User (set) / Supervisor (clear) bit mask. */ +#define X86_PTE_US RT_BIT(2) +/** Bit 3 - PWT - Page level write thru bit mask. */ +#define X86_PTE_PWT RT_BIT(3) +/** Bit 4 - PCD - Page level cache disable bit mask. */ +#define X86_PTE_PCD RT_BIT(4) +/** Bit 5 - A - Access bit mask. */ +#define X86_PTE_A RT_BIT(5) +/** Bit 6 - D - Dirty bit mask. */ +#define X86_PTE_D RT_BIT(6) +/** Bit 7 - PAT - Page Attribute Table index bit mask. Reserved and 0 if not supported. */ +#define X86_PTE_PAT RT_BIT(7) +/** Bit 8 - G - Global bit mask. */ +#define X86_PTE_G RT_BIT(8) + +/** Bits 9-11 - - Available for use to system software. */ +#define X86_PTE_AVL_MASK (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +/** Bits 12-31 - - Physical Page number of the next level. */ +#define X86_PTE_PG_MASK ( 0xfffff000 ) + +/** Bits 12-51 - - PAE - Physical Page number of the next level. */ +#define X86_PTE_PAE_PG_MASK UINT64_C(0x000ffffffffff000) +/** Bits 63 - NX - PAE/LM - No execution flag. */ +#define X86_PTE_PAE_NX RT_BIT_64(63) +/** Bits 62-52 - - PAE - MBZ bits when NX is active. */ +#define X86_PTE_PAE_MBZ_MASK_NX UINT64_C(0x7ff0000000000000) +/** Bits 63-52 - - PAE - MBZ bits when no NX. */ +#define X86_PTE_PAE_MBZ_MASK_NO_NX UINT64_C(0xfff0000000000000) +/** No bits - - LM - MBZ bits when NX is active. */ +#define X86_PTE_LM_MBZ_MASK_NX UINT64_C(0x0000000000000000) +/** Bits 63 - - LM - MBZ bits when no NX. */ +#define X86_PTE_LM_MBZ_MASK_NO_NX UINT64_C(0x8000000000000000) + +/** + * Page table entry. + */ +typedef struct X86PTEBITS +{ + /** Flags whether(=1) or not the page is present. */ + unsigned u1Present : 1; + /** Read(=0) / Write(=1) flag. */ + unsigned u1Write : 1; + /** User(=1) / Supervisor (=0) flag. */ + unsigned u1User : 1; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + unsigned u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + unsigned u1CacheDisable : 1; + /** Accessed flag. + * Indicates that the page have been read or written to. */ + unsigned u1Accessed : 1; + /** Dirty flag. + * Indicates that the page has been written to. */ + unsigned u1Dirty : 1; + /** Reserved / If PAT enabled, bit 2 of the index. */ + unsigned u1PAT : 1; + /** Global flag. (Ignored in all but final level.) */ + unsigned u1Global : 1; + /** Available for use to system software. */ + unsigned u3Available : 3; + /** Physical Page number of the next level. */ + unsigned u20PageNo : 20; +} X86PTEBITS; +/** Pointer to a page table entry. */ +typedef X86PTEBITS *PX86PTEBITS; +/** Pointer to a const page table entry. */ +typedef const X86PTEBITS *PCX86PTEBITS; + +/** + * Page table entry. + */ +typedef union X86PTE +{ + /** Unsigned integer view */ + X86PGUINT u; + /** Bit field view. */ + X86PTEBITS n; + /** 32-bit view. */ + uint32_t au32[1]; + /** 16-bit view. */ + uint16_t au16[2]; + /** 8-bit view. */ + uint8_t au8[4]; +} X86PTE; +/** Pointer to a page table entry. */ +typedef X86PTE *PX86PTE; +/** Pointer to a const page table entry. */ +typedef const X86PTE *PCX86PTE; + + +/** + * PAE page table entry. + */ +typedef struct X86PTEPAEBITS +{ + /** Flags whether(=1) or not the page is present. */ + uint32_t u1Present : 1; + /** Read(=0) / Write(=1) flag. */ + uint32_t u1Write : 1; + /** User(=1) / Supervisor(=0) flag. */ + uint32_t u1User : 1; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + uint32_t u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + uint32_t u1CacheDisable : 1; + /** Accessed flag. + * Indicates that the page have been read or written to. */ + uint32_t u1Accessed : 1; + /** Dirty flag. + * Indicates that the page has been written to. */ + uint32_t u1Dirty : 1; + /** Reserved / If PAT enabled, bit 2 of the index. */ + uint32_t u1PAT : 1; + /** Global flag. (Ignored in all but final level.) */ + uint32_t u1Global : 1; + /** Available for use to system software. */ + uint32_t u3Available : 3; + /** Physical Page number of the next level - Low Part. Don't use this. */ + uint32_t u20PageNoLow : 20; + /** Physical Page number of the next level - High Part. Don't use this. */ + uint32_t u20PageNoHigh : 20; + /** MBZ bits */ + uint32_t u11Reserved : 11; + /** No Execute flag. */ + uint32_t u1NoExecute : 1; +} X86PTEPAEBITS; +/** Pointer to a page table entry. */ +typedef X86PTEPAEBITS *PX86PTEPAEBITS; +/** Pointer to a page table entry. */ +typedef const X86PTEPAEBITS *PCX86PTEPAEBITS; + +/** + * PAE Page table entry. + */ +typedef union X86PTEPAE +{ + /** Unsigned integer view */ + X86PGPAEUINT u; + /** Bit field view. */ + X86PTEPAEBITS n; + /** 32-bit view. */ + uint32_t au32[2]; + /** 16-bit view. */ + uint16_t au16[4]; + /** 8-bit view. */ + uint8_t au8[8]; +} X86PTEPAE; +/** Pointer to a PAE page table entry. */ +typedef X86PTEPAE *PX86PTEPAE; +/** Pointer to a const PAE page table entry. */ +typedef const X86PTEPAE *PCX86PTEPAE; +/** @} */ + +/** + * Page table. + */ +typedef struct X86PT +{ + /** PTE Array. */ + X86PTE a[X86_PG_ENTRIES]; +} X86PT; +/** Pointer to a page table. */ +typedef X86PT *PX86PT; +/** Pointer to a const page table. */ +typedef const X86PT *PCX86PT; + +/** The page shift to get the PT index. */ +#define X86_PT_SHIFT 12 +/** The PT index mask (apply to a shifted page address). */ +#define X86_PT_MASK 0x3ff + + +/** + * Page directory. + */ +typedef struct X86PTPAE +{ + /** PTE Array. */ + X86PTEPAE a[X86_PG_PAE_ENTRIES]; +} X86PTPAE; +/** Pointer to a page table. */ +typedef X86PTPAE *PX86PTPAE; +/** Pointer to a const page table. */ +typedef const X86PTPAE *PCX86PTPAE; + +/** The page shift to get the PA PTE index. */ +#define X86_PT_PAE_SHIFT 12 +/** The PAE PT index mask (apply to a shifted page address). */ +#define X86_PT_PAE_MASK 0x1ff + + +/** @name 4KB Page Directory Entry + * @{ + */ +/** Bit 0 - P - Present bit. */ +#define X86_PDE_P RT_BIT(0) +/** Bit 1 - R/W - Read (clear) / Write (set) bit. */ +#define X86_PDE_RW RT_BIT(1) +/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. */ +#define X86_PDE_US RT_BIT(2) +/** Bit 3 - PWT - Page level write thru bit. */ +#define X86_PDE_PWT RT_BIT(3) +/** Bit 4 - PCD - Page level cache disable bit. */ +#define X86_PDE_PCD RT_BIT(4) +/** Bit 5 - A - Access bit. */ +#define X86_PDE_A RT_BIT(5) +/** Bit 7 - PS - Page size attribute. + * Clear mean 4KB pages, set means large pages (2/4MB). */ +#define X86_PDE_PS RT_BIT(7) +/** Bits 9-11 - - Available for use to system software. */ +#define X86_PDE_AVL_MASK (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +/** Bits 12-31 - - Physical Page number of the next level. */ +#define X86_PDE_PG_MASK ( 0xfffff000 ) + +/** Bits 12-51 - - PAE - Physical Page number of the next level. */ +#define X86_PDE_PAE_PG_MASK UINT64_C(0x000ffffffffff000) +/** Bits 63 - NX - PAE/LM - No execution flag. */ +#define X86_PDE_PAE_NX RT_BIT_64(63) +/** Bits 62-52, 7 - - PAE - MBZ bits when NX is active. */ +#define X86_PDE_PAE_MBZ_MASK_NX UINT64_C(0x7ff0000000000080) +/** Bits 63-52, 7 - - PAE - MBZ bits when no NX. */ +#define X86_PDE_PAE_MBZ_MASK_NO_NX UINT64_C(0xfff0000000000080) +/** Bit 7 - - LM - MBZ bits when NX is active. */ +#define X86_PDE_LM_MBZ_MASK_NX UINT64_C(0x0000000000000080) +/** Bits 63, 7 - - LM - MBZ bits when no NX. */ +#define X86_PDE_LM_MBZ_MASK_NO_NX UINT64_C(0x8000000000000080) + +/** + * Page directory entry. + */ +typedef struct X86PDEBITS +{ + /** Flags whether(=1) or not the page is present. */ + unsigned u1Present : 1; + /** Read(=0) / Write(=1) flag. */ + unsigned u1Write : 1; + /** User(=1) / Supervisor (=0) flag. */ + unsigned u1User : 1; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + unsigned u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + unsigned u1CacheDisable : 1; + /** Accessed flag. + * Indicates that the page has been read or written to. */ + unsigned u1Accessed : 1; + /** Reserved / Ignored (dirty bit). */ + unsigned u1Reserved0 : 1; + /** Size bit if PSE is enabled - in any event it's 0. */ + unsigned u1Size : 1; + /** Reserved / Ignored (global bit). */ + unsigned u1Reserved1 : 1; + /** Available for use to system software. */ + unsigned u3Available : 3; + /** Physical Page number of the next level. */ + unsigned u20PageNo : 20; +} X86PDEBITS; +/** Pointer to a page directory entry. */ +typedef X86PDEBITS *PX86PDEBITS; +/** Pointer to a const page directory entry. */ +typedef const X86PDEBITS *PCX86PDEBITS; + + +/** + * PAE page directory entry. + */ +typedef struct X86PDEPAEBITS +{ + /** Flags whether(=1) or not the page is present. */ + uint32_t u1Present : 1; + /** Read(=0) / Write(=1) flag. */ + uint32_t u1Write : 1; + /** User(=1) / Supervisor (=0) flag. */ + uint32_t u1User : 1; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + uint32_t u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + uint32_t u1CacheDisable : 1; + /** Accessed flag. + * Indicates that the page has been read or written to. */ + uint32_t u1Accessed : 1; + /** Reserved / Ignored (dirty bit). */ + uint32_t u1Reserved0 : 1; + /** Size bit if PSE is enabled - in any event it's 0. */ + uint32_t u1Size : 1; + /** Reserved / Ignored (global bit). / */ + uint32_t u1Reserved1 : 1; + /** Available for use to system software. */ + uint32_t u3Available : 3; + /** Physical Page number of the next level - Low Part. Don't use! */ + uint32_t u20PageNoLow : 20; + /** Physical Page number of the next level - High Part. Don't use! */ + uint32_t u20PageNoHigh : 20; + /** MBZ bits */ + uint32_t u11Reserved : 11; + /** No Execute flag. */ + uint32_t u1NoExecute : 1; +} X86PDEPAEBITS; +/** Pointer to a page directory entry. */ +typedef X86PDEPAEBITS *PX86PDEPAEBITS; +/** Pointer to a const page directory entry. */ +typedef const X86PDEPAEBITS *PCX86PDEPAEBITS; + +/** @} */ + + +/** @name 2/4MB Page Directory Entry + * @{ + */ +/** Bit 0 - P - Present bit. */ +#define X86_PDE4M_P RT_BIT(0) +/** Bit 1 - R/W - Read (clear) / Write (set) bit. */ +#define X86_PDE4M_RW RT_BIT(1) +/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. */ +#define X86_PDE4M_US RT_BIT(2) +/** Bit 3 - PWT - Page level write thru bit. */ +#define X86_PDE4M_PWT RT_BIT(3) +/** Bit 4 - PCD - Page level cache disable bit. */ +#define X86_PDE4M_PCD RT_BIT(4) +/** Bit 5 - A - Access bit. */ +#define X86_PDE4M_A RT_BIT(5) +/** Bit 6 - D - Dirty bit. */ +#define X86_PDE4M_D RT_BIT(6) +/** Bit 7 - PS - Page size attribute. Clear mean 4KB pages, set means large pages (2/4MB). */ +#define X86_PDE4M_PS RT_BIT(7) +/** Bit 8 - G - Global flag. */ +#define X86_PDE4M_G RT_BIT(8) +/** Bits 9-11 - AVL - Available for use to system software. */ +#define X86_PDE4M_AVL (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +/** Bit 12 - PAT - Page Attribute Table index bit. Reserved and 0 if not supported. */ +#define X86_PDE4M_PAT RT_BIT(12) +/** Shift to get from X86_PTE_PAT to X86_PDE4M_PAT. */ +#define X86_PDE4M_PAT_SHIFT (12 - 7) +/** Bits 22-31 - - Physical Page number. */ +#define X86_PDE4M_PG_MASK ( 0xffc00000 ) +/** Bits 20-13 - - Physical Page number high part (32-39 bits). AMD64 hack. */ +#define X86_PDE4M_PG_HIGH_MASK ( 0x001fe000 ) +/** The number of bits to the high part of the page number. */ +#define X86_PDE4M_PG_HIGH_SHIFT 19 +/** Bit 21 - - MBZ bits for AMD CPUs, no PSE36. */ +#define X86_PDE4M_MBZ_MASK RT_BIT_32(21) + +/** Bits 21-51 - - PAE/LM - Physical Page number. + * (Bits 40-51 (long mode) & bits 36-51 (pae legacy) are reserved according to the Intel docs; AMD allows for more.) */ +#define X86_PDE2M_PAE_PG_MASK UINT64_C(0x000fffffffe00000) +/** Bits 63 - NX - PAE/LM - No execution flag. */ +#define X86_PDE2M_PAE_NX RT_BIT_64(63) +/** Bits 62-52, 20-13 - - PAE - MBZ bits when NX is active. */ +#define X86_PDE2M_PAE_MBZ_MASK_NX UINT64_C(0x7ff00000001fe000) +/** Bits 63-52, 20-13 - - PAE - MBZ bits when no NX. */ +#define X86_PDE2M_PAE_MBZ_MASK_NO_NX UINT64_C(0xfff00000001fe000) +/** Bits 20-13 - - LM - MBZ bits when NX is active. */ +#define X86_PDE2M_LM_MBZ_MASK_NX UINT64_C(0x00000000001fe000) +/** Bits 63, 20-13 - - LM - MBZ bits when no NX. */ +#define X86_PDE2M_LM_MBZ_MASK_NO_NX UINT64_C(0x80000000001fe000) + +/** + * 4MB page directory entry. + */ +typedef struct X86PDE4MBITS +{ + /** Flags whether(=1) or not the page is present. */ + unsigned u1Present : 1; + /** Read(=0) / Write(=1) flag. */ + unsigned u1Write : 1; + /** User(=1) / Supervisor (=0) flag. */ + unsigned u1User : 1; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + unsigned u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + unsigned u1CacheDisable : 1; + /** Accessed flag. + * Indicates that the page have been read or written to. */ + unsigned u1Accessed : 1; + /** Dirty flag. + * Indicates that the page has been written to. */ + unsigned u1Dirty : 1; + /** Page size flag - always 1 for 4MB entries. */ + unsigned u1Size : 1; + /** Global flag. */ + unsigned u1Global : 1; + /** Available for use to system software. */ + unsigned u3Available : 3; + /** Reserved / If PAT enabled, bit 2 of the index. */ + unsigned u1PAT : 1; + /** Bits 32-39 of the page number on AMD64. + * This AMD64 hack allows accessing 40bits of physical memory without PAE. */ + unsigned u8PageNoHigh : 8; + /** Reserved. */ + unsigned u1Reserved : 1; + /** Physical Page number of the page. */ + unsigned u10PageNo : 10; +} X86PDE4MBITS; +/** Pointer to a page table entry. */ +typedef X86PDE4MBITS *PX86PDE4MBITS; +/** Pointer to a const page table entry. */ +typedef const X86PDE4MBITS *PCX86PDE4MBITS; + + +/** + * 2MB PAE page directory entry. + */ +typedef struct X86PDE2MPAEBITS +{ + /** Flags whether(=1) or not the page is present. */ + uint32_t u1Present : 1; + /** Read(=0) / Write(=1) flag. */ + uint32_t u1Write : 1; + /** User(=1) / Supervisor(=0) flag. */ + uint32_t u1User : 1; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + uint32_t u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + uint32_t u1CacheDisable : 1; + /** Accessed flag. + * Indicates that the page have been read or written to. */ + uint32_t u1Accessed : 1; + /** Dirty flag. + * Indicates that the page has been written to. */ + uint32_t u1Dirty : 1; + /** Page size flag - always 1 for 2MB entries. */ + uint32_t u1Size : 1; + /** Global flag. */ + uint32_t u1Global : 1; + /** Available for use to system software. */ + uint32_t u3Available : 3; + /** Reserved / If PAT enabled, bit 2 of the index. */ + uint32_t u1PAT : 1; + /** Reserved. */ + uint32_t u9Reserved : 9; + /** Physical Page number of the next level - Low part. Don't use! */ + uint32_t u10PageNoLow : 10; + /** Physical Page number of the next level - High part. Don't use! */ + uint32_t u20PageNoHigh : 20; + /** MBZ bits */ + uint32_t u11Reserved : 11; + /** No Execute flag. */ + uint32_t u1NoExecute : 1; +} X86PDE2MPAEBITS; +/** Pointer to a 2MB PAE page table entry. */ +typedef X86PDE2MPAEBITS *PX86PDE2MPAEBITS; +/** Pointer to a 2MB PAE page table entry. */ +typedef const X86PDE2MPAEBITS *PCX86PDE2MPAEBITS; + +/** @} */ + +/** + * Page directory entry. + */ +typedef union X86PDE +{ + /** Unsigned integer view. */ + X86PGUINT u; + /** Normal view. */ + X86PDEBITS n; + /** 4MB view (big). */ + X86PDE4MBITS b; + /** 8 bit unsigned integer view. */ + uint8_t au8[4]; + /** 16 bit unsigned integer view. */ + uint16_t au16[2]; + /** 32 bit unsigned integer view. */ + uint32_t au32[1]; +} X86PDE; +/** Pointer to a page directory entry. */ +typedef X86PDE *PX86PDE; +/** Pointer to a const page directory entry. */ +typedef const X86PDE *PCX86PDE; + +/** + * PAE page directory entry. + */ +typedef union X86PDEPAE +{ + /** Unsigned integer view. */ + X86PGPAEUINT u; + /** Normal view. */ + X86PDEPAEBITS n; + /** 2MB page view (big). */ + X86PDE2MPAEBITS b; + /** 8 bit unsigned integer view. */ + uint8_t au8[8]; + /** 16 bit unsigned integer view. */ + uint16_t au16[4]; + /** 32 bit unsigned integer view. */ + uint32_t au32[2]; +} X86PDEPAE; +/** Pointer to a page directory entry. */ +typedef X86PDEPAE *PX86PDEPAE; +/** Pointer to a const page directory entry. */ +typedef const X86PDEPAE *PCX86PDEPAE; + +/** + * Page directory. + */ +typedef struct X86PD +{ + /** PDE Array. */ + X86PDE a[X86_PG_ENTRIES]; +} X86PD; +/** Pointer to a page directory. */ +typedef X86PD *PX86PD; +/** Pointer to a const page directory. */ +typedef const X86PD *PCX86PD; + +/** The page shift to get the PD index. */ +#define X86_PD_SHIFT 22 +/** The PD index mask (apply to a shifted page address). */ +#define X86_PD_MASK 0x3ff + + +/** + * PAE page directory. + */ +typedef struct X86PDPAE +{ + /** PDE Array. */ + X86PDEPAE a[X86_PG_PAE_ENTRIES]; +} X86PDPAE; +/** Pointer to a PAE page directory. */ +typedef X86PDPAE *PX86PDPAE; +/** Pointer to a const PAE page directory. */ +typedef const X86PDPAE *PCX86PDPAE; + +/** The page shift to get the PAE PD index. */ +#define X86_PD_PAE_SHIFT 21 +/** The PAE PD index mask (apply to a shifted page address). */ +#define X86_PD_PAE_MASK 0x1ff + + +/** @name Page Directory Pointer Table Entry (PAE) + * @{ + */ +/** Bit 0 - P - Present bit. */ +#define X86_PDPE_P RT_BIT(0) +/** Bit 1 - R/W - Read (clear) / Write (set) bit. Long Mode only. */ +#define X86_PDPE_RW RT_BIT(1) +/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. Long Mode only. */ +#define X86_PDPE_US RT_BIT(2) +/** Bit 3 - PWT - Page level write thru bit. */ +#define X86_PDPE_PWT RT_BIT(3) +/** Bit 4 - PCD - Page level cache disable bit. */ +#define X86_PDPE_PCD RT_BIT(4) +/** Bit 5 - A - Access bit. Long Mode only. */ +#define X86_PDPE_A RT_BIT(5) +/** Bit 7 - PS - Page size (1GB). Long Mode only. */ +#define X86_PDPE_LM_PS RT_BIT(7) +/** Bits 9-11 - - Available for use to system software. */ +#define X86_PDPE_AVL_MASK (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +/** Bits 12-51 - - PAE - Physical Page number of the next level. */ +#define X86_PDPE_PG_MASK UINT64_C(0x000ffffffffff000) +/** Bits 63-52, 8-5, 2-1 - - PAE - MBZ bits (NX is long mode only). */ +#define X86_PDPE_PAE_MBZ_MASK UINT64_C(0xfff00000000001e6) +/** Bits 63 - NX - LM - No execution flag. Long Mode only. */ +#define X86_PDPE_LM_NX RT_BIT_64(63) +/** Bits 8, 7 - - LM - MBZ bits when NX is active. */ +#define X86_PDPE_LM_MBZ_MASK_NX UINT64_C(0x0000000000000180) +/** Bits 63, 8, 7 - - LM - MBZ bits when no NX. */ +#define X86_PDPE_LM_MBZ_MASK_NO_NX UINT64_C(0x8000000000000180) +/** Bits 29-13 - - LM - MBZ bits for 1GB page entry when NX is active. */ +#define X86_PDPE1G_LM_MBZ_MASK_NX UINT64_C(0x000000003fffe000) +/** Bits 63, 29-13 - - LM - MBZ bits for 1GB page entry when no NX. */ +#define X86_PDPE1G_LM_MBZ_MASK_NO_NX UINT64_C(0x800000003fffe000) + + +/** + * Page directory pointer table entry. + */ +typedef struct X86PDPEBITS +{ + /** Flags whether(=1) or not the page is present. */ + uint32_t u1Present : 1; + /** Chunk of reserved bits. */ + uint32_t u2Reserved : 2; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + uint32_t u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + uint32_t u1CacheDisable : 1; + /** Chunk of reserved bits. */ + uint32_t u4Reserved : 4; + /** Available for use to system software. */ + uint32_t u3Available : 3; + /** Physical Page number of the next level - Low Part. Don't use! */ + uint32_t u20PageNoLow : 20; + /** Physical Page number of the next level - High Part. Don't use! */ + uint32_t u20PageNoHigh : 20; + /** MBZ bits */ + uint32_t u12Reserved : 12; +} X86PDPEBITS; +/** Pointer to a page directory pointer table entry. */ +typedef X86PDPEBITS *PX86PTPEBITS; +/** Pointer to a const page directory pointer table entry. */ +typedef const X86PDPEBITS *PCX86PTPEBITS; + +/** + * Page directory pointer table entry. AMD64 version + */ +typedef struct X86PDPEAMD64BITS +{ + /** Flags whether(=1) or not the page is present. */ + uint32_t u1Present : 1; + /** Read(=0) / Write(=1) flag. */ + uint32_t u1Write : 1; + /** User(=1) / Supervisor (=0) flag. */ + uint32_t u1User : 1; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + uint32_t u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + uint32_t u1CacheDisable : 1; + /** Accessed flag. + * Indicates that the page have been read or written to. */ + uint32_t u1Accessed : 1; + /** Chunk of reserved bits. */ + uint32_t u3Reserved : 3; + /** Available for use to system software. */ + uint32_t u3Available : 3; + /** Physical Page number of the next level - Low Part. Don't use! */ + uint32_t u20PageNoLow : 20; + /** Physical Page number of the next level - High Part. Don't use! */ + uint32_t u20PageNoHigh : 20; + /** MBZ bits */ + uint32_t u11Reserved : 11; + /** No Execute flag. */ + uint32_t u1NoExecute : 1; +} X86PDPEAMD64BITS; +/** Pointer to a page directory pointer table entry. */ +typedef X86PDPEAMD64BITS *PX86PDPEAMD64BITS; +/** Pointer to a const page directory pointer table entry. */ +typedef const X86PDPEAMD64BITS *PCX86PDPEAMD64BITS; + +/** + * Page directory pointer table entry. + */ +typedef union X86PDPE +{ + /** Unsigned integer view. */ + X86PGPAEUINT u; + /** Normal view. */ + X86PDPEBITS n; + /** AMD64 view. */ + X86PDPEAMD64BITS lm; + /** 8 bit unsigned integer view. */ + uint8_t au8[8]; + /** 16 bit unsigned integer view. */ + uint16_t au16[4]; + /** 32 bit unsigned integer view. */ + uint32_t au32[2]; +} X86PDPE; +/** Pointer to a page directory pointer table entry. */ +typedef X86PDPE *PX86PDPE; +/** Pointer to a const page directory pointer table entry. */ +typedef const X86PDPE *PCX86PDPE; + + +/** + * Page directory pointer table. + */ +typedef struct X86PDPT +{ + /** PDE Array. */ + X86PDPE a[X86_PG_AMD64_PDPE_ENTRIES]; +} X86PDPT; +/** Pointer to a page directory pointer table. */ +typedef X86PDPT *PX86PDPT; +/** Pointer to a const page directory pointer table. */ +typedef const X86PDPT *PCX86PDPT; + +/** The page shift to get the PDPT index. */ +#define X86_PDPT_SHIFT 30 +/** The PDPT index mask (apply to a shifted page address). (32 bits PAE) */ +#define X86_PDPT_MASK_PAE 0x3 +/** The PDPT index mask (apply to a shifted page address). (64 bits PAE)*/ +#define X86_PDPT_MASK_AMD64 0x1ff + +/** @} */ + + +/** @name Page Map Level-4 Entry (Long Mode PAE) + * @{ + */ +/** Bit 0 - P - Present bit. */ +#define X86_PML4E_P RT_BIT(0) +/** Bit 1 - R/W - Read (clear) / Write (set) bit. */ +#define X86_PML4E_RW RT_BIT(1) +/** Bit 2 - U/S - User (set) / Supervisor (clear) bit. */ +#define X86_PML4E_US RT_BIT(2) +/** Bit 3 - PWT - Page level write thru bit. */ +#define X86_PML4E_PWT RT_BIT(3) +/** Bit 4 - PCD - Page level cache disable bit. */ +#define X86_PML4E_PCD RT_BIT(4) +/** Bit 5 - A - Access bit. */ +#define X86_PML4E_A RT_BIT(5) +/** Bits 9-11 - - Available for use to system software. */ +#define X86_PML4E_AVL_MASK (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +/** Bits 12-51 - - PAE - Physical Page number of the next level. */ +#define X86_PML4E_PG_MASK UINT64_C(0x000ffffffffff000) +/** Bits 8, 7 - - MBZ bits when NX is active. */ +#define X86_PML4E_MBZ_MASK_NX UINT64_C(0x0000000000000080) +/** Bits 63, 7 - - MBZ bits when no NX. */ +#define X86_PML4E_MBZ_MASK_NO_NX UINT64_C(0x8000000000000080) +/** Bits 63 - NX - PAE - No execution flag. */ +#define X86_PML4E_NX RT_BIT_64(63) + +/** + * Page Map Level-4 Entry + */ +typedef struct X86PML4EBITS +{ + /** Flags whether(=1) or not the page is present. */ + uint32_t u1Present : 1; + /** Read(=0) / Write(=1) flag. */ + uint32_t u1Write : 1; + /** User(=1) / Supervisor (=0) flag. */ + uint32_t u1User : 1; + /** Write Thru flag. If PAT enabled, bit 0 of the index. */ + uint32_t u1WriteThru : 1; + /** Cache disabled flag. If PAT enabled, bit 1 of the index. */ + uint32_t u1CacheDisable : 1; + /** Accessed flag. + * Indicates that the page have been read or written to. */ + uint32_t u1Accessed : 1; + /** Chunk of reserved bits. */ + uint32_t u3Reserved : 3; + /** Available for use to system software. */ + uint32_t u3Available : 3; + /** Physical Page number of the next level - Low Part. Don't use! */ + uint32_t u20PageNoLow : 20; + /** Physical Page number of the next level - High Part. Don't use! */ + uint32_t u20PageNoHigh : 20; + /** MBZ bits */ + uint32_t u11Reserved : 11; + /** No Execute flag. */ + uint32_t u1NoExecute : 1; +} X86PML4EBITS; +/** Pointer to a page map level-4 entry. */ +typedef X86PML4EBITS *PX86PML4EBITS; +/** Pointer to a const page map level-4 entry. */ +typedef const X86PML4EBITS *PCX86PML4EBITS; + +/** + * Page Map Level-4 Entry. + */ +typedef union X86PML4E +{ + /** Unsigned integer view. */ + X86PGPAEUINT u; + /** Normal view. */ + X86PML4EBITS n; + /** 8 bit unsigned integer view. */ + uint8_t au8[8]; + /** 16 bit unsigned integer view. */ + uint16_t au16[4]; + /** 32 bit unsigned integer view. */ + uint32_t au32[2]; +} X86PML4E; +/** Pointer to a page map level-4 entry. */ +typedef X86PML4E *PX86PML4E; +/** Pointer to a const page map level-4 entry. */ +typedef const X86PML4E *PCX86PML4E; + + +/** + * Page Map Level-4. + */ +typedef struct X86PML4 +{ + /** PDE Array. */ + X86PML4E a[X86_PG_PAE_ENTRIES]; +} X86PML4; +/** Pointer to a page map level-4. */ +typedef X86PML4 *PX86PML4; +/** Pointer to a const page map level-4. */ +typedef const X86PML4 *PCX86PML4; + +/** The page shift to get the PML4 index. */ +#define X86_PML4_SHIFT 39 +/** The PML4 index mask (apply to a shifted page address). */ +#define X86_PML4_MASK 0x1ff + +/** @} */ + +/** @} */ + + +/** + * 80-bit MMX/FPU register type. + */ +typedef struct X86FPUMMX +{ + uint8_t reg[10]; +} X86FPUMMX; +/** Pointer to a 80-bit MMX/FPU register type. */ +typedef X86FPUMMX *PX86FPUMMX; +/** Pointer to a const 80-bit MMX/FPU register type. */ +typedef const X86FPUMMX *PCX86FPUMMX; + +/** + * 32-bit FPU state (aka FSAVE/FRSTOR Memory Region). + * @todo verify this... + */ +#pragma pack(1) +typedef struct X86FPUSTATE +{ + /** 0x00 - Control word. */ + uint16_t FCW; + /** 0x02 - Alignment word */ + uint16_t Dummy1; + /** 0x04 - Status word. */ + uint16_t FSW; + /** 0x06 - Alignment word */ + uint16_t Dummy2; + /** 0x08 - Tag word */ + uint16_t FTW; + /** 0x0a - Alignment word */ + uint16_t Dummy3; + + /** 0x0c - Instruction pointer. */ + uint32_t FPUIP; + /** 0x10 - Code selector. */ + uint16_t CS; + /** 0x12 - Opcode. */ + uint16_t FOP; + /** 0x14 - FOO. */ + uint32_t FPUOO; + /** 0x18 - FOS. */ + uint32_t FPUOS; + /** 0x1c */ + union + { + /** MMX view. */ + uint64_t mmx; + /** FPU view - todo. */ + X86FPUMMX fpu; + /** Extended precision floating point view. */ + RTFLOAT80U r80; + /** Extended precision floating point view v2. */ + RTFLOAT80U2 r80Ex; + /** 8-bit view. */ + uint8_t au8[16]; + /** 16-bit view. */ + uint16_t au16[8]; + /** 32-bit view. */ + uint32_t au32[4]; + /** 64-bit view. */ + uint64_t au64[2]; + /** 128-bit view. (yeah, very helpful) */ + uint128_t au128[1]; + } regs[8]; +} X86FPUSTATE; +#pragma pack() +/** Pointer to a FPU state. */ +typedef X86FPUSTATE *PX86FPUSTATE; +/** Pointer to a const FPU state. */ +typedef const X86FPUSTATE *PCX86FPUSTATE; + +/** + * FPU Extended state (aka FXSAVE/FXRSTORE Memory Region). + */ +#pragma pack(1) +typedef struct X86FXSTATE +{ + /** 0x00 - Control word. */ + uint16_t FCW; + /** 0x02 - Status word. */ + uint16_t FSW; + /** 0x04 - Tag word. (The upper byte is always zero.) */ + uint16_t FTW; + /** 0x06 - Opcode. */ + uint16_t FOP; + /** 0x08 - Instruction pointer. */ + uint32_t FPUIP; + /** 0x0c - Code selector. */ + uint16_t CS; + uint16_t Rsrvd1; + /** 0x10 - Data pointer. */ + uint32_t FPUDP; + /** 0x14 - Data segment */ + uint16_t DS; + /** 0x16 */ + uint16_t Rsrvd2; + /** 0x18 */ + uint32_t MXCSR; + /** 0x1c */ + uint32_t MXCSR_MASK; + /** 0x20 */ + union + { + /** MMX view. */ + uint64_t mmx; + /** FPU view - todo. */ + X86FPUMMX fpu; + /** Extended precision floating point view. */ + RTFLOAT80U r80; + /** Extended precision floating point view v2 */ + RTFLOAT80U2 r80Ex; + /** 8-bit view. */ + uint8_t au8[16]; + /** 16-bit view. */ + uint16_t au16[8]; + /** 32-bit view. */ + uint32_t au32[4]; + /** 64-bit view. */ + uint64_t au64[2]; + /** 128-bit view. (yeah, very helpful) */ + uint128_t au128[1]; + } aRegs[8]; + /* - offset 160 - */ + union + { + /** XMM Register view *. */ + uint128_t xmm; + /** 8-bit view. */ + uint8_t au8[16]; + /** 16-bit view. */ + uint16_t au16[8]; + /** 32-bit view. */ + uint32_t au32[4]; + /** 64-bit view. */ + uint64_t au64[2]; + /** 128-bit view. (yeah, very helpful) */ + uint128_t au128[1]; + } aXMM[16]; /* 8 registers in 32 bits mode; 16 in long mode */ + /* - offset 416 - */ + uint32_t au32RsrvdRest[(512 - 416) / sizeof(uint32_t)]; +} X86FXSTATE; +#pragma pack() +/** Pointer to a FPU Extended state. */ +typedef X86FXSTATE *PX86FXSTATE; +/** Pointer to a const FPU Extended state. */ +typedef const X86FXSTATE *PCX86FXSTATE; + +/** @name FPU status word flags. + * @{ */ +/** Exception Flag: Invalid operation. */ +#define X86_FSW_IE RT_BIT(0) +/** Exception Flag: Denormalized operand. */ +#define X86_FSW_DE RT_BIT(1) +/** Exception Flag: Zero divide. */ +#define X86_FSW_ZE RT_BIT(2) +/** Exception Flag: Overflow. */ +#define X86_FSW_OE RT_BIT(3) +/** Exception Flag: Underflow. */ +#define X86_FSW_UE RT_BIT(4) +/** Exception Flag: Precision. */ +#define X86_FSW_PE RT_BIT(5) +/** Stack fault. */ +#define X86_FSW_SF RT_BIT(6) +/** Error summary status. */ +#define X86_FSW_ES RT_BIT(7) +/** Mask of exceptions flags, excluding the summary bit. */ +#define X86_FSW_XCPT_MASK UINT16_C(0x007f) +/** Mask of exceptions flags, including the summary bit. */ +#define X86_FSW_XCPT_ES_MASK UINT16_C(0x00ff) +/** Condition code 0. */ +#define X86_FSW_C0 RT_BIT(8) +/** Condition code 1. */ +#define X86_FSW_C1 RT_BIT(9) +/** Condition code 2. */ +#define X86_FSW_C2 RT_BIT(10) +/** Top of the stack mask. */ +#define X86_FSW_TOP_MASK UINT16_C(0x3800) +/** TOP shift value. */ +#define X86_FSW_TOP_SHIFT 11 +/** Mask for getting TOP value after shifting it right. */ +#define X86_FSW_TOP_SMASK UINT16_C(0x0007) +/** Get the TOP value. */ +#define X86_FSW_TOP_GET(a_uFsw) (((a_uFsw) >> X86_FSW_TOP_SHIFT) & X86_FSW_TOP_SMASK) +/** Condition code 3. */ +#define X86_FSW_C3 RT_BIT(14) +/** Mask of exceptions flags, including the summary bit. */ +#define X86_FSW_C_MASK UINT16_C(0x4700) +/** FPU busy. */ +#define X86_FSW_B RT_BIT(15) +/** @} */ + + +/** @name FPU control word flags. + * @{ */ +/** Exception Mask: Invalid operation. */ +#define X86_FCW_IM RT_BIT(0) +/** Exception Mask: Denormalized operand. */ +#define X86_FCW_DM RT_BIT(1) +/** Exception Mask: Zero divide. */ +#define X86_FCW_ZM RT_BIT(2) +/** Exception Mask: Overflow. */ +#define X86_FCW_OM RT_BIT(3) +/** Exception Mask: Underflow. */ +#define X86_FCW_UM RT_BIT(4) +/** Exception Mask: Precision. */ +#define X86_FCW_PM RT_BIT(5) +/** Mask all exceptions, the value typically loaded (by for instance fninit). + * @remarks This includes reserved bit 6. */ +#define X86_FCW_MASK_ALL UINT16_C(0x007f) +/** Mask all exceptions. Same as X86_FSW_XCPT_MASK. */ +#define X86_FCW_XCPT_MASK UINT16_C(0x003f) +/** Precision control mask. */ +#define X86_FCW_PC_MASK UINT16_C(0x0300) +/** Precision control: 24-bit. */ +#define X86_FCW_PC_24 UINT16_C(0x0000) +/** Precision control: Reserved. */ +#define X86_FCW_PC_RSVD UINT16_C(0x0100) +/** Precision control: 53-bit. */ +#define X86_FCW_PC_53 UINT16_C(0x0200) +/** Precision control: 64-bit. */ +#define X86_FCW_PC_64 UINT16_C(0x0300) +/** Rounding control mask. */ +#define X86_FCW_RC_MASK UINT16_C(0x0c00) +/** Rounding control: To nearest. */ +#define X86_FCW_RC_NEAREST UINT16_C(0x0000) +/** Rounding control: Down. */ +#define X86_FCW_RC_DOWN UINT16_C(0x0400) +/** Rounding control: Up. */ +#define X86_FCW_RC_UP UINT16_C(0x0800) +/** Rounding control: Towards zero. */ +#define X86_FCW_RC_ZERO UINT16_C(0x0c00) +/** Bits which should be zero, apparently. */ +#define X86_FCW_ZERO_MASK UINT16_C(0xf080) +/** @} */ + + +/** @name Selector Descriptor + * @{ + */ + +#ifndef VBOX_FOR_DTRACE_LIB +/** + * Descriptor attributes. + */ +typedef struct X86DESCATTRBITS +{ + /** 00 - Segment Type. */ + unsigned u4Type : 4; + /** 04 - Descriptor Type. System(=0) or code/data selector */ + unsigned u1DescType : 1; + /** 05 - Descriptor Privelege level. */ + unsigned u2Dpl : 2; + /** 07 - Flags selector present(=1) or not. */ + unsigned u1Present : 1; + /** 08 - Segment limit 16-19. */ + unsigned u4LimitHigh : 4; + /** 0c - Available for system software. */ + unsigned u1Available : 1; + /** 0d - 32 bits mode: Reserved - 0, long mode: Long Attribute Bit. */ + unsigned u1Long : 1; + /** 0e - This flags meaning depends on the segment type. Try make sense out + * of the intel manual yourself. */ + unsigned u1DefBig : 1; + /** 0f - Granularity of the limit. If set 4KB granularity is used, if + * clear byte. */ + unsigned u1Granularity : 1; +} X86DESCATTRBITS; +#endif /* !VBOX_FOR_DTRACE_LIB */ + +#pragma pack(1) +typedef union X86DESCATTR +{ + /** Unsigned integer view. */ + uint32_t u; +#ifndef VBOX_FOR_DTRACE_LIB + /** Normal view. */ + X86DESCATTRBITS n; +#endif +} X86DESCATTR; +#pragma pack() +/** Pointer to descriptor attributes. */ +typedef X86DESCATTR *PX86DESCATTR; +/** Pointer to const descriptor attributes. */ +typedef const X86DESCATTR *PCX86DESCATTR; + +#ifndef VBOX_FOR_DTRACE_LIB + +/** + * Generic descriptor table entry + */ +#pragma pack(1) +typedef struct X86DESCGENERIC +{ + /** Limit - Low word. */ + unsigned u16LimitLow : 16; + /** Base address - lowe word. + * Don't try set this to 24 because MSC is doing stupid things then. */ + unsigned u16BaseLow : 16; + /** Base address - first 8 bits of high word. */ + unsigned u8BaseHigh1 : 8; + /** Segment Type. */ + unsigned u4Type : 4; + /** Descriptor Type. System(=0) or code/data selector */ + unsigned u1DescType : 1; + /** Descriptor Privelege level. */ + unsigned u2Dpl : 2; + /** Flags selector present(=1) or not. */ + unsigned u1Present : 1; + /** Segment limit 16-19. */ + unsigned u4LimitHigh : 4; + /** Available for system software. */ + unsigned u1Available : 1; + /** 32 bits mode: Reserved - 0, long mode: Long Attribute Bit. */ + unsigned u1Long : 1; + /** This flags meaning depends on the segment type. Try make sense out + * of the intel manual yourself. */ + unsigned u1DefBig : 1; + /** Granularity of the limit. If set 4KB granularity is used, if + * clear byte. */ + unsigned u1Granularity : 1; + /** Base address - highest 8 bits. */ + unsigned u8BaseHigh2 : 8; +} X86DESCGENERIC; +#pragma pack() +/** Pointer to a generic descriptor entry. */ +typedef X86DESCGENERIC *PX86DESCGENERIC; +/** Pointer to a const generic descriptor entry. */ +typedef const X86DESCGENERIC *PCX86DESCGENERIC; + +/** @name Bit offsets of X86DESCGENERIC members. + * @{*/ +#define X86DESCGENERIC_BIT_OFF_LIMIT_LOW (0) /**< Bit offset of X86DESCGENERIC::u16LimitLow. */ +#define X86DESCGENERIC_BIT_OFF_BASE_LOW (16) /**< Bit offset of X86DESCGENERIC::u16BaseLow. */ +#define X86DESCGENERIC_BIT_OFF_BASE_HIGH1 (32) /**< Bit offset of X86DESCGENERIC::u8BaseHigh1. */ +#define X86DESCGENERIC_BIT_OFF_TYPE (40) /**< Bit offset of X86DESCGENERIC::u4Type. */ +#define X86DESCGENERIC_BIT_OFF_DESC_TYPE (44) /**< Bit offset of X86DESCGENERIC::u1DescType. */ +#define X86DESCGENERIC_BIT_OFF_DPL (45) /**< Bit offset of X86DESCGENERIC::u2Dpl. */ +#define X86DESCGENERIC_BIT_OFF_PRESENT (47) /**< Bit offset of X86DESCGENERIC::uu1Present. */ +#define X86DESCGENERIC_BIT_OFF_LIMIT_HIGH (48) /**< Bit offset of X86DESCGENERIC::u4LimitHigh. */ +#define X86DESCGENERIC_BIT_OFF_AVAILABLE (52) /**< Bit offset of X86DESCGENERIC::u1Available. */ +#define X86DESCGENERIC_BIT_OFF_LONG (53) /**< Bit offset of X86DESCGENERIC::u1Long. */ +#define X86DESCGENERIC_BIT_OFF_DEF_BIG (54) /**< Bit offset of X86DESCGENERIC::u1DefBig. */ +#define X86DESCGENERIC_BIT_OFF_GRANULARITY (55) /**< Bit offset of X86DESCGENERIC::u1Granularity. */ +#define X86DESCGENERIC_BIT_OFF_BASE_HIGH2 (56) /**< Bit offset of X86DESCGENERIC::u8BaseHigh2. */ +/** @} */ + +/** + * Call-, Interrupt-, Trap- or Task-gate descriptor (legacy). + */ +typedef struct X86DESCGATE +{ + /** 00 - Target code segment offset - Low word. + * Ignored if task-gate. */ + unsigned u16OffsetLow : 16; + /** 10 - Target code segment selector for call-, interrupt- and trap-gates, + * TSS selector if task-gate. */ + unsigned u16Sel : 16; + /** 20 - Number of parameters for a call-gate. + * Ignored if interrupt-, trap- or task-gate. */ + unsigned u4ParmCount : 4; + /** 24 - Reserved / ignored. */ + unsigned u4Reserved : 4; + /** 28 - Segment Type. */ + unsigned u4Type : 4; + /** 2c - Descriptor Type (0 = system). */ + unsigned u1DescType : 1; + /** 2d - Descriptor Privelege level. */ + unsigned u2Dpl : 2; + /** 2f - Flags selector present(=1) or not. */ + unsigned u1Present : 1; + /** 30 - Target code segment offset - High word. + * Ignored if task-gate. */ + unsigned u16OffsetHigh : 16; +} X86DESCGATE; +/** Pointer to a Call-, Interrupt-, Trap- or Task-gate descriptor entry. */ +typedef X86DESCGATE *PX86DESCGATE; +/** Pointer to a const Call-, Interrupt-, Trap- or Task-gate descriptor entry. */ +typedef const X86DESCGATE *PCX86DESCGATE; + +#endif /* VBOX_FOR_DTRACE_LIB */ + +/** + * Descriptor table entry. + */ +#pragma pack(1) +typedef union X86DESC +{ +#ifndef VBOX_FOR_DTRACE_LIB + /** Generic descriptor view. */ + X86DESCGENERIC Gen; + /** Gate descriptor view. */ + X86DESCGATE Gate; +#endif + + /** 8 bit unsigned integer view. */ + uint8_t au8[8]; + /** 16 bit unsigned integer view. */ + uint16_t au16[4]; + /** 32 bit unsigned integer view. */ + uint32_t au32[2]; + /** 64 bit unsigned integer view. */ + uint64_t au64[1]; + /** Unsigned integer view. */ + uint64_t u; +} X86DESC; +#ifndef VBOX_FOR_DTRACE_LIB +AssertCompileSize(X86DESC, 8); +#endif +#pragma pack() +/** Pointer to descriptor table entry. */ +typedef X86DESC *PX86DESC; +/** Pointer to const descriptor table entry. */ +typedef const X86DESC *PCX86DESC; + +/** @def X86DESC_BASE + * Return the base address of a descriptor. + */ +#define X86DESC_BASE(a_pDesc) /*ASM-NOINC*/ \ + ( ((uint32_t)((a_pDesc)->Gen.u8BaseHigh2) << 24) \ + | ( (a_pDesc)->Gen.u8BaseHigh1 << 16) \ + | ( (a_pDesc)->Gen.u16BaseLow ) ) + +/** @def X86DESC_LIMIT + * Return the limit of a descriptor. + */ +#define X86DESC_LIMIT(a_pDesc) /*ASM-NOINC*/ \ + ( ((uint32_t)((a_pDesc)->Gen.u4LimitHigh) << 16) \ + | ( (a_pDesc)->Gen.u16LimitLow ) ) + +/** @def X86DESC_LIMIT_G + * Return the limit of a descriptor with the granularity bit taken into account. + * @returns Selector limit (uint32_t). + * @param a_pDesc Pointer to the descriptor. + */ +#define X86DESC_LIMIT_G(a_pDesc) /*ASM-NOINC*/ \ + ( (a_pDesc)->Gen.u1Granularity \ + ? ( ( ((uint32_t)(a_pDesc)->Gen.u4LimitHigh << 16) | (a_pDesc)->Gen.u16LimitLow ) << 12 ) | UINT32_C(0xfff) \ + : ((uint32_t)(a_pDesc)->Gen.u4LimitHigh << 16) | (a_pDesc)->Gen.u16LimitLow \ + ) + +/** @def X86DESC_GET_HID_ATTR + * Get the descriptor attributes for the hidden register. + */ +#define X86DESC_GET_HID_ATTR(a_pDesc) /*ASM-NOINC*/ \ + ( ((a_pDesc)->u >> (16+16+8)) & UINT32_C(0xf0ff) ) /** @todo do we have a define for 0xf0ff? */ + +#ifndef VBOX_FOR_DTRACE_LIB + +/** + * 64 bits generic descriptor table entry + * Note: most of these bits have no meaning in long mode. + */ +#pragma pack(1) +typedef struct X86DESC64GENERIC +{ + /** Limit - Low word - *IGNORED*. */ + unsigned u16LimitLow : 16; + /** Base address - low word. - *IGNORED* + * Don't try set this to 24 because MSC is doing stupid things then. */ + unsigned u16BaseLow : 16; + /** Base address - first 8 bits of high word. - *IGNORED* */ + unsigned u8BaseHigh1 : 8; + /** Segment Type. */ + unsigned u4Type : 4; + /** Descriptor Type. System(=0) or code/data selector */ + unsigned u1DescType : 1; + /** Descriptor Privelege level. */ + unsigned u2Dpl : 2; + /** Flags selector present(=1) or not. */ + unsigned u1Present : 1; + /** Segment limit 16-19. - *IGNORED* */ + unsigned u4LimitHigh : 4; + /** Available for system software. - *IGNORED* */ + unsigned u1Available : 1; + /** Long mode flag. */ + unsigned u1Long : 1; + /** This flags meaning depends on the segment type. Try make sense out + * of the intel manual yourself. */ + unsigned u1DefBig : 1; + /** Granularity of the limit. If set 4KB granularity is used, if + * clear byte. - *IGNORED* */ + unsigned u1Granularity : 1; + /** Base address - highest 8 bits. - *IGNORED* */ + unsigned u8BaseHigh2 : 8; + /** Base address - bits 63-32. */ + unsigned u32BaseHigh3 : 32; + unsigned u8Reserved : 8; + unsigned u5Zeros : 5; + unsigned u19Reserved : 19; +} X86DESC64GENERIC; +#pragma pack() +/** Pointer to a generic descriptor entry. */ +typedef X86DESC64GENERIC *PX86DESC64GENERIC; +/** Pointer to a const generic descriptor entry. */ +typedef const X86DESC64GENERIC *PCX86DESC64GENERIC; + +/** + * System descriptor table entry (64 bits) + * + * @remarks This is, save a couple of comments, identical to X86DESC64GENERIC... + */ +#pragma pack(1) +typedef struct X86DESC64SYSTEM +{ + /** Limit - Low word. */ + unsigned u16LimitLow : 16; + /** Base address - lowe word. + * Don't try set this to 24 because MSC is doing stupid things then. */ + unsigned u16BaseLow : 16; + /** Base address - first 8 bits of high word. */ + unsigned u8BaseHigh1 : 8; + /** Segment Type. */ + unsigned u4Type : 4; + /** Descriptor Type. System(=0) or code/data selector */ + unsigned u1DescType : 1; + /** Descriptor Privelege level. */ + unsigned u2Dpl : 2; + /** Flags selector present(=1) or not. */ + unsigned u1Present : 1; + /** Segment limit 16-19. */ + unsigned u4LimitHigh : 4; + /** Available for system software. */ + unsigned u1Available : 1; + /** Reserved - 0. */ + unsigned u1Reserved : 1; + /** This flags meaning depends on the segment type. Try make sense out + * of the intel manual yourself. */ + unsigned u1DefBig : 1; + /** Granularity of the limit. If set 4KB granularity is used, if + * clear byte. */ + unsigned u1Granularity : 1; + /** Base address - bits 31-24. */ + unsigned u8BaseHigh2 : 8; + /** Base address - bits 63-32. */ + unsigned u32BaseHigh3 : 32; + unsigned u8Reserved : 8; + unsigned u5Zeros : 5; + unsigned u19Reserved : 19; +} X86DESC64SYSTEM; +#pragma pack() +/** Pointer to a system descriptor entry. */ +typedef X86DESC64SYSTEM *PX86DESC64SYSTEM; +/** Pointer to a const system descriptor entry. */ +typedef const X86DESC64SYSTEM *PCX86DESC64SYSTEM; + +/** + * Call-, Interrupt-, Trap- or Task-gate descriptor (64-bit). + */ +typedef struct X86DESC64GATE +{ + /** Target code segment offset - Low word. */ + unsigned u16OffsetLow : 16; + /** Target code segment selector. */ + unsigned u16Sel : 16; + /** Interrupt stack table for interrupt- and trap-gates. + * Ignored by call-gates. */ + unsigned u3IST : 3; + /** Reserved / ignored. */ + unsigned u5Reserved : 5; + /** Segment Type. */ + unsigned u4Type : 4; + /** Descriptor Type (0 = system). */ + unsigned u1DescType : 1; + /** Descriptor Privelege level. */ + unsigned u2Dpl : 2; + /** Flags selector present(=1) or not. */ + unsigned u1Present : 1; + /** Target code segment offset - High word. + * Ignored if task-gate. */ + unsigned u16OffsetHigh : 16; + /** Target code segment offset - Top dword. + * Ignored if task-gate. */ + unsigned u32OffsetTop : 32; + /** Reserved / ignored / must be zero. + * For call-gates bits 8 thru 12 must be zero, the other gates ignores this. */ + unsigned u32Reserved : 32; +} X86DESC64GATE; +AssertCompileSize(X86DESC64GATE, 16); +/** Pointer to a Call-, Interrupt-, Trap- or Task-gate descriptor entry. */ +typedef X86DESC64GATE *PX86DESC64GATE; +/** Pointer to a const Call-, Interrupt-, Trap- or Task-gate descriptor entry. */ +typedef const X86DESC64GATE *PCX86DESC64GATE; + +#endif /* VBOX_FOR_DTRACE_LIB */ + +/** + * Descriptor table entry. + */ +#pragma pack(1) +typedef union X86DESC64 +{ +#ifndef VBOX_FOR_DTRACE_LIB + /** Generic descriptor view. */ + X86DESC64GENERIC Gen; + /** System descriptor view. */ + X86DESC64SYSTEM System; + /** Gate descriptor view. */ + X86DESC64GATE Gate; +#endif + + /** 8 bit unsigned integer view. */ + uint8_t au8[16]; + /** 16 bit unsigned integer view. */ + uint16_t au16[8]; + /** 32 bit unsigned integer view. */ + uint32_t au32[4]; + /** 64 bit unsigned integer view. */ + uint64_t au64[2]; +} X86DESC64; +#ifndef VBOX_FOR_DTRACE_LIB +AssertCompileSize(X86DESC64, 16); +#endif +#pragma pack() +/** Pointer to descriptor table entry. */ +typedef X86DESC64 *PX86DESC64; +/** Pointer to const descriptor table entry. */ +typedef const X86DESC64 *PCX86DESC64; + +/** @def X86DESC64_BASE + * Return the base of a 64-bit descriptor. + */ +#define X86DESC64_BASE(a_pDesc) /*ASM-NOINC*/ \ + ( ((uint64_t)((a_pDesc)->Gen.u32BaseHigh3) << 32) \ + | ((uint32_t)((a_pDesc)->Gen.u8BaseHigh2) << 24) \ + | ( (a_pDesc)->Gen.u8BaseHigh1 << 16) \ + | ( (a_pDesc)->Gen.u16BaseLow ) ) + + + +/** @name Host system descriptor table entry - Use with care! + * @{ */ +/** Host system descriptor table entry. */ +#if HC_ARCH_BITS == 64 +typedef X86DESC64 X86DESCHC; +#else +typedef X86DESC X86DESCHC; +#endif +/** Pointer to a host system descriptor table entry. */ +#if HC_ARCH_BITS == 64 +typedef PX86DESC64 PX86DESCHC; +#else +typedef PX86DESC PX86DESCHC; +#endif +/** Pointer to a const host system descriptor table entry. */ +#if HC_ARCH_BITS == 64 +typedef PCX86DESC64 PCX86DESCHC; +#else +typedef PCX86DESC PCX86DESCHC; +#endif +/** @} */ + + +/** @name Selector Descriptor Types. + * @{ + */ + +/** @name Non-System Selector Types. + * @{ */ +/** Code(=set)/Data(=clear) bit. */ +#define X86_SEL_TYPE_CODE 8 +/** Memory(=set)/System(=clear) bit. */ +#define X86_SEL_TYPE_MEMORY RT_BIT(4) +/** Accessed bit. */ +#define X86_SEL_TYPE_ACCESSED 1 +/** Expand down bit (for data selectors only). */ +#define X86_SEL_TYPE_DOWN 4 +/** Conforming bit (for code selectors only). */ +#define X86_SEL_TYPE_CONF 4 +/** Write bit (for data selectors only). */ +#define X86_SEL_TYPE_WRITE 2 +/** Read bit (for code selectors only). */ +#define X86_SEL_TYPE_READ 2 +/** The bit number of the code segment read bit (relative to u4Type). */ +#define X86_SEL_TYPE_READ_BIT 1 + +/** Read only selector type. */ +#define X86_SEL_TYPE_RO 0 +/** Accessed read only selector type. */ +#define X86_SEL_TYPE_RO_ACC (0 | X86_SEL_TYPE_ACCESSED) +/** Read write selector type. */ +#define X86_SEL_TYPE_RW 2 +/** Accessed read write selector type. */ +#define X86_SEL_TYPE_RW_ACC (2 | X86_SEL_TYPE_ACCESSED) +/** Expand down read only selector type. */ +#define X86_SEL_TYPE_RO_DOWN 4 +/** Accessed expand down read only selector type. */ +#define X86_SEL_TYPE_RO_DOWN_ACC (4 | X86_SEL_TYPE_ACCESSED) +/** Expand down read write selector type. */ +#define X86_SEL_TYPE_RW_DOWN 6 +/** Accessed expand down read write selector type. */ +#define X86_SEL_TYPE_RW_DOWN_ACC (6 | X86_SEL_TYPE_ACCESSED) +/** Execute only selector type. */ +#define X86_SEL_TYPE_EO (0 | X86_SEL_TYPE_CODE) +/** Accessed execute only selector type. */ +#define X86_SEL_TYPE_EO_ACC (0 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED) +/** Execute and read selector type. */ +#define X86_SEL_TYPE_ER (2 | X86_SEL_TYPE_CODE) +/** Accessed execute and read selector type. */ +#define X86_SEL_TYPE_ER_ACC (2 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED) +/** Conforming execute only selector type. */ +#define X86_SEL_TYPE_EO_CONF (4 | X86_SEL_TYPE_CODE) +/** Accessed Conforming execute only selector type. */ +#define X86_SEL_TYPE_EO_CONF_ACC (4 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED) +/** Conforming execute and write selector type. */ +#define X86_SEL_TYPE_ER_CONF (6 | X86_SEL_TYPE_CODE) +/** Accessed Conforming execute and write selector type. */ +#define X86_SEL_TYPE_ER_CONF_ACC (6 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED) +/** @} */ + + +/** @name System Selector Types. + * @{ */ +/** The TSS busy bit mask. */ +#define X86_SEL_TYPE_SYS_TSS_BUSY_MASK 2 + +/** Undefined system selector type. */ +#define X86_SEL_TYPE_SYS_UNDEFINED 0 +/** 286 TSS selector. */ +#define X86_SEL_TYPE_SYS_286_TSS_AVAIL 1 +/** LDT selector. */ +#define X86_SEL_TYPE_SYS_LDT 2 +/** 286 TSS selector - Busy. */ +#define X86_SEL_TYPE_SYS_286_TSS_BUSY 3 +/** 286 Callgate selector. */ +#define X86_SEL_TYPE_SYS_286_CALL_GATE 4 +/** Taskgate selector. */ +#define X86_SEL_TYPE_SYS_TASK_GATE 5 +/** 286 Interrupt gate selector. */ +#define X86_SEL_TYPE_SYS_286_INT_GATE 6 +/** 286 Trapgate selector. */ +#define X86_SEL_TYPE_SYS_286_TRAP_GATE 7 +/** Undefined system selector. */ +#define X86_SEL_TYPE_SYS_UNDEFINED2 8 +/** 386 TSS selector. */ +#define X86_SEL_TYPE_SYS_386_TSS_AVAIL 9 +/** Undefined system selector. */ +#define X86_SEL_TYPE_SYS_UNDEFINED3 0xA +/** 386 TSS selector - Busy. */ +#define X86_SEL_TYPE_SYS_386_TSS_BUSY 0xB +/** 386 Callgate selector. */ +#define X86_SEL_TYPE_SYS_386_CALL_GATE 0xC +/** Undefined system selector. */ +#define X86_SEL_TYPE_SYS_UNDEFINED4 0xD +/** 386 Interruptgate selector. */ +#define X86_SEL_TYPE_SYS_386_INT_GATE 0xE +/** 386 Trapgate selector. */ +#define X86_SEL_TYPE_SYS_386_TRAP_GATE 0xF +/** @} */ + +/** @name AMD64 System Selector Types. + * @{ */ +/** LDT selector. */ +#define AMD64_SEL_TYPE_SYS_LDT 2 +/** TSS selector - Busy. */ +#define AMD64_SEL_TYPE_SYS_TSS_AVAIL 9 +/** TSS selector - Busy. */ +#define AMD64_SEL_TYPE_SYS_TSS_BUSY 0xB +/** Callgate selector. */ +#define AMD64_SEL_TYPE_SYS_CALL_GATE 0xC +/** Interruptgate selector. */ +#define AMD64_SEL_TYPE_SYS_INT_GATE 0xE +/** Trapgate selector. */ +#define AMD64_SEL_TYPE_SYS_TRAP_GATE 0xF +/** @} */ + +/** @} */ + + +/** @name Descriptor Table Entry Flag Masks. + * These are for the 2nd 32-bit word of a descriptor. + * @{ */ +/** Bits 8-11 - TYPE - Descriptor type mask. */ +#define X86_DESC_TYPE_MASK (RT_BIT(8) | RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +/** Bit 12 - S - System (=0) or Code/Data (=1). */ +#define X86_DESC_S RT_BIT(12) +/** Bits 13-14 - DPL - Descriptor Privilege Level. */ +#define X86_DESC_DPL (RT_BIT(13) | RT_BIT(14)) +/** Bit 15 - P - Present. */ +#define X86_DESC_P RT_BIT(15) +/** Bit 20 - AVL - Available for system software. */ +#define X86_DESC_AVL RT_BIT(20) +/** Bit 22 - DB - Default operation size. 0 = 16 bit, 1 = 32 bit. */ +#define X86_DESC_DB RT_BIT(22) +/** Bit 23 - G - Granularity of the limit. If set 4KB granularity is + * used, if clear byte. */ +#define X86_DESC_G RT_BIT(23) +/** @} */ + +/** @} */ + + +/** @name Task Segments. + * @{ + */ + +/** + * 16-bit Task Segment (TSS). + */ +#pragma pack(1) +typedef struct X86TSS16 +{ + /** Back link to previous task. (static) */ + RTSEL selPrev; + /** Ring-0 stack pointer. (static) */ + uint16_t sp0; + /** Ring-0 stack segment. (static) */ + RTSEL ss0; + /** Ring-1 stack pointer. (static) */ + uint16_t sp1; + /** Ring-1 stack segment. (static) */ + RTSEL ss1; + /** Ring-2 stack pointer. (static) */ + uint16_t sp2; + /** Ring-2 stack segment. (static) */ + RTSEL ss2; + /** IP before task switch. */ + uint16_t ip; + /** FLAGS before task switch. */ + uint16_t flags; + /** AX before task switch. */ + uint16_t ax; + /** CX before task switch. */ + uint16_t cx; + /** DX before task switch. */ + uint16_t dx; + /** BX before task switch. */ + uint16_t bx; + /** SP before task switch. */ + uint16_t sp; + /** BP before task switch. */ + uint16_t bp; + /** SI before task switch. */ + uint16_t si; + /** DI before task switch. */ + uint16_t di; + /** ES before task switch. */ + RTSEL es; + /** CS before task switch. */ + RTSEL cs; + /** SS before task switch. */ + RTSEL ss; + /** DS before task switch. */ + RTSEL ds; + /** LDTR before task switch. */ + RTSEL selLdt; +} X86TSS16; +#ifndef VBOX_FOR_DTRACE_LIB +AssertCompileSize(X86TSS16, 44); +#endif +#pragma pack() +/** Pointer to a 16-bit task segment. */ +typedef X86TSS16 *PX86TSS16; +/** Pointer to a const 16-bit task segment. */ +typedef const X86TSS16 *PCX86TSS16; + + +/** + * 32-bit Task Segment (TSS). + */ +#pragma pack(1) +typedef struct X86TSS32 +{ + /** Back link to previous task. (static) */ + RTSEL selPrev; + uint16_t padding1; + /** Ring-0 stack pointer. (static) */ + uint32_t esp0; + /** Ring-0 stack segment. (static) */ + RTSEL ss0; + uint16_t padding_ss0; + /** Ring-1 stack pointer. (static) */ + uint32_t esp1; + /** Ring-1 stack segment. (static) */ + RTSEL ss1; + uint16_t padding_ss1; + /** Ring-2 stack pointer. (static) */ + uint32_t esp2; + /** Ring-2 stack segment. (static) */ + RTSEL ss2; + uint16_t padding_ss2; + /** Page directory for the task. (static) */ + uint32_t cr3; + /** EIP before task switch. */ + uint32_t eip; + /** EFLAGS before task switch. */ + uint32_t eflags; + /** EAX before task switch. */ + uint32_t eax; + /** ECX before task switch. */ + uint32_t ecx; + /** EDX before task switch. */ + uint32_t edx; + /** EBX before task switch. */ + uint32_t ebx; + /** ESP before task switch. */ + uint32_t esp; + /** EBP before task switch. */ + uint32_t ebp; + /** ESI before task switch. */ + uint32_t esi; + /** EDI before task switch. */ + uint32_t edi; + /** ES before task switch. */ + RTSEL es; + uint16_t padding_es; + /** CS before task switch. */ + RTSEL cs; + uint16_t padding_cs; + /** SS before task switch. */ + RTSEL ss; + uint16_t padding_ss; + /** DS before task switch. */ + RTSEL ds; + uint16_t padding_ds; + /** FS before task switch. */ + RTSEL fs; + uint16_t padding_fs; + /** GS before task switch. */ + RTSEL gs; + uint16_t padding_gs; + /** LDTR before task switch. */ + RTSEL selLdt; + uint16_t padding_ldt; + /** Debug trap flag */ + uint16_t fDebugTrap; + /** Offset relative to the TSS of the start of the I/O Bitmap + * and the end of the interrupt redirection bitmap. */ + uint16_t offIoBitmap; + /** 32 bytes for the virtual interrupt redirection bitmap. (VME) */ + uint8_t IntRedirBitmap[32]; +} X86TSS32; +#pragma pack() +/** Pointer to task segment. */ +typedef X86TSS32 *PX86TSS32; +/** Pointer to const task segment. */ +typedef const X86TSS32 *PCX86TSS32; + + +/** + * 64-bit Task segment. + */ +#pragma pack(1) +typedef struct X86TSS64 +{ + /** Reserved. */ + uint32_t u32Reserved; + /** Ring-0 stack pointer. (static) */ + uint64_t rsp0; + /** Ring-1 stack pointer. (static) */ + uint64_t rsp1; + /** Ring-2 stack pointer. (static) */ + uint64_t rsp2; + /** Reserved. */ + uint32_t u32Reserved2[2]; + /* IST */ + uint64_t ist1; + uint64_t ist2; + uint64_t ist3; + uint64_t ist4; + uint64_t ist5; + uint64_t ist6; + uint64_t ist7; + /* Reserved. */ + uint16_t u16Reserved[5]; + /** Offset relative to the TSS of the start of the I/O Bitmap + * and the end of the interrupt redirection bitmap. */ + uint16_t offIoBitmap; + /** 32 bytes for the virtual interrupt redirection bitmap. (VME) */ + uint8_t IntRedirBitmap[32]; +} X86TSS64; +#pragma pack() +/** Pointer to a 64-bit task segment. */ +typedef X86TSS64 *PX86TSS64; +/** Pointer to a const 64-bit task segment. */ +typedef const X86TSS64 *PCX86TSS64; +#ifndef VBOX_FOR_DTRACE_LIB +AssertCompileSize(X86TSS64, 136); +#endif + +/** @} */ + + +/** @name Selectors. + * @{ + */ + +/** + * The shift used to convert a selector from and to index an index (C). + */ +#define X86_SEL_SHIFT 3 + +/** + * The mask used to mask off the table indicator and RPL of an selector. + */ +#define X86_SEL_MASK 0xfff8U + +/** + * The mask used to mask off the RPL of an selector. + * This is suitable for checking for NULL selectors. + */ +#define X86_SEL_MASK_OFF_RPL 0xfffcU + +/** + * The bit indicating that a selector is in the LDT and not in the GDT. + */ +#define X86_SEL_LDT 0x0004U + +/** + * The bit mask for getting the RPL of a selector. + */ +#define X86_SEL_RPL 0x0003U + +/** + * The mask covering both RPL and LDT. + * This is incidentally the same as sizeof(X86DESC) - 1, so good for limit + * checks. + */ +#define X86_SEL_RPL_LDT 0x0007U + +/** @} */ + + +/** + * x86 Exceptions/Faults/Traps. + */ +typedef enum X86XCPT +{ + /** \#DE - Divide error. */ + X86_XCPT_DE = 0x00, + /** \#DB - Debug event (single step, DRx, ..) */ + X86_XCPT_DB = 0x01, + /** NMI - Non-Maskable Interrupt */ + X86_XCPT_NMI = 0x02, + /** \#BP - Breakpoint (INT3). */ + X86_XCPT_BP = 0x03, + /** \#OF - Overflow (INTO). */ + X86_XCPT_OF = 0x04, + /** \#BR - Bound range exceeded (BOUND). */ + X86_XCPT_BR = 0x05, + /** \#UD - Undefined opcode. */ + X86_XCPT_UD = 0x06, + /** \#NM - Device not available (math coprocessor device). */ + X86_XCPT_NM = 0x07, + /** \#DF - Double fault. */ + X86_XCPT_DF = 0x08, + /** ??? - Coprocessor segment overrun (obsolete). */ + X86_XCPT_CO_SEG_OVERRUN = 0x09, + /** \#TS - Taskswitch (TSS). */ + X86_XCPT_TS = 0x0a, + /** \#NP - Segment no present. */ + X86_XCPT_NP = 0x0b, + /** \#SS - Stack segment fault. */ + X86_XCPT_SS = 0x0c, + /** \#GP - General protection fault. */ + X86_XCPT_GP = 0x0d, + /** \#PF - Page fault. */ + X86_XCPT_PF = 0x0e, + /* 0x0f is reserved. */ + /** \#MF - Math fault (FPU). */ + X86_XCPT_MF = 0x10, + /** \#AC - Alignment check. */ + X86_XCPT_AC = 0x11, + /** \#MC - Machine check. */ + X86_XCPT_MC = 0x12, + /** \#XF - SIMD Floating-Pointer Exception. */ + X86_XCPT_XF = 0x13 +} X86XCPT; +/** Pointer to a x86 exception code. */ +typedef X86XCPT *PX86XCPT; +/** Pointer to a const x86 exception code. */ +typedef const X86XCPT *PCX86XCPT; + + +/** @name Trap Error Codes + * @{ + */ +/** External indicator. */ +#define X86_TRAP_ERR_EXTERNAL 1 +/** IDT indicator. */ +#define X86_TRAP_ERR_IDT 2 +/** Descriptor table indicator - If set LDT, if clear GDT. */ +#define X86_TRAP_ERR_TI 4 +/** Mask for getting the selector. */ +#define X86_TRAP_ERR_SEL_MASK 0xfff8 +/** Shift for getting the selector table index (C type index). */ +#define X86_TRAP_ERR_SEL_SHIFT 3 +/** @} */ + + +/** @name \#PF Trap Error Codes + * @{ + */ +/** Bit 0 - P - Not present (clear) or page level protection (set) fault. */ +#define X86_TRAP_PF_P RT_BIT(0) +/** Bit 1 - R/W - Read (clear) or write (set) access. */ +#define X86_TRAP_PF_RW RT_BIT(1) +/** Bit 2 - U/S - CPU executing in user mode (set) or supervisor mode (clear). */ +#define X86_TRAP_PF_US RT_BIT(2) +/** Bit 3 - RSVD- Reserved bit violation (set), i.e. reserved bit was set to 1. */ +#define X86_TRAP_PF_RSVD RT_BIT(3) +/** Bit 4 - I/D - Instruction fetch (set) / Data access (clear) - PAE + NXE. */ +#define X86_TRAP_PF_ID RT_BIT(4) +/** @} */ + +#pragma pack(1) +/** + * 32-bit IDTR/GDTR. + */ +typedef struct X86XDTR32 +{ + /** Size of the descriptor table. */ + uint16_t cb; + /** Address of the descriptor table. */ +#ifndef VBOX_FOR_DTRACE_LIB + uint32_t uAddr; +#else + uint16_t au16Addr[2]; +#endif +} X86XDTR32, *PX86XDTR32; +#pragma pack() + +#pragma pack(1) +/** + * 64-bit IDTR/GDTR. + */ +typedef struct X86XDTR64 +{ + /** Size of the descriptor table. */ + uint16_t cb; + /** Address of the descriptor table. */ +#ifndef VBOX_FOR_DTRACE_LIB + uint64_t uAddr; +#else + uint16_t au16Addr[4]; +#endif +} X86XDTR64, *PX86XDTR64; +#pragma pack() + + +/** @name ModR/M + * @{ */ +#define X86_MODRM_RM_MASK UINT8_C(0x07) +#define X86_MODRM_REG_MASK UINT8_C(0x38) +#define X86_MODRM_REG_SMASK UINT8_C(0x07) +#define X86_MODRM_REG_SHIFT 3 +#define X86_MODRM_MOD_MASK UINT8_C(0xc0) +#define X86_MODRM_MOD_SMASK UINT8_C(0x03) +#define X86_MODRM_MOD_SHIFT 6 +#ifndef VBOX_FOR_DTRACE_LIB +AssertCompile((X86_MODRM_RM_MASK | X86_MODRM_REG_MASK | X86_MODRM_MOD_MASK) == 0xff); +AssertCompile((X86_MODRM_REG_MASK >> X86_MODRM_REG_SHIFT) == X86_MODRM_REG_SMASK); +AssertCompile((X86_MODRM_MOD_MASK >> X86_MODRM_MOD_SHIFT) == X86_MODRM_MOD_SMASK); +#endif +/** @} */ + +/** @name SIB + * @{ */ +#define X86_SIB_BASE_MASK UINT8_C(0x07) +#define X86_SIB_INDEX_MASK UINT8_C(0x38) +#define X86_SIB_INDEX_SMASK UINT8_C(0x07) +#define X86_SIB_INDEX_SHIFT 3 +#define X86_SIB_SCALE_MASK UINT8_C(0xc0) +#define X86_SIB_SCALE_SMASK UINT8_C(0x03) +#define X86_SIB_SCALE_SHIFT 6 +#ifndef VBOX_FOR_DTRACE_LIB +AssertCompile((X86_SIB_BASE_MASK | X86_SIB_INDEX_MASK | X86_SIB_SCALE_MASK) == 0xff); +AssertCompile((X86_SIB_INDEX_MASK >> X86_SIB_INDEX_SHIFT) == X86_SIB_INDEX_SMASK); +AssertCompile((X86_SIB_SCALE_MASK >> X86_SIB_SCALE_SHIFT) == X86_SIB_SCALE_SMASK); +#endif +/** @} */ + +/** @name General register indexes + * @{ */ +#define X86_GREG_xAX 0 +#define X86_GREG_xCX 1 +#define X86_GREG_xDX 2 +#define X86_GREG_xBX 3 +#define X86_GREG_xSP 4 +#define X86_GREG_xBP 5 +#define X86_GREG_xSI 6 +#define X86_GREG_xDI 7 +#define X86_GREG_x8 8 +#define X86_GREG_x9 9 +#define X86_GREG_x10 10 +#define X86_GREG_x11 11 +#define X86_GREG_x12 12 +#define X86_GREG_x13 13 +#define X86_GREG_x14 14 +#define X86_GREG_x15 15 +/** @} */ + +/** @name X86_SREG_XXX - Segment register indexes. + * @{ */ +#define X86_SREG_ES 0 +#define X86_SREG_CS 1 +#define X86_SREG_SS 2 +#define X86_SREG_DS 3 +#define X86_SREG_FS 4 +#define X86_SREG_GS 5 +/** @} */ +/** Segment register count. */ +#define X86_SREG_COUNT 6 + + +/** @} */ + +#endif + diff --git a/include/iprt/x86.mac b/include/iprt/x86.mac new file mode 100644 index 00000000..d9765261 --- /dev/null +++ b/include/iprt/x86.mac @@ -0,0 +1,706 @@ +%ifndef ___iprt_x86_h +%define ___iprt_x86_h +%ifndef VBOX_FOR_DTRACE_LIB +%else +%endif +%ifdef RT_OS_SOLARIS +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%define X86_EFL_CF RT_BIT(0) +%define X86_EFL_1 RT_BIT(1) +%define X86_EFL_PF RT_BIT(2) +%define X86_EFL_AF RT_BIT(4) +%define X86_EFL_ZF RT_BIT(6) +%define X86_EFL_SF RT_BIT(7) +%define X86_EFL_TF RT_BIT(8) +%define X86_EFL_IF RT_BIT(9) +%define X86_EFL_DF RT_BIT(10) +%define X86_EFL_OF RT_BIT(11) +%define X86_EFL_IOPL (RT_BIT(12) | RT_BIT(13)) +%define X86_EFL_NT RT_BIT(14) +%define X86_EFL_RF RT_BIT(16) +%define X86_EFL_VM RT_BIT(17) +%define X86_EFL_AC RT_BIT(18) +%define X86_EFL_VIF RT_BIT(19) +%define X86_EFL_VIP RT_BIT(20) +%define X86_EFL_ID RT_BIT(21) +%define X86_EFL_IOPL_SHIFT 12 +%define X86_EFL_GET_IOPL(efl) (((efl) >> X86_EFL_IOPL_SHIFT) & 3) +%define X86_EFL_POPF_BITS (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT | X86_EFL_AC | X86_EFL_ID) +%ifndef VBOX_FOR_DTRACE_LIB +%else +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%else +%endif +%define X86_CPUID_VENDOR_INTEL_EBX 0x756e6547 +%define X86_CPUID_VENDOR_INTEL_ECX 0x6c65746e +%define X86_CPUID_VENDOR_INTEL_EDX 0x49656e69 +%define X86_CPUID_VENDOR_AMD_EBX 0x68747541 +%define X86_CPUID_VENDOR_AMD_ECX 0x444d4163 +%define X86_CPUID_VENDOR_AMD_EDX 0x69746e65 +%define X86_CPUID_VENDOR_VIA_EBX 0x746e6543 +%define X86_CPUID_VENDOR_VIA_ECX 0x736c7561 +%define X86_CPUID_VENDOR_VIA_EDX 0x48727561 +%define X86_CPUID_FEATURE_ECX_SSE3 RT_BIT(0) +%define X86_CPUID_FEATURE_ECX_PCLMUL RT_BIT(1) +%define X86_CPUID_FEATURE_ECX_DTES64 RT_BIT(2) +%define X86_CPUID_FEATURE_ECX_MONITOR RT_BIT(3) +%define X86_CPUID_FEATURE_ECX_CPLDS RT_BIT(4) +%define X86_CPUID_FEATURE_ECX_VMX RT_BIT(5) +%define X86_CPUID_FEATURE_ECX_SMX RT_BIT(6) +%define X86_CPUID_FEATURE_ECX_EST RT_BIT(7) +%define X86_CPUID_FEATURE_ECX_TM2 RT_BIT(8) +%define X86_CPUID_FEATURE_ECX_SSSE3 RT_BIT(9) +%define X86_CPUID_FEATURE_ECX_CNTXID RT_BIT(10) +%define X86_CPUID_FEATURE_ECX_FMA RT_BIT(12) +%define X86_CPUID_FEATURE_ECX_CX16 RT_BIT(13) +%define X86_CPUID_FEATURE_ECX_TPRUPDATE RT_BIT(14) +%define X86_CPUID_FEATURE_ECX_PDCM RT_BIT(15) +%define X86_CPUID_FEATURE_ECX_PCID RT_BIT(17) +%define X86_CPUID_FEATURE_ECX_DCA RT_BIT(18) +%define X86_CPUID_FEATURE_ECX_SSE4_1 RT_BIT(19) +%define X86_CPUID_FEATURE_ECX_SSE4_2 RT_BIT(20) +%define X86_CPUID_FEATURE_ECX_X2APIC RT_BIT(21) +%define X86_CPUID_FEATURE_ECX_MOVBE RT_BIT(22) +%define X86_CPUID_FEATURE_ECX_POPCNT RT_BIT(23) +%define X86_CPUID_FEATURE_ECX_TSCDEADL RT_BIT(24) +%define X86_CPUID_FEATURE_ECX_AES RT_BIT(25) +%define X86_CPUID_FEATURE_ECX_XSAVE RT_BIT(26) +%define X86_CPUID_FEATURE_ECX_OSXSAVE RT_BIT(27) +%define X86_CPUID_FEATURE_ECX_AVX RT_BIT(28) +%define X86_CPUID_FEATURE_ECX_HVP RT_BIT(31) +%define X86_CPUID_FEATURE_EDX_FPU RT_BIT(0) +%define X86_CPUID_FEATURE_EDX_VME RT_BIT(1) +%define X86_CPUID_FEATURE_EDX_DE RT_BIT(2) +%define X86_CPUID_FEATURE_EDX_PSE RT_BIT(3) +%define X86_CPUID_FEATURE_EDX_TSC RT_BIT(4) +%define X86_CPUID_FEATURE_EDX_MSR RT_BIT(5) +%define X86_CPUID_FEATURE_EDX_PAE RT_BIT(6) +%define X86_CPUID_FEATURE_EDX_MCE RT_BIT(7) +%define X86_CPUID_FEATURE_EDX_CX8 RT_BIT(8) +%define X86_CPUID_FEATURE_EDX_APIC RT_BIT(9) +%define X86_CPUID_FEATURE_EDX_SEP RT_BIT(11) +%define X86_CPUID_FEATURE_EDX_MTRR RT_BIT(12) +%define X86_CPUID_FEATURE_EDX_PGE RT_BIT(13) +%define X86_CPUID_FEATURE_EDX_MCA RT_BIT(14) +%define X86_CPUID_FEATURE_EDX_CMOV RT_BIT(15) +%define X86_CPUID_FEATURE_EDX_PAT RT_BIT(16) +%define X86_CPUID_FEATURE_EDX_PSE36 RT_BIT(17) +%define X86_CPUID_FEATURE_EDX_PSN RT_BIT(18) +%define X86_CPUID_FEATURE_EDX_CLFSH RT_BIT(19) +%define X86_CPUID_FEATURE_EDX_DS RT_BIT(21) +%define X86_CPUID_FEATURE_EDX_ACPI RT_BIT(22) +%define X86_CPUID_FEATURE_EDX_MMX RT_BIT(23) +%define X86_CPUID_FEATURE_EDX_FXSR RT_BIT(24) +%define X86_CPUID_FEATURE_EDX_SSE RT_BIT(25) +%define X86_CPUID_FEATURE_EDX_SSE2 RT_BIT(26) +%define X86_CPUID_FEATURE_EDX_SS RT_BIT(27) +%define X86_CPUID_FEATURE_EDX_HTT RT_BIT(28) +%define X86_CPUID_FEATURE_EDX_TM RT_BIT(29) +%define X86_CPUID_FEATURE_EDX_PBE RT_BIT(31) +%define X86_CPUID_MWAIT_ECX_EXT RT_BIT(0) +%define X86_CPUID_MWAIT_ECX_BREAKIRQIF0 RT_BIT(1) +%define X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF RT_BIT(0) +%define X86_CPUID_EXT_FEATURE_EDX_SYSCALL RT_BIT(11) +%define X86_CPUID_EXT_FEATURE_EDX_NX RT_BIT(20) +%define X86_CPUID_EXT_FEATURE_EDX_PAGE1GB RT_BIT(26) +%define X86_CPUID_EXT_FEATURE_EDX_RDTSCP RT_BIT(27) +%define X86_CPUID_EXT_FEATURE_EDX_LONG_MODE RT_BIT(29) +%define X86_CPUID_AMD_FEATURE_EDX_FPU RT_BIT(0) +%define X86_CPUID_AMD_FEATURE_EDX_VME RT_BIT(1) +%define X86_CPUID_AMD_FEATURE_EDX_DE RT_BIT(2) +%define X86_CPUID_AMD_FEATURE_EDX_PSE RT_BIT(3) +%define X86_CPUID_AMD_FEATURE_EDX_TSC RT_BIT(4) +%define X86_CPUID_AMD_FEATURE_EDX_MSR RT_BIT(5) +%define X86_CPUID_AMD_FEATURE_EDX_PAE RT_BIT(6) +%define X86_CPUID_AMD_FEATURE_EDX_MCE RT_BIT(7) +%define X86_CPUID_AMD_FEATURE_EDX_CX8 RT_BIT(8) +%define X86_CPUID_AMD_FEATURE_EDX_APIC RT_BIT(9) +%define X86_CPUID_AMD_FEATURE_EDX_MTRR RT_BIT(12) +%define X86_CPUID_AMD_FEATURE_EDX_PGE RT_BIT(13) +%define X86_CPUID_AMD_FEATURE_EDX_MCA RT_BIT(14) +%define X86_CPUID_AMD_FEATURE_EDX_CMOV RT_BIT(15) +%define X86_CPUID_AMD_FEATURE_EDX_PAT RT_BIT(16) +%define X86_CPUID_AMD_FEATURE_EDX_PSE36 RT_BIT(17) +%define X86_CPUID_AMD_FEATURE_EDX_AXMMX RT_BIT(22) +%define X86_CPUID_AMD_FEATURE_EDX_MMX RT_BIT(23) +%define X86_CPUID_AMD_FEATURE_EDX_FXSR RT_BIT(24) +%define X86_CPUID_AMD_FEATURE_EDX_FFXSR RT_BIT(25) +%define X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX RT_BIT(30) +%define X86_CPUID_AMD_FEATURE_EDX_3DNOW RT_BIT(31) +%define X86_CPUID_AMD_FEATURE_ECX_CMPL RT_BIT(1) +%define X86_CPUID_AMD_FEATURE_ECX_SVM RT_BIT(2) +%define X86_CPUID_AMD_FEATURE_ECX_EXT_APIC RT_BIT(3) +%define X86_CPUID_AMD_FEATURE_ECX_CR8L RT_BIT(4) +%define X86_CPUID_AMD_FEATURE_ECX_ABM RT_BIT(5) +%define X86_CPUID_AMD_FEATURE_ECX_SSE4A RT_BIT(6) +%define X86_CPUID_AMD_FEATURE_ECX_MISALNSSE RT_BIT(7) +%define X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF RT_BIT(8) +%define X86_CPUID_AMD_FEATURE_ECX_OSVW RT_BIT(9) +%define X86_CPUID_AMD_FEATURE_ECX_IBS RT_BIT(10) +%define X86_CPUID_AMD_FEATURE_ECX_SSE5 RT_BIT(11) +%define X86_CPUID_AMD_FEATURE_ECX_SKINIT RT_BIT(12) +%define X86_CPUID_AMD_FEATURE_ECX_WDT RT_BIT(13) +%define X86_CPUID_AMD_ADVPOWER_EDX_TS RT_BIT(0) +%define X86_CPUID_AMD_ADVPOWER_EDX_FID RT_BIT(1) +%define X86_CPUID_AMD_ADVPOWER_EDX_VID RT_BIT(2) +%define X86_CPUID_AMD_ADVPOWER_EDX_TTP RT_BIT(3) +%define X86_CPUID_AMD_ADVPOWER_EDX_TM RT_BIT(4) +%define X86_CPUID_AMD_ADVPOWER_EDX_STC RT_BIT(5) +%define X86_CPUID_AMD_ADVPOWER_EDX_MC RT_BIT(6) +%define X86_CPUID_AMD_ADVPOWER_EDX_HWPSTATE RT_BIT(7) +%define X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR RT_BIT(8) +%define X86_CR0_PE RT_BIT(0) +%define X86_CR0_PROTECTION_ENABLE RT_BIT(0) +%define X86_CR0_MP RT_BIT(1) +%define X86_CR0_MONITOR_COPROCESSOR RT_BIT(1) +%define X86_CR0_EM RT_BIT(2) +%define X86_CR0_EMULATE_FPU RT_BIT(2) +%define X86_CR0_TS RT_BIT(3) +%define X86_CR0_TASK_SWITCH RT_BIT(3) +%define X86_CR0_ET RT_BIT(4) +%define X86_CR0_EXTENSION_TYPE RT_BIT(4) +%define X86_CR0_NE RT_BIT(5) +%define X86_CR0_NUMERIC_ERROR RT_BIT(5) +%define X86_CR0_WP RT_BIT(16) +%define X86_CR0_WRITE_PROTECT RT_BIT(16) +%define X86_CR0_AM RT_BIT(18) +%define X86_CR0_ALIGMENT_MASK RT_BIT(18) +%define X86_CR0_NW RT_BIT(29) +%define X86_CR0_NOT_WRITE_THROUGH RT_BIT(29) +%define X86_CR0_CD RT_BIT(30) +%define X86_CR0_CACHE_DISABLE RT_BIT(30) +%define X86_CR0_PG RT_BIT(31) +%define X86_CR0_PAGING RT_BIT(31) +%define X86_CR3_PWT RT_BIT(3) +%define X86_CR3_PCD RT_BIT(4) +%define X86_CR3_PAGE_MASK (0xfffff000) +%define X86_CR3_PAE_PAGE_MASK (0xffffffe0) +%define X86_CR3_AMD64_PAGE_MASK 0x000ffffffffff000 +%define X86_CR4_VME RT_BIT(0) +%define X86_CR4_PVI RT_BIT(1) +%define X86_CR4_TSD RT_BIT(2) +%define X86_CR4_DE RT_BIT(3) +%define X86_CR4_PSE RT_BIT(4) +%define X86_CR4_PAE RT_BIT(5) +%define X86_CR4_MCE RT_BIT(6) +%define X86_CR4_PGE RT_BIT(7) +%define X86_CR4_PCE RT_BIT(8) +%define X86_CR4_OSFSXR RT_BIT(9) +%define X86_CR4_OSXMMEEXCPT RT_BIT(10) +%define X86_CR4_VMXE RT_BIT(13) +%define X86_CR4_SMXE RT_BIT(14) +%define X86_CR4_PCIDE RT_BIT(17) +%define X86_CR4_OSXSAVE RT_BIT(18) +%define X86_CR4_SMEP RT_BIT(20) +%define X86_DR6_B0 RT_BIT(0) +%define X86_DR6_B1 RT_BIT(1) +%define X86_DR6_B2 RT_BIT(2) +%define X86_DR6_B3 RT_BIT(3) +%define X86_DR6_BD RT_BIT(13) +%define X86_DR6_BS RT_BIT(14) +%define X86_DR6_BT RT_BIT(15) +%define X86_DR6_INIT_VAL 0xFFFF0FF0 +%define X86_DR7_L0 RT_BIT(0) +%define X86_DR7_G0 RT_BIT(1) +%define X86_DR7_L1 RT_BIT(2) +%define X86_DR7_G1 RT_BIT(3) +%define X86_DR7_L2 RT_BIT(4) +%define X86_DR7_G2 RT_BIT(5) +%define X86_DR7_L3 RT_BIT(6) +%define X86_DR7_G3 RT_BIT(7) +%define X86_DR7_LE RT_BIT(8) +%define X86_DR7_GE RT_BIT(9) +%define X86_DR7_GD RT_BIT(13) +%define X86_DR7_RW0_MASK (3 << 16) +%define X86_DR7_LEN0_MASK (3 << 18) +%define X86_DR7_RW1_MASK (3 << 20) +%define X86_DR7_LEN1_MASK (3 << 22) +%define X86_DR7_RW2_MASK (3 << 24) +%define X86_DR7_LEN2_MASK (3 << 26) +%define X86_DR7_RW3_MASK (3 << 28) +%define X86_DR7_LEN3_MASK (3 << 30) +%define X86_DR7_MB1_MASK (RT_BIT(10)) +%define X86_DR7_L(iBp) ( 1 << (iBp * 2) ) +%define X86_DR7_G(iBp) ( 1 << (iBp * 2 + 1) ) +%define X86_DR7_RW_EO 0 +%define X86_DR7_RW_WO 1 +%define X86_DR7_RW_IO 2 +%define X86_DR7_RW_RW 3 +%define X86_DR7_RW(iBp, fRw) ( (fRw) << ((iBp) * 4 + 16) ) +%define X86_DR7_LEN_BYTE 0 +%define X86_DR7_LEN_WORD 1 +%define X86_DR7_LEN_QWORD 2 +%define X86_DR7_LEN_DWORD 3 +%define X86_DR7_LEN(iBp, cb) ( (cb) << ((iBp) * 4 + 18) ) +%define X86_DR7_GET_LEN(uDR7, iBp) ( ( (uDR7) >> ((iBp) * 4 + 18) ) & 0x3) +%define X86_DR7_ENABLED_MASK (RT_BIT(0) | RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7)) +%define X86_DR7_IO_ENABLED_MASK (X86_DR7_RW(0, X86_DR7_RW_IO) | X86_DR7_RW(1, X86_DR7_RW_IO) | X86_DR7_RW(2, X86_DR7_RW_IO) | X86_DR7_RW(3, X86_DR7_RW_IO)) +%define X86_DR7_INIT_VAL 0x400 +%define MSR_IA32_TSC 0x10 +%define MSR_IA32_PLATFORM_ID 0x17 +%ifndef MSR_IA32_APICBASE +%define MSR_IA32_APICBASE 0x1b +%endif +%define MSR_IA32_FEATURE_CONTROL 0x3A +%define MSR_IA32_FEATURE_CONTROL_LOCK RT_BIT(0) +%define MSR_IA32_FEATURE_CONTROL_VMXON RT_BIT(2) +%define MSR_IA32_BIOS_UPDT_TRIG 0x79 +%define MSR_IA32_BIOS_SIGN_ID 0x8B +%define MSR_IA32_PMC0 0xC1 +%define MSR_IA32_PMC1 0xC2 +%define MSR_IA32_PMC2 0xC3 +%define MSR_IA32_PMC3 0xC4 +%define MSR_IA32_PLATFORM_INFO 0xCE +%define MSR_IA32_FSB_CLOCK_STS 0xCD +%define MSR_IA32_MTRR_CAP 0xFE +%ifndef MSR_IA32_SYSENTER_CS +%define MSR_IA32_SYSENTER_CS 0x174 +%define MSR_IA32_SYSENTER_ESP 0x175 +%define MSR_IA32_SYSENTER_EIP 0x176 +%endif +%define MSR_IA32_MCP_CAP 0x179 +%define MSR_IA32_MCP_STATUS 0x17A +%define MSR_IA32_MCP_CTRL 0x17B +%define MSR_IA32_DEBUGCTL 0x1D9 +%define MSR_IA32_CR_PAT 0x277 +%define MSR_IA32_PERFEVTSEL0 0x186 +%define MSR_IA32_PERFEVTSEL1 0x187 +%define MSR_IA32_FLEX_RATIO 0x194 +%define MSR_IA32_PERF_STATUS 0x198 +%define MSR_IA32_PERF_CTL 0x199 +%define MSR_IA32_THERM_STATUS 0x19c +%define MSR_IA32_MISC_ENABLE 0x1A0 +%define MSR_IA32_MISC_ENABLE_FAST_STRINGS RT_BIT(0) +%define MSR_IA32_MISC_ENABLE_TCC RT_BIT(3) +%define MSR_IA32_MISC_ENABLE_PERF_MON RT_BIT(7) +%define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL RT_BIT(11) +%define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL RT_BIT(12) +%define MSR_IA32_MISC_ENABLE_SST_ENABLE RT_BIT(16) +%define MSR_IA32_MISC_ENABLE_MONITOR RT_BIT(18) +%define MSR_IA32_MISC_ENABLE_LIMIT_CPUID RT_BIT(22) +%define MSR_IA32_MISC_ENABLE_XTPR_MSG_DISABLE RT_BIT(23) +%define MSR_IA32_MISC_ENABLE_XD_DISABLE RT_BIT(34) +%define IA32_MTRR_PHYSBASE0 0x200 +%define IA32_MTRR_PHYSMASK0 0x201 +%define IA32_MTRR_PHYSBASE1 0x202 +%define IA32_MTRR_PHYSMASK1 0x203 +%define IA32_MTRR_PHYSBASE2 0x204 +%define IA32_MTRR_PHYSMASK2 0x205 +%define IA32_MTRR_PHYSBASE3 0x206 +%define IA32_MTRR_PHYSMASK3 0x207 +%define IA32_MTRR_PHYSBASE4 0x208 +%define IA32_MTRR_PHYSMASK4 0x209 +%define IA32_MTRR_PHYSBASE5 0x20a +%define IA32_MTRR_PHYSMASK5 0x20b +%define IA32_MTRR_PHYSBASE6 0x20c +%define IA32_MTRR_PHYSMASK6 0x20d +%define IA32_MTRR_PHYSBASE7 0x20e +%define IA32_MTRR_PHYSMASK7 0x20f +%define IA32_MTRR_PHYSBASE8 0x210 +%define IA32_MTRR_PHYSMASK8 0x211 +%define IA32_MTRR_PHYSBASE9 0x212 +%define IA32_MTRR_PHYSMASK9 0x213 +%define IA32_MTRR_FIX64K_00000 0x250 +%define IA32_MTRR_FIX16K_80000 0x258 +%define IA32_MTRR_FIX16K_A0000 0x259 +%define IA32_MTRR_FIX4K_C0000 0x268 +%define IA32_MTRR_FIX4K_C8000 0x269 +%define IA32_MTRR_FIX4K_D0000 0x26a +%define IA32_MTRR_FIX4K_D8000 0x26b +%define IA32_MTRR_FIX4K_E0000 0x26c +%define IA32_MTRR_FIX4K_E8000 0x26d +%define IA32_MTRR_FIX4K_F0000 0x26e +%define IA32_MTRR_FIX4K_F8000 0x26f +%define MSR_IA32_MTRR_DEF_TYPE 0x2FF +%define MSR_IA32_MC0_CTL 0x400 +%define MSR_IA32_MC0_STATUS 0x401 +%define MSR_IA32_VMX_BASIC_INFO 0x480 +%define MSR_IA32_VMX_PINBASED_CTLS 0x481 +%define MSR_IA32_VMX_PROCBASED_CTLS 0x482 +%define MSR_IA32_VMX_EXIT_CTLS 0x483 +%define MSR_IA32_VMX_ENTRY_CTLS 0x484 +%define MSR_IA32_VMX_MISC 0x485 +%define MSR_IA32_VMX_CR0_FIXED0 0x486 +%define MSR_IA32_VMX_CR0_FIXED1 0x487 +%define MSR_IA32_VMX_CR4_FIXED0 0x488 +%define MSR_IA32_VMX_CR4_FIXED1 0x489 +%define MSR_IA32_VMX_VMCS_ENUM 0x48A +%define MSR_IA32_VMX_PROCBASED_CTLS2 0x48B +%define MSR_IA32_VMX_EPT_CAPS 0x48C +%define MSR_IA32_DS_AREA 0x600 +%define MSR_IA32_APIC_START 0x800 +%define MSR_IA32_APIC_END 0x900 +%define MSR_K6_EFER 0xc0000080 +%define MSR_K6_EFER_SCE RT_BIT(0) +%define MSR_K6_EFER_LME RT_BIT(8) +%define MSR_K6_EFER_LMA RT_BIT(10) +%define MSR_K6_EFER_NXE RT_BIT(11) +%define MSR_K6_EFER_SVME RT_BIT(12) +%define MSR_K6_EFER_LMSLE RT_BIT(13) +%define MSR_K6_EFER_FFXSR RT_BIT(14) +%define MSR_K6_STAR 0xc0000081 +%define MSR_K6_STAR_SYSRET_CS_SS_SHIFT 48 +%define MSR_K6_STAR_SYSCALL_CS_SS_SHIFT 32 +%define MSR_K6_STAR_SEL_MASK 0xffff +%define MSR_K6_STAR_SYSCALL_EIP_MASK 0xffffffff +%define MSR_K6_WHCR 0xc0000082 +%define MSR_K6_UWCCR 0xc0000085 +%define MSR_K6_PSOR 0xc0000087 +%define MSR_K6_PFIR 0xc0000088 +%define MSR_K7_EVNTSEL0 0xc0010000 +%define MSR_K7_EVNTSEL1 0xc0010001 +%define MSR_K7_EVNTSEL2 0xc0010002 +%define MSR_K7_EVNTSEL3 0xc0010003 +%define MSR_K7_PERFCTR0 0xc0010004 +%define MSR_K7_PERFCTR1 0xc0010005 +%define MSR_K7_PERFCTR2 0xc0010006 +%define MSR_K7_PERFCTR3 0xc0010007 +%define MSR_K8_LSTAR 0xc0000082 +%define MSR_K8_CSTAR 0xc0000083 +%define MSR_K8_SF_MASK 0xc0000084 +%define MSR_K8_FS_BASE 0xc0000100 +%define MSR_K8_GS_BASE 0xc0000101 +%define MSR_K8_KERNEL_GS_BASE 0xc0000102 +%define MSR_K8_TSC_AUX 0xc0000103 +%define MSR_K8_SYSCFG 0xc0010010 +%define MSR_K8_HWCR 0xc0010015 +%define MSR_K8_IORRBASE0 0xc0010016 +%define MSR_K8_IORRMASK0 0xc0010017 +%define MSR_K8_IORRBASE1 0xc0010018 +%define MSR_K8_IORRMASK1 0xc0010019 +%define MSR_K8_TOP_MEM1 0xc001001a +%define MSR_K8_TOP_MEM2 0xc001001d +%define MSR_K8_VM_CR 0xc0010114 +%define MSR_K8_VM_CR_SVM_DISABLE RT_BIT(4) +%define MSR_K8_IGNNE 0xc0010115 +%define MSR_K8_SMM_CTL 0xc0010116 +%define MSR_K8_VM_HSAVE_PA 0xc0010117 +%define X86_PG_ENTRIES 1024 +%define X86_PG_PAE_ENTRIES 512 +%define X86_PG_PAE_PDPE_ENTRIES 4 +%define X86_PG_AMD64_ENTRIES X86_PG_PAE_ENTRIES +%define X86_PG_AMD64_PDPE_ENTRIES X86_PG_AMD64_ENTRIES +%define X86_PAGE_4K_SIZE _4K +%define X86_PAGE_4K_SHIFT 12 +%define X86_PAGE_4K_OFFSET_MASK 0xfff +%define X86_PAGE_4K_BASE_MASK 0xfffffffffffff000 +%define X86_PAGE_4K_BASE_MASK_32 0xfffff000 +%define X86_PAGE_2M_SIZE _2M +%define X86_PAGE_2M_SHIFT 21 +%define X86_PAGE_2M_OFFSET_MASK 0x001fffff +%define X86_PAGE_2M_BASE_MASK 0xffffffffffe00000 +%define X86_PAGE_2M_BASE_MASK_32 0xffe00000 +%define X86_PAGE_4M_SIZE _4M +%define X86_PAGE_4M_SHIFT 22 +%define X86_PAGE_4M_OFFSET_MASK 0x003fffff +%define X86_PAGE_4M_BASE_MASK 0xffffffffffc00000 +%define X86_PAGE_4M_BASE_MASK_32 0xffc00000 +%define X86_PTE_BIT_P 0 +%define X86_PTE_BIT_RW 1 +%define X86_PTE_BIT_US 2 +%define X86_PTE_BIT_PWT 3 +%define X86_PTE_BIT_PCD 4 +%define X86_PTE_BIT_A 5 +%define X86_PTE_BIT_D 6 +%define X86_PTE_BIT_PAT 7 +%define X86_PTE_BIT_G 8 +%define X86_PTE_P RT_BIT(0) +%define X86_PTE_RW RT_BIT(1) +%define X86_PTE_US RT_BIT(2) +%define X86_PTE_PWT RT_BIT(3) +%define X86_PTE_PCD RT_BIT(4) +%define X86_PTE_A RT_BIT(5) +%define X86_PTE_D RT_BIT(6) +%define X86_PTE_PAT RT_BIT(7) +%define X86_PTE_G RT_BIT(8) +%define X86_PTE_AVL_MASK (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +%define X86_PTE_PG_MASK ( 0xfffff000 ) +%define X86_PTE_PAE_PG_MASK 0x000ffffffffff000 +%define X86_PTE_PAE_NX RT_BIT_64(63) +%define X86_PTE_PAE_MBZ_MASK_NX 0x7ff0000000000000 +%define X86_PTE_PAE_MBZ_MASK_NO_NX 0xfff0000000000000 +%define X86_PTE_LM_MBZ_MASK_NX 0x0000000000000000 +%define X86_PTE_LM_MBZ_MASK_NO_NX 0x8000000000000000 +%define X86_PT_SHIFT 12 +%define X86_PT_MASK 0x3ff +%define X86_PT_PAE_SHIFT 12 +%define X86_PT_PAE_MASK 0x1ff +%define X86_PDE_P RT_BIT(0) +%define X86_PDE_RW RT_BIT(1) +%define X86_PDE_US RT_BIT(2) +%define X86_PDE_PWT RT_BIT(3) +%define X86_PDE_PCD RT_BIT(4) +%define X86_PDE_A RT_BIT(5) +%define X86_PDE_PS RT_BIT(7) +%define X86_PDE_AVL_MASK (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +%define X86_PDE_PG_MASK ( 0xfffff000 ) +%define X86_PDE_PAE_PG_MASK 0x000ffffffffff000 +%define X86_PDE_PAE_NX RT_BIT_64(63) +%define X86_PDE_PAE_MBZ_MASK_NX 0x7ff0000000000080 +%define X86_PDE_PAE_MBZ_MASK_NO_NX 0xfff0000000000080 +%define X86_PDE_LM_MBZ_MASK_NX 0x0000000000000080 +%define X86_PDE_LM_MBZ_MASK_NO_NX 0x8000000000000080 +%define X86_PDE4M_P RT_BIT(0) +%define X86_PDE4M_RW RT_BIT(1) +%define X86_PDE4M_US RT_BIT(2) +%define X86_PDE4M_PWT RT_BIT(3) +%define X86_PDE4M_PCD RT_BIT(4) +%define X86_PDE4M_A RT_BIT(5) +%define X86_PDE4M_D RT_BIT(6) +%define X86_PDE4M_PS RT_BIT(7) +%define X86_PDE4M_G RT_BIT(8) +%define X86_PDE4M_AVL (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +%define X86_PDE4M_PAT RT_BIT(12) +%define X86_PDE4M_PAT_SHIFT (12 - 7) +%define X86_PDE4M_PG_MASK ( 0xffc00000 ) +%define X86_PDE4M_PG_HIGH_MASK ( 0x001fe000 ) +%define X86_PDE4M_PG_HIGH_SHIFT 19 +%define X86_PDE4M_MBZ_MASK RT_BIT_32(21) +%define X86_PDE2M_PAE_PG_MASK 0x000fffffffe00000 +%define X86_PDE2M_PAE_NX RT_BIT_64(63) +%define X86_PDE2M_PAE_MBZ_MASK_NX 0x7ff00000001fe000 +%define X86_PDE2M_PAE_MBZ_MASK_NO_NX 0xfff00000001fe000 +%define X86_PDE2M_LM_MBZ_MASK_NX 0x00000000001fe000 +%define X86_PDE2M_LM_MBZ_MASK_NO_NX 0x80000000001fe000 +%define X86_PD_SHIFT 22 +%define X86_PD_MASK 0x3ff +%define X86_PD_PAE_SHIFT 21 +%define X86_PD_PAE_MASK 0x1ff +%define X86_PDPE_P RT_BIT(0) +%define X86_PDPE_RW RT_BIT(1) +%define X86_PDPE_US RT_BIT(2) +%define X86_PDPE_PWT RT_BIT(3) +%define X86_PDPE_PCD RT_BIT(4) +%define X86_PDPE_A RT_BIT(5) +%define X86_PDPE_LM_PS RT_BIT(7) +%define X86_PDPE_AVL_MASK (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +%define X86_PDPE_PG_MASK 0x000ffffffffff000 +%define X86_PDPE_PAE_MBZ_MASK 0xfff00000000001e6 +%define X86_PDPE_LM_NX RT_BIT_64(63) +%define X86_PDPE_LM_MBZ_MASK_NX 0x0000000000000180 +%define X86_PDPE_LM_MBZ_MASK_NO_NX 0x8000000000000180 +%define X86_PDPE1G_LM_MBZ_MASK_NX 0x000000003fffe000 +%define X86_PDPE1G_LM_MBZ_MASK_NO_NX 0x800000003fffe000 +%define X86_PDPT_SHIFT 30 +%define X86_PDPT_MASK_PAE 0x3 +%define X86_PDPT_MASK_AMD64 0x1ff +%define X86_PML4E_P RT_BIT(0) +%define X86_PML4E_RW RT_BIT(1) +%define X86_PML4E_US RT_BIT(2) +%define X86_PML4E_PWT RT_BIT(3) +%define X86_PML4E_PCD RT_BIT(4) +%define X86_PML4E_A RT_BIT(5) +%define X86_PML4E_AVL_MASK (RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +%define X86_PML4E_PG_MASK 0x000ffffffffff000 +%define X86_PML4E_MBZ_MASK_NX 0x0000000000000080 +%define X86_PML4E_MBZ_MASK_NO_NX 0x8000000000000080 +%define X86_PML4E_NX RT_BIT_64(63) +%define X86_PML4_SHIFT 39 +%define X86_PML4_MASK 0x1ff +%define X86_FSW_IE RT_BIT(0) +%define X86_FSW_DE RT_BIT(1) +%define X86_FSW_ZE RT_BIT(2) +%define X86_FSW_OE RT_BIT(3) +%define X86_FSW_UE RT_BIT(4) +%define X86_FSW_PE RT_BIT(5) +%define X86_FSW_SF RT_BIT(6) +%define X86_FSW_ES RT_BIT(7) +%define X86_FSW_XCPT_MASK 0x007f +%define X86_FSW_XCPT_ES_MASK 0x00ff +%define X86_FSW_C0 RT_BIT(8) +%define X86_FSW_C1 RT_BIT(9) +%define X86_FSW_C2 RT_BIT(10) +%define X86_FSW_TOP_MASK 0x3800 +%define X86_FSW_TOP_SHIFT 11 +%define X86_FSW_TOP_SMASK 0x0007 +%define X86_FSW_TOP_GET(a_uFsw) (((a_uFsw) >> X86_FSW_TOP_SHIFT) & X86_FSW_TOP_SMASK) +%define X86_FSW_C3 RT_BIT(14) +%define X86_FSW_C_MASK 0x4700 +%define X86_FSW_B RT_BIT(15) +%define X86_FCW_IM RT_BIT(0) +%define X86_FCW_DM RT_BIT(1) +%define X86_FCW_ZM RT_BIT(2) +%define X86_FCW_OM RT_BIT(3) +%define X86_FCW_UM RT_BIT(4) +%define X86_FCW_PM RT_BIT(5) +%define X86_FCW_MASK_ALL 0x007f +%define X86_FCW_XCPT_MASK 0x003f +%define X86_FCW_PC_MASK 0x0300 +%define X86_FCW_PC_24 0x0000 +%define X86_FCW_PC_RSVD 0x0100 +%define X86_FCW_PC_53 0x0200 +%define X86_FCW_PC_64 0x0300 +%define X86_FCW_RC_MASK 0x0c00 +%define X86_FCW_RC_NEAREST 0x0000 +%define X86_FCW_RC_DOWN 0x0400 +%define X86_FCW_RC_UP 0x0800 +%define X86_FCW_RC_ZERO 0x0c00 +%define X86_FCW_ZERO_MASK 0xf080 +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%define X86DESCGENERIC_BIT_OFF_LIMIT_LOW (0) +%define X86DESCGENERIC_BIT_OFF_BASE_LOW (16) +%define X86DESCGENERIC_BIT_OFF_BASE_HIGH1 (32) +%define X86DESCGENERIC_BIT_OFF_TYPE (40) +%define X86DESCGENERIC_BIT_OFF_DESC_TYPE (44) +%define X86DESCGENERIC_BIT_OFF_DPL (45) +%define X86DESCGENERIC_BIT_OFF_PRESENT (47) +%define X86DESCGENERIC_BIT_OFF_LIMIT_HIGH (48) +%define X86DESCGENERIC_BIT_OFF_AVAILABLE (52) +%define X86DESCGENERIC_BIT_OFF_LONG (53) +%define X86DESCGENERIC_BIT_OFF_DEF_BIG (54) +%define X86DESCGENERIC_BIT_OFF_GRANULARITY (55) +%define X86DESCGENERIC_BIT_OFF_BASE_HIGH2 (56) +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%if HC_ARCH_BITS == 64 +%else +%endif +%if HC_ARCH_BITS == 64 +%else +%endif +%if HC_ARCH_BITS == 64 +%else +%endif +%define X86_SEL_TYPE_CODE 8 +%define X86_SEL_TYPE_MEMORY RT_BIT(4) +%define X86_SEL_TYPE_ACCESSED 1 +%define X86_SEL_TYPE_DOWN 4 +%define X86_SEL_TYPE_CONF 4 +%define X86_SEL_TYPE_WRITE 2 +%define X86_SEL_TYPE_READ 2 +%define X86_SEL_TYPE_READ_BIT 1 +%define X86_SEL_TYPE_RO 0 +%define X86_SEL_TYPE_RO_ACC (0 | X86_SEL_TYPE_ACCESSED) +%define X86_SEL_TYPE_RW 2 +%define X86_SEL_TYPE_RW_ACC (2 | X86_SEL_TYPE_ACCESSED) +%define X86_SEL_TYPE_RO_DOWN 4 +%define X86_SEL_TYPE_RO_DOWN_ACC (4 | X86_SEL_TYPE_ACCESSED) +%define X86_SEL_TYPE_RW_DOWN 6 +%define X86_SEL_TYPE_RW_DOWN_ACC (6 | X86_SEL_TYPE_ACCESSED) +%define X86_SEL_TYPE_EO (0 | X86_SEL_TYPE_CODE) +%define X86_SEL_TYPE_EO_ACC (0 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED) +%define X86_SEL_TYPE_ER (2 | X86_SEL_TYPE_CODE) +%define X86_SEL_TYPE_ER_ACC (2 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED) +%define X86_SEL_TYPE_EO_CONF (4 | X86_SEL_TYPE_CODE) +%define X86_SEL_TYPE_EO_CONF_ACC (4 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED) +%define X86_SEL_TYPE_ER_CONF (6 | X86_SEL_TYPE_CODE) +%define X86_SEL_TYPE_ER_CONF_ACC (6 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED) +%define X86_SEL_TYPE_SYS_TSS_BUSY_MASK 2 +%define X86_SEL_TYPE_SYS_UNDEFINED 0 +%define X86_SEL_TYPE_SYS_286_TSS_AVAIL 1 +%define X86_SEL_TYPE_SYS_LDT 2 +%define X86_SEL_TYPE_SYS_286_TSS_BUSY 3 +%define X86_SEL_TYPE_SYS_286_CALL_GATE 4 +%define X86_SEL_TYPE_SYS_TASK_GATE 5 +%define X86_SEL_TYPE_SYS_286_INT_GATE 6 +%define X86_SEL_TYPE_SYS_286_TRAP_GATE 7 +%define X86_SEL_TYPE_SYS_UNDEFINED2 8 +%define X86_SEL_TYPE_SYS_386_TSS_AVAIL 9 +%define X86_SEL_TYPE_SYS_UNDEFINED3 0xA +%define X86_SEL_TYPE_SYS_386_TSS_BUSY 0xB +%define X86_SEL_TYPE_SYS_386_CALL_GATE 0xC +%define X86_SEL_TYPE_SYS_UNDEFINED4 0xD +%define X86_SEL_TYPE_SYS_386_INT_GATE 0xE +%define X86_SEL_TYPE_SYS_386_TRAP_GATE 0xF +%define AMD64_SEL_TYPE_SYS_LDT 2 +%define AMD64_SEL_TYPE_SYS_TSS_AVAIL 9 +%define AMD64_SEL_TYPE_SYS_TSS_BUSY 0xB +%define AMD64_SEL_TYPE_SYS_CALL_GATE 0xC +%define AMD64_SEL_TYPE_SYS_INT_GATE 0xE +%define AMD64_SEL_TYPE_SYS_TRAP_GATE 0xF +%define X86_DESC_TYPE_MASK (RT_BIT(8) | RT_BIT(9) | RT_BIT(10) | RT_BIT(11)) +%define X86_DESC_S RT_BIT(12) +%define X86_DESC_DPL (RT_BIT(13) | RT_BIT(14)) +%define X86_DESC_P RT_BIT(15) +%define X86_DESC_AVL RT_BIT(20) +%define X86_DESC_DB RT_BIT(22) +%define X86_DESC_G RT_BIT(23) +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%define X86_SEL_SHIFT 3 +%define X86_SEL_MASK 0xfff8 +%define X86_SEL_MASK_OFF_RPL 0xfffc +%define X86_SEL_LDT 0x0004 +%define X86_SEL_RPL 0x0003 +%define X86_SEL_RPL_LDT 0x0007 +%define X86_TRAP_ERR_EXTERNAL 1 +%define X86_TRAP_ERR_IDT 2 +%define X86_TRAP_ERR_TI 4 +%define X86_TRAP_ERR_SEL_MASK 0xfff8 +%define X86_TRAP_ERR_SEL_SHIFT 3 +%define X86_TRAP_PF_P RT_BIT(0) +%define X86_TRAP_PF_RW RT_BIT(1) +%define X86_TRAP_PF_US RT_BIT(2) +%define X86_TRAP_PF_RSVD RT_BIT(3) +%define X86_TRAP_PF_ID RT_BIT(4) +%ifndef VBOX_FOR_DTRACE_LIB +%else +%endif +%ifndef VBOX_FOR_DTRACE_LIB +%else +%endif +%define X86_MODRM_RM_MASK 0x07 +%define X86_MODRM_REG_MASK 0x38 +%define X86_MODRM_REG_SMASK 0x07 +%define X86_MODRM_REG_SHIFT 3 +%define X86_MODRM_MOD_MASK 0xc0 +%define X86_MODRM_MOD_SMASK 0x03 +%define X86_MODRM_MOD_SHIFT 6 +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%define X86_SIB_BASE_MASK 0x07 +%define X86_SIB_INDEX_MASK 0x38 +%define X86_SIB_INDEX_SMASK 0x07 +%define X86_SIB_INDEX_SHIFT 3 +%define X86_SIB_SCALE_MASK 0xc0 +%define X86_SIB_SCALE_SMASK 0x03 +%define X86_SIB_SCALE_SHIFT 6 +%ifndef VBOX_FOR_DTRACE_LIB +%endif +%define X86_GREG_xAX 0 +%define X86_GREG_xCX 1 +%define X86_GREG_xDX 2 +%define X86_GREG_xBX 3 +%define X86_GREG_xSP 4 +%define X86_GREG_xBP 5 +%define X86_GREG_xSI 6 +%define X86_GREG_xDI 7 +%define X86_GREG_x8 8 +%define X86_GREG_x9 9 +%define X86_GREG_x10 10 +%define X86_GREG_x11 11 +%define X86_GREG_x12 12 +%define X86_GREG_x13 13 +%define X86_GREG_x14 14 +%define X86_GREG_x15 15 +%define X86_SREG_ES 0 +%define X86_SREG_CS 1 +%define X86_SREG_SS 2 +%define X86_SREG_DS 3 +%define X86_SREG_FS 4 +%define X86_SREG_GS 5 +%define X86_SREG_COUNT 6 +%endif +%include "iprt/x86extra.mac" diff --git a/include/iprt/x86extra.mac b/include/iprt/x86extra.mac new file mode 100644 index 00000000..f705984c --- /dev/null +++ b/include/iprt/x86extra.mac @@ -0,0 +1,103 @@ +;; @file +; IPRT - X86 and AMD64 Structures and Definitions that are not automatically +; converted from the C header file. +; + +; +; Copyright (C) 2012 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. +; + +%ifndef ___iprt_x86extra_mac +%define ___iprt_x86extra_mac + + +%define X86_XCPT_UD 6 +%define X86_XCPT_GP 13 +%define X86_XCPT_PF 14 +%define X86_XCPT_MF 16 + +%define PAGE_SIZE 0x1000 + + +;; +; 32-bit protected mode fstenv image. +; +struc X86FSTENV32P + .FCW resw 1 + .padding1 resw 1 + .FSW resw 1 + .padding2 resw 1 + .FTW resw 1 + .padding3 resw 1 + .FPUIP resd 1 + .FPUCS resw 1 + .FOP resw 1 + .FPUDP resd 1 + .FPUDS resw 1 + .padding4 resw 1 +endstruc + + +;; +; The image saved by FXSAVE. +; +struc X86FXSTATE + .FCW resw 1 + .FSW resw 1 + .FTW resw 1 + .FOP resw 1 + .FPUIP resd 1 + .FPUCS resw 1 + .Rsrvd1 resw 1 + .FPUDP resd 1 + .FPUDS resw 1 + .Rsrvd2 resw 1 + .MXCSR resd 1 + .MXCSR_MASK resd 1 + .st0 resd 4 + .st1 resd 4 + .st2 resd 4 + .st3 resd 4 + .st4 resd 4 + .st5 resd 4 + .st6 resd 4 + .st7 resd 4 + .xmm0 resd 4 + .xmm1 resd 4 + .xmm2 resd 4 + .xmm3 resd 4 + .xmm4 resd 4 + .xmm5 resd 4 + .xmm6 resd 4 + .xmm7 resd 4 + .xmm8 resd 4 + .xmm9 resd 4 + .xmm10 resd 4 + .xmm11 resd 4 + .xmm12 resd 4 + .xmm13 resd 4 + .xmm14 resd 4 + .xmm15 resd 4 + .au32RsrvdRest resd 24 +endstruc + + +%endif + diff --git a/include/iprt/zip.h b/include/iprt/zip.h new file mode 100644 index 00000000..f3bfd4bd --- /dev/null +++ b/include/iprt/zip.h @@ -0,0 +1,263 @@ +/** @file + * IPRT - Compression. + */ + +/* + * Copyright (C) 2006-2007 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. + */ + +#ifndef ___iprt_zip_h +#define ___iprt_zip_h + +#include <iprt/cdefs.h> +#include <iprt/types.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_zip RTZip - Compression + * @ingroup grp_rt + * @{ + */ + + + +/** + * Callback function for consuming compressed data during compression. + * + * @returns iprt status code. + * @param pvUser User argument. + * @param pvBuf Compressed data. + * @param cbBuf Size of the compressed data. + */ +typedef DECLCALLBACK(int) FNRTZIPOUT(void *pvUser, const void *pvBuf, size_t cbBuf); +/** Pointer to FNRTZIPOUT() function. */ +typedef FNRTZIPOUT *PFNRTZIPOUT; + +/** + * Callback function for supplying compressed data during decompression. + * + * @returns iprt status code. + * @param pvUser User argument. + * @param pvBuf Where to store the compressed data. + * @param cbBuf Size of the buffer. + * @param pcbBuf Number of bytes actually stored in the buffer. + */ +typedef DECLCALLBACK(int) FNRTZIPIN(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbBuf); +/** Pointer to FNRTZIPIN() function. */ +typedef FNRTZIPIN *PFNRTZIPIN; + +/** + * Compression type. + * (Be careful with these they are stored in files!) + */ +typedef enum RTZIPTYPE +{ + /** Invalid. */ + RTZIPTYPE_INVALID = 0, + /** Choose best fitting one. */ + RTZIPTYPE_AUTO, + /** Store the data. */ + RTZIPTYPE_STORE, + /** Zlib compression the data. */ + RTZIPTYPE_ZLIB, + /** BZlib compress. */ + RTZIPTYPE_BZLIB, + /** libLZF compress. */ + RTZIPTYPE_LZF, + /** Lempel-Ziv-Jeff-Bonwick compression. */ + RTZIPTYPE_LZJB, + /** Lempel-Ziv-Oberhumer compression. */ + RTZIPTYPE_LZO, + /** End of valid the valid compression types. */ + RTZIPTYPE_END +} RTZIPTYPE; + +/** + * Compression level. + */ +typedef enum RTZIPLEVEL +{ + /** Store, don't compress. */ + RTZIPLEVEL_STORE = 0, + /** Fast compression. */ + RTZIPLEVEL_FAST, + /** Default compression. */ + RTZIPLEVEL_DEFAULT, + /** Maximal compression. */ + RTZIPLEVEL_MAX +} RTZIPLEVEL; + + +/** + * Create a stream compressor instance. + * + * @returns iprt status code. + * @param ppZip Where to store the instance handle. + * @param pvUser User argument which will be passed on to pfnOut and pfnIn. + * @param pfnOut Callback for consuming output of compression. + * @param enmType Type of compressor to create. + * @param enmLevel Compression level. + */ +RTDECL(int) RTZipCompCreate(PRTZIPCOMP *ppZip, void *pvUser, PFNRTZIPOUT pfnOut, RTZIPTYPE enmType, RTZIPLEVEL enmLevel); + +/** + * Compresses a chunk of memory. + * + * @returns iprt status code. + * @param pZip The compressor instance. + * @param pvBuf Pointer to buffer containing the bits to compress. + * @param cbBuf Number of bytes to compress. + */ +RTDECL(int) RTZipCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf); + +/** + * Finishes the compression. + * This will flush all data and terminate the compression data stream. + * + * @returns iprt status code. + * @param pZip The stream compressor instance. + */ +RTDECL(int) RTZipCompFinish(PRTZIPCOMP pZip); + +/** + * Destroys the stream compressor instance. + * + * @returns iprt status code. + * @param pZip The compressor instance. + */ +RTDECL(int) RTZipCompDestroy(PRTZIPCOMP pZip); + + +/** + * Create a stream decompressor instance. + * + * @returns iprt status code. + * @param ppZip Where to store the instance handle. + * @param pvUser User argument which will be passed on to pfnOut and pfnIn. + * @param pfnIn Callback for producing input for decompression. + */ +RTDECL(int) RTZipDecompCreate(PRTZIPDECOMP *ppZip, void *pvUser, PFNRTZIPIN pfnIn); + +/** + * Decompresses a chunk of memory. + * + * @returns iprt status code. + * @param pZip The stream decompressor instance. + * @param pvBuf Where to store the decompressed data. + * @param cbBuf Number of bytes to produce. If pcbWritten is set + * any number of bytes up to cbBuf might be returned. + * @param pcbWritten Number of bytes actually written to the buffer. If NULL + * cbBuf number of bytes must be written. + */ +RTDECL(int) RTZipDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten); + +/** + * Destroys the stream decompressor instance. + * + * @returns iprt status code. + * @param pZip The decompressor instance. + */ +RTDECL(int) RTZipDecompDestroy(PRTZIPDECOMP pZip); + + +/** + * Compress a chunk of memory into a block. + * + * @returns IPRT status code. + * + * @param enmType The compression type. + * @param enmLevel The compression level. + * @param fFlags Flags reserved for future extensions, MBZ. + * @param pvSrc Pointer to the input block. + * @param cbSrc Size of the input block. + * @param pvDst Pointer to the output buffer. + * @param cbDst The size of the output buffer. + * @param pcbDstActual Where to return the compressed size. + */ +RTDECL(int) RTZipBlockCompress(RTZIPTYPE enmType, RTZIPLEVEL enmLevel, uint32_t fFlags, + void const *pvSrc, size_t cbSrc, + void *pvDst, size_t cbDst, size_t *pcbDstActual) RT_NO_THROW; + + +/** + * Decompress a block. + * + * @returns IPRT status code. + * + * @param enmType The compression type. + * @param fFlags Flags reserved for future extensions, MBZ. + * @param pvSrc Pointer to the input block. + * @param cbSrc Size of the input block. + * @param pcbSrcActual Where to return the compressed size. + * @param pvDst Pointer to the output buffer. + * @param cbDst The size of the output buffer. + * @param pcbDstActual Where to return the decompressed size. + */ +RTDECL(int) RTZipBlockDecompress(RTZIPTYPE enmType, uint32_t fFlags, + void const *pvSrc, size_t cbSrc, size_t *pcbSrcActual, + void *pvDst, size_t cbDst, size_t *pcbDstActual) RT_NO_THROW; + + +/** + * Opens a gzip decompression I/O stream. + * + * @returns IPRT status code. + * + * @param hVfsIosIn The compressed input stream. The reference is + * not consumed, instead another one is retained. + * @param fFlags Flags, MBZ. + * @param phVfsIosOut Where to return the handle to the gzip I/O + * stream. + */ +RTDECL(int) RTZipGzipDecompressIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSIOSTREAM phVfsIosOut); + +/** + * Opens a TAR filesystem stream. + * + * This is used to extract, list or check a TAR archive. + * + * @returns IPRT status code. + * + * @param hVfsIosIn The compressed input stream. The reference is + * not consumed, instead another one is retained. + * @param fFlags Flags, MBZ. + * @param phVfsFss Where to return the handle to the TAR + * filesystem stream. + */ +RTDECL(int) RTZipTarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss); + +/** + * A mini TAR program. + * + * @returns Program exit code. + * + * @param cArgs The number of arguments. + * @param papszArgs The argument vector. (Note that this may be + * reordered, so the memory must be writable.) + */ +RTDECL(RTEXITCODE) RTZipTarCmd(unsigned cArgs, char **papszArgs); + +/** @} */ + +RT_C_DECLS_END + +#endif + |