Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
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 <unistd.h>␊ |
56 | ␊ |
57 | #include "qthread.h"␊ |
58 | #include "qthread_p.h"␊ |
59 | ␊ |
60 | ␊ |
61 | /**************************************************************************␊ |
62 | ** QThreadPrivate␊ |
63 | *************************************************************************/␊ |
64 | ␊ |
65 | QThreadPrivate::QThreadPrivate() :␊ |
66 | running(FALSE), finished(FALSE), terminated(FALSE), stackSize(0)␊ |
67 | {␊ |
68 | thread_id = 0;␊ |
69 | }␊ |
70 | ␊ |
71 | QThreadPrivate::~QThreadPrivate()␊ |
72 | {␊ |
73 | }␊ |
74 | ␊ |
75 | void *QThreadPrivate::start(void *arg)␊ |
76 | {␊ |
77 | pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);␊ |
78 | pthread_cleanup_push(QThreadPrivate::finish, arg);␊ |
79 | ␊ |
80 | QThread *thr = reinterpret_cast<QThread *>(arg);␊ |
81 | ␊ |
82 | thr->started();␊ |
83 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);␊ |
84 | pthread_testcancel();␊ |
85 | thr->run();␊ |
86 | ␊ |
87 | pthread_cleanup_pop(1);␊ |
88 | return 0;␊ |
89 | }␊ |
90 | ␊ |
91 | void QThreadPrivate::finish(void *arg)␊ |
92 | {␊ |
93 | QThread *thr = reinterpret_cast<QThread *>(arg);␊ |
94 | QThreadPrivate *d = thr->d;␊ |
95 | QMutexLocker locker(&d->mutex);␊ |
96 | ␊ |
97 | d->running = FALSE;␊ |
98 | d->finished = TRUE;␊ |
99 | if (d->terminated)␊ |
100 | thr->terminated();␊ |
101 | d->terminated = FALSE;␊ |
102 | thr->finished();␊ |
103 | ␊ |
104 | d->thread_id = 0;␊ |
105 | d->thread_done.wakeAll();␊ |
106 | }␊ |
107 | ␊ |
108 | ␊ |
109 | ␊ |
110 | ␊ |
111 | /**************************************************************************␊ |
112 | ** QThread␊ |
113 | *************************************************************************/␊ |
114 | ␊ |
115 | void QThread::start()␊ |
116 | {␊ |
117 | QMutexLocker locker(&d->mutex);␊ |
118 | if (d->running) return;␊ |
119 | ␊ |
120 | d->running = TRUE;␊ |
121 | d->finished = FALSE;␊ |
122 | ␊ |
123 | pthread_attr_t attr;␊ |
124 | pthread_attr_init(&attr);␊ |
125 | pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);␊ |
126 | pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);␊ |
127 | if (d->stackSize>0)␊ |
128 | {␊ |
129 | #if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0>0)␊ |
130 | pthread_attr_setstacksize(&attr,d->stackSize);␊ |
131 | #endif␊ |
132 | }␊ |
133 | int code = pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);␊ |
134 | pthread_attr_destroy(&attr);␊ |
135 | ␊ |
136 | if (code)␊ |
137 | {␊ |
138 | qWarning("QThread::start: Thread creation error: %d", code);␊ |
139 | ␊ |
140 | d->running = FALSE;␊ |
141 | d->finished = FALSE;␊ |
142 | d->thread_id = 0;␊ |
143 | }␊ |
144 | }␊ |
145 | ␊ |
146 | void QThread::terminate()␊ |
147 | {␊ |
148 | QMutexLocker locker(&d->mutex);␊ |
149 | ␊ |
150 | if (!d->thread_id) return;␊ |
151 | ␊ |
152 | int code = pthread_cancel(d->thread_id);␊ |
153 | if (code)␊ |
154 | {␊ |
155 | qWarning("QThread::start: Thread termination error: %d", code);␊ |
156 | }␊ |
157 | else␊ |
158 | {␊ |
159 | d->terminated = TRUE;␊ |
160 | }␊ |
161 | }␊ |
162 | ␊ |
163 | void QThread::wait()␊ |
164 | {␊ |
165 | QMutexLocker locker(&d->mutex);␊ |
166 | if (d->finished || !d->running) return;␊ |
167 | ␊ |
168 | while (d->running)␊ |
169 | {␊ |
170 | d->thread_done.wait(locker.mutex());␊ |
171 | }␊ |
172 | }␊ |
173 | ␊ |
174 | #if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)␊ |
175 | // LSB doesn't define _SC_NPROCESSORS_ONLN.␊ |
176 | # define _SC_NPROCESSORS_ONLN 84␊ |
177 | #endif␊ |
178 | ␊ |
179 | int QThread::idealThreadCount()␊ |
180 | {␊ |
181 | int cores = -1;␊ |
182 | #if defined(_OS_MAC_)␊ |
183 | // Mac OS X␊ |
184 | cores = MPProcessorsScheduled();␊ |
185 | #elif defined(_OS_HPUX_)␊ |
186 | // HP-UX␊ |
187 | struct pst_dynamic psd;␊ |
188 | if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) == -1) ␊ |
189 | {␊ |
190 | perror("pstat_getdynamic");␊ |
191 | cores = -1;␊ |
192 | } ␊ |
193 | else ␊ |
194 | {␊ |
195 | cores = (int)psd.psd_proc_cnt;␊ |
196 | }␊ |
197 | #elif defined(_OS_BSDI_)␊ |
198 | // FreeBSD, OpenBSD, NetBSD, BSD/OS␊ |
199 | size_t len = sizeof(cores);␊ |
200 | int mib[2];␊ |
201 | mib[0] = CTL_HW;␊ |
202 | mib[1] = HW_NCPU;␊ |
203 | ␊ |
204 | if (sysctl(mib, 2, &cores, &len, NULL, 0) != 0) ␊ |
205 | {␊ |
206 | perror("sysctl");␊ |
207 | cores = -1;␊ |
208 | }␊ |
209 | #elif defined(_OS_IRIX_)␊ |
210 | // IRIX␊ |
211 | cores = (int)sysconf(_SC_NPROC_ONLN);␊ |
212 | #else␊ |
213 | // the rest: Linux, Solaris, AIX, Tru64␊ |
214 | cores = (int)sysconf(_SC_NPROCESSORS_ONLN);␊ |
215 | #endif␊ |
216 | return cores; ␊ |
217 | }␊ |
218 | ␊ |
219 |