system/bt
Revision | feb2d84f4b69392b5f37ae1ec9d53ac728514275 (tree) |
---|---|
Zeit | 2017-04-28 10:27:09 |
Autor | Philip Cuadra <philipcuadra@goog...> |
Commiter | Philip Cuadra |
Revert "Make Bluetooth audio threads use RT scheduling"
This reverts commit eaa42774f393eb3ccaee91a958e8df6a8fb09b91.
http://b/37733903
Test: confirmed switching users does not hang.
Change-Id: Ic54e4ed2dda057e681df225a37a574c221cd8fc3
@@ -929,9 +929,17 @@ static bool btif_av_state_started_handler(btif_sm_event_t event, void* p_data) { | ||
929 | 929 | * see update_audio_focus_state() |
930 | 930 | */ |
931 | 931 | btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda)); |
932 | + | |
933 | + /* increase the a2dp consumer task priority temporarily when start | |
934 | + ** audio playing, to avoid overflow the audio packet queue. */ | |
935 | + adjust_priority_a2dp(true); | |
936 | + | |
932 | 937 | break; |
933 | 938 | |
934 | 939 | case BTIF_SM_EXIT_EVT: |
940 | + /* restore the a2dp consumer task priority when stop audio playing. */ | |
941 | + adjust_priority_a2dp(false); | |
942 | + | |
935 | 943 | break; |
936 | 944 | |
937 | 945 | case BTIF_AV_START_STREAM_REQ_EVT: |
@@ -63,9 +63,6 @@ typedef struct { | ||
63 | 63 | #define DEFAULT_STARTUP_TIMEOUT_MS 8000 |
64 | 64 | #define STRING_VALUE_OF(x) #x |
65 | 65 | |
66 | -// RT priority for HCI thread | |
67 | -static const int BT_HCI_RT_PRIORITY = 1; | |
68 | - | |
69 | 66 | // Abort if there is no response to an HCI command. |
70 | 67 | static const uint32_t COMMAND_PENDING_TIMEOUT_MS = 2000; |
71 | 68 |
@@ -191,9 +188,6 @@ static future_t* hci_module_start_up(void) { | ||
191 | 188 | LOG_ERROR(LOG_TAG, "%s unable to create thread.", __func__); |
192 | 189 | goto error; |
193 | 190 | } |
194 | - if (!thread_set_rt_priority(thread, BT_HCI_RT_PRIORITY)) { | |
195 | - LOG_ERROR(LOG_TAG, "%s unable to make thread RT.", __func__); | |
196 | - } | |
197 | 191 | |
198 | 192 | commands_pending_response = list_new(NULL); |
199 | 193 | if (!commands_pending_response) { |
@@ -65,13 +65,6 @@ void thread_stop(thread_t* thread); | ||
65 | 65 | // Returns true on success. |
66 | 66 | bool thread_set_priority(thread_t* thread, int priority); |
67 | 67 | |
68 | -// Attempts to set |thread| to the real-time SCHED_FIFO |priority|. | |
69 | -// The |thread| has to be running for this call to succeed. | |
70 | -// Priority values are valid in the range sched_get_priority_max(SCHED_FIFO) | |
71 | -// to sched_get_priority_min(SCHED_FIFO). Larger values are higher priority. | |
72 | -// Returns true on success. | |
73 | -bool thread_set_rt_priority(thread_t* thread, int priority); | |
74 | - | |
75 | 68 | // Returns true if the current thread is the same as the one represented by |
76 | 69 | // |thread|. |
77 | 70 | // |thread| may not be NULL. |
@@ -27,7 +27,6 @@ | ||
27 | 27 | #include <fcntl.h> |
28 | 28 | #include <inttypes.h> |
29 | 29 | #include <malloc.h> |
30 | -#include <pthread.h> | |
31 | 30 | #include <signal.h> |
32 | 31 | #include <string.h> |
33 | 32 | #include <time.h> |
@@ -45,9 +44,12 @@ | ||
45 | 44 | #include "osi/include/thread.h" |
46 | 45 | #include "osi/include/wakelock.h" |
47 | 46 | |
48 | -// Callback and timer threads should run at RT priority in order to ensure they | |
49 | -// meet audio deadlines. Use this priority for all audio/timer related thread. | |
50 | -static const int THREAD_RT_PRIORITY = 1; | |
47 | +// Make callbacks run at high thread priority. Some callbacks are used for audio | |
48 | +// related timer tasks as well as re-transmissions etc. Since we at this point | |
49 | +// cannot differentiate what callback we are dealing with, assume high priority | |
50 | +// for now. | |
51 | +// TODO(eisenbach): Determine correct thread priority (from parent?/per alarm?) | |
52 | +static const int CALLBACK_THREAD_PRIORITY_HIGH = -19; | |
51 | 53 | |
52 | 54 | typedef struct { |
53 | 55 | size_t count; |
@@ -312,7 +314,7 @@ static bool lazy_initialize(void) { | ||
312 | 314 | __func__); |
313 | 315 | goto error; |
314 | 316 | } |
315 | - thread_set_rt_priority(default_callback_thread, THREAD_RT_PRIORITY); | |
317 | + thread_set_priority(default_callback_thread, CALLBACK_THREAD_PRIORITY_HIGH); | |
316 | 318 | default_callback_queue = fixed_queue_new(SIZE_MAX); |
317 | 319 | if (default_callback_queue == NULL) { |
318 | 320 | LOG_ERROR(LOG_TAG, "%s unable to create default alarm callbacks queue.", |
@@ -328,7 +330,8 @@ static bool lazy_initialize(void) { | ||
328 | 330 | LOG_ERROR(LOG_TAG, "%s unable to create alarm callback thread.", __func__); |
329 | 331 | goto error; |
330 | 332 | } |
331 | - thread_set_rt_priority(dispatcher_thread, THREAD_RT_PRIORITY); | |
333 | + | |
334 | + thread_set_priority(dispatcher_thread, CALLBACK_THREAD_PRIORITY_HIGH); | |
332 | 335 | thread_post(dispatcher_thread, callback_dispatch, NULL); |
333 | 336 | return true; |
334 | 337 |
@@ -622,18 +625,9 @@ static bool timer_create_internal(const clockid_t clock_id, timer_t* timer) { | ||
622 | 625 | CHECK(timer != NULL); |
623 | 626 | |
624 | 627 | struct sigevent sigevent; |
625 | - // create timer with RT priority thread | |
626 | - pthread_attr_t thread_attr; | |
627 | - pthread_attr_init(&thread_attr); | |
628 | - pthread_attr_setschedpolicy(&thread_attr, SCHED_FIFO); | |
629 | - struct sched_param param; | |
630 | - param.sched_priority = THREAD_RT_PRIORITY; | |
631 | - pthread_attr_setschedparam(&thread_attr, ¶m); | |
632 | - | |
633 | 628 | memset(&sigevent, 0, sizeof(sigevent)); |
634 | 629 | sigevent.sigev_notify = SIGEV_THREAD; |
635 | 630 | sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback; |
636 | - sigevent.sigev_notify_attributes = (void*)(&thread_attr); | |
637 | 631 | if (timer_create(clock_id, &sigevent, timer) == -1) { |
638 | 632 | LOG_ERROR(LOG_TAG, "%s unable to create timer with clock %d: %s", __func__, |
639 | 633 | clock_id, strerror(errno)); |
@@ -159,23 +159,6 @@ bool thread_set_priority(thread_t* thread, int priority) { | ||
159 | 159 | return true; |
160 | 160 | } |
161 | 161 | |
162 | -bool thread_set_rt_priority(thread_t* thread, int priority) { | |
163 | - if (!thread) return false; | |
164 | - | |
165 | - struct sched_param rt_params; | |
166 | - rt_params.sched_priority = priority; | |
167 | - | |
168 | - const int rc = sched_setscheduler(thread->tid, SCHED_FIFO, &rt_params); | |
169 | - if (rc != 0) { | |
170 | - LOG_ERROR(LOG_TAG, | |
171 | - "%s unable to set SCHED_FIFO priority %d for tid %d, error %s", | |
172 | - __func__, priority, thread->tid, strerror(errno)); | |
173 | - return false; | |
174 | - } | |
175 | - | |
176 | - return true; | |
177 | -} | |
178 | - | |
179 | 162 | bool thread_is_self(const thread_t* thread) { |
180 | 163 | CHECK(thread != NULL); |
181 | 164 | return !!pthread_equal(pthread_self(), thread->pthread); |
@@ -36,8 +36,9 @@ | ||
36 | 36 | #include "sdpint.h" |
37 | 37 | #include "smp_int.h" |
38 | 38 | |
39 | -// RT priority for audio-related tasks | |
40 | -#define BTU_TASK_RT_PRIORITY 1 | |
39 | +// Increase BTU task thread priority to avoid pre-emption | |
40 | +// of audio realated tasks. | |
41 | +#define BTU_TASK_THREAD_PRIORITY (-19) | |
41 | 42 | |
42 | 43 | extern fixed_queue_t* btif_msg_queue; |
43 | 44 |
@@ -129,7 +130,7 @@ void BTU_StartUp(void) { | ||
129 | 130 | bt_workqueue_thread = thread_new(BT_WORKQUEUE_NAME); |
130 | 131 | if (bt_workqueue_thread == NULL) goto error_exit; |
131 | 132 | |
132 | - thread_set_rt_priority(bt_workqueue_thread, BTU_TASK_RT_PRIORITY); | |
133 | + thread_set_priority(bt_workqueue_thread, BTU_TASK_THREAD_PRIORITY); | |
133 | 134 | |
134 | 135 | // Continue startup on bt workqueue thread. |
135 | 136 | thread_post(bt_workqueue_thread, btu_task_start_up, NULL); |
@@ -36,5 +36,6 @@ typedef enum { | ||
36 | 36 | ******************************************************************************/ |
37 | 37 | |
38 | 38 | void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task); |
39 | +void adjust_priority_a2dp(int start); | |
39 | 40 | |
40 | 41 | #endif /* BT_UTILS_H */ |
@@ -37,9 +37,12 @@ | ||
37 | 37 | #include <unistd.h> |
38 | 38 | #include <mutex> |
39 | 39 | |
40 | -#define A2DP_RT_PRIORITY 1 | |
41 | -#ifndef OS_GENERIC | |
40 | +#ifdef OS_GENERIC | |
41 | +#define ANDROID_PRIORITY_AUDIO -16 | |
42 | +#define ANDROID_PRIORITY_URGENT_AUDIO -19 | |
43 | +#else | |
42 | 44 | #include <cutils/sched_policy.h> |
45 | +#include <utils/ThreadDefs.h> | |
43 | 46 | #endif |
44 | 47 | |
45 | 48 | #include "bt_types.h" |
@@ -113,6 +116,7 @@ static void check_do_scheduling_group(void) { | ||
113 | 116 | void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) { |
114 | 117 | int rc = 0; |
115 | 118 | int tid = gettid(); |
119 | + int priority = ANDROID_PRIORITY_AUDIO; | |
116 | 120 | |
117 | 121 | { |
118 | 122 | std::lock_guard<std::mutex> lock(gIdxLock); |
@@ -139,17 +143,41 @@ void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) { | ||
139 | 143 | errno); |
140 | 144 | } |
141 | 145 | |
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(LOG_TAG, | |
151 | - "%s unable to set SCHED_FIFO priority %d for tid %d, error %s", | |
152 | - __func__, A2DP_RT_PRIORITY, tid, strerror(errno)); | |
146 | + // always use urgent priority for HCI worker thread until we can adjust | |
147 | + // its prio individually. All other threads can be dynamically adjusted voa | |
148 | + // adjust_priority_a2dp() | |
149 | + | |
150 | + priority = ANDROID_PRIORITY_URGENT_AUDIO; | |
151 | + | |
152 | + if (setpriority(PRIO_PROCESS, tid, priority) < 0) { | |
153 | + LOG_WARN(LOG_TAG, "failed to change priority tid: %d to %d", tid, priority); | |
154 | + } | |
155 | +} | |
156 | + | |
157 | +/***************************************************************************** | |
158 | + * | |
159 | + * Function adjust_priority_a2dp | |
160 | + * | |
161 | + * Description Increase the a2dp consumer task priority temporarily when | |
162 | + * audio starts playing to avoid overflowing the audio packet | |
163 | + * queue. Restore the a2dp consumer task priority when audio | |
164 | + * is not playing. | |
165 | + * | |
166 | + * Returns void | |
167 | + * | |
168 | + ******************************************************************************/ | |
169 | +void adjust_priority_a2dp(int start) { | |
170 | + int priority = start ? ANDROID_PRIORITY_URGENT_AUDIO : ANDROID_PRIORITY_AUDIO; | |
171 | + int tid; | |
172 | + int i; | |
173 | + | |
174 | + for (i = 0; i < TASK_HIGH_MAX; i++) { | |
175 | + tid = g_TaskIDs[i]; | |
176 | + if (tid != INVALID_TASK_ID) { | |
177 | + if (setpriority(PRIO_PROCESS, tid, priority) < 0) { | |
178 | + LOG_WARN(LOG_TAG, "failed to change priority tid: %d to %d", tid, | |
179 | + priority); | |
180 | + } | |
153 | 181 | } |
154 | 182 | } |
155 | 183 | } |