From 539ed34cb9257d5e23da246c5ea54450c13037a4 Mon Sep 17 00:00:00 2001 From: YoungHun Kim Date: Mon, 9 Sep 2024 17:44:08 +0900 Subject: [PATCH] Fix emulator service file issue - Add systemd-tmpfiles-setup.service dependency - Remove CRLF - Update spec file using %{name} Change-Id: Ic12cf9d39958c0dc2048a0149890f76fcd10b6d6 --- packaging/rscmgr-msgq.service | 2 +- packaging/rscmgr-service.spec | 4 +- src/manager/CCache.cpp | 90 +- src/manager/CConsumer.cpp | 474 ++++----- src/manager/CConsumerContainer.cpp | 168 +-- src/manager/CDebugUtils.cpp | 1482 +++++++++++++------------- src/manager/CLockController.cpp | 168 +-- src/manager/CPriority.cpp | 312 +++--- src/manager/CResource.cpp | 996 +++++++++--------- src/manager/CResourceCategory.cpp | 320 +++--- src/manager/CResourceDB.cpp | 1578 ++++++++++++++-------------- src/manager/CVideoController.cpp | 348 +++--- src/manager/CVirtualResource.cpp | 66 +- 13 files changed, 3004 insertions(+), 3004 deletions(-) diff --git a/packaging/rscmgr-msgq.service b/packaging/rscmgr-msgq.service index 22ac434..b2cfdd7 100644 --- a/packaging/rscmgr-msgq.service +++ b/packaging/rscmgr-msgq.service @@ -1,6 +1,6 @@ [Unit] Description=Generate RM Message Queue -DefaultDependencies=no +After=systemd-tmpfiles-setup.service [Service] Type=oneshot diff --git a/packaging/rscmgr-service.spec b/packaging/rscmgr-service.spec index e275779..7fe386e 100644 --- a/packaging/rscmgr-service.spec +++ b/packaging/rscmgr-service.spec @@ -1,7 +1,7 @@ Name: rscmgr-service Summary: Daemon for resource manager Version: 0.1 -Release: 10 +Release: 11 Group: Multimedia/Libraries License: Apache-2.0 Source0: %{name}-%{version}.tar.gz @@ -81,7 +81,7 @@ cp %SOURCE4 %{buildroot}%{_sysconfdir}/dbus-1/system.d rm -rf %{buildroot} %files -%manifest rscmgr-service.manifest +%manifest %{name}.manifest %license LICENSE.APLv2 %{TZ_SYS_BIN}/gen_rm_msgq %{TZ_SYS_BIN}/%{name} diff --git a/src/manager/CCache.cpp b/src/manager/CCache.cpp index adde21f..7d8efbe 100644 --- a/src/manager/CCache.cpp +++ b/src/manager/CCache.cpp @@ -1,45 +1,45 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -CCache *CCache::m_instance = NULL; - -CCache *CCache::getInstance(void) -{ - if (!m_instance) { - m_instance = new(std::nothrow) CCache; - } - - return m_instance; -} - -void CCache::SetAppStatus(std::string app_id, int status) -{ - m_visibility.insert(std::pair(app_id, status)); -} - -int CCache::GetAppStatus(std::string app_id) -{ - auto it = m_visibility.find(app_id); - - return (it == m_visibility.end()) ? -1 : it->second; -} - -void CCache::Drop(void) -{ - m_visibility.clear(); -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +CCache *CCache::m_instance = NULL; + +CCache *CCache::getInstance(void) +{ + if (!m_instance) { + m_instance = new(std::nothrow) CCache; + } + + return m_instance; +} + +void CCache::SetAppStatus(std::string app_id, int status) +{ + m_visibility.insert(std::pair(app_id, status)); +} + +int CCache::GetAppStatus(std::string app_id) +{ + auto it = m_visibility.find(app_id); + + return (it == m_visibility.end()) ? -1 : it->second; +} + +void CCache::Drop(void) +{ + m_visibility.clear(); +} diff --git a/src/manager/CConsumer.cpp b/src/manager/CConsumer.cpp index 12bac79..9585e46 100644 --- a/src/manager/CConsumer.cpp +++ b/src/manager/CConsumer.cpp @@ -1,237 +1,237 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -CConsumer::CConsumer(IN const rms_consumer_s *consumer) -{ - m_consumerID = consumer->consumer_id; - m_priority = consumer->priority; - m_pid = consumer->process_id; - m_app_id.assign(consumer->app_id); - - SetCmdName(m_pid); -} - -void CConsumer::SetCmdName(long pid) -{ - char cmd_name[RMS_NAME_BUF_SIZE] = {0, }; - std::string delimiter = "/"; - - rms_get_cmd_name(m_pid, cmd_name, RMS_NAME_BUF_SIZE); - m_cmd_name.assign(cmd_name); - SERVER_WARN("pid %ld cmd name %s", m_pid, cmd_name); - m_cmd_name = m_cmd_name.substr(m_cmd_name.find_last_of(delimiter) + 1, m_cmd_name.length()); - SERVER_WARN("m_cmd_name %s", m_cmd_name.c_str()); -} - -bool CConsumer::AddResource(IN int device_id) -{ - if (IsUsingResource(device_id)) { - SERVER_INFO("already registered device id(%d) in Consumer(%d)", device_id, m_consumerID); - return false; - } - - m_resources.insert(device_id); - return true; -} - -int CConsumer::ReleaseResource(IN int device_id) -{ - if (!IsUsingResource(device_id)) { - SERVER_WARN("CID[%d] / DevID[%d] the consumer does not use this device", m_consumerID, device_id); - return RMS_ERROR; - } - - m_resources.erase(device_id); - - return RMS_OK; -} - -bool CConsumer::IsUsingResource(IN int device_id) -{ - auto it = m_resources.find(device_id); - - return (it != m_resources.end()); -} - -void CConsumer::SetAppID(IN const char *app_id) -{ - m_app_id.assign(app_id); -} - -std::string CConsumer::GetAppId(int pid) -{ - char app_id[RMS_NAME_BUF_SIZE] ={0, }; - std::string result; - - if (aul_app_get_appid_bypid(pid, app_id, sizeof(app_id)) != AUL_R_OK) { - SERVER_ERR("failed to get appid of %d", pid); - return result; - } - - result.assign(app_id); - - return result; -} - -rms_error_type_e CConsumer::ComparePriority(CConsumer *requester) -{ - std::string app_id = requester->GetAppID(); - - m_app_id = (m_app_id.empty()) ? GetAppId((int) m_pid) : m_app_id; - - if (!CheckVisibility(app_id)) { - SERVER_ERR("The application is not visible. cannot take resource"); - return RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS; - } - - rms_priority_s requester_priority = requester->GetPriority(); - - if (!ComparePriority(requester_priority, m_priority)) { - char cmd[RMS_NAME_BUF_SIZE] = {0,}; - rms_get_cmd_name(m_pid, cmd, sizeof(cmd)); - SERVER_ERR("rqs_priority(%d/%d) - user_priority(%s-%d/%d)", requester_priority.main, requester_priority.sub, cmd, m_priority.main, m_priority.sub); - return RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS; - } - - return RMS_ERR_TYPE_NONE; -} - -bool CConsumer::ComparePriority(IN rms_priority_s priority1, IN rms_priority_s priority2) -{ - if (priority1.main > priority2.main) { - return true; - } else if (priority1.main == priority2.main) { - return priority1.sub >= priority2.sub; - } else { - return false; - } -} - -bool CConsumer::CheckVisibility(IN std::string app_id_requester) -{ - if (app_id_requester.empty()) { - SERVER_INFO("requester app id : (null)"); - return true; - } - - bool visibility_consumer = (m_app_id.empty()) ? true : GetAppVisibility(m_app_id, false); - bool visibility_requester = GetAppVisibility(app_id_requester, true); - - if (visibility_requester) { - SERVER_INFO("requester is visible(%s)", app_id_requester.c_str()); - return true; - } - - if (!visibility_consumer) { - SERVER_INFO("current consumer(%d) is invisible(%s)", m_consumerID, m_app_id.c_str()); - return true; - } - - SERVER_ERR("current consumer(%s)- visibility:(%d)", (m_app_id.empty()) ? "null" : m_app_id.c_str(), visibility_consumer); - SERVER_ERR("requester(%s)- visibility:(%d)", app_id_requester.c_str(), visibility_requester); - - return false; -} - -int CConsumer::UpdateAppStatus(std::string app_id) -{ - char buf[RMS_NAME_BUF_SIZE]; - int status; - int n_max = 4; - snprintf(buf, RMS_NAME_BUF_SIZE, "Get visibility of application '%s'", app_id.c_str()); - - for (int i = 0; i < n_max; i++) { - usleep(50*1000); - - trace_begin(buf); - status = aul_app_get_status(app_id.c_str()); - trace_end(); - SERVER_INFO("app(%s) / status(%d) / (%d)", app_id.c_str(), status, i); - - if (IsVisibleStatus(status)) { - SERVER_ERR("status %d", status); - return status; - } - } - return status; -} - -bool CConsumer::NeedStatusUpdate(std::string app_id) -{ - return false; -} - -bool CConsumer::IsVisibleStatus(int status) -{ - return (status == STATUS_FOCUS || status == STATUS_VISIBLE); -} - -bool CConsumer::GetAppVisibility(std::string app_id, bool requester) -{ - CCache *cache = CCache::getInstance(); - int status = cache->GetAppStatus(app_id); - - if (status == -1) { - status = aul_app_get_status(app_id.c_str()); - - if (!IsVisibleStatus(status) && requester && NeedStatusUpdate(app_id)) - status = UpdateAppStatus(app_id); - - cache->SetAppStatus(app_id, status); - } - - return IsVisibleStatus(status); -} - -bool CConsumer::CheckWebAppState(IN std::string app_id_requesting) -{ - if (app_id_requesting.length() == 0) - return false; - - std::string webapp_vconf_key = std::string("rtc/memory/WebApp/") + app_id_requesting; - - char *status = vconf_get_str(webapp_vconf_key.c_str()); - if (!status) { - SERVER_INFO("%s is not webapp", app_id_requesting.c_str()); - return false; - } - - std::string webapp_status(status); - if (webapp_status.compare("resume")) { - SERVER_INFO("%s is not in resume status (%s)", app_id_requesting.c_str(), webapp_status.c_str()); - free(status); - return false; - } - - SERVER_INFO("%s is in resume status (%s)", app_id_requesting.c_str(), webapp_status.c_str()); - free(status); - - return true; -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +CConsumer::CConsumer(IN const rms_consumer_s *consumer) +{ + m_consumerID = consumer->consumer_id; + m_priority = consumer->priority; + m_pid = consumer->process_id; + m_app_id.assign(consumer->app_id); + + SetCmdName(m_pid); +} + +void CConsumer::SetCmdName(long pid) +{ + char cmd_name[RMS_NAME_BUF_SIZE] = {0, }; + std::string delimiter = "/"; + + rms_get_cmd_name(m_pid, cmd_name, RMS_NAME_BUF_SIZE); + m_cmd_name.assign(cmd_name); + SERVER_WARN("pid %ld cmd name %s", m_pid, cmd_name); + m_cmd_name = m_cmd_name.substr(m_cmd_name.find_last_of(delimiter) + 1, m_cmd_name.length()); + SERVER_WARN("m_cmd_name %s", m_cmd_name.c_str()); +} + +bool CConsumer::AddResource(IN int device_id) +{ + if (IsUsingResource(device_id)) { + SERVER_INFO("already registered device id(%d) in Consumer(%d)", device_id, m_consumerID); + return false; + } + + m_resources.insert(device_id); + return true; +} + +int CConsumer::ReleaseResource(IN int device_id) +{ + if (!IsUsingResource(device_id)) { + SERVER_WARN("CID[%d] / DevID[%d] the consumer does not use this device", m_consumerID, device_id); + return RMS_ERROR; + } + + m_resources.erase(device_id); + + return RMS_OK; +} + +bool CConsumer::IsUsingResource(IN int device_id) +{ + auto it = m_resources.find(device_id); + + return (it != m_resources.end()); +} + +void CConsumer::SetAppID(IN const char *app_id) +{ + m_app_id.assign(app_id); +} + +std::string CConsumer::GetAppId(int pid) +{ + char app_id[RMS_NAME_BUF_SIZE] ={0, }; + std::string result; + + if (aul_app_get_appid_bypid(pid, app_id, sizeof(app_id)) != AUL_R_OK) { + SERVER_ERR("failed to get appid of %d", pid); + return result; + } + + result.assign(app_id); + + return result; +} + +rms_error_type_e CConsumer::ComparePriority(CConsumer *requester) +{ + std::string app_id = requester->GetAppID(); + + m_app_id = (m_app_id.empty()) ? GetAppId((int) m_pid) : m_app_id; + + if (!CheckVisibility(app_id)) { + SERVER_ERR("The application is not visible. cannot take resource"); + return RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS; + } + + rms_priority_s requester_priority = requester->GetPriority(); + + if (!ComparePriority(requester_priority, m_priority)) { + char cmd[RMS_NAME_BUF_SIZE] = {0,}; + rms_get_cmd_name(m_pid, cmd, sizeof(cmd)); + SERVER_ERR("rqs_priority(%d/%d) - user_priority(%s-%d/%d)", requester_priority.main, requester_priority.sub, cmd, m_priority.main, m_priority.sub); + return RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS; + } + + return RMS_ERR_TYPE_NONE; +} + +bool CConsumer::ComparePriority(IN rms_priority_s priority1, IN rms_priority_s priority2) +{ + if (priority1.main > priority2.main) { + return true; + } else if (priority1.main == priority2.main) { + return priority1.sub >= priority2.sub; + } else { + return false; + } +} + +bool CConsumer::CheckVisibility(IN std::string app_id_requester) +{ + if (app_id_requester.empty()) { + SERVER_INFO("requester app id : (null)"); + return true; + } + + bool visibility_consumer = (m_app_id.empty()) ? true : GetAppVisibility(m_app_id, false); + bool visibility_requester = GetAppVisibility(app_id_requester, true); + + if (visibility_requester) { + SERVER_INFO("requester is visible(%s)", app_id_requester.c_str()); + return true; + } + + if (!visibility_consumer) { + SERVER_INFO("current consumer(%d) is invisible(%s)", m_consumerID, m_app_id.c_str()); + return true; + } + + SERVER_ERR("current consumer(%s)- visibility:(%d)", (m_app_id.empty()) ? "null" : m_app_id.c_str(), visibility_consumer); + SERVER_ERR("requester(%s)- visibility:(%d)", app_id_requester.c_str(), visibility_requester); + + return false; +} + +int CConsumer::UpdateAppStatus(std::string app_id) +{ + char buf[RMS_NAME_BUF_SIZE]; + int status; + int n_max = 4; + snprintf(buf, RMS_NAME_BUF_SIZE, "Get visibility of application '%s'", app_id.c_str()); + + for (int i = 0; i < n_max; i++) { + usleep(50*1000); + + trace_begin(buf); + status = aul_app_get_status(app_id.c_str()); + trace_end(); + SERVER_INFO("app(%s) / status(%d) / (%d)", app_id.c_str(), status, i); + + if (IsVisibleStatus(status)) { + SERVER_ERR("status %d", status); + return status; + } + } + return status; +} + +bool CConsumer::NeedStatusUpdate(std::string app_id) +{ + return false; +} + +bool CConsumer::IsVisibleStatus(int status) +{ + return (status == STATUS_FOCUS || status == STATUS_VISIBLE); +} + +bool CConsumer::GetAppVisibility(std::string app_id, bool requester) +{ + CCache *cache = CCache::getInstance(); + int status = cache->GetAppStatus(app_id); + + if (status == -1) { + status = aul_app_get_status(app_id.c_str()); + + if (!IsVisibleStatus(status) && requester && NeedStatusUpdate(app_id)) + status = UpdateAppStatus(app_id); + + cache->SetAppStatus(app_id, status); + } + + return IsVisibleStatus(status); +} + +bool CConsumer::CheckWebAppState(IN std::string app_id_requesting) +{ + if (app_id_requesting.length() == 0) + return false; + + std::string webapp_vconf_key = std::string("rtc/memory/WebApp/") + app_id_requesting; + + char *status = vconf_get_str(webapp_vconf_key.c_str()); + if (!status) { + SERVER_INFO("%s is not webapp", app_id_requesting.c_str()); + return false; + } + + std::string webapp_status(status); + if (webapp_status.compare("resume")) { + SERVER_INFO("%s is not in resume status (%s)", app_id_requesting.c_str(), webapp_status.c_str()); + free(status); + return false; + } + + SERVER_INFO("%s is in resume status (%s)", app_id_requesting.c_str(), webapp_status.c_str()); + free(status); + + return true; +} diff --git a/src/manager/CConsumerContainer.cpp b/src/manager/CConsumerContainer.cpp index 3e75cb5..7dfdadc 100644 --- a/src/manager/CConsumerContainer.cpp +++ b/src/manager/CConsumerContainer.cpp @@ -1,84 +1,84 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -CConsumerContainer *CConsumerContainer::m_instance = NULL; - -CConsumerContainer *CConsumerContainer::getInstance(void) -{ - if (!m_instance) { - m_instance = new(std::nothrow) CConsumerContainer; - assert(m_instance); - } - - return m_instance; -} - -CConsumer *CConsumerContainer::findConsumer(int consumer_id) -{ - std::map::iterator it = m_consumers.find(consumer_id); - - return (it == m_consumers.end()) ? NULL : (*it).second; -} - -bool CConsumerContainer::AddConsumer(int consumer_id, CConsumer *consumer) -{ - std::map::iterator it = m_consumers.find(consumer_id); - - if (it != m_consumers.end()) - return false; - - m_consumers.insert(std::pair(consumer_id, consumer)); - return true; -} - -void CConsumerContainer::RemoveConsumer(int consumer_id) -{ - m_consumers.erase(consumer_id); -} - -std::map CConsumerContainer::findConsumers(int pid) -{ - std::map result; - - for (auto const &it : m_consumers) { - CConsumer *consumer = it.second; - - if (consumer->GetPid() != pid) - continue; - - result.insert(std::pair(it.first, it.second)); - } - - return result; -} - -std::map CConsumerContainer::FindConsumers(std::string app_id) -{ - std::map result; - for (auto const &it : m_consumers) { - CConsumer *consumer = it.second; - if (app_id.compare(consumer->GetAppID())) - continue; - - result.insert(std::pair(it.first, it.second)); - } - - return result; -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +CConsumerContainer *CConsumerContainer::m_instance = NULL; + +CConsumerContainer *CConsumerContainer::getInstance(void) +{ + if (!m_instance) { + m_instance = new(std::nothrow) CConsumerContainer; + assert(m_instance); + } + + return m_instance; +} + +CConsumer *CConsumerContainer::findConsumer(int consumer_id) +{ + std::map::iterator it = m_consumers.find(consumer_id); + + return (it == m_consumers.end()) ? NULL : (*it).second; +} + +bool CConsumerContainer::AddConsumer(int consumer_id, CConsumer *consumer) +{ + std::map::iterator it = m_consumers.find(consumer_id); + + if (it != m_consumers.end()) + return false; + + m_consumers.insert(std::pair(consumer_id, consumer)); + return true; +} + +void CConsumerContainer::RemoveConsumer(int consumer_id) +{ + m_consumers.erase(consumer_id); +} + +std::map CConsumerContainer::findConsumers(int pid) +{ + std::map result; + + for (auto const &it : m_consumers) { + CConsumer *consumer = it.second; + + if (consumer->GetPid() != pid) + continue; + + result.insert(std::pair(it.first, it.second)); + } + + return result; +} + +std::map CConsumerContainer::FindConsumers(std::string app_id) +{ + std::map result; + for (auto const &it : m_consumers) { + CConsumer *consumer = it.second; + if (app_id.compare(consumer->GetAppID())) + continue; + + result.insert(std::pair(it.first, it.second)); + } + + return result; +} diff --git a/src/manager/CDebugUtils.cpp b/src/manager/CDebugUtils.cpp index 9d5d0a8..4f7813b 100644 --- a/src/manager/CDebugUtils.cpp +++ b/src/manager/CDebugUtils.cpp @@ -1,741 +1,741 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -static bool product_type_init = false; -static int product_type = 0; //SYSTEM_INFO_PRODUCT_TYPE_TV; - -// The process list which is killed by resource manager -static GHashTable *process_htable = NULL; - -#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0) - -const char *rm_convert_state_enum_to_string(rms_resource_internal_state_e state_enum) -{ - switch (state_enum) { - case RMS_INTERNAL_STATE_FREE: - return "FREE"; - case RMS_INTERNAL_STATE_SHARABLE: - return "SHARABLE"; - case RMS_INTERNAL_STATE_SHARED: - return "SHARED"; - case RMS_INTERNAL_STATE_EXCLUSIVE: - return "EXCLUSIVE"; - case RMS_INTERNAL_STATE_ERROR: - default: - return "NONE"; - } -} - -const char *rm_convert_requested_state_enum_to_string(rms_requests_resource_state_e state_enum) -{ - switch (state_enum) { - case RMS_STATE_PASSIVE: - return "PASSIVE"; - case RMS_STATE_SHARABLE: - return "SHARABLE"; - case RMS_STATE_EXCLUSIVE: - return "EXCLUSIVE"; - case RMS_STATE_EXCLUSIVE_CONDITIONAL: - return "EXCLUSIVE_CONDITIONAL"; - case RMS_STATE_EXCLUSIVE_AUTO: - return "EXCLUSIVE_AUTO"; - case RMS_STATE_EXCLUSIVE_PREFERENCE: - return "EXCLUSIVE_PREFERENCE"; - default: - return "NONE"; - } -} - -const char *rm_convert_category_enum_to_string(rms_rsc_category_e category_enum) -{ - switch (category_enum) { - case RMS_CATEGORY_NONE: - return "NONE"; - case RMS_CATEGORY_AUDIO_DECODER: - return "Audio_Decoder"; - case RMS_CATEGORY_AUDIO_SPDIF_ES_OUTPUT: - return "Not Defined Yet"; - case RMS_CATEGORY_VIDEO_DECODER: - return "Video_Decoder"; - case RMS_CATEGORY_DEMUX: - return "Demux_Main"; - case RMS_CATEGORY_AUDIO_ENCODER: - return "Audio_Encoder"; - case RMS_CATEGORY_VIDEO_ENCODER: - return "Video_Encoder"; - case RMS_CATEGORY_SCALER: - return "Video_Scaler"; - case RMS_CATEGORY_TUNER: - return "Tuner"; - case RMS_CATEGORY_AUDIO_MAIN_OUT: - return "Audio_Main_Out"; - case RMS_CATEGORY_AUDIO_REMOTE_OUT: - return "Audio_Remote_Out"; - case RMS_CATEGORY_AUDIO_SCART_OUT: - return "Audio_Scart_Out"; - case RMS_CATEGORY_MM_PCM_OUT: - return "MM_PCM_playback"; - case RMS_CATEGORY_AUDIO_DECODER_SUB: - return "Audio_Decorder_Sub"; - case RMS_CATEGORY_JPEG_DECODER: - return "JPEG_Decoder"; - case RMS_CATEGORY_MJPEG_DECODER: - return "MJPEG_Decoder"; - case RMS_CATEGORY_SCALER_SUB: - return "Video_Scaler_Sub"; - case RMS_CATEGORY_EXT_VIDEO_SRC: - return "Ext_Video_Src"; - case RMS_CATEGORY_EXT_AUDIO_SRC: - return "Ext_Audio_Src"; - case RMS_CATEGORY_EXT_HDMI_SRC: - return "Ext_HDMI_Src"; - case RMS_CATEGORY_VIDEO_DECODER_SUB: - return "Video_Decoder_Sub"; - case RMS_CATEGORY_CAMERA: - return "Camera"; - case RMS_CATEGORY_DEMUX_REC: - return "Demux_Rec"; - case RMS_CATEGORY_TUNER_SUB: - return "Tuner_Sub"; - case RMS_CATEGORY_VIDEO_DECODER_UHD: - return "Video_Decoder UHD"; - case RMS_CATEGORY_INPUT_SRC_DTV: - return "Input_Src_DTV"; - case RMS_CATEGORY_INPUT_SRC_ATV: - return "Input_Src_ATV"; - case RMS_CATEGORY_INPUT_SRC_HDMI: - return "Input_Src_HDMI"; - case RMS_CATEGORY_INPUT_SRC_COMP: - return "Input_Src_COMP"; - case RMS_CATEGORY_INPUT_SRC_AV: - return "Input_Src_AV"; - case RMS_CATEGORY_INPUT_SRC_SCART: - return "Input_Src_SCART"; - case RMS_CATEGORY_MIC: - return "Mic"; - case RMS_CATEGORY_SW_DECODER: - return "SWDecoder"; - case RMS_CATEGORY_MMP_MEMORY_CLUSTER: - return "MMPlayer MemoryCluster"; - case RMS_CATEGORY_JPEG_DECODER_8K: - return "JPEG_Decoder 8K"; - case RMS_CATEGORY_SCALER_BG: - return "Video_Scaler_BG"; - default: - return ""; - } -} - -const char *rm_convert_device_enum_to_string(rms_device_e device_enum) -{ - switch (device_enum) { - case RMS_DEVICE_NONE: - return "NONE"; - case RMS_DEVICE_AUDIO_MAIN_OUT: - return "audio_main_out"; - case RMS_DEVICE_AUDIO_REMOTE_OUT: - return "audio_remote_out"; - case RMS_DEVICE_AUDIO_SCART_OUT: - return "audio_scart_out"; - case RMS_DEVICE_MM_PCM_OUT: - return "mm_pcm_out"; - case RMS_DEVICE_JPEG_DECODER: - return "jpeg_decoder"; - case RMS_DEVICE_DEMUX0: - return "demux0"; - case RMS_DEVICE_DEMUX1: - return "demux1"; - case RMS_DEVICE_DEMUX2: - return "demux2"; - case RMS_DEVICE_DEMUX3: - return "demux3"; - case RMS_DEVICE_AUDIO_ENCODER: - return "audio_encoder"; - case RMS_DEVICE_VIDEO_ENCODER: - return "video_encoder"; - case RMS_DEVICE_SCALER: - return "scaler"; - case RMS_DEVICE_EXT_VIDEO_SRC: - return "ext_video_src"; - case RMS_DEVICE_EXT_AUDIO_SRC: - return "ext_autio_src"; - case RMS_DEVICE_EXT_HDMI_SRC: - return "ext_hdmi_src"; - case RMS_DEVICE_CAMERA: - return "camera"; - case RMS_DEVICE_TUNER: - return "tuner"; - case RMS_DEVICE_TUNER_SUB: - return "tuner_sub"; - case RMS_DEVICE_SCALER_SUB: - return "scaler_sub"; - case RMS_DEVICE_AUDIO_DECODER: - return "audio_decoder"; - case RMS_DEVICE_AUDIO_DECODER_SUB: - return "audio_decoder_sub"; - case RMS_DEVICE_VIDEO_DECODER_MAIN: - return "video_decoder_main"; - case RMS_DEVICE_VIDEO_DECODER_SUB: - return "video_decoder_sub"; - case RMS_DEVICE_VIDEO_DECODER_UDDEC: - return "video_decoder_uddec"; - case RMS_DEVICE_VIDEO_DECODER_UDHEVC: - return "video_decoder_udhevc"; - case RMS_DEVICE_AUDIO_SPDIF_ES_OUTPUT: - return "audio_spdif_es_output"; - case RMS_DEVICE_MIC: - return "mic"; - case RMS_DEVICE_EXT_COMP_SRC: - return "ext_comp_src"; - case RMS_DEVICE_EXT_AV_SRC: - return "av_src"; - case RMS_DEVICE_MJPEG_DECODER: - return "mjpeg_decoder"; - case RMS_DEVICE_JPEG_DECODER_UHD: - return "jpeg_decoder_uhd"; - case RMS_DEVICE_MJPEG_DECODER_UHD: - return "mjpeg_decoder_uhd"; - case RMS_DEVICE_SW_DECODER: - return "sw_decoder"; - default: - return ""; - } -} - -const char *rm_print_allocation_failure_reason(int ret_value) -{ - switch (ret_value) { - case RMS_OK: - return "OK"; - case RMS_ERROR: - return "Cannot Allocate Resources"; - case RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER: - return "RESOURCE CONFLICT - Other Consumer Is Using"; - case RMS_OK_UHD_RESOURCE_CONFLICT: - return "UHD RESOURCE CONFLICT - Other Consumer Is Using"; - default: - return ""; - } -} -void rms_create_popup(const char *title, const char *text) -{ - bundle *(*bundle_create_fp) (void); - int (*bundle_add_fp)(bundle*, const char*, const char*); - const char *(*bundle_get_val_fp) (bundle*, const char*); - int (*bundle_free_fp) (bundle*); - int (*syspopup_launch_fp) (char*, bundle*); - void *libsyspopup_handle = NULL; - void *libbundle_handle = NULL; - bundle *b = NULL; - char *error; - - libsyspopup_handle = dlopen(LIBDIR"/libsyspopup_caller.so.0.1.0", RTLD_LAZY); - if (!libsyspopup_handle) { - SERVER_ERR("failed to load syspopup library"); - goto end; - } - - libbundle_handle = dlopen(LIBDIR"/libbundle.so.0", RTLD_LAZY); - - if (!libbundle_handle) { - SERVER_ERR("failed to load bundle library"); - goto end; - } - - error = NULL; - - bundle_create_fp = (bundle *(*)(void)) dlsym(libbundle_handle, "bundle_create"); - - if ((error = dlerror()) != NULL) { - SERVER_ERR("failed to find bundle_create"); - goto end; - - } - - bundle_add_fp = (int (*)(bundle*, const char*, const char*)) dlsym(libbundle_handle, "bundle_add"); - - if ((error = dlerror()) != NULL) { - SERVER_ERR("failed to find bundle_add"); - goto end; - } - - bundle_get_val_fp = (const char *(*)(bundle*, const char*)) dlsym(libbundle_handle, "bundle_get_val"); - - if ((error = dlerror()) != NULL) { - SERVER_ERR("failed to find bundle_get_val"); - goto end; - } - - bundle_free_fp = (int (*)(bundle*)) dlsym(libbundle_handle, "bundle_free"); - - if ((error = dlerror()) != NULL) { - SERVER_ERR("failed to find bundle_free"); - goto end; - } - - syspopup_launch_fp = (int (*)(char*, bundle*)) dlsym(libsyspopup_handle, "syspopup_launch"); - - if ((error = dlerror()) != NULL) { - SERVER_ERR("failed to find alert-syspopup"); - goto end; - } - - b = bundle_create_fp(); - if (!b) { - SERVER_ERR("failed to create bundle"); - goto end; - } - - bundle_add_fp(b, "type", "title_message_1button"); - bundle_add_fp(b, "title", title); - bundle_add_fp(b, "text", text); - - bundle_get_val_fp(b, "type"); - bundle_get_val_fp(b, "title"); - bundle_get_val_fp(b, "text"); - - syspopup_launch_fp((char*)"alert-syspopup", b); - bundle_free_fp(b); - -end: - if (libsyspopup_handle) - dlclose(libsyspopup_handle); - - if (libbundle_handle) - dlclose(libbundle_handle); -} - -int rms_get_cmd_name(pid_t pid, char *name_out, int size) -{ - char name[RMS_NAME_BUF_SIZE] = {0,}; - FILE *f; - size_t sz; - - snprintf(name, sizeof(name), "/proc/%d/cmdline", pid); - // Check if the process exists and is accessible - if (access(name, R_OK) != 0) { - SERVER_ERR("failed to access (%s) : %d", name, errno); - return RMS_ERROR; - } - - f = fopen(name, "r"); - if (!f) { - SERVER_ERR("failed to open cmdline(%s) : %d", name, errno); - return RMS_ERROR; - } - - sz = fread(name, sizeof(char), sizeof(name)-1, f); - name[sz] = '\0'; - fclose(f); - - snprintf(name_out, size, "%s", name); - - return RMS_OK; -} - -void rms_print_log_console(char *buf) -{ - int fd, ret; - char output[RMS_CONSOLE_BUF_SIZE] ={0,}; - - struct timespec tnow; - - fd = open("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); - - if (fd < 0) { - SERVER_ERR("console device open fail"); - return; - } - - if (is_symlink_file("/dev/console")) { - SERVER_ERR("%s is symbolic link file", "/dev/console"); - close(fd); - return; - } - - ret = clock_gettime(CLOCK_MONOTONIC, &tnow); - snprintf(output, RMS_CONSOLE_BUF_SIZE, "[RMS][%ld.%6ld] %s", tnow.tv_sec, tnow.tv_nsec/1000, buf); - ret = write(fd, output, strlen(output)); - - if (ret < 0) { - SERVER_ERR("Fail to write on console directly"); - } - - close(fd); -} - -int rm_get_product_type(void) -{ - if (product_type_init) - return product_type; - - int type = 0; /* SYSTEM_INFO_PRODUCT_TYPE_TV */ - - if (system_info_get_custom_int("com.samsung/featureconf/product.product_type", &type) != SYSTEM_INFO_ERROR_NONE) { - SERVER_ERR("Failed to get com.samsung/featureconf/product.product_type"); - } - - product_type_init = true; - product_type = type; - - return product_type; -} - -int rm_is_valid_pid(int pid) -{ - if (kill((pid_t) pid, 0) == 0) { - SERVER_INFO("pid(%d) is alive", pid); - return 1; - } - - SERVER_ERR("pid(%d) / errno(%d)", pid, errno); - - return (errno == ESRCH) ? 0 : 1; -} - -static void process_htable_destory_key(gpointer key) -{ - if (key) - free(key); -} - -static void process_htable_create(void) -{ - if (process_htable) { - SERVER_ERR("hash table already created"); - return; - } - - process_htable = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)process_htable_destory_key, NULL); - - SERVER_INFO("process hash table created"); -} - -static void process_htable_clear(void) -{ - SERVER_INFO("clear process hash table"); - - if (!process_htable) - return; - - g_hash_table_remove_all(process_htable); -} - -static void process_htable_insert(const char *name) -{ - const int PROCESS_DATA_LIMIT = 100; // The maxinum size is (RMS_NAME_BUF_SIZE * PROCESS_DATA_LIMIT) - - if (!process_htable) - process_htable_create(); - - if (g_hash_table_contains(process_htable, name)) - return; - - if (g_hash_table_size(process_htable) >= PROCESS_DATA_LIMIT) - process_htable_clear(); - - char *key_name = (char*) strndup(name, strlen(name)); - - g_hash_table_insert(process_htable, key_name, (gpointer) 1); - - SERVER_ERR("process info (%s) inserted to hash table (%d)", name, g_hash_table_size(process_htable)); -} - - -bool process_htable_contains(const char *name) -{ - bool result = false; - - if (!process_htable) { - SERVER_INFO("(%s) - no table", name); - return false; - } - - if (g_hash_table_size(process_htable) == 0) { - SERVER_INFO("(%s) - empty", name); - return false; - } - - result = g_hash_table_contains(process_htable, name); - - SERVER_INFO("(%s) - result(%d)", name, result); - - // resource manager is supposed to clear data once it's checked by application - process_htable_clear(); - - return result; -} - -int rms_report_emergency(IN int cid, IN int pid, IN int requester) -{ - const char *vconf_request_cold_poweroff = "memory/boot/cold_poweroff_request_pkg"; - int retry = 25; // 20ms * 25 times => 500ms - int ret = 0; - - SERVER_ERR("consumer is not responding....CID[%d]/PID[%d]/Requester(%d) - set cold power off mode", cid, pid, requester); - - if (vconf_set_str(vconf_request_cold_poweroff, "resource-manager") != 0) { - SERVER_ERR("Failed to set request cold power off"); - } else { - SERVER_ERR("memory/boot/cold_poweroff_request_pkg set as resource-manager"); - } - - char process_name[RMS_NAME_BUF_SIZE] = {0,}; - - if (rms_get_cmd_name(pid, process_name, RMS_NAME_BUF_SIZE) == RMS_OK) { - process_htable_insert(process_name); - } - - SERVER_ERR("kill PID(%d)", pid); - - int signal = SIGKILL; - - if (RMS_IS_DEBUG_IMAGE) { - signal = SIGABRT; - retry = 250; // 20ms * 250 times => 5 sec - } - - ret = kill(pid, signal); - - if (ret!=0) { - SERVER_ERR("Failed to kill(%d), errno(%d)", pid, errno); - } - - // wait until process is really terminated for 500ms - while (retry > 0 && rm_is_valid_pid(pid)) { - retry--; - SERVER_ERR("pid(%d) still alive(%d)", pid, retry); - usleep(20*1000); - continue; - } - - if (RMS_IS_DEBUG_IMAGE && retry <= 0) { - //process didn't get terminated for 5 seconds - SERVER_ERR("pid(%d) is not terminated.", pid); - return RMS_ERROR; - } - - return RMS_OK; -} - -void rms_display_timeout_error_popup(rms_alarm_reason_e reason, rms_consumer_tobe_returned_s info) -{ - const char *title = "Resource Allocation Failure"; - const char *style_notification_msg = ""; - const char *style_process_name = ""; - const char *indent = " "; - const char *notification_msg = "Please contact the owner(s) of process(es) below
"; - const char *reason0 = " Resource allocation failed because there is no callback response from below process(es)
"; - const char *reason1 = " Resource allocation failed because below process(es) did not request deallocation
"; - - char name[RMS_NAME_BUF_SIZE] = {0,}; - GString *gstr; - - if (!RMS_IS_DEBUG_IMAGE) { - SERVER_ERR("Not debug mode. Timeout alarm popup is not shown. reason(%d)", (int)reason); - return; - } - - SERVER_ERR("timeout alarm"); - - gstr = g_string_new(""); - - if (!gstr) { - SERVER_ERR("Failed to create debug popup command"); - return; - } - - g_string_append_printf(gstr, "%s", style_notification_msg); - - switch (reason) { - case RMS_ALARM_NO_CALLBACK_RESPONSE: - g_string_append_printf(gstr, "%s%s", indent, reason0); - break; - case RMS_ALARM_NO_DEALLOCATION: - g_string_append_printf(gstr, "%s%s", indent, reason1); - break; - default : - break; - } - - g_string_append_printf(gstr, "%s%s%s", indent, notification_msg, style_process_name); - - rms_get_cmd_name(info.process_id, name, sizeof(name)); - g_string_append_printf(gstr, "%s%s : %d - %s%s", indent, "pid", (int)(info.process_id), name, "
"); - - for (int i = 0; i < info.n_conflicted; i++) { - g_string_append_printf(gstr, "%s [%d] %s%s", indent, i+1, rm_convert_category_enum_to_string(info.conflicted_resources[i].category_id), "
"); - } - rms_create_popup(title, gstr->str); - SERVER_ERR("Command: %s", gstr->str); - g_string_free(gstr, true); -} - -static bool rms_read_index(int *data) -{ - FILE *fp = NULL; - char str[10] = {0,}; - size_t str_size; - const char *filename = "/proc/device-tree/rm_tbl_idx"; - - if (!data) { - SERVER_ERR("invalid input : null data"); - return false; - } - - fp = fopen(filename, "rb"); - - if (!fp) { - SERVER_ERR("failed to open (%s) - errno(%d)", filename, errno); - return false; - } - - str_size = fread(str, sizeof(char), sizeof(str)-1, fp); - - str[str_size] = '\0'; - - if (str_size == 0) { - fclose(fp); - return false; - } - - *data = atoi(str); - - fclose(fp); - fp = NULL; - - return true; -} - -void rms_display_resource_table_error_popup(void) -{ - const char *title = "FATAL ERROR!!!"; - const char *reason = " Resource Manager can't find a resource table for this board
"; - const char *style_notification_msg = ""; - const char *indent = " "; - const char *notification_msg = "
"; - - GString *gstr = g_string_new(""); - char *chipset_info; - int model_index = -1; - - if (!gstr) { - SERVER_ERR("Failed to create debug popup command"); - return; - } - - g_string_append_printf(gstr, "%s%s", indent, reason); - g_string_append_printf(gstr, "%s%s%s", indent, notification_msg, style_notification_msg); - g_string_append_printf(gstr, "%sProduct type : %d%s", indent, rm_get_product_type(), "
"); - - if (system_info_get_custom_string("com.samsung/featureconf/product.chipset", &chipset_info)!= SYSTEM_INFO_ERROR_NONE) { - SERVER_ERR("Failed to get chipset from system-info"); - goto end; - } - - g_string_append_printf(gstr, "%sChipset : %s%s", indent, chipset_info, "
"); - - if (!rms_read_index(&model_index)) { - SERVER_ERR("failed to read model index"); - } - - g_string_append_printf(gstr, "%sIndex : %d%s", indent, model_index, "
"); - - rms_create_popup(title,gstr->str); - - if (chipset_info) { - free(chipset_info); - } - -end: - g_string_free(gstr, true); - return; -} - -void rms_print_model_info(void) -{ - static char *chipset_info = NULL; - static int rm_index = -1; - - if (!chipset_info) { - if (system_info_get_custom_string("com.samsung/featureconf/product.chipset", &chipset_info)!= SYSTEM_INFO_ERROR_NONE) - SERVER_ERR("Failed to get chipset"); - } - - if (rm_index == -1) { - if (!rms_read_index(&rm_index)) - SERVER_ERR("failed to read rm index"); - } - - SERVER_ERR("> chipset(%s)/product_type(%d)/rm_index(%d)", chipset_info? chipset_info:"", rm_get_product_type(), rm_index); - - char buf[512]; - snprintf(buf, 512, "resource table not loaded! > chipset(%s)/product_type(%d)/rm_index(%d)", chipset_info? chipset_info:"", rm_get_product_type(), rm_index); - rms_print_log_console(buf); -} - -int is_symlink_file(const char *path) -{ - struct stat st; - if (lstat(path, &st) == -1) { - SERVER_ERR("stat error. file path(%s)", path); - return 0; - } - - return (S_ISLNK(st.st_mode)) ? 1 : 0; -} - -const char *rm_convert_error_type_to_string(rms_error_type_e error_type) -{ - switch (error_type) { - case RMS_ERR_TYPE_NONE: - return "None"; - case RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS: - return "Request of invisible process"; - case RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS: - return "Request of low priority process"; - case RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE: - return "Not available resource"; - case RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST: - return "Requested resource does not exist"; - case RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER: - return "Take resource from other consumer"; - default: - return ""; - } -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +static bool product_type_init = false; +static int product_type = 0; //SYSTEM_INFO_PRODUCT_TYPE_TV; + +// The process list which is killed by resource manager +static GHashTable *process_htable = NULL; + +#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0) + +const char *rm_convert_state_enum_to_string(rms_resource_internal_state_e state_enum) +{ + switch (state_enum) { + case RMS_INTERNAL_STATE_FREE: + return "FREE"; + case RMS_INTERNAL_STATE_SHARABLE: + return "SHARABLE"; + case RMS_INTERNAL_STATE_SHARED: + return "SHARED"; + case RMS_INTERNAL_STATE_EXCLUSIVE: + return "EXCLUSIVE"; + case RMS_INTERNAL_STATE_ERROR: + default: + return "NONE"; + } +} + +const char *rm_convert_requested_state_enum_to_string(rms_requests_resource_state_e state_enum) +{ + switch (state_enum) { + case RMS_STATE_PASSIVE: + return "PASSIVE"; + case RMS_STATE_SHARABLE: + return "SHARABLE"; + case RMS_STATE_EXCLUSIVE: + return "EXCLUSIVE"; + case RMS_STATE_EXCLUSIVE_CONDITIONAL: + return "EXCLUSIVE_CONDITIONAL"; + case RMS_STATE_EXCLUSIVE_AUTO: + return "EXCLUSIVE_AUTO"; + case RMS_STATE_EXCLUSIVE_PREFERENCE: + return "EXCLUSIVE_PREFERENCE"; + default: + return "NONE"; + } +} + +const char *rm_convert_category_enum_to_string(rms_rsc_category_e category_enum) +{ + switch (category_enum) { + case RMS_CATEGORY_NONE: + return "NONE"; + case RMS_CATEGORY_AUDIO_DECODER: + return "Audio_Decoder"; + case RMS_CATEGORY_AUDIO_SPDIF_ES_OUTPUT: + return "Not Defined Yet"; + case RMS_CATEGORY_VIDEO_DECODER: + return "Video_Decoder"; + case RMS_CATEGORY_DEMUX: + return "Demux_Main"; + case RMS_CATEGORY_AUDIO_ENCODER: + return "Audio_Encoder"; + case RMS_CATEGORY_VIDEO_ENCODER: + return "Video_Encoder"; + case RMS_CATEGORY_SCALER: + return "Video_Scaler"; + case RMS_CATEGORY_TUNER: + return "Tuner"; + case RMS_CATEGORY_AUDIO_MAIN_OUT: + return "Audio_Main_Out"; + case RMS_CATEGORY_AUDIO_REMOTE_OUT: + return "Audio_Remote_Out"; + case RMS_CATEGORY_AUDIO_SCART_OUT: + return "Audio_Scart_Out"; + case RMS_CATEGORY_MM_PCM_OUT: + return "MM_PCM_playback"; + case RMS_CATEGORY_AUDIO_DECODER_SUB: + return "Audio_Decorder_Sub"; + case RMS_CATEGORY_JPEG_DECODER: + return "JPEG_Decoder"; + case RMS_CATEGORY_MJPEG_DECODER: + return "MJPEG_Decoder"; + case RMS_CATEGORY_SCALER_SUB: + return "Video_Scaler_Sub"; + case RMS_CATEGORY_EXT_VIDEO_SRC: + return "Ext_Video_Src"; + case RMS_CATEGORY_EXT_AUDIO_SRC: + return "Ext_Audio_Src"; + case RMS_CATEGORY_EXT_HDMI_SRC: + return "Ext_HDMI_Src"; + case RMS_CATEGORY_VIDEO_DECODER_SUB: + return "Video_Decoder_Sub"; + case RMS_CATEGORY_CAMERA: + return "Camera"; + case RMS_CATEGORY_DEMUX_REC: + return "Demux_Rec"; + case RMS_CATEGORY_TUNER_SUB: + return "Tuner_Sub"; + case RMS_CATEGORY_VIDEO_DECODER_UHD: + return "Video_Decoder UHD"; + case RMS_CATEGORY_INPUT_SRC_DTV: + return "Input_Src_DTV"; + case RMS_CATEGORY_INPUT_SRC_ATV: + return "Input_Src_ATV"; + case RMS_CATEGORY_INPUT_SRC_HDMI: + return "Input_Src_HDMI"; + case RMS_CATEGORY_INPUT_SRC_COMP: + return "Input_Src_COMP"; + case RMS_CATEGORY_INPUT_SRC_AV: + return "Input_Src_AV"; + case RMS_CATEGORY_INPUT_SRC_SCART: + return "Input_Src_SCART"; + case RMS_CATEGORY_MIC: + return "Mic"; + case RMS_CATEGORY_SW_DECODER: + return "SWDecoder"; + case RMS_CATEGORY_MMP_MEMORY_CLUSTER: + return "MMPlayer MemoryCluster"; + case RMS_CATEGORY_JPEG_DECODER_8K: + return "JPEG_Decoder 8K"; + case RMS_CATEGORY_SCALER_BG: + return "Video_Scaler_BG"; + default: + return ""; + } +} + +const char *rm_convert_device_enum_to_string(rms_device_e device_enum) +{ + switch (device_enum) { + case RMS_DEVICE_NONE: + return "NONE"; + case RMS_DEVICE_AUDIO_MAIN_OUT: + return "audio_main_out"; + case RMS_DEVICE_AUDIO_REMOTE_OUT: + return "audio_remote_out"; + case RMS_DEVICE_AUDIO_SCART_OUT: + return "audio_scart_out"; + case RMS_DEVICE_MM_PCM_OUT: + return "mm_pcm_out"; + case RMS_DEVICE_JPEG_DECODER: + return "jpeg_decoder"; + case RMS_DEVICE_DEMUX0: + return "demux0"; + case RMS_DEVICE_DEMUX1: + return "demux1"; + case RMS_DEVICE_DEMUX2: + return "demux2"; + case RMS_DEVICE_DEMUX3: + return "demux3"; + case RMS_DEVICE_AUDIO_ENCODER: + return "audio_encoder"; + case RMS_DEVICE_VIDEO_ENCODER: + return "video_encoder"; + case RMS_DEVICE_SCALER: + return "scaler"; + case RMS_DEVICE_EXT_VIDEO_SRC: + return "ext_video_src"; + case RMS_DEVICE_EXT_AUDIO_SRC: + return "ext_autio_src"; + case RMS_DEVICE_EXT_HDMI_SRC: + return "ext_hdmi_src"; + case RMS_DEVICE_CAMERA: + return "camera"; + case RMS_DEVICE_TUNER: + return "tuner"; + case RMS_DEVICE_TUNER_SUB: + return "tuner_sub"; + case RMS_DEVICE_SCALER_SUB: + return "scaler_sub"; + case RMS_DEVICE_AUDIO_DECODER: + return "audio_decoder"; + case RMS_DEVICE_AUDIO_DECODER_SUB: + return "audio_decoder_sub"; + case RMS_DEVICE_VIDEO_DECODER_MAIN: + return "video_decoder_main"; + case RMS_DEVICE_VIDEO_DECODER_SUB: + return "video_decoder_sub"; + case RMS_DEVICE_VIDEO_DECODER_UDDEC: + return "video_decoder_uddec"; + case RMS_DEVICE_VIDEO_DECODER_UDHEVC: + return "video_decoder_udhevc"; + case RMS_DEVICE_AUDIO_SPDIF_ES_OUTPUT: + return "audio_spdif_es_output"; + case RMS_DEVICE_MIC: + return "mic"; + case RMS_DEVICE_EXT_COMP_SRC: + return "ext_comp_src"; + case RMS_DEVICE_EXT_AV_SRC: + return "av_src"; + case RMS_DEVICE_MJPEG_DECODER: + return "mjpeg_decoder"; + case RMS_DEVICE_JPEG_DECODER_UHD: + return "jpeg_decoder_uhd"; + case RMS_DEVICE_MJPEG_DECODER_UHD: + return "mjpeg_decoder_uhd"; + case RMS_DEVICE_SW_DECODER: + return "sw_decoder"; + default: + return ""; + } +} + +const char *rm_print_allocation_failure_reason(int ret_value) +{ + switch (ret_value) { + case RMS_OK: + return "OK"; + case RMS_ERROR: + return "Cannot Allocate Resources"; + case RMS_ERROR_TAKE_RESOURCE_FROM_OTHER_CONSUMER: + return "RESOURCE CONFLICT - Other Consumer Is Using"; + case RMS_OK_UHD_RESOURCE_CONFLICT: + return "UHD RESOURCE CONFLICT - Other Consumer Is Using"; + default: + return ""; + } +} +void rms_create_popup(const char *title, const char *text) +{ + bundle *(*bundle_create_fp) (void); + int (*bundle_add_fp)(bundle*, const char*, const char*); + const char *(*bundle_get_val_fp) (bundle*, const char*); + int (*bundle_free_fp) (bundle*); + int (*syspopup_launch_fp) (char*, bundle*); + void *libsyspopup_handle = NULL; + void *libbundle_handle = NULL; + bundle *b = NULL; + char *error; + + libsyspopup_handle = dlopen(LIBDIR"/libsyspopup_caller.so.0.1.0", RTLD_LAZY); + if (!libsyspopup_handle) { + SERVER_ERR("failed to load syspopup library"); + goto end; + } + + libbundle_handle = dlopen(LIBDIR"/libbundle.so.0", RTLD_LAZY); + + if (!libbundle_handle) { + SERVER_ERR("failed to load bundle library"); + goto end; + } + + error = NULL; + + bundle_create_fp = (bundle *(*)(void)) dlsym(libbundle_handle, "bundle_create"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find bundle_create"); + goto end; + + } + + bundle_add_fp = (int (*)(bundle*, const char*, const char*)) dlsym(libbundle_handle, "bundle_add"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find bundle_add"); + goto end; + } + + bundle_get_val_fp = (const char *(*)(bundle*, const char*)) dlsym(libbundle_handle, "bundle_get_val"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find bundle_get_val"); + goto end; + } + + bundle_free_fp = (int (*)(bundle*)) dlsym(libbundle_handle, "bundle_free"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find bundle_free"); + goto end; + } + + syspopup_launch_fp = (int (*)(char*, bundle*)) dlsym(libsyspopup_handle, "syspopup_launch"); + + if ((error = dlerror()) != NULL) { + SERVER_ERR("failed to find alert-syspopup"); + goto end; + } + + b = bundle_create_fp(); + if (!b) { + SERVER_ERR("failed to create bundle"); + goto end; + } + + bundle_add_fp(b, "type", "title_message_1button"); + bundle_add_fp(b, "title", title); + bundle_add_fp(b, "text", text); + + bundle_get_val_fp(b, "type"); + bundle_get_val_fp(b, "title"); + bundle_get_val_fp(b, "text"); + + syspopup_launch_fp((char*)"alert-syspopup", b); + bundle_free_fp(b); + +end: + if (libsyspopup_handle) + dlclose(libsyspopup_handle); + + if (libbundle_handle) + dlclose(libbundle_handle); +} + +int rms_get_cmd_name(pid_t pid, char *name_out, int size) +{ + char name[RMS_NAME_BUF_SIZE] = {0,}; + FILE *f; + size_t sz; + + snprintf(name, sizeof(name), "/proc/%d/cmdline", pid); + // Check if the process exists and is accessible + if (access(name, R_OK) != 0) { + SERVER_ERR("failed to access (%s) : %d", name, errno); + return RMS_ERROR; + } + + f = fopen(name, "r"); + if (!f) { + SERVER_ERR("failed to open cmdline(%s) : %d", name, errno); + return RMS_ERROR; + } + + sz = fread(name, sizeof(char), sizeof(name)-1, f); + name[sz] = '\0'; + fclose(f); + + snprintf(name_out, size, "%s", name); + + return RMS_OK; +} + +void rms_print_log_console(char *buf) +{ + int fd, ret; + char output[RMS_CONSOLE_BUF_SIZE] ={0,}; + + struct timespec tnow; + + fd = open("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); + + if (fd < 0) { + SERVER_ERR("console device open fail"); + return; + } + + if (is_symlink_file("/dev/console")) { + SERVER_ERR("%s is symbolic link file", "/dev/console"); + close(fd); + return; + } + + ret = clock_gettime(CLOCK_MONOTONIC, &tnow); + snprintf(output, RMS_CONSOLE_BUF_SIZE, "[RMS][%ld.%6ld] %s", tnow.tv_sec, tnow.tv_nsec/1000, buf); + ret = write(fd, output, strlen(output)); + + if (ret < 0) { + SERVER_ERR("Fail to write on console directly"); + } + + close(fd); +} + +int rm_get_product_type(void) +{ + if (product_type_init) + return product_type; + + int type = 0; /* SYSTEM_INFO_PRODUCT_TYPE_TV */ + + if (system_info_get_custom_int("com.samsung/featureconf/product.product_type", &type) != SYSTEM_INFO_ERROR_NONE) { + SERVER_ERR("Failed to get com.samsung/featureconf/product.product_type"); + } + + product_type_init = true; + product_type = type; + + return product_type; +} + +int rm_is_valid_pid(int pid) +{ + if (kill((pid_t) pid, 0) == 0) { + SERVER_INFO("pid(%d) is alive", pid); + return 1; + } + + SERVER_ERR("pid(%d) / errno(%d)", pid, errno); + + return (errno == ESRCH) ? 0 : 1; +} + +static void process_htable_destory_key(gpointer key) +{ + if (key) + free(key); +} + +static void process_htable_create(void) +{ + if (process_htable) { + SERVER_ERR("hash table already created"); + return; + } + + process_htable = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)process_htable_destory_key, NULL); + + SERVER_INFO("process hash table created"); +} + +static void process_htable_clear(void) +{ + SERVER_INFO("clear process hash table"); + + if (!process_htable) + return; + + g_hash_table_remove_all(process_htable); +} + +static void process_htable_insert(const char *name) +{ + const int PROCESS_DATA_LIMIT = 100; // The maxinum size is (RMS_NAME_BUF_SIZE * PROCESS_DATA_LIMIT) + + if (!process_htable) + process_htable_create(); + + if (g_hash_table_contains(process_htable, name)) + return; + + if (g_hash_table_size(process_htable) >= PROCESS_DATA_LIMIT) + process_htable_clear(); + + char *key_name = (char*) strndup(name, strlen(name)); + + g_hash_table_insert(process_htable, key_name, (gpointer) 1); + + SERVER_ERR("process info (%s) inserted to hash table (%d)", name, g_hash_table_size(process_htable)); +} + + +bool process_htable_contains(const char *name) +{ + bool result = false; + + if (!process_htable) { + SERVER_INFO("(%s) - no table", name); + return false; + } + + if (g_hash_table_size(process_htable) == 0) { + SERVER_INFO("(%s) - empty", name); + return false; + } + + result = g_hash_table_contains(process_htable, name); + + SERVER_INFO("(%s) - result(%d)", name, result); + + // resource manager is supposed to clear data once it's checked by application + process_htable_clear(); + + return result; +} + +int rms_report_emergency(IN int cid, IN int pid, IN int requester) +{ + const char *vconf_request_cold_poweroff = "memory/boot/cold_poweroff_request_pkg"; + int retry = 25; // 20ms * 25 times => 500ms + int ret = 0; + + SERVER_ERR("consumer is not responding....CID[%d]/PID[%d]/Requester(%d) - set cold power off mode", cid, pid, requester); + + if (vconf_set_str(vconf_request_cold_poweroff, "resource-manager") != 0) { + SERVER_ERR("Failed to set request cold power off"); + } else { + SERVER_ERR("memory/boot/cold_poweroff_request_pkg set as resource-manager"); + } + + char process_name[RMS_NAME_BUF_SIZE] = {0,}; + + if (rms_get_cmd_name(pid, process_name, RMS_NAME_BUF_SIZE) == RMS_OK) { + process_htable_insert(process_name); + } + + SERVER_ERR("kill PID(%d)", pid); + + int signal = SIGKILL; + + if (RMS_IS_DEBUG_IMAGE) { + signal = SIGABRT; + retry = 250; // 20ms * 250 times => 5 sec + } + + ret = kill(pid, signal); + + if (ret!=0) { + SERVER_ERR("Failed to kill(%d), errno(%d)", pid, errno); + } + + // wait until process is really terminated for 500ms + while (retry > 0 && rm_is_valid_pid(pid)) { + retry--; + SERVER_ERR("pid(%d) still alive(%d)", pid, retry); + usleep(20*1000); + continue; + } + + if (RMS_IS_DEBUG_IMAGE && retry <= 0) { + //process didn't get terminated for 5 seconds + SERVER_ERR("pid(%d) is not terminated.", pid); + return RMS_ERROR; + } + + return RMS_OK; +} + +void rms_display_timeout_error_popup(rms_alarm_reason_e reason, rms_consumer_tobe_returned_s info) +{ + const char *title = "Resource Allocation Failure"; + const char *style_notification_msg = ""; + const char *style_process_name = ""; + const char *indent = " "; + const char *notification_msg = "Please contact the owner(s) of process(es) below
"; + const char *reason0 = " Resource allocation failed because there is no callback response from below process(es)
"; + const char *reason1 = " Resource allocation failed because below process(es) did not request deallocation
"; + + char name[RMS_NAME_BUF_SIZE] = {0,}; + GString *gstr; + + if (!RMS_IS_DEBUG_IMAGE) { + SERVER_ERR("Not debug mode. Timeout alarm popup is not shown. reason(%d)", (int)reason); + return; + } + + SERVER_ERR("timeout alarm"); + + gstr = g_string_new(""); + + if (!gstr) { + SERVER_ERR("Failed to create debug popup command"); + return; + } + + g_string_append_printf(gstr, "%s", style_notification_msg); + + switch (reason) { + case RMS_ALARM_NO_CALLBACK_RESPONSE: + g_string_append_printf(gstr, "%s%s", indent, reason0); + break; + case RMS_ALARM_NO_DEALLOCATION: + g_string_append_printf(gstr, "%s%s", indent, reason1); + break; + default : + break; + } + + g_string_append_printf(gstr, "%s%s%s", indent, notification_msg, style_process_name); + + rms_get_cmd_name(info.process_id, name, sizeof(name)); + g_string_append_printf(gstr, "%s%s : %d - %s%s", indent, "pid", (int)(info.process_id), name, "
"); + + for (int i = 0; i < info.n_conflicted; i++) { + g_string_append_printf(gstr, "%s [%d] %s%s", indent, i+1, rm_convert_category_enum_to_string(info.conflicted_resources[i].category_id), "
"); + } + rms_create_popup(title, gstr->str); + SERVER_ERR("Command: %s", gstr->str); + g_string_free(gstr, true); +} + +static bool rms_read_index(int *data) +{ + FILE *fp = NULL; + char str[10] = {0,}; + size_t str_size; + const char *filename = "/proc/device-tree/rm_tbl_idx"; + + if (!data) { + SERVER_ERR("invalid input : null data"); + return false; + } + + fp = fopen(filename, "rb"); + + if (!fp) { + SERVER_ERR("failed to open (%s) - errno(%d)", filename, errno); + return false; + } + + str_size = fread(str, sizeof(char), sizeof(str)-1, fp); + + str[str_size] = '\0'; + + if (str_size == 0) { + fclose(fp); + return false; + } + + *data = atoi(str); + + fclose(fp); + fp = NULL; + + return true; +} + +void rms_display_resource_table_error_popup(void) +{ + const char *title = "FATAL ERROR!!!"; + const char *reason = " Resource Manager can't find a resource table for this board
"; + const char *style_notification_msg = ""; + const char *indent = " "; + const char *notification_msg = "
"; + + GString *gstr = g_string_new(""); + char *chipset_info; + int model_index = -1; + + if (!gstr) { + SERVER_ERR("Failed to create debug popup command"); + return; + } + + g_string_append_printf(gstr, "%s%s", indent, reason); + g_string_append_printf(gstr, "%s%s%s", indent, notification_msg, style_notification_msg); + g_string_append_printf(gstr, "%sProduct type : %d%s", indent, rm_get_product_type(), "
"); + + if (system_info_get_custom_string("com.samsung/featureconf/product.chipset", &chipset_info)!= SYSTEM_INFO_ERROR_NONE) { + SERVER_ERR("Failed to get chipset from system-info"); + goto end; + } + + g_string_append_printf(gstr, "%sChipset : %s%s", indent, chipset_info, "
"); + + if (!rms_read_index(&model_index)) { + SERVER_ERR("failed to read model index"); + } + + g_string_append_printf(gstr, "%sIndex : %d%s", indent, model_index, "
"); + + rms_create_popup(title,gstr->str); + + if (chipset_info) { + free(chipset_info); + } + +end: + g_string_free(gstr, true); + return; +} + +void rms_print_model_info(void) +{ + static char *chipset_info = NULL; + static int rm_index = -1; + + if (!chipset_info) { + if (system_info_get_custom_string("com.samsung/featureconf/product.chipset", &chipset_info)!= SYSTEM_INFO_ERROR_NONE) + SERVER_ERR("Failed to get chipset"); + } + + if (rm_index == -1) { + if (!rms_read_index(&rm_index)) + SERVER_ERR("failed to read rm index"); + } + + SERVER_ERR("> chipset(%s)/product_type(%d)/rm_index(%d)", chipset_info? chipset_info:"", rm_get_product_type(), rm_index); + + char buf[512]; + snprintf(buf, 512, "resource table not loaded! > chipset(%s)/product_type(%d)/rm_index(%d)", chipset_info? chipset_info:"", rm_get_product_type(), rm_index); + rms_print_log_console(buf); +} + +int is_symlink_file(const char *path) +{ + struct stat st; + if (lstat(path, &st) == -1) { + SERVER_ERR("stat error. file path(%s)", path); + return 0; + } + + return (S_ISLNK(st.st_mode)) ? 1 : 0; +} + +const char *rm_convert_error_type_to_string(rms_error_type_e error_type) +{ + switch (error_type) { + case RMS_ERR_TYPE_NONE: + return "None"; + case RMS_ERR_TYPE_REQUEST_OF_INVISIBLE_PROCESS: + return "Request of invisible process"; + case RMS_ERR_TYPE_REQUEST_OF_LOW_PRIORITY_PROCESS: + return "Request of low priority process"; + case RMS_ERR_TYPE_NOT_AVAILABLE_RESOURCE: + return "Not available resource"; + case RMS_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST: + return "Requested resource does not exist"; + case RMS_ERR_TYPE_TAKE_RESOURCE_FROM_OTHER_CONSUMER: + return "Take resource from other consumer"; + default: + return ""; + } +} diff --git a/src/manager/CLockController.cpp b/src/manager/CLockController.cpp index b094c2a..bc2659a 100644 --- a/src/manager/CLockController.cpp +++ b/src/manager/CLockController.cpp @@ -1,84 +1,84 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -std::mutex m; -CLockController *CLockController::m_instance = nullptr; - -CLockController *CLockController::GetInstance(void) -{ - if (m_instance == nullptr) - { - m_instance = new(std::nothrow) CLockController(); - } - - return m_instance; -} - -void CLockController::Lock(ResourceType rsc_type) -{ - std::unique_lock lock(m); - unsigned int count = 0; - auto it = m_locks.find(rsc_type); - - count = (it == m_locks.end()) ? 1 : ++it->second; - - m_locks.insert(std::pair(rsc_type, count)); -} - -void CLockController::Unlock(ResourceType rsc_type) -{ - std::unique_lock lock(m); - - auto it = m_locks.find(rsc_type); - if (it == m_locks.end()) - return; - - if (it->second == 0) - return; - - m_locks.at(rsc_type) = --it->second; - - if (m_locks.at(rsc_type) == 0) - NotifyUnlock(); -} - -unsigned int CLockController::GetLockCount(void) -{ - std::unique_lock lock(m); - unsigned int count = 0; - - for (auto &it : m_locks) - count += it.second; - - return count; -} - -void CLockController::NotifyUnlock(void) -{ - CMessage *msg = new CMessage("NotifyUnlock"); - m_msg_q->push(msg); -} - -bool CLockController::IsLocked(CMessage *msg) -{ - if ((m_locks.at(ResourceType::VIDEO_SCALER) > 0) && msg->IsMsgFor(ResourceType::VIDEO_SCALER)) - return true; - - return false; -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +std::mutex m; +CLockController *CLockController::m_instance = nullptr; + +CLockController *CLockController::GetInstance(void) +{ + if (m_instance == nullptr) + { + m_instance = new(std::nothrow) CLockController(); + } + + return m_instance; +} + +void CLockController::Lock(ResourceType rsc_type) +{ + std::unique_lock lock(m); + unsigned int count = 0; + auto it = m_locks.find(rsc_type); + + count = (it == m_locks.end()) ? 1 : ++it->second; + + m_locks.insert(std::pair(rsc_type, count)); +} + +void CLockController::Unlock(ResourceType rsc_type) +{ + std::unique_lock lock(m); + + auto it = m_locks.find(rsc_type); + if (it == m_locks.end()) + return; + + if (it->second == 0) + return; + + m_locks.at(rsc_type) = --it->second; + + if (m_locks.at(rsc_type) == 0) + NotifyUnlock(); +} + +unsigned int CLockController::GetLockCount(void) +{ + std::unique_lock lock(m); + unsigned int count = 0; + + for (auto &it : m_locks) + count += it.second; + + return count; +} + +void CLockController::NotifyUnlock(void) +{ + CMessage *msg = new CMessage("NotifyUnlock"); + m_msg_q->push(msg); +} + +bool CLockController::IsLocked(CMessage *msg) +{ + if ((m_locks.at(ResourceType::VIDEO_SCALER) > 0) && msg->IsMsgFor(ResourceType::VIDEO_SCALER)) + return true; + + return false; +} diff --git a/src/manager/CPriority.cpp b/src/manager/CPriority.cpp index f85ee21..79f4612 100644 --- a/src/manager/CPriority.cpp +++ b/src/manager/CPriority.cpp @@ -1,156 +1,156 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include - -int CPriority::compare(int cur_consumer_id, int consumer_id) -{ - CConsumerContainer *c_container = CConsumerContainer::getInstance(); - CConsumer *cur_consumer = c_container->findConsumer(cur_consumer_id); - if (!cur_consumer) - return HIGH_PRIORITY; - - CConsumer *consumer = c_container->findConsumer(consumer_id); - if (!consumer) - return LOW_PRIORITY; - - return (cur_consumer->ComparePriority(consumer) == RMS_ERR_TYPE_NONE) ? HIGH_PRIORITY : LOW_PRIORITY; -} - -int CPriority::compareCurConsumers(int device_id, int consumer_id) -{ - CConsumerContainer *c_container = CConsumerContainer::getInstance(); - - CConsumer *consumer = c_container->findConsumer(consumer_id); - if (!consumer) - return LOW_PRIORITY; - - CResource *resource = CResourceDB::getInstance()->FindResource(device_id); - if (!resource) - return HIGH_PRIORITY; - - std::set rsc_consumers = resource->GetConsumers(); - - for (auto const &it : rsc_consumers) { - CConsumer *rsc_consumer = c_container->findConsumer(it); - - if (!rsc_consumer) - continue; - - if (rsc_consumer->GetId() == consumer_id) { - SERVER_WARN("consumer(%d) is already using (%d)", consumer_id, device_id); - return SAME_PRIORITY; - } - - if (rsc_consumer->ComparePriority(consumer) != RMS_ERR_TYPE_NONE) { - SERVER_WARN("LOW PRORITY consumer (%d) device (%d)", consumer_id, device_id); - return LOW_PRIORITY; - } - } - - return HIGH_PRIORITY; -} - -int CPriority::getReclaimableConsumersShare(int device_id, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type) -{ - CResource *resource = CResourceDB::getInstance()->FindResource(device_id); - CConsumer *requester = CConsumerContainer::getInstance()->findConsumer(consumer_id); - - if (!resource || !requester) - return RMS_ERROR; - - if (resource->IsSharableState()) - return RMS_ERROR; - - std::set consumers = resource->GetConsumers(); - - for (auto const &it : consumers) { - int cid = it; - - if (isReclaimableConsumer(cid , consumer_id, err_type)) { - reclaimables->insert(std::pair(device_id, cid)); - break; - } - } - - if (reclaimables->empty()) { - SERVER_ERR("high priority consumer is using device(%d)", device_id); - return RMS_ERROR; - } - - return RMS_OK; -} - -bool CPriority::isReclaimableConsumer(int consumer_id, int requester_id, rms_error_type_e *err_type) -{ - CConsumerContainer *c_container = CConsumerContainer::getInstance(); - CConsumer *consumer = c_container->findConsumer(consumer_id); - CConsumer *requester = c_container->findConsumer(requester_id); - - if (!consumer || !requester) - return false; - - if (consumer_id == requester_id) - return false; - - rms_error_type_e error_type = consumer->ComparePriority(requester); - - if (error_type != RMS_ERR_TYPE_NONE) { - if (err_type) - *err_type = error_type; - - return false; - } - - return true; -} - -int CPriority::getReclaimableConsumers(int device_id, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type) -{ - CResource *resource = CResourceDB::getInstance()->FindResource(device_id); - CConsumer *requester = CConsumerContainer::getInstance()->findConsumer(consumer_id); - - if (!resource || !requester) - return RMS_ERROR; - - if (resource->IsFreeState()) - return RMS_ERROR; - - std::set consumers = resource->GetConsumers(); - - for (auto const &it : consumers) { - int cid = it; - - if (!isReclaimableConsumer(cid , consumer_id, err_type)) - continue; - - reclaimables->insert(std::pair(device_id, cid)); - } - - if (reclaimables->empty()) - { - SERVER_ERR("high priority consumer is using device(%d)", device_id); - return RMS_ERROR; - } - - return RMS_OK; -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +int CPriority::compare(int cur_consumer_id, int consumer_id) +{ + CConsumerContainer *c_container = CConsumerContainer::getInstance(); + CConsumer *cur_consumer = c_container->findConsumer(cur_consumer_id); + if (!cur_consumer) + return HIGH_PRIORITY; + + CConsumer *consumer = c_container->findConsumer(consumer_id); + if (!consumer) + return LOW_PRIORITY; + + return (cur_consumer->ComparePriority(consumer) == RMS_ERR_TYPE_NONE) ? HIGH_PRIORITY : LOW_PRIORITY; +} + +int CPriority::compareCurConsumers(int device_id, int consumer_id) +{ + CConsumerContainer *c_container = CConsumerContainer::getInstance(); + + CConsumer *consumer = c_container->findConsumer(consumer_id); + if (!consumer) + return LOW_PRIORITY; + + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + if (!resource) + return HIGH_PRIORITY; + + std::set rsc_consumers = resource->GetConsumers(); + + for (auto const &it : rsc_consumers) { + CConsumer *rsc_consumer = c_container->findConsumer(it); + + if (!rsc_consumer) + continue; + + if (rsc_consumer->GetId() == consumer_id) { + SERVER_WARN("consumer(%d) is already using (%d)", consumer_id, device_id); + return SAME_PRIORITY; + } + + if (rsc_consumer->ComparePriority(consumer) != RMS_ERR_TYPE_NONE) { + SERVER_WARN("LOW PRORITY consumer (%d) device (%d)", consumer_id, device_id); + return LOW_PRIORITY; + } + } + + return HIGH_PRIORITY; +} + +int CPriority::getReclaimableConsumersShare(int device_id, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type) +{ + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + CConsumer *requester = CConsumerContainer::getInstance()->findConsumer(consumer_id); + + if (!resource || !requester) + return RMS_ERROR; + + if (resource->IsSharableState()) + return RMS_ERROR; + + std::set consumers = resource->GetConsumers(); + + for (auto const &it : consumers) { + int cid = it; + + if (isReclaimableConsumer(cid , consumer_id, err_type)) { + reclaimables->insert(std::pair(device_id, cid)); + break; + } + } + + if (reclaimables->empty()) { + SERVER_ERR("high priority consumer is using device(%d)", device_id); + return RMS_ERROR; + } + + return RMS_OK; +} + +bool CPriority::isReclaimableConsumer(int consumer_id, int requester_id, rms_error_type_e *err_type) +{ + CConsumerContainer *c_container = CConsumerContainer::getInstance(); + CConsumer *consumer = c_container->findConsumer(consumer_id); + CConsumer *requester = c_container->findConsumer(requester_id); + + if (!consumer || !requester) + return false; + + if (consumer_id == requester_id) + return false; + + rms_error_type_e error_type = consumer->ComparePriority(requester); + + if (error_type != RMS_ERR_TYPE_NONE) { + if (err_type) + *err_type = error_type; + + return false; + } + + return true; +} + +int CPriority::getReclaimableConsumers(int device_id, int consumer_id, std::multimap* reclaimables, rms_error_type_e *err_type) +{ + CResource *resource = CResourceDB::getInstance()->FindResource(device_id); + CConsumer *requester = CConsumerContainer::getInstance()->findConsumer(consumer_id); + + if (!resource || !requester) + return RMS_ERROR; + + if (resource->IsFreeState()) + return RMS_ERROR; + + std::set consumers = resource->GetConsumers(); + + for (auto const &it : consumers) { + int cid = it; + + if (!isReclaimableConsumer(cid , consumer_id, err_type)) + continue; + + reclaimables->insert(std::pair(device_id, cid)); + } + + if (reclaimables->empty()) + { + SERVER_ERR("high priority consumer is using device(%d)", device_id); + return RMS_ERROR; + } + + return RMS_OK; +} diff --git a/src/manager/CResource.cpp b/src/manager/CResource.cpp index 1b7fb61..f72f63a 100644 --- a/src/manager/CResource.cpp +++ b/src/manager/CResource.cpp @@ -1,498 +1,498 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#define RMS_SUBSCALER_FLAG "memory/rsc_mgr/subscaler_status" - -using namespace std; -void CResource::m_SetSubScalerFlag(int next_state) -{ - if (next_state == RMS_INTERNAL_STATE_ERROR) - return; - int value = 0; - switch (next_state) { - case RMS_INTERNAL_STATE_FREE: - value = 0; - break; - case RMS_INTERNAL_STATE_SHARABLE: - case RMS_INTERNAL_STATE_SHARED: - case RMS_INTERNAL_STATE_EXCLUSIVE: - value = 1; - break; - } - if (vconf_set_int(RMS_SUBSCALER_FLAG,value) != 0) { - SERVER_ERR("Failed to Set vconf key - %s",RMS_SUBSCALER_FLAG); - return; - } - SERVER_INFO("Subscaler flag set to - %d", value); -} - -CResource::CResource(const int device_id, const rms_rsc_category_e category_type, const char *name, const char *path, - std::set mem_cluster, int is_main_device, const char *audio_codec, int sharable_count) -:m_id(device_id), m_device_name(name), m_device_path(path), m_is_main_device(is_main_device), m_sharable_count(sharable_count) -{ - m_mem_clusters = mem_cluster; - - if (audio_codec) - m_audio_codec.assign(audio_codec); - - m_category_type = category_type; - m_cur_category = category_type; - m_is_scaler = IsScaler(category_type); -} - -CResource::~CResource() -{ -} - -bool CResource::IsScaler(rms_rsc_category_e category) -{ - bool result = false; - - switch (category) { - case RMS_CATEGORY_SCALER: - case RMS_CATEGORY_SCALER_BG: - case RMS_CATEGORY_SCALER_SUB: - case RMS_CATEGORY_SCALER_SUB2: - case RMS_CATEGORY_SCALER_SUB3: - result = true; - break; - default: - break; - } - - return result; -} - -void CResource::UpdateProperties(std::set mem_clusters, int bw, int category, int category_class, int vrsc_id) -{ - m_mem_clusters = mem_clusters; - m_occupied_bw = bw; - m_cur_category = category; - m_category_class = category_class; - m_vrsc_id = vrsc_id; -} - -int CResource::ReserveExclusive(int consumer_id) -{ - if (m_is_reserved && (consumer_id != m_reserved_consumer_id)) { - SERVER_ERR("rsc(%d) already reserved by(%d)", m_id, m_reserved_consumer_id); - return RMS_ERROR; - } - - m_reserved_consumer_id = consumer_id; - m_is_reserved = true; - - return RMS_OK; -} - -int CResource::ReserveShared(int consumer_id) -{ - if (m_is_reserved) { - SERVER_ERR("rsc(%d) already reserved by (%d) with exclusive mode", m_id, m_reserved_consumer_id); - return RMS_ERROR; - } - - m_reserved_count++; - - if ( (m_shared_count + m_reserved_count) > m_sharable_count) { - SERVER_ERR("can't reserve(%d) shared(%d), reserved(%d), max(%d)", m_id, m_shared_count, m_reserved_count, m_sharable_count); - m_reserved_count--; - return RMS_ERROR; - } - - SERVER_INFO("reserve share(%d) shared(%d), reserved(%d), max(%d)", m_id, m_shared_count, m_reserved_count, m_sharable_count); - - return RMS_OK; -} - -int CResource::Reserve(int consumer_id, rms_requests_resource_state_e state) -{ - return (state == RMS_STATE_SHARABLE) ? ReserveShared(consumer_id):ReserveExclusive(consumer_id); -} - -void CResource::CancelReservation(rms_requests_resource_state_e state) -{ - if (state == RMS_STATE_SHARABLE) - m_reserved_count = (--m_reserved_count < 0) ? 0 : m_reserved_count; - else - m_is_reserved = false; -} - -void CResource::AddConsumer(IN const int consumer_id, IN rms_requests_resource_state_e state) -{ - if (IsRegisteredConsumer(consumer_id)) { - IncreaseRefCount(consumer_id); - m_shared_count++; - SERVER_INFO("[rsc(%d)]increase ref count of (%d), shared(%d) by consumers(%zu)", m_id, consumer_id, m_shared_count, m_shared_consumers.size()); - return; - } - - m_consumers.insert(std::pair(consumer_id, 1)); - m_consumer_ids.insert(consumer_id); - - if (state == RMS_STATE_SHARABLE) { - m_shared_consumers.insert(consumer_id); - m_shared_count++; - SERVER_INFO("[rsc(%d)] consumer(%d) shares resource, shared(%d) by consumers(%zu)", m_id, consumer_id, m_shared_count, m_shared_consumers.size()); - } - - return; -} - -void CResource::ResetConsumer(std::set new_consumers) -{ - m_consumers.clear(); - m_consumer_ids.clear(); - m_shared_consumers.clear(); - m_shared_count = 0; - - for (auto &it : new_consumers) { - AddConsumer(it, RMS_STATE_EXCLUSIVE); - } -} - -bool CResource::IsRegisteredConsumer(int consumer_id) -{ - std::map::iterator it = m_consumers.find(consumer_id); - - return (it != m_consumers.end()); -} - -int CResource::IncreaseRefCount(int consumer_id) -{ - int ref_count = 0; - std::map::iterator it = m_consumers.find(consumer_id); - - if (it == m_consumers.end()) - return 0; - - ref_count = it->second; - m_consumers[consumer_id] = ++ref_count; - - return ref_count; -} - -int CResource::DecreaseRefCount(int consumer_id) -{ - int ref_count = 0; - std::map::iterator it = m_consumers.find(consumer_id); - - if (it == m_consumers.end()) - return 0; - - ref_count = it->second; - --ref_count; - ref_count = (ref_count < 0) ? 0 : ref_count; - m_consumers[consumer_id] = ref_count; - - return ref_count; -} - -int CResource::RemoveConsumer(IN int consumer_id, IN bool force) -{ - if (!IsRegisteredConsumer(consumer_id)) { - SERVER_ERR("[rsc(%d)] consumer(%d) is not found in list", m_id, consumer_id); - return 0; - } - - int ref_count = DecreaseRefCount(consumer_id); - - if (m_state == RMS_INTERNAL_STATE_SHARABLE || m_state == RMS_INTERNAL_STATE_SHARED) { - m_shared_count = (--m_shared_count < 0) ? 0 : m_shared_count; - - if (force) - m_shared_count = ((m_shared_count -= ref_count) < 0) ? 0 : m_shared_count; - } - - if (ref_count > 0 && !force) { - SERVER_INFO("consumer(%d) is still sharing resource(%d), ref(%d)", consumer_id, m_id, ref_count); - return ref_count; - } - - m_consumer_ids.erase(consumer_id); - m_consumers.erase(consumer_id); - ChangeStateByRelease(consumer_id); - - return 0; -} - -void CResource::ChangeState(rms_resource_internal_state_e next_state) -{ - if (m_state == next_state) - return; - - SERVER_INFO("state changed (%s : %s) - (%s -> %s)", - rm_convert_category_enum_to_string(m_category_type), - m_device_name, - rm_convert_state_enum_to_string(m_state), - rm_convert_state_enum_to_string(next_state)); - - m_state = next_state; - - if (m_category_type == RMS_CATEGORY_SCALER_SUB) - m_SetSubScalerFlag(next_state); -} - -bool CResource::ChangeStateByAllocation(IN rms_requests_resource_state_e requested_state, const int consumer_id, int mv_zone_id) -{ - if (requested_state == RMS_STATE_EXCLUSIVE_CONDITIONAL || requested_state == RMS_STATE_EXCLUSIVE_AUTO || requested_state == RMS_STATE_EXCLUSIVE_PREFERENCE) - requested_state = RMS_STATE_EXCLUSIVE; - - rms_resource_internal_state_e allocation_resource_state_matrix[4][3] = - {{RMS_INTERNAL_STATE_ERROR, RMS_INTERNAL_STATE_SHARABLE, RMS_INTERNAL_STATE_EXCLUSIVE}, - {RMS_INTERNAL_STATE_SHARABLE, RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_ERROR}, - {RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_ERROR}, - {RMS_INTERNAL_STATE_EXCLUSIVE, RMS_INTERNAL_STATE_ERROR, RMS_INTERNAL_STATE_ERROR}}; - - bool need_notify_by_alloc_matrix[4][3] = {{false, true, true}, - {false, true, false}, - {false, true, false}, - {false, false, true}}; - - rms_resource_internal_state_e next_state = allocation_resource_state_matrix[m_state][requested_state]; - SERVER_INFO("m_state %d requested_state %d next_state %d", m_state, requested_state, next_state); - - bool need_notify = need_notify_by_alloc_matrix[m_state][requested_state]; - - m_is_reserved = false; - m_reserved_consumer_id = 0; - - if (next_state == RMS_INTERNAL_STATE_ERROR) { - SERVER_ERR("state change error! device(%d) (%s) to (%s)", m_id, rm_convert_state_enum_to_string(m_state), rm_convert_state_enum_to_string(next_state)); - return false; - } - - m_state = next_state; - - if (m_category_type == RMS_CATEGORY_SCALER_SUB) - m_SetSubScalerFlag(next_state); - - if (mv_zone_id > 0) { - m_mv_zone_id = mv_zone_id; - SERVER_INFO("(%d) > zone_id(%d)", m_id, m_mv_zone_id); - } - - if (need_notify) - NotifyObservers(UPDATED_BY_ALLOC, consumer_id); - - return true; -} - -bool CResource::ChangeStateByRelease(int consumer_id) -{ - rms_resource_internal_state_e current_state = m_state; - rms_resource_internal_state_e next_state = RMS_INTERNAL_STATE_ERROR; - - bool need_notify = false; - - SERVER_INFO("current_state %d m_shared_count %d", current_state, m_shared_count); - - switch (current_state) { - case RMS_INTERNAL_STATE_SHARED: - m_shared_consumers.erase(consumer_id); - need_notify = true; - - if (m_shared_count > 1) { - next_state = RMS_INTERNAL_STATE_SHARED; - } else if (m_shared_count == 1) { - next_state = RMS_INTERNAL_STATE_SHARABLE; - } else { - next_state = RMS_INTERNAL_STATE_FREE; - } - break; - case RMS_INTERNAL_STATE_EXCLUSIVE: - case RMS_INTERNAL_STATE_SHARABLE: - next_state = RMS_INTERNAL_STATE_FREE; - need_notify = true; - break; - case RMS_INTERNAL_STATE_FREE: - default: - SERVER_ERR("unexpected resource state (%d)", current_state); - next_state = RMS_INTERNAL_STATE_FREE; - break; - } - - m_state = next_state; - SERVER_INFO("m_state %d need notify %d", m_state, need_notify); - - if (m_category_type == RMS_CATEGORY_SCALER_SUB) - m_SetSubScalerFlag(next_state); - - if (need_notify) { - m_mv_zone_id = -1; - NotifyObservers(UPDATED_BY_RELEASE, consumer_id); - } - - return true; -} - -bool CResource::IsAllocatableState(IN rms_requests_resource_state_e requested_state) -{ - bool can_allocation_matrix[4][6] = - /*requested_state*/ /* PASSIVE */ /*SHARABLE*/ /*EXCLUSIVE*/ /* EXCLUSIVE CON */ /* EXCLUSIVE AUTO */ /* EXCLUSIVE PREFERENCE */ - /* m_state */ /* FREE */{ {false, true, true, true, true, true }, - /* SHARABLE */ { true, true, false, false, false, false }, - /* SHARED */ { true, true, false, false, false, false }, - /* EXCLUSIVE */ { true, false, false, false, false, false } }; - - SERVER_INFO("Status - DevID[%d:%s] / CatID[%d] / CurState[%s] / ReqState[%s]", - m_id, m_device_name, m_category_type, rm_convert_state_enum_to_string(m_state), rm_convert_requested_state_enum_to_string(requested_state)); - - /* check requested_state is valid */ - if ((requested_state < RMS_STATE_PASSIVE) || (requested_state > RMS_STATE_EXCLUSIVE_PREFERENCE)) { - SERVER_ERR("rquested state is invalid"); - return false; - } - - return can_allocation_matrix[m_state][requested_state]; -} - -void CResource::SetDefaultBW(unsigned int bw) -{ - m_default_bw = bw; - m_occupied_bw = bw; -} -void CResource::SetAllocatedTime(void) -{ - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - unsigned long sec = t.tv_sec * 1000; - unsigned long nsec = t.tv_nsec / 1000000; - m_allocated_time = sec + nsec; -} - -void CResource::RegisterObserver(CResourceObserver *observer) -{ - if (!observer) { - SERVER_ERR("observer NULL"); - return; - } - - m_observers.push_back(observer); -} - -void CResource::UnregisterObserver(CResourceObserver *observer) -{ - auto it = std::find(m_observers.begin(), m_observers.end(), observer); - - if (it == m_observers.end()) { - SERVER_ERR("not registered observer"); - return; - } - - m_observers.erase(it); - - SERVER_INFO("observer removed"); -} - -void CResource::NotifyObservers(resource_update_type_e type, const int consumer_id) -{ - for (CResourceObserver *observer : m_observers) { - observer->Update(type, m_id, consumer_id); - } -} - -bool CResource::Allocate(const int consumer_id, rms_requests_resource_state_e state, int mv_zone_id) -{ - if (!ChangeStateByAllocation(state, consumer_id, mv_zone_id)) - return false; - - AddConsumer(consumer_id, state); - return true; -} - -void CResource::SetZoneId(int zone_id) -{ - SERVER_INFO("(%d) > zone_id(%d)", m_id, zone_id); - m_mv_zone_id = zone_id; -} - -void CResource::UpdateAudioCodec(std::string codec_name) -{ - m_audio_codec = codec_name; -} - -bool CResource::IsAudioDevice(void) -{ - if (m_category_type == RMS_CATEGORY_AUDIO_DECODER) - return true; - if (m_category_type == RMS_CATEGORY_AUDIO_DECODER_SUB) - return true; - if (m_category_type == RMS_CATEGORY_AUDIO_DECODER_PRIMARY) - return true; - if ((m_category_type > RMS_CATEGORY_AUDIO_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX)) - return true; - - return false; -} - -bool CResource::IsVideoDecoder(void) -{ - if (m_category_type == RMS_CATEGORY_VIDEO_DECODER) - return true; - if (m_category_type == RMS_CATEGORY_VIDEO_DECODER_SUB) - return true; - if ((m_category_type > RMS_CATEGORY_VIDEO_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX)) - return true; - if (m_category_type == RMS_CATEGORY_MJPEG_DECODER) - return true; - if ((m_category_type > RMS_CATEGORY_MJPEG_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_MJPEG_DECODER_OPTION_MAX)) - return true; - - return false; -} - -int CResource::GetFirstConsumer(void) -{ - if (m_consumer_ids.empty()) - return -1; - - auto it = m_consumer_ids.begin(); - return *it; -} - -int CResource::GetVirtualDeviceId(void) -{ - return (m_virtual_id < RI_VIRTUAL_ID_SCALER) ? m_id : m_virtual_id; -} - -bool CResource::IsJpegDecoder(void) -{ - if (m_category_type == RMS_CATEGORY_JPEG_DECODER) - return true; - if ((m_category_type > RMS_CATEGORY_JPEG_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_JPEG_DECODER_OPTION_MAX)) - return true; - - return false; -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define RMS_SUBSCALER_FLAG "memory/rsc_mgr/subscaler_status" + +using namespace std; +void CResource::m_SetSubScalerFlag(int next_state) +{ + if (next_state == RMS_INTERNAL_STATE_ERROR) + return; + int value = 0; + switch (next_state) { + case RMS_INTERNAL_STATE_FREE: + value = 0; + break; + case RMS_INTERNAL_STATE_SHARABLE: + case RMS_INTERNAL_STATE_SHARED: + case RMS_INTERNAL_STATE_EXCLUSIVE: + value = 1; + break; + } + if (vconf_set_int(RMS_SUBSCALER_FLAG,value) != 0) { + SERVER_ERR("Failed to Set vconf key - %s",RMS_SUBSCALER_FLAG); + return; + } + SERVER_INFO("Subscaler flag set to - %d", value); +} + +CResource::CResource(const int device_id, const rms_rsc_category_e category_type, const char *name, const char *path, + std::set mem_cluster, int is_main_device, const char *audio_codec, int sharable_count) +:m_id(device_id), m_device_name(name), m_device_path(path), m_is_main_device(is_main_device), m_sharable_count(sharable_count) +{ + m_mem_clusters = mem_cluster; + + if (audio_codec) + m_audio_codec.assign(audio_codec); + + m_category_type = category_type; + m_cur_category = category_type; + m_is_scaler = IsScaler(category_type); +} + +CResource::~CResource() +{ +} + +bool CResource::IsScaler(rms_rsc_category_e category) +{ + bool result = false; + + switch (category) { + case RMS_CATEGORY_SCALER: + case RMS_CATEGORY_SCALER_BG: + case RMS_CATEGORY_SCALER_SUB: + case RMS_CATEGORY_SCALER_SUB2: + case RMS_CATEGORY_SCALER_SUB3: + result = true; + break; + default: + break; + } + + return result; +} + +void CResource::UpdateProperties(std::set mem_clusters, int bw, int category, int category_class, int vrsc_id) +{ + m_mem_clusters = mem_clusters; + m_occupied_bw = bw; + m_cur_category = category; + m_category_class = category_class; + m_vrsc_id = vrsc_id; +} + +int CResource::ReserveExclusive(int consumer_id) +{ + if (m_is_reserved && (consumer_id != m_reserved_consumer_id)) { + SERVER_ERR("rsc(%d) already reserved by(%d)", m_id, m_reserved_consumer_id); + return RMS_ERROR; + } + + m_reserved_consumer_id = consumer_id; + m_is_reserved = true; + + return RMS_OK; +} + +int CResource::ReserveShared(int consumer_id) +{ + if (m_is_reserved) { + SERVER_ERR("rsc(%d) already reserved by (%d) with exclusive mode", m_id, m_reserved_consumer_id); + return RMS_ERROR; + } + + m_reserved_count++; + + if ( (m_shared_count + m_reserved_count) > m_sharable_count) { + SERVER_ERR("can't reserve(%d) shared(%d), reserved(%d), max(%d)", m_id, m_shared_count, m_reserved_count, m_sharable_count); + m_reserved_count--; + return RMS_ERROR; + } + + SERVER_INFO("reserve share(%d) shared(%d), reserved(%d), max(%d)", m_id, m_shared_count, m_reserved_count, m_sharable_count); + + return RMS_OK; +} + +int CResource::Reserve(int consumer_id, rms_requests_resource_state_e state) +{ + return (state == RMS_STATE_SHARABLE) ? ReserveShared(consumer_id):ReserveExclusive(consumer_id); +} + +void CResource::CancelReservation(rms_requests_resource_state_e state) +{ + if (state == RMS_STATE_SHARABLE) + m_reserved_count = (--m_reserved_count < 0) ? 0 : m_reserved_count; + else + m_is_reserved = false; +} + +void CResource::AddConsumer(IN const int consumer_id, IN rms_requests_resource_state_e state) +{ + if (IsRegisteredConsumer(consumer_id)) { + IncreaseRefCount(consumer_id); + m_shared_count++; + SERVER_INFO("[rsc(%d)]increase ref count of (%d), shared(%d) by consumers(%zu)", m_id, consumer_id, m_shared_count, m_shared_consumers.size()); + return; + } + + m_consumers.insert(std::pair(consumer_id, 1)); + m_consumer_ids.insert(consumer_id); + + if (state == RMS_STATE_SHARABLE) { + m_shared_consumers.insert(consumer_id); + m_shared_count++; + SERVER_INFO("[rsc(%d)] consumer(%d) shares resource, shared(%d) by consumers(%zu)", m_id, consumer_id, m_shared_count, m_shared_consumers.size()); + } + + return; +} + +void CResource::ResetConsumer(std::set new_consumers) +{ + m_consumers.clear(); + m_consumer_ids.clear(); + m_shared_consumers.clear(); + m_shared_count = 0; + + for (auto &it : new_consumers) { + AddConsumer(it, RMS_STATE_EXCLUSIVE); + } +} + +bool CResource::IsRegisteredConsumer(int consumer_id) +{ + std::map::iterator it = m_consumers.find(consumer_id); + + return (it != m_consumers.end()); +} + +int CResource::IncreaseRefCount(int consumer_id) +{ + int ref_count = 0; + std::map::iterator it = m_consumers.find(consumer_id); + + if (it == m_consumers.end()) + return 0; + + ref_count = it->second; + m_consumers[consumer_id] = ++ref_count; + + return ref_count; +} + +int CResource::DecreaseRefCount(int consumer_id) +{ + int ref_count = 0; + std::map::iterator it = m_consumers.find(consumer_id); + + if (it == m_consumers.end()) + return 0; + + ref_count = it->second; + --ref_count; + ref_count = (ref_count < 0) ? 0 : ref_count; + m_consumers[consumer_id] = ref_count; + + return ref_count; +} + +int CResource::RemoveConsumer(IN int consumer_id, IN bool force) +{ + if (!IsRegisteredConsumer(consumer_id)) { + SERVER_ERR("[rsc(%d)] consumer(%d) is not found in list", m_id, consumer_id); + return 0; + } + + int ref_count = DecreaseRefCount(consumer_id); + + if (m_state == RMS_INTERNAL_STATE_SHARABLE || m_state == RMS_INTERNAL_STATE_SHARED) { + m_shared_count = (--m_shared_count < 0) ? 0 : m_shared_count; + + if (force) + m_shared_count = ((m_shared_count -= ref_count) < 0) ? 0 : m_shared_count; + } + + if (ref_count > 0 && !force) { + SERVER_INFO("consumer(%d) is still sharing resource(%d), ref(%d)", consumer_id, m_id, ref_count); + return ref_count; + } + + m_consumer_ids.erase(consumer_id); + m_consumers.erase(consumer_id); + ChangeStateByRelease(consumer_id); + + return 0; +} + +void CResource::ChangeState(rms_resource_internal_state_e next_state) +{ + if (m_state == next_state) + return; + + SERVER_INFO("state changed (%s : %s) - (%s -> %s)", + rm_convert_category_enum_to_string(m_category_type), + m_device_name, + rm_convert_state_enum_to_string(m_state), + rm_convert_state_enum_to_string(next_state)); + + m_state = next_state; + + if (m_category_type == RMS_CATEGORY_SCALER_SUB) + m_SetSubScalerFlag(next_state); +} + +bool CResource::ChangeStateByAllocation(IN rms_requests_resource_state_e requested_state, const int consumer_id, int mv_zone_id) +{ + if (requested_state == RMS_STATE_EXCLUSIVE_CONDITIONAL || requested_state == RMS_STATE_EXCLUSIVE_AUTO || requested_state == RMS_STATE_EXCLUSIVE_PREFERENCE) + requested_state = RMS_STATE_EXCLUSIVE; + + rms_resource_internal_state_e allocation_resource_state_matrix[4][3] = + {{RMS_INTERNAL_STATE_ERROR, RMS_INTERNAL_STATE_SHARABLE, RMS_INTERNAL_STATE_EXCLUSIVE}, + {RMS_INTERNAL_STATE_SHARABLE, RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_ERROR}, + {RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_SHARED, RMS_INTERNAL_STATE_ERROR}, + {RMS_INTERNAL_STATE_EXCLUSIVE, RMS_INTERNAL_STATE_ERROR, RMS_INTERNAL_STATE_ERROR}}; + + bool need_notify_by_alloc_matrix[4][3] = {{false, true, true}, + {false, true, false}, + {false, true, false}, + {false, false, true}}; + + rms_resource_internal_state_e next_state = allocation_resource_state_matrix[m_state][requested_state]; + SERVER_INFO("m_state %d requested_state %d next_state %d", m_state, requested_state, next_state); + + bool need_notify = need_notify_by_alloc_matrix[m_state][requested_state]; + + m_is_reserved = false; + m_reserved_consumer_id = 0; + + if (next_state == RMS_INTERNAL_STATE_ERROR) { + SERVER_ERR("state change error! device(%d) (%s) to (%s)", m_id, rm_convert_state_enum_to_string(m_state), rm_convert_state_enum_to_string(next_state)); + return false; + } + + m_state = next_state; + + if (m_category_type == RMS_CATEGORY_SCALER_SUB) + m_SetSubScalerFlag(next_state); + + if (mv_zone_id > 0) { + m_mv_zone_id = mv_zone_id; + SERVER_INFO("(%d) > zone_id(%d)", m_id, m_mv_zone_id); + } + + if (need_notify) + NotifyObservers(UPDATED_BY_ALLOC, consumer_id); + + return true; +} + +bool CResource::ChangeStateByRelease(int consumer_id) +{ + rms_resource_internal_state_e current_state = m_state; + rms_resource_internal_state_e next_state = RMS_INTERNAL_STATE_ERROR; + + bool need_notify = false; + + SERVER_INFO("current_state %d m_shared_count %d", current_state, m_shared_count); + + switch (current_state) { + case RMS_INTERNAL_STATE_SHARED: + m_shared_consumers.erase(consumer_id); + need_notify = true; + + if (m_shared_count > 1) { + next_state = RMS_INTERNAL_STATE_SHARED; + } else if (m_shared_count == 1) { + next_state = RMS_INTERNAL_STATE_SHARABLE; + } else { + next_state = RMS_INTERNAL_STATE_FREE; + } + break; + case RMS_INTERNAL_STATE_EXCLUSIVE: + case RMS_INTERNAL_STATE_SHARABLE: + next_state = RMS_INTERNAL_STATE_FREE; + need_notify = true; + break; + case RMS_INTERNAL_STATE_FREE: + default: + SERVER_ERR("unexpected resource state (%d)", current_state); + next_state = RMS_INTERNAL_STATE_FREE; + break; + } + + m_state = next_state; + SERVER_INFO("m_state %d need notify %d", m_state, need_notify); + + if (m_category_type == RMS_CATEGORY_SCALER_SUB) + m_SetSubScalerFlag(next_state); + + if (need_notify) { + m_mv_zone_id = -1; + NotifyObservers(UPDATED_BY_RELEASE, consumer_id); + } + + return true; +} + +bool CResource::IsAllocatableState(IN rms_requests_resource_state_e requested_state) +{ + bool can_allocation_matrix[4][6] = + /*requested_state*/ /* PASSIVE */ /*SHARABLE*/ /*EXCLUSIVE*/ /* EXCLUSIVE CON */ /* EXCLUSIVE AUTO */ /* EXCLUSIVE PREFERENCE */ + /* m_state */ /* FREE */{ {false, true, true, true, true, true }, + /* SHARABLE */ { true, true, false, false, false, false }, + /* SHARED */ { true, true, false, false, false, false }, + /* EXCLUSIVE */ { true, false, false, false, false, false } }; + + SERVER_INFO("Status - DevID[%d:%s] / CatID[%d] / CurState[%s] / ReqState[%s]", + m_id, m_device_name, m_category_type, rm_convert_state_enum_to_string(m_state), rm_convert_requested_state_enum_to_string(requested_state)); + + /* check requested_state is valid */ + if ((requested_state < RMS_STATE_PASSIVE) || (requested_state > RMS_STATE_EXCLUSIVE_PREFERENCE)) { + SERVER_ERR("rquested state is invalid"); + return false; + } + + return can_allocation_matrix[m_state][requested_state]; +} + +void CResource::SetDefaultBW(unsigned int bw) +{ + m_default_bw = bw; + m_occupied_bw = bw; +} +void CResource::SetAllocatedTime(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + unsigned long sec = t.tv_sec * 1000; + unsigned long nsec = t.tv_nsec / 1000000; + m_allocated_time = sec + nsec; +} + +void CResource::RegisterObserver(CResourceObserver *observer) +{ + if (!observer) { + SERVER_ERR("observer NULL"); + return; + } + + m_observers.push_back(observer); +} + +void CResource::UnregisterObserver(CResourceObserver *observer) +{ + auto it = std::find(m_observers.begin(), m_observers.end(), observer); + + if (it == m_observers.end()) { + SERVER_ERR("not registered observer"); + return; + } + + m_observers.erase(it); + + SERVER_INFO("observer removed"); +} + +void CResource::NotifyObservers(resource_update_type_e type, const int consumer_id) +{ + for (CResourceObserver *observer : m_observers) { + observer->Update(type, m_id, consumer_id); + } +} + +bool CResource::Allocate(const int consumer_id, rms_requests_resource_state_e state, int mv_zone_id) +{ + if (!ChangeStateByAllocation(state, consumer_id, mv_zone_id)) + return false; + + AddConsumer(consumer_id, state); + return true; +} + +void CResource::SetZoneId(int zone_id) +{ + SERVER_INFO("(%d) > zone_id(%d)", m_id, zone_id); + m_mv_zone_id = zone_id; +} + +void CResource::UpdateAudioCodec(std::string codec_name) +{ + m_audio_codec = codec_name; +} + +bool CResource::IsAudioDevice(void) +{ + if (m_category_type == RMS_CATEGORY_AUDIO_DECODER) + return true; + if (m_category_type == RMS_CATEGORY_AUDIO_DECODER_SUB) + return true; + if (m_category_type == RMS_CATEGORY_AUDIO_DECODER_PRIMARY) + return true; + if ((m_category_type > RMS_CATEGORY_AUDIO_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_AUDIO_DECODER_OPTION_MAX)) + return true; + + return false; +} + +bool CResource::IsVideoDecoder(void) +{ + if (m_category_type == RMS_CATEGORY_VIDEO_DECODER) + return true; + if (m_category_type == RMS_CATEGORY_VIDEO_DECODER_SUB) + return true; + if ((m_category_type > RMS_CATEGORY_VIDEO_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_VIDEO_DECODER_OPTION_MAX)) + return true; + if (m_category_type == RMS_CATEGORY_MJPEG_DECODER) + return true; + if ((m_category_type > RMS_CATEGORY_MJPEG_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_MJPEG_DECODER_OPTION_MAX)) + return true; + + return false; +} + +int CResource::GetFirstConsumer(void) +{ + if (m_consumer_ids.empty()) + return -1; + + auto it = m_consumer_ids.begin(); + return *it; +} + +int CResource::GetVirtualDeviceId(void) +{ + return (m_virtual_id < RI_VIRTUAL_ID_SCALER) ? m_id : m_virtual_id; +} + +bool CResource::IsJpegDecoder(void) +{ + if (m_category_type == RMS_CATEGORY_JPEG_DECODER) + return true; + if ((m_category_type > RMS_CATEGORY_JPEG_DECODER_OPTION) && (m_category_type < RMS_CATEGORY_JPEG_DECODER_OPTION_MAX)) + return true; + + return false; +} diff --git a/src/manager/CResourceCategory.cpp b/src/manager/CResourceCategory.cpp index 4cae0b1..6d87196 100644 --- a/src/manager/CResourceCategory.cpp +++ b/src/manager/CResourceCategory.cpp @@ -1,160 +1,160 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -CResourceCategory::CResourceCategory(IN rms_rsc_category_e resource_category_id, IN int category_class) -:m_categoryID(resource_category_id) -{ - m_alloc_strategy = CAllocateStrategyProvider::getInstance()->GetStrategy(resource_category_id, category_class); - assert(m_alloc_strategy); -} - -CResourceCategory::~CResourceCategory() -{ - delete m_alloc_strategy; -} - -void CResourceCategory::AddVirtualResource(IN int device_id, IN CVirtualResource *vresource) -{ - std::map::iterator it = m_device_id_to_vresource_map.find(device_id); - - if (it != m_device_id_to_vresource_map.end()) - return; - - m_device_id_to_vresource_map.insert(std::pair(device_id, vresource)); -} - -CResource *CResourceCategory::ReserveCandidate(CRequest *req, bool apply_promotion) -{ - CVirtualResource *vrsc = m_alloc_strategy->findCandidate(m_device_id_to_vresource_map, req); - - if (!vrsc) - return NULL; - - if (m_alloc_strategy->reserveResource(vrsc, req) != RMS_OK) { - SERVER_INFO("can't find candidate (%d)", m_categoryID); - return NULL; - } - - SERVER_INFO("candidate found (%d:%d)", m_categoryID, vrsc->GetResource()->GetDeviceID()); - - req->SetResult(RMS_OK); - req->SetReason(RMS_ERR_TYPE_NONE); - - return vrsc->GetResource(); -} - -bool CResourceCategory::hasFreeStateResource(void) -{ - for (auto& it : m_device_id_to_vresource_map) { - CVirtualResource *vresource = it.second; - CResource *resource = vresource->GetResource(); - - if (resource->IsFreeState()) - return true; - } - - return false; -} - -void CResourceCategory::MakeResourceMapSortedByAllocTime(std::multimap *resource_map) -{ - for (auto& it : m_device_id_to_vresource_map) { - CVirtualResource *vresource = it.second; - CResource *rsc = vresource->GetResource(); - - resource_map->insert(std::pair(rsc->GetAllocatedTime(), vresource)); - } -} - -void CResourceCategory::GetRetirableConsumers(CRequest *req, - std::multimap* return_ids_in_category, - rms_error_type_e *err_type) -{ - assert(return_ids_in_category); - - std::multimap sorted_resource_map; - MakeResourceMapSortedByAllocTime(&sorted_resource_map); - m_alloc_strategy->GetRetirableConsumers(sorted_resource_map, req, return_ids_in_category, err_type); -} - -bool CResourceCategory::IsAvailableToUse(rms_requests_resource_state_e request_state) -{ - CResource *resource; - CDependencyController *dc = CDependencyController::getInstance(); - CBandwidth *bandwidth = CBandwidth::GetInstance(); - - for (auto& it : m_device_id_to_vresource_map) { - CVirtualResource *vresource = it.second; - resource = vresource->GetResource(); - - if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) { - SERVER_ERR("Not available: Mem Cluster is occupied."); - continue; - } - - if (vresource->GetBW() > bandwidth->GetAvail()) { - SERVER_ERR("Not available: BW is insufficient!!"); - continue; - } - - if ((request_state == RMS_STATE_SHARABLE) && (!resource->IsSharableDevice())) { - SERVER_ERR("Not available: resource(%d) cannot be shared", resource->GetDeviceID()); - continue; - } - - if (resource->IsAllocatableState(request_state)) - return true; - } - - return false; -} - -void CResourceCategory::GetResources(std::map *resource_map) -{ - int i = 0; - for (auto& it : m_device_id_to_vresource_map) { - CVirtualResource *vresource = it.second; - CResource *resource = vresource->GetResource(); - resource_map->insert(std::pair(i++, resource)); - } -} - -CResource *CResourceCategory::FindMainResource(void) -{ - for (auto& it : m_device_id_to_vresource_map) { - CVirtualResource *vresource = it.second; - CResource *resource = vresource->GetResource(); - - if (resource->IsMainDevice()) - return resource; - } - - return NULL; -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CResourceCategory::CResourceCategory(IN rms_rsc_category_e resource_category_id, IN int category_class) +:m_categoryID(resource_category_id) +{ + m_alloc_strategy = CAllocateStrategyProvider::getInstance()->GetStrategy(resource_category_id, category_class); + assert(m_alloc_strategy); +} + +CResourceCategory::~CResourceCategory() +{ + delete m_alloc_strategy; +} + +void CResourceCategory::AddVirtualResource(IN int device_id, IN CVirtualResource *vresource) +{ + std::map::iterator it = m_device_id_to_vresource_map.find(device_id); + + if (it != m_device_id_to_vresource_map.end()) + return; + + m_device_id_to_vresource_map.insert(std::pair(device_id, vresource)); +} + +CResource *CResourceCategory::ReserveCandidate(CRequest *req, bool apply_promotion) +{ + CVirtualResource *vrsc = m_alloc_strategy->findCandidate(m_device_id_to_vresource_map, req); + + if (!vrsc) + return NULL; + + if (m_alloc_strategy->reserveResource(vrsc, req) != RMS_OK) { + SERVER_INFO("can't find candidate (%d)", m_categoryID); + return NULL; + } + + SERVER_INFO("candidate found (%d:%d)", m_categoryID, vrsc->GetResource()->GetDeviceID()); + + req->SetResult(RMS_OK); + req->SetReason(RMS_ERR_TYPE_NONE); + + return vrsc->GetResource(); +} + +bool CResourceCategory::hasFreeStateResource(void) +{ + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (resource->IsFreeState()) + return true; + } + + return false; +} + +void CResourceCategory::MakeResourceMapSortedByAllocTime(std::multimap *resource_map) +{ + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + CResource *rsc = vresource->GetResource(); + + resource_map->insert(std::pair(rsc->GetAllocatedTime(), vresource)); + } +} + +void CResourceCategory::GetRetirableConsumers(CRequest *req, + std::multimap* return_ids_in_category, + rms_error_type_e *err_type) +{ + assert(return_ids_in_category); + + std::multimap sorted_resource_map; + MakeResourceMapSortedByAllocTime(&sorted_resource_map); + m_alloc_strategy->GetRetirableConsumers(sorted_resource_map, req, return_ids_in_category, err_type); +} + +bool CResourceCategory::IsAvailableToUse(rms_requests_resource_state_e request_state) +{ + CResource *resource; + CDependencyController *dc = CDependencyController::getInstance(); + CBandwidth *bandwidth = CBandwidth::GetInstance(); + + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + resource = vresource->GetResource(); + + if (!dc->isAvailableMemClusters(vresource->GetMemClusters())) { + SERVER_ERR("Not available: Mem Cluster is occupied."); + continue; + } + + if (vresource->GetBW() > bandwidth->GetAvail()) { + SERVER_ERR("Not available: BW is insufficient!!"); + continue; + } + + if ((request_state == RMS_STATE_SHARABLE) && (!resource->IsSharableDevice())) { + SERVER_ERR("Not available: resource(%d) cannot be shared", resource->GetDeviceID()); + continue; + } + + if (resource->IsAllocatableState(request_state)) + return true; + } + + return false; +} + +void CResourceCategory::GetResources(std::map *resource_map) +{ + int i = 0; + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + resource_map->insert(std::pair(i++, resource)); + } +} + +CResource *CResourceCategory::FindMainResource(void) +{ + for (auto& it : m_device_id_to_vresource_map) { + CVirtualResource *vresource = it.second; + CResource *resource = vresource->GetResource(); + + if (resource->IsMainDevice()) + return resource; + } + + return NULL; +} diff --git a/src/manager/CResourceDB.cpp b/src/manager/CResourceDB.cpp index ce93b02..b721137 100644 --- a/src/manager/CResourceDB.cpp +++ b/src/manager/CResourceDB.cpp @@ -1,789 +1,789 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -CResourceDB *CResourceDB::m_instance = NULL; - -CResourceDB *CResourceDB::getInstance(void) -{ - if (!m_instance) { - m_instance = new(std::nothrow) CResourceDB; - assert(m_instance); - } - - return m_instance; -} - -CResourceCategory *CResourceDB::FindResourceCategory(IN rms_rsc_category_e category_id) -{ - std::map::iterator it = m_resourceCategoryMap.find(category_id); - - if (it == m_resourceCategoryMap.end()) - return NULL; - - return (*it).second; -} - -CResource *CResourceDB::FindResource(IN const int device_id) -{ - std::map::iterator it = m_deviceid_to_rsc.find(device_id); - - if (it == m_deviceid_to_rsc.end()) { - SERVER_ERR("no device id(%d) in DB", device_id); - return NULL; - } - - return (*it).second; -} - -CVirtualResource *CResourceDB::FindVirtualResource(const int vid) -{ - auto it = m_v_deviceid_to_rsc.find(vid); - - return (it == m_v_deviceid_to_rsc.end()) ? nullptr : it->second; -} - -void CResourceDB::AddVirtualDeviceID(IN CVirtualResource *vresource) -{ - int vrsc_id = vresource->GetVResourceID(); - - std::map::iterator it = m_v_deviceid_to_rsc.find(vrsc_id); - - if (it != m_v_deviceid_to_rsc.end()) - return; - - m_v_deviceid_to_rsc.insert(std::pair(vrsc_id, vresource)); -} - -void CResourceDB::AddDeviceID(IN int device_id, IN CResource *resource) -{ - std::map::iterator it = m_deviceid_to_rsc.find(device_id); - - if (it != m_deviceid_to_rsc.end()) - return; - - m_deviceid_to_rsc.insert(std::pair(device_id, resource)); -} - -void CResourceDB::AddDeviceName(IN const char *device_name, IN CResource *resource) -{ - auto it = m_devicename_to_rsc.find(std::string(device_name)); - - if (it != m_devicename_to_rsc.end()) { - SERVER_DBG("already registered device name(%s) in DB", device_name); - return; - } - - m_devicename_to_rsc.insert(std::pair(std::string(device_name), resource)); -} - -void CResourceDB::AddResourceCategory(IN rms_rsc_category_e category_id, IN CResourceCategory *resource_category) -{ - std::map::iterator it = m_resourceCategoryMap.find(category_id); - - if (it != m_resourceCategoryMap.end()) - return; - - m_resourceCategoryMap.insert(std::pair(category_id, resource_category)); -} - -CResource *CResourceDB::FindResource(const char *device_name) -{ - auto it = m_devicename_to_rsc.find(std::string(device_name)); - - return (it == m_devicename_to_rsc.end()) ? NULL : it->second; -} - -void CResourceDB::AddVirtualResource(IN CVirtualResource *vrsc, - IN rms_rsc_category_e resource_category_id, - IN const char *name, - IN const char *path, - IN std::set mem_cluster_info, - IN unsigned int device_id_unique, - IN int is_main_device, - IN const char *audio_codec, - IN int sharable_count, - IN int mixing_count, - IN CResourceObserver *observer) -{ - assert(name); - assert(path); - - CResource *rsc = FindResource(name); - - if (!rsc) { - rsc = new CResource(device_id_unique, resource_category_id, name, path, mem_cluster_info, is_main_device, audio_codec, sharable_count); - - AddDeviceName(name, rsc); - AddDeviceID(device_id_unique, rsc); - - rsc->RegisterObserver(this); - rsc->RegisterObserver(observer); - } - - vrsc->SetResource(rsc); - - CAudioCodecCollection::getInstance()->registerAudioCodec(audio_codec, mixing_count); - - if (rsc->GetDefaultBW() == 0) - rsc->SetDefaultBW(vrsc->GetBW()); - - AddVirtualDeviceID(vrsc); -} - -void CResourceDB::UpdateBWbyRelease(CResource *rsc) -{ - if (!rsc) - return; - - if (rsc->GetBW() == 0) - return; - - CBandwidth *bw = CBandwidth::GetInstance(); - bw->RemoveConsumer(rsc->GetDeviceID(), rsc->GetCurCategory(), rsc->GetCategoryClass()); - bw->Increase(rsc->GetBW(), rsc->GetCurCategory(), rsc->GetCategoryClass(), rsc->GetDeviceID()); - - return; -} - -void CResourceDB::UpdateByRelease(CResource *resource, const int device_id, const int consumer_id) -{ - UpdateBWbyRelease(resource); - - if (resource->IsVideoDecoder()) - RemoveActiveVideoDecoder(device_id, resource->GetCategoryClass()); - - if (resource->IsJpegDecoder()) - RemoveActiveJpegDecoder(device_id); - - RemoveResourceHasZoneId(resource->GetDeviceID()); -} - -void CResourceDB::UpdateBWbyAllocation(const unsigned int bandwidth, CResource *rsc) -{ - CBandwidth *bw = CBandwidth::GetInstance(); - bw->Decrease(bandwidth, rsc->GetCurCategory(), rsc->GetCategoryClass(), rsc->GetDeviceID()); - - //SERVER_INFO("bw updated avail(%d)/max(%d)", bw->GetAvail(), bw->GetMax()); -} - -void CResourceDB::UpdateByAllocation(CResource *resource, const int device_id, const int consumer_id) -{ - unsigned int bw = resource->GetBW(); - - if (bw > 0) { - UpdateBWbyAllocation(bw, resource); - CBandwidth::GetInstance()->AddConsumer(device_id, consumer_id, resource->GetCurCategory(), resource->GetCategoryClass()); - } - - if (resource->IsVideoDecoder()) - AddActiveVideoDecoder(device_id, consumer_id, resource->GetCategoryClass()); - - if (resource->IsScaler()) - SetVirtualScalerId(resource); - - if (resource->IsJpegDecoder()) - AddActiveJpegDecoder(device_id, consumer_id); - - if (resource->GetZoneId() > 0) - InsertResourceHasZoneId(resource); -} - -void CResourceDB::SetVirtualScalerId(CResource *resource) -{ - int scaler_id = GetVirtualScalerId(resource); - - SERVER_INFO("map scaler (%d:%d)", scaler_id, resource->GetDeviceID()); - - resource->SetVirtualDeviceId(scaler_id); - InsertVirtualScaler(scaler_id, resource); -} - -void CResourceDB::PrintVirtualScalerMap(void) -{ - for (auto &it : m_scaler_map) { - if (it.second == nullptr) { - //SERVER_INFO("[%d : %d (%s)]", it.first, 0, "null"); - continue; - } - //SERVER_INFO("[%d : %d (%s)/(%d)]", it.first, it.second->GetDeviceID(), it.second->GetName().c_str(), it.second->GetVirtualDeviceId()); - } -} - -int CResourceDB::GetVirtualScalerId(CResource *resource) -{ - CResource *rsc = nullptr; - - for (auto &it : m_scaler_map) { - rsc = it.second; - if (rsc == nullptr) - continue; - if (rsc->GetDeviceID() == resource->GetDeviceID()) - return it.first; - } - - return resource->GetDedicatedVirtualDeviceId(); -} - -void CResourceDB::AddActiveVideoDecoder(const int device_id, const int consumer_id, const int category_class) -{ - m_active_vdecs.insert(std::pair(device_id, consumer_id)); - - if (category_class == RMS_CATEGORY_CLASS_N_DECODING) - m_active_nvdecs.insert(std::pair(device_id, consumer_id)); -} - -void CResourceDB::RemoveActiveVideoDecoder(const int device_id, const int category_class) -{ - m_active_vdecs.erase(device_id); - - if (category_class == RMS_CATEGORY_CLASS_N_DECODING) - m_active_nvdecs.erase(device_id); -} - -void CResourceDB::AddActiveJpegDecoder(const int device_id, const int consumer_id) -{ - m_active_jdecs.insert(std::pair(device_id, consumer_id)); -} - -void CResourceDB::RemoveActiveJpegDecoder(const int device_id) -{ - m_active_jdecs.erase(device_id); -} - -int CResourceDB::GetActiveDecoderNum(void) -{ - int num = 0; - - num += m_active_vdecs.size(); - num += m_active_jdecs.size(); - - return num; -} - -void CResourceDB::PrintVideoDecoderConsumers(void) -{ - for (auto const &it : m_active_vdecs) { - SERVER_INFO("dev(%d) by (%d)", it.first, it.second); - } -} - -bool CResourceDB::HasAvailableDecoder(void) -{ - int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; - int active_vdecs = m_active_vdecs.size(); - int active_ndecs = m_active_nvdecs.size(); - - SERVER_INFO("active(%d) / n_dec(%d) / max(%d / %d)", active_vdecs, active_ndecs, max_vdecs, m_max_vdecs); - - if (active_ndecs > 0) - active_vdecs = active_vdecs + (1 - active_ndecs); - - if (active_vdecs >= max_vdecs) - PrintVideoDecoderConsumers(); - - return (active_vdecs < max_vdecs); -} - -bool CResourceDB::HasAvailableDecoderNDecoding(void) -{ - int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; - int active_vdecs = m_active_vdecs.size(); - int active_ndecs = m_active_nvdecs.size(); - - SERVER_INFO("active(%d) / n_dec(%d) / max(%d %d)", active_vdecs, active_ndecs, max_vdecs, m_max_vdecs); - - if (active_ndecs > 0) { - active_vdecs = active_vdecs + (1 - active_ndecs); - return true; - } - - if (active_vdecs >= max_vdecs) - PrintVideoDecoderConsumers(); - - return (active_vdecs < max_vdecs); -} - -bool CResourceDB::HasAvailableDecoder(std::multimap retirables) -{ - int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; - std::map retirables_vdecs; - - SERVER_INFO("max(%d %d)", max_vdecs, m_max_vdecs); - - for (auto &it : retirables) { - CResource *rsc = FindResource(it.first); - if (!rsc) - continue; - - if (rsc->IsVideoDecoder()) - retirables_vdecs.insert(std::pair(it.first, it.second)); - } - - int active_vdecs = m_active_vdecs.size(); - int active_ndecs = m_active_nvdecs.size(); - int retirable_vdecs = retirables_vdecs.size(); - int retirable_ndecs = CountNDecoders(retirables_vdecs); - - int remain = 0; - - if ((active_ndecs - retirable_ndecs) > 0) - remain = (active_vdecs - retirable_vdecs) + (1 - (active_ndecs - retirable_ndecs)); - else - remain = active_vdecs - retirable_vdecs; - - SERVER_INFO("remain(%d)/max(%d), av(%d)/an(%d)/rv(%d)/rn(%d)", remain, max_vdecs, active_vdecs, active_ndecs, retirable_vdecs, retirable_ndecs); - - if (remain >= max_vdecs) - PrintVideoDecoderConsumers(); - - return (remain < max_vdecs); -} - -bool CResourceDB::HasAvailableDecoderNDecoding(std::multimap retirables) -{ - int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; - std::map retirables_vdecs; - - SERVER_INFO("max(%d %d)", max_vdecs, m_max_vdecs); - - for (auto &it : retirables) { - CResource *rsc = FindResource(it.first); - if (!rsc) - continue; - - if (rsc->IsVideoDecoder()) - retirables_vdecs.insert(std::pair(it.first, it.second)); - } - - int active_vdecs = m_active_vdecs.size(); - int active_ndecs = m_active_nvdecs.size(); - int retirable_vdecs = retirables_vdecs.size(); - int retirable_ndecs = CountNDecoders(retirables_vdecs); - - int remain = 0; - - if ((active_ndecs - retirable_ndecs) > 0) - remain = (active_vdecs - retirable_vdecs) + (1 - (active_ndecs - retirable_ndecs)); - else - remain = active_vdecs - retirable_vdecs; - - SERVER_INFO("remain(%d)/max(%d), av(%d)/an(%d)/rv(%d)/rn(%d)", remain, max_vdecs, active_vdecs, active_ndecs, retirable_vdecs, retirable_ndecs); - - if (active_ndecs > 0 && retirable_ndecs > 0) - return true; - - if (remain >= max_vdecs) - PrintVideoDecoderConsumers(); - - return (remain < max_vdecs); -} - -int CResourceDB::CountNDecoders(std::map retirables_vdecs) -{ - int ndecs = 0; - for (auto &it_rsc : retirables_vdecs) { - auto it_ndec = m_active_nvdecs.find(it_rsc.first); - - if (it_ndec != m_active_nvdecs.end()) - ndecs++; - } - - SERVER_INFO("ndecs(%d) in retirables(%zu)", ndecs, retirables_vdecs.size()); - return ndecs; -} - -void CResourceDB::Update(resource_update_type_e type, const int device_id, const int consumer_id) -{ - CResource *resource = FindResource(device_id); - - if (!resource) - return; - - switch (type) { - case UPDATED_BY_ALLOC: - SERVER_WARN("UPDATED_BY_ALLOC"); - UpdateByAllocation(resource, device_id, consumer_id); - break; - case UPDATED_BY_RELEASE: - SERVER_WARN("UPDATED_BY_RELEASE"); - UpdateByRelease(resource, device_id, consumer_id); - break; - default: - SERVER_ERR("unexpected update type (%d)", type); - break; - } - - NotifyResourceStateUpdatedAsync(resource, consumer_id); -} - -void CResourceDB::AddReclaimResources(consumer_reclaim_s *consumers) -{ - for (int i = 0; i < consumers->ret_quantity; i++) { - for (int j = 0; j < consumers->consumer_info[i].n_conflicted; j++) { - SERVER_INFO("add reclaim rsc (%d)", consumers->consumer_info[i].conflicted_resources[j].device_id); - m_reclaim_rscs.insert(consumers->consumer_info[i].conflicted_resources[j].device_id); - } - } -} - -void CResourceDB::ClearReclaimResources(void) -{ - m_reclaim_rscs.clear(); -} - -gboolean CResourceDB::NotifyResourceStateUpdated(gpointer data) -{ - if (!data) { - SERVER_ERR("invalid data"); - return G_SOURCE_REMOVE; - } - - CResourceState *state = (CResourceState*) data; - - GError *error = NULL; - GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - - if (!connection) { - SERVER_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); - goto out; - } - - SERVER_INFO("notify state changed (device id %d( type %d) : state %d)", state->GetDeviceId(), state->GetCategoryType(), state->GetState()); - - if (!g_dbus_connection_emit_signal(connection, - NULL, - RM_DBUS_OBJ_PATH, - RM_DBUS_INTERFACE_NAME, - "RscStateChanged", - g_variant_new("(iiiis)", state->GetDeviceId(), state->GetCategoryType(), state->GetState(), state->GetConsumerId(), state->GetAppId().c_str()), - &error)) - SERVER_ERR("failed to send state changed (%d:%s)", state->GetDeviceId(), (error) ? error->message : "unknown"); - -out: - if (error) - g_error_free(error); - - delete state; - return G_SOURCE_REMOVE; -} - -void CResourceDB::NotifyResourceStateUpdatedAsync(CResource *resource, int consumer_id) -{ - int device_id = resource->GetDeviceID(); - CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(consumer_id); - - if (!consumer) { - SERVER_WARN("Consumer %d is not found", consumer_id); - return; - } - - std::string app_id = consumer->GetAppID(); - - if (app_id.empty()) - app_id = consumer->GetCmdName(); - - SERVER_INFO("device id (%d) consumer id (%d)", device_id, consumer_id); - - if (m_reclaim_rscs.find(device_id) != m_reclaim_rscs.end()) { - SERVER_DBG("skip to notify state updated (%d)", device_id); - return; - } - - CResourceState *state = new CResourceState(resource->GetDeviceID(), resource->GetCategoryType(), consumer_id, resource->GetState(), app_id); - g_idle_add(&CResourceDB::NotifyResourceStateUpdated, state); -} - -CResource *CResourceDB::FindMainResource(rms_rsc_category_e category_id) -{ - CResourceCategory *category = FindResourceCategory(category_id); - if (!category) { - SERVER_ERR("category(%d) not found", category_id); - return NULL; - } - - return category->FindMainResource(); -} - -void CResourceDB::FindMainResources(IN std::map *resource_map) -{ - rms_rsc_category_e categories[5] = {RMS_CATEGORY_VIDEO_DECODER, - RMS_CATEGORY_VIDEO_DECODER_UHD, - RMS_CATEGORY_SCALER, - RMS_CATEGORY_AUDIO_DECODER, - RMS_CATEGORY_AUDIO_MAIN_OUT}; - CResource *resource = NULL; - - for (int i = 0; i < 5; i++) { - resource = FindMainResource(categories[i]); - if (!resource) { - SERVER_INFO("no main resource for (%d)", categories[i]); - continue; - } - - resource_map->insert(std::pair(resource->GetDeviceID(), resource)); - } -} - -void CResourceDB::FindActiveVideoDecoders(IN std::map *resource_map) -{ - CResource *rsc = nullptr; - for (auto const &it : m_active_vdecs) { - rsc = FindResource(it.first); - if (!rsc) - continue; - resource_map->insert(std::pair(it.first, rsc)); - } -} - -void CResourceDB::GetScalerList(std::map *scalers) -{ - CResource *rsc = nullptr; - for (auto &it : m_deviceid_to_rsc) { - rsc = it.second; - if (!rsc->IsScaler()) - continue; - - scalers->insert(std::pair(rsc->GetDeviceID(), rsc)); - } -} - -void CResourceDB::InitScalerTable(void) -{ - CResource *rsc = nullptr; - int sub_scaler_count = 0; - int vid = 0; - - std::map scalers; - GetScalerList(&scalers); - - for (auto &it : scalers) { - rsc = it.second; - - if (!rsc->IsMainDevice()) - sub_scaler_count++; - - vid = (rsc->IsMainDevice()) ? RI_VIRTUAL_ID_SCALER : (RI_VIRTUAL_ID_SCALER + sub_scaler_count); - rsc->SetDedicatedVirtualDeviceId(vid); - rsc->SetVirtualDeviceId(vid); - //SERVER_INFO("insert scaler (%d:%d)", vid, rsc->GetDeviceID()); - m_scaler_map.insert(std::pair(vid, rsc)); - } -} - -int CResourceDB::FindRealDeviceId(int virtual_id) -{ - auto it = m_scaler_map.find(virtual_id); - - if (it == m_scaler_map.end()) - return virtual_id; - - CResource *rsc = it->second; - - return (rsc == nullptr) ? virtual_id : rsc->GetDeviceID(); -} - -CResource *CResourceDB::FindScaler(int virtual_id) -{ - auto it = m_scaler_map.find(virtual_id); - if (it == m_scaler_map.end()) - return nullptr; - - return it->second; -} - -int CResourceDB::ToScalerId(int device_id) -{ - const int SCALER_ID_MAIN = 0; - const int SCALER_ID_SUB = 1; - const int SCALER_ID_SUB2 = 2; - const int SCALER_ID_SUB3 = 3; - const int SCALER_ID_UNKNOWN = 99; - int source_id = SCALER_ID_UNKNOWN; - - switch (device_id) { - case RMS_DEVICE_SCALER: - source_id = SCALER_ID_MAIN; - break; - case RMS_DEVICE_SCALER_SUB: - source_id = SCALER_ID_SUB; - break; - case RMS_DEVICE_SCALER_SUB2: - source_id = SCALER_ID_SUB2; - break; - case RMS_DEVICE_SCALER_SUB3: - source_id = SCALER_ID_SUB3; - break; - default: - SERVER_ERR("unexpected device_id(%d)", device_id); - break; - } - - return source_id; -} - -void CResourceDB::UpdateVirtualScalerIds(void) -{ - std::map scaler_map; - for (auto &it : m_scaler_map) { - if (it.second == nullptr) { - SERVER_INFO("[%d : %d (%s)]", it.first, 0, "null"); - continue; - } - - scaler_map.insert(std::pair(it.first, ToScalerId(it.second->GetDeviceID()))); - SERVER_INFO("[%d : %d (%s)/(%d)]", it.first, it.second->GetDeviceID(), it.second->GetName().c_str(), it.second->GetVirtualDeviceId()); - } - - CVideoController::GetInstance()->UpdateVirtualScalerIds(scaler_map); -} - -void CResourceDB::InsertVirtualScaler(int virtual_id, CResource *resource) -{ - m_scaler_map.erase(virtual_id); - m_scaler_map.insert(std::pair(virtual_id, resource)); - PrintVirtualScalerMap(); -} - -int CResourceDB::SwapScaler(int id_a, int id_b) -{ - CResource *rsc_a = FindScaler(id_a); - CResource *rsc_b = FindScaler(id_b); - - SERVER_INFO("scaler swap (%d <-> %d)", id_a, id_b); - - if (!rsc_a || !rsc_b) { - SERVER_ERR("invalid scaler id_a(%d)/id_b(%d)", id_a, id_b); - return -1; - } - - std::set consumers_a = rsc_a->GetConsumers(); - std::set consumers_b = rsc_b->GetConsumers(); - - int zone_a = rsc_a->GetZoneId(); - int zone_b = rsc_b->GetZoneId(); - - rsc_a->SetZoneId(zone_b); - rsc_b->SetZoneId(zone_a); - - rms_resource_internal_state_e state_a = (rms_resource_internal_state_e) rsc_a->GetState(); - rms_resource_internal_state_e state_b = (rms_resource_internal_state_e) rsc_b->GetState(); - rsc_a->ChangeState(state_b); - rsc_b->ChangeState(state_a); - - UpdateConsumerInfoOfResource(rsc_a, consumers_b, id_b); - UpdateConsumerInfoOfResource(rsc_b, consumers_a, id_a); - - // update resource info of each consumer - SwapResource(consumers_a, rsc_a->GetDeviceID(), rsc_b->GetDeviceID()); - SwapResource(consumers_b, rsc_b->GetDeviceID(), rsc_a->GetDeviceID()); - - // update memcluster owners - CDependencyController::getInstance()->SwapConsumers(rsc_a->GetDeviceID(), consumers_a, rsc_b->GetDeviceID(), consumers_b); - - // update virtual scaler table - InsertVirtualScaler(id_a, rsc_b); - InsertVirtualScaler(id_b, rsc_a); - return 0; -} - -void CResourceDB::UpdateConsumerInfoOfResource(CResource *resource, std::set new_consumers, int new_virtual_id) -{ - resource->ResetConsumer(new_consumers); - resource->SetVirtualDeviceId(new_virtual_id); -} - -void CResourceDB::SwapResource(std::set consumers, int cur_device_id, int new_device_id) -{ - CConsumer *consumer; - for (auto &it : consumers) { - consumer = CConsumerContainer::getInstance()->findConsumer(it); - if (!consumer) { - SERVER_ERR("invalid consumer (%d)", it); - continue; - } - - SERVER_INFO("swap resource (%d) :(%d>%d)", it, cur_device_id, new_device_id); - - if (consumer->IsUsingResource(new_device_id)) { - SERVER_INFO("no need to swap (%d:%d)", it, new_device_id); - continue; - } - consumer->ReleaseResource(cur_device_id); - consumer->AddResource(new_device_id); - } -} - -void CResourceDB::InsertResourceHasZoneId(CResource *rsc) -{ - int device_id = rsc->GetDeviceID(); - auto it = m_rscs_has_zone_id.find(device_id); - - if (it != m_rscs_has_zone_id.end()) - return; - - m_rscs_has_zone_id.insert(std::pair(device_id, rsc)); - SERVER_INFO("inserted (%d:%d:%zu)", device_id, rsc->GetZoneId(), m_rscs_has_zone_id.size()); -} - -void CResourceDB::RemoveResourceHasZoneId(int device_id) -{ - if (m_rscs_has_zone_id.empty()) - return; - - auto it = m_rscs_has_zone_id.find(device_id); - if (it != m_rscs_has_zone_id.end()) - return; - - m_rscs_has_zone_id.erase(device_id); - SERVER_INFO("removed (%d:%zu)", device_id, m_rscs_has_zone_id.size()); -} - -void CResourceDB::ResetZoneIds(void) -{ - CResource *rsc = nullptr; - SERVER_INFO("Reset zone ids"); - - for (auto &it : m_rscs_has_zone_id) { - rsc = it.second; - if (!rsc) - continue; - rsc->SetZoneId(-1); - } - m_rscs_has_zone_id.clear(); -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CResourceDB *CResourceDB::m_instance = NULL; + +CResourceDB *CResourceDB::getInstance(void) +{ + if (!m_instance) { + m_instance = new(std::nothrow) CResourceDB; + assert(m_instance); + } + + return m_instance; +} + +CResourceCategory *CResourceDB::FindResourceCategory(IN rms_rsc_category_e category_id) +{ + std::map::iterator it = m_resourceCategoryMap.find(category_id); + + if (it == m_resourceCategoryMap.end()) + return NULL; + + return (*it).second; +} + +CResource *CResourceDB::FindResource(IN const int device_id) +{ + std::map::iterator it = m_deviceid_to_rsc.find(device_id); + + if (it == m_deviceid_to_rsc.end()) { + SERVER_ERR("no device id(%d) in DB", device_id); + return NULL; + } + + return (*it).second; +} + +CVirtualResource *CResourceDB::FindVirtualResource(const int vid) +{ + auto it = m_v_deviceid_to_rsc.find(vid); + + return (it == m_v_deviceid_to_rsc.end()) ? nullptr : it->second; +} + +void CResourceDB::AddVirtualDeviceID(IN CVirtualResource *vresource) +{ + int vrsc_id = vresource->GetVResourceID(); + + std::map::iterator it = m_v_deviceid_to_rsc.find(vrsc_id); + + if (it != m_v_deviceid_to_rsc.end()) + return; + + m_v_deviceid_to_rsc.insert(std::pair(vrsc_id, vresource)); +} + +void CResourceDB::AddDeviceID(IN int device_id, IN CResource *resource) +{ + std::map::iterator it = m_deviceid_to_rsc.find(device_id); + + if (it != m_deviceid_to_rsc.end()) + return; + + m_deviceid_to_rsc.insert(std::pair(device_id, resource)); +} + +void CResourceDB::AddDeviceName(IN const char *device_name, IN CResource *resource) +{ + auto it = m_devicename_to_rsc.find(std::string(device_name)); + + if (it != m_devicename_to_rsc.end()) { + SERVER_DBG("already registered device name(%s) in DB", device_name); + return; + } + + m_devicename_to_rsc.insert(std::pair(std::string(device_name), resource)); +} + +void CResourceDB::AddResourceCategory(IN rms_rsc_category_e category_id, IN CResourceCategory *resource_category) +{ + std::map::iterator it = m_resourceCategoryMap.find(category_id); + + if (it != m_resourceCategoryMap.end()) + return; + + m_resourceCategoryMap.insert(std::pair(category_id, resource_category)); +} + +CResource *CResourceDB::FindResource(const char *device_name) +{ + auto it = m_devicename_to_rsc.find(std::string(device_name)); + + return (it == m_devicename_to_rsc.end()) ? NULL : it->second; +} + +void CResourceDB::AddVirtualResource(IN CVirtualResource *vrsc, + IN rms_rsc_category_e resource_category_id, + IN const char *name, + IN const char *path, + IN std::set mem_cluster_info, + IN unsigned int device_id_unique, + IN int is_main_device, + IN const char *audio_codec, + IN int sharable_count, + IN int mixing_count, + IN CResourceObserver *observer) +{ + assert(name); + assert(path); + + CResource *rsc = FindResource(name); + + if (!rsc) { + rsc = new CResource(device_id_unique, resource_category_id, name, path, mem_cluster_info, is_main_device, audio_codec, sharable_count); + + AddDeviceName(name, rsc); + AddDeviceID(device_id_unique, rsc); + + rsc->RegisterObserver(this); + rsc->RegisterObserver(observer); + } + + vrsc->SetResource(rsc); + + CAudioCodecCollection::getInstance()->registerAudioCodec(audio_codec, mixing_count); + + if (rsc->GetDefaultBW() == 0) + rsc->SetDefaultBW(vrsc->GetBW()); + + AddVirtualDeviceID(vrsc); +} + +void CResourceDB::UpdateBWbyRelease(CResource *rsc) +{ + if (!rsc) + return; + + if (rsc->GetBW() == 0) + return; + + CBandwidth *bw = CBandwidth::GetInstance(); + bw->RemoveConsumer(rsc->GetDeviceID(), rsc->GetCurCategory(), rsc->GetCategoryClass()); + bw->Increase(rsc->GetBW(), rsc->GetCurCategory(), rsc->GetCategoryClass(), rsc->GetDeviceID()); + + return; +} + +void CResourceDB::UpdateByRelease(CResource *resource, const int device_id, const int consumer_id) +{ + UpdateBWbyRelease(resource); + + if (resource->IsVideoDecoder()) + RemoveActiveVideoDecoder(device_id, resource->GetCategoryClass()); + + if (resource->IsJpegDecoder()) + RemoveActiveJpegDecoder(device_id); + + RemoveResourceHasZoneId(resource->GetDeviceID()); +} + +void CResourceDB::UpdateBWbyAllocation(const unsigned int bandwidth, CResource *rsc) +{ + CBandwidth *bw = CBandwidth::GetInstance(); + bw->Decrease(bandwidth, rsc->GetCurCategory(), rsc->GetCategoryClass(), rsc->GetDeviceID()); + + //SERVER_INFO("bw updated avail(%d)/max(%d)", bw->GetAvail(), bw->GetMax()); +} + +void CResourceDB::UpdateByAllocation(CResource *resource, const int device_id, const int consumer_id) +{ + unsigned int bw = resource->GetBW(); + + if (bw > 0) { + UpdateBWbyAllocation(bw, resource); + CBandwidth::GetInstance()->AddConsumer(device_id, consumer_id, resource->GetCurCategory(), resource->GetCategoryClass()); + } + + if (resource->IsVideoDecoder()) + AddActiveVideoDecoder(device_id, consumer_id, resource->GetCategoryClass()); + + if (resource->IsScaler()) + SetVirtualScalerId(resource); + + if (resource->IsJpegDecoder()) + AddActiveJpegDecoder(device_id, consumer_id); + + if (resource->GetZoneId() > 0) + InsertResourceHasZoneId(resource); +} + +void CResourceDB::SetVirtualScalerId(CResource *resource) +{ + int scaler_id = GetVirtualScalerId(resource); + + SERVER_INFO("map scaler (%d:%d)", scaler_id, resource->GetDeviceID()); + + resource->SetVirtualDeviceId(scaler_id); + InsertVirtualScaler(scaler_id, resource); +} + +void CResourceDB::PrintVirtualScalerMap(void) +{ + for (auto &it : m_scaler_map) { + if (it.second == nullptr) { + //SERVER_INFO("[%d : %d (%s)]", it.first, 0, "null"); + continue; + } + //SERVER_INFO("[%d : %d (%s)/(%d)]", it.first, it.second->GetDeviceID(), it.second->GetName().c_str(), it.second->GetVirtualDeviceId()); + } +} + +int CResourceDB::GetVirtualScalerId(CResource *resource) +{ + CResource *rsc = nullptr; + + for (auto &it : m_scaler_map) { + rsc = it.second; + if (rsc == nullptr) + continue; + if (rsc->GetDeviceID() == resource->GetDeviceID()) + return it.first; + } + + return resource->GetDedicatedVirtualDeviceId(); +} + +void CResourceDB::AddActiveVideoDecoder(const int device_id, const int consumer_id, const int category_class) +{ + m_active_vdecs.insert(std::pair(device_id, consumer_id)); + + if (category_class == RMS_CATEGORY_CLASS_N_DECODING) + m_active_nvdecs.insert(std::pair(device_id, consumer_id)); +} + +void CResourceDB::RemoveActiveVideoDecoder(const int device_id, const int category_class) +{ + m_active_vdecs.erase(device_id); + + if (category_class == RMS_CATEGORY_CLASS_N_DECODING) + m_active_nvdecs.erase(device_id); +} + +void CResourceDB::AddActiveJpegDecoder(const int device_id, const int consumer_id) +{ + m_active_jdecs.insert(std::pair(device_id, consumer_id)); +} + +void CResourceDB::RemoveActiveJpegDecoder(const int device_id) +{ + m_active_jdecs.erase(device_id); +} + +int CResourceDB::GetActiveDecoderNum(void) +{ + int num = 0; + + num += m_active_vdecs.size(); + num += m_active_jdecs.size(); + + return num; +} + +void CResourceDB::PrintVideoDecoderConsumers(void) +{ + for (auto const &it : m_active_vdecs) { + SERVER_INFO("dev(%d) by (%d)", it.first, it.second); + } +} + +bool CResourceDB::HasAvailableDecoder(void) +{ + int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; + int active_vdecs = m_active_vdecs.size(); + int active_ndecs = m_active_nvdecs.size(); + + SERVER_INFO("active(%d) / n_dec(%d) / max(%d / %d)", active_vdecs, active_ndecs, max_vdecs, m_max_vdecs); + + if (active_ndecs > 0) + active_vdecs = active_vdecs + (1 - active_ndecs); + + if (active_vdecs >= max_vdecs) + PrintVideoDecoderConsumers(); + + return (active_vdecs < max_vdecs); +} + +bool CResourceDB::HasAvailableDecoderNDecoding(void) +{ + int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; + int active_vdecs = m_active_vdecs.size(); + int active_ndecs = m_active_nvdecs.size(); + + SERVER_INFO("active(%d) / n_dec(%d) / max(%d %d)", active_vdecs, active_ndecs, max_vdecs, m_max_vdecs); + + if (active_ndecs > 0) { + active_vdecs = active_vdecs + (1 - active_ndecs); + return true; + } + + if (active_vdecs >= max_vdecs) + PrintVideoDecoderConsumers(); + + return (active_vdecs < max_vdecs); +} + +bool CResourceDB::HasAvailableDecoder(std::multimap retirables) +{ + int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; + std::map retirables_vdecs; + + SERVER_INFO("max(%d %d)", max_vdecs, m_max_vdecs); + + for (auto &it : retirables) { + CResource *rsc = FindResource(it.first); + if (!rsc) + continue; + + if (rsc->IsVideoDecoder()) + retirables_vdecs.insert(std::pair(it.first, it.second)); + } + + int active_vdecs = m_active_vdecs.size(); + int active_ndecs = m_active_nvdecs.size(); + int retirable_vdecs = retirables_vdecs.size(); + int retirable_ndecs = CountNDecoders(retirables_vdecs); + + int remain = 0; + + if ((active_ndecs - retirable_ndecs) > 0) + remain = (active_vdecs - retirable_vdecs) + (1 - (active_ndecs - retirable_ndecs)); + else + remain = active_vdecs - retirable_vdecs; + + SERVER_INFO("remain(%d)/max(%d), av(%d)/an(%d)/rv(%d)/rn(%d)", remain, max_vdecs, active_vdecs, active_ndecs, retirable_vdecs, retirable_ndecs); + + if (remain >= max_vdecs) + PrintVideoDecoderConsumers(); + + return (remain < max_vdecs); +} + +bool CResourceDB::HasAvailableDecoderNDecoding(std::multimap retirables) +{ + int max_vdecs = (m_max_vdecs > 1) ? m_max_vdecs : 1; + std::map retirables_vdecs; + + SERVER_INFO("max(%d %d)", max_vdecs, m_max_vdecs); + + for (auto &it : retirables) { + CResource *rsc = FindResource(it.first); + if (!rsc) + continue; + + if (rsc->IsVideoDecoder()) + retirables_vdecs.insert(std::pair(it.first, it.second)); + } + + int active_vdecs = m_active_vdecs.size(); + int active_ndecs = m_active_nvdecs.size(); + int retirable_vdecs = retirables_vdecs.size(); + int retirable_ndecs = CountNDecoders(retirables_vdecs); + + int remain = 0; + + if ((active_ndecs - retirable_ndecs) > 0) + remain = (active_vdecs - retirable_vdecs) + (1 - (active_ndecs - retirable_ndecs)); + else + remain = active_vdecs - retirable_vdecs; + + SERVER_INFO("remain(%d)/max(%d), av(%d)/an(%d)/rv(%d)/rn(%d)", remain, max_vdecs, active_vdecs, active_ndecs, retirable_vdecs, retirable_ndecs); + + if (active_ndecs > 0 && retirable_ndecs > 0) + return true; + + if (remain >= max_vdecs) + PrintVideoDecoderConsumers(); + + return (remain < max_vdecs); +} + +int CResourceDB::CountNDecoders(std::map retirables_vdecs) +{ + int ndecs = 0; + for (auto &it_rsc : retirables_vdecs) { + auto it_ndec = m_active_nvdecs.find(it_rsc.first); + + if (it_ndec != m_active_nvdecs.end()) + ndecs++; + } + + SERVER_INFO("ndecs(%d) in retirables(%zu)", ndecs, retirables_vdecs.size()); + return ndecs; +} + +void CResourceDB::Update(resource_update_type_e type, const int device_id, const int consumer_id) +{ + CResource *resource = FindResource(device_id); + + if (!resource) + return; + + switch (type) { + case UPDATED_BY_ALLOC: + SERVER_WARN("UPDATED_BY_ALLOC"); + UpdateByAllocation(resource, device_id, consumer_id); + break; + case UPDATED_BY_RELEASE: + SERVER_WARN("UPDATED_BY_RELEASE"); + UpdateByRelease(resource, device_id, consumer_id); + break; + default: + SERVER_ERR("unexpected update type (%d)", type); + break; + } + + NotifyResourceStateUpdatedAsync(resource, consumer_id); +} + +void CResourceDB::AddReclaimResources(consumer_reclaim_s *consumers) +{ + for (int i = 0; i < consumers->ret_quantity; i++) { + for (int j = 0; j < consumers->consumer_info[i].n_conflicted; j++) { + SERVER_INFO("add reclaim rsc (%d)", consumers->consumer_info[i].conflicted_resources[j].device_id); + m_reclaim_rscs.insert(consumers->consumer_info[i].conflicted_resources[j].device_id); + } + } +} + +void CResourceDB::ClearReclaimResources(void) +{ + m_reclaim_rscs.clear(); +} + +gboolean CResourceDB::NotifyResourceStateUpdated(gpointer data) +{ + if (!data) { + SERVER_ERR("invalid data"); + return G_SOURCE_REMOVE; + } + + CResourceState *state = (CResourceState*) data; + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + + if (!connection) { + SERVER_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + goto out; + } + + SERVER_INFO("notify state changed (device id %d( type %d) : state %d)", state->GetDeviceId(), state->GetCategoryType(), state->GetState()); + + if (!g_dbus_connection_emit_signal(connection, + NULL, + RM_DBUS_OBJ_PATH, + RM_DBUS_INTERFACE_NAME, + "RscStateChanged", + g_variant_new("(iiiis)", state->GetDeviceId(), state->GetCategoryType(), state->GetState(), state->GetConsumerId(), state->GetAppId().c_str()), + &error)) + SERVER_ERR("failed to send state changed (%d:%s)", state->GetDeviceId(), (error) ? error->message : "unknown"); + +out: + if (error) + g_error_free(error); + + delete state; + return G_SOURCE_REMOVE; +} + +void CResourceDB::NotifyResourceStateUpdatedAsync(CResource *resource, int consumer_id) +{ + int device_id = resource->GetDeviceID(); + CConsumer *consumer = CConsumerContainer::getInstance()->findConsumer(consumer_id); + + if (!consumer) { + SERVER_WARN("Consumer %d is not found", consumer_id); + return; + } + + std::string app_id = consumer->GetAppID(); + + if (app_id.empty()) + app_id = consumer->GetCmdName(); + + SERVER_INFO("device id (%d) consumer id (%d)", device_id, consumer_id); + + if (m_reclaim_rscs.find(device_id) != m_reclaim_rscs.end()) { + SERVER_DBG("skip to notify state updated (%d)", device_id); + return; + } + + CResourceState *state = new CResourceState(resource->GetDeviceID(), resource->GetCategoryType(), consumer_id, resource->GetState(), app_id); + g_idle_add(&CResourceDB::NotifyResourceStateUpdated, state); +} + +CResource *CResourceDB::FindMainResource(rms_rsc_category_e category_id) +{ + CResourceCategory *category = FindResourceCategory(category_id); + if (!category) { + SERVER_ERR("category(%d) not found", category_id); + return NULL; + } + + return category->FindMainResource(); +} + +void CResourceDB::FindMainResources(IN std::map *resource_map) +{ + rms_rsc_category_e categories[5] = {RMS_CATEGORY_VIDEO_DECODER, + RMS_CATEGORY_VIDEO_DECODER_UHD, + RMS_CATEGORY_SCALER, + RMS_CATEGORY_AUDIO_DECODER, + RMS_CATEGORY_AUDIO_MAIN_OUT}; + CResource *resource = NULL; + + for (int i = 0; i < 5; i++) { + resource = FindMainResource(categories[i]); + if (!resource) { + SERVER_INFO("no main resource for (%d)", categories[i]); + continue; + } + + resource_map->insert(std::pair(resource->GetDeviceID(), resource)); + } +} + +void CResourceDB::FindActiveVideoDecoders(IN std::map *resource_map) +{ + CResource *rsc = nullptr; + for (auto const &it : m_active_vdecs) { + rsc = FindResource(it.first); + if (!rsc) + continue; + resource_map->insert(std::pair(it.first, rsc)); + } +} + +void CResourceDB::GetScalerList(std::map *scalers) +{ + CResource *rsc = nullptr; + for (auto &it : m_deviceid_to_rsc) { + rsc = it.second; + if (!rsc->IsScaler()) + continue; + + scalers->insert(std::pair(rsc->GetDeviceID(), rsc)); + } +} + +void CResourceDB::InitScalerTable(void) +{ + CResource *rsc = nullptr; + int sub_scaler_count = 0; + int vid = 0; + + std::map scalers; + GetScalerList(&scalers); + + for (auto &it : scalers) { + rsc = it.second; + + if (!rsc->IsMainDevice()) + sub_scaler_count++; + + vid = (rsc->IsMainDevice()) ? RI_VIRTUAL_ID_SCALER : (RI_VIRTUAL_ID_SCALER + sub_scaler_count); + rsc->SetDedicatedVirtualDeviceId(vid); + rsc->SetVirtualDeviceId(vid); + //SERVER_INFO("insert scaler (%d:%d)", vid, rsc->GetDeviceID()); + m_scaler_map.insert(std::pair(vid, rsc)); + } +} + +int CResourceDB::FindRealDeviceId(int virtual_id) +{ + auto it = m_scaler_map.find(virtual_id); + + if (it == m_scaler_map.end()) + return virtual_id; + + CResource *rsc = it->second; + + return (rsc == nullptr) ? virtual_id : rsc->GetDeviceID(); +} + +CResource *CResourceDB::FindScaler(int virtual_id) +{ + auto it = m_scaler_map.find(virtual_id); + if (it == m_scaler_map.end()) + return nullptr; + + return it->second; +} + +int CResourceDB::ToScalerId(int device_id) +{ + const int SCALER_ID_MAIN = 0; + const int SCALER_ID_SUB = 1; + const int SCALER_ID_SUB2 = 2; + const int SCALER_ID_SUB3 = 3; + const int SCALER_ID_UNKNOWN = 99; + int source_id = SCALER_ID_UNKNOWN; + + switch (device_id) { + case RMS_DEVICE_SCALER: + source_id = SCALER_ID_MAIN; + break; + case RMS_DEVICE_SCALER_SUB: + source_id = SCALER_ID_SUB; + break; + case RMS_DEVICE_SCALER_SUB2: + source_id = SCALER_ID_SUB2; + break; + case RMS_DEVICE_SCALER_SUB3: + source_id = SCALER_ID_SUB3; + break; + default: + SERVER_ERR("unexpected device_id(%d)", device_id); + break; + } + + return source_id; +} + +void CResourceDB::UpdateVirtualScalerIds(void) +{ + std::map scaler_map; + for (auto &it : m_scaler_map) { + if (it.second == nullptr) { + SERVER_INFO("[%d : %d (%s)]", it.first, 0, "null"); + continue; + } + + scaler_map.insert(std::pair(it.first, ToScalerId(it.second->GetDeviceID()))); + SERVER_INFO("[%d : %d (%s)/(%d)]", it.first, it.second->GetDeviceID(), it.second->GetName().c_str(), it.second->GetVirtualDeviceId()); + } + + CVideoController::GetInstance()->UpdateVirtualScalerIds(scaler_map); +} + +void CResourceDB::InsertVirtualScaler(int virtual_id, CResource *resource) +{ + m_scaler_map.erase(virtual_id); + m_scaler_map.insert(std::pair(virtual_id, resource)); + PrintVirtualScalerMap(); +} + +int CResourceDB::SwapScaler(int id_a, int id_b) +{ + CResource *rsc_a = FindScaler(id_a); + CResource *rsc_b = FindScaler(id_b); + + SERVER_INFO("scaler swap (%d <-> %d)", id_a, id_b); + + if (!rsc_a || !rsc_b) { + SERVER_ERR("invalid scaler id_a(%d)/id_b(%d)", id_a, id_b); + return -1; + } + + std::set consumers_a = rsc_a->GetConsumers(); + std::set consumers_b = rsc_b->GetConsumers(); + + int zone_a = rsc_a->GetZoneId(); + int zone_b = rsc_b->GetZoneId(); + + rsc_a->SetZoneId(zone_b); + rsc_b->SetZoneId(zone_a); + + rms_resource_internal_state_e state_a = (rms_resource_internal_state_e) rsc_a->GetState(); + rms_resource_internal_state_e state_b = (rms_resource_internal_state_e) rsc_b->GetState(); + rsc_a->ChangeState(state_b); + rsc_b->ChangeState(state_a); + + UpdateConsumerInfoOfResource(rsc_a, consumers_b, id_b); + UpdateConsumerInfoOfResource(rsc_b, consumers_a, id_a); + + // update resource info of each consumer + SwapResource(consumers_a, rsc_a->GetDeviceID(), rsc_b->GetDeviceID()); + SwapResource(consumers_b, rsc_b->GetDeviceID(), rsc_a->GetDeviceID()); + + // update memcluster owners + CDependencyController::getInstance()->SwapConsumers(rsc_a->GetDeviceID(), consumers_a, rsc_b->GetDeviceID(), consumers_b); + + // update virtual scaler table + InsertVirtualScaler(id_a, rsc_b); + InsertVirtualScaler(id_b, rsc_a); + return 0; +} + +void CResourceDB::UpdateConsumerInfoOfResource(CResource *resource, std::set new_consumers, int new_virtual_id) +{ + resource->ResetConsumer(new_consumers); + resource->SetVirtualDeviceId(new_virtual_id); +} + +void CResourceDB::SwapResource(std::set consumers, int cur_device_id, int new_device_id) +{ + CConsumer *consumer; + for (auto &it : consumers) { + consumer = CConsumerContainer::getInstance()->findConsumer(it); + if (!consumer) { + SERVER_ERR("invalid consumer (%d)", it); + continue; + } + + SERVER_INFO("swap resource (%d) :(%d>%d)", it, cur_device_id, new_device_id); + + if (consumer->IsUsingResource(new_device_id)) { + SERVER_INFO("no need to swap (%d:%d)", it, new_device_id); + continue; + } + consumer->ReleaseResource(cur_device_id); + consumer->AddResource(new_device_id); + } +} + +void CResourceDB::InsertResourceHasZoneId(CResource *rsc) +{ + int device_id = rsc->GetDeviceID(); + auto it = m_rscs_has_zone_id.find(device_id); + + if (it != m_rscs_has_zone_id.end()) + return; + + m_rscs_has_zone_id.insert(std::pair(device_id, rsc)); + SERVER_INFO("inserted (%d:%d:%zu)", device_id, rsc->GetZoneId(), m_rscs_has_zone_id.size()); +} + +void CResourceDB::RemoveResourceHasZoneId(int device_id) +{ + if (m_rscs_has_zone_id.empty()) + return; + + auto it = m_rscs_has_zone_id.find(device_id); + if (it != m_rscs_has_zone_id.end()) + return; + + m_rscs_has_zone_id.erase(device_id); + SERVER_INFO("removed (%d:%zu)", device_id, m_rscs_has_zone_id.size()); +} + +void CResourceDB::ResetZoneIds(void) +{ + CResource *rsc = nullptr; + SERVER_INFO("Reset zone ids"); + + for (auto &it : m_rscs_has_zone_id) { + rsc = it.second; + if (!rsc) + continue; + rsc->SetZoneId(-1); + } + m_rscs_has_zone_id.clear(); +} diff --git a/src/manager/CVideoController.cpp b/src/manager/CVideoController.cpp index db9bfc0..47aa96b 100644 --- a/src/manager/CVideoController.cpp +++ b/src/manager/CVideoController.cpp @@ -1,174 +1,174 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include - -#define LWIPC_WM_READY "/tmp/.wm_ready" -#define LWIPC_TIMEOUT_MS 10000 -#define LWIPC_SWAP_DONE "/tmp/.scaler_swap_done" -#define LWIPC_SWAP_DONE_TIMEOUT_MS 3000 -#define LWIPC_SWAP_DONE_TIMEOUT_DBG_MS 4000 -#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0) - -CVideoController *CVideoController::m_instance = nullptr; - -static void registry_handle_global(void *data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version) -{ - void **tizen_video_rsc = (void**)data; - - if (strncmp(interface, "tizen_video_rsc", sizeof("tizen_video_rsc"))) - return; - - SERVER_INFO("%p : %s", tizen_video_rsc, interface); - //*tizen_video_rsc = wl_registry_bind(wl_registry, id, &tizen_video_rsc_interface, 1); -} - -static void registry_handle_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) -{ - -} - -void CVideoController::WaylandDisplayCreate(void) -{ - SERVER_INFO("Create Start"); - - SERVER_INFO("%s is created", LWIPC_WM_READY); - m_wl_display = wl_display_connect(nullptr); - - if (!m_wl_display) { - SERVER_ERR("Failed to connect to the wayland display"); - return; - } - - m_wl_registry = wl_display_get_registry(m_wl_display); - wl_registry_add_listener(m_wl_registry, &m_registry_listener, &m_tizen_video_rsc); - SERVER_INFO("Add listener : %p", &m_tizen_video_rsc); - - wl_display_roundtrip(m_wl_display); - - if (!m_tizen_video_rsc) - SERVER_ERR("Failed to get tizen_video_rsc"); - - SERVER_INFO("Create Done"); -} - -void CVideoController::WaylandDisplayDestroy(void) -{ - if (m_tizen_video_rsc) { - //tizen_video_rsc_destroy(m_tizen_video_rsc); - m_tizen_video_rsc = nullptr; - } - - if (m_wl_registry) { - wl_registry_destroy(m_wl_registry); - m_wl_registry = nullptr; - } - - SERVER_INFO("Display disconnect"); - - if (m_wl_display) { - wl_display_roundtrip(m_wl_display); - wl_display_disconnect(m_wl_display); - m_wl_display = nullptr; - } - - SERVER_INFO("Destroy Done"); -} - -CVideoController::CVideoController(void) : m_wl_display(nullptr), m_wl_registry(nullptr), m_tizen_video_rsc(nullptr), m_waiting_thread(nullptr) -{ - m_registry_listener.global = registry_handle_global; - m_registry_listener.global_remove = registry_handle_global_remove; - WaylandDisplayCreate(); - m_lock_ctr = CLockController::GetInstance(); - - SERVER_INFO("Initialize Done"); -} - -CVideoController::~CVideoController(void) -{ - WaylandDisplayDestroy(); - SERVER_INFO("Finalize Done"); -} - -CVideoController *CVideoController::GetInstance(void) -{ - if (m_instance == nullptr) - { - m_instance = new(std::nothrow) CVideoController(); - assert(m_instance); - } - - return m_instance; -} - -void CVideoController::UpdateVirtualScalerIds(std::map scaler_id_map) -{ - struct wl_array mapping_list; - scaler_id_pair_t *scaler_id_pair = NULL; - - wl_array_init(&mapping_list); - SERVER_ERR("Update virtual scaler ids"); - - for (auto it = scaler_id_map.begin(); it != scaler_id_map.end(); it++) { - scaler_id_pair = (scaler_id_pair_t*)wl_array_add(&mapping_list, sizeof(scaler_id_pair_t)); - scaler_id_pair->virtual_scaler_id = it->first; - scaler_id_pair->scaler_id = it->second; - SERVER_ERR("scaler(%d:%d)", it->first, it->second); - } - - //tizen_video_rsc_map_scaler_id(m_tizen_video_rsc, &mapping_list); - - wl_display_roundtrip(m_wl_display); - wl_array_release(&mapping_list); - - RunWaitingThread(); -} - -gpointer CVideoController::WaitingThread(gpointer data) -{ - assert(data); - CVideoController *ctr = (CVideoController*) data; - - ctr->m_lock_ctr->Unlock(ResourceType::VIDEO_SCALER); - ctr->m_waiting_thread = nullptr; - return 0; -} - -void CVideoController::RunWaitingThread(void) -{ - if (m_waiting_thread) - { - SERVER_ERR("already created"); - return; - } - - m_lock_ctr->Lock(ResourceType::VIDEO_SCALER); - - m_waiting_thread = g_thread_new("waiting_swap_done", WaitingThread, this); - if (m_waiting_thread == nullptr) { - m_lock_ctr->Unlock(ResourceType::VIDEO_SCALER); - SERVER_ERR("failed to create waiting_swap_done thread"); - return; - } - - SERVER_ERR("waiting_swap_done thread created"); -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#define LWIPC_WM_READY "/tmp/.wm_ready" +#define LWIPC_TIMEOUT_MS 10000 +#define LWIPC_SWAP_DONE "/tmp/.scaler_swap_done" +#define LWIPC_SWAP_DONE_TIMEOUT_MS 3000 +#define LWIPC_SWAP_DONE_TIMEOUT_DBG_MS 4000 +#define RMS_IS_DEBUG_IMAGE (access("/etc/debug", F_OK) == 0) + +CVideoController *CVideoController::m_instance = nullptr; + +static void registry_handle_global(void *data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version) +{ + void **tizen_video_rsc = (void**)data; + + if (strncmp(interface, "tizen_video_rsc", sizeof("tizen_video_rsc"))) + return; + + SERVER_INFO("%p : %s", tizen_video_rsc, interface); + //*tizen_video_rsc = wl_registry_bind(wl_registry, id, &tizen_video_rsc_interface, 1); +} + +static void registry_handle_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) +{ + +} + +void CVideoController::WaylandDisplayCreate(void) +{ + SERVER_INFO("Create Start"); + + SERVER_INFO("%s is created", LWIPC_WM_READY); + m_wl_display = wl_display_connect(nullptr); + + if (!m_wl_display) { + SERVER_ERR("Failed to connect to the wayland display"); + return; + } + + m_wl_registry = wl_display_get_registry(m_wl_display); + wl_registry_add_listener(m_wl_registry, &m_registry_listener, &m_tizen_video_rsc); + SERVER_INFO("Add listener : %p", &m_tizen_video_rsc); + + wl_display_roundtrip(m_wl_display); + + if (!m_tizen_video_rsc) + SERVER_ERR("Failed to get tizen_video_rsc"); + + SERVER_INFO("Create Done"); +} + +void CVideoController::WaylandDisplayDestroy(void) +{ + if (m_tizen_video_rsc) { + //tizen_video_rsc_destroy(m_tizen_video_rsc); + m_tizen_video_rsc = nullptr; + } + + if (m_wl_registry) { + wl_registry_destroy(m_wl_registry); + m_wl_registry = nullptr; + } + + SERVER_INFO("Display disconnect"); + + if (m_wl_display) { + wl_display_roundtrip(m_wl_display); + wl_display_disconnect(m_wl_display); + m_wl_display = nullptr; + } + + SERVER_INFO("Destroy Done"); +} + +CVideoController::CVideoController(void) : m_wl_display(nullptr), m_wl_registry(nullptr), m_tizen_video_rsc(nullptr), m_waiting_thread(nullptr) +{ + m_registry_listener.global = registry_handle_global; + m_registry_listener.global_remove = registry_handle_global_remove; + WaylandDisplayCreate(); + m_lock_ctr = CLockController::GetInstance(); + + SERVER_INFO("Initialize Done"); +} + +CVideoController::~CVideoController(void) +{ + WaylandDisplayDestroy(); + SERVER_INFO("Finalize Done"); +} + +CVideoController *CVideoController::GetInstance(void) +{ + if (m_instance == nullptr) + { + m_instance = new(std::nothrow) CVideoController(); + assert(m_instance); + } + + return m_instance; +} + +void CVideoController::UpdateVirtualScalerIds(std::map scaler_id_map) +{ + struct wl_array mapping_list; + scaler_id_pair_t *scaler_id_pair = NULL; + + wl_array_init(&mapping_list); + SERVER_ERR("Update virtual scaler ids"); + + for (auto it = scaler_id_map.begin(); it != scaler_id_map.end(); it++) { + scaler_id_pair = (scaler_id_pair_t*)wl_array_add(&mapping_list, sizeof(scaler_id_pair_t)); + scaler_id_pair->virtual_scaler_id = it->first; + scaler_id_pair->scaler_id = it->second; + SERVER_ERR("scaler(%d:%d)", it->first, it->second); + } + + //tizen_video_rsc_map_scaler_id(m_tizen_video_rsc, &mapping_list); + + wl_display_roundtrip(m_wl_display); + wl_array_release(&mapping_list); + + RunWaitingThread(); +} + +gpointer CVideoController::WaitingThread(gpointer data) +{ + assert(data); + CVideoController *ctr = (CVideoController*) data; + + ctr->m_lock_ctr->Unlock(ResourceType::VIDEO_SCALER); + ctr->m_waiting_thread = nullptr; + return 0; +} + +void CVideoController::RunWaitingThread(void) +{ + if (m_waiting_thread) + { + SERVER_ERR("already created"); + return; + } + + m_lock_ctr->Lock(ResourceType::VIDEO_SCALER); + + m_waiting_thread = g_thread_new("waiting_swap_done", WaitingThread, this); + if (m_waiting_thread == nullptr) { + m_lock_ctr->Unlock(ResourceType::VIDEO_SCALER); + SERVER_ERR("failed to create waiting_swap_done thread"); + return; + } + + SERVER_ERR("waiting_swap_done thread created"); +} diff --git a/src/manager/CVirtualResource.cpp b/src/manager/CVirtualResource.cpp index a9399fe..9f59ab2 100644 --- a/src/manager/CVirtualResource.cpp +++ b/src/manager/CVirtualResource.cpp @@ -1,33 +1,33 @@ -/* - * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -CVirtualResource::CVirtualResource(const int virtual_device_id, const rms_rsc_category_e category_type, unsigned int bw, std::set dependent, bool is_main_device, const char *audio_codec, int category_class) -:m_vir_rsc_id(virtual_device_id), m_category_type(category_type), m_vir_rsc_bw(bw), m_is_main_device(is_main_device), m_category_class(category_class), m_rsc() -{ - m_mem_clusters = dependent; - - if (audio_codec) - m_audio_codec.assign(audio_codec); -} - -void CVirtualResource::SetResource(CResource *resource) -{ - m_rsc = resource; -} +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +CVirtualResource::CVirtualResource(const int virtual_device_id, const rms_rsc_category_e category_type, unsigned int bw, std::set dependent, bool is_main_device, const char *audio_codec, int category_class) +:m_vir_rsc_id(virtual_device_id), m_category_type(category_type), m_vir_rsc_bw(bw), m_is_main_device(is_main_device), m_category_class(category_class), m_rsc() +{ + m_mem_clusters = dependent; + + if (audio_codec) + m_audio_codec.assign(audio_codec); +} + +void CVirtualResource::SetResource(CResource *resource) +{ + m_rsc = resource; +} -- 2.34.1