qthread_unix.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** No Commercial Usage
10 ** This file contains pre-release code and may not be distributed.
11 ** You may use this file in accordance with the terms and conditions
12 ** contained in the either Technology Preview License Agreement or the
13 ** Beta Release License Agreement.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** If you are unsure which license is appropriate for your use, please
37 ** contact the sales department at http://www.qtsoftware.com/contact.
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qglobal.h"
43 
44 #if defined(_OS_HPUX_)
45 #include <sys/pstat.h>
46 #elif defined(_OS_MAC_)
47 #undef DEBUG
48 #include <CoreServices/CoreServices.h>
49 #elif defined(_OS_BSDI_)
50 #include <mach/mach_types.h>
51 #include <sys/systm.h>
52 #include <sys/types.h>
53 #include <sys/sysctl.h>
54 #endif
55 #include <signal.h>
56 #include <unistd.h>
57 #include <stdio.h>
58 
59 #include "qthread.h"
60 #include "qthread_p.h"
61 
62 
63 /**************************************************************************
64  ** QThreadPrivate
65  *************************************************************************/
66 
68  running(FALSE), finished(FALSE), terminated(FALSE), stackSize(0)
69 {
70  thread_id = 0;
71 }
72 
74 {
75 }
76 
77 void *QThreadPrivate::start(void *arg)
78 {
79  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
80  pthread_cleanup_push(QThreadPrivate::finish, arg);
81 
82  QThread *thr = reinterpret_cast<QThread *>(arg);
83 
84  thr->started();
85  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
86  pthread_testcancel();
87  thr->run();
88 
89  pthread_cleanup_pop(1);
90  return 0;
91 }
92 
93 void QThreadPrivate::finish(void *arg)
94 {
95  QThread *thr = reinterpret_cast<QThread *>(arg);
96  QThreadPrivate *d = thr->d;
97  QMutexLocker locker(&d->mutex);
98 
99  d->running = FALSE;
100  d->finished = TRUE;
101  if (d->terminated)
102  thr->terminated();
103  d->terminated = FALSE;
104  thr->finished();
105 
106  d->thread_id = 0;
107  d->thread_done.wakeAll();
108 }
109 
110 
111 
112 
113 /**************************************************************************
114  ** QThread
115  *************************************************************************/
116 
118 {
119  QMutexLocker locker(&d->mutex);
120  if (d->running) return;
121 
122  // Block the SIGINT signal. The threads will inherit the signal mask.
123  // This will avoid them catching SIGINT instead of this thread.
124  sigset_t sigset, oldset;
125  sigemptyset(&sigset);
126  sigaddset(&sigset, SIGINT);
127  pthread_sigmask(SIG_BLOCK, &sigset, &oldset);
128 
129  d->running = TRUE;
130  d->finished = FALSE;
131 
132  pthread_attr_t attr;
133  pthread_attr_init(&attr);
134  pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
135  pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
136  if (d->stackSize>0)
137  {
138 #if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0>0)
139  pthread_attr_setstacksize(&attr,d->stackSize);
140 #endif
141  }
142  int code = pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
143  pthread_attr_destroy(&attr);
144 
145  if (code)
146  {
147  qWarning("QThread::start: Thread creation error: %d", code);
148 
149  d->running = FALSE;
150  d->finished = FALSE;
151  d->thread_id = 0;
152  }
153  else
154  {
155  // Restore the old signal mask only for this thread.
156  pthread_sigmask(SIG_SETMASK, &oldset, NULL);
157  }
158 }
159 
161 {
162  QMutexLocker locker(&d->mutex);
163 
164  if (!d->thread_id) return;
165 
166  int code = pthread_cancel(d->thread_id);
167  if (code)
168  {
169  qWarning("QThread::start: Thread termination error: %d", code);
170  }
171  else
172  {
173  d->terminated = TRUE;
174  }
175 }
176 
178 {
179  QMutexLocker locker(&d->mutex);
180  if (d->finished || !d->running) return;
181 
182  while (d->running)
183  {
184  d->thread_done.wait(locker.mutex());
185  }
186 }
187 
188 #if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)
189 // LSB doesn't define _SC_NPROCESSORS_ONLN.
190 # define _SC_NPROCESSORS_ONLN 84
191 #endif
192 
194 {
195  int cores = -1;
196 #if defined(_OS_MAC_)
197  // Mac OS X
198  cores = (int)MPProcessorsScheduled();
199 #elif defined(_OS_HPUX_)
200  // HP-UX
201  struct pst_dynamic psd;
202  if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) == -1)
203  {
204  perror("pstat_getdynamic");
205  cores = -1;
206  }
207  else
208  {
209  cores = (int)psd.psd_proc_cnt;
210  }
211 #elif defined(_OS_BSDI_)
212  // FreeBSD, OpenBSD, NetBSD, BSD/OS
213  size_t len = sizeof(cores);
214  int mib[2];
215  mib[0] = CTL_HW;
216  mib[1] = HW_NCPU;
217 
218  if (sysctl(mib, 2, &cores, &len, NULL, 0) != 0)
219  {
220  perror("sysctl");
221  cores = -1;
222  }
223 #elif defined(_OS_IRIX_)
224  // IRIX
225  cores = (int)sysconf(_SC_NPROC_ONLN);
226 #else
227  // the rest: Linux, Solaris, AIX, Tru64
228  cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
229 #endif
230  return cores;
231 }
232 
static void * start(void *arg)
pthread_t thread_id
Definition: qthread_p.h:71
G4double thr[100]
Definition: G4S2Light.cc:59
const bool FALSE
Definition: qglobal.h:370
void start()
static void finish(void *arg)
void qWarning(const char *msg,...)
Definition: qglobal.cpp:409
virtual void started()
Definition: qthread.h:65
virtual void finished()
Definition: qthread.h:66
virtual void run()
Definition: qthread.h:70
virtual void terminated()
Definition: qthread.h:67
CodeOutputInterface * code
int mib
QWaitCondition thread_done
Definition: qthread_p.h:72
QThreadPrivate * d
Definition: qthread.h:73
QMutex mutex
Definition: qthread_p.h:63
void terminate()
QMutex * mutex() const
Definition: qmutex.h:77
void wait()
const bool TRUE
Definition: qglobal.h:371
bool terminated
Definition: qthread_p.h:67
static int idealThreadCount()