/*
 * Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "precompiled.hpp"

#include "gc/shenandoah/shenandoahEvacOOMHandler.inline.hpp"
#include "gc/shenandoah/shenandoahUtils.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/os.hpp"

const jint ShenandoahEvacOOMCounter::OOM_MARKER_MASK = 0x80000000;

ShenandoahEvacOOMCounter::ShenandoahEvacOOMCounter() :
  _bits(0) {
}

void ShenandoahEvacOOMCounter::decrement() {
  assert(unmasked_count() > 0, "sanity");
  // NOTE: It's ok to simply decrement, even with mask set, because unmasked value is positive.
  Atomic::dec(&_bits);
}

void ShenandoahEvacOOMCounter::clear() {
  assert(unmasked_count() == 0, "sanity");
  Atomic::release_store_fence(&_bits, (jint)0);
}

void ShenandoahEvacOOMCounter::set_oom_bit(bool decrement) {
  jint threads_in_evac = Atomic::load_acquire(&_bits);
  while (true) {
    jint newval = decrement
      ? (threads_in_evac - 1) | OOM_MARKER_MASK
      : threads_in_evac | OOM_MARKER_MASK;

    jint other = Atomic::cmpxchg(&_bits, threads_in_evac, newval);
    if (other == threads_in_evac) {
      // Success: wait for other threads to get out of the protocol and return.
      break;
    } else {
      // Failure: try again with updated new value.
      threads_in_evac = other;
    }
  }
}

bool ShenandoahEvacOOMCounter::try_increment()
{
  jint threads_in_evac = Atomic::load_acquire(&_bits);

  while (true) {
    // Cannot enter evacuation if OOM_MARKER_MASK is set.
    if ((threads_in_evac & OOM_MARKER_MASK) != 0) {
      return false;
    }

    jint other = Atomic::cmpxchg(&_bits, threads_in_evac, threads_in_evac + 1);
    if (other == threads_in_evac) {
      // Success: caller may safely enter evacuation
      return true;
    } else {
      threads_in_evac = other;
    }
  }
}

ShenandoahEvacOOMHandler::ShenandoahEvacOOMHandler() :
  _num_counters(calc_num_counters()) {

  assert(_num_counters > 0, "sanity");
  assert(is_power_of_2(_num_counters), "must be");

  _threads_in_evac = NEW_C_HEAP_ARRAY(ShenandoahEvacOOMCounter, _num_counters, mtGC);
  for (int i = 0; i < _num_counters; i++) {
    new (&_threads_in_evac[i]) ShenandoahEvacOOMCounter();
  }
}

int ShenandoahEvacOOMHandler::calc_num_counters() {
  // Scale the number of counter buckets with the number of CPUs to
  // minimise contention.  Also make sure the number is a power of two
  // so we can map hash values to buckets with a simple mask.
  const int nproc = os::active_processor_count();
  const int clamped = MAX2(1, MIN2(nproc, 128));
  return round_up_power_of_2(clamped);
}

uint64_t ShenandoahEvacOOMHandler::hash_pointer(const void* p) {
  // Bit mixing function from MurmurHash3
  uint64_t key = (uintptr_t)p;
  key ^= (key >> 33);
  key *= UINT64_C(0xff51afd7ed558ccd);
  key ^= (key >> 33);
  key *= UINT64_C(0xc4ceb9fe1a85ec53);
  key ^= (key >> 33);
  return key;
}

ShenandoahEvacOOMCounter* ShenandoahEvacOOMHandler::counter_for_thread(Thread* t) {
  const uint64_t key = hash_pointer(t);
  return &_threads_in_evac[key & (_num_counters - 1)];
}

void ShenandoahEvacOOMHandler::wait_for_one_counter(ShenandoahEvacOOMCounter* ptr) {
  // We might be racing against handle_out_of_memory_during_evacuation()
  // setting the OOM_MARKER_MASK bit so we must make sure it is set here
  // *and* the counter is zero.
  while (ptr->load_acquire() != ShenandoahEvacOOMCounter::OOM_MARKER_MASK) {
    os::naked_short_sleep(1);
  }
}

void ShenandoahEvacOOMHandler::wait_for_no_evac_threads() {
  // Once the OOM_MARKER_MASK bit is set the counter can only decrease
  // so it's safe to check each bucket in turn.
  for (int i = 0; i < _num_counters; i++) {
    wait_for_one_counter(&_threads_in_evac[i]);
  }
  // At this point we are sure that no threads can evacuate anything. Raise
  // the thread-local oom_during_evac flag to indicate that any attempt
  // to evacuate should simply return the forwarding pointer instead (which is safe now).
  ShenandoahThreadLocalData::set_oom_during_evac(Thread::current(), true);
}

void ShenandoahEvacOOMHandler::register_thread(Thread* thr) {
  assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must not be set");

  ShenandoahEvacOOMCounter* counter = counter_for_thread(thr);
  if (!counter->try_increment()) {
    // Counter has OOM_MARKER_MASK set, loop until no more threads in evac
    wait_for_no_evac_threads();
  }
}

void ShenandoahEvacOOMHandler::unregister_thread(Thread* thr) {
  if (!ShenandoahThreadLocalData::is_oom_during_evac(thr)) {
    counter_for_thread(thr)->decrement();
  } else {
    // If we get here, the current thread has already gone through the
    // OOM-during-evac protocol and has thus either never entered or successfully left
    // the evacuation region. Simply flip its TL oom-during-evac flag back off.
    ShenandoahThreadLocalData::set_oom_during_evac(thr, false);
  }
  assert(!ShenandoahThreadLocalData::is_oom_during_evac(thr), "TL oom-during-evac must be turned off");
}

void ShenandoahEvacOOMHandler::handle_out_of_memory_during_evacuation() {
  assert(ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "sanity");
  assert(!ShenandoahThreadLocalData::is_oom_during_evac(Thread::current()), "TL oom-during-evac must not be set");

  ShenandoahEvacOOMCounter* self = counter_for_thread(Thread::current());
  assert(self->unmasked_count() > 0, "sanity");

  for (int i = 0; i < _num_counters; i++) {
    ShenandoahEvacOOMCounter* counter = &_threads_in_evac[i];
    counter->set_oom_bit(counter == self);
  }

  wait_for_no_evac_threads();
}

void ShenandoahEvacOOMHandler::clear() {
  assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "must be at a safepoint");
  for (int i = 0; i < _num_counters; i++) {
    _threads_in_evac[i].clear();
  }
}
