[4.0] Change Dali::Thread, Dali::Mutex and Dali::ConditionalWait to use std::thread...
[platform/core/uifw/dali-core.git] / dali / internal / common / mutex-trace.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
18 // HEADER
19 #include <dali/internal/common/mutex-trace.h>
20
21 #ifdef LOCK_BACKTRACE_ENABLED
22 // EXTERNAL INCLUDES
23 #include <cstdlib>
24 #include <execinfo.h>
25
26 // INTERNAL INCLUDES
27 #include <dali/public-api/common/dali-common.h>
28 #include <dali/integration-api/debug.h>
29
30 #endif // LOCK_BACKTRACE_ENABLED
31
32 // INTERNAL INCLUDES
33 #include <dali/integration-api/debug.h>
34
35 namespace Dali
36 {
37 #ifdef LOCK_BACKTRACE_ENABLED
38 extern std::string Demangle( const char* symbol );
39 #endif // LOCK_BACKTRACE_ENABLED
40
41 namespace Internal
42 {
43
44 namespace MutexTrace
45 {
46
47 namespace
48 {
49 #ifdef LOCK_BACKTRACE_ENABLED
50
51 // Constants
52 const unsigned int MAX_NUM_STACK_FRAMES = 4;
53 const unsigned int MAX_LOCK_SUPPORT = 5;
54
55 struct BackTraceInfo
56 {
57   void * frameArray[ MAX_NUM_STACK_FRAMES ]; ///< Stores the frame array where the lock occurred
58   int size;                                  ///< Number of frames in the frame array (can be less than MAX_NUM_STACK_FRAMES)
59 };
60
61 thread_local BackTraceInfo gBackTraceInfo[ MAX_LOCK_SUPPORT ]; ///< Thread local storage for the backtrace of the locks
62
63 #endif // LOCK_BACKTRACE_ENABLED
64
65 thread_local unsigned int gThreadLockCount = 0; ///< Thread local storage for the backtrace of the locks
66 } // unnamed namespace
67
68 void Lock()
69 {
70   ++gThreadLockCount;
71
72 #ifdef LOCK_BACKTRACE_ENABLED
73
74   if( gThreadLockCount <= MAX_LOCK_SUPPORT )
75   {
76     // Store the frame array for this lock
77     int backTraceIndex = gThreadLockCount - 1;
78     gBackTraceInfo[ backTraceIndex ].size = backtrace( gBackTraceInfo[ backTraceIndex ].frameArray, MAX_NUM_STACK_FRAMES );
79   }
80   else
81   {
82     DALI_LOG_ERROR( "Reached Maximum lock backtrace support. Previous Locks:\n" );
83   }
84
85   // If we've got more than one lock, then show a warning with a backtrace for all locks that we currently hold
86   if( gThreadLockCount > 1 )
87   {
88     for( unsigned int i = 0; ( i < gThreadLockCount ) && ( i < MAX_LOCK_SUPPORT ); ++i )
89     {
90       DALI_LOG_WARNING( "[Lock %d]\n", i+1 );
91       char** symbols = backtrace_symbols( gBackTraceInfo[ i ].frameArray, gBackTraceInfo[ i ].size );
92       for( int j = 1; j < gBackTraceInfo[ i ].size; ++j )
93       {
94         std::string demangled_symbol = Demangle( symbols[ j ] );
95         DALI_LOG_WARNING( "  [%02d] %s\n", j, demangled_symbol.c_str() );
96       }
97       free(symbols);
98     }
99     DALI_LOG_WARNING( "====================================\n" );
100   }
101
102 #else
103
104   // TODO: Uncomment when locks held per thread at any given time are 1
105   //DALI_ASSERT_DEBUG( gThreadLockCount == 1 );
106
107 #endif // LOCK_BACKTRACE_ENABLED
108 }
109
110 void Unlock()
111 {
112   --gThreadLockCount;
113 }
114
115 } // namespace MutexTrace
116
117 } // namespace Internal
118
119 } // namespace Dali