Serenity Operating System
at hosted 150 lines 4.2 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/HashTable.h> 28#include <AK/StdLibExtras.h> 29#include <AK/StringView.h> 30#include <Kernel/FileSystem/FIFO.h> 31#include <Kernel/FileSystem/FileDescription.h> 32#include <Kernel/Lock.h> 33#include <Kernel/Process.h> 34#include <Kernel/Thread.h> 35 36//#define FIFO_DEBUG 37 38namespace Kernel { 39 40Lockable<HashTable<FIFO*>>& all_fifos() 41{ 42 static Lockable<HashTable<FIFO*>>* s_table; 43 if (!s_table) 44 s_table = new Lockable<HashTable<FIFO*>>; 45 return *s_table; 46} 47 48static int s_next_fifo_id = 1; 49 50NonnullRefPtr<FIFO> FIFO::create(uid_t uid) 51{ 52 return adopt(*new FIFO(uid)); 53} 54 55NonnullRefPtr<FileDescription> FIFO::open_direction(FIFO::Direction direction) 56{ 57 auto description = FileDescription::create(*this); 58 attach(direction); 59 description->set_fifo_direction({}, direction); 60 return description; 61} 62 63FIFO::FIFO(uid_t uid) 64 : m_uid(uid) 65{ 66 LOCKER(all_fifos().lock()); 67 all_fifos().resource().set(this); 68 m_fifo_id = ++s_next_fifo_id; 69} 70 71FIFO::~FIFO() 72{ 73 LOCKER(all_fifos().lock()); 74 all_fifos().resource().remove(this); 75} 76 77void FIFO::attach(Direction direction) 78{ 79 if (direction == Direction::Reader) { 80 ++m_readers; 81#ifdef FIFO_DEBUG 82 klog() << "open reader (" << m_readers << ")"; 83#endif 84 } else if (direction == Direction::Writer) { 85 ++m_writers; 86#ifdef FIFO_DEBUG 87 klog() << "open writer (" << m_writers << ")"; 88#endif 89 } 90} 91 92void FIFO::detach(Direction direction) 93{ 94 if (direction == Direction::Reader) { 95#ifdef FIFO_DEBUG 96 klog() << "close reader (" << m_readers << " - 1)"; 97#endif 98 ASSERT(m_readers); 99 --m_readers; 100 } else if (direction == Direction::Writer) { 101#ifdef FIFO_DEBUG 102 klog() << "close writer (" << m_writers << " - 1)"; 103#endif 104 ASSERT(m_writers); 105 --m_writers; 106 } 107} 108 109bool FIFO::can_read(const FileDescription&) const 110{ 111 return !m_buffer.is_empty() || !m_writers; 112} 113 114bool FIFO::can_write(const FileDescription&) const 115{ 116 return m_buffer.space_for_writing() || !m_readers; 117} 118 119ssize_t FIFO::read(FileDescription&, u8* buffer, ssize_t size) 120{ 121 if (!m_writers && m_buffer.is_empty()) 122 return 0; 123#ifdef FIFO_DEBUG 124 dbg() << "fifo: read(" << size << ")\n"; 125#endif 126 ssize_t nread = m_buffer.read(buffer, size); 127#ifdef FIFO_DEBUG 128 dbg() << " -> read (" << String::format("%c", buffer[0]) << ") " << nread; 129#endif 130 return nread; 131} 132 133ssize_t FIFO::write(FileDescription&, const u8* buffer, ssize_t size) 134{ 135 if (!m_readers) { 136 Thread::current->send_signal(SIGPIPE, Process::current); 137 return -EPIPE; 138 } 139#ifdef FIFO_DEBUG 140 dbg() << "fifo: write(" << (const void*)buffer << ", " << size << ")"; 141#endif 142 return m_buffer.write(buffer, size); 143} 144 145String FIFO::absolute_path(const FileDescription&) const 146{ 147 return String::format("fifo:%u", m_fifo_id); 148} 149 150}