00001 00023 #ifndef GALOIS_RUNTIME_THREADS_H 00024 #define GALOIS_RUNTIME_THREADS_H 00025 00026 #include "Galois/Executable.h" 00027 #include <boost/intrusive/list.hpp> 00028 #include <vector> 00029 00030 namespace GaloisRuntime { 00031 00032 //declared out of line to correctly initialize data in Threads.cpp 00033 struct initMainThread { 00034 initMainThread(); 00035 }; 00036 00037 class ThreadPool { 00038 friend struct initMainThread; 00039 static __thread unsigned int LocalThreadID; 00040 static int nextThreadID; 00041 protected: 00042 unsigned int activeThreads; 00043 00044 protected: 00045 static void NotifyAware(bool starting); 00046 00047 public: 00050 virtual void run(Galois::Executable* work) = 0; 00051 00054 virtual unsigned int setActiveThreads(unsigned int num) = 0; 00055 00057 unsigned int getActiveThreads() const { return activeThreads; } 00058 00059 static unsigned int getMyID() __attribute__((pure)); 00060 00061 }; 00062 00063 //Returns or creates the appropriate thread pool for the system 00064 ThreadPool& getSystemThreadPool(); 00065 00066 class ThreadPolicy { 00067 protected: 00068 //num levels 00069 int numLevels; 00070 00071 //number of hw supported threads 00072 int numThreads; 00073 00074 //number of "real" processors 00075 int numCores; 00076 00077 //example levels: 00078 //thread(0), Cpu(1), numa(2), machine(3) 00079 00080 //Total number of threads in each level 00081 std::vector<int> levelSize; 00082 00083 //[numLevels][numThreads] -> item index for thread at level 00084 std::vector<int> levelMap; 00085 00086 public: 00087 int indexLevelMap(int level, int thr) const { 00088 return levelMap[level * numThreads + thr]; 00089 } 00090 00091 int getNumLevels() const { return numLevels; } 00092 00093 int getNumThreads() const { return numThreads; } 00094 00095 int getNumCores() const { return numCores; } 00096 00097 int getLevelSize(int S) const { return levelSize[S]; } 00098 00099 int isFirstInLevel(int level, int thr) const { 00100 int thrLevel = indexLevelMap(level, thr); 00101 for (int i = 0; i < getNumThreads(); ++i) 00102 if (indexLevelMap(level, i) == thrLevel) 00103 return i == thr; 00104 //Should be dead: 00105 return false; 00106 } 00107 00108 virtual void bindThreadToProcessor(int id) = 0; 00109 }; 00110 00111 ThreadPolicy& getSystemThreadPolicy(); 00112 void setSystemThreadPolicy(const char* name); 00113 00114 namespace HIDDEN { 00115 //Tag for invasive list 00116 class ThreadAwareTag; 00117 00118 //Hook type for invasive list 00119 typedef boost::intrusive::list_base_hook<boost::intrusive::tag<ThreadAwareTag> > ThreadAwareHook; 00120 } 00121 00122 //This notifies when the number of threads change 00123 class ThreadAware : public HIDDEN::ThreadAwareHook { 00124 friend class ThreadPool; 00125 static void NotifyOfChange(bool starting); 00126 00127 //This is called to notify the start and end of a parallel region 00128 //starting = true -> parallel code is initializing 00129 //starting = false -> parallel code is ending 00130 virtual void ThreadChange(bool starting) = 0; 00131 00132 public: 00133 ThreadAware(); 00134 virtual ~ThreadAware(); 00135 00136 }; 00137 00138 } 00139 00140 #endif