Example #1
0
File: hh_shared.c Project: 2bj/hhvm
void hh_shared_init() {
  /* MAP_NORESERVE is because we want a lot more virtual memory than what
   * we are actually going to use.
   */
  int flags = MAP_SHARED | MAP_ANONYMOUS | MAP_NORESERVE;
  int prot  = PROT_READ  | PROT_WRITE;

  page_size = getpagesize();

  shared_mem = 
    (char*)mmap(NULL, page_size + SHARED_MEM_SIZE, prot, flags, 0, 0);

  if(shared_mem == MAP_FAILED) {
    printf("Error initializing: %s\n", strerror(errno));
    exit(2);
  }

  // Keeping the pids around to make asserts.
  master_pid = getpid();
  my_pid = master_pid;

  init_shared_globals(shared_mem);

  // Uninstall ocaml's segfault handler. It's supposed to throw an exception on
  // stack overflow, but we don't actually handle that exception, so what
  // happens in practice is we terminate at toplevel with an unhandled exception
  // and a useless ocaml backtrace. A core dump is actually more useful. Sigh.
  struct sigaction sigact = {};
  sigact.sa_handler = SIG_DFL;
  sigemptyset(&sigact.sa_mask);
  sigact.sa_flags = 0;
  sigaction(SIGSEGV, &sigact, NULL);

  set_priorities();
}
Example #2
0
void hh_shared_reset() {
#ifndef _WIN32
  assert(shared_mem);
  early_counter = 1;
  memset(shared_mem, 0, heap_init - shared_mem);
  init_shared_globals(shared_mem);
#endif
}
Example #3
0
CAMLprim value hh_shared_init(
  value global_size_val,
  value heap_size_val
) {

  CAMLparam2(global_size_val, heap_size_val);

  global_size_b = Long_val(global_size_val);
  heap_size = Long_val(heap_size_val);

  size_t page_size = getpagesize();

  /* The total size of the shared memory.  Most of it is going to remain
   * virtual. */
  shared_mem_size =
    global_size_b + 2 * DEP_SIZE_B + HASHTBL_SIZE_B +
    heap_size + page_size;

#ifdef _WIN32
  /*

     We create an anonymous memory file, whose `handle` might be
     inherited by slave processes.

     This memory file is tagged "reserved" but not "committed". This
     means that the memory space will be reserved in the virtual
     memory table but the pages will not be bound to any physical
     memory yet. Further calls to 'VirtualAlloc' will "commit" pages,
     meaning they will be bound to physical memory.

     This is behavior that should reflect the 'MAP_NORESERVE' flag of
     'mmap' on Unix. But, on Unix, the "commit" is implicit.

     Committing the whole shared heap at once would require the same
     amount of free space in memory (or in swap file).

  */
  HANDLE handle = CreateFileMapping(
    INVALID_HANDLE_VALUE,
    NULL,
    PAGE_READWRITE | SEC_RESERVE,
    shared_mem_size >> 32, shared_mem_size & ((1ll << 32) - 1),
    NULL);
  if (handle == NULL) {
    win32_maperr(GetLastError());
    uerror("CreateFileMapping", Nothing);
  }
  if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
    win32_maperr(GetLastError());
    uerror("SetHandleInformation", Nothing);
  }
  shared_mem = MapViewOfFileEx(
    handle,
    FILE_MAP_ALL_ACCESS,
    0, 0, 0);
  if (shared_mem == NULL) {
    win32_maperr(GetLastError());
    uerror("MapViewOfFileEx", Nothing);
  }

#else /* _WIN32 */

  /* MAP_NORESERVE is because we want a lot more virtual memory than what
   * we are actually going to use.
   */
  int flags = MAP_SHARED | MAP_ANON | MAP_NORESERVE;
  int prot  = PROT_READ  | PROT_WRITE;

  shared_mem = (char*)mmap(NULL, shared_mem_size, prot, flags, 0, 0);
  if(shared_mem == MAP_FAILED) {
    printf("Error initializing: %s\n", strerror(errno));
    exit(2);
  }

#ifdef MADV_DONTDUMP
  // We are unlikely to get much useful information out of the shared heap in
  // a core file. Moreover, it can be HUGE, and the extensive work done dumping
  // it once for each CPU can mean that the user will reboot their machine
  // before the much more useful stack gets dumped!
  madvise(shared_mem, shared_mem_size, MADV_DONTDUMP);
#endif

  // Keeping the pids around to make asserts.
  master_pid = getpid();
  my_pid = master_pid;

#endif /* _WIN32 */

  char* bottom = shared_mem;
  init_shared_globals(shared_mem);

  // Checking that we did the maths correctly.
  assert(*heap + heap_size == bottom + shared_mem_size);

#ifndef _WIN32
  // Uninstall ocaml's segfault handler. It's supposed to throw an exception on
  // stack overflow, but we don't actually handle that exception, so what
  // happens in practice is we terminate at toplevel with an unhandled exception
  // and a useless ocaml backtrace. A core dump is actually more useful. Sigh.
  struct sigaction sigact;
  sigact.sa_handler = SIG_DFL;
  sigemptyset(&sigact.sa_mask);
  sigact.sa_flags = 0;
  sigaction(SIGSEGV, &sigact, NULL);
#endif

  CAMLreturn(Val_unit);
}
Example #4
0
void hh_shared_init(
  value global_size_val,
  value heap_size_val
) {

  CAMLparam2(global_size_val, heap_size_val);

  global_size_b = Long_val(global_size_val);
  heap_size = Long_val(heap_size_val);

  /* MAP_NORESERVE is because we want a lot more virtual memory than what
   * we are actually going to use.
   */
  int flags = MAP_SHARED | MAP_ANON | MAP_NORESERVE | MAP_FIXED;
  int prot  = PROT_READ  | PROT_WRITE;

  int page_size = getpagesize();

  /* The total size of the shared memory.  Most of it is going to remain
   * virtual. */
  size_t shared_mem_size = global_size_b + 2 * DEP_SIZE_B + HASHTBL_SIZE_B +
      heap_size;

  char* shared_mem =
    (char*)mmap((void*)SHARED_MEM_INIT, page_size + shared_mem_size, prot,
                flags, 0, 0);

  if(shared_mem == MAP_FAILED) {
    printf("Error initializing: %s\n", strerror(errno));
    exit(2);
  }

#ifdef MADV_DONTDUMP
  // We are unlikely to get much useful information out of the shared heap in
  // a core file. Moreover, it can be HUGE, and the extensive work done dumping
  // it once for each CPU can mean that the user will reboot their machine
  // before the much more useful stack gets dumped!
  madvise(shared_mem, page_size + shared_mem_size, MADV_DONTDUMP);
#endif

  // Keeping the pids around to make asserts.
  master_pid = getpid();
  my_pid = master_pid;

  char* bottom = shared_mem;

  init_shared_globals(shared_mem);

  // Checking that we did the maths correctly.
  assert(*heap + heap_size == bottom + shared_mem_size + page_size);

  // Uninstall ocaml's segfault handler. It's supposed to throw an exception on
  // stack overflow, but we don't actually handle that exception, so what
  // happens in practice is we terminate at toplevel with an unhandled exception
  // and a useless ocaml backtrace. A core dump is actually more useful. Sigh.
  struct sigaction sigact;
  sigact.sa_handler = SIG_DFL;
  sigemptyset(&sigact.sa_mask);
  sigact.sa_flags = 0;
  sigaction(SIGSEGV, &sigact, NULL);

  set_priorities();

  CAMLreturn0;
}