// 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

#pragma once

#include <kernel/event.h>
#include <kernel/thread.h>
#include <object/dispatcher.h>
#include <object/futex_context.h>
#include <object/handle.h>
#include <object/job_policy.h>
#include <object/thread_dispatcher.h>
#include <vm/vm_aspace.h>

#include <zircon/syscalls/object.h>
#include <zircon/types.h>
#include <fbl/array.h>
#include <fbl/canary.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/mutex.h>
#include <fbl/name.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fbl/string_piece.h>

class JobDispatcher;

class ProcessDispatcher final
    : public SoloDispatcher<ProcessDispatcher, ZX_DEFAULT_PROCESS_RIGHTS> {
public:
    static zx_status_t Create(
        fbl::RefPtr<JobDispatcher> job, fbl::StringPiece name, uint32_t flags,
        fbl::RefPtr<Dispatcher>* dispatcher, zx_rights_t* rights,
        fbl::RefPtr<VmAddressRegionDispatcher>* root_vmar_disp,
        zx_rights_t* root_vmar_rights);

    // Traits to belong in the parent job's raw list.
    struct JobListTraitsRaw {
        static fbl::DoublyLinkedListNodeState<ProcessDispatcher*>& node_state(
            ProcessDispatcher& obj) {
            return obj.dll_job_raw_;
        }
    };

    // Traits to belong in the parent job's list.
    struct JobListTraits {
        static fbl::SinglyLinkedListNodeState<fbl::RefPtr<ProcessDispatcher>>& node_state(
            ProcessDispatcher& obj) {
            return obj.dll_job_;
        }
    };

    static ProcessDispatcher* GetCurrent() {
        ThreadDispatcher* current = ThreadDispatcher::GetCurrent();
        DEBUG_ASSERT(current);
        return current->process();
    }

    // Dispatcher implementation
    zx_obj_type_t get_type() const final { return ZX_OBJ_TYPE_PROCESS; }
    void on_zero_handles() final;
    zx_koid_t get_related_koid() const final;

    ~ProcessDispatcher() final;

    // state of the process
    enum class State {
        INITIAL, // initial state, no thread present in process
        RUNNING, // first thread has started and is running
        DYING,   // process has delivered kill signal to all threads
        DEAD,    // all threads have entered DEAD state and potentially dropped refs on process
    };

    // Performs initialization on a newly constructed ProcessDispatcher
    // If this fails, then the object is invalid and should be deleted
    zx_status_t Initialize();

    // Maps a |handle| to an integer which can be given to usermode as a
    // handle value. Uses Handle->base_value() plus additional mixing.
    zx_handle_t MapHandleToValue(const Handle* handle) const;
    zx_handle_t MapHandleToValue(const HandleOwner& handle) const;

    // Maps a handle value into a Handle as long we can verify that
    // it belongs to this process. Use |skip_policy = true| for testing that
    // a handle is valid without potentially triggering a job policy exception.
    Handle* GetHandleLocked(
        zx_handle_t handle_value, bool skip_policy = false) TA_REQ(handle_table_lock_);

    // Adds |handle| to this process handle list. The handle->process_id() is
    // set to this process id().
    void AddHandle(HandleOwner handle);
    void AddHandleLocked(HandleOwner handle) TA_REQ(handle_table_lock_);

    // Removes the Handle corresponding to |handle_value| from this process
    // handle list.
    HandleOwner RemoveHandle(zx_handle_t handle_value);
    HandleOwner RemoveHandleLocked(zx_handle_t handle_value) TA_REQ(handle_table_lock_);

    // Remove all of an array of |user_handles| from the
    // process. Returns ZX_OK if all of the handles were removed, and
    // returns ZX_ERR_BAD_HANDLE if any were not.
    zx_status_t RemoveHandles(user_in_ptr<const zx_handle_t> user_handles,
                              size_t num_handles);

    // Get the dispatcher corresponding to this handle value.
    template <typename T>
    zx_status_t GetDispatcher(zx_handle_t handle_value,
                              fbl::RefPtr<T>* dispatcher) {
        return GetDispatcherAndRights(handle_value, dispatcher, nullptr);
    }

    // Get the dispatcher and the rights corresponding to this handle value.
    template <typename T>
    zx_status_t GetDispatcherAndRights(zx_handle_t handle_value,
                                       fbl::RefPtr<T>* dispatcher,
                                       zx_rights_t* out_rights) {
        fbl::RefPtr<Dispatcher> generic_dispatcher;
        auto status = GetDispatcherInternal(handle_value, &generic_dispatcher, out_rights);
        if (status != ZX_OK)
            return status;
        *dispatcher = DownCastDispatcher<T>(&generic_dispatcher);
        if (!*dispatcher)
            return ZX_ERR_WRONG_TYPE;
        return ZX_OK;
    }

    // Get the dispatcher corresponding to this handle value, after
    // checking that this handle has the desired rights.
    // Returns the rights the handle currently has.
    template <typename T>
    zx_status_t GetDispatcherWithRights(zx_handle_t handle_value,
                                        zx_rights_t desired_rights,
                                        fbl::RefPtr<T>* dispatcher,
                                        zx_rights_t* out_rights) {
        fbl::RefPtr<Dispatcher> generic_dispatcher;
        auto status = GetDispatcherWithRightsInternal(handle_value,
                                                      desired_rights,
                                                      &generic_dispatcher,
                                                      out_rights);
        if (status != ZX_OK)
            return status;
        *dispatcher = DownCastDispatcher<T>(&generic_dispatcher);
        if (!*dispatcher)
            return ZX_ERR_WRONG_TYPE;
        return ZX_OK;
    }

    // Get the dispatcher corresponding to this handle value, after
    // checking that this handle has the desired rights.
    template <typename T>
    zx_status_t GetDispatcherWithRights(zx_handle_t handle_value,
                                        zx_rights_t desired_rights,
                                        fbl::RefPtr<T>* dispatcher) {
        return GetDispatcherWithRights(handle_value, desired_rights, dispatcher, nullptr);
    }

    zx_koid_t GetKoidForHandle(zx_handle_t handle_value);

    bool IsHandleValid(zx_handle_t handle_value);
    bool IsHandleValidNoPolicyCheck(zx_handle_t handle_value);

    // Calls the provided
    // |zx_status_t func(zx_handle_t, zx_rights_t, fbl::RefPtr<Dispatcher>)|
    // on every handle owned by the process. Stops if |func| returns an error,
    // returning the error value.
    template <typename T>
    zx_status_t ForEachHandle(T func) const {
        Guard<fbl::Mutex> guard{&handle_table_lock_};
        for (const auto& handle : handles_) {
            const Dispatcher* dispatcher = handle.dispatcher().get();
            zx_status_t s = func(MapHandleToValue(&handle), handle.rights(),
                                 dispatcher);
            if (s != ZX_OK) {
                return s;
            }
        }
        return ZX_OK;
    }

    // accessors
    Lock<fbl::Mutex>* handle_table_lock() TA_RET_CAP(handle_table_lock_) {
        return &handle_table_lock_;
    }
    FutexContext* futex_context() { return &futex_context_; }
    State state() const;
    fbl::RefPtr<VmAspace> aspace() { return aspace_; }
    fbl::RefPtr<JobDispatcher> job();

    void get_name(char out_name[ZX_MAX_NAME_LEN]) const final;
    zx_status_t set_name(const char* name, size_t len) final;

    void Exit(int64_t retcode) __NO_RETURN;
    void Kill();

    // Suspends the process.
    //
    // Suspending a process causes all child threads to suspend as well as any new children
    // that are added until the process is resumed. Suspend() is cumulative, so the process
    // will only resume once Resume() has been called an equal number of times.
    //
    // Returns ZX_OK on success, or ZX_ERR_BAD_STATE iff the process is dying or dead.
    zx_status_t Suspend();
    void Resume();

    // Syscall helpers
    zx_status_t GetInfo(zx_info_process_t* info);
    zx_status_t GetStats(zx_info_task_stats_t* stats);
    // NOTE: Code outside of the syscall layer should not typically know about
    // user_ptrs; do not use this pattern as an example.
    zx_status_t GetAspaceMaps(user_out_ptr<zx_info_maps_t> maps, size_t max,
                              size_t* actual, size_t* available);
    zx_status_t GetVmos(user_out_ptr<zx_info_vmo_t> vmos, size_t max,
                        size_t* actual, size_t* available);

    zx_status_t GetThreads(fbl::Array<zx_koid_t>* threads);

    // exception handling support
    zx_status_t SetExceptionPort(fbl::RefPtr<ExceptionPort> eport);
    // Returns true if a port had been set.
    bool ResetExceptionPort(bool debugger);
    fbl::RefPtr<ExceptionPort> exception_port();
    fbl::RefPtr<ExceptionPort> debugger_exception_port();
    // |eport| can either be the process's eport or that of any parent job.
    void OnExceptionPortRemoval(const fbl::RefPtr<ExceptionPort>& eport);

    // The following two methods can be slow and inaccurate and should only be
    // called from diagnostics code.
    uint32_t ThreadCount() const;
    size_t PageCount() const;

    // Look up a process given its koid.
    // Returns nullptr if not found.
    static fbl::RefPtr<ProcessDispatcher> LookupProcessById(zx_koid_t koid);

    // Look up a thread in this process given its koid.
    // Returns nullptr if not found.
    fbl::RefPtr<ThreadDispatcher> LookupThreadById(zx_koid_t koid);

    uintptr_t get_debug_addr() const;
    zx_status_t set_debug_addr(uintptr_t addr);

    // Checks the |condition| against the parent job's policy.
    //
    // Must be called by syscalls before performing an action represented by an
    // ZX_POL_xxxxx condition. If the return value is ZX_OK the action can
    // proceed; otherwise, the process is not allowed to perform the action,
    // and the status value should be returned to the usermode caller.
    //
    // E.g., in sys_channel_create:
    //
    //     auto up = ProcessDispatcher::GetCurrent();
    //     zx_status_t res = up->QueryBasicPolicy(ZX_POL_NEW_CHANNEL);
    //     if (res != ZX_OK) {
    //         // Channel creation denied by the calling process's
    //         // parent job's policy.
    //         return res;
    //     }
    //     // Ok to create a channel.
    zx_status_t QueryBasicPolicy(uint32_t condition) const;

    // Returns this job's timer slack policy.
    TimerSlack GetTimerSlackPolicy() const;

    // return a cached copy of the vdso code address or compute a new one
    uintptr_t vdso_code_address() {
        if (unlikely(vdso_code_address_ == 0)) {
            return cache_vdso_code_address();
        }
        return vdso_code_address_;
    }

private:
    // compute the vdso code address and store in vdso_code_address_
    uintptr_t cache_vdso_code_address();

    // The diagnostic code is allow to know about the internals of this code.
    friend void DumpProcessList();
    friend void KillProcess(zx_koid_t id);
    friend void DumpProcessMemoryUsage(const char* prefix, size_t min_pages);

    ProcessDispatcher(fbl::RefPtr<JobDispatcher> job, fbl::StringPiece name, uint32_t flags);

    ProcessDispatcher(const ProcessDispatcher&) = delete;
    ProcessDispatcher& operator=(const ProcessDispatcher&) = delete;


    zx_status_t GetDispatcherInternal(zx_handle_t handle_value, fbl::RefPtr<Dispatcher>* dispatcher,
                                      zx_rights_t* rights);

    zx_status_t GetDispatcherWithRightsInternal(zx_handle_t handle_value, zx_rights_t desired_rights,
                                                fbl::RefPtr<Dispatcher>* dispatcher_out,
                                                zx_rights_t* out_rights);

    void OnProcessStartForJobDebugger(ThreadDispatcher *t);

    // Thread lifecycle support.
    //
    // |suspended| indicates whether the parent process is currently suspended or not. If true,
    // the child thread must increment its own suspend count by one and transition to suspend.
    friend class ThreadDispatcher;
    zx_status_t AddThread(ThreadDispatcher* t, bool initial_thread, bool* suspended);
    void RemoveThread(ThreadDispatcher* t);

    void SetStateLocked(State) TA_REQ(get_lock());
    void FinishDeadTransition();

    // Kill all threads
    void KillAllThreadsLocked() TA_REQ(get_lock());

    // TODO(dbort): Add "canary_.Assert()" calls to methods.
    fbl::Canary<fbl::magic("PROC")> canary_;

    // the enclosing job
    const fbl::RefPtr<JobDispatcher> job_;

    // Policy set by the Job during Create().
    //
    // It is critical that this field is immutable as it will be accessed without synchronization.
    const JobPolicy policy_;

    // The process can belong to either of these lists independently.
    fbl::DoublyLinkedListNodeState<ProcessDispatcher*> dll_job_raw_;
    fbl::SinglyLinkedListNodeState<fbl::RefPtr<ProcessDispatcher>> dll_job_;

    uint32_t handle_rand_ = 0;

    // list of threads in this process
    using ThreadList = fbl::DoublyLinkedList<ThreadDispatcher*, ThreadDispatcher::ThreadListTraits>;
    ThreadList thread_list_ TA_GUARDED(get_lock());

    // our address space
    fbl::RefPtr<VmAspace> aspace_;

    // our list of handles
    mutable DECLARE_MUTEX(ProcessDispatcher) handle_table_lock_; // protects |handles_|.
    fbl::DoublyLinkedList<Handle*> handles_ TA_GUARDED(handle_table_lock_);

    FutexContext futex_context_;

    // our state
    State state_ TA_GUARDED(get_lock()) = State::INITIAL;

    // Suspend count; incremented on Suspend(), decremented on Resume().
    int suspend_count_ TA_GUARDED(get_lock()) = 0;

    // True if FinishDeadTransition has been called.
    // This is used as a sanity check only.
    bool completely_dead_ = false;

    // process return code
    int64_t retcode_ = 0;

    // Exception ports bound to the process.
    fbl::RefPtr<ExceptionPort> exception_port_ TA_GUARDED(get_lock());
    fbl::RefPtr<ExceptionPort> debugger_exception_port_ TA_GUARDED(get_lock());

    // This is the value of _dl_debug_addr from ld.so.
    // See third_party/ulib/musl/ldso/dynlink.c.
    uintptr_t debug_addr_ TA_GUARDED(get_lock()) = 0;

    // This is a cache of aspace()->vdso_code_address().
    uintptr_t vdso_code_address_ = 0;

    // The user-friendly process name. For debug purposes only. That
    // is, there is no mechanism to mint a handle to a process via this name.
    fbl::Name<ZX_MAX_NAME_LEN> name_;
};

const char* StateToString(ProcessDispatcher::State state);
