diff options
author | deischen <deischen@FreeBSD.org> | 2001-02-11 22:07:32 +0000 |
---|---|---|
committer | deischen <deischen@FreeBSD.org> | 2001-02-11 22:07:32 +0000 |
commit | 3de2e69a0dc1cf1cb405a6267a7fefed942b7d1f (patch) | |
tree | 5a22dcd523f742073beada495d06ed1dc2fce5e9 /lib/libc_r | |
parent | 1143b5e42a7816a7665798bcab7d5db4a37935b3 (diff) | |
download | FreeBSD-src-3de2e69a0dc1cf1cb405a6267a7fefed942b7d1f.zip FreeBSD-src-3de2e69a0dc1cf1cb405a6267a7fefed942b7d1f.tar.gz |
Remove (int) file descriptor locking. It should be up to the
application to provide locking for I/O operations. This doesn't
break any of my tests, but the old behavior can be restored by
compiling with _FDLOCKS_ENABLED. This will eventually be removed
when it is obvious it does not cause any problems.
Remove most of flockfile implementation, with the exception of
flockfile_debug.
Make error messages more informational (submitted by Mike Heffner
<spock@techfour.net>, who's now known as mikeh@FreeBSD.org).
Diffstat (limited to 'lib/libc_r')
-rw-r--r-- | lib/libc_r/uthread/pthread_private.h | 3 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_exit.c | 13 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_fd.c | 40 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_file.c | 468 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_sig.c | 5 |
5 files changed, 51 insertions, 478 deletions
diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h index 78b75ef..7a37de8 100644 --- a/lib/libc_r/uthread/pthread_private.h +++ b/lib/libc_r/uthread/pthread_private.h @@ -1208,8 +1208,6 @@ void _cond_wait_backout(pthread_t); void _fd_lock_backout(pthread_t); int _find_dead_thread(pthread_t); int _find_thread(pthread_t); -void _flockfile_backout(pthread_t); -void _funlock_owned(pthread_t); struct pthread *_get_curthread(void); void _set_curthread(struct pthread *); void _join_backout(pthread_t); @@ -1241,6 +1239,7 @@ int _pthread_mutexattr_init(pthread_mutexattr_t *); int _pthread_mutexattr_destroy(pthread_mutexattr_t *); int _pthread_mutexattr_settype(pthread_mutexattr_t *, int); int _pthread_once(pthread_once_t *, void (*) (void)); +pthread_t _pthread_self(void); int _pthread_setspecific(pthread_key_t, const void *); void _waitq_insert(pthread_t pthread); void _waitq_remove(pthread_t pthread); diff --git a/lib/libc_r/uthread/uthread_exit.c b/lib/libc_r/uthread/uthread_exit.c index 169aa4f..fd0e84a 100644 --- a/lib/libc_r/uthread/uthread_exit.c +++ b/lib/libc_r/uthread/uthread_exit.c @@ -87,13 +87,9 @@ _thread_exit(char *fname, int lineno, char *string) char s[256]; /* Prepare an error message string: */ - strcpy(s, "Fatal error '"); - strcat(s, string); - strcat(s, "' at line ? "); - strcat(s, "in file "); - strcat(s, fname); - strcat(s, " (errno = ?"); - strcat(s, ")\n"); + snprintf(s, sizeof(s), + "Fatal error '%s' at line %d in file %s (errno = %d)\n", + string, lineno, fname, errno); /* Write the string to the standard error file descriptor: */ __sys_write(2, s, strlen(s)); @@ -127,9 +123,6 @@ _thread_exit_cleanup(void) /* Unlock all owned fd locks: */ _thread_fd_unlock_owned(curthread); - /* Unlock all owned file locks: */ - _funlock_owned(curthread); - /* Unlock all private mutexes: */ _mutex_unlock_private(curthread); diff --git a/lib/libc_r/uthread/uthread_fd.c b/lib/libc_r/uthread/uthread_fd.c index ef905e3..98a70e0 100644 --- a/lib/libc_r/uthread/uthread_fd.c +++ b/lib/libc_r/uthread/uthread_fd.c @@ -58,8 +58,10 @@ do { \ 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 /* @@ -180,6 +182,7 @@ _thread_fd_table_init(int fd) return (ret); } +#ifdef _FDLOCKS_ENABLED void _thread_fd_unlock(int fd, int lock_type) { @@ -991,3 +994,40 @@ fd_next_writer(int fd) return (pthread); } + +#else + +void +_thread_fd_unlock(int fd, int lock_type) +{ +} + +int +_thread_fd_lock(int fd, int lock_type, struct timespec * timeout) +{ + return (0); +} + +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) +{ + return (0); +} + +void +_thread_fd_unlock_owned(pthread_t pthread) +{ +} + +void +_fd_lock_backout(pthread_t pthread) +{ +} + +#endif diff --git a/lib/libc_r/uthread/uthread_file.c b/lib/libc_r/uthread/uthread_file.c index e5a8484..cbedbc7 100644 --- a/lib/libc_r/uthread/uthread_file.c +++ b/lib/libc_r/uthread/uthread_file.c @@ -1,5 +1,6 @@ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. + * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,472 +38,17 @@ * */ #include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/queue.h> #include <pthread.h> #include "pthread_private.h" -/* - * Weak symbols for externally visible functions in this file: - */ -#pragma weak flockfile=_flockfile -#pragma weak ftrylockfile=_ftrylockfile -#pragma weak funlockfile=_funlockfile - -/* - * The FILE lock structure. The FILE *fp is locked if the owner is - * not NULL. If not locked, the file lock structure can be - * reassigned to a different file by setting fp. - */ -struct file_lock { - LIST_ENTRY(file_lock) entry; /* Entry if file list. */ - TAILQ_HEAD(lock_head, pthread) - l_head; /* Head of queue for threads */ - /* waiting on this lock. */ - FILE *fp; /* The target file. */ - pthread_t owner; /* Thread that owns lock. */ - int count; /* Lock count for owner. */ -}; - -/* - * The number of file lock lists into which the file pointer is - * hashed. Ideally, the FILE structure size would have been increased, - * but this causes incompatibility, so separate data structures are - * required. - */ -#define NUM_HEADS 128 - -/* - * This macro casts a file pointer to a long integer and right - * shifts this by the number of bytes in a pointer. The shifted - * value is then remaindered using the maximum number of hash - * entries to produce and index into the array of static lock - * structures. If there is a collision, a linear search of the - * dynamic list of locks linked to each static lock is perfomed. - */ -#define file_idx(_p) ((((u_long) _p) >> sizeof(void *)) % NUM_HEADS) - -/* - * Global array of file locks. The first lock for each hash bucket is - * allocated statically in the hope that there won't be too many - * collisions that require a malloc and an element added to the list. - */ -struct static_file_lock { - LIST_HEAD(file_list_head, file_lock) head; - struct file_lock fl; -} flh[NUM_HEADS]; - -/* Set to non-zero when initialisation is complete: */ -static int init_done = 0; - -/* Lock for accesses to the hash table: */ -static spinlock_t hash_lock = _SPINLOCK_INITIALIZER; - -/* - * Find a lock structure for a FILE, return NULL if the file is - * not locked: - */ -static -struct file_lock * -find_lock(int idx, FILE *fp) -{ - struct file_lock *p; - - /* Check if the file is locked using the static structure: */ - if (flh[idx].fl.fp == fp && flh[idx].fl.owner != NULL) - /* Return a pointer to the static lock: */ - p = &flh[idx].fl; - else { - /* Point to the first dynamic lock: */ - p = LIST_FIRST(&flh[idx].head); - - /* - * Loop through the dynamic locks looking for the - * target file: - */ - while (p != NULL && (p->fp != fp || p->owner == NULL)) - /* Not this file, try the next: */ - p = LIST_NEXT(p, entry); - } - return(p); -} - -/* - * Lock a file, assuming that there is no lock structure currently - * assigned to it. - */ -static -struct file_lock * -do_lock(int idx, FILE *fp) -{ - struct pthread *curthread = _get_curthread(); - struct file_lock *p; - - /* Check if the static structure is not being used: */ - if (flh[idx].fl.owner == NULL) { - /* Return a pointer to the static lock: */ - p = &flh[idx].fl; - } - else { - /* Point to the first dynamic lock: */ - p = LIST_FIRST(&flh[idx].head); - - /* - * Loop through the dynamic locks looking for a - * lock structure that is not being used: - */ - while (p != NULL && p->owner != NULL) - /* This one is used, try the next: */ - p = LIST_NEXT(p, entry); - } - - /* - * If an existing lock structure has not been found, - * allocate memory for a new one: - */ - if (p == NULL && (p = (struct file_lock *) - malloc(sizeof(struct file_lock))) != NULL) { - /* Add the new element to the list: */ - LIST_INSERT_HEAD(&flh[idx].head, p, entry); - } - - /* Check if there is a lock structure to acquire: */ - if (p != NULL) { - /* Acquire the lock for the running thread: */ - p->fp = fp; - p->owner = curthread; - p->count = 1; - TAILQ_INIT(&p->l_head); - } - return(p); -} - -void -_flockfile_debug(FILE * fp, char *fname, int lineno) -{ - struct pthread *curthread = _get_curthread(); - int idx = file_idx(fp); - struct file_lock *p; - - /* Check if this is a real file: */ - if (fp->_file >= 0) { - /* Lock the hash table: */ - _SPINLOCK(&hash_lock); - - /* Check if the static array has not been initialised: */ - if (!init_done) { - /* Initialise the global array: */ - memset(flh,0,sizeof(flh)); - - /* Flag the initialisation as complete: */ - init_done = 1; - } - - /* Get a pointer to any existing lock for the file: */ - if ((p = find_lock(idx, fp)) == NULL) { - /* - * The file is not locked, so this thread can - * grab the lock: - */ - p = do_lock(idx, fp); - - /* Unlock the hash table: */ - _SPINUNLOCK(&hash_lock); - - /* - * The file is already locked, so check if the - * running thread is the owner: - */ - } else if (p->owner == curthread) { - /* - * The running thread is already the - * owner, so increment the count of - * the number of times it has locked - * the file: - */ - p->count++; - - /* Unlock the hash table: */ - _SPINUNLOCK(&hash_lock); - } else { - /* Clear the interrupted flag: */ - curthread->interrupted = 0; - - /* - * Prevent being context switched out while - * adding this thread to the file lock queue. - */ - _thread_kern_sig_defer(); - - /* - * The file is locked for another thread. - * Append this thread to the queue of - * threads waiting on the lock. - */ - TAILQ_INSERT_TAIL(&p->l_head,curthread,qe); - curthread->flags |= PTHREAD_FLAGS_IN_FILEQ; - - /* Unlock the hash table: */ - _SPINUNLOCK(&hash_lock); - - curthread->data.fp = fp; - - /* Wait on the FILE lock: */ - _thread_kern_sched_state(PS_FILE_WAIT, fname, lineno); - - if ((curthread->flags & PTHREAD_FLAGS_IN_FILEQ) != 0) { - TAILQ_REMOVE(&p->l_head,curthread,qe); - curthread->flags &= ~PTHREAD_FLAGS_IN_FILEQ; - } - - _thread_kern_sig_undefer(); - - if (curthread->interrupted != 0 && - curthread->continuation != NULL) - curthread->continuation((void *)curthread); - } - } -} +extern void _flockfile(FILE *); void -_flockfile(FILE * fp) -{ - _flockfile_debug(fp, __FILE__, __LINE__); -} - -int -_ftrylockfile(FILE * fp) -{ - struct pthread *curthread = _get_curthread(); - int ret = -1; - int idx = file_idx(fp); - struct file_lock *p; - - /* Check if this is a real file: */ - if (fp->_file >= 0) { - /* Lock the hash table: */ - _SPINLOCK(&hash_lock); - - /* Get a pointer to any existing lock for the file: */ - if ((p = find_lock(idx, fp)) == NULL) { - /* - * The file is not locked, so this thread can - * grab the lock: - */ - p = do_lock(idx, fp); - - /* - * The file is already locked, so check if the - * running thread is the owner: - */ - } else if (p->owner == curthread) { - /* - * The running thread is already the - * owner, so increment the count of - * the number of times it has locked - * the file: - */ - p->count++; - } else { - /* - * The file is locked for another thread, - * so this try fails. - */ - p = NULL; - } - - /* Check if the lock was obtained: */ - if (p != NULL) - /* Return success: */ - ret = 0; - - /* Unlock the hash table: */ - _SPINUNLOCK(&hash_lock); - - } - return (ret); -} - -void -_funlockfile(FILE * fp) +_flockfile_debug(FILE *fp, char *fname, int lineno) { - struct pthread *curthread = _get_curthread(); - int idx = file_idx(fp); - struct file_lock *p; - - /* Check if this is a real file: */ - if (fp->_file >= 0) { - /* - * Defer signals to protect the scheduling queues from - * access by the signal handler: - */ - _thread_kern_sig_defer(); - - /* Lock the hash table: */ - _SPINLOCK(&hash_lock); - - /* - * Get a pointer to the lock for the file and check that - * the running thread is the one with the lock: - */ - if ((p = find_lock(idx, fp)) != NULL && - p->owner == curthread) { - /* - * Check if this thread has locked the FILE - * more than once: - */ - if (p->count > 1) - /* - * Decrement the count of the number of - * times the running thread has locked this - * file: - */ - p->count--; - else { - /* - * The running thread will release the - * lock now: - */ - p->count = 0; - - /* Get the new owner of the lock: */ - while ((p->owner = TAILQ_FIRST(&p->l_head)) != NULL) { - /* Pop the thread off the queue: */ - TAILQ_REMOVE(&p->l_head,p->owner,qe); - p->owner->flags &= ~PTHREAD_FLAGS_IN_FILEQ; - - if (p->owner->interrupted == 0) { - /* - * This is the first lock for - * the new owner: - */ - p->count = 1; - - /* Allow the new owner to run: */ - PTHREAD_NEW_STATE(p->owner,PS_RUNNING); - - /* End the loop when we find a - * thread that hasn't been - * cancelled or interrupted; - */ - break; - } - } - } - } - - /* Unlock the hash table: */ - _SPINUNLOCK(&hash_lock); + pthread_t curthread = _pthread_self(); - /* - * Undefer and handle pending signals, yielding if - * necessary: - */ - _thread_kern_sig_undefer(); - } + curthread->lineno = lineno; + curthread->fname = fname; + _flockfile(fp); } - -void -_funlock_owned(pthread_t pthread) -{ - int idx; - struct file_lock *p, *next_p; - - /* - * Defer signals to protect the scheduling queues from - * access by the signal handler: - */ - _thread_kern_sig_defer(); - - /* Lock the hash table: */ - _SPINLOCK(&hash_lock); - - for (idx = 0; idx < NUM_HEADS; idx++) { - /* Check the static file lock first: */ - p = &flh[idx].fl; - next_p = LIST_FIRST(&flh[idx].head); - - while (p != NULL) { - if (p->owner == pthread) { - /* - * The running thread will release the - * lock now: - */ - p->count = 0; - - /* Get the new owner of the lock: */ - while ((p->owner = TAILQ_FIRST(&p->l_head)) != NULL) { - /* Pop the thread off the queue: */ - TAILQ_REMOVE(&p->l_head,p->owner,qe); - p->owner->flags &= ~PTHREAD_FLAGS_IN_FILEQ; - - if (p->owner->interrupted == 0) { - /* - * This is the first lock for - * the new owner: - */ - p->count = 1; - - /* Allow the new owner to run: */ - PTHREAD_NEW_STATE(p->owner,PS_RUNNING); - - /* End the loop when we find a - * thread that hasn't been - * cancelled or interrupted; - */ - break; - } - } - } - p = next_p; - if (next_p != NULL) - next_p = LIST_NEXT(next_p, entry); - } - } - - /* Unlock the hash table: */ - _SPINUNLOCK(&hash_lock); - - /* - * Undefer and handle pending signals, yielding if - * necessary: - */ - _thread_kern_sig_undefer(); -} - -void -_flockfile_backout(pthread_t pthread) -{ - int idx = file_idx(pthread->data.fp); - struct file_lock *p; - - /* - * Defer signals to protect the scheduling queues from - * access by the signal handler: - */ - _thread_kern_sig_defer(); - - /* - * Get a pointer to the lock for the file and check that - * the running thread is the one with the lock: - */ - if (((pthread->flags & PTHREAD_FLAGS_IN_FILEQ) != 0) && - ((p = find_lock(idx, pthread->data.fp)) != NULL)) { - /* Lock the hash table: */ - _SPINLOCK(&hash_lock); - - /* Remove the thread from the queue: */ - TAILQ_REMOVE(&p->l_head, pthread, qe); - pthread->flags &= ~PTHREAD_FLAGS_IN_FILEQ; - - /* Unlock the hash table: */ - _SPINUNLOCK(&hash_lock); - } - - /* - * Undefer and handle pending signals, yielding if necessary: - */ - _thread_kern_sig_undefer(); -} - diff --git a/lib/libc_r/uthread/uthread_sig.c b/lib/libc_r/uthread/uthread_sig.c index 9559bb7..a005adf 100644 --- a/lib/libc_r/uthread/uthread_sig.c +++ b/lib/libc_r/uthread/uthread_sig.c @@ -941,11 +941,6 @@ _thread_sig_wrapper(void) psf->saved_state.psd_state = PS_RUNNING; break; - case PS_FILE_WAIT: - _flockfile_backout(thread); - psf->saved_state.psd_state = PS_RUNNING; - break; - case PS_COND_WAIT: _cond_wait_backout(thread); psf->saved_state.psd_state = PS_RUNNING; |