VirtualBox

Changeset 25748 in vbox


Ignore:
Timestamp:
Jan 12, 2010 10:27:27 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
56499
Message:

iprt/cdefs,*: Use RT_LOCK_STRICT and RT_LOCK_STRICT_ORDER for controlling deadlock detection and lock order validation. Currently both are disabled by default, but it's possible to add VBOX_WITH_STRICT_LOCKS=1 to LocalConfig.kmk to enable it all.

Location:
trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Config.kmk

    r25633 r25748  
    547547 VBOX_WITH_VMMR0_DISABLE_PREEMPTION = 1
    548548endif
    549 
    550 ## Enabled the live migration API changes.
    551 #VBOX_WITH_LIVE_MIGRATION = 1
     549## For testing deadlock detection and lock order validation.
     550# (Temporary, will be made default for debug and strict builds soon.)
     551if1of ($(KBUILD_TARGET),)
     552 VBOX_WITH_STRICT_LOCKS = 1
     553endif
     554
    552555
    553556#
     
    11471150ifdef VBOX_PATH_APP_DOCS
    11481151 DEFS += RTPATH_APP_DOCS=\"$(VBOX_PATH_APP_DOCS)\"
     1152endif
     1153ifdef VBOX_WITH_STRICT_LOCKS
     1154 DEFS += RT_LOCK_STRICT RT_LOCK_STRICT_ORDER
    11491155endif
    11501156
  • trunk/include/iprt/cdefs.h

    r25645 r25748  
    8484#define IN_RT_STATIC
    8585#define RT_STRICT
     86#define RT_LOCK_STRICT
     87#define RT_LOCK_NO_STRICT
     88#define RT_LOCK_STRICT_ORDER
     89#define RT_LOCK_NO_STRICT_ORDER
    8690#define Breakpoint
    8791#define RT_NO_DEPRECATED_MACROS
     
    17881792#endif
    17891793
     1794/** @todo remove this: */
     1795#if !defined(RT_LOCK_STRICT) && !defined(DEBUG_bird)
     1796# define RT_LOCK_NO_STRICT
     1797#endif
     1798#if !defined(RT_LOCK_STRICT_ORDER) && !defined(DEBUG_bird)
     1799# define RT_LOCK_NO_STRICT_ORDER
     1800#endif
     1801
     1802/** @def RT_LOCK_STRICT
     1803 * The \#define RT_LOCK_STRICT controls whether deadlock detection and related
     1804 * checks are done in the lock and semaphore code.  It is by default enabled in
     1805 * RT_STRICT builds, but this behavior can be overriden by defining
     1806 * RT_LOCK_NO_STRICT. */
     1807#if !defined(RT_LOCK_STRICT) && !defined(RT_LOCK_NO_STRICT) && defined(RT_STRICT)
     1808# define RT_LOCK_STRICT
     1809#endif
     1810/** @def RT_LOCK_NO_STRICT
     1811 * The \#define RT_LOCK_NO_STRICT disables RT_LOCK_STRICT.  */
     1812#if defined(RT_LOCK_NO_STRICT) && defined(RT_LOCK_STRICT)
     1813# undef RT_LOCK_STRICT
     1814#endif
     1815
     1816/** @def RT_LOCK_STRICT_ORDER
     1817 * The \#define RT_LOCK_STRICT_ORDER controls whether locking order is checked
     1818 * by the lock and semaphore code.  It is by default enabled in RT_STRICT
     1819 * builds, but this behavior can be overriden by defining
     1820 * RT_LOCK_NO_STRICT_ORDER. */
     1821#if !defined(RT_LOCK_STRICT_ORDER) && !defined(RT_LOCK_NO_STRICT_ORDER) && defined(RT_STRICT)
     1822# define RT_LOCK_STRICT_ORDER
     1823#endif
     1824/** @def RT_LOCK_NO_STRICT_ORDER
     1825 * The \#define RT_LOCK_NO_STRICT_ORDER disables RT_LOCK_STRICT_ORDER.  */
     1826#if defined(RT_LOCK_NO_STRICT_ORDER) && defined(RT_LOCK_STRICT_ORDER)
     1827# undef RT_LOCK_STRICT_ORDER
     1828#endif
     1829
     1830
    17901831/** Source position. */
    17911832#define RT_SRC_POS         __FILE__, __LINE__, __PRETTY_FUNCTION__
     
    17961837/** Source position arguments. */
    17971838#define RT_SRC_POS_ARGS    pszFile, iLine, pszFunction
     1839
     1840/** Applies NOREF() to the source position arguments. */
     1841#define RT_SRC_POS_NOREF() do { NOREF(pszFile); NOREF(iLine); NOREF(pszFunction); } while (0)
    17981842
    17991843/** @} */
  • trunk/include/iprt/cpp/lock.h

    r25345 r25748  
    2828 */
    2929
    30 #ifndef ___iprt_lock_h
    31 #define ___iprt_lock_h
     30#ifndef ___iprt_cpp_lock_h
     31#define ___iprt_cpp_lock_h
    3232
    3333#include <iprt/critsect.h>
     34#ifdef RT_LOCK_STRICT
     35# include <iprt/lockvalidator.h>
     36#endif
    3437
    3538RT_C_DECLS_BEGIN
     
    6164        RTLockMtx()
    6265        {
     66#ifdef RT_LOCK_STRICT_ORDER
     67            RTCritSectInitEx(&mMtx, 0 /*fFlags*/,
     68                             RTLockValidatorClassCreateUnique(RT_SRC_POS, NULL),
     69                             RTLOCKVAL_SUB_CLASS_NONE, NULL);
     70#else
    6371            RTCritSectInit(&mMtx);
     72#endif
     73        }
     74
     75        /** Use to when creating locks that belongs in the same "class".  */
     76        RTLockMtx(RT_SRC_POS_DECL, uint32_t uSubClass = RTLOCKVAL_SUB_CLASS_NONE)
     77        {
     78#ifdef RT_LOCK_STRICT_ORDER
     79            RTCritSectInitEx(&mMtx, 0 /*fFlags*/,
     80                             RTLockValidatorClassForSrcPos(RT_SRC_POS_ARGS, NULL),
     81                             uSubClass, NULL);
     82#else
     83            RTCritSectInit(&mMtx);
     84            RT_SRC_POS_NOREF();
     85#endif
    6486        }
    6587
  • trunk/include/iprt/critsect.h

    r25707 r25748  
    3737# include <iprt/thread.h>
    3838#endif
    39 
     39#ifdef RT_LOCK_STRICT_ORDER
     40# include <iprt/lockvalidator.h>
     41#endif
    4042
    4143RT_C_DECLS_BEGIN
     
    336338}
    337339
    338 /* Strict build: Remap the three enter calls to the debug versions. */
    339 #ifdef RT_STRICT
     340/* Lock strict build: Remap the three enter calls to the debug versions. */
     341#ifdef RT_LOCK_STRICT
    340342# ifdef ___iprt_asm_h
    341343#  define RTCritSectEnter(pCritSect)                        RTCritSectEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
     
    349351#endif
    350352
     353/* Strict lock order: Automatically classify locks by init location. */
     354#ifdef RT_LOCK_STRICT_ORDER
     355# define RTCritSectInit(pCritSect) \
     356    RTCritSectInitEx((pCritSect), 0 /*fFlags*/, \
     357                     RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
     358                     RTLOCKVAL_SUB_CLASS_NONE, NULL)
     359#endif
     360
    351361/** @} */
    352362
  • trunk/include/iprt/lockvalidator.h

    r25732 r25748  
    901901
    902902/**
     903 * Creates a new lock validator class with a reference that is consumed by the
     904 * first call to RTLockValidatorClassRetain.
     905 *
     906 * This is tailored for use in the parameter list of a semaphore constructor.
     907 *
     908 * @returns Class handle with a reference that is automatically consumed by the
     909 *          first retainer.  NIL_RTLOCKVALCLASS if we run into trouble.
     910 *
     911 * @param   pszFile             The source position of the call, file.
     912 * @param   iLine               The source position of the call, line.
     913 * @param   pszFunction         The source position of the call, function.
     914 * @param   pszNameFmt          Class name format string, optional (NULL).  Max
     915 *                              length is 32 bytes.
     916 * @param   ...                 Format string arguments.
     917 */
     918RTDECL(RTLOCKVALCLASS) RTLockValidatorClassCreateUnique(RT_SRC_POS_DECL, const char *pszNameFmt, ...);
     919
     920/**
    903921 * Finds a class for the specified source position.
    904922 *
  • trunk/src/VBox/Main/AutoLock.cpp

    r25736 r25748  
    259259 */
    260260
    261     int vrc = RTSemRWCreate(&m->sem);
     261    int vrc = RTSemRWCreateEx(&m->sem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
    262262    AssertRC(vrc);
    263263
     
    283283    validateLock(LOCKVAL_SRC_POS_ARGS);
    284284#endif
    285 #if defined(RT_STRICT) && defined(VBOX_WITH_DEBUG_LOCK_VALIDATOR)
     285#if defined(RT_LOCK_STRICT) && defined(VBOX_WITH_DEBUG_LOCK_VALIDATOR)
    286286    int vrc = RTSemRWRequestWriteDebug(m->sem, RT_INDEFINITE_WAIT, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
    287 #elif defined(RT_STRICT)
     287#elif defined(RT_LOCK_STRICT)
    288288    int vrc = RTSemRWRequestWriteDebug(m->sem, RT_INDEFINITE_WAIT, (uintptr_t)ASMReturnAddress(), RT_SRC_POS);
    289289#else
     
    308308    validateLock(LOCKVAL_SRC_POS_ARGS);
    309309#endif
    310 #if defined(RT_STRICT) && defined(VBOX_WITH_DEBUG_LOCK_VALIDATOR)
     310#if defined(RT_LOCK_STRICT) && defined(VBOX_WITH_DEBUG_LOCK_VALIDATOR)
    311311    int vrc = RTSemRWRequestReadDebug(m->sem, RT_INDEFINITE_WAIT, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
    312 #elif defined(RT_STRICT)
     312#elif defined(RT_LOCK_STRICT)
    313313    int vrc = RTSemRWRequestReadDebug(m->sem, RT_INDEFINITE_WAIT, (uintptr_t)ASMReturnAddress(), RT_SRC_POS);
    314314#else
     
    361361{
    362362    m = new Data;
    363     RTCritSectInit(&m->sem);
     363    /** @todo see todo in RWLockHandle::RWLockHandle(). */
     364    int vrc = RTCritSectInitEx(&m->sem, 0/*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
     365    AssertRC(vrc);
    364366
    365367#ifdef VBOX_WITH_DEBUG_LOCK_VALIDATOR
     
    385387#endif
    386388
    387 #if defined(RT_STRICT) && defined(VBOX_WITH_DEBUG_LOCK_VALIDATOR)
     389#if defined(RT_LOCK_STRICT) && defined(VBOX_WITH_DEBUG_LOCK_VALIDATOR)
    388390    RTCritSectEnterDebug(&m->sem, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
    389 #elif defined(RT_STRICT)
     391#elif defined(RT_LOCK_STRICT)
    390392    RTCritSectEnterDebug(&m->sem, (uintptr_t)ASMReturnAddress(),
    391393                         "return address >>>", 0, __PRETTY_FUNCTION__);
  • trunk/src/VBox/Main/webservice/Makefile.kmk

    r24913 r25748  
    257257 ifdef VBOX_USE_VCC80
    258258  vboxwebsrv_CXXFLAGS.win += -bigobj
     259 endif
     260 ifn1of ($(KBUILD_TARGET), win)
     261  vboxwebsrv_CXXFLAGS += -Wno-shadow
    259262 endif
    260263 vboxwebsrv_LIBS += \
  • trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp

    r25732 r25748  
    190190    /** Whether this class is in the tree. */
    191191    bool                    fInTree;
     192    /** Donate a reference to the next retainer. This is a hack to make
     193     *  RTLockValidatorClassCreateUnique work. */
     194    bool volatile           fDonateRefToNextRetainer;
     195    /** Reserved future use / explicit alignment. */
     196    bool                    afReserved[3];
    192197    /** The minimum wait interval for which we do deadlock detection
    193198     *  (milliseconds). */
     
    196201    RTMSINTERVAL            cMsMinOrder;
    197202    /** More padding. */
    198     uint32_t                au32Reserved[ARCH_BITS == 32 ? 6 : 3];
     203    uint32_t                au32Reserved[ARCH_BITS == 32 ? 5 : 2];
    199204    /** Classes that may be taken prior to this one.
    200205     * This is a linked list where each node contains a chunk of locks so that we
     
    274279    {
    275280        if (!RTCritSectIsInitialized(&g_LockValClassTeachCS))
    276             RTCritSectInit(&g_LockValClassTeachCS);
     281            RTCritSectInitEx(&g_LockValClassTeachCS, RTCRITSECT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS,
     282                             RTLOCKVAL_SUB_CLASS_ANY, "RTLockVal-Teach");
    277283
    278284        if (g_hLockValClassTreeRWLock == NIL_RTSEMRW)
    279285        {
    280286            RTSEMRW hSemRW;
    281             int rc = RTSemRWCreate(&hSemRW);
     287            int rc = RTSemRWCreateEx(&hSemRW, RTSEMRW_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_ANY, "RTLockVal-Tree");
    282288            if (RT_SUCCESS(rc))
    283289                ASMAtomicWriteHandle(&g_hLockValClassTreeRWLock, hSemRW);
     
    990996    pThis->fStrictReleaseOrder  = fStrictReleaseOrder;
    991997    pThis->fInTree              = false;
     998    pThis->fDonateRefToNextRetainer = false;
     999    pThis->afReserved[0]        = false;
     1000    pThis->afReserved[1]        = false;
     1001    pThis->afReserved[2]        = false;
    9921002    pThis->cMsMinDeadlock       = cMsMinDeadlock;
    9931003    pThis->cMsMinOrder          = cMsMinOrder;
     
    10391049
    10401050/**
     1051 * Creates a new lock validator class with a reference that is consumed by the
     1052 * first call to RTLockValidatorClassRetain.
     1053 *
     1054 * This is tailored for use in the parameter list of a semaphore constructor.
     1055 *
     1056 * @returns Class handle with a reference that is automatically consumed by the
     1057 *          first retainer.  NIL_RTLOCKVALCLASS if we run into trouble.
     1058 *
     1059 * @param   pszFile             The source position of the call, file.
     1060 * @param   iLine               The source position of the call, line.
     1061 * @param   pszFunction         The source position of the call, function.
     1062 * @param   pszNameFmt          Class name format string, optional (NULL).  Max
     1063 *                              length is 32 bytes.
     1064 * @param   ...                 Format string arguments.
     1065 */
     1066RTDECL(RTLOCKVALCLASS) RTLockValidatorClassCreateUnique(RT_SRC_POS_DECL, const char *pszNameFmt, ...)
     1067{
     1068    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_POS_NO_ID();
     1069    RTLOCKVALCLASSINT *pClass;
     1070    va_list va;
     1071    va_start(va, pszNameFmt);
     1072    int rc = RTLockValidatorClassCreateExV(&pClass, &SrcPos,
     1073                                           true /*fAutodidact*/, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/,
     1074                                           1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/,
     1075                                           pszNameFmt, va);
     1076    va_end(va);
     1077    if (RT_FAILURE(rc))
     1078        return NIL_RTLOCKVALCLASS;
     1079    ASMAtomicWriteBool(&pClass->fDonateRefToNextRetainer, true); /* see rtLockValidatorClassRetain */
     1080    return pClass;
     1081}
     1082
     1083
     1084/**
    10411085 * Internal class retainer.
    10421086 * @returns The new reference count.
     
    10481092    if (cRefs > RTLOCKVALCLASS_MAX_REFS)
    10491093        ASMAtomicWriteU32(&pClass->cRefs, RTLOCKVALCLASS_MAX_REFS);
     1094    else if (   cRefs == 2
     1095             && ASMAtomicXchgBool(&pClass->fDonateRefToNextRetainer, false))
     1096        cRefs = ASMAtomicDecU32(&pClass->cRefs);
    10501097    return cRefs;
    10511098}
     
    27762823static int rtLockValidatorDeadlockDetection(PRTLOCKVALRECUNION pRec, PRTTHREADINT pThreadSelf, PCRTLOCKVALSRCPOS pSrcPos)
    27772824{
    2778 #ifdef DEBUG_bird
    27792825    RTLOCKVALDDSTACK Stack;
    27802826    int rc = rtLockValidatorDdDoDetection(&Stack, pRec, pThreadSelf);
     
    27992845    rcLockValidatorDoDeadlockComplaining(&Stack, pRec, pThreadSelf, pSrcPos, rc);
    28002846    return rc;
    2801 #else
    2802     return VINF_SUCCESS;
    2803 #endif
    28042847}
    28052848
  • trunk/src/VBox/Runtime/generic/semrw-generic.cpp

    r25724 r25748  
    115115         * Create the semaphores.
    116116         */
    117         rc = RTSemEventCreate(&pThis->WriteEvent);
     117        rc = RTSemEventCreateEx(&pThis->WriteEvent, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL);
    118118        if (RT_SUCCESS(rc))
    119119        {
    120             rc = RTSemEventMultiCreate(&pThis->ReadEvent);
     120            rc = RTSemEventMultiCreateEx(&pThis->ReadEvent, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL);
    121121            if (RT_SUCCESS(rc))
    122122            {
  • trunk/src/VBox/Runtime/include/internal/strict.h

    r25638 r25748  
    3535 * @{ */
    3636
    37 #ifdef DEBUG_bird /** @todo reenable this for everyone. Just being a little be cautious right now... */
    3837/** @def RTCRITSECT_STRICT
    3938 * Enables strictness checks and lock accounting of the RTCritSect API.
    4039 */
    41 #if defined(DOXYGEN_RUNNING) || (!defined(RTCRITSECT_STRICT) && defined(IN_RING3) && (defined(RT_STRICT) || defined(RT_LOCK_STRICT)))
     40#if (!defined(RTCRITSECT_STRICT)      && defined(IN_RING3) && defined(RT_LOCK_STRICT)) || defined(DOXYGEN_RUNNING)
    4241# define RTCRITSECT_STRICT
    4342#endif
     
    4645 * Enables strictness checks and lock accounting of the RTSemEvent API.
    4746 */
    48 #if defined(DOXYGEN_RUNNING) || (!defined(RTSEMEVENT_STRICT) && defined(IN_RING3) && (defined(RT_STRICT) || defined(RT_LOCK_STRICT) || defined(RTSEM_STRICT)))
     47#if (!defined(RTSEMEVENT_STRICT)      && defined(IN_RING3) && defined(RT_LOCK_STRICT)) || defined(DOXYGEN_RUNNING)
    4948# define RTSEMEVENT_STRICT
    5049#endif
     
    5352 * Enables strictness checks and lock accounting of the RTSemEventMulti API.
    5453 */
    55 #if defined(DOXYGEN_RUNNING) || (!defined(RTSEMEVENTMULTI_STRICT) && defined(IN_RING3) && (defined(RT_STRICT) || defined(RT_LOCK_STRICT) || defined(RTSEM_STRICT)))
     54#if (!defined(RTSEMEVENTMULTI_STRICT) && defined(IN_RING3) && defined(RT_LOCK_STRICT)) || defined(DOXYGEN_RUNNING)
    5655# define RTSEMEVENTMULTI_STRICT
    5756#endif
     
    6059 * Enables strictness checks and lock accounting of the RTSemMutex API.
    6160 */
    62 #if defined(DOXYGEN_RUNNING) || (!defined(RTSEMMUTEX_STRICT) && defined(IN_RING3) && (defined(RT_STRICT) || defined(RT_LOCK_STRICT) || defined(RTSEM_STRICT)))
     61#if (!defined(RTSEMMUTEX_STRICT)      && defined(IN_RING3) && defined(RT_LOCK_STRICT)) || defined(DOXYGEN_RUNNING)
    6362# define RTSEMMUTEX_STRICT
    6463#endif
     
    6867 * Enables strictness checks and lock accounting of the RTSemRW API.
    6968 */
    70 #if defined(DOXYGEN_RUNNING) || (!defined(RTSEMRW_STRICT) && defined(IN_RING3) && (defined(RT_STRICT) || defined(RT_LOCK_STRICT) || defined(RTSEM_STRICT)))
     69#if (!defined(RTSEMRW_STRICT)         && defined(IN_RING3) && defined(RT_LOCK_STRICT)) || defined(DOXYGEN_RUNNING)
    7170# define RTSEMRW_STRICT
    7271#endif
    73 #endif /* DEBUG_bird */
    7472
    7573
  • trunk/src/VBox/Runtime/r3/xml.cpp

    r25645 r25748  
    5757 *
    5858 * The constructor and destructor of this structure are used to perform global
    59  * module initiaizaton and cleanup. Thee must be only one global variable of
     59 * module initiaizaton and cleanup. There must be only one global variable of
    6060 * this structure.
    6161 */
  • trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp

    r25732 r25748  
    12001200    RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemRWDestroy(hSemRW), false);
    12011201
    1202 #if 0 /** @todo detect it on RTSemMutex... */
     1202#if 0 /** @todo detect it on RTSemMutex... wrong locking order? */
    12031203    RTSEMMUTEX hSemMtx;
    12041204    RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemMutexCreate(&hSemRW), false);
     
    12531253    RTLockValidatorSetQuiet(false);
    12541254
    1255     bool fTestDd = false;//true;
     1255    bool fTestDd = true;
    12561256    bool fTestLo = true;
    12571257
  • trunk/src/VBox/VMM/PDMCritSect.cpp

    r25732 r25748  
    139139#else
    140140            rc = RTLockValidatorRecExclCreate(&pCritSect->Core.pValidatorRec,
     141# ifdef RT_LOCK_STRICT_ORDER
    141142                                              RTLockValidatorClassForSrcPos(RT_SRC_POS_ARGS, "%s", pszName),
     143# else
     144                                              NIL_RTLOCKVALCLASS,
     145# endif
    142146                                              RTLOCKVAL_SUB_CLASS_NONE,
    143147                                              pCritSect, true, "%s", pszName);
  • trunk/src/VBox/VMM/PDMDevHlp.cpp

    r25732 r25748  
    5151 */
    5252#if /*defined(DEBUG_bird) ||*/ defined(DOXYGEN_RUNNING)
    53 # define PDM_DEVHLP_DEADLOCK_DETECTION
     53# define PDM_DEVHLP_DEADLOCK_DETECTION /**< @todo enable DevHlp deadlock detection! */
    5454#endif
    5555
  • trunk/src/VBox/VMM/PDMInternal.h

    r25732 r25748  
    5353/** @def PDMCRITSECT_STRICT
    5454 * Enables/disables PDM critsect strictness like deadlock detection. */
    55 #ifdef DEBUG_bird /** @todo temporarily bird only */
    56 #if (defined(VBOX_STRICT) && defined(IN_RING3)) || defined(DOXYGEN_RUNNING)
     55#if (defined(RT_LOCK_STRICT) && defined(IN_RING3)) || defined(DOXYGEN_RUNNING)
    5756# define PDMCRITSECT_STRICT
    58 #endif
    5957#endif
    6058
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette