X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fregcache.c;h=adffa415e5bda2c2c5af9327f8a13ce844561957;hb=refs%2Fheads%2Finferior-thread-map-2019-12-18;hp=6e3eee96631e0a397eccb1605af1ffda6aa9af97;hpb=0747795c085d3b2a35da6bb474f32c58ce1b70c8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/regcache.c b/gdb/regcache.c index 6e3eee9663..adffa415e5 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -168,7 +168,7 @@ register_size (struct gdbarch *gdbarch, int regnum) return size; } -/* See common/common-regcache.h. */ +/* See gdbsupport/common-regcache.h. */ int regcache_register_size (const struct regcache *regcache, int n) @@ -284,7 +284,7 @@ regcache::restore (readonly_detached_regcache *src) } } -/* See common/common-regcache.h. */ +/* See gdbsupport/common-regcache.h. */ enum register_status reg_buffer::get_register_status (int regnum) const @@ -317,21 +317,58 @@ reg_buffer::assert_regnum (int regnum) const recording if the register values have been changed (eg. by the user). Therefore all registers must be written back to the target when appropriate. */ -std::forward_list regcache::current_regcache; + +/* Key for the hash map keeping the regcaches. */ + +struct ptid_arch +{ + ptid_arch (ptid_t ptid, gdbarch *arch) + : ptid (ptid), arch (arch) + {} + + ptid_t ptid; + gdbarch *arch; + + bool operator== (const ptid_arch &other) const + { + return this->ptid == other.ptid && this->arch == other.arch; + } +}; + +/* Hash function for ptid_arch. */ + +struct hash_ptid_arch +{ + size_t operator() (const ptid_arch &val) const + { + hash_ptid h_ptid; + std::hash h_long; + return h_ptid (val.ptid) + h_long ((long) val.arch); + } +}; + +using ptid_arch_regcache_map = std::unordered_map; + +/* Hash map containing the regcaches. */ + +static ptid_arch_regcache_map the_regcaches; struct regcache * -get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch, +get_thread_arch_aspace_regcache (ptid_t ptid, gdbarch *arch, struct address_space *aspace) { - for (const auto ®cache : regcache::current_regcache) - if (regcache->ptid () == ptid && regcache->arch () == gdbarch) - return regcache; + /* Look up a regcache for this (ptid, arch). */ + ptid_arch key (ptid, arch); + auto it = the_regcaches.find (key); + if (it != the_regcaches.end ()) + return it->second; - regcache *new_regcache = new regcache (gdbarch, aspace); - - regcache::current_regcache.push_front (new_regcache); + /* It does not exist, create it. */ + regcache *new_regcache = new regcache (arch, aspace); new_regcache->set_ptid (ptid); + the_regcaches[key] = new_regcache; + return new_regcache; } @@ -372,7 +409,7 @@ get_current_regcache (void) return get_thread_regcache (inferior_thread ()); } -/* See common/common-regcache.h. */ +/* See gdbsupport/common-regcache.h. */ struct regcache * get_thread_regcache_for_ptid (ptid_t ptid) @@ -390,13 +427,32 @@ regcache_observer_target_changed (struct target_ops *target) /* Update global variables old ptids to hold NEW_PTID if they were holding OLD_PTID. */ -void -regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) +static void +regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) { - for (auto ®cache : regcache::current_regcache) + std::vector keys_to_update; + + /* Find all the regcaches to updates. */ + for (auto &pair : the_regcaches) + { + regcache *rc = pair.second; + if (rc->ptid () == old_ptid) + keys_to_update.push_back (pair.first); + } + + for (const ptid_arch &old_key : keys_to_update) { - if (regcache->ptid () == old_ptid) - regcache->set_ptid (new_ptid); + /* Get the regcache, delete the hash map entry. */ + auto it = the_regcaches.find (old_key); + gdb_assert (it != the_regcaches.end ()); + regcache *rc = it->second; + + the_regcaches.erase (it); + + /* Insert the regcache back, with an updated key. */ + ptid_arch new_key (new_ptid, rc->arch ()); + rc->set_ptid (new_ptid); + the_regcaches[new_key] = rc; } } @@ -414,18 +470,17 @@ regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) void registers_changed_ptid (ptid_t ptid) { - for (auto oit = regcache::current_regcache.before_begin (), - it = std::next (oit); - it != regcache::current_regcache.end (); - ) + for (auto iter = the_regcaches.begin (); iter != the_regcaches.end (); ) { - if ((*it)->ptid ().matches (ptid)) + regcache *rc = iter->second; + + if (rc->ptid ().matches (ptid)) { - delete *it; - it = regcache::current_regcache.erase_after (oit); + delete iter->second; + iter = the_regcaches.erase (iter); } else - oit = it++; + ++iter; } if (current_thread_ptid.matches (ptid)) @@ -454,13 +509,6 @@ void registers_changed (void) { registers_changed_ptid (minus_one_ptid); - - /* Force cleanup of any alloca areas if using C alloca instead of - a builtin alloca. This particular call is used to clean up - areas allocated by low level target code which may build up - during lengthy interactions between gdb and the target before - gdb gives control to the user (ie watchpoints). */ - alloca (0); } void @@ -938,7 +986,7 @@ regcache::cooked_write_part (int regnum, int offset, int len, write_part (regnum, offset, len, buf, false); } -/* See common/common-regcache.h. */ +/* See gdbsupport/common-regcache.h. */ void reg_buffer::raw_supply (int regnum, const void *buf) @@ -1003,7 +1051,7 @@ reg_buffer::raw_supply_zeroed (int regnum) m_register_status[regnum] = REG_VALID; } -/* See common/common-regcache.h. */ +/* See gdbsupport/common-regcache.h. */ void reg_buffer::raw_collect (int regnum, void *buf) const @@ -1155,7 +1203,7 @@ regcache::collect_regset (const struct regset *regset, transfer_regset (regset, nullptr, regnum, nullptr, (gdb_byte *) buf, size); } -/* See common/common-regcache.h. */ +/* See gdbsupport/common-regcache.h. */ bool reg_buffer::raw_compare (int regnum, const void *buf, int offset) const @@ -1387,7 +1435,7 @@ register_dump::dump (ui_file *file) } #if GDB_SELF_TEST -#include "common/selftest.h" +#include "gdbsupport/selftest.h" #include "selftest-arch.h" #include "target-float.h" @@ -1402,8 +1450,7 @@ public: static size_t current_regcache_size () { - return std::distance (regcache::current_regcache.begin (), - regcache::current_regcache.end ()); + return the_regcaches.size (); } }; @@ -1542,6 +1589,7 @@ cooked_read_test (struct gdbarch *gdbarch) mock_inferior.gdbarch = gdbarch; mock_inferior.aspace = &mock_aspace; thread_info mock_thread (&mock_inferior, mock_ptid); + mock_inferior.thread_map[mock_ptid] = &mock_thread; /* Add the mock inferior to the inferior list so that look ups by target+ptid can find it. */ @@ -1612,10 +1660,7 @@ cooked_read_test (struct gdbarch *gdbarch) SELF_CHECK (mock_target.fetch_registers_called == 0); SELF_CHECK (mock_target.store_registers_called == 0); - - /* Some SPU pseudo registers are got via TARGET_OBJECT_SPU. */ - if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu) - SELF_CHECK (mock_target.xfer_partial_called == 0); + SELF_CHECK (mock_target.xfer_partial_called == 0); mock_target.reset (); } @@ -1731,16 +1776,12 @@ cooked_write_test (struct gdbarch *gdbarch) auto bfd_arch = gdbarch_bfd_arch_info (gdbarch)->arch; - if ((bfd_arch == bfd_arch_sparc - /* SPARC64_CWP_REGNUM, SPARC64_PSTATE_REGNUM, - SPARC64_ASI_REGNUM and SPARC64_CCR_REGNUM are hard to test. */ - && gdbarch_ptr_bit (gdbarch) == 64 - && (regnum >= gdbarch_num_regs (gdbarch) - && regnum <= gdbarch_num_regs (gdbarch) + 4)) - || (bfd_arch == bfd_arch_spu - /* SPU pseudo registers except SPU_SP_REGNUM are got by - TARGET_OBJECT_SPU. */ - && regnum >= gdbarch_num_regs (gdbarch) && regnum != 130)) + if (bfd_arch == bfd_arch_sparc + /* SPARC64_CWP_REGNUM, SPARC64_PSTATE_REGNUM, + SPARC64_ASI_REGNUM and SPARC64_CCR_REGNUM are hard to test. */ + && gdbarch_ptr_bit (gdbarch) == 64 + && (regnum >= gdbarch_num_regs (gdbarch) + && regnum <= gdbarch_num_regs (gdbarch) + 4)) continue; std::vector expected (register_size (gdbarch, regnum), 0); @@ -1816,11 +1857,10 @@ _initialize_regcache (void) = gdbarch_data_register_post_init (init_regcache_descr); gdb::observers::target_changed.attach (regcache_observer_target_changed); - gdb::observers::thread_ptid_changed.attach - (regcache::regcache_thread_ptid_changed); + gdb::observers::thread_ptid_changed.attach (regcache_thread_ptid_changed); add_com ("flushregs", class_maintenance, reg_flush_command, - _("Force gdb to flush its register cache (maintainer command)")); + _("Force gdb to flush its register cache (maintainer command).")); #if GDB_SELF_TEST selftests::register_test ("current_regcache", selftests::current_regcache_test);