mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
Allow character devices to block write attempts until there is more space.
This commit is contained in:
parent
49b63281a0
commit
e452303c66
Notes:
sideshowbarker
2024-07-19 16:02:08 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/e452303c664
21 changed files with 39 additions and 7 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue