VirtualBox

Changeset 90861 in vbox


Ignore:
Timestamp:
Aug 25, 2021 12:10:47 AM (3 years ago)
Author:
vboxsync
Message:

IPRT/log: Cleanups. Moving stuff around for more logical grouping within log.cpp. bugref:10086

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/err.h

    r90829 r90861  
    14461446/** The internal logger revision did not match. */
    14471447#define VERR_LOG_REVISION_MISMATCH                  (-22300)
     1448/** Logging is disabled or logger instance could not be created. */
     1449#define VINF_LOG_DISABLED                           (22301)
     1450/** No logger instance. */
     1451#define VINF_LOG_NO_LOGGER                          (22302)
    14481452/** @} */
    14491453
  • trunk/include/iprt/log.h

    r90860 r90861  
    21732173 * Modifies the flag settings for the given logger.
    21742174 *
    2175  * @returns IPRT status code.  Returns VINF_SUCCESS if no default logger and @a
    2176  *          pLogger is NULL.
     2175 * @returns IPRT status code.  Returns VINF_LOG_NO_LOGGER if no default logger
     2176 *          and @a pLogger is NULL.
    21772177 * @param   pLogger     Logger instance (NULL for default logger).
    21782178 * @param   fSet        Mask of flags to set (OR).
     
    22302230 * additional arguments, like RTLOGDEST_FILE.
    22312231 *
    2232  * @returns IPRT status code.  Returns VINF_SUCCESS if no default logger and @a
    2233  *          pLogger is NULL.
     2232 * @returns IPRT status code.  Returns VINF_LOG_NO_LOGGER if no default logger
     2233 *          and @a pLogger is NULL.
    22342234 * @param   pLogger     Logger instance (NULL for default logger).
    22352235 * @param   fSet        Mask of destinations to set (OR).
     
    23182318 * Flushes the specified logger.
    23192319 *
     2320 * @returns IRPT status code.
    23202321 * @param   pLogger     The logger instance to flush.
    23212322 *                      If NULL the default instance is used. The default instance
    23222323 *                      will not be initialized by this call.
    23232324 */
    2324 RTDECL(void) RTLogFlush(PRTLOGGER pLogger);
     2325RTDECL(int) RTLogFlush(PRTLOGGER pLogger);
    23252326
    23262327/**
     
    23672368 * logging kind which is currently enabled before writing anything to the log.
    23682369 *
     2370 * @returns VINF_SUCCESS, VINF_LOG_NO_LOGGER, VINF_LOG_DISABLED, or IPRT error
     2371 *          status.
    23692372 * @param   pLogger     Pointer to logger instance. If NULL the default logger instance will be attempted.
    23702373 * @param   fFlags      The logging flags.
     
    23752378 * @param   args        Format arguments.
    23762379 */
    2377 RTDECL(void) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
    2378                             const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(4, 0);
     2380RTDECL(int) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
     2381                           const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(4, 0);
    23792382
    23802383/**
  • trunk/src/VBox/Runtime/common/log/log.cpp

    r90860 r90861  
    9898
    9999
     100/** Resolved a_pLoggerInt to the default logger if NULL, returning @a a_rcRet if
     101 * no default logger could be created. */
     102#define RTLOG_RESOLVE_DEFAULT_RET(a_pLoggerInt, a_rcRet) do {\
     103        if (a_pLoggerInt) { /*maybe*/ } \
     104        else \
     105        { \
     106            a_pLoggerInt = (PRTLOGGERINTERNAL)rtLogDefaultInstanceCommon(); \
     107            if (a_pLoggerInt) { /*maybe*/ } \
     108            else \
     109                return (a_rcRet); \
     110        } \
     111    } while (0)
     112
     113
    100114/*********************************************************************************************************************************
    101115*   Structures and Typedefs                                                                                                      *
     
    256270*********************************************************************************************************************************/
    257271static unsigned rtlogGroupFlags(const char *psz);
    258 #ifdef IN_RING0
    259 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt,
    260                                     const char *pszFormat, va_list va);
    261 #endif
    262272#ifdef IN_RING3
    263273static int  rtR3LogOpenFileDestination(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo);
     
    265275static void rtLogRingBufFlush(PRTLOGGERINTERNAL pLoggerInt);
    266276static void rtlogFlush(PRTLOGGERINTERNAL pLoggerInt, bool fNeedSpace);
    267 static DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars);
    268 static void rtlogLoggerExVLocked(PRTLOGGERINTERNAL pLoggerInt, unsigned fFlags, unsigned iGroup,
    269                                  const char *pszFormat, va_list args);
    270 static void rtlogLoggerExFLocked(PRTLOGGERINTERNAL pLoggerInt, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...);
     277#ifdef IN_RING3
     278static FNRTLOGPHASEMSG rtlogPhaseMsgLocked;
     279static FNRTLOGPHASEMSG rtlogPhaseMsgNormal;
     280#endif
    271281
    272282
     
    426436}
    427437
    428 #ifdef IN_RING3
    429 
    430 /**
    431  * Log phase callback function, assumes the lock is already held
    432  *
    433  * @param   pLogger     The logger instance.
    434  * @param   pszFormat   Format string.
    435  * @param   ...         Optional arguments as specified in the format string.
    436  */
    437 static DECLCALLBACK(void) rtlogPhaseMsgLocked(PRTLOGGER pLogger, const char *pszFormat, ...)
     438
     439/*********************************************************************************************************************************
     440*   Logger Instance Management.                                                                                                  *
     441*********************************************************************************************************************************/
     442
     443/**
     444 * Common worker for RTLogDefaultInstance and RTLogDefaultInstanceEx.
     445 */
     446DECL_NO_INLINE(static, PRTLOGGER) rtLogDefaultInstanceCreateNew(void)
     447{
     448    PRTLOGGER pRet = RTLogDefaultInit();
     449    if (pRet)
     450    {
     451        bool fRc = ASMAtomicCmpXchgPtr(&g_pLogger, pRet, NULL);
     452        if (!fRc)
     453        {
     454            RTLogDestroy(pRet);
     455            pRet = g_pLogger;
     456        }
     457    }
     458    return pRet;
     459}
     460
     461
     462/**
     463 * Common worker for RTLogDefaultInstance and RTLogDefaultInstanceEx.
     464 */
     465DECL_FORCE_INLINE(PRTLOGGER) rtLogDefaultInstanceCommon(void)
     466{
     467    PRTLOGGER pRet;
     468
     469#ifdef IN_RING0
     470    /*
     471     * Check per thread loggers first.
     472     */
     473    if (g_cPerThreadLoggers)
     474    {
     475        const RTNATIVETHREAD Self = RTThreadNativeSelf();
     476        int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
     477        while (i-- > 0)
     478            if (g_aPerThreadLoggers[i].NativeThread == Self)
     479                return g_aPerThreadLoggers[i].pLogger;
     480    }
     481#endif /* IN_RING0 */
     482
     483    /*
     484     * If no per thread logger, use the default one.
     485     */
     486    pRet = g_pLogger;
     487    if (RT_LIKELY(pRet))
     488    { /* likely */ }
     489    else
     490        pRet = rtLogDefaultInstanceCreateNew();
     491    return pRet;
     492}
     493
     494
     495RTDECL(PRTLOGGER)   RTLogDefaultInstance(void)
     496{
     497    return rtLogDefaultInstanceCommon();
     498}
     499RT_EXPORT_SYMBOL(RTLogDefaultInstance);
     500
     501
     502/**
     503 * Worker for RTLogDefaultInstanceEx, RTLogGetDefaultInstanceEx,
     504 * RTLogRelGetDefaultInstanceEx and RTLogCheckGroupFlags.
     505 */
     506DECL_FORCE_INLINE(PRTLOGGERINTERNAL) rtLogCheckGroupFlagsWorker(PRTLOGGERINTERNAL pLoggerInt, uint32_t fFlagsAndGroup)
     507{
     508    if (pLoggerInt->fFlags & RTLOGFLAGS_DISABLED)
     509        pLoggerInt = NULL;
     510    else
     511    {
     512        uint32_t const fFlags = RT_LO_U16(fFlagsAndGroup);
     513        uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
     514        if (   iGroup != UINT16_MAX
     515             && (   (pLoggerInt->afGroups[iGroup < pLoggerInt->cGroups ? iGroup : 0] & (fFlags | RTLOGGRPFLAGS_ENABLED))
     516                 != (fFlags | RTLOGGRPFLAGS_ENABLED)))
     517            pLoggerInt = NULL;
     518    }
     519    return pLoggerInt;
     520}
     521
     522
     523RTDECL(PRTLOGGER)   RTLogDefaultInstanceEx(uint32_t fFlagsAndGroup)
     524{
     525    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)rtLogDefaultInstanceCommon();
     526    if (pLoggerInt)
     527        pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
     528    AssertCompileMemberOffset(RTLOGGERINTERNAL, Core, 0);
     529    return (PRTLOGGER)pLoggerInt;
     530}
     531RT_EXPORT_SYMBOL(RTLogDefaultInstanceEx);
     532
     533
     534/**
     535 * Common worker for RTLogGetDefaultInstance and RTLogGetDefaultInstanceEx.
     536 */
     537DECL_FORCE_INLINE(PRTLOGGER) rtLogGetDefaultInstanceCommon(void)
     538{
     539#ifdef IN_RING0
     540    /*
     541     * Check per thread loggers first.
     542     */
     543    if (g_cPerThreadLoggers)
     544    {
     545        const RTNATIVETHREAD Self = RTThreadNativeSelf();
     546        int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
     547        while (i-- > 0)
     548            if (g_aPerThreadLoggers[i].NativeThread == Self)
     549                return g_aPerThreadLoggers[i].pLogger;
     550    }
     551#endif /* IN_RING0 */
     552
     553    return g_pLogger;
     554}
     555
     556
     557RTDECL(PRTLOGGER) RTLogGetDefaultInstance(void)
     558{
     559    return rtLogGetDefaultInstanceCommon();
     560}
     561RT_EXPORT_SYMBOL(RTLogGetDefaultInstance);
     562
     563
     564RTDECL(PRTLOGGER) RTLogGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
     565{
     566    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)rtLogGetDefaultInstanceCommon();
     567    if (pLoggerInt)
     568        pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
     569    AssertCompileMemberOffset(RTLOGGERINTERNAL, Core, 0);
     570    return (PRTLOGGER)pLoggerInt;
     571}
     572RT_EXPORT_SYMBOL(RTLogGetDefaultInstanceEx);
     573
     574
     575/**
     576 * Sets the default logger instance.
     577 *
     578 * @returns iprt status code.
     579 * @param   pLogger     The new default logger instance.
     580 */
     581RTDECL(PRTLOGGER) RTLogSetDefaultInstance(PRTLOGGER pLogger)
     582{
     583    return ASMAtomicXchgPtrT(&g_pLogger, pLogger, PRTLOGGER);
     584}
     585RT_EXPORT_SYMBOL(RTLogSetDefaultInstance);
     586
     587
     588#ifdef IN_RING0
     589/**
     590 * Changes the default logger instance for the current thread.
     591 *
     592 * @returns IPRT status code.
     593 * @param   pLogger     The logger instance. Pass NULL for deregistration.
     594 * @param   uKey        Associated key for cleanup purposes. If pLogger is NULL,
     595 *                      all instances with this key will be deregistered. So in
     596 *                      order to only deregister the instance associated with the
     597 *                      current thread use 0.
     598 */
     599RTR0DECL(int) RTLogSetDefaultInstanceThread(PRTLOGGER pLogger, uintptr_t uKey)
     600{
     601    int             rc;
     602    RTNATIVETHREAD  Self = RTThreadNativeSelf();
     603    if (pLogger)
     604    {
     605        int32_t i;
     606        unsigned j;
     607
     608        AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
     609
     610        /*
     611         * Iterate the table to see if there is already an entry for this thread.
     612         */
     613        i = RT_ELEMENTS(g_aPerThreadLoggers);
     614        while (i-- > 0)
     615            if (g_aPerThreadLoggers[i].NativeThread == Self)
     616            {
     617                ASMAtomicWritePtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, (void *)uKey);
     618                g_aPerThreadLoggers[i].pLogger = pLogger;
     619                return VINF_SUCCESS;
     620            }
     621
     622        /*
     623         * Allocate a new table entry.
     624         */
     625        i = ASMAtomicIncS32(&g_cPerThreadLoggers);
     626        if (i > (int32_t)RT_ELEMENTS(g_aPerThreadLoggers))
     627        {
     628            ASMAtomicDecS32(&g_cPerThreadLoggers);
     629            return VERR_BUFFER_OVERFLOW; /* horrible error code! */
     630        }
     631
     632        for (j = 0; j < 10; j++)
     633        {
     634            i = RT_ELEMENTS(g_aPerThreadLoggers);
     635            while (i-- > 0)
     636            {
     637                AssertCompile(sizeof(RTNATIVETHREAD) == sizeof(void*));
     638                if (    g_aPerThreadLoggers[i].NativeThread == NIL_RTNATIVETHREAD
     639                    &&  ASMAtomicCmpXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].NativeThread, (void *)Self, (void *)NIL_RTNATIVETHREAD))
     640                {
     641                    ASMAtomicWritePtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, (void *)uKey);
     642                    ASMAtomicWritePtr(&g_aPerThreadLoggers[i].pLogger, pLogger);
     643                    return VINF_SUCCESS;
     644                }
     645            }
     646        }
     647
     648        ASMAtomicDecS32(&g_cPerThreadLoggers);
     649        rc = VERR_INTERNAL_ERROR;
     650    }
     651    else
     652    {
     653        /*
     654         * Search the array for the current thread.
     655         */
     656        int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
     657        while (i-- > 0)
     658            if (    g_aPerThreadLoggers[i].NativeThread == Self
     659                ||  g_aPerThreadLoggers[i].uKey == uKey)
     660            {
     661                ASMAtomicWriteNullPtr((void * volatile *)&g_aPerThreadLoggers[i].uKey);
     662                ASMAtomicWriteNullPtr(&g_aPerThreadLoggers[i].pLogger);
     663                ASMAtomicWriteHandle(&g_aPerThreadLoggers[i].NativeThread, NIL_RTNATIVETHREAD);
     664                ASMAtomicDecS32(&g_cPerThreadLoggers);
     665            }
     666
     667        rc = VINF_SUCCESS;
     668    }
     669    return rc;
     670}
     671RT_EXPORT_SYMBOL(RTLogSetDefaultInstanceThread);
     672#endif /* IN_RING0 */
     673
     674
     675RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstance(void)
     676{
     677    return g_pRelLogger;
     678}
     679RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstance);
     680
     681
     682RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
     683{
     684    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)g_pRelLogger;
     685    if (pLoggerInt)
     686        pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
     687    return (PRTLOGGER)pLoggerInt;
     688}
     689RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstanceEx);
     690
     691
     692/**
     693 * Sets the default logger instance.
     694 *
     695 * @returns iprt status code.
     696 * @param   pLogger     The new default release logger instance.
     697 */
     698RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger)
     699{
     700    return ASMAtomicXchgPtrT(&g_pRelLogger, pLogger, PRTLOGGER);
     701}
     702RT_EXPORT_SYMBOL(RTLogRelSetDefaultInstance);
     703
     704
     705/**
     706 *
     707 * This is the 2nd half of what RTLogGetDefaultInstanceEx() and
     708 * RTLogRelGetDefaultInstanceEx() does.
     709 *
     710 * @returns If the group has the specified flags enabled @a pLogger will be
     711 *          returned returned.  Otherwise NULL is returned.
     712 * @param   pLogger         The logger.  NULL is NULL.
     713 * @param   fFlagsAndGroup  The flags in the lower 16 bits, the group number in
     714 *                          the high 16 bits.
     715 */
     716RTDECL(PRTLOGGER)   RTLogCheckGroupFlags(PRTLOGGER pLogger, uint32_t fFlagsAndGroup)
    438717{
    439718    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    440     AssertPtrReturnVoid(pLoggerInt);
    441     Assert(pLoggerInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
    442 
    443     va_list args;
    444     va_start(args, pszFormat);
    445     rtlogLoggerExVLocked(pLoggerInt, 0, ~0U, pszFormat, args);
    446     va_end(args);
    447 }
    448 
    449 
    450 /**
    451  * Log phase callback function, assumes the lock is not held.
    452  *
    453  * @param   pLogger     The logger instance.
    454  * @param   pszFormat   Format string.
    455  * @param   ...         Optional arguments as specified in the format string.
    456  */
    457 static DECLCALLBACK(void) rtlogPhaseMsgNormal(PRTLOGGER pLogger, const char *pszFormat, ...)
    458 {
    459     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    460     AssertPtrReturnVoid(pLoggerInt);
    461     Assert(pLoggerInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
    462 
    463     va_list args;
    464     va_start(args, pszFormat);
    465     RTLogLoggerExV(&pLoggerInt->Core, 0, ~0U, pszFormat, args);
    466     va_end(args);
    467 }
    468 
    469 #endif /* IN_RING3 */
     719    if (pLoggerInt)
     720        pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
     721    return (PRTLOGGER)pLoggerInt;
     722}
     723RT_EXPORT_SYMBOL(RTLogCheckGroupFlags);
     724
     725
     726/*********************************************************************************************************************************
     727*   Ring Buffer                                                                                                                  *
     728*********************************************************************************************************************************/
    470729
    471730/**
     
    7431002}
    7441003
     1004
     1005/*********************************************************************************************************************************
     1006*   Create, Destroy, Setup                                                                                                       *
     1007*********************************************************************************************************************************/
    7451008
    7461009RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, const char *pszEnvVarBase, uint64_t fFlags, const char *pszGroupSettings,
     
    12121475RTDECL(int) RTLogSetCustomPrefixCallback(PRTLOGGER pLogger, PFNRTLOGPREFIX pfnCallback, void *pvUser)
    12131476{
    1214     /*
    1215      * Resolve defaults.
    1216      */
     1477    int               rc;
    12171478    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    1218     if (!pLoggerInt)
    1219     {
    1220         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1221         if (!pLoggerInt)
    1222             return VINF_SUCCESS;
    1223     }
    1224     AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
     1479    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    12251480
    12261481    /*
    12271482     * Do the work.
    12281483     */
    1229     rtlogLock(pLoggerInt);
    1230     pLoggerInt->pvPrefixUserArg = pvUser;
    1231     pLoggerInt->pfnPrefix       = pfnCallback;
    1232     rtlogUnlock(pLoggerInt);
    1233 
    1234     return VINF_SUCCESS;
     1484    rc = rtlogLock(pLoggerInt);
     1485    if (RT_SUCCESS(rc))
     1486    {
     1487        pLoggerInt->pvPrefixUserArg = pvUser;
     1488        pLoggerInt->pfnPrefix       = pfnCallback;
     1489        rtlogUnlock(pLoggerInt);
     1490    }
     1491
     1492    return rc;
    12351493}
    12361494RT_EXPORT_SYMBOL(RTLogSetCustomPrefixCallback);
     
    12501508RTDECL(int) RTLogSetFlushCallback(PRTLOGGER pLogger, PFNRTLOGFLUSH pfnFlush)
    12511509{
    1252     int rc;
    1253 
    1254     /*
    1255      * Resolve defaults.
    1256      */
     1510    int               rc;
    12571511    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    1258     if (!pLoggerInt)
    1259     {
    1260         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1261         if (!pLoggerInt)
    1262             return VINF_SUCCESS;
    1263     }
    1264     AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
     1512    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    12651513
    12661514    /*
     
    13681616RTDECL(int) RTLogGroupSettings(PRTLOGGER pLogger, const char *pszValue)
    13691617{
    1370 
    1371     /*
    1372      * Resolve defaults.
    1373      */
    13741618    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    1375     if (!pLoggerInt)
    1376     {
    1377         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1378         if (!pLoggerInt)
    1379             return VINF_SUCCESS;
    1380     }
     1619    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    13811620    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
    13821621
     
    16261865RTDECL(int) RTLogQueryGroupSettings(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
    16271866{
    1628     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    16291867    bool              fNotFirst  = false;
    16301868    int               rc         = VINF_SUCCESS;
     
    16321870    uint32_t          fGroup;
    16331871    uint32_t          i;
    1634 
     1872    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
     1873    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
     1874    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
    16351875    Assert(cchBuf);
    16361876
    16371877    /*
    1638      * Resolve defaults.
    1639      */
    1640     if (!pLoggerInt)
    1641     {
    1642         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1643         if (!pLoggerInt)
    1644         {
    1645             *pszBuf = '\0';
    1646             return VINF_SUCCESS;
    1647         }
    1648     }
    1649     Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
    1650 
     1878     * Check if all are the same.
     1879     */
    16511880    cGroups = pLoggerInt->cGroups;
    1652 
    1653     /*
    1654      * Check if all are the same.
    1655      */
    1656     fGroup = pLoggerInt->afGroups[0];
     1881    fGroup  = pLoggerInt->afGroups[0];
    16571882    for (i = 1; i < cGroups; i++)
    16581883        if (pLoggerInt->afGroups[i] != fGroup)
     
    16991924RTDECL(int) RTLogFlags(PRTLOGGER pLogger, const char *pszValue)
    17001925{
     1926    int               rc         = VINF_SUCCESS;
    17011927    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    1702     int               rc         = VINF_SUCCESS;
    1703 
    1704     /*
    1705      * Resolve defaults.
    1706      */
    1707     if (!pLoggerInt)
    1708     {
    1709         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1710         if (!pLoggerInt)
    1711             return VINF_SUCCESS;
    1712     }
     1928    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
     1929    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
    17131930
    17141931    /*
     
    17952012RTDECL(bool) RTLogSetBuffering(PRTLOGGER pLogger, bool fBuffered)
    17962013{
     2014    int               rc;
     2015    bool              fOld       = false;
    17972016    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    1798     bool              fOld;
    1799 
    1800     /*
    1801      * Resolve the logger instance.
    1802      */
    1803     if (!pLoggerInt)
    1804     {
    1805         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1806         if (!pLoggerInt)
    1807             return false;
    1808     }
    1809 
    1810     rtlogLock(pLoggerInt);
    1811     fOld  = !!(pLoggerInt->fFlags & RTLOGFLAGS_BUFFERED);
    1812     if (fBuffered)
    1813         pLoggerInt->fFlags |= RTLOGFLAGS_BUFFERED;
    1814     else
    1815         pLoggerInt->fFlags &= ~RTLOGFLAGS_BUFFERED;
    1816     rtlogUnlock(pLoggerInt);
     2017    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, false);
     2018
     2019    rc = rtlogLock(pLoggerInt);
     2020    if (RT_SUCCESS(rc))
     2021    {
     2022        fOld  = !!(pLoggerInt->fFlags & RTLOGFLAGS_BUFFERED);
     2023        if (fBuffered)
     2024            pLoggerInt->fFlags |= RTLOGFLAGS_BUFFERED;
     2025        else
     2026            pLoggerInt->fFlags &= ~RTLOGFLAGS_BUFFERED;
     2027        rtlogUnlock(pLoggerInt);
     2028    }
    18172029
    18182030    return fOld;
     
    18232035RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup)
    18242036{
     2037    int               rc;
     2038    uint32_t          cOld       = UINT32_MAX;
    18252039    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    1826 
    1827     /*
    1828      * Resolve the logger instance.
    1829      */
    1830     if (!pLoggerInt)
    1831     {
    1832         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1833         if (!pLoggerInt)
    1834             return UINT32_MAX;
    1835     }
    1836 
    1837     rtlogLock(pLoggerInt);
    1838     uint32_t cOld = pLoggerInt->cMaxEntriesPerGroup;
    1839     pLoggerInt->cMaxEntriesPerGroup = cMaxEntriesPerGroup;
    1840     rtlogUnlock(pLoggerInt);
     2040    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, UINT32_MAX);
     2041
     2042    rc = rtlogLock(pLoggerInt);
     2043    if (RT_SUCCESS(rc))
     2044    {
     2045        cOld = pLoggerInt->cMaxEntriesPerGroup;
     2046        pLoggerInt->cMaxEntriesPerGroup = cMaxEntriesPerGroup;
     2047        rtlogUnlock(pLoggerInt);
     2048    }
    18412049
    18422050    return cOld;
     
    18822090{
    18832091    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    1884     if (!pLoggerInt)
    1885     {
    1886         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1887         if (!pLoggerInt)
    1888             return UINT64_MAX;
    1889     }
     2092    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, UINT64_MAX);
     2093    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
    18902094    return pLoggerInt->fFlags;
    18912095}
     
    18962100 * Modifies the flag settings for the given logger.
    18972101 *
    1898  * @returns IPRT status code.  Returns VINF_SUCCESS if no default logger and @a
     2102 * @returns IPRT status code.  Returns VINF_SUCCESS if VINF_LOG_NO_LOGGER and @a
    18992103 *          pLogger is NULL.
    19002104 * @param   pLogger         Logger instance (NULL for default logger).
     
    19052109RTDECL(int) RTLogChangeFlags(PRTLOGGER pLogger, uint64_t fSet, uint64_t fClear)
    19062110{
     2111    int               rc;
     2112    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    19072113    AssertReturn(!(fSet & ~RTLOG_F_VALID_MASK), VERR_INVALID_FLAGS);
    1908 
    1909     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    1910     if (!pLoggerInt)
    1911     {
    1912         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1913         if (!pLoggerInt)
    1914             return VINF_SUCCESS;
    1915     }
    1916     AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
    1917     AssertReturn(pLoggerInt->uRevision == RTLOGGERINTERNAL_REV, VERR_LOG_REVISION_MISMATCH);
     2114    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    19182115
    19192116    /*
    19202117     * Make the changes.
    19212118     */
    1922     pLoggerInt->fFlags &= ~fClear;
    1923     pLoggerInt->fFlags |= fSet;
    1924 
    1925     return VINF_SUCCESS;
     2119    rc = rtlogLock(pLoggerInt);
     2120    if (RT_SUCCESS(rc))
     2121    {
     2122        pLoggerInt->fFlags &= ~fClear;
     2123        pLoggerInt->fFlags |= fSet;
     2124        rtlogUnlock(pLoggerInt);
     2125    }
     2126    return rc;
    19262127}
    19272128RT_EXPORT_SYMBOL(RTLogChangeFlags);
     
    19392140RTDECL(int) RTLogQueryFlags(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
    19402141{
    1941     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    19422142    bool              fNotFirst  = false;
    19432143    int               rc         = VINF_SUCCESS;
    19442144    uint32_t          fFlags;
    19452145    unsigned          i;
     2146    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    19462147
    19472148    Assert(cchBuf);
    1948 
    1949     /*
    1950      * Resolve defaults.
    1951      */
    1952     if (!pLoggerInt)
    1953     {
    1954         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    1955         if (!pLoggerInt)
    1956         {
    1957             *pszBuf = '\0';
    1958             return VINF_SUCCESS;
    1959         }
    1960     }
     2149    *pszBuf = '\0';
     2150    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
     2151    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
    19612152
    19622153    /*
     
    20432234RTDECL(int) RTLogDestinations(PRTLOGGER pLogger, char const *pszValue)
    20442235{
    2045     /*
    2046      * Resolve defaults.
    2047      */
    20482236    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    2049     if (!pLoggerInt)
    2050     {
    2051         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    2052         if (!pLoggerInt)
    2053             return VINF_SUCCESS;
    2054     }
     2237    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
     2238    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
     2239    /** @todo locking?   */
    20552240
    20562241    /*
     
    22482433RTDECL(int) RTLogClearFileDelayFlag(PRTLOGGER pLogger, PRTERRINFO pErrInfo)
    22492434{
    2250     /*
    2251      * Resolve defaults.
    2252      */
    22532435    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    2254     if (!pLoggerInt)
    2255     {
    2256         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    2257         if (!pLoggerInt)
    2258             return VINF_SUCCESS;
    2259     }
     2436    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    22602437
    22612438    /*
     
    22922469 * additional arguments, like RTLOGDEST_FILE.
    22932470 *
    2294  * @returns IPRT status code.  Returns VINF_SUCCESS if no default logger and @a
    2295  *          pLogger is NULL.
     2471 * @returns IPRT status code.  Returns VINF_LOG_NO_LOGGER if VINF_LOG_NO_LOGGER
     2472 *          and @a pLogger is NULL.
    22962473 * @param   pLogger            Logger instance (NULL for default logger).
    22972474 * @param   fSet               Mask of destinations to set (OR).
     
    23002477RTDECL(int) RTLogChangeDestinations(PRTLOGGER pLogger, uint32_t fSet, uint32_t fClear)
    23012478{
     2479    int               rc;
    23022480    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    23032481    AssertCompile((RTLOG_DST_VALID_MASK & RTLOG_DST_CHANGE_MASK) == RTLOG_DST_CHANGE_MASK);
    23042482    AssertReturn(!(fSet & ~RTLOG_DST_CHANGE_MASK), VERR_INVALID_FLAGS);
    23052483    AssertReturn(!(fClear & ~RTLOG_DST_CHANGE_MASK), VERR_INVALID_FLAGS);
    2306 
    2307     /*
    2308      * Resolve defaults.
    2309      */
    2310     if (!pLoggerInt)
    2311     {
    2312         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    2313         if (!pLoggerInt)
    2314             return VINF_SUCCESS;
    2315     }
    2316     AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
    2317     AssertReturn(pLoggerInt->uRevision == RTLOGGERINTERNAL_REV, VERR_LOG_REVISION_MISMATCH);
     2484    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    23182485
    23192486    /*
    23202487     * Make the changes.
    23212488     */
    2322     pLoggerInt->fDestFlags &= ~fClear;
    2323     pLoggerInt->fDestFlags |= fSet;
     2489    rc = rtlogLock(pLoggerInt);
     2490    if (RT_SUCCESS(rc))
     2491    {
     2492        pLoggerInt->fDestFlags &= ~fClear;
     2493        pLoggerInt->fDestFlags |= fSet;
     2494        rtlogUnlock(pLoggerInt);
     2495    }
    23242496
    23252497    return VINF_SUCCESS;
     
    23672539    AssertReturn(cchBuf, VERR_INVALID_PARAMETER);
    23682540    *pszBuf = '\0';
    2369 
    2370     /*
    2371      * Resolve defaults.
    2372      */
    2373     if (!pLoggerInt)
    2374     {
    2375         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    2376         if (!pLoggerInt)
    2377             return VINF_SUCCESS;
    2378     }
     2541    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
     2542    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
    23792543
    23802544    /*
     
    24782642}
    24792643
     2644#ifdef IN_RING3
     2645
     2646/**
     2647 * Opens/creates the log file.
     2648 *
     2649 * @param   pLoggerInt      The logger instance to update. NULL is not allowed!
     2650 * @param   pErrInfo        Where to return extended error information.
     2651 *                          Optional.
     2652 */
     2653static int rtlogFileOpen(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo)
     2654{
     2655    uint32_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_NONE;
     2656    if (pLoggerInt->fFlags & RTLOGFLAGS_APPEND)
     2657        fOpen |= RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND;
     2658    else
     2659    {
     2660        RTFileDelete(pLoggerInt->szFilename);
     2661        fOpen |= RTFILE_O_CREATE;
     2662    }
     2663    if (pLoggerInt->fFlags & RTLOGFLAGS_WRITE_THROUGH)
     2664        fOpen |= RTFILE_O_WRITE_THROUGH;
     2665    if (pLoggerInt->fDestFlags & RTLOGDEST_F_NO_DENY)
     2666        fOpen = (fOpen & ~RTFILE_O_DENY_NONE) | RTFILE_O_DENY_NOT_DELETE;
     2667
     2668    unsigned cBackoff = 0;
     2669    int rc = RTFileOpen(&pLoggerInt->hFile, pLoggerInt->szFilename, fOpen);
     2670    while (   (   rc == VERR_SHARING_VIOLATION
     2671               || (rc == VERR_ALREADY_EXISTS && !(pLoggerInt->fFlags & RTLOGFLAGS_APPEND)))
     2672           && cBackoff < RT_ELEMENTS(g_acMsLogBackoff))
     2673    {
     2674        RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
     2675        if (!(pLoggerInt->fFlags & RTLOGFLAGS_APPEND))
     2676            RTFileDelete(pLoggerInt->szFilename);
     2677        rc = RTFileOpen(&pLoggerInt->hFile, pLoggerInt->szFilename, fOpen);
     2678    }
     2679    if (RT_SUCCESS(rc))
     2680    {
     2681        rc = RTFileQuerySize(pLoggerInt->hFile, &pLoggerInt->cbHistoryFileWritten);
     2682        if (RT_FAILURE(rc))
     2683        {
     2684            /* Don't complain if this fails, assume the file is empty. */
     2685            pLoggerInt->cbHistoryFileWritten = 0;
     2686            rc = VINF_SUCCESS;
     2687        }
     2688    }
     2689    else
     2690    {
     2691        pLoggerInt->hFile = NIL_RTFILE;
     2692        RTErrInfoSetF(pErrInfo, rc, N_("could not open file '%s' (fOpen=%#x)"), pLoggerInt->szFilename, fOpen);
     2693    }
     2694    return rc;
     2695}
     2696
     2697
     2698/**
     2699 * Closes, rotates and opens the log files if necessary.
     2700 *
     2701 * Used by the rtlogFlush() function as well as RTLogCreateExV() by way of
     2702 * rtR3LogOpenFileDestination().
     2703 *
     2704 * @param   pLoggerInt  The logger instance to update. NULL is not allowed!
     2705 * @param   uTimeSlot   Current time slot (for tikme based rotation).
     2706 * @param   fFirst      Flag whether this is the beginning of logging, i.e.
     2707 *                      called from RTLogCreateExV.  Prevents pfnPhase from
     2708 *                      being called.
     2709 * @param   pErrInfo    Where to return extended error information. Optional.
     2710 */
     2711static void rtlogRotate(PRTLOGGERINTERNAL pLoggerInt, uint32_t uTimeSlot, bool fFirst, PRTERRINFO pErrInfo)
     2712{
     2713    /* Suppress rotating empty log files simply because the time elapsed. */
     2714    if (RT_UNLIKELY(!pLoggerInt->cbHistoryFileWritten))
     2715        pLoggerInt->uHistoryTimeSlotStart = uTimeSlot;
     2716
     2717    /* Check rotation condition: file still small enough and not too old? */
     2718    if (RT_LIKELY(   pLoggerInt->cbHistoryFileWritten < pLoggerInt->cbHistoryFileMax
     2719                  && uTimeSlot == pLoggerInt->uHistoryTimeSlotStart))
     2720        return;
     2721
     2722    /*
     2723     * Save "disabled" log flag and make sure logging is disabled.
     2724     * The logging in the functions called during log file history
     2725     * rotation would cause severe trouble otherwise.
     2726     */
     2727    uint32_t const fSavedFlags = pLoggerInt->fFlags;
     2728    pLoggerInt->fFlags |= RTLOGFLAGS_DISABLED;
     2729
     2730    /*
     2731     * Disable log rotation temporarily, otherwise with extreme settings and
     2732     * chatty phase logging we could run into endless rotation.
     2733     */
     2734    uint32_t const cSavedHistory = pLoggerInt->cHistory;
     2735    pLoggerInt->cHistory = 0;
     2736
     2737    /*
     2738     * Close the old log file.
     2739     */
     2740    if (pLoggerInt->hFile != NIL_RTFILE)
     2741    {
     2742        /* Use the callback to generate some final log contents, but only if
     2743         * this is a rotation with a fully set up logger. Leave the other case
     2744         * to the RTLogCreateExV function. */
     2745        if (pLoggerInt->pfnPhase && !fFirst)
     2746        {
     2747            uint32_t fODestFlags = pLoggerInt->fDestFlags;
     2748            pLoggerInt->fDestFlags &= RTLOGDEST_FILE;
     2749            pLoggerInt->pfnPhase(&pLoggerInt->Core, RTLOGPHASE_PREROTATE, rtlogPhaseMsgLocked);
     2750            pLoggerInt->fDestFlags = fODestFlags;
     2751        }
     2752        RTFileClose(pLoggerInt->hFile);
     2753        pLoggerInt->hFile = NIL_RTFILE;
     2754    }
     2755
     2756    if (cSavedHistory)
     2757    {
     2758        /*
     2759         * Rotate the log files.
     2760         */
     2761        for (uint32_t i = cSavedHistory - 1; i + 1 > 0; i--)
     2762        {
     2763            char szOldName[sizeof(pLoggerInt->szFilename) + 32];
     2764            if (i > 0)
     2765                RTStrPrintf(szOldName, sizeof(szOldName), "%s.%u", pLoggerInt->szFilename, i);
     2766            else
     2767                RTStrCopy(szOldName, sizeof(szOldName), pLoggerInt->szFilename);
     2768
     2769            char szNewName[sizeof(pLoggerInt->szFilename) + 32];
     2770            RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLoggerInt->szFilename, i + 1);
     2771
     2772            unsigned cBackoff = 0;
     2773            int rc = RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE);
     2774            while (   rc == VERR_SHARING_VIOLATION
     2775                   && cBackoff < RT_ELEMENTS(g_acMsLogBackoff))
     2776            {
     2777                RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
     2778                rc = RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE);
     2779            }
     2780
     2781            if (rc == VERR_FILE_NOT_FOUND)
     2782                RTFileDelete(szNewName);
     2783        }
     2784
     2785        /*
     2786         * Delete excess log files.
     2787         */
     2788        for (uint32_t i = cSavedHistory + 1; ; i++)
     2789        {
     2790            char szExcessName[sizeof(pLoggerInt->szFilename) + 32];
     2791            RTStrPrintf(szExcessName, sizeof(szExcessName), "%s.%u", pLoggerInt->szFilename, i);
     2792            int rc = RTFileDelete(szExcessName);
     2793            if (RT_FAILURE(rc))
     2794                break;
     2795        }
     2796    }
     2797
     2798    /*
     2799     * Update logger state and create new log file.
     2800     */
     2801    pLoggerInt->cbHistoryFileWritten = 0;
     2802    pLoggerInt->uHistoryTimeSlotStart = uTimeSlot;
     2803    rtlogFileOpen(pLoggerInt, pErrInfo);
     2804
     2805    /*
     2806     * Use the callback to generate some initial log contents, but only if this
     2807     * is a rotation with a fully set up logger.  Leave the other case to the
     2808     * RTLogCreateExV function.
     2809     */
     2810    if (pLoggerInt->pfnPhase && !fFirst)
     2811    {
     2812        uint32_t const fSavedDestFlags = pLoggerInt->fDestFlags;
     2813        pLoggerInt->fDestFlags &= RTLOGDEST_FILE;
     2814        pLoggerInt->pfnPhase(&pLoggerInt->Core, RTLOGPHASE_POSTROTATE, rtlogPhaseMsgLocked);
     2815        pLoggerInt->fDestFlags = fSavedDestFlags;
     2816    }
     2817
     2818    /* Restore saved values. */
     2819    pLoggerInt->cHistory = cSavedHistory;
     2820    pLoggerInt->fFlags   = fSavedFlags;
     2821}
     2822
     2823
     2824/**
     2825 * Worker for RTLogCreateExV and RTLogClearFileDelayFlag.
     2826 *
     2827 * This will later be used to reopen the file by RTLogDestinations.
     2828 *
     2829 * @returns IPRT status code.
     2830 * @param   pLoggerInt          The logger.
     2831 * @param   pErrInfo            Where to return extended error information.
     2832 *                              Optional.
     2833 */
     2834static int rtR3LogOpenFileDestination(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo)
     2835{
     2836    int rc;
     2837    if (pLoggerInt->fFlags & RTLOGFLAGS_APPEND)
     2838    {
     2839        rc = rtlogFileOpen(pLoggerInt, pErrInfo);
     2840
     2841        /* Rotate in case of appending to a too big log file,
     2842           otherwise this simply doesn't do anything. */
     2843        rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
     2844    }
     2845    else
     2846    {
     2847        /* Force rotation if it is configured. */
     2848        pLoggerInt->cbHistoryFileWritten = UINT64_MAX;
     2849        rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
     2850
     2851        /* If the file is not open then rotation is not set up. */
     2852        if (pLoggerInt->hFile == NIL_RTFILE)
     2853        {
     2854            pLoggerInt->cbHistoryFileWritten = 0;
     2855            rc = rtlogFileOpen(pLoggerInt, pErrInfo);
     2856        }
     2857        else
     2858            rc = VINF_SUCCESS;
     2859    }
     2860    return rc;
     2861}
     2862
     2863#endif /* IN_RING3 */
     2864
     2865
     2866/*********************************************************************************************************************************
     2867*   Bulk Reconfig & Logging for ring-0 EMT loggers.                                                                              *
     2868*********************************************************************************************************************************/
    24802869
    24812870/**
     
    24952884RTDECL(int) RTLogBulkUpdate(PRTLOGGER pLogger, uint64_t fFlags, uint32_t uGroupCrc32, uint32_t cGroups, uint32_t const *pafGroups)
    24962885{
     2886    int               rc;
    24972887    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    2498     int               rc;
    2499 
    2500     /*
    2501      * Resolve defaults.
    2502      */
    2503     if (!pLoggerInt)
    2504     {
    2505         pLoggerInt = (PRTLOGGERINTERNAL)g_pLogger;
    2506         if (!pLoggerInt)
    2507             return VINF_SUCCESS;
    2508     }
     2888    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    25092889
    25102890    /*
     
    25532933    uint32_t const    cGroupsAlloc = *pcGroups;
    25542934
    2555     /*
    2556      * Resolve defaults.
    2557      */
    2558     if (!pLoggerInt)
    2559     {
    2560         pLoggerInt = (PRTLOGGERINTERNAL)g_pLogger;
    2561         if (!pLoggerInt)
    2562         {
    2563             *pfFlags      = 0;
    2564             *puGroupCrc32 = 0;
    2565             *pcGroups     = 0;
    2566             return VINF_SUCCESS;
    2567         }
    2568     }
     2935    *pfFlags      = 0;
     2936    *puGroupCrc32 = 0;
     2937    *pcGroups     = 0;
     2938    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    25692939    AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
    25702940
     
    25802950        return VINF_SUCCESS;
    25812951    }
    2582     *puGroupCrc32 = 0;
    25832952    return VERR_BUFFER_OVERFLOW;
    25842953}
     
    26002969RTDECL(int) RTLogBulkWrite(PRTLOGGER pLogger, const char *pch, size_t cch)
    26012970{
    2602     /*
    2603      * Resolve defaults.
    2604      */
    26052971    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    2606     if (!pLoggerInt)
    2607     {
    2608         pLoggerInt = (PRTLOGGERINTERNAL)g_pLogger;
    2609         if (!pLoggerInt)
    2610             return VINF_SUCCESS;
    2611     }
     2972    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    26122973
    26132974    /*
     
    26633024
    26643025
     3026/*********************************************************************************************************************************
     3027*   Flushing                                                                                                                     *
     3028*********************************************************************************************************************************/
     3029
    26653030/**
    26663031 * Flushes the specified logger.
     
    26703035 *                      will not be initialized by this call.
    26713036 */
    2672 RTDECL(void) RTLogFlush(PRTLOGGER pLogger)
    2673 {
    2674     /*
    2675      * Resolve defaults.
    2676      */
     3037RTDECL(int) RTLogFlush(PRTLOGGER pLogger)
     3038{
    26773039    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    2678     if (!pLoggerInt)
    2679     {
    2680         pLoggerInt = (PRTLOGGERINTERNAL)g_pLogger;
    2681         if (!pLoggerInt)
    2682             return;
    2683     }
     3040    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
    26843041    Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC);
    26853042    AssertPtr(pLoggerInt->pBufDesc);
     
    26873044
    26883045    /*
    2689      * Any thing to flush?
    2690      */
    2691     if (   pLoggerInt->pBufDesc->offBuf > 0
    2692         || (pLoggerInt->fDestFlags & RTLOGDEST_RINGBUF))
     3046     * Acquire logger instance sem.
     3047     */
     3048    int rc = rtlogLock(pLoggerInt);
     3049    if (RT_SUCCESS(rc))
    26933050    {
    26943051        /*
    2695          * Acquire logger instance sem.
     3052         * Any thing to flush?
    26963053         */
    2697         int rc = rtlogLock(pLoggerInt);
    2698         if (RT_SUCCESS(rc))
     3054        if (   pLoggerInt->pBufDesc->offBuf > 0
     3055            || (pLoggerInt->fDestFlags & RTLOGDEST_RINGBUF))
    26993056        {
    27003057            /*
     
    27103067                && pLoggerInt->pszRingBuf /* paranoia */)
    27113068                rtLogRingBufFlush(pLoggerInt);
    2712 
    2713             /*
    2714              * Release the semaphore.
    2715              */
    2716             rtlogUnlock(pLoggerInt);
    2717         }
    2718     }
     3069        }
     3070
     3071        rtlogUnlock(pLoggerInt);
     3072    }
     3073    return rc;
    27193074}
    27203075RT_EXPORT_SYMBOL(RTLogFlush);
    27213076
    2722 
    2723 /**
    2724  * Common worker for RTLogDefaultInstance and RTLogDefaultInstanceEx.
    2725  */
    2726 DECL_NO_INLINE(static, PRTLOGGER) rtLogDefaultInstanceCreateNew(void)
    2727 {
    2728     PRTLOGGER pRet = RTLogDefaultInit();
    2729     if (pRet)
    2730     {
    2731         bool fRc = ASMAtomicCmpXchgPtr(&g_pLogger, pRet, NULL);
    2732         if (!fRc)
    2733         {
    2734             RTLogDestroy(pRet);
    2735             pRet = g_pLogger;
    2736         }
    2737     }
    2738     return pRet;
    2739 }
    2740 
    2741 
    2742 /**
    2743  * Common worker for RTLogDefaultInstance and RTLogDefaultInstanceEx.
    2744  */
    2745 DECL_FORCE_INLINE(PRTLOGGER) rtLogDefaultInstanceCommon(void)
    2746 {
    2747     PRTLOGGER pRet;
    2748 
    2749 #ifdef IN_RING0
    2750     /*
    2751      * Check per thread loggers first.
    2752      */
    2753     if (g_cPerThreadLoggers)
    2754     {
    2755         const RTNATIVETHREAD Self = RTThreadNativeSelf();
    2756         int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
    2757         while (i-- > 0)
    2758             if (g_aPerThreadLoggers[i].NativeThread == Self)
    2759                 return g_aPerThreadLoggers[i].pLogger;
    2760     }
    2761 #endif /* IN_RING0 */
    2762 
    2763     /*
    2764      * If no per thread logger, use the default one.
    2765      */
    2766     pRet = g_pLogger;
    2767     if (RT_LIKELY(pRet))
    2768     { /* likely */ }
    2769     else
    2770         pRet = rtLogDefaultInstanceCreateNew();
    2771     return pRet;
    2772 }
    2773 
    2774 
    2775 RTDECL(PRTLOGGER)   RTLogDefaultInstance(void)
    2776 {
    2777     return rtLogDefaultInstanceCommon();
    2778 }
    2779 RT_EXPORT_SYMBOL(RTLogDefaultInstance);
    2780 
    2781 
    2782 /**
    2783  * Worker for RTLogDefaultInstanceEx, RTLogGetDefaultInstanceEx,
    2784  * RTLogRelGetDefaultInstanceEx and RTLogCheckGroupFlags.
    2785  */
    2786 DECL_FORCE_INLINE(PRTLOGGERINTERNAL) rtLogCheckGroupFlagsWorker(PRTLOGGERINTERNAL pLoggerInt, uint32_t fFlagsAndGroup)
    2787 {
    2788     if (pLoggerInt->fFlags & RTLOGFLAGS_DISABLED)
    2789         pLoggerInt = NULL;
    2790     else
    2791     {
    2792         uint32_t const fFlags = RT_LO_U16(fFlagsAndGroup);
    2793         uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);
    2794         if (   iGroup != UINT16_MAX
    2795              && (   (pLoggerInt->afGroups[iGroup < pLoggerInt->cGroups ? iGroup : 0] & (fFlags | RTLOGGRPFLAGS_ENABLED))
    2796                  != (fFlags | RTLOGGRPFLAGS_ENABLED)))
    2797             pLoggerInt = NULL;
    2798     }
    2799     return pLoggerInt;
    2800 }
    2801 
    2802 
    2803 RTDECL(PRTLOGGER)   RTLogDefaultInstanceEx(uint32_t fFlagsAndGroup)
    2804 {
    2805     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)rtLogDefaultInstanceCommon();
    2806     if (pLoggerInt)
    2807         pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
    2808     AssertCompileMemberOffset(RTLOGGERINTERNAL, Core, 0);
    2809     return (PRTLOGGER)pLoggerInt;
    2810 }
    2811 RT_EXPORT_SYMBOL(RTLogDefaultInstanceEx);
    2812 
    2813 
    2814 /**
    2815  * Common worker for RTLogGetDefaultInstance and RTLogGetDefaultInstanceEx.
    2816  */
    2817 DECL_FORCE_INLINE(PRTLOGGER) rtLogGetDefaultInstanceCommon(void)
    2818 {
    2819 #ifdef IN_RING0
    2820     /*
    2821      * Check per thread loggers first.
    2822      */
    2823     if (g_cPerThreadLoggers)
    2824     {
    2825         const RTNATIVETHREAD Self = RTThreadNativeSelf();
    2826         int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
    2827         while (i-- > 0)
    2828             if (g_aPerThreadLoggers[i].NativeThread == Self)
    2829                 return g_aPerThreadLoggers[i].pLogger;
    2830     }
    2831 #endif /* IN_RING0 */
    2832 
    2833     return g_pLogger;
    2834 }
    2835 
    2836 
    2837 RTDECL(PRTLOGGER) RTLogGetDefaultInstance(void)
    2838 {
    2839     return rtLogGetDefaultInstanceCommon();
    2840 }
    2841 RT_EXPORT_SYMBOL(RTLogGetDefaultInstance);
    2842 
    2843 
    2844 RTDECL(PRTLOGGER) RTLogGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
    2845 {
    2846     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)rtLogGetDefaultInstanceCommon();
    2847     if (pLoggerInt)
    2848         pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
    2849     AssertCompileMemberOffset(RTLOGGERINTERNAL, Core, 0);
    2850     return (PRTLOGGER)pLoggerInt;
    2851 }
    2852 RT_EXPORT_SYMBOL(RTLogGetDefaultInstanceEx);
    2853 
    2854 
    2855 /**
    2856  * Sets the default logger instance.
    2857  *
    2858  * @returns iprt status code.
    2859  * @param   pLogger     The new default logger instance.
    2860  */
    2861 RTDECL(PRTLOGGER) RTLogSetDefaultInstance(PRTLOGGER pLogger)
    2862 {
    2863     return ASMAtomicXchgPtrT(&g_pLogger, pLogger, PRTLOGGER);
    2864 }
    2865 RT_EXPORT_SYMBOL(RTLogSetDefaultInstance);
    2866 
    2867 
    2868 #ifdef IN_RING0
    2869 /**
    2870  * Changes the default logger instance for the current thread.
    2871  *
    2872  * @returns IPRT status code.
    2873  * @param   pLogger     The logger instance. Pass NULL for deregistration.
    2874  * @param   uKey        Associated key for cleanup purposes. If pLogger is NULL,
    2875  *                      all instances with this key will be deregistered. So in
    2876  *                      order to only deregister the instance associated with the
    2877  *                      current thread use 0.
    2878  */
    2879 RTR0DECL(int) RTLogSetDefaultInstanceThread(PRTLOGGER pLogger, uintptr_t uKey)
    2880 {
    2881     int             rc;
    2882     RTNATIVETHREAD  Self = RTThreadNativeSelf();
    2883     if (pLogger)
    2884     {
    2885         int32_t i;
    2886         unsigned j;
    2887 
    2888         AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
    2889 
    2890         /*
    2891          * Iterate the table to see if there is already an entry for this thread.
    2892          */
    2893         i = RT_ELEMENTS(g_aPerThreadLoggers);
    2894         while (i-- > 0)
    2895             if (g_aPerThreadLoggers[i].NativeThread == Self)
    2896             {
    2897                 ASMAtomicWritePtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, (void *)uKey);
    2898                 g_aPerThreadLoggers[i].pLogger = pLogger;
    2899                 return VINF_SUCCESS;
    2900             }
    2901 
    2902         /*
    2903          * Allocate a new table entry.
    2904          */
    2905         i = ASMAtomicIncS32(&g_cPerThreadLoggers);
    2906         if (i > (int32_t)RT_ELEMENTS(g_aPerThreadLoggers))
    2907         {
    2908             ASMAtomicDecS32(&g_cPerThreadLoggers);
    2909             return VERR_BUFFER_OVERFLOW; /* horrible error code! */
    2910         }
    2911 
    2912         for (j = 0; j < 10; j++)
    2913         {
    2914             i = RT_ELEMENTS(g_aPerThreadLoggers);
    2915             while (i-- > 0)
    2916             {
    2917                 AssertCompile(sizeof(RTNATIVETHREAD) == sizeof(void*));
    2918                 if (    g_aPerThreadLoggers[i].NativeThread == NIL_RTNATIVETHREAD
    2919                     &&  ASMAtomicCmpXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].NativeThread, (void *)Self, (void *)NIL_RTNATIVETHREAD))
    2920                 {
    2921                     ASMAtomicWritePtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, (void *)uKey);
    2922                     ASMAtomicWritePtr(&g_aPerThreadLoggers[i].pLogger, pLogger);
    2923                     return VINF_SUCCESS;
    2924                 }
    2925             }
    2926         }
    2927 
    2928         ASMAtomicDecS32(&g_cPerThreadLoggers);
    2929         rc = VERR_INTERNAL_ERROR;
    2930     }
    2931     else
    2932     {
    2933         /*
    2934          * Search the array for the current thread.
    2935          */
    2936         int32_t i = RT_ELEMENTS(g_aPerThreadLoggers);
    2937         while (i-- > 0)
    2938             if (    g_aPerThreadLoggers[i].NativeThread == Self
    2939                 ||  g_aPerThreadLoggers[i].uKey == uKey)
    2940             {
    2941                 ASMAtomicWriteNullPtr((void * volatile *)&g_aPerThreadLoggers[i].uKey);
    2942                 ASMAtomicWriteNullPtr(&g_aPerThreadLoggers[i].pLogger);
    2943                 ASMAtomicWriteHandle(&g_aPerThreadLoggers[i].NativeThread, NIL_RTNATIVETHREAD);
    2944                 ASMAtomicDecS32(&g_cPerThreadLoggers);
    2945             }
    2946 
    2947         rc = VINF_SUCCESS;
    2948     }
    2949     return rc;
    2950 }
    2951 RT_EXPORT_SYMBOL(RTLogSetDefaultInstanceThread);
    2952 #endif /* IN_RING0 */
    2953 
    2954 
    2955 RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstance(void)
    2956 {
    2957     return g_pRelLogger;
    2958 }
    2959 RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstance);
    2960 
    2961 
    2962 RTDECL(PRTLOGGER)   RTLogRelGetDefaultInstanceEx(uint32_t fFlagsAndGroup)
    2963 {
    2964     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)g_pRelLogger;
    2965     if (pLoggerInt)
    2966         pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
    2967     return (PRTLOGGER)pLoggerInt;
    2968 }
    2969 RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstanceEx);
    2970 
    2971 
    2972 /**
    2973  * Sets the default logger instance.
    2974  *
    2975  * @returns iprt status code.
    2976  * @param   pLogger     The new default release logger instance.
    2977  */
    2978 RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger)
    2979 {
    2980     return ASMAtomicXchgPtrT(&g_pRelLogger, pLogger, PRTLOGGER);
    2981 }
    2982 RT_EXPORT_SYMBOL(RTLogRelSetDefaultInstance);
    2983 
    2984 
    2985 /**
    2986  *
    2987  * This is the 2nd half of what RTLogGetDefaultInstanceEx() and
    2988  * RTLogRelGetDefaultInstanceEx() does.
    2989  *
    2990  * @returns If the group has the specified flags enabled @a pLogger will be
    2991  *          returned returned.  Otherwise NULL is returned.
    2992  * @param   pLogger         The logger.  NULL is NULL.
    2993  * @param   fFlagsAndGroup  The flags in the lower 16 bits, the group number in
    2994  *                          the high 16 bits.
    2995  */
    2996 RTDECL(PRTLOGGER)   RTLogCheckGroupFlags(PRTLOGGER pLogger, uint32_t fFlagsAndGroup)
    2997 {
    2998     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    2999     if (pLoggerInt)
    3000         pLoggerInt = rtLogCheckGroupFlagsWorker(pLoggerInt, fFlagsAndGroup);
    3001     return (PRTLOGGER)pLoggerInt;
    3002 }
    3003 RT_EXPORT_SYMBOL(RTLogCheckGroupFlags);
    3004 
    3005 
    3006 /**
    3007  * Write to a logger instance.
    3008  *
    3009  * @param   pLogger     Pointer to logger instance.
    3010  * @param   pszFormat   Format string.
    3011  * @param   args        Format arguments.
    3012  */
    3013 RTDECL(void) RTLogLoggerV(PRTLOGGER pLogger, const char *pszFormat, va_list args)
    3014 {
    3015     RTLogLoggerExV(pLogger, 0, ~0U, pszFormat, args);
    3016 }
    3017 RT_EXPORT_SYMBOL(RTLogLoggerV);
    3018 
    3019 
    3020 /**
    3021  * Write to a logger instance.
    3022  *
    3023  * This function will check whether the instance, group and flags makes up a
    3024  * logging kind which is currently enabled before writing anything to the log.
    3025  *
    3026  * @param   pLogger     Pointer to logger instance. If NULL the default logger instance will be attempted.
    3027  * @param   fFlags      The logging flags.
    3028  * @param   iGroup      The group.
    3029  *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
    3030  *                      only for internal usage!
    3031  * @param   pszFormat   Format string.
    3032  * @param   args        Format arguments.
    3033  */
    3034 RTDECL(void) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args)
    3035 {
    3036     PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
    3037     int               rc;
    3038 
    3039     /*
    3040      * A NULL logger means default instance.
    3041      */
    3042     if (!pLoggerInt)
    3043     {
    3044         pLoggerInt = (PRTLOGGERINTERNAL)RTLogDefaultInstance();
    3045         if (!pLoggerInt)
    3046             return;
    3047     }
    3048 
    3049     /*
    3050      * Validate and correct iGroup.
    3051      */
    3052     if (iGroup != ~0U && iGroup >= pLoggerInt->cGroups)
    3053         iGroup = 0;
    3054 
    3055     /*
    3056      * If no output, then just skip it.
    3057      */
    3058     if (    (pLoggerInt->fFlags & RTLOGFLAGS_DISABLED)
    3059         || !pLoggerInt->fDestFlags
    3060         || !pszFormat || !*pszFormat)
    3061         return;
    3062     if (    iGroup != ~0U
    3063         &&  (pLoggerInt->afGroups[iGroup] & (fFlags | RTLOGGRPFLAGS_ENABLED)) != (fFlags | RTLOGGRPFLAGS_ENABLED))
    3064         return;
    3065 
    3066     /*
    3067      * Acquire logger instance sem.
    3068      */
    3069     rc = rtlogLock(pLoggerInt);
    3070     if (RT_FAILURE(rc))
    3071     {
    3072 #ifdef IN_RING0
    3073         if (pLoggerInt->fDestFlags & ~RTLOGDEST_FILE)
    3074             rtR0LogLoggerExFallback(pLoggerInt->fDestFlags, pLoggerInt->fFlags, pLoggerInt, pszFormat, args);
    3075 #endif
    3076         return;
    3077     }
    3078 
    3079     /*
    3080      * Check restrictions and call worker.
    3081      */
    3082     if (RT_UNLIKELY(   (pLoggerInt->fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
    3083                     && iGroup < pLoggerInt->cGroups
    3084                     && (pLoggerInt->afGroups[iGroup] & RTLOGGRPFLAGS_RESTRICT)
    3085                     && ++pLoggerInt->pacEntriesPerGroup[iGroup] >= pLoggerInt->cMaxEntriesPerGroup ))
    3086     {
    3087         uint32_t cEntries = pLoggerInt->pacEntriesPerGroup[iGroup];
    3088         if (cEntries > pLoggerInt->cMaxEntriesPerGroup)
    3089             pLoggerInt->pacEntriesPerGroup[iGroup] = cEntries - 1;
    3090         else
    3091         {
    3092             rtlogLoggerExVLocked(pLoggerInt, fFlags, iGroup, pszFormat, args);
    3093             if (   pLoggerInt->papszGroups
    3094                 && pLoggerInt->papszGroups[iGroup])
    3095                 rtlogLoggerExFLocked(pLoggerInt, fFlags, iGroup, "%u messages from group %s (#%u), muting it.\n",
    3096                                      cEntries, pLoggerInt->papszGroups[iGroup], iGroup);
    3097             else
    3098                 rtlogLoggerExFLocked(pLoggerInt, fFlags, iGroup, "%u messages from group #%u, muting it.\n", cEntries, iGroup);
    3099         }
    3100     }
    3101     else
    3102         rtlogLoggerExVLocked(pLoggerInt, fFlags, iGroup, pszFormat, args);
    3103 
    3104     /*
    3105      * Release the semaphore.
    3106      */
    3107     rtlogUnlock(pLoggerInt);
    3108 }
    3109 RT_EXPORT_SYMBOL(RTLogLoggerExV);
    3110 
    3111 #ifdef IN_RING0
    3112 
    3113 /**
    3114  * For rtR0LogLoggerExFallbackOutput and rtR0LogLoggerExFallbackFlush.
    3115  */
    3116 typedef struct RTR0LOGLOGGERFALLBACK
    3117 {
    3118     /** The current scratch buffer offset. */
    3119     uint32_t            offScratch;
    3120     /** The destination flags. */
    3121     uint32_t            fDestFlags;
    3122     /** For ring buffer output. */
    3123     PRTLOGGERINTERNAL   pInt;
    3124     /** The scratch buffer. */
    3125     char                achScratch[80];
    3126 } RTR0LOGLOGGERFALLBACK;
    3127 /** Pointer to RTR0LOGLOGGERFALLBACK which is used by
    3128  * rtR0LogLoggerExFallbackOutput. */
    3129 typedef RTR0LOGLOGGERFALLBACK *PRTR0LOGLOGGERFALLBACK;
    3130 
    3131 
    3132 /**
    3133  * Flushes the fallback buffer.
    3134  *
    3135  * @param   pThis       The scratch buffer.
    3136  */
    3137 static void rtR0LogLoggerExFallbackFlush(PRTR0LOGLOGGERFALLBACK pThis)
    3138 {
    3139     if (!pThis->offScratch)
    3140         return;
    3141 
    3142     if (   (pThis->fDestFlags & RTLOGDEST_RINGBUF)
    3143         && pThis->pInt
    3144         && pThis->pInt->pszRingBuf /* paranoia */)
    3145         rtLogRingBufWrite(pThis->pInt, pThis->achScratch, pThis->offScratch);
    3146     else
    3147     {
    3148         if (pThis->fDestFlags & RTLOGDEST_USER)
    3149             RTLogWriteUser(pThis->achScratch, pThis->offScratch);
    3150 
    3151         if (pThis->fDestFlags & RTLOGDEST_DEBUGGER)
    3152             RTLogWriteDebugger(pThis->achScratch, pThis->offScratch);
    3153 
    3154         if (pThis->fDestFlags & RTLOGDEST_STDOUT)
    3155             RTLogWriteStdOut(pThis->achScratch, pThis->offScratch);
    3156 
    3157         if (pThis->fDestFlags & RTLOGDEST_STDERR)
    3158             RTLogWriteStdErr(pThis->achScratch, pThis->offScratch);
    3159 
    3160 # ifndef LOG_NO_COM
    3161         if (pThis->fDestFlags & RTLOGDEST_COM)
    3162             RTLogWriteCom(pThis->achScratch, pThis->offScratch);
    3163 # endif
    3164     }
    3165 
    3166     /* empty the buffer. */
    3167     pThis->offScratch = 0;
    3168 }
    3169 
    3170 
    3171 /**
    3172  * Callback for RTLogFormatV used by rtR0LogLoggerExFallback.
    3173  * See PFNLOGOUTPUT() for details.
    3174  */
    3175 static DECLCALLBACK(size_t) rtR0LogLoggerExFallbackOutput(void *pv, const char *pachChars, size_t cbChars)
    3176 {
    3177     PRTR0LOGLOGGERFALLBACK pThis = (PRTR0LOGLOGGERFALLBACK)pv;
    3178     if (cbChars)
    3179     {
    3180         size_t cbRet = 0;
    3181         for (;;)
    3182         {
    3183             /* how much */
    3184             uint32_t cb = sizeof(pThis->achScratch) - pThis->offScratch - 1; /* minus 1 - for the string terminator. */
    3185             if (cb > cbChars)
    3186                 cb = (uint32_t)cbChars;
    3187 
    3188             /* copy */
    3189             memcpy(&pThis->achScratch[pThis->offScratch], pachChars, cb);
    3190 
    3191             /* advance */
    3192             pThis->offScratch += cb;
    3193             cbRet += cb;
    3194             cbChars -= cb;
    3195 
    3196             /* done? */
    3197             if (cbChars <= 0)
    3198                 return cbRet;
    3199 
    3200             pachChars += cb;
    3201 
    3202             /* flush */
    3203             pThis->achScratch[pThis->offScratch] = '\0';
    3204             rtR0LogLoggerExFallbackFlush(pThis);
    3205         }
    3206 
    3207         /* won't ever get here! */
    3208     }
    3209     else
    3210     {
    3211         /*
    3212          * Termination call, flush the log.
    3213          */
    3214         pThis->achScratch[pThis->offScratch] = '\0';
    3215         rtR0LogLoggerExFallbackFlush(pThis);
    3216         return 0;
    3217     }
    3218 }
    3219 
    3220 
    3221 /**
    3222  * Ring-0 fallback for cases where we're unable to grab the lock.
    3223  *
    3224  * This will happen when we're at a too high IRQL on Windows for instance and
    3225  * needs to be dealt with or we'll drop a lot of log output. This fallback will
    3226  * only output to some of the log destinations as a few of them may be doing
    3227  * dangerous things. We won't be doing any prefixing here either, at least not
    3228  * for the present, because it's too much hassle.
    3229  *
    3230  * @param   fDestFlags  The destination flags.
    3231  * @param   fFlags      The logger flags.
    3232  * @param   pInt        The internal logger data, for ring buffer output.
    3233  * @param   pszFormat   The format string.
    3234  * @param   va          The format arguments.
    3235  */
    3236 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt,
    3237                                     const char *pszFormat, va_list va)
    3238 {
    3239     RTR0LOGLOGGERFALLBACK This;
    3240     This.fDestFlags = fDestFlags;
    3241     This.pInt = pInt;
    3242 
    3243     /* fallback indicator. */
    3244     This.offScratch = 2;
    3245     This.achScratch[0] = '[';
    3246     This.achScratch[1] = 'F';
    3247 
    3248     /* selected prefixes */
    3249     if (fFlags & RTLOGFLAGS_PREFIX_PID)
    3250     {
    3251         RTPROCESS Process = RTProcSelf();
    3252         This.achScratch[This.offScratch++] = ' ';
    3253         This.offScratch += RTStrFormatNumber(&This.achScratch[This.offScratch], Process, 16, sizeof(RTPROCESS) * 2, 0, RTSTR_F_ZEROPAD);
    3254     }
    3255     if (fFlags & RTLOGFLAGS_PREFIX_TID)
    3256     {
    3257         RTNATIVETHREAD Thread = RTThreadNativeSelf();
    3258         This.achScratch[This.offScratch++] = ' ';
    3259         This.offScratch += RTStrFormatNumber(&This.achScratch[This.offScratch], Thread, 16, sizeof(RTNATIVETHREAD) * 2, 0, RTSTR_F_ZEROPAD);
    3260     }
    3261 
    3262     This.achScratch[This.offScratch++] = ']';
    3263     This.achScratch[This.offScratch++] = ' ';
    3264 
    3265     RTLogFormatV(rtR0LogLoggerExFallbackOutput, &This, pszFormat, va);
    3266 }
    3267 
    3268 #endif /* IN_RING0 */
    3269 
    3270 /**
    3271  * vprintf like function for writing to the default log.
    3272  *
    3273  * @param   pszFormat   Printf like format string.
    3274  * @param   va          Optional arguments as specified in pszFormat.
    3275  *
    3276  * @remark The API doesn't support formatting of floating point numbers at the moment.
    3277  */
    3278 RTDECL(void) RTLogPrintfV(const char *pszFormat, va_list va)
    3279 {
    3280     RTLogLoggerV(NULL, pszFormat, va);
    3281 }
    3282 RT_EXPORT_SYMBOL(RTLogPrintfV);
    3283 
    3284 
    3285 /**
    3286  * Dumper vprintf-like function outputting to a logger.
    3287  *
    3288  * @param   pvUser          Pointer to the logger instance to use, NULL for
    3289  *                          default instance.
    3290  * @param   pszFormat       Format string.
    3291  * @param   va              Format arguments.
    3292  */
    3293 RTDECL(void) RTLogDumpPrintfV(void *pvUser, const char *pszFormat, va_list va)
    3294 {
    3295     RTLogLoggerV((PRTLOGGER)pvUser, pszFormat, va);
    3296 }
    3297 RT_EXPORT_SYMBOL(RTLogDumpPrintfV);
    3298 
    3299 #ifdef IN_RING3
    3300 
    3301 /**
    3302  * Opens/creates the log file.
    3303  *
    3304  * @param   pLoggerInt      The logger instance to update. NULL is not allowed!
    3305  * @param   pErrInfo        Where to return extended error information.
    3306  *                          Optional.
    3307  */
    3308 static int rtlogFileOpen(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo)
    3309 {
    3310     uint32_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_NONE;
    3311     if (pLoggerInt->fFlags & RTLOGFLAGS_APPEND)
    3312         fOpen |= RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND;
    3313     else
    3314     {
    3315         RTFileDelete(pLoggerInt->szFilename);
    3316         fOpen |= RTFILE_O_CREATE;
    3317     }
    3318     if (pLoggerInt->fFlags & RTLOGFLAGS_WRITE_THROUGH)
    3319         fOpen |= RTFILE_O_WRITE_THROUGH;
    3320     if (pLoggerInt->fDestFlags & RTLOGDEST_F_NO_DENY)
    3321         fOpen = (fOpen & ~RTFILE_O_DENY_NONE) | RTFILE_O_DENY_NOT_DELETE;
    3322 
    3323     unsigned cBackoff = 0;
    3324     int rc = RTFileOpen(&pLoggerInt->hFile, pLoggerInt->szFilename, fOpen);
    3325     while (   (   rc == VERR_SHARING_VIOLATION
    3326                || (rc == VERR_ALREADY_EXISTS && !(pLoggerInt->fFlags & RTLOGFLAGS_APPEND)))
    3327            && cBackoff < RT_ELEMENTS(g_acMsLogBackoff))
    3328     {
    3329         RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
    3330         if (!(pLoggerInt->fFlags & RTLOGFLAGS_APPEND))
    3331             RTFileDelete(pLoggerInt->szFilename);
    3332         rc = RTFileOpen(&pLoggerInt->hFile, pLoggerInt->szFilename, fOpen);
    3333     }
    3334     if (RT_SUCCESS(rc))
    3335     {
    3336         rc = RTFileQuerySize(pLoggerInt->hFile, &pLoggerInt->cbHistoryFileWritten);
    3337         if (RT_FAILURE(rc))
    3338         {
    3339             /* Don't complain if this fails, assume the file is empty. */
    3340             pLoggerInt->cbHistoryFileWritten = 0;
    3341             rc = VINF_SUCCESS;
    3342         }
    3343     }
    3344     else
    3345     {
    3346         pLoggerInt->hFile = NIL_RTFILE;
    3347         RTErrInfoSetF(pErrInfo, rc, N_("could not open file '%s' (fOpen=%#x)"), pLoggerInt->szFilename, fOpen);
    3348     }
    3349     return rc;
    3350 }
    3351 
    3352 
    3353 /**
    3354  * Closes, rotates and opens the log files if necessary.
    3355  *
    3356  * Used by the rtlogFlush() function as well as RTLogCreateExV.
    3357  *
    3358  * @param   pLoggerInt  The logger instance to update. NULL is not allowed!
    3359  * @param   uTimeSlot   Current time slot (for tikme based rotation).
    3360  * @param   fFirst      Flag whether this is the beginning of logging, i.e.
    3361  *                      called from RTLogCreateExV.  Prevents pfnPhase from
    3362  *                      being called.
    3363  * @param   pErrInfo    Where to return extended error information. Optional.
    3364  */
    3365 static void rtlogRotate(PRTLOGGERINTERNAL pLoggerInt, uint32_t uTimeSlot, bool fFirst, PRTERRINFO pErrInfo)
    3366 {
    3367     /* Suppress rotating empty log files simply because the time elapsed. */
    3368     if (RT_UNLIKELY(!pLoggerInt->cbHistoryFileWritten))
    3369         pLoggerInt->uHistoryTimeSlotStart = uTimeSlot;
    3370 
    3371     /* Check rotation condition: file still small enough and not too old? */
    3372     if (RT_LIKELY(   pLoggerInt->cbHistoryFileWritten < pLoggerInt->cbHistoryFileMax
    3373                   && uTimeSlot == pLoggerInt->uHistoryTimeSlotStart))
    3374         return;
    3375 
    3376     /*
    3377      * Save "disabled" log flag and make sure logging is disabled.
    3378      * The logging in the functions called during log file history
    3379      * rotation would cause severe trouble otherwise.
    3380      */
    3381     uint32_t const fSavedFlags = pLoggerInt->fFlags;
    3382     pLoggerInt->fFlags |= RTLOGFLAGS_DISABLED;
    3383 
    3384     /*
    3385      * Disable log rotation temporarily, otherwise with extreme settings and
    3386      * chatty phase logging we could run into endless rotation.
    3387      */
    3388     uint32_t const cSavedHistory = pLoggerInt->cHistory;
    3389     pLoggerInt->cHistory = 0;
    3390 
    3391     /*
    3392      * Close the old log file.
    3393      */
    3394     if (pLoggerInt->hFile != NIL_RTFILE)
    3395     {
    3396         /* Use the callback to generate some final log contents, but only if
    3397          * this is a rotation with a fully set up logger. Leave the other case
    3398          * to the RTLogCreateExV function. */
    3399         if (pLoggerInt->pfnPhase && !fFirst)
    3400         {
    3401             uint32_t fODestFlags = pLoggerInt->fDestFlags;
    3402             pLoggerInt->fDestFlags &= RTLOGDEST_FILE;
    3403             pLoggerInt->pfnPhase(&pLoggerInt->Core, RTLOGPHASE_PREROTATE, rtlogPhaseMsgLocked);
    3404             pLoggerInt->fDestFlags = fODestFlags;
    3405         }
    3406         RTFileClose(pLoggerInt->hFile);
    3407         pLoggerInt->hFile = NIL_RTFILE;
    3408     }
    3409 
    3410     if (cSavedHistory)
    3411     {
    3412         /*
    3413          * Rotate the log files.
    3414          */
    3415         for (uint32_t i = cSavedHistory - 1; i + 1 > 0; i--)
    3416         {
    3417             char szOldName[sizeof(pLoggerInt->szFilename) + 32];
    3418             if (i > 0)
    3419                 RTStrPrintf(szOldName, sizeof(szOldName), "%s.%u", pLoggerInt->szFilename, i);
    3420             else
    3421                 RTStrCopy(szOldName, sizeof(szOldName), pLoggerInt->szFilename);
    3422 
    3423             char szNewName[sizeof(pLoggerInt->szFilename) + 32];
    3424             RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLoggerInt->szFilename, i + 1);
    3425 
    3426             unsigned cBackoff = 0;
    3427             int rc = RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE);
    3428             while (   rc == VERR_SHARING_VIOLATION
    3429                    && cBackoff < RT_ELEMENTS(g_acMsLogBackoff))
    3430             {
    3431                 RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
    3432                 rc = RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE);
    3433             }
    3434 
    3435             if (rc == VERR_FILE_NOT_FOUND)
    3436                 RTFileDelete(szNewName);
    3437         }
    3438 
    3439         /*
    3440          * Delete excess log files.
    3441          */
    3442         for (uint32_t i = cSavedHistory + 1; ; i++)
    3443         {
    3444             char szExcessName[sizeof(pLoggerInt->szFilename) + 32];
    3445             RTStrPrintf(szExcessName, sizeof(szExcessName), "%s.%u", pLoggerInt->szFilename, i);
    3446             int rc = RTFileDelete(szExcessName);
    3447             if (RT_FAILURE(rc))
    3448                 break;
    3449         }
    3450     }
    3451 
    3452     /*
    3453      * Update logger state and create new log file.
    3454      */
    3455     pLoggerInt->cbHistoryFileWritten = 0;
    3456     pLoggerInt->uHistoryTimeSlotStart = uTimeSlot;
    3457     rtlogFileOpen(pLoggerInt, pErrInfo);
    3458 
    3459     /*
    3460      * Use the callback to generate some initial log contents, but only if this
    3461      * is a rotation with a fully set up logger.  Leave the other case to the
    3462      * RTLogCreateExV function.
    3463      */
    3464     if (pLoggerInt->pfnPhase && !fFirst)
    3465     {
    3466         uint32_t const fSavedDestFlags = pLoggerInt->fDestFlags;
    3467         pLoggerInt->fDestFlags &= RTLOGDEST_FILE;
    3468         pLoggerInt->pfnPhase(&pLoggerInt->Core, RTLOGPHASE_POSTROTATE, rtlogPhaseMsgLocked);
    3469         pLoggerInt->fDestFlags = fSavedDestFlags;
    3470     }
    3471 
    3472     /* Restore saved values. */
    3473     pLoggerInt->cHistory = cSavedHistory;
    3474     pLoggerInt->fFlags   = fSavedFlags;
    3475 }
    3476 
    3477 
    3478 /**
    3479  * Worker for RTLogCreateExV and RTLogClearFileDelayFlag.
    3480  *
    3481  * This will later be used to reopen the file by RTLogDestinations.
    3482  *
    3483  * @returns IPRT status code.
    3484  * @param   pLoggerInt          The logger.
    3485  * @param   pErrInfo            Where to return extended error information.
    3486  *                              Optional.
    3487  */
    3488 static int rtR3LogOpenFileDestination(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo)
    3489 {
    3490     int rc;
    3491     if (pLoggerInt->fFlags & RTLOGFLAGS_APPEND)
    3492     {
    3493         rc = rtlogFileOpen(pLoggerInt, pErrInfo);
    3494 
    3495         /* Rotate in case of appending to a too big log file,
    3496            otherwise this simply doesn't do anything. */
    3497         rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
    3498     }
    3499     else
    3500     {
    3501         /* Force rotation if it is configured. */
    3502         pLoggerInt->cbHistoryFileWritten = UINT64_MAX;
    3503         rtlogRotate(pLoggerInt, 0, true /* fFirst */, pErrInfo);
    3504 
    3505         /* If the file is not open then rotation is not set up. */
    3506         if (pLoggerInt->hFile == NIL_RTFILE)
    3507         {
    3508             pLoggerInt->cbHistoryFileWritten = 0;
    3509             rc = rtlogFileOpen(pLoggerInt, pErrInfo);
    3510         }
    3511         else
    3512             rc = VINF_SUCCESS;
    3513     }
    3514     return rc;
    3515 }
    3516 
    3517 #endif /* IN_RING3 */
    35183077
    35193078/**
     
    36533212#endif
    36543213}
     3214
     3215
     3216/*********************************************************************************************************************************
     3217*   Logger Core                                                                                                                  *
     3218*********************************************************************************************************************************/
     3219
     3220#ifdef IN_RING0
     3221
     3222/**
     3223 * For rtR0LogLoggerExFallbackOutput and rtR0LogLoggerExFallbackFlush.
     3224 */
     3225typedef struct RTR0LOGLOGGERFALLBACK
     3226{
     3227    /** The current scratch buffer offset. */
     3228    uint32_t            offScratch;
     3229    /** The destination flags. */
     3230    uint32_t            fDestFlags;
     3231    /** For ring buffer output. */
     3232    PRTLOGGERINTERNAL   pInt;
     3233    /** The scratch buffer. */
     3234    char                achScratch[80];
     3235} RTR0LOGLOGGERFALLBACK;
     3236/** Pointer to RTR0LOGLOGGERFALLBACK which is used by
     3237 * rtR0LogLoggerExFallbackOutput. */
     3238typedef RTR0LOGLOGGERFALLBACK *PRTR0LOGLOGGERFALLBACK;
     3239
     3240
     3241/**
     3242 * Flushes the fallback buffer.
     3243 *
     3244 * @param   pThis       The scratch buffer.
     3245 */
     3246static void rtR0LogLoggerExFallbackFlush(PRTR0LOGLOGGERFALLBACK pThis)
     3247{
     3248    if (!pThis->offScratch)
     3249        return;
     3250
     3251    if (   (pThis->fDestFlags & RTLOGDEST_RINGBUF)
     3252        && pThis->pInt
     3253        && pThis->pInt->pszRingBuf /* paranoia */)
     3254        rtLogRingBufWrite(pThis->pInt, pThis->achScratch, pThis->offScratch);
     3255    else
     3256    {
     3257        if (pThis->fDestFlags & RTLOGDEST_USER)
     3258            RTLogWriteUser(pThis->achScratch, pThis->offScratch);
     3259
     3260        if (pThis->fDestFlags & RTLOGDEST_DEBUGGER)
     3261            RTLogWriteDebugger(pThis->achScratch, pThis->offScratch);
     3262
     3263        if (pThis->fDestFlags & RTLOGDEST_STDOUT)
     3264            RTLogWriteStdOut(pThis->achScratch, pThis->offScratch);
     3265
     3266        if (pThis->fDestFlags & RTLOGDEST_STDERR)
     3267            RTLogWriteStdErr(pThis->achScratch, pThis->offScratch);
     3268
     3269# ifndef LOG_NO_COM
     3270        if (pThis->fDestFlags & RTLOGDEST_COM)
     3271            RTLogWriteCom(pThis->achScratch, pThis->offScratch);
     3272# endif
     3273    }
     3274
     3275    /* empty the buffer. */
     3276    pThis->offScratch = 0;
     3277}
     3278
     3279
     3280/**
     3281 * Callback for RTLogFormatV used by rtR0LogLoggerExFallback.
     3282 * See PFNLOGOUTPUT() for details.
     3283 */
     3284static DECLCALLBACK(size_t) rtR0LogLoggerExFallbackOutput(void *pv, const char *pachChars, size_t cbChars)
     3285{
     3286    PRTR0LOGLOGGERFALLBACK pThis = (PRTR0LOGLOGGERFALLBACK)pv;
     3287    if (cbChars)
     3288    {
     3289        size_t cbRet = 0;
     3290        for (;;)
     3291        {
     3292            /* how much */
     3293            uint32_t cb = sizeof(pThis->achScratch) - pThis->offScratch - 1; /* minus 1 - for the string terminator. */
     3294            if (cb > cbChars)
     3295                cb = (uint32_t)cbChars;
     3296
     3297            /* copy */
     3298            memcpy(&pThis->achScratch[pThis->offScratch], pachChars, cb);
     3299
     3300            /* advance */
     3301            pThis->offScratch += cb;
     3302            cbRet += cb;
     3303            cbChars -= cb;
     3304
     3305            /* done? */
     3306            if (cbChars <= 0)
     3307                return cbRet;
     3308
     3309            pachChars += cb;
     3310
     3311            /* flush */
     3312            pThis->achScratch[pThis->offScratch] = '\0';
     3313            rtR0LogLoggerExFallbackFlush(pThis);
     3314        }
     3315
     3316        /* won't ever get here! */
     3317    }
     3318    else
     3319    {
     3320        /*
     3321         * Termination call, flush the log.
     3322         */
     3323        pThis->achScratch[pThis->offScratch] = '\0';
     3324        rtR0LogLoggerExFallbackFlush(pThis);
     3325        return 0;
     3326    }
     3327}
     3328
     3329
     3330/**
     3331 * Ring-0 fallback for cases where we're unable to grab the lock.
     3332 *
     3333 * This will happen when we're at a too high IRQL on Windows for instance and
     3334 * needs to be dealt with or we'll drop a lot of log output. This fallback will
     3335 * only output to some of the log destinations as a few of them may be doing
     3336 * dangerous things. We won't be doing any prefixing here either, at least not
     3337 * for the present, because it's too much hassle.
     3338 *
     3339 * @param   fDestFlags  The destination flags.
     3340 * @param   fFlags      The logger flags.
     3341 * @param   pInt        The internal logger data, for ring buffer output.
     3342 * @param   pszFormat   The format string.
     3343 * @param   va          The format arguments.
     3344 */
     3345static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt,
     3346                                    const char *pszFormat, va_list va)
     3347{
     3348    RTR0LOGLOGGERFALLBACK This;
     3349    This.fDestFlags = fDestFlags;
     3350    This.pInt = pInt;
     3351
     3352    /* fallback indicator. */
     3353    This.offScratch = 2;
     3354    This.achScratch[0] = '[';
     3355    This.achScratch[1] = 'F';
     3356
     3357    /* selected prefixes */
     3358    if (fFlags & RTLOGFLAGS_PREFIX_PID)
     3359    {
     3360        RTPROCESS Process = RTProcSelf();
     3361        This.achScratch[This.offScratch++] = ' ';
     3362        This.offScratch += RTStrFormatNumber(&This.achScratch[This.offScratch], Process, 16, sizeof(RTPROCESS) * 2, 0, RTSTR_F_ZEROPAD);
     3363    }
     3364    if (fFlags & RTLOGFLAGS_PREFIX_TID)
     3365    {
     3366        RTNATIVETHREAD Thread = RTThreadNativeSelf();
     3367        This.achScratch[This.offScratch++] = ' ';
     3368        This.offScratch += RTStrFormatNumber(&This.achScratch[This.offScratch], Thread, 16, sizeof(RTNATIVETHREAD) * 2, 0, RTSTR_F_ZEROPAD);
     3369    }
     3370
     3371    This.achScratch[This.offScratch++] = ']';
     3372    This.achScratch[This.offScratch++] = ' ';
     3373
     3374    RTLogFormatV(rtR0LogLoggerExFallbackOutput, &This, pszFormat, va);
     3375}
     3376
     3377#endif /* IN_RING0 */
    36553378
    36563379
     
    42353958    {
    42363959        pAuxDesc->fFlushedIndicator = false;
    4237         pBufDesc->offBuf        = 0;
     3960        pBufDesc->offBuf            = 0;
    42383961    }
    42393962
     
    42874010}
    42884011
     4012
     4013/**
     4014 * Write to a logger instance.
     4015 *
     4016 * This function will check whether the instance, group and flags makes up a
     4017 * logging kind which is currently enabled before writing anything to the log.
     4018 *
     4019 * @returns VINF_SUCCESS, VINF_LOG_NO_LOGGER, VINF_LOG_DISABLED, or IPRT error
     4020 *          status.
     4021 * @param   pLogger     Pointer to logger instance. If NULL the default logger instance will be attempted.
     4022 * @param   fFlags      The logging flags.
     4023 * @param   iGroup      The group.
     4024 *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
     4025 *                      only for internal usage!
     4026 * @param   pszFormat   Format string.
     4027 * @param   args        Format arguments.
     4028 */
     4029RTDECL(int) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args)
     4030{
     4031    int               rc;
     4032    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
     4033    RTLOG_RESOLVE_DEFAULT_RET(pLoggerInt, VINF_LOG_NO_LOGGER);
     4034
     4035    /*
     4036     * Validate and correct iGroup.
     4037     */
     4038    if (iGroup != ~0U && iGroup >= pLoggerInt->cGroups)
     4039        iGroup = 0;
     4040
     4041    /*
     4042     * If no output, then just skip it.
     4043     */
     4044    if (    (pLoggerInt->fFlags & RTLOGFLAGS_DISABLED)
     4045        || !pLoggerInt->fDestFlags
     4046        || !pszFormat || !*pszFormat)
     4047        return VINF_LOG_DISABLED;
     4048    if (    iGroup != ~0U
     4049        &&  (pLoggerInt->afGroups[iGroup] & (fFlags | RTLOGGRPFLAGS_ENABLED)) != (fFlags | RTLOGGRPFLAGS_ENABLED))
     4050        return VINF_LOG_DISABLED;
     4051
     4052    /*
     4053     * Acquire logger instance sem.
     4054     */
     4055    rc = rtlogLock(pLoggerInt);
     4056    if (RT_SUCCESS(rc))
     4057    {
     4058        /*
     4059         * Check group restrictions and call worker.
     4060         */
     4061        if (RT_LIKELY(   !(pLoggerInt->fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
     4062                      || iGroup >= pLoggerInt->cGroups
     4063                      || !(pLoggerInt->afGroups[iGroup] & RTLOGGRPFLAGS_RESTRICT)
     4064                      || ++pLoggerInt->pacEntriesPerGroup[iGroup] < pLoggerInt->cMaxEntriesPerGroup ))
     4065            rtlogLoggerExVLocked(pLoggerInt, fFlags, iGroup, pszFormat, args);
     4066        else
     4067        {
     4068            uint32_t cEntries = pLoggerInt->pacEntriesPerGroup[iGroup];
     4069            if (cEntries > pLoggerInt->cMaxEntriesPerGroup)
     4070                pLoggerInt->pacEntriesPerGroup[iGroup] = cEntries - 1;
     4071            else
     4072            {
     4073                rtlogLoggerExVLocked(pLoggerInt, fFlags, iGroup, pszFormat, args);
     4074                if (   pLoggerInt->papszGroups
     4075                    && pLoggerInt->papszGroups[iGroup])
     4076                    rtlogLoggerExFLocked(pLoggerInt, fFlags, iGroup, "%u messages from group %s (#%u), muting it.\n",
     4077                                         cEntries, pLoggerInt->papszGroups[iGroup], iGroup);
     4078                else
     4079                    rtlogLoggerExFLocked(pLoggerInt, fFlags, iGroup, "%u messages from group #%u, muting it.\n", cEntries, iGroup);
     4080            }
     4081        }
     4082
     4083        /*
     4084         * Release the semaphore.
     4085         */
     4086        rtlogUnlock(pLoggerInt);
     4087        return VINF_SUCCESS;
     4088    }
     4089
     4090#ifdef IN_RING0
     4091    if (pLoggerInt->fDestFlags & ~RTLOGDEST_FILE)
     4092    {
     4093        rtR0LogLoggerExFallback(pLoggerInt->fDestFlags, pLoggerInt->fFlags, pLoggerInt, pszFormat, args);
     4094        return VINF_SUCCESS;
     4095    }
     4096#endif
     4097    return rc;
     4098}
     4099RT_EXPORT_SYMBOL(RTLogLoggerExV);
     4100
     4101
     4102/**
     4103 * Write to a logger instance.
     4104 *
     4105 * @param   pLogger     Pointer to logger instance.
     4106 * @param   pszFormat   Format string.
     4107 * @param   args        Format arguments.
     4108 */
     4109RTDECL(void) RTLogLoggerV(PRTLOGGER pLogger, const char *pszFormat, va_list args)
     4110{
     4111    RTLogLoggerExV(pLogger, 0, ~0U, pszFormat, args);
     4112}
     4113RT_EXPORT_SYMBOL(RTLogLoggerV);
     4114
     4115
     4116/**
     4117 * vprintf like function for writing to the default log.
     4118 *
     4119 * @param   pszFormat   Printf like format string.
     4120 * @param   va          Optional arguments as specified in pszFormat.
     4121 *
     4122 * @remark The API doesn't support formatting of floating point numbers at the moment.
     4123 */
     4124RTDECL(void) RTLogPrintfV(const char *pszFormat, va_list va)
     4125{
     4126    RTLogLoggerV(NULL, pszFormat, va);
     4127}
     4128RT_EXPORT_SYMBOL(RTLogPrintfV);
     4129
     4130
     4131/**
     4132 * Dumper vprintf-like function outputting to a logger.
     4133 *
     4134 * @param   pvUser          Pointer to the logger instance to use, NULL for
     4135 *                          default instance.
     4136 * @param   pszFormat       Format string.
     4137 * @param   va              Format arguments.
     4138 */
     4139RTDECL(void) RTLogDumpPrintfV(void *pvUser, const char *pszFormat, va_list va)
     4140{
     4141    RTLogLoggerV((PRTLOGGER)pvUser, pszFormat, va);
     4142}
     4143RT_EXPORT_SYMBOL(RTLogDumpPrintfV);
     4144
     4145#ifdef IN_RING3
     4146
     4147/**
     4148 * @callback_method_impl{FNRTLOGPHASEMSG,
     4149 * Log phase callback function - assumes the lock is already held.}
     4150 */
     4151static DECLCALLBACK(void) rtlogPhaseMsgLocked(PRTLOGGER pLogger, const char *pszFormat, ...)
     4152{
     4153    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
     4154    AssertPtrReturnVoid(pLoggerInt);
     4155    Assert(pLoggerInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
     4156
     4157    va_list args;
     4158    va_start(args, pszFormat);
     4159    rtlogLoggerExVLocked(pLoggerInt, 0, ~0U, pszFormat, args);
     4160    va_end(args);
     4161}
     4162
     4163
     4164/**
     4165 * @callback_method_impl{FNRTLOGPHASEMSG,
     4166 * Log phase callback function - assumes the lock is not held.}
     4167 */
     4168static DECLCALLBACK(void) rtlogPhaseMsgNormal(PRTLOGGER pLogger, const char *pszFormat, ...)
     4169{
     4170    PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;
     4171    AssertPtrReturnVoid(pLoggerInt);
     4172    Assert(pLoggerInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
     4173
     4174    va_list args;
     4175    va_start(args, pszFormat);
     4176    RTLogLoggerExV(&pLoggerInt->Core, 0, ~0U, pszFormat, args);
     4177    va_end(args);
     4178}
     4179
     4180#endif /* IN_RING3 */
     4181
Note: See TracChangeset for help on using the changeset viewer.

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