From: Paul Pluzhnikov Date: Tue, 26 Jul 2011 15:24:02 +0000 (+0000) Subject: 2011-07-26 Paul Pluzhnikov X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1a532630dc4d78abd1ddf6e4a97e789dad88787d;p=binutils-gdb.git 2011-07-26 Paul Pluzhnikov * 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 * gdb.texinfo (Caching Remote Data): Document {set,show} dcache size and line-size. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 41dc0b2ea6a..207acdc54a2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2011-07-26 Paul Pluzhnikov + + * 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 * progspace.h (struct program_space): Add solib_add_generation. diff --git a/gdb/NEWS b/gdb/NEWS index 263b70b5539..f1c255cfff4 100644 --- a/gdb/NEWS +++ b/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]". diff --git a/gdb/dcache.c b/gdb/dcache.c index 0f034705a03..bcc7bf455ce 100644 --- a/gdb/dcache.c +++ b/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 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); } diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 34590f6c931..b636a95f601 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2011-07-26 Paul Pluzhnikov + + * gdb.texinfo (Caching Remote Data): Document {set,show} dcache + size and line-size. + 2011-07-21 Matt Rice PR macros/12999 diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 16bb6bc7f52..b5cfc7d8a3d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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