20#include "pedigree/kernel/process/Thread.h"
21#include "pedigree/kernel/processor/Processor.h"
22#include "pedigree/kernel/processor/ProcessorInformation.h"
23#include "pedigree/kernel/processor/types.h"
24#include "pedigree/kernel/syscallError.h"
25#include "pedigree/kernel/utilities/Buffer.h"
26#include "pedigree/kernel/utilities/String.h"
27#include "pedigree/kernel/utilities/utility.h"
30#include "ConsoleDefines.h"
31#include "modules/system/vfs/File.h"
40 void readinessChanged(ReadyMask mask)
override {
41 m_Owner->terminalReadinessChanged(mask);
49ConsolePhysicalFile::ConsolePhysicalFile(
size_t nth,
File* pTerminal,
String consoleName,
52 m_pTerminal(pTerminal),
53 m_TerminalNumber(nth),
54 m_TerminalReadinessObserver(new PhysicalTerminalReadinessObserver(this)) {
56 if (!m_pTerminal->subscribeReadiness(ReadyAll, m_TerminalReadinessObserver,
57 m_TerminalReadinessSubscription)) {
59 "ConsolePhysicalFile failed to subscribe to readiness in its constructor - this is a "
60 "silent failure (console="
61 << consoleName <<
")");
66void ConsolePhysicalFile::terminalReadinessChanged(ReadyMask mask) {
76 Semaphore::SemaphoreError error = Semaphore::NoError;
77 if (!state.physicalWake.
acquireWithError(1, 0, 10000, error) && error != Semaphore::TimedOut) {
78 SYSCALL_ERROR(Interrupted);
81 return !state.revoked();
85void ConsolePhysicalFile::collectInput(
ConsoleIoState& state,
bool canBlock) {
87 size_t amount = m_pTerminal->
read(0,
sizeof(input),
reinterpret_cast<uintptr_t
>(input),
false);
92 while (!state.revoked() && state.output.
canRead(
false)) {
93 size_t echoed = state.output.
read(echo,
sizeof(echo),
false);
94 if (!echoed || writeIo(state, echoed,
reinterpret_cast<uintptr_t
>(echo), canBlock) != echoed) {
103 if (!state.revoked() && !state.input.
canRead(
false)) {
104 collectInput(state,
false);
109uint64_t ConsolePhysicalFile::readIo(
ConsoleIoState& state, uint64_t size, uintptr_t buffer,
111 while (!state.revoked()) {
112 if (state.input.
canRead(
false)) {
113 return state.input.
read(
reinterpret_cast<char*
>(buffer), size,
false);
115 collectInput(state, canBlock);
116 if (state.input.
canRead(
false))
118 if (!canBlock || !waitPhysical(state))
124uint64_t ConsolePhysicalFile::writeIo(
ConsoleIoState& state, uint64_t size, uintptr_t buffer,
127 while (total < size && !state.revoked()) {
129 size_t chunk = size - total;
130 if (chunk >
sizeof(output) / 2)
131 chunk =
sizeof(output) / 2;
132 MemoryCopy(output,
reinterpret_cast<const void*
>(buffer + total), chunk);
135 while (sent < length && !state.revoked()) {
137 m_pTerminal->
write(0, length - sent,
reinterpret_cast<uintptr_t
>(output + sent),
false);
139 if (!amount && (!canBlock || !waitPhysical(state)))
151 return readEpoch(captureOpenEpoch(), size, buffer, canBlock);
156 return writeEpoch(captureOpenEpoch(), size, buffer, canBlock);
161 return m_pTerminal->
select(
true, timeout);
162 auto state = captureOpenEpoch(
false);
163 if (state && state->input.
canRead(
false))
165 return m_pTerminal->
select(
false, timeout);
size_t read(T *buffer, size_t count, bool block=true)
static size_t outputLineDiscipline(char *buf, size_t len, size_t maxSz, size_t flags=0)
Output line discipline.
size_t inputLineDiscipline(ConsoleIoState &state, char *buf, size_t len, bool canBlock, size_t flags=~0U, const char *controlChars=nullptr)
Input line discipline.
virtual int select(bool bWriting, int timeout)
select - check and optionally for a particular state.
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t read(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
virtual uint64_t write(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
virtual int select(bool bWriting=false, int timeout=0)
void notifyReadiness(ReadyMask mask)
MUST_USE_RESULT bool acquireWithError(size_t n, size_t timeoutSecs, size_t timeoutUsecs, SemaphoreError &error)