21#include "pedigree/kernel/LockGuard.h"
22#include "pedigree/kernel/process/Mutex.h"
23#include "pedigree/kernel/process/Process.h"
24#include "pedigree/kernel/process/Thread.h"
25#include "pedigree/kernel/processor/Processor.h"
26#include "pedigree/kernel/processor/ProcessorInformation.h"
27#include "pedigree/kernel/utilities/ZombieQueue.h"
28#include "pedigree/kernel/utilities/new"
41ZombiePipe::~ZombiePipe() {
42 NOTICE(
"ZombiePipe: freeing " << m_pPipe);
50 m_Buffer(bufferChanged, this),
54 m_HangupGeneration(0),
56 m_bRetirementQueued(false) {
57 if constexpr (VERBOSE_KERNEL) {
58 NOTICE(
"Pipe: new anonymous pipe " <<
reinterpret_cast<uintptr_t
>(
this));
62Pipe::Pipe(
const String& name, Time::Timestamp accessedTime, Time::Timestamp modifiedTime,
63 Time::Timestamp creationTime, uintptr_t inode,
Filesystem* pFs,
size_t size,
64 File* pParent,
bool bIsAnonymous)
65 :
File(name, accessedTime, modifiedTime, creationTime, inode, pFs, size, pParent),
66 m_bIsAnonymous(bIsAnonymous),
68 m_Buffer(bufferChanged, this),
72 m_HangupGeneration(0),
74 m_bRetirementQueued(false) {
75 if constexpr (VERBOSE_KERNEL) {
76 NOTICE(
"Pipe: new " << (bIsAnonymous ?
"anonymous" :
"named") <<
" pipe " <<
Hex <<
this);
89void Pipe::bufferChanged(
void* context) {
99 return m_Buffer.canWrite(timeout > 0) ? 1 : 0;
101 return m_Buffer.canRead(timeout > 0) ? 1 : 0;
107 ReadyMask ready = ReadyNone;
110 ready |= ReadyHangup;
125 if (!m_nReaders ||
m_Buffer.canWrite(
false)) {
136 generations.read =
m_Buffer.readableGeneration();
137 generations.write =
m_Buffer.writableGeneration() + m_WriteGeneration;
138 generations.error = m_ErrorGeneration;
139 generations.hangup = m_HangupGeneration;
147 if (m_nWriters == 0) {
152 uint8_t* pBuf =
reinterpret_cast<uint8_t*
>(buffer);
153 return m_Buffer.read(pBuf, size, bCanBlock);
159 if (m_nReaders == 0) {
165 uint8_t* pBuf =
reinterpret_cast<uint8_t*
>(buffer);
166 return size <= PIPE_BUF_MAX ?
m_Buffer.writeAtomic(pBuf, size, bCanBlock)
167 :
m_Buffer.write(pBuf, size, bCanBlock);
178void Pipe::increaseRefCount(
bool bIsWriter) {
206 bool bDataChanged =
false;
207 bool queueRetirement =
false;
211 if (m_nReaders == 0 && m_nWriters == 0) {
213 ERROR(
"Pipe: decreasing refcount when refcount is already zero.");
219 if (m_nWriters == 0) {
220 ++m_HangupGeneration;
227 const bool wasReadyForWrite = !m_nReaders ||
m_Buffer.canWrite(
false);
229 if (m_nReaders == 0) {
230 if (!wasReadyForWrite) {
241 if (!m_nReaders && !m_nWriters) {
245 queueRetirement = shouldQueueRetirementLocked();
246 if (queueRetirement) {
247 bDataChanged =
false;
251 if (queueRetirement) {
253 if constexpr (VERBOSE_KERNEL) {
254 NOTICE(
"Adding pipe [" << pid <<
"] " <<
this <<
" to ZombieQueue");
256 ZombieQueue::instance().addObject(
new ZombiePipe(
this));
284 bool queueRetirement =
false;
289 queueRetirement = shouldQueueRetirementLocked();
292 if (queueRetirement) {
294 if constexpr (VERBOSE_KERNEL) {
295 NOTICE(
"Adding pipe [" << pid <<
"] " <<
this <<
" to ZombieQueue");
297 ZombieQueue::instance().addObject(
new ZombiePipe(
this));
301bool Pipe::shouldQueueRetirementLocked() {
322 while (!m_nReaders) {
328 ConditionVariable::Error error = ConditionVariable::NoError;
MUST_USE_RESULT bool wait(Mutex &mutex, Time::Timestamp &timeout, Error &error, WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
static bool mutexAcquired(Error error)
virtual bool retainVfsReference()
virtual void releaseVfsReference()
ReadinessGenerations readinessGenerations() override
virtual bool isFifo() const
void releaseVfsReference() override
bool waitForReader(bool bCanBlock)
bool retainVfsReference() override
virtual bool isPipe() const
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual void decreaseRefCount(bool bIsWriter)
ReadyMask queryReady(bool reading, bool writing) override
virtual int select(bool bWriting=false, int timeout=0)
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
ConditionVariable m_ReaderCondition
static ProcessorInformation & information()
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)