* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: lprintf.c
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#pragma ident "@(#)lprintf.c 1.12 06/08/14 SMI"
#define LOGSPACE (LOGLINES*LOGLINE_SIZE)
FILE *fp
; /* output file handle */
log_entry_t entry
[LOGLINES
];
static void log_internal_printf(int id
, char * fmt
, va_list args
);
log
.bufferp
= Xcalloc(log
.bufsize
, char);
pthread_mutex_init(&log
.lock
, NULL
);
log
.enabled
= options
.analyzer
;
if (options
.log_file
!= NULL
) {
log
.fp
= fopen(options
.log_file
, "w");
fatal("cannot open log: %s", options
.log_file
);
log
.fp
= stdout
; /* stdout by default */
* Was any buffering requested?
if (options
.buffersz
!= -1) {
if (options
.buffersz
<= 0) {
(void) setvbuf(log
.fp
, NULL
, _IOLBF
, 0);
log
.fp_buffer
= Xmalloc(options
.buffersz
);
(void) setvbuf(log
.fp
, log
.fp_buffer
,
_IOFBF
, options
.buffersz
);
/* Output stream if no logging enabled. */
* Very simple printf scheme for a rotating log file ...
* ... has a generous buffer but checks for potential overflow
* Idea is that it logs the last N lines of printf output into a rotating buffer Q
* excellent way to thrash the heap, but useful for debugging.
void lprintf(int id
, char * fmt
, ...)
log_internal_printf(id
, fmt
, args
);
pthread_mutex_lock( &log
.lock
);
pthread_mutex_unlock( &log
.lock
);
* Assumes you've already requested log_lock();
void log_printf(int id
, char * fmt
, ...)
log_internal_printf(id
, fmt
, args
);
static void log_internal_printf(int id
, char * fmt
, va_list args
)
int len
, lostsize
, space
;
fprintf(NO_LOG_FP
,"[%d] ",id
);
vfprintf(NO_LOG_FP
,fmt
,args
);
* Dont bother tracking how many live lines there are...
* just bother assigning pointers correctly ...
* then determine validity in the dump routine.
space
= log
.bufsize
- log
.freeoff
;
* returned len is the full output length,
* not including the null byte
len
= vsnprintf(log
.bufferp
+ log
.freeoff
, space
, fmt
, args
);
/* didn't get all the output */
fatal("lprintf: Ug! LOGSPACE needs to be raised to at least %d\n", len
+1);
if (log
.idx
>=log
.num
) log
.idx
=0;
log
.entry
[log
.idx
].id
= id
;
log
.entry
[log
.idx
].off
= log
.freeoff
;
log
.entry
[log
.idx
].len
= len
;
log
.entry
[log
.idx
].size
= lostsize
;
if (log
.freeoff
== log
.bufsize
) log
.freeoff
= 0;
space
= log
.entry
[i
].size
+ log
.entry
[i
].len
;
for(num
= 0; space
<log
.bufsize
&& num
<log
.num
; num
++) {
space
+= log
.entry
[i
].size
+ log
.entry
[i
].len
;
if (log
.entry
[i
].id
!= -1)
fprintf(log
.fp
, "[%d] ", log
.entry
[i
].id
);
fwrite(log
.bufferp
+ log
.entry
[i
].off
, log
.entry
[i
].len
, 1, log
.fp
);