/****************************************************************************** * * Copyright 2012 Broadcom Corporation * * 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. * ******************************************************************************/ /******************************************************************************* * * Filename: bt_utils.cc * * Description: Miscellaneous helper functions * * ******************************************************************************/ #define LOG_TAG "bt_utils" #include "bt_utils.h" #include <errno.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <sys/resource.h> #include <unistd.h> #include <mutex> #define A2DP_RT_PRIORITY 1 #ifndef OS_GENERIC #include <processgroup/sched_policy.h> #endif #include "bt_types.h" #include "btcore/include/module.h" #include "osi/include/compat.h" #include "osi/include/log.h" #include "osi/include/properties.h" /******************************************************************************* * Type definitions for callback functions ******************************************************************************/ static pthread_once_t g_DoSchedulingGroupOnce[TASK_HIGH_MAX]; static bool g_DoSchedulingGroup[TASK_HIGH_MAX]; static std::mutex gIdxLock; static int g_TaskIdx; static int g_TaskIDs[TASK_HIGH_MAX]; #define INVALID_TASK_ID (-1) static future_t* init(void) { int i; for (i = 0; i < TASK_HIGH_MAX; i++) { g_DoSchedulingGroupOnce[i] = PTHREAD_ONCE_INIT; g_DoSchedulingGroup[i] = true; g_TaskIDs[i] = INVALID_TASK_ID; } return NULL; } static future_t* clean_up(void) { return NULL; } EXPORT_SYMBOL extern const module_t bt_utils_module = {.name = BT_UTILS_MODULE, .init = init, .start_up = NULL, .shut_down = NULL, .clean_up = clean_up, .dependencies = {NULL}}; /***************************************************************************** * * Function check_do_scheduling_group * * Description check if it is ok to change schedule group * * Returns void * ******************************************************************************/ static void check_do_scheduling_group(void) { char buf[PROPERTY_VALUE_MAX]; int len = osi_property_get("debug.sys.noschedgroups", buf, ""); if (len > 0) { int temp; if (sscanf(buf, "%d", &temp) == 1) { g_DoSchedulingGroup[g_TaskIdx] = temp == 0; } } } /***************************************************************************** * * Function raise_priority_a2dp * * Description Raise task priority for A2DP streaming * * Returns void * ******************************************************************************/ void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) { int rc = 0; int tid = gettid(); { std::lock_guard<std::mutex> lock(gIdxLock); g_TaskIdx = high_task; // TODO(armansito): Remove this conditional check once we find a solution // for system/core on non-Android platforms. #if defined(OS_GENERIC) rc = -1; #else // !defined(OS_GENERIC) pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx], check_do_scheduling_group); if (g_DoSchedulingGroup[g_TaskIdx]) { // set_sched_policy does not support tid == 0 rc = set_sched_policy(tid, SP_AUDIO_SYS); } #endif // defined(OS_GENERIC) g_TaskIDs[high_task] = tid; } if (rc) { LOG_WARN(LOG_TAG, "failed to change sched policy, tid %d, err: %d", tid, errno); } // make A2DP threads use RT scheduling policy since they are part of the // audio pipeline { struct sched_param rt_params; rt_params.sched_priority = A2DP_RT_PRIORITY; const int rc = sched_setscheduler(tid, SCHED_FIFO, &rt_params); if (rc != 0) { LOG_ERROR(LOG_TAG, "%s unable to set SCHED_FIFO priority %d for tid %d, error %s", __func__, A2DP_RT_PRIORITY, tid, strerror(errno)); } } }