/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * 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.
 */

#ifndef __ARCH_GENERIC_LINUX_THREADINFO_HH__
#define __ARCH_GENERIC_LINUX_THREADINFO_HH__

#include "cpu/thread_context.hh"
#include "sim/system.hh"
#include "sim/vptr.hh"

namespace Linux {

class ThreadInfo
{
  private:
    ThreadContext *tc;
    System *sys;
    Addr pcbb;

    template <typename T>
    bool
    get_data(const char *symbol, T &data)
    {
        Addr addr = 0;
        if (!sys->workload->symtab(tc)->findAddress(symbol, addr)) {
            warn_once("Unable to find kernel symbol %s\n", symbol);
            warn_once("Kernel not compiled with task_struct info; can't get "
                      "currently executing task/process/thread name/ids!\n");
            return false;
        }

        data = tc->getVirtProxy().read<T>(addr, TheISA::GuestByteOrder);

        return true;
    }

  public:
    ThreadInfo(ThreadContext *_tc, Addr _pcbb = 0)
        : tc(_tc), sys(tc->getSystemPtr()), pcbb(_pcbb)
    {

    }
    ~ThreadInfo()
    {}

    inline Addr
    curThreadInfo()
    {
        if (!TheISA::CurThreadInfoImplemented)
            panic("curThreadInfo() not implemented for this ISA");

        Addr addr = pcbb;
        Addr sp;

        if (!addr)
            addr = tc->readMiscRegNoEffect(TheISA::CurThreadInfoReg);

        PortProxy &p = tc->getPhysProxy();
        p.readBlob(addr, &sp, sizeof(Addr));

        return sp & ~ULL(0x3fff);
    }

    inline Addr
    curTaskInfo(Addr thread_info = 0)
    {
        // Note that in Linux 4.10 the thread_info struct will no longer have a
        // pointer to the task_struct for arm64. See:
        // https://patchwork.kernel.org/patch/9333699/
        int32_t offset = 0;
        if (!get_data("thread_info_task", offset))
            return 0;

        if (!thread_info)
            thread_info = curThreadInfo();

        return tc->getVirtProxy().read<Addr>(thread_info + offset);
    }

    int32_t
    curTaskPIDFromTaskStruct(Addr task_struct) {
        int32_t offset = 0;
        if (!get_data("task_struct_pid", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskPID(Addr thread_info = 0)
    {
        return curTaskPIDFromTaskStruct(curTaskInfo(thread_info));
    }

    int32_t
    curTaskTGIDFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        if (!get_data("task_struct_tgid", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskTGID(Addr thread_info = 0)
    {
        return curTaskTGIDFromTaskStruct(curTaskInfo(thread_info));
    }

    int64_t
    curTaskStartFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        if (!get_data("task_struct_start_time", offset))
            return -1;

        // start_time is actually of type timespec, but if we just
        // grab the first long, we'll get the seconds out of it
        return tc->getVirtProxy().read<int64_t>(task_struct + offset);
    }

    int64_t
    curTaskStart(Addr thread_info = 0)
    {
        return curTaskStartFromTaskStruct(curTaskInfo(thread_info));
    }

    std::string
    curTaskNameFromTaskStruct(Addr task_struct)
    {
        int32_t offset = 0;
        int32_t size = 0;

        if (!get_data("task_struct_comm", offset))
            return "FailureIn_curTaskName";

        if (!get_data("task_struct_comm_size", size))
            return "FailureIn_curTaskName";

        char buffer[size + 1];
        tc->getVirtProxy().readString(buffer, task_struct + offset, size);

        return buffer;
    }

    std::string
    curTaskName(Addr thread_info = 0)
    {
        return curTaskNameFromTaskStruct(curTaskInfo(thread_info));
    }

    int32_t
    curTaskMmFromTaskStruct(Addr task_struct)
    {
        int32_t offset;
        if (!get_data("task_struct_mm", offset))
            return -1;

        return tc->getVirtProxy().read<int32_t>(task_struct + offset);
    }

    int32_t
    curTaskMm(Addr thread_info = 0)
    {
        return curTaskMmFromTaskStruct(curTaskInfo(thread_info));
    }
};

} // namespace Linux

#endif // __ARCH_GENERIC_LINUX_THREADINFO_HH__
