diff options
author | jb <jb@FreeBSD.org> | 1998-04-11 07:47:22 +0000 |
---|---|---|
committer | jb <jb@FreeBSD.org> | 1998-04-11 07:47:22 +0000 |
commit | 19185ac5121f9f5c12adb893404acf3e8c9db6d4 (patch) | |
tree | d3cd2f1400e0868d686f6f4a6969a4e33d538f1c /lib | |
parent | 0ff63017b40dda207b2aadc9881e0c93e7fd2753 (diff) | |
download | FreeBSD-src-19185ac5121f9f5c12adb893404acf3e8c9db6d4.zip FreeBSD-src-19185ac5121f9f5c12adb893404acf3e8c9db6d4.tar.gz |
Change the FILE locking to be by FILE, not by the underlying fd as
it was. Add a FILE_WAIT state and queue threads waiting for a FILE
lock. Start using the sys/queue.h macros instead of the way that MIT
pthreads did it.
Add a thread name to the private thread structure and a non-POSIX
function to set this. This helps (me at least) when sending a SIGINFO
to a threaded process to get a /tmp/uthread.dump to see what the
<expletive deleted> threads are doing this time. It is nice to be
able to recognise (yes, I spell that with an 's' too) which threads
are which.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc_r/uthread/pthread_private.h | 11 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_create.c | 7 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_file.c | 330 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_info.c | 27 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_kern.c | 5 | ||||
-rw-r--r-- | lib/libkse/thread/thr_create.c | 7 | ||||
-rw-r--r-- | lib/libkse/thread/thr_info.c | 27 | ||||
-rw-r--r-- | lib/libkse/thread/thr_kern.c | 5 | ||||
-rw-r--r-- | lib/libkse/thread/thr_private.h | 11 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_create.c | 7 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_info.c | 27 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_kern.c | 5 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_private.h | 11 |
13 files changed, 399 insertions, 81 deletions
diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h index dc36d8d..5ceeaba 100644 --- a/lib/libc_r/uthread/pthread_private.h +++ b/lib/libc_r/uthread/pthread_private.h @@ -50,6 +50,7 @@ */ #include <setjmp.h> #include <signal.h> +#include <sys/queue.h> #include <sys/types.h> #include <sys/time.h> #include <sched.h> @@ -219,6 +220,7 @@ enum pthread_state { PS_FDLW_WAIT, PS_FDR_WAIT, PS_FDW_WAIT, + PS_FILE_WAIT, PS_SELECT_WAIT, PS_SLEEP_WAIT, PS_WAIT_WAIT, @@ -283,6 +285,7 @@ struct pthread { */ #define PTHREAD_MAGIC ((u_int32_t) 0xd09ba115) u_int32_t magic; + char *name; /* * Pointer to the next thread in the thread linked list. @@ -387,12 +390,18 @@ struct pthread { * The current thread can belong to only one queue at a time. * * Pointer to queue (if any) on which the current thread is waiting. + * + * XXX The queuing should be changed to use the TAILQ entry below. + * XXX For the time being, it's hybrid. */ struct pthread_queue *queue; /* Pointer to next element in queue. */ struct pthread *qnxt; + /* Queue entry for this thread: */ + TAILQ_ENTRY(pthread) qe; + /* Wait data. */ union pthread_wait_data data; @@ -634,8 +643,6 @@ ssize_t _thread_sys_sendto(int, const void *,size_t, int, const struct sockaddr /* #include <stdio.h> */ #ifdef _STDIO_H_ -void _thread_flockfile(FILE *fp,char *fname,int lineno); -void _thread_funlockfile(FILE *fp); FILE *_thread_sys_fdopen(int, const char *); FILE *_thread_sys_fopen(const char *, const char *); FILE *_thread_sys_freopen(const char *, const char *, FILE *); diff --git a/lib/libc_r/uthread/uthread_create.c b/lib/libc_r/uthread/uthread_create.c index 3dcd944..c9c6c9f 100644 --- a/lib/libc_r/uthread/uthread_create.c +++ b/lib/libc_r/uthread/uthread_create.c @@ -40,6 +40,7 @@ #include <machine/reg.h> #include <pthread.h> #include "pthread_private.h" +#include "libc_private.h" int _thread_create(pthread_t * thread, const pthread_attr_t * attr, @@ -254,6 +255,12 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, int ret = 0; /* + * Locking functions in libc are required when there are + * threads other than the initial thread. + */ + __isthreaded = 1; + + /* * Call the low level thread creation function which allows a parent * thread to be specified: */ diff --git a/lib/libc_r/uthread/uthread_file.c b/lib/libc_r/uthread/uthread_file.c index 0d8e9a3..6d88c0a 100644 --- a/lib/libc_r/uthread/uthread_file.c +++ b/lib/libc_r/uthread/uthread_file.c @@ -29,92 +29,326 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $Id$ + * + * POSIX stdio FILE locking functions. These assume that the locking + * is only required at FILE structure level, not at file descriptor + * level too. + * */ -#include <signal.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/queue.h> #ifdef _THREAD_SAFE #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) ((((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; + +/* + * 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 = flh[idx].head.lh_first; + + /* + * 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 = p->entry.le_next; + } + return(p); +} + +/* + * Lock a file, assuming that there is no lock structure currently1 + * assigned to it. + */ +static +struct file_lock * +do_lock(int idx, FILE *fp) +{ + 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 = flh[idx].head.lh_first; + + /* + * 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 = p->entry.le_next; + } + + /* + * 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 = _thread_run; + p->count = 1; + TAILQ_INIT(&p->l_head); + } + return(p); +} + void -_thread_flockfile(FILE * fp, char *fname, int lineno) +_flockfile_debug(FILE * fp, char *fname, int lineno) { - int fd, flags; - int status; + int fd, flags; + int status; + int idx = file_idx(fp); + struct file_lock *p; + + /* Check if this is a real file: */ + if (fp->_file >= 0) { + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* 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; + } - /* Block signals: */ - _thread_kern_sig_block(&status); + /* 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); - if ((fd = fileno(fp)) >= 0) { - if (fp->_flags & __SRW) { - flags = FD_READ | FD_WRITE; + /* + * The file is already locked, so check if the + * running thread is the owner: + */ + } 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 { - if (fp->_flags & __SWR) { - flags = FD_WRITE; - } else { - flags = FD_READ; - } + /* + * 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); + + /* Wait on the FILE lock: */ + _thread_kern_sched_state(PS_FILE_WAIT, fname, lineno); + + /* Block signals again: */ + _thread_kern_sig_block(NULL); } - /* This might fail but POSIX doesn't give a damn. */ - _thread_fd_lock(fd, flags, NULL, fname, lineno); + /* Unblock signals: */ + _thread_kern_sig_unblock(status); } - /* Unblock signals: */ - _thread_kern_sig_unblock(status); + return; +} + +void +_flockfile(FILE * fp) +{ + _flockfile_debug(fp, __FILE__, __LINE__); return; } int -_thread_ftrylockfile(FILE * fp) +_ftrylockfile(FILE * fp) { - int fd = 0; - int flags; - int status; + int ret = -1; + int status; + int idx = file_idx(fp); + struct file_lock *p; - if ((fd = fileno(fp)) >= 0) { + /* Check if this is a real file: */ + if (fp->_file >= 0) { /* Block signals: */ _thread_kern_sig_block(&status); - if (fp->_flags & __SRW) { - flags = FD_READ | FD_WRITE; - } else { - if (fp->_flags & __SWR) { - flags = FD_WRITE; - } else { - flags = FD_READ; - } - } - if (!(_thread_fd_table[fd]->r_owner && _thread_fd_table[fd]->w_owner)) { - _thread_fd_lock(fd, flags, NULL, __FILE__, __LINE__); - fd = 0; + /* 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 running thread is already the + * owner, so increment the count of + * the number of times it has locked + * the file: + */ + p->count++; } else { - fd = -1; + /* + * 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; + /* Unblock signals: */ _thread_kern_sig_unblock(status); } - return (fd); + return (ret); } void -_thread_funlockfile(FILE * fp) +_funlockfile(FILE * fp) { - int fd, flags; - int status; + int status; + int idx = file_idx(fp); + struct file_lock *p; - if ((fd = fileno(fp)) >= 0) { + /* Check if this is a real file: */ + if (fp->_file >= 0) { /* Block signals: */ _thread_kern_sig_block(&status); - if (fp->_flags & __SRW) { - flags = FD_READ | FD_WRITE; - } else if (fp->_flags & __SWR) { - flags = FD_WRITE; - } else { - flags = FD_READ; + /* + * 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) { + /* + * 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: */ + 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); + } + } } - _thread_fd_unlock(fd, flags); /* Unblock signals: */ _thread_kern_sig_unblock(status); diff --git a/lib/libc_r/uthread/uthread_info.c b/lib/libc_r/uthread/uthread_info.c index be25d45..fe6565b 100644 --- a/lib/libc_r/uthread/uthread_info.c +++ b/lib/libc_r/uthread/uthread_info.c @@ -52,7 +52,8 @@ static const struct s_thread_info thread_info[] = { {PS_FDLR_WAIT , "Waiting for a file read lock"}, {PS_FDLW_WAIT , "Waiting for a file write lock"}, {PS_FDR_WAIT , "Waiting for read"}, - {PS_FDW_WAIT , "Waitingfor write"}, + {PS_FDW_WAIT , "Waiting for write"}, + {PS_FILE_WAIT , "Waiting for FILE lock"}, {PS_SELECT_WAIT , "Waiting on select"}, {PS_SLEEP_WAIT , "Sleeping"}, {PS_WAIT_WAIT , "Waiting process"}, @@ -87,8 +88,8 @@ _thread_dump_info(void) if (thread_info[j].state == pthread->state) break; /* Output a record for the current thread: */ - sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n", - pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); + sprintf(s, "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n", + pthread, (pthread->name == NULL) ? "":pthread->name, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); /* Check if this is the running thread: */ @@ -105,7 +106,7 @@ _thread_dump_info(void) } /* Process according to thread state: */ switch (pthread->state) { - /* File descriptor read lock wait: */ + /* File descriptor read lock wait: */ case PS_FDLR_WAIT: case PS_FDLW_WAIT: case PS_FDR_WAIT: @@ -117,10 +118,10 @@ _thread_dump_info(void) _thread_sys_write(fd, s, strlen(s)); break; - /* - * Trap other states that are not explicitly - * coded to dump information: - */ + /* + * Trap other states that are not explicitly + * coded to dump information: + */ default: /* Nothing to do here. */ break; @@ -179,4 +180,14 @@ _thread_dump_info(void) } return; } + +/* Set the thread name for debug: */ +void +pthread_set_name_np(pthread_t thread, char *name) +{ + /* Check if the caller has specified a valid thread: */ + if (thread != NULL && thread->magic == PTHREAD_MAGIC) + thread->name = strdup(name); + return; +} #endif diff --git a/lib/libc_r/uthread/uthread_kern.c b/lib/libc_r/uthread/uthread_kern.c index eeae75c..9356c4c 100644 --- a/lib/libc_r/uthread/uthread_kern.c +++ b/lib/libc_r/uthread/uthread_kern.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: uthread_kern.c,v 1.6 1998/02/13 01:27:33 julian Exp $ + * $Id: uthread_kern.c,v 1.7 1998/03/09 04:46:26 jb Exp $ * */ #include <errno.h> @@ -844,6 +844,7 @@ _thread_signal(pthread_t pthread, int sig) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_RUNNING: @@ -1142,6 +1143,7 @@ _thread_kern_select(int wait_reqd) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_RUNNING: @@ -1491,6 +1493,7 @@ _thread_kern_select(int wait_reqd) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_SIGWAIT: diff --git a/lib/libkse/thread/thr_create.c b/lib/libkse/thread/thr_create.c index 3dcd944..c9c6c9f 100644 --- a/lib/libkse/thread/thr_create.c +++ b/lib/libkse/thread/thr_create.c @@ -40,6 +40,7 @@ #include <machine/reg.h> #include <pthread.h> #include "pthread_private.h" +#include "libc_private.h" int _thread_create(pthread_t * thread, const pthread_attr_t * attr, @@ -254,6 +255,12 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, int ret = 0; /* + * Locking functions in libc are required when there are + * threads other than the initial thread. + */ + __isthreaded = 1; + + /* * Call the low level thread creation function which allows a parent * thread to be specified: */ diff --git a/lib/libkse/thread/thr_info.c b/lib/libkse/thread/thr_info.c index be25d45..fe6565b 100644 --- a/lib/libkse/thread/thr_info.c +++ b/lib/libkse/thread/thr_info.c @@ -52,7 +52,8 @@ static const struct s_thread_info thread_info[] = { {PS_FDLR_WAIT , "Waiting for a file read lock"}, {PS_FDLW_WAIT , "Waiting for a file write lock"}, {PS_FDR_WAIT , "Waiting for read"}, - {PS_FDW_WAIT , "Waitingfor write"}, + {PS_FDW_WAIT , "Waiting for write"}, + {PS_FILE_WAIT , "Waiting for FILE lock"}, {PS_SELECT_WAIT , "Waiting on select"}, {PS_SLEEP_WAIT , "Sleeping"}, {PS_WAIT_WAIT , "Waiting process"}, @@ -87,8 +88,8 @@ _thread_dump_info(void) if (thread_info[j].state == pthread->state) break; /* Output a record for the current thread: */ - sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n", - pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); + sprintf(s, "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n", + pthread, (pthread->name == NULL) ? "":pthread->name, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); /* Check if this is the running thread: */ @@ -105,7 +106,7 @@ _thread_dump_info(void) } /* Process according to thread state: */ switch (pthread->state) { - /* File descriptor read lock wait: */ + /* File descriptor read lock wait: */ case PS_FDLR_WAIT: case PS_FDLW_WAIT: case PS_FDR_WAIT: @@ -117,10 +118,10 @@ _thread_dump_info(void) _thread_sys_write(fd, s, strlen(s)); break; - /* - * Trap other states that are not explicitly - * coded to dump information: - */ + /* + * Trap other states that are not explicitly + * coded to dump information: + */ default: /* Nothing to do here. */ break; @@ -179,4 +180,14 @@ _thread_dump_info(void) } return; } + +/* Set the thread name for debug: */ +void +pthread_set_name_np(pthread_t thread, char *name) +{ + /* Check if the caller has specified a valid thread: */ + if (thread != NULL && thread->magic == PTHREAD_MAGIC) + thread->name = strdup(name); + return; +} #endif diff --git a/lib/libkse/thread/thr_kern.c b/lib/libkse/thread/thr_kern.c index eeae75c..9356c4c 100644 --- a/lib/libkse/thread/thr_kern.c +++ b/lib/libkse/thread/thr_kern.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: uthread_kern.c,v 1.6 1998/02/13 01:27:33 julian Exp $ + * $Id: uthread_kern.c,v 1.7 1998/03/09 04:46:26 jb Exp $ * */ #include <errno.h> @@ -844,6 +844,7 @@ _thread_signal(pthread_t pthread, int sig) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_RUNNING: @@ -1142,6 +1143,7 @@ _thread_kern_select(int wait_reqd) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_RUNNING: @@ -1491,6 +1493,7 @@ _thread_kern_select(int wait_reqd) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_SIGWAIT: diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h index dc36d8d..5ceeaba 100644 --- a/lib/libkse/thread/thr_private.h +++ b/lib/libkse/thread/thr_private.h @@ -50,6 +50,7 @@ */ #include <setjmp.h> #include <signal.h> +#include <sys/queue.h> #include <sys/types.h> #include <sys/time.h> #include <sched.h> @@ -219,6 +220,7 @@ enum pthread_state { PS_FDLW_WAIT, PS_FDR_WAIT, PS_FDW_WAIT, + PS_FILE_WAIT, PS_SELECT_WAIT, PS_SLEEP_WAIT, PS_WAIT_WAIT, @@ -283,6 +285,7 @@ struct pthread { */ #define PTHREAD_MAGIC ((u_int32_t) 0xd09ba115) u_int32_t magic; + char *name; /* * Pointer to the next thread in the thread linked list. @@ -387,12 +390,18 @@ struct pthread { * The current thread can belong to only one queue at a time. * * Pointer to queue (if any) on which the current thread is waiting. + * + * XXX The queuing should be changed to use the TAILQ entry below. + * XXX For the time being, it's hybrid. */ struct pthread_queue *queue; /* Pointer to next element in queue. */ struct pthread *qnxt; + /* Queue entry for this thread: */ + TAILQ_ENTRY(pthread) qe; + /* Wait data. */ union pthread_wait_data data; @@ -634,8 +643,6 @@ ssize_t _thread_sys_sendto(int, const void *,size_t, int, const struct sockaddr /* #include <stdio.h> */ #ifdef _STDIO_H_ -void _thread_flockfile(FILE *fp,char *fname,int lineno); -void _thread_funlockfile(FILE *fp); FILE *_thread_sys_fdopen(int, const char *); FILE *_thread_sys_fopen(const char *, const char *); FILE *_thread_sys_freopen(const char *, const char *, FILE *); diff --git a/lib/libpthread/thread/thr_create.c b/lib/libpthread/thread/thr_create.c index 3dcd944..c9c6c9f 100644 --- a/lib/libpthread/thread/thr_create.c +++ b/lib/libpthread/thread/thr_create.c @@ -40,6 +40,7 @@ #include <machine/reg.h> #include <pthread.h> #include "pthread_private.h" +#include "libc_private.h" int _thread_create(pthread_t * thread, const pthread_attr_t * attr, @@ -254,6 +255,12 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, int ret = 0; /* + * Locking functions in libc are required when there are + * threads other than the initial thread. + */ + __isthreaded = 1; + + /* * Call the low level thread creation function which allows a parent * thread to be specified: */ diff --git a/lib/libpthread/thread/thr_info.c b/lib/libpthread/thread/thr_info.c index be25d45..fe6565b 100644 --- a/lib/libpthread/thread/thr_info.c +++ b/lib/libpthread/thread/thr_info.c @@ -52,7 +52,8 @@ static const struct s_thread_info thread_info[] = { {PS_FDLR_WAIT , "Waiting for a file read lock"}, {PS_FDLW_WAIT , "Waiting for a file write lock"}, {PS_FDR_WAIT , "Waiting for read"}, - {PS_FDW_WAIT , "Waitingfor write"}, + {PS_FDW_WAIT , "Waiting for write"}, + {PS_FILE_WAIT , "Waiting for FILE lock"}, {PS_SELECT_WAIT , "Waiting on select"}, {PS_SLEEP_WAIT , "Sleeping"}, {PS_WAIT_WAIT , "Waiting process"}, @@ -87,8 +88,8 @@ _thread_dump_info(void) if (thread_info[j].state == pthread->state) break; /* Output a record for the current thread: */ - sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n", - pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); + sprintf(s, "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n", + pthread, (pthread->name == NULL) ? "":pthread->name, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); /* Check if this is the running thread: */ @@ -105,7 +106,7 @@ _thread_dump_info(void) } /* Process according to thread state: */ switch (pthread->state) { - /* File descriptor read lock wait: */ + /* File descriptor read lock wait: */ case PS_FDLR_WAIT: case PS_FDLW_WAIT: case PS_FDR_WAIT: @@ -117,10 +118,10 @@ _thread_dump_info(void) _thread_sys_write(fd, s, strlen(s)); break; - /* - * Trap other states that are not explicitly - * coded to dump information: - */ + /* + * Trap other states that are not explicitly + * coded to dump information: + */ default: /* Nothing to do here. */ break; @@ -179,4 +180,14 @@ _thread_dump_info(void) } return; } + +/* Set the thread name for debug: */ +void +pthread_set_name_np(pthread_t thread, char *name) +{ + /* Check if the caller has specified a valid thread: */ + if (thread != NULL && thread->magic == PTHREAD_MAGIC) + thread->name = strdup(name); + return; +} #endif diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c index eeae75c..9356c4c 100644 --- a/lib/libpthread/thread/thr_kern.c +++ b/lib/libpthread/thread/thr_kern.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: uthread_kern.c,v 1.6 1998/02/13 01:27:33 julian Exp $ + * $Id: uthread_kern.c,v 1.7 1998/03/09 04:46:26 jb Exp $ * */ #include <errno.h> @@ -844,6 +844,7 @@ _thread_signal(pthread_t pthread, int sig) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_RUNNING: @@ -1142,6 +1143,7 @@ _thread_kern_select(int wait_reqd) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_RUNNING: @@ -1491,6 +1493,7 @@ _thread_kern_select(int wait_reqd) case PS_DEAD: case PS_FDLR_WAIT: case PS_FDLW_WAIT: + case PS_FILE_WAIT: case PS_JOIN: case PS_MUTEX_WAIT: case PS_SIGWAIT: diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h index dc36d8d..5ceeaba 100644 --- a/lib/libpthread/thread/thr_private.h +++ b/lib/libpthread/thread/thr_private.h @@ -50,6 +50,7 @@ */ #include <setjmp.h> #include <signal.h> +#include <sys/queue.h> #include <sys/types.h> #include <sys/time.h> #include <sched.h> @@ -219,6 +220,7 @@ enum pthread_state { PS_FDLW_WAIT, PS_FDR_WAIT, PS_FDW_WAIT, + PS_FILE_WAIT, PS_SELECT_WAIT, PS_SLEEP_WAIT, PS_WAIT_WAIT, @@ -283,6 +285,7 @@ struct pthread { */ #define PTHREAD_MAGIC ((u_int32_t) 0xd09ba115) u_int32_t magic; + char *name; /* * Pointer to the next thread in the thread linked list. @@ -387,12 +390,18 @@ struct pthread { * The current thread can belong to only one queue at a time. * * Pointer to queue (if any) on which the current thread is waiting. + * + * XXX The queuing should be changed to use the TAILQ entry below. + * XXX For the time being, it's hybrid. */ struct pthread_queue *queue; /* Pointer to next element in queue. */ struct pthread *qnxt; + /* Queue entry for this thread: */ + TAILQ_ENTRY(pthread) qe; + /* Wait data. */ union pthread_wait_data data; @@ -634,8 +643,6 @@ ssize_t _thread_sys_sendto(int, const void *,size_t, int, const struct sockaddr /* #include <stdio.h> */ #ifdef _STDIO_H_ -void _thread_flockfile(FILE *fp,char *fname,int lineno); -void _thread_funlockfile(FILE *fp); FILE *_thread_sys_fdopen(int, const char *); FILE *_thread_sys_fopen(const char *, const char *); FILE *_thread_sys_freopen(const char *, const char *, FILE *); |