1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "running_lock.h" 17 18#include <stdint.h> 19#include <stdlib.h> 20 21#include <common.h> 22#include <ohos_errno.h> 23#include <pthread.h> 24#include <securec.h> 25 26#include "hilog_wrapper.h" 27#include "running_lock_entry.h" 28#include "running_lock_framework.h" 29 30static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 31static BOOL g_inited = FALSE; 32static Vector g_runningLocks; 33 34static BOOL AddRunningLock(RunningLock *lock) 35{ 36 pthread_mutex_lock(&g_mutex); 37 if (g_inited == FALSE) { 38 g_runningLocks = VECTOR_Make(NULL, NULL); 39 g_inited = TRUE; 40 } 41 int16_t pos = VECTOR_Add(&g_runningLocks, (void *)lock); 42 if (pos == INVALID_INDEX) { 43 POWER_HILOGE("Failed to add lock to vector"); 44 pthread_mutex_unlock(&g_mutex); 45 return FALSE; 46 } 47 POWER_HILOGD("Add running lock, name: %s, type: %d", lock->name, lock->type); 48 pthread_mutex_unlock(&g_mutex); 49 return TRUE; 50} 51 52static BOOL RemoveRunningLock(const RunningLock *lock) 53{ 54 pthread_mutex_lock(&g_mutex); 55 int16_t pos = VECTOR_Find(&g_runningLocks, (void *)lock); 56 if (pos < 0) { 57 POWER_HILOGE("Non-existent running lock"); 58 pthread_mutex_unlock(&g_mutex); 59 return FALSE; 60 } 61 VECTOR_Swap(&g_runningLocks, pos, NULL); 62 POWER_HILOGD("Remove running lock, name: %s, type: %d", lock->name, lock->type); 63 pthread_mutex_unlock(&g_mutex); 64 return TRUE; 65} 66 67static BOOL IsRunningLockExisted(const RunningLock *lock) 68{ 69 if (lock == NULL) { 70 POWER_HILOGE("Invalid running lock"); 71 return FALSE; 72 } 73 pthread_mutex_lock(&g_mutex); 74 BOOL ret = (VECTOR_Find(&g_runningLocks, (void *)lock) >= 0) ? TRUE : FALSE; 75 pthread_mutex_unlock(&g_mutex); 76 return ret; 77} 78 79static RunningLockEntry *CreateRunningLockEntry(const char *name, RunningLockType type, RunningLockFlag flag) 80{ 81 RunningLockEntry *entry = (RunningLockEntry *)malloc(sizeof(RunningLockEntry)); 82 if (entry == NULL) { 83 POWER_HILOGE("Failed allocate running lock entry"); 84 return NULL; 85 } 86 (void)memset_s(entry, sizeof(RunningLockEntry), 0, sizeof(RunningLockEntry)); 87 InitIdentity(entry); 88 entry->lock.type = type; 89 entry->lock.flag = flag; 90 if (strcpy_s(entry->lock.name, sizeof(entry->lock.name), name) != EOK) { 91 free(entry); 92 return NULL; 93 } 94 return entry; 95} 96 97static inline void DestroyRunningLockEntry(RunningLockEntry *entry) 98{ 99 if (entry != NULL) { 100 POWER_HILOGD("Free entry: %p", entry); 101 free(entry); 102 } 103} 104 105const RunningLock *CreateRunningLock(const char *name, RunningLockType type, RunningLockFlag flag) 106{ 107 if ((name == NULL) || (type >= RUNNINGLOCK_BUTT)) { 108 POWER_HILOGE("Invalid running lock name"); 109 return NULL; 110 } 111 112 RunningLockEntry *entry = CreateRunningLockEntry(name, type, flag); 113 if (entry == NULL) { 114 POWER_HILOGE("Failed create running lock entry"); 115 return NULL; 116 } 117 AddRunningLock(&entry->lock); 118 POWER_HILOGD("Create %s, pid: %u, token: %llu", name, entry->identity.pid, (long long)entry->identity.token); 119 return &entry->lock; 120} 121 122BOOL AcquireRunningLock(const RunningLock *lock) 123{ 124 if (IsRunningLockExisted(lock) == FALSE) { 125 POWER_HILOGE("Non-existent running lock"); 126 return FALSE; 127 } 128 RunningLockEntry *entry = GetRunningLockEntry(lock); 129 if (entry->status.isHolding == TRUE) { 130 POWER_HILOGD("Already acquired, name: %s", lock->name); 131 return TRUE; 132 } 133 entry->status.isHolding = AcquireRunningLockEntry(entry, -1); 134 return entry->status.isHolding; 135} 136 137BOOL ReleaseRunningLock(const RunningLock *lock) 138{ 139 if (IsRunningLockExisted(lock) == FALSE) { 140 POWER_HILOGE("Non-existent running lock"); 141 return FALSE; 142 } 143 RunningLockEntry *entry = GetRunningLockEntry(lock); 144 if (entry->status.isHolding == FALSE) { 145 POWER_HILOGD("Already released, name: %s", lock->name); 146 return TRUE; 147 } 148 entry->status.isHolding = !ReleaseRunningLockEntry(entry); 149 return !entry->status.isHolding; 150} 151 152void DestroyRunningLock(const RunningLock *lock) 153{ 154 if (lock == NULL) { 155 POWER_HILOGE("Invalid running lock"); 156 return; 157 } 158 ReleaseRunningLock(lock); 159 if (RemoveRunningLock(lock) == TRUE) { 160 DestroyRunningLockEntry(GetRunningLockEntry(lock)); 161 } 162} 163 164BOOL IsRunningLockHolding(const RunningLock *lock) 165{ 166 if (IsRunningLockExisted(lock) == FALSE) { 167 POWER_HILOGE("Non-existent running lock"); 168 return FALSE; 169 } 170 RunningLockEntry *entry = GetRunningLockEntry(lock); 171 return entry->status.isHolding; 172} 173