diff --git a/src/add-ons/kernel/drivers/tty/Jamfile b/src/add-ons/kernel/drivers/tty/Jamfile index 30ada5bd7c..6d98563a0f 100644 --- a/src/add-ons/kernel/drivers/tty/Jamfile +++ b/src/add-ons/kernel/drivers/tty/Jamfile @@ -8,4 +8,6 @@ KernelAddon tty : kernel drivers dev : line_buffer.cpp master.cpp slave.cpp + SemaphorePool.cpp ; + diff --git a/src/add-ons/kernel/drivers/tty/SemaphorePool.cpp b/src/add-ons/kernel/drivers/tty/SemaphorePool.cpp new file mode 100644 index 0000000000..5828ecf4a4 --- /dev/null +++ b/src/add-ons/kernel/drivers/tty/SemaphorePool.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ + +#include + +#include + +#include "SemaphorePool.h" + + +status_t +Semaphore::ZeroCount() +{ + int32 count; + status_t error = get_sem_count(fSemaphore, &count); + if (error != B_OK) + return error; + + if (count > 0) + error = acquire_sem_etc(fSemaphore, count, B_RELATIVE_TIMEOUT, 0); + else if (count < 0) + error = release_sem_etc(fSemaphore, -count, 0); + + return error; +} + + +// #pragma mark - + +SemaphorePool::SemaphorePool(int32 maxCached) + : fSemaphores(), + fCount(0), + fMaxCount(maxCached) +{ + if (fMaxCount < 0) + fMaxCount = 8; +} + + +SemaphorePool::~SemaphorePool() +{ + while (Semaphore *sem = fSemaphores.Head()) { + fSemaphores.Remove(sem); + delete sem; + } + + mutex_destroy(&fLock); +} + + +status_t +SemaphorePool::Init() +{ + return mutex_init(&fLock, "tty semaphore pool"); +} + + +status_t +SemaphorePool::Get(Semaphore *&semaphore) +{ + MutexLocker _(fLock); + + // use a cached one, if available + if (fCount > 0) { + fCount--; + semaphore = fSemaphores.Head(); + fSemaphores.Remove(semaphore); + return B_OK; + } + + // create a new one + Semaphore *sem = new(nothrow) Semaphore(0, "pool semaphore"); + if (!sem) + return B_NO_MEMORY; + + status_t error = sem->ZeroCount(); + if (error != B_OK) { + delete sem; + return error; + } + + semaphore = sem; + return B_OK; +} + + +void +SemaphorePool::Put(Semaphore *semaphore) +{ + if (!semaphore) + return; + + MutexLocker _(fLock); + + if (fCount >= fMaxCount || semaphore->InitCheck() != B_OK) { + delete semaphore; + return; + } + + fSemaphores.Add(semaphore); + fCount++; +} diff --git a/src/add-ons/kernel/drivers/tty/SemaphorePool.h b/src/add-ons/kernel/drivers/tty/SemaphorePool.h new file mode 100644 index 0000000000..74768d10aa --- /dev/null +++ b/src/add-ons/kernel/drivers/tty/SemaphorePool.h @@ -0,0 +1,67 @@ +/* + * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ +#ifndef TTY_SEMAPHORE_POOL_H +#define TTY_SEMAPHORE_POOL_H + +#include +#include + +class Semaphore : public DoublyLinkedListLinkImpl { +public: + Semaphore(sem_id sem) + : fSemaphore(sem) + { + } + + Semaphore(int32 count, const char *name) + { + fSemaphore = create_sem(count, name); + } + + ~Semaphore() + { + if (fSemaphore >= 0) + delete_sem(fSemaphore); + } + + status_t InitCheck() const + { + return (fSemaphore >= 0 ? B_OK : fSemaphore); + } + + sem_id ID() const + { + return fSemaphore; + } + + status_t ZeroCount(); + +private: + sem_id fSemaphore; + +public: + Semaphore *fNext; +}; + +class SemaphorePool { +public: + SemaphorePool(int32 maxCached); + ~SemaphorePool(); + + status_t Init(); + + status_t Get(Semaphore *&semaphore); + void Put(Semaphore *semaphore); + +private: + typedef DoublyLinkedList SemaphoreList; + + struct mutex fLock; + SemaphoreList fSemaphores; + int32 fCount; + int32 fMaxCount; +}; + +#endif // TTY_SEMAPHORE_POOL_H