Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
tbb::interface5::internal::hash_map_base Class Reference

base class of concurrent_hash_map More...

#include <concurrent_hash_map.h>

Inheritance diagram for tbb::interface5::internal::hash_map_base:
Collaboration diagram for tbb::interface5::internal::hash_map_base:

Classes

struct  bucket
 Bucket type. More...
 
struct  enable_segment_failsafe
 Exception safety helper. More...
 

Public Types

typedef size_t size_type
 Size type. More...
 
typedef size_t hashcode_t
 Type of a hash code. More...
 
typedef size_t segment_index_t
 Segment index type. More...
 
typedef hash_map_node_base node_base
 Node base type. More...
 
typedef bucketsegment_ptr_t
 Segment pointer. More...
 
typedef segment_ptr_t segments_table_t[pointers_per_table]
 Segment pointers table type. More...
 

Public Member Functions

 hash_map_base ()
 Constructor. More...
 
void enable_segment (segment_index_t k, bool is_initial=false)
 Enable segment. More...
 
bucketget_bucket (hashcode_t h) const throw ()
 Get bucket by (masked) hashcode. More...
 
void mark_rehashed_levels (hashcode_t h) throw ()
 
bool check_mask_race (const hashcode_t h, hashcode_t &m) const
 Check for mask race. More...
 
bool check_rehashing_collision (const hashcode_t h, hashcode_t m_old, hashcode_t m) const
 Process mask race, check for rehashing collision. More...
 
segment_index_t insert_new_node (bucket *b, node_base *n, hashcode_t mask)
 Insert a node and check for load factor. More...
 
void reserve (size_type buckets)
 Prepare enough segments for number of buckets. More...
 
void internal_swap (hash_map_base &table)
 Swap hash_map_bases. More...
 

Static Public Member Functions

static segment_index_t segment_index_of (size_type index)
 
static segment_index_t segment_base (segment_index_t k)
 
static size_type segment_size (segment_index_t k)
 
static bool is_valid (void *ptr)
 
static void init_buckets (segment_ptr_t ptr, size_type sz, bool is_initial)
 Initialize buckets. More...
 
static void add_to_bucket (bucket *b, node_base *n)
 Add node. More...
 

Public Attributes

atomic< hashcode_tmy_mask
 Hash mask = sum of allocated segment sizes - 1. More...
 
segments_table_t my_table
 Segment pointers table. Also prevents false sharing between my_mask and my_size. More...
 
atomic< size_typemy_size
 Size of container in stored items. More...
 
bucket my_embedded_segment [embedded_buckets]
 Zero segment. More...
 

Static Public Attributes

static size_type const embedded_block = 1
 Count of segments in the first block. More...
 
static size_type const embedded_buckets = 1<<embedded_block
 Count of segments in the first block. More...
 
static size_type const first_block = 8
 Count of segments in the first block. More...
 
static size_type const pointers_per_table = sizeof(segment_index_t) * 8
 Size of a pointer / table size. More...
 

Detailed Description

base class of concurrent_hash_map

Definition at line 76 of file concurrent_hash_map.h.

Member Typedef Documentation

◆ hashcode_t

Type of a hash code.

Definition at line 81 of file concurrent_hash_map.h.

◆ node_base

◆ segment_index_t

Segment index type.

Definition at line 83 of file concurrent_hash_map.h.

◆ segment_ptr_t

Segment pointer.

Definition at line 104 of file concurrent_hash_map.h.

◆ segments_table_t

typedef segment_ptr_t tbb::interface5::internal::hash_map_base::segments_table_t[pointers_per_table]

Segment pointers table type.

Definition at line 106 of file concurrent_hash_map.h.

◆ size_type

Size type.

Definition at line 79 of file concurrent_hash_map.h.

Constructor & Destructor Documentation

◆ hash_map_base()

tbb::interface5::internal::hash_map_base::hash_map_base ( )
inline

Constructor.

Definition at line 121 of file concurrent_hash_map.h.

121  {
122  std::memset( this, 0, pointers_per_table*sizeof(segment_ptr_t) // 32*4=128 or 64*8=512
123  + sizeof(my_size) + sizeof(my_mask) // 4+4 or 8+8
124  + embedded_buckets*sizeof(bucket) ); // n*8 or n*16
125  for( size_type i = 0; i < embedded_block; i++ ) // fill the table
128  __TBB_ASSERT( embedded_block <= first_block, "The first block number must include embedded blocks");
129 #if __TBB_STATISTICS
130  my_info_resizes = 0; // concurrent ones
131  my_info_restarts = 0; // race collisions
132  my_info_rehashes = 0; // invocations of rehash_bucket
133 #endif
134  }
segments_table_t my_table
Segment pointers table. Also prevents false sharing between my_mask and my_size.
atomic< size_type > my_size
Size of container in stored items.
static size_type const embedded_block
Count of segments in the first block.
bucket my_embedded_segment[embedded_buckets]
Zero segment.
static size_type const first_block
Count of segments in the first block.
static segment_index_t segment_base(segment_index_t k)
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
static size_type const embedded_buckets
Count of segments in the first block.
atomic< hashcode_t > my_mask
Hash mask = sum of allocated segment sizes - 1.
static size_type const pointers_per_table
Size of a pointer / table size.

Member Function Documentation

◆ add_to_bucket()

static void tbb::interface5::internal::hash_map_base::add_to_bucket ( bucket b,
node_base n 
)
inlinestatic

Add node.

  • n to bucket
  • b

Definition at line 166 of file concurrent_hash_map.h.

166  {
167  __TBB_ASSERT(b->node_list != rehash_req, NULL);
168  n->next = b->node_list;
169  b->node_list = n; // its under lock and flag is set
170  }
static hash_map_node_base *const rehash_req
Incompleteness flag value.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169

References __TBB_ASSERT, tbb::interface5::internal::hash_map_node_base::next, tbb::interface5::internal::hash_map_base::bucket::node_list, and tbb::interface5::internal::rehash_req.

Referenced by tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::rehash_bucket().

Here is the caller graph for this function:

◆ check_mask_race()

bool tbb::interface5::internal::hash_map_base::check_mask_race ( const hashcode_t  h,
hashcode_t m 
) const
inline

Check for mask race.

Definition at line 228 of file concurrent_hash_map.h.

228  {
229  hashcode_t m_now, m_old = m;
231  if( m_old != m_now )
232  return check_rehashing_collision( h, m_old, m = m_now );
233  return false;
234  }
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h
T itt_load_word_with_acquire(const tbb::atomic< T > &src)
atomic< hashcode_t > my_mask
Hash mask = sum of allocated segment sizes - 1.
bool check_rehashing_collision(const hashcode_t h, hashcode_t m_old, hashcode_t m) const
Process mask race, check for rehashing collision.

References h, and tbb::internal::itt_load_word_with_acquire().

Referenced by tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::internal_fast_find().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_rehashing_collision()

bool tbb::interface5::internal::hash_map_base::check_rehashing_collision ( const hashcode_t  h,
hashcode_t  m_old,
hashcode_t  m 
) const
inline

Process mask race, check for rehashing collision.

Definition at line 237 of file concurrent_hash_map.h.

237  {
238  __TBB_ASSERT(m_old != m, NULL); // TODO?: m arg could be optimized out by passing h = h&m
239  if( (h & m_old) != (h & m) ) { // mask changed for this hashcode, rare event
240  // condition above proves that 'h' has some other bits set beside 'm_old'
241  // find next applicable mask after m_old //TODO: look at bsl instruction
242  for( ++m_old; !(h & m_old); m_old <<= 1 ) // at maximum few rounds depending on the first block size
243  ;
244  m_old = (m_old<<1) - 1; // get full mask from a bit
245  __TBB_ASSERT((m_old&(m_old+1))==0 && m_old <= m, NULL);
246  // check whether it is rehashing/ed
247  if( itt_load_word_with_acquire(get_bucket(h & m_old)->node_list) != rehash_req )
248  {
249 #if __TBB_STATISTICS
250  my_info_restarts++; // race collisions
251 #endif
252  return true;
253  }
254  }
255  return false;
256  }
static hash_map_node_base *const rehash_req
Incompleteness flag value.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h
T itt_load_word_with_acquire(const tbb::atomic< T > &src)
bucket * get_bucket(hashcode_t h) const
Get bucket by (masked) hashcode.

References __TBB_ASSERT, h, tbb::internal::itt_load_word_with_acquire(), and tbb::interface5::internal::rehash_req.

Here is the call graph for this function:

◆ enable_segment()

void tbb::interface5::internal::hash_map_base::enable_segment ( segment_index_t  k,
bool  is_initial = false 
)
inline

Enable segment.

Definition at line 182 of file concurrent_hash_map.h.

182  {
183  __TBB_ASSERT( k, "Zero segment must be embedded" );
184  enable_segment_failsafe watchdog( my_table, k );
185  cache_aligned_allocator<bucket> alloc;
186  size_type sz;
187  __TBB_ASSERT( !is_valid(my_table[k]), "Wrong concurrent assignment");
188  if( k >= first_block ) {
189  sz = segment_size( k );
190  segment_ptr_t ptr = alloc.allocate( sz );
191  init_buckets( ptr, sz, is_initial );
192  itt_hide_store_word( my_table[k], ptr );
193  sz <<= 1;// double it to get entire capacity of the container
194  } else { // the first block
195  __TBB_ASSERT( k == embedded_block, "Wrong segment index" );
196  sz = segment_size( first_block );
197  segment_ptr_t ptr = alloc.allocate( sz - embedded_buckets );
198  init_buckets( ptr, sz - embedded_buckets, is_initial );
200  for(segment_index_t i = embedded_block; i < first_block; i++) // calc the offsets
201  itt_hide_store_word( my_table[i], ptr + segment_base(i) );
202  }
204  watchdog.my_segment_ptr = 0;
205  }
segments_table_t my_table
Segment pointers table. Also prevents false sharing between my_mask and my_size.
static size_type const embedded_block
Count of segments in the first block.
static size_type const first_block
Count of segments in the first block.
static segment_index_t segment_base(segment_index_t k)
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
static size_type const embedded_buckets
Count of segments in the first block.
static void init_buckets(segment_ptr_t ptr, size_type sz, bool is_initial)
Initialize buckets.
atomic< hashcode_t > my_mask
Hash mask = sum of allocated segment sizes - 1.
static size_type segment_size(segment_index_t k)
void itt_hide_store_word(T &dst, T src)
void itt_store_word_with_release(tbb::atomic< T > &dst, U src)

References __TBB_ASSERT, tbb::cache_aligned_allocator< T >::allocate(), tbb::internal::itt_hide_store_word(), tbb::internal::itt_store_word_with_release(), and tbb::interface5::internal::hash_map_base::enable_segment_failsafe::my_segment_ptr.

Here is the call graph for this function:

◆ get_bucket()

bucket* tbb::interface5::internal::hash_map_base::get_bucket ( hashcode_t  h) const
throw (
)
inline

Get bucket by (masked) hashcode.

Definition at line 208 of file concurrent_hash_map.h.

208  { // TODO: add throw() everywhere?
210  h -= segment_base(s);
211  segment_ptr_t seg = my_table[s];
212  __TBB_ASSERT( is_valid(seg), "hashcode must be cut by valid mask for allocated segments" );
213  return &seg[h];
214  }
segments_table_t my_table
Segment pointers table. Also prevents false sharing between my_mask and my_size.
void const char const char int ITT_FORMAT __itt_group_sync s
static segment_index_t segment_index_of(size_type index)
static segment_index_t segment_base(segment_index_t k)
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h

References __TBB_ASSERT, h, and s.

Referenced by tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor::acquire(), tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::internal_copy(), and tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::internal_fast_find().

Here is the caller graph for this function:

◆ init_buckets()

static void tbb::interface5::internal::hash_map_base::init_buckets ( segment_ptr_t  ptr,
size_type  sz,
bool  is_initial 
)
inlinestatic

Initialize buckets.

Definition at line 157 of file concurrent_hash_map.h.

157  {
158  if( is_initial ) std::memset( static_cast<void*>(ptr), 0, sz*sizeof(bucket) );
159  else for(size_type i = 0; i < sz; i++, ptr++) {
160  *reinterpret_cast<intptr_t*>(&ptr->mutex) = 0;
161  ptr->node_list = rehash_req;
162  }
163  }
static hash_map_node_base *const rehash_req
Incompleteness flag value.

References tbb::interface5::internal::hash_map_base::bucket::mutex, tbb::interface5::internal::hash_map_base::bucket::node_list, and tbb::interface5::internal::rehash_req.

◆ insert_new_node()

segment_index_t tbb::interface5::internal::hash_map_base::insert_new_node ( bucket b,
node_base n,
hashcode_t  mask 
)
inline

Insert a node and check for load factor.

Returns
segment index to enable.

Definition at line 259 of file concurrent_hash_map.h.

259  {
260  size_type sz = ++my_size; // prefix form is to enforce allocation after the first item inserted
261  add_to_bucket( b, n );
262  // check load factor
263  if( sz >= mask ) { // TODO: add custom load_factor
264  segment_index_t new_seg = __TBB_Log2( mask+1 ); //optimized segment_index_of
265  __TBB_ASSERT( is_valid(my_table[new_seg-1]), "new allocations must not publish new mask until segment has allocated");
266  static const segment_ptr_t is_allocating = (segment_ptr_t)2;
267  if( !itt_hide_load_word(my_table[new_seg])
268  && as_atomic(my_table[new_seg]).compare_and_swap(is_allocating, NULL) == NULL )
269  return new_seg; // The value must be processed
270  }
271  return 0;
272  }
segments_table_t my_table
Segment pointers table. Also prevents false sharing between my_mask and my_size.
intptr_t __TBB_Log2(uintptr_t x)
Definition: tbb_machine.h:864
T itt_hide_load_word(const T &src)
atomic< size_type > my_size
Size of container in stored items.
atomic< T > & as_atomic(T &t)
Definition: atomic.h:547
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
static void add_to_bucket(bucket *b, node_base *n)
Add node.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int mask

References __TBB_ASSERT, __TBB_Log2(), tbb::internal::as_atomic(), tbb::internal::itt_hide_load_word(), and mask.

Here is the call graph for this function:

◆ internal_swap()

void tbb::interface5::internal::hash_map_base::internal_swap ( hash_map_base table)
inline

Swap hash_map_bases.

Definition at line 282 of file concurrent_hash_map.h.

282  {
283  using std::swap;
284  swap(this->my_mask, table.my_mask);
285  swap(this->my_size, table.my_size);
286  for(size_type i = 0; i < embedded_buckets; i++)
287  swap(this->my_embedded_segment[i].node_list, table.my_embedded_segment[i].node_list);
288  for(size_type i = embedded_block; i < pointers_per_table; i++)
289  swap(this->my_table[i], table.my_table[i]);
290  }
segments_table_t my_table
Segment pointers table. Also prevents false sharing between my_mask and my_size.
atomic< size_type > my_size
Size of container in stored items.
static size_type const embedded_block
Count of segments in the first block.
bucket my_embedded_segment[embedded_buckets]
Zero segment.
static size_type const embedded_buckets
Count of segments in the first block.
atomic< hashcode_t > my_mask
Hash mask = sum of allocated segment sizes - 1.
void swap(concurrent_hash_map< Key, T, HashCompare, A > &a, concurrent_hash_map< Key, T, HashCompare, A > &b)
static size_type const pointers_per_table
Size of a pointer / table size.

References my_embedded_segment, my_mask, my_size, my_table, tbb::interface5::internal::hash_map_base::bucket::node_list, and tbb::swap().

Here is the call graph for this function:

◆ is_valid()

static bool tbb::interface5::internal::hash_map_base::is_valid ( void ptr)
inlinestatic

◆ mark_rehashed_levels()

void tbb::interface5::internal::hash_map_base::mark_rehashed_levels ( hashcode_t  h)
throw (
)
inline

Definition at line 217 of file concurrent_hash_map.h.

217  {
219  while( segment_ptr_t seg = my_table[++s] )
220  if( seg[h].node_list == rehash_req ) {
221  seg[h].node_list = empty_rehashed;
222  mark_rehashed_levels( h + ((hashcode_t)1<<s) ); // optimized segment_base(s)
223  }
224  }
segments_table_t my_table
Segment pointers table. Also prevents false sharing between my_mask and my_size.
void const char const char int ITT_FORMAT __itt_group_sync s
static segment_index_t segment_index_of(size_type index)
static hash_map_node_base *const rehash_req
Incompleteness flag value.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h
static hash_map_node_base *const empty_rehashed
Rehashed empty bucket flag.

References tbb::interface5::internal::empty_rehashed, h, tbb::interface5::internal::rehash_req, and s.

◆ reserve()

void tbb::interface5::internal::hash_map_base::reserve ( size_type  buckets)
inline

Prepare enough segments for number of buckets.

Definition at line 275 of file concurrent_hash_map.h.

275  {
276  if( !buckets-- ) return;
277  bool is_initial = !my_size;
278  for( size_type m = my_mask; buckets > m; m = my_mask )
279  enable_segment( segment_index_of( m+1 ), is_initial );
280  }
atomic< size_type > my_size
Size of container in stored items.
static segment_index_t segment_index_of(size_type index)
void enable_segment(segment_index_t k, bool is_initial=false)
Enable segment.
atomic< hashcode_t > my_mask
Hash mask = sum of allocated segment sizes - 1.

Referenced by tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::concurrent_hash_map().

Here is the caller graph for this function:

◆ segment_base()

static segment_index_t tbb::interface5::internal::hash_map_base::segment_base ( segment_index_t  k)
inlinestatic
Returns
the first array index of given segment

Definition at line 142 of file concurrent_hash_map.h.

142  {
143  return (segment_index_t(1)<<k & ~segment_index_t(1));
144  }

◆ segment_index_of()

static segment_index_t tbb::interface5::internal::hash_map_base::segment_index_of ( size_type  index)
inlinestatic
Returns
segment index of given index in the array

Definition at line 137 of file concurrent_hash_map.h.

137  {
138  return segment_index_t( __TBB_Log2( index|1 ) );
139  }
intptr_t __TBB_Log2(uintptr_t x)
Definition: tbb_machine.h:864

References __TBB_Log2().

Here is the call graph for this function:

◆ segment_size()

static size_type tbb::interface5::internal::hash_map_base::segment_size ( segment_index_t  k)
inlinestatic
Returns
segment size except for
  • k == 0

Definition at line 147 of file concurrent_hash_map.h.

147  {
148  return size_type(1)<<k; // fake value for k==0
149  }

Member Data Documentation

◆ embedded_block

size_type const tbb::interface5::internal::hash_map_base::embedded_block = 1
static

Count of segments in the first block.

Definition at line 96 of file concurrent_hash_map.h.

◆ embedded_buckets

size_type const tbb::interface5::internal::hash_map_base::embedded_buckets = 1<<embedded_block
static

Count of segments in the first block.

Definition at line 98 of file concurrent_hash_map.h.

◆ first_block

size_type const tbb::interface5::internal::hash_map_base::first_block = 8
static

Count of segments in the first block.

Definition at line 100 of file concurrent_hash_map.h.

◆ my_embedded_segment

bucket tbb::interface5::internal::hash_map_base::my_embedded_segment[embedded_buckets]

◆ my_mask

◆ my_size

◆ my_table

segments_table_t tbb::interface5::internal::hash_map_base::my_table

Segment pointers table. Also prevents false sharing between my_mask and my_size.

Definition at line 110 of file concurrent_hash_map.h.

Referenced by internal_swap().

◆ pointers_per_table

size_type const tbb::interface5::internal::hash_map_base::pointers_per_table = sizeof(segment_index_t) * 8
static

Size of a pointer / table size.

Definition at line 102 of file concurrent_hash_map.h.


The documentation for this class was generated from the following file:

Copyright © 2005-2018 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.