mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
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.
This commit is contained in:
parent
ec216c2634
commit
d60f0fa60d
13 changed files with 404 additions and 86 deletions
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -253,6 +254,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:
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
void
|
||||
_thread_flockfile(FILE * fp, char *fname, int lineno)
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
int fd, flags;
|
||||
int status;
|
||||
struct file_lock *p;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
/* 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;
|
||||
|
||||
if ((fd = fileno(fp)) >= 0) {
|
||||
if (fp->_flags & __SRW) {
|
||||
flags = FD_READ | FD_WRITE;
|
||||
} else {
|
||||
if (fp->_flags & __SWR) {
|
||||
flags = FD_WRITE;
|
||||
} else {
|
||||
flags = FD_READ;
|
||||
}
|
||||
}
|
||||
|
||||
/* This might fail but POSIX doesn't give a damn. */
|
||||
_thread_fd_lock(fd, flags, NULL, fname, lineno);
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
return;
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
_thread_ftrylockfile(FILE * fp)
|
||||
/*
|
||||
* Lock a file, assuming that there is no lock structure currently1
|
||||
* assigned to it.
|
||||
*/
|
||||
static
|
||||
struct file_lock *
|
||||
do_lock(int idx, FILE *fp)
|
||||
{
|
||||
int fd = 0;
|
||||
int flags;
|
||||
int status;
|
||||
struct file_lock *p;
|
||||
|
||||
if ((fd = fileno(fp)) >= 0) {
|
||||
/* 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
|
||||
_flockfile_debug(FILE * fp, char *fname, int lineno)
|
||||
{
|
||||
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);
|
||||
|
||||
if (fp->_flags & __SRW) {
|
||||
flags = FD_READ | FD_WRITE;
|
||||
} else {
|
||||
if (fp->_flags & __SWR) {
|
||||
flags = FD_WRITE;
|
||||
} else {
|
||||
flags = FD_READ;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
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.
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
return (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_thread_funlockfile(FILE * fp)
|
||||
void
|
||||
_flockfile(FILE * fp)
|
||||
{
|
||||
int fd, flags;
|
||||
int status;
|
||||
_flockfile_debug(fp, __FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((fd = fileno(fp)) >= 0) {
|
||||
int
|
||||
_ftrylockfile(FILE * fp)
|
||||
{
|
||||
int ret = -1;
|
||||
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);
|
||||
|
||||
if (fp->_flags & __SRW) {
|
||||
flags = FD_READ | FD_WRITE;
|
||||
} else if (fp->_flags & __SWR) {
|
||||
flags = FD_WRITE;
|
||||
/* 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 {
|
||||
flags = FD_READ;
|
||||
/*
|
||||
* 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 (ret);
|
||||
}
|
||||
|
||||
void
|
||||
_funlockfile(FILE * fp)
|
||||
{
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -253,6 +254,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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -253,6 +254,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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
Loading…
Reference in a new issue