• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /*******************************************************************************
20  *
21  *  Filename:      bt_utils.cc
22  *
23  *  Description:   Miscellaneous helper functions
24  *
25  *
26  ******************************************************************************/
27 
28 #define LOG_TAG "bt_utils"
29 
30 #include "bt_utils.h"
31 
32 #include <errno.h>
33 #include <pthread.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/resource.h>
37 #include <unistd.h>
38 #include <mutex>
39 
40 #define A2DP_RT_PRIORITY 1
41 #ifdef OS_ANDROID
42 #include <processgroup/sched_policy.h>
43 #endif
44 
45 #include "btcore/include/module.h"
46 #include "osi/include/compat.h"
47 #include "osi/include/log.h"
48 #include "osi/include/properties.h"
49 
50 /*******************************************************************************
51  *  Type definitions for callback functions
52  ******************************************************************************/
53 static pthread_once_t g_DoSchedulingGroupOnce[TASK_HIGH_MAX];
54 static bool g_DoSchedulingGroup[TASK_HIGH_MAX];
55 static std::mutex gIdxLock;
56 static int g_TaskIdx;
57 static int g_TaskIDs[TASK_HIGH_MAX];
58 #define INVALID_TASK_ID (-1)
59 
init(void)60 static future_t* init(void) {
61   int i;
62 
63   for (i = 0; i < TASK_HIGH_MAX; i++) {
64     g_DoSchedulingGroupOnce[i] = PTHREAD_ONCE_INIT;
65     g_DoSchedulingGroup[i] = true;
66     g_TaskIDs[i] = INVALID_TASK_ID;
67   }
68 
69   return NULL;
70 }
71 
clean_up(void)72 static future_t* clean_up(void) {
73   return NULL;
74 }
75 
76 EXPORT_SYMBOL extern const module_t bt_utils_module = {.name = BT_UTILS_MODULE,
77                                                        .init = init,
78                                                        .start_up = NULL,
79                                                        .shut_down = NULL,
80                                                        .clean_up = clean_up,
81                                                        .dependencies = {NULL}};
82 
83 #ifdef OS_ANDROID
84 /*****************************************************************************
85  *
86  * Function        check_do_scheduling_group
87  *
88  * Description     check if it is ok to change schedule group
89  *
90  * Returns         void
91  *
92  ******************************************************************************/
check_do_scheduling_group(void)93 static void check_do_scheduling_group(void) {
94   char buf[PROPERTY_VALUE_MAX];
95   int len = osi_property_get("debug.sys.noschedgroups", buf, "");
96   if (len > 0) {
97     int temp;
98     if (sscanf(buf, "%d", &temp) == 1) {
99       g_DoSchedulingGroup[g_TaskIdx] = temp == 0;
100     }
101   }
102 }
103 #endif
104 
105 /*****************************************************************************
106  *
107  * Function        raise_priority_a2dp
108  *
109  * Description     Raise task priority for A2DP streaming
110  *
111  * Returns         void
112  *
113  ******************************************************************************/
raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task)114 void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) {
115   int rc = 0;
116   int tid = gettid();
117 
118   {
119     std::lock_guard<std::mutex> lock(gIdxLock);
120     g_TaskIdx = high_task;
121 
122 // TODO(armansito): Remove this conditional check once we find a solution
123 // for system/core on non-Android platforms.
124 #ifndef OS_ANDROID
125     rc = -1;
126 #else   // defined(OS_ANDROID)
127     pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx],
128                  check_do_scheduling_group);
129     if (g_DoSchedulingGroup[g_TaskIdx]) {
130       // set_sched_policy does not support tid == 0
131       rc = set_sched_policy(tid, SP_AUDIO_SYS);
132     }
133 #endif  // ifndef(OS_ANDROID)
134 
135     g_TaskIDs[high_task] = tid;
136   }
137 
138   if (rc) {
139     LOG_WARN("failed to change sched policy, tid %d, err: %d", tid, errno);
140   }
141 
142   // make A2DP threads use RT scheduling policy since they are part of the
143   // audio pipeline
144   {
145     struct sched_param rt_params;
146     rt_params.sched_priority = A2DP_RT_PRIORITY;
147 
148     const int rc = sched_setscheduler(tid, SCHED_FIFO, &rt_params);
149     if (rc != 0) {
150       LOG_ERROR("%s unable to set SCHED_FIFO priority %d for tid %d, error %s",
151                 __func__, A2DP_RT_PRIORITY, tid, strerror(errno));
152     }
153   }
154 }
155