kmp_io.c

Go to the documentation of this file.
00001 /*
00002  * kmp_io.c -- RTL IO
00003  * $Revision: 42150 $
00004  * $Date: 2013-03-15 15:40:38 -0500 (Fri, 15 Mar 2013) $
00005  */
00006 
00007 /* <copyright>
00008     Copyright (c) 1997-2013 Intel Corporation.  All Rights Reserved.
00009 
00010     Redistribution and use in source and binary forms, with or without
00011     modification, are permitted provided that the following conditions
00012     are met:
00013 
00014       * Redistributions of source code must retain the above copyright
00015         notice, this list of conditions and the following disclaimer.
00016       * Redistributions in binary form must reproduce the above copyright
00017         notice, this list of conditions and the following disclaimer in the
00018         documentation and/or other materials provided with the distribution.
00019       * Neither the name of Intel Corporation nor the names of its
00020         contributors may be used to endorse or promote products derived
00021         from this software without specific prior written permission.
00022 
00023     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 
00035 
00036 ------------------------------------------------------------------------
00037 
00038     Portions of this software are protected under the following patents:
00039         U.S. Patent 5,812,852
00040         U.S. Patent 6,792,599
00041         U.S. Patent 7,069,556
00042         U.S. Patent 7,328,433
00043         U.S. Patent 7,500,242
00044 
00045 </copyright> */
00046 
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include <stddef.h>
00050 #include <stdarg.h>
00051 #include <string.h>
00052 #ifndef __ABSOFT_WIN
00053 # include <sys/types.h>
00054 #endif
00055 
00056 #include "kmp_os.h"
00057 #include "kmp_lock.h"
00058 #include "kmp_str.h"
00059 #include "kmp_io.h"
00060 #include "kmp.h" // KMP_GTID_DNE, __kmp_debug_buf, etc
00061 
00062 #if KMP_OS_WINDOWS
00063 # pragma warning( push )
00064 # pragma warning( disable: 271 310 )
00065 # include <windows.h>
00066 # pragma warning( pop )
00067 #endif
00068 
00069 /* ------------------------------------------------------------------------ */
00070 /* ------------------------------------------------------------------------ */
00071 
00072 kmp_bootstrap_lock_t __kmp_stdio_lock   = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_stdio_lock   ); /* Control stdio functions */
00073 kmp_bootstrap_lock_t __kmp_console_lock = KMP_BOOTSTRAP_LOCK_INITIALIZER( __kmp_console_lock ); /* Control console initialization */
00074 
00075 #if KMP_OS_WINDOWS
00076 
00077     # ifdef KMP_DEBUG 
00078     /* __kmp_stdout is used only for dev build */
00079     static HANDLE    __kmp_stdout = NULL;
00080     # endif
00081     static HANDLE        __kmp_stderr = NULL;
00082     static int           __kmp_console_exists = FALSE;
00083     static kmp_str_buf_t __kmp_console_buf;
00084 
00085     static int
00086     is_console( void )
00087     {
00088         char buffer[ 128 ];
00089         DWORD rc  = 0;
00090         DWORD err = 0;
00091         // Try to get console title.
00092         SetLastError( 0 );
00093             // GetConsoleTitle does not reset last error in case of success or short buffer,
00094             // so we need to clear it explicitly.
00095         rc = GetConsoleTitle( buffer, sizeof( buffer ) );
00096         if ( rc == 0 ) {
00097             // rc == 0 means getting console title failed. Let us find out why.
00098             err = GetLastError();
00099             // err == 0 means buffer too short (we suppose console exists).
00100             // In Window applications we usually have err == 6 (invalid handle).
00101         }; // if
00102         return rc > 0 || err == 0;
00103     }
00104 
00105     void
00106     __kmp_close_console( void )
00107     {
00108         /* wait until user presses return before closing window */
00109         /* TODO only close if a window was opened */
00110         if( __kmp_console_exists ) {
00111             #ifdef KMP_DEBUG 
00112             /* standard out is used only in dev build */
00113             __kmp_stdout = NULL;
00114             #endif
00115             __kmp_stderr = NULL;
00116             __kmp_str_buf_free( &__kmp_console_buf );
00117             __kmp_console_exists = FALSE;
00118         }
00119     }
00120 
00121     /* For windows, call this before stdout, stderr, or stdin are used.
00122      * It opens a console window and starts processing */
00123     static void
00124     __kmp_redirect_output( void )
00125     {
00126         __kmp_acquire_bootstrap_lock( &__kmp_console_lock );
00127 
00128         if( ! __kmp_console_exists ) {
00129             #ifdef KMP_DEBUG 
00130             /* standard out is used only in dev build */
00131             HANDLE ho;
00132             #endif
00133             HANDLE he;
00134 
00135             __kmp_str_buf_init( &__kmp_console_buf );
00136 
00137             AllocConsole();
00138             // We do not check the result of AllocConsole because
00139             //  1. the call is harmless
00140             //  2. it is not clear how to communicate failue
00141             //  3. we will detect failure later when we get handle(s)
00142 
00143             #ifdef KMP_DEBUG
00144                 ho = GetStdHandle( STD_OUTPUT_HANDLE );
00145                 if ( ho == INVALID_HANDLE_VALUE || ho == NULL ) {
00146 
00147                     DWORD  err = GetLastError();
00148                     // TODO: output error somehow (maybe message box)
00149                     __kmp_stdout = NULL;
00150 
00151                 } else {
00152 
00153                     __kmp_stdout = ho; // temporary code, need new global for ho
00154 
00155                 }
00156             #endif
00157             he = GetStdHandle( STD_ERROR_HANDLE );
00158             if ( he == INVALID_HANDLE_VALUE || he == NULL ) {
00159 
00160                 DWORD  err = GetLastError();
00161                 // TODO: output error somehow (maybe message box)
00162                 __kmp_stderr = NULL;
00163 
00164             } else {
00165 
00166                 __kmp_stderr = he; // temporary code, need new global
00167             }
00168             __kmp_console_exists = TRUE;
00169         }
00170         __kmp_release_bootstrap_lock( &__kmp_console_lock );
00171     }
00172 
00173 #else
00174     #define       __kmp_stderr     (stderr)
00175 #endif /* KMP_OS_WINDOWS */
00176 
00177 void
00178 __kmp_vprintf( enum kmp_io __kmp_io, char const * format, va_list ap )
00179 {
00180     #if KMP_OS_WINDOWS
00181         if( !__kmp_console_exists ) {
00182             __kmp_redirect_output();
00183         }
00184             if( ! __kmp_stderr && __kmp_io == kmp_err ) {
00185             return;
00186         }
00187         #ifdef KMP_DEBUG
00188             if( ! __kmp_stdout && __kmp_io == kmp_out ) {
00189                 return;
00190             }
00191         #endif
00192     #endif /* KMP_OS_WINDOWS */
00193 
00194     if ( __kmp_debug_buf && __kmp_debug_buffer != NULL ) {
00195 
00196         int dc = ( __kmp_debug_buf_atomic ?
00197                    KMP_TEST_THEN_INC32( & __kmp_debug_count) : __kmp_debug_count++ )
00198                    % __kmp_debug_buf_lines;
00199         char *db = & __kmp_debug_buffer[ dc * __kmp_debug_buf_chars ];
00200         int chars = 0;
00201 
00202         #ifdef KMP_DEBUG_PIDS
00203             chars = sprintf( db, "pid=%d: ", getpid() );
00204         #endif
00205         chars += vsprintf( db, format, ap );
00206 
00207         if ( chars + 1 > __kmp_debug_buf_chars ) {
00208             if ( chars + 1 > __kmp_debug_buf_warn_chars ) {
00209                 #if KMP_OS_WINDOWS
00210                     DWORD count;
00211                     __kmp_str_buf_print( &__kmp_console_buf,
00212                         "OMP warning: Debugging buffer overflow; increase KMP_DEBUG_BUF_CHARS to %d\n",
00213                         chars + 1 );
00214                     WriteFile( __kmp_stderr, __kmp_console_buf.str, __kmp_console_buf.used, &count, NULL );
00215                     __kmp_str_buf_clear( &__kmp_console_buf );
00216                 #else
00217                     fprintf( __kmp_stderr,
00218                          "OMP warning: Debugging buffer overflow; increase KMP_DEBUG_BUF_CHARS to %d\n",
00219                          chars + 1 );
00220                     fflush( __kmp_stderr );
00221                 #endif
00222                 __kmp_debug_buf_warn_chars = chars + 1;
00223             }
00224             /* terminate string if overflow occurred */
00225             db[ __kmp_debug_buf_chars - 2 ] = '\n';
00226             db[ __kmp_debug_buf_chars - 1 ] = '\0';
00227         }
00228     } else {
00229         #if KMP_OS_WINDOWS
00230             DWORD count;
00231             #ifdef KMP_DEBUG_PIDS
00232                 __kmp_str_buf_print( &__kmp_console_buf, "pid=%d: ", getpid() );
00233             #endif
00234             __kmp_str_buf_vprint( &__kmp_console_buf, format, ap );
00235             WriteFile(
00236                 __kmp_stderr,
00237                 __kmp_console_buf.str,
00238                 __kmp_console_buf.used,
00239                 &count,
00240                 NULL
00241             );
00242             __kmp_str_buf_clear( &__kmp_console_buf );
00243         #else
00244             #ifdef KMP_DEBUG_PIDS
00245                 fprintf( __kmp_stderr, "pid=%d: ", getpid() );
00246             #endif
00247             vfprintf( __kmp_stderr, format, ap );
00248             fflush( __kmp_stderr );
00249         #endif
00250     }
00251 }
00252 
00253 void
00254 __kmp_printf( char const * format, ... )
00255 {
00256     va_list ap;
00257     va_start( ap, format );
00258 
00259     __kmp_acquire_bootstrap_lock( & __kmp_stdio_lock );
00260     __kmp_vprintf( kmp_err, format, ap );
00261     __kmp_release_bootstrap_lock( & __kmp_stdio_lock );
00262 
00263     va_end( ap );
00264 }
00265 
00266 void
00267 __kmp_printf_no_lock( char const * format, ... )
00268 {
00269     va_list ap;
00270     va_start( ap, format );
00271 
00272     __kmp_vprintf( kmp_err, format, ap );
00273 
00274     va_end( ap );
00275 }
00276 
00277 /* ------------------------------------------------------------------------ */
00278 /* ------------------------------------------------------------------------ */

Generated on 25 Aug 2013 for libomp_oss by  doxygen 1.6.1