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