blob: 615b98ea7868b7864ec7f448632f0fcaa7e63e32 [file] [log] [blame]
/*
*Licensed to the Apache Software Foundation (ASF) under one
*or more contributor license agreements. See the NOTICE file
*distributed with this work for additional information
*regarding copyright ownership. The ASF licenses this file
*to you under the Apache License, Version 2.0 (the
*"License"); you may not use this file except in compliance
*with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing,
*software distributed under the License is distributed on an
*"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
*specific language governing permissions and limitations
*under the License.
*/
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <stdio.h>
#include <math.h>
#include "benchmark.h"
static const char * const BENCHMARK_NAME = "MUTEX";
static const double SAMPLE_FACTOR = 1;
struct benchmark {
pthread_mutex_t mutex;
math_service_pt math;
};
typedef struct thread_info {
benchmark_pt benchmark;
int nrOfSamples;
unsigned int result;
struct timeval begin;
struct timeval end;
unsigned int skips;
} thread_info_t;
static void benchmark_thread(thread_info_t *info);
celix_status_t benchmark_create(benchmark_pt *benchmark) {
(*benchmark) = malloc(sizeof(struct benchmark));
(*benchmark)->math = NULL;
pthread_mutex_init(&(*benchmark)->mutex, NULL);
return CELIX_SUCCESS;
}
celix_status_t benchmark_destroy(benchmark_pt benchmark) {
free(benchmark);
return CELIX_SUCCESS;
}
benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) {
int i;
pthread_t threads[nrOfThreads];
thread_info_t infos[nrOfThreads];
benchmark_result_t result;
unsigned long elapsedTime = 0;
result.skips =0;
for (i = 0 ; i < nrOfThreads ; i += 1) {
infos[i].benchmark = benchmark;
infos[i].nrOfSamples = nrOfSamples;
infos[i].skips = 0;
infos[i].result = rand();
pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]);
}
for (i = 0; i < nrOfThreads ; i += 1) {
pthread_join(threads[i], NULL);
elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec);
result.skips += infos[i].skips;
}
unsigned int actualSamples = (nrOfSamples * nrOfThreads) - result.skips;
result.averageCallTimeInNanoseconds = actualSamples == 0 ? NAN : ((double)elapsedTime * 1000) / (nrOfSamples * nrOfThreads);
result.callFrequencyInMhz = ((double)(actualSamples * nrOfThreads) / elapsedTime);
result.nrOfThreads = nrOfThreads;
result.nrOfsamples = actualSamples;
result.requestedNrOfSamples = (nrOfSamples * nrOfThreads);
return result;
}
static void benchmark_thread(thread_info_t *info) {
int i;
gettimeofday(&info->begin, NULL);
for (i = 0; i < info->nrOfSamples; i += 1) {
pthread_mutex_lock(&info->benchmark->mutex);
if (info->benchmark->math != NULL) {
info->result = info->benchmark->math->calc(info->benchmark->math->handle, info->result, i);
} else {
info->skips += 1; //should not happen
}
pthread_mutex_unlock(&info->benchmark->mutex);
}
gettimeofday(&info->end, NULL);
}
char * benchmark_getName(benchmark_pt benchmark) {
return (char *)BENCHMARK_NAME;
}
celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) {
pthread_mutex_lock(&benchmark->mutex);
benchmark->math = mathService;
pthread_mutex_unlock(&benchmark->mutex);
return CELIX_SUCCESS;
}
celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) {
pthread_mutex_lock(&benchmark->mutex);
if (benchmark->math == mathService) {
benchmark->math = NULL;
}
pthread_mutex_unlock(&benchmark->mutex);
return CELIX_SUCCESS;
}
double benchmark_getSampleFactor(benchmark_pt benchmark) {
return SAMPLE_FACTOR;
}