SHECD_FIFO和Posix条件变量

时间:2019-02-01 16:12:59

标签: c++ linux posix real-time

我正在使用SCHED_FIFO和pthread条件变量。

程序由3个线程组成:cpu 0上具有较高优先级的“ main”,cpu 0上也具有“ task_1”的优先级以及cpu 1上具有最低优先级的“ task_2”。

从posix条件变量的角度来看,“主要”是生产者,其他线程是“消费者”。

问题如下:调用广播后,主程序被优先级较低的task_1抢占,然后task_2在主程序之前也完成了执行...

跟踪(总是)是以下跟踪:

[main]   creating task_2
[task_2] lock
[task_2] wait
[main]   creating task_1
[task_1] lock
[task_1] wait
[main]   before lock
[main]   before unlock
[task_1] running
[main]   after unlock
[task_1] unlock
[task_2] running
[main]   finished
[task_2] unlock
using time_ns_t = uint64_t;
constexpr time_ns_t sec_to_us(time_ns_t sec) {
  return sec * 1000000;
}
pthread_mutex_t mutex;
void            mutex_init() {
  pthread_mutexattr_t attr;
  pthread_mutexattr_init(&attr);
  // pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
  pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_NONE);
  pthread_mutex_init(&mutex, &attr);
}
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
bool ready = false;
//--------------------------------------------------
uint64_t total_usage(const struct rusage& usage) {
  uint64_t u_sec   = usage.ru_utime.tv_sec;
  uint64_t u_micro = usage.ru_utime.tv_usec;
  uint64_t s_sec   = usage.ru_stime.tv_sec;
  uint64_t s_micro = usage.ru_stime.tv_usec;    
  return (u_sec + s_sec) * 1000000 + (u_micro + s_micro);
}

uint64_t burn_cpu(uint64_t microsec) {
  struct rusage usage;
  getrusage(RUSAGE_THREAD, &usage);
  uint64_t init     = total_usage(usage);
  uint64_t duration = 0;
  while (duration < microsec) {
    getrusage(RUSAGE_THREAD, &usage);
    duration = total_usage(usage) - init;
  }
  return duration;
}
//--------------------------------------------------
int set_cpu(int cpu) {
  cpu_set_t set;
  CPU_ZERO(&set);
  CPU_SET(cpu, &set);
  return sched_setaffinity(0, sizeof(cpu_set_t), &set);
}
int set_rt_priority(int priority) {
  struct sched_param sp;
  sp.sched_priority = priority;
  return sched_setscheduler(0, SCHED_FIFO, &sp);
}
//--------------------------------------------------
void* thread_start_1(void* data) {
  set_cpu(0);
  set_rt_priority(20);
  std::cout << "[task_1] lock\n";
  pthread_mutex_lock(&mutex);
  while (!ready) {
    std::cout << "[task_1] wait\n";
    pthread_cond_wait(&cond, &mutex);
  }
  std::cout << "[task_1] running\n";
  burn_cpu(sec_to_us(1));
  pthread_mutex_unlock(&mutex);
  std::cout << "[task_1] unlock\n";
  return nullptr;
}

void* thread_start_2(void* data) {
  set_cpu(1);
  set_rt_priority(10);
  std::cout << "[task_2] lock\n";
  pthread_mutex_lock(&mutex);
  while (!ready) {
    std::cout << "[task_2] wait\n";
    pthread_cond_wait(&cond, &mutex);
  }
  std::cout << "[task_2] running\n";
  burn_cpu(sec_to_us(1));
  pthread_mutex_unlock(&mutex);
  std::cout << "[task_2] unlock\n";
  return nullptr;
}

int main(int argc, char* argv[]) {
  pthread_t id_1, id_2;

  set_cpu(0);
  set_rt_priority(50);

  burn_cpu(sec_to_us(1));

  std::cout << "[main]   creating task_2\n";
  pthread_create(&id_2, nullptr, thread_start_2, nullptr);
  burn_cpu(sec_to_us(1));

  std::cout << "[main]   creating task_1\n";
  pthread_create(&id_1, nullptr, thread_start_1, nullptr);
  burn_cpu(sec_to_us(1));

  std::cout << "[main]   before lock\n";
  pthread_mutex_lock(&mutex);
  ready = true;
  pthread_cond_broadcast(&cond);
  std::cout << "[main]   before unlock\n";
  pthread_mutex_unlock(&mutex);
  std::cout << "[main]   after unlock\n";

  burn_cpu(sec_to_us(1));
  std::cout << "[main]   finished\n";

  pthread_join(id_1, nullptr);
  pthread_join(id_2, nullptr);

  return 0;
}

0 个答案:

没有答案