blob: 91ebefe5ed59307eeff0dfad3b284f3ebab39675 [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
Jim Cownie5e8470a2013-09-27 10:38:44 +00005//===----------------------------------------------------------------------===//
6//
7// The LLVM Compiler Infrastructure
8//
9// This file is dual licensed under the MIT and the University of Illinois Open
10// Source Licenses. See LICENSE.txt for details.
11//
12//===----------------------------------------------------------------------===//
13
Jonathan Peyton30419822017-05-12 18:01:32 +000014#include <stdarg.h>
15#include <stddef.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000016#include <stdio.h>
17#include <stdlib.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000018#include <string.h>
19#ifndef __ABSOFT_WIN
Jonathan Peyton30419822017-05-12 18:01:32 +000020#include <sys/types.h>
Jim Cownie5e8470a2013-09-27 10:38:44 +000021#endif
22
Jim Cownie5e8470a2013-09-27 10:38:44 +000023#include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc
Jonathan Peyton30419822017-05-12 18:01:32 +000024#include "kmp_io.h"
25#include "kmp_lock.h"
26#include "kmp_os.h"
27#include "kmp_str.h"
Jim Cownie5e8470a2013-09-27 10:38:44 +000028
29#if KMP_OS_WINDOWS
Jonathan Peyton30419822017-05-12 18:01:32 +000030#pragma warning(push)
31#pragma warning(disable : 271 310)
32#include <windows.h>
33#pragma warning(pop)
Jim Cownie5e8470a2013-09-27 10:38:44 +000034#endif
35
36/* ------------------------------------------------------------------------ */
Jim Cownie5e8470a2013-09-27 10:38:44 +000037
Jonathan Peyton30419822017-05-12 18:01:32 +000038kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
39 __kmp_stdio_lock); /* Control stdio functions */
40kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER(
41 __kmp_console_lock); /* Control console initialization */
Jim Cownie5e8470a2013-09-27 10:38:44 +000042
43#if KMP_OS_WINDOWS
44
Jonathan Peyton30419822017-05-12 18:01:32 +000045#ifdef KMP_DEBUG
46/* __kmp_stdout is used only for dev build */
47static HANDLE __kmp_stdout = NULL;
48#endif
49static HANDLE __kmp_stderr = NULL;
50static int __kmp_console_exists = FALSE;
51static kmp_str_buf_t __kmp_console_buf;
Jim Cownie5e8470a2013-09-27 10:38:44 +000052
Jonathan Peyton30419822017-05-12 18:01:32 +000053static 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 Peytonbd3a7632017-09-27 20:36:27 +000067 }
Jonathan Peyton30419822017-05-12 18:01:32 +000068 return rc > 0 || err == 0;
69}
70
71void __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) {
75#ifdef KMP_DEBUG
76 /* standard out is used only in dev build */
77 __kmp_stdout = NULL;
78#endif
79 __kmp_stderr = NULL;
80 __kmp_str_buf_free(&__kmp_console_buf);
81 __kmp_console_exists = FALSE;
82 }
83}
84
85/* For windows, call this before stdout, stderr, or stdin are used.
86 It opens a console window and starts processing */
87static void __kmp_redirect_output(void) {
88 __kmp_acquire_bootstrap_lock(&__kmp_console_lock);
89
90 if (!__kmp_console_exists) {
91#ifdef KMP_DEBUG
92 /* standard out is used only in dev build */
93 HANDLE ho;
94#endif
95 HANDLE he;
96
97 __kmp_str_buf_init(&__kmp_console_buf);
98
99 AllocConsole();
100// We do not check the result of AllocConsole because
101// 1. the call is harmless
102// 2. it is not clear how to communicate failue
103// 3. we will detect failure later when we get handle(s)
104
105#ifdef KMP_DEBUG
106 ho = GetStdHandle(STD_OUTPUT_HANDLE);
107 if (ho == INVALID_HANDLE_VALUE || ho == NULL) {
108
109 DWORD err = GetLastError();
110 // TODO: output error somehow (maybe message box)
111 __kmp_stdout = NULL;
112
113 } else {
114
115 __kmp_stdout = ho; // temporary code, need new global for ho
Jim Cownie5e8470a2013-09-27 10:38:44 +0000116 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000117#endif
118 he = GetStdHandle(STD_ERROR_HANDLE);
119 if (he == INVALID_HANDLE_VALUE || he == NULL) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000120
Jonathan Peyton30419822017-05-12 18:01:32 +0000121 DWORD err = GetLastError();
122 // TODO: output error somehow (maybe message box)
123 __kmp_stderr = NULL;
124
125 } else {
126
127 __kmp_stderr = he; // temporary code, need new global
Jim Cownie5e8470a2013-09-27 10:38:44 +0000128 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000129 __kmp_console_exists = TRUE;
130 }
131 __kmp_release_bootstrap_lock(&__kmp_console_lock);
132}
Jim Cownie5e8470a2013-09-27 10:38:44 +0000133
134#else
Jonathan Peyton30419822017-05-12 18:01:32 +0000135#define __kmp_stderr (stderr)
Jim Cownie5e8470a2013-09-27 10:38:44 +0000136#endif /* KMP_OS_WINDOWS */
137
Jonathan Peyton30419822017-05-12 18:01:32 +0000138void __kmp_vprintf(enum kmp_io __kmp_io, char const *format, va_list ap) {
139#if KMP_OS_WINDOWS
140 if (!__kmp_console_exists) {
141 __kmp_redirect_output();
142 }
143 if (!__kmp_stderr && __kmp_io == kmp_err) {
144 return;
145 }
146#ifdef KMP_DEBUG
147 if (!__kmp_stdout && __kmp_io == kmp_out) {
148 return;
149 }
150#endif
151#endif /* KMP_OS_WINDOWS */
Jim Cownie5e8470a2013-09-27 10:38:44 +0000152
Jonathan Peyton30419822017-05-12 18:01:32 +0000153 if (__kmp_debug_buf && __kmp_debug_buffer != NULL) {
Jim Cownie5e8470a2013-09-27 10:38:44 +0000154
Jonathan Peyton30419822017-05-12 18:01:32 +0000155 int dc = (__kmp_debug_buf_atomic ? KMP_TEST_THEN_INC32(&__kmp_debug_count)
156 : __kmp_debug_count++) %
157 __kmp_debug_buf_lines;
158 char *db = &__kmp_debug_buffer[dc * __kmp_debug_buf_chars];
159 int chars = 0;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000160
Jonathan Peyton30419822017-05-12 18:01:32 +0000161#ifdef KMP_DEBUG_PIDS
162 chars = KMP_SNPRINTF(db, __kmp_debug_buf_chars, "pid=%d: ",
163 (kmp_int32)getpid());
164#endif
165 chars += KMP_VSNPRINTF(db, __kmp_debug_buf_chars, format, ap);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000166
Jonathan Peyton30419822017-05-12 18:01:32 +0000167 if (chars + 1 > __kmp_debug_buf_chars) {
168 if (chars + 1 > __kmp_debug_buf_warn_chars) {
169#if KMP_OS_WINDOWS
170 DWORD count;
171 __kmp_str_buf_print(&__kmp_console_buf, "OMP warning: Debugging buffer "
172 "overflow; increase "
173 "KMP_DEBUG_BUF_CHARS to %d\n",
174 chars + 1);
175 WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used,
176 &count, NULL);
177 __kmp_str_buf_clear(&__kmp_console_buf);
178#else
179 fprintf(__kmp_stderr, "OMP warning: Debugging buffer overflow; "
180 "increase KMP_DEBUG_BUF_CHARS to %d\n",
181 chars + 1);
182 fflush(__kmp_stderr);
183#endif
184 __kmp_debug_buf_warn_chars = chars + 1;
185 }
186 /* terminate string if overflow occurred */
187 db[__kmp_debug_buf_chars - 2] = '\n';
188 db[__kmp_debug_buf_chars - 1] = '\0';
Jim Cownie5e8470a2013-09-27 10:38:44 +0000189 }
Jonathan Peyton30419822017-05-12 18:01:32 +0000190 } else {
191#if KMP_OS_WINDOWS
192 DWORD count;
193#ifdef KMP_DEBUG_PIDS
194 __kmp_str_buf_print(&__kmp_console_buf, "pid=%d: ", (kmp_int32)getpid());
195#endif
196 __kmp_str_buf_vprint(&__kmp_console_buf, format, ap);
197 WriteFile(__kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used,
198 &count, NULL);
199 __kmp_str_buf_clear(&__kmp_console_buf);
200#else
201#ifdef KMP_DEBUG_PIDS
202 fprintf(__kmp_stderr, "pid=%d: ", (kmp_int32)getpid());
203#endif
204 vfprintf(__kmp_stderr, format, ap);
205 fflush(__kmp_stderr);
206#endif
207 }
Jim Cownie5e8470a2013-09-27 10:38:44 +0000208}
209
Jonathan Peyton30419822017-05-12 18:01:32 +0000210void __kmp_printf(char const *format, ...) {
211 va_list ap;
212 va_start(ap, format);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000213
Jonathan Peyton30419822017-05-12 18:01:32 +0000214 __kmp_acquire_bootstrap_lock(&__kmp_stdio_lock);
215 __kmp_vprintf(kmp_err, format, ap);
216 __kmp_release_bootstrap_lock(&__kmp_stdio_lock);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000217
Jonathan Peyton30419822017-05-12 18:01:32 +0000218 va_end(ap);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000219}
220
Jonathan Peyton30419822017-05-12 18:01:32 +0000221void __kmp_printf_no_lock(char const *format, ...) {
222 va_list ap;
223 va_start(ap, format);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000224
Jonathan Peyton30419822017-05-12 18:01:32 +0000225 __kmp_vprintf(kmp_err, format, ap);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000226
Jonathan Peyton30419822017-05-12 18:01:32 +0000227 va_end(ap);
Jim Cownie5e8470a2013-09-27 10:38:44 +0000228}