summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjb <jb@FreeBSD.org>1998-04-11 07:47:22 +0000
committerjb <jb@FreeBSD.org>1998-04-11 07:47:22 +0000
commit19185ac5121f9f5c12adb893404acf3e8c9db6d4 (patch)
treed3cd2f1400e0868d686f6f4a6969a4e33d538f1c /lib
parent0ff63017b40dda207b2aadc9881e0c93e7fd2753 (diff)
downloadFreeBSD-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.h11
-rw-r--r--lib/libc_r/uthread/uthread_create.c7
-rw-r--r--lib/libc_r/uthread/uthread_file.c330
-rw-r--r--lib/libc_r/uthread/uthread_info.c27
-rw-r--r--lib/libc_r/uthread/uthread_kern.c5
-rw-r--r--lib/libkse/thread/thr_create.c7
-rw-r--r--lib/libkse/thread/thr_info.c27
-rw-r--r--lib/libkse/thread/thr_kern.c5
-rw-r--r--lib/libkse/thread/thr_private.h11
-rw-r--r--lib/libpthread/thread/thr_create.c7
-rw-r--r--lib/libpthread/thread/thr_info.c27
-rw-r--r--lib/libpthread/thread/thr_kern.c5
-rw-r--r--lib/libpthread/thread/thr_private.h11
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 *);
OpenPOWER on IntegriCloud