src/share/vm/utilities/ostream.cpp

Thu, 20 Nov 2008 16:56:09 -0800

author
ysr
date
Thu, 20 Nov 2008 16:56:09 -0800
changeset 888
c96030fff130
parent 791
1ee8caae33af
child 948
2328d1d3f8cf
permissions
-rw-r--r--

6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa

duke@435 1 /*
xdono@631 2 * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
duke@435 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@435 20 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@435 21 * have any questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 # include "incls/_precompiled.incl"
duke@435 26 # include "incls/_ostream.cpp.incl"
duke@435 27
duke@435 28 extern "C" void jio_print(const char* s); // Declarationtion of jvm method
duke@435 29
duke@435 30 outputStream::outputStream(int width) {
duke@435 31 _width = width;
duke@435 32 _position = 0;
duke@435 33 _newlines = 0;
duke@435 34 _precount = 0;
duke@435 35 _indentation = 0;
duke@435 36 }
duke@435 37
duke@435 38 outputStream::outputStream(int width, bool has_time_stamps) {
duke@435 39 _width = width;
duke@435 40 _position = 0;
duke@435 41 _newlines = 0;
duke@435 42 _precount = 0;
duke@435 43 _indentation = 0;
duke@435 44 if (has_time_stamps) _stamp.update();
duke@435 45 }
duke@435 46
duke@435 47 void outputStream::update_position(const char* s, size_t len) {
duke@435 48 for (size_t i = 0; i < len; i++) {
duke@435 49 char ch = s[i];
duke@435 50 if (ch == '\n') {
duke@435 51 _newlines += 1;
duke@435 52 _precount += _position + 1;
duke@435 53 _position = 0;
duke@435 54 } else if (ch == '\t') {
jrose@535 55 int tw = 8 - (_position & 7);
jrose@535 56 _position += tw;
jrose@535 57 _precount -= tw-1; // invariant: _precount + _position == total count
duke@435 58 } else {
duke@435 59 _position += 1;
duke@435 60 }
duke@435 61 }
duke@435 62 }
duke@435 63
duke@435 64 // Execute a vsprintf, using the given buffer if necessary.
duke@435 65 // Return a pointer to the formatted string.
duke@435 66 const char* outputStream::do_vsnprintf(char* buffer, size_t buflen,
duke@435 67 const char* format, va_list ap,
duke@435 68 bool add_cr,
duke@435 69 size_t& result_len) {
duke@435 70 const char* result;
duke@435 71 if (add_cr) buflen--;
duke@435 72 if (!strchr(format, '%')) {
duke@435 73 // constant format string
duke@435 74 result = format;
duke@435 75 result_len = strlen(result);
duke@435 76 if (add_cr && result_len >= buflen) result_len = buflen-1; // truncate
duke@435 77 } else if (format[0] == '%' && format[1] == 's' && format[2] == '\0') {
duke@435 78 // trivial copy-through format string
duke@435 79 result = va_arg(ap, const char*);
duke@435 80 result_len = strlen(result);
duke@435 81 if (add_cr && result_len >= buflen) result_len = buflen-1; // truncate
duke@435 82 } else if (vsnprintf(buffer, buflen, format, ap) >= 0) {
duke@435 83 result = buffer;
duke@435 84 result_len = strlen(result);
duke@435 85 } else {
duke@435 86 DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
duke@435 87 result = buffer;
duke@435 88 result_len = buflen - 1;
duke@435 89 buffer[result_len] = 0;
duke@435 90 }
duke@435 91 if (add_cr) {
duke@435 92 if (result != buffer) {
duke@435 93 strncpy(buffer, result, buflen);
duke@435 94 result = buffer;
duke@435 95 }
duke@435 96 buffer[result_len++] = '\n';
duke@435 97 buffer[result_len] = 0;
duke@435 98 }
duke@435 99 return result;
duke@435 100 }
duke@435 101
duke@435 102 void outputStream::print(const char* format, ...) {
duke@435 103 char buffer[O_BUFLEN];
duke@435 104 va_list ap;
duke@435 105 va_start(ap, format);
duke@435 106 size_t len;
duke@435 107 const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, false, len);
duke@435 108 write(str, len);
duke@435 109 va_end(ap);
duke@435 110 }
duke@435 111
duke@435 112 void outputStream::print_cr(const char* format, ...) {
duke@435 113 char buffer[O_BUFLEN];
duke@435 114 va_list ap;
duke@435 115 va_start(ap, format);
duke@435 116 size_t len;
duke@435 117 const char* str = do_vsnprintf(buffer, O_BUFLEN, format, ap, true, len);
duke@435 118 write(str, len);
duke@435 119 va_end(ap);
duke@435 120 }
duke@435 121
duke@435 122 void outputStream::vprint(const char *format, va_list argptr) {
duke@435 123 char buffer[O_BUFLEN];
duke@435 124 size_t len;
duke@435 125 const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, false, len);
duke@435 126 write(str, len);
duke@435 127 }
duke@435 128
duke@435 129 void outputStream::vprint_cr(const char* format, va_list argptr) {
duke@435 130 char buffer[O_BUFLEN];
duke@435 131 size_t len;
duke@435 132 const char* str = do_vsnprintf(buffer, O_BUFLEN, format, argptr, true, len);
duke@435 133 write(str, len);
duke@435 134 }
duke@435 135
duke@435 136 void outputStream::fill_to(int col) {
jrose@535 137 int need_fill = col - position();
jrose@535 138 sp(need_fill);
jrose@535 139 }
jrose@535 140
jrose@535 141 void outputStream::move_to(int col, int slop, int min_space) {
jrose@535 142 if (position() >= col + slop)
jrose@535 143 cr();
jrose@535 144 int need_fill = col - position();
jrose@535 145 if (need_fill < min_space)
jrose@535 146 need_fill = min_space;
jrose@535 147 sp(need_fill);
duke@435 148 }
duke@435 149
duke@435 150 void outputStream::put(char ch) {
duke@435 151 assert(ch != 0, "please fix call site");
duke@435 152 char buf[] = { ch, '\0' };
duke@435 153 write(buf, 1);
duke@435 154 }
duke@435 155
jrose@535 156 #define SP_USE_TABS false
jrose@535 157
jrose@535 158 void outputStream::sp(int count) {
jrose@535 159 if (count < 0) return;
jrose@535 160 if (SP_USE_TABS && count >= 8) {
jrose@535 161 int target = position() + count;
jrose@535 162 while (count >= 8) {
jrose@535 163 this->write("\t", 1);
jrose@535 164 count -= 8;
jrose@535 165 }
jrose@535 166 count = target - position();
jrose@535 167 }
jrose@535 168 while (count > 0) {
jrose@535 169 int nw = (count > 8) ? 8 : count;
jrose@535 170 this->write(" ", nw);
jrose@535 171 count -= nw;
jrose@535 172 }
duke@435 173 }
duke@435 174
duke@435 175 void outputStream::cr() {
duke@435 176 this->write("\n", 1);
duke@435 177 }
duke@435 178
duke@435 179 void outputStream::stamp() {
duke@435 180 if (! _stamp.is_updated()) {
duke@435 181 _stamp.update(); // start at 0 on first call to stamp()
duke@435 182 }
duke@435 183
duke@435 184 // outputStream::stamp() may get called by ostream_abort(), use snprintf
duke@435 185 // to avoid allocating large stack buffer in print().
duke@435 186 char buf[40];
duke@435 187 jio_snprintf(buf, sizeof(buf), "%.3f", _stamp.seconds());
duke@435 188 print_raw(buf);
duke@435 189 }
duke@435 190
ysr@777 191 void outputStream::stamp(bool guard,
ysr@777 192 const char* prefix,
ysr@777 193 const char* suffix) {
ysr@777 194 if (!guard) {
ysr@777 195 return;
ysr@777 196 }
ysr@777 197 print_raw(prefix);
ysr@777 198 stamp();
ysr@777 199 print_raw(suffix);
ysr@777 200 }
ysr@777 201
duke@435 202 void outputStream::date_stamp(bool guard,
duke@435 203 const char* prefix,
duke@435 204 const char* suffix) {
duke@435 205 if (!guard) {
duke@435 206 return;
duke@435 207 }
duke@435 208 print_raw(prefix);
duke@435 209 static const char error_time[] = "yyyy-mm-ddThh:mm:ss.mmm+zzzz";
duke@435 210 static const int buffer_length = 32;
duke@435 211 char buffer[buffer_length];
duke@435 212 const char* iso8601_result = os::iso8601_time(buffer, buffer_length);
duke@435 213 if (iso8601_result != NULL) {
duke@435 214 print_raw(buffer);
duke@435 215 } else {
duke@435 216 print_raw(error_time);
duke@435 217 }
duke@435 218 print_raw(suffix);
duke@435 219 return;
duke@435 220 }
duke@435 221
duke@435 222 void outputStream::indent() {
duke@435 223 while (_position < _indentation) sp();
duke@435 224 }
duke@435 225
duke@435 226 void outputStream::print_jlong(jlong value) {
duke@435 227 // N.B. Same as INT64_FORMAT
duke@435 228 print(os::jlong_format_specifier(), value);
duke@435 229 }
duke@435 230
duke@435 231 void outputStream::print_julong(julong value) {
duke@435 232 // N.B. Same as UINT64_FORMAT
duke@435 233 print(os::julong_format_specifier(), value);
duke@435 234 }
duke@435 235
duke@435 236 stringStream::stringStream(size_t initial_size) : outputStream() {
duke@435 237 buffer_length = initial_size;
duke@435 238 buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
duke@435 239 buffer_pos = 0;
duke@435 240 buffer_fixed = false;
duke@435 241 }
duke@435 242
duke@435 243 // useful for output to fixed chunks of memory, such as performance counters
duke@435 244 stringStream::stringStream(char* fixed_buffer, size_t fixed_buffer_size) : outputStream() {
duke@435 245 buffer_length = fixed_buffer_size;
duke@435 246 buffer = fixed_buffer;
duke@435 247 buffer_pos = 0;
duke@435 248 buffer_fixed = true;
duke@435 249 }
duke@435 250
duke@435 251 void stringStream::write(const char* s, size_t len) {
duke@435 252 size_t write_len = len; // number of non-null bytes to write
duke@435 253 size_t end = buffer_pos + len + 1; // position after write and final '\0'
duke@435 254 if (end > buffer_length) {
duke@435 255 if (buffer_fixed) {
duke@435 256 // if buffer cannot resize, silently truncate
duke@435 257 end = buffer_length;
duke@435 258 write_len = end - buffer_pos - 1; // leave room for the final '\0'
duke@435 259 } else {
duke@435 260 // For small overruns, double the buffer. For larger ones,
duke@435 261 // increase to the requested size.
duke@435 262 if (end < buffer_length * 2) {
duke@435 263 end = buffer_length * 2;
duke@435 264 }
duke@435 265 char* oldbuf = buffer;
duke@435 266 buffer = NEW_RESOURCE_ARRAY(char, end);
duke@435 267 strncpy(buffer, oldbuf, buffer_pos);
duke@435 268 buffer_length = end;
duke@435 269 }
duke@435 270 }
duke@435 271 // invariant: buffer is always null-terminated
duke@435 272 guarantee(buffer_pos + write_len + 1 <= buffer_length, "stringStream oob");
duke@435 273 buffer[buffer_pos + write_len] = 0;
duke@435 274 strncpy(buffer + buffer_pos, s, write_len);
duke@435 275 buffer_pos += write_len;
duke@435 276
duke@435 277 // Note that the following does not depend on write_len.
duke@435 278 // This means that position and count get updated
duke@435 279 // even when overflow occurs.
duke@435 280 update_position(s, len);
duke@435 281 }
duke@435 282
duke@435 283 char* stringStream::as_string() {
duke@435 284 char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1);
duke@435 285 strncpy(copy, buffer, buffer_pos);
duke@435 286 copy[buffer_pos] = 0; // terminating null
duke@435 287 return copy;
duke@435 288 }
duke@435 289
duke@435 290 stringStream::~stringStream() {}
duke@435 291
duke@435 292 xmlStream* xtty;
duke@435 293 outputStream* tty;
duke@435 294 outputStream* gclog_or_tty;
duke@435 295 extern Mutex* tty_lock;
duke@435 296
duke@435 297 fileStream::fileStream(const char* file_name) {
duke@435 298 _file = fopen(file_name, "w");
duke@435 299 _need_close = true;
duke@435 300 }
duke@435 301
duke@435 302 void fileStream::write(const char* s, size_t len) {
duke@435 303 if (_file != NULL) fwrite(s, 1, len, _file);
duke@435 304 update_position(s, len);
duke@435 305 }
duke@435 306
duke@435 307 fileStream::~fileStream() {
duke@435 308 if (_file != NULL) {
duke@435 309 if (_need_close) fclose(_file);
duke@435 310 _file = NULL;
duke@435 311 }
duke@435 312 }
duke@435 313
duke@435 314 void fileStream::flush() {
duke@435 315 fflush(_file);
duke@435 316 }
duke@435 317
duke@435 318 fdStream::fdStream(const char* file_name) {
duke@435 319 _fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
duke@435 320 _need_close = true;
duke@435 321 }
duke@435 322
duke@435 323 fdStream::~fdStream() {
duke@435 324 if (_fd != -1) {
duke@435 325 if (_need_close) close(_fd);
duke@435 326 _fd = -1;
duke@435 327 }
duke@435 328 }
duke@435 329
duke@435 330 void fdStream::write(const char* s, size_t len) {
duke@435 331 if (_fd != -1) ::write(_fd, s, (int)len);
duke@435 332 update_position(s, len);
duke@435 333 }
duke@435 334
duke@435 335 defaultStream* defaultStream::instance = NULL;
duke@435 336 int defaultStream::_output_fd = 1;
duke@435 337 int defaultStream::_error_fd = 2;
duke@435 338 FILE* defaultStream::_output_stream = stdout;
duke@435 339 FILE* defaultStream::_error_stream = stderr;
duke@435 340
duke@435 341 #define LOG_MAJOR_VERSION 160
duke@435 342 #define LOG_MINOR_VERSION 1
duke@435 343
duke@435 344 void defaultStream::init() {
duke@435 345 _inited = true;
duke@435 346 if (LogVMOutput || LogCompilation) {
duke@435 347 init_log();
duke@435 348 }
duke@435 349 }
duke@435 350
duke@435 351 bool defaultStream::has_log_file() {
duke@435 352 // lazily create log file (at startup, LogVMOutput is false even
duke@435 353 // if +LogVMOutput is used, because the flags haven't been parsed yet)
duke@435 354 // For safer printing during fatal error handling, do not init logfile
duke@435 355 // if a VM error has been reported.
duke@435 356 if (!_inited && !is_error_reported()) init();
duke@435 357 return _log_file != NULL;
duke@435 358 }
duke@435 359
duke@435 360 static const char* make_log_name(const char* log_name, const char* force_directory, char* buf) {
duke@435 361 const char* basename = log_name;
duke@435 362 char file_sep = os::file_separator()[0];
duke@435 363 const char* cp;
duke@435 364 for (cp = log_name; *cp != '\0'; cp++) {
duke@435 365 if (*cp == '/' || *cp == file_sep) {
duke@435 366 basename = cp+1;
duke@435 367 }
duke@435 368 }
duke@435 369 const char* nametail = log_name;
duke@435 370
duke@435 371 strcpy(buf, "");
duke@435 372 if (force_directory != NULL) {
duke@435 373 strcat(buf, force_directory);
duke@435 374 strcat(buf, os::file_separator());
duke@435 375 nametail = basename; // completely skip directory prefix
duke@435 376 }
duke@435 377
duke@435 378 const char* star = strchr(basename, '*');
duke@435 379 int star_pos = (star == NULL) ? -1 : (star - nametail);
duke@435 380
duke@435 381 if (star_pos >= 0) {
duke@435 382 // convert foo*bar.log to foo123bar.log
duke@435 383 int buf_pos = (int) strlen(buf);
duke@435 384 strncpy(&buf[buf_pos], nametail, star_pos);
duke@435 385 sprintf(&buf[buf_pos + star_pos], "%u", os::current_process_id());
duke@435 386 nametail += star_pos + 1; // skip prefix and star
duke@435 387 }
duke@435 388
duke@435 389 strcat(buf, nametail); // append rest of name, or all of name
duke@435 390 return buf;
duke@435 391 }
duke@435 392
duke@435 393 void defaultStream::init_log() {
duke@435 394 // %%% Need a MutexLocker?
duke@435 395 const char* log_name = LogFile != NULL ? LogFile : "hotspot.log";
duke@435 396 char buf[O_BUFLEN*2];
duke@435 397 const char* try_name = make_log_name(log_name, NULL, buf);
duke@435 398 fileStream* file = new(ResourceObj::C_HEAP) fileStream(try_name);
duke@435 399 if (!file->is_open()) {
duke@435 400 // Try again to open the file.
duke@435 401 char warnbuf[O_BUFLEN*2];
duke@435 402 sprintf(warnbuf, "Warning: Cannot open log file: %s\n", try_name);
duke@435 403 // Note: This feature is for maintainer use only. No need for L10N.
duke@435 404 jio_print(warnbuf);
duke@435 405 try_name = make_log_name("hs_pid*.log", os::get_temp_directory(), buf);
duke@435 406 sprintf(warnbuf, "Warning: Forcing option -XX:LogFile=%s\n", try_name);
duke@435 407 jio_print(warnbuf);
duke@435 408 delete file;
duke@435 409 file = new(ResourceObj::C_HEAP) fileStream(try_name);
duke@435 410 }
duke@435 411 if (file->is_open()) {
duke@435 412 _log_file = file;
duke@435 413 xmlStream* xs = new(ResourceObj::C_HEAP) xmlStream(file);
duke@435 414 _outer_xmlStream = xs;
duke@435 415 if (this == tty) xtty = xs;
duke@435 416 // Write XML header.
duke@435 417 xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
duke@435 418 // (For now, don't bother to issue a DTD for this private format.)
duke@435 419 jlong time_ms = os::javaTimeMillis() - tty->time_stamp().milliseconds();
duke@435 420 // %%% Should be: jlong time_ms = os::start_time_milliseconds(), if
duke@435 421 // we ever get round to introduce that method on the os class
duke@435 422 xs->head("hotspot_log version='%d %d'"
duke@435 423 " process='%d' time_ms='"INT64_FORMAT"'",
duke@435 424 LOG_MAJOR_VERSION, LOG_MINOR_VERSION,
duke@435 425 os::current_process_id(), time_ms);
duke@435 426 // Write VM version header immediately.
duke@435 427 xs->head("vm_version");
duke@435 428 xs->head("name"); xs->text("%s", VM_Version::vm_name()); xs->cr();
duke@435 429 xs->tail("name");
duke@435 430 xs->head("release"); xs->text("%s", VM_Version::vm_release()); xs->cr();
duke@435 431 xs->tail("release");
duke@435 432 xs->head("info"); xs->text("%s", VM_Version::internal_vm_info_string()); xs->cr();
duke@435 433 xs->tail("info");
duke@435 434 xs->tail("vm_version");
duke@435 435 // Record information about the command-line invocation.
duke@435 436 xs->head("vm_arguments"); // Cf. Arguments::print_on()
duke@435 437 if (Arguments::num_jvm_flags() > 0) {
duke@435 438 xs->head("flags");
duke@435 439 Arguments::print_jvm_flags_on(xs->text());
duke@435 440 xs->tail("flags");
duke@435 441 }
duke@435 442 if (Arguments::num_jvm_args() > 0) {
duke@435 443 xs->head("args");
duke@435 444 Arguments::print_jvm_args_on(xs->text());
duke@435 445 xs->tail("args");
duke@435 446 }
duke@435 447 if (Arguments::java_command() != NULL) {
duke@435 448 xs->head("command"); xs->text()->print_cr("%s", Arguments::java_command());
duke@435 449 xs->tail("command");
duke@435 450 }
duke@435 451 if (Arguments::sun_java_launcher() != NULL) {
duke@435 452 xs->head("launcher"); xs->text()->print_cr("%s", Arguments::sun_java_launcher());
duke@435 453 xs->tail("launcher");
duke@435 454 }
duke@435 455 if (Arguments::system_properties() != NULL) {
duke@435 456 xs->head("properties");
duke@435 457 // Print it as a java-style property list.
duke@435 458 // System properties don't generally contain newlines, so don't bother with unparsing.
duke@435 459 for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
duke@435 460 xs->text()->print_cr("%s=%s", p->key(), p->value());
duke@435 461 }
duke@435 462 xs->tail("properties");
duke@435 463 }
duke@435 464 xs->tail("vm_arguments");
duke@435 465 // tty output per se is grouped under the <tty>...</tty> element.
duke@435 466 xs->head("tty");
duke@435 467 // All further non-markup text gets copied to the tty:
duke@435 468 xs->_text = this; // requires friend declaration!
duke@435 469 } else {
duke@435 470 delete(file);
duke@435 471 // and leave xtty as NULL
duke@435 472 LogVMOutput = false;
duke@435 473 DisplayVMOutput = true;
duke@435 474 LogCompilation = false;
duke@435 475 }
duke@435 476 }
duke@435 477
duke@435 478 // finish_log() is called during normal VM shutdown. finish_log_on_error() is
duke@435 479 // called by ostream_abort() after a fatal error.
duke@435 480 //
duke@435 481 void defaultStream::finish_log() {
duke@435 482 xmlStream* xs = _outer_xmlStream;
duke@435 483 xs->done("tty");
duke@435 484
duke@435 485 // Other log forks are appended here, at the End of Time:
duke@435 486 CompileLog::finish_log(xs->out()); // write compile logging, if any, now
duke@435 487
duke@435 488 xs->done("hotspot_log");
duke@435 489 xs->flush();
duke@435 490
duke@435 491 fileStream* file = _log_file;
duke@435 492 _log_file = NULL;
duke@435 493
duke@435 494 delete _outer_xmlStream;
duke@435 495 _outer_xmlStream = NULL;
duke@435 496
duke@435 497 file->flush();
duke@435 498 delete file;
duke@435 499 }
duke@435 500
duke@435 501 void defaultStream::finish_log_on_error(char *buf, int buflen) {
duke@435 502 xmlStream* xs = _outer_xmlStream;
duke@435 503
duke@435 504 if (xs && xs->out()) {
duke@435 505
duke@435 506 xs->done_raw("tty");
duke@435 507
duke@435 508 // Other log forks are appended here, at the End of Time:
duke@435 509 CompileLog::finish_log_on_error(xs->out(), buf, buflen); // write compile logging, if any, now
duke@435 510
duke@435 511 xs->done_raw("hotspot_log");
duke@435 512 xs->flush();
duke@435 513
duke@435 514 fileStream* file = _log_file;
duke@435 515 _log_file = NULL;
duke@435 516 _outer_xmlStream = NULL;
duke@435 517
duke@435 518 if (file) {
duke@435 519 file->flush();
duke@435 520
duke@435 521 // Can't delete or close the file because delete and fclose aren't
duke@435 522 // async-safe. We are about to die, so leave it to the kernel.
duke@435 523 // delete file;
duke@435 524 }
duke@435 525 }
duke@435 526 }
duke@435 527
duke@435 528 intx defaultStream::hold(intx writer_id) {
duke@435 529 bool has_log = has_log_file(); // check before locking
duke@435 530 if (// impossible, but who knows?
duke@435 531 writer_id == NO_WRITER ||
duke@435 532
duke@435 533 // bootstrap problem
duke@435 534 tty_lock == NULL ||
duke@435 535
duke@435 536 // can't grab a lock or call Thread::current() if TLS isn't initialized
duke@435 537 ThreadLocalStorage::thread() == NULL ||
duke@435 538
duke@435 539 // developer hook
duke@435 540 !SerializeVMOutput ||
duke@435 541
duke@435 542 // VM already unhealthy
duke@435 543 is_error_reported() ||
duke@435 544
duke@435 545 // safepoint == global lock (for VM only)
duke@435 546 (SafepointSynchronize::is_synchronizing() &&
duke@435 547 Thread::current()->is_VM_thread())
duke@435 548 ) {
duke@435 549 // do not attempt to lock unless we know the thread and the VM is healthy
duke@435 550 return NO_WRITER;
duke@435 551 }
duke@435 552 if (_writer == writer_id) {
duke@435 553 // already held, no need to re-grab the lock
duke@435 554 return NO_WRITER;
duke@435 555 }
duke@435 556 tty_lock->lock_without_safepoint_check();
duke@435 557 // got the lock
duke@435 558 if (writer_id != _last_writer) {
duke@435 559 if (has_log) {
duke@435 560 _log_file->bol();
duke@435 561 // output a hint where this output is coming from:
duke@435 562 _log_file->print_cr("<writer thread='"INTX_FORMAT"'/>", writer_id);
duke@435 563 }
duke@435 564 _last_writer = writer_id;
duke@435 565 }
duke@435 566 _writer = writer_id;
duke@435 567 return writer_id;
duke@435 568 }
duke@435 569
duke@435 570 void defaultStream::release(intx holder) {
duke@435 571 if (holder == NO_WRITER) {
duke@435 572 // nothing to release: either a recursive lock, or we scribbled (too bad)
duke@435 573 return;
duke@435 574 }
duke@435 575 if (_writer != holder) {
duke@435 576 return; // already unlocked, perhaps via break_tty_lock_for_safepoint
duke@435 577 }
duke@435 578 _writer = NO_WRITER;
duke@435 579 tty_lock->unlock();
duke@435 580 }
duke@435 581
duke@435 582
duke@435 583 // Yuck: jio_print does not accept char*/len.
duke@435 584 static void call_jio_print(const char* s, size_t len) {
duke@435 585 char buffer[O_BUFLEN+100];
duke@435 586 if (len > sizeof(buffer)-1) {
duke@435 587 warning("increase O_BUFLEN in ostream.cpp -- output truncated");
duke@435 588 len = sizeof(buffer)-1;
duke@435 589 }
duke@435 590 strncpy(buffer, s, len);
duke@435 591 buffer[len] = '\0';
duke@435 592 jio_print(buffer);
duke@435 593 }
duke@435 594
duke@435 595
duke@435 596 void defaultStream::write(const char* s, size_t len) {
duke@435 597 intx thread_id = os::current_thread_id();
duke@435 598 intx holder = hold(thread_id);
duke@435 599
duke@435 600 if (DisplayVMOutput &&
duke@435 601 (_outer_xmlStream == NULL || !_outer_xmlStream->inside_attrs())) {
duke@435 602 // print to output stream. It can be redirected by a vfprintf hook
duke@435 603 if (s[len] == '\0') {
duke@435 604 jio_print(s);
duke@435 605 } else {
duke@435 606 call_jio_print(s, len);
duke@435 607 }
duke@435 608 }
duke@435 609
duke@435 610 // print to log file
duke@435 611 if (has_log_file()) {
duke@435 612 int nl0 = _newlines;
duke@435 613 xmlTextStream::write(s, len);
duke@435 614 // flush the log file too, if there were any newlines
duke@435 615 if (nl0 != _newlines){
duke@435 616 flush();
duke@435 617 }
duke@435 618 } else {
duke@435 619 update_position(s, len);
duke@435 620 }
duke@435 621
duke@435 622 release(holder);
duke@435 623 }
duke@435 624
duke@435 625 intx ttyLocker::hold_tty() {
duke@435 626 if (defaultStream::instance == NULL) return defaultStream::NO_WRITER;
duke@435 627 intx thread_id = os::current_thread_id();
duke@435 628 return defaultStream::instance->hold(thread_id);
duke@435 629 }
duke@435 630
duke@435 631 void ttyLocker::release_tty(intx holder) {
duke@435 632 if (holder == defaultStream::NO_WRITER) return;
duke@435 633 defaultStream::instance->release(holder);
duke@435 634 }
duke@435 635
duke@435 636 void ttyLocker::break_tty_lock_for_safepoint(intx holder) {
duke@435 637 if (defaultStream::instance != NULL &&
duke@435 638 defaultStream::instance->writer() == holder) {
duke@435 639 if (xtty != NULL) {
duke@435 640 xtty->print_cr("<!-- safepoint while printing -->");
duke@435 641 }
duke@435 642 defaultStream::instance->release(holder);
duke@435 643 }
duke@435 644 // (else there was no lock to break)
duke@435 645 }
duke@435 646
duke@435 647 void ostream_init() {
duke@435 648 if (defaultStream::instance == NULL) {
duke@435 649 defaultStream::instance = new(ResourceObj::C_HEAP) defaultStream();
duke@435 650 tty = defaultStream::instance;
duke@435 651
duke@435 652 // We want to ensure that time stamps in GC logs consider time 0
duke@435 653 // the time when the JVM is initialized, not the first time we ask
duke@435 654 // for a time stamp. So, here, we explicitly update the time stamp
duke@435 655 // of tty.
duke@435 656 tty->time_stamp().update_to(1);
duke@435 657 }
duke@435 658 }
duke@435 659
duke@435 660 void ostream_init_log() {
duke@435 661 // For -Xloggc:<file> option - called in runtime/thread.cpp
duke@435 662 // Note : this must be called AFTER ostream_init()
duke@435 663
duke@435 664 gclog_or_tty = tty; // default to tty
duke@435 665 if (Arguments::gc_log_filename() != NULL) {
duke@435 666 fileStream * gclog = new(ResourceObj::C_HEAP)
duke@435 667 fileStream(Arguments::gc_log_filename());
duke@435 668 if (gclog->is_open()) {
duke@435 669 // now we update the time stamp of the GC log to be synced up
duke@435 670 // with tty.
duke@435 671 gclog->time_stamp().update_to(tty->time_stamp().ticks());
duke@435 672 gclog_or_tty = gclog;
duke@435 673 }
duke@435 674 }
duke@435 675
duke@435 676 // If we haven't lazily initialized the logfile yet, do it now,
duke@435 677 // to avoid the possibility of lazy initialization during a VM
duke@435 678 // crash, which can affect the stability of the fatal error handler.
duke@435 679 defaultStream::instance->has_log_file();
duke@435 680 }
duke@435 681
duke@435 682 // ostream_exit() is called during normal VM exit to finish log files, flush
duke@435 683 // output and free resource.
duke@435 684 void ostream_exit() {
duke@435 685 static bool ostream_exit_called = false;
duke@435 686 if (ostream_exit_called) return;
duke@435 687 ostream_exit_called = true;
duke@435 688 if (gclog_or_tty != tty) {
duke@435 689 delete gclog_or_tty;
duke@435 690 }
duke@435 691 {
duke@435 692 // we temporaly disable PrintMallocFree here
duke@435 693 // as otherwise it'll lead to using of almost deleted
duke@435 694 // tty or defaultStream::instance in logging facility
duke@435 695 // of HeapFree(), see 6391258
duke@435 696 DEBUG_ONLY(FlagSetting fs(PrintMallocFree, false);)
duke@435 697 if (tty != defaultStream::instance) {
duke@435 698 delete tty;
duke@435 699 }
duke@435 700 if (defaultStream::instance != NULL) {
duke@435 701 delete defaultStream::instance;
duke@435 702 }
duke@435 703 }
duke@435 704 tty = NULL;
duke@435 705 xtty = NULL;
duke@435 706 gclog_or_tty = NULL;
duke@435 707 defaultStream::instance = NULL;
duke@435 708 }
duke@435 709
duke@435 710 // ostream_abort() is called by os::abort() when VM is about to die.
duke@435 711 void ostream_abort() {
duke@435 712 // Here we can't delete gclog_or_tty and tty, just flush their output
duke@435 713 if (gclog_or_tty) gclog_or_tty->flush();
duke@435 714 if (tty) tty->flush();
duke@435 715
duke@435 716 if (defaultStream::instance != NULL) {
duke@435 717 static char buf[4096];
duke@435 718 defaultStream::instance->finish_log_on_error(buf, sizeof(buf));
duke@435 719 }
duke@435 720 }
duke@435 721
duke@435 722 staticBufferStream::staticBufferStream(char* buffer, size_t buflen,
duke@435 723 outputStream *outer_stream) {
duke@435 724 _buffer = buffer;
duke@435 725 _buflen = buflen;
duke@435 726 _outer_stream = outer_stream;
duke@435 727 }
duke@435 728
duke@435 729 void staticBufferStream::write(const char* c, size_t len) {
duke@435 730 _outer_stream->print_raw(c, (int)len);
duke@435 731 }
duke@435 732
duke@435 733 void staticBufferStream::flush() {
duke@435 734 _outer_stream->flush();
duke@435 735 }
duke@435 736
duke@435 737 void staticBufferStream::print(const char* format, ...) {
duke@435 738 va_list ap;
duke@435 739 va_start(ap, format);
duke@435 740 size_t len;
duke@435 741 const char* str = do_vsnprintf(_buffer, _buflen, format, ap, false, len);
duke@435 742 write(str, len);
duke@435 743 va_end(ap);
duke@435 744 }
duke@435 745
duke@435 746 void staticBufferStream::print_cr(const char* format, ...) {
duke@435 747 va_list ap;
duke@435 748 va_start(ap, format);
duke@435 749 size_t len;
duke@435 750 const char* str = do_vsnprintf(_buffer, _buflen, format, ap, true, len);
duke@435 751 write(str, len);
duke@435 752 va_end(ap);
duke@435 753 }
duke@435 754
duke@435 755 void staticBufferStream::vprint(const char *format, va_list argptr) {
duke@435 756 size_t len;
duke@435 757 const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, false, len);
duke@435 758 write(str, len);
duke@435 759 }
duke@435 760
duke@435 761 void staticBufferStream::vprint_cr(const char* format, va_list argptr) {
duke@435 762 size_t len;
duke@435 763 const char* str = do_vsnprintf(_buffer, _buflen, format, argptr, true, len);
duke@435 764 write(str, len);
duke@435 765 }
duke@435 766
never@657 767 bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() {
duke@435 768 buffer_length = initial_size;
duke@435 769 buffer = NEW_C_HEAP_ARRAY(char, buffer_length);
duke@435 770 buffer_pos = 0;
duke@435 771 buffer_fixed = false;
never@657 772 buffer_max = bufmax;
duke@435 773 }
duke@435 774
never@657 775 bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax) : outputStream() {
duke@435 776 buffer_length = fixed_buffer_size;
duke@435 777 buffer = fixed_buffer;
duke@435 778 buffer_pos = 0;
duke@435 779 buffer_fixed = true;
never@657 780 buffer_max = bufmax;
duke@435 781 }
duke@435 782
duke@435 783 void bufferedStream::write(const char* s, size_t len) {
never@657 784
never@657 785 if(buffer_pos + len > buffer_max) {
never@657 786 flush();
never@657 787 }
never@657 788
duke@435 789 size_t end = buffer_pos + len;
duke@435 790 if (end >= buffer_length) {
duke@435 791 if (buffer_fixed) {
duke@435 792 // if buffer cannot resize, silently truncate
duke@435 793 len = buffer_length - buffer_pos - 1;
duke@435 794 } else {
duke@435 795 // For small overruns, double the buffer. For larger ones,
duke@435 796 // increase to the requested size.
duke@435 797 if (end < buffer_length * 2) {
duke@435 798 end = buffer_length * 2;
duke@435 799 }
duke@435 800 buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end);
duke@435 801 buffer_length = end;
duke@435 802 }
duke@435 803 }
duke@435 804 memcpy(buffer + buffer_pos, s, len);
duke@435 805 buffer_pos += len;
duke@435 806 update_position(s, len);
duke@435 807 }
duke@435 808
duke@435 809 char* bufferedStream::as_string() {
duke@435 810 char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1);
duke@435 811 strncpy(copy, buffer, buffer_pos);
duke@435 812 copy[buffer_pos] = 0; // terminating null
duke@435 813 return copy;
duke@435 814 }
duke@435 815
duke@435 816 bufferedStream::~bufferedStream() {
duke@435 817 if (!buffer_fixed) {
duke@435 818 FREE_C_HEAP_ARRAY(char, buffer);
duke@435 819 }
duke@435 820 }
duke@435 821
duke@435 822 #ifndef PRODUCT
duke@435 823
duke@435 824 #if defined(SOLARIS) || defined(LINUX)
duke@435 825 #include <sys/types.h>
duke@435 826 #include <sys/socket.h>
duke@435 827 #include <netinet/in.h>
duke@435 828 #include <arpa/inet.h>
duke@435 829 #endif
duke@435 830
duke@435 831 // Network access
never@657 832 networkStream::networkStream() : bufferedStream(1024*10, 1024*10) {
duke@435 833
duke@435 834 _socket = -1;
duke@435 835
duke@435 836 hpi::initialize_socket_library();
duke@435 837
duke@435 838 int result = hpi::socket(AF_INET, SOCK_STREAM, 0);
duke@435 839 if (result <= 0) {
duke@435 840 assert(false, "Socket could not be created!");
duke@435 841 } else {
duke@435 842 _socket = result;
duke@435 843 }
duke@435 844 }
duke@435 845
duke@435 846 int networkStream::read(char *buf, size_t len) {
duke@435 847 return hpi::recv(_socket, buf, (int)len, 0);
duke@435 848 }
duke@435 849
duke@435 850 void networkStream::flush() {
duke@435 851 if (size() != 0) {
never@657 852 int result = hpi::raw_send(_socket, (char *)base(), (int)size(), 0);
never@657 853 assert(result != -1, "connection error");
never@657 854 assert(result == (int)size(), "didn't send enough data");
duke@435 855 }
duke@435 856 reset();
duke@435 857 }
duke@435 858
duke@435 859 networkStream::~networkStream() {
duke@435 860 close();
duke@435 861 }
duke@435 862
duke@435 863 void networkStream::close() {
duke@435 864 if (_socket != -1) {
duke@435 865 flush();
duke@435 866 hpi::socket_close(_socket);
duke@435 867 _socket = -1;
duke@435 868 }
duke@435 869 }
duke@435 870
duke@435 871 bool networkStream::connect(const char *ip, short port) {
duke@435 872
duke@435 873 struct sockaddr_in server;
duke@435 874 server.sin_family = AF_INET;
duke@435 875 server.sin_port = htons(port);
duke@435 876
duke@435 877 server.sin_addr.s_addr = inet_addr(ip);
jcoomes@515 878 if (server.sin_addr.s_addr == (uint32_t)-1) {
duke@435 879 #ifdef _WINDOWS
duke@435 880 struct hostent* host = hpi::get_host_by_name((char*)ip);
duke@435 881 #else
duke@435 882 struct hostent* host = gethostbyname(ip);
duke@435 883 #endif
duke@435 884 if (host != NULL) {
duke@435 885 memcpy(&server.sin_addr, host->h_addr_list[0], host->h_length);
duke@435 886 } else {
duke@435 887 return false;
duke@435 888 }
duke@435 889 }
duke@435 890
duke@435 891
duke@435 892 int result = hpi::connect(_socket, (struct sockaddr*)&server, sizeof(struct sockaddr_in));
duke@435 893 return (result >= 0);
duke@435 894 }
duke@435 895
duke@435 896 #endif

mercurial