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