diff options
Diffstat (limited to 'lib/libc_r/uthread/uthread_fd.c')
-rw-r--r-- | lib/libc_r/uthread/uthread_fd.c | 1054 |
1 files changed, 0 insertions, 1054 deletions
diff --git a/lib/libc_r/uthread/uthread_fd.c b/lib/libc_r/uthread/uthread_fd.c deleted file mode 100644 index 4258323..0000000 --- a/lib/libc_r/uthread/uthread_fd.c +++ /dev/null @@ -1,1054 +0,0 @@ -/* - * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - * - */ -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <pthread.h> -#include "pthread_private.h" - -#define FDQ_INSERT(q,p) \ -do { \ - TAILQ_INSERT_TAIL(q,p,qe); \ - p->flags |= PTHREAD_FLAGS_IN_FDQ; \ -} while (0) - -#define FDQ_REMOVE(q,p) \ -do { \ - if ((p->flags & PTHREAD_FLAGS_IN_FDQ) != 0) { \ - TAILQ_REMOVE(q,p,qe); \ - p->flags &= ~PTHREAD_FLAGS_IN_FDQ; \ - } \ -} while (0) - - -/* Static variables: */ -static spinlock_t fd_table_lock = _SPINLOCK_INITIALIZER; - -/* Prototypes: */ -#ifdef _FDLOCKS_ENABLED -static inline pthread_t fd_next_reader(int fd); -static inline pthread_t fd_next_writer(int fd); -#endif - - -/* - * This function *must* return -1 and set the thread specific errno - * as a system call. This is because the error return from this - * function is propagated directly back from thread-wrapped system - * calls. - */ - -int -_thread_fd_table_init(int fd) -{ - int ret = 0; - struct fd_table_entry *entry; - int saved_errno; - - if (_thread_initial == NULL) - _thread_init(); - - /* Check if the file descriptor is out of range: */ - if (fd < 0 || fd >= _thread_dtablesize) { - /* Return a bad file descriptor error: */ - errno = EBADF; - ret = -1; - } - - /* - * Check if memory has already been allocated for this file - * descriptor: - */ - else if (_thread_fd_table[fd] != NULL) { - /* Memory has already been allocated. */ - - /* Allocate memory for the file descriptor table entry: */ - } else if ((entry = (struct fd_table_entry *) - malloc(sizeof(struct fd_table_entry))) == NULL) { - /* Return an insufficient memory error: */ - errno = ENOMEM; - ret = -1; - } else { - /* Initialise the file locks: */ - memset(&entry->lock, 0, sizeof(entry->lock)); - entry->r_owner = NULL; - entry->w_owner = NULL; - entry->r_fname = NULL; - entry->w_fname = NULL; - entry->r_lineno = 0; - entry->w_lineno = 0; - entry->r_lockcount = 0; - entry->w_lockcount = 0; - - /* Initialise the read/write queues: */ - TAILQ_INIT(&entry->r_queue); - TAILQ_INIT(&entry->w_queue); - - /* Get the flags for the file: */ - if (((fd >= 3) || (_pthread_stdio_flags[fd] == -1)) && - (entry->flags = __sys_fcntl(fd, F_GETFL, 0)) == -1) { - ret = -1; - } - else { - /* Check if a stdio descriptor: */ - if ((fd < 3) && (_pthread_stdio_flags[fd] != -1)) - /* - * Use the stdio flags read by - * _pthread_init() to avoid - * mistaking the non-blocking - * flag that, when set on one - * stdio fd, is set on all stdio - * fds. - */ - entry->flags = _pthread_stdio_flags[fd]; - - /* - * Make the file descriptor non-blocking. - * This might fail if the device driver does - * not support non-blocking calls, or if the - * driver is naturally non-blocking. - */ - saved_errno = errno; - __sys_fcntl(fd, F_SETFL, - entry->flags | O_NONBLOCK); - errno = saved_errno; - - /* Lock the file descriptor table: */ - _SPINLOCK(&fd_table_lock); - - /* - * Check if another thread allocated the - * file descriptor entry while this thread - * was doing the same thing. The table wasn't - * kept locked during this operation because - * it has the potential to recurse. - */ - if (_thread_fd_table[fd] == NULL) { - /* This thread wins: */ - _thread_fd_table[fd] = entry; - entry = NULL; - } - - /* Unlock the file descriptor table: */ - _SPINUNLOCK(&fd_table_lock); - } - - /* - * Check if another thread initialised the table entry - * before this one could: - */ - if (entry != NULL) - /* - * Throw away the table entry that this thread - * prepared. The other thread wins. - */ - free(entry); - } - - /* Return the completion status: */ - return (ret); -} - -int -_thread_fd_getflags(int fd) -{ - if (_thread_fd_table[fd] != NULL) - return (_thread_fd_table[fd]->flags); - else - return (0); -} - -void -_thread_fd_setflags(int fd, int flags) -{ - if (_thread_fd_table[fd] != NULL) - _thread_fd_table[fd]->flags = flags; -} - -#ifdef _FDLOCKS_ENABLED -void -_thread_fd_unlock(int fd, int lock_type) -{ - struct pthread *curthread = _get_curthread(); - int ret; - - /* - * Check that the file descriptor table is initialised for this - * entry: - */ - if ((ret = _thread_fd_table_init(fd)) == 0) { - /* - * Defer signals to protect the scheduling queues from - * access by the signal handler: - */ - _thread_kern_sig_defer(); - - /* - * Lock the file descriptor table entry to prevent - * other threads for clashing with the current - * thread's accesses: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - /* Check if the running thread owns the read lock: */ - if (_thread_fd_table[fd]->r_owner == curthread) { - /* Check the file descriptor and lock types: */ - if (lock_type == FD_READ || lock_type == FD_RDWR) { - /* - * Decrement the read lock count for the - * running thread: - */ - _thread_fd_table[fd]->r_lockcount--; - - /* - * Check if the running thread still has read - * locks on this file descriptor: - */ - if (_thread_fd_table[fd]->r_lockcount != 0) { - } - /* - * Get the next thread in the queue for a - * read lock on this file descriptor: - */ - else if ((_thread_fd_table[fd]->r_owner = fd_next_reader(fd)) == NULL) { - } else { - /* Remove this thread from the queue: */ - FDQ_REMOVE(&_thread_fd_table[fd]->r_queue, - _thread_fd_table[fd]->r_owner); - - /* - * Set the state of the new owner of - * the thread to running: - */ - PTHREAD_NEW_STATE(_thread_fd_table[fd]->r_owner,PS_RUNNING); - - /* - * Reset the number of read locks. - * This will be incremented by the - * new owner of the lock when it sees - * that it has the lock. - */ - _thread_fd_table[fd]->r_lockcount = 0; - } - } - } - /* Check if the running thread owns the write lock: */ - if (_thread_fd_table[fd]->w_owner == curthread) { - /* Check the file descriptor and lock types: */ - if (lock_type == FD_WRITE || lock_type == FD_RDWR) { - /* - * Decrement the write lock count for the - * running thread: - */ - _thread_fd_table[fd]->w_lockcount--; - - /* - * Check if the running thread still has - * write locks on this file descriptor: - */ - if (_thread_fd_table[fd]->w_lockcount != 0) { - } - /* - * Get the next thread in the queue for a - * write lock on this file descriptor: - */ - else if ((_thread_fd_table[fd]->w_owner = fd_next_writer(fd)) == NULL) { - } else { - /* Remove this thread from the queue: */ - FDQ_REMOVE(&_thread_fd_table[fd]->w_queue, - _thread_fd_table[fd]->w_owner); - - /* - * Set the state of the new owner of - * the thread to running: - */ - PTHREAD_NEW_STATE(_thread_fd_table[fd]->w_owner,PS_RUNNING); - - /* - * Reset the number of write locks. - * This will be incremented by the - * new owner of the lock when it - * sees that it has the lock. - */ - _thread_fd_table[fd]->w_lockcount = 0; - } - } - } - - /* Unlock the file descriptor table entry: */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - /* - * Undefer and handle pending signals, yielding if - * necessary: - */ - _thread_kern_sig_undefer(); - } -} - -int -_thread_fd_lock(int fd, int lock_type, struct timespec * timeout) -{ - struct pthread *curthread = _get_curthread(); - int ret; - - /* - * Check that the file descriptor table is initialised for this - * entry: - */ - if ((ret = _thread_fd_table_init(fd)) == 0) { - /* Clear the interrupted flag: */ - curthread->interrupted = 0; - - /* - * Lock the file descriptor table entry to prevent - * other threads for clashing with the current - * thread's accesses: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - /* Check the file descriptor and lock types: */ - if (lock_type == FD_READ || lock_type == FD_RDWR) { - /* - * Wait for the file descriptor to be locked - * for read for the current thread: - */ - while ((_thread_fd_table[fd]->r_owner != curthread) && - (curthread->interrupted == 0)) { - /* - * Check if the file descriptor is locked by - * another thread: - */ - if (_thread_fd_table[fd]->r_owner != NULL) { - /* - * Another thread has locked the file - * descriptor for read, so join the - * queue of threads waiting for a - * read lock on this file descriptor: - */ - FDQ_INSERT(&_thread_fd_table[fd]->r_queue, curthread); - - /* - * Save the file descriptor details - * in the thread structure for the - * running thread: - */ - curthread->data.fd.fd = fd; - - /* Set the timeout: */ - _thread_kern_set_timeout(timeout); - - /* - * Unlock the file descriptor - * table entry: - */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - /* - * Schedule this thread to wait on - * the read lock. It will only be - * woken when it becomes the next in - * the queue and is granted access - * to the lock by the thread - * that is unlocking the file - * descriptor. - */ - _thread_kern_sched_state(PS_FDLR_WAIT, __FILE__, __LINE__); - - /* - * Lock the file descriptor - * table entry again: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - if (curthread->interrupted != 0) { - FDQ_REMOVE(&_thread_fd_table[fd]->r_queue, - curthread); - } - } else { - /* - * The running thread now owns the - * read lock on this file descriptor: - */ - _thread_fd_table[fd]->r_owner = curthread; - - /* - * Reset the number of read locks for - * this file descriptor: - */ - _thread_fd_table[fd]->r_lockcount = 0; - } - } - - if (_thread_fd_table[fd]->r_owner == curthread) - /* Increment the read lock count: */ - _thread_fd_table[fd]->r_lockcount++; - } - - /* Check the file descriptor and lock types: */ - if (curthread->interrupted == 0 && - (lock_type == FD_WRITE || lock_type == FD_RDWR)) { - /* - * Wait for the file descriptor to be locked - * for write for the current thread: - */ - while ((_thread_fd_table[fd]->w_owner != curthread) && - (curthread->interrupted == 0)) { - /* - * Check if the file descriptor is locked by - * another thread: - */ - if (_thread_fd_table[fd]->w_owner != NULL) { - /* - * Another thread has locked the file - * descriptor for write, so join the - * queue of threads waiting for a - * write lock on this file - * descriptor: - */ - FDQ_INSERT(&_thread_fd_table[fd]->w_queue, curthread); - - /* - * Save the file descriptor details - * in the thread structure for the - * running thread: - */ - curthread->data.fd.fd = fd; - - /* Set the timeout: */ - _thread_kern_set_timeout(timeout); - - /* - * Unlock the file descriptor - * table entry: - */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - /* - * Schedule this thread to wait on - * the write lock. It will only be - * woken when it becomes the next in - * the queue and is granted access to - * the lock by the thread that is - * unlocking the file descriptor. - */ - _thread_kern_sched_state(PS_FDLW_WAIT, __FILE__, __LINE__); - - /* - * Lock the file descriptor - * table entry again: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - if (curthread->interrupted != 0) { - FDQ_REMOVE(&_thread_fd_table[fd]->w_queue, - curthread); - } - } else { - /* - * The running thread now owns the - * write lock on this file - * descriptor: - */ - _thread_fd_table[fd]->w_owner = curthread; - - /* - * Reset the number of write locks - * for this file descriptor: - */ - _thread_fd_table[fd]->w_lockcount = 0; - } - } - - if (_thread_fd_table[fd]->w_owner == curthread) - /* Increment the write lock count: */ - _thread_fd_table[fd]->w_lockcount++; - } - - /* Unlock the file descriptor table entry: */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - if (curthread->interrupted != 0) { - ret = -1; - errno = EINTR; - if (curthread->continuation != NULL) - curthread->continuation((void *)curthread); - } - } - - /* Return the completion status: */ - return (ret); -} - -void -_thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) -{ - struct pthread *curthread = _get_curthread(); - int ret; - - /* - * Check that the file descriptor table is initialised for this - * entry: - */ - if ((ret = _thread_fd_table_init(fd)) == 0) { - /* - * Defer signals to protect the scheduling queues from - * access by the signal handler: - */ - _thread_kern_sig_defer(); - - /* - * Lock the file descriptor table entry to prevent - * other threads for clashing with the current - * thread's accesses: - */ - _spinlock_debug(&_thread_fd_table[fd]->lock, fname, lineno); - - /* Check if the running thread owns the read lock: */ - if (_thread_fd_table[fd]->r_owner == curthread) { - /* Check the file descriptor and lock types: */ - if (lock_type == FD_READ || lock_type == FD_RDWR) { - /* - * Decrement the read lock count for the - * running thread: - */ - _thread_fd_table[fd]->r_lockcount--; - - /* - * Check if the running thread still has read - * locks on this file descriptor: - */ - if (_thread_fd_table[fd]->r_lockcount != 0) { - } - /* - * Get the next thread in the queue for a - * read lock on this file descriptor: - */ - else if ((_thread_fd_table[fd]->r_owner = fd_next_reader(fd)) == NULL) { - } else { - /* Remove this thread from the queue: */ - FDQ_REMOVE(&_thread_fd_table[fd]->r_queue, - _thread_fd_table[fd]->r_owner); - - /* - * Set the state of the new owner of - * the thread to running: - */ - PTHREAD_NEW_STATE(_thread_fd_table[fd]->r_owner,PS_RUNNING); - - /* - * Reset the number of read locks. - * This will be incremented by the - * new owner of the lock when it sees - * that it has the lock. - */ - _thread_fd_table[fd]->r_lockcount = 0; - } - } - } - /* Check if the running thread owns the write lock: */ - if (_thread_fd_table[fd]->w_owner == curthread) { - /* Check the file descriptor and lock types: */ - if (lock_type == FD_WRITE || lock_type == FD_RDWR) { - /* - * Decrement the write lock count for the - * running thread: - */ - _thread_fd_table[fd]->w_lockcount--; - - /* - * Check if the running thread still has - * write locks on this file descriptor: - */ - if (_thread_fd_table[fd]->w_lockcount != 0) { - } - /* - * Get the next thread in the queue for a - * write lock on this file descriptor: - */ - else if ((_thread_fd_table[fd]->w_owner = fd_next_writer(fd)) == NULL) { - } else { - /* Remove this thread from the queue: */ - FDQ_REMOVE(&_thread_fd_table[fd]->w_queue, - _thread_fd_table[fd]->w_owner); - - /* - * Set the state of the new owner of - * the thread to running: - */ - PTHREAD_NEW_STATE(_thread_fd_table[fd]->w_owner,PS_RUNNING); - - /* - * Reset the number of write locks. - * This will be incremented by the - * new owner of the lock when it - * sees that it has the lock. - */ - _thread_fd_table[fd]->w_lockcount = 0; - } - } - } - - /* Unlock the file descriptor table entry: */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - /* - * Undefer and handle pending signals, yielding if - * necessary. - */ - _thread_kern_sig_undefer(); - } -} - -int -_thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout, - char *fname, int lineno) -{ - struct pthread *curthread = _get_curthread(); - int ret; - - /* - * Check that the file descriptor table is initialised for this - * entry: - */ - if ((ret = _thread_fd_table_init(fd)) == 0) { - /* Clear the interrupted flag: */ - curthread->interrupted = 0; - - /* - * Lock the file descriptor table entry to prevent - * other threads for clashing with the current - * thread's accesses: - */ - _spinlock_debug(&_thread_fd_table[fd]->lock, fname, lineno); - - /* Check the file descriptor and lock types: */ - if (lock_type == FD_READ || lock_type == FD_RDWR) { - /* - * Wait for the file descriptor to be locked - * for read for the current thread: - */ - while ((_thread_fd_table[fd]->r_owner != curthread) && - (curthread->interrupted == 0)) { - /* - * Check if the file descriptor is locked by - * another thread: - */ - if (_thread_fd_table[fd]->r_owner != NULL) { - /* - * Another thread has locked the file - * descriptor for read, so join the - * queue of threads waiting for a - * read lock on this file descriptor: - */ - FDQ_INSERT(&_thread_fd_table[fd]->r_queue, curthread); - - /* - * Save the file descriptor details - * in the thread structure for the - * running thread: - */ - curthread->data.fd.fd = fd; - curthread->data.fd.branch = lineno; - curthread->data.fd.fname = fname; - - /* Set the timeout: */ - _thread_kern_set_timeout(timeout); - - /* - * Unlock the file descriptor - * table entry: - */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - /* - * Schedule this thread to wait on - * the read lock. It will only be - * woken when it becomes the next in - * the queue and is granted access - * to the lock by the thread - * that is unlocking the file - * descriptor. - */ - _thread_kern_sched_state(PS_FDLR_WAIT, __FILE__, __LINE__); - - /* - * Lock the file descriptor - * table entry again: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - if (curthread->interrupted != 0) { - FDQ_REMOVE(&_thread_fd_table[fd]->r_queue, - curthread); - } - } else { - /* - * The running thread now owns the - * read lock on this file descriptor: - */ - _thread_fd_table[fd]->r_owner = curthread; - - /* - * Reset the number of read locks for - * this file descriptor: - */ - _thread_fd_table[fd]->r_lockcount = 0; - - /* - * Save the source file details for - * debugging: - */ - _thread_fd_table[fd]->r_fname = fname; - _thread_fd_table[fd]->r_lineno = lineno; - } - } - - if (_thread_fd_table[fd]->r_owner == curthread) - /* Increment the read lock count: */ - _thread_fd_table[fd]->r_lockcount++; - } - - /* Check the file descriptor and lock types: */ - if (curthread->interrupted == 0 && - (lock_type == FD_WRITE || lock_type == FD_RDWR)) { - /* - * Wait for the file descriptor to be locked - * for write for the current thread: - */ - while ((_thread_fd_table[fd]->w_owner != curthread) && - (curthread->interrupted == 0)) { - /* - * Check if the file descriptor is locked by - * another thread: - */ - if (_thread_fd_table[fd]->w_owner != NULL) { - /* - * Another thread has locked the file - * descriptor for write, so join the - * queue of threads waiting for a - * write lock on this file - * descriptor: - */ - FDQ_INSERT(&_thread_fd_table[fd]->w_queue, curthread); - - /* - * Save the file descriptor details - * in the thread structure for the - * running thread: - */ - curthread->data.fd.fd = fd; - curthread->data.fd.branch = lineno; - curthread->data.fd.fname = fname; - - /* Set the timeout: */ - _thread_kern_set_timeout(timeout); - - /* - * Unlock the file descriptor - * table entry: - */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - /* - * Schedule this thread to wait on - * the write lock. It will only be - * woken when it becomes the next in - * the queue and is granted access to - * the lock by the thread that is - * unlocking the file descriptor. - */ - _thread_kern_sched_state(PS_FDLW_WAIT, __FILE__, __LINE__); - - /* - * Lock the file descriptor - * table entry again: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - if (curthread->interrupted != 0) { - FDQ_REMOVE(&_thread_fd_table[fd]->w_queue, - curthread); - } - } else { - /* - * The running thread now owns the - * write lock on this file - * descriptor: - */ - _thread_fd_table[fd]->w_owner = curthread; - - /* - * Reset the number of write locks - * for this file descriptor: - */ - _thread_fd_table[fd]->w_lockcount = 0; - - /* - * Save the source file details for - * debugging: - */ - _thread_fd_table[fd]->w_fname = fname; - _thread_fd_table[fd]->w_lineno = lineno; - } - } - - if (_thread_fd_table[fd]->w_owner == curthread) - /* Increment the write lock count: */ - _thread_fd_table[fd]->w_lockcount++; - } - - /* Unlock the file descriptor table entry: */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - if (curthread->interrupted != 0) { - ret = -1; - errno = EINTR; - if (curthread->continuation != NULL) - curthread->continuation((void *)curthread); - } - } - - /* Return the completion status: */ - return (ret); -} - -void -_thread_fd_unlock_owned(pthread_t pthread) -{ - int fd; - - for (fd = 0; fd < _thread_dtablesize; fd++) { - if ((_thread_fd_table[fd] != NULL) && - ((_thread_fd_table[fd]->r_owner == pthread) || - (_thread_fd_table[fd]->w_owner == pthread))) { - /* - * Defer signals to protect the scheduling queues - * from access by the signal handler: - */ - _thread_kern_sig_defer(); - - /* - * Lock the file descriptor table entry to prevent - * other threads for clashing with the current - * thread's accesses: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - /* Check if the thread owns the read lock: */ - if (_thread_fd_table[fd]->r_owner == pthread) { - /* Clear the read lock count: */ - _thread_fd_table[fd]->r_lockcount = 0; - - /* - * Get the next thread in the queue for a - * read lock on this file descriptor: - */ - if ((_thread_fd_table[fd]->r_owner = fd_next_reader(fd)) != NULL) { - /* Remove this thread from the queue: */ - FDQ_REMOVE(&_thread_fd_table[fd]->r_queue, - _thread_fd_table[fd]->r_owner); - - /* - * Set the state of the new owner of - * the thread to running: - */ - PTHREAD_NEW_STATE(_thread_fd_table[fd]->r_owner,PS_RUNNING); - } - } - - /* Check if the thread owns the write lock: */ - if (_thread_fd_table[fd]->w_owner == pthread) { - /* Clear the write lock count: */ - _thread_fd_table[fd]->w_lockcount = 0; - - /* - * Get the next thread in the queue for a - * write lock on this file descriptor: - */ - if ((_thread_fd_table[fd]->w_owner = fd_next_writer(fd)) != NULL) { - /* Remove this thread from the queue: */ - FDQ_REMOVE(&_thread_fd_table[fd]->w_queue, - _thread_fd_table[fd]->w_owner); - - /* - * Set the state of the new owner of - * the thread to running: - */ - PTHREAD_NEW_STATE(_thread_fd_table[fd]->w_owner,PS_RUNNING); - - } - } - - /* Unlock the file descriptor table entry: */ - _SPINUNLOCK(&_thread_fd_table[fd]->lock); - - /* - * Undefer and handle pending signals, yielding if - * necessary. - */ - _thread_kern_sig_undefer(); - } - } -} - -void -_fd_lock_backout(pthread_t pthread) -{ - int fd; - - /* - * Defer signals to protect the scheduling queues - * from access by the signal handler: - */ - _thread_kern_sig_defer(); - - switch (pthread->state) { - - case PS_FDLR_WAIT: - fd = pthread->data.fd.fd; - - /* - * Lock the file descriptor table entry to prevent - * other threads for clashing with the current - * thread's accesses: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - /* Remove the thread from the waiting queue: */ - FDQ_REMOVE(&_thread_fd_table[fd]->r_queue, pthread); - break; - - case PS_FDLW_WAIT: - fd = pthread->data.fd.fd; - - /* - * Lock the file descriptor table entry to prevent - * other threads from clashing with the current - * thread's accesses: - */ - _SPINLOCK(&_thread_fd_table[fd]->lock); - - /* Remove the thread from the waiting queue: */ - FDQ_REMOVE(&_thread_fd_table[fd]->w_queue, pthread); - break; - - default: - break; - } - - /* - * Undefer and handle pending signals, yielding if - * necessary. - */ - _thread_kern_sig_undefer(); -} - -static inline pthread_t -fd_next_reader(int fd) -{ - pthread_t pthread; - - while (((pthread = TAILQ_FIRST(&_thread_fd_table[fd]->r_queue)) != NULL) && - (pthread->interrupted != 0)) { - /* - * This thread has either been interrupted by a signal or - * it has been canceled. Remove it from the queue. - */ - FDQ_REMOVE(&_thread_fd_table[fd]->r_queue, pthread); - } - - return (pthread); -} - -static inline pthread_t -fd_next_writer(int fd) -{ - pthread_t pthread; - - while (((pthread = TAILQ_FIRST(&_thread_fd_table[fd]->w_queue)) != NULL) && - (pthread->interrupted != 0)) { - /* - * This thread has either been interrupted by a signal or - * it has been canceled. Remove it from the queue. - */ - FDQ_REMOVE(&_thread_fd_table[fd]->w_queue, pthread); - } - - return (pthread); -} - -#else - -void -_thread_fd_unlock(int fd, int lock_type) -{ -} - -int -_thread_fd_lock(int fd, int lock_type, struct timespec * timeout) -{ - /* - * Insure that the file descriptor table is initialized for this - * entry: - */ - return (_thread_fd_table_init(fd)); -} - -void -_thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) -{ -} - -int -_thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout, - char *fname, int lineno) -{ - /* - * Insure that the file descriptor table is initialized for this - * entry: - */ - return (_thread_fd_table_init(fd)); -} - -void -_thread_fd_unlock_owned(pthread_t pthread) -{ -} - -void -_fd_lock_backout(pthread_t pthread) -{ -} - -#endif |