task.h

00001 /*
00002     Copyright 2005-2011 Intel Corporation.  All Rights Reserved.
00003 
00004     The source code contained or described herein and all documents related
00005     to the source code ("Material") are owned by Intel Corporation or its
00006     suppliers or licensors.  Title to the Material remains with Intel
00007     Corporation or its suppliers and licensors.  The Material is protected
00008     by worldwide copyright laws and treaty provisions.  No part of the
00009     Material may be used, copied, reproduced, modified, published, uploaded,
00010     posted, transmitted, distributed, or disclosed in any way without
00011     Intel's prior express written permission.
00012 
00013     No license under any patent, copyright, trade secret or other
00014     intellectual property right is granted to or conferred upon you by
00015     disclosure or delivery of the Materials, either expressly, by
00016     implication, inducement, estoppel or otherwise.  Any license under such
00017     intellectual property rights must be express and approved by Intel in
00018     writing.
00019 */
00020 
00021 #ifndef __TBB_task_H
00022 #define __TBB_task_H
00023 
00024 #include "tbb_stddef.h"
00025 #include "tbb_machine.h"
00026 #include <climits>
00027 
00028 typedef struct ___itt_caller *__itt_caller;
00029 
00030 namespace tbb {
00031 
00032 class task;
00033 class task_list;
00034 
00035 #if __TBB_TASK_GROUP_CONTEXT
00036 class task_group_context;
00037 #endif /* __TBB_TASK_GROUP_CONTEXT */
00038 
00039 // MSVC does not allow taking the address of a member that was defined
00040 // privately in task_base and made public in class task via a using declaration.
00041 #if _MSC_VER || (__GNUC__==3 && __GNUC_MINOR__<3)
00042 #define __TBB_TASK_BASE_ACCESS public
00043 #else
00044 #define __TBB_TASK_BASE_ACCESS private
00045 #endif
00046 
00047 namespace internal {
00048 
00049     class allocate_additional_child_of_proxy: no_assign {
00051         task* self;
00052         task& parent;
00053     public:
00054         explicit allocate_additional_child_of_proxy( task& parent_ ) : self(NULL), parent(parent_) {}
00055         task& __TBB_EXPORTED_METHOD allocate( size_t size ) const;
00056         void __TBB_EXPORTED_METHOD free( task& ) const;
00057     };
00058 
00059 }
00060 
00061 namespace interface5 {
00062     namespace internal {
00064 
00069         class task_base: tbb::internal::no_copy {
00070         __TBB_TASK_BASE_ACCESS:
00071             friend class tbb::task;
00072 
00074             static void spawn( task& t );
00075 
00077             static void spawn( task_list& list );
00078 
00080 
00082             static tbb::internal::allocate_additional_child_of_proxy allocate_additional_child_of( task& t ) {
00083                 return tbb::internal::allocate_additional_child_of_proxy(t);
00084             }
00085 
00087 
00091             static void __TBB_EXPORTED_FUNC destroy( task& victim );
00092         };
00093     } // internal
00094 } // interface5
00095 
00097 namespace internal {
00098 
00099     class scheduler: no_copy {
00100     public:
00102         virtual void spawn( task& first, task*& next ) = 0;
00103 
00105         virtual void wait_for_all( task& parent, task* child ) = 0;
00106 
00108         virtual void spawn_root_and_wait( task& first, task*& next ) = 0;
00109 
00111         //  Have to have it just to shut up overzealous compilation warnings
00112         virtual ~scheduler() = 0;
00113 
00115         virtual void enqueue( task& t, void* reserved ) = 0;
00116     };
00117 
00119 
00120     typedef intptr_t reference_count;
00121 
00123     typedef unsigned short affinity_id;
00124 
00125 #if __TBB_TASK_GROUP_CONTEXT
00126     class generic_scheduler;
00127 
00128     struct context_list_node_t {
00129         context_list_node_t *my_prev,
00130                             *my_next;
00131     };
00132 
00133     class allocate_root_with_context_proxy: no_assign {
00134         task_group_context& my_context;
00135     public:
00136         allocate_root_with_context_proxy ( task_group_context& ctx ) : my_context(ctx) {}
00137         task& __TBB_EXPORTED_METHOD allocate( size_t size ) const;
00138         void __TBB_EXPORTED_METHOD free( task& ) const;
00139     };
00140 #endif /* __TBB_TASK_GROUP_CONTEXT */
00141 
00142     class allocate_root_proxy: no_assign {
00143     public:
00144         static task& __TBB_EXPORTED_FUNC allocate( size_t size );
00145         static void __TBB_EXPORTED_FUNC free( task& );
00146     };
00147 
00148     class allocate_continuation_proxy: no_assign {
00149     public:
00150         task& __TBB_EXPORTED_METHOD allocate( size_t size ) const;
00151         void __TBB_EXPORTED_METHOD free( task& ) const;
00152     };
00153 
00154     class allocate_child_proxy: no_assign {
00155     public:
00156         task& __TBB_EXPORTED_METHOD allocate( size_t size ) const;
00157         void __TBB_EXPORTED_METHOD free( task& ) const;
00158     };
00159 
00161 
00172     class task_prefix {
00173     private:
00174         friend class tbb::task;
00175         friend class tbb::interface5::internal::task_base;
00176         friend class tbb::task_list;
00177         friend class internal::scheduler;
00178         friend class internal::allocate_root_proxy;
00179         friend class internal::allocate_child_proxy;
00180         friend class internal::allocate_continuation_proxy;
00181         friend class internal::allocate_additional_child_of_proxy;
00182 
00183 #if __TBB_TASK_GROUP_CONTEXT
00185 
00188         task_group_context  *context;
00189 #endif /* __TBB_TASK_GROUP_CONTEXT */
00190 
00192 
00197         scheduler* origin;
00198 
00199 #if __TBB_TASK_PRIORITY
00200         union {
00201 #endif /* __TBB_TASK_PRIORITY */
00203 
00205         scheduler* owner;
00206 
00207 #if __TBB_TASK_PRIORITY
00209 
00210         task* next_offloaded;
00211         };
00212 #endif /* __TBB_TASK_PRIORITY */
00213 
00215 
00218         tbb::task* parent;
00219 
00221 
00225         __TBB_atomic reference_count ref_count;
00226 
00228 
00230         int depth;
00231 
00233 
00234         unsigned char state;
00235 
00237 
00242         unsigned char extra_state;
00243 
00244         affinity_id affinity;
00245 
00247         tbb::task* next;
00248 
00250         tbb::task& task() {return *reinterpret_cast<tbb::task*>(this+1);}
00251     };
00252 
00253 } // namespace internal
00255 
00256 #if __TBB_TASK_GROUP_CONTEXT
00257 
00258 #if __TBB_TASK_PRIORITY
00259 namespace internal {
00260     static const int priority_stride_v4 = INT_MAX / 4;
00261 }
00262 
00263 enum priority_t {
00264     priority_normal = internal::priority_stride_v4 * 2,
00265     priority_low = priority_normal - internal::priority_stride_v4,
00266     priority_high = priority_normal + internal::priority_stride_v4
00267 };
00268 
00269 #endif /* __TBB_TASK_PRIORITY */
00270 
00271 #if TBB_USE_CAPTURED_EXCEPTION
00272     class tbb_exception;
00273 #else
00274     namespace internal {
00275         class tbb_exception_ptr;
00276     }
00277 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
00278 
00279 class task_scheduler_init;
00280 
00282 
00302 class task_group_context : internal::no_copy {
00303 private:
00304     friend class internal::generic_scheduler;
00305     friend class task_scheduler_init;
00306 
00307 #if TBB_USE_CAPTURED_EXCEPTION
00308     typedef tbb_exception exception_container_type;
00309 #else
00310     typedef internal::tbb_exception_ptr exception_container_type;
00311 #endif
00312 
00313     enum version_traits_word_layout {
00314         traits_offset = 16,
00315         version_mask = 0xFFFF,
00316         traits_mask = 0xFFFFul << traits_offset
00317     };
00318 
00319 public:
00320     enum kind_type {
00321         isolated,
00322         bound
00323     };
00324 
00325     enum traits_type {
00326         exact_exception = 0x0001ul << traits_offset,
00327         concurrent_wait = 0x0004ul << traits_offset,
00328 #if TBB_USE_CAPTURED_EXCEPTION
00329         default_traits = 0
00330 #else
00331         default_traits = exact_exception
00332 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
00333     };
00334 
00335 private:
00336     enum state {
00337         may_have_children = 1
00338     };
00339 
00340     union {
00342         kind_type my_kind;
00343         uintptr_t _my_kind_aligner;
00344     };
00345 
00347     task_group_context *my_parent;
00348 
00350 
00352     internal::context_list_node_t my_node;
00353 
00355     __itt_caller itt_caller;
00356 
00358 
00361     char _leading_padding[internal::NFS_MaxLineSize
00362                           - 2 * sizeof(uintptr_t)- sizeof(void*) - sizeof(internal::context_list_node_t)
00363                           - sizeof(__itt_caller)];
00364 
00366     uintptr_t my_cancellation_requested;
00367 
00369 
00372     uintptr_t  my_version_and_traits;
00373 
00375     exception_container_type *my_exception;
00376 
00378     internal::generic_scheduler *my_owner;
00379 
00381     uintptr_t my_state;
00382 
00383 #if __TBB_TASK_PRIORITY
00385     intptr_t my_priority;
00386 #endif /* __TBB_TASK_PRIORITY */
00387 
00389 
00390     char _trailing_padding[internal::NFS_MaxLineSize - 2 * sizeof(uintptr_t) - 2 * sizeof(void*)
00391 #if __TBB_TASK_PRIORITY
00392                             - sizeof(intptr_t)
00393 #endif /* __TBB_TASK_PRIORITY */
00394                           ];
00395 
00396 public:
00398 
00426     task_group_context ( kind_type relation_with_parent = bound,
00427                          uintptr_t traits = default_traits )
00428         : my_kind(relation_with_parent)
00429         , my_version_and_traits(1 | traits)
00430     {
00431         init();
00432     }
00433 
00434     __TBB_EXPORTED_METHOD ~task_group_context ();
00435 
00437 
00444     void __TBB_EXPORTED_METHOD reset ();
00445 
00447 
00454     bool __TBB_EXPORTED_METHOD cancel_group_execution ();
00455 
00457     bool __TBB_EXPORTED_METHOD is_group_execution_cancelled () const;
00458 
00460 
00466     void __TBB_EXPORTED_METHOD register_pending_exception ();
00467 
00468 #if __TBB_TASK_PRIORITY
00470     void set_priority ( priority_t );
00471 
00473     priority_t priority () const;
00474 #endif /* __TBB_TASK_PRIORITY */
00475 
00476 protected:
00478 
00479     void __TBB_EXPORTED_METHOD init ();
00480 
00481 private:
00482     friend class task;
00483     friend class internal::allocate_root_with_context_proxy;
00484 
00485     static const kind_type binding_required = bound;
00486     static const kind_type binding_completed = kind_type(bound+1);
00487     static const kind_type detached = kind_type(binding_completed+1);
00488     static const kind_type dying = kind_type(detached+1);
00489 
00491 
00493     template <typename T>
00494     void propagate_state_from_ancestors ( T task_group_context::*mptr_state, T new_state );
00495 
00497     inline void finish_initialization ( internal::generic_scheduler *local_sched );
00498 
00500     void bind_to ( internal::generic_scheduler *local_sched );
00501 
00503     void register_with ( internal::generic_scheduler *local_sched );
00504 
00505 }; // class task_group_context
00506 
00507 #endif /* __TBB_TASK_GROUP_CONTEXT */
00508 
00510 
00511 class task: __TBB_TASK_BASE_ACCESS interface5::internal::task_base {
00512 
00514     void __TBB_EXPORTED_METHOD internal_set_ref_count( int count );
00515 
00517     internal::reference_count __TBB_EXPORTED_METHOD internal_decrement_ref_count();
00518 
00519 protected:
00521     task() {prefix().extra_state=1;}
00522 
00523 public:
00525     virtual ~task() {}
00526 
00528     virtual task* execute() = 0;
00529 
00531     enum state_type {
00533         executing,
00535         reexecute,
00537         ready,
00539         allocated,
00541         freed,
00543         recycle
00544     };
00545 
00546     //------------------------------------------------------------------------
00547     // Allocating tasks
00548     //------------------------------------------------------------------------
00549 
00551     static internal::allocate_root_proxy allocate_root() {
00552         return internal::allocate_root_proxy();
00553     }
00554 
00555 #if __TBB_TASK_GROUP_CONTEXT
00557     static internal::allocate_root_with_context_proxy allocate_root( task_group_context& ctx ) {
00558         return internal::allocate_root_with_context_proxy(ctx);
00559     }
00560 #endif /* __TBB_TASK_GROUP_CONTEXT */
00561 
00563 
00564     internal::allocate_continuation_proxy& allocate_continuation() {
00565         return *reinterpret_cast<internal::allocate_continuation_proxy*>(this);
00566     }
00567 
00569     internal::allocate_child_proxy& allocate_child() {
00570         return *reinterpret_cast<internal::allocate_child_proxy*>(this);
00571     }
00572 
00574     using task_base::allocate_additional_child_of;
00575 
00576 #if __TBB_DEPRECATED_TASK_INTERFACE
00578 
00582     void __TBB_EXPORTED_METHOD destroy( task& t );
00583 #else /* !__TBB_DEPRECATED_TASK_INTERFACE */
00585     using task_base::destroy;
00586 #endif /* !__TBB_DEPRECATED_TASK_INTERFACE */
00587 
00588     //------------------------------------------------------------------------
00589     // Recycling of tasks
00590     //------------------------------------------------------------------------
00591 
00593 
00599     void recycle_as_continuation() {
00600         __TBB_ASSERT( prefix().state==executing, "execute not running?" );
00601         prefix().state = allocated;
00602     }
00603 
00605 
00607     void recycle_as_safe_continuation() {
00608         __TBB_ASSERT( prefix().state==executing, "execute not running?" );
00609         prefix().state = recycle;
00610     }
00611 
00613     void recycle_as_child_of( task& new_parent ) {
00614         internal::task_prefix& p = prefix();
00615         __TBB_ASSERT( prefix().state==executing||prefix().state==allocated, "execute not running, or already recycled" );
00616         __TBB_ASSERT( prefix().ref_count==0, "no child tasks allowed when recycled as a child" );
00617         __TBB_ASSERT( p.parent==NULL, "parent must be null" );
00618         __TBB_ASSERT( new_parent.prefix().state<=recycle, "corrupt parent's state" );
00619         __TBB_ASSERT( new_parent.prefix().state!=freed, "parent already freed" );
00620         p.state = allocated;
00621         p.parent = &new_parent;
00622 #if __TBB_TASK_GROUP_CONTEXT
00623         p.context = new_parent.prefix().context;
00624 #endif /* __TBB_TASK_GROUP_CONTEXT */
00625     }
00626 
00628 
00629     void recycle_to_reexecute() {
00630         __TBB_ASSERT( prefix().state==executing, "execute not running, or already recycled" );
00631         __TBB_ASSERT( prefix().ref_count==0, "no child tasks allowed when recycled for reexecution" );
00632         prefix().state = reexecute;
00633     }
00634 
00635     // All depth-related methods are obsolete, and are retained for the sake
00636     // of backward source compatibility only
00637     intptr_t depth() const {return 0;}
00638     void set_depth( intptr_t ) {}
00639     void add_to_depth( int ) {}
00640 
00641 
00642     //------------------------------------------------------------------------
00643     // Spawning and blocking
00644     //------------------------------------------------------------------------
00645 
00647     void set_ref_count( int count ) {
00648 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00649         internal_set_ref_count(count);
00650 #else
00651         prefix().ref_count = count;
00652 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00653     }
00654 
00656 
00657     void increment_ref_count() {
00658         __TBB_FetchAndIncrementWacquire( &prefix().ref_count );
00659     }
00660 
00662 
00663     int decrement_ref_count() {
00664 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
00665         return int(internal_decrement_ref_count());
00666 #else
00667         return int(__TBB_FetchAndDecrementWrelease( &prefix().ref_count ))-1;
00668 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
00669     }
00670 
00672     using task_base::spawn;
00673 
00675     void spawn_and_wait_for_all( task& child ) {
00676         prefix().owner->wait_for_all( *this, &child );
00677     }
00678 
00680     void __TBB_EXPORTED_METHOD spawn_and_wait_for_all( task_list& list );
00681 
00683     static void spawn_root_and_wait( task& root ) {
00684         root.prefix().owner->spawn_root_and_wait( root, root.prefix().next );
00685     }
00686 
00688 
00690     static void spawn_root_and_wait( task_list& root_list );
00691 
00693 
00694     void wait_for_all() {
00695         prefix().owner->wait_for_all( *this, NULL );
00696     }
00697 
00699 #if __TBB_TASK_PRIORITY
00700 
00710 #endif /* __TBB_TASK_PRIORITY */
00711     static void enqueue( task& t ) {
00712         t.prefix().owner->enqueue( t, NULL );
00713     }
00714 
00715 #if __TBB_TASK_PRIORITY
00717     static void enqueue( task& t, priority_t p ) {
00718         __TBB_ASSERT( p == priority_low || p == priority_normal || p == priority_high, "Invalid priority level value" );
00719         t.prefix().owner->enqueue( t, (void*)p );
00720     }
00721 #endif /* __TBB_TASK_PRIORITY */
00722 
00724     static task& __TBB_EXPORTED_FUNC self();
00725 
00727     task* parent() const {return prefix().parent;}
00728 
00730     void set_parent(task* p) {
00731 #if __TBB_TASK_GROUP_CONTEXT
00732         __TBB_ASSERT(prefix().context == p->prefix().context, "The tasks must be in the same context");
00733 #endif
00734         prefix().parent = p;
00735     }
00736 
00737 #if __TBB_TASK_GROUP_CONTEXT
00739 
00740     task_group_context* context() {return prefix().context;}
00741 
00743     task_group_context* group () { return prefix().context; }
00744 #endif /* __TBB_TASK_GROUP_CONTEXT */
00745 
00747     bool is_stolen_task() const {
00748         return (prefix().extra_state & 0x80)!=0;
00749     }
00750 
00751     //------------------------------------------------------------------------
00752     // Debugging
00753     //------------------------------------------------------------------------
00754 
00756     state_type state() const {return state_type(prefix().state);}
00757 
00759     int ref_count() const {
00760 #if TBB_USE_ASSERT
00761         internal::reference_count ref_count_ = prefix().ref_count;
00762         __TBB_ASSERT( ref_count_==int(ref_count_), "integer overflow error");
00763 #endif
00764         return int(prefix().ref_count);
00765     }
00766 
00768     bool __TBB_EXPORTED_METHOD is_owned_by_current_thread() const;
00769 
00770     //------------------------------------------------------------------------
00771     // Affinity
00772     //------------------------------------------------------------------------
00773 
00775 
00776     typedef internal::affinity_id affinity_id;
00777 
00779     void set_affinity( affinity_id id ) {prefix().affinity = id;}
00780 
00782     affinity_id affinity() const {return prefix().affinity;}
00783 
00785 
00789     virtual void __TBB_EXPORTED_METHOD note_affinity( affinity_id id );
00790 
00791 #if __TBB_TASK_GROUP_CONTEXT
00793 
00803     void __TBB_EXPORTED_METHOD change_group ( task_group_context& ctx );
00804 
00806 
00807     bool cancel_group_execution () { return prefix().context->cancel_group_execution(); }
00808 
00810     bool is_cancelled () const { return prefix().context->is_group_execution_cancelled(); }
00811 #endif /* __TBB_TASK_GROUP_CONTEXT */
00812 
00813 #if __TBB_TASK_PRIORITY
00815     void set_group_priority ( priority_t p ) {  prefix().context->set_priority(p); }
00816 
00818     priority_t group_priority () const { return prefix().context->priority(); }
00819 
00820 #endif /* __TBB_TASK_PRIORITY */
00821 
00822 private:
00823     friend class interface5::internal::task_base;
00824     friend class task_list;
00825     friend class internal::scheduler;
00826     friend class internal::allocate_root_proxy;
00827 #if __TBB_TASK_GROUP_CONTEXT
00828     friend class internal::allocate_root_with_context_proxy;
00829 #endif /* __TBB_TASK_GROUP_CONTEXT */
00830     friend class internal::allocate_continuation_proxy;
00831     friend class internal::allocate_child_proxy;
00832     friend class internal::allocate_additional_child_of_proxy;
00833 
00835 
00836     internal::task_prefix& prefix( internal::version_tag* = NULL ) const {
00837         return reinterpret_cast<internal::task_prefix*>(const_cast<task*>(this))[-1];
00838     }
00839 }; // class task
00840 
00842 
00843 class empty_task: public task {
00844     /*override*/ task* execute() {
00845         return NULL;
00846     }
00847 };
00848 
00850 
00852 class task_list: internal::no_copy {
00853 private:
00854     task* first;
00855     task** next_ptr;
00856     friend class task;
00857     friend class interface5::internal::task_base;
00858 public:
00860     task_list() : first(NULL), next_ptr(&first) {}
00861 
00863     ~task_list() {}
00864 
00866     bool empty() const {return !first;}
00867 
00869     void push_back( task& task ) {
00870         task.prefix().next = NULL;
00871         *next_ptr = &task;
00872         next_ptr = &task.prefix().next;
00873     }
00874 
00876     task& pop_front() {
00877         __TBB_ASSERT( !empty(), "attempt to pop item from empty task_list" );
00878         task* result = first;
00879         first = result->prefix().next;
00880         if( !first ) next_ptr = &first;
00881         return *result;
00882     }
00883 
00885     void clear() {
00886         first=NULL;
00887         next_ptr=&first;
00888     }
00889 };
00890 
00891 inline void interface5::internal::task_base::spawn( task& t ) {
00892     t.prefix().owner->spawn( t, t.prefix().next );
00893 }
00894 
00895 inline void interface5::internal::task_base::spawn( task_list& list ) {
00896     if( task* t = list.first ) {
00897         t->prefix().owner->spawn( *t, *list.next_ptr );
00898         list.clear();
00899     }
00900 }
00901 
00902 inline void task::spawn_root_and_wait( task_list& root_list ) {
00903     if( task* t = root_list.first ) {
00904         t->prefix().owner->spawn_root_and_wait( *t, *root_list.next_ptr );
00905         root_list.clear();
00906     }
00907 }
00908 
00909 } // namespace tbb
00910 
00911 inline void *operator new( size_t bytes, const tbb::internal::allocate_root_proxy& ) {
00912     return &tbb::internal::allocate_root_proxy::allocate(bytes);
00913 }
00914 
00915 inline void operator delete( void* task, const tbb::internal::allocate_root_proxy& ) {
00916     tbb::internal::allocate_root_proxy::free( *static_cast<tbb::task*>(task) );
00917 }
00918 
00919 #if __TBB_TASK_GROUP_CONTEXT
00920 inline void *operator new( size_t bytes, const tbb::internal::allocate_root_with_context_proxy& p ) {
00921     return &p.allocate(bytes);
00922 }
00923 
00924 inline void operator delete( void* task, const tbb::internal::allocate_root_with_context_proxy& p ) {
00925     p.free( *static_cast<tbb::task*>(task) );
00926 }
00927 #endif /* __TBB_TASK_GROUP_CONTEXT */
00928 
00929 inline void *operator new( size_t bytes, const tbb::internal::allocate_continuation_proxy& p ) {
00930     return &p.allocate(bytes);
00931 }
00932 
00933 inline void operator delete( void* task, const tbb::internal::allocate_continuation_proxy& p ) {
00934     p.free( *static_cast<tbb::task*>(task) );
00935 }
00936 
00937 inline void *operator new( size_t bytes, const tbb::internal::allocate_child_proxy& p ) {
00938     return &p.allocate(bytes);
00939 }
00940 
00941 inline void operator delete( void* task, const tbb::internal::allocate_child_proxy& p ) {
00942     p.free( *static_cast<tbb::task*>(task) );
00943 }
00944 
00945 inline void *operator new( size_t bytes, const tbb::internal::allocate_additional_child_of_proxy& p ) {
00946     return &p.allocate(bytes);
00947 }
00948 
00949 inline void operator delete( void* task, const tbb::internal::allocate_additional_child_of_proxy& p ) {
00950     p.free( *static_cast<tbb::task*>(task) );
00951 }
00952 
00953 #endif /* __TBB_task_H */

Copyright © 2005-2011 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.