summaryrefslogtreecommitdiff
path: root/gcc/gcov-io.h
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2003-03-04 20:56:24 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2003-03-04 20:56:24 +0000
commit2dcd3a4d10c167ae6dd11f565ea2568e636d161d (patch)
tree9d5d6ef4d35ecaea4dd2bfdfb63a27fc5e81d9de /gcc/gcov-io.h
parentc0b4b46336c29f8da5c10ba64e64255996e35aab (diff)
downloadgcc-2dcd3a4d10c167ae6dd11f565ea2568e636d161d.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@63800 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gcov-io.h')
-rw-r--r--gcc/gcov-io.h326
1 files changed, 310 insertions, 16 deletions
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index ce29f67c8cb..4fcd7de5d21 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -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 */