src/share/vm/utilities/ostream.cpp

Thu, 02 Aug 2018 03:54:51 -0700

author
kevinw
date
Thu, 02 Aug 2018 03:54:51 -0700
changeset 9478
f3108e56b502
parent 9327
f96fcd9e1e1b
child 9572
624a0741915c
child 9904
4698900b8221
permissions
-rw-r--r--

8196882: VS2017 Hotspot Defined vsnprintf Function Causes C2084 Already Defined Compilation Error
Summary: Add os::vsnprintf and os::snprintf.
Reviewed-by: kbarrett, lfoltan, stuefe, mlarsson

     1 /*
     2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "compiler/compileLog.hpp"
    27 #include "gc_implementation/shared/gcId.hpp"
    28 #include "oops/oop.inline.hpp"
    29 #include "runtime/arguments.hpp"
    30 #include "runtime/os.hpp"
    31 #include "utilities/defaultStream.hpp"
    32 #include "utilities/ostream.hpp"
    33 #include "utilities/top.hpp"
    34 #include "utilities/xmlstream.hpp"
    35 #ifdef TARGET_OS_FAMILY_linux
    36 # include "os_linux.inline.hpp"
    37 #endif
    38 #ifdef TARGET_OS_FAMILY_solaris
    39 # include "os_solaris.inline.hpp"
    40 #endif
    41 #ifdef TARGET_OS_FAMILY_windows
    42 # include "os_windows.inline.hpp"
    43 #endif
    44 #ifdef TARGET_OS_FAMILY_aix
    45 # include "os_aix.inline.hpp"
    46 #endif
    47 #ifdef TARGET_OS_FAMILY_bsd
    48 # include "os_bsd.inline.hpp"
    49 #endif
    51 extern "C" void jio_print(const char* s); // Declarationtion of jvm method
    53 outputStream::outputStream(int width) {
    54   _width       = width;
    55   _position    = 0;
    56   _newlines    = 0;
    57   _precount    = 0;
    58   _indentation = 0;
    59 }
    61 outputStream::outputStream(int width, bool has_time_stamps) {
    62   _width       = width;
    63   _position    = 0;
    64   _newlines    = 0;
    65   _precount    = 0;
    66   _indentation = 0;
    67   if (has_time_stamps)  _stamp.update();
    68 }
    70 void outputStream::update_position(const char* s, size_t len) {
    71   for (size_t i = 0; i < len; i++) {
    72     char ch = s[i];
    73     if (ch == '\n') {
    74       _newlines += 1;
    75       _precount += _position + 1;
    76       _position = 0;
    77     } else if (ch == '\t') {
    78       int tw = 8 - (_position & 7);
    79       _position += tw;
    80       _precount -= tw-1;  // invariant:  _precount + _position == total count
    81     } else {
    82       _position += 1;
    83     }
    84   }
    85 }
    87 // Execute a vsprintf, using the given buffer if necessary.
    88 // Return a pointer to the formatted string.
    89 const char* outputStream::do_vsnprintf(char* buffer, size_t buflen,
    90                                        const char* format, va_list ap,
    91                                        bool add_cr,
    92                                        size_t& result_len) {
    93   assert(buflen >= 2, "buffer too small");
    95   const char* result;
    96   if (add_cr)  buflen--;
    97   if (!strchr(format, '%')) {
    98     // constant format string
    99     result = format;
   100     result_len = strlen(result);
   101     if (add_cr && result_len >= buflen)  result_len = buflen-1;  // truncate
   102   } else if (format[0] == '%' && format[1] == 's' && format[2] == '\0') {
   103     // trivial copy-through format string
   104     result = va_arg(ap, const char*);
   105     result_len = strlen(result);
   106     if (add_cr && result_len >= buflen)  result_len = buflen-1;  // truncate
   107   } else {
   108     int written = os::vsnprintf(buffer, buflen, format, ap);
   109     assert(written >= 0, "vsnprintf encoding error");
   110     result = buffer;
   111     if ((size_t)written < buflen) {
   112       result_len = written;
   113     } else {
   114       DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
   115       result_len = buflen - 1;
   116     }
   117   }
   118   if (add_cr) {
   119     if (result != buffer) {
   120       memcpy(buffer, result, result_len);
   121       result = buffer;
   122     }
   123     buffer[result_len++] = '\n';
   124     buffer[result_len] = 0;
   125   }
   126   return result;
   127 }
   129 void outputStream::print(const char* format, ...) {
   130   char buffer[O_BUFLEN];
   131   va_list ap;
   132   va_start(ap, format);
   133   size_t len;
   134   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, false, len);
   135   write(str, len);
   136   va_end(ap);
   137 }
   139 void outputStream::print_cr(const char* format, ...) {
   140   char buffer[O_BUFLEN];
   141   va_list ap;
   142   va_start(ap, format);
   143   size_t len;
   144   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, true, len);
   145   write(str, len);
   146   va_end(ap);
   147 }
   149 void outputStream::vprint(const char *format, va_list argptr) {
   150   char buffer[O_BUFLEN];
   151   size_t len;
   152   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, false, len);
   153   write(str, len);
   154 }
   156 void outputStream::vprint_cr(const char* format, va_list argptr) {
   157   char buffer[O_BUFLEN];
   158   size_t len;
   159   const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, true, len);
   160   write(str, len);
   161 }
   163 void outputStream::fill_to(int col) {
   164   int need_fill = col - position();
   165   sp(need_fill);
   166 }
   168 void outputStream::move_to(int col, int slop, int min_space) {
   169   if (position() >= col + slop)
   170     cr();
   171   int need_fill = col - position();
   172   if (need_fill < min_space)
   173     need_fill = min_space;
   174   sp(need_fill);
   175 }
   177 void outputStream::put(char ch) {
   178   assert(ch != 0, "please fix call site");
   179   char buf[] = { ch, '\0' };
   180   write(buf, 1);
   181 }
   183 #define SP_USE_TABS false
   185 void outputStream::sp(int count) {
   186   if (count < 0)  return;
   187   if (SP_USE_TABS && count >= 8) {
   188     int target = position() + count;
   189     while (count >= 8) {
   190       this->write("\t", 1);
   191       count -= 8;
   192     }
   193     count = target - position();
   194   }
   195   while (count > 0) {
   196     int nw = (count > 8) ? 8 : count;
   197     this->write("        ", nw);
   198     count -= nw;
   199   }
   200 }
   202 void outputStream::cr() {
   203   this->write("\n", 1);
   204 }
   206 void outputStream::stamp() {
   207   if (! _stamp.is_updated()) {
   208     _stamp.update(); // start at 0 on first call to stamp()
   209   }
   211   // outputStream::stamp() may get called by ostream_abort(), use snprintf
   212   // to avoid allocating large stack buffer in print().
   213   char buf[40];
   214   jio_snprintf(buf, sizeof(buf), "%.3f", _stamp.seconds());
   215   print_raw(buf);
   216 }
   218 void outputStream::stamp(bool guard,
   219                          const char* prefix,
   220                          const char* suffix) {
   221   if (!guard) {
   222     return;
   223   }
   224   print_raw(prefix);
   225   stamp();
   226   print_raw(suffix);
   227 }
   229 void outputStream::date_stamp(bool guard,
   230                               const char* prefix,
   231                               const char* suffix) {
   232   if (!guard) {
   233     return;
   234   }
   235   print_raw(prefix);
   236   static const char error_time[] = "yyyy-mm-ddThh:mm:ss.mmm+zzzz";
   237   static const int buffer_length = 32;
   238   char buffer[buffer_length];
   239   const char* iso8601_result = os::iso8601_time(buffer, buffer_length);
   240   if (iso8601_result != NULL) {
   241     print_raw(buffer);
   242   } else {
   243     print_raw(error_time);
   244   }
   245   print_raw(suffix);
   246   return;
   247 }
   249 void outputStream::gclog_stamp(const GCId& gc_id) {
   250   date_stamp(PrintGCDateStamps);
   251   stamp(PrintGCTimeStamps);
   252   if (PrintGCID) {
   253     print("#%u: ", gc_id.id());
   254   }
   255 }
   257 outputStream& outputStream::indent() {
   258   while (_position < _indentation) sp();
   259   return *this;
   260 }
   262 void outputStream::print_jlong(jlong value) {
   263   print(JLONG_FORMAT, value);
   264 }
   266 void outputStream::print_julong(julong value) {
   267   print(JULONG_FORMAT, value);
   268 }
   270 /**
   271  * This prints out hex data in a 'windbg' or 'xxd' form, where each line is:
   272  *   <hex-address>: 8 * <hex-halfword> <ascii translation (optional)>
   273  * example:
   274  * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000  .DOF............
   275  * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005  .......@... ....
   276  * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d  .......@.......]
   277  * ...
   278  *
   279  * indent is applied to each line.  Ends with a CR.
   280  */
   281 void outputStream::print_data(void* data, size_t len, bool with_ascii) {
   282   size_t limit = (len + 16) / 16 * 16;
   283   for (size_t i = 0; i < limit; ++i) {
   284     if (i % 16 == 0) {
   285       indent().print(SIZE_FORMAT_HEX_W(07) ":", i);
   286     }
   287     if (i % 2 == 0) {
   288       print(" ");
   289     }
   290     if (i < len) {
   291       print("%02x", ((unsigned char*)data)[i]);
   292     } else {
   293       print("  ");
   294     }
   295     if ((i + 1) % 16 == 0) {
   296       if (with_ascii) {
   297         print("  ");
   298         for (size_t j = 0; j < 16; ++j) {
   299           size_t idx = i + j - 15;
   300           if (idx < len) {
   301             char c = ((char*)data)[idx];
   302             print("%c", c >= 32 && c <= 126 ? c : '.');
   303           }
   304         }
   305       }
   306       cr();
   307     }
   308   }
   309 }
   311 stringStream::stringStream(size_t initial_size) : outputStream() {
   312   buffer_length = initial_size;
   313   buffer        = NEW_RESOURCE_ARRAY(char, buffer_length);
   314   buffer_pos    = 0;
   315   buffer_fixed  = false;
   316   DEBUG_ONLY(rm = Thread::current()->current_resource_mark();)
   317 }
   319 // useful for output to fixed chunks of memory, such as performance counters
   320 stringStream::stringStream(char* fixed_buffer, size_t fixed_buffer_size) : outputStream() {
   321   buffer_length = fixed_buffer_size;
   322   buffer        = fixed_buffer;
   323   buffer_pos    = 0;
   324   buffer_fixed  = true;
   325 }
   327 void stringStream::write(const char* s, size_t len) {
   328   size_t write_len = len;               // number of non-null bytes to write
   329   size_t end = buffer_pos + len + 1;    // position after write and final '\0'
   330   if (end > buffer_length) {
   331     if (buffer_fixed) {
   332       // if buffer cannot resize, silently truncate
   333       end = buffer_length;
   334       write_len = end - buffer_pos - 1; // leave room for the final '\0'
   335     } else {
   336       // For small overruns, double the buffer.  For larger ones,
   337       // increase to the requested size.
   338       if (end < buffer_length * 2) {
   339         end = buffer_length * 2;
   340       }
   341       char* oldbuf = buffer;
   342       assert(rm == NULL || Thread::current()->current_resource_mark() == rm,
   343              "stringStream is re-allocated with a different ResourceMark");
   344       buffer = NEW_RESOURCE_ARRAY(char, end);
   345       strncpy(buffer, oldbuf, buffer_pos);
   346       buffer_length = end;
   347     }
   348   }
   349   // invariant: buffer is always null-terminated
   350   guarantee(buffer_pos + write_len + 1 <= buffer_length, "stringStream oob");
   351   buffer[buffer_pos + write_len] = 0;
   352   strncpy(buffer + buffer_pos, s, write_len);
   353   buffer_pos += write_len;
   355   // Note that the following does not depend on write_len.
   356   // This means that position and count get updated
   357   // even when overflow occurs.
   358   update_position(s, len);
   359 }
   361 char* stringStream::as_string() {
   362   char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos + 1);
   363   strncpy(copy, buffer, buffer_pos);
   364   copy[buffer_pos] = 0;  // terminating null
   365   return copy;
   366 }
   368 stringStream::~stringStream() {}
   370 xmlStream*   xtty;
   371 outputStream* tty;
   372 outputStream* gclog_or_tty;
   373 CDS_ONLY(fileStream* classlist_file;) // Only dump the classes that can be stored into the CDS archive
   374 extern Mutex* tty_lock;
   376 #define EXTRACHARLEN   32
   377 #define CURRENTAPPX    ".current"
   378 // convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS
   379 char* get_datetime_string(char *buf, size_t len) {
   380   os::local_time_string(buf, len);
   381   int i = (int)strlen(buf);
   382   while (i-- >= 0) {
   383     if (buf[i] == ' ') buf[i] = '_';
   384     else if (buf[i] == ':') buf[i] = '-';
   385   }
   386   return buf;
   387 }
   389 static const char* make_log_name_internal(const char* log_name, const char* force_directory,
   390                                                 int pid, const char* tms) {
   391   const char* basename = log_name;
   392   char file_sep = os::file_separator()[0];
   393   const char* cp;
   394   char  pid_text[32];
   396   for (cp = log_name; *cp != '\0'; cp++) {
   397     if (*cp == '/' || *cp == file_sep) {
   398       basename = cp + 1;
   399     }
   400   }
   401   const char* nametail = log_name;
   402   // Compute buffer length
   403   size_t buffer_length;
   404   if (force_directory != NULL) {
   405     buffer_length = strlen(force_directory) + strlen(os::file_separator()) +
   406                     strlen(basename) + 1;
   407   } else {
   408     buffer_length = strlen(log_name) + 1;
   409   }
   411   const char* pts = strstr(basename, "%p");
   412   int pid_pos = (pts == NULL) ? -1 : (pts - nametail);
   414   if (pid_pos >= 0) {
   415     jio_snprintf(pid_text, sizeof(pid_text), "pid%u", pid);
   416     buffer_length += strlen(pid_text);
   417   }
   419   pts = strstr(basename, "%t");
   420   int tms_pos = (pts == NULL) ? -1 : (pts - nametail);
   421   if (tms_pos >= 0) {
   422     buffer_length += strlen(tms);
   423   }
   425   // File name is too long.
   426   if (buffer_length > JVM_MAXPATHLEN) {
   427     return NULL;
   428   }
   430   // Create big enough buffer.
   431   char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
   433   strcpy(buf, "");
   434   if (force_directory != NULL) {
   435     strcat(buf, force_directory);
   436     strcat(buf, os::file_separator());
   437     nametail = basename;       // completely skip directory prefix
   438   }
   440   // who is first, %p or %t?
   441   int first = -1, second = -1;
   442   const char *p1st = NULL;
   443   const char *p2nd = NULL;
   445   if (pid_pos >= 0 && tms_pos >= 0) {
   446     // contains both %p and %t
   447     if (pid_pos < tms_pos) {
   448       // case foo%pbar%tmonkey.log
   449       first  = pid_pos;
   450       p1st   = pid_text;
   451       second = tms_pos;
   452       p2nd   = tms;
   453     } else {
   454       // case foo%tbar%pmonkey.log
   455       first  = tms_pos;
   456       p1st   = tms;
   457       second = pid_pos;
   458       p2nd   = pid_text;
   459     }
   460   } else if (pid_pos >= 0) {
   461     // contains %p only
   462     first  = pid_pos;
   463     p1st   = pid_text;
   464   } else if (tms_pos >= 0) {
   465     // contains %t only
   466     first  = tms_pos;
   467     p1st   = tms;
   468   }
   470   int buf_pos = (int)strlen(buf);
   471   const char* tail = nametail;
   473   if (first >= 0) {
   474     tail = nametail + first + 2;
   475     strncpy(&buf[buf_pos], nametail, first);
   476     strcpy(&buf[buf_pos + first], p1st);
   477     buf_pos = (int)strlen(buf);
   478     if (second >= 0) {
   479       strncpy(&buf[buf_pos], tail, second - first - 2);
   480       strcpy(&buf[buf_pos + second - first - 2], p2nd);
   481       tail = nametail + second + 2;
   482     }
   483   }
   484   strcat(buf, tail);      // append rest of name, or all of name
   485   return buf;
   486 }
   488 // log_name comes from -XX:LogFile=log_name, -Xloggc:log_name or
   489 // -XX:DumpLoadedClassList=<file_name>
   490 // in log_name, %p => pid1234 and
   491 //              %t => YYYY-MM-DD_HH-MM-SS
   492 static const char* make_log_name(const char* log_name, const char* force_directory) {
   493   char timestr[32];
   494   get_datetime_string(timestr, sizeof(timestr));
   495   return make_log_name_internal(log_name, force_directory, os::current_process_id(),
   496                                 timestr);
   497 }
   499 #ifndef PRODUCT
   500 void test_loggc_filename() {
   501   int pid;
   502   char  tms[32];
   503   char  i_result[JVM_MAXPATHLEN];
   504   const char* o_result;
   505   get_datetime_string(tms, sizeof(tms));
   506   pid = os::current_process_id();
   508   // test.log
   509   jio_snprintf(i_result, JVM_MAXPATHLEN, "test.log", tms);
   510   o_result = make_log_name_internal("test.log", NULL, pid, tms);
   511   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)");
   512   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
   514   // test-%t-%p.log
   515   jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%s-pid%u.log", tms, pid);
   516   o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms);
   517   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)");
   518   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
   520   // test-%t%p.log
   521   jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%spid%u.log", tms, pid);
   522   o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms);
   523   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)");
   524   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
   526   // %p%t.log
   527   jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u%s.log", pid, tms);
   528   o_result = make_log_name_internal("%p%t.log", NULL, pid, tms);
   529   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)");
   530   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
   532   // %p-test.log
   533   jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u-test.log", pid);
   534   o_result = make_log_name_internal("%p-test.log", NULL, pid, tms);
   535   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)");
   536   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
   538   // %t.log
   539   jio_snprintf(i_result, JVM_MAXPATHLEN, "%s.log", tms);
   540   o_result = make_log_name_internal("%t.log", NULL, pid, tms);
   541   assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)");
   542   FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
   544   {
   545     // longest filename
   546     char longest_name[JVM_MAXPATHLEN];
   547     memset(longest_name, 'a', sizeof(longest_name));
   548     longest_name[JVM_MAXPATHLEN - 1] = '\0';
   549     o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
   550     assert(strcmp(longest_name, o_result) == 0, err_msg("longest name does not match. expected '%s' but got '%s'", longest_name, o_result));
   551     FREE_C_HEAP_ARRAY(char, o_result, mtInternal);
   552   }
   554   {
   555     // too long file name
   556     char too_long_name[JVM_MAXPATHLEN + 100];
   557     int too_long_length = sizeof(too_long_name);
   558     memset(too_long_name, 'a', too_long_length);
   559     too_long_name[too_long_length - 1] = '\0';
   560     o_result = make_log_name_internal((const char*)&too_long_name, NULL, pid, tms);
   561     assert(o_result == NULL, err_msg("Too long file name should return NULL, but got '%s'", o_result));
   562   }
   564   {
   565     // too long with timestamp
   566     char longest_name[JVM_MAXPATHLEN];
   567     memset(longest_name, 'a', JVM_MAXPATHLEN);
   568     longest_name[JVM_MAXPATHLEN - 3] = '%';
   569     longest_name[JVM_MAXPATHLEN - 2] = 't';
   570     longest_name[JVM_MAXPATHLEN - 1] = '\0';
   571     o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
   572     assert(o_result == NULL, err_msg("Too long file name after timestamp expansion should return NULL, but got '%s'", o_result));
   573   }
   575   {
   576     // too long with pid
   577     char longest_name[JVM_MAXPATHLEN];
   578     memset(longest_name, 'a', JVM_MAXPATHLEN);
   579     longest_name[JVM_MAXPATHLEN - 3] = '%';
   580     longest_name[JVM_MAXPATHLEN - 2] = 'p';
   581     longest_name[JVM_MAXPATHLEN - 1] = '\0';
   582     o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
   583     assert(o_result == NULL, err_msg("Too long file name after pid expansion should return NULL, but got '%s'", o_result));
   584   }
   585 }
   587 //////////////////////////////////////////////////////////////////////////////
   588 // Test os::vsnprintf and friends.
   590 void check_snprintf_result(int expected, size_t limit, int actual, bool expect_count) {
   591   if (expect_count || ((size_t)expected < limit)) {
   592     assert(expected == actual, "snprintf result not expected value");
   593   } else {
   594     // Make this check more permissive for jdk8u, don't assert that actual == 0.
   595     // e.g. jio_vsnprintf_wrapper and jio_snprintf return -1 when expected >= limit
   596     if (expected >= (int) limit) {
   597       assert(actual == -1, "snprintf result should be -1 for expected >= limit");
   598     } else {
   599       assert(actual > 0, "snprintf result should be >0 for expected < limit");
   600     }
   601   }
   602 }
   604 // PrintFn is expected to be int (*)(char*, size_t, const char*, ...).
   605 // But jio_snprintf is a C-linkage function with that signature, which
   606 // has a different type on some platforms (like Solaris).
   607 template<typename PrintFn>
   608 void test_snprintf(PrintFn pf, bool expect_count) {
   609   const char expected[] = "abcdefghijklmnopqrstuvwxyz";
   610   const int expected_len = sizeof(expected) - 1;
   611   const size_t padding_size = 10;
   612   char buffer[2 * (sizeof(expected) + padding_size)];
   613   char check_buffer[sizeof(buffer)];
   614   const char check_char = '1';  // Something not in expected.
   615   memset(check_buffer, check_char, sizeof(check_buffer));
   616   const size_t sizes_to_test[] = {
   617     sizeof(buffer) - padding_size,       // Fits, with plenty of space to spare.
   618     sizeof(buffer)/2,                    // Fits, with space to spare.
   619     sizeof(buffer)/4,                    // Doesn't fit.
   620     sizeof(expected) + padding_size + 1, // Fits, with a little room to spare
   621     sizeof(expected) + padding_size,     // Fits exactly.
   622     sizeof(expected) + padding_size - 1, // Doesn't quite fit.
   623     2,                                   // One char + terminating NUL.
   624     1,                                   // Only space for terminating NUL.
   625     0 };                                 // No space at all.
   626   for (unsigned i = 0; i < ARRAY_SIZE(sizes_to_test); ++i) {
   627     memset(buffer, check_char, sizeof(buffer)); // To catch stray writes.
   628     size_t test_size = sizes_to_test[i];
   629     ResourceMark rm;
   630     stringStream s;
   631     s.print("test_size: " SIZE_FORMAT, test_size);
   632     size_t prefix_size = padding_size;
   633     guarantee(test_size <= (sizeof(buffer) - prefix_size), "invariant");
   634     size_t write_size = MIN2(sizeof(expected), test_size);
   635     size_t suffix_size = sizeof(buffer) - prefix_size - write_size;
   636     char* write_start = buffer + prefix_size;
   637     char* write_end = write_start + write_size;
   639     int result = pf(write_start, test_size, "%s", expected);
   641     check_snprintf_result(expected_len, test_size, result, expect_count);
   643     // Verify expected output.
   644     if (test_size > 0) {
   645       assert(0 == strncmp(write_start, expected, write_size - 1), "strncmp failure");
   646       // Verify terminating NUL of output.
   647       assert('\0' == write_start[write_size - 1], "null terminator failure");
   648     } else {
   649       guarantee(test_size == 0, "invariant");
   650       guarantee(write_size == 0, "invariant");
   651       guarantee(prefix_size + suffix_size == sizeof(buffer), "invariant");
   652       guarantee(write_start == write_end, "invariant");
   653     }
   655     // Verify no scribbling on prefix or suffix.
   656     assert(0 == strncmp(buffer, check_buffer, prefix_size), "prefix scribble");
   657     assert(0 == strncmp(write_end, check_buffer, suffix_size), "suffix scribble");
   658   }
   660   // Special case of 0-length buffer with empty (except for terminator) output.
   661   check_snprintf_result(0, 0, pf(NULL, 0, "%s", ""), expect_count);
   662   check_snprintf_result(0, 0, pf(NULL, 0, ""), expect_count);
   663 }
   665 // This is probably equivalent to os::snprintf, but we're being
   666 // explicit about what we're testing here.
   667 static int vsnprintf_wrapper(char* buf, size_t len, const char* fmt, ...) {
   668   va_list args;
   669   va_start(args, fmt);
   670   int result = os::vsnprintf(buf, len, fmt, args);
   671   va_end(args);
   672   return result;
   673 }
   675 // These are declared in jvm.h; test here, with related functions.
   676 extern "C" {
   677 int jio_vsnprintf(char*, size_t, const char*, va_list);
   678 int jio_snprintf(char*, size_t, const char*, ...);
   679 }
   681 // This is probably equivalent to jio_snprintf, but we're being
   682 // explicit about what we're testing here.
   683 static int jio_vsnprintf_wrapper(char* buf, size_t len, const char* fmt, ...) {
   684   va_list args;
   685   va_start(args, fmt);
   686   int result = jio_vsnprintf(buf, len, fmt, args);
   687   va_end(args);
   688   return result;
   689 }
   691 void test_snprintf() {
   692   test_snprintf(vsnprintf_wrapper, true);
   693   test_snprintf(os::snprintf, true);
   694   test_snprintf(jio_vsnprintf_wrapper, false); // jio_vsnprintf returns -1 on error including exceeding buffer size
   695   test_snprintf(jio_snprintf, false);          // jio_snprintf calls jio_vsnprintf
   696 }
   697 #endif // PRODUCT
   699 fileStream::fileStream(const char* file_name) {
   700   _file = fopen(file_name, "w");
   701   if (_file != NULL) {
   702     _need_close = true;
   703   } else {
   704     warning("Cannot open file %s due to %s\n", file_name, strerror(errno));
   705     _need_close = false;
   706   }
   707 }
   709 fileStream::fileStream(const char* file_name, const char* opentype) {
   710   _file = fopen(file_name, opentype);
   711   if (_file != NULL) {
   712     _need_close = true;
   713   } else {
   714     warning("Cannot open file %s due to %s\n", file_name, strerror(errno));
   715     _need_close = false;
   716   }
   717 }
   719 void fileStream::write(const char* s, size_t len) {
   720   if (_file != NULL)  {
   721     // Make an unused local variable to avoid warning from gcc 4.x compiler.
   722     size_t count = fwrite(s, 1, len, _file);
   723   }
   724   update_position(s, len);
   725 }
   727 long fileStream::fileSize() {
   728   long size = -1;
   729   if (_file != NULL) {
   730     long pos  = ::ftell(_file);
   731     if (::fseek(_file, 0, SEEK_END) == 0) {
   732       size = ::ftell(_file);
   733     }
   734     ::fseek(_file, pos, SEEK_SET);
   735   }
   736   return size;
   737 }
   739 char* fileStream::readln(char *data, int count ) {
   740   char * ret = ::fgets(data, count, _file);
   741   //Get rid of annoying \n char
   742   data[::strlen(data)-1] = '\0';
   743   return ret;
   744 }
   746 fileStream::~fileStream() {
   747   if (_file != NULL) {
   748     if (_need_close) fclose(_file);
   749     _file      = NULL;
   750   }
   751 }
   753 void fileStream::flush() {
   754   fflush(_file);
   755 }
   757 fdStream::fdStream(const char* file_name) {
   758   _fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
   759   _need_close = true;
   760 }
   762 fdStream::~fdStream() {
   763   if (_fd != -1) {
   764     if (_need_close) close(_fd);
   765     _fd = -1;
   766   }
   767 }
   769 void fdStream::write(const char* s, size_t len) {
   770   if (_fd != -1) {
   771     // Make an unused local variable to avoid warning from gcc 4.x compiler.
   772     size_t count = ::write(_fd, s, (int)len);
   773   }
   774   update_position(s, len);
   775 }
   777 // dump vm version, os version, platform info, build id,
   778 // memory usage and command line flags into header
   779 void gcLogFileStream::dump_loggc_header() {
   780   if (is_open()) {
   781     print_cr("%s", Abstract_VM_Version::internal_vm_info_string());
   782     os::print_memory_info(this);
   783     print("CommandLine flags: ");
   784     CommandLineFlags::printSetFlags(this);
   785   }
   786 }
   788 gcLogFileStream::~gcLogFileStream() {
   789   if (_file != NULL) {
   790     if (_need_close) fclose(_file);
   791     _file = NULL;
   792   }
   793   if (_file_name != NULL) {
   794     FREE_C_HEAP_ARRAY(char, _file_name, mtInternal);
   795     _file_name = NULL;
   796   }
   797 }
   799 gcLogFileStream::gcLogFileStream(const char* file_name) {
   800   _cur_file_num = 0;
   801   _bytes_written = 0L;
   802   _file_name = make_log_name(file_name, NULL);
   804   if (_file_name == NULL) {
   805     warning("Cannot open file %s: file name is too long.\n", file_name);
   806     _need_close = false;
   807     UseGCLogFileRotation = false;
   808     return;
   809   }
   811   // gc log file rotation
   812   if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) {
   813     char tempbuf[JVM_MAXPATHLEN];
   814     jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
   815     _file = fopen(tempbuf, "w");
   816   } else {
   817     _file = fopen(_file_name, "w");
   818   }
   819   if (_file != NULL) {
   820     _need_close = true;
   821     dump_loggc_header();
   822   } else {
   823     warning("Cannot open file %s due to %s\n", _file_name, strerror(errno));
   824     _need_close = false;
   825   }
   826 }
   828 void gcLogFileStream::write(const char* s, size_t len) {
   829   if (_file != NULL) {
   830     size_t count = fwrite(s, 1, len, _file);
   831     _bytes_written += count;
   832   }
   833   update_position(s, len);
   834 }
   836 // rotate_log must be called from VMThread at safepoint. In case need change parameters
   837 // for gc log rotation from thread other than VMThread, a sub type of VM_Operation
   838 // should be created and be submitted to VMThread's operation queue. DO NOT call this
   839 // function directly. Currently, it is safe to rotate log at safepoint through VMThread.
   840 // That is, no mutator threads and concurrent GC threads run parallel with VMThread to
   841 // write to gc log file at safepoint. If in future, changes made for mutator threads or
   842 // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
   843 // must be synchronized.
   844 void gcLogFileStream::rotate_log(bool force, outputStream* out) {
   845   char time_msg[O_BUFLEN];
   846   char time_str[EXTRACHARLEN];
   847   char current_file_name[JVM_MAXPATHLEN];
   848   char renamed_file_name[JVM_MAXPATHLEN];
   850   if (!should_rotate(force)) {
   851     return;
   852   }
   854 #ifdef ASSERT
   855   Thread *thread = Thread::current();
   856   assert(thread == NULL ||
   857          (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()),
   858          "Must be VMThread at safepoint");
   859 #endif
   860   if (NumberOfGCLogFiles == 1) {
   861     // rotate in same file
   862     rewind();
   863     _bytes_written = 0L;
   864     jio_snprintf(time_msg, sizeof(time_msg), "File  %s rotated at %s\n",
   865                  _file_name, os::local_time_string((char *)time_str, sizeof(time_str)));
   866     write(time_msg, strlen(time_msg));
   868     if (out != NULL) {
   869       out->print("%s", time_msg);
   870     }
   872     dump_loggc_header();
   873     return;
   874   }
   876 #if defined(_WINDOWS)
   877 #ifndef F_OK
   878 #define F_OK 0
   879 #endif
   880 #endif // _WINDOWS
   882   // rotate file in names extended_filename.0, extended_filename.1, ...,
   883   // extended_filename.<NumberOfGCLogFiles - 1>. Current rotation file name will
   884   // have a form of extended_filename.<i>.current where i is the current rotation
   885   // file number. After it reaches max file size, the file will be saved and renamed
   886   // with .current removed from its tail.
   887   if (_file != NULL) {
   888     jio_snprintf(renamed_file_name, JVM_MAXPATHLEN, "%s.%d",
   889                  _file_name, _cur_file_num);
   890     int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN,
   891                               "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
   892     if (result >= JVM_MAXPATHLEN) {
   893       warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
   894       return;
   895     }
   897     const char* msg = force ? "GC log rotation request has been received."
   898                             : "GC log file has reached the maximum size.";
   899     jio_snprintf(time_msg, sizeof(time_msg), "%s %s Saved as %s\n",
   900                      os::local_time_string((char *)time_str, sizeof(time_str)),
   901                                                          msg, renamed_file_name);
   902     write(time_msg, strlen(time_msg));
   904     if (out != NULL) {
   905       out->print("%s", time_msg);
   906     }
   908     fclose(_file);
   909     _file = NULL;
   911     bool can_rename = true;
   912     if (access(current_file_name, F_OK) != 0) {
   913       // current file does not exist?
   914       warning("No source file exists, cannot rename\n");
   915       can_rename = false;
   916     }
   917     if (can_rename) {
   918       if (access(renamed_file_name, F_OK) == 0) {
   919         if (remove(renamed_file_name) != 0) {
   920           warning("Could not delete existing file %s\n", renamed_file_name);
   921           can_rename = false;
   922         }
   923       } else {
   924         // file does not exist, ok to rename
   925       }
   926     }
   927     if (can_rename && rename(current_file_name, renamed_file_name) != 0) {
   928       warning("Could not rename %s to %s\n", _file_name, renamed_file_name);
   929     }
   930   }
   932   _cur_file_num++;
   933   if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0;
   934   int result = jio_snprintf(current_file_name,  JVM_MAXPATHLEN, "%s.%d" CURRENTAPPX,
   935                _file_name, _cur_file_num);
   936   if (result >= JVM_MAXPATHLEN) {
   937     warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
   938     return;
   939   }
   941   _file = fopen(current_file_name, "w");
   943   if (_file != NULL) {
   944     _bytes_written = 0L;
   945     _need_close = true;
   946     // reuse current_file_name for time_msg
   947     jio_snprintf(current_file_name, JVM_MAXPATHLEN,
   948                  "%s.%d", _file_name, _cur_file_num);
   949     jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n",
   950                  os::local_time_string((char *)time_str, sizeof(time_str)), current_file_name);
   951     write(time_msg, strlen(time_msg));
   953     if (out != NULL) {
   954       out->print("%s", time_msg);
   955     }
   957     dump_loggc_header();
   958     // remove the existing file
   959     if (access(current_file_name, F_OK) == 0) {
   960       if (remove(current_file_name) != 0) {
   961         warning("Could not delete existing file %s\n", current_file_name);
   962       }
   963     }
   964   } else {
   965     warning("failed to open rotation log file %s due to %s\n"
   966             "Turned off GC log file rotation\n",
   967                   _file_name, strerror(errno));
   968     _need_close = false;
   969     FLAG_SET_DEFAULT(UseGCLogFileRotation, false);
   970   }
   971 }
   973 defaultStream* defaultStream::instance = NULL;
   974 int defaultStream::_output_fd = 1;
   975 int defaultStream::_error_fd  = 2;
   976 FILE* defaultStream::_output_stream = stdout;
   977 FILE* defaultStream::_error_stream  = stderr;
   979 #define LOG_MAJOR_VERSION 160
   980 #define LOG_MINOR_VERSION 1
   982 void defaultStream::init() {
   983   _inited = true;
   984   if (LogVMOutput || LogCompilation) {
   985     init_log();
   986   }
   987 }
   989 bool defaultStream::has_log_file() {
   990   // lazily create log file (at startup, LogVMOutput is false even
   991   // if +LogVMOutput is used, because the flags haven't been parsed yet)
   992   // For safer printing during fatal error handling, do not init logfile
   993   // if a VM error has been reported.
   994   if (!_inited && !is_error_reported())  init();
   995   return _log_file != NULL;
   996 }
   998 fileStream* defaultStream::open_file(const char* log_name) {
   999   const char* try_name = make_log_name(log_name, NULL);
  1000   if (try_name == NULL) {
  1001     warning("Cannot open file %s: file name is too long.\n", log_name);
  1002     return NULL;
  1005   fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
  1006   FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
  1007   if (file->is_open()) {
  1008     return file;
  1011   // Try again to open the file in the temp directory.
  1012   delete file;
  1013   char warnbuf[O_BUFLEN*2];
  1014   jio_snprintf(warnbuf, sizeof(warnbuf), "Warning:  Cannot open log file: %s\n", log_name);
  1015   // Note:  This feature is for maintainer use only.  No need for L10N.
  1016   jio_print(warnbuf);
  1017   try_name = make_log_name(log_name, os::get_temp_directory());
  1018   if (try_name == NULL) {
  1019     warning("Cannot open file %s: file name is too long for directory %s.\n", log_name, os::get_temp_directory());
  1020     return NULL;
  1023   jio_snprintf(warnbuf, sizeof(warnbuf),
  1024                "Warning:  Forcing option -XX:LogFile=%s\n", try_name);
  1025   jio_print(warnbuf);
  1027   file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
  1028   FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
  1029   if (file->is_open()) {
  1030     return file;
  1033   delete file;
  1034   return NULL;
  1037 void defaultStream::init_log() {
  1038   // %%% Need a MutexLocker?
  1039   const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log";
  1040   fileStream* file = open_file(log_name);
  1042   if (file != NULL) {
  1043     _log_file = file;
  1044     _outer_xmlStream = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
  1045     start_log();
  1046   } else {
  1047     // and leave xtty as NULL
  1048     LogVMOutput = false;
  1049     DisplayVMOutput = true;
  1050     LogCompilation = false;
  1054 void defaultStream::start_log() {
  1055   xmlStream*xs = _outer_xmlStream;
  1056     if (this == tty)  xtty = xs;
  1057     // Write XML header.
  1058     xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
  1059     // (For now, don't bother to issue a DTD for this private format.)
  1060     jlong time_ms = os::javaTimeMillis() - tty->time_stamp().milliseconds();
  1061     // %%% Should be: jlong time_ms = os::start_time_milliseconds(), if
  1062     // we ever get round to introduce that method on the os class
  1063     xs->head("hotspot_log version='%d %d'"
  1064              " process='%d' time_ms='" INT64_FORMAT "'",
  1065              LOG_MAJOR_VERSION, LOG_MINOR_VERSION,
  1066              os::current_process_id(), (int64_t)time_ms);
  1067     // Write VM version header immediately.
  1068     xs->head("vm_version");
  1069     xs->head("name"); xs->text("%s", VM_Version::vm_name()); xs->cr();
  1070     xs->tail("name");
  1071     xs->head("release"); xs->text("%s", VM_Version::vm_release()); xs->cr();
  1072     xs->tail("release");
  1073     xs->head("info"); xs->text("%s", VM_Version::internal_vm_info_string()); xs->cr();
  1074     xs->tail("info");
  1075     xs->tail("vm_version");
  1076     // Record information about the command-line invocation.
  1077     xs->head("vm_arguments");  // Cf. Arguments::print_on()
  1078     if (Arguments::num_jvm_flags() > 0) {
  1079       xs->head("flags");
  1080       Arguments::print_jvm_flags_on(xs->text());
  1081       xs->tail("flags");
  1083     if (Arguments::num_jvm_args() > 0) {
  1084       xs->head("args");
  1085       Arguments::print_jvm_args_on(xs->text());
  1086       xs->tail("args");
  1088     if (Arguments::java_command() != NULL) {
  1089       xs->head("command"); xs->text()->print_cr("%s", Arguments::java_command());
  1090       xs->tail("command");
  1092     if (Arguments::sun_java_launcher() != NULL) {
  1093       xs->head("launcher"); xs->text()->print_cr("%s", Arguments::sun_java_launcher());
  1094       xs->tail("launcher");
  1096     if (Arguments::system_properties() !=  NULL) {
  1097       xs->head("properties");
  1098       // Print it as a java-style property list.
  1099       // System properties don't generally contain newlines, so don't bother with unparsing.
  1100       for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
  1101         xs->text()->print_cr("%s=%s", p->key(), p->value());
  1103       xs->tail("properties");
  1105     xs->tail("vm_arguments");
  1106     // tty output per se is grouped under the <tty>...</tty> element.
  1107     xs->head("tty");
  1108     // All further non-markup text gets copied to the tty:
  1109     xs->_text = this;  // requires friend declaration!
  1112 // finish_log() is called during normal VM shutdown. finish_log_on_error() is
  1113 // called by ostream_abort() after a fatal error.
  1114 //
  1115 void defaultStream::finish_log() {
  1116   xmlStream* xs = _outer_xmlStream;
  1117   xs->done("tty");
  1119   // Other log forks are appended here, at the End of Time:
  1120   CompileLog::finish_log(xs->out());  // write compile logging, if any, now
  1122   xs->done("hotspot_log");
  1123   xs->flush();
  1125   fileStream* file = _log_file;
  1126   _log_file = NULL;
  1128   delete _outer_xmlStream;
  1129   _outer_xmlStream = NULL;
  1131   file->flush();
  1132   delete file;
  1135 void defaultStream::finish_log_on_error(char *buf, int buflen) {
  1136   xmlStream* xs = _outer_xmlStream;
  1138   if (xs && xs->out()) {
  1140     xs->done_raw("tty");
  1142     // Other log forks are appended here, at the End of Time:
  1143     CompileLog::finish_log_on_error(xs->out(), buf, buflen);  // write compile logging, if any, now
  1145     xs->done_raw("hotspot_log");
  1146     xs->flush();
  1148     fileStream* file = _log_file;
  1149     _log_file = NULL;
  1150     _outer_xmlStream = NULL;
  1152     if (file) {
  1153       file->flush();
  1155       // Can't delete or close the file because delete and fclose aren't
  1156       // async-safe. We are about to die, so leave it to the kernel.
  1157       // delete file;
  1162 intx defaultStream::hold(intx writer_id) {
  1163   bool has_log = has_log_file();  // check before locking
  1164   if (// impossible, but who knows?
  1165       writer_id == NO_WRITER ||
  1167       // bootstrap problem
  1168       tty_lock == NULL ||
  1170       // can't grab a lock or call Thread::current() if TLS isn't initialized
  1171       ThreadLocalStorage::thread() == NULL ||
  1173       // developer hook
  1174       !SerializeVMOutput ||
  1176       // VM already unhealthy
  1177       is_error_reported() ||
  1179       // safepoint == global lock (for VM only)
  1180       (SafepointSynchronize::is_synchronizing() &&
  1181        Thread::current()->is_VM_thread())
  1182       ) {
  1183     // do not attempt to lock unless we know the thread and the VM is healthy
  1184     return NO_WRITER;
  1186   if (_writer == writer_id) {
  1187     // already held, no need to re-grab the lock
  1188     return NO_WRITER;
  1190   tty_lock->lock_without_safepoint_check();
  1191   // got the lock
  1192   if (writer_id != _last_writer) {
  1193     if (has_log) {
  1194       _log_file->bol();
  1195       // output a hint where this output is coming from:
  1196       _log_file->print_cr("<writer thread='" UINTX_FORMAT "'/>", writer_id);
  1198     _last_writer = writer_id;
  1200   _writer = writer_id;
  1201   return writer_id;
  1204 void defaultStream::release(intx holder) {
  1205   if (holder == NO_WRITER) {
  1206     // nothing to release:  either a recursive lock, or we scribbled (too bad)
  1207     return;
  1209   if (_writer != holder) {
  1210     return;  // already unlocked, perhaps via break_tty_lock_for_safepoint
  1212   _writer = NO_WRITER;
  1213   tty_lock->unlock();
  1217 // Yuck:  jio_print does not accept char*/len.
  1218 static void call_jio_print(const char* s, size_t len) {
  1219   char buffer[O_BUFLEN+100];
  1220   if (len > sizeof(buffer)-1) {
  1221     warning("increase O_BUFLEN in ostream.cpp -- output truncated");
  1222     len = sizeof(buffer)-1;
  1224   strncpy(buffer, s, len);
  1225   buffer[len] = '\0';
  1226   jio_print(buffer);
  1230 void defaultStream::write(const char* s, size_t len) {
  1231   intx thread_id = os::current_thread_id();
  1232   intx holder = hold(thread_id);
  1234   if (DisplayVMOutput &&
  1235       (_outer_xmlStream == NULL || !_outer_xmlStream->inside_attrs())) {
  1236     // print to output stream. It can be redirected by a vfprintf hook
  1237     if (s[len] == '\0') {
  1238       jio_print(s);
  1239     } else {
  1240       call_jio_print(s, len);
  1244   // print to log file
  1245   if (has_log_file()) {
  1246     int nl0 = _newlines;
  1247     xmlTextStream::write(s, len);
  1248     // flush the log file too, if there were any newlines
  1249     if (nl0 != _newlines){
  1250       flush();
  1252   } else {
  1253     update_position(s, len);
  1256   release(holder);
  1259 intx ttyLocker::hold_tty() {
  1260   if (defaultStream::instance == NULL)  return defaultStream::NO_WRITER;
  1261   intx thread_id = os::current_thread_id();
  1262   return defaultStream::instance->hold(thread_id);
  1265 void ttyLocker::release_tty(intx holder) {
  1266   if (holder == defaultStream::NO_WRITER)  return;
  1267   defaultStream::instance->release(holder);
  1270 bool ttyLocker::release_tty_if_locked() {
  1271   intx thread_id = os::current_thread_id();
  1272   if (defaultStream::instance->writer() == thread_id) {
  1273     // release the lock and return true so callers know if was
  1274     // previously held.
  1275     release_tty(thread_id);
  1276     return true;
  1278   return false;
  1281 void ttyLocker::break_tty_lock_for_safepoint(intx holder) {
  1282   if (defaultStream::instance != NULL &&
  1283       defaultStream::instance->writer() == holder) {
  1284     if (xtty != NULL) {
  1285       xtty->print_cr("<!-- safepoint while printing -->");
  1287     defaultStream::instance->release(holder);
  1289   // (else there was no lock to break)
  1292 void ostream_init() {
  1293   if (defaultStream::instance == NULL) {
  1294     defaultStream::instance = new(ResourceObj::C_HEAP, mtInternal) defaultStream();
  1295     tty = defaultStream::instance;
  1297     // We want to ensure that time stamps in GC logs consider time 0
  1298     // the time when the JVM is initialized, not the first time we ask
  1299     // for a time stamp. So, here, we explicitly update the time stamp
  1300     // of tty.
  1301     tty->time_stamp().update_to(1);
  1305 void ostream_init_log() {
  1306   // For -Xloggc:<file> option - called in runtime/thread.cpp
  1307   // Note : this must be called AFTER ostream_init()
  1309   gclog_or_tty = tty; // default to tty
  1310   if (Arguments::gc_log_filename() != NULL) {
  1311     fileStream * gclog  = new(ResourceObj::C_HEAP, mtInternal)
  1312                              gcLogFileStream(Arguments::gc_log_filename());
  1313     if (gclog->is_open()) {
  1314       // now we update the time stamp of the GC log to be synced up
  1315       // with tty.
  1316       gclog->time_stamp().update_to(tty->time_stamp().ticks());
  1318     gclog_or_tty = gclog;
  1321 #if INCLUDE_CDS
  1322   // For -XX:DumpLoadedClassList=<file> option
  1323   if (DumpLoadedClassList != NULL) {
  1324     const char* list_name = make_log_name(DumpLoadedClassList, NULL);
  1325     classlist_file = new(ResourceObj::C_HEAP, mtInternal)
  1326                          fileStream(list_name);
  1327     FREE_C_HEAP_ARRAY(char, list_name, mtInternal);
  1329 #endif
  1331   // If we haven't lazily initialized the logfile yet, do it now,
  1332   // to avoid the possibility of lazy initialization during a VM
  1333   // crash, which can affect the stability of the fatal error handler.
  1334   defaultStream::instance->has_log_file();
  1337 // ostream_exit() is called during normal VM exit to finish log files, flush
  1338 // output and free resource.
  1339 void ostream_exit() {
  1340   static bool ostream_exit_called = false;
  1341   if (ostream_exit_called)  return;
  1342   ostream_exit_called = true;
  1343 #if INCLUDE_CDS
  1344   if (classlist_file != NULL) {
  1345     delete classlist_file;
  1347 #endif
  1348   if (gclog_or_tty != tty) {
  1349       delete gclog_or_tty;
  1352       // we temporaly disable PrintMallocFree here
  1353       // as otherwise it'll lead to using of almost deleted
  1354       // tty or defaultStream::instance in logging facility
  1355       // of HeapFree(), see 6391258
  1356       DEBUG_ONLY(FlagSetting fs(PrintMallocFree, false);)
  1357       if (tty != defaultStream::instance) {
  1358           delete tty;
  1360       if (defaultStream::instance != NULL) {
  1361           delete defaultStream::instance;
  1364   tty = NULL;
  1365   xtty = NULL;
  1366   gclog_or_tty = NULL;
  1367   defaultStream::instance = NULL;
  1370 // ostream_abort() is called by os::abort() when VM is about to die.
  1371 void ostream_abort() {
  1372   // Here we can't delete gclog_or_tty and tty, just flush their output
  1373   if (gclog_or_tty) gclog_or_tty->flush();
  1374   if (tty) tty->flush();
  1376   if (defaultStream::instance != NULL) {
  1377     static char buf[4096];
  1378     defaultStream::instance->finish_log_on_error(buf, sizeof(buf));
  1382 staticBufferStream::staticBufferStream(char* buffer, size_t buflen,
  1383                                        outputStream *outer_stream) {
  1384   _buffer = buffer;
  1385   _buflen = buflen;
  1386   _outer_stream = outer_stream;
  1387   // compile task prints time stamp relative to VM start
  1388   _stamp.update_to(1);
  1391 void staticBufferStream::write(const char* c, size_t len) {
  1392   _outer_stream->print_raw(c, (int)len);
  1395 void staticBufferStream::flush() {
  1396   _outer_stream->flush();
  1399 void staticBufferStream::print(const char* format, ...) {
  1400   va_list ap;
  1401   va_start(ap, format);
  1402   size_t len;
  1403   const char* str = do_vsnprintf(_buffer, _buflen, format, ap, false, len);
  1404   write(str, len);
  1405   va_end(ap);
  1408 void staticBufferStream::print_cr(const char* format, ...) {
  1409   va_list ap;
  1410   va_start(ap, format);
  1411   size_t len;
  1412   const char* str = do_vsnprintf(_buffer, _buflen, format, ap, true, len);
  1413   write(str, len);
  1414   va_end(ap);
  1417 void staticBufferStream::vprint(const char *format, va_list argptr) {
  1418   size_t len;
  1419   const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, false, len);
  1420   write(str, len);
  1423 void staticBufferStream::vprint_cr(const char* format, va_list argptr) {
  1424   size_t len;
  1425   const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, true, len);
  1426   write(str, len);
  1429 bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() {
  1430   buffer_length = initial_size;
  1431   buffer        = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
  1432   buffer_pos    = 0;
  1433   buffer_fixed  = false;
  1434   buffer_max    = bufmax;
  1437 bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax) : outputStream() {
  1438   buffer_length = fixed_buffer_size;
  1439   buffer        = fixed_buffer;
  1440   buffer_pos    = 0;
  1441   buffer_fixed  = true;
  1442   buffer_max    = bufmax;
  1445 void bufferedStream::write(const char* s, size_t len) {
  1447   if(buffer_pos + len > buffer_max) {
  1448     flush();
  1451   size_t end = buffer_pos + len;
  1452   if (end >= buffer_length) {
  1453     if (buffer_fixed) {
  1454       // if buffer cannot resize, silently truncate
  1455       len = buffer_length - buffer_pos - 1;
  1456     } else {
  1457       // For small overruns, double the buffer.  For larger ones,
  1458       // increase to the requested size.
  1459       if (end < buffer_length * 2) {
  1460         end = buffer_length * 2;
  1462       buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end, mtInternal);
  1463       buffer_length = end;
  1466   memcpy(buffer + buffer_pos, s, len);
  1467   buffer_pos += len;
  1468   update_position(s, len);
  1471 char* bufferedStream::as_string() {
  1472   char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1);
  1473   strncpy(copy, buffer, buffer_pos);
  1474   copy[buffer_pos] = 0;  // terminating null
  1475   return copy;
  1478 bufferedStream::~bufferedStream() {
  1479   if (!buffer_fixed) {
  1480     FREE_C_HEAP_ARRAY(char, buffer, mtInternal);
  1484 #ifndef PRODUCT
  1486 #if defined(SOLARIS) || defined(LINUX) || defined(AIX) || defined(_ALLBSD_SOURCE)
  1487 #include <sys/types.h>
  1488 #include <sys/socket.h>
  1489 #include <netinet/in.h>
  1490 #include <arpa/inet.h>
  1491 #endif
  1493 // Network access
  1494 networkStream::networkStream() : bufferedStream(1024*10, 1024*10) {
  1496   _socket = -1;
  1498   int result = os::socket(AF_INET, SOCK_STREAM, 0);
  1499   if (result <= 0) {
  1500     assert(false, "Socket could not be created!");
  1501   } else {
  1502     _socket = result;
  1506 int networkStream::read(char *buf, size_t len) {
  1507   return os::recv(_socket, buf, (int)len, 0);
  1510 void networkStream::flush() {
  1511   if (size() != 0) {
  1512     int result = os::raw_send(_socket, (char *)base(), size(), 0);
  1513     assert(result != -1, "connection error");
  1514     assert(result == (int)size(), "didn't send enough data");
  1516   reset();
  1519 networkStream::~networkStream() {
  1520   close();
  1523 void networkStream::close() {
  1524   if (_socket != -1) {
  1525     flush();
  1526     os::socket_close(_socket);
  1527     _socket = -1;
  1531 bool networkStream::connect(const char *ip, short port) {
  1533   struct sockaddr_in server;
  1534   server.sin_family = AF_INET;
  1535   server.sin_port = htons(port);
  1537   server.sin_addr.s_addr = inet_addr(ip);
  1538   if (server.sin_addr.s_addr == (uint32_t)-1) {
  1539     struct hostent* host = os::get_host_by_name((char*)ip);
  1540     if (host != NULL) {
  1541       memcpy(&server.sin_addr, host->h_addr_list[0], host->h_length);
  1542     } else {
  1543       return false;
  1548   int result = os::connect(_socket, (struct sockaddr*)&server, sizeof(struct sockaddr_in));
  1549   return (result >= 0);
  1552 #endif

mercurial