gcov-io.h (gcov_save_position, [...]): Modified to enable reading/ writing of whole .da file just once.

* gcov-io.h (gcov_save_position, gcov_reserve_length, gcov_resync,
	gcov_skip, gcov_skip_string, gcov_write_unsigned, gcov_write_counter,
	gcov_write_string, gcov_read_unsigned, gcov_read_counter,
	gcov_read_string, gcov_write_length): Modified to enable reading/
	writing of whole .da file just once.
	(da_file_open, da_file_close, da_file_eof, da_file_error,
	da_file_position, da_file_seek, da_file_write, da_file_read): New
	functions.
	(actual_da_file, actual_da_file_position, actual_da_file_length,
	actual_da_file_buffer, actual_da_file_buffer_size): New static
	functions.
	* libgcov.c (gcov_exit): Modified to read/write the whole .da file at
	just once.

From-SVN: r63800
This commit is contained in:
Zdenek Dvorak 2003-03-04 21:56:24 +01:00 committed by Zdenek Dvorak
parent 79dbeefca8
commit ec4a0419ad
3 changed files with 383 additions and 82 deletions

View File

@ -1,3 +1,20 @@
2003-03-04 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* gcov-io.h (gcov_save_position, gcov_reserve_length, gcov_resync,
gcov_skip, gcov_skip_string, gcov_write_unsigned, gcov_write_counter,
gcov_write_string, gcov_read_unsigned, gcov_read_counter,
gcov_read_string, gcov_write_length): Modified to enable reading/
writing of whole .da file just once.
(da_file_open, da_file_close, da_file_eof, da_file_error,
da_file_position, da_file_seek, da_file_write, da_file_read): New
functions.
(actual_da_file, actual_da_file_position, actual_da_file_length,
actual_da_file_buffer, actual_da_file_buffer_size): New static
functions.
* libgcov.c (gcov_exit): Modified to read/write the whole .da file at
just once.
2003-03-04 Andreas Schwab <schwab@suse.de>
* config/m68k/m68k.c (m68k_output_function_prologue): Fix CFA

View File

@ -302,18 +302,27 @@ static int gcov_write_summary PARAMS ((FILE *, unsigned,
ATTRIBUTE_UNUSED;
#endif
#define gcov_save_position(STREAM) \
ftell (STREAM)
da_file_position (STREAM)
#define gcov_reserve_length(STREAM) \
(gcov_write_unsigned (STREAM, 0) ? 0 : ftell (STREAM) - 4)
(gcov_write_unsigned (STREAM, 0) ? 0 : da_file_position (STREAM) - 4)
static int gcov_write_length PARAMS((FILE *, long))
ATTRIBUTE_UNUSED;
#define gcov_resync(STREAM, BASE, LENGTH) \
fseek (STREAM, BASE + (long)LENGTH, SEEK_SET)
da_file_seek (STREAM, BASE + (long)LENGTH, SEEK_SET)
#define gcov_skip(STREAM, LENGTH) \
fseek (STREAM, LENGTH, SEEK_CUR)
da_file_seek (STREAM, LENGTH, SEEK_CUR)
#define gcov_skip_string(STREAM, LENGTH) \
fseek (STREAM, (LENGTH) + 4 - ((LENGTH) & 3), SEEK_CUR)
da_file_seek (STREAM, (LENGTH) + 4 - ((LENGTH) & 3), SEEK_CUR)
#if IN_LIBGCC2
static FILE *da_file_open PARAMS ((const char *, int *));
static int da_file_close PARAMS ((void));
static int da_file_eof PARAMS ((void));
static int da_file_error PARAMS ((void));
#endif
static unsigned long da_file_position PARAMS ((FILE *));
static int da_file_seek PARAMS ((FILE *, long, int));
static size_t da_file_write PARAMS ((const void *, size_t, size_t, FILE *));
static size_t da_file_read PARAMS ((void *, size_t, size_t, FILE *));
/* Write VALUE to coverage file FILE. Return nonzero if failed due to
file i/o error, or value error. */
@ -332,7 +341,7 @@ gcov_write_unsigned (file, value)
value >>= 8;
}
return ((sizeof (value) > sizeof (buffer) && value)
|| fwrite (buffer, sizeof (buffer), 1, file) != 1);
|| da_file_write (buffer, 1, sizeof (buffer), file) != sizeof (buffer));
}
/* Write VALUE to coverage file FILE. Return nonzero if failed due to
@ -353,7 +362,7 @@ gcov_write_counter (file, value)
value >>= 8;
}
return ((sizeof (value) > sizeof (buffer) && value != 0 && value != -1)
|| fwrite (buffer, sizeof (buffer), 1, file) != 1);
|| da_file_write (buffer, 1, sizeof (buffer), file) != sizeof (buffer));
}
/* Write VALUE to coverage file FILE. Return nonzero if failed due to
@ -366,11 +375,12 @@ gcov_write_string (file, string, length)
const char *string;
{
unsigned pad = 0;
unsigned rem = 4 - (length & 3);
if (string)
return (gcov_write_unsigned (file, length)
|| fwrite (string, length, 1, file) != 1
|| fwrite (&pad, 4 - (length & 3), 1, file) != 1);
|| da_file_write (string, 1, length, file) != length
|| da_file_write (&pad, 1, rem, file) != rem);
else
return gcov_write_unsigned (file, 0);
}
@ -387,7 +397,7 @@ gcov_read_unsigned (file, value_p)
unsigned ix;
unsigned char buffer[4];
if (fread (buffer, sizeof (buffer), 1, file) != 1)
if (da_file_read (buffer, 1, sizeof (buffer), file) != sizeof (buffer))
return 1;
for (ix = sizeof (value); ix < sizeof (buffer); ix++)
if (buffer[ix])
@ -413,7 +423,7 @@ gcov_read_counter (file, value_p)
unsigned ix;
unsigned char buffer[8];
if (fread (buffer, sizeof (buffer), 1, file) != 1)
if (da_file_read (buffer, 1, sizeof (buffer), file) != sizeof (buffer))
return 1;
for (ix = sizeof (value); ix < sizeof (buffer); ix++)
if (buffer[ix])
@ -457,7 +467,7 @@ gcov_read_string (file, string_p, length_p)
length += 4 - (length & 3);
*string_p = (char *) xmalloc (length);
return fread (*string_p, length, 1, file) != 1;
return da_file_read (*string_p, 1, length, file) != length;
}
@ -472,10 +482,10 @@ gcov_write_length (file, place)
FILE *file;
long place;
{
long here = ftell (file);
int result = (!place || fseek (file, place, SEEK_SET)
long here = da_file_position (file);
int result = (!place || da_file_seek (file, place, SEEK_SET)
|| gcov_write_unsigned (file, here - place - 4));
if (fseek (file, here, SEEK_SET))
if (da_file_seek (file, here, SEEK_SET))
result = 1;
return result;
}
@ -517,4 +527,288 @@ gcov_write_summary (da_file, tag, summary)
}
#endif
#if IN_LIBGCC2
/* The kernel had problems with managing a lot of small reads/writes we use;
the functions below are used to buffer whole file in memory, thus reading and
writing it only once. This should be feasible, as we have this amount
of memory for counters allocated anyway. */
static FILE *actual_da_file;
static unsigned long actual_da_file_position;
static unsigned long actual_da_file_length;
static char *actual_da_file_buffer;
static unsigned long actual_da_file_buffer_size;
/* Open the file NAME and return it; in EXISTED return 1 if it existed
already. */
static FILE *
da_file_open (name, existed)
const char *name;
int *existed;
{
#if defined (TARGET_HAS_F_SETLKW)
struct flock s_flock;
s_flock.l_type = F_WRLCK;
s_flock.l_whence = SEEK_SET;
s_flock.l_start = 0;
s_flock.l_len = 0; /* Until EOF. */
s_flock.l_pid = getpid ();
#endif
if (actual_da_file)
return 0;
actual_da_file_position = 0;
if (!actual_da_file_buffer)
{
actual_da_file_buffer = malloc (1);
actual_da_file_buffer_size = 1;
}
actual_da_file = fopen (name, "r+t");
if (actual_da_file)
*existed = 1;
else
{
actual_da_file = fopen (name, "w+t");
if (actual_da_file)
*existed = 0;
else
return 0;
}
#if defined (TARGET_HAS_F_SETLKW)
/* After a fork, another process might try to read and/or write
the same file simultaneously. So if we can, lock the file to
avoid race conditions. */
while (fcntl (fileno (actual_da_file), F_SETLKW, &s_flock)
&& errno == EINTR)
continue;
#endif
if (*existed)
{
if (fseek (actual_da_file, 0, SEEK_END))
{
fclose (actual_da_file);
actual_da_file = 0;
return 0;
}
actual_da_file_length = ftell (actual_da_file);
rewind (actual_da_file);
}
else
actual_da_file_length = 0;
if (actual_da_file_length > actual_da_file_buffer_size)
{
actual_da_file_buffer_size = actual_da_file_length;
actual_da_file_buffer = realloc (actual_da_file_buffer,
actual_da_file_buffer_size);
if (!actual_da_file_buffer)
{
fclose (actual_da_file);
actual_da_file = 0;
return 0;
}
}
if (*existed)
{
if (fread (actual_da_file_buffer, actual_da_file_length,
1, actual_da_file) != 1)
{
fclose (actual_da_file);
actual_da_file = 0;
return 0;
}
rewind (actual_da_file);
}
return actual_da_file;
}
/* Write changes to the .da file and close it. */
static int da_file_close ()
{
if (!actual_da_file)
return -1;
if (fwrite (actual_da_file_buffer, actual_da_file_length,
1, actual_da_file) != 1)
return da_file_error ();
if (fclose (actual_da_file))
{
actual_da_file = 0;
return -1;
}
actual_da_file = 0;
return 0;
}
/* Returns current position in .da file. */
static unsigned long
da_file_position (file)
FILE *file;
{
if (file)
return ftell (file);
return actual_da_file_position;
}
/* Tests whether we have reached end of .da file. */
static int
da_file_eof ()
{
return actual_da_file_position == actual_da_file_length;
}
/* Change position in the .da file. */
static int
da_file_seek (file, pos, whence)
FILE *file;
long pos;
int whence;
{
if (file)
return fseek (file, pos, whence);
if (!actual_da_file)
return -1;
switch (whence)
{
case SEEK_CUR:
if (pos < 0 && (unsigned long) -pos > actual_da_file_position)
return da_file_error ();
actual_da_file_position += pos;
break;
case SEEK_SET:
actual_da_file_position = pos;
break;
case SEEK_END:
if ((unsigned long) -pos > actual_da_file_length)
return da_file_error ();
actual_da_file_position = actual_da_file_length + pos;
}
if (actual_da_file_position > actual_da_file_length)
return da_file_error ();
return 0;
}
/* Write LEN chars of DATA to actual .da file; ELTS is expected to be 1,
FILE 0. */
static size_t
da_file_write (data, elts, len, file)
const void *data;
size_t elts;
size_t len;
FILE *file;
{
size_t l = len;
const char *dat = data;
if (file)
return fwrite (data, elts, len, file);
if (elts != 1)
abort ();
if (!actual_da_file)
return -1;
if (actual_da_file_position + len > actual_da_file_buffer_size)
{
actual_da_file_buffer_size = 2 * (actual_da_file_position + len);
actual_da_file_buffer = realloc (actual_da_file_buffer,
actual_da_file_buffer_size);
if (!actual_da_file_buffer)
return da_file_error ();
}
while (len--)
actual_da_file_buffer[actual_da_file_position++] = *dat++;
if (actual_da_file_position > actual_da_file_length)
actual_da_file_length = actual_da_file_position;
return l;
}
/* Read LEN chars of DATA from actual .da file; ELTS is expected to be 1,
FILE 0. */
static size_t
da_file_read (data, elts, len, file)
void *data;
size_t elts;
size_t len;
FILE *file;
{
size_t l;
char *dat = data;
if (file)
return fread (data, elts, len, file);
if (elts != 1)
abort ();
if (!actual_da_file)
return -1;
if (actual_da_file_position + len > actual_da_file_length)
len = actual_da_file_length - actual_da_file_position;
l = len;
while (len--)
*dat++ = actual_da_file_buffer[actual_da_file_position++];
return l;
}
/* Close the current .da file and report error. */
static int
da_file_error ()
{
if (actual_da_file)
fclose (actual_da_file);
actual_da_file = 0;
return -1;
}
#else /* !IN_LIBGCC2 */
static size_t
da_file_write (data, elts, len, file)
const void *data;
size_t elts;
size_t len;
FILE *file;
{
return fwrite (data, elts, len, file);
}
static size_t
da_file_read (data, elts, len, file)
void *data;
size_t elts;
size_t len;
FILE *file;
{
return fread (data, elts, len, file);
}
static unsigned long
da_file_position (file)
FILE *file;
{
return ftell (file);
}
static int
da_file_seek (file, pos, whence)
FILE *file;
long pos;
int whence;
{
return fseek (file, pos, whence);
}
#endif
#endif /* GCC_GCOV_IO_H */

View File

@ -41,12 +41,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
#include "gcov-io.h"
#include <string.h>
#if defined (TARGET_HAS_F_SETLKW)
#include <fcntl.h>
#include <errno.h>
#endif
#include "gcov-io.h"
/* Chain of per-object gcov structures. */
static struct gcov_info *gcov_list;
@ -106,7 +106,6 @@ gcov_exit (void)
for (ptr = gcov_list; ptr; ptr = ptr->next)
{
FILE *da_file;
struct gcov_summary object;
struct gcov_summary local_prg;
int merging = 0;
@ -154,39 +153,27 @@ gcov_exit (void)
memset (&object, 0, sizeof (object));
/* Open for modification */
if ((da_file = fopen (ptr->filename, "r+b")))
merging = 1;
else if ((da_file = fopen (ptr->filename, "w+b")))
;
else
if (!da_file_open (ptr->filename, &merging))
{
fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
ptr->filename = 0;
continue;
}
#if defined (TARGET_HAS_F_SETLKW)
/* After a fork, another process might try to read and/or write
the same file simultaneously. So if we can, lock the file to
avoid race conditions. */
while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
&& errno == EINTR)
continue;
#endif
if (merging)
{
/* Merge data from file. */
if (gcov_read_unsigned (da_file, &tag) || tag != GCOV_DATA_MAGIC)
if (gcov_read_unsigned (0, &tag) || tag != GCOV_DATA_MAGIC)
{
fprintf (stderr, "profiling:%s:Not a gcov data file\n",
ptr->filename);
read_fatal:;
fclose (da_file);
da_file_close ();
ptr->filename = 0;
continue;
}
if (gcov_read_unsigned (da_file, &length) || length != GCOV_VERSION)
if (gcov_read_unsigned (0, &length) || length != GCOV_VERSION)
{
gcov_version_mismatch (ptr, length);
goto read_fatal;
@ -196,8 +183,8 @@ gcov_exit (void)
for (ix = ptr->n_functions, fn_info = ptr->functions;
ix--; fn_info++)
{
if (gcov_read_unsigned (da_file, &tag)
|| gcov_read_unsigned (da_file, &length))
if (gcov_read_unsigned (0, &tag)
|| gcov_read_unsigned (0, &length))
{
read_error:;
fprintf (stderr, "profiling:%s:Error merging\n",
@ -214,9 +201,9 @@ gcov_exit (void)
goto read_fatal;
}
if (gcov_read_unsigned (da_file, &flength)
|| gcov_skip_string (da_file, flength)
|| gcov_read_unsigned (da_file, &checksum))
if (gcov_read_unsigned (0, &flength)
|| gcov_skip_string (0, flength)
|| gcov_read_unsigned (0, &checksum))
goto read_error;
if (flength != strlen (fn_info->name)
|| checksum != fn_info->checksum)
@ -227,46 +214,51 @@ gcov_exit (void)
f_sect_index < fn_info->n_counter_sections;
f_sect_index++)
{
if (gcov_read_unsigned (da_file, &tag)
|| gcov_read_unsigned (da_file, &length))
unsigned n_counters;
if (gcov_read_unsigned (0, &tag)
|| gcov_read_unsigned (0, &length))
goto read_error;
for (sect_index = 0;
sect_index < ptr->n_counter_sections;
sect_index++)
if (ptr->counter_sections[sect_index].tag == tag)
break;
if (fn_info->counter_sections[f_sect_index].tag != tag
|| sect_index == ptr->n_counter_sections
|| length / 8 != fn_info->counter_sections[f_sect_index].n_counters)
if (sect_index == ptr->n_counter_sections
|| fn_info->counter_sections[f_sect_index].tag != tag)
goto read_mismatch;
for (jx = fn_info->counter_sections[f_sect_index].n_counters;
jx--; counters[sect_index]++)
if (gcov_read_counter (da_file, &count))
goto read_error;
n_counters = fn_info->counter_sections[f_sect_index].n_counters;
if (n_counters != length / 8)
goto read_mismatch;
for (jx = 0; jx < n_counters; jx++)
if (gcov_read_counter (0, &count))
goto read_error;
else
*counters[sect_index] += count;
counters[sect_index][jx] += count;
counters[sect_index] += n_counters;
}
}
/* Check object summary */
if (gcov_read_unsigned (da_file, &tag)
|| gcov_read_unsigned (da_file, &length))
if (gcov_read_unsigned (0, &tag)
|| gcov_read_unsigned (0, &length))
goto read_error;
if (tag != GCOV_TAG_OBJECT_SUMMARY)
goto read_mismatch;
if (gcov_read_summary (da_file, &object))
if (gcov_read_summary (0, &object))
goto read_error;
/* Check program summary */
while (1)
{
long base = ftell (da_file);
long base = da_file_position (0);
if (gcov_read_unsigned (da_file, &tag)
|| gcov_read_unsigned (da_file, &length))
if (gcov_read_unsigned (0, &tag)
|| gcov_read_unsigned (0, &length))
{
if (feof (da_file))
if (da_file_eof ())
break;
goto read_error;
}
@ -274,7 +266,7 @@ gcov_exit (void)
&& tag != GCOV_TAG_PLACEHOLDER_SUMMARY
&& tag != GCOV_TAG_INCORRECT_SUMMARY)
goto read_mismatch;
if (gcov_read_summary (da_file, &local_prg))
if (gcov_read_summary (0, &local_prg))
goto read_error;
if (local_prg.checksum != program.checksum)
continue;
@ -301,7 +293,7 @@ gcov_exit (void)
ptr->wkspc = base;
break;
}
fseek (da_file, 0, SEEK_SET);
da_file_seek (0, 0, SEEK_SET);
}
object.runs++;
@ -313,12 +305,12 @@ gcov_exit (void)
/* Write out the data. */
if (/* magic */
gcov_write_unsigned (da_file, GCOV_DATA_MAGIC)
gcov_write_unsigned (0, GCOV_DATA_MAGIC)
/* version number */
|| gcov_write_unsigned (da_file, GCOV_VERSION))
|| gcov_write_unsigned (0, GCOV_VERSION))
{
write_error:;
fclose (da_file);
da_file_close ();
fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
ptr->filename = 0;
continue;
@ -330,14 +322,14 @@ gcov_exit (void)
for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
{
/* Announce function. */
if (gcov_write_unsigned (da_file, GCOV_TAG_FUNCTION)
|| !(base = gcov_reserve_length (da_file))
if (gcov_write_unsigned (0, GCOV_TAG_FUNCTION)
|| !(base = gcov_reserve_length (0))
/* function name */
|| gcov_write_string (da_file, fn_info->name,
|| gcov_write_string (0, fn_info->name,
strlen (fn_info->name))
/* function checksum */
|| gcov_write_unsigned (da_file, fn_info->checksum)
|| gcov_write_length (da_file, base))
|| gcov_write_unsigned (0, fn_info->checksum)
|| gcov_write_length (0, base))
goto write_error;
/* counters. */
@ -354,8 +346,8 @@ gcov_exit (void)
if (sect_index == ptr->n_counter_sections)
abort ();
if (gcov_write_unsigned (da_file, tag)
|| !(base = gcov_reserve_length (da_file)))
if (gcov_write_unsigned (0, tag)
|| !(base = gcov_reserve_length (0)))
goto write_error;
for (jx = fn_info->counter_sections[f_sect_index].n_counters; jx--;)
@ -368,43 +360,41 @@ gcov_exit (void)
if (object.arc_max_sum < count)
object.arc_max_sum = count;
}
if (gcov_write_counter (da_file, count))
if (gcov_write_counter (0, count))
goto write_error; /* RIP Edsger Dijkstra */
}
if (gcov_write_length (da_file, base))
if (gcov_write_length (0, base))
goto write_error;
}
}
/* Object file summary. */
if (gcov_write_summary (da_file, GCOV_TAG_OBJECT_SUMMARY, &object))
if (gcov_write_summary (0, GCOV_TAG_OBJECT_SUMMARY, &object))
goto write_error;
if (merging >= 0)
{
if (fseek (da_file, 0, SEEK_END))
if (da_file_seek (0, 0, SEEK_END))
goto write_error;
ptr->wkspc = ftell (da_file);
if (gcov_write_summary (da_file, GCOV_TAG_PLACEHOLDER_SUMMARY,
ptr->wkspc = da_file_position (0);
if (gcov_write_summary (0, GCOV_TAG_PLACEHOLDER_SUMMARY,
&program))
goto write_error;
}
else if (ptr->wkspc)
{
/* Zap trailing program summary */
if (fseek (da_file, ptr->wkspc, SEEK_SET))
if (da_file_seek (0, ptr->wkspc, SEEK_SET))
goto write_error;
if (!local_prg.runs)
ptr->wkspc = 0;
if (gcov_write_unsigned (da_file,
local_prg.runs ? GCOV_TAG_PLACEHOLDER_SUMMARY
: GCOV_TAG_INCORRECT_SUMMARY))
if (gcov_write_unsigned (0, local_prg.runs
? GCOV_TAG_PLACEHOLDER_SUMMARY
: GCOV_TAG_INCORRECT_SUMMARY))
goto write_error;
}
if (fflush (da_file))
goto write_error;
if (fclose (da_file))
if (da_file_close ())
{
fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
ptr->filename = 0;