* commit '445c202073f4fd35e1171dc11bcd13a7accf7018': bionic: benchmarks: Add BM_semaphore_sem_post
This commit is contained in:
		@@ -16,7 +16,10 @@
 | 
			
		||||
 | 
			
		||||
#include "benchmark.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <semaphore.h>
 | 
			
		||||
#include <stdatomic.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
static void BM_semaphore_sem_getvalue(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
@@ -47,3 +50,94 @@ static void BM_semaphore_sem_wait_sem_post(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_semaphore_sem_wait_sem_post);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *    This test reports the overhead of the underlying futex wake syscall on
 | 
			
		||||
 * the producer. It does not report the overhead from issuing the wake to the
 | 
			
		||||
 * point where the posted consumer thread wakes up. It suffers from
 | 
			
		||||
 * clock_gettime syscall overhead. Lock the CPU speed for consistent results
 | 
			
		||||
 * as we may not reach >50% cpu utilization.
 | 
			
		||||
 *
 | 
			
		||||
 *    We will run a background thread that catches the sem_post wakeup and
 | 
			
		||||
 * loops immediately returning back to sleep in sem_wait for the next one. This
 | 
			
		||||
 * thread is run with policy SCHED_OTHER (normal policy), a middle policy.
 | 
			
		||||
 *
 | 
			
		||||
 *    The primary thread will run at SCHED_IDLE (lowest priority policy) when
 | 
			
		||||
 * monitoring the background thread to detect when it hits sem_wait sleep. It
 | 
			
		||||
 * will do so with no clock running. Once we are ready, we will switch to
 | 
			
		||||
 * SCHED_FIFO (highest priority policy) to time the act of running sem_post
 | 
			
		||||
 * with the benchmark clock running. This ensures nothing else in the system
 | 
			
		||||
 * can preempt our timed activity, including the background thread. We are
 | 
			
		||||
 * also protected with the scheduling policy of letting a process hit a
 | 
			
		||||
 * resource limit rather than get hit with a context switch.
 | 
			
		||||
 *
 | 
			
		||||
 *    The background thread will start executing either on another CPU, or
 | 
			
		||||
 * after we back down from SCHED_FIFO, but certainly not in the context of
 | 
			
		||||
 * the timing of the sem_post.
 | 
			
		||||
 */
 | 
			
		||||
static atomic_int BM_semaphore_sem_post_running;
 | 
			
		||||
 | 
			
		||||
static void *BM_semaphore_sem_post_start_thread(void *obj) {
 | 
			
		||||
    sem_t *semaphore = reinterpret_cast<sem_t *>(obj);
 | 
			
		||||
 | 
			
		||||
    while ((BM_semaphore_sem_post_running > 0) && !sem_wait(semaphore)) {
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
    BM_semaphore_sem_post_running = -1;
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void BM_semaphore_sem_post(int iters) {
 | 
			
		||||
  StopBenchmarkTiming();
 | 
			
		||||
 | 
			
		||||
  sem_t semaphore;
 | 
			
		||||
  sem_init(&semaphore, 0, 0);
 | 
			
		||||
 | 
			
		||||
  pthread_attr_t attr;
 | 
			
		||||
  pthread_attr_init(&attr);
 | 
			
		||||
  BM_semaphore_sem_post_running = 1;
 | 
			
		||||
  struct sched_param param = { 0, };
 | 
			
		||||
  pthread_attr_setschedparam(&attr, ¶m);
 | 
			
		||||
  pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
 | 
			
		||||
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 | 
			
		||||
  pthread_t pthread;
 | 
			
		||||
  pthread_create(&pthread, &attr, BM_semaphore_sem_post_start_thread, &semaphore);
 | 
			
		||||
  pthread_attr_destroy(&attr);
 | 
			
		||||
 | 
			
		||||
  sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    int trys = 3, dummy = 0;
 | 
			
		||||
    do {
 | 
			
		||||
      if (BM_semaphore_sem_post_running < 0) {
 | 
			
		||||
        sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
 | 
			
		||||
        fprintf(stderr, "BM_semaphore_sem_post: start_thread died unexpectedly\n");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      sched_yield();
 | 
			
		||||
      sem_getvalue(&semaphore, &dummy);
 | 
			
		||||
      if (dummy < 0) {  // POSIX.1-2001 possibility 1
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (dummy == 0) { // POSIX.1-2001 possibility 2
 | 
			
		||||
        --trys;
 | 
			
		||||
      }
 | 
			
		||||
    } while (trys);
 | 
			
		||||
    param.sched_priority = 1;
 | 
			
		||||
    sched_setscheduler((pid_t)0, SCHED_FIFO, ¶m);
 | 
			
		||||
    StartBenchmarkTiming();
 | 
			
		||||
    sem_post(&semaphore);
 | 
			
		||||
    StopBenchmarkTiming(); // Remember to subtract clock syscall overhead
 | 
			
		||||
    param.sched_priority = 0;
 | 
			
		||||
    sched_setscheduler((pid_t)0, SCHED_IDLE, ¶m);
 | 
			
		||||
  }
 | 
			
		||||
  sched_setscheduler((pid_t)0, SCHED_OTHER, ¶m);
 | 
			
		||||
 | 
			
		||||
  if (BM_semaphore_sem_post_running > 0) {
 | 
			
		||||
    BM_semaphore_sem_post_running = 0;
 | 
			
		||||
  }
 | 
			
		||||
  do {
 | 
			
		||||
    sem_post(&semaphore);
 | 
			
		||||
    sched_yield();
 | 
			
		||||
  } while (!BM_semaphore_sem_post_running);
 | 
			
		||||
}
 | 
			
		||||
BENCHMARK(BM_semaphore_sem_post);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user