17cc577a4SJonathan Peyton /* 2*de4749b7SJonathan Peyton * kmp_io.cpp -- RTL IO 37cc577a4SJonathan Peyton */ 47cc577a4SJonathan Peyton 57cc577a4SJonathan Peyton 67cc577a4SJonathan Peyton //===----------------------------------------------------------------------===// 77cc577a4SJonathan Peyton // 87cc577a4SJonathan Peyton // The LLVM Compiler Infrastructure 97cc577a4SJonathan Peyton // 107cc577a4SJonathan Peyton // This file is dual licensed under the MIT and the University of Illinois Open 117cc577a4SJonathan Peyton // Source Licenses. See LICENSE.txt for details. 127cc577a4SJonathan Peyton // 137cc577a4SJonathan Peyton //===----------------------------------------------------------------------===// 147cc577a4SJonathan Peyton 157cc577a4SJonathan Peyton 167cc577a4SJonathan Peyton #include <stdio.h> 177cc577a4SJonathan Peyton #include <stdlib.h> 187cc577a4SJonathan Peyton #include <stddef.h> 197cc577a4SJonathan Peyton #include <stdarg.h> 207cc577a4SJonathan Peyton #include <string.h> 217cc577a4SJonathan Peyton #ifndef __ABSOFT_WIN 227cc577a4SJonathan Peyton # include <sys/types.h> 237cc577a4SJonathan Peyton #endif 247cc577a4SJonathan Peyton 257cc577a4SJonathan Peyton #include "kmp_os.h" 267cc577a4SJonathan Peyton #include "kmp_lock.h" 277cc577a4SJonathan Peyton #include "kmp_str.h" 287cc577a4SJonathan Peyton #include "kmp_io.h" 297cc577a4SJonathan Peyton #include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc 307cc577a4SJonathan Peyton 317cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 327cc577a4SJonathan Peyton # pragma warning( push ) 337cc577a4SJonathan Peyton # pragma warning( disable: 271 310 ) 347cc577a4SJonathan Peyton # include <windows.h> 357cc577a4SJonathan Peyton # pragma warning( pop ) 367cc577a4SJonathan Peyton #endif 377cc577a4SJonathan Peyton 387cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */ 397cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */ 407cc577a4SJonathan Peyton 417cc577a4SJonathan Peyton kmp_bootstrap_lock_t __kmp_stdio_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_stdio_lock ); /* Control stdio functions */ 427cc577a4SJonathan Peyton kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_console_lock ); /* Control console initialization */ 437cc577a4SJonathan Peyton 447cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 457cc577a4SJonathan Peyton 467cc577a4SJonathan Peyton # ifdef KMP_DEBUG 477cc577a4SJonathan Peyton /* __kmp_stdout is used only for dev build */ 487cc577a4SJonathan Peyton static HANDLE __kmp_stdout = NULL; 497cc577a4SJonathan Peyton # endif 507cc577a4SJonathan Peyton static HANDLE __kmp_stderr = NULL; 517cc577a4SJonathan Peyton static int __kmp_console_exists = FALSE; 527cc577a4SJonathan Peyton static kmp_str_buf_t __kmp_console_buf; 537cc577a4SJonathan Peyton 547cc577a4SJonathan Peyton static int 557cc577a4SJonathan Peyton is_console( void ) 567cc577a4SJonathan Peyton { 577cc577a4SJonathan Peyton char buffer[ 128 ]; 587cc577a4SJonathan Peyton DWORD rc = 0; 597cc577a4SJonathan Peyton DWORD err = 0; 607cc577a4SJonathan Peyton // Try to get console title. 617cc577a4SJonathan Peyton SetLastError( 0 ); 627cc577a4SJonathan Peyton // GetConsoleTitle does not reset last error in case of success or short buffer, 637cc577a4SJonathan Peyton // so we need to clear it explicitly. 647cc577a4SJonathan Peyton rc = GetConsoleTitle( buffer, sizeof( buffer ) ); 657cc577a4SJonathan Peyton if ( rc == 0 ) { 667cc577a4SJonathan Peyton // rc == 0 means getting console title failed. Let us find out why. 677cc577a4SJonathan Peyton err = GetLastError(); 687cc577a4SJonathan Peyton // err == 0 means buffer too short (we suppose console exists). 697cc577a4SJonathan Peyton // In Window applications we usually have err == 6 (invalid handle). 707cc577a4SJonathan Peyton }; // if 717cc577a4SJonathan Peyton return rc > 0 || err == 0; 727cc577a4SJonathan Peyton } 737cc577a4SJonathan Peyton 747cc577a4SJonathan Peyton void 757cc577a4SJonathan Peyton __kmp_close_console( void ) 767cc577a4SJonathan Peyton { 777cc577a4SJonathan Peyton /* wait until user presses return before closing window */ 787cc577a4SJonathan Peyton /* TODO only close if a window was opened */ 797cc577a4SJonathan Peyton if( __kmp_console_exists ) { 807cc577a4SJonathan Peyton #ifdef KMP_DEBUG 817cc577a4SJonathan Peyton /* standard out is used only in dev build */ 827cc577a4SJonathan Peyton __kmp_stdout = NULL; 837cc577a4SJonathan Peyton #endif 847cc577a4SJonathan Peyton __kmp_stderr = NULL; 857cc577a4SJonathan Peyton __kmp_str_buf_free( &__kmp_console_buf ); 867cc577a4SJonathan Peyton __kmp_console_exists = FALSE; 877cc577a4SJonathan Peyton } 887cc577a4SJonathan Peyton } 897cc577a4SJonathan Peyton 907cc577a4SJonathan Peyton /* For windows, call this before stdout, stderr, or stdin are used. 917cc577a4SJonathan Peyton * It opens a console window and starts processing */ 927cc577a4SJonathan Peyton static void 937cc577a4SJonathan Peyton __kmp_redirect_output( void ) 947cc577a4SJonathan Peyton { 957cc577a4SJonathan Peyton __kmp_acquire_bootstrap_lock( &__kmp_console_lock ); 967cc577a4SJonathan Peyton 977cc577a4SJonathan Peyton if( ! __kmp_console_exists ) { 987cc577a4SJonathan Peyton #ifdef KMP_DEBUG 997cc577a4SJonathan Peyton /* standard out is used only in dev build */ 1007cc577a4SJonathan Peyton HANDLE ho; 1017cc577a4SJonathan Peyton #endif 1027cc577a4SJonathan Peyton HANDLE he; 1037cc577a4SJonathan Peyton 1047cc577a4SJonathan Peyton __kmp_str_buf_init( &__kmp_console_buf ); 1057cc577a4SJonathan Peyton 1067cc577a4SJonathan Peyton AllocConsole(); 1077cc577a4SJonathan Peyton // We do not check the result of AllocConsole because 1087cc577a4SJonathan Peyton // 1. the call is harmless 1097cc577a4SJonathan Peyton // 2. it is not clear how to communicate failue 1107cc577a4SJonathan Peyton // 3. we will detect failure later when we get handle(s) 1117cc577a4SJonathan Peyton 1127cc577a4SJonathan Peyton #ifdef KMP_DEBUG 1137cc577a4SJonathan Peyton ho = GetStdHandle( STD_OUTPUT_HANDLE ); 1147cc577a4SJonathan Peyton if ( ho == INVALID_HANDLE_VALUE || ho == NULL ) { 1157cc577a4SJonathan Peyton 1167cc577a4SJonathan Peyton DWORD err = GetLastError(); 1177cc577a4SJonathan Peyton // TODO: output error somehow (maybe message box) 1187cc577a4SJonathan Peyton __kmp_stdout = NULL; 1197cc577a4SJonathan Peyton 1207cc577a4SJonathan Peyton } else { 1217cc577a4SJonathan Peyton 1227cc577a4SJonathan Peyton __kmp_stdout = ho; // temporary code, need new global for ho 1237cc577a4SJonathan Peyton 1247cc577a4SJonathan Peyton } 1257cc577a4SJonathan Peyton #endif 1267cc577a4SJonathan Peyton he = GetStdHandle( STD_ERROR_HANDLE ); 1277cc577a4SJonathan Peyton if ( he == INVALID_HANDLE_VALUE || he == NULL ) { 1287cc577a4SJonathan Peyton 1297cc577a4SJonathan Peyton DWORD err = GetLastError(); 1307cc577a4SJonathan Peyton // TODO: output error somehow (maybe message box) 1317cc577a4SJonathan Peyton __kmp_stderr = NULL; 1327cc577a4SJonathan Peyton 1337cc577a4SJonathan Peyton } else { 1347cc577a4SJonathan Peyton 1357cc577a4SJonathan Peyton __kmp_stderr = he; // temporary code, need new global 1367cc577a4SJonathan Peyton } 1377cc577a4SJonathan Peyton __kmp_console_exists = TRUE; 1387cc577a4SJonathan Peyton } 1397cc577a4SJonathan Peyton __kmp_release_bootstrap_lock( &__kmp_console_lock ); 1407cc577a4SJonathan Peyton } 1417cc577a4SJonathan Peyton 1427cc577a4SJonathan Peyton #else 1437cc577a4SJonathan Peyton #define __kmp_stderr (stderr) 1447cc577a4SJonathan Peyton #endif /* KMP_OS_WINDOWS */ 1457cc577a4SJonathan Peyton 1467cc577a4SJonathan Peyton void 1477cc577a4SJonathan Peyton __kmp_vprintf( enum kmp_io __kmp_io, char const * format, va_list ap ) 1487cc577a4SJonathan Peyton { 1497cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1507cc577a4SJonathan Peyton if( !__kmp_console_exists ) { 1517cc577a4SJonathan Peyton __kmp_redirect_output(); 1527cc577a4SJonathan Peyton } 1537cc577a4SJonathan Peyton if( ! __kmp_stderr && __kmp_io == kmp_err ) { 1547cc577a4SJonathan Peyton return; 1557cc577a4SJonathan Peyton } 1567cc577a4SJonathan Peyton #ifdef KMP_DEBUG 1577cc577a4SJonathan Peyton if( ! __kmp_stdout && __kmp_io == kmp_out ) { 1587cc577a4SJonathan Peyton return; 1597cc577a4SJonathan Peyton } 1607cc577a4SJonathan Peyton #endif 1617cc577a4SJonathan Peyton #endif /* KMP_OS_WINDOWS */ 1627cc577a4SJonathan Peyton 1637cc577a4SJonathan Peyton if ( __kmp_debug_buf && __kmp_debug_buffer != NULL ) { 1647cc577a4SJonathan Peyton 1657cc577a4SJonathan Peyton int dc = ( __kmp_debug_buf_atomic ? 1667cc577a4SJonathan Peyton KMP_TEST_THEN_INC32( & __kmp_debug_count) : __kmp_debug_count++ ) 1677cc577a4SJonathan Peyton % __kmp_debug_buf_lines; 1687cc577a4SJonathan Peyton char *db = & __kmp_debug_buffer[ dc * __kmp_debug_buf_chars ]; 1697cc577a4SJonathan Peyton int chars = 0; 1707cc577a4SJonathan Peyton 1717cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 1727cc577a4SJonathan Peyton chars = KMP_SNPRINTF( db, __kmp_debug_buf_chars, "pid=%d: ", (kmp_int32)getpid() ); 1737cc577a4SJonathan Peyton #endif 1747cc577a4SJonathan Peyton chars += KMP_VSNPRINTF( db, __kmp_debug_buf_chars, format, ap ); 1757cc577a4SJonathan Peyton 1767cc577a4SJonathan Peyton if ( chars + 1 > __kmp_debug_buf_chars ) { 1777cc577a4SJonathan Peyton if ( chars + 1 > __kmp_debug_buf_warn_chars ) { 1787cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1797cc577a4SJonathan Peyton DWORD count; 1807cc577a4SJonathan Peyton __kmp_str_buf_print( &__kmp_console_buf, 1817cc577a4SJonathan Peyton "OMP warning: Debugging buffer overflow; increase KMP_DEBUG_BUF_CHARS to %d\n", 1827cc577a4SJonathan Peyton chars + 1 ); 1837cc577a4SJonathan Peyton WriteFile( __kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used, &count, NULL ); 1847cc577a4SJonathan Peyton __kmp_str_buf_clear( &__kmp_console_buf ); 1857cc577a4SJonathan Peyton #else 1867cc577a4SJonathan Peyton fprintf( __kmp_stderr, 1877cc577a4SJonathan Peyton "OMP warning: Debugging buffer overflow; increase KMP_DEBUG_BUF_CHARS to %d\n", 1887cc577a4SJonathan Peyton chars + 1 ); 1897cc577a4SJonathan Peyton fflush( __kmp_stderr ); 1907cc577a4SJonathan Peyton #endif 1917cc577a4SJonathan Peyton __kmp_debug_buf_warn_chars = chars + 1; 1927cc577a4SJonathan Peyton } 1937cc577a4SJonathan Peyton /* terminate string if overflow occurred */ 1947cc577a4SJonathan Peyton db[ __kmp_debug_buf_chars - 2 ] = '\n'; 1957cc577a4SJonathan Peyton db[ __kmp_debug_buf_chars - 1 ] = '\0'; 1967cc577a4SJonathan Peyton } 1977cc577a4SJonathan Peyton } else { 1987cc577a4SJonathan Peyton #if KMP_OS_WINDOWS 1997cc577a4SJonathan Peyton DWORD count; 2007cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 2017cc577a4SJonathan Peyton __kmp_str_buf_print( &__kmp_console_buf, "pid=%d: ", 2027cc577a4SJonathan Peyton (kmp_int32)getpid() ); 2037cc577a4SJonathan Peyton #endif 2047cc577a4SJonathan Peyton __kmp_str_buf_vprint( &__kmp_console_buf, format, ap ); 2057cc577a4SJonathan Peyton WriteFile( 2067cc577a4SJonathan Peyton __kmp_stderr, 2077cc577a4SJonathan Peyton __kmp_console_buf.str, 2087cc577a4SJonathan Peyton __kmp_console_buf.used, 2097cc577a4SJonathan Peyton &count, 2107cc577a4SJonathan Peyton NULL 2117cc577a4SJonathan Peyton ); 2127cc577a4SJonathan Peyton __kmp_str_buf_clear( &__kmp_console_buf ); 2137cc577a4SJonathan Peyton #else 2147cc577a4SJonathan Peyton #ifdef KMP_DEBUG_PIDS 2157cc577a4SJonathan Peyton fprintf( __kmp_stderr, "pid=%d: ", (kmp_int32)getpid() ); 2167cc577a4SJonathan Peyton #endif 2177cc577a4SJonathan Peyton vfprintf( __kmp_stderr, format, ap ); 2187cc577a4SJonathan Peyton fflush( __kmp_stderr ); 2197cc577a4SJonathan Peyton #endif 2207cc577a4SJonathan Peyton } 2217cc577a4SJonathan Peyton } 2227cc577a4SJonathan Peyton 2237cc577a4SJonathan Peyton void 2247cc577a4SJonathan Peyton __kmp_printf( char const * format, ... ) 2257cc577a4SJonathan Peyton { 2267cc577a4SJonathan Peyton va_list ap; 2277cc577a4SJonathan Peyton va_start( ap, format ); 2287cc577a4SJonathan Peyton 2297cc577a4SJonathan Peyton __kmp_acquire_bootstrap_lock( & __kmp_stdio_lock ); 2307cc577a4SJonathan Peyton __kmp_vprintf( kmp_err, format, ap ); 2317cc577a4SJonathan Peyton __kmp_release_bootstrap_lock( & __kmp_stdio_lock ); 2327cc577a4SJonathan Peyton 2337cc577a4SJonathan Peyton va_end( ap ); 2347cc577a4SJonathan Peyton } 2357cc577a4SJonathan Peyton 2367cc577a4SJonathan Peyton void 2377cc577a4SJonathan Peyton __kmp_printf_no_lock( char const * format, ... ) 2387cc577a4SJonathan Peyton { 2397cc577a4SJonathan Peyton va_list ap; 2407cc577a4SJonathan Peyton va_start( ap, format ); 2417cc577a4SJonathan Peyton 2427cc577a4SJonathan Peyton __kmp_vprintf( kmp_err, format, ap ); 2437cc577a4SJonathan Peyton 2447cc577a4SJonathan Peyton va_end( ap ); 2457cc577a4SJonathan Peyton } 2467cc577a4SJonathan Peyton 2477cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */ 2487cc577a4SJonathan Peyton /* ------------------------------------------------------------------------ */ 249