PageRenderTime 46ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/src/qt/qtbase/src/corelib/thread/qthread_unix.cpp

https://gitlab.com/x33n/phantomjs
C++ | 745 lines | 526 code | 122 blank | 97 comment | 94 complexity | 5971312ca9ebdc8652b1b5ab6c736b68 MD5 | raw file
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
  4. ** Contact: http://www.qt-project.org/legal
  5. **
  6. ** This file is part of the QtCore module of the Qt Toolkit.
  7. **
  8. ** $QT_BEGIN_LICENSE:LGPL$
  9. ** Commercial License Usage
  10. ** Licensees holding valid commercial Qt licenses may use this file in
  11. ** accordance with the commercial license agreement provided with the
  12. ** Software or, alternatively, in accordance with the terms contained in
  13. ** a written agreement between you and Digia. For licensing terms and
  14. ** conditions see http://qt.digia.com/licensing. For further information
  15. ** use the contact form at http://qt.digia.com/contact-us.
  16. **
  17. ** GNU Lesser General Public License Usage
  18. ** Alternatively, this file may be used under the terms of the GNU Lesser
  19. ** General Public License version 2.1 as published by the Free Software
  20. ** Foundation and appearing in the file LICENSE.LGPL included in the
  21. ** packaging of this file. Please review the following information to
  22. ** ensure the GNU Lesser General Public License version 2.1 requirements
  23. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  24. **
  25. ** In addition, as a special exception, Digia gives you certain additional
  26. ** rights. These rights are described in the Digia Qt LGPL Exception
  27. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  28. **
  29. ** GNU General Public License Usage
  30. ** Alternatively, this file may be used under the terms of the GNU
  31. ** General Public License version 3.0 as published by the Free Software
  32. ** Foundation and appearing in the file LICENSE.GPL included in the
  33. ** packaging of this file. Please review the following information to
  34. ** ensure the GNU General Public License version 3.0 requirements will be
  35. ** met: http://www.gnu.org/copyleft/gpl.html.
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "qthread.h"
  42. #include "qplatformdefs.h"
  43. #include <private/qcoreapplication_p.h>
  44. #if defined(Q_OS_BLACKBERRY)
  45. # include <private/qeventdispatcher_blackberry_p.h>
  46. #else
  47. # if !defined(QT_NO_GLIB)
  48. # include "../kernel/qeventdispatcher_glib_p.h"
  49. # endif
  50. # include <private/qeventdispatcher_unix_p.h>
  51. #endif
  52. #include "qthreadstorage.h"
  53. #include "qthread_p.h"
  54. #include "qdebug.h"
  55. #include <sched.h>
  56. #include <errno.h>
  57. #ifdef Q_OS_BSD4
  58. #include <sys/sysctl.h>
  59. #endif
  60. #ifdef Q_OS_VXWORKS
  61. # if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6))
  62. # include <vxCpuLib.h>
  63. # include <cpuset.h>
  64. # define QT_VXWORKS_HAS_CPUSET
  65. # endif
  66. #endif
  67. #ifdef Q_OS_HPUX
  68. #include <sys/pstat.h>
  69. #endif
  70. #if defined(Q_OS_MAC)
  71. # ifdef qDebug
  72. # define old_qDebug qDebug
  73. # undef qDebug
  74. # endif
  75. #ifdef Q_OS_MACX
  76. # include <CoreServices/CoreServices.h>
  77. #endif // Q_OS_MACX
  78. # ifdef old_qDebug
  79. # undef qDebug
  80. # define qDebug QT_NO_QDEBUG_MACRO
  81. # undef old_qDebug
  82. # endif
  83. #endif
  84. #if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
  85. #include <sys/prctl.h>
  86. #endif
  87. #if defined(Q_OS_LINUX) && !defined(SCHED_IDLE)
  88. // from linux/sched.h
  89. # define SCHED_IDLE 5
  90. #endif
  91. #if defined(Q_OS_DARWIN) || !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0)
  92. #define QT_HAS_THREAD_PRIORITY_SCHEDULING
  93. #endif
  94. QT_BEGIN_NAMESPACE
  95. #ifndef QT_NO_THREAD
  96. enum { ThreadPriorityResetFlag = 0x80000000 };
  97. #if defined(Q_OS_LINUX) && defined(__GLIBC__) && (defined(Q_CC_GNU) || defined(Q_CC_INTEL)) && !defined(QT_LINUXBASE)
  98. /* LSB doesn't have __thread, https://lsbbugs.linuxfoundation.org/show_bug.cgi?id=993 */
  99. #define HAVE_TLS
  100. #endif
  101. #if defined(Q_CC_XLC) || defined (Q_CC_SUN)
  102. #define HAVE_TLS
  103. #endif
  104. #ifdef HAVE_TLS
  105. static __thread QThreadData *currentThreadData = 0;
  106. #endif
  107. static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
  108. static pthread_key_t current_thread_data_key;
  109. static void destroy_current_thread_data(void *p)
  110. {
  111. #if defined(Q_OS_VXWORKS)
  112. // Calling setspecific(..., 0) sets the value to 0 for ALL threads.
  113. // The 'set to 1' workaround adds a bit of an overhead though,
  114. // since this function is called twice now.
  115. if (p == (void *)1)
  116. return;
  117. #endif
  118. // POSIX says the value in our key is set to zero before calling
  119. // this destructor function, so we need to set it back to the
  120. // right value...
  121. pthread_setspecific(current_thread_data_key, p);
  122. QThreadData *data = static_cast<QThreadData *>(p);
  123. if (data->isAdopted) {
  124. QThread *thread = data->thread;
  125. Q_ASSERT(thread);
  126. QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
  127. Q_ASSERT(!thread_p->finished);
  128. thread_p->finish(thread);
  129. }
  130. data->deref();
  131. // ... but we must reset it to zero before returning so we aren't
  132. // called again (POSIX allows implementations to call destructor
  133. // functions repeatedly until all values are zero)
  134. pthread_setspecific(current_thread_data_key,
  135. #if defined(Q_OS_VXWORKS)
  136. (void *)1);
  137. #else
  138. 0);
  139. #endif
  140. }
  141. static void create_current_thread_data_key()
  142. {
  143. pthread_key_create(&current_thread_data_key, destroy_current_thread_data);
  144. }
  145. static void destroy_current_thread_data_key()
  146. {
  147. pthread_once(&current_thread_data_once, create_current_thread_data_key);
  148. pthread_key_delete(current_thread_data_key);
  149. // Reset current_thread_data_once in case we end up recreating
  150. // the thread-data in the rare case of QObject construction
  151. // after destroying the QThreadData.
  152. pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT;
  153. current_thread_data_once = pthread_once_init;
  154. }
  155. Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
  156. // Utility functions for getting, setting and clearing thread specific data.
  157. static QThreadData *get_thread_data()
  158. {
  159. #ifdef HAVE_TLS
  160. return currentThreadData;
  161. #else
  162. pthread_once(&current_thread_data_once, create_current_thread_data_key);
  163. return reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
  164. #endif
  165. }
  166. static void set_thread_data(QThreadData *data)
  167. {
  168. #ifdef HAVE_TLS
  169. currentThreadData = data;
  170. #endif
  171. pthread_once(&current_thread_data_once, create_current_thread_data_key);
  172. pthread_setspecific(current_thread_data_key, data);
  173. }
  174. static void clear_thread_data()
  175. {
  176. #ifdef HAVE_TLS
  177. currentThreadData = 0;
  178. #endif
  179. pthread_setspecific(current_thread_data_key, 0);
  180. }
  181. void QThreadData::clearCurrentThreadData()
  182. {
  183. clear_thread_data();
  184. }
  185. QThreadData *QThreadData::current(bool createIfNecessary)
  186. {
  187. QThreadData *data = get_thread_data();
  188. if (!data && createIfNecessary) {
  189. data = new QThreadData;
  190. QT_TRY {
  191. set_thread_data(data);
  192. data->thread = new QAdoptedThread(data);
  193. } QT_CATCH(...) {
  194. clear_thread_data();
  195. data->deref();
  196. data = 0;
  197. QT_RETHROW;
  198. }
  199. data->deref();
  200. data->isAdopted = true;
  201. data->threadId = (Qt::HANDLE)pthread_self();
  202. if (!QCoreApplicationPrivate::theMainThread)
  203. QCoreApplicationPrivate::theMainThread = data->thread;
  204. }
  205. return data;
  206. }
  207. void QAdoptedThread::init()
  208. {
  209. Q_D(QThread);
  210. d->thread_id = pthread_self();
  211. }
  212. /*
  213. QThreadPrivate
  214. */
  215. #if defined(Q_C_CALLBACKS)
  216. extern "C" {
  217. #endif
  218. typedef void*(*QtThreadCallback)(void*);
  219. #if defined(Q_C_CALLBACKS)
  220. }
  221. #endif
  222. #endif // QT_NO_THREAD
  223. void QThreadPrivate::createEventDispatcher(QThreadData *data)
  224. {
  225. #if defined(Q_OS_BLACKBERRY)
  226. data->eventDispatcher.storeRelease(new QEventDispatcherBlackberry);
  227. #else
  228. #if !defined(QT_NO_GLIB)
  229. if (qEnvironmentVariableIsEmpty("QT_NO_GLIB")
  230. && qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")
  231. && QEventDispatcherGlib::versionSupported())
  232. data->eventDispatcher.storeRelease(new QEventDispatcherGlib);
  233. else
  234. #endif
  235. data->eventDispatcher.storeRelease(new QEventDispatcherUNIX);
  236. #endif
  237. data->eventDispatcher.load()->startingUp();
  238. }
  239. #ifndef QT_NO_THREAD
  240. #if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
  241. static void setCurrentThreadName(pthread_t threadId, const char *name)
  242. {
  243. # if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
  244. Q_UNUSED(threadId);
  245. prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
  246. # elif defined(Q_OS_MAC)
  247. Q_UNUSED(threadId);
  248. pthread_setname_np(name);
  249. # elif defined(Q_OS_QNX)
  250. pthread_setname_np(threadId, name);
  251. # endif
  252. }
  253. #endif
  254. void *QThreadPrivate::start(void *arg)
  255. {
  256. #if !defined(Q_OS_ANDROID)
  257. pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
  258. #endif
  259. pthread_cleanup_push(QThreadPrivate::finish, arg);
  260. QThread *thr = reinterpret_cast<QThread *>(arg);
  261. QThreadData *data = QThreadData::get2(thr);
  262. {
  263. QMutexLocker locker(&thr->d_func()->mutex);
  264. // do we need to reset the thread priority?
  265. if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) {
  266. thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
  267. }
  268. data->threadId = (Qt::HANDLE)pthread_self();
  269. set_thread_data(data);
  270. data->ref();
  271. data->quitNow = thr->d_func()->exited;
  272. }
  273. if (data->eventDispatcher.load()) // custom event dispatcher set?
  274. data->eventDispatcher.load()->startingUp();
  275. else
  276. createEventDispatcher(data);
  277. #if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
  278. // sets the name of the current thread.
  279. QString objectName = thr->objectName();
  280. if (Q_LIKELY(objectName.isEmpty()))
  281. setCurrentThreadName(thr->d_func()->thread_id, thr->metaObject()->className());
  282. else
  283. setCurrentThreadName(thr->d_func()->thread_id, objectName.toLocal8Bit());
  284. #endif
  285. emit thr->started(QThread::QPrivateSignal());
  286. #if !defined(Q_OS_ANDROID)
  287. pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  288. pthread_testcancel();
  289. #endif
  290. thr->run();
  291. pthread_cleanup_pop(1);
  292. return 0;
  293. }
  294. void QThreadPrivate::finish(void *arg)
  295. {
  296. QThread *thr = reinterpret_cast<QThread *>(arg);
  297. QThreadPrivate *d = thr->d_func();
  298. QMutexLocker locker(&d->mutex);
  299. d->isInFinish = true;
  300. d->priority = QThread::InheritPriority;
  301. void *data = &d->data->tls;
  302. locker.unlock();
  303. emit thr->finished(QThread::QPrivateSignal());
  304. QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
  305. QThreadStorageData::finish((void **)data);
  306. locker.relock();
  307. QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
  308. if (eventDispatcher) {
  309. d->data->eventDispatcher = 0;
  310. locker.unlock();
  311. eventDispatcher->closingDown();
  312. delete eventDispatcher;
  313. locker.relock();
  314. }
  315. d->thread_id = 0;
  316. d->running = false;
  317. d->finished = true;
  318. d->interruptionRequested = false;
  319. d->isInFinish = false;
  320. d->thread_done.wakeAll();
  321. }
  322. /**************************************************************************
  323. ** QThread
  324. *************************************************************************/
  325. Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
  326. {
  327. // requires a C cast here otherwise we run into trouble on AIX
  328. return (Qt::HANDLE)pthread_self();
  329. }
  330. #if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)
  331. // LSB doesn't define _SC_NPROCESSORS_ONLN.
  332. # define _SC_NPROCESSORS_ONLN 84
  333. #endif
  334. int QThread::idealThreadCount() Q_DECL_NOTHROW
  335. {
  336. int cores = -1;
  337. #if defined(Q_OS_HPUX)
  338. // HP-UX
  339. struct pst_dynamic psd;
  340. if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) == -1) {
  341. perror("pstat_getdynamic");
  342. cores = -1;
  343. } else {
  344. cores = (int)psd.psd_proc_cnt;
  345. }
  346. #elif defined(Q_OS_BSD4)
  347. // FreeBSD, OpenBSD, NetBSD, BSD/OS, Mac OS X
  348. size_t len = sizeof(cores);
  349. int mib[2];
  350. mib[0] = CTL_HW;
  351. mib[1] = HW_NCPU;
  352. if (sysctl(mib, 2, &cores, &len, NULL, 0) != 0) {
  353. perror("sysctl");
  354. cores = -1;
  355. }
  356. #elif defined(Q_OS_IRIX)
  357. // IRIX
  358. cores = (int)sysconf(_SC_NPROC_ONLN);
  359. #elif defined(Q_OS_INTEGRITY)
  360. #if (__INTEGRITY_MAJOR_VERSION >= 10)
  361. // Integrity V10+ does support multicore CPUs
  362. Value processorCount;
  363. if (GetProcessorCount(CurrentTask(), &processorCount) == 0)
  364. cores = processorCount;
  365. else
  366. #endif
  367. // as of aug 2008 Integrity only supports one single core CPU
  368. cores = 1;
  369. #elif defined(Q_OS_VXWORKS)
  370. // VxWorks
  371. # if defined(QT_VXWORKS_HAS_CPUSET)
  372. cpuset_t cpus = vxCpuEnabledGet();
  373. cores = 0;
  374. // 128 cores should be enough for everyone ;)
  375. for (int i = 0; i < 128 && !CPUSET_ISZERO(cpus); ++i) {
  376. if (CPUSET_ISSET(cpus, i)) {
  377. CPUSET_CLR(cpus, i);
  378. cores++;
  379. }
  380. }
  381. # else
  382. // as of aug 2008 VxWorks < 6.6 only supports one single core CPU
  383. cores = 1;
  384. # endif
  385. #else
  386. // the rest: Linux, Solaris, AIX, Tru64
  387. cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
  388. #endif
  389. return cores;
  390. }
  391. void QThread::yieldCurrentThread()
  392. {
  393. sched_yield();
  394. }
  395. static timespec makeTimespec(time_t secs, long nsecs)
  396. {
  397. struct timespec ts;
  398. ts.tv_sec = secs;
  399. ts.tv_nsec = nsecs;
  400. return ts;
  401. }
  402. void QThread::sleep(unsigned long secs)
  403. {
  404. qt_nanosleep(makeTimespec(secs, 0));
  405. }
  406. void QThread::msleep(unsigned long msecs)
  407. {
  408. qt_nanosleep(makeTimespec(msecs / 1000, msecs % 1000 * 1000 * 1000));
  409. }
  410. void QThread::usleep(unsigned long usecs)
  411. {
  412. qt_nanosleep(makeTimespec(usecs / 1000 / 1000, usecs % (1000*1000) * 1000));
  413. }
  414. #ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
  415. // Does some magic and calculate the Unix scheduler priorities
  416. // sched_policy is IN/OUT: it must be set to a valid policy before calling this function
  417. // sched_priority is OUT only
  418. static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority)
  419. {
  420. #ifdef SCHED_IDLE
  421. if (priority == QThread::IdlePriority) {
  422. *sched_policy = SCHED_IDLE;
  423. *sched_priority = 0;
  424. return true;
  425. }
  426. const int lowestPriority = QThread::LowestPriority;
  427. #else
  428. const int lowestPriority = QThread::IdlePriority;
  429. #endif
  430. const int highestPriority = QThread::TimeCriticalPriority;
  431. int prio_min;
  432. int prio_max;
  433. #if defined(Q_OS_VXWORKS) && defined(VXWORKS_DKM)
  434. // for other scheduling policies than SCHED_RR or SCHED_FIFO
  435. prio_min = SCHED_FIFO_LOW_PRI;
  436. prio_max = SCHED_FIFO_HIGH_PRI;
  437. if ((*sched_policy == SCHED_RR) || (*sched_policy == SCHED_FIFO))
  438. #endif
  439. {
  440. prio_min = sched_get_priority_min(*sched_policy);
  441. prio_max = sched_get_priority_max(*sched_policy);
  442. }
  443. if (prio_min == -1 || prio_max == -1)
  444. return false;
  445. int prio;
  446. // crudely scale our priority enum values to the prio_min/prio_max
  447. prio = ((priority - lowestPriority) * (prio_max - prio_min) / highestPriority) + prio_min;
  448. prio = qMax(prio_min, qMin(prio_max, prio));
  449. *sched_priority = prio;
  450. return true;
  451. }
  452. #endif
  453. void QThread::start(Priority priority)
  454. {
  455. Q_D(QThread);
  456. QMutexLocker locker(&d->mutex);
  457. if (d->isInFinish)
  458. d->thread_done.wait(locker.mutex());
  459. if (d->running)
  460. return;
  461. d->running = true;
  462. d->finished = false;
  463. d->returnCode = 0;
  464. d->exited = false;
  465. d->interruptionRequested = false;
  466. pthread_attr_t attr;
  467. pthread_attr_init(&attr);
  468. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  469. d->priority = priority;
  470. #if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
  471. switch (priority) {
  472. case InheritPriority:
  473. {
  474. pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
  475. break;
  476. }
  477. default:
  478. {
  479. int sched_policy;
  480. if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) {
  481. // failed to get the scheduling policy, don't bother
  482. // setting the priority
  483. qWarning("QThread::start: Cannot determine default scheduler policy");
  484. break;
  485. }
  486. int prio;
  487. if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
  488. // failed to get the scheduling parameters, don't
  489. // bother setting the priority
  490. qWarning("QThread::start: Cannot determine scheduler priority range");
  491. break;
  492. }
  493. sched_param sp;
  494. sp.sched_priority = prio;
  495. if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0
  496. || pthread_attr_setschedpolicy(&attr, sched_policy) != 0
  497. || pthread_attr_setschedparam(&attr, &sp) != 0) {
  498. // could not set scheduling hints, fallback to inheriting them
  499. // we'll try again from inside the thread
  500. pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
  501. d->priority = Priority(priority | ThreadPriorityResetFlag);
  502. }
  503. break;
  504. }
  505. }
  506. #endif // QT_HAS_THREAD_PRIORITY_SCHEDULING
  507. if (d->stackSize > 0) {
  508. #if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0)
  509. int code = pthread_attr_setstacksize(&attr, d->stackSize);
  510. #else
  511. int code = ENOSYS; // stack size not supported, automatically fail
  512. #endif // _POSIX_THREAD_ATTR_STACKSIZE
  513. if (code) {
  514. qWarning("QThread::start: Thread stack size error: %s",
  515. qPrintable(qt_error_string(code)));
  516. // we failed to set the stacksize, and as the documentation states,
  517. // the thread will fail to run...
  518. d->running = false;
  519. d->finished = false;
  520. return;
  521. }
  522. }
  523. int code =
  524. pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
  525. if (code == EPERM) {
  526. // caller does not have permission to set the scheduling
  527. // parameters/policy
  528. #if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
  529. pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
  530. #endif
  531. code =
  532. pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
  533. }
  534. pthread_attr_destroy(&attr);
  535. if (code) {
  536. qWarning("QThread::start: Thread creation error: %s", qPrintable(qt_error_string(code)));
  537. d->running = false;
  538. d->finished = false;
  539. d->thread_id = 0;
  540. }
  541. }
  542. void QThread::terminate()
  543. {
  544. #if !defined(Q_OS_ANDROID)
  545. Q_D(QThread);
  546. QMutexLocker locker(&d->mutex);
  547. if (!d->thread_id)
  548. return;
  549. int code = pthread_cancel(d->thread_id);
  550. if (code) {
  551. qWarning("QThread::start: Thread termination error: %s",
  552. qPrintable(qt_error_string((code))));
  553. }
  554. #endif
  555. }
  556. bool QThread::wait(unsigned long time)
  557. {
  558. Q_D(QThread);
  559. QMutexLocker locker(&d->mutex);
  560. if (d->thread_id == pthread_self()) {
  561. qWarning("QThread::wait: Thread tried to wait on itself");
  562. return false;
  563. }
  564. if (d->finished || !d->running)
  565. return true;
  566. while (d->running) {
  567. if (!d->thread_done.wait(locker.mutex(), time))
  568. return false;
  569. }
  570. return true;
  571. }
  572. void QThread::setTerminationEnabled(bool enabled)
  573. {
  574. QThread *thr = currentThread();
  575. Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()",
  576. "Current thread was not started with QThread.");
  577. Q_UNUSED(thr)
  578. #if defined(Q_OS_ANDROID)
  579. Q_UNUSED(enabled);
  580. #else
  581. pthread_setcancelstate(enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, NULL);
  582. if (enabled)
  583. pthread_testcancel();
  584. #endif
  585. }
  586. // Caller must lock the mutex
  587. void QThreadPrivate::setPriority(QThread::Priority threadPriority)
  588. {
  589. priority = threadPriority;
  590. // copied from start() with a few modifications:
  591. #ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
  592. int sched_policy;
  593. sched_param param;
  594. if (pthread_getschedparam(thread_id, &sched_policy, &param) != 0) {
  595. // failed to get the scheduling policy, don't bother setting
  596. // the priority
  597. qWarning("QThread::setPriority: Cannot get scheduler parameters");
  598. return;
  599. }
  600. int prio;
  601. if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
  602. // failed to get the scheduling parameters, don't
  603. // bother setting the priority
  604. qWarning("QThread::setPriority: Cannot determine scheduler priority range");
  605. return;
  606. }
  607. param.sched_priority = prio;
  608. int status = pthread_setschedparam(thread_id, sched_policy, &param);
  609. # ifdef SCHED_IDLE
  610. // were we trying to set to idle priority and failed?
  611. if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) {
  612. // reset to lowest priority possible
  613. pthread_getschedparam(thread_id, &sched_policy, &param);
  614. param.sched_priority = sched_get_priority_min(sched_policy);
  615. pthread_setschedparam(thread_id, sched_policy, &param);
  616. }
  617. # else
  618. Q_UNUSED(status);
  619. # endif // SCHED_IDLE
  620. #endif
  621. }
  622. #endif // QT_NO_THREAD
  623. QT_END_NAMESPACE