17cc577a4SJonathan Peyton /* 2de4749b7SJonathan Peyton * kmp_io.cpp -- RTL IO 37cc577a4SJonathan Peyton */ 47cc577a4SJonathan Peyton 57cc577a4SJonathan Peyton //===----------------------------------------------------------------------===// 67cc577a4SJonathan Peyton // 77cc577a4SJonathan Peyton // The LLVM Compiler Infrastructure 87cc577a4SJonathan Peyton // 97cc577a4SJonathan Peyton // This file is dual licensed under the MIT and the University of Illinois Open 107cc577a4SJonathan Peyton // Source Licenses. See LICENSE.txt for details. 117cc577a4SJonathan Peyton // 127cc577a4SJonathan Peyton //===----------------------------------------------------------------------===// 137cc577a4SJonathan Peyton 143041982dSJonathan Peyton #include <stdarg.h> 153041982dSJonathan Peyton #include <stddef.h> 167cc577a4SJonathan Peyton #include <stdio.h> 177cc577a4SJonathan Peyton #include <stdlib.h> 187cc577a4SJonathan Peyton #include <string.h> 197cc577a4SJonathan Peyton #ifndef __ABSOFT_WIN 207cc577a4SJonathan Peyton #include <sys/types.h> 217cc577a4SJonathan Peyton #endif 227cc577a4SJonathan Peyton 237cc577a4SJonathan Peyton #include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc 243041982dSJonathan Peyton #include "kmp_io.h" 253041982dSJonathan Peyton #include "kmp_lock.h" 263041982dSJonathan Peyton #include "kmp_os.h" 273041982dSJonathan Peyton #include "kmp_str.h" 287cc577a4SJonathan Peyton 297cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 307cc577a4SJonathan Peyton #pragma warning(push) 317cc577a4SJonathan Peyton #pragma warning(disable : 271 310) 327cc577a4SJonathan Peyton #include <windows.h> 337cc577a4SJonathan Peyton #pragma warning(pop) 347cc577a4SJonathan Peyton #endif 357cc577a4SJonathan Peyton 367cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */ 377cc577a4SJonathan Peyton 383041982dSJonathan Peyton kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( 393041982dSJonathan Peyton __kmp_stdio_lock); /* Control stdio functions */ 403041982dSJonathan Peyton kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( 413041982dSJonathan Peyton __kmp_console_lock); /* Control console initialization */ 427cc577a4SJonathan Peyton 437cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 447cc577a4SJonathan Peyton 457cc577a4SJonathan Peyton #ifdef KMP_DEBUG 467cc577a4SJonathan Peyton /* __kmp_stdout is used only for dev build */ 477cc577a4SJonathan Peyton static HANDLE __kmp_stdout = NULL; 487cc577a4SJonathan Peyton #endif 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 #ifdef KMP_DEBUG 767cc577a4SJonathan Peyton /* standard out is used only in dev build */ 777cc577a4SJonathan Peyton __kmp_stdout = NULL; 787cc577a4SJonathan Peyton #endif 797cc577a4SJonathan Peyton __kmp_stderr = NULL; 807cc577a4SJonathan Peyton __kmp_str_buf_free(&__kmp_console_buf); 817cc577a4SJonathan Peyton __kmp_console_exists = FALSE; 827cc577a4SJonathan Peyton } 837cc577a4SJonathan Peyton } 847cc577a4SJonathan Peyton 857cc577a4SJonathan Peyton /* For windows, call this before stdout, stderr, or stdin are used. 863041982dSJonathan Peyton It opens a console window and starts processing */ 873041982dSJonathan Peyton static void __kmp_redirect_output(void) { 887cc577a4SJonathan Peyton __kmp_acquire_bootstrap_lock(&__kmp_console_lock); 897cc577a4SJonathan Peyton 907cc577a4SJonathan Peyton if (!__kmp_console_exists) { 917cc577a4SJonathan Peyton #ifdef KMP_DEBUG 927cc577a4SJonathan Peyton /* standard out is used only in dev build */ 937cc577a4SJonathan Peyton HANDLE ho; 947cc577a4SJonathan Peyton #endif 957cc577a4SJonathan Peyton HANDLE he; 967cc577a4SJonathan Peyton 977cc577a4SJonathan Peyton __kmp_str_buf_init(&__kmp_console_buf); 987cc577a4SJonathan Peyton 997cc577a4SJonathan Peyton AllocConsole(); 1007cc577a4SJonathan Peyton // We do not check the result of AllocConsole because 1017cc577a4SJonathan Peyton // 1. the call is harmless 1027cc577a4SJonathan Peyton // 2. it is not clear how to communicate failue 1037cc577a4SJonathan Peyton // 3. we will detect failure later when we get handle(s) 1047cc577a4SJonathan Peyton 1057cc577a4SJonathan Peyton #ifdef KMP_DEBUG 1067cc577a4SJonathan Peyton ho = GetStdHandle(STD_OUTPUT_HANDLE); 1077cc577a4SJonathan Peyton if (ho == INVALID_HANDLE_VALUE || ho == NULL) { 1087cc577a4SJonathan Peyton 1097cc577a4SJonathan Peyton DWORD err = GetLastError(); 1107cc577a4SJonathan Peyton // TODO: output error somehow (maybe message box) 1117cc577a4SJonathan Peyton __kmp_stdout = NULL; 1127cc577a4SJonathan Peyton 1137cc577a4SJonathan Peyton } else { 1147cc577a4SJonathan Peyton 1157cc577a4SJonathan Peyton __kmp_stdout = ho; // temporary code, need new global for ho 1167cc577a4SJonathan Peyton } 1177cc577a4SJonathan Peyton #endif 1187cc577a4SJonathan Peyton he = GetStdHandle(STD_ERROR_HANDLE); 1197cc577a4SJonathan Peyton if (he == INVALID_HANDLE_VALUE || he == NULL) { 1207cc577a4SJonathan Peyton 1217cc577a4SJonathan Peyton DWORD err = GetLastError(); 1227cc577a4SJonathan Peyton // TODO: output error somehow (maybe message box) 1237cc577a4SJonathan Peyton __kmp_stderr = NULL; 1247cc577a4SJonathan Peyton 1257cc577a4SJonathan Peyton } else { 1267cc577a4SJonathan Peyton 1277cc577a4SJonathan Peyton __kmp_stderr = he; // temporary code, need new global 1287cc577a4SJonathan Peyton } 1297cc577a4SJonathan Peyton __kmp_console_exists = TRUE; 1307cc577a4SJonathan Peyton } 1317cc577a4SJonathan Peyton __kmp_release_bootstrap_lock(&__kmp_console_lock); 1327cc577a4SJonathan Peyton } 1337cc577a4SJonathan Peyton 1347cc577a4SJonathan Peyton #else 1357cc577a4SJonathan Peyton #define __kmp_stderr (stderr) 1367cc577a4SJonathan Peyton #endif /* KMP_OS_WINDOWS */ 1377cc577a4SJonathan Peyton 1383041982dSJonathan Peyton void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap) { 1397cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1407cc577a4SJonathan Peyton if (!__kmp_console_exists) { 1417cc577a4SJonathan Peyton __kmp_redirect_output(); 1427cc577a4SJonathan Peyton } 1437cc577a4SJonathan Peyton if (!__kmp_stderr && __kmp_io == kmp_err) { 1447cc577a4SJonathan Peyton return; 1457cc577a4SJonathan Peyton } 1467cc577a4SJonathan Peyton #ifdef KMP_DEBUG 1477cc577a4SJonathan Peyton if (!__kmp_stdout && __kmp_io == kmp_out) { 1487cc577a4SJonathan Peyton return; 1497cc577a4SJonathan Peyton } 1507cc577a4SJonathan Peyton #endif 1517cc577a4SJonathan Peyton #endif /* KMP_OS_WINDOWS */ 1527cc577a4SJonathan Peyton 1537cc577a4SJonathan Peyton if (__kmp_debug_buf && __kmp_debug_buffer != NULL) { 1547cc577a4SJonathan Peyton 155*37e2ef54SJonathan Peyton int dc = __kmp_debug_count++ % __kmp_debug_buf_lines; 1567cc577a4SJonathan Peyton char *db = &__kmp_debug_buffer[dc * __kmp_debug_buf_chars]; 1577cc577a4SJonathan Peyton int chars = 0; 1587cc577a4SJonathan Peyton 1597cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 1603041982dSJonathan Peyton chars = KMP_SNPRINTF(db, __kmp_debug_buf_chars, "pid=%d: ", 1613041982dSJonathan Peyton (kmp_int32)getpid()); 1627cc577a4SJonathan Peyton #endif 1637cc577a4SJonathan Peyton chars += KMP_VSNPRINTF(db, __kmp_debug_buf_chars, format, ap); 1647cc577a4SJonathan Peyton 1657cc577a4SJonathan Peyton if (chars + 1 > __kmp_debug_buf_chars) { 1667cc577a4SJonathan Peyton if (chars + 1 > __kmp_debug_buf_warn_chars) { 1677cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1687cc577a4SJonathan Peyton DWORD count; 1693041982dSJonathan Peyton __kmp_str_buf_print(&__kmp_console_buf, "OMP warning: Debugging buffer " 1703041982dSJonathan Peyton "overflow; increase " 1713041982dSJonathan Peyton "KMP_DEBUG_BUF_CHARS to %d\n", 1727cc577a4SJonathan Peyton chars + 1); 1733041982dSJonathan Peyton WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used, 1743041982dSJonathan Peyton &count, NULL); 1757cc577a4SJonathan Peyton __kmp_str_buf_clear(&__kmp_console_buf); 1767cc577a4SJonathan Peyton #else 1773041982dSJonathan Peyton fprintf(__kmp_stderr, "OMP warning: Debugging buffer overflow; " 1783041982dSJonathan Peyton "increase KMP_DEBUG_BUF_CHARS to %d\n", 1797cc577a4SJonathan Peyton chars + 1); 1807cc577a4SJonathan Peyton fflush(__kmp_stderr); 1817cc577a4SJonathan Peyton #endif 1827cc577a4SJonathan Peyton __kmp_debug_buf_warn_chars = chars + 1; 1837cc577a4SJonathan Peyton } 1847cc577a4SJonathan Peyton /* terminate string if overflow occurred */ 1857cc577a4SJonathan Peyton db[__kmp_debug_buf_chars - 2] = '\n'; 1867cc577a4SJonathan Peyton db[__kmp_debug_buf_chars - 1] = '\0'; 1877cc577a4SJonathan Peyton } 1887cc577a4SJonathan Peyton } else { 1897cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1907cc577a4SJonathan Peyton DWORD count; 1917cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 1923041982dSJonathan Peyton __kmp_str_buf_print(&__kmp_console_buf, "pid=%d: ", (kmp_int32)getpid()); 1937cc577a4SJonathan Peyton #endif 1947cc577a4SJonathan Peyton __kmp_str_buf_vprint(&__kmp_console_buf, format, ap); 1953041982dSJonathan Peyton WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used, 1963041982dSJonathan Peyton &count, NULL); 1977cc577a4SJonathan Peyton __kmp_str_buf_clear(&__kmp_console_buf); 1987cc577a4SJonathan Peyton #else 1997cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 2007cc577a4SJonathan Peyton fprintf(__kmp_stderr, "pid=%d: ", (kmp_int32)getpid()); 2017cc577a4SJonathan Peyton #endif 2027cc577a4SJonathan Peyton vfprintf(__kmp_stderr, format, ap); 2037cc577a4SJonathan Peyton fflush(__kmp_stderr); 2047cc577a4SJonathan Peyton #endif 2057cc577a4SJonathan Peyton } 2067cc577a4SJonathan Peyton } 2077cc577a4SJonathan Peyton 2083041982dSJonathan Peyton void __kmp_printf(char const *format, ...) { 2097cc577a4SJonathan Peyton va_list ap; 2107cc577a4SJonathan Peyton va_start(ap, format); 2117cc577a4SJonathan Peyton 2127cc577a4SJonathan Peyton __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock); 2137cc577a4SJonathan Peyton __kmp_vprintf(kmp_err, format, ap); 2147cc577a4SJonathan Peyton __kmp_release_bootstrap_lock(&__kmp_stdio_lock); 2157cc577a4SJonathan Peyton 2167cc577a4SJonathan Peyton va_end(ap); 2177cc577a4SJonathan Peyton } 2187cc577a4SJonathan Peyton 2193041982dSJonathan Peyton void __kmp_printf_no_lock(char const *format, ...) { 2207cc577a4SJonathan Peyton va_list ap; 2217cc577a4SJonathan Peyton va_start(ap, format); 2227cc577a4SJonathan Peyton 2237cc577a4SJonathan Peyton __kmp_vprintf(kmp_err, format, ap); 2247cc577a4SJonathan Peyton 2257cc577a4SJonathan Peyton va_end(ap); 2267cc577a4SJonathan Peyton } 227