mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-17 13:10:12 +08:00
2011-07-26 Paul Pluzhnikov <ppluzhnikov@google.com>
* NEWS: Mention dcache configuration. * dcache.c (dcache_set_list, dcache_show_list): New variables. (dcache_size, dcache_line_size): New variables. (LINE_SIZE_MASK, XFORM, MASK): Adjust. (struct dcache_block): Make it expandable. (struct dcache_struct): New field. (dcache_invalidate): Discard freelist upon dcache_line_size changes. (dcache_hit, dcache_alloc, dcache_peek_byte): Adjust. (dcache_poke_byte, dcache_print_line): Adjust. (set_dcache_size, set_dcache_line_size): New functions. (set_dcache_command, show_dcache_command): New functions. (_initialize_dcache): Add new commands. doc/ChangeLog: 2011-07-26 Paul Pluzhnikov <ppluzhnikov@google.com> * gdb.texinfo (Caching Remote Data): Document {set,show} dcache size and line-size.
This commit is contained in:
parent
2eff07b325
commit
1a532630dc
@ -1,3 +1,18 @@
|
||||
2011-07-26 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
* NEWS: Mention dcache configuration.
|
||||
* dcache.c (dcache_set_list, dcache_show_list): New variables.
|
||||
(dcache_size, dcache_line_size): New variables.
|
||||
(LINE_SIZE_MASK, XFORM, MASK): Adjust.
|
||||
(struct dcache_block): Make it expandable.
|
||||
(struct dcache_struct): New field.
|
||||
(dcache_invalidate): Discard freelist upon dcache_line_size changes.
|
||||
(dcache_hit, dcache_alloc, dcache_peek_byte): Adjust.
|
||||
(dcache_poke_byte, dcache_print_line): Adjust.
|
||||
(set_dcache_size, set_dcache_line_size): New functions.
|
||||
(set_dcache_command, show_dcache_command): New functions.
|
||||
(_initialize_dcache): Add new commands.
|
||||
|
||||
2011-07-26 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
* progspace.h (struct program_space): Add solib_add_generation.
|
||||
|
3
gdb/NEWS
3
gdb/NEWS
@ -74,6 +74,9 @@ QTDisable
|
||||
|
||||
Dynamically disable a tracepoint in a started trace experiment.
|
||||
|
||||
* Dcache size (number of lines) and line-size are now runtime-configurable
|
||||
via "set dcache line" and "set dcache line-size" commands.
|
||||
|
||||
*** Changes in GDB 7.3
|
||||
|
||||
* GDB has a new command: "thread find [REGEXP]".
|
||||
|
168
gdb/dcache.c
168
gdb/dcache.c
@ -27,6 +27,10 @@
|
||||
#include "inferior.h"
|
||||
#include "splay-tree.h"
|
||||
|
||||
/* Commands with a prefix of `{set,show} dcache'. */
|
||||
static struct cmd_list_element *dcache_set_list = NULL;
|
||||
static struct cmd_list_element *dcache_show_list = NULL;
|
||||
|
||||
/* The data cache could lead to incorrect results because it doesn't
|
||||
know about volatile variables, thus making it impossible to debug
|
||||
functions which use memory mapped I/O devices. Set the nocache
|
||||
@ -71,20 +75,21 @@
|
||||
|
||||
/* The maximum number of lines stored. The total size of the cache is
|
||||
equal to DCACHE_SIZE times LINE_SIZE. */
|
||||
#define DCACHE_SIZE 4096
|
||||
#define DCACHE_DEFAULT_SIZE 4096
|
||||
static unsigned dcache_size = DCACHE_DEFAULT_SIZE;
|
||||
|
||||
/* The size of a cache line. Smaller values reduce the time taken to
|
||||
/* The default size of a cache line. Smaller values reduce the time taken to
|
||||
read a single byte and make the cache more granular, but increase
|
||||
overhead and reduce the effectiveness of the cache as a prefetcher. */
|
||||
#define LINE_SIZE_POWER 6
|
||||
#define LINE_SIZE (1 << LINE_SIZE_POWER)
|
||||
#define DCACHE_DEFAULT_LINE_SIZE 64
|
||||
static unsigned dcache_line_size = DCACHE_DEFAULT_LINE_SIZE;
|
||||
|
||||
/* Each cache block holds LINE_SIZE bytes of data
|
||||
starting at a multiple-of-LINE_SIZE address. */
|
||||
|
||||
#define LINE_SIZE_MASK ((LINE_SIZE - 1))
|
||||
#define XFORM(x) ((x) & LINE_SIZE_MASK)
|
||||
#define MASK(x) ((x) & ~LINE_SIZE_MASK)
|
||||
#define LINE_SIZE_MASK(dcache) ((dcache->line_size - 1))
|
||||
#define XFORM(dcache, x) ((x) & LINE_SIZE_MASK (dcache))
|
||||
#define MASK(dcache, x) ((x) & ~LINE_SIZE_MASK (dcache))
|
||||
|
||||
struct dcache_block
|
||||
{
|
||||
@ -93,8 +98,8 @@ struct dcache_block
|
||||
struct dcache_block *next;
|
||||
|
||||
CORE_ADDR addr; /* address of data */
|
||||
gdb_byte data[LINE_SIZE]; /* bytes at given address */
|
||||
int refs; /* # hits */
|
||||
gdb_byte data[1]; /* line_size bytes at given address */
|
||||
};
|
||||
|
||||
struct dcache_struct
|
||||
@ -108,6 +113,7 @@ struct dcache_struct
|
||||
|
||||
/* The number of in-use lines in the cache. */
|
||||
int size;
|
||||
CORE_ADDR line_size; /* current line_size. */
|
||||
|
||||
/* The ptid of last inferior to use cache or null_ptid. */
|
||||
ptid_t ptid;
|
||||
@ -207,6 +213,29 @@ for_each_block (struct dcache_block **blist, block_func *func, void *param)
|
||||
while (*blist && db != *blist);
|
||||
}
|
||||
|
||||
/* BLOCK_FUNC routine for dcache_free. */
|
||||
|
||||
static void
|
||||
free_block (struct dcache_block *block, void *param)
|
||||
{
|
||||
xfree (block);
|
||||
}
|
||||
|
||||
/* Free a data cache. */
|
||||
|
||||
void
|
||||
dcache_free (DCACHE *dcache)
|
||||
{
|
||||
if (last_cache == dcache)
|
||||
last_cache = NULL;
|
||||
|
||||
splay_tree_delete (dcache->tree);
|
||||
for_each_block (&dcache->oldest, free_block, NULL);
|
||||
for_each_block (&dcache->freelist, free_block, NULL);
|
||||
xfree (dcache);
|
||||
}
|
||||
|
||||
|
||||
/* BLOCK_FUNC function for dcache_invalidate.
|
||||
This doesn't remove the block from the oldest list on purpose.
|
||||
dcache_invalidate will do it later. */
|
||||
@ -230,6 +259,16 @@ dcache_invalidate (DCACHE *dcache)
|
||||
dcache->oldest = NULL;
|
||||
dcache->size = 0;
|
||||
dcache->ptid = null_ptid;
|
||||
|
||||
if (dcache->line_size != dcache_line_size)
|
||||
{
|
||||
/* We've been asked to use a different line size.
|
||||
All of our freelist blocks are now the wrong size, so free them. */
|
||||
|
||||
for_each_block (&dcache->freelist, free_block, dcache);
|
||||
dcache->freelist = NULL;
|
||||
dcache->line_size = dcache_line_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalidate the line associated with ADDR. */
|
||||
@ -257,7 +296,7 @@ dcache_hit (DCACHE *dcache, CORE_ADDR addr)
|
||||
struct dcache_block *db;
|
||||
|
||||
splay_tree_node node = splay_tree_lookup (dcache->tree,
|
||||
(splay_tree_key) MASK (addr));
|
||||
(splay_tree_key) MASK (dcache, addr));
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
@ -281,7 +320,7 @@ dcache_read_line (DCACHE *dcache, struct dcache_block *db)
|
||||
int reg_len;
|
||||
struct mem_region *region;
|
||||
|
||||
len = LINE_SIZE;
|
||||
len = dcache->line_size;
|
||||
memaddr = db->addr;
|
||||
myaddr = db->data;
|
||||
|
||||
@ -325,7 +364,7 @@ dcache_alloc (DCACHE *dcache, CORE_ADDR addr)
|
||||
{
|
||||
struct dcache_block *db;
|
||||
|
||||
if (dcache->size >= DCACHE_SIZE)
|
||||
if (dcache->size >= dcache_size)
|
||||
{
|
||||
/* Evict the least recently allocated line. */
|
||||
db = dcache->oldest;
|
||||
@ -339,12 +378,13 @@ dcache_alloc (DCACHE *dcache, CORE_ADDR addr)
|
||||
if (db)
|
||||
remove_block (&dcache->freelist, db);
|
||||
else
|
||||
db = xmalloc (sizeof (struct dcache_block));
|
||||
db = xmalloc (offsetof (struct dcache_block, data) +
|
||||
dcache->line_size);
|
||||
|
||||
dcache->size++;
|
||||
}
|
||||
|
||||
db->addr = MASK (addr);
|
||||
db->addr = MASK (dcache, addr);
|
||||
db->refs = 0;
|
||||
|
||||
/* Put DB at the end of the list, it's the newest. */
|
||||
@ -374,7 +414,7 @@ dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ptr = db->data[XFORM (addr)];
|
||||
*ptr = db->data[XFORM (dcache, addr)];
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -395,7 +435,7 @@ dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr)
|
||||
struct dcache_block *db = dcache_hit (dcache, addr);
|
||||
|
||||
if (db)
|
||||
db->data[XFORM (addr)] = *ptr;
|
||||
db->data[XFORM (dcache, addr)] = *ptr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -427,33 +467,13 @@ dcache_init (void)
|
||||
dcache->oldest = NULL;
|
||||
dcache->freelist = NULL;
|
||||
dcache->size = 0;
|
||||
dcache->line_size = dcache_line_size;
|
||||
dcache->ptid = null_ptid;
|
||||
last_cache = dcache;
|
||||
|
||||
return dcache;
|
||||
}
|
||||
|
||||
/* BLOCK_FUNC routine for dcache_free. */
|
||||
|
||||
static void
|
||||
free_block (struct dcache_block *block, void *param)
|
||||
{
|
||||
free (block);
|
||||
}
|
||||
|
||||
/* Free a data cache. */
|
||||
|
||||
void
|
||||
dcache_free (DCACHE *dcache)
|
||||
{
|
||||
if (last_cache == dcache)
|
||||
last_cache = NULL;
|
||||
|
||||
splay_tree_delete (dcache->tree);
|
||||
for_each_block (&dcache->oldest, free_block, NULL);
|
||||
for_each_block (&dcache->freelist, free_block, NULL);
|
||||
xfree (dcache);
|
||||
}
|
||||
|
||||
/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
|
||||
to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
|
||||
@ -571,12 +591,12 @@ dcache_print_line (int index)
|
||||
printf_filtered (_("Line %d: address %s [%d hits]\n"),
|
||||
index, paddress (target_gdbarch, db->addr), db->refs);
|
||||
|
||||
for (j = 0; j < LINE_SIZE; j++)
|
||||
for (j = 0; j < last_cache->line_size; j++)
|
||||
{
|
||||
printf_filtered ("%02x ", db->data[j]);
|
||||
|
||||
/* Print a newline every 16 bytes (48 characters). */
|
||||
if ((j % 16 == 15) && (j != LINE_SIZE - 1))
|
||||
if ((j % 16 == 15) && (j != last_cache->line_size - 1))
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
printf_filtered ("\n");
|
||||
@ -603,8 +623,10 @@ dcache_info (char *exp, int tty)
|
||||
return;
|
||||
}
|
||||
|
||||
printf_filtered (_("Dcache line width %d, maximum size %d\n"),
|
||||
LINE_SIZE, DCACHE_SIZE);
|
||||
printf_filtered (_("Dcache %u lines of %u bytes each.\n"),
|
||||
dcache_size,
|
||||
last_cache ? (unsigned) last_cache->line_size
|
||||
: dcache_line_size);
|
||||
|
||||
if (!last_cache || ptid_equal (last_cache->ptid, null_ptid))
|
||||
{
|
||||
@ -635,6 +657,48 @@ dcache_info (char *exp, int tty)
|
||||
printf_filtered (_("Cache state: %d active lines, %d hits\n"), i, refcount);
|
||||
}
|
||||
|
||||
static void
|
||||
set_dcache_size (char *args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
if (dcache_size == 0)
|
||||
{
|
||||
dcache_size = DCACHE_DEFAULT_SIZE;
|
||||
error (_("Dcache size must be greater than 0."));
|
||||
}
|
||||
if (last_cache)
|
||||
dcache_invalidate (last_cache);
|
||||
}
|
||||
|
||||
static void
|
||||
set_dcache_line_size (char *args, int from_tty,
|
||||
struct cmd_list_element *c)
|
||||
{
|
||||
if (dcache_line_size < 2
|
||||
|| (dcache_line_size & (dcache_line_size - 1)) != 0)
|
||||
{
|
||||
unsigned d = dcache_line_size;
|
||||
dcache_line_size = DCACHE_DEFAULT_LINE_SIZE;
|
||||
error (_("Invalid dcache line size: %u (must be power of 2)."), d);
|
||||
}
|
||||
if (last_cache)
|
||||
dcache_invalidate (last_cache);
|
||||
}
|
||||
|
||||
static void
|
||||
set_dcache_command (char *arg, int from_tty)
|
||||
{
|
||||
printf_unfiltered (
|
||||
"\"set dcache\" must be followed by the name of a subcommand.\n");
|
||||
help_list (dcache_set_list, "set dcache ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
show_dcache_command (char *args, int from_tty)
|
||||
{
|
||||
cmd_show_list (dcache_show_list, from_tty, "");
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_dcache (void)
|
||||
{
|
||||
@ -656,4 +720,28 @@ Print information on the dcache performance.\n\
|
||||
With no arguments, this command prints the cache configuration and a\n\
|
||||
summary of each line in the cache. Use \"info dcache <lineno> to dump\"\n\
|
||||
the contents of a given line."));
|
||||
|
||||
add_prefix_cmd ("dcache", class_obscure, set_dcache_command, _("\
|
||||
Use this command to set number of lines in dcache and line-size."),
|
||||
&dcache_set_list, "set dcache ", /*allow_unknown*/0, &setlist);
|
||||
add_prefix_cmd ("dcache", class_obscure, show_dcache_command, _("\
|
||||
Show dcachesettings."),
|
||||
&dcache_show_list, "show dcache ", /*allow_unknown*/0, &showlist);
|
||||
|
||||
add_setshow_uinteger_cmd ("line-size", class_obscure,
|
||||
&dcache_line_size, _("\
|
||||
Set dcache line size in bytes (must be power of 2)."), _("\
|
||||
Show dcache line size."),
|
||||
NULL,
|
||||
set_dcache_line_size,
|
||||
NULL,
|
||||
&dcache_set_list, &dcache_show_list);
|
||||
add_setshow_uinteger_cmd ("size", class_obscure,
|
||||
&dcache_size, _("\
|
||||
Set number of dcache lines."), _("\
|
||||
Show number of dcache lines."),
|
||||
NULL,
|
||||
set_dcache_size,
|
||||
NULL,
|
||||
&dcache_set_list, &dcache_show_list);
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
2011-07-26 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
* gdb.texinfo (Caching Remote Data): Document {set,show} dcache
|
||||
size and line-size.
|
||||
|
||||
2011-07-21 Matt Rice <ratmice@gmail.com>
|
||||
|
||||
PR macros/12999
|
||||
|
@ -9332,6 +9332,26 @@ operation.
|
||||
|
||||
If a line number is specified, the contents of that line will be
|
||||
printed in hex.
|
||||
|
||||
@item set dcache size @var{size}
|
||||
@cindex dcache size
|
||||
@kindex set dcache size
|
||||
Set maximum number of entries in dcache (dcache depth above).
|
||||
|
||||
@item set dcache line-size @var{line-size}
|
||||
@cindex dcache line-size
|
||||
@kindex set dcache line-size
|
||||
Set number of bytes each dcache entry caches (dcache width above).
|
||||
Must be a power of 2.
|
||||
|
||||
@item show dcache size
|
||||
@kindex show dcache size
|
||||
Show maximum number of dcache entries. See also @ref{Caching Remote Data, info dcache}.
|
||||
|
||||
@item show dcache line-size
|
||||
@kindex show dcache line-size
|
||||
Show default size of dcache lines. See also @ref{Caching Remote Data, info dcache}.
|
||||
|
||||
@end table
|
||||
|
||||
@node Searching Memory
|
||||
|
Loading…
Reference in New Issue
Block a user