18d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev// A benchmark that executes malloc/free pairs in parallel.
28d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev// Usage: ./a.out number_of_threads total_number_of_allocations
38d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev// RUN: %clangxx_lsan %s -o %t
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// RUN: %run %t 5 1000000 2>&1
58d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev#include <assert.h>
68d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev#include <pthread.h>
78d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev#include <stdlib.h>
88d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev#include <stdio.h>
98d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev
108d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveevint num_threads;
118d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveevint total_num_alloc;
125bd2174c1385ec10b172cc9a32bc33b1967d60b5Alexey Samsonovconst int kMaxNumThreads = 5000;
135bd2174c1385ec10b172cc9a32bc33b1967d60b5Alexey Samsonovpthread_t tid[kMaxNumThreads];
148d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev
158d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveevpthread_cond_t cond = PTHREAD_COND_INITIALIZER;
168d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveevpthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
178d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveevbool go = false;
188d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev
195bd2174c1385ec10b172cc9a32bc33b1967d60b5Alexey Samsonovvoid *thread_fun(void *arg) {
208d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  pthread_mutex_lock(&mutex);
218d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  while (!go) pthread_cond_wait(&cond, &mutex);
228d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  pthread_mutex_unlock(&mutex);
238d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  for (int i = 0; i < total_num_alloc / num_threads; i++) {
248d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev    void *p = malloc(10);
258d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev    __asm__ __volatile__("" : : "r"(p) : "memory");
268d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev    free((void *)p);
278d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  }
288d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  return 0;
298d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev}
308d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev
318d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveevint main(int argc, char** argv) {
328d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  assert(argc == 3);
338d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  num_threads = atoi(argv[1]);
348d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  assert(num_threads > 0);
355bd2174c1385ec10b172cc9a32bc33b1967d60b5Alexey Samsonov  assert(num_threads <= kMaxNumThreads);
368d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  total_num_alloc = atoi(argv[2]);
378d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  assert(total_num_alloc > 0);
388d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  printf("%d threads, %d allocations in each\n", num_threads,
398d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev         total_num_alloc / num_threads);
408d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  for (int i = 0; i < num_threads; i++)
418d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev    pthread_create(&tid[i], 0, thread_fun, 0);
428d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  pthread_mutex_lock(&mutex);
438d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  go = true;
448d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  pthread_cond_broadcast(&cond);
458d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  pthread_mutex_unlock(&mutex);
468d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  for (int i = 0; i < num_threads; i++) pthread_join(tid[i], 0);
478d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev  return 0;
488d0c5ba5a63e2934136336db1884804c00932be9Sergey Matveev}
49