1 | /* |
2 | Copyright (c) 2005-2019 Intel Corporation |
3 | |
4 | Licensed under the Apache License, Version 2.0 (the "License"); |
5 | you may not use this file except in compliance with the License. |
6 | You may obtain a copy of the License at |
7 | |
8 | http://www.apache.org/licenses/LICENSE-2.0 |
9 | |
10 | Unless required by applicable law or agreed to in writing, software |
11 | distributed under the License is distributed on an "AS IS" BASIS, |
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | See the License for the specific language governing permissions and |
14 | limitations under the License. |
15 | */ |
16 | |
17 | class LimitTLSKeysTo { |
18 | #if _WIN32 || _WIN64 |
19 | #if __TBB_WIN8UI_SUPPORT && !defined(TLS_OUT_OF_INDEXES) |
20 | // for SDKs for Windows*8 Store Apps that did not redirect TLS to FLS |
21 | #define TlsAlloc() FlsAlloc(NULL) |
22 | #define TlsFree FlsFree |
23 | #define TLS_OUT_OF_INDEXES FLS_OUT_OF_INDEXES |
24 | #endif |
25 | typedef DWORD handle; |
26 | #else // _WIN32 || _WIN64 |
27 | typedef pthread_key_t handle; |
28 | #endif |
29 | // for platforms that not limit number of TLS keys, set artificial limit |
30 | static const int LIMIT = 16*1024; |
31 | handle handles[LIMIT]; |
32 | int lastUsedIdx; |
33 | public: |
34 | LimitTLSKeysTo(int keep_keys) { |
35 | for (lastUsedIdx=0; lastUsedIdx<LIMIT; lastUsedIdx++) { |
36 | #if _WIN32 || _WIN64 |
37 | handle h = TlsAlloc(); |
38 | if (h==TLS_OUT_OF_INDEXES) |
39 | #else |
40 | int setspecific_dummy=10; |
41 | if (pthread_key_create(&handles[lastUsedIdx], NULL)!=0) |
42 | #endif |
43 | { |
44 | break; |
45 | } |
46 | #if _WIN32 || _WIN64 |
47 | handles[lastUsedIdx] = h; |
48 | #else |
49 | pthread_setspecific(handles[lastUsedIdx], &setspecific_dummy); |
50 | #endif |
51 | } |
52 | lastUsedIdx--; |
53 | ASSERT(lastUsedIdx >= keep_keys-1, "Less TLS keys are available than requested" ); |
54 | for (; keep_keys>0; keep_keys--, lastUsedIdx--) { |
55 | #if _WIN32 || _WIN64 |
56 | TlsFree(handles[lastUsedIdx]); |
57 | #else |
58 | int ret = pthread_key_delete(handles[lastUsedIdx]); |
59 | ASSERT(!ret, "Can't delete a key" ); |
60 | #endif |
61 | } |
62 | REMARK("%d thread local objects allocated in advance\n" , lastUsedIdx+1); |
63 | } |
64 | ~LimitTLSKeysTo() { |
65 | for (int i=0; i<=lastUsedIdx; i++) { |
66 | #if _WIN32 || _WIN64 |
67 | TlsFree(handles[i]); |
68 | #else |
69 | int ret = pthread_key_delete(handles[i]); |
70 | ASSERT(!ret, "Can't delete a key" ); |
71 | #endif |
72 | } |
73 | lastUsedIdx = 0; |
74 | } |
75 | }; |
76 | |