1//
2// Thread_STD_POSIX.cpp
3//
4// Library: Foundation
5// Package: Threading
6// Module: Thread
7//
8// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Thread_STD.h"
16#include "Poco/Thread.h"
17#include "Poco/Exception.h"
18#include <pthread.h>
19#include <signal.h>
20#if defined(__sun) && defined(__SVR4)
21 #if !defined(__EXTENSIONS__)
22 #define __EXTENSIONS__
23 #endif
24#endif
25#if POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_MAC_OS_X || POCO_OS == POCO_OS_QNX
26 #include <time.h>
27 #include <unistd.h>
28#endif
29#if POCO_OS == POCO_OS_MAC_OS_X
30 #include <mach/mach.h>
31 #include <mach/task.h>
32 #include <mach/thread_policy.h>
33#endif
34#if POCO_OS == POCO_OS_LINUX
35 #include <sys/syscall.h>
36#endif
37#include <cstring>
38
39
40namespace Poco {
41
42
43int mapPrio(int prio, int policy)
44{
45 int pmin = ThreadImpl::getMinOSPriorityImpl(policy);
46 int pmax = ThreadImpl::getMaxOSPriorityImpl(policy);
47
48 switch (prio)
49 {
50 case ThreadImpl::PRIO_LOWEST_IMPL:
51 return pmin;
52 case ThreadImpl::PRIO_LOW_IMPL:
53 return pmin + (pmax - pmin) / 4;
54 case ThreadImpl::PRIO_NORMAL_IMPL:
55 return pmin + (pmax - pmin) / 2;
56 case ThreadImpl::PRIO_HIGH_IMPL:
57 return pmin + 3 * (pmax - pmin) / 4;
58 case ThreadImpl::PRIO_HIGHEST_IMPL:
59 return pmax;
60 default:
61 poco_bugcheck_msg("invalid thread priority");
62 }
63 return -1; // just to satisfy compiler - we'll never get here anyway
64}
65
66
67int reverseMapPrio(int prio, int policy)
68{
69 if (policy == SCHED_OTHER)
70 {
71 int pmin = ThreadImpl::getMinOSPriorityImpl(policy);
72 int pmax = ThreadImpl::getMaxOSPriorityImpl(policy);
73 int normal = pmin + (pmax - pmin) / 2;
74 if (prio == pmax)
75 return ThreadImpl::PRIO_HIGHEST_IMPL;
76 if (prio > normal)
77 return ThreadImpl::PRIO_HIGH_IMPL;
78 else if (prio == normal)
79 return ThreadImpl::PRIO_NORMAL_IMPL;
80 else if (prio > pmin)
81 return ThreadImpl::PRIO_LOW_IMPL;
82 else
83 return ThreadImpl::PRIO_LOWEST_IMPL;
84 }
85 else return ThreadImpl::PRIO_HIGHEST_IMPL;
86}
87
88
89void ThreadImpl::setPriorityImpl(int prio)
90{
91 if (prio != _pData->prio)
92 {
93 _pData->prio = prio;
94 _pData->policy = SCHED_OTHER;
95 if (isRunningImpl())
96 {
97 struct sched_param par;
98 struct MyStruct
99 {
100
101 };
102 par.sched_priority = mapPrio(_pData->prio, SCHED_OTHER);
103 if (pthread_setschedparam(_pData->thread->native_handle(), SCHED_OTHER, &par))
104 throw SystemException("cannot set thread priority");
105 }
106 }
107}
108
109
110void ThreadImpl::setOSPriorityImpl(int prio, int policy)
111{
112 if (prio != _pData->osPrio || policy != _pData->policy)
113 {
114 if (_pData->pRunnableTarget)
115 {
116 struct sched_param par;
117 par.sched_priority = prio;
118 if (pthread_setschedparam(_pData->thread->native_handle(), policy, &par))
119 throw SystemException("cannot set thread priority");
120 }
121 _pData->prio = reverseMapPrio(prio, policy);
122 _pData->osPrio = prio;
123 _pData->policy = policy;
124 }
125}
126
127
128int ThreadImpl::getMinOSPriorityImpl(int policy)
129{
130#if defined(POCO_THREAD_PRIORITY_MIN)
131 return POCO_THREAD_PRIORITY_MIN;
132#elif defined(__VMS) || defined(__digital__)
133 return PRI_OTHER_MIN;
134#else
135 return sched_get_priority_min(policy);
136#endif
137}
138
139
140int ThreadImpl::getMaxOSPriorityImpl(int policy)
141{
142#if defined(POCO_THREAD_PRIORITY_MAX)
143 return POCO_THREAD_PRIORITY_MAX;
144#elif defined(__VMS) || defined(__digital__)
145 return PRI_OTHER_MAX;
146#else
147 return sched_get_priority_max(policy);
148#endif
149}
150
151
152void ThreadImpl::setStackSizeImpl(int size)
153{
154 _pData->stackSize = size;
155 // not supported
156}
157
158
159void ThreadImpl::setAffinityImpl(int cpu)
160{
161#if defined (POCO_OS_FAMILY_UNIX) && POCO_OS != POCO_OS_MAC_OS_X && POCO_OS != POCO_OS_FREE_BSD
162#ifdef HAVE_PTHREAD_SETAFFINITY_NP
163 cpu_set_t cpuset;
164 CPU_ZERO(&cpuset);
165 CPU_SET(cpu, &cpuset);
166#ifdef HAVE_THREE_PARAM_SCHED_SETAFFINITY
167 if (pthread_setaffinity_np(_pData->thread->native_handle(), sizeof(cpuset), &cpuset) != 0)
168 throw SystemException("Failed to set affinity");
169#else
170 if (pthread_setaffinity_np(_pData->thread->native_handle(), &cpuset) != 0)
171 throw SystemException("Failed to set affinity");
172#endif
173#endif
174#endif // defined unix & !defined mac os x
175
176#if POCO_OS == POCO_OS_MAC_OS_X
177 kern_return_t ret;
178 thread_affinity_policy policy;
179 policy.affinity_tag = cpu;
180
181 ret = thread_policy_set(pthread_mach_thread_np(_pData->thread->native_handle()),
182 THREAD_AFFINITY_POLICY,
183 (thread_policy_t)&policy,
184 THREAD_AFFINITY_POLICY_COUNT);
185 if (ret != KERN_SUCCESS)
186 {
187 throw SystemException("Failed to set affinity");
188 }
189#endif
190 yieldImpl();
191 _pData->cpu = cpu;
192}
193
194
195int ThreadImpl::getAffinityImpl() const
196{
197 int cpuSet = -1;
198#if defined (POCO_OS_FAMILY_UNIX) && POCO_OS != POCO_OS_MAC_OS_X && POCO_OS != POCO_OS_FREE_BSD
199#ifdef HAVE_PTHREAD_SETAFFINITY_NP
200 cpu_set_t cpuset;
201 CPU_ZERO(&cpuset);
202#ifdef HAVE_THREE_PARAM_SCHED_SETAFFINITY
203 if (pthread_getaffinity_np(_pData->thread->native_handle(), sizeof(cpuset), &cpuset) != 0)
204 throw SystemException("Failed to get affinity", errno);
205#else
206 if (pthread_getaffinity_np(_pData->thread->native_handle(), &cpuset) != 0)
207 throw SystemException("Failed to get affinity", errno);
208#endif
209 int cpuCount = Environment::processorCount();
210 for (int i = 0; i < cpuCount; i++)
211 {
212 if (CPU_ISSET(i, &cpuset))
213 {
214 cpuSet = i;
215 break;
216 }
217 }
218#endif
219#endif // defined unix & !defined mac os x
220
221#if POCO_OS == POCO_OS_MAC_OS_X
222 kern_return_t ret;
223 thread_affinity_policy policy;
224 mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT;
225 boolean_t get_default = false;
226 ret = thread_policy_get(pthread_mach_thread_np(_pData->thread->native_handle()),
227 THREAD_AFFINITY_POLICY,
228 (thread_policy_t)&policy,
229 &count,
230 &get_default);
231 if (ret != KERN_SUCCESS)
232 {
233 throw SystemException("Failed to get affinity", errno);
234 }
235 cpuSet = policy.affinity_tag;
236 int cpuCount = Environment::processorCount();
237 if (cpuSet >= cpuCount)
238 cpuSet = -1;
239
240#endif
241 return cpuSet;
242}
243
244
245} // namespace Poco
246