// © 2020 Erik Rigtorp <erik@rigtorp.se>
// SPDX-License-Identifier: MIT

// Demonstrate how munmap triggers TLB shootdowns
// See https://rigtorp.se/virtual-memory/ for details
//
// Example:
// $ perf stat -e tlb:tlb_flush ./tlbshootdown 100000
//
//  Performance counter stats for './tlbshootdown 100000':
//
//            100,038      tlb:tlb_flush
//
//        0.272227205 seconds time elapsed
//
//        0.014726000 seconds user
//        0.243955000 seconds sys
//
// This shows that 100000 TLB shootdowns would have been triggered in a
// multithreaded application.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int iter = atoi(argv[1]);
  for (int i = 0; i < iter; ++i) {
    void *p = mmap(NULL, 128, PROT_READ | PROT_WRITE,
                   MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if (p == MAP_FAILED) {
      perror("mmap");
      exit(1);
    }
    memset(p, 0, 128);
    if (munmap(p, 128) < 0) {
      perror("munmap");
      exit(1);
    }
  }
  return 0;
}
