1 /*
2     Copyright 2005-2014 Intel Corporation.  All Rights Reserved.
3 
4     This file is part of Threading Building Blocks. Threading Building Blocks is free software;
5     you can redistribute it and/or modify it under the terms of the GNU General Public License
6     version 2  as  published  by  the  Free Software Foundation.  Threading Building Blocks is
7     distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
8     implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9     See  the GNU General Public License for more details.   You should have received a copy of
10     the  GNU General Public License along with Threading Building Blocks; if not, write to the
11     Free Software Foundation, Inc.,  51 Franklin St,  Fifth Floor,  Boston,  MA 02110-1301 USA
12 
13     As a special exception,  you may use this file  as part of a free software library without
14     restriction.  Specifically,  if other files instantiate templates  or use macros or inline
15     functions from this file, or you compile this file and link it with other files to produce
16     an executable,  this file does not by itself cause the resulting executable to be covered
17     by the GNU General Public License. This exception does not however invalidate any other
18     reasons why the executable file might be covered by the GNU General Public License.
19 */
20 
21 #ifndef __TBB_profiling_H
22 #define __TBB_profiling_H
23 
24 namespace tbb {
25     namespace internal {
26 
27         //
28         // This is not under __TBB_ITT_STRUCTURE_API because these values are used directly in flow_graph.h.
29         //
30 
31         // include list of index names
32         #define TBB_STRING_RESOURCE(index_name,str) index_name,
33         enum string_index {
34            #include "internal/_tbb_strings.h"
35            NUM_STRINGS
36         };
37         #undef TBB_STRING_RESOURCE
38 
39         enum itt_relation
40         {
41         __itt_relation_is_unknown = 0,
42         __itt_relation_is_dependent_on,         /**< "A is dependent on B" means that A cannot start until B completes */
43         __itt_relation_is_sibling_of,           /**< "A is sibling of B" means that A and B were created as a group */
44         __itt_relation_is_parent_of,            /**< "A is parent of B" means that A created B */
45         __itt_relation_is_continuation_of,      /**< "A is continuation of B" means that A assumes the dependencies of B */
46         __itt_relation_is_child_of,             /**< "A is child of B" means that A was created by B (inverse of is_parent_of) */
47         __itt_relation_is_continued_by,         /**< "A is continued by B" means that B assumes the dependencies of A (inverse of is_continuation_of) */
48         __itt_relation_is_predecessor_to        /**< "A is predecessor to B" means that B cannot start until A completes (inverse of is_dependent_on) */
49         };
50 
51     }
52 }
53 
54 // Check if the tools support is enabled
55 #if (_WIN32||_WIN64||__linux__) && !__MINGW32__ && TBB_USE_THREADING_TOOLS
56 
57 #if _WIN32||_WIN64
58 #include <stdlib.h>  /* mbstowcs_s */
59 #endif
60 #include "tbb_stddef.h"
61 
62 namespace tbb {
63     namespace internal {
64 
65 #if _WIN32||_WIN64
66         void __TBB_EXPORTED_FUNC itt_set_sync_name_v3( void *obj, const wchar_t* name );
multibyte_to_widechar(wchar_t * wcs,const char * mbs,size_t bufsize)67         inline size_t multibyte_to_widechar( wchar_t* wcs, const char* mbs, size_t bufsize) {
68 #if _MSC_VER>=1400
69             size_t len;
70             mbstowcs_s( &len, wcs, bufsize, mbs, _TRUNCATE );
71             return len;   // mbstowcs_s counts null terminator
72 #else
73             size_t len = mbstowcs( wcs, mbs, bufsize );
74             if(wcs && len!=size_t(-1) )
75                 wcs[len<bufsize-1? len: bufsize-1] = wchar_t('\0');
76             return len+1; // mbstowcs does not count null terminator
77 #endif
78         }
79 #else
80         void __TBB_EXPORTED_FUNC itt_set_sync_name_v3( void *obj, const char* name );
81 #endif
82     } // namespace internal
83 } // namespace tbb
84 
85 //! Macro __TBB_DEFINE_PROFILING_SET_NAME(T) defines "set_name" methods for sync objects of type T
86 /** Should be used in the "tbb" namespace only.
87     Don't place semicolon after it to avoid compiler warnings. **/
88 #if _WIN32||_WIN64
89     #define __TBB_DEFINE_PROFILING_SET_NAME(sync_object_type)                       \
90         namespace profiling {                                                       \
91             inline void set_name( sync_object_type& obj, const wchar_t* name ) {    \
92                 tbb::internal::itt_set_sync_name_v3( &obj, name );                  \
93             }                                                                       \
94             inline void set_name( sync_object_type& obj, const char* name ) {       \
95                 size_t len = tbb::internal::multibyte_to_widechar(NULL, name, 0);   \
96                 wchar_t *wname = new wchar_t[len];                                  \
97                 tbb::internal::multibyte_to_widechar(wname, name, len);             \
98                 set_name( obj, wname );                                             \
99                 delete[] wname;                                                     \
100             }                                                                       \
101         }
102 #else /* !WIN */
103     #define __TBB_DEFINE_PROFILING_SET_NAME(sync_object_type)                       \
104         namespace profiling {                                                       \
105             inline void set_name( sync_object_type& obj, const char* name ) {       \
106                 tbb::internal::itt_set_sync_name_v3( &obj, name );                  \
107             }                                                                       \
108         }
109 #endif /* !WIN */
110 
111 #else /* no tools support */
112 
113 #if _WIN32||_WIN64
114     #define __TBB_DEFINE_PROFILING_SET_NAME(sync_object_type)               \
115         namespace profiling {                                               \
116             inline void set_name( sync_object_type&, const wchar_t* ) {}    \
117             inline void set_name( sync_object_type&, const char* ) {}       \
118         }
119 #else /* !WIN */
120     #define __TBB_DEFINE_PROFILING_SET_NAME(sync_object_type)               \
121         namespace profiling {                                               \
122             inline void set_name( sync_object_type&, const char* ) {}       \
123         }
124 #endif /* !WIN */
125 
126 #endif /* no tools support */
127 
128 #include "atomic.h"
129 // Need these to work regardless of tools support
130 namespace tbb {
131     namespace internal {
132 
133         enum notify_type {prepare=0, cancel, acquired, releasing};
134 
135         const uintptr_t NUM_NOTIFY_TYPES = 4; // set to # elements in enum above
136 
137         void __TBB_EXPORTED_FUNC call_itt_notify_v5(int t, void *ptr);
138         void __TBB_EXPORTED_FUNC itt_store_pointer_with_release_v3(void *dst, void *src);
139         void* __TBB_EXPORTED_FUNC itt_load_pointer_with_acquire_v3(const void *src);
140         void* __TBB_EXPORTED_FUNC itt_load_pointer_v3( const void* src );
141 #if __TBB_ITT_STRUCTURE_API
142         enum itt_domain_enum { ITT_DOMAIN_FLOW=0 };
143 
144         void __TBB_EXPORTED_FUNC itt_make_task_group_v7( itt_domain_enum domain, void *group, unsigned long long group_extra,
145                                                          void *parent, unsigned long long parent_extra, string_index name_index );
146         void __TBB_EXPORTED_FUNC itt_metadata_str_add_v7( itt_domain_enum domain, void *addr, unsigned long long addr_extra,
147                                                           string_index key, const char *value );
148         void __TBB_EXPORTED_FUNC itt_relation_add_v7( itt_domain_enum domain, void *addr0, unsigned long long addr0_extra,
149                                                       itt_relation relation, void *addr1, unsigned long long addr1_extra );
150         void __TBB_EXPORTED_FUNC itt_task_begin_v7( itt_domain_enum domain, void *task, unsigned long long task_extra,
151                                                     void *parent, unsigned long long parent_extra, string_index name_index );
152         void __TBB_EXPORTED_FUNC itt_task_end_v7( itt_domain_enum domain );
153 #endif // __TBB_ITT_STRUCTURE_API
154 
155         // two template arguments are to workaround /Wp64 warning with tbb::atomic specialized for unsigned type
156         template <typename T, typename U>
itt_store_word_with_release(tbb::atomic<T> & dst,U src)157         inline void itt_store_word_with_release(tbb::atomic<T>& dst, U src) {
158 #if TBB_USE_THREADING_TOOLS
159             // This assertion should be replaced with static_assert
160             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized.");
161             itt_store_pointer_with_release_v3(&dst, (void *)uintptr_t(src));
162 #else
163             dst = src;
164 #endif // TBB_USE_THREADING_TOOLS
165         }
166 
167         template <typename T>
itt_load_word_with_acquire(const tbb::atomic<T> & src)168         inline T itt_load_word_with_acquire(const tbb::atomic<T>& src) {
169 #if TBB_USE_THREADING_TOOLS
170             // This assertion should be replaced with static_assert
171             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized.");
172 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
173             // Workaround for overzealous compiler warnings
174             #pragma warning (push)
175             #pragma warning (disable: 4311)
176 #endif
177             T result = (T)itt_load_pointer_with_acquire_v3(&src);
178 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
179             #pragma warning (pop)
180 #endif
181             return result;
182 #else
183             return src;
184 #endif // TBB_USE_THREADING_TOOLS
185         }
186 
187         template <typename T>
itt_store_word_with_release(T & dst,T src)188         inline void itt_store_word_with_release(T& dst, T src) {
189 #if TBB_USE_THREADING_TOOLS
190             // This assertion should be replaced with static_assert
191             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized.");
192             itt_store_pointer_with_release_v3(&dst, (void *)src);
193 #else
194             __TBB_store_with_release(dst, src);
195 #endif // TBB_USE_THREADING_TOOLS
196         }
197 
198         template <typename T>
itt_load_word_with_acquire(const T & src)199         inline T itt_load_word_with_acquire(const T& src) {
200 #if TBB_USE_THREADING_TOOLS
201             // This assertion should be replaced with static_assert
202             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized");
203             return (T)itt_load_pointer_with_acquire_v3(&src);
204 #else
205             return __TBB_load_with_acquire(src);
206 #endif // TBB_USE_THREADING_TOOLS
207         }
208 
209         template <typename T>
itt_hide_store_word(T & dst,T src)210         inline void itt_hide_store_word(T& dst, T src) {
211 #if TBB_USE_THREADING_TOOLS
212             //TODO: This assertion should be replaced with static_assert
213             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized");
214             itt_store_pointer_with_release_v3(&dst, (void *)src);
215 #else
216             dst = src;
217 #endif
218         }
219 
220         //TODO: rename to itt_hide_load_word_relaxed
221         template <typename T>
itt_hide_load_word(const T & src)222         inline T itt_hide_load_word(const T& src) {
223 #if TBB_USE_THREADING_TOOLS
224             //TODO: This assertion should be replaced with static_assert
225             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized.");
226             return (T)itt_load_pointer_v3(&src);
227 #else
228             return src;
229 #endif
230         }
231 
232 #if TBB_USE_THREADING_TOOLS
call_itt_notify(notify_type t,void * ptr)233         inline void call_itt_notify(notify_type t, void *ptr) {
234             call_itt_notify_v5((int)t, ptr);
235         }
236 
237 #else
call_itt_notify(notify_type,void *)238         inline void call_itt_notify(notify_type /*t*/, void * /*ptr*/) {}
239 
240 #endif // TBB_USE_THREADING_TOOLS
241 
242 #if __TBB_ITT_STRUCTURE_API
itt_make_task_group(itt_domain_enum domain,void * group,unsigned long long group_extra,void * parent,unsigned long long parent_extra,string_index name_index)243         inline void itt_make_task_group( itt_domain_enum domain, void *group, unsigned long long group_extra,
244                                          void *parent, unsigned long long parent_extra, string_index name_index ) {
245             itt_make_task_group_v7( domain, group, group_extra, parent, parent_extra, name_index );
246         }
247 
itt_metadata_str_add(itt_domain_enum domain,void * addr,unsigned long long addr_extra,string_index key,const char * value)248         inline void itt_metadata_str_add( itt_domain_enum domain, void *addr, unsigned long long addr_extra,
249                                           string_index key, const char *value ) {
250             itt_metadata_str_add_v7( domain, addr, addr_extra, key, value );
251         }
252 
itt_relation_add(itt_domain_enum domain,void * addr0,unsigned long long addr0_extra,itt_relation relation,void * addr1,unsigned long long addr1_extra)253         inline void itt_relation_add( itt_domain_enum domain, void *addr0, unsigned long long addr0_extra,
254                                       itt_relation relation, void *addr1, unsigned long long addr1_extra ) {
255             itt_relation_add_v7( domain, addr0, addr0_extra, relation, addr1, addr1_extra );
256         }
257 
itt_task_begin(itt_domain_enum domain,void * task,unsigned long long task_extra,void * parent,unsigned long long parent_extra,string_index name_index)258         inline void itt_task_begin( itt_domain_enum domain, void *task, unsigned long long task_extra,
259                                                         void *parent, unsigned long long parent_extra, string_index name_index ) {
260             itt_task_begin_v7( domain, task, task_extra, parent, parent_extra, name_index );
261         }
262 
itt_task_end(itt_domain_enum domain)263         inline void itt_task_end( itt_domain_enum domain ) {
264             itt_task_end_v7( domain );
265         }
266 #endif // __TBB_ITT_STRUCTURE_API
267 
268     } // namespace internal
269 } // namespace tbb
270 
271 #endif /* __TBB_profiling_H */
272