已合并
异步栈并发加锁 #2693
Cooper创建于 11 天前
异步栈并发加锁 #2693
已合并
共 4 个文件变更+120-34
| @@ -19,6 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | + | ||
| 23 | + | ||
| 22 | 24 | ||
| 23 | 25 | ||
| 24 | 26 | ||
| @@ -39,7 +41,7 @@ DfxAsyncContextPool* DfxAsyncContextPool::Instance() | |||
| 39 | 41 | ||
| 40 | bool DfxAsyncContextPool::Init() | 42 | bool DfxAsyncContextPool::Init() |
| 41 | { | 43 | { |
| 42 | - std::lock_guard<std::mutex> lock(mutex_); | 44 | + std::lock_guard<std::shared_mutex> lock(sharedMutex_); |
| 43 | if (initialized_.load()) { | 45 | if (initialized_.load()) { |
| 44 | return true; | 46 | return true; |
| 45 | } | 47 | } |
| @@ -50,8 +52,9 @@ bool DfxAsyncContextPool::Init() | |||
| 50 | return false; | 52 | return false; |
| 51 | } | 53 | } |
| 52 | size_t poolMemSize = static_cast<size_t>(poolSize_) * sizeof(DfxAsyncContext); | 54 | size_t poolMemSize = static_cast<size_t>(poolSize_) * sizeof(DfxAsyncContext); |
| 53 | - pool_ = static_cast<DfxAsyncContext*>(mmap(nullptr, poolMemSize, PROT_READ | PROT_WRITE, | 55 | + pool_ = reinterpret_cast<DfxAsyncContext*>(static_cast<uintptr_t>( |
| 54 | - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); | 56 | + syscall(SYS_mmap, nullptr, poolMemSize, PROT_READ | PROT_WRITE, |
C | |||
| 57 | + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0))); | ||
| 55 | if (pool_ == MAP_FAILED) { | 58 | if (pool_ == MAP_FAILED) { |
| 56 | pool_ = nullptr; | 59 | pool_ = nullptr; |
| 57 | DFXLOGE("init async context pool mmap failed poolSize %{public}u, errno %{public}d", | 60 | DFXLOGE("init async context pool mmap failed poolSize %{public}u, errno %{public}d", |
| @@ -61,22 +64,20 @@ bool DfxAsyncContextPool::Init() | |||
| 61 | freeListHead_ = &pool_[0]; | 64 | freeListHead_ = &pool_[0]; |
| 62 | for (uint32_t i = 0; i < poolSize_ - 1; i++) { | 65 | for (uint32_t i = 0; i < poolSize_ - 1; i++) { |
| 63 | pool_[i].next = &pool_[i + 1]; | 66 | pool_[i].next = &pool_[i + 1]; |
| 64 | - pool_[i].valid = false; | 67 | + pool_[i].valid.store(false, std::memory_order_relaxed); |
| 65 | } | 68 | } |
| 66 | pool_[poolSize_ - 1].next = nullptr; | 69 | pool_[poolSize_ - 1].next = nullptr; |
| 67 | - pool_[poolSize_ - 1].valid = false; | 70 | + pool_[poolSize_ - 1].valid.store(false, std::memory_order_relaxed); |
| 68 | freeListTail_ = &pool_[poolSize_ - 1]; | 71 | freeListTail_ = &pool_[poolSize_ - 1]; |
| 69 | 72 | ||
| 70 | freeThreadList_ = &threadCtxPool_[0]; | 73 | freeThreadList_ = &threadCtxPool_[0]; |
| 71 | - for (uint32_t i = 0; i < THREAD_POOL_SIZE - 1; i++) { | 74 | + for (uint32_t i = 0; i < THREAD_POOL_SIZE; i++) { |
| 72 | - memset_s(&(threadCtxPool_[i].contexts), sizeof(threadCtxPool_[i].contexts), | 75 | + (void)memset_s(&(threadCtxPool_[i].contexts), sizeof(threadCtxPool_[i].contexts), |
| 73 | 0, sizeof(threadCtxPool_[i].contexts)); | 76 | 0, sizeof(threadCtxPool_[i].contexts)); |
| 74 | - threadCtxPool_[i].valid = false; | 77 | + threadCtxPool_[i].valid.store(false, std::memory_order_relaxed); |
| 75 | threadCtxPool_[i].curAsyncContextsCnt = 0; | 78 | threadCtxPool_[i].curAsyncContextsCnt = 0; |
| 76 | - threadCtxPool_[i].next = &threadCtxPool_[i + 1]; | 79 | + threadCtxPool_[i].next = (i == THREAD_POOL_SIZE - 1) ? nullptr : &threadCtxPool_[i + 1]; |
| 77 | } | 80 | } |
| 78 | - threadCtxPool_[THREAD_POOL_SIZE - 1].next = nullptr; | ||
| 79 | - threadCtxPool_[THREAD_POOL_SIZE - 1].valid = false; | ||
| 80 | 81 | ||
| 81 | initialized_.store(true); | 82 | initialized_.store(true); |
| 82 | DFXLOGI("async context pool init success"); | 83 | DFXLOGI("async context pool init success"); |
| @@ -85,14 +86,14 @@ bool DfxAsyncContextPool::Init() | |||
| 85 | 86 | ||
| 86 | void DfxAsyncContextPool::DeInit() | 87 | void DfxAsyncContextPool::DeInit() |
| 87 | { | 88 | { |
| 88 | - std::lock_guard<std::mutex> lock(mutex_); | 89 | + std::lock_guard<std::shared_mutex> lock(sharedMutex_); |
| 89 | if (!initialized_.load()) { | 90 | if (!initialized_.load()) { |
| 90 | return; | 91 | return; |
| 91 | } | 92 | } |
| 92 | initialized_.store(false); | 93 | initialized_.store(false); |
| 93 | if (pool_ != nullptr) { | 94 | if (pool_ != nullptr) { |
| 94 | size_t poolMemSize = static_cast<size_t>(poolSize_) * sizeof(DfxAsyncContext); | 95 | size_t poolMemSize = static_cast<size_t>(poolSize_) * sizeof(DfxAsyncContext); |
| 95 | - munmap(pool_, poolMemSize); | 96 | + (void)syscall(SYS_munmap, pool_, poolMemSize); |
| 96 | pool_ = nullptr; | 97 | pool_ = nullptr; |
| 97 | } | 98 | } |
| 98 | poolSize_ = 0; | 99 | poolSize_ = 0; |
| @@ -103,7 +104,7 @@ void DfxAsyncContextPool::DeInit() | |||
| 103 | 104 | ||
| 104 | DfxAsyncContext* DfxAsyncContextPool::AcquireAsyncContext() | 105 | DfxAsyncContext* DfxAsyncContextPool::AcquireAsyncContext() |
| 105 | { | 106 | { |
| 106 | - std::lock_guard<std::mutex> lock(mutex_); | 107 | + std::lock_guard<std::shared_mutex> lock(sharedMutex_); |
| 107 | if (!initialized_.load()) { | 108 | if (!initialized_.load()) { |
| 108 | return nullptr; | 109 | return nullptr; |
| 109 | } | 110 | } |
| @@ -113,7 +114,7 @@ DfxAsyncContext* DfxAsyncContextPool::AcquireAsyncContext() | |||
| 113 | } | 114 | } |
| 114 | DfxAsyncContext* ctx = freeListHead_; | 115 | DfxAsyncContext* ctx = freeListHead_; |
| 115 | freeListHead_ = freeListHead_->next; | 116 | freeListHead_ = freeListHead_->next; |
| 116 | - ctx->valid = true; | 117 | + ctx->valid.store(true, std::memory_order_release); |
| 117 | return ctx; | 118 | return ctx; |
| 118 | } | 119 | } |
| 119 | 120 | ||
| @@ -123,24 +124,26 @@ void DfxAsyncContextPool::ReleaseAsyncContext(DfxAsyncContext* ctx) | |||
| 123 | DFXLOGW("ReleaseAsyncContext ctx is nullptr"); | 124 | DFXLOGW("ReleaseAsyncContext ctx is nullptr"); |
| 124 | return; | 125 | return; |
| 125 | } | 126 | } |
| 126 | - std::lock_guard<std::mutex> lock(mutex_); | 127 | + std::lock_guard<std::shared_mutex> lock(sharedMutex_); |
| 127 | if (!initialized_.load()) { | 128 | if (!initialized_.load()) { |
| 128 | return; | 129 | return; |
| 129 | } | 130 | } |
| 130 | - if (!ctx->valid) { | 131 | + if (!ctx->valid.load(std::memory_order_acquire)) { |
| 131 | DFXLOGW("ReleaseAsyncContext ctx is invalid"); | 132 | DFXLOGW("ReleaseAsyncContext ctx is invalid"); |
| 132 | return; | 133 | return; |
| 133 | } | 134 | } |
| 135 | + DFXLOGD("ReleaseAsyncContext tid:%{public}d, type %{public}llu", | ||
| 136 | + gettid(), static_cast<unsigned long long>(ctx->ctxs[0].type)); | ||
| 134 | (void)memset_s(&ctx->ctxs[0], sizeof(ctx->ctxs), 0, sizeof(ctx->ctxs)); | 137 | (void)memset_s(&ctx->ctxs[0], sizeof(ctx->ctxs), 0, sizeof(ctx->ctxs)); |
| 135 | freeListTail_->next = ctx; | 138 | freeListTail_->next = ctx; |
| 136 | freeListTail_ = ctx; | 139 | freeListTail_ = ctx; |
| 137 | - ctx->valid = false; | 140 | + ctx->valid.store(false, std::memory_order_release); |
| 138 | ctx->next = nullptr; | 141 | ctx->next = nullptr; |
| 139 | } | 142 | } |
| 140 | 143 | ||
| 141 | DfxThreadAsyncContext* DfxAsyncContextPool::AcquireThreadContext() | 144 | DfxThreadAsyncContext* DfxAsyncContextPool::AcquireThreadContext() |
| 142 | { | 145 | { |
| 143 | - std::lock_guard<std::mutex> lock(mutex_); | 146 | + std::lock_guard<std::shared_mutex> lock(sharedMutex_); |
| 144 | if (!initialized_.load()) { | 147 | if (!initialized_.load()) { |
| 145 | return nullptr; | 148 | return nullptr; |
| 146 | } | 149 | } |
| @@ -150,8 +153,9 @@ DfxThreadAsyncContext* DfxAsyncContextPool::AcquireThreadContext() | |||
| 150 | } | 153 | } |
| 151 | DfxThreadAsyncContext* ctx = freeThreadList_; | 154 | DfxThreadAsyncContext* ctx = freeThreadList_; |
| 152 | freeThreadList_ = freeThreadList_->next; | 155 | freeThreadList_ = freeThreadList_->next; |
| 153 | - ctx->valid = true; | 156 | + ctx->valid.store(true, std::memory_order_release); |
| 154 | ctx->curAsyncContextsCnt = 0; | 157 | ctx->curAsyncContextsCnt = 0; |
| 158 | + (void)memset_s(&(ctx->contexts), sizeof(ctx->contexts), 0, sizeof(ctx->contexts)); | ||
| 155 | return ctx; | 159 | return ctx; |
| 156 | } | 160 | } |
| 157 | 161 | ||
| @@ -161,11 +165,15 @@ void DfxAsyncContextPool::ReleaseThreadContext(DfxThreadAsyncContext* ctx) | |||
| 161 | DFXLOGW("ReleaseThreadContext ctx is nullptr"); | 165 | DFXLOGW("ReleaseThreadContext ctx is nullptr"); |
| 162 | return; | 166 | return; |
| 163 | } | 167 | } |
| 164 | - std::lock_guard<std::mutex> lock(mutex_); | 168 | + std::lock_guard<std::shared_mutex> lock(sharedMutex_); |
| 165 | if (!initialized_.load()) { | 169 | if (!initialized_.load()) { |
| 166 | return; | 170 | return; |
| 167 | } | 171 | } |
| 168 | - ctx->valid = false; | 172 | + if (!ctx->valid.load(std::memory_order_acquire)) { |
| 173 | + DFXLOGW("ReleaseThreadContext ctx is invalid"); | ||
| 174 | + return; | ||
| 175 | + } | ||
| 176 | + ctx->valid.store(false, std::memory_order_release); | ||
| 169 | ctx->next = freeThreadList_; | 177 | ctx->next = freeThreadList_; |
| 170 | ctx->curAsyncContextsCnt = 0; | 178 | ctx->curAsyncContextsCnt = 0; |
| 171 | freeThreadList_ = ctx; | 179 | freeThreadList_ = ctx; |
| @@ -195,6 +203,7 @@ void ThreadAsyncContextDestructor(void *arg) | |||
| 195 | 203 | ||
| 196 | bool DfxAsyncContextManager::Init() | 204 | bool DfxAsyncContextManager::Init() |
| 197 | { | 205 | { |
| 206 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 198 | if (initialized_.load()) { | 207 | if (initialized_.load()) { |
| 199 | return true; | 208 | return true; |
| 200 | } | 209 | } |
| @@ -203,6 +212,7 @@ bool DfxAsyncContextManager::Init() | |||
| 203 | return false; | 212 | return false; |
| 204 | } | 213 | } |
| 205 | if (pthread_key_create(&threadAsyncCtxKey_, ThreadAsyncContextDestructor) != 0) { | 214 | if (pthread_key_create(&threadAsyncCtxKey_, ThreadAsyncContextDestructor) != 0) { |
| 215 | + DfxAsyncContextPool::Instance()->DeInit(); | ||
| 206 | DFXLOGE("pthread_key_create failed"); | 216 | DFXLOGE("pthread_key_create failed"); |
| 207 | return false; | 217 | return false; |
| 208 | } | 218 | } |
| @@ -213,12 +223,13 @@ bool DfxAsyncContextManager::Init() | |||
| 213 | 223 | ||
| 214 | void DfxAsyncContextManager::DeInit() | 224 | void DfxAsyncContextManager::DeInit() |
| 215 | { | 225 | { |
| 226 | + std::lock_guard<std::mutex> lock(mutex_); | ||
| 216 | if (!initialized_.load()) { | 227 | if (!initialized_.load()) { |
| 217 | return; | 228 | return; |
| 218 | } | 229 | } |
| 230 | + initialized_.store(false); | ||
| 219 | DfxAsyncContextPool::Instance()->DeInit(); | 231 | DfxAsyncContextPool::Instance()->DeInit(); |
| 220 | pthread_key_delete(threadAsyncCtxKey_); | 232 | pthread_key_delete(threadAsyncCtxKey_); |
| 221 | - initialized_.store(false); | ||
| 222 | DFXLOGI("AsyncContextManager deinit success"); | 233 | DFXLOGI("AsyncContextManager deinit success"); |
| 223 | } | 234 | } |
| 224 | 235 | ||
| @@ -233,7 +244,7 @@ DfxAsyncContext* DfxAsyncContextManager::GetCurrentContext() | |||
| 233 | return nullptr; | 244 | return nullptr; |
| 234 | } | 245 | } |
| 235 | if (threadCtx->curAsyncContextsCnt <= 0 || threadCtx->curAsyncContextsCnt > MAX_THREAD_ASYNC_CTX_DEPTH || | 246 | if (threadCtx->curAsyncContextsCnt <= 0 || threadCtx->curAsyncContextsCnt > MAX_THREAD_ASYNC_CTX_DEPTH || |
| 236 | - !threadCtx->valid) { | 247 | + !threadCtx->valid.load(std::memory_order_acquire)) { |
| 237 | DFXLOGD("GetCurrentContext thread context count is invalid"); | 248 | DFXLOGD("GetCurrentContext thread context count is invalid"); |
| 238 | return nullptr; | 249 | return nullptr; |
| 239 | } | 250 | } |
| @@ -248,7 +259,7 @@ void DfxAsyncContextManager::ClearThreadContext(DfxThreadAsyncContext* threadCtx | |||
| 248 | return; | 259 | return; |
| 249 | } | 260 | } |
| 250 | if (threadCtx->curAsyncContextsCnt < 0 || threadCtx->curAsyncContextsCnt > MAX_THREAD_ASYNC_CTX_DEPTH || | 261 | if (threadCtx->curAsyncContextsCnt < 0 || threadCtx->curAsyncContextsCnt > MAX_THREAD_ASYNC_CTX_DEPTH || |
| 251 | - !threadCtx->valid) { | 262 | + !threadCtx->valid.load(std::memory_order_acquire)) { |
| 252 | DFXLOGW("ClearThreadContext invalid thread context"); | 263 | DFXLOGW("ClearThreadContext invalid thread context"); |
| 253 | return; | 264 | return; |
| 254 | } | 265 | } |
| @@ -260,7 +271,20 @@ bool DfxAsyncContextPool::IsValidAsyncContextAddress(DfxAsyncContext* ctx) | |||
| 260 | if (ctx == nullptr) { | 271 | if (ctx == nullptr) { |
| 261 | return false; | 272 | return false; |
| 262 | } | 273 | } |
| 263 | - std::lock_guard<std::mutex> lock(mutex_); | 274 | + std::shared_lock<std::shared_mutex> lock(sharedMutex_); |
| 275 | + return IsValidAsyncContextAddressLocked(ctx); | ||
| 276 | +} | ||
| 277 | + | ||
| 278 | +std::shared_lock<std::shared_mutex> DfxAsyncContextPool::AcquireReadLock() | ||
| 279 | +{ | ||
| 280 | + return std::shared_lock<std::shared_mutex>(sharedMutex_); | ||
| 281 | +} | ||
| 282 | + | ||
| 283 | +bool DfxAsyncContextPool::IsValidAsyncContextAddressLocked(DfxAsyncContext* ctx) | ||
| 284 | +{ | ||
| 285 | + if (ctx == nullptr) { | ||
| 286 | + return false; | ||
| 287 | + } | ||
| 264 | if (!initialized_.load() || pool_ == nullptr || poolSize_ == 0) { | 288 | if (!initialized_.load() || pool_ == nullptr || poolSize_ == 0) { |
| 265 | return false; | 289 | return false; |
| 266 | } | 290 | } |
| @@ -282,8 +306,6 @@ bool DfxAsyncContextManager::RecycleAsyncContext(DfxAsyncContext* ctx) | |||
| 282 | DFXLOGW("RecycleAsyncContext ctx invalid"); | 306 | DFXLOGW("RecycleAsyncContext ctx invalid"); |
| 283 | return false; | 307 | return false; |
| 284 | } | 308 | } |
| 285 | - DFXLOGD("RecycleAsyncContext tid:%{public}d, type %{public}llu", | ||
| 286 | - gettid(), static_cast<unsigned long long>(ctx->ctxs[0].type)); | ||
| 287 | DfxAsyncContextPool::Instance()->ReleaseAsyncContext(ctx); | 309 | DfxAsyncContextPool::Instance()->ReleaseAsyncContext(ctx); |
| 288 | return true; | 310 | return true; |
| 289 | } | 311 | } |
| @@ -301,6 +323,7 @@ void DfxAsyncContextManager::PushAsyncContext(DfxThreadAsyncContext* threadCtx, | |||
| 301 | threadCtx->curAsyncContextsCnt); | 323 | threadCtx->curAsyncContextsCnt); |
| 302 | return; | 324 | return; |
| 303 | } | 325 | } |
| 326 | + auto readLock = DfxAsyncContextPool::Instance()->AcquireReadLock(); | ||
| 304 | threadCtx->contexts[threadCtx->curAsyncContextsCnt++] = ctx; | 327 | threadCtx->contexts[threadCtx->curAsyncContextsCnt++] = ctx; |
| 305 | } | 328 | } |
| 306 | 329 | ||
| @@ -338,6 +361,10 @@ void DfxAsyncContextManager::PopCurrentThreadContext(uint64_t stackId) | |||
| 338 | pthread_setspecific(threadAsyncCtxKey_, threadCtx); | 361 | pthread_setspecific(threadAsyncCtxKey_, threadCtx); |
| 339 | } | 362 | } |
| 340 | 363 | ||
| 364 | + if (threadCtx->curAsyncContextsCnt <= 0) { | ||
| 365 | + DFXLOGW("PopCurrentThreadContext empty stack tid:%{public}d", gettid()); | ||
| 366 | + return; | ||
| 367 | + } | ||
| 341 | if (ctx == threadCtx->contexts[threadCtx->curAsyncContextsCnt - 1]) { | 368 | if (ctx == threadCtx->contexts[threadCtx->curAsyncContextsCnt - 1]) { |
| 342 | PopAsyncContext(threadCtx); | 369 | PopAsyncContext(threadCtx); |
| 343 | } | 370 | } |
| @@ -364,8 +391,13 @@ void DfxAsyncContextManager::SetCurrentThreadContext(uint64_t stackId) | |||
| 364 | if (ctx == nullptr) { | 391 | if (ctx == nullptr) { |
| 365 | PopAsyncContext(threadCtx); | 392 | PopAsyncContext(threadCtx); |
| 366 | return; | 393 | return; |
| 367 | - } else if (IsValidAsyncContext(ctx) && (ctx->ctxs[0].type & CLEAR_THREAD_CTX_TYPE)) { | 394 | + } |
| 368 | - ClearThreadContext(threadCtx); | 395 | + { |
| 396 | + auto readLock = DfxAsyncContextPool::Instance()->AcquireReadLock(); | ||
| 397 | + if (DfxAsyncContextPool::Instance()->IsValidAsyncContextAddressLocked(ctx) && | ||
| 398 | + (ctx->ctxs[0].type & CLEAR_THREAD_CTX_TYPE)) { | ||
| 399 | + ClearThreadContext(threadCtx); | ||
| 400 | + } | ||
| 369 | } | 401 | } |
| 370 | PushAsyncContext(threadCtx, ctx); | 402 | PushAsyncContext(threadCtx, ctx); |
| 371 | } | 403 | } |
| @@ -377,6 +409,7 @@ DfxAsyncContext* DfxAsyncContextManager::HandleCollectAsyncStack(uint64_t stackI | |||
| 377 | DFXLOGW("HandleCollectAsyncStack acquire async context failed"); | 409 | DFXLOGW("HandleCollectAsyncStack acquire async context failed"); |
| 378 | return nullptr; | 410 | return nullptr; |
| 379 | } | 411 | } |
| 412 | + auto readLock = DfxAsyncContextPool::Instance()->AcquireReadLock(); | ||
| 380 | ctx->ctxs[0].id = stackId; | 413 | ctx->ctxs[0].id = stackId; |
| 381 | ctx->ctxs[0].type = asyncType; | 414 | ctx->ctxs[0].type = asyncType; |
| 382 | auto curCtx = GetCurrentContext(); | 415 | auto curCtx = GetCurrentContext(); |
| @@ -239,6 +239,7 @@ extern "C" int GetCurrentChainedAsyncContext(DfxAsyncCtx buffer[], size_t sz) | |||
| 239 | DFXLOGW("GetCurrentChainedAsyncContext sz is 0"); | 239 | DFXLOGW("GetCurrentChainedAsyncContext sz is 0"); |
| 240 | return 0; | 240 | return 0; |
| 241 | } | 241 | } |
| 242 | + auto readLock = DfxAsyncContextPool::Instance()->AcquireReadLock(); | ||
C 只保留这个,其他asyncstack可以去掉 ![]() ![]() | |||
| 242 | DfxAsyncContext* ctx = DfxAsyncContextManager::Instance()->GetCurrentContext(); | 243 | DfxAsyncContext* ctx = DfxAsyncContextManager::Instance()->GetCurrentContext(); |
| 243 | if (ctx == nullptr) { | 244 | if (ctx == nullptr) { |
| 244 | DFXLOGD("GetCurrentContext failed, ctx is nullptr"); | 245 | DFXLOGD("GetCurrentContext failed, ctx is nullptr"); |
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | + | ||
| 21 | 22 | ||
| 22 | 23 | ||
| 23 | 24 | ||
| @@ -36,14 +37,14 @@ constexpr uint32_t PRINT_CHAIN_INTERVAL = 10; | |||
| 36 | 37 | ||
| 37 | typedef struct DfxAsyncContext { | 38 | typedef struct DfxAsyncContext { |
| 38 | DfxAsyncContext* next; | 39 | DfxAsyncContext* next; |
| 39 | - bool valid; | 40 | + std::atomic<bool> valid; |
| 40 | DfxAsyncCtx ctxs[MAX_ASYNC_CHAIN_LAYERS_LIMIT]; | 41 | DfxAsyncCtx ctxs[MAX_ASYNC_CHAIN_LAYERS_LIMIT]; |
| 41 | } DfxAsyncContext; | 42 | } DfxAsyncContext; |
| 42 | 43 | ||
| 43 | typedef struct DfxThreadAsyncContext { | 44 | typedef struct DfxThreadAsyncContext { |
| 44 | DfxAsyncContext* contexts[MAX_THREAD_ASYNC_CTX_DEPTH]; | 45 | DfxAsyncContext* contexts[MAX_THREAD_ASYNC_CTX_DEPTH]; |
| 45 | DfxThreadAsyncContext* next; | 46 | DfxThreadAsyncContext* next; |
| 46 | - bool valid; | 47 | + std::atomic<bool> valid; |
| 47 | int32_t curAsyncContextsCnt; | 48 | int32_t curAsyncContextsCnt; |
| 48 | } DfxThreadAsyncContext; | 49 | } DfxThreadAsyncContext; |
| 49 | 50 | ||
| @@ -60,6 +61,8 @@ public: | |||
| 60 | DfxThreadAsyncContext* AcquireThreadContext(); | 61 | DfxThreadAsyncContext* AcquireThreadContext(); |
| 61 | void ReleaseThreadContext(DfxThreadAsyncContext* ctx); | 62 | void ReleaseThreadContext(DfxThreadAsyncContext* ctx); |
| 62 | bool IsValidAsyncContextAddress(DfxAsyncContext* ctx); | 63 | bool IsValidAsyncContextAddress(DfxAsyncContext* ctx); |
| 64 | + std::shared_lock<std::shared_mutex> AcquireReadLock(); | ||
| 65 | + bool IsValidAsyncContextAddressLocked(DfxAsyncContext* ctx); | ||
| 63 | private: | 66 | private: |
| 64 | DfxAsyncContextPool() = default; | 67 | DfxAsyncContextPool() = default; |
| 65 | ~DfxAsyncContextPool() = default; | 68 | ~DfxAsyncContextPool() = default; |
| @@ -71,7 +74,7 @@ private: | |||
| 71 | DfxAsyncContext* freeListHead_{nullptr}; | 74 | DfxAsyncContext* freeListHead_{nullptr}; |
| 72 | DfxAsyncContext* freeListTail_{nullptr}; | 75 | DfxAsyncContext* freeListTail_{nullptr}; |
| 73 | DfxThreadAsyncContext* freeThreadList_{nullptr}; | 76 | DfxThreadAsyncContext* freeThreadList_{nullptr}; |
| 74 | - std::mutex mutex_; | 77 | + std::shared_mutex sharedMutex_; |
| 75 | std::atomic<bool> initialized_{false}; | 78 | std::atomic<bool> initialized_{false}; |
| 76 | }; | 79 | }; |
| 77 | 80 | ||
| @@ -95,7 +98,8 @@ private: | |||
| 95 | void PushAsyncContext(DfxThreadAsyncContext* threadCtx, DfxAsyncContext* ctx); | 98 | void PushAsyncContext(DfxThreadAsyncContext* threadCtx, DfxAsyncContext* ctx); |
| 96 | void PopAsyncContext(DfxThreadAsyncContext* threadCtx); | 99 | void PopAsyncContext(DfxThreadAsyncContext* threadCtx); |
| 97 | pthread_key_t threadAsyncCtxKey_; | 100 | pthread_key_t threadAsyncCtxKey_; |
| 98 | - std::atomic<bool> initialized_; | 101 | + std::atomic<bool> initialized_{false}; |
| 102 | + std::mutex mutex_; | ||
| 99 | }; | 103 | }; |
| 100 | 104 | ||
| 101 | } // namespace HiviewDFX | 105 | } // namespace HiviewDFX |
| @@ -677,5 +677,53 @@ HWTEST_F(AsyncStackTest, AsyncStackTest015, TestSize.Level2) | |||
| 677 | 677 | ||
| 678 | GTEST_LOG_(INFO) << "AsyncStackTest015: end."; | 678 | GTEST_LOG_(INFO) << "AsyncStackTest015: end."; |
| 679 | } | 679 | } |
| 680 | + | ||
| 681 | +/** | ||
| 682 | + * @tc.name: AsyncStackTest016 | ||
| 683 | + * @tc.desc: test concurrent GetCurrentChainedAsyncContext with SetAsyncStackMode DeInit/munmap | ||
| 684 | + * @tc.type: FUNC | ||
| 685 | + */ | ||
| 686 | +HWTEST_F(AsyncStackTest, AsyncStackTest016, TestSize.Level2) | ||
| 687 | +{ | ||
| 688 | + | ||
| 689 | + GTEST_LOG_(INFO) << "AsyncStackTest016: start."; | ||
| 690 | + ASSERT_TRUE(DfxInitAsyncStack()); | ||
| 691 | + constexpr int ROUND_COUNT = 30; | ||
| 692 | + for (int round = 0; round < ROUND_COUNT; round++) { | ||
| 693 | + SetAsyncStackMode(MODE_CHAINED_STACKTRACE); | ||
| 694 | + DfxSetAsyncStackType(DEFAULT_ASYNC_TYPE); | ||
| 695 | + std::atomic<bool> stopFlag{false}; | ||
| 696 | + std::atomic<bool> started{false}; | ||
| 697 | + auto reader = [&stopFlag, &started]() { | ||
| 698 | + uint64_t sid = DfxCollectAsyncStack(ASYNC_TYPE_LIBUV_QUEUE); | ||
| 699 | + DfxSetSubmitterStackId(sid); | ||
| 700 | + started.store(true, std::memory_order_release); | ||
| 701 | + DfxAsyncCtx buffer[5]; | ||
| 702 | + while (!stopFlag.load(std::memory_order_relaxed)) { | ||
| 703 | + (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); | ||
| 704 | + GetCurrentChainedAsyncContext(buffer, 5); | ||
| 705 | + } | ||
| 706 | + DfxSetSubmitterStackId(0); | ||
| 707 | + }; | ||
| 708 | + auto toggler = [&stopFlag, &started]() { | ||
| 709 | + while (!started.load(std::memory_order_acquire)) { | ||
| 710 | + std::this_thread::yield(); | ||
| 711 | + } | ||
| 712 | + std::this_thread::yield(); | ||
| 713 | + SetAsyncStackMode(MODE_LAST_STACKTRACE); | ||
| 714 | + SetAsyncStackMode(MODE_CHAINED_STACKTRACE); | ||
| 715 | + stopFlag.store(true, std::memory_order_relaxed); | ||
| 716 | + }; | ||
| 717 | + std::thread t0(reader); | ||
| 718 | + std::thread t1(toggler); | ||
| 719 | + t0.join(); | ||
| 720 | + t1.join(); | ||
| 721 | + SetAsyncStackMode(MODE_LAST_STACKTRACE); | ||
| 722 | + } | ||
| 723 | + GTEST_LOG_(INFO) << "AsyncStackTest016: survived " << ROUND_COUNT << " rounds."; | ||
| 724 | + SUCCEED(); | ||
| 725 | + GTEST_LOG_(INFO) << "AsyncStackTest016: end."; | ||
| 726 | + | ||
| 727 | +} | ||
| 680 | } // namespace HiviewDFX | 728 | } // namespace HiviewDFX |
| 681 | } // namespace OHOS | 729 | } // namespace OHOS |


1.确认了能解决问题吗2.profiler是否hook syscall