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
30 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
31 static BOOL g_inited = FALSE;
32 static Vector g_runningLocks;
33
AddRunningLock(RunningLock * lock)34 static 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
RemoveRunningLock(const RunningLock * lock)52 static 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
IsRunningLockExisted(const RunningLock * lock)67 static 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
CreateRunningLockEntry(const char * name,RunningLockType type,RunningLockFlag flag)79 static 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
DestroyRunningLockEntry(RunningLockEntry * entry)97 static inline void DestroyRunningLockEntry(RunningLockEntry *entry)
98 {
99 if (entry != NULL) {
100 POWER_HILOGD("Free entry: %p", entry);
101 free(entry);
102 }
103 }
104
CreateRunningLock(const char * name,RunningLockType type,RunningLockFlag flag)105 const 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
AcquireRunningLock(const RunningLock * lock)122 BOOL 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
ReleaseRunningLock(const RunningLock * lock)137 BOOL 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
DestroyRunningLock(const RunningLock * lock)152 void 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
IsRunningLockHolding(const RunningLock * lock)164 BOOL 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