X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fregcache.c;h=87d95010e3bd37b2b3027dab37464c2cf9937573;hb=refs%2Fheads%2Finferior-thread-map-2020-01-16;hp=2dfe8eaf5feb13b23bebbd8323c2fb6bd00d34da;hpb=2301204a3b3cd6553f7490498b3adc5973157c1b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/regcache.c b/gdb/regcache.c index 2dfe8eaf5f..87d95010e3 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -318,26 +318,65 @@ 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 target_ptid_arch +{ + target_ptid_arch (process_stratum_target *target, ptid_t ptid, gdbarch *arch) + : target (target), ptid (ptid), arch (arch) + {} + + process_stratum_target *target; + ptid_t ptid; + gdbarch *arch; + + bool operator== (const target_ptid_arch &other) const + { + return (this->target == other.target + && this->ptid == other.ptid + && this->arch == other.arch); + } +}; + +/* Hash function for target_ptid_arch. */ + +struct hash_target_ptid_arch +{ + size_t operator() (const target_ptid_arch &val) const + { + hash_ptid h_ptid; + std::hash h_long; + return h_ptid (val.ptid) + h_long ((long) val.arch); + } +}; + +using target_ptid_arch_regcache_map + = std::unordered_map; + +/* Hash map containing the regcaches. */ + +static target_ptid_arch_regcache_map the_regcaches; struct regcache * get_thread_arch_aspace_regcache (process_stratum_target *target, - ptid_t ptid, struct gdbarch *gdbarch, + ptid_t ptid, gdbarch *arch, struct address_space *aspace) { gdb_assert (target != nullptr); - for (const auto ®cache : regcache::current_regcache) - if (regcache->target () == target - && regcache->ptid () == ptid - && regcache->arch () == gdbarch) - return regcache; - - regcache *new_regcache = new regcache (target, gdbarch, aspace); + /* Look up a regcache for this (target, ptid, arch). */ + target_ptid_arch key (target, ptid, arch); + auto it = the_regcaches.find (key); + if (it != the_regcaches.end ()) + return it->second; - regcache::current_regcache.push_front (new_regcache); + /* It does not exist, create it. */ + regcache *new_regcache = new regcache (target, arch, aspace); new_regcache->set_ptid (ptid); + the_regcaches[key] = new_regcache; + return new_regcache; } @@ -413,13 +452,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) { - if (regcache->ptid () == old_ptid) - regcache->set_ptid (new_ptid); + regcache *rc = pair.second; + if (rc->ptid () == old_ptid) + keys_to_update.push_back (pair.first); + } + + for (const target_ptid_arch &old_key : keys_to_update) + { + /* 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. */ + target_ptid_arch new_key (rc->target (), new_ptid, rc->arch ()); + rc->set_ptid (new_ptid); + the_regcaches[new_key] = rc; } } @@ -437,20 +495,22 @@ regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) void registers_changed_ptid (process_stratum_target *target, ptid_t ptid) { - for (auto oit = regcache::current_regcache.before_begin (), - it = std::next (oit); - it != regcache::current_regcache.end (); - ) + /* If we have a non-minus_one_ptid, we must have a non-NULL target. */ + if (ptid != minus_one_ptid) + gdb_assert (target != nullptr); + + for (auto iter = the_regcaches.begin (); iter != the_regcaches.end (); ) { - struct regcache *regcache = *it; - if ((target == nullptr || regcache->target () == target) - && regcache->ptid ().matches (ptid)) + regcache *rc = iter->second; + + if ((target == nullptr || rc->target () == target) + && rc->ptid ().matches (ptid)) { - delete regcache; - it = regcache::current_regcache.erase_after (oit); + delete iter->second; + iter = the_regcaches.erase (iter); } else - oit = it++; + ++iter; } if ((target == nullptr || current_thread_target == target) @@ -1423,8 +1483,7 @@ public: static size_t current_regcache_size () { - return std::distance (regcache::current_regcache.begin (), - regcache::current_regcache.end ()); + return the_regcaches.size (); } }; @@ -1861,8 +1920,7 @@ _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)."));