summaryrefslogtreecommitdiff
path: root/lib/libpthread/uthread
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2009-11-09 00:18:29 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2009-11-09 00:18:29 +0000
commitad0592d657a970d3b3d8200773732a354fad0461 (patch)
tree2d36a0624d8d3c7fac96e04ac86511d85bbcc56f /lib/libpthread/uthread
parent13102e76b8d893f7a1f4a778cc16d5e67e719a12 (diff)
Fix the handle locking in stdio to use flockfile/funlockfile
internally when and where required. Macros in <stdio.h> are updated to automatically call the underlying functions when the process is threaded to obtain the necessary locking. A private mutex is added to protect __sglue, the internal list of FILE handles, and another to protect the one-time initialization. Some routines in libc that use getc() change to use getc_unlocked() as they're either protected by their own lock or aren't thread-safe routines anyway. committing on behalf of and okay guenther@ now that we have install media space available.
Diffstat (limited to 'lib/libpthread/uthread')
-rw-r--r--lib/libpthread/uthread/uthread_file.c253
1 files changed, 122 insertions, 131 deletions
diff --git a/lib/libpthread/uthread/uthread_file.c b/lib/libpthread/uthread/uthread_file.c
index d8c9cdcb818..25c2d0945cc 100644
--- a/lib/libpthread/uthread/uthread_file.c
+++ b/lib/libpthread/uthread/uthread_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_file.c,v 1.16 2009/10/22 01:23:16 guenther Exp $ */
+/* $OpenBSD: uthread_file.c,v 1.17 2009/11/09 00:18:27 kurt Exp $ */
/*
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -41,6 +41,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <sys/queue.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
@@ -173,68 +174,65 @@ do_lock(int idx, FILE *fp)
return(p);
}
+
void
flockfile(FILE * fp)
{
int idx = file_idx(fp);
struct file_lock *p;
- /* Check if this is a real file: */
- if (fileno(fp) >= 0) {
- /* Lock the hash table: */
- _SPINLOCK(&hash_lock);
+ /* 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));
+ /* 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;
- }
+ /* 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);
+ /* 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);
+ /* 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 == _thread_run) {
/*
- * The file is already locked, so check if the
- * running thread is the owner:
+ * The running thread is already the
+ * owner, so increment the count of
+ * the number of times it has locked
+ * the file:
*/
- } else if (p->owner == _thread_run) {
- /*
- * The running thread is already the
- * owner, so increment the count of
- * the number of times it has locked
- * the file:
- */
- p->count++;
+ p->count++;
- /* Unlock the hash table: */
- _SPINUNLOCK(&hash_lock);
- } else {
- /*
- * 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,_thread_run,qe);
+ /* Unlock the hash table: */
+ _SPINUNLOCK(&hash_lock);
+ } else {
+ /*
+ * 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,_thread_run,qe);
- /* Unlock the hash table: */
- _SPINUNLOCK(&hash_lock);
+ /* Unlock the hash table: */
+ _SPINUNLOCK(&hash_lock);
- /* Wait on the FILE lock: */
- _thread_kern_sched_state(PS_FILE_WAIT, "", 0);
- }
+ /* Wait on the FILE lock: */
+ _thread_kern_sched_state(PS_FILE_WAIT, "", 0);
}
- return;
}
int
@@ -244,48 +242,45 @@ ftrylockfile(FILE * fp)
int idx = file_idx(fp);
struct file_lock *p;
- /* Check if this is a real file: */
- if (fileno(fp) >= 0) {
- /* Lock the hash table: */
- _SPINLOCK(&hash_lock);
+ /* 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);
+ /* 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 == _thread_run) {
/*
- * The file is already locked, so check if the
- * running thread is the owner:
+ * The running thread is already the
+ * owner, so increment the count of
+ * the number of times it has locked
+ * the file:
*/
- } else if (p->owner == _thread_run) {
- /*
- * 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;
- }
+ 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;
+ /* Check if the lock was obtained: */
+ if (p != NULL)
+ /* Return success: */
+ ret = 0;
- /* Unlock the hash table: */
- _SPINUNLOCK(&hash_lock);
+ /* Unlock the hash table: */
+ _SPINUNLOCK(&hash_lock);
- }
return (ret);
}
@@ -295,68 +290,64 @@ funlockfile(FILE * fp)
int idx = file_idx(fp);
struct file_lock *p;
- /* Check if this is a real file: */
- if (fileno(fp) >= 0) {
- /*
- * Defer signals to protect the scheduling queues from
- * access by the signal handler:
- */
- _thread_kern_sig_defer();
+ /*
+ * Defer signals to protect the scheduling queues from
+ * access by the signal handler:
+ */
+ _thread_kern_sig_defer();
- /* Lock the hash table: */
- _SPINLOCK(&hash_lock);
+ /* 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 == _thread_run) {
/*
- * Get a pointer to the lock for the file and check that
- * the running thread is the one with the lock:
+ * Check if this thread has locked the FILE
+ * more than once:
*/
- if ((p = find_lock(idx, fp)) != NULL &&
- p->owner == _thread_run) {
+ if (p->count > 1)
/*
- * Check if this thread has locked the FILE
- * more than once:
+ * Decrement the count of the number of
+ * times the running thread has locked this
+ * file:
*/
- if (p->count > 1)
- /*
- * Decrement the count of the number of
- * times the running thread has locked this
- * file:
- */
- p->count--;
- else {
+ p->count--;
+ else {
+ /*
+ * The running thread will release the
+ * lock now:
+ */
+ p->count = 0;
+
+ /* Get the new owner of the lock: */
+ if ((p->owner = TAILQ_FIRST(&p->l_head)) != NULL) {
+ /* Pop the thread off the queue: */
+ TAILQ_REMOVE(&p->l_head,p->owner,qe);
+
/*
- * The running thread will release the
- * lock now:
+ * This is the first lock for the new
+ * owner:
*/
- p->count = 0;
-
- /* Get the new owner of the lock: */
- if ((p->owner = TAILQ_FIRST(&p->l_head)) != NULL) {
- /* Pop the thread off the queue: */
- TAILQ_REMOVE(&p->l_head,p->owner,qe);
-
- /*
- * 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);
- }
+ p->count = 1;
+
+ /* Allow the new owner to run: */
+ PTHREAD_NEW_STATE(p->owner,PS_RUNNING);
}
}
+ }
- /* Unlock the hash table: */
- _SPINUNLOCK(&hash_lock);
+ /* Unlock the hash table: */
+ _SPINUNLOCK(&hash_lock);
- /*
- * Undefer and handle pending signals, yielding if
- * necessary:
- */
- _thread_kern_sig_undefer();
- }
- return;
+ /*
+ * Undefer and handle pending signals, yielding if
+ * necessary:
+ */
+ _thread_kern_sig_undefer();
}
#endif