blob: 609dd18e0bb0afb65e0179ea282ec87c70511bb2 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001/*
Jonathan Peytonde4749b2016-12-14 23:01:24 +00002 * kmp_io.cpp -- RTL IO
Jim Cownie5e8470a2013-09-27 10:38:44 +00003 */
4
5
6//===----------------------------------------------------------------------===//
7//
8// The LLVM Compiler Infrastructure
9//
10// This file is dual licensed under the MIT and the University of Illinois Open
11// Source Licenses. See LICENSE.txt for details.
12//
13//===----------------------------------------------------------------------===//
14
15
Jonathan Peyton30419822017-05-12 18:01:32 +000016#include <stdarg.h>
17#include <stddef.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000018#include <stdio.h>
19#include <stdlib.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000020#include <string.h>
21#ifndef __ABSOFT_WIN
Jonathan Peyton30419822017-05-12 18:01:32 +000022#include <sys/types.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000023#endif
24
Jim Cownie5e8470a2013-09-27 10:38:44 +000025#include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc
Jonathan Peyton30419822017-05-12 18:01:32 +000026#include "kmp_io.h"
27#include "kmp_lock.h"
28#include "kmp_os.h"
29#include "kmp_str.h"
Jim Cownie5e8470a2013-09-27 10:38:44 +000030
31#if KMP_OS_WINDOWS
Jonathan Peyton30419822017-05-12 18:01:32 +000032#pragma warning(push)
33#pragma warning(disable : 271 310)
34#include <windows.h>
35#pragma warning(pop)
Jim Cownie5e8470a2013-09-27 10:38:44 +000036#endif
37
38/* ------------------------------------------------------------------------ */
Jim Cownie5e8470a2013-09-27 10:38:44 +000039
Jonathan Peyton30419822017-05-12 18:01:32 +000040kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
41 __kmp_stdio_lock); /* Control stdio functions */
42kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
43 __kmp_console_lock); /* Control console initialization */
Jim Cownie5e8470a2013-09-27 10:38:44 +000044
45#if KMP_OS_WINDOWS
46
Jonathan Peyton30419822017-05-12 18:01:32 +000047#ifdef KMP_DEBUG
48/* __kmp_stdout is used only for dev build */
49static HANDLE __kmp_stdout = NULL;
50#endif
51static HANDLE __kmp_stderr = NULL;
52static int __kmp_console_exists = FALSE;
53static kmp_str_buf_t __kmp_console_buf;
Jim Cownie5e8470a2013-09-27 10:38:44 +000054
Jonathan Peyton30419822017-05-12 18:01:32 +000055static int is_console(void) {
56 char buffer[128];
57 DWORD rc = 0;
58 DWORD err = 0;
59 // Try to get console title.
60 SetLastError(0);
61 // GetConsoleTitle does not reset last error in case of success or short
62 // buffer, so we need to clear it explicitly.
63 rc = GetConsoleTitle(buffer, sizeof(buffer));
64 if (rc == 0) {
65 // rc == 0 means getting console title failed. Let us find out why.
66 err = GetLastError();
67 // err == 0 means buffer too short (we suppose console exists).
68 // In Window applications we usually have err == 6 (invalid handle).
Jonathan Peytonbd3a7632017-09-27 20:36:27 +000069 }
Jonathan Peyton30419822017-05-12 18:01:32 +000070 return rc > 0 || err == 0;
71}
72
73void __kmp_close_console(void) {
74 /* wait until user presses return before closing window */
75 /* TODO only close if a window was opened */
76 if (__kmp_console_exists) {
77#ifdef KMP_DEBUG
78 /* standard out is used only in dev build */
79 __kmp_stdout = NULL;
80#endif
81 __kmp_stderr = NULL;
82 __kmp_str_buf_free(&__kmp_console_buf);
83 __kmp_console_exists = FALSE;
84 }
85}
86
87/* For windows, call this before stdout, stderr, or stdin are used.
88 It opens a console window and starts processing */
89static void __kmp_redirect_output(void) {
90 __kmp_acquire_bootstrap_lock(&__kmp_console_lock);
91
92 if (!__kmp_console_exists) {
93#ifdef KMP_DEBUG
94 /* standard out is used only in dev build */
95 HANDLE ho;
96#endif
97 HANDLE he;
98
99 __kmp_str_buf_init(&__kmp_console_buf);
100
101 AllocConsole();
102// We do not check the result of AllocConsole because
103// 1. the call is harmless
104// 2. it is not clear how to communicate failue
105// 3. we will detect failure later when we get handle(s)
106
107#ifdef KMP_DEBUG
108 ho = GetStdHandle(STD_OUTPUT_HANDLE);
109 if (ho == INVALID_HANDLE_VALUE || ho == NULL) {
110
111 DWORD err = GetLastError();
112 // TODO: output error somehow (maybe message box)
113 __kmp_stdout = NULL;
114
115 } else {
116
117 __kmp_stdout = ho; // temporary code, need new global for ho
Jim Cownie5e8470a2013-09-27 10:38:44 +0000118 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000119#endif
120 he = GetStdHandle(STD_ERROR_HANDLE);
121 if (he == INVALID_HANDLE_VALUE || he == NULL) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000122
Jonathan Peyton30419822017-05-12 18:01:32 +0000123 DWORD err = GetLastError();
124 // TODO: output error somehow (maybe message box)
125 __kmp_stderr = NULL;
126
127 } else {
128
129 __kmp_stderr = he; // temporary code, need new global
Jim Cownie5e8470a2013-09-27 10:38:44 +0000130 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000131 __kmp_console_exists = TRUE;
132 }
133 __kmp_release_bootstrap_lock(&__kmp_console_lock);
134}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000135
136#else
Jonathan Peyton30419822017-05-12 18:01:32 +0000137#define __kmp_stderr (stderr)
Jim Cownie5e8470a2013-09-27 10:38:44 +0000138#endif /* KMP_OS_WINDOWS */
139
Jonathan Peyton30419822017-05-12 18:01:32 +0000140void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap) {
141#if KMP_OS_WINDOWS
142 if (!__kmp_console_exists) {
143 __kmp_redirect_output();
144 }
145 if (!__kmp_stderr && __kmp_io == kmp_err) {
146 return;
147 }
148#ifdef KMP_DEBUG
149 if (!__kmp_stdout && __kmp_io == kmp_out) {
150 return;
151 }
152#endif
153#endif /* KMP_OS_WINDOWS */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000154
Jonathan Peyton30419822017-05-12 18:01:32 +0000155 if (__kmp_debug_buf && __kmp_debug_buffer != NULL) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000156
Jonathan Peyton30419822017-05-12 18:01:32 +0000157 int dc = (__kmp_debug_buf_atomic ? KMP_TEST_THEN_INC32(&__kmp_debug_count)
158 : __kmp_debug_count++) %
159 __kmp_debug_buf_lines;
160 char *db = &__kmp_debug_buffer[dc * __kmp_debug_buf_chars];
161 int chars = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000162
Jonathan Peyton30419822017-05-12 18:01:32 +0000163#ifdef KMP_DEBUG_PIDS
164 chars = KMP_SNPRINTF(db, __kmp_debug_buf_chars, "pid=%d: ",
165 (kmp_int32)getpid());
166#endif
167 chars += KMP_VSNPRINTF(db, __kmp_debug_buf_chars, format, ap);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000168
Jonathan Peyton30419822017-05-12 18:01:32 +0000169 if (chars + 1 > __kmp_debug_buf_chars) {
170 if (chars + 1 > __kmp_debug_buf_warn_chars) {
171#if KMP_OS_WINDOWS
172 DWORD count;
173 __kmp_str_buf_print(&__kmp_console_buf, "OMP warning: Debugging buffer "
174 "overflow; increase "
175 "KMP_DEBUG_BUF_CHARS to %d\n",
176 chars + 1);
177 WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used,
178 &count, NULL);
179 __kmp_str_buf_clear(&__kmp_console_buf);
180#else
181 fprintf(__kmp_stderr, "OMP warning: Debugging buffer overflow; "
182 "increase KMP_DEBUG_BUF_CHARS to %d\n",
183 chars + 1);
184 fflush(__kmp_stderr);
185#endif
186 __kmp_debug_buf_warn_chars = chars + 1;
187 }
188 /* terminate string if overflow occurred */
189 db[__kmp_debug_buf_chars - 2] = '\n';
190 db[__kmp_debug_buf_chars - 1] = '\0';
Jim Cownie5e8470a2013-09-27 10:38:44 +0000191 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000192 } else {
193#if KMP_OS_WINDOWS
194 DWORD count;
195#ifdef KMP_DEBUG_PIDS
196 __kmp_str_buf_print(&__kmp_console_buf, "pid=%d: ", (kmp_int32)getpid());
197#endif
198 __kmp_str_buf_vprint(&__kmp_console_buf, format, ap);
199 WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used,
200 &count, NULL);
201 __kmp_str_buf_clear(&__kmp_console_buf);
202#else
203#ifdef KMP_DEBUG_PIDS
204 fprintf(__kmp_stderr, "pid=%d: ", (kmp_int32)getpid());
205#endif
206 vfprintf(__kmp_stderr, format, ap);
207 fflush(__kmp_stderr);
208#endif
209 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000210}
211
Jonathan Peyton30419822017-05-12 18:01:32 +0000212void __kmp_printf(char const *format, ...) {
213 va_list ap;
214 va_start(ap, format);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000215
Jonathan Peyton30419822017-05-12 18:01:32 +0000216 __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
217 __kmp_vprintf(kmp_err, format, ap);
218 __kmp_release_bootstrap_lock(&__kmp_stdio_lock);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000219
Jonathan Peyton30419822017-05-12 18:01:32 +0000220 va_end(ap);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000221}
222
Jonathan Peyton30419822017-05-12 18:01:32 +0000223void __kmp_printf_no_lock(char const *format, ...) {
224 va_list ap;
225 va_start(ap, format);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000226
Jonathan Peyton30419822017-05-12 18:01:32 +0000227 __kmp_vprintf(kmp_err, format, ap);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000228
Jonathan Peyton30419822017-05-12 18:01:32 +0000229 va_end(ap);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000230}