Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 1 | /* |
Jonathan Peyton | de4749b | 2016-12-14 23:01:24 +0000 | [diff] [blame] | 2 | * kmp_io.cpp -- RTL IO |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 3 | */ |
| 4 | |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 5 | //===----------------------------------------------------------------------===// |
| 6 | // |
Chandler Carruth | 57b08b0 | 2019-01-19 10:56:40 +0000 | [diff] [blame] | 7 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 8 | // See https://llvm.org/LICENSE.txt for license information. |
| 9 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 13 | #include <stdarg.h> |
| 14 | #include <stddef.h> |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 15 | #include <stdio.h> |
| 16 | #include <stdlib.h> |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 17 | #include <string.h> |
| 18 | #ifndef __ABSOFT_WIN |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 19 | #include <sys/types.h> |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 20 | #endif |
| 21 | |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 22 | #include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 23 | #include "kmp_io.h" |
| 24 | #include "kmp_lock.h" |
| 25 | #include "kmp_os.h" |
| 26 | #include "kmp_str.h" |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 27 | |
| 28 | #if KMP_OS_WINDOWS |
Andrey Churbanov | f700e9e | 2018-12-10 13:45:00 +0000 | [diff] [blame] | 29 | #if KMP_MSVC_COMPAT |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 30 | #pragma warning(push) |
| 31 | #pragma warning(disable : 271 310) |
Andrey Churbanov | f700e9e | 2018-12-10 13:45:00 +0000 | [diff] [blame] | 32 | #endif |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 33 | #include <windows.h> |
Andrey Churbanov | f700e9e | 2018-12-10 13:45:00 +0000 | [diff] [blame] | 34 | #if KMP_MSVC_COMPAT |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 35 | #pragma warning(pop) |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 36 | #endif |
Andrey Churbanov | f700e9e | 2018-12-10 13:45:00 +0000 | [diff] [blame] | 37 | #endif |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 38 | |
| 39 | /* ------------------------------------------------------------------------ */ |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 40 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 41 | kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( |
| 42 | __kmp_stdio_lock); /* Control stdio functions */ |
| 43 | kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( |
| 44 | __kmp_console_lock); /* Control console initialization */ |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 45 | |
| 46 | #if KMP_OS_WINDOWS |
| 47 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 48 | static HANDLE __kmp_stdout = NULL; |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 49 | static HANDLE __kmp_stderr = NULL; |
| 50 | static int __kmp_console_exists = FALSE; |
| 51 | static kmp_str_buf_t __kmp_console_buf; |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 52 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 53 | static int is_console(void) { |
| 54 | char buffer[128]; |
| 55 | DWORD rc = 0; |
| 56 | DWORD err = 0; |
| 57 | // Try to get console title. |
| 58 | SetLastError(0); |
| 59 | // GetConsoleTitle does not reset last error in case of success or short |
| 60 | // buffer, so we need to clear it explicitly. |
| 61 | rc = GetConsoleTitle(buffer, sizeof(buffer)); |
| 62 | if (rc == 0) { |
| 63 | // rc == 0 means getting console title failed. Let us find out why. |
| 64 | err = GetLastError(); |
| 65 | // err == 0 means buffer too short (we suppose console exists). |
| 66 | // In Window applications we usually have err == 6 (invalid handle). |
Jonathan Peyton | bd3a763 | 2017-09-27 20:36:27 +0000 | [diff] [blame] | 67 | } |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 68 | return rc > 0 || err == 0; |
| 69 | } |
| 70 | |
| 71 | void __kmp_close_console(void) { |
| 72 | /* wait until user presses return before closing window */ |
| 73 | /* TODO only close if a window was opened */ |
| 74 | if (__kmp_console_exists) { |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 75 | __kmp_stdout = NULL; |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 76 | __kmp_stderr = NULL; |
| 77 | __kmp_str_buf_free(&__kmp_console_buf); |
| 78 | __kmp_console_exists = FALSE; |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | /* For windows, call this before stdout, stderr, or stdin are used. |
| 83 | It opens a console window and starts processing */ |
| 84 | static void __kmp_redirect_output(void) { |
| 85 | __kmp_acquire_bootstrap_lock(&__kmp_console_lock); |
| 86 | |
| 87 | if (!__kmp_console_exists) { |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 88 | HANDLE ho; |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 89 | HANDLE he; |
| 90 | |
| 91 | __kmp_str_buf_init(&__kmp_console_buf); |
| 92 | |
| 93 | AllocConsole(); |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 94 | // We do not check the result of AllocConsole because |
| 95 | // 1. the call is harmless |
| 96 | // 2. it is not clear how to communicate failue |
| 97 | // 3. we will detect failure later when we get handle(s) |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 98 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 99 | ho = GetStdHandle(STD_OUTPUT_HANDLE); |
| 100 | if (ho == INVALID_HANDLE_VALUE || ho == NULL) { |
| 101 | |
| 102 | DWORD err = GetLastError(); |
| 103 | // TODO: output error somehow (maybe message box) |
| 104 | __kmp_stdout = NULL; |
| 105 | |
| 106 | } else { |
| 107 | |
| 108 | __kmp_stdout = ho; // temporary code, need new global for ho |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 109 | } |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 110 | he = GetStdHandle(STD_ERROR_HANDLE); |
| 111 | if (he == INVALID_HANDLE_VALUE || he == NULL) { |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 112 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 113 | DWORD err = GetLastError(); |
| 114 | // TODO: output error somehow (maybe message box) |
| 115 | __kmp_stderr = NULL; |
| 116 | |
| 117 | } else { |
| 118 | |
| 119 | __kmp_stderr = he; // temporary code, need new global |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 120 | } |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 121 | __kmp_console_exists = TRUE; |
| 122 | } |
| 123 | __kmp_release_bootstrap_lock(&__kmp_console_lock); |
| 124 | } |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 125 | |
| 126 | #else |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 127 | #define __kmp_stderr (stderr) |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 128 | #define __kmp_stdout (stdout) |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 129 | #endif /* KMP_OS_WINDOWS */ |
| 130 | |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 131 | void __kmp_vprintf(enum kmp_io out_stream, char const *format, va_list ap) { |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 132 | #if KMP_OS_WINDOWS |
| 133 | if (!__kmp_console_exists) { |
| 134 | __kmp_redirect_output(); |
| 135 | } |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 136 | if (!__kmp_stderr && out_stream == kmp_err) { |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 137 | return; |
| 138 | } |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 139 | if (!__kmp_stdout && out_stream == kmp_out) { |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 140 | return; |
| 141 | } |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 142 | #endif /* KMP_OS_WINDOWS */ |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 143 | auto stream = ((out_stream == kmp_out) ? __kmp_stdout : __kmp_stderr); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 144 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 145 | if (__kmp_debug_buf && __kmp_debug_buffer != NULL) { |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 146 | |
Jonathan Peyton | 37e2ef5 | 2018-07-09 17:36:22 +0000 | [diff] [blame] | 147 | int dc = __kmp_debug_count++ % __kmp_debug_buf_lines; |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 148 | char *db = &__kmp_debug_buffer[dc * __kmp_debug_buf_chars]; |
| 149 | int chars = 0; |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 150 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 151 | #ifdef KMP_DEBUG_PIDS |
| 152 | chars = KMP_SNPRINTF(db, __kmp_debug_buf_chars, "pid=%d: ", |
| 153 | (kmp_int32)getpid()); |
| 154 | #endif |
| 155 | chars += KMP_VSNPRINTF(db, __kmp_debug_buf_chars, format, ap); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 156 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 157 | if (chars + 1 > __kmp_debug_buf_chars) { |
| 158 | if (chars + 1 > __kmp_debug_buf_warn_chars) { |
| 159 | #if KMP_OS_WINDOWS |
| 160 | DWORD count; |
| 161 | __kmp_str_buf_print(&__kmp_console_buf, "OMP warning: Debugging buffer " |
| 162 | "overflow; increase " |
| 163 | "KMP_DEBUG_BUF_CHARS to %d\n", |
| 164 | chars + 1); |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 165 | WriteFile(stream, __kmp_console_buf.str, __kmp_console_buf.used, &count, |
| 166 | NULL); |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 167 | __kmp_str_buf_clear(&__kmp_console_buf); |
| 168 | #else |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 169 | fprintf(stream, "OMP warning: Debugging buffer overflow; " |
| 170 | "increase KMP_DEBUG_BUF_CHARS to %d\n", |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 171 | chars + 1); |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 172 | fflush(stream); |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 173 | #endif |
| 174 | __kmp_debug_buf_warn_chars = chars + 1; |
| 175 | } |
| 176 | /* terminate string if overflow occurred */ |
| 177 | db[__kmp_debug_buf_chars - 2] = '\n'; |
| 178 | db[__kmp_debug_buf_chars - 1] = '\0'; |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 179 | } |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 180 | } else { |
| 181 | #if KMP_OS_WINDOWS |
| 182 | DWORD count; |
| 183 | #ifdef KMP_DEBUG_PIDS |
| 184 | __kmp_str_buf_print(&__kmp_console_buf, "pid=%d: ", (kmp_int32)getpid()); |
| 185 | #endif |
| 186 | __kmp_str_buf_vprint(&__kmp_console_buf, format, ap); |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 187 | WriteFile(stream, __kmp_console_buf.str, __kmp_console_buf.used, &count, |
| 188 | NULL); |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 189 | __kmp_str_buf_clear(&__kmp_console_buf); |
| 190 | #else |
| 191 | #ifdef KMP_DEBUG_PIDS |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 192 | fprintf(stream, "pid=%d: ", (kmp_int32)getpid()); |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 193 | #endif |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 194 | vfprintf(stream, format, ap); |
| 195 | fflush(stream); |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 196 | #endif |
| 197 | } |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 198 | } |
| 199 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 200 | void __kmp_printf(char const *format, ...) { |
| 201 | va_list ap; |
| 202 | va_start(ap, format); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 203 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 204 | __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock); |
| 205 | __kmp_vprintf(kmp_err, format, ap); |
| 206 | __kmp_release_bootstrap_lock(&__kmp_stdio_lock); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 207 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 208 | va_end(ap); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 209 | } |
| 210 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 211 | void __kmp_printf_no_lock(char const *format, ...) { |
| 212 | va_list ap; |
| 213 | va_start(ap, format); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 214 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 215 | __kmp_vprintf(kmp_err, format, ap); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 216 | |
Jonathan Peyton | 3041982 | 2017-05-12 18:01:32 +0000 | [diff] [blame] | 217 | va_end(ap); |
Jim Cownie | 5e8470a | 2013-09-27 10:38:44 +0000 | [diff] [blame] | 218 | } |
Jonathan Peyton | 6d88e04 | 2018-12-13 23:14:24 +0000 | [diff] [blame] | 219 | |
| 220 | void __kmp_fprintf(enum kmp_io stream, char const *format, ...) { |
| 221 | va_list ap; |
| 222 | va_start(ap, format); |
| 223 | |
| 224 | __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock); |
| 225 | __kmp_vprintf(stream, format, ap); |
| 226 | __kmp_release_bootstrap_lock(&__kmp_stdio_lock); |
| 227 | |
| 228 | va_end(ap); |
| 229 | } |