00001 /* 00002 * Copyright 2004-2006 Intel Corporation 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 00018 #ifndef _OASYS_THREAD_H_ 00019 #define _OASYS_THREAD_H_ 00020 00021 #include "config.h" 00022 00023 #include <sys/types.h> 00024 00025 #ifdef __win32__ 00026 00027 #include <Windows.h> 00028 00029 #else 00030 00031 #include <pthread.h> 00032 #include <signal.h> 00033 00034 #ifdef HAVE_SCHED_YIELD 00035 #include <sched.h> 00036 #endif 00037 00038 #endif // __win32__ 00039 00040 #include <vector> 00041 00042 #include "../debug/DebugUtils.h" 00043 00044 namespace oasys { 00045 00046 #ifdef __win32__ 00047 typedef DWORD ThreadId_t; 00048 #else 00049 typedef pthread_t ThreadId_t; 00050 #endif 00051 00052 class SpinLock; 00053 00059 class Thread { 00060 public: 00064 enum thread_flags_t { 00067 CREATE_JOINABLE = 1 << 0, 00069 DELETE_ON_EXIT = 1 << 1, 00071 INTERRUPTABLE = 1 << 2, 00073 STARTED = 1 << 3, 00075 SHOULD_STOP = 1 << 4, 00077 STOPPED = 1 << 5, 00078 }; 00079 00080 #ifndef __win32__ 00081 00085 enum thread_signal_t { 00086 INTERRUPT_SIG = SIGURG 00087 }; 00088 #endif 00089 00093 static const int max_live_threads_ = 256; 00094 00099 static Thread* all_threads_[Thread::max_live_threads_]; 00100 00105 static SpinLock* all_threads_lock_; 00106 00114 static void activate_start_barrier(); 00115 00120 static void release_start_barrier(); 00121 00125 static bool start_barrier_enabled() { 00126 return start_barrier_enabled_; 00127 } 00128 00134 static void yield(); 00135 00145 static void spin_yield(); 00146 00153 static ThreadId_t current(); 00154 00158 static bool id_equal(ThreadId_t a, ThreadId_t b); 00159 00163 Thread(const char* name, int flags = 0); 00164 00168 virtual ~Thread(); 00169 00174 void start(); 00175 00179 void join(); 00180 00184 void kill(int sig); 00185 00193 void interrupt(); 00194 00204 void set_interruptable(bool interruptable); 00205 00213 void set_should_stop() { flags_ |= SHOULD_STOP; } 00214 00218 bool should_stop() { return ((flags_ & SHOULD_STOP) != 0); } 00219 00223 bool is_stopped() { return ((flags_ & STOPPED) != 0); } 00224 00228 bool started() { return ((flags_ & STARTED) != 0); } 00229 00233 void set_flag(thread_flags_t flag) { flags_ |= flag; } 00234 00238 void clear_flag(thread_flags_t flag) { flags_ &= ~flag; } 00239 00244 ThreadId_t thread_id() { return thread_id_; } 00245 00246 protected: 00247 #ifdef __win32__ 00249 static __declspec(thread) Thread* current_thread_; 00250 HANDLE join_event_; 00251 #endif // __win32__ 00252 00253 #ifndef __win32__ 00254 static bool signals_inited_; 00255 static sigset_t interrupt_sigset_; 00256 #endif 00257 00258 static bool start_barrier_enabled_; 00259 static std::vector<Thread*> threads_in_barrier_; 00260 00261 ThreadId_t thread_id_; 00262 int flags_; 00263 char name_[64]; 00264 00268 #ifdef __win32__ 00269 static DWORD WINAPI pre_thread_run(void* t); 00270 #else 00271 static void* pre_thread_run(void* t); 00272 #endif 00273 00277 static void interrupt_signal(int sig); 00278 00283 void thread_run(const char* thread_name, ThreadId_t thread_id); 00284 00289 virtual void run() = 0; 00290 }; 00291 00292 //--------------------------------------------------------------------------- 00293 inline ThreadId_t 00294 Thread::current() 00295 { 00296 #ifdef __win32__ 00297 return current_thread_->thread_id_; 00298 #else 00299 return pthread_self(); 00300 #endif 00301 } 00302 00303 //--------------------------------------------------------------------------- 00304 inline void 00305 Thread::yield() 00306 { 00307 #ifndef __win32__ 00308 #ifdef HAVE_THREAD_ID_YIELD 00309 thread_id_yield(); 00310 #elif HAVE_SCHED_YIELD 00311 sched_yield(); 00312 #else 00313 #error MUST EITHER HAVE THREAD_ID_YIELD OR SCHED_YIELD 00314 #endif 00315 #endif // __win32__ 00316 } 00317 00318 //--------------------------------------------------------------------------- 00319 inline void 00320 Thread::spin_yield() 00321 { 00322 // XXX/bowei: 00323 // 1-p call yield() 00324 // o.w. spin 00325 Thread::yield(); 00326 } 00327 00328 } // namespace oasys 00329 00330 #endif /* _OASYS_THREAD_H_ */