diff --git a/headers/private/kernel/fs/select_sync_pool.h b/headers/private/kernel/fs/select_sync_pool.h new file mode 100644 index 0000000000..297817007c --- /dev/null +++ b/headers/private/kernel/fs/select_sync_pool.h @@ -0,0 +1,31 @@ +/* + * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_SELECT_SYNC_POOL_H +#define _KERNEL_SELECT_SYNC_POOL_H + +#include + +struct selectsync; +typedef struct select_sync_pool select_sync_pool; + + +#ifdef __cplusplus +extern "C" { +#endif + + +status_t add_select_sync_pool_entry(select_sync_pool **pool, selectsync *sync, + uint32 ref, uint8 event); +status_t remove_select_sync_pool_entry(select_sync_pool **pool, + selectsync *sync, uint8 event); +void notify_select_event_pool(select_sync_pool *pool, uint8 event); + + +#ifdef __cplusplus +} +#endif + + +#endif // _KERNEL_SELECT_SYNC_POOL_H diff --git a/src/kernel/core/fs/Jamfile b/src/kernel/core/fs/Jamfile index 9684d55bdb..498e60f4b2 100644 --- a/src/kernel/core/fs/Jamfile +++ b/src/kernel/core/fs/Jamfile @@ -12,7 +12,7 @@ KernelMergeObject kernel_fs.o : pipefs.cpp fd.c vfs.cpp - vfs_select.c + vfs_select.cpp message.c node_monitor.cpp IOScheduler.cpp diff --git a/src/kernel/core/fs/vfs_select.c b/src/kernel/core/fs/vfs_select.cpp similarity index 74% rename from src/kernel/core/fs/vfs_select.c rename to src/kernel/core/fs/vfs_select.cpp index 0d07111b9d..95ced24021 100644 --- a/src/kernel/core/fs/vfs_select.c +++ b/src/kernel/core/fs/vfs_select.cpp @@ -7,13 +7,23 @@ #include #include #include +#include #include "vfs_select.h" #include #include -#include +#include #include +//#define TRACE_VFS_SELECT +#ifdef TRACE_VFS_SELECT +# define PRINT(x) dprintf x +# define FUNCTION(x) dprintf x +#else +# define PRINT(x) ; +# define FUNCTION(x) ; +#endif + /** Selects all events in the mask on the specified file descriptor */ @@ -71,6 +81,9 @@ common_select(int numfds, fd_set *readSet, fd_set *writeSet, fd_set *errorSet, int count = 0; int fd; + FUNCTION(("common_select(%d, %p, %p, %p, %lld, %p, %d)\n", numfds, readSet, + writeSet, errorSet, timeout, sigMask, kernel)); + // ToDo: set sigMask to make pselect() functional different from select() // check if fds are valid before doing anything @@ -93,7 +106,7 @@ common_select(int numfds, fd_set *readSet, fd_set *writeSet, fd_set *errorSet, set_sem_owner(sync.sem, B_SYSTEM_TEAM); - sync.set = malloc(sizeof(select_info) * numfds); + sync.set = (select_info*)malloc(sizeof(select_info) * numfds); if (sync.set == NULL) { delete_sem(sync.sem); return B_NO_MEMORY; @@ -190,7 +203,7 @@ common_poll(struct pollfd *fds, nfds_t numfds, bigtime_t timeout, bool kernel) set_sem_owner(sync.sem, B_SYSTEM_TEAM); - sync.set = malloc(numfds * sizeof(select_info)); + sync.set = (select_info*)malloc(numfds * sizeof(select_info)); if (sync.set == NULL) { delete_sem(sync.sem); return B_NO_MEMORY; @@ -269,6 +282,8 @@ notify_select_event(struct selectsync *_sync, uint32 ref, uint8 event) { select_sync *sync = (select_sync *)_sync; + FUNCTION(("notify_select_event(%p, %lu, %u)\n", _sync, ref, event)); + if (sync == NULL || sync->sem < B_OK || ref > sync->count) @@ -285,6 +300,128 @@ notify_select_event(struct selectsync *_sync, uint32 ref, uint8 event) } +// #pragma mark - +// currently private select sync pool functions exported to the kernel + + +static select_sync_pool_entry * +find_select_sync_pool_entry(select_sync_pool *pool, selectsync *sync, + uint32 ref) +{ + for (SelectSyncPoolEntryList::Iterator it = pool->entries.GetIterator(); + it.HasNext();) { + select_sync_pool_entry *entry = it.Next(); + if (entry->sync == sync && entry->ref == ref) + return entry; + } + + return NULL; +} + + +static status_t +add_select_sync_pool_entry(select_sync_pool *pool, selectsync *sync, + uint32 ref, uint8 event) +{ + // check, whether the entry does already exist + select_sync_pool_entry *entry = find_select_sync_pool_entry(pool, sync, + ref); + if (!entry) { + entry = new(nothrow) select_sync_pool_entry; + if (!entry) + return B_NO_MEMORY; + + entry->sync = sync; + entry->ref = ref; + entry->events = 0; + } + + entry->events |= SELECT_FLAG(event); + + return B_OK; +} + + +status_t +add_select_sync_pool_entry(select_sync_pool **_pool, selectsync *sync, + uint32 ref, uint8 event) +{ + // create the pool, if necessary + select_sync_pool *pool = *_pool; + if (!pool) { + pool = new(nothrow) select_sync_pool; + if (!pool) + return B_NO_MEMORY; + + *_pool = pool; + } + + // add the entry + status_t error = add_select_sync_pool_entry(pool, sync, ref, event); + + // cleanup + if (pool->entries.IsEmpty()) { + delete pool; + *_pool = NULL; + } + + return error; +} + + +status_t +remove_select_sync_pool_entry(select_sync_pool **_pool, selectsync *sync, + uint8 event) +{ + select_sync_pool *pool = *_pool; + if (!pool) + return B_ENTRY_NOT_FOUND; + + // clear the event flag of the concerned entries + bool found = false; + for (SelectSyncPoolEntryList::Iterator it = pool->entries.GetIterator(); + it.HasNext();) { + select_sync_pool_entry *entry = it.Next(); + if (entry->sync == sync) { + found = true; + entry->events &= ~SELECT_FLAG(event); + + // remove the entry, if no longer needed + if (entry->events == 0) { + it.Remove(); + delete entry; + } + } + } + + if (!found) + return B_ENTRY_NOT_FOUND; + + // delete the pool, if no longer needed + if (pool->entries.IsEmpty()) { + delete pool; + *_pool = NULL; + } + + return B_OK; +} + + +void +notify_select_event_pool(select_sync_pool *pool, uint8 event) +{ + if (!pool) + return; + + for (SelectSyncPoolEntryList::Iterator it = pool->entries.GetIterator(); + it.HasNext();) { + select_sync_pool_entry *entry = it.Next(); + if (entry->events & SELECT_FLAG(event)) + notify_select_event(entry->sync, entry->ref, event); + } +} + + // #pragma mark - // Functions called from the POSIX layer @@ -325,7 +462,7 @@ _user_select(int numfds, fd_set *userReadSet, fd_set *userWriteSet, fd_set *user // copy parameters if (userReadSet != NULL) { - readSet = malloc(bytes); + readSet = (fd_set *)malloc(bytes); if (readSet == NULL) return B_NO_MEMORY; @@ -336,7 +473,7 @@ _user_select(int numfds, fd_set *userReadSet, fd_set *userWriteSet, fd_set *user } if (userWriteSet != NULL) { - writeSet = malloc(bytes); + writeSet = (fd_set *)malloc(bytes); if (writeSet == NULL) { result = B_NO_MEMORY; goto err; @@ -348,7 +485,7 @@ _user_select(int numfds, fd_set *userReadSet, fd_set *userWriteSet, fd_set *user } if (userErrorSet != NULL) { - errorSet = malloc(bytes); + errorSet = (fd_set *)malloc(bytes); if (errorSet == NULL) { result = B_NO_MEMORY; goto err; @@ -396,7 +533,7 @@ _user_poll(struct pollfd *userfds, int numfds, bigtime_t timeout) // copy parameters - fds = malloc(bytes = numfds * sizeof(struct pollfd)); + fds = (struct pollfd *)malloc(bytes = numfds * sizeof(struct pollfd)); if (fds == NULL) return B_NO_MEMORY; diff --git a/src/kernel/core/fs/vfs_select.h b/src/kernel/core/fs/vfs_select.h index 267852b180..8bd0c7d592 100644 --- a/src/kernel/core/fs/vfs_select.h +++ b/src/kernel/core/fs/vfs_select.h @@ -5,8 +5,8 @@ #ifndef VFS_SELECT_H #define VFS_SELECT_H - #include +#include typedef struct select_info { @@ -22,4 +22,17 @@ typedef struct select_sync { #define SELECT_FLAG(type) (1L << (type - 1)) +struct select_sync_pool_entry + : DoublyLinkedListLinkImpl { + selectsync *sync; + uint32 ref; + uint16 events; +}; + +typedef DoublyLinkedList SelectSyncPoolEntryList; + +struct select_sync_pool { + SelectSyncPoolEntryList entries; +}; + #endif /* VFS_SELECT_H */