Newer
Older
minerva / Kernel / Tasks / HostnameContext.cpp
@minerva minerva on 13 Jul 2 KB Initial commit
/*
 * Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <AK/Atomic.h>
#include <AK/Singleton.h>
#include <Kernel/Sections.h>
#include <Kernel/Tasks/HostnameContext.h>

namespace Kernel {

static Atomic<u64> s_hostname_context_id = 0;
static Singleton<RecursiveSpinlockProtected<HostnameContext::List, LockRank::None>> s_all_instances {};

UNMAP_AFTER_INIT ErrorOr<NonnullRefPtr<HostnameContext>> HostnameContext::create_initial()
{
    return create_with_name("courage"sv);
}

ErrorOr<NonnullRefPtr<HostnameContext>> HostnameContext::create_with_name(StringView name)
{
    return s_all_instances->with([&](auto& list) -> ErrorOr<NonnullRefPtr<HostnameContext>> {
        auto hostname_context = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) HostnameContext(name)));
        list.append(hostname_context);
        return hostname_context;
    });
}

ErrorOr<NonnullRefPtr<HostnameContext>> HostnameContext::hostname_context_for_id(int id)
{
    if (id < 0)
        return Error::from_errno(EINVAL);
    auto index = static_cast<IndexID>(id);
    return s_all_instances->with([&](auto& list) -> ErrorOr<NonnullRefPtr<HostnameContext>> {
        for (auto& hostname_context : list) {
            if (hostname_context.id() == index)
                return hostname_context;
        }
        return Error::from_errno(ESRCNOTFOUND);
    });
}

void HostnameContext::set_attached(Badge<Process>)
{
    m_attach_count.with([&](auto& my_attach_count) {
        my_attach_count++;
        s_all_instances->with([&](auto& list) {
            // NOTE: It could happen that we have been detached from the
            // global list but a Process got a reference and wants to
            // attach so now re-attach this context.
            if (!list.contains(*this))
                list.append(*this);
        });
    });
}

void HostnameContext::detach(Badge<Process>)
{
    VERIFY(ref_count() > 0);
    m_attach_count.with([&](auto& my_attach_count) {
        VERIFY(my_attach_count > 0);
        my_attach_count--;
        if (my_attach_count == 0) {
            s_all_instances->with([&](auto&) {
                m_list_node.remove();
            });
        }
    });
}

HostnameContext::HostnameContext(StringView name)
    : m_id(s_hostname_context_id.fetch_add(1))
{
    m_buffer.with([name](auto& buffer) {
        buffer.store_characters(name);
    });
}

}