log.cpp revision f0dd841cb99154da8ec0a31cae2f89044895a23f
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Runtime VBox - Logger.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * The contents of this file may alternatively be used under the terms
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * of the Common Development and Distribution License Version 1.0
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * CDDL are applicable instead of those of the GPL.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * You may elect to license modified versions of this file under the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * terms and conditions of either the GPL or the CDDL or both.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * additional information or have any questions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync/*******************************************************************************
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync* Structures and Typedefs *
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync*******************************************************************************/
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * Arguments passed to the output function.
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync /** The logger instance. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The flags. (used for prefixing.) */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The group. (used for prefixing.) */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync} RTLOGOUTPUTPREFIXEDARGS, *PRTLOGOUTPUTPREFIXEDARGS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Internal Functions *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, const char *pszFormat, va_list va);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(size_t) rtLogOutputPrefixed(void *pv, const char *pachChars, size_t cbChars);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/*******************************************************************************
22e281e75ed636601178296c6daebda8f1d17c59vboxsync* Global Variables *
22e281e75ed636601178296c6daebda8f1d17c59vboxsync*******************************************************************************/
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/** Default logger instance. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#else /* !IN_RC */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/** Default logger instance. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#endif /* !IN_RC */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/** The RTThreadGetWriteLockCount() change caused by the logger mutex semaphore. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/** Number of per-thread loggers. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/** Per-thread loggers.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * This is just a quick TLS hack suitable for debug logging only.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * If we run out of entries, just unload and reload the driver. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** The thread. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** The (process / session) key. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /** The logger instance.*/
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#endif /* IN_RING0 */
d1cbbd799d8912978f5146960b6780f387bb414bvboxsync * Logger flags instructions.
22e281e75ed636601178296c6daebda8f1d17c59vboxsyncstatic struct
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "disabled", sizeof("disabled" ) - 1, RTLOGFLAGS_DISABLED, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "enabled", sizeof("enabled" ) - 1, RTLOGFLAGS_DISABLED, true },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "buffered", sizeof("buffered" ) - 1, RTLOGFLAGS_BUFFERED, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "unbuffered", sizeof("unbuffered" ) - 1, RTLOGFLAGS_BUFFERED, true },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "usecrlf", sizeof("usecrlf" ) - 1, RTLOGFLAGS_USECRLF, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "uself", sizeof("uself" ) - 1, RTLOGFLAGS_USECRLF, true },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "append", sizeof("append" ) - 1, RTLOGFLAGS_APPEND, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "overwrite", sizeof("overwrite" ) - 1, RTLOGFLAGS_APPEND, true },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "rel", sizeof("rel" ) - 1, RTLOGFLAGS_REL_TS, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "abs", sizeof("abs" ) - 1, RTLOGFLAGS_REL_TS, true },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "dec", sizeof("dec" ) - 1, RTLOGFLAGS_DECIMAL_TS, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "hex", sizeof("hex" ) - 1, RTLOGFLAGS_DECIMAL_TS, true },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "lockcnts", sizeof("lockcnts" ) - 1, RTLOGFLAGS_PREFIX_LOCK_COUNTS, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "cpuid", sizeof("cpuid" ) - 1, RTLOGFLAGS_PREFIX_CPUID, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "pid", sizeof("pid" ) - 1, RTLOGFLAGS_PREFIX_PID, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "flagno", sizeof("flagno" ) - 1, RTLOGFLAGS_PREFIX_FLAG_NO, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "flag", sizeof("flag" ) - 1, RTLOGFLAGS_PREFIX_FLAG, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "groupno", sizeof("groupno" ) - 1, RTLOGFLAGS_PREFIX_GROUP_NO, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "group", sizeof("group" ) - 1, RTLOGFLAGS_PREFIX_GROUP, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "tid", sizeof("tid" ) - 1, RTLOGFLAGS_PREFIX_TID, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "thread", sizeof("thread" ) - 1, RTLOGFLAGS_PREFIX_THREAD, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "custom", sizeof("custom" ) - 1, RTLOGFLAGS_PREFIX_CUSTOM, false },
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync { "timeprog", sizeof("timeprog" ) - 1, RTLOGFLAGS_PREFIX_TIME_PROG, false },
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync { "time", sizeof("time" ) - 1, RTLOGFLAGS_PREFIX_TIME, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "msprog", sizeof("msprog" ) - 1, RTLOGFLAGS_PREFIX_MS_PROG, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "tsc", sizeof("tsc" ) - 1, RTLOGFLAGS_PREFIX_TSC, false }, /* before ts! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "ts", sizeof("ts" ) - 1, RTLOGFLAGS_PREFIX_TS, false },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Logger destination instructions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic struct
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t fFlag; /**< The corresponding destination flag. */
3ecf9412133496b2aeb090cfd33a286404ec59fbvboxsync { "file", sizeof("file" ) - 1, RTLOGDEST_FILE }, /* Must be 1st! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "dir", sizeof("dir" ) - 1, RTLOGDEST_FILE }, /* Must be 2nd! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "stdout", sizeof("stdout" ) - 1, RTLOGDEST_STDOUT },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "stderr", sizeof("stderr" ) - 1, RTLOGDEST_STDERR },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync { "debugger", sizeof("debugger") - 1, RTLOGDEST_DEBUGGER },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Locks the logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns See RTSemSpinMutexRequest().
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pLogger The logger instance.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Unlocks the logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pLogger The logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Create a logger instance, comprehensive version.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * @returns iprt status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ppLogger Where to store the logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlags Logger instance flags, a combination of the RTLOGFLAGS_* values.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszGroupSettings The initial group settings.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszEnvVarBase Base name for the environment variables for this instance.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param cGroups Number of groups in the array.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param papszGroups Pointer to array of groups. This must stick around for the life of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * logger instance.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param fDestFlags The destination flags. RTLOGDEST_FILE is ORed if pszFilenameFmt specified.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszErrorMsg A buffer which is filled with an error message if something fails. May be NULL.
909f4391cc20b4a3a9a2d3f8718084b669663ab2vboxsync * @param cchErrorMsg The size of the error message buffer.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * @param pszFilenameFmt Log filename format string. Standard RTStrFormat().
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param ... Format arguments.
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsyncRTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
3ecd8008b81f02a04220705ae0033142af363280vboxsync const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
3ecd8008b81f02a04220705ae0033142af363280vboxsync uint32_t fDestFlags, char *pszErrorMsg, size_t cchErrorMsg, const char *pszFilenameFmt, va_list args)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTStrPrintf(pszErrorMsg, cchErrorMsg, "unknown error");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate a logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cb = RT_OFFSETOF(RTLOGGER, afGroups[cGroups + 1]) + RTPATH_MAX;
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync pLogger->pszFilename = (char *)&pLogger->afGroups[cGroups + 1];
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * Emit wrapper code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#if defined(RT_ARCH_AMD64) || (defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC))
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync /* this wrapper will not be used on AMD64, we will be requiring C99 compilers there. */
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync pu8Code += sizeof(void *);
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync *(uint32_t *)pu8Code = (uintptr_t)RTLogLogger - ((uintptr_t)pu8Code + sizeof(uint32_t));
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync AssertMsg((uintptr_t)pu8Code - (uintptr_t)pLogger->pfnLogger <= 64,
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync ("Wrapper assembly is too big! %d bytes\n", (uintptr_t)pu8Code - (uintptr_t)pLogger->pfnLogger));
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync#ifdef IN_RING3 /* files and env.vars. are only accessible when in R3 at the present time. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Format the filename.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync RTStrPrintfV(pLogger->pszFilename, RTPATH_MAX, pszFilenameFmt, args);
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Parse the environment variables.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync /* make temp copy of environment variable base. */
1843553dbdf4e46417158b4c6348c503adf10740vboxsync char *pszEnvVar = (char *)alloca(cchEnvVarBase + 16);
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Destination.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * The flags.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * The group settings.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync#endif /* IN_RING3 */
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * Open the destination(s).
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync rc = RTFileOpen(&pLogger->File, pLogger->pszFilename,
1843553dbdf4e46417158b4c6348c503adf10740vboxsync RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE);
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync /** @todo RTFILE_O_APPEND. */
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync rc = RTFileOpen(&pLogger->File, pLogger->pszFilename,
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTFileSeek(pLogger->File, 0, RTFILE_SEEK_END, NULL);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync RTStrPrintf(pszErrorMsg, cchErrorMsg, "could not open file '%s'", pLogger->pszFilename);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#endif /* IN_RING3 */
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Create mutex and check how much it counts when entering the lock
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * so that we can report the values for RTLOGFLAGS_PREFIX_LOCK_COUNTS.
0e77737b0ba913683e614db11463b31ca67aacbevboxsync rc = RTSemSpinMutexCreate(&pLogger->hSpinMtx, RTSEMSPINMUTEX_FLAGS_IRQ_SAFE);
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync#ifdef IN_RING3 /** @todo do counters in ring-0 too? */
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync int32_t c = RTLockValidatorWriteLockGetCount(Thread);
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync RTStrPrintf(pszErrorMsg, cchErrorMsg, "failed to create sempahore");
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync#if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
8e972b677df5ee27b99211fc7e456a5aa50f3e68vboxsync * RTMemAlloc() succeeded but RTMemExecAlloc() failed -- most probably an SELinux problem.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTStrPrintf(pszErrorMsg, cchErrorMsg, "mmap(PROT_WRITE | PROT_EXEC) failed -- SELinux?");
22e281e75ed636601178296c6daebda8f1d17c59vboxsync#endif /* RT_OS_LINUX */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Create a logger instance.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @returns iprt status code.
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * @param ppLogger Where to store the logger instance.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @param fFlags Logger instance flags, a combination of the RTLOGFLAGS_* values.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @param pszGroupSettings The initial group settings.
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync * @param pszEnvVarBase Base name for the environment variables for this instance.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param cGroups Number of groups in the array.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @param papszGroups Pointer to array of groups. This must stick around for the life of the
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fDestFlags The destination flags. RTLOGDEST_FILE is ORed if pszFilenameFmt specified.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * @param pszFilenameFmt Log filename format string. Standard RTStrFormat().
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ... Format arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTLogCreate(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
806d0b554daa555364af5f87bc96eccbe760db7avboxsync uint32_t fDestFlags, const char *pszFilenameFmt, ...)
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync rc = RTLogCreateExV(ppLogger, fFlags, pszGroupSettings, pszEnvVarBase, cGroups, papszGroups, fDestFlags, NULL, 0, pszFilenameFmt, args);
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * Create a logger instance.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @returns iprt status code.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @param ppLogger Where to store the logger instance.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @param fFlags Logger instance flags, a combination of the RTLOGFLAGS_* values.
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * @param pszGroupSettings The initial group settings.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @param pszEnvVarBase Base name for the environment variables for this instance.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @param cGroups Number of groups in the array.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param papszGroups Pointer to array of groups. This must stick around for the life of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fDestFlags The destination flags. RTLOGDEST_FILE is ORed if pszFilenameFmt specified.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszErrorMsg A buffer which is filled with an error message if something fails. May be NULL.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * @param cchErrorMsg The size of the error message buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszFilenameFmt Log filename format string. Standard RTStrFormat().
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ... Format arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
22e281e75ed636601178296c6daebda8f1d17c59vboxsync uint32_t fDestFlags, char *pszErrorMsg, size_t cchErrorMsg, const char *pszFilenameFmt, ...)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTLogCreateExV(ppLogger, fFlags, pszGroupSettings, pszEnvVarBase, cGroups, papszGroups, fDestFlags, pszErrorMsg, cchErrorMsg, pszFilenameFmt, args);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Destroys a logger instance.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * The instance is flushed and all output destinations closed (where applicable).
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @returns iprt status code.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * @param pLogger The logger instance which close destroyed. NULL is fine.
1157941288c9533575a655c660af55d13da31eefvboxsync * Validate input.
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync AssertReturn(VALID_PTR(pLogger), VERR_INVALID_POINTER);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * Acquire logger instance sem and disable all logging. (paranoia)
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync while (iGroup-- > 0)
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * Flush it.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Close output stuffs.
8e8844a522f5d335f177a0313b03067d79cce201vboxsync * Free the mutex, the wrapper and the instance memory.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync#if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * Create a logger instance clone for RC usage.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * @returns iprt status code.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * @param pLogger The logger instance to be cloned.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param pLoggerRC Where to create the RC logger instance.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param cbLoggerRC Amount of memory allocated to for the RC logger
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * instance clone.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @param pfnLoggerRCPtr Pointer to logger wrapper function for this
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * instance (RC Ptr).
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param pfnFlushRCPtr Pointer to flush function (RC Ptr).
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @param fFlags Logger instance flags, a combination of the RTLOGFLAGS_* values.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsyncRTDECL(int) RTLogCloneRC(PRTLOGGER pLogger, PRTLOGGERRC pLoggerRC, size_t cbLoggerRC,
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync RTRCPTR pfnLoggerRCPtr, RTRCPTR pfnFlushRCPtr, uint32_t fFlags)
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Validate input.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync AssertMsgFailed(("%d min=%d\n", cbLoggerRC, sizeof(*pLoggerRC)));
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Initialize GC instance.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Resolve defaults.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Check if there's enough space for the groups.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync if (cbLoggerRC < (size_t)RT_OFFSETOF(RTLOGGERRC, afGroups[pLogger->cGroups]))
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync AssertMsgFailed(("%d req=%d cGroups=%d\n", cbLoggerRC, RT_OFFSETOF(RTLOGGERRC, afGroups[pLogger->cGroups]), pLogger->cGroups));
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync memcpy(&pLoggerRC->afGroups[0], &pLogger->afGroups[0], pLogger->cGroups * sizeof(pLoggerRC->afGroups[0]));
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync * Copy bits from the HC instance.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync pLoggerRC->fPendingPrefix = pLogger->fPendingPrefix;
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * Check if we can remove the disabled flag.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync && !((pLogger->fFlags | fFlags) & RTLOGFLAGS_DISABLED))
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync * Flushes a RC logger instance to a R3 logger.
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync * @returns iprt status code.
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync * @param pLogger The R3 logger instance to flush pLoggerRC to. If NULL
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * the default logger is used.
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * @param pLoggerRC The RC logger instance to flush.
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncRTDECL(void) RTLogFlushRC(PRTLOGGER pLogger, PRTLOGGERRC pLoggerRC)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * Resolve defaults.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * Any thing to flush?
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Acquire logger instance sem.
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync * Write whatever the GC instance contains to the HC one, and then
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync * flush the HC instance.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync rtLogOutput(pLogger, pLoggerRC->achScratch, pLoggerRC->offScratch);
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * Release the semaphore.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * Create a logger instance for singled threaded ring-0 usage.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @returns iprt status code.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param pLogger Where to create the logger instance.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @param cbLogger The amount of memory available for the logger instance.
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync * @param pfnLogger Pointer to logger wrapper function for the clone.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param pfnFlush Pointer to flush function for the clone.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param fFlags Logger instance flags for the clone, a combination of the RTLOGFLAGS_* values.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param fDestFlags The destination flags.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsyncRTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger, PFNRTLOGGER pfnLogger, PFNRTLOGFLUSH pfnFlush,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(cbLogger >= sizeof(*pLogger), VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initialize the ring-0 instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pLogger->hSpinMtx = NIL_RTSEMSPINMUTEX; /* Not serialized. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pLogger->fDestFlags = fDestFlags & ~RTLOGDEST_FILE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pLogger->cMaxGroups = (uint32_t)((cbLogger - RT_OFFSETOF(RTLOGGER, afGroups[0])) / sizeof(pLogger->afGroups[0]));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* IN_RING3 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copies the group settings and flags from logger instance to another.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns IPRT status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pDstLogger The destination logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pSrcLogger The source logger instance. If NULL the default one is used.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlagsOr OR mask for the flags.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlagsAnd AND mask for the flags.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTLogCopyGroupsAndFlags(PRTLOGGER pDstLogger, PCRTLOGGER pSrcLogger, unsigned fFlagsOr, unsigned fFlagsAnd)
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrReturn(pDstLogger, VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrNullReturn(pSrcLogger, VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Resolve defaults.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copy flags and group settings.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync pDstLogger->fFlags = (pSrcLogger->fFlags & fFlagsAnd) | fFlagsOr;
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync AssertMsgFailed(("cMaxGroups=%zd cGroups=%zd (min size %d)\n", pDstLogger->cMaxGroups,
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync pSrcLogger->cGroups, RT_OFFSETOF(RTLOGGER, afGroups[pSrcLogger->cGroups])));
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync memcpy(&pDstLogger->afGroups[0], &pSrcLogger->afGroups[0], cGroups * sizeof(pDstLogger->afGroups[0]));
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync * Flushes the buffer in one logger instance onto another logger.
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync * @returns iprt status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pSrcLogger The logger instance to flush.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pDstLogger The logger instance to flush onto.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * If NULL the default logger will be used.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(void) RTLogFlushToLogger(PRTLOGGER pSrcLogger, PRTLOGGER pDstLogger)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Resolve defaults.
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync /* flushing to "/dev/null". */
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync * Any thing to flush?
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Acquire logger semaphores.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Write whatever the GC instance contains to the HC one, and then
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * flush the HC instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtLogOutput(pDstLogger, pSrcLogger->achScratch, pSrcLogger->offScratch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Release the semaphores.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Sets the custom prefix callback.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns IPRT status code.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param pLogger The logger instance.
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync * @param pfnCallback The callback.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @param pvUser The user argument for the callback.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTLogSetCustomPrefixCallback(PRTLOGGER pLogger, PFNRTLOGPREFIX pfnCallback, void *pvUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Resolve defaults.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Do the work.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Matches a group name with a pattern mask in an case insensitive manner (ASCII).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns true if matching and *ppachMask set to the end of the pattern.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns false if no match.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszGrp The group name.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ppachMask Pointer to the pointer to the mask. Only wildcard supported is '*'.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cchMask The length of the mask, including modifiers. The modifiers is why
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * we update *ppachMask on match.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic bool rtlogIsGroupMatching(const char *pszGrp, const char **ppachMask, size_t cchMask)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const char *pachMask;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync if (RT_C_TO_LOWER(*pszGrp) != RT_C_TO_LOWER(*pachMask))
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync const char *pszTmp;
5ace91141404400247438502a84a418fba00c8cfvboxsync * Check for wildcard and do a minimal match if found.
5ace91141404400247438502a84a418fba00c8cfvboxsync return false;
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync /* eat '*'s. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* is there more to match? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break; /* we're good */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* do extremely minimal matching (fixme) */
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync return false;
3241f1be564f7351b07ce8a807673fa77a7847bcvboxsync /* done? */
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync /* trailing wildcard is ok. */
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync break; /* we're good */
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync return false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
5cf54b3ffeb7ee90685dcaec329ef71a729f5947vboxsync /* match */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Updates the group settings for the logger instance using the specified
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * specification string.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns iprt status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Failures can safely be ignored.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * @param pLogger Logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszVar Value to parse.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsyncRTDECL(int) RTLogGroupSettings(PRTLOGGER pLogger, const char *pszVar)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Resolve defaults.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Iterate the string.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Skip prefixes (blanks, ;, + and -).
3241f1be564f7351b07ce8a807673fa77a7847bcvboxsync bool fEnabled = true;
3241f1be564f7351b07ce8a807673fa77a7847bcvboxsync const char *pszStart;
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync unsigned i;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while ((ch = *pszVar) == '+' || ch == '-' || ch == ' ' || ch == '\t' || ch == '\n' || ch == ';')
3e6d3b0af632bdcd931b5149915c7b8be1a732cdvboxsync * Find end.
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync while ((ch = *pszVar) != '\0' && ch != '+' && ch != '-' && ch != ' ' && ch != '\t')
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Find the group (ascii case insensitive search).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Special group 'all'.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (cch == 3 || pszStart[3] == '.' || pszStart[3] == '='))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Specific group(s).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rtlogIsGroupMatching(pLogger->papszGroups[i], &psz2, cch))
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync unsigned fFlags = RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1;
14dfd448b0f1b9a46c4a4658a77752cb7561cd47vboxsync } /* for each group */
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync } /* parse specification */
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync * Interprets the group flags suffix.
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync * @returns Flags specified. (0 is possible!)
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync * @param psz Start of Suffix. (Either dot or equal sign.)
97b2abd2828499b2f4c2d5721952c9570ced1ebcvboxsync unsigned fFlags = 0;
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync * Litteral flags.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync static struct
5ace91141404400247438502a84a418fba00c8cfvboxsync { "e", RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1 },
5ace91141404400247438502a84a418fba00c8cfvboxsync { "enabled", RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1 },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync unsigned i;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fFound = false;
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync for (i = 0; i < RT_ELEMENTS(aFlags) && !fFound; i++)
5ace91141404400247438502a84a418fba00c8cfvboxsync } /* strincmp */
5ace91141404400247438502a84a418fba00c8cfvboxsync } /* for each flags */
5ace91141404400247438502a84a418fba00c8cfvboxsync * Flag value.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * Helper for RTLogGetGroupSettings.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsyncstatic int rtLogGetGroupSettingsAddOne(const char *pszName, uint32_t fGroup, char **ppszBuf, size_t *pcchBuf, bool *pfNotFirst)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define APPEND_PSZ(psz,cch) do { memcpy(*ppszBuf, (psz), (cch)); *ppszBuf += (cch); *pcchBuf -= (cch); } while (0)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync#define APPEND_SZ(sz) APPEND_PSZ(sz, sizeof(sz) - 1)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync#define APPEND_CH(ch) do { **ppszBuf = (ch); *ppszBuf += 1; *pcchBuf -= 1; } while (0)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * Add the name.
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync * Only generate mnemonics for the simple+common bits.
5ace91141404400247438502a84a418fba00c8cfvboxsync if (fGroup == (RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1))
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync /* nothing */;
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync else if ( fGroup == (RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1 | RTLOGGRPFLAGS_LEVEL_2 | RTLOGGRPFLAGS_FLOW)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync else if ( fGroup == (RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1 | RTLOGGRPFLAGS_FLOW)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync cch = RTStrFormatNumber(*ppszBuf, fGroup, 16, 0, 0, RTSTR_F_SPECIAL | RTSTR_F_32BIT);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Get the current log group settings as a string.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @param pLogger Logger instance (NULL for default logger).
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @param pszBuf The output buffer.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * @param cchBuf The size of the output buffer. Must be greater
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * than zero.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsyncRTDECL(int) RTLogGetGroupSettings(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync bool fNotFirst = false;
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * Resolve defaults.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * Check if all are the same.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync rc = rtLogGetGroupSettingsAddOne("all", fGroup, &pszBuf, &cchBuf, &fNotFirst);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Iterate all the groups and print all that are enabled.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync for (i = 0; i < cGroups; i++)
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync rc = rtLogGetGroupSettingsAddOne(pszName, fGroup, &pszBuf, &cchBuf, &fNotFirst);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !IN_RC */
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync * Updates the flags for the logger instance using the specified
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync * specification string.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * @returns iprt status code.
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync * Failures can safely be ignored.
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync * @param pLogger Logger instance (NULL for default logger).
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync * @param pszVar Value to parse.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTLogFlags(PRTLOGGER pLogger, const char *pszVar)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Resolve defaults.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Iterate the string.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync /* check no prefix. */
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync bool fNo = false;
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync unsigned i;
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync /* skip blanks. */
2460483cb9999f0b06ed7e595ffc8259007350b4vboxsync /* instruction. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync if (!strncmp(pszVar, s_aLogFlags[i].pszInstr, s_aLogFlags[i].cchInstr))
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* unknown instruction? */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync AssertMsgFailed(("Invalid flags! unknown instruction %.20s\n", pszVar));
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* skip blanks and delimiters. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync } /* while more environment variable value left */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Get the current log flags as a string.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @param pLogger Logger instance (NULL for default logger).
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @param pszBuf The output buffer.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @param cchBuf The size of the output buffer. Must be greater
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * than zero.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsyncRTDECL(int) RTLogGetFlags(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync bool fNotFirst = false;
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync unsigned i;
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Resolve defaults.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Add the flags in the list.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Updates the logger desination using the specified string.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @param pLogger Logger instance (NULL for default logger).
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @param pszVar The value to parse.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsyncRTDECL(int) RTLogDestinations(PRTLOGGER pLogger, char const *pszVar)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Resolve defaults.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Do the parsing.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync unsigned i;
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync /* skip blanks. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* check no prefix. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* instruction. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync if (!strncmp(pszVar, s_aLogDst[i].pszInstr, cchInstr))
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* check for value. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync const char *pszEnd;
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* log file name */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* log directory */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync const char *pszFile = RTPathFilename(pLogger->pszFilename);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync AssertReturn(cchFile + cch + 1 < RTPATH_MAX, VERR_OUT_OF_RANGE);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync memcpy(szTmp, cchFile ? pszFile : "", cchFile + 1);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync memcpy(&pLogger->pszFilename[cch], szTmp, cchFile);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync AssertMsgFailedReturn(("Invalid destination value! %s%s doesn't take a value!\n",
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync /* assert known instruction */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ("Invalid destination value! unknown instruction %.20s\n", pszVar),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* skip blanks and delimiters. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } /* while more environment variable value left */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get the current log destinations as a string.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pLogger Logger instance (NULL for default logger).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszBuf The output buffer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cchBuf The size of the output buffer. Must be greater
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTLogGetDestinations(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fNotFirst = false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync unsigned i;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Resolve defaults.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define APPEND_PSZ(psz,cch) do { memcpy(pszBuf, (psz), (cch)); pszBuf += (cch); cchBuf -= (cch); } while (0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define APPEND_SZ(sz) APPEND_PSZ(sz, sizeof(sz) - 1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define APPEND_CH(ch) do { *pszBuf++ = (ch); cchBuf--; } while (0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Add the flags in the list.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Add the filename.
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync if (cchFilename + sizeof("file=") - 1 + fNotFirst + 1 <= cchBuf)
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync#endif /* !IN_RC */
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * Flushes the specified logger.
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * @param pLogger The logger instance to flush.
8b03ab0bcd5c238021bc8a43d887dd9d0870c0f5vboxsync * If NULL the default instance is used. The default instance
8b03ab0bcd5c238021bc8a43d887dd9d0870c0f5vboxsync * will not be initialized by this call.
2885e130ed9e2da2cb7c2cced97ca1b5779d6e71vboxsync * Resolve defaults.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Any thing to flush?
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Acquire logger instance sem.
e85d76a7e5a047db3cdc8576ff5f412c7b73bbabvboxsync * Call worker.
b55721e255f55546462b62c2d09259bb7bf8ef90vboxsync * Release the semaphore.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * Gets the default logger instance, creating it if necessary.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @returns Pointer to default logger instance.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @returns NULL if no default logger instance available.
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync#else /* !IN_RC */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Check per thread loggers first.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync while (i-- > 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# endif /* IN_RING0 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * If no per thread logger, use the default one.
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync#endif /* !IN_RC */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the default logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns Pointer to default logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns NULL if no default logger instance available.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * Check per thread loggers first.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while (i-- > 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# endif /* IN_RING0 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Sets the default logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns iprt status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pLogger The new default logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(PRTLOGGER) RTLogSetDefaultInstance(PRTLOGGER pLogger)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return (PRTLOGGER)ASMAtomicXchgPtr((void * volatile *)&g_pLogger, pLogger);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* !IN_RC */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Changes the default logger instance for the current thread.
6b022885f2cb6a55167609edecd89570cd80001dvboxsync * @returns IPRT status code.
b45d66c0e496e2fd861479202f3d43aad592bd14vboxsync * @param pLogger The logger instance. Pass NULL for deregistration.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param uKey Associated key for cleanup purposes. If pLogger is NULL,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * all instances with this key will be deregistered. So in
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * order to only deregister the instance associated with the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * current thread use 0.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTLogSetDefaultInstanceThread(PRTLOGGER pLogger, uintptr_t uKey)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync unsigned j;
74991d7531692858fd22acf371a7ee941567977cvboxsync AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
3a21cbe769e7500039a2d17c794a911f7acb2dadvboxsync * Iterate the table to see if there is already an entry for this thread.
3a21cbe769e7500039a2d17c794a911f7acb2dadvboxsync while (i-- > 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, (void *)uKey);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate a new table entry.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_BUFFER_OVERFLOW; /* horrible error code! */
74991d7531692858fd22acf371a7ee941567977cvboxsync for (j = 0; j < 10; j++)
74991d7531692858fd22acf371a7ee941567977cvboxsync while (i-- > 0)
74991d7531692858fd22acf371a7ee941567977cvboxsync AssertCompile(sizeof(RTNATIVETHREAD) == sizeof(void*));
74991d7531692858fd22acf371a7ee941567977cvboxsync if ( g_aPerThreadLoggers[i].NativeThread == NIL_RTNATIVETHREAD
74991d7531692858fd22acf371a7ee941567977cvboxsync && ASMAtomicCmpXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].NativeThread, (void *)Self, (void *)NIL_RTNATIVETHREAD))
74991d7531692858fd22acf371a7ee941567977cvboxsync ASMAtomicXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, (void *)uKey);
74991d7531692858fd22acf371a7ee941567977cvboxsync ASMAtomicXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].pLogger, pLogger);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Search the array for the current thread.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while (i-- > 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].uKey, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].pLogger, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicXchgPtr((void * volatile *)&g_aPerThreadLoggers[i].NativeThread, (void *)NIL_RTNATIVETHREAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Write to a logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pLogger Pointer to logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszFormat Format string.
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync * @param args Format arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(void) RTLogLoggerV(PRTLOGGER pLogger, const char *pszFormat, va_list args)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Write to a logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This function will check whether the instance, group and flags makes up a
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * logging kind which is currently enabled before writing anything to the log.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pLogger Pointer to logger instance. If NULL the default logger instance will be attempted.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlags The logging flags.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param iGroup The group.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The value ~0U is reserved for compatability with RTLogLogger[V] and is
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * only for internal usage!
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszFormat Format string.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param args Format arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(void) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * A NULL logger means default instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate and correct iGroup.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * If no output, then just skip it.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (pLogger->afGroups[iGroup] & (fFlags | RTLOGGRPFLAGS_ENABLED)) != (fFlags | RTLOGGRPFLAGS_ENABLED))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Acquire logger instance sem.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtR0LogLoggerExFallback(pLogger->fDestFlags, pLogger->fFlags, pszFormat, args);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Format the message and perhaps flush it.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pLogger->fFlags & (RTLOGFLAGS_PREFIX_MASK | RTLOGFLAGS_USECRLF))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogFormatV(rtLogOutputPrefixed, &OutputArgs, pszFormat, args);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogFormatV(rtLogOutput, pLogger, pszFormat, args);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * Release the semaphore.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * For rtR0LogLoggerExFallbackOutput and rtR0LogLoggerExFallbackFlush.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The current scratch buffer offset. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The destination flags. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The scratch buffer. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** Pointer to RTR0LOGLOGGERFALLBACK which is used by
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * rtR0LogLoggerExFallbackOutput. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsynctypedef RTR0LOGLOGGERFALLBACK *PRTR0LOGLOGGERFALLBACK;
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync * Flushes the fallback buffer.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * @param pThis The scratch buffer.
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsyncstatic void rtR0LogLoggerExFallbackFlush(PRTR0LOGLOGGERFALLBACK pThis)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogWriteUser(pThis->achScratch, pThis->offScratch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogWriteDebugger(pThis->achScratch, pThis->offScratch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogWriteStdOut(pThis->achScratch, pThis->offScratch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogWriteStdErr(pThis->achScratch, pThis->offScratch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogWriteCom(pThis->achScratch, pThis->offScratch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* empty the buffer. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Callback for RTLogFormatV used by rtR0LogLoggerExFallback.
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync * See PFNLOGOUTPUT() for details.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(size_t) rtR0LogLoggerExFallbackOutput(void *pv, const char *pachChars, size_t cbChars)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTR0LOGLOGGERFALLBACK pThis = (PRTR0LOGLOGGERFALLBACK)pv;
a27fbcbb29ffc2196c2ebd0f2dad92f40c7ec65dvboxsync /* how much */
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync uint32_t cb = sizeof(pThis->achScratch) - pThis->offScratch - 1; /* minus 1 - for the string terminator. */
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync memcpy(&pThis->achScratch[pThis->offScratch], pachChars, cb);
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync /* advance */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* done? */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /* flush */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* won't ever get here! */
57f41f24b7a290eba73c63449f44017d7917561dvboxsync * Termination call, flush the log.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Ring-0 fallback for cases where we're unable to grab the lock.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This will happen when we're at a too high IRQL on Windows for instance and
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * needs to be dealt with or we'll drop a lot of log output. This fallback will
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * only output to some of the log destinations as a few of them may be doing
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * dangerouse things. We won't be doing any prefixing here either, at least not
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * for the present, because it's too much hazzle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fDestFlags The destination flags.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fFlags The logger flags.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszFormat The format string.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * @param va The format arguments.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsyncstatic void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, const char *pszFormat, va_list va)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* fallback indicator. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* selected prefixes */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync This.offScratch += RTStrFormatNumber(&This.achScratch[This.offScratch], Process, 16, sizeof(RTPROCESS) * 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync This.offScratch += RTStrFormatNumber(&This.achScratch[This.offScratch], Thread, 16, sizeof(RTNATIVETHREAD) * 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogFormatV(rtR0LogLoggerExFallbackOutput, &This, pszFormat, va);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* IN_RING0 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * vprintf like function for writing to the default log.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszFormat Printf like format string.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param args Optional arguments as specified in pszFormat.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @remark The API doesn't support formatting of floating point numbers at the moment.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(void) RTLogPrintfV(const char *pszFormat, va_list args)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Writes the buffer to the given log device without checking for buffered
a27fbcbb29ffc2196c2ebd0f2dad92f40c7ec65dvboxsync * data or anything.
a27fbcbb29ffc2196c2ebd0f2dad92f40c7ec65dvboxsync * Used by the RTLogFlush() function.
315f443a509c31db47b8f5cb94d26e54c3d5c497vboxsync * @param pLogger The logger instance to write to. NULL is not allowed!
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync return; /* nothing to flush. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogWriteUser(pLogger->achScratch, pLogger->offScratch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogWriteDebugger(pLogger->achScratch, pLogger->offScratch);
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync RTFileWrite(pLogger->File, pLogger->achScratch, pLogger->offScratch, NULL);
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync RTLogWriteStdOut(pLogger->achScratch, pLogger->offScratch);
75fca099c974cbbd48f132af1378c60232614760vboxsync RTLogWriteStdErr(pLogger->achScratch, pLogger->offScratch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# if (defined(IN_RING0) || defined(IN_RC)) && !defined(LOG_NO_COM)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTLogWriteCom(pLogger->achScratch, pLogger->offScratch);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync#endif /* !IN_RC */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* empty the buffer. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Callback for RTLogFormatV which writes to the com port.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * See PFNLOGOUTPUT() for details.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(size_t) rtLogOutput(void *pv, const char *pachChars, size_t cbChars)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* sanity */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pLogger->offScratch >= sizeof(pLogger->achScratch))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fprintf(stderr, "pLogger->offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pLogger->offScratch, (unsigned)sizeof(pLogger->achScratch));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* how much */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync size_t cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(&pLogger->achScratch[pLogger->offScratch], pachChars, cb);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* advance */
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync /* done? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* flush */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* won't ever get here! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Termination call.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * There's always space for a terminator, and it's not counted.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Callback for RTLogFormatV which writes to the logger instance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This version supports prefixes.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * See PFNLOGOUTPUT() for details.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(size_t) rtLogOutputPrefixed(void *pv, const char *pachChars, size_t cbChars)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTLOGOUTPUTPREFIXEDARGS pArgs = (PRTLOGOUTPUTPREFIXEDARGS)pv;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync size_t cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Pending prefix?
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* sanity */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pLogger->offScratch >= sizeof(pLogger->achScratch))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fprintf(stderr, "pLogger->offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pLogger->offScratch, (unsigned)sizeof(pLogger->achScratch));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Flush the buffer if there isn't enough room for the maximum prefix config.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Max is 256, add a couple of extra bytes.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Write the prefixes.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * psz is pointing to the current position.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* We could have been preempted just before reading of s_u64LastTs by
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * another thread which wrote s_u64LastTs. In that case the difference
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * is negative which we simply ignore. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* 1E15 nanoseconds = 11 days */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, u64, iBase, 16, 0, fFlags); /* +17 */
52694110156cee1511e430c9ae800de121a20050vboxsync /* We could have been preempted just before reading of s_u64LastTsc by
52694110156cee1511e430c9ae800de121a20050vboxsync * another thread which wrote s_u64LastTsc. In that case the difference
52694110156cee1511e430c9ae800de121a20050vboxsync * is negative which we simply ignore. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* 1E15 ticks at 4GHz = 69 hours */
52694110156cee1511e430c9ae800de121a20050vboxsync psz += RTStrFormatNumber(psz, u64, iBase, 16, 0, fFlags); /* +17 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* 1E8 milliseconds = 27 hours */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, u64, 10, 9, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, Time.u8Hour, 10, 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, Time.u8Minute, 10, 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, Time.u8Second, 10, 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, Time.u32Nanosecond / 1000000, 10, 3, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, (uint32_t)(u64 / (60 * 60 * 1000)), 10, 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, u32 / (60 * 1000), 10, 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, u32 / 1000, 10, 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, u32 % 1000, 10, 3, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTTimeSpecToString(RTTimeNow(&Time), szDate, sizeof(szDate));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, Process, 16, sizeof(RTPROCESS) * 2, 0, RTSTR_F_ZEROPAD);
18db01bbe01d709ed64ef78717e98b94b7fee056vboxsync psz += RTStrFormatNumber(psz, Thread, 16, sizeof(RTNATIVETHREAD) * 2, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync psz += RTStrFormatNumber(psz, idCpu, 16, sizeof(idCpu) * 2, 0, RTSTR_F_ZEROPAD);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync psz += pLogger->pfnPrefix(pLogger, psz, 31, pLogger->pvPrefixUserArg);
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync if (pLogger->fFlags & RTLOGFLAGS_PREFIX_LOCK_COUNTS)
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync#ifdef IN_RING3 /** @todo implement these counters in ring-0 too? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t cReadLocks = RTLockValidatorReadLockGetCount(Thread);
0138777a0eae9d74905d86f792f1f1c497dab65evboxsync uint32_t cWriteLocks = RTLockValidatorWriteLockGetCount(Thread) - g_cLoggerLockCount;
bc8991845b5bd7e98758795748d3d76408756793vboxsync psz += RTStrFormatNumber(psz, cReadLocks, 16, 1, 0, RTSTR_F_ZEROPAD);
06de36c1229f14000638fa27993b13c9133e85f5vboxsync psz += RTStrFormatNumber(psz, cWriteLocks, 16, 1, 0, RTSTR_F_ZEROPAD);
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync psz += RTStrFormatNumber(psz, pArgs->fFlags, 16, 8, 0, RTSTR_F_ZEROPAD);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync const char *pszGroup = pArgs->iGroup != ~0U ? pLogger->papszGroups[pArgs->iGroup] : NULL;
9a99bb9ca6c5bc8ef1977e01e13b05e5cc58319bvboxsync psz += RTStrFormatNumber(psz, pArgs->iGroup, 16, 3, 0, RTSTR_F_ZEROPAD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned fGrp = pLogger->afGroups[pArgs->iGroup != ~0U ? pArgs->iGroup : 0];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const char *pszGroup;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case 0: pszGroup = "--------"; cch = sizeof("--------") - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_ENABLED: pszGroup = "enabled" ; cch = sizeof("enabled" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_LEVEL_1: pszGroup = "level 1" ; cch = sizeof("level 1" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_LEVEL_2: pszGroup = "level 2" ; cch = sizeof("level 2" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_LEVEL_3: pszGroup = "level 3" ; cch = sizeof("level 3" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_LEVEL_4: pszGroup = "level 4" ; cch = sizeof("level 4" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_LEVEL_5: pszGroup = "level 5" ; cch = sizeof("level 5" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_LEVEL_6: pszGroup = "level 6" ; cch = sizeof("level 6" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_FLOW: pszGroup = "flow" ; cch = sizeof("flow" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* personal groups */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_LELIK: pszGroup = "lelik" ; cch = sizeof("lelik" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_MICHAEL: pszGroup = "Michael" ; cch = sizeof("Michael" ) - 1; break;
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync case RTLOGGRPFLAGS_DMIK: pszGroup = "dmik" ; cch = sizeof("dmik" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_SUNLOVER: pszGroup = "sunlover"; cch = sizeof("sunlover") - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_ACHIM: pszGroup = "Achim" ; cch = sizeof("Achim" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_SANDER: pszGroup = "Sander" ; cch = sizeof("Sander" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_KLAUS: pszGroup = "Klaus" ; cch = sizeof("Klaus" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_FRANK: pszGroup = "Frank" ; cch = sizeof("Frank" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_BIRD: pszGroup = "bird" ; cch = sizeof("bird" ) - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case RTLOGGRPFLAGS_NONAME: pszGroup = "noname" ; cch = sizeof("noname" ) - 1; break;
750d4d0506a38b2e80c997075d40aad474e675fbvboxsync default: pszGroup = "????????"; cch = sizeof("????????") - 1; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Done, figure what we've used and advance the buffer and free size.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cb = psz - &pLogger->achScratch[pLogger->offScratch];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else if (cb <= 0)
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsync cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* sanity */
2c080f6fc6ab70995d6390eeaa199d590c1a34d5vboxsync if (pLogger->offScratch >= sizeof(pLogger->achScratch))
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync fprintf(stderr, "pLogger->offScratch >= sizeof(pLogger->achScratch) (%#x >= %#x)\n",
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pLogger->offScratch, (unsigned)sizeof(pLogger->achScratch));
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync /* how much */
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync /* have newline? */
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pszNewLine = (const char *)memchr(pachChars, '\n', cb);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(&pLogger->achScratch[pLogger->offScratch], pachChars, cb);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* advance */
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync && pLogger->offScratch + 2 < sizeof(pLogger->achScratch))
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync memcpy(&pLogger->achScratch[pLogger->offScratch], "\r\n", 2);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* done? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* won't ever get here! */
6b022885f2cb6a55167609edecd89570cd80001dvboxsync * Termination call.
6b022885f2cb6a55167609edecd89570cd80001dvboxsync * There's always space for a terminator, and it's not counted.