Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Singleton.h>
8#include <Kernel/API/POSIX/errno.h>
9#include <Kernel/Debug.h>
10#include <Kernel/FileSystem/OpenFileDescription.h>
11#include <Kernel/Sections.h>
12#include <Kernel/TTY/MasterPTY.h>
13#include <Kernel/TTY/PTYMultiplexer.h>
14
15namespace Kernel {
16
17static Singleton<PTYMultiplexer> s_the;
18
19PTYMultiplexer& PTYMultiplexer::the()
20{
21 return *s_the;
22}
23
24UNMAP_AFTER_INIT PTYMultiplexer::PTYMultiplexer()
25 : CharacterDevice(5, 2)
26{
27 m_freelist.with([&](auto& freelist) {
28 freelist.ensure_capacity(max_pty_pairs);
29 for (int i = max_pty_pairs; i > 0; --i)
30 freelist.unchecked_append(i - 1);
31 });
32}
33
34UNMAP_AFTER_INIT PTYMultiplexer::~PTYMultiplexer() = default;
35
36UNMAP_AFTER_INIT void PTYMultiplexer::initialize()
37{
38 MUST(the().after_inserting());
39}
40
41ErrorOr<NonnullRefPtr<OpenFileDescription>> PTYMultiplexer::open(int options)
42{
43 return m_freelist.with([&](auto& freelist) -> ErrorOr<NonnullRefPtr<OpenFileDescription>> {
44 if (freelist.is_empty())
45 return EBUSY;
46
47 auto master_index = freelist.take_last();
48 auto master = TRY(MasterPTY::try_create(master_index));
49 dbgln_if(PTMX_DEBUG, "PTYMultiplexer::open: Vending master {}", master->index());
50 auto description = TRY(OpenFileDescription::try_create(*master));
51 description->set_rw_mode(options);
52 description->set_file_flags(options);
53 return description;
54 });
55}
56
57void PTYMultiplexer::notify_master_destroyed(Badge<MasterPTY>, unsigned index)
58{
59 m_freelist.with([&](auto& freelist) {
60 freelist.append(index);
61 dbgln_if(PTMX_DEBUG, "PTYMultiplexer: {} added to freelist", index);
62 });
63}
64
65}