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