/*
 * Copyright 2006, Google Inc.
 *
 * Exercise malloc with values close to the edge.
 * Compile with: gcc malloc-large.c -lpthread
 */

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void* RunThread(void* UNUSED) {
  int i;
  for (i = 0; i < 300; ++i) {
    malloc(32);  /* Imagine deferred deallocation */
  }
  return NULL;
}

int main(int argc, char** argv) {
  /* The thread activity causes malloc to allocate per-thread heaps. */
  const int kNumThreads = 20;
  pthread_t threads[kNumThreads];
  int i;
  for (i = 0; i < kNumThreads; ++i) {
    pthread_create(&threads[i], NULL, RunThread, NULL);
  }
  for (i = 0; i < kNumThreads; ++i) {
    pthread_join(threads[i], NULL);
  }

  /* This just provides a convenient strace marker. */
  getppid();

  /* malloc a lot of blocks near the max possible size. */
  const size_t kMaxSize = ~ (size_t) 0;
  for (i = 0; i < 10000; i++) {
    if (malloc(kMaxSize - i) != NULL) {
      fprintf(stderr, "Oops\n");
      return 1;
    }
  }

  printf("PASS\n");
  return 0;
}
