00001
00031 #include "linden_common.h"
00032 #include "llapr.h"
00033
00034 #include "apr-1/apr_portable.h"
00035
00036 #include "llthread.h"
00037
00038 #include "lltimer.h"
00039
00040 #if LL_LINUX || LL_SOLARIS
00041 #include <sched.h>
00042 #endif
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
00068 {
00069 LLThread *threadp = (LLThread *)datap;
00070
00071
00072 threadp->mStatus = RUNNING;
00073
00074
00075 threadp->run();
00076
00077 llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl;
00078
00079
00080 threadp->mStatus = STOPPED;
00081
00082 return NULL;
00083 }
00084
00085
00086 LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
00087 mPaused(FALSE),
00088 mName(name),
00089 mAPRThreadp(NULL),
00090 mStatus(STOPPED)
00091 {
00092
00093 if (poolp)
00094 {
00095 mIsLocalPool = FALSE;
00096 mAPRPoolp = poolp;
00097 }
00098 else
00099 {
00100 mIsLocalPool = TRUE;
00101 apr_pool_create(&mAPRPoolp, NULL);
00102 }
00103 mRunCondition = new LLCondition(mAPRPoolp);
00104 }
00105
00106
00107 LLThread::~LLThread()
00108 {
00109 shutdown();
00110 }
00111
00112 void LLThread::shutdown()
00113 {
00114
00115
00116 if (mAPRThreadp)
00117 {
00118 if (!isStopped())
00119 {
00120
00121
00122 setQuitting();
00123
00124 llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl;
00125
00126
00127
00128 S32 counter = 0;
00129 const S32 MAX_WAIT = 600;
00130 while (counter < MAX_WAIT)
00131 {
00132 if (isStopped())
00133 {
00134 break;
00135 }
00136
00137 ms_sleep(100);
00138 yield();
00139 counter++;
00140 }
00141 }
00142
00143 if (!isStopped())
00144 {
00145
00146 llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
00147 return;
00148 }
00149 mAPRThreadp = NULL;
00150 }
00151
00152 delete mRunCondition;
00153
00154 if (mIsLocalPool)
00155 {
00156 apr_pool_destroy(mAPRPoolp);
00157 }
00158 }
00159
00160
00161 void LLThread::start()
00162 {
00163 apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
00164
00165
00166 apr_thread_detach(mAPRThreadp);
00167 }
00168
00169
00170
00171
00172
00173
00174 void LLThread::pause()
00175 {
00176 if (!mPaused)
00177 {
00178
00179 mPaused = 1;
00180 }
00181 }
00182
00183 void LLThread::unpause()
00184 {
00185 if (mPaused)
00186 {
00187 mPaused = 0;
00188 }
00189
00190 wake();
00191 }
00192
00193
00194 bool LLThread::runCondition(void)
00195 {
00196
00197 return true;
00198 }
00199
00200
00201
00202
00203 void LLThread::checkPause()
00204 {
00205 mRunCondition->lock();
00206
00207
00208 while(shouldSleep())
00209 {
00210 mRunCondition->wait();
00211
00212 }
00213
00214 mRunCondition->unlock();
00215 }
00216
00217
00218
00219 void LLThread::setQuitting()
00220 {
00221 mRunCondition->lock();
00222 if (mStatus == RUNNING)
00223 {
00224 mStatus = QUITTING;
00225 }
00226 mRunCondition->unlock();
00227 wake();
00228 }
00229
00230
00231 U32 LLThread::currentID()
00232 {
00233 return (U32)apr_os_thread_current();
00234 }
00235
00236
00237 void LLThread::yield()
00238 {
00239 #if LL_LINUX || LL_SOLARIS
00240 sched_yield();
00241 #else
00242 apr_thread_yield();
00243 #endif
00244 }
00245
00246 void LLThread::wake()
00247 {
00248 mRunCondition->lock();
00249 if(!shouldSleep())
00250 {
00251 mRunCondition->signal();
00252 }
00253 mRunCondition->unlock();
00254 }
00255
00256 void LLThread::wakeLocked()
00257 {
00258 if(!shouldSleep())
00259 {
00260 mRunCondition->signal();
00261 }
00262 }
00263
00264
00265
00266 LLMutex::LLMutex(apr_pool_t *poolp) :
00267 mAPRMutexp(NULL)
00268 {
00269 if (poolp)
00270 {
00271 mIsLocalPool = FALSE;
00272 mAPRPoolp = poolp;
00273 }
00274 else
00275 {
00276 mIsLocalPool = TRUE;
00277 apr_pool_create(&mAPRPoolp, NULL);
00278 }
00279 apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
00280 }
00281
00282
00283 LLMutex::~LLMutex()
00284 {
00285 #if _DEBUG
00286 llassert(!isLocked());
00287 #endif
00288 apr_thread_mutex_destroy(mAPRMutexp);
00289 mAPRMutexp = NULL;
00290 if (mIsLocalPool)
00291 {
00292 apr_pool_destroy(mAPRPoolp);
00293 }
00294 }
00295
00296
00297 void LLMutex::lock()
00298 {
00299 apr_thread_mutex_lock(mAPRMutexp);
00300 }
00301
00302 void LLMutex::unlock()
00303 {
00304 apr_thread_mutex_unlock(mAPRMutexp);
00305 }
00306
00307 bool LLMutex::isLocked()
00308 {
00309 apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
00310 if (APR_STATUS_IS_EBUSY(status))
00311 {
00312 return true;
00313 }
00314 else
00315 {
00316 apr_thread_mutex_unlock(mAPRMutexp);
00317 return false;
00318 }
00319 }
00320
00321
00322
00323 LLCondition::LLCondition(apr_pool_t *poolp) :
00324 LLMutex(poolp)
00325 {
00326
00327
00328 apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
00329 }
00330
00331
00332 LLCondition::~LLCondition()
00333 {
00334 apr_thread_cond_destroy(mAPRCondp);
00335 mAPRCondp = NULL;
00336 }
00337
00338
00339 void LLCondition::wait()
00340 {
00341 apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
00342 }
00343
00344 void LLCondition::signal()
00345 {
00346 apr_thread_cond_signal(mAPRCondp);
00347 }
00348
00349 void LLCondition::broadcast()
00350 {
00351 apr_thread_cond_broadcast(mAPRCondp);
00352 }
00353
00354
00355
00356
00357
00358
00359 LLMutex* LLThreadSafeRefCount::sMutex = 0;
00360
00361
00362 void LLThreadSafeRefCount::initClass()
00363 {
00364 if (!sMutex)
00365 {
00366 sMutex = new LLMutex(0);
00367 }
00368 }
00369
00370
00371 void LLThreadSafeRefCount::cleanupClass()
00372 {
00373 delete sMutex;
00374 sMutex = NULL;
00375 }
00376
00377
00378
00379
00380 LLThreadSafeRefCount::LLThreadSafeRefCount() :
00381 mRef(0)
00382 {
00383 }
00384
00385 LLThreadSafeRefCount::~LLThreadSafeRefCount()
00386 {
00387 if (mRef != 0)
00388 {
00389 llerrs << "deleting non-zero reference" << llendl;
00390 }
00391 }
00392
00393
00394
00395 LLResponder::~LLResponder()
00396 {
00397 }
00398
00399