diff --git a/src/system/kernel/fs/fifo.cpp b/src/system/kernel/fs/fifo.cpp index 0e385177b8..b24e258e87 100644 --- a/src/system/kernel/fs/fifo.cpp +++ b/src/system/kernel/fs/fifo.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2007-2013, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include #include @@ -62,6 +62,8 @@ public: ssize_t Write(const void* buffer, size_t length); ssize_t Read(void* buffer, size_t length); + ssize_t Peek(size_t offset, void* buffer, + size_t length) const; ssize_t UserWrite(const void* buffer, ssize_t length); ssize_t UserRead(void* buffer, ssize_t length); @@ -102,6 +104,11 @@ public: } } + Thread* GetThread() const + { + return fThread; + } + file_cookie* Cookie() const { return fCookie; @@ -117,18 +124,25 @@ private: class WriteRequest : public DoublyLinkedListLinkImpl { public: - WriteRequest(size_t minimalWriteCount) + WriteRequest(Thread* thread, size_t minimalWriteCount) : + fThread(thread), fMinimalWriteCount(minimalWriteCount) { } + Thread* GetThread() const + { + return fThread; + } + size_t MinimalWriteCount() const { return fMinimalWriteCount; } private: + Thread* fThread; size_t fMinimalWriteCount; }; @@ -183,6 +197,9 @@ public: status_t Deselect(uint8 event, selectsync* sync, int openMode); + void Dump(bool dumpData) const; + static int Dump(int argc, char** argv); + private: timespec fCreationTime; timespec fModificationTime; @@ -283,6 +300,16 @@ RingBuffer::Read(void* buffer, size_t length) } +inline ssize_t +RingBuffer::Peek(size_t offset, void* buffer, size_t length) const +{ + if (fBuffer == NULL) + return B_NO_MEMORY; + + return ring_buffer_peek(fBuffer, offset, (uint8*)buffer, length); +} + + inline ssize_t RingBuffer::UserWrite(const void* buffer, ssize_t length) { @@ -388,7 +415,7 @@ Inode::WriteDataToBuffer(const void* _data, size_t* _length, bool nonBlocking) ConditionVariableEntry entry; entry.Add(this); - WriteRequest request(minToWrite); + WriteRequest request(thread_get_current_thread(), minToWrite); fWriteRequests.Add(&request); mutex_unlock(&fRequestLock); @@ -713,6 +740,101 @@ Inode::Deselect(uint8 event, selectsync* sync, int openMode) } +void +Inode::Dump(bool dumpData) const +{ + kprintf("FIFO %p\n", this); + kprintf(" active: %s\n", fActive ? "true" : "false"); + kprintf(" readers: %" B_PRId32 "\n", fReaderCount); + kprintf(" writers: %" B_PRId32 "\n", fWriterCount); + + if (!fReadRequests.IsEmpty()) { + kprintf(" pending readers:\n"); + for (ReadRequestList::ConstIterator it = fReadRequests.GetIterator(); + ReadRequest* request = it.Next();) { + kprintf(" %p: thread %" B_PRId32 ", cookie: %p\n", request, + request->GetThread()->id, request->Cookie()); + } + } + + if (!fWriteRequests.IsEmpty()) { + kprintf(" pending writers:\n"); + for (WriteRequestList::ConstIterator it = fWriteRequests.GetIterator(); + WriteRequest* request = it.Next();) { + kprintf(" %p: thread %" B_PRId32 ", min count: %zu\n", request, + request->GetThread()->id, request->MinimalWriteCount()); + } + } + + kprintf(" %zu bytes buffered\n", fBuffer.Readable()); + + if (dumpData && fBuffer.Readable() > 0) { + struct DataProvider : BKernel::HexDumpDataProvider { + DataProvider(const RingBuffer& buffer) + : + fBuffer(buffer), + fOffset(0) + { + } + + virtual bool HasMoreData() const + { + return fOffset < fBuffer.Readable(); + } + + virtual uint8 NextByte() + { + uint8 byte = '\0'; + if (fOffset < fBuffer.Readable()) { + fBuffer.Peek(fOffset, &byte, 1); + fOffset++; + } + return byte; + } + + virtual bool GetAddressString(char* buffer, size_t bufferSize) const + { + snprintf(buffer, bufferSize, " %4zx", fOffset); + return true; + } + + private: + const RingBuffer& fBuffer; + size_t fOffset; + }; + + DataProvider dataProvider(fBuffer); + BKernel::print_hex_dump(dataProvider, fBuffer.Readable()); + } +} + + +/*static*/ int +Inode::Dump(int argc, char** argv) +{ + bool dumpData = false; + int argi = 1; + if (argi < argc && strcmp(argv[argi], "-d") == 0) { + dumpData = true; + argi++; + } + + if (argi >= argc || argi + 2 < argc) { + print_debugger_command_usage(argv[0]); + return 0; + } + + Inode* node = (Inode*)parse_expression(argv[argi]); + if (IS_USER_ADDRESS(node)) { + kprintf("invalid FIFO address\n"); + return 0; + } + + node->Dump(dumpData); + return 0; +} + + // #pragma mark - vnode API @@ -1135,3 +1257,16 @@ create_fifo_vnode(fs_volume* superVolume, fs_vnode* vnode) return B_OK; } + + +void +fifo_init() +{ + add_debugger_command_etc("fifo", &Inode::Dump, + "Print info about the specified FIFO node", + "[ \"-d\" ]
\n" + "Prints information about the FIFO node specified by address\n" + "
. If \"-d\" is given, the data in the FIFO's ring buffer\n" + "hexdumped as well.\n", + 0); +} diff --git a/src/system/kernel/fs/fifo.h b/src/system/kernel/fs/fifo.h index 3a873381f8..6bce058873 100644 --- a/src/system/kernel/fs/fifo.h +++ b/src/system/kernel/fs/fifo.h @@ -9,6 +9,7 @@ status_t create_fifo_vnode(fs_volume* superVolume, fs_vnode* vnode); +void fifo_init(); #endif // _VFS_FIFO_H diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index d6c09097d3..304d58a5c1 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2005-2013, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2002-2011, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * @@ -5152,6 +5152,7 @@ vfs_init(kernel_args* args) | B_KERNEL_RESOURCE_ADDRESS_SPACE, 0); + fifo_init(); file_map_init(); return file_cache_init();