mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:42:44 +00:00 
			
		
		
		
	Implement a basic way for read() to block.
FileHandle gets a hasDataAvailableForRead() getter. If this returns true in sys$read(), the task will block(BlockedRead) + yield. The fd blocked on is stored in Task::m_fdBlockedOnRead. The scheduler then looks at the state of that fd during the unblock phase. This makes "sh" restful. :^) There's still some problem with the kernel not surviving the colonel task getting scheduled. I need to figure that out and fix it.
This commit is contained in:
		
							parent
							
								
									ba56f4afde
								
							
						
					
					
						commit
						c6f2890d8e
					
				
					 18 changed files with 86 additions and 17 deletions
				
			
		|  | @ -21,6 +21,11 @@ Console::~Console() | |||
| { | ||||
| } | ||||
| 
 | ||||
| bool Console::hasDataAvailableForRead() const | ||||
| { | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| ssize_t Console::read(byte* buffer, size_t bufferSize) | ||||
| { | ||||
|     // FIXME: Implement reading from the console.
 | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ public: | |||
|     Console(); | ||||
|     virtual ~Console() override; | ||||
| 
 | ||||
|     virtual bool hasDataAvailableForRead() const override; | ||||
|     virtual ssize_t read(byte* buffer, size_t size) override; | ||||
|     virtual ssize_t write(const byte* data, size_t size) override; | ||||
| 
 | ||||
|  |  | |||
|  | @ -86,6 +86,11 @@ Keyboard::~Keyboard() | |||
|     ASSERT_NOT_REACHED(); | ||||
| } | ||||
| 
 | ||||
| bool Keyboard::hasDataAvailableForRead() const | ||||
| { | ||||
|     return !m_queue.isEmpty(); | ||||
| } | ||||
| 
 | ||||
| ssize_t Keyboard::read(byte* buffer, size_t size) | ||||
| { | ||||
|     ssize_t nread = 0; | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ private: | |||
|     // ^CharacterDevice
 | ||||
|     virtual ssize_t read(byte* buffer, size_t) override; | ||||
|     virtual ssize_t write(const byte* buffer, size_t) override; | ||||
|     virtual bool hasDataAvailableForRead() const override; | ||||
| 
 | ||||
|     CircularQueue<byte, 16> m_queue; | ||||
|     byte m_modifiers { 0 }; | ||||
|  |  | |||
|  | @ -466,6 +466,14 @@ bool scheduleNewTask() | |||
|                 continue; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (task->state() == Task::BlockedRead) { | ||||
|             ASSERT(task->m_fdBlockedOnRead != -1); | ||||
|             if (task->m_fileHandles[task->m_fdBlockedOnRead]->hasDataAvailableForRead()) { | ||||
|                 task->unblock(); | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| #if 0 | ||||
|  | @ -619,6 +627,13 @@ ssize_t Task::sys$read(int fd, void* outbuf, size_t nread) | |||
| #ifdef DEBUG_IO | ||||
|     kprintf("call read on handle=%p\n", handle); | ||||
| #endif | ||||
|     if (handle->isBlocking()) { | ||||
|         if (!handle->hasDataAvailableForRead()) { | ||||
|             m_fdBlockedOnRead = fd; | ||||
|             block(BlockedRead); | ||||
|             yield(); | ||||
|         } | ||||
|     } | ||||
|     nread = handle->read((byte*)outbuf, nread); | ||||
| #ifdef DEBUG_IO | ||||
|     kprintf("Task::sys$read: nread=%u\n", nread); | ||||
|  |  | |||
|  | @ -31,11 +31,12 @@ public: | |||
|         Invalid = 0, | ||||
|         Runnable = 1, | ||||
|         Running = 2, | ||||
|         BlockedSleep = 3, | ||||
|         BlockedWait = 4, | ||||
|         Terminated = 5, | ||||
|         Crashing = 6, | ||||
|         Exiting = 7, | ||||
|         Terminated = 3, | ||||
|         Crashing = 4, | ||||
|         Exiting = 5, | ||||
|         BlockedSleep = 6, | ||||
|         BlockedWait = 7, | ||||
|         BlockedRead = 8, | ||||
|     }; | ||||
| 
 | ||||
|     enum RingLevel { | ||||
|  | @ -114,6 +115,7 @@ public: | |||
| 
 | ||||
| private: | ||||
|     friend class MemoryManager; | ||||
|     friend bool scheduleNewTask(); | ||||
| 
 | ||||
|     Task(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel); | ||||
| 
 | ||||
|  | @ -143,6 +145,7 @@ private: | |||
|     void* m_kernelStack { nullptr }; | ||||
|     dword m_timesScheduled { 0 }; | ||||
|     pid_t m_waitee { -1 }; | ||||
|     int m_fdBlockedOnRead { -1 }; | ||||
| 
 | ||||
|     String m_cwd; | ||||
| 
 | ||||
|  |  | |||
|  | @ -165,7 +165,7 @@ static void init_stage2() | |||
| #endif | ||||
| 
 | ||||
|     for (;;) { | ||||
|         sleep(3600 * TICKS_PER_SECOND); | ||||
|         //sleep(3600 * TICKS_PER_SECOND);
 | ||||
|         asm("hlt"); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -7,6 +7,8 @@ class CharacterDevice { | |||
| public: | ||||
|     virtual ~CharacterDevice(); | ||||
| 
 | ||||
|     virtual bool hasDataAvailableForRead() const = 0; | ||||
| 
 | ||||
|     virtual Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) = 0; | ||||
|     virtual Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -107,6 +107,13 @@ Unix::ssize_t FileHandle::read(byte* buffer, Unix::size_t count) | |||
|     return nread; | ||||
| } | ||||
| 
 | ||||
| bool FileHandle::hasDataAvailableForRead() | ||||
| { | ||||
|     if (m_vnode->isCharacterDevice()) | ||||
|         return m_vnode->characterDevice()->hasDataAvailableForRead(); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| ByteBuffer FileHandle::readEntireFile() | ||||
| { | ||||
|     Locker locker(VirtualFileSystem::lock()); | ||||
|  |  | |||
|  | @ -12,6 +12,8 @@ public: | |||
|     Unix::ssize_t read(byte* buffer, Unix::size_t count); | ||||
|     int stat(Unix::stat*); | ||||
| 
 | ||||
|     bool hasDataAvailableForRead(); | ||||
| 
 | ||||
|     ssize_t get_dir_entries(byte* buffer, Unix::size_t); | ||||
| 
 | ||||
|     ByteBuffer readEntireFile(); | ||||
|  | @ -21,6 +23,9 @@ public: | |||
| #ifdef SERENITY | ||||
|     int fd() const { return m_fd; } | ||||
|     void setFD(int fd) { m_fd = fd; } | ||||
| 
 | ||||
|     bool isBlocking() const { return m_isBlocking; } | ||||
|     void setBlocking(bool b) { m_isBlocking = b; } | ||||
| #endif | ||||
| 
 | ||||
| private: | ||||
|  | @ -32,6 +37,7 @@ private: | |||
| 
 | ||||
| #ifdef SERENITY | ||||
|     int m_fd { -1 }; | ||||
|     bool m_isBlocking { true }; | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,11 @@ FullDevice::~FullDevice() | |||
| { | ||||
| } | ||||
| 
 | ||||
| bool FullDevice::hasDataAvailableForRead() const | ||||
| { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| Unix::ssize_t FullDevice::read(byte* buffer, Unix::size_t bufferSize) | ||||
| { | ||||
|     kprintf("FullDevice: read from full\n"); | ||||
|  |  | |||
|  | @ -7,7 +7,8 @@ public: | |||
|     FullDevice(); | ||||
|     virtual ~FullDevice(); | ||||
| 
 | ||||
|     Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) override; | ||||
|     Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual bool hasDataAvailableForRead() const override; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,11 @@ NullDevice::~NullDevice() | |||
| { | ||||
| } | ||||
| 
 | ||||
| bool NullDevice::hasDataAvailableForRead() const | ||||
| { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| Unix::ssize_t NullDevice::read(byte*, Unix::size_t) | ||||
| { | ||||
|     kprintf("NullDevice: read from null\n"); | ||||
|  |  | |||
|  | @ -5,9 +5,10 @@ | |||
| class NullDevice final : public CharacterDevice { | ||||
| public: | ||||
|     NullDevice(); | ||||
|     virtual ~NullDevice(); | ||||
|     virtual ~NullDevice() override; | ||||
| 
 | ||||
|     Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) override; | ||||
|     Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual bool hasDataAvailableForRead() const override; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,6 +28,11 @@ static void mysrand(unsigned seed) | |||
| } | ||||
| #endif | ||||
| 
 | ||||
| bool RandomDevice::hasDataAvailableForRead() const | ||||
| { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| Unix::ssize_t RandomDevice::read(byte* buffer, Unix::size_t bufferSize) | ||||
| { | ||||
|     const int range = 'z' - 'a'; | ||||
|  |  | |||
|  | @ -5,9 +5,10 @@ | |||
| class RandomDevice final : public CharacterDevice { | ||||
| public: | ||||
|     RandomDevice(); | ||||
|     virtual ~RandomDevice(); | ||||
|     virtual ~RandomDevice() override; | ||||
| 
 | ||||
|     Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) override; | ||||
|     Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual bool hasDataAvailableForRead() const override; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,11 @@ ZeroDevice::~ZeroDevice() | |||
| { | ||||
| } | ||||
| 
 | ||||
| bool ZeroDevice::hasDataAvailableForRead() const | ||||
| { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| Unix::ssize_t ZeroDevice::read(byte* buffer, Unix::size_t bufferSize) | ||||
| { | ||||
|     kprintf("ZeroDevice: read from zero\n"); | ||||
|  |  | |||
|  | @ -5,9 +5,10 @@ | |||
| class ZeroDevice final : public CharacterDevice { | ||||
| public: | ||||
|     ZeroDevice(); | ||||
|     virtual ~ZeroDevice(); | ||||
|     virtual ~ZeroDevice() override; | ||||
| 
 | ||||
|     Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) override; | ||||
|     Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual Unix::ssize_t read(byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual Unix::ssize_t write(const byte* buffer, Unix::size_t bufferSize) override; | ||||
|     virtual bool hasDataAvailableForRead() const override; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling