Implement TARGET_OBJECT_STACK_MEMORY.

* NEWS: Add note on new "set stack-cache" option.
	* corefile.c (read_stack): New function.
	* dcache.c (dcache_struct): New member ptid.
	(dcache_enable_p): Mark as obsolete.
	(show_dcache_enabled_p): Flag option as deprecated.
	(dcache_invalidate): Update ptid.
	(dcache_invalidate_line): New function.
	(dcache_read_line): No longer check cacheable attribute, stack
	accesses get cached despite attribute.
	(dcache_init): Set ptid.
	(dcache_xfer_memory): Flush cache if from different ptid than before.
	Update cache after write.
	(dcache_update): New function.
	(dcache_info): Report ptid.
	(_initialize_dcache): Update text for `remotecache' to indicate it
	is obsolete.
	* dcache.h (dcache_update): Declare.
	* dwarf2loc.c (dwarf2_evaluate_loc_desc): Mark values on stack with
	set_value_stack.
	* frame-unwind.c (frame_unwind_got_memory): Ditto.
	* gdbcore.h (read_stack): Declare.
	* memattr.c (mem_enable_command): Call target_dcache_invalidate
	instead of dcache_invalidate.
	(mem_disable_command, mem_delete_command): Ditto.
	* target.c (stack_cache_enabled_p_1): New static global.
	(stack_cache_enabled_p): New static global.
	(set_stack_cache_enabled_p): New function.
	(show_stack_cache_enabled_p): New function.
	(target_dcache): Make static.
	(target_dcache_invalidate): New function.
	(target_load, target_resume): Call target_dcache_invalidate
	instead of dcache_invalidate.
	(memory_xfer_partial): New arg object, all callers updated.
	Check for existing inferior before calling dcache routines.
	When writing non-TARGET_OBJECT_STACK_MEMORY, notify dcache.
	(target_xfer_partial): Call memory_xfer_partial for
	TARGET_OBJECT_STACK_MEMORY.
	(target_read_stack): New function.
	(initialize_targets): Install new option `stack-cache'.
	* target.h: Remove #include of dcache.h.
	(enum target_object): New value TARGET_OBJECT_STACK_MEMORY.
	(target_dcache): Delete.
	(target_dcache_invalidate): Declare.
	(target_read_stack): Declare.
	* top.c (prepare_execute_command): New function.
	(execute_command): Call prepare_execute_command
	instead of free_all_values.
	* top.h (prepare_execute_command): Declare.
	* valops.c (get_value_at): New function.
	(value_at): Guts moved to get_value_at.
	(value_at_lazy): Similarly.
	(value_fetch_lazy): Call read_stack for stack values.
	* value.c (struct value): New member `stack'.
	(value_stack, set_value_stack): New functions.
	* value.h (value_stack, set_value_stack): Declare.
	* mi/mi-main.c (mi_cmd_execute): Call prepare_execute_command
	instead of free_all_values.

	doc/
	* gdb.texinfo (Caching Data of Remote Targets): Update text.
	Mark `set/show remotecache' options as obsolete.
	Document new `set/show stack-cache' option.
	Update text for `info dcache'.
This commit is contained in:
Doug Evans
2009-08-31 20:18:46 +00:00
parent f1c2d4afbe
commit 4e5d721fc0
19 changed files with 378 additions and 71 deletions

View File

@@ -210,7 +210,45 @@ show_targetdebug (struct ui_file *file, int from_tty,
static void setup_target_debug (void);
DCACHE *target_dcache;
/* The option sets this. */
static int stack_cache_enabled_p_1 = 1;
/* And set_stack_cache_enabled_p updates this.
The reason for the separation is so that we don't flush the cache for
on->on transitions. */
static int stack_cache_enabled_p = 1;
/* This is called *after* the stack-cache has been set.
Flush the cache for off->on and on->off transitions.
There's no real need to flush the cache for on->off transitions,
except cleanliness. */
static void
set_stack_cache_enabled_p (char *args, int from_tty,
struct cmd_list_element *c)
{
if (stack_cache_enabled_p != stack_cache_enabled_p_1)
target_dcache_invalidate ();
stack_cache_enabled_p = stack_cache_enabled_p_1;
}
static void
show_stack_cache_enabled_p (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("Cache use for stack accesses is %s.\n"), value);
}
/* Cache of memory operations, to speed up remote access. */
static DCACHE *target_dcache;
/* Invalidate the target dcache. */
void
target_dcache_invalidate (void)
{
dcache_invalidate (target_dcache);
}
/* The user just typed 'target' without the name of a target. */
@@ -413,7 +451,7 @@ target_kill (void)
void
target_load (char *arg, int from_tty)
{
dcache_invalidate (target_dcache);
target_dcache_invalidate ();
(*current_target.to_load) (arg, from_tty);
}
@@ -1143,12 +1181,14 @@ target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
value are just as for target_xfer_partial. */
static LONGEST
memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf,
ULONGEST memaddr, LONGEST len)
memory_xfer_partial (struct target_ops *ops, enum target_object object,
void *readbuf, const void *writebuf, ULONGEST memaddr,
LONGEST len)
{
LONGEST res;
int reg_len;
struct mem_region *region;
struct inferior *inf;
/* Zero length requests are ok and require no work. */
if (len == 0)
@@ -1223,7 +1263,11 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
return -1;
}
if (region->attrib.cache)
inf = find_inferior_pid (ptid_get_pid (inferior_ptid));
if (inf != NULL
&& (region->attrib.cache
|| (stack_cache_enabled_p && object == TARGET_OBJECT_STACK_MEMORY)))
{
if (readbuf != NULL)
res = dcache_xfer_memory (ops, target_dcache, memaddr, readbuf,
@@ -1245,6 +1289,19 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
}
}
/* Make sure the cache gets updated no matter what - if we are writing
to the stack, even if this write is not tagged as such, we still need
to update the cache. */
if (inf != NULL
&& readbuf == NULL
&& !region->attrib.cache
&& stack_cache_enabled_p
&& object != TARGET_OBJECT_STACK_MEMORY)
{
dcache_update (target_dcache, memaddr, (void *) writebuf, reg_len);
}
/* If none of those methods found the memory we wanted, fall back
to a target partial transfer. Normally a single call to
to_xfer_partial is enough; if it doesn't recognize an object
@@ -1308,8 +1365,9 @@ target_xfer_partial (struct target_ops *ops,
/* If this is a memory transfer, let the memory-specific code
have a look at it instead. Memory transfers are more
complicated. */
if (object == TARGET_OBJECT_MEMORY)
retval = memory_xfer_partial (ops, readbuf, writebuf, offset, len);
if (object == TARGET_OBJECT_MEMORY || object == TARGET_OBJECT_STACK_MEMORY)
retval = memory_xfer_partial (ops, object, readbuf,
writebuf, offset, len);
else
{
enum target_object raw_object = object;
@@ -1391,6 +1449,23 @@ target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
return EIO;
}
/* Like target_read_memory, but specify explicitly that this is a read from
the target's stack. This may trigger different cache behavior. */
int
target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
{
/* Dispatch to the topmost target, not the flattened current_target.
Memory accesses check target->to_has_(all_)memory, and the
flattened target doesn't inherit those. */
if (target_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL,
myaddr, memaddr, len) == len)
return 0;
else
return EIO;
}
int
target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
{
@@ -2055,7 +2130,7 @@ target_resume (ptid_t ptid, int step, enum target_signal signal)
{
struct target_ops *t;
dcache_invalidate (target_dcache);
target_dcache_invalidate ();
for (t = current_target.beneath; t != NULL; t = t->beneath)
{
@@ -3479,5 +3554,16 @@ Tells gdb whether to control the inferior in asynchronous mode."),
&setlist,
&showlist);
add_setshow_boolean_cmd ("stack-cache", class_support,
&stack_cache_enabled_p, _("\
Set cache use for stack access."), _("\
Show cache use for stack access."), _("\
When on, use the data cache for all stack access, regardless of any\n\
configured memory regions. This improves remote performance significantly.\n\
By default, caching for stack access is on."),
set_stack_cache_enabled_p,
show_stack_cache_enabled_p,
&setlist, &showlist);
target_dcache = dcache_init ();
}