// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

// This file defines:
// * Initialization code for kernel/object module
// * Singleton instances and global locks
// * Helper functions
//
// TODO(dbort): Split this file into self-consistent pieces.

#include <trace.h>

#include <kernel/cmdline.h>

#include <lk/init.h>

#include <lib/oom.h>

#include <object/diagnostics.h>
#include <object/excp_port.h>
#include <object/job_dispatcher.h>
#include <object/policy_manager.h>
#include <object/port_dispatcher.h>
#include <object/process_dispatcher.h>

#include <fbl/function.h>

#include <zircon/types.h>

#define LOCAL_TRACE 0

// All jobs and processes are rooted at the |root_job|.
static fbl::RefPtr<JobDispatcher> root_job;

// The singleton policy manager, for jobs and processes. This is
// not a Dispatcher, just a plain class.
static PolicyManager* policy_manager;

zx_status_t SetSystemExceptionPort(fbl::RefPtr<ExceptionPort> eport) {
    DEBUG_ASSERT(eport->type() == ExceptionPort::Type::JOB);
    return root_job->SetExceptionPort(fbl::move(eport));
}

bool ResetSystemExceptionPort() {
    return root_job->ResetExceptionPort(false /* quietly */);
}

fbl::RefPtr<JobDispatcher> GetRootJobDispatcher() {
    return root_job;
}

PolicyManager* GetSystemPolicyManager() {
    return policy_manager;
}

// Counts and optionally prints all job/process descendants of a job.
namespace {
class OomJobEnumerator final : public JobEnumerator {
public:
    // If |prefix| is non-null, also prints each job/process.
    OomJobEnumerator(const char* prefix)
        : prefix_(prefix) { reset_counts(); }
    void reset_counts() {
        num_jobs_ = 0;
        num_processes_ = 0;
        num_running_processes_ = 0;
    }
    size_t num_jobs() const { return num_jobs_; }
    size_t num_processes() const { return num_processes_; }
    size_t num_running_processes() const { return num_running_processes_; }

private:
    bool OnJob(JobDispatcher* job) final {
        if (prefix_ != nullptr) {
            char name[ZX_MAX_NAME_LEN];
            job->get_name(name);
            printf("%sjob %6" PRIu64 " '%s'\n", prefix_, job->get_koid(), name);
        }
        num_jobs_++;
        return true;
    }
    bool OnProcess(ProcessDispatcher* process) final {
        // Since we want to free memory by actually killing something, only
        // count running processes that aren't attached to a debugger.
        // It's a race, but will stop us from re-killing a job that only has
        // blocked-by-debugger processes.
        zx_info_process_t info = {};
        process->GetInfo(&info);
        if (info.started && !info.exited && !info.debugger_attached) {
            num_running_processes_++;
        }
        if (prefix_ != nullptr) {
            const char* tag = "new";
            if (info.started) {
                tag = "run";
            }
            if (info.exited) {
                tag = "dead";
            }
            if (info.debugger_attached) {
                tag = "dbg";
            }
            char name[ZX_MAX_NAME_LEN];
            process->get_name(name);
            printf("%sproc %5" PRIu64 " %4s '%s'\n",
                   prefix_, process->get_koid(), tag, name);
        }
        num_processes_++;
        return true;
    }

    const char* prefix_;
    size_t num_jobs_;
    size_t num_processes_;
    size_t num_running_processes_;
};
} // namespace

// Called from a dedicated kernel thread when the system is low on memory.
static void oom_lowmem(size_t shortfall_bytes) {
    printf("OOM: oom_lowmem(shortfall_bytes=%zu) called\n", shortfall_bytes);
    printf("OOM: Process mapped committed bytes:\n");
    DumpProcessMemoryUsage("OOM:   ", /*min_pages=*/8 * MB / PAGE_SIZE);
    printf("OOM: Finding a job to kill...\n");

    OomJobEnumerator job_counter(nullptr);
    OomJobEnumerator job_printer("OOM:        + ");

    bool killed = false;
    int next = 3; // Used to print a few "up next" jobs.
    JobDispatcher::ForEachJobByImportance([&](JobDispatcher* job) {
        // TODO(dbort): Consider adding an "immortal" bit on jobs and skip them
        // here if they (and and all of their ancestors) have it set.
        bool kill = false;
        if (!killed) {
            // We want to kill a job that will actually free memory by dying, so
            // look for one with running process descendants (i.e., started,
            // non-exited, not blocked in a debugger).
            job_counter.reset_counts();
            job->EnumerateChildren(&job_counter, /*recurse=*/true);
            kill = job_counter.num_running_processes() > 0;
        }

        const char* tag;
        if (kill) {
            tag = "*KILL*";
        } else if (!killed) {
            tag = "(skip)";
        } else {
            tag = "(next)";
        }
        char name[ZX_MAX_NAME_LEN];
        job->get_name(name);
        printf("OOM:   %s job %6" PRIu64 " '%s'\n", tag, job->get_koid(), name);
        if (kill) {
            // Print the descendants of the job we're about to kill.
            job_printer.reset_counts();
            job->EnumerateChildren(&job_printer, /*recurse=*/true);
            printf("OOM:        = %zu running procs (%zu total), %zu jobs\n",
                   job_printer.num_running_processes(),
                   job_printer.num_processes(), job_printer.num_jobs());
            // TODO(dbort): Join on dying processes/jobs to make sure we've
            // freed memory before returning control to the OOM thread?
            // TODO(ZX-961): 'kill -9' these processes (which will require new
            // ProcessDispatcher features) so we can reclaim the memory of
            // processes that are stuck in a debugger or in the crashlogger.
            job->Kill();
            killed = true;
        } else if (killed) {
            if (--next == 0) {
                return ZX_ERR_STOP;
            }
        }
        return ZX_OK;
    });
}

static void object_glue_init(uint level) TA_NO_THREAD_SAFETY_ANALYSIS {
    HandleTableInit();
    root_job = JobDispatcher::CreateRootJob();
    policy_manager = PolicyManager::Create();
    PortDispatcher::Init();
    // Be sure to update kernel_cmdline.md if any of these defaults change.
    oom_init(cmdline_get_bool("kernel.oom.enable", true),
             ZX_SEC(cmdline_get_uint64("kernel.oom.sleep-sec", 1)),
             cmdline_get_uint64("kernel.oom.redline-mb", 50) * MB,
             oom_lowmem);
}

LK_INIT_HOOK(libobject, object_glue_init, LK_INIT_LEVEL_THREADING);
