1 /* 2 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_UTILITIES_CONCURRENTHASHTABLE_HPP 26 #define SHARE_UTILITIES_CONCURRENTHASHTABLE_HPP 27 28 #include "memory/allocation.hpp" 29 #include "utilities/globalCounter.hpp" 30 #include "utilities/globalDefinitions.hpp" 31 #include "utilities/tableStatistics.hpp" 32 33 // A mostly concurrent-hash-table where the read-side is wait-free, inserts are 34 // CAS and deletes mutual exclude each other on per bucket-basis. VALUE is the 35 // type kept inside each Node and CONFIG contains hash and allocation methods. 36 // A CALLBACK_FUNC and LOOKUP_FUNC needs to be provided for get and insert. 37 38 class Thread; 39 class Mutex; 40 41 template <typename CONFIG, MEMFLAGS F> 42 class ConcurrentHashTable : public CHeapObj<F> { 43 typedef typename CONFIG::Value VALUE; 44 private: 45 // This is the internal node structure. 46 // Only constructed with placement new from memory allocated with MEMFLAGS of 47 // the InternalTable or user-defined memory. 48 class Node { 49 private: 50 Node * volatile _next; 51 VALUE _value; 52 public: Node(const VALUE & value,Node * next=NULL)53 Node(const VALUE& value, Node* next = NULL) 54 : _next(next), _value(value) { 55 assert((((uintptr_t)this) & ((uintptr_t)0x3)) == 0, 56 "Must 16 bit aligned."); 57 } 58 59 Node* next() const; set_next(Node * node)60 void set_next(Node* node) { _next = node; } next_ptr()61 Node* const volatile * next_ptr() { return &_next; } 62 value()63 VALUE* value() { return &_value; } 64 65 // Creates a node. create_node(const VALUE & value,Node * next=NULL)66 static Node* create_node(const VALUE& value, Node* next = NULL) { 67 return new (CONFIG::allocate_node(sizeof(Node), value)) Node(value, next); 68 } 69 // Destroys a node. destroy_node(Node * node)70 static void destroy_node(Node* node) { 71 CONFIG::free_node((void*)node, node->_value); 72 } 73 print_on(outputStream * st) const74 void print_on(outputStream* st) const {}; print_value_on(outputStream * st) const75 void print_value_on(outputStream* st) const {}; 76 }; 77 78 // Only constructed with placement new from an array allocated with MEMFLAGS 79 // of InternalTable. 80 class Bucket { 81 private: 82 83 // Embedded state in two low bits in first pointer is a spinlock with 3 84 // states, unlocked, locked, redirect. You must never busy-spin on trylock() 85 // or call lock() without _resize_lock, that would deadlock. Redirect can 86 // only be installed by owner and is the final state of a bucket. 87 // The only two valid flows are: 88 // unlocked -> locked -> unlocked 89 // unlocked -> locked -> redirect 90 // Locked state only applies to an updater. 91 // Reader only check for redirect. 92 Node * volatile _first; 93 94 static const uintptr_t STATE_LOCK_BIT = 0x1; 95 static const uintptr_t STATE_REDIRECT_BIT = 0x2; 96 static const uintptr_t STATE_MASK = 0x3; 97 98 // Get the first pointer unmasked. 99 Node* first_raw() const; 100 101 // Methods to manipulate the embedded. is_state(Node * node,uintptr_t bits)102 static bool is_state(Node* node, uintptr_t bits) { 103 return (bits & (uintptr_t)node) == bits; 104 } 105 set_state(Node * n,uintptr_t bits)106 static Node* set_state(Node* n, uintptr_t bits) { 107 return (Node*)(bits | (uintptr_t)n); 108 } 109 get_state(Node * node)110 static uintptr_t get_state(Node* node) { 111 return (((uintptr_t)node) & STATE_MASK); 112 } 113 clear_state(Node * node)114 static Node* clear_state(Node* node) { 115 return (Node*)(((uintptr_t)node) & (~(STATE_MASK))); 116 } 117 clear_set_state(Node * node,Node * state)118 static Node* clear_set_state(Node* node, Node* state) { 119 return (Node*)(((uintptr_t)clear_state(node)) ^ get_state(state)); 120 } 121 122 public: 123 // A bucket is only one pointer with the embedded state. Bucket()124 Bucket() : _first(NULL) {}; 125 126 // Get the first pointer unmasked. 127 Node* first() const; 128 129 // Get a pointer to the const first pointer. Do not deference this 130 // pointer, the pointer pointed to _may_ contain an embedded state. Such 131 // pointer should only be used as input to release_assign_node_ptr. first_ptr()132 Node* const volatile * first_ptr() { return &_first; } 133 134 // This is the only place where a pointer to a Node pointer that potentially 135 // is _first should be changed. Otherwise we destroy the embedded state. We 136 // only give out pointer to const Node pointer to avoid accidental 137 // assignment, thus here we must cast const part away. Method is not static 138 // due to an assert. 139 void release_assign_node_ptr(Node* const volatile * dst, Node* node) const; 140 141 // This method assigns this buckets last Node next ptr to input Node. 142 void release_assign_last_node_next(Node* node); 143 144 // Setting the first pointer must be done with CAS. 145 bool cas_first(Node *node, Node* expect); 146 147 // Returns true if this bucket is redirecting to a new table. 148 // Redirect is a terminal state and will never change. 149 bool have_redirect() const; 150 151 // Return true if this bucket is locked for updates. 152 bool is_locked() const; 153 154 // Return true if this bucket was locked. 155 bool trylock(); 156 157 // The bucket might be invalid, due to a concurrent resize. The lock() 158 // method do no respect that and can deadlock if caller do not hold 159 // _resize_lock. 160 void lock(); 161 162 // Unlocks this bucket. 163 void unlock(); 164 165 // Installs redirect in this bucket. 166 // Prior to doing so you must have successfully locked this bucket. 167 void redirect(); 168 }; 169 170 // The backing storage table holding the buckets and it's size and mask-bits. 171 // Table is always a power of two for two reasons: 172 // - Re-size can only change the size into half or double 173 // (any pow 2 would also be possible). 174 // - Use masking of hash for bucket index. 175 class InternalTable : public CHeapObj<F> { 176 private: 177 Bucket* _buckets; // Bucket array. 178 public: 179 const size_t _log2_size; // Size in log2. 180 const size_t _size; // Size in log10. 181 182 // The mask used on hash for selecting bucket. 183 // The masked value is guaranteed be to inside the buckets array. 184 const size_t _hash_mask; 185 186 // Create a backing table 187 InternalTable(size_t log2_size); 188 ~InternalTable(); 189 get_buckets()190 Bucket* get_buckets() { return _buckets; } get_bucket(size_t idx)191 Bucket* get_bucket(size_t idx) { return &_buckets[idx]; } 192 }; 193 194 // Used as default functor when no functor supplied for some methods. 195 struct NoOp { operator ()ConcurrentHashTable::NoOp196 void operator()(VALUE*) {} operator ()ConcurrentHashTable::NoOp197 const VALUE& operator()() {} operator ()ConcurrentHashTable::NoOp198 void operator()(bool, VALUE*) {} 199 } noOp; 200 201 // For materializing a supplied value. 202 class LazyValueRetrieve { 203 private: 204 const VALUE& _val; 205 public: LazyValueRetrieve(const VALUE & val)206 LazyValueRetrieve(const VALUE& val) : _val(val) {} operator ()()207 const VALUE& operator()() { return _val; } 208 }; 209 210 InternalTable* _table; // Active table. 211 InternalTable* _new_table; // Table we are resizing to. 212 213 // Default sizes 214 static const size_t DEFAULT_MAX_SIZE_LOG2 = 21; 215 static const size_t DEFAULT_START_SIZE_LOG2 = 13; 216 static const size_t DEFAULT_GROW_HINT = 4; // Chain length 217 218 const size_t _log2_size_limit; // The biggest size. 219 const size_t _log2_start_size; // Start size. 220 const size_t _grow_hint; // Number of linked items 221 222 volatile bool _size_limit_reached; 223 224 // We serialize resizers and other bulk operations which do not support 225 // concurrent resize with this lock. 226 Mutex* _resize_lock; 227 // Since we need to drop mutex for safepoints, but stop other threads from 228 // taking the mutex after a safepoint this bool is the actual state. After 229 // acquiring the mutex you must check if this is already locked. If so you 230 // must drop the mutex until the real lock holder grabs the mutex. 231 volatile Thread* _resize_lock_owner; 232 233 // Return true if lock mutex/state succeeded. 234 bool try_resize_lock(Thread* locker); 235 // Returns when both mutex and state are proper locked. 236 void lock_resize_lock(Thread* locker); 237 // Unlocks mutex and state. 238 void unlock_resize_lock(Thread* locker); 239 240 // This method sets the _invisible_epoch and do a write_synchronize. 241 // Subsequent calls check the state of _invisible_epoch and determine if the 242 // write_synchronize can be avoided. If not, it sets the _invisible_epoch 243 // again and do a write_synchronize. 244 void write_synchonize_on_visible_epoch(Thread* thread); 245 // To be-able to avoid write_synchronize in resize and other bulk operation, 246 // this field keep tracks if a version of the hash-table was ever been seen. 247 // We the working thread pointer as tag for debugging. The _invisible_epoch 248 // can only be used by the owner of _resize_lock. 249 volatile Thread* _invisible_epoch; 250 251 // Scoped critical section, which also handles the invisible epochs. 252 // An invisible epoch/version do not need a write_synchronize(). 253 class ScopedCS: public StackObj { 254 protected: 255 Thread* _thread; 256 ConcurrentHashTable<CONFIG, F>* _cht; 257 GlobalCounter::CSContext _cs_context; 258 public: 259 ScopedCS(Thread* thread, ConcurrentHashTable<CONFIG, F>* cht); 260 ~ScopedCS(); 261 }; 262 263 264 // Max number of deletes in one bucket chain during bulk delete. 265 static const size_t BULK_DELETE_LIMIT = 256; 266 267 // Simple getters and setters for the internal table. 268 InternalTable* get_table() const; 269 InternalTable* get_new_table() const; 270 InternalTable* set_table_from_new(); 271 272 // Destroys all nodes. 273 void free_nodes(); 274 275 // Mask away high bits of hash. bucket_idx_hash(InternalTable * table,const uintx hash)276 static size_t bucket_idx_hash(InternalTable* table, const uintx hash) { 277 return ((size_t)hash) & table->_hash_mask; 278 } 279 280 // Returns bucket for hash for that internal table. get_bucket_in(InternalTable * table,const uintx hash) const281 Bucket* get_bucket_in(InternalTable* table, const uintx hash) const { 282 size_t bucket_index = bucket_idx_hash(table, hash); 283 return table->get_bucket(bucket_index); 284 } 285 286 // Return correct bucket for reading and handles resizing. 287 Bucket* get_bucket(const uintx hash) const; 288 289 // Return correct bucket for updates and handles resizing. 290 Bucket* get_bucket_locked(Thread* thread, const uintx hash); 291 292 // Finds a node. 293 template <typename LOOKUP_FUNC> 294 Node* get_node(const Bucket* const bucket, LOOKUP_FUNC& lookup_f, 295 bool* have_dead, size_t* loops = NULL) const; 296 297 // Method for shrinking. 298 bool internal_shrink_prolog(Thread* thread, size_t log2_size); 299 void internal_shrink_epilog(Thread* thread); 300 void internal_shrink_range(Thread* thread, size_t start, size_t stop); 301 bool internal_shrink(Thread* thread, size_t size_limit_log2); 302 303 // Methods for growing. 304 bool unzip_bucket(Thread* thread, InternalTable* old_table, 305 InternalTable* new_table, size_t even_index, 306 size_t odd_index); 307 bool internal_grow_prolog(Thread* thread, size_t log2_size); 308 void internal_grow_epilog(Thread* thread); 309 void internal_grow_range(Thread* thread, size_t start, size_t stop); 310 bool internal_grow(Thread* thread, size_t log2_size); 311 312 // Get a value. 313 template <typename LOOKUP_FUNC> 314 VALUE* internal_get(Thread* thread, LOOKUP_FUNC& lookup_f, 315 bool* grow_hint = NULL); 316 317 // Plain insert. 318 template <typename LOOKUP_FUNC> 319 bool internal_insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value, 320 bool* grow_hint, bool* clean_hint); 321 322 // Returns true if an item matching LOOKUP_FUNC is removed. 323 // Calls DELETE_FUNC before destroying the node. 324 template <typename LOOKUP_FUNC, typename DELETE_FUNC> 325 bool internal_remove(Thread* thread, LOOKUP_FUNC& lookup_f, 326 DELETE_FUNC& delete_f); 327 328 // Visits nodes with FUNC. 329 template <typename FUNC> 330 static bool visit_nodes(Bucket* bucket, FUNC& visitor_f); 331 332 // During shrink/grow we cannot guarantee that we only visit nodes once, with 333 // current algorithm. To keep it simple caller will have locked 334 // _resize_lock. 335 template <typename FUNC> 336 void do_scan_locked(Thread* thread, FUNC& scan_f); 337 338 // Check for dead items in a bucket. 339 template <typename EVALUATE_FUNC> 340 size_t delete_check_nodes(Bucket* bucket, EVALUATE_FUNC& eval_f, 341 size_t num_del, Node** ndel); 342 343 // Check for dead items in this table. During shrink/grow we cannot guarantee 344 // that we only visit nodes once. To keep it simple caller will have locked 345 // _resize_lock. 346 template <typename EVALUATE_FUNC, typename DELETE_FUNC> do_bulk_delete_locked(Thread * thread,EVALUATE_FUNC & eval_f,DELETE_FUNC & del_f)347 void do_bulk_delete_locked(Thread* thread, EVALUATE_FUNC& eval_f 348 , DELETE_FUNC& del_f) { 349 do_bulk_delete_locked_for(thread, 0, _table->_size, eval_f, del_f); 350 } 351 352 // To have prefetching for a VALUE that is pointer during 353 // do_bulk_delete_locked, we have this helper classes. One for non-pointer 354 // case without prefect and one for pointer with prefect. 355 template <bool b, typename EVALUATE_FUNC> 356 struct HaveDeletables { 357 static bool have_deletable(Bucket* bucket, EVALUATE_FUNC& eval_f, 358 Bucket* prefetch_bucket); 359 }; 360 template<typename EVALUATE_FUNC> 361 struct HaveDeletables<true, EVALUATE_FUNC> { 362 static bool have_deletable(Bucket* bucket, EVALUATE_FUNC& eval_f, 363 Bucket* prefetch_bucket); 364 }; 365 366 // Check for dead items in this table with range. During shrink/grow we cannot 367 // guarantee that we only visit nodes once. To keep it simple caller will 368 // have locked _resize_lock. 369 template <typename EVALUATE_FUNC, typename DELETE_FUNC> 370 void do_bulk_delete_locked_for(Thread* thread, size_t start_idx, 371 size_t stop_idx, EVALUATE_FUNC& eval_f, 372 DELETE_FUNC& del_f, bool is_mt = false); 373 374 // Method to delete one items. 375 template <typename LOOKUP_FUNC> 376 void delete_in_bucket(Thread* thread, Bucket* bucket, LOOKUP_FUNC& lookup_f); 377 378 public: 379 ConcurrentHashTable(size_t log2size = DEFAULT_START_SIZE_LOG2, 380 size_t log2size_limit = DEFAULT_MAX_SIZE_LOG2, 381 size_t grow_hint = DEFAULT_GROW_HINT); 382 383 ~ConcurrentHashTable(); 384 385 TableRateStatistics _stats_rate; 386 387 size_t get_size_log2(Thread* thread); get_node_size() const388 size_t get_node_size() const { return sizeof(Node); } is_max_size_reached()389 bool is_max_size_reached() { return _size_limit_reached; } 390 391 // This means no paused bucket resize operation is going to resume 392 // on this table. is_safepoint_safe()393 bool is_safepoint_safe() { return _resize_lock_owner == NULL; } 394 395 // Re-size operations. 396 bool shrink(Thread* thread, size_t size_limit_log2 = 0); 397 bool grow(Thread* thread, size_t size_limit_log2 = 0); 398 399 // All callbacks for get are under critical sections. Other callbacks may be 400 // under critical section or may have locked parts of table. Calling any 401 // methods on the table during a callback is not supported.Only MultiGetHandle 402 // supports multiple gets. 403 404 // Get methods return true on found item with LOOKUP_FUNC and FOUND_FUNC is 405 // called. 406 template <typename LOOKUP_FUNC, typename FOUND_FUNC> 407 bool get(Thread* thread, LOOKUP_FUNC& lookup_f, FOUND_FUNC& foundf, 408 bool* grow_hint = NULL); 409 410 // Returns true true if the item was inserted, duplicates are found with 411 // LOOKUP_FUNC. 412 template <typename LOOKUP_FUNC> insert(Thread * thread,LOOKUP_FUNC & lookup_f,const VALUE & value,bool * grow_hint=NULL,bool * clean_hint=NULL)413 bool insert(Thread* thread, LOOKUP_FUNC& lookup_f, const VALUE& value, 414 bool* grow_hint = NULL, bool* clean_hint = NULL) { 415 return internal_insert(thread, lookup_f, value, grow_hint, clean_hint); 416 } 417 418 // This does a fast unsafe insert and can thus only be used when there is no 419 // risk for a duplicates and no other threads uses this table. 420 bool unsafe_insert(const VALUE& value); 421 422 // Returns true if items was deleted matching LOOKUP_FUNC and 423 // prior to destruction DELETE_FUNC is called. 424 template <typename LOOKUP_FUNC, typename DELETE_FUNC> remove(Thread * thread,LOOKUP_FUNC & lookup_f,DELETE_FUNC & del_f)425 bool remove(Thread* thread, LOOKUP_FUNC& lookup_f, DELETE_FUNC& del_f) { 426 return internal_remove(thread, lookup_f, del_f); 427 } 428 429 // Same without DELETE_FUNC. 430 template <typename LOOKUP_FUNC> remove(Thread * thread,LOOKUP_FUNC & lookup_f)431 bool remove(Thread* thread, LOOKUP_FUNC& lookup_f) { 432 return internal_remove(thread, lookup_f, noOp); 433 } 434 435 // Visit all items with SCAN_FUNC if no concurrent resize. Takes the resize 436 // lock to avoid concurrent resizes. Else returns false. 437 template <typename SCAN_FUNC> 438 bool try_scan(Thread* thread, SCAN_FUNC& scan_f); 439 440 // Visit all items with SCAN_FUNC when the resize lock is obtained. 441 template <typename SCAN_FUNC> 442 void do_scan(Thread* thread, SCAN_FUNC& scan_f); 443 444 // Visit all items with SCAN_FUNC without any protection. 445 // It will assume there is no other thread accessing this 446 // table during the safepoint. Must be called with VM thread. 447 template <typename SCAN_FUNC> 448 void do_safepoint_scan(SCAN_FUNC& scan_f); 449 450 // Destroying items matching EVALUATE_FUNC, before destroying items 451 // DELETE_FUNC is called, if resize lock is obtained. Else returns false. 452 template <typename EVALUATE_FUNC, typename DELETE_FUNC> 453 bool try_bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, 454 DELETE_FUNC& del_f); 455 456 // Destroying items matching EVALUATE_FUNC, before destroying items 457 // DELETE_FUNC is called, when the resize lock is successfully obtained. 458 template <typename EVALUATE_FUNC, typename DELETE_FUNC> 459 void bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f); 460 461 // Calcuate statistics. Item sizes are calculated with VALUE_SIZE_FUNC. 462 template <typename VALUE_SIZE_FUNC> 463 TableStatistics statistics_calculate(Thread* thread, VALUE_SIZE_FUNC& vs_f); 464 465 // Gets statistics if available, if not return old one. Item sizes are calculated with 466 // VALUE_SIZE_FUNC. 467 template <typename VALUE_SIZE_FUNC> 468 TableStatistics statistics_get(Thread* thread, VALUE_SIZE_FUNC& vs_f, TableStatistics old); 469 470 // Writes statistics to the outputStream. Item sizes are calculated with 471 // VALUE_SIZE_FUNC. 472 template <typename VALUE_SIZE_FUNC> 473 void statistics_to(Thread* thread, VALUE_SIZE_FUNC& vs_f, outputStream* st, 474 const char* table_name); 475 476 // Moves all nodes from this table to to_cht 477 bool try_move_nodes_to(Thread* thread, ConcurrentHashTable<CONFIG, F>* to_cht); 478 479 // Scoped multi getter. 480 class MultiGetHandle : private ScopedCS { 481 public: MultiGetHandle(Thread * thread,ConcurrentHashTable<CONFIG,F> * cht)482 MultiGetHandle(Thread* thread, ConcurrentHashTable<CONFIG, F>* cht) 483 : ScopedCS(thread, cht) {} 484 // In the MultiGetHandle scope you can lookup items matching LOOKUP_FUNC. 485 // The VALUEs are safe as long as you never save the VALUEs outside the 486 // scope, e.g. after ~MultiGetHandle(). 487 template <typename LOOKUP_FUNC> 488 VALUE* get(LOOKUP_FUNC& lookup_f, bool* grow_hint = NULL); 489 }; 490 491 private: 492 class BucketsOperation; 493 494 public: 495 class BulkDeleteTask; 496 class GrowTask; 497 }; 498 499 #endif // SHARE_UTILITIES_CONCURRENTHASHTABLE_HPP 500