Changeset 90861 in vbox
- Timestamp:
- Aug 25, 2021 12:10:47 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/err.h
r90829 r90861 1446 1446 /** The internal logger revision did not match. */ 1447 1447 #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) 1448 1452 /** @} */ 1449 1453 -
trunk/include/iprt/log.h
r90860 r90861 2173 2173 * Modifies the flag settings for the given logger. 2174 2174 * 2175 * @returns IPRT status code. Returns VINF_ SUCCESS if no default logger and @a2176 * pLogger is NULL.2175 * @returns IPRT status code. Returns VINF_LOG_NO_LOGGER if no default logger 2176 * and @a pLogger is NULL. 2177 2177 * @param pLogger Logger instance (NULL for default logger). 2178 2178 * @param fSet Mask of flags to set (OR). … … 2230 2230 * additional arguments, like RTLOGDEST_FILE. 2231 2231 * 2232 * @returns IPRT status code. Returns VINF_ SUCCESS if no default logger and @a2233 * pLogger is NULL.2232 * @returns IPRT status code. Returns VINF_LOG_NO_LOGGER if no default logger 2233 * and @a pLogger is NULL. 2234 2234 * @param pLogger Logger instance (NULL for default logger). 2235 2235 * @param fSet Mask of destinations to set (OR). … … 2318 2318 * Flushes the specified logger. 2319 2319 * 2320 * @returns IRPT status code. 2320 2321 * @param pLogger The logger instance to flush. 2321 2322 * If NULL the default instance is used. The default instance 2322 2323 * will not be initialized by this call. 2323 2324 */ 2324 RTDECL( void) RTLogFlush(PRTLOGGER pLogger);2325 RTDECL(int) RTLogFlush(PRTLOGGER pLogger); 2325 2326 2326 2327 /** … … 2367 2368 * logging kind which is currently enabled before writing anything to the log. 2368 2369 * 2370 * @returns VINF_SUCCESS, VINF_LOG_NO_LOGGER, VINF_LOG_DISABLED, or IPRT error 2371 * status. 2369 2372 * @param pLogger Pointer to logger instance. If NULL the default logger instance will be attempted. 2370 2373 * @param fFlags The logging flags. … … 2375 2378 * @param args Format arguments. 2376 2379 */ 2377 RTDECL( void) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,2378 2380 RTDECL(int) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, 2381 const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(4, 0); 2379 2382 2380 2383 /** -
trunk/src/VBox/Runtime/common/log/log.cpp
r90860 r90861 98 98 99 99 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 100 114 /********************************************************************************************************************************* 101 115 * Structures and Typedefs * … … 256 270 *********************************************************************************************************************************/ 257 271 static unsigned rtlogGroupFlags(const char *psz); 258 #ifdef IN_RING0259 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt,260 const char *pszFormat, va_list va);261 #endif262 272 #ifdef IN_RING3 263 273 static int rtR3LogOpenFileDestination(PRTLOGGERINTERNAL pLoggerInt, PRTERRINFO pErrInfo); … … 265 275 static void rtLogRingBufFlush(PRTLOGGERINTERNAL pLoggerInt); 266 276 static 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 278 static FNRTLOGPHASEMSG rtlogPhaseMsgLocked; 279 static FNRTLOGPHASEMSG rtlogPhaseMsgNormal; 280 #endif 271 281 272 282 … … 426 436 } 427 437 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 */ 446 DECL_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 */ 465 DECL_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 495 RTDECL(PRTLOGGER) RTLogDefaultInstance(void) 496 { 497 return rtLogDefaultInstanceCommon(); 498 } 499 RT_EXPORT_SYMBOL(RTLogDefaultInstance); 500 501 502 /** 503 * Worker for RTLogDefaultInstanceEx, RTLogGetDefaultInstanceEx, 504 * RTLogRelGetDefaultInstanceEx and RTLogCheckGroupFlags. 505 */ 506 DECL_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 523 RTDECL(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 } 531 RT_EXPORT_SYMBOL(RTLogDefaultInstanceEx); 532 533 534 /** 535 * Common worker for RTLogGetDefaultInstance and RTLogGetDefaultInstanceEx. 536 */ 537 DECL_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 557 RTDECL(PRTLOGGER) RTLogGetDefaultInstance(void) 558 { 559 return rtLogGetDefaultInstanceCommon(); 560 } 561 RT_EXPORT_SYMBOL(RTLogGetDefaultInstance); 562 563 564 RTDECL(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 } 572 RT_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 */ 581 RTDECL(PRTLOGGER) RTLogSetDefaultInstance(PRTLOGGER pLogger) 582 { 583 return ASMAtomicXchgPtrT(&g_pLogger, pLogger, PRTLOGGER); 584 } 585 RT_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 */ 599 RTR0DECL(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 } 671 RT_EXPORT_SYMBOL(RTLogSetDefaultInstanceThread); 672 #endif /* IN_RING0 */ 673 674 675 RTDECL(PRTLOGGER) RTLogRelGetDefaultInstance(void) 676 { 677 return g_pRelLogger; 678 } 679 RT_EXPORT_SYMBOL(RTLogRelGetDefaultInstance); 680 681 682 RTDECL(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 } 689 RT_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 */ 698 RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger) 699 { 700 return ASMAtomicXchgPtrT(&g_pRelLogger, pLogger, PRTLOGGER); 701 } 702 RT_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 */ 716 RTDECL(PRTLOGGER) RTLogCheckGroupFlags(PRTLOGGER pLogger, uint32_t fFlagsAndGroup) 438 717 { 439 718 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 } 723 RT_EXPORT_SYMBOL(RTLogCheckGroupFlags); 724 725 726 /********************************************************************************************************************************* 727 * Ring Buffer * 728 *********************************************************************************************************************************/ 470 729 471 730 /** … … 743 1002 } 744 1003 1004 1005 /********************************************************************************************************************************* 1006 * Create, Destroy, Setup * 1007 *********************************************************************************************************************************/ 745 1008 746 1009 RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, const char *pszEnvVarBase, uint64_t fFlags, const char *pszGroupSettings, … … 1212 1475 RTDECL(int) RTLogSetCustomPrefixCallback(PRTLOGGER pLogger, PFNRTLOGPREFIX pfnCallback, void *pvUser) 1213 1476 { 1214 /* 1215 * Resolve defaults. 1216 */ 1477 int rc; 1217 1478 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); 1225 1480 1226 1481 /* 1227 1482 * Do the work. 1228 1483 */ 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; 1235 1493 } 1236 1494 RT_EXPORT_SYMBOL(RTLogSetCustomPrefixCallback); … … 1250 1508 RTDECL(int) RTLogSetFlushCallback(PRTLOGGER pLogger, PFNRTLOGFLUSH pfnFlush) 1251 1509 { 1252 int rc; 1253 1254 /* 1255 * Resolve defaults. 1256 */ 1510 int rc; 1257 1511 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); 1265 1513 1266 1514 /* … … 1368 1616 RTDECL(int) RTLogGroupSettings(PRTLOGGER pLogger, const char *pszValue) 1369 1617 { 1370 1371 /*1372 * Resolve defaults.1373 */1374 1618 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); 1381 1620 Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC); 1382 1621 … … 1626 1865 RTDECL(int) RTLogQueryGroupSettings(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf) 1627 1866 { 1628 PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;1629 1867 bool fNotFirst = false; 1630 1868 int rc = VINF_SUCCESS; … … 1632 1870 uint32_t fGroup; 1633 1871 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); 1635 1875 Assert(cchBuf); 1636 1876 1637 1877 /* 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 */ 1651 1880 cGroups = pLoggerInt->cGroups; 1652 1653 /* 1654 * Check if all are the same. 1655 */ 1656 fGroup = pLoggerInt->afGroups[0]; 1881 fGroup = pLoggerInt->afGroups[0]; 1657 1882 for (i = 1; i < cGroups; i++) 1658 1883 if (pLoggerInt->afGroups[i] != fGroup) … … 1699 1924 RTDECL(int) RTLogFlags(PRTLOGGER pLogger, const char *pszValue) 1700 1925 { 1926 int rc = VINF_SUCCESS; 1701 1927 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); 1713 1930 1714 1931 /* … … 1795 2012 RTDECL(bool) RTLogSetBuffering(PRTLOGGER pLogger, bool fBuffered) 1796 2013 { 2014 int rc; 2015 bool fOld = false; 1797 2016 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 } 1817 2029 1818 2030 return fOld; … … 1823 2035 RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup) 1824 2036 { 2037 int rc; 2038 uint32_t cOld = UINT32_MAX; 1825 2039 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 } 1841 2049 1842 2050 return cOld; … … 1882 2090 { 1883 2091 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); 1890 2094 return pLoggerInt->fFlags; 1891 2095 } … … 1896 2100 * Modifies the flag settings for the given logger. 1897 2101 * 1898 * @returns IPRT status code. Returns VINF_SUCCESS if no default loggerand @a2102 * @returns IPRT status code. Returns VINF_SUCCESS if VINF_LOG_NO_LOGGER and @a 1899 2103 * pLogger is NULL. 1900 2104 * @param pLogger Logger instance (NULL for default logger). … … 1905 2109 RTDECL(int) RTLogChangeFlags(PRTLOGGER pLogger, uint64_t fSet, uint64_t fClear) 1906 2110 { 2111 int rc; 2112 PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger; 1907 2113 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); 1918 2115 1919 2116 /* 1920 2117 * Make the changes. 1921 2118 */ 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; 1926 2127 } 1927 2128 RT_EXPORT_SYMBOL(RTLogChangeFlags); … … 1939 2140 RTDECL(int) RTLogQueryFlags(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf) 1940 2141 { 1941 PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger;1942 2142 bool fNotFirst = false; 1943 2143 int rc = VINF_SUCCESS; 1944 2144 uint32_t fFlags; 1945 2145 unsigned i; 2146 PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger; 1946 2147 1947 2148 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); 1961 2152 1962 2153 /* … … 2043 2234 RTDECL(int) RTLogDestinations(PRTLOGGER pLogger, char const *pszValue) 2044 2235 { 2045 /*2046 * Resolve defaults.2047 */2048 2236 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? */ 2055 2240 2056 2241 /* … … 2248 2433 RTDECL(int) RTLogClearFileDelayFlag(PRTLOGGER pLogger, PRTERRINFO pErrInfo) 2249 2434 { 2250 /*2251 * Resolve defaults.2252 */2253 2435 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); 2260 2437 2261 2438 /* … … 2292 2469 * additional arguments, like RTLOGDEST_FILE. 2293 2470 * 2294 * @returns IPRT status code. Returns VINF_ SUCCESS if no default logger and @a2295 * pLogger is NULL.2471 * @returns IPRT status code. Returns VINF_LOG_NO_LOGGER if VINF_LOG_NO_LOGGER 2472 * and @a pLogger is NULL. 2296 2473 * @param pLogger Logger instance (NULL for default logger). 2297 2474 * @param fSet Mask of destinations to set (OR). … … 2300 2477 RTDECL(int) RTLogChangeDestinations(PRTLOGGER pLogger, uint32_t fSet, uint32_t fClear) 2301 2478 { 2479 int rc; 2302 2480 PRTLOGGERINTERNAL pLoggerInt = (PRTLOGGERINTERNAL)pLogger; 2303 2481 AssertCompile((RTLOG_DST_VALID_MASK & RTLOG_DST_CHANGE_MASK) == RTLOG_DST_CHANGE_MASK); 2304 2482 AssertReturn(!(fSet & ~RTLOG_DST_CHANGE_MASK), VERR_INVALID_FLAGS); 2305 2483 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); 2318 2485 2319 2486 /* 2320 2487 * Make the changes. 2321 2488 */ 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 } 2324 2496 2325 2497 return VINF_SUCCESS; … … 2367 2539 AssertReturn(cchBuf, VERR_INVALID_PARAMETER); 2368 2540 *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); 2379 2543 2380 2544 /* … … 2478 2642 } 2479 2643 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 */ 2653 static 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 */ 2711 static 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 */ 2834 static 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 *********************************************************************************************************************************/ 2480 2869 2481 2870 /** … … 2495 2884 RTDECL(int) RTLogBulkUpdate(PRTLOGGER pLogger, uint64_t fFlags, uint32_t uGroupCrc32, uint32_t cGroups, uint32_t const *pafGroups) 2496 2885 { 2886 int rc; 2497 2887 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); 2509 2889 2510 2890 /* … … 2553 2933 uint32_t const cGroupsAlloc = *pcGroups; 2554 2934 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); 2569 2939 AssertReturn(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC); 2570 2940 … … 2580 2950 return VINF_SUCCESS; 2581 2951 } 2582 *puGroupCrc32 = 0;2583 2952 return VERR_BUFFER_OVERFLOW; 2584 2953 } … … 2600 2969 RTDECL(int) RTLogBulkWrite(PRTLOGGER pLogger, const char *pch, size_t cch) 2601 2970 { 2602 /*2603 * Resolve defaults.2604 */2605 2971 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); 2612 2973 2613 2974 /* … … 2663 3024 2664 3025 3026 /********************************************************************************************************************************* 3027 * Flushing * 3028 *********************************************************************************************************************************/ 3029 2665 3030 /** 2666 3031 * Flushes the specified logger. … … 2670 3035 * will not be initialized by this call. 2671 3036 */ 2672 RTDECL(void) RTLogFlush(PRTLOGGER pLogger) 2673 { 2674 /* 2675 * Resolve defaults. 2676 */ 3037 RTDECL(int) RTLogFlush(PRTLOGGER pLogger) 3038 { 2677 3039 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); 2684 3041 Assert(pLoggerInt->Core.u32Magic == RTLOGGER_MAGIC); 2685 3042 AssertPtr(pLoggerInt->pBufDesc); … … 2687 3044 2688 3045 /* 2689 * A ny thing to flush?2690 */ 2691 i f ( pLoggerInt->pBufDesc->offBuf > 02692 || (pLoggerInt->fDestFlags & RTLOGDEST_RINGBUF))3046 * Acquire logger instance sem. 3047 */ 3048 int rc = rtlogLock(pLoggerInt); 3049 if (RT_SUCCESS(rc)) 2693 3050 { 2694 3051 /* 2695 * A cquire logger instance sem.3052 * Any thing to flush? 2696 3053 */ 2697 i nt rc = rtlogLock(pLoggerInt);2698 if (RT_SUCCESS(rc))3054 if ( pLoggerInt->pBufDesc->offBuf > 0 3055 || (pLoggerInt->fDestFlags & RTLOGDEST_RINGBUF)) 2699 3056 { 2700 3057 /* … … 2710 3067 && pLoggerInt->pszRingBuf /* paranoia */) 2711 3068 rtLogRingBufFlush(pLoggerInt); 2712 2713 /* 2714 * Release the semaphore. 2715 */ 2716 rtlogUnlock(pLoggerInt); 2717 } 2718 } 3069 } 3070 3071 rtlogUnlock(pLoggerInt); 3072 } 3073 return rc; 2719 3074 } 2720 3075 RT_EXPORT_SYMBOL(RTLogFlush); 2721 3076 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_RING02750 /*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 else2770 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 else2791 {2792 uint32_t const fFlags = RT_LO_U16(fFlagsAndGroup);2793 uint16_t const iGroup = RT_HI_U16(fFlagsAndGroup);2794 if ( iGroup != UINT16_MAX2795 && ( (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_RING02820 /*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_RING02869 /**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 in2876 * order to only deregister the instance associated with the2877 * 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_RTNATIVETHREAD2919 && 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 else2932 {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 == Self2939 || 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() and2988 * RTLogRelGetDefaultInstanceEx() does.2989 *2990 * @returns If the group has the specified flags enabled @a pLogger will be2991 * 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 in2994 * 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 a3024 * 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 is3030 * 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->fDestFlags3060 || !pszFormat || !*pszFormat)3061 return;3062 if ( iGroup != ~0U3063 && (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_RING03073 if (pLoggerInt->fDestFlags & ~RTLOGDEST_FILE)3074 rtR0LogLoggerExFallback(pLoggerInt->fDestFlags, pLoggerInt->fFlags, pLoggerInt, pszFormat, args);3075 #endif3076 return;3077 }3078 3079 /*3080 * Check restrictions and call worker.3081 */3082 if (RT_UNLIKELY( (pLoggerInt->fFlags & RTLOGFLAGS_RESTRICT_GROUPS)3083 && iGroup < pLoggerInt->cGroups3084 && (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 else3091 {3092 rtlogLoggerExVLocked(pLoggerInt, fFlags, iGroup, pszFormat, args);3093 if ( pLoggerInt->papszGroups3094 && pLoggerInt->papszGroups[iGroup])3095 rtlogLoggerExFLocked(pLoggerInt, fFlags, iGroup, "%u messages from group %s (#%u), muting it.\n",3096 cEntries, pLoggerInt->papszGroups[iGroup], iGroup);3097 else3098 rtlogLoggerExFLocked(pLoggerInt, fFlags, iGroup, "%u messages from group #%u, muting it.\n", cEntries, iGroup);3099 }3100 }3101 else3102 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_RING03112 3113 /**3114 * For rtR0LogLoggerExFallbackOutput and rtR0LogLoggerExFallbackFlush.3115 */3116 typedef struct RTR0LOGLOGGERFALLBACK3117 {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 by3128 * 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->pInt3144 && pThis->pInt->pszRingBuf /* paranoia */)3145 rtLogRingBufWrite(pThis->pInt, pThis->achScratch, pThis->offScratch);3146 else3147 {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_COM3161 if (pThis->fDestFlags & RTLOGDEST_COM)3162 RTLogWriteCom(pThis->achScratch, pThis->offScratch);3163 # endif3164 }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 else3210 {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 and3225 * needs to be dealt with or we'll drop a lot of log output. This fallback will3226 * only output to some of the log destinations as a few of them may be doing3227 * dangerous things. We won't be doing any prefixing here either, at least not3228 * 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 for3289 * 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_RING33300 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 else3314 {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_VIOLATION3326 || (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 else3345 {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 from3362 * 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->cbHistoryFileMax3373 && 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 history3379 * 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 and3386 * 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 if3397 * this is a rotation with a fully set up logger. Leave the other case3398 * 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 else3421 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_VIOLATION3429 && 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 this3461 * is a rotation with a fully set up logger. Leave the other case to the3462 * 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 else3500 {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 else3512 rc = VINF_SUCCESS;3513 }3514 return rc;3515 }3516 3517 #endif /* IN_RING3 */3518 3077 3519 3078 /** … … 3653 3212 #endif 3654 3213 } 3214 3215 3216 /********************************************************************************************************************************* 3217 * Logger Core * 3218 *********************************************************************************************************************************/ 3219 3220 #ifdef IN_RING0 3221 3222 /** 3223 * For rtR0LogLoggerExFallbackOutput and rtR0LogLoggerExFallbackFlush. 3224 */ 3225 typedef 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. */ 3238 typedef RTR0LOGLOGGERFALLBACK *PRTR0LOGLOGGERFALLBACK; 3239 3240 3241 /** 3242 * Flushes the fallback buffer. 3243 * 3244 * @param pThis The scratch buffer. 3245 */ 3246 static 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 */ 3284 static 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 */ 3345 static 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 */ 3655 3378 3656 3379 … … 4235 3958 { 4236 3959 pAuxDesc->fFlushedIndicator = false; 4237 pBufDesc->offBuf = 0;3960 pBufDesc->offBuf = 0; 4238 3961 } 4239 3962 … … 4287 4010 } 4288 4011 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 */ 4029 RTDECL(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 } 4099 RT_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 */ 4109 RTDECL(void) RTLogLoggerV(PRTLOGGER pLogger, const char *pszFormat, va_list args) 4110 { 4111 RTLogLoggerExV(pLogger, 0, ~0U, pszFormat, args); 4112 } 4113 RT_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 */ 4124 RTDECL(void) RTLogPrintfV(const char *pszFormat, va_list va) 4125 { 4126 RTLogLoggerV(NULL, pszFormat, va); 4127 } 4128 RT_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 */ 4139 RTDECL(void) RTLogDumpPrintfV(void *pvUser, const char *pszFormat, va_list va) 4140 { 4141 RTLogLoggerV((PRTLOGGER)pvUser, pszFormat, va); 4142 } 4143 RT_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 */ 4151 static 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 */ 4168 static 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.