vts_many_threads_bench.cc [plain text]
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
class __attribute__((aligned(64))) Mutex {
public:
Mutex() { pthread_mutex_init(&m_, NULL); }
~Mutex() { pthread_mutex_destroy(&m_); }
void Lock() { pthread_mutex_lock(&m_); }
void Unlock() { pthread_mutex_unlock(&m_); }
private:
pthread_mutex_t m_;
};
const int kNumMutexes = 1024;
Mutex mutexes[kNumMutexes];
int n_threads, n_iterations;
pthread_barrier_t all_threads_ready, main_threads_ready;
void* GarbageThread(void *unused) {
pthread_barrier_wait(&all_threads_ready);
return 0;
}
void *Thread(void *arg) {
long idx = (long)arg;
pthread_barrier_wait(&all_threads_ready);
pthread_barrier_wait(&main_threads_ready);
printf("Thread %ld go!\n", idx);
int offset = idx * kNumMutexes / n_threads;
for (int i = 0; i < n_iterations; i++) {
mutexes[(offset + i) % kNumMutexes].Lock();
mutexes[(offset + i) % kNumMutexes].Unlock();
}
printf("Thread %ld done\n", idx);
return 0;
}
int main(int argc, char **argv) {
int n_garbage_threads;
if (argc == 1) {
n_threads = 2;
n_garbage_threads = 200;
n_iterations = 20000000;
} else if (argc == 4) {
n_threads = atoi(argv[1]);
assert(n_threads > 0 && n_threads <= 32);
n_garbage_threads = atoi(argv[2]);
assert(n_garbage_threads > 0 && n_garbage_threads <= 16000);
n_iterations = atoi(argv[3]);
} else {
printf("Usage: %s n_threads n_garbage_threads n_iterations\n", argv[0]);
return 1;
}
printf("%s: n_threads=%d n_garbage_threads=%d n_iterations=%d\n",
__FILE__, n_threads, n_garbage_threads, n_iterations);
pthread_barrier_init(&all_threads_ready, NULL, n_garbage_threads + n_threads + 1);
pthread_barrier_init(&main_threads_ready, NULL, n_threads + 1);
pthread_t *t = new pthread_t[n_threads];
{
pthread_t *g_t = new pthread_t[n_garbage_threads];
for (int i = 0; i < n_garbage_threads; i++) {
int status = pthread_create(&g_t[i], 0, GarbageThread, NULL);
assert(status == 0);
}
for (int i = 0; i < n_threads; i++) {
int status = pthread_create(&t[i], 0, Thread, (void*)i);
assert(status == 0);
}
pthread_barrier_wait(&all_threads_ready);
printf("All threads started! Killing the garbage threads.\n");
for (int i = 0; i < n_garbage_threads; i++) {
pthread_join(g_t[i], 0);
}
delete [] g_t;
}
printf("Resuming the main threads.\n");
pthread_barrier_wait(&main_threads_ready);
for (int i = 0; i < n_threads; i++) {
pthread_join(t[i], 0);
}
delete [] t;
return 0;
}