Allow character devices to block write attempts until there is more space.

This commit is contained in:
Andreas Kling 2019-01-15 09:17:22 +01:00
parent 49b63281a0
commit e452303c66
Notes: sideshowbarker 2024-07-19 16:02:08 +09:00
21 changed files with 39 additions and 7 deletions

View file

@ -19,6 +19,7 @@ public:
virtual ~Console() override; virtual ~Console() override;
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
virtual bool can_write(Process&) const override { return true; }
virtual ssize_t read(byte* buffer, size_t size) override; virtual ssize_t read(byte* buffer, size_t size) override;
virtual ssize_t write(const byte* data, size_t size) override; virtual ssize_t write(const byte* data, size_t size) override;

View file

@ -16,6 +16,8 @@ public:
bool is_empty() const { return m_read_buffer_index >= m_read_buffer->size() && m_write_buffer->is_empty(); } bool is_empty() const { return m_read_buffer_index >= m_read_buffer->size() && m_write_buffer->is_empty(); }
size_t bytes_in_write_buffer() const { return m_write_buffer->size(); }
private: private:
void flip(); void flip();

View file

@ -51,7 +51,7 @@ bool FIFO::can_read() const
bool FIFO::can_write() const bool FIFO::can_write() const
{ {
return true; return m_buffer.bytes_in_write_buffer() < 4096;
} }
ssize_t FIFO::read(byte* buffer, size_t size) ssize_t FIFO::read(byte* buffer, size_t size)

View file

@ -40,6 +40,7 @@ private:
virtual ssize_t read(byte* buffer, size_t) override; virtual ssize_t read(byte* buffer, size_t) override;
virtual ssize_t write(const byte* buffer, size_t) override; virtual ssize_t write(const byte* buffer, size_t) override;
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
virtual bool can_write(Process&) const override { return true; }
void emit(byte); void emit(byte);

View file

@ -36,6 +36,11 @@ bool MasterPTY::has_data_available_for_reading(Process&) const
return !m_buffer.is_empty(); return !m_buffer.is_empty();
} }
bool MasterPTY::can_write(Process&) const
{
return m_buffer.bytes_in_write_buffer() < 4096;
}
void MasterPTY::on_slave_write(const byte* data, size_t size) void MasterPTY::on_slave_write(const byte* data, size_t size)
{ {
m_buffer.write(data, size); m_buffer.write(data, size);

View file

@ -14,6 +14,7 @@ public:
virtual ssize_t read(byte*, size_t) override; virtual ssize_t read(byte*, size_t) override;
virtual ssize_t write(const byte*, size_t) override; virtual ssize_t write(const byte*, size_t) override;
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
virtual bool can_write(Process&) const override;
virtual bool is_master_pty() const override { return true; } virtual bool is_master_pty() const override { return true; }
String pts_name() const; String pts_name() const;

View file

@ -15,6 +15,7 @@ public:
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
virtual ssize_t read(byte* buffer, size_t) override; virtual ssize_t read(byte* buffer, size_t) override;
virtual ssize_t write(const byte* buffer, size_t) override; virtual ssize_t write(const byte* buffer, size_t) override;
virtual bool can_write(Process&) const override { return true; }
private: private:
// ^IRQHandler // ^IRQHandler

View file

@ -1023,7 +1023,7 @@ ssize_t Process::sys$write(int fd, const void* data, size_t size)
#ifdef IO_DEBUG #ifdef IO_DEBUG
dbgprintf("while %u < %u\n", nwritten, size); dbgprintf("while %u < %u\n", nwritten, size);
#endif #endif
if (!descriptor->can_write()) { if (!descriptor->can_write(*this)) {
#ifdef IO_DEBUG #ifdef IO_DEBUG
dbgprintf("block write on %d\n", fd); dbgprintf("block write on %d\n", fd);
#endif #endif

View file

@ -59,7 +59,7 @@ bool Scheduler::pick_next()
if (process.state() == Process::BlockedWrite) { if (process.state() == Process::BlockedWrite) {
ASSERT(process.m_blocked_fd != -1); ASSERT(process.m_blocked_fd != -1);
if (process.m_fds[process.m_blocked_fd].descriptor->can_write()) if (process.m_fds[process.m_blocked_fd].descriptor->can_write(process))
process.unblock(); process.unblock();
return true; return true;
} }

View file

@ -29,3 +29,8 @@ void SlavePTY::on_tty_write(const byte* data, size_t size)
{ {
m_master->on_slave_write(data, size); m_master->on_slave_write(data, size);
} }
bool SlavePTY::can_write(Process& process) const
{
return m_master->can_write(process);
}

View file

@ -16,6 +16,7 @@ public:
protected: protected:
virtual void on_tty_write(const byte*, size_t) override; virtual void on_tty_write(const byte*, size_t) override;
virtual bool can_write(Process&) const override;
private: private:
unsigned m_index; unsigned m_index;

View file

@ -47,6 +47,11 @@ bool TTY::has_data_available_for_reading(Process&) const
return !m_buffer.is_empty(); return !m_buffer.is_empty();
} }
bool TTY::can_write(Process&) const
{
return true;
}
void TTY::emit(byte ch) void TTY::emit(byte ch)
{ {
if (should_generate_signals()) { if (should_generate_signals()) {

View file

@ -13,6 +13,7 @@ public:
virtual ssize_t read(byte*, size_t) override; virtual ssize_t read(byte*, size_t) override;
virtual ssize_t write(const byte*, size_t) override; virtual ssize_t write(const byte*, size_t) override;
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
virtual bool can_write(Process&) const override;
virtual int ioctl(Process&, unsigned request, unsigned arg) override final; virtual int ioctl(Process&, unsigned request, unsigned arg) override final;
virtual String tty_name() const = 0; virtual String tty_name() const = 0;

View file

@ -13,6 +13,7 @@ public:
RetainPtr<FileDescriptor> open(int options); RetainPtr<FileDescriptor> open(int options);
virtual bool has_data_available_for_reading(Process&) const = 0; virtual bool has_data_available_for_reading(Process&) const = 0;
virtual bool can_write(Process&) const = 0;
virtual ssize_t read(byte* buffer, size_t bufferSize) = 0; virtual ssize_t read(byte* buffer, size_t bufferSize) = 0;
virtual ssize_t write(const byte* buffer, size_t bufferSize) = 0; virtual ssize_t write(const byte* buffer, size_t bufferSize) = 0;

View file

@ -165,12 +165,14 @@ ssize_t FileDescriptor::write(const byte* data, size_t size)
return -1; return -1;
} }
bool FileDescriptor::can_write() bool FileDescriptor::can_write(Process& process)
{ {
if (is_fifo()) { if (is_fifo()) {
ASSERT(fifo_direction() == FIFO::Writer); ASSERT(fifo_direction() == FIFO::Writer);
return m_fifo->can_write(); return m_fifo->can_write();
} }
if (m_vnode->isCharacterDevice())
return m_vnode->characterDevice()->can_write(process);
return true; return true;
} }

View file

@ -30,7 +30,7 @@ public:
int stat(Unix::stat*); int stat(Unix::stat*);
bool has_data_available_for_reading(Process&); bool has_data_available_for_reading(Process&);
bool can_write(); bool can_write(Process&);
ssize_t get_dir_entries(byte* buffer, size_t); ssize_t get_dir_entries(byte* buffer, size_t);

View file

@ -6,10 +6,11 @@ class FullDevice final : public CharacterDevice {
AK_MAKE_ETERNAL AK_MAKE_ETERNAL
public: public:
FullDevice(); FullDevice();
virtual ~FullDevice(); virtual ~FullDevice() override;
virtual ssize_t read(byte* buffer, size_t bufferSize) override; virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override; virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
virtual bool can_write(Process&) const override { return true; }
}; };

View file

@ -10,6 +10,7 @@ public:
virtual ssize_t read(byte* buffer, size_t bufferSize) override; virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override; virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
virtual bool can_write(Process&) const override { return true; }
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
}; };

View file

@ -11,5 +11,6 @@ public:
virtual ssize_t read(byte* buffer, size_t bufferSize) override; virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override; virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
virtual bool can_write(Process&) const override { return true; }
}; };

View file

@ -11,5 +11,6 @@ public:
virtual ssize_t read(byte* buffer, size_t bufferSize) override; virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override; virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
virtual bool has_data_available_for_reading(Process&) const override; virtual bool has_data_available_for_reading(Process&) const override;
virtual bool can_write(Process&) const override { return true; }
}; };

View file

@ -8,7 +8,9 @@ public:
virtual ~GUIEventDevice() override; virtual ~GUIEventDevice() override;
private: private:
virtual bool has_data_available_for_reading(Process&) const override; // ^CharacterDevice
virtual ssize_t read(byte* buffer, size_t bufferSize) override; virtual ssize_t read(byte* buffer, size_t bufferSize) override;
virtual ssize_t write(const byte* buffer, size_t bufferSize) override; virtual ssize_t write(const byte* buffer, size_t bufferSize) override;
virtual bool has_data_available_for_reading(Process&) const override;
virtual bool can_write(Process&) const override { return true; }
}; };