/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "base/fiber.hh"

#if HAVE_VALGRIND
#include <valgrind/valgrind.h>
#endif

#include <sys/mman.h>
#include <unistd.h>

#include <cerrno>
#include <cstdio>
#include <cstring>

#include "base/logging.hh"

using namespace std;

namespace
{

/*
 * The PrimaryFiber class is a special case that attaches to the currently
 * executing context. That makes handling the "primary" fiber, aka the one
 * which most of gem5 is running under, no different than other Fibers.
 */
class PrimaryFiber : public Fiber
{
  public:
    PrimaryFiber() : Fiber(nullptr, 0) { setStarted(); }
    void main() { panic("PrimaryFiber main executed.\n"); }
};

PrimaryFiber _primaryFiber;

// A pointer to whatever the currently executing Fiber is.
Fiber *_currentFiber = &_primaryFiber;

// A pointer to the Fiber which is currently being started/initialized.
Fiber *startingFiber = nullptr;

} // anonymous namespace

void
Fiber::entryTrampoline()
{
    startingFiber->start();
}

Fiber::Fiber(size_t stack_size) : Fiber(primaryFiber(), stack_size)
{}

Fiber::Fiber(Fiber *link, size_t stack_size) :
    link(link), stack(nullptr), stackSize(stack_size), guardPage(nullptr),
    guardPageSize(sysconf(_SC_PAGE_SIZE)), started(false), _finished(false)
{
    if (stack_size) {
        guardPage = mmap(nullptr, guardPageSize + stack_size,
                         PROT_READ | PROT_WRITE,
                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (guardPage == (void *)MAP_FAILED) {
            perror("mmap");
            fatal("Could not mmap %d byte fiber stack.\n", stack_size);
        }
        stack = (void *)((uint8_t *)guardPage + guardPageSize);
        if (mprotect(guardPage, guardPageSize, PROT_NONE)) {
            perror("mprotect");
            fatal("Could not forbid access to fiber stack guard page.");
        }
    }
#if HAVE_VALGRIND
    valgrindStackId = VALGRIND_STACK_REGISTER(
            stack, (uint8_t *)stack + stack_size);
#endif
}

Fiber::~Fiber()
{
    panic_if(stack && _currentFiber == this, "Fiber stack is in use.");
#if HAVE_VALGRIND
    VALGRIND_STACK_DEREGISTER(valgrindStackId);
#endif
    if (guardPage)
        munmap(guardPage, guardPageSize + stackSize);
}

void
Fiber::createContext()
{
    // Set up a context for the new fiber, starting it in the trampoline.
    getcontext(&ctx);
    ctx.uc_stack.ss_sp = stack;
    ctx.uc_stack.ss_size = stackSize;
    ctx.uc_link = nullptr;
    makecontext(&ctx, &entryTrampoline, 0);

    // Swap to the new context so it can enter its start() function. It
    // will then swap itself back out and return here.
    startingFiber = this;
    panic_if(!_currentFiber, "No active Fiber object.");
    swapcontext(&_currentFiber->ctx, &ctx);

    // The new context is now ready and about to call main().
}

void
Fiber::start()
{
    // Avoid a dangling pointer.
    startingFiber = nullptr;

    setStarted();

    // Swap back to the parent context which is still considered "current",
    // now that we're ready to go.
    int ret M5_VAR_USED = swapcontext(&ctx, &_currentFiber->ctx);
    panic_if(ret == -1, strerror(errno));

    // Call main() when we're been reactivated for the first time.
    main();

    // main has returned, so this Fiber has finished. Switch to the "link"
    // Fiber.
    _finished = true;
    link->run();
}

void
Fiber::run()
{
    panic_if(_finished, "Fiber has already run to completion.");

    // If we're already running this fiber, we're done.
    if (_currentFiber == this)
        return;

    if (!started)
        createContext();

    // Switch out of the current Fiber's context and this one's in.
    Fiber *prev = _currentFiber;
    Fiber *next = this;
    _currentFiber = next;
    swapcontext(&prev->ctx, &next->ctx);
}

Fiber *Fiber::currentFiber() { return _currentFiber; }
Fiber *Fiber::primaryFiber() { return &_primaryFiber; }
