1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrSingleOwner_DEFINED 9 #define GrSingleOwner_DEFINED 10 11 #include "include/core/SkTypes.h" 12 13 #if defined(SK_DEBUG) || defined(SKIA_OHOS_SINGLE_OWNER) 14 #include "include/private/SkMutex.h" 15 #include "include/private/SkThreadID.h" 16 17 #ifdef SKIA_OHOS_SINGLE_OWNER 18 #include <thread> 19 #include <string> 20 #include <sstream> 21 #include "include/core/SkLog.h" 22 #include <csignal> 23 #endif 24 25 26 #define GR_ASSERT_SINGLE_OWNER(obj) \ 27 GrSingleOwner::AutoEnforce debug_SingleOwner(obj, __FILE__, __LINE__); 28 29 static const int SIGNO_FOR_OCEAN = 42; 30 // This is a debug tool to verify an object is only being used from one thread at a time. 31 class GrSingleOwner { 32 public: GrSingleOwner()33 GrSingleOwner() : fOwner(kIllegalThreadID), fReentranceCount(0) {} 34 35 struct AutoEnforce { AutoEnforceAutoEnforce36 AutoEnforce(GrSingleOwner* so, const char* file, int line) 37 : fFile(file), fLine(line), fSO(so) { 38 fSO->enter(file, line); 39 } ~AutoEnforceAutoEnforce40 ~AutoEnforce() { fSO->exit(fFile, fLine); } 41 42 const char* fFile; 43 int fLine; 44 GrSingleOwner* fSO; 45 }; 46 47 private: enter(const char * file,int line)48 void enter(const char* file, int line) { 49 #ifdef SKIA_OHOS_SINGLE_OWNER 50 if (!GetEnableSkiaSingleOwner()) { 51 return; 52 } 53 #endif 54 SkAutoMutexExclusive lock(fMutex); 55 SkThreadID self = SkGetThreadID(); 56 #ifdef SKIA_OHOS_SINGLE_OWNER 57 bool assertCheck = (fOwner == self || fOwner == kIllegalThreadID); 58 if (!assertCheck) { 59 SK_LOGE("\n\n\n\n ========== BackTrace Start =========="); 60 PrintBackTrace(fOwnerTid); 61 SK_LOGE("========== BackTrace End ========== occur file:%{public}s line:%{public}d\n\n\n\n", 62 file, line); 63 raise(SIGNO_FOR_OCEAN); // report to Ocean 64 } 65 fReentranceCount++; 66 fOwner = self; 67 fOwnerTid = gettid(); 68 #else 69 SkASSERTF(fOwner == self || fOwner == kIllegalThreadID, "%s:%d Single owner failure.", 70 file, line); 71 fReentranceCount++; 72 fOwner = self; 73 #endif 74 } 75 exit(const char * file,int line)76 void exit(const char* file, int line) { 77 #ifdef SKIA_OHOS_SINGLE_OWNER 78 if (!GetEnableSkiaSingleOwner()) { 79 return; 80 } 81 #endif 82 SkAutoMutexExclusive lock(fMutex); 83 #ifdef SKIA_OHOS_SINGLE_OWNER 84 SkThreadID self = SkGetThreadID(); 85 bool assertCheck = (fOwner == self || fOwner == kIllegalThreadID); 86 if (!assertCheck) { 87 SK_LOGE("\n\n\n\n ========== BackTrace Start =========="); 88 PrintBackTrace(fOwnerTid); 89 SK_LOGE("========== BackTrace End ========== occur file:%{public}s line:%{public}d\n\n\n\n", 90 file, line); 91 raise(SIGNO_FOR_OCEAN); // report to Ocean 92 } 93 fReentranceCount--; 94 if (fReentranceCount <= 0) { 95 fOwner = kIllegalThreadID; 96 fOwnerTid = 0; 97 } 98 #else 99 SkASSERTF(fOwner == SkGetThreadID(), "%s:%d Single owner failure.", file, line); 100 fReentranceCount--; 101 if (fReentranceCount == 0) { 102 fOwner = kIllegalThreadID; 103 } 104 #endif 105 } 106 107 #ifdef SKIA_OHOS_SINGLE_OWNER 108 pid_t fOwnerTid SK_GUARDED_BY(fMutex); 109 #endif 110 SkMutex fMutex; 111 SkThreadID fOwner SK_GUARDED_BY(fMutex); 112 int fReentranceCount SK_GUARDED_BY(fMutex); 113 }; 114 #else 115 #define GR_ASSERT_SINGLE_OWNER(obj) 116 class GrSingleOwner {}; // Provide a no-op implementation so we can pass pointers to constructors 117 #endif 118 119 #endif 120