00001 // Per CPU/Thread data support -*- C++ -*- 00002 /* 00003 Galois, a framework to exploit amorphous data-parallelism in irregular 00004 programs. 00005 00006 Copyright (C) 2011, The University of Texas at Austin. All rights reserved. 00007 UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS SOFTWARE 00008 AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR ANY 00009 PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF PERFORMANCE, AND ANY 00010 WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF DEALING OR USAGE OF TRADE. 00011 NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH RESPECT TO THE USE OF THE 00012 SOFTWARE OR DOCUMENTATION. Under no circumstances shall University be liable 00013 for incidental, special, indirect, direct or consequential damages or loss of 00014 profits, interruption of business, or related expenses which may arise from use 00015 of Software or Documentation, including but not limited to those resulting from 00016 defects in Software and/or Documentation, or loss or inaccuracy of data of any 00017 kind. 00018 */ 00019 00020 #ifndef __GALOIS_PERCPU_H 00021 #define __GALOIS_PERCPU_H 00022 00023 #include "Threads.h" 00024 #include "CacheLineStorage.h" 00025 00026 #include <boost/utility.hpp> 00027 #include <cassert> 00028 00029 namespace GaloisRuntime { 00030 00031 //Stores 1 item per thread 00032 //The master thread is thread 0 00033 //Durring Parallel regions the threads index 00034 //from 0 -> num - 1 (one thread pool thread shares an index with the user thread) 00035 template<typename T> 00036 class PerCPU : private boost::noncopyable { 00037 protected: 00038 cache_line_storage<T>* datum; 00039 unsigned int num; 00040 00041 int myID() const { 00042 int i = ThreadPool::getMyID(); 00043 return std::max(0, i - 1); 00044 } 00045 00046 public: 00047 PerCPU() 00048 { 00049 num = getSystemThreadPolicy().getNumThreads(); 00050 datum = new cache_line_storage<T>[num]; 00051 } 00052 explicit PerCPU(const T& ival) 00053 { 00054 num = getSystemThreadPolicy().getNumThreads(); 00055 datum = new cache_line_storage<T>[num]; 00056 reset(ival); 00057 } 00058 00059 virtual ~PerCPU() { 00060 delete[] datum; 00061 } 00062 00063 void reset(const T& d) { 00064 for (unsigned int i = 0; i < num; ++i) 00065 datum[i].data = d; 00066 } 00067 00068 unsigned int myEffectiveID() const { 00069 return myID(); 00070 } 00071 00072 T& get(unsigned int i) { 00073 assert(i < num); 00074 assert(datum); 00075 return datum[i].data; 00076 } 00077 00078 const T& get(unsigned int i) const { 00079 assert(i < num); 00080 assert(datum); 00081 return datum[i].data; 00082 } 00083 00084 T& get() { 00085 return get(myID()); 00086 } 00087 00088 const T& get() const { 00089 return get(myID()); 00090 } 00091 00092 T& getNext() { 00093 return get((myID() + 1) % getSystemThreadPool().getActiveThreads()); 00094 } 00095 00096 const T& getNext() const { 00097 return get((myID() + 1) % getSystemThreadPool().getActiveThreads()); 00098 } 00099 00100 unsigned int size() const { 00101 return num; 00102 } 00103 }; 00104 00105 template<typename T> 00106 class PerLevel { 00107 cache_line_storage<T>* datum; 00108 unsigned int num; 00109 unsigned int level; 00110 ThreadPolicy& P; 00111 00112 protected: 00113 00114 unsigned int myID() const { 00115 int i = ThreadPool::getMyID(); 00116 return std::max(0, i - 1); 00117 } 00118 00119 00120 public: 00121 PerLevel() :P(getSystemThreadPolicy()) 00122 { 00123 //last iteresting level (should be package) 00124 level = P.getNumLevels() - 1; 00125 num = P.getLevelSize(level); 00126 datum = new cache_line_storage<T>[num]; 00127 } 00128 00129 virtual ~PerLevel() { 00130 delete[] datum; 00131 } 00132 00133 unsigned int myEffectiveID() const { 00134 return P.indexLevelMap(level, myID()); 00135 } 00136 00137 T& get(unsigned int i) { 00138 assert(i < num); 00139 assert(datum); 00140 return datum[i].data; 00141 } 00142 00143 const T& get(unsigned int i) const { 00144 assert(i < num); 00145 assert(datum); 00146 return datum[i].data; 00147 } 00148 00149 T& get() { 00150 return get(myEffectiveID()); 00151 } 00152 00153 const T& get() const { 00154 return get(myEffectiveID()); 00155 } 00156 00157 unsigned int size() const { 00158 return num; 00159 } 00160 00161 bool isFirstInLevel() const { 00162 return P.isFirstInLevel(level, myID()); 00163 } 00164 00165 }; 00166 00167 } 00168 00169 #endif 00170