Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7e322cd authored by Philip Cuadra's avatar Philip Cuadra Committed by android-build-merger
Browse files

Make Bluetooth audio threads use RT scheduling

am: 0448438c

Change-Id: Idcea625a9ca29fe5f5b4c0cc81e74e28d3670b04
parents 30cc4fd9 0448438c
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -929,17 +929,9 @@ static bool btif_av_state_started_handler(btif_sm_event_t event, void* p_data) {
       * see update_audio_focus_state()
       */
      btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda));

      /* increase the a2dp consumer task priority temporarily when start
      ** audio playing, to avoid overflow the audio packet queue. */
      adjust_priority_a2dp(true);

      break;

    case BTIF_SM_EXIT_EVT:
      /* restore the a2dp consumer task priority when stop audio playing. */
      adjust_priority_a2dp(false);

      break;

    case BTIF_AV_START_STREAM_REQ_EVT:
+6 −0
Original line number Diff line number Diff line
@@ -63,6 +63,9 @@ typedef struct {
#define DEFAULT_STARTUP_TIMEOUT_MS 8000
#define STRING_VALUE_OF(x) #x

// RT priority for HCI thread
static const int BT_HCI_RT_PRIORITY = 1;

// Abort if there is no response to an HCI command.
static const uint32_t COMMAND_PENDING_TIMEOUT_MS = 2000;

@@ -188,6 +191,9 @@ static future_t* hci_module_start_up(void) {
    LOG_ERROR(LOG_TAG, "%s unable to create thread.", __func__);
    goto error;
  }
  if (!thread_set_rt_priority(thread, BT_HCI_RT_PRIORITY)) {
    LOG_ERROR(LOG_TAG, "%s unable to make thread RT.", __func__);
  }

  commands_pending_response = list_new(NULL);
  if (!commands_pending_response) {
+7 −0
Original line number Diff line number Diff line
@@ -65,6 +65,13 @@ void thread_stop(thread_t* thread);
// Returns true on success.
bool thread_set_priority(thread_t* thread, int priority);

// Attempts to set |thread| to the real-time SCHED_FIFO |priority|.
// The |thread| has to be running for this call to succeed.
// Priority values are valid in the range sched_get_priority_max(SCHED_FIFO)
// to sched_get_priority_min(SCHED_FIFO).  Larger values are higher priority.
// Returns true on success.
bool thread_set_rt_priority(thread_t* thread, int priority);

// Returns true if the current thread is the same as the one represented by
// |thread|.
// |thread| may not be NULL.
+15 −9
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <malloc.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <time.h>
@@ -44,12 +45,9 @@
#include "osi/include/thread.h"
#include "osi/include/wakelock.h"

// Make callbacks run at high thread priority. Some callbacks are used for audio
// related timer tasks as well as re-transmissions etc. Since we at this point
// cannot differentiate what callback we are dealing with, assume high priority
// for now.
// TODO(eisenbach): Determine correct thread priority (from parent?/per alarm?)
static const int CALLBACK_THREAD_PRIORITY_HIGH = -19;
// Callback and timer threads should run at RT priority in order to ensure they
// meet audio deadlines.  Use this priority for all audio/timer related thread.
static const int THREAD_RT_PRIORITY = 1;

typedef struct {
  size_t count;
@@ -314,7 +312,7 @@ static bool lazy_initialize(void) {
              __func__);
    goto error;
  }
  thread_set_priority(default_callback_thread, CALLBACK_THREAD_PRIORITY_HIGH);
  thread_set_rt_priority(default_callback_thread, THREAD_RT_PRIORITY);
  default_callback_queue = fixed_queue_new(SIZE_MAX);
  if (default_callback_queue == NULL) {
    LOG_ERROR(LOG_TAG, "%s unable to create default alarm callbacks queue.",
@@ -330,8 +328,7 @@ static bool lazy_initialize(void) {
    LOG_ERROR(LOG_TAG, "%s unable to create alarm callback thread.", __func__);
    goto error;
  }

  thread_set_priority(dispatcher_thread, CALLBACK_THREAD_PRIORITY_HIGH);
  thread_set_rt_priority(dispatcher_thread, THREAD_RT_PRIORITY);
  thread_post(dispatcher_thread, callback_dispatch, NULL);
  return true;

@@ -625,9 +622,18 @@ static bool timer_create_internal(const clockid_t clock_id, timer_t* timer) {
  CHECK(timer != NULL);

  struct sigevent sigevent;
  // create timer with RT priority thread
  pthread_attr_t thread_attr;
  pthread_attr_init(&thread_attr);
  pthread_attr_setschedpolicy(&thread_attr, SCHED_FIFO);
  struct sched_param param;
  param.sched_priority = THREAD_RT_PRIORITY;
  pthread_attr_setschedparam(&thread_attr, &param);

  memset(&sigevent, 0, sizeof(sigevent));
  sigevent.sigev_notify = SIGEV_THREAD;
  sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback;
  sigevent.sigev_notify_attributes = (void*)(&thread_attr);
  if (timer_create(clock_id, &sigevent, timer) == -1) {
    LOG_ERROR(LOG_TAG, "%s unable to create timer with clock %d: %s", __func__,
              clock_id, strerror(errno));
+17 −0
Original line number Diff line number Diff line
@@ -159,6 +159,23 @@ bool thread_set_priority(thread_t* thread, int priority) {
  return true;
}

bool thread_set_rt_priority(thread_t* thread, int priority) {
  if (!thread) return false;

  struct sched_param rt_params;
  rt_params.sched_priority = priority;

  const int rc = sched_setscheduler(thread->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__, priority, thread->tid, strerror(errno));
    return false;
  }

  return true;
}

bool thread_is_self(const thread_t* thread) {
  CHECK(thread != NULL);
  return !!pthread_equal(pthread_self(), thread->pthread);
Loading