/*
 * Copyright (c) 2011, 2019, Oracle and/or its affiliates. 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 "jfr/recorder/storage/jfrBuffer.hpp"
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/thread.inline.hpp"

static const u1* const MUTEX_CLAIM = NULL;

JfrBuffer::JfrBuffer() : _next(NULL),
                         _prev(NULL),
                         _identity(NULL),
                         _pos(NULL),
                         _top(NULL),
                         _flags(0),
                         _header_size(0),
                         _size(0) {}

bool JfrBuffer::initialize(size_t header_size, size_t size, const void* id /* NULL */) {
  _header_size = (u2)header_size;
  _size = (u4)(size / BytesPerWord);
  assert(_identity == NULL, "invariant");
  _identity = id;
  set_pos(start());
  set_top(start());
  assert(_next == NULL, "invariant");
  assert(free_size() == size, "invariant");
  assert(!transient(), "invariant");
  assert(!lease(), "invariant");
  assert(!retired(), "invariant");
  return true;
}

void JfrBuffer::reinitialize(bool exclusion /* false */) {
  assert(!lease(), "invariant");
  assert(!transient(), "invariant");
  set_pos(start());
  if (exclusion != excluded()) {
    // update
    if (exclusion) {
      set_excluded();
    } else {
      clear_excluded();
    }
  }
  clear_retired();
  set_top(start());
}

void JfrBuffer::concurrent_reinitialization() {
  concurrent_top();
  assert(!lease(), "invariant");
  assert(!transient(), "invariant");
  set_pos(start());
  set_concurrent_top(start());
  clear_retired();
}

size_t JfrBuffer::discard() {
  size_t discard_size = unflushed_size();
  set_top(pos());
  return discard_size;
}

const u1* JfrBuffer::stable_top() const {
  const u1* current_top;
  do {
    current_top = Atomic::load(&_top);
  } while (MUTEX_CLAIM == current_top);
  return current_top;
}

const u1* JfrBuffer::top() const {
  return _top;
}

void JfrBuffer::set_top(const u1* new_top) {
  _top = new_top;
}

const u1* JfrBuffer::concurrent_top() const {
  do {
    const u1* current_top = stable_top();
    if (Atomic::cmpxchg(MUTEX_CLAIM, &_top, current_top) == current_top) {
      return current_top;
    }
  } while (true);
}

void JfrBuffer::set_concurrent_top(const u1* new_top) {
  assert(new_top != MUTEX_CLAIM, "invariant");
  assert(new_top <= end(), "invariant");
  assert(new_top >= start(), "invariant");
  assert(top() == MUTEX_CLAIM, "invariant");
  OrderAccess::storestore();
  _top = new_top;
}

size_t JfrBuffer::unflushed_size() const {
  return pos() - stable_top();
}

void JfrBuffer::acquire(const void* id) {
  assert(id != NULL, "invariant");
  const void* current_id;
  do {
    current_id = Atomic::load(&_identity);
  } while (current_id != NULL || Atomic::cmpxchg(id, &_identity, current_id) != current_id);
}

bool JfrBuffer::try_acquire(const void* id) {
  assert(id != NULL, "invariant");
  const void* const current_id = Atomic::load(&_identity);
  return current_id == NULL && Atomic::cmpxchg(id, &_identity, current_id) == current_id;
}

void JfrBuffer::release() {
  OrderAccess::storestore();
  _identity = NULL;
}

bool JfrBuffer::acquired_by(const void* id) const {
  return identity() == id;
}

bool JfrBuffer::acquired_by_self() const {
  return acquired_by(Thread::current());
}

#ifdef ASSERT
static bool validate_to(const JfrBuffer* const to, size_t size) {
  assert(to != NULL, "invariant");
  assert(to->acquired_by_self(), "invariant");
  assert(to->free_size() >= size, "invariant");
  return true;
}

static bool validate_concurrent_this(const JfrBuffer* const t, size_t size) {
  assert(t->top() == MUTEX_CLAIM, "invariant");
  return true;
}

static bool validate_this(const JfrBuffer* const t, size_t size) {
  assert(t->top() + size <= t->pos(), "invariant");
  return true;
}
#endif // ASSERT

void JfrBuffer::move(JfrBuffer* const to, size_t size) {
  assert(validate_to(to, size), "invariant");
  assert(validate_this(this, size), "invariant");
  const u1* current_top = top();
  assert(current_top != NULL, "invariant");
  memcpy(to->pos(), current_top, size);
  to->set_pos(size);
  to->release();
  set_top(current_top + size);
}

void JfrBuffer::concurrent_move_and_reinitialize(JfrBuffer* const to, size_t size) {
  assert(validate_to(to, size), "invariant");
  const u1* current_top = concurrent_top();
  assert(validate_concurrent_this(this, size), "invariant");
  const size_t actual_size = MIN2(size, (size_t)(pos() - current_top));
  assert(actual_size <= size, "invariant");
  memcpy(to->pos(), current_top, actual_size);
  to->set_pos(actual_size);
  set_pos(start());
  to->release();
  set_concurrent_top(start());
}

enum FLAG {
  RETIRED = 1,
  TRANSIENT = 2,
  LEASE = 4,
  EXCLUDED = 8
};

bool JfrBuffer::transient() const {
  return (u1)TRANSIENT == (_flags & (u1)TRANSIENT);
}

void JfrBuffer::set_transient() {
  _flags |= (u1)TRANSIENT;
  assert(transient(), "invariant");
}

void JfrBuffer::clear_transient() {
  if (transient()) {
    _flags ^= (u1)TRANSIENT;
  }
  assert(!transient(), "invariant");
}

bool JfrBuffer::lease() const {
  return (u1)LEASE == (_flags & (u1)LEASE);
}

void JfrBuffer::set_lease() {
  _flags |= (u1)LEASE;
  assert(lease(), "invariant");
}

void JfrBuffer::clear_lease() {
  if (lease()) {
    _flags ^= (u1)LEASE;
  }
  assert(!lease(), "invariant");
}

bool JfrBuffer::excluded() const {
  return (u1)EXCLUDED == (_flags & (u1)EXCLUDED);
}

void JfrBuffer::set_excluded() {
  _flags |= (u1)EXCLUDED;
  assert(excluded(), "invariant");
}

void JfrBuffer::clear_excluded() {
  if (excluded()) {
    OrderAccess::storestore();
    _flags ^= (u1)EXCLUDED;
  }
  assert(!excluded(), "invariant");
}

bool JfrBuffer::retired() const {
  return (_flags & (u1)RETIRED) == (u1)RETIRED;
}

void JfrBuffer::set_retired() {
  OrderAccess::storestore();
  _flags |= (u1)RETIRED;
}

void JfrBuffer::clear_retired() {
  if (retired()) {
    OrderAccess::storestore();
    _flags ^= (u1)RETIRED;
  }
}
