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 <stdio.h> 17cb69b360Sopenharmony_ci#include <stdint.h> 18cb69b360Sopenharmony_ci#include <unistd.h> 19cb69b360Sopenharmony_ci#include <pthread.h> 20cb69b360Sopenharmony_ci#include "hilog_wrapper.h" 21cb69b360Sopenharmony_ci#include "power/suspend_ops.h" 22cb69b360Sopenharmony_ci 23cb69b360Sopenharmony_ci#define SUSPEND_CHECK_INTERVAL_US 500000 24cb69b360Sopenharmony_ci 25cb69b360Sopenharmony_cistatic pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 26cb69b360Sopenharmony_cistatic pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER; 27cb69b360Sopenharmony_cistatic pthread_t g_suspendThread; 28cb69b360Sopenharmony_cistatic AutoSuspendLoop g_suspendLoop = NULL; 29cb69b360Sopenharmony_cistatic uint32_t g_suspendBlockCounter = 0; 30cb69b360Sopenharmony_ci 31cb69b360Sopenharmony_ciint usleep(useconds_t usec); 32cb69b360Sopenharmony_cistatic BOOL SuspendConditionSatisfied() 33cb69b360Sopenharmony_ci{ 34cb69b360Sopenharmony_ci return (g_suspendBlockCounter == 0) ? TRUE : FALSE; 35cb69b360Sopenharmony_ci} 36cb69b360Sopenharmony_ci 37cb69b360Sopenharmony_cistatic void WaitingSuspendCondition() 38cb69b360Sopenharmony_ci{ 39cb69b360Sopenharmony_ci pthread_mutex_lock(&g_mutex); 40cb69b360Sopenharmony_ci while (SuspendConditionSatisfied() == FALSE) { 41cb69b360Sopenharmony_ci pthread_cond_wait(&g_cond, &g_mutex); 42cb69b360Sopenharmony_ci } 43cb69b360Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 44cb69b360Sopenharmony_ci} 45cb69b360Sopenharmony_ci 46cb69b360Sopenharmony_cistatic void *SuspendThreadLoop(void *arg) 47cb69b360Sopenharmony_ci{ 48cb69b360Sopenharmony_ci if (!g_suspendLoop) { 49cb69b360Sopenharmony_ci return NULL; 50cb69b360Sopenharmony_ci } 51cb69b360Sopenharmony_ci 52cb69b360Sopenharmony_ci POWER_HILOGI("Suspend thread enter loop"); 53cb69b360Sopenharmony_ci while (1) { 54cb69b360Sopenharmony_ci usleep(SUSPEND_CHECK_INTERVAL_US); 55cb69b360Sopenharmony_ci if (g_suspendLoop(WaitingSuspendCondition) == FALSE) { 56cb69b360Sopenharmony_ci break; 57cb69b360Sopenharmony_ci } 58cb69b360Sopenharmony_ci } 59cb69b360Sopenharmony_ci return NULL; 60cb69b360Sopenharmony_ci} 61cb69b360Sopenharmony_ci 62cb69b360Sopenharmony_cistatic void Enable() 63cb69b360Sopenharmony_ci{ 64cb69b360Sopenharmony_ci static BOOL started = FALSE; 65cb69b360Sopenharmony_ci if (started == TRUE) { 66cb69b360Sopenharmony_ci return; 67cb69b360Sopenharmony_ci } 68cb69b360Sopenharmony_ci 69cb69b360Sopenharmony_ci int32_t ret = pthread_create(&g_suspendThread, NULL, SuspendThreadLoop, NULL); 70cb69b360Sopenharmony_ci if (ret != 0) { 71cb69b360Sopenharmony_ci POWER_HILOGE("Failed to create suspend thread"); 72cb69b360Sopenharmony_ci return; 73cb69b360Sopenharmony_ci } 74cb69b360Sopenharmony_ci pthread_detach(g_suspendThread); 75cb69b360Sopenharmony_ci started = TRUE; 76cb69b360Sopenharmony_ci} 77cb69b360Sopenharmony_ci 78cb69b360Sopenharmony_cistatic void IncSuspendBlockCounter() 79cb69b360Sopenharmony_ci{ 80cb69b360Sopenharmony_ci pthread_mutex_lock(&g_mutex); 81cb69b360Sopenharmony_ci g_suspendBlockCounter++; 82cb69b360Sopenharmony_ci POWER_HILOGD("Suspend block counter: %{public}d", g_suspendBlockCounter); 83cb69b360Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 84cb69b360Sopenharmony_ci} 85cb69b360Sopenharmony_ci 86cb69b360Sopenharmony_cistatic void DecSuspendBlockCounter() 87cb69b360Sopenharmony_ci{ 88cb69b360Sopenharmony_ci pthread_mutex_lock(&g_mutex); 89cb69b360Sopenharmony_ci g_suspendBlockCounter--; 90cb69b360Sopenharmony_ci POWER_HILOGD("Suspend block counter: %{public}d", g_suspendBlockCounter); 91cb69b360Sopenharmony_ci if (SuspendConditionSatisfied() == TRUE) { 92cb69b360Sopenharmony_ci pthread_cond_signal(&g_cond); 93cb69b360Sopenharmony_ci } 94cb69b360Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 95cb69b360Sopenharmony_ci} 96cb69b360Sopenharmony_ci 97cb69b360Sopenharmony_cistatic struct AutoSuspendOps g_ops = { 98cb69b360Sopenharmony_ci .Enable = Enable, 99cb69b360Sopenharmony_ci .IncSuspendBlockCounter = IncSuspendBlockCounter, 100cb69b360Sopenharmony_ci .DecSuspendBlockCounter = DecSuspendBlockCounter, 101cb69b360Sopenharmony_ci}; 102cb69b360Sopenharmony_ci 103cb69b360Sopenharmony_cistruct AutoSuspendOps* AutoSuspendOpsInit() 104cb69b360Sopenharmony_ci{ 105cb69b360Sopenharmony_ci g_suspendLoop = AutoSuspendLoopInit(); 106cb69b360Sopenharmony_ci if (!g_suspendLoop) { 107cb69b360Sopenharmony_ci POWER_HILOGE("Failed to init auto suspend loop"); 108cb69b360Sopenharmony_ci return NULL; 109cb69b360Sopenharmony_ci } 110cb69b360Sopenharmony_ci return &g_ops; 111cb69b360Sopenharmony_ci} 112