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
17class 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;
33public:
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