/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/system_wrappers/source/thread_posix.h"

#include <algorithm>

#include <errno.h>
#include <unistd.h>
#ifdef WEBRTC_LINUX
#include <linux/unistd.h>
#include <sched.h>
#include <sys/types.h>
#endif

#include "webrtc/base/checks.h"
#include "webrtc/base/platform_thread.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {
namespace {
struct ThreadAttributes {
  ThreadAttributes() { pthread_attr_init(&attr); }
  ~ThreadAttributes() { pthread_attr_destroy(&attr); }
  pthread_attr_t* operator&() { return &attr; }
  pthread_attr_t attr;
};
}  // namespace

int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
                            int max_prio) {
  DCHECK(max_prio - min_prio > 2);
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;

  switch (priority) {
    case kLowPriority:
      return low_prio;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      return (low_prio + top_prio - 1) / 2;
    case kHighPriority:
      return std::max(top_prio - 2, low_prio);
    case kHighestPriority:
      return std::max(top_prio - 1, low_prio);
    case kRealtimePriority:
      return top_prio;
  }
  DCHECK(false);
  return low_prio;
}

// static
void* ThreadPosix::StartThread(void* param) {
  static_cast<ThreadPosix*>(param)->Run();
  return 0;
}

ThreadPosix::ThreadPosix(ThreadRunFunction func, void* obj,
                         const char* thread_name)
    : run_function_(func),
      obj_(obj),
      stop_event_(false, false),
      name_(thread_name ? thread_name : "webrtc"),
      thread_(0) {
  DCHECK(name_.length() < 64);
}

uint32_t ThreadWrapper::GetThreadId() {
  return rtc::CurrentThreadId();
}

ThreadPosix::~ThreadPosix() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

// TODO(pbos): Make Start void, calling code really doesn't support failures
// here.
bool ThreadPosix::Start() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!thread_) << "Thread already started?";

  ThreadAttributes attr;
  // Set the stack stack size to 1M.
  pthread_attr_setstacksize(&attr, 1024 * 1024);
  CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this));
  return true;
}

bool ThreadPosix::Stop() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!thread_)
    return true;

  stop_event_.Set();
  CHECK_EQ(0, pthread_join(thread_, nullptr));
  thread_ = 0;

  return true;
}

bool ThreadPosix::SetPriority(ThreadPriority priority) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!thread_)
    return false;
#if defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
  // TODO(tommi): Switch to the same mechanism as Chromium uses for
  // changing thread priorities.
  return true;
#else
#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);
  if (min_prio == -1 || max_prio == -1) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to retreive min or max priority for threads");
    return false;
  }

  if (max_prio - min_prio <= 2)
    return false;

  sched_param param;
  param.sched_priority = ConvertToSystemPriority(priority, min_prio, max_prio);
  if (pthread_setschedparam(thread_, policy, &param) != 0) {
    WEBRTC_TRACE(
        kTraceError, kTraceUtility, -1, "unable to set thread priority");
    return false;
  }

  return true;
#endif  // defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
}

void ThreadPosix::Run() {
  if (!name_.empty()) {
    // Setting the thread name may fail (harmlessly) if running inside a
    // sandbox. Ignore failures if they happen.
    rtc::SetCurrentThreadName(name_.substr(0, 63).c_str());
  }

  // It's a requirement that for successful thread creation that the run
  // function be called at least once (see RunFunctionIsCalled unit test),
  // so to fullfill that requirement, we use a |do| loop and not |while|.
  do {
    if (!run_function_(obj_))
      break;
  } while (!stop_event_.Wait(0));
}

}  // namespace webrtc
