17cc577a4SJonathan Peyton /* 2de4749b7SJonathan Peyton * kmp_io.cpp -- RTL IO 37cc577a4SJonathan Peyton */ 47cc577a4SJonathan Peyton 57cc577a4SJonathan Peyton //===----------------------------------------------------------------------===// 67cc577a4SJonathan Peyton // 757b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 857b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 957b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 107cc577a4SJonathan Peyton // 117cc577a4SJonathan Peyton //===----------------------------------------------------------------------===// 127cc577a4SJonathan Peyton 133041982dSJonathan Peyton #include <stdarg.h> 143041982dSJonathan Peyton #include <stddef.h> 157cc577a4SJonathan Peyton #include <stdio.h> 167cc577a4SJonathan Peyton #include <stdlib.h> 177cc577a4SJonathan Peyton #include <string.h> 187cc577a4SJonathan Peyton #ifndef __ABSOFT_WIN 197cc577a4SJonathan Peyton #include <sys/types.h> 207cc577a4SJonathan Peyton #endif 217cc577a4SJonathan Peyton 227cc577a4SJonathan Peyton #include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc 233041982dSJonathan Peyton #include "kmp_io.h" 243041982dSJonathan Peyton #include "kmp_lock.h" 253041982dSJonathan Peyton #include "kmp_os.h" 263041982dSJonathan Peyton #include "kmp_str.h" 277cc577a4SJonathan Peyton 287cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 29f700e9edSAndrey Churbanov #if KMP_MSVC_COMPAT 307cc577a4SJonathan Peyton #pragma warning(push) 317cc577a4SJonathan Peyton #pragma warning(disable : 271 310) 32f700e9edSAndrey Churbanov #endif 337cc577a4SJonathan Peyton #include <windows.h> 34f700e9edSAndrey Churbanov #if KMP_MSVC_COMPAT 357cc577a4SJonathan Peyton #pragma warning(pop) 367cc577a4SJonathan Peyton #endif 37f700e9edSAndrey Churbanov #endif 387cc577a4SJonathan Peyton 397cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */ 407cc577a4SJonathan Peyton 413041982dSJonathan Peyton kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( 423041982dSJonathan Peyton __kmp_stdio_lock); /* Control stdio functions */ 433041982dSJonathan Peyton kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( 443041982dSJonathan Peyton __kmp_console_lock); /* Control console initialization */ 457cc577a4SJonathan Peyton 467cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 477cc577a4SJonathan Peyton 487cc577a4SJonathan Peyton static HANDLE __kmp_stdout = NULL; 497cc577a4SJonathan Peyton static HANDLE __kmp_stderr = NULL; 507cc577a4SJonathan Peyton static int __kmp_console_exists = FALSE; 517cc577a4SJonathan Peyton static kmp_str_buf_t __kmp_console_buf; 527cc577a4SJonathan Peyton 533041982dSJonathan Peyton static int is_console(void) { 547cc577a4SJonathan Peyton char buffer[128]; 557cc577a4SJonathan Peyton DWORD rc = 0; 567cc577a4SJonathan Peyton DWORD err = 0; 577cc577a4SJonathan Peyton // Try to get console title. 587cc577a4SJonathan Peyton SetLastError(0); 593041982dSJonathan Peyton // GetConsoleTitle does not reset last error in case of success or short 603041982dSJonathan Peyton // buffer, so we need to clear it explicitly. 617cc577a4SJonathan Peyton rc = GetConsoleTitle(buffer, sizeof(buffer)); 627cc577a4SJonathan Peyton if (rc == 0) { 637cc577a4SJonathan Peyton // rc == 0 means getting console title failed. Let us find out why. 647cc577a4SJonathan Peyton err = GetLastError(); 657cc577a4SJonathan Peyton // err == 0 means buffer too short (we suppose console exists). 667cc577a4SJonathan Peyton // In Window applications we usually have err == 6 (invalid handle). 67bd3a7633SJonathan Peyton } 687cc577a4SJonathan Peyton return rc > 0 || err == 0; 697cc577a4SJonathan Peyton } 707cc577a4SJonathan Peyton 713041982dSJonathan Peyton void __kmp_close_console(void) { 727cc577a4SJonathan Peyton /* wait until user presses return before closing window */ 737cc577a4SJonathan Peyton /* TODO only close if a window was opened */ 747cc577a4SJonathan Peyton if (__kmp_console_exists) { 757cc577a4SJonathan Peyton __kmp_stdout = NULL; 767cc577a4SJonathan Peyton __kmp_stderr = NULL; 777cc577a4SJonathan Peyton __kmp_str_buf_free(&__kmp_console_buf); 787cc577a4SJonathan Peyton __kmp_console_exists = FALSE; 797cc577a4SJonathan Peyton } 807cc577a4SJonathan Peyton } 817cc577a4SJonathan Peyton 827cc577a4SJonathan Peyton /* For windows, call this before stdout, stderr, or stdin are used. 833041982dSJonathan Peyton It opens a console window and starts processing */ 843041982dSJonathan Peyton static void __kmp_redirect_output(void) { 857cc577a4SJonathan Peyton __kmp_acquire_bootstrap_lock(&__kmp_console_lock); 867cc577a4SJonathan Peyton 87*16428a8dSMartin Storsjö (void)is_console; 887cc577a4SJonathan Peyton if (!__kmp_console_exists) { 897cc577a4SJonathan Peyton HANDLE ho; 907cc577a4SJonathan Peyton HANDLE he; 917cc577a4SJonathan Peyton 927cc577a4SJonathan Peyton __kmp_str_buf_init(&__kmp_console_buf); 937cc577a4SJonathan Peyton 947cc577a4SJonathan Peyton AllocConsole(); 957cc577a4SJonathan Peyton // We do not check the result of AllocConsole because 967cc577a4SJonathan Peyton // 1. the call is harmless 977cc577a4SJonathan Peyton // 2. it is not clear how to communicate failue 987cc577a4SJonathan Peyton // 3. we will detect failure later when we get handle(s) 997cc577a4SJonathan Peyton 1007cc577a4SJonathan Peyton ho = GetStdHandle(STD_OUTPUT_HANDLE); 1017cc577a4SJonathan Peyton if (ho == INVALID_HANDLE_VALUE || ho == NULL) { 1027cc577a4SJonathan Peyton 1037cc577a4SJonathan Peyton DWORD err = GetLastError(); 1047cc577a4SJonathan Peyton // TODO: output error somehow (maybe message box) 105b3d84790SMartin Storsjö (void)err; 1067cc577a4SJonathan Peyton __kmp_stdout = NULL; 1077cc577a4SJonathan Peyton 1087cc577a4SJonathan Peyton } else { 1097cc577a4SJonathan Peyton 1107cc577a4SJonathan Peyton __kmp_stdout = ho; // temporary code, need new global for ho 1117cc577a4SJonathan Peyton } 1127cc577a4SJonathan Peyton he = GetStdHandle(STD_ERROR_HANDLE); 1137cc577a4SJonathan Peyton if (he == INVALID_HANDLE_VALUE || he == NULL) { 1147cc577a4SJonathan Peyton 1157cc577a4SJonathan Peyton DWORD err = GetLastError(); 1167cc577a4SJonathan Peyton // TODO: output error somehow (maybe message box) 117b3d84790SMartin Storsjö (void)err; 1187cc577a4SJonathan Peyton __kmp_stderr = NULL; 1197cc577a4SJonathan Peyton 1207cc577a4SJonathan Peyton } else { 1217cc577a4SJonathan Peyton 1227cc577a4SJonathan Peyton __kmp_stderr = he; // temporary code, need new global 1237cc577a4SJonathan Peyton } 1247cc577a4SJonathan Peyton __kmp_console_exists = TRUE; 1257cc577a4SJonathan Peyton } 1267cc577a4SJonathan Peyton __kmp_release_bootstrap_lock(&__kmp_console_lock); 1277cc577a4SJonathan Peyton } 1287cc577a4SJonathan Peyton 1297cc577a4SJonathan Peyton #else 1307cc577a4SJonathan Peyton #define __kmp_stderr (stderr) 1316d88e049SJonathan Peyton #define __kmp_stdout (stdout) 1327cc577a4SJonathan Peyton #endif /* KMP_OS_WINDOWS */ 1337cc577a4SJonathan Peyton 1346d88e049SJonathan Peyton void __kmp_vprintf(enum kmp_io out_stream, char const *format, va_list ap) { 1357cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1367cc577a4SJonathan Peyton if (!__kmp_console_exists) { 1377cc577a4SJonathan Peyton __kmp_redirect_output(); 1387cc577a4SJonathan Peyton } 1396d88e049SJonathan Peyton if (!__kmp_stderr && out_stream == kmp_err) { 1407cc577a4SJonathan Peyton return; 1417cc577a4SJonathan Peyton } 1426d88e049SJonathan Peyton if (!__kmp_stdout && out_stream == kmp_out) { 1437cc577a4SJonathan Peyton return; 1447cc577a4SJonathan Peyton } 1457cc577a4SJonathan Peyton #endif /* KMP_OS_WINDOWS */ 1466d88e049SJonathan Peyton auto stream = ((out_stream == kmp_out) ? __kmp_stdout : __kmp_stderr); 1477cc577a4SJonathan Peyton 1487cc577a4SJonathan Peyton if (__kmp_debug_buf && __kmp_debug_buffer != NULL) { 1497cc577a4SJonathan Peyton 15037e2ef54SJonathan Peyton int dc = __kmp_debug_count++ % __kmp_debug_buf_lines; 1517cc577a4SJonathan Peyton char *db = &__kmp_debug_buffer[dc * __kmp_debug_buf_chars]; 1527cc577a4SJonathan Peyton int chars = 0; 1537cc577a4SJonathan Peyton 1547cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 1553041982dSJonathan Peyton chars = KMP_SNPRINTF(db, __kmp_debug_buf_chars, "pid=%d: ", 1563041982dSJonathan Peyton (kmp_int32)getpid()); 1577cc577a4SJonathan Peyton #endif 1587cc577a4SJonathan Peyton chars += KMP_VSNPRINTF(db, __kmp_debug_buf_chars, format, ap); 1597cc577a4SJonathan Peyton 1607cc577a4SJonathan Peyton if (chars + 1 > __kmp_debug_buf_chars) { 1617cc577a4SJonathan Peyton if (chars + 1 > __kmp_debug_buf_warn_chars) { 1627cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1637cc577a4SJonathan Peyton DWORD count; 1643041982dSJonathan Peyton __kmp_str_buf_print(&__kmp_console_buf, "OMP warning: Debugging buffer " 1653041982dSJonathan Peyton "overflow; increase " 1663041982dSJonathan Peyton "KMP_DEBUG_BUF_CHARS to %d\n", 1677cc577a4SJonathan Peyton chars + 1); 1686d88e049SJonathan Peyton WriteFile(stream, __kmp_console_buf.str, __kmp_console_buf.used, &count, 1696d88e049SJonathan Peyton NULL); 1707cc577a4SJonathan Peyton __kmp_str_buf_clear(&__kmp_console_buf); 1717cc577a4SJonathan Peyton #else 1726d88e049SJonathan Peyton fprintf(stream, "OMP warning: Debugging buffer overflow; " 1733041982dSJonathan Peyton "increase KMP_DEBUG_BUF_CHARS to %d\n", 1747cc577a4SJonathan Peyton chars + 1); 1756d88e049SJonathan Peyton fflush(stream); 1767cc577a4SJonathan Peyton #endif 1777cc577a4SJonathan Peyton __kmp_debug_buf_warn_chars = chars + 1; 1787cc577a4SJonathan Peyton } 1797cc577a4SJonathan Peyton /* terminate string if overflow occurred */ 1807cc577a4SJonathan Peyton db[__kmp_debug_buf_chars - 2] = '\n'; 1817cc577a4SJonathan Peyton db[__kmp_debug_buf_chars - 1] = '\0'; 1827cc577a4SJonathan Peyton } 1837cc577a4SJonathan Peyton } else { 1847cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1857cc577a4SJonathan Peyton DWORD count; 1867cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 1873041982dSJonathan Peyton __kmp_str_buf_print(&__kmp_console_buf, "pid=%d: ", (kmp_int32)getpid()); 1887cc577a4SJonathan Peyton #endif 1897cc577a4SJonathan Peyton __kmp_str_buf_vprint(&__kmp_console_buf, format, ap); 1906d88e049SJonathan Peyton WriteFile(stream, __kmp_console_buf.str, __kmp_console_buf.used, &count, 1916d88e049SJonathan Peyton NULL); 1927cc577a4SJonathan Peyton __kmp_str_buf_clear(&__kmp_console_buf); 1937cc577a4SJonathan Peyton #else 1947cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 1956d88e049SJonathan Peyton fprintf(stream, "pid=%d: ", (kmp_int32)getpid()); 1967cc577a4SJonathan Peyton #endif 1976d88e049SJonathan Peyton vfprintf(stream, format, ap); 1986d88e049SJonathan Peyton fflush(stream); 1997cc577a4SJonathan Peyton #endif 2007cc577a4SJonathan Peyton } 2017cc577a4SJonathan Peyton } 2027cc577a4SJonathan Peyton 2033041982dSJonathan Peyton void __kmp_printf(char const *format, ...) { 2047cc577a4SJonathan Peyton va_list ap; 2057cc577a4SJonathan Peyton va_start(ap, format); 2067cc577a4SJonathan Peyton 2077cc577a4SJonathan Peyton __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock); 2087cc577a4SJonathan Peyton __kmp_vprintf(kmp_err, format, ap); 2097cc577a4SJonathan Peyton __kmp_release_bootstrap_lock(&__kmp_stdio_lock); 2107cc577a4SJonathan Peyton 2117cc577a4SJonathan Peyton va_end(ap); 2127cc577a4SJonathan Peyton } 2137cc577a4SJonathan Peyton 2143041982dSJonathan Peyton void __kmp_printf_no_lock(char const *format, ...) { 2157cc577a4SJonathan Peyton va_list ap; 2167cc577a4SJonathan Peyton va_start(ap, format); 2177cc577a4SJonathan Peyton 2187cc577a4SJonathan Peyton __kmp_vprintf(kmp_err, format, ap); 2197cc577a4SJonathan Peyton 2207cc577a4SJonathan Peyton va_end(ap); 2217cc577a4SJonathan Peyton } 2226d88e049SJonathan Peyton 2236d88e049SJonathan Peyton void __kmp_fprintf(enum kmp_io stream, char const *format, ...) { 2246d88e049SJonathan Peyton va_list ap; 2256d88e049SJonathan Peyton va_start(ap, format); 2266d88e049SJonathan Peyton 2276d88e049SJonathan Peyton __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock); 2286d88e049SJonathan Peyton __kmp_vprintf(stream, format, ap); 2296d88e049SJonathan Peyton __kmp_release_bootstrap_lock(&__kmp_stdio_lock); 2306d88e049SJonathan Peyton 2316d88e049SJonathan Peyton va_end(ap); 2326d88e049SJonathan Peyton } 233