summaryrefslogtreecommitdiffstats
path: root/lib/libpthread
diff options
context:
space:
mode:
authorpeter <peter@openbsd.org>1998-07-21 13:18:53 +0000
committerpeter <peter@openbsd.org>1998-07-21 13:18:53 +0000
commitf952fe14eda234ea5d83f0b522bb74b1b138dec8 (patch)
treed163cb6c22fefe1aeb984101bd7bf3bf8a2fd7d9 /lib/libpthread
parentComplete initial import from mySQL 3.22.4 (mit-pthreads/). (diff)
downloadwireguard-openbsd-f952fe14eda234ea5d83f0b522bb74b1b138dec8.tar.xz
wireguard-openbsd-f952fe14eda234ea5d83f0b522bb74b1b138dec8.zip
Complete initial import from mySQL 3.22.4 (mit-pthreads/).
Lots of dross to move and remove yet. At minimum: o remove GNU config and GNU Makefiles o build arch directory and migrate away machdep/ o rebuild BSD Makefiles o move notes etc. into doc/
Diffstat (limited to 'lib/libpthread')
-rw-r--r--lib/libpthread/COPYRIGHT4
-rw-r--r--lib/libpthread/README93
-rw-r--r--lib/libpthread/pthreads/Makefile.inc64
-rw-r--r--lib/libpthread/pthreads/cond.c329
-rw-r--r--lib/libpthread/pthreads/fd.c954
-rw-r--r--lib/libpthread/pthreads/fd_kern.c1949
-rw-r--r--lib/libpthread/pthreads/fd_pipe.c133
-rw-r--r--lib/libpthread/pthreads/file.c82
-rw-r--r--lib/libpthread/pthreads/globals.c38
-rw-r--r--lib/libpthread/pthreads/malloc.c114
-rw-r--r--lib/libpthread/pthreads/mutex.c262
-rw-r--r--lib/libpthread/pthreads/pthread.c289
-rw-r--r--lib/libpthread/pthreads/pthread_attr.c159
-rw-r--r--lib/libpthread/pthreads/pthread_detach.c58
-rw-r--r--lib/libpthread/pthreads/pthread_join.c118
-rw-r--r--lib/libpthread/pthreads/pthread_once.c14
-rw-r--r--lib/libpthread/pthreads/queue.c28
-rw-r--r--lib/libpthread/pthreads/signal.c604
-rw-r--r--lib/libpthread/pthreads/sleep.c403
-rw-r--r--lib/libpthread/stdio/Makefile.inc18
-rw-r--r--lib/libpthread/stdio/README19
-rw-r--r--lib/libpthread/stdio/clrerr.c3
-rw-r--r--lib/libpthread/stdio/fclose.c10
-rw-r--r--lib/libpthread/stdio/fdopen.c5
-rw-r--r--lib/libpthread/stdio/feof.c3
-rw-r--r--lib/libpthread/stdio/ferror.c3
-rw-r--r--lib/libpthread/stdio/fflush.c7
-rw-r--r--lib/libpthread/stdio/fgetc.c18
-rw-r--r--lib/libpthread/stdio/fgetline.c7
-rw-r--r--lib/libpthread/stdio/fgetpos.c41
-rw-r--r--lib/libpthread/stdio/fgets.c8
-rw-r--r--lib/libpthread/stdio/fileno.c3
-rw-r--r--lib/libpthread/stdio/findfp.c28
-rw-r--r--lib/libpthread/stdio/flags.c7
-rw-r--r--lib/libpthread/stdio/floatio.h2
-rw-r--r--lib/libpthread/stdio/fopen.c7
-rw-r--r--lib/libpthread/stdio/fpurge.c3
-rw-r--r--lib/libpthread/stdio/fputc.c21
-rw-r--r--lib/libpthread/stdio/fputs.c3
-rw-r--r--lib/libpthread/stdio/fread.c7
-rw-r--r--lib/libpthread/stdio/freopen.c11
-rw-r--r--lib/libpthread/stdio/fsetpos.c3
-rw-r--r--lib/libpthread/stdio/fvwrite.c8
-rw-r--r--lib/libpthread/stdio/fvwrite.h4
-rw-r--r--lib/libpthread/stdio/fwalk.c15
-rw-r--r--lib/libpthread/stdio/fwrite.c5
-rw-r--r--lib/libpthread/stdio/getc.c3
-rw-r--r--lib/libpthread/stdio/getc_unlocked.c3
-rw-r--r--lib/libpthread/stdio/getchar.c3
-rw-r--r--lib/libpthread/stdio/getchar_unlocked.c3
-rw-r--r--lib/libpthread/stdio/gets.c4
-rw-r--r--lib/libpthread/stdio/getw.c3
-rw-r--r--lib/libpthread/stdio/glue.h7
-rw-r--r--lib/libpthread/stdio/local.h36
-rw-r--r--lib/libpthread/stdio/makebuf.c5
-rw-r--r--lib/libpthread/stdio/mktemp.c2
-rw-r--r--lib/libpthread/stdio/perror.c36
-rw-r--r--lib/libpthread/stdio/printf.c4
-rw-r--r--lib/libpthread/stdio/putc.c3
-rw-r--r--lib/libpthread/stdio/putc_unlocked.c3
-rw-r--r--lib/libpthread/stdio/putchar.c3
-rw-r--r--lib/libpthread/stdio/putchar_unlocked.c3
-rw-r--r--lib/libpthread/stdio/puts.c3
-rw-r--r--lib/libpthread/stdio/putw.c3
-rw-r--r--lib/libpthread/stdio/refill.c26
-rw-r--r--lib/libpthread/stdio/remove.c4
-rw-r--r--lib/libpthread/stdio/rewind.c3
-rw-r--r--lib/libpthread/stdio/rget.c3
-rw-r--r--lib/libpthread/stdio/setbuf.c3
-rw-r--r--lib/libpthread/stdio/setbuffer.c3
-rw-r--r--lib/libpthread/stdio/setvbuf.c5
-rw-r--r--lib/libpthread/stdio/stdio.c28
-rw-r--r--lib/libpthread/stdio/tmpfile.c6
-rw-r--r--lib/libpthread/stdio/tmpnam.c2
-rw-r--r--lib/libpthread/stdio/ungetc.c7
-rw-r--r--lib/libpthread/stdio/vfprintf.c30
-rw-r--r--lib/libpthread/stdio/vprintf.c6
-rw-r--r--lib/libpthread/stdio/vscanf.c6
-rw-r--r--lib/libpthread/stdio/vsnprintf.c8
-rw-r--r--lib/libpthread/stdio/vsprintf.c9
-rw-r--r--lib/libpthread/stdio/vsscanf.c6
-rw-r--r--lib/libpthread/stdio/wbuf.c1
-rw-r--r--lib/libpthread/stdio/wsetup.c7
83 files changed, 4622 insertions, 1632 deletions
diff --git a/lib/libpthread/COPYRIGHT b/lib/libpthread/COPYRIGHT
index 1fb4e43cf26..1b727cd8dac 100644
--- a/lib/libpthread/COPYRIGHT
+++ b/lib/libpthread/COPYRIGHT
@@ -1,5 +1,5 @@
-Copyright (c) 1993 by Chris Provenzano and contributors, proven@mit.edu
-All rights reserved.
+Copyright (c) 1993, 1994, 1995, 1996 by Chris Provenzano and contributors,
+proven@mit.edu All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/lib/libpthread/README b/lib/libpthread/README
index f546325d948..0a55bcd94bb 100644
--- a/lib/libpthread/README
+++ b/lib/libpthread/README
@@ -1,15 +1,19 @@
-This pthread package is/will be based on the POSIX1003.4a Draft 7 pthread
-standard, and Frank Mullers paper on signal handelling presented
-at the Winter 93 USENIX conference.
+This pthread package is/will be based on the POSIX1003.1c Draft 10 pthread
+standard, and Frank Muellers paper on signal handeling presented at the
+Winter 93 USENIX conference.
It is currently being designed and written by me, Chris Provenzano.
-All bug, comments, and questions can be sent me at either
-proven@athena.mit.edu or proven@sun-lamp.cs.berkeley.edu
-PLEASE, don't send questions, bugs or patches to any of the *BSD* mailing lists.
+All bug, comments, and questions can be sent me at proven@mit.edu,
+or pthreads@mit.edu.
-Thanks goes to John Carr jfc@mit.edu for porting this to the IBM/RT,
-and for his bug reports and fixes, Greg Hudson and Mark Eichin for the
-testing they've done, and all the others.
+PLEASE, don't send questions, bugs or patches to any of the *BSD*, Linux
+or GNU mailing lists.
+
+Thanks goes to Ken Raeburn for his help on the Sparc port, the configurator,
+and his many suggestions, Greg Hudson for the thread safe net routines and
+all the testing he's done.
+
+More thanks to Mark Eichin and all the others for the testing they have done.
PORTING
One of the goals of this user space implementation of pthreads is that it
@@ -18,68 +22,19 @@ but some is.
If you want to port it to another platform here are a few basic hints.
-There are currently three files you'll have to creat for your
-architecture, machdep.h, machdep.c and syscall.S.
-The first two are necessary to get the context switch section of
-the pthread package running, the third is for all the syscalls.
-
-To do an initial port, create an appropriate machdep.h, and machdep.c
-and define PTHREAD_INITIAL_PORT in the Makefile
-
-Comment out references to the stdio package.
+You will need to create a machdep.h, machdep.c and syscall.S for the
+new architecture. The first two are necessary to get the context switch
+section of the pthread package running, the third is for all the syscalls.
INCLUDE FILES AND PORTING
-To continue to make this package portable, some basic rules on includes
-files must be followed.
-
-pthread.h should be included first (if it is to be included).
-machdep.h should define size_t if the system doesn't define it already
-
-posix.h should be included last. This file is used to correct non
-POSIX features, after everything else has been defined.
-
-INTERNAL LOCKING
-To prevent deadlocks the following rules were used for locks.
-
-1. Local locks for mutex queues and other like things are only locked
- by running threads, at NO time will a local lock be held by
- a thread in a non running state.
-2. Only threads that are in a run state can attempt to lock another thread,
- this way, we can assume that the lock will be released shortly, and don't
- have to unlock the local lock.
-3. The only time a thread will have a pthread->lock and is not in a run
- state is when it is in the reschedule routine.
-4. The reschedule routine assumes all local locks have been released,
- there is a lock on the currently running thread (pthread_run),
- and that this thread is being rescheduled to a non running state.
- It is safe to unlock the currently running threads lock after it
- has been rescheduled.
-5. The reschedule routine locks the kernel, sets the state of the currently
- running thread, unlocks the currently running thread, calls the
- context switch routines.
-6 the kernel lock is used only ...
-
-
-7. The order of locking is ...
-
-1 local locks
-2 pthread->lock /* Assumes it will get it soon */
-3 pthread_run->lock /* Assumes it will get it soon, but must release 2 */
-4 kernel lock /* Currently assumes it will ALWAYS get it. */
-
-8. The kernel lock will be changed to a spin lock for systems that
-already support kernel threads, this way we can mutiplex threads onto
-kernel threads.
-9. There are points where the kernel is locked and it needs to get
-either a local lock or a pthread lock, if at these points the code
-fails to get the lock the kernel gives up and sets a flag which will
-be checked at a later point.
-10. Interrupts are dissabled while the kernel is locked, the interrupt
-mask must be checked afterwards or cleared in some way, after interrputs
-have been reenabled, this allows back to back interrupts, but should always
-avoid missing one.
-
-Copyright (c) 1993 Chris Provenzano. All rights reserved.
+In addition to the above three files you need to create a slew of .h files.
+Take a look at an existing port to determine what is in each, and then
+take a look at your system header files to determine what to put in them.
+------------------------------------------------------------------------------
+Copyright (c) 1993, 1994, 1995, 1996 Chris Provenzano. All rights reserved.
This product includes software developed by the Univeristy of California,
Berkeley and its contributors.
+
+For further licencing and distribution restrictions see the file COPYRIGHT
+included in this directory.
diff --git a/lib/libpthread/pthreads/Makefile.inc b/lib/libpthread/pthreads/Makefile.inc
index 86c63233c1a..dfb02045351 100644
--- a/lib/libpthread/pthreads/Makefile.inc
+++ b/lib/libpthread/pthreads/Makefile.inc
@@ -1,9 +1,65 @@
# from: @(#)Makefile.inc 5.6 (Berkeley) 6/4/91
# pthread sources
-.PATH: ${.CURDIR}/pthreads
+.PATH: ${srcdir}/pthreads
-SRCS+= cond.c fd.c fd_kern.c fd_pipe.c file.c globals.c malloc.c mutex.c \
- pthread.c pthread_attr.c queue.c signal.c pthread_join.c \
- pthread_detach.c sleep.c
+SRCS+= cleanup.c cond.c fd.c fd_kern.c fd_pipe.c file.c globals.c malloc.c \
+ mutex.c pthread.c pthread_attr.c queue.c signal.c machdep.c syscall.S \
+ pthread_join.c pthread_detach.c pthread_once.c sleep.c specific.c \
+ process.c wait.c errno.c schedparam.c _exit.c prio_queue.c \
+ pthread_init.c init.cc sig.c info.c mutexattr.c select.c wrapper.c \
+ dump_state.c pthread_kill.c condattr.c pthread_cancel.c panic.c
+
+.if $(HAVE_SYSCALL_TEMPLATE) == yes
+OBJS+= syscalls.o
+.if !defined(NOPIC)
+SOBJS+= syscalls.so
+SYSCALL_PIC_COMPILE= $(CC) $(CFLAGS) -DSYSCALL_NAME=$$syscall -DPIC -c ${.CURDIR}/syscall-template.S -o ${.OBJDIR}/syscalls/S$$syscall.so
+.else
+SYSCALL_PIC_COMPILE= true
+.endif
+.if !defined(NOPROFILE)
+POBJS+= syscalls.po
+SYSCALL_PROF_COMPILE= $(CC) $(CFLAGS) -DSYSCALL_NAME=$$syscall -pg -c ${.CURDIR}/syscall-template.S -o ${.OBJDIR}/syscalls/S$$syscall.po
+.else
+SYSCALL_PROF_COMPILE= true
+.endif
+
+syscalls.o syscalls.so syscalls.po : syscall-template.S
+ -rm -rf ${.OBJDIR}/syscalls
+ mkdir ${.OBJDIR}/syscalls
+ for syscall in $(AVAILABLE_SYSCALLS) ; do \
+ case " $(SYSCALL_EXCEPTIONS) " in \
+ *" "$$syscall" "*) ;; \
+ *) echo $$syscall ; \
+ $(CC) $(CFLAGS) -DSYSCALL_NAME=$$syscall -c ${.CURDIR}/syscall-template.S -o ${.OBJDIR}/syscalls/S$$syscall.o ; \
+ $(SYSCALL_PIC_COMPILE) ; \
+ $(SYSCALL_PROF_COMPILE) ;; \
+ esac ; \
+ done
+ x=`pwd` && cd ${.OBJDIR}/syscalls && ld -r -o ../syscalls.o *.o && cd $$x
+.if !defined(NOPIC)
+ x=`pwd` && cd ${.OBJDIR}/syscalls && ld -r -o ../syscalls.so *.so && cd $$x
+.endif
+.if !defined(NOPROFILE)
+ x=`pwd` && cd ${.OBJDIR}/syscalls && ld -r -o ../syscalls.po *.po && cd $$x
+.endif
+ rm -r ${.OBJDIR}/syscalls
+.endif
+
+syscall.o: syscall.S
+ cpp ${CPPFLAGS} ${.CURDIR}/syscall.S > syscall.i
+ as syscall.i
+ rm syscall.i
+ mv a.out syscall.o
+
+syscall.po: syscall.S
+ cpp ${CPPFLAGS} ${.CURDIR}/syscall.S > syscall.i
+ as syscall.i
+ rm syscall.i
+ mv a.out syscall.po
+
+MAN2+=
+
+MAN3+=
diff --git a/lib/libpthread/pthreads/cond.c b/lib/libpthread/pthreads/cond.c
index 50e7c8e3905..f84cfce0aab 100644
--- a/lib/libpthread/pthreads/cond.c
+++ b/lib/libpthread/pthreads/cond.c
@@ -29,19 +29,47 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Description : Condition cariable functions.
+ * Description : Condition variable functions.
*
* 1.00 93/10/28 proven
* -Started coding this file.
*/
#ifndef lint
-static const char rcsid[] = "$Id: cond.c,v 1.1.1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: cond.c,v 1.16 1994/02/07 02:18:35 proven Exp $";
+static const char rcsid[] = "$Id: cond.c,v 1.1.1.2 1998/07/21 13:19:50 peter Exp $";
#endif
#include <pthread.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <timers.h>
#include <errno.h>
+#ifndef ETIME
+#define ETIME ETIMEDOUT
+#endif
+
+/* ==========================================================================
+ * pthread_cond_is_debug()
+ *
+ * Check that cond is a debug cond and if so returns entry number into
+ * array of debug condes.
+ */
+static int pthread_cond_debug_count = 0;
+static pthread_cond_t ** pthread_cond_debug_ptrs = NULL;
+static pthread_mutex_t pthread_cond_debug_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static inline int pthread_cond_is_debug(pthread_cond_t * cond)
+{
+ int i;
+
+ for (i = 0; i < pthread_cond_debug_count; i++) {
+ if (pthread_cond_debug_ptrs[i] == cond) {
+ return(i);
+ }
+ }
+ return(NOTOK);
+}
/* ==========================================================================
* pthread_cond_init()
*
@@ -49,24 +77,52 @@ static const char rcsid[] = "$Id: cond.c,v 1.1.1.1 1995/10/18 08:43:04 deraadt E
* ENOMEM, EAGAIN should never be returned. Arch that have
* weird constraints may need special coding.
*/
-int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
+int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
{
+ enum pthread_condtype type;
+
/* Only check if attr specifies some mutex type other than fast */
if ((cond_attr) && (cond_attr->c_type != COND_TYPE_FAST)) {
if (cond_attr->c_type >= COND_TYPE_MAX) {
return(EINVAL);
}
- if (cond->c_flags & COND_FLAGS_INITED) {
+ type = cond_attr->c_type;
+ } else {
+ type = COND_TYPE_FAST;
+ }
+
+ switch (type) {
+ case COND_TYPE_FAST:
+ case COND_TYPE_COUNTING_FAST:
+ break;
+ case COND_TYPE_DEBUG:
+ pthread_mutex_lock(&pthread_cond_debug_mutex);
+ if (pthread_cond_is_debug(cond) == NOTOK) {
+ pthread_cond_t ** new;
+
+ if ((new = (pthread_cond_t **)realloc(pthread_cond_debug_ptrs,
+ (pthread_cond_debug_count + 1) * (sizeof(void *)))) == NULL) {
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+ return(ENOMEM);
+ }
+ pthread_cond_debug_ptrs = new;
+ pthread_cond_debug_ptrs[pthread_cond_debug_count++] = cond;
+ } else {
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
return(EBUSY);
}
- cond->c_type = cond_attr->c_type;
- } else {
- cond->c_type = COND_TYPE_FAST;
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+ break;
+ case COND_TYPE_STATIC_FAST:
+ defualt:
+ return(EINVAL);
+ break;
}
+
/* Set all other paramaters */
pthread_queue_init(&cond->c_queue);
cond->c_flags |= COND_FLAGS_INITED;
- cond->c_lock = SEMAPHORE_CLEAR;
+ cond->c_type = type;
return(OK);
}
@@ -75,10 +131,29 @@ int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
*/
int pthread_cond_destroy(pthread_cond_t *cond)
{
+ int i;
+
/* Only check if cond is of type other than fast */
switch(cond->c_type) {
case COND_TYPE_FAST:
+ case COND_TYPE_COUNTING_FAST:
break;
+ case COND_TYPE_DEBUG:
+ if (pthread_queue_get(&(cond->c_queue))) {
+ return(EBUSY);
+ }
+ pthread_mutex_lock(&pthread_cond_debug_mutex);
+ if ((i = pthread_cond_is_debug(cond)) == NOTOK) {
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+ return(EINVAL);
+ }
+
+ /* Remove the cond from the list of debug condition variables */
+ pthread_cond_debug_ptrs[i] =
+ pthread_cond_debug_ptrs[--pthread_cond_debug_count];
+ pthread_cond_debug_ptrs[pthread_cond_debug_count] = NULL;
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+ break;
case COND_TYPE_STATIC_FAST:
default:
return(EINVAL);
@@ -87,8 +162,6 @@ int pthread_cond_destroy(pthread_cond_t *cond)
/* Cleanup cond, others might want to use it. */
pthread_queue_init(&cond->c_queue);
- cond->c_flags |= COND_FLAGS_INITED;
- cond->c_lock = SEMAPHORE_CLEAR;
cond->c_flags = 0;
return(OK);
}
@@ -98,38 +171,170 @@ int pthread_cond_destroy(pthread_cond_t *cond)
*/
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
- semaphore *lock, *plock;
int rval;
- lock = &(cond->c_lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
+ pthread_sched_prevent();
+ switch (cond->c_type) {
+ case COND_TYPE_DEBUG:
+ pthread_mutex_lock(&pthread_cond_debug_mutex);
+ if (pthread_cond_is_debug(cond) == NOTOK) {
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+ pthread_sched_resume();
+ return(EINVAL);
+ }
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+
+ /*
+ * Fast condition variables do not check for any error conditions.
+ */
+ case COND_TYPE_FAST:
+ case COND_TYPE_STATIC_FAST:
+ pthread_queue_enq(&cond->c_queue, pthread_run);
+ pthread_mutex_unlock(mutex);
+
+ pthread_run->data.mutex = mutex;
+
+ SET_PF_WAIT_EVENT(pthread_run);
+ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ /* Reschedule will unlock pthread_run */
+ pthread_resched_resume(PS_COND_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+ CLEAR_PF_DONE_EVENT(pthread_run);
+
+ pthread_run->data.mutex = NULL;
+
+ rval = pthread_mutex_lock(mutex);
+ return(rval);
+ break;
+ case COND_TYPE_COUNTING_FAST:
+ {
+ int count = mutex->m_data.m_count;
+
+ pthread_queue_enq(&cond->c_queue, pthread_run);
+ pthread_mutex_unlock(mutex);
+ mutex->m_data.m_count = 1;
+
+ pthread_run->data.mutex = mutex;
+
+ SET_PF_WAIT_EVENT(pthread_run);
+ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ /* Reschedule will unlock pthread_run */
+ pthread_resched_resume(PS_COND_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+ CLEAR_PF_DONE_EVENT(pthread_run);
+
+ pthread_run->data.mutex = NULL;
+
+ rval = pthread_mutex_lock(mutex);
+ mutex->m_data.m_count = count;
+ return(rval);
+ break;
+ }
+ default:
+ rval = EINVAL;
+ break;
}
+ pthread_sched_resume();
+ return(rval);
+}
+
+/* ==========================================================================
+ * pthread_cond_timedwait()
+ */
+int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec * abstime)
+{
+ struct timespec current_time, new_time;
+ int rval = OK;
+ pthread_sched_prevent();
+ machdep_gettimeofday(& current_time);
+
switch (cond->c_type) {
+ case COND_TYPE_DEBUG:
+ pthread_mutex_lock(&pthread_cond_debug_mutex);
+ if (pthread_cond_is_debug(cond) == NOTOK) {
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+ pthread_sched_resume();
+ return(EINVAL);
+ }
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+
/*
* Fast condition variables do not check for any error conditions.
*/
case COND_TYPE_FAST:
case COND_TYPE_STATIC_FAST:
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
+
+ /* Set pthread wakeup time*/
+ pthread_run->wakeup_time = *abstime;
+
+ /* Install us on the sleep queue */
+ sleep_schedule (&current_time, &(pthread_run->wakeup_time));
+
+ pthread_queue_enq(&cond->c_queue, pthread_run);
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_mutex_unlock(mutex);
+
+ pthread_run->data.mutex = mutex;
+
+ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ /* Reschedule will unlock pthread_run */
+ pthread_resched_resume(PS_COND_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+
+ pthread_run->data.mutex = NULL;
+
+ /* Remove ourselves from sleep queue. If we fail then we timedout */
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ SET_ERRNO(ETIME);
+ rval = ETIME;
}
+
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_mutex_lock(mutex);
+ return(rval);
+ break;
+ case COND_TYPE_COUNTING_FAST:
+ {
+ int count = mutex->m_data.m_count;
+
+ /* Set pthread wakeup time*/
+ pthread_run->wakeup_time = *abstime;
+
+ /* Install us on the sleep queue */
+ sleep_schedule (&current_time, &(pthread_run->wakeup_time));
+
pthread_queue_enq(&cond->c_queue, pthread_run);
+ SET_PF_WAIT_EVENT(pthread_run);
pthread_mutex_unlock(mutex);
- SEMAPHORE_RESET(lock);
+ pthread_run->data.mutex = mutex;
+
+ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
/* Reschedule will unlock pthread_run */
- reschedule(PS_COND_WAIT);
+ pthread_resched_resume(PS_COND_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+
+ pthread_run->data.mutex = NULL;
+
+ /* Remove ourselves from sleep queue. If we fail then we timedout */
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ SET_ERRNO(ETIME);
+ rval = ETIME;
+ }
- return(pthread_mutex_lock(mutex));
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_mutex_lock(mutex);
+ mutex->m_data.m_count = count;
+ return(rval);
break;
+ }
default:
rval = EINVAL;
break;
}
- SEMAPHORE_RESET(lock);
+ pthread_sched_resume();
return(rval);
}
@@ -139,25 +344,28 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_signal(pthread_cond_t *cond)
{
struct pthread *pthread;
- semaphore *lock, *plock;
int rval;
- lock = &(cond->c_lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
+ pthread_sched_prevent();
switch (cond->c_type) {
+ case COND_TYPE_DEBUG:
+ pthread_mutex_lock(&pthread_cond_debug_mutex);
+ if (pthread_cond_is_debug(cond) == NOTOK) {
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+ pthread_sched_resume();
+ return(EINVAL);
+ }
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+
case COND_TYPE_FAST:
case COND_TYPE_STATIC_FAST:
- if (pthread = pthread_queue_get(&cond->c_queue)) {
- plock = &(pthread->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
+ if (pthread = pthread_queue_deq(&cond->c_queue)) {
+ if ((SET_PF_DONE_EVENT(pthread)) == OK) {
+ pthread_sched_other_resume(pthread);
+ } else {
+ pthread_sched_resume();
}
- pthread_queue_deq(&cond->c_queue);
- pthread->state = PS_RUNNING;
- SEMAPHORE_RESET(plock);
+ return(OK);
}
rval = OK;
break;
@@ -165,7 +373,7 @@ int pthread_cond_signal(pthread_cond_t *cond)
rval = EINVAL;
break;
}
- SEMAPHORE_RESET(lock);
+ pthread_sched_resume();
return(rval);
}
@@ -176,26 +384,46 @@ int pthread_cond_signal(pthread_cond_t *cond)
*/
int pthread_cond_broadcast(pthread_cond_t *cond)
{
- struct pthread *pthread;
- semaphore *lock, *plock;
+ struct pthread * pthread, * high_pthread, * low_pthread;
int rval;
- lock = &(cond->c_lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
+ pthread_sched_prevent();
switch (cond->c_type) {
+ case COND_TYPE_DEBUG:
+ pthread_mutex_lock(&pthread_cond_debug_mutex);
+ if (pthread_cond_is_debug(cond) == NOTOK) {
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+ pthread_sched_resume();
+ return(EINVAL);
+ }
+ pthread_mutex_unlock(&pthread_cond_debug_mutex);
+
case COND_TYPE_FAST:
case COND_TYPE_STATIC_FAST:
- while (pthread = pthread_queue_get(&cond->c_queue)) {
- plock = &(pthread->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
- pthread_queue_deq(&cond->c_queue);
+ if (pthread = pthread_queue_deq(&cond->c_queue)) {
pthread->state = PS_RUNNING;
- SEMAPHORE_RESET(plock);
+ high_pthread = pthread;
+
+ while (pthread = pthread_queue_deq(&cond->c_queue)) {
+ if (pthread->pthread_priority >
+ high_pthread->pthread_priority) {
+ low_pthread = high_pthread;
+ high_pthread = pthread;
+ } else {
+ low_pthread = pthread;
+ }
+ if ((SET_PF_DONE_EVENT(low_pthread)) == OK) {
+ pthread_prio_queue_enq(pthread_current_prio_queue,
+ low_pthread);
+ low_pthread->state = PS_RUNNING;
+ }
+ }
+ if ((SET_PF_DONE_EVENT(high_pthread)) == OK) {
+ pthread_sched_other_resume(high_pthread);
+ } else {
+ pthread_sched_resume();
+ }
+ return(OK);
}
rval = OK;
break;
@@ -203,6 +431,7 @@ int pthread_cond_broadcast(pthread_cond_t *cond)
rval = EINVAL;
break;
}
- SEMAPHORE_RESET(lock);
+ pthread_sched_resume();
return(rval);
}
+
diff --git a/lib/libpthread/pthreads/fd.c b/lib/libpthread/pthreads/fd.c
index 158dea9b00e..b7bf501dbab 100644
--- a/lib/libpthread/pthreads/fd.c
+++ b/lib/libpthread/pthreads/fd.c
@@ -39,13 +39,25 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: fd.c,v 1.1.1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: fd.c,v 1.16 1994/02/07 02:18:39 proven Exp $";
+static const char rcsid[] = "$Id: fd.c,v 1.1.1.2 1998/07/21 13:19:53 peter Exp $";
#endif
#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/uio.h>
+#include <sys/ioctl.h>
+#include "config.h"
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h> /* For ioctl */
+#endif
+#if __STDC__
#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
#include <fcntl.h>
#include <errno.h>
#include <pthread/posix.h>
@@ -55,8 +67,77 @@ static const char rcsid[] = "$Id: fd.c,v 1.1.1.1 1995/10/18 08:43:04 deraadt Exp
*
* I really should dynamically figure out what the table size is.
*/
-int dtablesize = 64;
-static struct fd_table_entry fd_entry[64];
+static pthread_mutex_t fd_table_mutex = PTHREAD_MUTEX_INITIALIZER;
+static const int dtablecount = 4096/sizeof(struct fd_table_entry);
+int dtablesize;
+
+static int fd_get_pthread_fd_from_kernel_fd( int );
+
+/* ==========================================================================
+ * Allocate dtablecount entries at once and populate the fd_table.
+ *
+ * fd_init_entry()
+ */
+int fd_init_entry(int entry)
+{
+ struct fd_table_entry *fd_entry;
+ int i, round;
+
+ if (fd_table[entry] == NULL) {
+ round = entry - entry % dtablecount;
+
+ if ((fd_entry = (struct fd_table_entry *)malloc(
+ sizeof(struct fd_table_entry) * dtablecount)) == NULL) {
+ return(NOTOK);
+ }
+
+ for (i = 0; i < dtablecount && round+i < dtablesize; i++) {
+ fd_table[round + i] = &fd_entry[i];
+
+ fd_table[round + i]->ops = NULL;
+ fd_table[round + i]->type = FD_NT;
+ fd_table[round + i]->fd.i = NOTOK;
+ fd_table[round + i]->flags = 0;
+ fd_table[round + i]->count = 0;
+
+ pthread_mutex_init(&(fd_table[round + i]->mutex), NULL);
+ pthread_queue_init(&(fd_table[round + i]->r_queue));
+ pthread_queue_init(&(fd_table[round + i]->w_queue));
+ fd_table[round + i]->r_owner = NULL;
+ fd_table[round + i]->w_owner = NULL;
+ fd_table[round + i]->r_lockcount= 0;
+ fd_table[round + i]->w_lockcount= 0;
+
+ fd_table[round + i]->next = NULL;
+ }
+ }
+ return(OK);
+}
+
+/* ==========================================================================
+ * fd_check_entry()
+ */
+int fd_check_entry(unsigned int entry)
+{
+ int ret = OK;
+
+ pthread_mutex_lock(&fd_table_mutex);
+
+ if (entry < dtablesize) {
+ if (fd_table[entry] == NULL) {
+ if (fd_init_entry(entry)) {
+ SET_ERRNO(EBADF);
+ ret = -EBADF;
+ }
+ }
+ } else {
+ SET_ERRNO(EBADF);
+ ret = -EBADF;
+ }
+
+ pthread_mutex_unlock(&fd_table_mutex);
+ return(ret);
+}
/* ==========================================================================
* fd_init()
@@ -65,30 +146,32 @@ void fd_init(void)
{
int i;
- for (i = 0; i < dtablesize; i++) {
- fd_table[i] = &fd_entry[i];
-
- fd_table[i]->ops = NULL;
- fd_table[i]->type = FD_NT;
- fd_table[i]->fd.i = NOTOK;
- fd_table[i]->flags = 0;
- fd_table[i]->count = 0;
-
- pthread_queue_init(&(fd_table[i]->r_queue));
- pthread_queue_init(&(fd_table[i]->w_queue));
-
- fd_table[i]->r_owner = NULL;
- fd_table[i]->w_owner = NULL;
- fd_table[i]->lock = SEMAPHORE_CLEAR;
- fd_table[i]->next = NULL;
- fd_table[i]->lockcount = 0;
+ if ((dtablesize = machdep_sys_getdtablesize()) < 0) {
+ /* Can't figure out the table size. */
+ PANIC();
}
- /* Currently only initialize first 3 fds. */
- fd_kern_init(0);
- fd_kern_init(1);
- fd_kern_init(2);
- printf ("Warning: threaded process may have changed open file descriptors\n");
+ /* select() can only handle FD_SETSIZE descriptors, so our inner loop will
+ * break if dtablesize is higher than that. This should be removed if and
+ * when the inner loop is rewritten to use poll(). */
+ if (dtablesize > FD_SETSIZE) {
+ dtablesize = FD_SETSIZE;
+ }
+
+ if (fd_table = (struct fd_table_entry **)malloc(
+ sizeof(struct fd_table_entry) * dtablesize)) {
+ memset(fd_table, 0, sizeof(struct fd_table_entry) * dtablesize);
+ if (fd_check_entry(0) == OK) {
+ return;
+ }
+ }
+
+ /*
+ * There isn't enough memory to allocate a fd table at init time.
+ * This is a problem.
+ */
+ PANIC();
+
}
/* ==========================================================================
@@ -96,116 +179,143 @@ void fd_init(void)
*/
int fd_allocate()
{
- semaphore *lock;
+ pthread_mutex_t * mutex;
int i;
for (i = 0; i < dtablesize; i++) {
- lock = &(fd_table[i]->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- continue;
- }
- if (fd_table[i]->count || fd_table[i]->r_owner
- || fd_table[i]->w_owner) {
- SEMAPHORE_RESET(lock);
- continue;
- }
- if (fd_table[i]->type == FD_NT) {
- /* Test to see if the kernel version is in use */
- /* If so continue; */
+ if (fd_check_entry(i) == OK) {
+ mutex = &(fd_table[i]->mutex);
+ if (pthread_mutex_trylock(mutex)) {
+ continue;
+ }
+ if (fd_table[i]->count || fd_table[i]->r_owner
+ || fd_table[i]->w_owner) {
+ pthread_mutex_unlock(mutex);
+ continue;
+ }
+ if (fd_table[i]->type == FD_NT) {
+ /* Test to see if the kernel version is in use */
+ if ((machdep_sys_fcntl(i, F_GETFL, NULL)) >= OK) {
+ /* If so continue; */
+ pthread_mutex_unlock(mutex);
+ continue;
+ }
+ }
+ fd_table[i]->count++;
+ pthread_mutex_unlock(mutex);
+ return(i);
}
- fd_table[i]->count++;
- SEMAPHORE_RESET(lock);
- return(i);
}
- pthread_run->error = ENFILE;
+ SET_ERRNO(ENFILE);
return(NOTOK);
}
-/* ==========================================================================
- * fd_free()
- *
- * Assumes fd is locked and owner by pthread_run
- * Don't clear the queues, fd_unlock will do that.
- */
-int fd_free(int fd)
+/*----------------------------------------------------------------------
+ * Function: fd_get_pthread_fd_from_kernel_fd
+ * Purpose: get the fd_table index of a kernel fd
+ * Args: fd = kernel fd to convert
+ * Returns: fd_table index, -1 if not found
+ * Notes:
+ *----------------------------------------------------------------------*/
+static int
+fd_get_pthread_fd_from_kernel_fd( int kfd )
{
- struct fd_table_entry *fd_valid;
- int ret;
+ int j;
- if (ret = --fd_table[fd]->count) {
- /* Separate pthread queue into two distinct queues. */
- fd_valid = fd_table[fd];
- fd_table[fd] = fd_table[fd]->next;
- fd_valid->next = fd_table[fd]->next;
+ /* This is *SICK*, but unless there is a faster way to
+ * turn a kernel fd into an fd_table index, this has to do.
+ */
+ for( j=0; j < dtablesize; j++ ) {
+ if( fd_table[j] &&
+ fd_table[j]->type != FD_NT &&
+ fd_table[j]->type != FD_NIU &&
+ fd_table[j]->fd.i == kfd ) {
+ return j;
+ }
}
- fd_table[fd]->type = FD_NIU;
- fd_table[fd]->fd.i = NOTOK;
- fd_table[fd]->next = NULL;
- fd_table[fd]->flags = 0;
- fd_table[fd]->count = 0;
- return(ret);
+ /* Not listed byfd, Check for kernel fd == pthread fd */
+ if( fd_table[kfd] == NULL || fd_table[kfd]->type == FD_NT ) {
+ /* Assume that the kernel fd is the same */
+ return kfd;
+ }
+
+ return NOTOK; /* Not found */
}
/* ==========================================================================
- * fd_basic_unlock()
- *
+ * fd_basic_basic_unlock()
+ *
* The real work of unlock without the locking of fd_table[fd].lock.
*/
-void fd_basic_unlock(int fd, int lock_type)
+void fd_basic_basic_unlock(struct fd_table_entry * entry, int lock_type)
{
struct pthread *pthread;
- semaphore *plock;
- if (fd_table[fd]->r_owner == pthread_run) {
- if (pthread = pthread_queue_get(&fd_table[fd]->r_queue)) {
-
- plock = &(pthread->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
- pthread_queue_deq(&fd_table[fd]->r_queue);
- fd_table[fd]->r_owner = pthread;
- pthread->state = PS_RUNNING;
- SEMAPHORE_RESET(plock);
- } else {
- fd_table[fd]->r_owner = NULL;
- }
+ if (entry->r_owner == pthread_run) {
+ if ((entry->type == FD_HALF_DUPLEX) ||
+ (entry->type == FD_TEST_HALF_DUPLEX) ||
+ (lock_type == FD_READ) || (lock_type == FD_RDWR)) {
+ if (entry->r_lockcount == 0) {
+ if (pthread = pthread_queue_deq(&entry->r_queue)) {
+ pthread_sched_prevent();
+ entry->r_owner = pthread;
+ if ((SET_PF_DONE_EVENT(pthread)) == OK) {
+ pthread_sched_other_resume(pthread);
+ } else {
+ pthread_sched_resume();
+ }
+ } else {
+ entry->r_owner = NULL;
+ }
+ } else {
+ entry->r_lockcount--;
+ }
+ }
}
- if (fd_table[fd]->w_owner == pthread_run) {
- if (pthread = pthread_queue_get(&fd_table[fd]->w_queue)) {
- plock = &(pthread->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
- pthread_queue_deq(&fd_table[fd]->r_queue);
- fd_table[fd]->w_owner = pthread;
- pthread->state = PS_RUNNING;
- SEMAPHORE_RESET(plock);
- } else {
- fd_table[fd]->w_owner = NULL;
- }
+ if (entry->w_owner == pthread_run) {
+ if ((entry->type != FD_HALF_DUPLEX) &&
+ (entry->type != FD_TEST_HALF_DUPLEX) &&
+ ((lock_type == FD_WRITE) || (lock_type == FD_RDWR))) {
+ if (entry->w_lockcount == 0) {
+ if (pthread = pthread_queue_deq(&entry->w_queue)) {
+ pthread_sched_prevent();
+ entry->w_owner = pthread;
+ if ((SET_PF_DONE_EVENT(pthread)) == OK) {
+ pthread_sched_other_resume(pthread);
+ } else {
+ pthread_sched_resume();
+ }
+ } else {
+ entry->w_owner = NULL;
+ }
+ } else {
+ entry->w_lockcount--;
+ }
+ }
}
}
/* ==========================================================================
+ * fd_basic_unlock()
+ */
+void fd_basic_unlock(int fd, int lock_type)
+{
+ fd_basic_basic_unlock(fd_table[fd], lock_type);
+}
+
+/* ==========================================================================
* fd_unlock()
- * If there is a lock count then the function fileunlock will do
- * the unlocking, just return.
*/
void fd_unlock(int fd, int lock_type)
{
- semaphore *lock;
+ pthread_mutex_t *mutex;
- if (!(fd_table[fd]->lockcount)) {
- lock = &(fd_table[fd]->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
- fd_basic_unlock(fd, lock_type);
- SEMAPHORE_RESET(lock);
- }
+ mutex = &(fd_table[fd]->mutex);
+ pthread_mutex_lock(mutex);
+ fd_basic_basic_unlock(fd_table[fd], lock_type);
+ pthread_mutex_unlock(mutex);
}
/* ==========================================================================
@@ -214,64 +324,126 @@ void fd_unlock(int fd, int lock_type)
* The real work of lock without the locking of fd_table[fd].lock.
* Be sure to leave the lock the same way you found it. i.e. locked.
*/
-int fd_basic_lock(unsigned int fd, int lock_type, semaphore * lock)
+int fd_basic_lock(unsigned int fd, int lock_type, pthread_mutex_t * mutex,
+ struct timespec * timeout)
{
semaphore *plock;
- /* If not in use return EBADF error */
- if (fd_table[fd]->type == FD_NIU) {
+ switch (fd_table[fd]->type) {
+ case FD_NIU:
+ /* If not in use return EBADF error */
+ SET_ERRNO(EBADF);
return(NOTOK);
- }
-
- /* If not tested, test it and see if it is valid */
- if (fd_table[fd]->type == FD_NT) {
- /* If not ok return EBADF error */
- if (fd_kern_init(fd) != OK) {
+ break;
+ case FD_NT:
+ /*
+ * If not tested, test it and see if it is valid
+ * If not ok return EBADF error
+ */
+ fd_kern_init(fd);
+ if (fd_table[fd]->type == FD_NIU) {
+ SET_ERRNO(EBADF);
return(NOTOK);
}
+ break;
+ case FD_TEST_HALF_DUPLEX:
+ case FD_TEST_FULL_DUPLEX:
+ /* If a parent process reset the fd to its proper state */
+ if (!fork_lock) {
+ /* It had better be a kernel fd */
+ fd_kern_reset(fd);
+ }
+ break;
+ default:
+ break;
}
+
if ((fd_table[fd]->type == FD_HALF_DUPLEX) ||
- (lock_type & FD_READ)) {
+ (fd_table[fd]->type == FD_TEST_HALF_DUPLEX) ||
+ (lock_type == FD_READ) || (lock_type == FD_RDWR)) {
if (fd_table[fd]->r_owner) {
if (fd_table[fd]->r_owner != pthread_run) {
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+ pthread_sched_prevent();
pthread_queue_enq(&fd_table[fd]->r_queue, pthread_run);
- SEMAPHORE_RESET(lock);
-
- /* Reschedule will unlock pthread_run */
- reschedule(PS_FDLR_WAIT);
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_mutex_unlock(mutex);
- while(SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ /* Reschedule will unlock pthread_run */
+ pthread_run->data.fd.fd = fd;
+ pthread_run->data.fd.branch = __LINE__;
+ pthread_resched_resume(PS_FDLR_WAIT);
+ pthread_mutex_lock(mutex);
+
+ /* If we're the owner then we have to cancel the sleep */
+ if (fd_table[fd]->r_owner != pthread_run) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ SET_ERRNO(ETIMEDOUT);
+ return(NOTOK);
+ }
+ sleep_cancel(pthread_run);
+ } else {
+ /* Reschedule will unlock pthread_run */
+ pthread_run->data.fd.fd = fd;
+ pthread_run->data.fd.branch = __LINE__;
+ pthread_resched_resume(PS_FDLR_WAIT);
+ pthread_mutex_lock(mutex);
}
+ CLEAR_PF_DONE_EVENT(pthread_run);
} else {
- if (!fd_table[fd]->lockcount) {
- PANIC();
- }
+ fd_table[fd]->r_lockcount++;
}
}
fd_table[fd]->r_owner = pthread_run;
}
if ((fd_table[fd]->type != FD_HALF_DUPLEX) &&
- (lock_type & FD_WRITE)) {
+ (fd_table[fd]->type != FD_TEST_HALF_DUPLEX) &&
+ ((lock_type == FD_WRITE) || (lock_type == FD_RDWR))) {
if (fd_table[fd]->w_owner) {
if (fd_table[fd]->w_owner != pthread_run) {
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+ pthread_sched_prevent();
pthread_queue_enq(&fd_table[fd]->w_queue, pthread_run);
- SEMAPHORE_RESET(lock);
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_mutex_unlock(mutex);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
- /* Reschedule will unlock pthread_run */
- reschedule(PS_FDLW_WAIT);
+ /* Reschedule will unlock pthread_run */
+ pthread_run->data.fd.fd = fd;
+ pthread_run->data.fd.branch = __LINE__;
+ pthread_resched_resume(PS_FDLR_WAIT);
+ pthread_mutex_lock(mutex);
- while(SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
+ /* If we're the owner then we have to cancel the sleep */
+ if (fd_table[fd]->w_owner != pthread_run) {
+ if (lock_type == FD_RDWR) {
+ /* Unlock current thread */
+ fd_basic_unlock(fd, FD_READ);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ SET_ERRNO(ETIMEDOUT);
+ return(NOTOK);
+ }
+ sleep_cancel(pthread_run);
+ } else {
+ /* Reschedule will unlock pthread_run */
+ pthread_run->data.fd.fd = fd;
+ pthread_run->data.fd.branch = __LINE__;
+ pthread_resched_resume(PS_FDLR_WAIT);
+ pthread_mutex_lock(mutex);
}
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+ fd_table[fd]->w_lockcount++;
}
}
fd_table[fd]->w_owner = pthread_run;
@@ -283,24 +455,144 @@ int fd_basic_lock(unsigned int fd, int lock_type, semaphore * lock)
return(OK);
}
+/*----------------------------------------------------------------------
+ * Function: fd_unlock_for_cancel
+ * Purpose: Unlock all fd locks held prior to being cancelled
+ * Args: void
+ * Returns:
+ * OK or NOTOK
+ * Notes:
+ * Assumes the kernel is locked on entry
+ *----------------------------------------------------------------------*/
+int
+fd_unlock_for_cancel( void )
+{
+ int i, fd;
+ struct pthread_select_data *data;
+ int rdlk, wrlk, lktype;
+ int found;
+
+ /* What we do depends on the previous state of the thread */
+ switch( pthread_run->old_state ) {
+ case PS_RUNNING:
+ case PS_JOIN:
+ case PS_SLEEP_WAIT:
+ case PS_WAIT_WAIT:
+ case PS_SIGWAIT:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_DEAD:
+ case PS_UNALLOCED:
+ break; /* Nothing to do */
+
+ case PS_COND_WAIT:
+ CLEAR_PF_GROUP( pthread_run, PF_EVENT_GROUP );
+ /* Must reaquire the mutex according to the standard */
+ if( pthread_run->data.mutex == NULL ) {
+ PANIC();
+ }
+ pthread_mutex_lock( pthread_run->data.mutex );
+ break;
+
+ case PS_FDR_WAIT:
+ CLEAR_PF_GROUP( pthread_run, PF_EVENT_GROUP);
+ /* Free the lock on the fd being used */
+ fd = fd_get_pthread_fd_from_kernel_fd( pthread_run->data.fd.fd );
+ if( fd == NOTOK ) {
+ PANIC(); /* Can't find fd */
+ }
+ fd_unlock( fd, FD_READ );
+ break;
+
+ case PS_FDW_WAIT: /* Waiting on i/o */
+ CLEAR_PF_GROUP( pthread_run, PF_EVENT_GROUP);
+ /* Free the lock on the fd being used */
+ fd = fd_get_pthread_fd_from_kernel_fd( pthread_run->data.fd.fd );
+ if( fd == NOTOK ) {
+ PANIC(); /* Can't find fd */
+ }
+ fd_unlock( fd, FD_WRITE );
+ break;
+
+ case PS_SELECT_WAIT:
+ data = pthread_run->data.select_data;
+
+ CLEAR_PF_GROUP( pthread_run, PF_EVENT_GROUP);
+
+ for( i = 0; i < data->nfds; i++) {
+ rdlk =(FD_ISSET(i,&data->readfds)
+ || FD_ISSET(i,&data->exceptfds));
+ wrlk = FD_ISSET(i, &data->writefds);
+ lktype = rdlk ? (wrlk ? FD_RDWR : FD_READ) : FD_WRITE;
+
+ if( ! (rdlk || wrlk) )
+ continue; /* No locks, no unlock */
+
+ if( (fd = fd_get_pthread_fd_from_kernel_fd( i )) == NOTOK ) {
+ PANIC(); /* Can't find fd */
+ }
+
+ fd_unlock( fd, lktype );
+ }
+ break;
+
+ case PS_MUTEX_WAIT:
+ PANIC(); /* Should never cancel a mutex wait */
+
+ default:
+ PANIC(); /* Unknown thread status */
+ }
+}
+
/* ==========================================================================
* fd_lock()
*/
-int fd_lock(unsigned int fd, int lock_type)
+#define pthread_mutex_lock_timedwait(a, b) pthread_mutex_lock(a)
+
+int fd_lock(unsigned int fd, int lock_type, struct timespec * timeout)
{
- semaphore *lock;
+ struct timespec current_time;
+ pthread_mutex_t *mutex;
int error;
- if (fd < dtablesize) {
- lock = &(fd_table[fd]->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
+ if ((error = fd_check_entry(fd)) == OK) {
+ mutex = &(fd_table[fd]->mutex);
+ if (pthread_mutex_lock_timedwait(mutex, timeout)) {
+ SET_ERRNO(ETIMEDOUT);
+ return(-ETIMEDOUT);
}
- error = fd_basic_lock(fd, lock_type, lock);
- SEMAPHORE_RESET(lock);
- return(error);
+ error = fd_basic_lock(fd, lock_type, mutex, timeout);
+ pthread_mutex_unlock(mutex);
}
- return(NOTOK);
+ return(error);
+}
+
+/* ==========================================================================
+ * fd_free()
+ *
+ * Assumes fd is locked and owner by pthread_run
+ * Don't clear the queues, fd_unlock will do that.
+ */
+struct fd_table_entry * fd_free(int fd)
+{
+ struct fd_table_entry *fd_valid;
+
+ fd_valid = NULL;
+ fd_table[fd]->r_lockcount = 0;
+ fd_table[fd]->w_lockcount = 0;
+ if (--fd_table[fd]->count) {
+ fd_valid = fd_table[fd];
+ fd_table[fd] = fd_table[fd]->next;
+ fd_valid->next = fd_table[fd]->next;
+ /* Don't touch queues of fd_valid */
+ }
+
+ fd_table[fd]->type = FD_NIU;
+ fd_table[fd]->fd.i = NOTOK;
+ fd_table[fd]->next = NULL;
+ fd_table[fd]->flags = 0;
+ fd_table[fd]->count = 0;
+ return(fd_valid);
}
@@ -308,73 +600,111 @@ int fd_lock(unsigned int fd, int lock_type)
* ======================================================================= */
/* ==========================================================================
- * read()
+ * read_timedwait()
*/
-ssize_t read(int fd, void *buf, size_t nbytes)
+ssize_t read_timedwait(int fd, void *buf, size_t nbytes,
+ struct timespec * timeout)
{
int ret;
- if ((ret = fd_lock(fd, FD_READ)) == OK) {
+ if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
ret = fd_table[fd]->ops->read(fd_table[fd]->fd,
- fd_table[fd]->flags, buf, nbytes);
+ fd_table[fd]->flags, buf, nbytes, timeout);
fd_unlock(fd, FD_READ);
}
return(ret);
}
/* ==========================================================================
- * readv()
+ * read()
*/
-int readv(int fd, const struct iovec *iov, int iovcnt)
+ssize_t read(int fd, void *buf, size_t nbytes)
+{
+ return(read_timedwait(fd, buf, nbytes, NULL));
+}
+
+/* ==========================================================================
+ * readv_timedwait()
+ */
+int readv_timedwait(int fd, const struct iovec *iov, int iovcnt,
+ struct timespec * timeout)
{
int ret;
- if ((ret = fd_lock(fd, FD_READ)) == OK) {
+ if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
ret = fd_table[fd]->ops->readv(fd_table[fd]->fd,
- fd_table[fd]->flags, iov, iovcnt);
+ fd_table[fd]->flags, iov, iovcnt, timeout);
fd_unlock(fd, FD_READ);
}
return(ret);
}
/* ==========================================================================
+ * readv()
+ */
+ssize_t readv(int fd, const struct iovec *iov, int iovcnt)
+{
+ return(readv_timedwait(fd, iov, iovcnt, NULL));
+}
+
+/* ==========================================================================
* write()
*/
-ssize_t write(int fd, const void *buf, size_t nbytes)
+ssize_t write_timedwait(int fd, const void *buf, size_t nbytes,
+ struct timespec * timeout)
{
- int ret;
+ int ret;
- if ((ret = fd_lock(fd, FD_WRITE)) == OK) {
- ret = fd_table[fd]->ops->write(fd_table[fd]->fd,
- fd_table[fd]->flags, buf, nbytes);
- fd_unlock(fd, FD_WRITE);
- }
- return(ret);
+ if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK)
+ {
+ ret = fd_table[fd]->ops->write(fd_table[fd]->fd,
+ fd_table[fd]->flags, buf, nbytes,
+ timeout);
+ fd_unlock(fd, FD_WRITE);
+ }
+ return(ret);
}
/* ==========================================================================
- * writev()
+ * write()
+ */
+ssize_t write(int fd, const void * buf, size_t nbytes)
+{
+ return(write_timedwait(fd, buf, nbytes, NULL));
+}
+
+/* ==========================================================================
+ * writev_timedwait()
*/
-int writev(int fd, const struct iovec *iov, int iovcnt)
+int writev_timedwait(int fd, const struct iovec *iov, int iovcnt,
+ struct timespec * timeout)
{
int ret;
- if ((ret = fd_lock(fd, FD_WRITE)) == OK) {
+ if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
ret = fd_table[fd]->ops->writev(fd_table[fd]->fd,
- fd_table[fd]->flags, iov, iovcnt);
+ fd_table[fd]->flags, iov, iovcnt, timeout);
fd_unlock(fd, FD_WRITE);
}
return(ret);
}
/* ==========================================================================
+ * writev()
+ */
+ssize_t writev(int fd, const struct iovec *iov, int iovcnt)
+{
+ return(writev_timedwait(fd, iov, iovcnt, NULL));
+}
+
+/* ==========================================================================
* lseek()
*/
off_t lseek(int fd, off_t offset, int whence)
{
int ret;
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
ret = fd_table[fd]->ops->seek(fd_table[fd]->fd,
fd_table[fd]->flags, offset, whence);
fd_unlock(fd, FD_RDWR);
@@ -393,66 +723,178 @@ off_t lseek(int fd, off_t offset, int whence)
* to the fd_table[fd] queue, and the count is set to zero, (BUT THE LOCK IS NOT
* RELEASED). close() then calls fd_unlock which give the fd to the next queued
* element which determins that the fd is closed and then calls fd_unlock etc...
+ *
+ * XXX close() is even uglier now. You may assume that the kernel fd is the
+ * same as fd if fd_table[fd] == NULL or if fd_table[fd]->type == FD_NT.
+ * This is true because before any fd_table[fd] is allocated the corresponding
+ * kernel fd must be checks to see if it's valid.
*/
int close(int fd)
{
- union fd_data realfd;
- int ret, flags;
+ struct fd_table_entry * entry;
+ pthread_mutex_t *mutex;
+ union fd_data realfd;
+ int ret, flags;
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
- flags = fd_table[fd]->flags;
- realfd = fd_table[fd]->fd;
- if (fd_free(fd) == OK) {
- ret = fd_table[fd]->ops->close(realfd, flags);
- }
- fd_unlock(fd, FD_RDWR);
+ if(fd < 0 || fd >= dtablesize)
+ {
+ SET_ERRNO(EBADF);
+ return -1;
+ }
+ /* Need to lock the newfd by hand */
+ pthread_mutex_lock(&fd_table_mutex);
+ if (fd_table[fd]) {
+ pthread_mutex_unlock(&fd_table_mutex);
+ mutex = &(fd_table[fd]->mutex);
+ pthread_mutex_lock(mutex);
+
+ /*
+ * XXX Gross hack ... because of fork(), any fd closed by the
+ * parent should not change the fd of the child, unless it owns it.
+ */
+ switch(fd_table[fd]->type) {
+ case FD_NIU:
+ pthread_mutex_unlock(mutex);
+ ret = -EBADF;
+ break;
+ case FD_NT:
+ /*
+ * If it's not tested then the only valid possibility is it's
+ * kernel fd.
+ */
+ ret = machdep_sys_close(fd);
+ fd_table[fd]->type = FD_NIU;
+ pthread_mutex_unlock(mutex);
+ break;
+ case FD_TEST_FULL_DUPLEX:
+ case FD_TEST_HALF_DUPLEX:
+ realfd = fd_table[fd]->fd;
+ flags = fd_table[fd]->flags;
+ if ((entry = fd_free(fd)) == NULL) {
+ ret = fd_table[fd]->ops->close(realfd, flags);
+ } else {
+ /* There can't be any others waiting for fd. */
+ pthread_mutex_unlock(&entry->mutex);
+ /* Note: entry->mutex = mutex */
+ mutex = &(fd_table[fd]->mutex);
+ }
+ pthread_mutex_unlock(mutex);
+ break;
+ default:
+ ret = fd_basic_lock(fd, FD_RDWR, mutex, NULL);
+ if (ret == OK) {
+ realfd = fd_table[fd]->fd;
+ flags = fd_table[fd]->flags;
+ pthread_mutex_unlock(mutex);
+ if ((entry = fd_free(fd)) == NULL) {
+ ret = fd_table[fd]->ops->close(realfd, flags);
+ } else {
+ fd_basic_basic_unlock(entry, FD_RDWR);
+ pthread_mutex_unlock(&entry->mutex);
+ /* Note: entry->mutex = mutex */
}
- return(ret);
+ fd_unlock(fd, FD_RDWR);
+ } else {
+ pthread_mutex_unlock(mutex);
+ }
+ break;
+ }
+ } else {
+ /* Don't bother creating a table entry */
+ pthread_mutex_unlock(&fd_table_mutex);
+ ret = machdep_sys_close(fd);
+ }
+ if( ret < 0) {
+ SET_ERRNO(-ret);
+ ret = -1;
+ }
+ return(ret);
}
/* ==========================================================================
* fd_basic_dup()
*
- * Might need to do more than just what's below.
+ *
+ * This is a MAJOR guess!! I don't know if the mutext unlock is valid
+ * in the BIG picture. But it seems to be needed to avoid deadlocking
+ * with ourselves when we try to close the duped file descriptor.
*/
static inline void fd_basic_dup(int fd, int newfd)
{
fd_table[newfd]->next = fd_table[fd]->next;
fd_table[fd]->next = fd_table[newfd];
+ fd_table[newfd] = fd_table[fd];
fd_table[fd]->count++;
+ pthread_mutex_unlock(&fd_table[newfd]->next->mutex);
+
}
/* ==========================================================================
* dup2()
*
- * Always lock the lower number fd first to avoid deadlocks.
- * newfd must be locked by hand so it can be closed if it is open,
- * or it won't be opened while dup is in progress.
+ * Note: Always lock the lower number fd first to avoid deadlocks.
+ * Note: Leave the newfd locked. It will be unlocked at close() time.
+ * Note: newfd must be locked by hand so it can be closed if it is open,
+ * or it won't be opened while dup is in progress.
*/
int dup2(fd, newfd)
{
+ struct fd_table_entry * entry;
+ pthread_mutex_t *mutex;
union fd_data realfd;
- semaphore *lock;
int ret, flags;
+ if ((ret = fd_check_entry(newfd)) != OK)
+ return ret;
+
if (newfd < dtablesize) {
if (fd < newfd) {
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
/* Need to lock the newfd by hand */
- lock = &(fd_table[newfd]->lock);
- while(SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ mutex = &(fd_table[newfd]->mutex);
+ pthread_mutex_lock(mutex);
/* Is it inuse */
- if (fd_basic_lock(newfd, FD_RDWR, lock) == OK) {
+ if (fd_basic_lock(newfd, FD_RDWR, mutex, NULL) == OK) {
+ realfd = fd_table[newfd]->fd;
+ flags = fd_table[newfd]->flags;
/* free it and check close status */
- flags = fd_table[fd]->flags;
- realfd = fd_table[fd]->fd;
- if (fd_free(fd) == OK) {
- ret = fd_table[fd]->ops->close(realfd, flags);
+ if ((entry = fd_free(newfd)) == NULL) {
+ entry = fd_table[newfd];
+ entry->ops->close(realfd, flags);
+ if (entry->r_queue.q_next) {
+ if (fd_table[fd]->next) {
+ fd_table[fd]->r_queue.q_last->next =
+ entry->r_queue.q_next;
+ } else {
+ fd_table[fd]->r_queue.q_next =
+ entry->r_queue.q_next;
+ }
+ fd_table[fd]->r_queue.q_last =
+ entry->r_queue.q_last;
+ }
+ if (entry->w_queue.q_next) {
+ if (fd_table[fd]->next) {
+ fd_table[fd]->w_queue.q_last->next =
+ entry->w_queue.q_next;
+ } else {
+ fd_table[fd]->w_queue.q_next =
+ entry->w_queue.q_next;
+ }
+ fd_table[fd]->w_queue.q_last =
+ entry->w_queue.q_last;
+ }
+ entry->r_queue.q_next = NULL;
+ entry->w_queue.q_next = NULL;
+ entry->r_queue.q_last = NULL;
+ entry->w_queue.q_last = NULL;
+ entry->r_owner = NULL;
+ entry->w_owner = NULL;
+ ret = OK;
} else {
- /* Lots of work to do */
+ fd_basic_basic_unlock(entry, FD_RDWR);
+ pthread_mutex_unlock(&entry->mutex);
+ /* Note: entry->mutex = mutex */
}
}
fd_basic_dup(fd, newfd);
@@ -460,27 +902,56 @@ int dup2(fd, newfd)
fd_unlock(fd, FD_RDWR);
} else {
/* Need to lock the newfd by hand */
- lock = &(fd_table[newfd]->lock);
- while(SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
- }
- /* Is it inuse */
- if ((ret = fd_basic_lock(newfd, FD_RDWR, lock)) == OK) {
- /* free it and check close status */
- flags = fd_table[fd]->flags;
- realfd = fd_table[fd]->fd;
- if (fd_free(fd) == OK) {
- ret = fd_table[fd]->ops->close(realfd, flags);
- } else {
- /* Lots of work to do */
- }
+ mutex = &(fd_table[newfd]->mutex);
+ pthread_mutex_lock(mutex);
- fd_basic_dup(fd, newfd);
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ /* Is newfd inuse */
+ if ((ret = fd_basic_lock(newfd, FD_RDWR, mutex, NULL)) == OK) {
+ realfd = fd_table[newfd]->fd;
+ flags = fd_table[newfd]->flags;
+ /* free it and check close status */
+ if ((entry = fd_free(newfd)) == NULL) {
+ entry = fd_table[newfd];
+ entry->ops->close(realfd, flags);
+ if (entry->r_queue.q_next) {
+ if (fd_table[fd]->next) {
+ fd_table[fd]->r_queue.q_last->next =
+ entry->r_queue.q_next;
+ } else {
+ fd_table[fd]->r_queue.q_next =
+ entry->r_queue.q_next;
+ }
+ fd_table[fd]->r_queue.q_last =
+ entry->r_queue.q_last;
+ }
+ if (entry->w_queue.q_next) {
+ if (fd_table[fd]->next) {
+ fd_table[fd]->w_queue.q_last->next =
+ entry->w_queue.q_next;
+ } else {
+ fd_table[fd]->w_queue.q_next =
+ entry->w_queue.q_next;
+ }
+ fd_table[fd]->w_queue.q_last =
+ entry->w_queue.q_last;
+ }
+ entry->r_queue.q_next = NULL;
+ entry->w_queue.q_next = NULL;
+ entry->r_queue.q_last = NULL;
+ entry->w_queue.q_last = NULL;
+ entry->r_owner = NULL;
+ entry->w_owner = NULL;
+ ret = OK;
+ } else {
+ fd_basic_basic_unlock(entry, FD_RDWR);
+ pthread_mutex_unlock(&entry->mutex);
+ /* Note: entry->mutex = mutex */
+ }
+ fd_basic_dup(fd, newfd);
+ }
fd_unlock(fd, FD_RDWR);
}
- SEMAPHORE_RESET(lock);
}
} else {
ret = NOTOK;
@@ -496,7 +967,7 @@ int dup(int fd)
{
int ret;
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
ret = fd_allocate();
fd_basic_dup(fd, ret);
fd_unlock(fd, FD_RDWR);
@@ -515,7 +986,7 @@ int fcntl(int fd, int cmd, ...)
va_list ap;
flags = 0;
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
va_start(ap, cmd);
switch(cmd) {
case F_DUPFD:
@@ -523,10 +994,8 @@ int fcntl(int fd, int cmd, ...)
fd_basic_dup(va_arg(ap, int), ret);
break;
case F_SETFD:
- flags = va_arg(ap, int);
+ break;
case F_GETFD:
- ret = fd_table[fd]->ops->fcntl(fd_table[fd]->fd,
- fd_table[fd]->flags, cmd, flags | __FD_NONBLOCK);
break;
case F_GETFL:
ret = fd_table[fd]->flags;
@@ -560,3 +1029,54 @@ int fcntl(int fd, int cmd, ...)
}
return(ret);
}
+
+/* ==========================================================================
+ * getdtablesize()
+ */
+int getdtablesize()
+{
+ return dtablesize;
+}
+
+/* ==========================================================================
+ * ioctl()
+ *
+ * Really want to do a real implementation of this that parses the args ala
+ * fcntl(), above, but it will have to be a totally platform-specific,
+ * nightmare-on-elm-st-style sort of thing. Might even deserve its own file
+ * ala select()... --SNL
+ */
+#ifndef ioctl_request_type
+#define ioctl_request_type unsigned long /* Dummy patch by Monty */
+#endif
+
+int
+ioctl(int fd, ioctl_request_type request, ...)
+{
+ int ret;
+ pthread_va_list ap;
+ caddr_t arg;
+
+ va_start( ap, request ); /* Get the arg */
+ arg = va_arg(ap,caddr_t);
+ va_end( ap );
+
+ if (fd < 0 || fd >= dtablesize)
+ ret = NOTOK;
+ else if (fd_table[fd]->fd.i == NOTOK)
+ ret = machdep_sys_ioctl(fd, request, arg);
+ else if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ ret = machdep_sys_ioctl(fd_table[fd]->fd.i, request, arg);
+ if( ret == 0 && request == FIONBIO ) {
+ /* Properly set NONBLOCK flag */
+ int v = *(int *)arg;
+ if( v )
+ fd_table[fd]->flags |= __FD_NONBLOCK;
+ else
+ fd_table[fd]->flags &= ~__FD_NONBLOCK;
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+ return ret;
+}
+
diff --git a/lib/libpthread/pthreads/fd_kern.c b/lib/libpthread/pthreads/fd_kern.c
index a9eb69af9b7..42489569ab7 100644
--- a/lib/libpthread/pthreads/fd_kern.c
+++ b/lib/libpthread/pthreads/fd_kern.c
@@ -39,10 +39,12 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: fd_kern.c,v 1.1.1.1 1995/10/18 08:43:04 deraadt Exp $ $provenid: fd_kern.c,v 1.7 1994/02/07 02:18:49 proven Exp $";
+static const char rcsid[] = "$Id: fd_kern.c,v 1.1.1.2 1998/07/21 13:19:55 peter Exp $";
#endif
#include <pthread.h>
+#include <unistd.h>
+#include <sys/compat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -53,12 +55,229 @@ static const char rcsid[] = "$Id: fd_kern.c,v 1.1.1.1 1995/10/18 08:43:04 deraad
#include <fcntl.h>
#include <errno.h>
#include <pthread/posix.h>
+#include <string.h>
+
+#include "config.h"
+
+#if defined (HAVE_SYSCALL_SENDTO) && !defined (HAVE_SYSCALL_SEND)
+
+pthread_ssize_t machdep_sys_send (int fd, const void *msg, size_t len,
+ int flags)
+{
+ return machdep_sys_sendto (fd, msg, len, flags,
+ (const struct sockaddr *) 0, 0);
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_RECVFROM) && !defined (HAVE_SYSCALL_RECV)
+
+pthread_ssize_t machdep_sys_recv (int fd, void *buf, size_t len, int flags)
+{
+ return machdep_sys_recvfrom (fd, buf, len, flags,
+ (struct sockaddr *) 0, (int *) 0);
+}
+
+#endif
+
+/* ==========================================================================
+ * Check if there is any signal with must be handled. Added by Monty
+ * This could be somewhat system dependent but it should work.
+ */
+
+static int fd_check_if_pending_signal(struct pthread *pthread)
+{
+ int i;
+ unsigned long *pending,*mask;
+ if (!pthread->sigcount)
+ return 0;
+ pending= (unsigned long*) &pthread->sigpending;
+ mask= (unsigned long*) &pthread->sigmask;
+
+ for (i=0 ; i < sizeof(pthread->sigpending)/sizeof(unsigned long); i++)
+ {
+ if (*pending && (*mask ^ (unsigned) ~0L))
+ return 1;
+ pending++;
+ mask++;
+ }
+ return 0;
+}
/* ==========================================================================
* Variables used by both fd_kern_poll and fd_kern_wait
*/
-static struct pthread *fd_wait_read, *fd_wait_write;
-static fd_set fd_set_read, fd_set_write;
+struct pthread_queue fd_wait_read = PTHREAD_QUEUE_INITIALIZER;
+struct pthread_queue fd_wait_write = PTHREAD_QUEUE_INITIALIZER;
+struct pthread_queue fd_wait_select = PTHREAD_QUEUE_INITIALIZER;
+
+static struct timeval __fd_kern_poll_timeout = { 0, 0 }; /* Moved by monty */
+extern struct timeval __fd_kern_wait_timeout;
+extern volatile sig_atomic_t sig_to_process;
+
+/*
+ * ==========================================================================
+ * Do a select if there is someting to wait for.
+ * This is to a combination of the old fd_kern_poll() and fd_kern_wait()
+ * Return 1 if nothing to do.
+ */
+
+static int fd_kern_select(struct timeval *timeout)
+{
+ fd_set fd_set_read, fd_set_write, fd_set_except;
+ struct pthread *pthread, *deq;
+ int count, i;
+
+ if (!fd_wait_read.q_next && !fd_wait_write.q_next && !fd_wait_select.q_next)
+ return 1; /* Nothing to do */
+
+ FD_ZERO(&fd_set_read);
+ FD_ZERO(&fd_set_write);
+ FD_ZERO(&fd_set_except);
+ for (pthread = fd_wait_read.q_next; pthread; pthread = pthread->next)
+ FD_SET(pthread->data.fd.fd, &fd_set_read);
+ for (pthread = fd_wait_write.q_next; pthread; pthread = pthread->next)
+ FD_SET(pthread->data.fd.fd, &fd_set_write);
+ for (pthread = fd_wait_select.q_next; pthread; pthread = pthread->next)
+ {
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds))
+ FD_SET(i, &fd_set_except);
+ if (FD_ISSET(i, &pthread->data.select_data->writefds))
+ FD_SET(i, &fd_set_write);
+ if (FD_ISSET(i, &pthread->data.select_data->readfds))
+ FD_SET(i, &fd_set_read);
+ }
+ }
+
+ /* Turn off interrupts for real while we set the timer. */
+
+ if (timeout == &__fd_kern_wait_timeout)
+ { /* from fd_kern_wait() */
+ sigset_t sig_to_block, oset;
+ sigfillset(&sig_to_block);
+ machdep_sys_sigprocmask(SIG_BLOCK, &sig_to_block, &oset);
+
+ machdep_unset_thread_timer(NULL);
+ __fd_kern_wait_timeout.tv_usec = 0;
+ __fd_kern_wait_timeout.tv_sec = (sig_to_process) ? 0 : 3600;
+
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
+ }
+ /*
+ * There is a small but finite chance that an interrupt will
+ * occure between the unblock and the select. Because of this
+ * sig_handler_real() sets the value of __fd_kern_wait_timeout
+ * to zero causing the select to do a poll instead of a wait.
+ */
+
+ while ((count = machdep_sys_select(dtablesize, &fd_set_read,
+ &fd_set_write, &fd_set_except,
+ timeout)) < OK)
+ {
+ if (count == -EINTR)
+ return 0;
+ PANIC();
+ }
+
+ for (pthread = fd_wait_read.q_next; pthread; ) {
+ if (count && FD_ISSET(pthread->data.fd.fd, &fd_set_read) ||
+ fd_check_if_pending_signal(pthread))
+ {
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_read))
+ count--;
+ deq = pthread;
+ pthread = pthread->next;
+ pthread_queue_remove(&fd_wait_read, deq);
+ if (SET_PF_DONE_EVENT(deq) == OK) {
+ pthread_prio_queue_enq(pthread_current_prio_queue, deq);
+ deq->state = PS_RUNNING;
+ }
+ continue;
+ }
+ pthread = pthread->next;
+ }
+
+ for (pthread = fd_wait_write.q_next; pthread; ) {
+ if (count && FD_ISSET(pthread->data.fd.fd, &fd_set_write) ||
+ fd_check_if_pending_signal(pthread))
+ {
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_read))
+ count--;
+ deq = pthread;
+ pthread = pthread->next;
+ pthread_queue_remove(&fd_wait_write, deq);
+ if (SET_PF_DONE_EVENT(deq) == OK) {
+ pthread_prio_queue_enq(pthread_current_prio_queue, deq);
+ deq->state = PS_RUNNING;
+ }
+ continue;
+ }
+ pthread = pthread->next;
+ }
+
+ for (pthread = fd_wait_select.q_next; pthread; )
+ {
+ int found_one=0; /* Loop fixed by monty */
+ if (count)
+ {
+ fd_set tmp_readfds, tmp_writefds, tmp_exceptfds;
+ memcpy(&tmp_readfds, &pthread->data.select_data->readfds,
+ sizeof(fd_set));
+ memcpy(&tmp_writefds, &pthread->data.select_data->writefds,
+ sizeof(fd_set));
+ memcpy(&tmp_exceptfds, &pthread->data.select_data->exceptfds,
+ sizeof(fd_set));
+
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ if (FD_ISSET(i, &tmp_exceptfds))
+ {
+ if (! FD_ISSET(i, &fd_set_except))
+ FD_CLR(i, &tmp_exceptfds);
+ else
+ found_one=1;
+ }
+ if (FD_ISSET(i, &tmp_writefds))
+ {
+ if (! FD_ISSET(i, &fd_set_write))
+ FD_CLR(i, &tmp_writefds);
+ else
+ found_one=1;
+ }
+ if (FD_ISSET(i, &tmp_readfds))
+ {
+ if (! FD_ISSET(i, &fd_set_read))
+ FD_CLR(i, &tmp_readfds);
+ else
+ found_one=1;
+ }
+ }
+ if (found_one)
+ {
+ memcpy(&pthread->data.select_data->readfds, &tmp_readfds,
+ sizeof(fd_set));
+ memcpy(&pthread->data.select_data->writefds, &tmp_writefds,
+ sizeof(fd_set));
+ memcpy(&pthread->data.select_data->exceptfds, &tmp_exceptfds,
+ sizeof(fd_set));
+ }
+ }
+ if (found_one || fd_check_if_pending_signal(pthread))
+ {
+ deq = pthread;
+ pthread = pthread->next;
+ pthread_queue_remove(&fd_wait_select, deq);
+ if (SET_PF_DONE_EVENT(deq) == OK) {
+ pthread_prio_queue_enq(pthread_current_prio_queue, deq);
+ deq->state = PS_RUNNING;
+ }
+ } else {
+ pthread = pthread->next;
+ }
+ }
+ return 0;
+}
+
/* ==========================================================================
* fd_kern_poll()
@@ -67,152 +286,27 @@ static fd_set fd_set_read, fd_set_write;
*
* This function uses a linked list of waiting pthreads, NOT a queue.
*/
-static semaphore fd_wait_lock = SEMAPHORE_CLEAR;
void fd_kern_poll()
{
- struct timeval __fd_kern_poll_timeout = { 0, 0 };
- struct pthread **pthread;
- semaphore *lock;
- int count;
-
- /* If someone has the lock then they are in RUNNING state, just return */
- lock = &fd_wait_lock;
- if (SEMAPHORE_TEST_AND_SET(lock)) {
- return;
- }
- if (fd_wait_read || fd_wait_write) {
- for (pthread = &fd_wait_read; *pthread; pthread = &((*pthread)->next)) {
- FD_SET((*pthread)->fd, &fd_set_read);
- }
- for (pthread = &fd_wait_write; *pthread; pthread = &((*pthread)->next)) {
- FD_SET((*pthread)->fd, &fd_set_write);
- }
-
- if ((count = machdep_sys_select(dtablesize, &fd_set_read,
- &fd_set_write, NULL, &__fd_kern_poll_timeout)) < OK) {
- if (count == -EINTR) {
- SEMAPHORE_RESET(lock);
- return;
- }
- PANIC();
- }
-
- for (pthread = &fd_wait_read; count && *pthread; ) {
- if (FD_ISSET((*pthread)->fd, &fd_set_read)) {
- /* Get lock on thread */
-
- (*pthread)->state = PS_RUNNING;
- *pthread = (*pthread)->next;
- count--;
- continue;
- }
- pthread = &((*pthread)->next);
- }
-
- for (pthread = &fd_wait_write; count && *pthread; ) {
- if (FD_ISSET((*pthread)->fd, &fd_set_write)) {
- semaphore *plock;
-
- /* Get lock on thread */
- plock = &(*pthread)->lock;
- if (!(SEMAPHORE_TEST_AND_SET(plock))) {
- /* Thread locked, skip it. */
- (*pthread)->state = PS_RUNNING;
- *pthread = (*pthread)->next;
- SEMAPHORE_RESET(plock);
- }
- count--;
- continue;
- }
- pthread = &((*pthread)->next);
- }
- }
- SEMAPHORE_RESET(lock);
+ fd_kern_select(&__fd_kern_poll_timeout);
}
+
/* ==========================================================================
* fd_kern_wait()
*
* Called when there is no active thread to run.
*/
-extern struct timeval __fd_kern_wait_timeout;
void fd_kern_wait()
{
- struct pthread **pthread;
- sigset_t sig_to_block;
- int count;
-
- if (fd_wait_read || fd_wait_write) {
- for (pthread = &fd_wait_read; *pthread; pthread = &((*pthread)->next)) {
- FD_SET((*pthread)->fd, &fd_set_read);
- }
- for (pthread = &fd_wait_write; *pthread; pthread = &((*pthread)->next)) {
- FD_SET((*pthread)->fd, &fd_set_write);
- }
-
- /* Turn off interrupts for real while we set the timer. */
-
- sigfillset(&sig_to_block);
- sigprocmask(SIG_BLOCK, &sig_to_block, NULL);
-
- machdep_unset_thread_timer();
- __fd_kern_wait_timeout.tv_usec = 0;
- __fd_kern_wait_timeout.tv_sec = 3600;
-
- sigprocmask(SIG_UNBLOCK, &sig_to_block, NULL);
-
- /*
- * There is a small but finite chance that an interrupt will
- * occure between the unblock and the select. Because of this
- * sig_handler_real() sets the value of __fd_kern_wait_timeout
- * to zero causing the select to do a poll instead of a wait.
- */
-
- while ((count = machdep_sys_select(dtablesize, &fd_set_read,
- &fd_set_write, NULL, &__fd_kern_wait_timeout)) < OK) {
- if (count == -EINTR) {
- return;
- }
- PANIC();
- }
-
- for (pthread = &fd_wait_read; count && *pthread; ) {
- if (FD_ISSET((*pthread)->fd, &fd_set_read)) {
- /* Get lock on thread */
-
- (*pthread)->state = PS_RUNNING;
- *pthread = (*pthread)->next;
- count--;
- continue;
- }
- pthread = &((*pthread)->next);
- }
-
- for (pthread = &fd_wait_write; count && *pthread; ) {
- if (FD_ISSET((*pthread)->fd, &fd_set_write)) {
- semaphore *plock;
-
- /* Get lock on thread */
- plock = &(*pthread)->lock;
- if (!(SEMAPHORE_TEST_AND_SET(plock))) {
- /* Thread locked, skip it. */
- (*pthread)->state = PS_RUNNING;
- *pthread = (*pthread)->next;
- SEMAPHORE_RESET(plock);
- }
- count--;
- continue;
- }
- pthread = &((*pthread)->next);
- }
- } else {
- /* No threads, waiting on I/O, do a sigsuspend */
- sig_handler_pause();
- }
+ if (fd_kern_select(&__fd_kern_wait_timeout))
+ /* No threads, waiting on I/O, do a sigsuspend */
+ sig_handler_pause();
}
+
/* ==========================================================================
* Special Note: All operations return the errno as a negative of the errno
* listed in errno.h
@@ -221,143 +315,231 @@ void fd_kern_wait()
/* ==========================================================================
* read()
*/
-ssize_t __fd_kern_read(int fd, int flags, void *buf, size_t nbytes)
+pthread_ssize_t __fd_kern_read(union fd_data fd_data, int flags, void *buf,
+ size_t nbytes, struct timespec * timeout)
{
- semaphore *lock, *plock;
- int ret;
-
- while ((ret = machdep_sys_read(fd, buf, nbytes)) < OK) {
- if (ret == -EWOULDBLOCK) {
- /* Lock queue */
- lock = &fd_wait_lock;
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
- /* Lock pthread */
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
-
- /* queue pthread for a FDR_WAIT */
- pthread_run->next = fd_wait_read;
- fd_wait_read = pthread_run;
- pthread_run->fd = fd;
- SEMAPHORE_RESET(lock);
- reschedule(PS_FDR_WAIT);
- } else {
- pthread_run->error = -ret;
- ret = NOTOK;
- break;
- }
+ int fd = fd_data.i;
+ int ret;
+
+ pthread_run->sighandled=0; /* Added by monty */
+ while ((ret = machdep_sys_read(fd, buf, nbytes)) < OK) {
+ if (!(flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDR_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd;
+ pthread_queue_enq(&fd_wait_read, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ SET_PF_AT_CANCEL_POINT(pthread_run);
+ pthread_resched_resume(PS_FDR_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+ ret= NOTOK;
+ break;
}
- return(ret);
+ pthread_sched_resume();
+ } else {
+ SET_PF_AT_CANCEL_POINT(pthread_run);
+ pthread_resched_resume(PS_FDR_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ SET_ERRNO(EINTR);
+ ret= NOTOK;
+ break;
+ }
+ } else {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ break;
+ }
+ }
+ return(ret);
}
/* ==========================================================================
* readv()
*/
-int __fd_kern_readv(int fd, int flags, struct iovec *iov, int iovcnt)
+int __fd_kern_readv(union fd_data fd_data, int flags, const struct iovec *iov,
+ int iovcnt, struct timespec * timeout)
{
- semaphore *lock, *plock;
- int ret;
-
- while ((ret = machdep_sys_readv(fd, iov, iovcnt)) < OK) {
- if (ret == -EWOULDBLOCK) {
- /* Lock queue */
- lock = &fd_wait_lock;
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
- /* Lock pthread */
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
-
- /* queue pthread for a FDR_WAIT */
- pthread_run->next = fd_wait_read;
- fd_wait_read = pthread_run;
- pthread_run->fd = fd;
- SEMAPHORE_RESET(lock);
- reschedule(PS_FDR_WAIT);
- } else {
- pthread_run->error = -ret;
- ret = NOTOK;
- break;
- }
+ int fd = fd_data.i;
+ int ret;
+
+ pthread_run->sighandled=0; /* Added by monty */
+ while ((ret = machdep_sys_readv(fd, iov, iovcnt)) < OK) {
+ if (!(flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDR_WAIT */
+ pthread_run->data.fd.fd = fd;
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_queue_enq(&fd_wait_read, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ SET_PF_AT_CANCEL_POINT(pthread_run);
+ pthread_resched_resume(PS_FDW_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+ ret = NOTOK;
+ break;
}
- return(ret);
+ pthread_sched_resume();
+ } else {
+ SET_PF_AT_CANCEL_POINT(pthread_run);
+ pthread_resched_resume(PS_FDW_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ SET_ERRNO(EINTR);
+ ret= NOTOK;
+ break;
+ }
+ } else {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ break;
+ }
+ }
+ return(ret);
}
/* ==========================================================================
* write()
*/
-ssize_t __fd_kern_write(int fd, int flags, const void *buf, size_t nbytes)
+pthread_ssize_t __fd_kern_write(union fd_data fd_data, int flags,
+ const void *buf, size_t nbytes, struct timespec * timeout)
{
- semaphore *lock, *plock;
- int ret;
-
- while ((ret = machdep_sys_write(fd, buf, nbytes)) < OK) {
- if (pthread_run->error == -EWOULDBLOCK) {
- /* Lock queue */
- lock = &fd_wait_lock;
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
- /* Lock pthread */
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
-
- /* queue pthread for a FDW_WAIT */
- pthread_run->next = fd_wait_write;
- fd_wait_write = pthread_run;
- pthread_run->fd = fd;
- SEMAPHORE_RESET(lock);
- reschedule(PS_FDW_WAIT);
- } else {
- pthread_run->error = ret;
- break;
- }
+ int fd = fd_data.i;
+ int ret;
+
+ pthread_run->sighandled=0; /* Added by monty */
+ while ((ret = machdep_sys_write(fd, buf, nbytes)) < OK) {
+ if (!(flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDW_WAIT */
+ pthread_run->data.fd.fd = fd;
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_queue_enq(&fd_wait_write, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDW_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+ ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
+ pthread_resched_resume(PS_FDW_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ SET_ERRNO(EINTR);
+ ret= NOTOK;
+ break;
+ }
+ } else {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ break;
}
- return(ret);
+ }
+ return(ret);
}
/* ==========================================================================
* writev()
*/
-int __fd_kern_writev(int fd, int flags, struct iovec *iov, int iovcnt)
+int __fd_kern_writev(union fd_data fd_data, int flags, const struct iovec *iov,
+ int iovcnt, struct timespec * timeout)
{
- semaphore *lock, *plock;
+ int fd = fd_data.i;
int ret;
+ pthread_run->sighandled=0; /* Added by monty */
while ((ret = machdep_sys_writev(fd, iov, iovcnt)) < OK) {
- if (pthread_run->error == -EWOULDBLOCK) {
- /* Lock queue */
- lock = &fd_wait_lock;
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
- /* Lock pthread */
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+ if (!(flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
/* queue pthread for a FDW_WAIT */
- pthread_run->next = fd_wait_write;
- fd_wait_write = pthread_run;
- pthread_run->fd = fd;
- SEMAPHORE_RESET(lock);
- reschedule(PS_FDW_WAIT);
+ pthread_run->data.fd.fd = fd;
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_queue_enq(&fd_wait_write, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDW_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+ ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
+ pthread_resched_resume(PS_FDW_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ SET_ERRNO(EINTR);
+ ret= NOTOK;
+ break;
+ }
} else {
- pthread_run->error = ret;
break;
}
}
@@ -368,25 +550,38 @@ int __fd_kern_writev(int fd, int flags, struct iovec *iov, int iovcnt)
* For blocking version we really should set an interrupt
* fcntl()
*/
-int __fd_kern_fcntl(int fd, int flags, int cmd, int arg)
+int __fd_kern_fcntl(union fd_data fd_data, int flags, int cmd, int arg)
{
+ int fd = fd_data.i;
+
return(machdep_sys_fcntl(fd, cmd, arg));
}
/* ==========================================================================
* close()
*/
-int __fd_kern_close(int fd, int flags)
+int __fd_kern_close(union fd_data fd_data, int flags)
{
+ int fd = fd_data.i;
+
return(machdep_sys_close(fd));
}
/* ==========================================================================
* lseek()
+ * Assume that error number is in the range 0- 255 to get bigger
+ * range of seek. ; Monty
*/
-int __fd_kern_lseek(int fd, int flags, off_t offset, int whence)
+off_t __fd_kern_lseek(union fd_data fd_data, int f, off_t offset, int whence)
{
- return(machdep_sys_lseek(fd, offset, whence));
+ int fd = fd_data.i;
+ off_t ret=machdep_sys_lseek(fd, offset, whence);
+ if ((long) ret < 0L && (long) ret >= -255L)
+ {
+ SET_ERRNO(ret);
+ ret= NOTOK;
+ }
+ return ret;
}
/*
@@ -397,7 +592,7 @@ extern machdep_sys_close();
/* Normal file operations */
static struct fd_ops __fd_kern_ops = {
__fd_kern_write, __fd_kern_read, __fd_kern_close, __fd_kern_fcntl,
- __fd_kern_readv, __fd_kern_writev, __fd_kern_lseek
+ __fd_kern_writev, __fd_kern_readv, __fd_kern_lseek, 1
};
/* NFS file opperations */
@@ -416,7 +611,7 @@ static struct fd_ops __fd_kern_ops = {
*
* This is not done yet
*
- * A reqular file on the local system needs no special treatment.
+ * A regular file on the local system needs no special treatment.
*/
int open(const char *path, int flags, ...)
{
@@ -440,8 +635,8 @@ int open(const char *path, int flags, ...)
if (!((fd_kern = machdep_sys_open(path, flags, mode)) < OK)) {
/* fstat the file to determine what type it is */
- if (fstat(fd_kern, &stat_buf)) {
-printf("error %d stating new fd %d\n", errno, fd);
+ if (machdep_sys_fstat(fd_kern, &stat_buf)) {
+ PANIC();
}
if (S_ISREG(stat_buf.st_mode)) {
fd_table[fd]->ops = &(__fd_kern_ops);
@@ -450,41 +645,421 @@ printf("error %d stating new fd %d\n", errno, fd);
fd_table[fd]->ops = &(__fd_kern_ops);
fd_table[fd]->type = FD_FULL_DUPLEX;
}
- fd_table[fd]->fd = fd_kern;
+ fd_table[fd]->fd.i = fd_kern;
return(fd);
}
- pthread_run->error = - fd_kern;
fd_table[fd]->count = 0;
+ SET_ERRNO(-fd_kern);
}
return(NOTOK);
}
/* ==========================================================================
+ * create()
+ */
+int create(const char *path, mode_t mode)
+{
+ return creat (path, mode);
+}
+
+/* ==========================================================================
+ * creat()
+ */
+#undef creat
+
+int creat(const char *path, mode_t mode)
+{
+ return open (path, O_CREAT | O_TRUNC | O_WRONLY, mode);
+}
+
+/* ==========================================================================
+ * fchown()
+ */
+int fchown(int fd, uid_t owner, gid_t group)
+{
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
+ if ((ret = machdep_sys_fchown(fd_table[fd]->fd.i, owner, group)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_WRITE);
+ }
+ return(ret);
+}
+
+/* ==========================================================================
+ * fchmod()
+ */
+int fchmod(int fd, mode_t mode)
+{
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
+ if ((ret = machdep_sys_fchmod(fd_table[fd]->fd.i, mode)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_WRITE);
+ }
+ return(ret);
+}
+
+/* ==========================================================================
+ * ftruncate()
+ */
+int ftruncate(int fd, off_t length)
+{
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
+ if ((ret = machdep_sys_ftruncate(fd_table[fd]->fd.i, length)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_WRITE);
+ }
+ return(ret);
+}
+
+#if defined (HAVE_SYSCALL_FLOCK)
+/* ==========================================================================
+ * flock()
+ *
+ * Added (mevans)
+ */
+int flock(int fd, int operation)
+{
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_flock(fd_table[fd]->fd.i,
+ operation)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+ return(ret);
+}
+#endif
+
+/* ==========================================================================
+ * pipe()
+ */
+int pipe(int fds[2])
+{
+ int kfds[2];
+ int ret;
+
+ if ((fds[0] = fd_allocate()) >= OK) {
+ if ((fds[1] = fd_allocate()) >= OK) {
+ if ((ret = machdep_sys_pipe(kfds)) >= OK) {
+ fd_table[fds[0]]->flags = machdep_sys_fcntl(kfds[0], F_GETFL, NULL);
+ machdep_sys_fcntl(kfds[0], F_SETFL, fd_table[fds[0]]->flags | __FD_NONBLOCK);
+ fd_table[fds[1]]->flags = machdep_sys_fcntl(kfds[1], F_GETFL, NULL);
+ machdep_sys_fcntl(kfds[1], F_SETFL, fd_table[fds[1]]->flags | __FD_NONBLOCK);
+
+ fd_table[fds[0]]->ops = &(__fd_kern_ops);
+ fd_table[fds[1]]->ops = &(__fd_kern_ops);
+
+ /* Not really full duplex but ... */
+ fd_table[fds[0]]->type = FD_FULL_DUPLEX;
+ fd_table[fds[1]]->type = FD_FULL_DUPLEX;
+
+ fd_table[fds[0]]->fd.i = kfds[0];
+ fd_table[fds[1]]->fd.i = kfds[1];
+
+ return(OK);
+ } else {
+ SET_ERRNO(-ret);
+ }
+ fd_table[fds[1]]->count = 0;
+ }
+ fd_table[fds[0]]->count = 0;
+ }
+ return(NOTOK);
+}
+
+/* ==========================================================================
+ * fd_kern_reset()
+ * Change the fcntl blocking flag back to NONBLOCKING. This should only
+ * be called after a fork.
+ */
+void fd_kern_reset(int fd)
+{
+ switch (fd_table[fd]->type) {
+ case FD_TEST_HALF_DUPLEX:
+ machdep_sys_fcntl(fd_table[fd]->fd.i, F_SETFL,
+ fd_table[fd]->flags | __FD_NONBLOCK);
+ fd_table[fd]->type = FD_HALF_DUPLEX;
+ break;
+ case FD_TEST_FULL_DUPLEX:
+ machdep_sys_fcntl(fd_table[fd]->fd.i, F_SETFL,
+ fd_table[fd]->flags | __FD_NONBLOCK);
+ fd_table[fd]->type = FD_FULL_DUPLEX;
+ break;
+ default:
+ break;
+ }
+}
+
+/* ==========================================================================
* fd_kern_init()
*
* Assume the entry is locked before routine is invoked
*
* This may change. The problem is setting the fd to nonblocking changes
* the parents fd too, which may not be the desired result.
+ *
+ * New added feature: If the fd in question is a tty then we open it again
+ * and close the original, this way we don't have to worry about the
+ * fd being NONBLOCKING to the outside world.
*/
-static fd_kern_init_called = 0;
void fd_kern_init(int fd)
{
if ((fd_table[fd]->flags = machdep_sys_fcntl(fd, F_GETFL, NULL)) >= OK) {
+ if (isatty_basic(fd)) {
+ int new_fd;
+
+ if ((new_fd = machdep_sys_open(__ttyname_basic(fd), O_RDWR)) >= OK){
+ if (machdep_sys_dup2(new_fd, fd) == OK) {
+ /* Should print a warning */
+
+ /* Should also set the flags to that of opened outside of
+ process */
+ }
+ machdep_sys_close(new_fd);
+ }
+ }
+ /* We do these things regaurdless of the above results */
machdep_sys_fcntl(fd, F_SETFL, fd_table[fd]->flags | __FD_NONBLOCK);
fd_table[fd]->ops = &(__fd_kern_ops);
fd_table[fd]->type = FD_HALF_DUPLEX;
- fd_table[fd]->fd = fd;
+ fd_table[fd]->fd.i = fd;
fd_table[fd]->count = 1;
}
}
/* ==========================================================================
+ * fd_kern_gettableentry()
+ *
+ * Remember only return a a file descriptor that I will modify later.
+ * Don't return file descriptors that aren't owned by the child, or don't
+ * have kernel operations.
+ */
+static int fd_kern_gettableentry(const int child, int fd)
+{
+ int i;
+
+ for (i = 0; i < dtablesize; i++) {
+ if (fd_table[i]) {
+ if (fd_table[i]->fd.i == fd) {
+ if (child) {
+ if ((fd_table[i]->type != FD_TEST_HALF_DUPLEX) &&
+ (fd_table[i]->type != FD_TEST_FULL_DUPLEX)) {
+ continue;
+ }
+ } else {
+ if ((fd_table[i]->type == FD_NT) ||
+ (fd_table[i]->type == FD_NIU)) {
+ continue;
+ }
+ }
+ /* Is it a kernel fd ? */
+ if ((!fd_table[i]->ops) ||
+ (fd_table[i]->ops->use_kfds != 1)) {
+ continue;
+ }
+ return(i);
+ }
+ }
+ }
+ return(NOTOK);
+}
+
+/* ==========================================================================
+ * fd_kern_exec()
+ *
+ * Fixup the fd_table such that (fd == fd_table[fd]->fd.i) this way
+ * the new immage will be OK.
+ *
+ * Only touch those that won't be used by the parent if we're in a child
+ * otherwise fixup all.
+ *
+ * Returns:
+ * 0 no fixup necessary
+ * 1 fixup without problems
+ * 2 failed fixup on some descriptors, and clobbered them.
+ */
+int fd_kern_exec(const int child)
+{
+ int ret = 0;
+ int fd, i;
+
+ for (fd = 0; fd < dtablesize; fd++) {
+ if (fd_table[fd] == NULL) {
+ continue;
+ }
+ /* Is the fd already in use ? */
+ if (child) {
+ if ((fd_table[fd]->type != FD_TEST_HALF_DUPLEX) &&
+ (fd_table[fd]->type != FD_TEST_FULL_DUPLEX)) {
+ continue;
+ }
+ } else {
+ if ((fd_table[fd]->type == FD_NT) ||
+ (fd_table[fd]->type == FD_NIU)) {
+ continue;
+ }
+ }
+ /* Is it a kernel fd ? */
+ if ((!fd_table[fd]->ops) ||
+ (fd_table[fd]->ops->use_kfds != 1)) {
+ continue;
+ }
+ /* Does it match ? */
+ if (fd_table[fd]->fd.i == fd) {
+ continue;
+ }
+ /* OK, fixup entry: Read comments before changing. This isn't obvious */
+
+ /* i is the real file descriptor fd currently represents */
+ if (((i = fd_table[fd]->fd.i) >= dtablesize) || (i < 0)) {
+ /* This should never happen */
+ PANIC();
+ }
+
+ /*
+ * if the real file descriptor with the same number as the fake file
+ * descriptor number fd is actually in use by the program, we have
+ * to move it out of the way
+ */
+ if ((machdep_sys_fcntl(fd, F_GETFL, NULL)) >= OK) {
+ /* fd is busy */
+ int j;
+
+ /*
+ * j is the fake file descriptor that represents the real file
+ * descriptor that we want to move. This way the fake file
+ * descriptor fd can move its real file descriptor i such that
+ * fd == i.
+ */
+ if ((j = fd_kern_gettableentry(child, fd)) >= OK) {
+
+ /*
+ * Since j represents a fake file descriptor and fd represents
+ * a fake file descriptor. If j < fd then a previous pass
+ * should have set fd_table[j]->fd.i == j.
+ */
+ if (fd < j) {
+ if ((fd_table[j]->fd.i = machdep_sys_dup(fd)) < OK) {
+ /* Close j, there is nothing else we can do */
+ fd_table[j]->type = FD_NIU;
+ ret = 2;
+ }
+ } else {
+ /* This implies fd_table[j]->fd.i != j */
+ PANIC();
+ }
+ }
+ }
+
+ /*
+ * Here the real file descriptor i is set to equel the fake file
+ * descriptor fd
+ */
+ machdep_sys_dup2(i, fd);
+
+ /*
+ * Now comes the really complicated part: UNDERSTAND before changing
+ *
+ * Here are the things this routine wants to do ...
+ *
+ * Case 1. The real file descriptor has only one fake file descriptor
+ * representing it.
+ * fd -> i, fd != i ===> fd -> fd, close(i)
+ * Example fd = 4, i = 2: then close(2), set fd -> i = 4
+ *
+ * Case 2. The real file descriptor has more than one fake file
+ * descriptor representing it, and this is the first fake file
+ * descriptor representing the real file descriptor
+ * fd -> i, fd' -> i, fd != i ===> fd -> fd, fd' -> fd, close(i)
+ *
+ * The problem is achiving the above is very messy and difficult,
+ * but I should be able to take a short cut. If fd > i then there
+ * will be no need to ever move i, this is because the fake file
+ * descriptor foo that we would have wanted to represent the real
+ * file descriptor i has already been processed. If fd < i then by
+ * moving i to fd all subsequent fake file descriptors fd' should fall
+ * into the previous case and won't need aditional adjusting.
+ *
+ * Does this break the above fd < j check .... It shouldn't because j
+ * is a fake file descriptor and if j < fd then j has already moved
+ * its real file descriptor foo such that foo <= j therefore foo < fd
+ * and not foo == fd therefor j cannot represent the real
+ * filedescriptor that fd want to move to and be less than fd
+ */
+ if (fd < i) {
+ fd_table[fd]->fd.i = fd;
+ machdep_sys_close(i);
+ }
+ if (ret < 1) {
+ ret = 1;
+ }
+ }
+}
+
+/* ==========================================================================
+ * fd_kern_fork()
+ */
+void fd_kern_fork()
+{
+ pthread_mutex_t *mutex;
+ int fd;
+
+ for (fd = 0; fd < dtablesize; fd++) {
+ if (fd_table[fd] == NULL) {
+ continue;
+ }
+ mutex = & (fd_table[fd]->mutex);
+ if (pthread_mutex_trylock(mutex)) {
+ continue;
+ }
+ if ((fd_table[fd]->r_owner) || (fd_table[fd]->w_owner)) {
+ pthread_mutex_unlock(mutex);
+ continue;
+ }
+ /* Is it a kernel fd ? */
+ if ((!fd_table[fd]->ops) || (fd_table[fd]->ops->use_kfds != 1)) {
+ pthread_mutex_unlock(mutex);
+ continue;
+ }
+ switch (fd_table[fd]->type) {
+ case FD_HALF_DUPLEX:
+ machdep_sys_fcntl(fd_table[fd]->fd.i, F_SETFL, fd_table[fd]->flags);
+ fd_table[fd]->type = FD_TEST_HALF_DUPLEX;
+ break;
+ case FD_FULL_DUPLEX:
+ machdep_sys_fcntl(fd_table[fd]->fd.i, F_SETFL, fd_table[fd]->flags);
+ fd_table[fd]->type = FD_TEST_FULL_DUPLEX;
+ break;
+ default:
+ break;
+ }
+ pthread_mutex_unlock(mutex);
+ }
+}
+
+/* ==========================================================================
* Here are the berkeley socket functions. These are not POSIX.
* ======================================================================= */
+#if defined (HAVE_SYSCALL_SOCKET) || defined (HAVE_SYSCALL_SOCKETCALL)
+
/* ==========================================================================
* socket()
*/
@@ -495,153 +1070,843 @@ int socket(int af, int type, int protocol)
if (!((fd = fd_allocate()) < OK)) {
if (!((fd_kern = machdep_sys_socket(af, type, protocol)) < OK)) {
- machdep_sys_fcntl(fd_kern, F_SETFL, __FD_NONBLOCK);
+ int tmp_flags;
+
+ tmp_flags = machdep_sys_fcntl(fd_kern, F_GETFL, 0);
+ machdep_sys_fcntl(fd_kern, F_SETFL, tmp_flags | __FD_NONBLOCK);
/* Should fstat the file to determine what type it is */
fd_table[fd]->ops = & __fd_kern_ops;
fd_table[fd]->type = FD_FULL_DUPLEX;
- fd_table[fd]->fd = fd_kern;
- fd_table[fd]->flags = 0;
+ fd_table[fd]->fd.i = fd_kern;
+ fd_table[fd]->flags = tmp_flags;
return(fd);
}
- pthread_run->error = - fd_kern;
fd_table[fd]->count = 0;
+ SET_ERRNO(-fd_kern);
}
return(NOTOK);
}
+#endif
+
+#if defined (HAVE_SYSCALL_BIND) || defined (HAVE_SYSCALL_SOCKETCALL)
+
/* ==========================================================================
* bind()
*/
int bind(int fd, const struct sockaddr *name, int namelen)
{
/* Not much to do in bind */
- semaphore *plock;
int ret;
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
- if ((ret = machdep_sys_bind(fd_table[fd]->fd, name, namelen)) < OK) {
- pthread_run->error = - ret;
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_bind(fd_table[fd]->fd.i, name, namelen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
}
fd_unlock(fd, FD_RDWR);
}
return(ret);
}
+#endif
+
+#if defined (HAVE_SYSCALL_CONNECT) || defined (HAVE_SYSCALL_SOCKETCALL)
+
/* ==========================================================================
* connect()
*/
int connect(int fd, const struct sockaddr *name, int namelen)
{
- semaphore *lock, *plock;
- struct sockaddr tmpname;
- int ret, tmpnamelen;
-
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
- if ((ret = machdep_sys_connect(fd_table[fd]->fd, name, namelen)) < OK) {
- if ((ret == -EWOULDBLOCK) || (ret == -EINPROGRESS) ||
- (ret == -EALREADY)) {
- /* Lock queue */
- lock = &fd_wait_lock;
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ struct sockaddr tmpname;
+ int ret, tmpnamelen;
+
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_connect(fd_table[fd]->fd.i, name, namelen)) < OK) {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EINPROGRESS) ||
+ (ret == -EALREADY) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDW_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd_table[fd]->fd.i;
+ pthread_queue_enq(&fd_wait_write, pthread_run);
+
+ pthread_resched_resume(PS_FDW_WAIT);
+ CLEAR_PF_DONE_EVENT(pthread_run);
+
+ tmpnamelen = sizeof(tmpname);
+ /* OK now lets see if it really worked */
+ if (((ret = machdep_sys_getpeername(fd_table[fd]->fd.i,
+ &tmpname, &tmpnamelen)) < OK) &&
+ (ret == -ENOTCONN))
+ {
+ /* Get the error, this function should not fail */
+ machdep_sys_getsockopt(fd_table[fd]->fd.i, SOL_SOCKET,
+ SO_ERROR, &ret, &tmpnamelen);
+ SET_ERRNO(ret); /* ret is already positive (mevans) */
+ ret = NOTOK;
+ }
+ } else {
+ if (ret < 0)
+ {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ }
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+ return(ret);
+}
- /* Lock pthread */
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+#endif
- /* queue pthread for a FDW_WAIT */
- pthread_run->fd = fd_table[fd]->fd.i;
- pthread_run->next = fd_wait_write;
- fd_wait_write = pthread_run;
- SEMAPHORE_RESET(lock);
- reschedule(PS_FDW_WAIT);
+#if defined (HAVE_SYSCALL_ACCEPT) || defined (HAVE_SYSCALL_SOCKETCALL)
- /* OK now lets see if it really worked */
- if (((ret = machdep_sys_getpeername(fd_table[fd]->fd,
- &tmpname, &tmpnamelen)) < OK) && (ret == -ENOTCONN)) {
+/* ==========================================================================
+ * accept()
+ */
+int accept(int fd, struct sockaddr *name, int *namelen)
+{
+ int ret, fd_kern;
+
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ while ((fd_kern = machdep_sys_accept(fd_table[fd]->fd.i, name, namelen)) < OK) {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+ ((fd_kern == -EWOULDBLOCK) || (fd_kern == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDR_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd_table[fd]->fd.i;
+ pthread_queue_enq(&fd_wait_read, pthread_run);
+
+ pthread_resched_resume(PS_FDR_WAIT);
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+ fd_unlock(fd, FD_RDWR);
+ SET_ERRNO(-fd_kern);
+ return(NOTOK);
+ }
+ }
+ fd_unlock(fd, FD_RDWR);
- /* Get the error, this function should not fail */
- machdep_sys_getsockopt(fd_table[fd]->fd, SOL_SOCKET,
- SO_ERROR, &pthread_run->error, &tmpnamelen);
- }
- } else {
- pthread_run->error = -ret;
+ if (!((ret = fd_allocate()) < OK)) {
+
+ /* This may be unnecessary */
+ machdep_sys_fcntl(fd_kern, F_SETFL, __FD_NONBLOCK);
+
+ /* Should fstat the file to determine what type it is */
+ fd_table[ret]->ops = & __fd_kern_ops;
+ fd_table[ret]->type = FD_FULL_DUPLEX;
+ fd_table[ret]->fd.i = fd_kern;
+
+ /* XXX Flags should be the same as those on the listening fd */
+ fd_table[ret]->flags = fd_table[fd]->flags;
+ }
+ }
+ return(ret);
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_LISTEN) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * listen()
+ */
+int listen(int fd, int backlog)
+{
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_listen(fd_table[fd]->fd.i, backlog)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+ return(ret);
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_SEND) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * send_timedwait()
+ */
+ssize_t send_timedwait(int fd, const void * msg, size_t len, int flags,
+ struct timespec * timeout)
+{
+ int ret;
+
+ pthread_run->sighandled=0; /* Added by monty */
+ if ((ret = fd_lock(fd, FD_WRITE, timeout)) == OK) {
+ while ((ret = machdep_sys_send(fd_table[fd]->fd.i,
+ msg, len, flags)) < OK)
+ {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN)))
+ {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDW_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd_table[fd]->fd.i;
+ pthread_queue_enq(&fd_wait_write, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDW_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
+ pthread_resched_resume(PS_FDW_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ ret= -EINTR;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ fd_unlock(fd, FD_WRITE);
+ }
+ if (ret < 0)
+ {
+ SET_ERRNO(-ret);
+ return(NOTOK);
+ }
+ return ret;
+}
+
+/* ==========================================================================
+ * send()
+ */
+ssize_t send(int fd, const void * msg, size_t len, int flags)
+{
+ return(send_timedwait(fd, msg, len, flags, NULL));
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_SENDTO) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * sendto_timedwait()
+ */
+ssize_t sendto_timedwait(int fd, const void * msg, size_t len,
+ int flags, const struct sockaddr *to, int to_len,
+ struct timespec * timeout)
+{
+ int ret;
+
+ pthread_run->sighandled=0; /* Added by monty */
+ if ((ret = fd_lock(fd, FD_WRITE, timeout)) == OK) {
+ while ((ret = machdep_sys_sendto(fd_table[fd]->fd.i,
+ msg, len, flags, to, to_len)) < OK) {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDW_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd_table[fd]->fd.i;
+ pthread_queue_enq(&fd_wait_write, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDW_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ ret= -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
+ pthread_resched_resume(PS_FDW_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ ret= -EINTR;
+ break;
+ }
+ }
+ else
+ break; /* ret contains the errorcode */
+ }
+ fd_unlock(fd, FD_WRITE);
+ }
+ if (ret < 0)
+ {
+ SET_ERRNO(-ret);
+ return(NOTOK);
+ }
+ return(ret);
+}
+
+/* ==========================================================================
+ * sendto()
+ */
+ssize_t sendto(int fd, const void * msg, size_t len, int flags,
+ const struct sockaddr *to, int to_len)
+{
+ return(sendto_timedwait(fd, msg, len, flags, to, to_len, NULL));
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_SENDMSG) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * sendmsg_timedwait()
+ */
+ssize_t sendmsg_timedwait(int fd, const struct msghdr *msg, int flags,
+ struct timespec * timeout)
+{
+ int passed_fd, ret, i;
+
+ /* Handle getting the real file descriptor */
+ for(i = 0; i < (((struct omsghdr *)msg)->msg_accrightslen/sizeof(i)); i++) {
+ passed_fd = *(((int *)((struct omsghdr *)msg)->msg_accrights) + i);
+ if ((ret = fd_lock(passed_fd, FD_RDWR, NULL)) == OK) {
+ *(((int *)((struct omsghdr *)msg)->msg_accrights) + i)
+ = fd_table[passed_fd]->fd.i;
+ machdep_sys_fcntl(fd_table[passed_fd]->fd.i, F_SETFL,
+ fd_table[passed_fd]->flags);
+ switch(fd_table[passed_fd]->type) {
+ case FD_TEST_FULL_DUPLEX:
+ case FD_TEST_HALF_DUPLEX:
+ break;
+ case FD_FULL_DUPLEX:
+ fd_table[passed_fd]->type = FD_TEST_FULL_DUPLEX;
+ break;
+ case FD_HALF_DUPLEX:
+ fd_table[passed_fd]->type = FD_TEST_HALF_DUPLEX;
+ break;
+ default:
+ PANIC();
+ }
+ } else {
+ fd_unlock(fd, FD_RDWR);
+ SET_ERRNO(EBADF);
+ return(NOTOK);
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+
+ pthread_run->sighandled=0; /* Added by monty */
+ if ((ret = fd_lock(fd, FD_WRITE, timeout)) == OK) {
+ while((ret = machdep_sys_sendmsg(fd_table[fd]->fd.i, msg, flags)) < OK){
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDW_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd_table[fd]->fd.i;
+ pthread_queue_enq(&fd_wait_write, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDW_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+ ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+
+ } else {
+ pthread_resched_resume(PS_FDW_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ SET_ERRNO(EINTR);
+ ret= NOTOK;
+ break;
+ }
+
+ } else {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ break;
+ }
+ }
+ fd_unlock(fd, FD_WRITE);
+ }
+ return(ret);
+}
+
+/* ==========================================================================
+ * sendmsg()
+ */
+ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
+{
+ return(sendmsg_timedwait(fd, msg, flags, NULL));
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_RECV) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * recv_timedwait()
+ */
+ssize_t recv_timedwait(int fd, void * buf, size_t len, int flags,
+ struct timespec * timeout)
+{
+ int ret;
+
+ pthread_run->sighandled=0; /* Added by monty */
+ if ((ret = fd_lock(fd, FD_READ, timeout)) == OK) {
+ while ((ret = machdep_sys_recv(fd_table[fd]->fd.i,
+ buf, len, flags)) < OK) {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDR_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd_table[fd]->fd.i;
+ pthread_queue_enq(&fd_wait_read, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDR_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
+ pthread_resched_resume(PS_FDR_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ ret= -EINTR;
+ break;
+ }
+
+ } else {
+ break;
+ }
+ }
+ fd_unlock(fd, FD_READ);
+ }
+ if (ret < 0)
+ {
+ SET_ERRNO(-ret);
+ return(NOTOK);
+ }
+ return(ret);
+}
+
+/* ==========================================================================
+ * recv()
+ */
+ssize_t recv(int fd, void * buf, size_t len, int flags)
+{
+ return(recv_timedwait(fd, buf, len, flags, NULL));
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_RECVFROM) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * recvfrom_timedwait()
+ */
+ssize_t recvfrom_timedwait(int fd, void * buf, size_t len, int flags,
+ struct sockaddr * from, int * from_len,
+ struct timespec * timeout)
+{
+ int ret;
+
+ pthread_run->sighandled=0; /* Added by monty */
+ if ((ret = fd_lock(fd, FD_READ, timeout)) == OK) {
+ while ((ret = machdep_sys_recvfrom(fd_table[fd]->fd.i,
+ buf, len, flags, from, from_len)) < OK) {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDR_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd_table[fd]->fd.i;
+ pthread_queue_enq(&fd_wait_read, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDR_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ ret= -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+
+ } else {
+ pthread_resched_resume(PS_FDR_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ ret= -EINTR;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ fd_unlock(fd, FD_READ);
+ }
+ if (ret < 0)
+ {
+ SET_ERRNO(-ret);
+ return(NOTOK);
+ }
+ return(ret);
+}
+
+/* ==========================================================================
+ * recvfrom()
+ */
+ssize_t recvfrom(int fd, void * buf, size_t len, int flags,
+ struct sockaddr * from, int * from_len)
+{
+ return(recvfrom_timedwait(fd, buf, len, flags, from, from_len, NULL));
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_RECVMSG) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * recvmsg_timedwait()
+ */
+ssize_t recvmsg_timedwait(int fd, struct msghdr *msg, int flags,
+ struct timespec * timeout)
+{
+ struct stat stat_buf;
+ int passed_fd, ret, i;
+
+ pthread_run->sighandled=0; /* Added by monty */
+ if ((ret = fd_lock(fd, FD_READ, timeout)) == OK) {
+ while ((ret = machdep_sys_recvmsg(fd_table[fd]->fd.i, msg, flags)) < OK) {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+ ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDR_WAIT */
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_run->data.fd.fd = fd_table[fd]->fd.i;
+ pthread_queue_enq(&fd_wait_read, pthread_run);
+
+ if (timeout) {
+ /* get current time */
+ struct timespec current_time;
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDR_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+ ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+
+ } else {
+ pthread_resched_resume(PS_FDR_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ if (pthread_run->sighandled) /* Added by monty */
+ { /* We where aborted */
+ SET_ERRNO(EINTR);
+ ret= NOTOK;
+ break;
+ }
+ } else {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ break;
+ }
+ }
+ fd_unlock(fd, FD_READ);
+
+ /* Handle getting the real file descriptor */
+ for (i = 0; i < (((struct omsghdr *)msg)->msg_accrightslen / sizeof(i));
+ i++) {
+ passed_fd = *(((int *)((struct omsghdr *)msg)->msg_accrights) + i);
+ if (!((fd = fd_allocate()) < OK)) {
+ fd_table[fd]->flags = machdep_sys_fcntl(passed_fd, F_GETFL);
+
+ if (!( fd_table[fd]->flags & __FD_NONBLOCK)) {
+ machdep_sys_fcntl(passed_fd, F_SETFL,
+ fd_table[fd]->flags | __FD_NONBLOCK);
+ }
+
+ /* fstat the file to determine what type it is */
+ machdep_sys_fstat(passed_fd, &stat_buf);
+ if (S_ISREG(stat_buf.st_mode)) {
+ fd_table[fd]->type = FD_HALF_DUPLEX;
+ } else {
+ fd_table[fd]->type = FD_FULL_DUPLEX;
+ }
+ *(((int *)((struct omsghdr *)msg)->msg_accrights) + i) = fd;
+ fd_table[fd]->ops = &(__fd_kern_ops);
+ fd_table[fd]->fd.i = passed_fd;
+ } else {
+ SET_ERRNO(EBADF);
+ return(NOTOK);
+ break;
+ }
+ }
+ }
+ return(ret);
+}
+
+/* ==========================================================================
+ * recvmsg()
+ */
+ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
+{
+ return(recvmsg_timedwait(fd, msg, flags, NULL));
+}
+
+#endif
+
+#if defined (HAVE_SYSCALL_SHUTDOWN) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * shutdown()
+ */
+int shutdown(int fd, int how)
+{
+ int ret;
+
+ switch(how) {
+ case 0: /* Read */
+ if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+ if ((ret = machdep_sys_shutdown(fd_table[fd]->fd.i, how)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
}
+ fd_unlock(fd, FD_READ);
}
- fd_unlock(fd, FD_RDWR);
+ case 1: /* Write */
+ if ((ret = fd_lock(fd, FD_WRITE, NULL)) == OK) {
+ if ((ret = machdep_sys_shutdown(fd_table[fd]->fd.i, how)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_WRITE);
+ }
+ case 2: /* Read-Write */
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_shutdown(fd_table[fd]->fd.i, how)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+ default:
+ SET_ERRNO(EBADF);
+ ret = NOTOK;
+ break;
}
return(ret);
}
+#endif
+
+#if defined (HAVE_SYSCALL_SETSOCKOPT) || defined (HAVE_SYSCALL_SOCKETCALL)
+
/* ==========================================================================
- * accept()
+ * setsockopt()
*/
-int accept(int fd, struct sockaddr *name, int *namelen)
+int setsockopt(int fd, int level, int optname, const void * optval, int optlen)
{
- semaphore *lock, *plock;
- int ret, fd_kern;
+ int ret;
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_setsockopt(fd_table[fd]->fd.i, level,
+ optname, optval, optlen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+ return ret;
+}
+#endif
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
- while ((fd_kern = machdep_sys_accept(fd_table[fd]->fd, name, namelen)) < OK) {
- if (fd_kern == -EWOULDBLOCK) {
- /* Lock queue */
- lock = &fd_wait_lock;
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+#if defined (HAVE_SYSCALL_GETSOCKOPT) || defined (HAVE_SYSCALL_SOCKETCALL)
- /* Lock pthread */
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+/* ==========================================================================
+ * getsockopt()
+ */
+int getsockopt(int fd, int level, int optname, void * optval, int * optlen)
+{
+ int ret;
- /* queue pthread for a FDR_WAIT */
- pthread_run->fd = fd_table[fd]->fd.i;
- pthread_run->next = fd_wait_write;
- pthread_run->next = fd_wait_read;
- fd_wait_read = pthread_run;
- SEMAPHORE_RESET(lock);
- reschedule(PS_FDR_WAIT);
- } else {
- fd_unlock(fd, FD_RDWR);
- return(fd_kern);
- }
- }
- fd_unlock(fd, FD_RDWR);
+ if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+ if ((ret = machdep_sys_getsockopt(fd_table[fd]->fd.i, level,
+ optname, optval, optlen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+ return ret;
+}
- if (!((ret = fd_allocate()) < OK)) {
+#endif
- /* This may be unnecessary */
- machdep_sys_fcntl(fd_kern, F_SETFL, __FD_NONBLOCK);
+#if defined (HAVE_SYSCALL_GETSOCKOPT) || defined (HAVE_SYSCALL_SOCKETCALL)
- /* Should fstat the file to determine what type it is */
- fd_table[ret]->ops = & __fd_kern_ops;
- fd_table[ret]->type = FD_FULL_DUPLEX;
- fd_table[ret]->fd = fd_kern;
- fd_table[ret]->flags = 0;
+/* ==========================================================================
+ * getsockname()
+ */
+int getsockname(int fd, struct sockaddr * name, int * naddrlen)
+{
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+ if ((ret = machdep_sys_getsockname(fd_table[fd]->fd.i,
+ name, naddrlen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
}
+ fd_unlock(fd, FD_RDWR);
}
- return(ret);
+ return ret;
}
+#endif
+
+#if defined (HAVE_SYSCALL_GETPEERNAME) || defined (HAVE_SYSCALL_SOCKETCALL)
+
/* ==========================================================================
- * listen()
+ * getpeername()
*/
-int listen(int fd, int backlog)
+int getpeername(int fd, struct sockaddr * peer, int * paddrlen)
{
int ret;
- if ((ret = fd_lock(fd, FD_RDWR)) == OK) {
- ret = machdep_sys_listen(fd_table[fd]->fd, backlog);
- fd_unlock(fd, FD_RDWR);
+ if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+ if ((ret = machdep_sys_getpeername(fd_table[fd]->fd.i,
+ peer, paddrlen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_READ);
}
- return(ret);
+ return ret;
}
+
+#endif
+
+#if defined (HAVE_SYSCALL_SOCKETPAIR) || defined (HAVE_SYSCALL_SOCKETCALL)
+
+/* ==========================================================================
+ * socketpair()
+ */
+int socketpair(int af, int type, int protocol, int pair[2])
+{
+ int ret, fd[2];
+
+ if (!((pair[0] = fd_allocate()) < OK)) {
+ if (!((pair[1] = fd_allocate()) < OK)) {
+ if (!((ret = machdep_sys_socketpair(af, type, protocol, fd)) < OK)){
+ int tmp_flags;
+
+ tmp_flags = machdep_sys_fcntl(fd[0], F_GETFL, 0);
+ machdep_sys_fcntl(fd[0], F_SETFL, tmp_flags | __FD_NONBLOCK);
+ fd_table[pair[0]]->ops = & __fd_kern_ops;
+ fd_table[pair[0]]->type = FD_FULL_DUPLEX;
+ fd_table[pair[0]]->flags = tmp_flags;
+ fd_table[pair[0]]->fd.i = fd[0];
+
+ tmp_flags = machdep_sys_fcntl(fd[1], F_GETFL, 0);
+ machdep_sys_fcntl(fd[1], F_SETFL, tmp_flags | __FD_NONBLOCK);
+ fd_table[pair[1]]->ops = & __fd_kern_ops;
+ fd_table[pair[1]]->type = FD_FULL_DUPLEX;
+ fd_table[pair[1]]->flags = tmp_flags;
+ fd_table[pair[1]]->fd.i = fd[1];
+
+ return(ret);
+ }
+ fd_table[pair[1]]->count = 0;
+ }
+ fd_table[pair[0]]->count = 0;
+ SET_ERRNO(-ret);
+ }
+ return(NOTOK);
+}
+
+#endif
diff --git a/lib/libpthread/pthreads/fd_pipe.c b/lib/libpthread/pthreads/fd_pipe.c
index cfd18555c95..6e8a732640d 100644
--- a/lib/libpthread/pthreads/fd_pipe.c
+++ b/lib/libpthread/pthreads/fd_pipe.c
@@ -39,7 +39,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: fd_pipe.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: fd_pipe.c,v 1.16 1994/02/07 02:18:52 proven Exp $";
+static const char rcsid[] = "$Id: fd_pipe.c,v 1.1.1.2 1998/07/21 13:19:58 peter Exp $";
#endif
#include <pthread.h>
@@ -50,38 +50,39 @@ static const char rcsid[] = "$Id: fd_pipe.c,v 1.1.1.1 1995/10/18 08:43:05 deraad
#include <fcntl.h>
#include <errno.h>
#include <pthread/posix.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
/* ==========================================================================
* The pipe lock is never unlocked until all pthreads waiting are done with it
* read()
*/
-ssize_t __pipe_read(struct __pipe *fd, int flags, void *buf, size_t nbytes)
+pthread_ssize_t __pipe_read(union fd_data fd_data, int flags, void *buf,
+ size_t nbytes, struct timespec * timeout)
{
- semaphore *lock, *plock;
+ struct __pipe *fd = (struct __pipe *)fd_data.ptr;
+ struct pthread * pthread;
int ret = 0;
if (flags & O_ACCMODE) { return(NOTOK); }
- lock = &(fd->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
/* If there is nothing to read, go to sleep */
if (fd->count == 0) {
if (flags == WR_CLOSED) {
- SEMAPHORE_RESET(lock);
return(0);
- } /* Lock pthread */
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
}
+ pthread_sched_prevent();
+
/* queue pthread for a FDR_WAIT */
pthread_run->next = NULL;
fd->wait = pthread_run;
- SEMAPHORE_RESET(lock);
- reschedule(PS_FDR_WAIT);
+
+ pthread_resched_resume(PS_FDR_WAIT);
ret = fd->size;
} else {
ret = MIN(nbytes, fd->count);
@@ -90,17 +91,10 @@ ssize_t __pipe_read(struct __pipe *fd, int flags, void *buf, size_t nbytes)
fd->offset = 0;
}
- /* Should try to read more from the waiting writer */
-
- if (fd->wait) {
- plock = &(fd->wait->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
- fd->wait->state = PS_RUNNING;
- SEMAPHORE_RESET(plock);
- } else {
- SEMAPHORE_RESET(lock);
+ if (pthread = fd->wait) {
+ fd->wait = NULL;
+ pthread_sched_prevent();
+ pthread_sched_other_resume(pthread);
}
}
return(ret);
@@ -116,23 +110,18 @@ ssize_t __pipe_read(struct __pipe *fd, int flags, void *buf, size_t nbytes)
* copies as much data as it can into the pipe buffer and it there
* is still data it goes to sleep.
*/
-ssize_t __pipe_write(struct __pipe *fd, int flags, const void *buf, size_t nbytes) {
- semaphore *lock, *plock;
+pthread_ssize_t __pipe_write(union fd_data fd_data, int flags, const void *buf,
+ size_t nbytes, struct timespec * timeout) {
+ struct __pipe *fd = (struct __pipe *)fd_data.ptr;
+ struct pthread * pthread;
int ret, count;
if (!(flags & O_ACCMODE)) { return(NOTOK); }
- lock = &(fd->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
while (fd->flags != RD_CLOSED) {
- if (fd->wait) {
- /* Lock pthread */
- plock = &(fd->wait->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+ if (pthread = fd->wait) {
+
+ pthread_sched_prevent();
/* Copy data directly into waiting pthreads buf */
fd->wait_size = MIN(nbytes, fd->wait_size);
@@ -140,11 +129,10 @@ ssize_t __pipe_write(struct __pipe *fd, int flags, const void *buf, size_t nbyte
buf = (const char *)buf + fd->wait_size;
nbytes -= fd->wait_size;
ret = fd->wait_size;
+ fd->wait = NULL;
/* Wake up waiting pthread */
- fd->wait->state = PS_RUNNING;
- SEMAPHORE_RESET(plock);
- fd->wait = NULL;
+ pthread_sched_other_resume(pthread);
}
if (count = MIN(nbytes, fd->size - (fd->offset + fd->count))) {
@@ -154,15 +142,9 @@ ssize_t __pipe_write(struct __pipe *fd, int flags, const void *buf, size_t nbyte
ret += count;
}
if (nbytes) {
- /* Lock pthread */
- plock = &(fd->wait->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
-
+ pthread_sched_prevent();
fd->wait = pthread_run;
- SEMAPHORE_RESET(lock);
- reschedule(PS_FDW_WAIT);
+ pthread_resched_resume(PS_FDW_WAIT);
} else {
return(ret);
}
@@ -184,29 +166,16 @@ ssize_t __pipe_write(struct __pipe *fd, int flags, const void *buf, size_t nbyte
*/
int __pipe_close(struct __pipe *fd, int flags)
{
- semaphore *lock, *plock;
+ struct pthread * pthread;
- lock = &(fd->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
if (!(fd->flags)) {
- if (fd->wait) {
+ if (pthread = fd->wait) {
if (flags & O_ACCMODE) {
- fd->flags |= WR_CLOSED;
- /* Lock pthread */
- /* Write side closed, wake read side and return EOF */
- plock = &((fd->wait)->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
-
fd->count = 0;
-
- /* Wake up waiting pthread */
- fd->wait->state = PS_RUNNING;
- SEMAPHORE_RESET(plock);
fd->wait = NULL;
+ fd->flags |= WR_CLOSED;
+ pthread_sched_prevent();
+ pthread_resched_resume(pthread);
} else {
/* Should send a signal */
fd->flags |= RD_CLOSED;
@@ -216,16 +185,37 @@ int __pipe_close(struct __pipe *fd, int flags)
free(fd);
return(OK);
}
- SEMAPHORE_RESET(lock);
}
/* ==========================================================================
- * For those function that aren't implemented yet
+ * For fcntl() which isn't implemented yet
* __pipe_enosys()
*/
static int __pipe_enosys()
{
- pthread_run->error = ENOSYS;
+ SET_ERRNO(ENOSYS);
+ return(NOTOK);
+}
+
+/* ==========================================================================
+ * For writev() and readv() which aren't implemented yet
+ * __pipe_enosys_v()
+ */
+static int __pipe_enosys_v(union fd_data fd, int flags,
+ const struct iovec *vec, int nvec,
+ struct timespec *timeout)
+{
+ SET_ERRNO(ENOSYS);
+ return(NOTOK);
+}
+
+/* ==========================================================================
+ * For lseek() which isn't implemented yet
+ * __pipe_enosys_o()
+ */
+static off_t __pipe_enosys_o()
+{
+ SET_ERRNO(ENOSYS);
return(NOTOK);
}
@@ -233,9 +223,8 @@ static int __pipe_enosys()
* File descriptor operations
*/
struct fd_ops fd_ops[] = {
-{ NULL, NULL, }, /* Non operations */
-{ __pipe_write, __pipe_read, __pipe_close, __pipe_enosys, __pipe_enosys,
- __pipe_enosys },
+{ __pipe_write, __pipe_read, __pipe_close, __pipe_enosys,
+ __pipe_enosys_v, __pipe_enosys_v, __pipe_enosys_o, 0 },
};
/* ==========================================================================
diff --git a/lib/libpthread/pthreads/file.c b/lib/libpthread/pthreads/file.c
index 0cdc462da52..f4b4150bb90 100644
--- a/lib/libpthread/pthreads/file.c
+++ b/lib/libpthread/pthreads/file.c
@@ -36,7 +36,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: file.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: file.c,v 1.16 1994/02/07 02:18:55 proven Exp $";
+static const char rcsid[] = "$Id: file.c,v 1.1.1.2 1998/07/21 13:20:00 peter Exp $";
#endif
#include <pthread.h>
@@ -47,21 +47,26 @@ static const char rcsid[] = "$Id: file.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt E
*/
void flockfile(FILE *fp)
{
- semaphore *lock;
- int fd;
+ pthread_mutex_t *mutex;
+ int fd, flags;
- fd = fileno(fp);
- lock = &(fd_table[fd]->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ if ((fd = fileno(fp)) >= 0) {
+ pthread_mutex_lock(mutex = &(fd_table[fd]->mutex));
+
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else {
+ if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
+ }
- if (fd_table[fd]->r_owner != pthread_run) {
/* This might fail but POSIX doesn't give a damn. */
- fd_basic_lock(fd, FD_RDWR, lock);
+ fd_basic_lock(fd, flags, mutex, NULL);
+ pthread_mutex_unlock(mutex);
}
- fd_table[fd]->lockcount++;
- SEMAPHORE_RESET(lock);
}
/* ==========================================================================
@@ -69,27 +74,31 @@ void flockfile(FILE *fp)
*/
int ftrylockfile(FILE *fp)
{
- semaphore *lock;
- int fd;
+ pthread_mutex_t *mutex;
+ int fd, flags;
- fd = fileno(fp);
- lock = &(fd_table[fd]->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ if ((fd = fileno(fp)) >= 0) {
+ pthread_mutex_lock(mutex = &(fd_table[fd]->mutex));
- if (fd_table[fd]->r_owner != pthread_run) {
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else {
+ if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
+ }
if (!(fd_table[fd]->r_owner && fd_table[fd]->w_owner)) {
- fd_basic_lock(fd, FD_RDWR, lock);
+ fd_basic_lock(fd, flags, mutex, NULL);
fd = OK;
} else {
fd = NOTOK;
}
+ pthread_mutex_unlock(mutex);
} else {
- fd_table[fd]->lockcount++;
fd = OK;
}
- SEMAPHORE_RESET(lock);
return(fd);
}
@@ -98,20 +107,23 @@ int ftrylockfile(FILE *fp)
*/
void funlockfile(FILE *fp)
{
- semaphore *lock;
- int fd;
+ pthread_mutex_t *mutex;
+ int fd, flags;
- fd = fileno(fp);
- lock = &(fd_table[fd]->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ if ((fd = fileno(fp)) >= 0) {
+ pthread_mutex_lock(mutex = &(fd_table[fd]->mutex));
- if (fd_table[fd]->r_owner == pthread_run) {
- if (--fd_table[fd]->lockcount == 0) {
- fd_basic_unlock(fd, FD_RDWR);
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else {
+ if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
}
- }
- SEMAPHORE_RESET(lock);
+ fd_basic_unlock(fd, flags);
+ pthread_mutex_unlock(mutex);
+ }
}
diff --git a/lib/libpthread/pthreads/globals.c b/lib/libpthread/pthreads/globals.c
index 6d68f58028d..48315ed12ec 100644
--- a/lib/libpthread/pthreads/globals.c
+++ b/lib/libpthread/pthreads/globals.c
@@ -36,32 +36,50 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: globals.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: globals.c,v 1.16 1994/02/07 02:18:57 proven Exp $";
+static const char rcsid[] = "$Id: globals.c,v 1.1.1.2 1998/07/21 13:20:02 peter Exp $";
#endif
#include <pthread.h>
/*
- * Initial thread, running thread, and top of link list
- * of all threads.
+ * Initial thread, running thread, and top of link list of all threads.
*/
-struct pthread *pthread_run;
-struct pthread *pthread_initial;
-struct pthread *pthread_link_list;
+struct pthread *pthread_run=NULL;
+struct pthread *pthread_initial=NULL;
+struct pthread *pthread_link_list=NULL;
+
+sigset_t * uthread_sigmask; /* Current process signal mask */
/*
- * default thread attributes
+ * Dead thread queue, and threads elligible to be alloced queue.
*/
-pthread_attr_t pthread_default_attr = { SCHED_RR, NULL, PTHREAD_STACK_DEFAULT };
+struct pthread_queue pthread_dead_queue;
+struct pthread_queue pthread_alloc_queue;
/*
* Queue for all threads elidgeable to run this scheduling round.
*/
-struct pthread_queue pthread_current_queue = PTHREAD_QUEUE_INITIALIZER;
+struct pthread_prio_queue * pthread_current_prio_queue=NULL;
+
+/*
+ * default thread attributes
+ */
+pthread_attr_t pthread_attr_default = { SCHED_RR, PTHREAD_DEFAULT_PRIORITY,
+ PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, PTHREAD_STACK_DEFAULT };
/*
* File table information
*/
-struct fd_table_entry *fd_table[64];
+struct fd_table_entry **fd_table=NULL;
+/*
+ * A we a fork()ed process
+ */
+volatile int fork_lock = 0;
+volatile int pthread_kernel_lock=0;
+
+/*
+ * The page size, as returned by getpagesize()
+ */
+size_t pthread_pagesize=0;
diff --git a/lib/libpthread/pthreads/malloc.c b/lib/libpthread/pthreads/malloc.c
index 02118537c9f..b071fd8f04f 100644
--- a/lib/libpthread/pthreads/malloc.c
+++ b/lib/libpthread/pthreads/malloc.c
@@ -46,7 +46,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: malloc.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: malloc.c,v 1.16 1994/02/07 02:19:00 proven Exp $";
+static const char rcsid[] = "$Id: malloc.c,v 1.1.1.2 1998/07/21 13:20:05 peter Exp $";
#endif
#include <pthread.h>
@@ -64,14 +64,20 @@ static const char rcsid[] = "$Id: malloc.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt
* The order of elements is critical: ov_magic must overlay the low order
* bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
*/
+#ifdef __alpha
+#define _MOST_RESTRICTIVE_ALIGNMENT_TYPE char*
+#else
+#define _MOST_RESTRICTIVE_ALIGNMENT_TYPE double
+#endif /* __alpha */
union overhead {
+ _MOST_RESTRICTIVE_ALIGNMENT_TYPE __alignment_pad0;
union overhead *ov_next; /* when free */
struct {
u_char ovu_magic; /* magic number */
u_char ovu_index; /* bucket # */
#ifdef RCHECK
u_short ovu_rmagic; /* range magic number */
- u_int ovu_size; /* actual block size */
+ size_t ovu_size; /* actual block size */
#endif
} ovu;
#define ov_magic ovu.ovu_magic
@@ -96,11 +102,13 @@ union overhead {
*/
#define NBUCKETS 30
static union overhead *nextf[NBUCKETS];
+#ifndef hpux
extern char *sbrk();
+#endif
-static int pagesz; /* page size */
+static size_t pagesz; /* page size */
static int pagebucket; /* page size bucket */
-static semaphore malloc_lock = SEMAPHORE_CLEAR;
+static pthread_mutex_t malloc_mutex = PTHREAD_MUTEX_INITIALIZER;
#if defined(DEBUG) || defined(RCHECK)
#define ASSERT(p) if (!(p)) botch("p")
@@ -125,15 +133,15 @@ botch(s)
static inline void morecore(int bucket)
{
register union overhead *op;
- register int sz; /* size of desired block */
- int amt; /* amount to allocate */
- int nblks; /* how many blocks we get */
+ register size_t sz; /* size of desired block */
+ size_t amt; /* amount to allocate */
+ size_t nblks; /* how many blocks we get */
/*
* sbrk_size <= 0 only for big, FLUFFY, requests (about
* 2^30 bytes on a VAX, I think) or for a negative arg.
*/
- sz = 1 << (bucket + 3);
+ sz = 1L << (bucket + 3);
#ifdef DEBUG
ASSERT(sz > 0);
#else
@@ -149,8 +157,8 @@ static inline void morecore(int bucket)
}
op = (union overhead *)sbrk(amt);
/* no more room! */
- if ((int)op == -1)
- return;
+ if (op == (union overhead *) -1)
+ return;
/*
* Add new memory allocated to that on
* free list for this hash bucket.
@@ -167,28 +175,32 @@ static inline void morecore(int bucket)
*/
void *malloc(size_t nbytes)
{
+ pthread_mutex_t *mutex;
union overhead *op;
- unsigned int amt;
- int bucket, n;
- semaphore *lock;
+ size_t amt;
+ size_t bucket, n;
- lock = &malloc_lock;
- while(SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ mutex = &malloc_mutex;
+ pthread_mutex_lock(mutex);
/*
* First time malloc is called, setup page size and
* align break pointer so all data will be page aligned.
*/
if (pagesz == 0) {
+ size_t x;
pagesz = n = getpagesize();
op = (union overhead *)sbrk(0);
- n = n - sizeof (*op) - ((int)op & (n - 1));
- if (n < 0)
- n += pagesz;
+ x = sizeof (*op) - ((long)op & (n - 1));
+ if (n < x)
+ n = n + pagesz - x;
+ else
+ n = n - x;
if (n) {
- if (sbrk(n) == (char *)-1)
- return (NULL);
+ if (sbrk(n) == (char *)-1) {
+ /* Unlock before returning (mevans) */
+ pthread_mutex_unlock(mutex);
+ return (NULL);
+ }
}
bucket = 0;
amt = 8;
@@ -219,11 +231,12 @@ void *malloc(size_t nbytes)
while (nbytes > amt + n) {
amt <<= 1;
if (amt == 0) {
- SEMAPHORE_RESET(lock);
+ pthread_mutex_unlock(mutex);
return (NULL);
}
bucket++;
}
+ ASSERT (bucket < NBUCKETS);
/*
* If nothing in hash bucket right now,
* request more memory from the system.
@@ -231,7 +244,7 @@ void *malloc(size_t nbytes)
if ((op = nextf[bucket]) == NULL) {
morecore(bucket);
if ((op = nextf[bucket]) == NULL) {
- SEMAPHORE_RESET(lock);
+ pthread_mutex_unlock(mutex);
return (NULL);
}
}
@@ -248,7 +261,7 @@ void *malloc(size_t nbytes)
op->ov_rmagic = RMAGIC;
*(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
#endif
- SEMAPHORE_RESET(lock);
+ pthread_mutex_unlock(mutex);
return ((char *)(op + 1));
}
@@ -257,16 +270,14 @@ void *malloc(size_t nbytes)
*/
void free(void *cp)
{
+ pthread_mutex_t *mutex;
union overhead *op;
- semaphore *lock;
- int size;
+ int size;
- lock = &malloc_lock;
- while(SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ mutex = &malloc_mutex;
+ pthread_mutex_lock(mutex);
if (cp == NULL) {
- SEMAPHORE_RESET(lock);
+ pthread_mutex_unlock(mutex);
return;
}
op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
@@ -274,7 +285,7 @@ void free(void *cp)
ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */
#else
if (op->ov_magic != MAGIC) {
- SEMAPHORE_RESET(lock);
+ pthread_mutex_unlock(mutex);
return; /* sanity */
}
#endif
@@ -287,7 +298,7 @@ void free(void *cp)
op->ov_next = nextf[size]; /* also clobbers ov_magic */
nextf[size] = op;
- SEMAPHORE_RESET(lock);
+ pthread_mutex_unlock(mutex);
}
/* ==========================================================================
@@ -297,9 +308,9 @@ void free(void *cp)
*/
void *realloc(void *cp, size_t nbytes)
{
- u_int onb;
- int i;
- semaphore *lock;
+ pthread_mutex_t *mutex;
+ size_t onb;
+ size_t i;
union overhead *op;
char *res;
@@ -319,11 +330,9 @@ void *realloc(void *cp, size_t nbytes)
return(NULL);
}
- lock = &malloc_lock;
- while(SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
- onb = 1 << (i + 3);
+ mutex = &malloc_mutex;
+ pthread_mutex_lock(mutex);
+ onb = 1L << (i + 3);
if (onb < pagesz)
onb -= sizeof (*op) + RSLOP;
else
@@ -331,7 +340,7 @@ void *realloc(void *cp, size_t nbytes)
/* avoid the copy if same size block */
if (i) {
- i = 1 << (i + 2);
+ i = 1L << (i + 2);
if (i < pagesz)
i -= sizeof (*op) + RSLOP;
else
@@ -343,19 +352,32 @@ void *realloc(void *cp, size_t nbytes)
op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
*(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
#endif
- SEMAPHORE_RESET(lock);
+ pthread_mutex_unlock(mutex);
return(cp);
}
- SEMAPHORE_RESET(lock);
+ pthread_mutex_unlock(mutex);
if ((res = malloc(nbytes)) == NULL) {
free(cp);
return (NULL);
}
- bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
+ memcpy(res, cp, (nbytes < onb) ? nbytes : onb);
free(cp);
return (res);
}
+/* ==========================================================================
+ * calloc()
+ *
+ * Added to ensure pthread's allocation is used (mevans).
+ */
+void *calloc(size_t nmemb, size_t size)
+{
+ void *p;
+ size *= nmemb;
+ p = malloc(size);
+ if (p) memset(p, 0, size);
+ return (p);
+}
diff --git a/lib/libpthread/pthreads/mutex.c b/lib/libpthread/pthreads/mutex.c
index 339f9d922b9..9e53df5add3 100644
--- a/lib/libpthread/pthreads/mutex.c
+++ b/lib/libpthread/pthreads/mutex.c
@@ -1,4 +1,4 @@
-/* ==== mutex.c ============================================================
+/* ==== mutex.c ==============================================================
* Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
* All rights reserved.
*
@@ -36,22 +36,33 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: mutex.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: mutex.c,v 1.16 1994/02/07 02:19:03 proven Exp $";
+static const char rcsid[] = "$Id: mutex.c,v 1.1.1.2 1998/07/21 13:20:07 peter Exp $";
#endif
#include <pthread.h>
+#include <stdlib.h>
#include <errno.h>
-/*
- * Basic mutex functionality
-
- * This is the basic lock order
- * queue
- * pthread
- * global
+/* ==========================================================================
+ * pthread_mutex_is_debug()
*
- * semaphore functionality is defined in machdep.h
+ * Check that mutex is a debug mutex and if so returns entry number into
+ * array of debug mutexes.
*/
+static int pthread_mutex_debug_count = 0;
+static pthread_mutex_t ** pthread_mutex_debug_ptrs = NULL;
+
+static inline int pthread_mutex_is_debug(pthread_mutex_t * mutex)
+{
+ int i;
+
+ for (i = 0; i < pthread_mutex_debug_count; i++) {
+ if (pthread_mutex_debug_ptrs[i] == mutex) {
+ return(i);
+ }
+ }
+ return(NOTOK);
+}
/* ==========================================================================
* pthread_mutex_init()
@@ -60,25 +71,62 @@ static const char rcsid[] = "$Id: mutex.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt
* ENOMEM, EAGAIN should never be returned. Arch that have
* weird constraints may need special coding.
*/
-int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *mutex_attr)
+int pthread_mutex_init(pthread_mutex_t *mutex,
+ const pthread_mutexattr_t *mutex_attr)
{
+ enum pthread_mutextype type;
+
/* Only check if attr specifies some mutex type other than fast */
if ((mutex_attr) && (mutex_attr->m_type != MUTEX_TYPE_FAST)) {
if (mutex_attr->m_type >= MUTEX_TYPE_MAX) {
return(EINVAL);
}
- if (mutex->m_flags & MUTEX_FLAGS_INITED) {
- return(EBUSY);
- }
- mutex->m_type = mutex_attr->m_type;
+ type = mutex_attr->m_type;
} else {
- mutex->m_type = MUTEX_TYPE_FAST;
+ type = MUTEX_TYPE_FAST;
+ }
+ mutex->m_flags = 0;
+
+ pthread_sched_prevent();
+
+ switch(type) {
+ case MUTEX_TYPE_FAST:
+ break;
+ case MUTEX_TYPE_STATIC_FAST:
+ pthread_sched_resume();
+ return(EINVAL);
+ break;
+ case MUTEX_TYPE_COUNTING_FAST:
+ mutex->m_data.m_count = 0;
+ break;
+ case MUTEX_TYPE_DEBUG:
+ if (pthread_mutex_is_debug(mutex) == NOTOK) {
+ pthread_mutex_t ** new;
+
+ if ((new = (pthread_mutex_t **)realloc(pthread_mutex_debug_ptrs,
+ (pthread_mutex_debug_count + 1) * (sizeof(void *)))) == NULL) {
+ pthread_sched_resume();
+ return(ENOMEM);
+ }
+ pthread_mutex_debug_ptrs = new;
+ pthread_mutex_debug_ptrs[pthread_mutex_debug_count++] = mutex;
+ } else {
+ pthread_sched_resume();
+ return(EBUSY);
+ }
+ break;
+ default:
+ pthread_sched_resume();
+ return(EINVAL);
+ break;
}
/* Set all other paramaters */
pthread_queue_init(&mutex->m_queue);
mutex->m_flags |= MUTEX_FLAGS_INITED;
- mutex->m_lock = SEMAPHORE_CLEAR;
mutex->m_owner = NULL;
+ mutex->m_type = type;
+
+ pthread_sched_resume();
return(OK);
}
@@ -87,22 +135,48 @@ int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *mutex_attr)
*/
int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
+ int i;
+
+ pthread_sched_prevent();
+
/* Only check if mutex is of type other than fast */
switch(mutex->m_type) {
case MUTEX_TYPE_FAST:
break;
case MUTEX_TYPE_STATIC_FAST:
+ pthread_sched_resume();
+ return(EINVAL);
+ break;
+ case MUTEX_TYPE_COUNTING_FAST:
+ mutex->m_data.m_count = 0;
+ break;
+ case MUTEX_TYPE_DEBUG:
+ if ((i = pthread_mutex_is_debug(mutex)) == NOTOK) {
+ pthread_sched_resume();
+ return(EINVAL);
+ }
+ if (mutex->m_owner) {
+ pthread_sched_resume();
+ return(EBUSY);
+ }
+
+ /* Remove the mutex from the list of debug mutexes */
+ pthread_mutex_debug_ptrs[i] =
+ pthread_mutex_debug_ptrs[--pthread_mutex_debug_count];
+ pthread_mutex_debug_ptrs[pthread_mutex_debug_count] = NULL;
+ break;
default:
+ pthread_sched_resume();
return(EINVAL);
break;
}
/* Cleanup mutex, others might want to use it. */
pthread_queue_init(&mutex->m_queue);
- mutex->m_flags |= MUTEX_FLAGS_INITED;
- mutex->m_lock = SEMAPHORE_CLEAR;
mutex->m_owner = NULL;
mutex->m_flags = 0;
+
+ pthread_sched_resume();
return(OK);
}
@@ -111,14 +185,9 @@ int pthread_mutex_destroy(pthread_mutex_t *mutex)
*/
int pthread_mutex_trylock(pthread_mutex_t *mutex)
{
- semaphore *lock;
int rval;
- lock = &(mutex->m_lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
+ pthread_sched_prevent();
switch (mutex->m_type) {
/*
* Fast mutexes do not check for any error conditions.
@@ -132,11 +201,37 @@ int pthread_mutex_trylock(pthread_mutex_t *mutex)
rval = EBUSY;
}
break;
+ case MUTEX_TYPE_COUNTING_FAST:
+ if (mutex->m_owner) {
+ if (mutex->m_owner == pthread_run) {
+ mutex->m_data.m_count++;
+ rval = OK;
+ } else {
+ rval = EBUSY;
+ }
+ } else {
+ mutex->m_owner = pthread_run;
+ rval = OK;
+ }
+ break;
+ case MUTEX_TYPE_DEBUG:
+ if (pthread_mutex_is_debug(mutex) != NOTOK) {
+ if (!mutex->m_owner) {
+ mutex->m_owner = pthread_run;
+ rval = OK;
+ } else {
+ rval = EBUSY;
+ }
+ } else {
+ rval = EINVAL;
+ }
+ break;
default:
rval = EINVAL;
break;
}
- SEMAPHORE_RESET(lock);
+
+ pthread_sched_resume();
return(rval);
}
@@ -145,14 +240,9 @@ int pthread_mutex_trylock(pthread_mutex_t *mutex)
*/
int pthread_mutex_lock(pthread_mutex_t *mutex)
{
- semaphore *lock, *plock;
int rval;
- lock = &(mutex->m_lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
+ pthread_sched_prevent();
switch (mutex->m_type) {
/*
* Fast mutexes do not check for any error conditions.
@@ -160,25 +250,60 @@ int pthread_mutex_lock(pthread_mutex_t *mutex)
case MUTEX_TYPE_FAST:
case MUTEX_TYPE_STATIC_FAST:
if (mutex->m_owner) {
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
pthread_queue_enq(&mutex->m_queue, pthread_run);
- SEMAPHORE_RESET(lock);
- /* Reschedule will unlock pthread_run */
- reschedule(PS_MUTEX_WAIT);
+ /* Reschedule will unlock scheduler */
+ pthread_resched_resume(PS_MUTEX_WAIT);
return(OK);
}
mutex->m_owner = pthread_run;
rval = OK;
break;
+ case MUTEX_TYPE_COUNTING_FAST:
+ if (mutex->m_owner) {
+ if (mutex->m_owner != pthread_run) {
+ pthread_queue_enq(&mutex->m_queue, pthread_run);
+
+ /* Reschedule will unlock scheduler */
+ pthread_resched_resume(PS_MUTEX_WAIT);
+ return(OK);
+ } else {
+ mutex->m_data.m_count++;
+ }
+ } else {
+ mutex->m_owner = pthread_run;
+ }
+ rval = OK;
+ break;
+ case MUTEX_TYPE_DEBUG:
+ if (pthread_mutex_is_debug(mutex) != NOTOK) {
+ if (mutex->m_owner) {
+ if (mutex->m_owner != pthread_run) {
+ pthread_queue_enq(&mutex->m_queue, pthread_run);
+
+ /* Reschedule will unlock pthread_run */
+ pthread_resched_resume(PS_MUTEX_WAIT);
+
+ if (mutex->m_owner != pthread_run) {
+ PANIC();
+ }
+ return(OK);
+ }
+ rval = EDEADLK;
+ break;
+ }
+ mutex->m_owner = pthread_run;
+ rval = OK;
+ break;
+ }
+ rval = EINVAL;
+ break;
default:
rval = EINVAL;
break;
}
- SEMAPHORE_RESET(lock);
+
+ pthread_sched_resume();
return(rval);
}
@@ -188,40 +313,59 @@ int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
struct pthread *pthread;
- semaphore *lock, *plock;
int rval;
- lock = &(mutex->m_lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
+ pthread_sched_prevent();
+
switch (mutex->m_type) {
/*
* Fast mutexes do not check for any error conditions.
*/
case MUTEX_TYPE_FAST:
case MUTEX_TYPE_STATIC_FAST:
- if (pthread = pthread_queue_get(&mutex->m_queue)) {
- plock = &(pthread->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
- mutex->m_owner = pthread;
+ if (mutex->m_owner = pthread_queue_deq(&mutex->m_queue)) {
- /* Reset pthread state */
- pthread_queue_deq(&mutex->m_queue);
- pthread->state = PS_RUNNING;
- SEMAPHORE_RESET(plock);
- } else {
- mutex->m_owner = NULL;
+ /* Reschedule will unlock scheduler */
+ pthread_sched_other_resume(mutex->m_owner);
+ return(OK);
+ }
+ rval = OK;
+ break;
+ case MUTEX_TYPE_COUNTING_FAST:
+ if (mutex->m_data.m_count) {
+ mutex->m_data.m_count--;
+ rval = OK;
+ break;
+ }
+ if (mutex->m_owner = pthread_queue_deq(&mutex->m_queue)) {
+
+ /* Reschedule will unlock scheduler */
+ pthread_sched_other_resume(mutex->m_owner);
+ return(OK);
}
rval = OK;
break;
+ case MUTEX_TYPE_DEBUG:
+ if (pthread_mutex_is_debug(mutex) != NOTOK) {
+ if (mutex->m_owner == pthread_run) {
+ if (mutex->m_owner = pthread_queue_deq(&mutex->m_queue)) {
+
+ /* Reschedule will unlock scheduler */
+ pthread_sched_other_resume(mutex->m_owner);
+ return(OK);
+ }
+ rval = OK;
+ } else {
+ rval = EPERM;
+ }
+ } else {
+ rval = EINVAL;
+ }
+ break;
default:
rval = EINVAL;
break;
}
- SEMAPHORE_RESET(lock);
+ pthread_sched_resume();
return(rval);
}
diff --git a/lib/libpthread/pthreads/pthread.c b/lib/libpthread/pthreads/pthread.c
index 7bf9ad35897..0460b8e08f9 100644
--- a/lib/libpthread/pthreads/pthread.c
+++ b/lib/libpthread/pthreads/pthread.c
@@ -36,52 +36,23 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: pthread.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread.c,v 1.16 1994/02/07 02:19:06 proven Exp $";
+static const char rcsid[] = "$Id: pthread.c,v 1.1.1.2 1998/07/21 13:20:09 peter Exp $";
#endif
-#include "pthread.h"
+#include <pthread.h>
+#include <stdlib.h>
#include <signal.h>
#include <errno.h>
-
-/*
- * These first functions really should not be called by the user.
- */
+#include <string.h>
+#include <sched.h>
/* ==========================================================================
- * pthread_init()
- *
- * This function should be called in crt0.o before main() is called.
- * But on some systems It may not be possible to change crt0.o so currently
- * I'm requiring this function to be called first thing after main.
- * Actually I'm assuming it is, because I do no locking here.
+ * sched_yield()
*/
-void pthread_init(void)
+int sched_yield()
{
- struct machdep_pthread machdep_data = MACHDEP_PTHREAD_INIT;
-
- /* Initialize the first thread */
- if (pthread_initial = (pthread_t)malloc(sizeof(struct pthread))) {
- memcpy(&(pthread_initial->machdep_data), &machdep_data, sizeof(machdep_data));
- pthread_initial->state = PS_RUNNING;
- pthread_initial->queue = NULL;
- pthread_initial->next = NULL;
- pthread_initial->pll = NULL;
-
- pthread_initial->lock = SEMAPHORE_CLEAR;
- pthread_initial->error = 0;
-
- pthread_link_list = pthread_initial;
- pthread_run = pthread_initial;
-
- /* Initialize the signal handler. */
- sig_init();
-
- /* Initialize the fd table. */
- fd_init();
-
- return;
- }
- PANIC();
+ sig_handler_fake(SIGVTALRM);
+ return(OK);
}
/* ==========================================================================
@@ -92,7 +63,6 @@ void pthread_yield()
sig_handler_fake(SIGVTALRM);
}
-/* ======================================================================= */
/* ==========================================================================
* pthread_self()
*/
@@ -112,41 +82,141 @@ int pthread_equal(pthread_t t1, pthread_t t2)
/* ==========================================================================
* pthread_exit()
*/
+extern void pthread_cleanupspecific(void);
+
void pthread_exit(void *status)
{
- semaphore *lock, *plock;
pthread_t pthread;
- lock = &pthread_run->lock;
- if (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
-
/* Save return value */
pthread_run->ret = status;
/* First execute all cleanup handlers */
-
-
- /*
- * Are there any threads joined to this one,
- * if so wake them and let them detach this thread.
- */
- if (pthread = pthread_queue_get(&(pthread_run->join_queue))) {
- /* The current thread pthread_run can't be detached */
- plock = &(pthread->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
- (void)pthread_queue_deq(&(pthread_run->join_queue));
- pthread->state = PS_RUNNING;
+ while (pthread_run->cleanup) {
+ pthread_cleanup_pop(1);
+ }
+
+ /* Don't forget the cleanup attr */
+ if (pthread_run->attr.cleanup_attr) {
+ pthread_run->attr.cleanup_attr(pthread_run->attr.arg_attr);
+ }
- /* Thread will unlock itself in pthread_join() */
+ /* Next run thread-specific data desctructors */
+ if (pthread_run->specific_data) {
+ pthread_cleanupspecific();
+ }
+
+ pthread_sched_prevent();
+
+ if (!(pthread_run->attr.flags & PTHREAD_DETACHED)) {
+ /*
+ * Are there any threads joined to this one,
+ * if so wake them and let them detach this thread.
+ */
+ while (pthread = pthread_queue_deq(&(pthread_run->join_queue))) {
+ pthread_prio_queue_enq(pthread_current_prio_queue, pthread);
+ pthread->state = PS_RUNNING;
+ }
+ pthread_queue_enq(&pthread_dead_queue, pthread_run);
+ pthread_resched_resume(PS_DEAD);
+ } else {
+ pthread_queue_enq(&pthread_alloc_queue, pthread_run);
+ pthread_resched_resume(PS_UNALLOCED);
}
/* This thread will never run again */
- reschedule(PS_DEAD);
PANIC();
+
+}
+
+/*----------------------------------------------------------------------
+ * Function: __pthread_is_valid
+ * Purpose: Scan the list of threads to see if a specified thread exists
+ * Args:
+ * pthread = The thread to scan for
+ * Returns:
+ * int = 1 if found, 0 if not
+ * Notes:
+ * The kernel is assumed to be locked
+ *----------------------------------------------------------------------*/
+int
+__pthread_is_valid( pthread_t pthread )
+{
+ int rtn = 0; /* Assume not found */
+ pthread_t t;
+
+ for( t = pthread_link_list; t; t = t->pll ) {
+ if( t == pthread ) {
+ rtn = 1; /* Found it */
+ break;
+ }
+ }
+
+ return rtn;
+}
+
+/* ==========================================================================
+ * __pthread_free()
+ */
+static inline void __pthread_free(pthread_t new_thread)
+{
+ pthread_sched_prevent();
+ new_thread->state = PS_UNALLOCED;
+ new_thread->attr.stacksize_attr = 0;
+ new_thread->attr.stackaddr_attr = NULL;
+ pthread_queue_enq(&pthread_alloc_queue, new_thread);
+ pthread_sched_resume();
+}
+/* ==========================================================================
+ * __pthread_alloc()
+ */
+/* static inline pthread_t __pthread_alloc(const pthread_attr_t *attr) */
+static pthread_t __pthread_alloc(const pthread_attr_t *attr)
+{
+ pthread_t thread;
+ void * stack;
+ void * old;
+
+ pthread_sched_prevent();
+ thread = pthread_queue_deq(&pthread_alloc_queue);
+ pthread_sched_resume();
+
+ if (thread) {
+ if (stack = attr->stackaddr_attr) {
+ __machdep_stack_repl(&(thread->machdep_data), stack);
+ } else {
+ if ((__machdep_stack_get(&(thread->machdep_data)) == NULL)
+ || (attr->stacksize_attr > thread->attr.stacksize_attr)) {
+ if (stack = __machdep_stack_alloc(attr->stacksize_attr)) {
+ __machdep_stack_repl(&(thread->machdep_data), stack);
+ } else {
+ __pthread_free(thread);
+ thread = NULL;
+ }
+ }
+ }
+ } else {
+ /* We should probable allocate several for efficiency */
+ if (thread = (pthread_t)malloc(sizeof(struct pthread))) {
+ /* Link new thread into list of all threads */
+
+ pthread_sched_prevent();
+ thread->state = PS_UNALLOCED;
+ thread->pll = pthread_link_list;
+ pthread_link_list = thread;
+ pthread_sched_resume();
+
+ if ((stack = attr->stackaddr_attr) ||
+ (stack = __machdep_stack_alloc(attr->stacksize_attr))) {
+ __machdep_stack_set(&(thread->machdep_data), stack);
+ } else {
+ __machdep_stack_set(&(thread->machdep_data), NULL);
+ __pthread_free(thread);
+ thread = NULL;
+ }
+ }
+ }
+ return(thread);
}
/* ==========================================================================
@@ -159,46 +229,65 @@ void pthread_exit(void *status)
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void * (*start_routine)(void *), void *arg)
{
- long nsec = 100000000;
- void *stack;
-
- if ((*thread) = (pthread_t)malloc(sizeof(struct pthread))) {
-
- if (! attr) { attr = &pthread_default_attr; }
-
- /* Get a stack, if necessary */
- if ((stack = attr->stackaddr_attr) ||
- (stack = (void *)malloc(attr->stacksize_attr))) {
-
- machdep_pthread_create(&((*thread)->machdep_data),
- start_routine, arg, 65536, stack, nsec);
-
- memcpy(&(*thread)->attr, attr, sizeof(pthread_attr_t));
-
- (*thread)->queue = NULL;
- (*thread)->next = NULL;
-
- (*thread)->lock = SEMAPHORE_CLEAR;
- (*thread)->error = 0;
-
- sig_prevent();
-
- /* Add to the link list of all threads. */
- (*thread)->pll = pthread_link_list;
- pthread_link_list = (*thread);
-
- (*thread)->state = PS_RUNNING;
- sig_check_and_resume();
+ pthread_t new_thread;
+ int nsec = 100000000;
+ int retval = OK;
+
+ if (! attr)
+ attr = &pthread_attr_default;
+
+ if (new_thread = __pthread_alloc(attr)) {
+
+ __machdep_pthread_create(&(new_thread->machdep_data),
+ start_routine, arg, attr->stacksize_attr, nsec, 0);
+
+ memcpy(&new_thread->attr, attr, sizeof(pthread_attr_t));
+ if (new_thread->attr.flags & PTHREAD_INHERIT_SCHED) {
+ new_thread->pthread_priority = pthread_run->pthread_priority;
+ new_thread->attr.sched_priority = pthread_run->pthread_priority;
+ new_thread->attr.schedparam_policy =
+ pthread_run->attr.schedparam_policy;
+ } else {
+ new_thread->pthread_priority = new_thread->attr.sched_priority;
+ }
- return(OK);
+ if (!(new_thread->attr.flags & PTHREAD_NOFLOAT)) {
+ machdep_save_float_state(new_thread);
}
- free((*thread));
+
+ /* Initialize signalmask */
+ new_thread->sigmask = pthread_run->sigmask;
+ sigemptyset(&(new_thread->sigpending));
+ new_thread->sigcount = 0;
+
+ pthread_queue_init(&(new_thread->join_queue));
+ new_thread->specific_data = NULL;
+ new_thread->specific_data_count = 0;
+ new_thread->cleanup = NULL;
+ new_thread->queue = NULL;
+ new_thread->next = NULL;
+ new_thread->flags = 0;
+
+ /* PTHREADS spec says we start with cancellability on and deferred */
+ SET_PF_CANCEL_STATE(new_thread, PTHREAD_CANCEL_ENABLE);
+ SET_PF_CANCEL_TYPE(new_thread, PTHREAD_CANCEL_DEFERRED);
+
+ new_thread->error_p = NULL;
+ new_thread->sll = NULL;
+
+ pthread_sched_prevent();
+
+
+ pthread_sched_other_resume(new_thread);
+ /*
+ * Assignment must be outside of the locked pthread kernel incase
+ * thread is a bogus address resulting in a seg-fault. We want the
+ * original thread to be capable of handling the resulting signal.
+ * --proven
+ */
+ (*thread) = new_thread;
+ } else {
+ retval = EAGAIN;
}
- return(ENOMEM);
+ return(retval);
}
-
-/* ==========================================================================
- * pthread_cancel()
- *
- * This routine will also require a sig_prevent/sig_check_and_resume()
- */
diff --git a/lib/libpthread/pthreads/pthread_attr.c b/lib/libpthread/pthreads/pthread_attr.c
index 8efdf32b4f6..397c1fe115c 100644
--- a/lib/libpthread/pthreads/pthread_attr.c
+++ b/lib/libpthread/pthreads/pthread_attr.c
@@ -36,11 +36,12 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: pthread_attr.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread_attr.c,v 1.16 1994/02/07 02:19:14 proven Exp $";
+static const char rcsid[] = "$Id: pthread_attr.c,v 1.1.1.2 1998/07/21 13:20:12 peter Exp $";
#endif
#include <pthread.h>
#include <errno.h>
+#include <string.h>
/* Currently we do no locking, should we just to be safe? CAP */
/* ==========================================================================
@@ -48,7 +49,7 @@ static const char rcsid[] = "$Id: pthread_attr.c,v 1.1.1.1 1995/10/18 08:43:05 d
*/
int pthread_attr_init(pthread_attr_t *attr)
{
- memcpy(attr, &pthread_default_attr, sizeof(pthread_attr_t));
+ memcpy(attr, &pthread_attr_default, sizeof(pthread_attr_t));
return(OK);
}
@@ -98,3 +99,157 @@ int pthread_attr_setstackaddr(pthread_attr_t *attr, void * stackaddr)
attr->stackaddr_attr = stackaddr;
return(OK);
}
+
+/* ==========================================================================
+ * pthread_attr_setcleanup()
+ */
+int pthread_attr_setcleanup(pthread_attr_t *attr, void (*routine)(void *),
+ void * arg)
+{
+ attr->cleanup_attr = routine;
+ attr->arg_attr = arg;
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_getdetachstate()
+ */
+int pthread_attr_getdetachstate(pthread_attr_t *attr, int * detachstate)
+{
+ *detachstate = attr->flags & PTHREAD_DETACHED;
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_setdetachstate()
+ */
+int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
+{
+ attr->flags = (attr->flags & ~(PTHREAD_DETACHED)) |
+ (detachstate & PTHREAD_DETACHED);
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_getfloatstate()
+ */
+int pthread_attr_getfloatstate(pthread_attr_t *attr, int * floatstate)
+{
+ *floatstate = attr->flags & PTHREAD_NOFLOAT;
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_setfloatstate()
+ */
+int pthread_attr_setfloatstate(pthread_attr_t *attr, int floatstate)
+{
+ attr->flags = (attr->flags & ~(PTHREAD_NOFLOAT)) |
+ (floatstate & PTHREAD_NOFLOAT);
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_getscope()
+ */
+int pthread_attr_getscope(pthread_attr_t *attr, int * contentionscope)
+{
+ *contentionscope = attr->flags & PTHREAD_SCOPE_SYSTEM;
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_setscope()
+ */
+int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
+{
+ int ret;
+
+ switch (contentionscope) {
+ case PTHREAD_SCOPE_PROCESS:
+ attr->flags = (attr->flags & ~(PTHREAD_SCOPE_PROCESS))
+ | PTHREAD_SCOPE_PROCESS;
+ ret = OK;
+ break;
+ case PTHREAD_SCOPE_SYSTEM:
+ ret = ENOSYS;
+ break;
+ default:
+ ret = EINVAL;
+ break;
+ }
+
+ return(ret);
+}
+
+/* ==========================================================================
+ * pthread_attr_getinheritsched()
+ */
+int pthread_attr_getinheritsched(pthread_attr_t *attr, int * inheritsched)
+{
+ *inheritsched = attr->flags & PTHREAD_INHERIT_SCHED;
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_setinheritsched()
+ */
+int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched)
+{
+ attr->flags = (attr->flags & ~(PTHREAD_INHERIT_SCHED)) |
+ (inheritsched & PTHREAD_INHERIT_SCHED);
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_getschedpolicy()
+ */
+int pthread_attr_getschedpolicy(pthread_attr_t *attr, int * schedpolicy)
+{
+ *schedpolicy = (int)attr->schedparam_policy;
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_setschedpolicy()
+ */
+int pthread_attr_setschedpolicy(pthread_attr_t *attr, int schedpolicy)
+{
+ int ret;
+
+ switch(schedpolicy) {
+ case SCHED_FIFO:
+ case SCHED_IO:
+ case SCHED_RR:
+ attr->schedparam_policy = schedpolicy;
+ ret = OK;
+ break;
+ default:
+ ret = EINVAL;
+ break;
+ }
+ return(ret);
+}
+
+/* ==========================================================================
+ * pthread_attr_getschedparam()
+ */
+int pthread_attr_getschedparam(pthread_attr_t *attr, struct sched_param * param)
+{
+ param->sched_priority = attr->sched_priority;
+ return(OK);
+}
+
+/* ==========================================================================
+ * pthread_attr_setschedparam()
+ */
+int pthread_attr_setschedparam(pthread_attr_t *attr, struct sched_param * param)
+{
+ if ((param->sched_priority >= PTHREAD_MIN_PRIORITY) &&
+ (param->sched_priority <= PTHREAD_MAX_PRIORITY)) {
+ attr->sched_priority = param->sched_priority;
+ return(OK);
+ }
+ return(EINVAL);
+}
+
diff --git a/lib/libpthread/pthreads/pthread_detach.c b/lib/libpthread/pthreads/pthread_detach.c
index 733fa45436e..1aa2656ac77 100644
--- a/lib/libpthread/pthreads/pthread_detach.c
+++ b/lib/libpthread/pthreads/pthread_detach.c
@@ -36,9 +36,10 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: pthread_detach.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread_detach.c,v 1.16 1994/02/07 02:19:16 proven Exp $";
+static const char rcsid[] = "$Id: pthread_detach.c,v 1.1.1.2 1998/07/21 13:20:14 peter Exp $";
#endif
+#include <errno.h>
#include <pthread.h>
/* ==========================================================================
@@ -46,45 +47,46 @@ static const char rcsid[] = "$Id: pthread_detach.c,v 1.1.1.1 1995/10/18 08:43:05
*/
int pthread_detach(pthread_t pthread)
{
- semaphore *plock;
+ struct pthread * next_thread, * high_thread, * low_thread;
int ret;
- plock = &(pthread->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+ pthread_sched_prevent();
/* Check that thread isn't detached already */
- if (!(pthread->flags & PF_DETACHED)) {
-
- pthread->flags |= PF_DETACHED;
+ if (!(pthread->attr.flags & PTHREAD_DETACHED)) {
- /* Wakeup first threads waiting on a join */
- {
- struct pthread * next_thread;
- semaphore * next_lock;
+ pthread->attr.flags |= PTHREAD_DETACHED;
- if (next_thread = pthread_queue_get(&(pthread->join_queue))) {
- next_lock = &(next_thread->lock);
- while (SEMAPHORE_TEST_AND_SET(next_lock)) {
- pthread_yield();
+ /* Wakeup all threads waiting on a join */
+ if (next_thread = pthread_queue_deq(&(pthread->join_queue))) {
+ high_thread = next_thread;
+
+ while (next_thread = pthread_queue_deq(&(pthread->join_queue))) {
+ if (high_thread->pthread_priority < next_thread->pthread_priority) {
+ low_thread = high_thread;
+ high_thread = next_thread;
+ } else {
+ low_thread = next_thread;
}
- pthread_queue_deq(&(pthread->join_queue));
- next_thread->state = PS_RUNNING;
- /*
- * Thread will wake up in pthread_join(), see the thread
- * it was joined to already detached and unlock itself
- * and pthread
- */
- } else {
- SEMAPHORE_RESET(plock);
+ pthread_prio_queue_enq(pthread_current_prio_queue, low_thread);
+ low_thread->state = PS_RUNNING;
+ }
+ /* If the thread is dead then move it to the alloc queue */
+ if (pthread_queue_remove(&pthread_dead_queue, pthread) == OK) {
+ pthread_queue_enq(&pthread_alloc_queue, pthread);
}
+ pthread_sched_other_resume(high_thread);
+ return(OK);
+ }
+ /* If the thread is dead then move it to the alloc queue */
+ if (pthread_queue_remove(&pthread_dead_queue, pthread) == OK) {
+ pthread_queue_enq(&pthread_alloc_queue, pthread);
+ pthread->state = PS_UNALLOCED;
}
ret = OK;
-
} else {
- SEMAPHORE_RESET(plock);
ret = ESRCH;
}
+ pthread_sched_resume();
return(ret);
}
diff --git a/lib/libpthread/pthreads/pthread_join.c b/lib/libpthread/pthreads/pthread_join.c
index a1dbdefc1d4..f0e503510aa 100644
--- a/lib/libpthread/pthreads/pthread_join.c
+++ b/lib/libpthread/pthreads/pthread_join.c
@@ -36,78 +36,104 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: pthread_join.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread_join.c,v 1.16 1994/02/07 02:19:19 proven Exp $";
+static const char rcsid[] = "$Id: pthread_join.c,v 1.1.1.2 1998/07/21 13:20:16 peter Exp $";
#endif
#include <pthread.h>
+#include <errno.h>
+
+static int testDeadlock( struct pthread_queue *queue, pthread_t target );
/* ==========================================================================
* pthread_join()
*/
int pthread_join(pthread_t pthread, void **thread_return)
{
- semaphore *lock, *plock;
int ret;
+ pthread_sched_prevent();
- plock = &(pthread->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+ /* Ensure they gave us a legal pthread pointer */
+ if( ! __pthread_is_valid( pthread ) ) {
+ pthread_sched_resume();
+ return(EINVAL);
+ }
/* Check that thread isn't detached already */
- if (pthread->flags & PF_DETACHED) {
- SEMAPHORE_RESET(plock);
+ if (pthread->attr.flags & PTHREAD_DETACHED) {
+ pthread_sched_resume();
return(ESRCH);
}
- lock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ /*
+ * Now check if other thread has exited
+ * Note: This must happen after checking detached state.
+ */
+ if (pthread_queue_remove(&pthread_dead_queue, pthread) != OK) {
- /* If OK then queue current thread. */
- pthread_queue(&(pthread->join_queue), pthread_run);
+ /* Before we pend on the join, ensure there is no dead lock */
- SEMAPHORE_RESET(plock);
- reschedule(PS_JOIN);
+ if( testDeadlock( &pthread_run->join_queue, pthread ) == NOTOK ) {
+ ret = EDEADLK;
+ } else {
+ pthread_queue_enq(&(pthread->join_queue), pthread_run);
+ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ pthread_resched_resume(PS_JOIN);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+ pthread_sched_prevent();
- /*
- * At this point the thread is locked from the pthread_exit
- * and so are we, so no extra locking is required, but be sure
- * to unlock at least ourself.
- */
- if (!(pthread->flags & PF_DETACHED)) {
- if (thread_return) {
- *thread_return = pthread->ret;
+ if (pthread_queue_remove(&pthread_dead_queue, pthread) == OK) {
+ pthread_queue_enq(&pthread_alloc_queue, pthread);
+ pthread->attr.flags |= PTHREAD_DETACHED;
+ pthread->state = PS_UNALLOCED;
+ if (thread_return) {
+ *thread_return = pthread->ret;
+ }
+ ret = OK;
+ } else {
+ ret = ESRCH;
+ }
}
- pthread->flags |= PF_DETACHED;
+ } else {
+ /* Just get the return value and detach the thread */
+ pthread_queue_enq(&pthread_alloc_queue, pthread);
+ pthread->attr.flags |= PTHREAD_DETACHED;
+ pthread->state = PS_UNALLOCED;
+ if (thread_return) {
+ *thread_return = pthread->ret;
+ }
ret = OK;
- } else {
- ret = ESRCH;
}
+ pthread_sched_resume();
+ return(ret);
+}
+
+/*----------------------------------------------------------------------
+ * Function: testDeadlock
+ * Purpose: recursive queue walk to check for deadlocks
+ * Args:
+ * queue = the queue to walk
+ * pthread = target to scan for
+ * Returns:
+ * OK = no deadlock, NOTOK = deadlock
+ * Notes:
+ *----------------------------------------------------------------------*/
+static int
+testDeadlock( struct pthread_queue *queue, pthread_t target )
+{
+ pthread_t t;
- /* Cant do a cleanup until queue is cleared */
- {
- struct pthread * next_thread;
- semaphore * next_lock;
+ if( queue == NULL )
+ return OK; /* Empty queue, obviously ok */
- if (next_thread = pthread_queue_get(&(pthread->join_queue))) {
- next_lock = &(next_thread->lock);
- while (SEMAPHORE_TEST_AND_SET(next_lock)) {
- pthread_yield();
- }
- pthread_queue_deq(&(pthread->join_queue));
- next_thread->state = PS_RUNNING;
- /*
- * Thread will wake up in pthread_join(), see the thread
- * it was joined to already detached and unlock itself
- */
- } else {
- SEMAPHORE_RESET(lock);
+ for( t = queue->q_next; t; t = t->next ) {
+ if( t == target )
+ return NOTOK; /* bang, your dead */
+
+ if( testDeadlock( &t->join_queue, target ) == NOTOK ) {
+ return NOTOK;
}
}
- SEMAPHORE_RESET(plock);
- return(ret);
+ return OK; /* No deadlock */
}
diff --git a/lib/libpthread/pthreads/pthread_once.c b/lib/libpthread/pthreads/pthread_once.c
index 0510635c66c..b654d221ee9 100644
--- a/lib/libpthread/pthreads/pthread_once.c
+++ b/lib/libpthread/pthreads/pthread_once.c
@@ -36,7 +36,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: pthread_once.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: pthread_once.c,v 1.4 1994/02/07 02:19:22 proven Exp $";
+static const char rcsid[] = "$Id: pthread_once.c,v 1.1.1.2 1998/07/21 13:20:18 peter Exp $";
#endif
#include <pthread.h>
@@ -44,18 +44,16 @@ static const char rcsid[] = "$Id: pthread_once.c,v 1.1.1.1 1995/10/18 08:43:05 d
/* ==========================================================================
* pthread_once()
*/
-static pthread_mutex_t __pthread_once_mutex = PTHREAD_MUTEX_INITIALIZER;
-
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
/* Check first for speed */
- if (*once_control == PTHREAD_ONCE_INIT) {
- pthread_mutex_lock(&__pthread_once_mutex);
- if (*once_control == PTHREAD_ONCE_INIT) {
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ pthread_mutex_lock(&(once_control->mutex));
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
init_routine();
- (*once_control)++;
+ once_control->state = PTHREAD_DONE_INIT;
}
- pthread_mutex_unlock(&__pthread_once_mutex);
+ pthread_mutex_unlock(&(once_control->mutex));
}
return(OK);
}
diff --git a/lib/libpthread/pthreads/queue.c b/lib/libpthread/pthreads/queue.c
index fb3b76f0346..80d7845c4d8 100644
--- a/lib/libpthread/pthreads/queue.c
+++ b/lib/libpthread/pthreads/queue.c
@@ -36,7 +36,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: queue.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: queue.c,v 1.16 1994/02/07 02:19:24 proven Exp $";
+static const char rcsid[] = "$Id: queue.c,v 1.1.1.2 1998/07/21 13:20:20 peter Exp $";
#endif
#include <pthread.h>
@@ -101,10 +101,11 @@ struct pthread *pthread_queue_deq(struct pthread_queue *queue)
/* ==========================================================================
* pthread_queue_remove()
*/
-void pthread_queue_remove(struct pthread_queue *queue, struct pthread *thread)
+int pthread_queue_remove(struct pthread_queue *queue, struct pthread *thread)
{
struct pthread **current = &(queue->q_next);
struct pthread *prev = NULL;
+ int ret = NOTOK;
while (*current) {
if (*current == thread) {
@@ -114,10 +115,29 @@ void pthread_queue_remove(struct pthread_queue *queue, struct pthread *thread)
queue->q_last = prev;
*current = NULL;
}
+ thread->queue = NULL;
+ thread->next = NULL;
+ ret = OK;
+ break;
}
prev = *current;
current = &((*current)->next);
}
- thread->queue = NULL;
- thread->next = NULL;
+ return(ret);
}
+
+/* ==========================================================================
+ * pthread_llist_remove()
+ */
+int pthread_llist_remove(struct pthread **llist, struct pthread *thread)
+{
+ while (*llist) {
+ if (*llist == thread) {
+ *llist = thread->next;
+ return(OK);
+ }
+ llist = &(*llist)->next;
+ }
+ return(NOTOK);
+}
+
diff --git a/lib/libpthread/pthreads/signal.c b/lib/libpthread/pthreads/signal.c
index fb621b826f0..9f96607b4e7 100644
--- a/lib/libpthread/pthreads/signal.c
+++ b/lib/libpthread/pthreads/signal.c
@@ -36,11 +36,20 @@
*/
#ifndef lint
-static const char rcsid[] = "$Id: signal.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: signal.c,v 1.18 1994/02/07 02:19:28 proven Exp $";
+static const char rcsid[] = "$Id: signal.c,v 1.1.1.2 1998/07/21 13:20:22 peter Exp $";
#endif
#include <pthread.h>
#include <signal.h>
+#include <config.h>
+
+/* This will force init.o to get dragged in; if you've got support for
+ C++ initialization, that'll cause pthread_init to be called at
+ program startup automatically, so the application won't need to
+ call it explicitly. */
+
+extern char __pthread_init_hack;
+char *__pthread_init_hack_2 = &__pthread_init_hack;
/*
* Time which select in fd_kern_wait() will sleep.
@@ -54,13 +63,16 @@ struct timeval __fd_kern_wait_timeout = { 0, 0 };
/*
* Global for user-kernel lock, and blocked signals
*/
-static volatile sigset_t sig_to_tryagain;
-static volatile sigset_t sig_to_process;
-static volatile int kernel_lock = 0;
+
+static sig_atomic_t signum_to_process[SIGMAX + 1] = { 0, };
+volatile sig_atomic_t sig_to_process = 0;
+
+/* static volatile sigset_t sig_to_process; */
static volatile int sig_count = 0;
static void sig_handler(int signal);
static void set_thread_timer();
+static void __cleanup_after_resume( void );
void sig_prevent(void);
void sig_resume(void);
@@ -75,99 +87,101 @@ void sig_resume(void);
*/
static void context_switch()
{
- struct pthread **current, *next, *last;
- semaphore *lock;
- int count;
+ struct pthread **current, *next, *last, **dead;
+
+ if (pthread_run->state == PS_RUNNING) {
+ /* Put current thread back on the queue */
+ pthread_prio_queue_enq(pthread_current_prio_queue, pthread_run);
+ }
+ /* save floating point registers if necessary */
+ if (!(pthread_run->attr.flags & PTHREAD_NOFLOAT)) {
+ machdep_save_float_state(pthread_run);
+ }
/* save state of current thread */
if (machdep_save_state()) {
return;
}
last = pthread_run;
- if (pthread_run = pthread_queue_deq(&pthread_current_queue)) {
- /* restore state of new current thread */
- machdep_restore_state();
- return;
- }
- /* Poll all the kernel fds */
+ /* Poll all fds */
fd_kern_poll();
context_switch_reschedule:;
- /*
- * Go through the reschedule list once, this is the only place
- * that goes through the queue without using the queue routines.
- *
- * But first delete the current queue.
- */
- pthread_queue_init(&pthread_current_queue);
- current = &(pthread_link_list);
- count = 0;
-
- while (*current) {
- switch((*current)->state) {
- case PS_RUNNING:
- pthread_queue_enq(&pthread_current_queue, *current);
- current = &((*current)->pll);
- count++;
- break;
- case PS_DEAD:
- /* Cleanup thread, unless we're using the stack */
- if (((*current)->flags & PF_DETACHED) && (*current != last)) {
- next = (*current)->pll;
- lock = &((*current)->lock);
- if (SEMAPHORE_TEST_AND_SET(lock)) {
- /* Couldn't cleanup this time, try again later */
- current = &((*current)->pll);
- } else {
- if (!((*current)->attr.stackaddr_attr)) {
- free (machdep_pthread_cleanup(&((*current)->machdep_data)));
- }
- free (*current);
- *current = next;
- }
- } else {
- current = &((*current)->pll);
- }
- break;
- default:
- /* Should be on a different queue. Ignore. */
- current = &((*current)->pll);
- count++;
- break;
- }
- }
-
/* Are there any threads to run */
- if (pthread_run = pthread_queue_deq(&pthread_current_queue)) {
- /* restore state of new current thread */
+ if (pthread_run = pthread_prio_queue_deq(pthread_current_prio_queue)) {
+ /* restore floating point registers if necessary */
+ if (!(pthread_run->attr.flags & PTHREAD_NOFLOAT)) {
+ machdep_restore_float_state();
+ }
+ uthread_sigmask = &(pthread_run->sigmask);
+ /* restore state of new current thread */
machdep_restore_state();
- return;
- }
+ return;
+ }
/* Are there any threads at all */
- if (count) {
- /*
- * Do a wait, timeout is set to a hour unless we get an interrupt
- * before the select in wich case it polls and returns.
- */
- fd_kern_wait();
-
- /* Check for interrupts, but ignore SIGVTALR */
- sigdelset(&sig_to_process, SIGVTALRM);
-
- if (sig_to_process) {
- /* Process interrupts */
- sig_handler(0);
+ for (next = pthread_link_list; next; next = next->pll) {
+ if ((next->state != PS_UNALLOCED) && (next->state != PS_DEAD)) {
+ sigset_t sig_to_block, oset;
+
+ sigfillset(&sig_to_block);
+
+ /*
+ * Check sig_to_process before calling fd_kern_wait, to handle
+ * things like zero timeouts to select() which would register
+ * a signal with the sig_handler_fake() call.
+ *
+ * This case should ignore SIGVTALRM
+ */
+ machdep_sys_sigprocmask(SIG_BLOCK, &sig_to_block, &oset);
+ signum_to_process[SIGVTALRM] = 0;
+ if (sig_to_process) {
+ /* Process interrupts */
+ /*
+ * XXX pthread_run should not be set!
+ * Places where it dumps core should be fixed to
+ * check for the existance of pthread_run --proven
+ */
+ sig_handler(0);
+ } else {
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
+ /*
+ * Do a wait, timeout is set to a hour unless we get an
+ * intr. before the select in wich case it polls.
+ */
+ fd_kern_wait();
+ machdep_sys_sigprocmask(SIG_BLOCK, &sig_to_block, &oset);
+ /* Check for interrupts, but ignore SIGVTALR */
+ signum_to_process[SIGVTALRM] = 0;
+ if (sig_to_process) {
+ /* Process interrupts */
+ sig_handler(0);
+ }
+ }
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
+ goto context_switch_reschedule;
}
-
- goto context_switch_reschedule;
-
}
+
+ /* There are no threads alive. */
+ pthread_run = last;
exit(0);
}
+#if !defined(HAVE_SYSCALL_SIGSUSPEND) && defined(HAVE_SYSCALL_SIGPAUSE)
+
+/* ==========================================================================
+ * machdep_sys_sigsuspend()
+ */
+int machdep_sys_sigsuspend(sigset_t * set)
+{
+ return(machdep_sys_sigpause(* set));
+}
+
+#endif
+
/* ==========================================================================
* sig_handler_pause()
*
@@ -175,15 +189,16 @@ context_switch_reschedule:;
*/
void sig_handler_pause()
{
- sigset_t sig_to_block, sig_to_pause;
+ sigset_t sig_to_block, sig_to_pause, oset;
sigfillset(&sig_to_block);
sigemptyset(&sig_to_pause);
- sigprocmask(SIG_BLOCK, &sig_to_block, NULL);
+ machdep_sys_sigprocmask(SIG_BLOCK, &sig_to_block, &oset);
+/* if (!(SIG_ANY(sig_to_process))) { */
if (!sig_to_process) {
- sigsuspend(&sig_to_pause);
+ machdep_sys_sigsuspend(&sig_to_pause);
}
- sigprocmask(SIG_UNBLOCK, &sig_to_block, NULL);
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
}
/* ==========================================================================
@@ -198,7 +213,8 @@ void sig_handler_pause()
*/
void context_switch_done()
{
- sigdelset(&sig_to_process, SIGVTALRM);
+ /* sigdelset((sigset_t *)&sig_to_process, SIGVTALRM); */
+ signum_to_process[SIGVTALRM] = 0;
set_thread_timer();
}
@@ -211,13 +227,13 @@ static void set_thread_timer()
{
static int last_sched_attr = SCHED_RR;
- switch (pthread_run->attr.sched_attr) {
+ switch (pthread_run->attr.schedparam_policy) {
case SCHED_RR:
machdep_set_thread_timer(&(pthread_run->machdep_data));
break;
case SCHED_FIFO:
if (last_sched_attr != SCHED_FIFO) {
- machdep_unset_thread_timer();
+ machdep_unset_thread_timer(NULL);
}
break;
case SCHED_IO:
@@ -229,90 +245,158 @@ static void set_thread_timer()
machdep_set_thread_timer(&(pthread_run->machdep_data));
break;
}
- last_sched_attr = pthread_run->attr.sched_attr;
+ last_sched_attr = pthread_run->attr.schedparam_policy;
}
/* ==========================================================================
- * sig_handler()
- *
- * Assumes the kernel is locked.
+ * sigvtalrm()
*/
-static void sig_handler(int sig)
+static inline void sigvtalrm()
{
+ if (sig_count) {
+ sigset_t sigall, oset;
- /*
- * First check for old signals, do one pass through and don't
- * check any twice.
- */
- if (sig_to_tryagain) {
- if (sigismember(&sig_to_tryagain, SIGALRM)) {
- switch (sleep_wakeup()) {
- case 1:
- /* Do the default action, no threads were sleeping */
- case OK:
- /* Woke up a sleeping thread */
- sigdelset(&sig_to_tryagain, SIGALRM);
+ sig_count = 0;
+
+ /* Unblock all signals */
+ sigemptyset(&sigall);
+ machdep_sys_sigprocmask(SIG_SETMASK, &sigall, &oset);
+ }
+ context_switch();
+ context_switch_done();
+}
+
+/* ==========================================================================
+ * sigdefault()
+ */
+static inline void sigdefault(int sig)
+{
+ int ret;
+
+ ret = pthread_sig_register(sig);
+ if (pthread_run && (ret > pthread_run->pthread_priority)) {
+ sigvtalrm();
+ }
+}
+
+/* ==========================================================================
+ * sig_handler_switch()
+ */
+static inline void sig_handler_switch(int sig)
+{
+ int ret;
+
+ switch(sig) {
+ case 0:
break;
- case NOTOK:
- /* Couldn't get appropriate locks, try again later */
+ case SIGVTALRM:
+ sigvtalrm();
break;
- }
- } else {
- PANIC();
+ case SIGALRM:
+/* sigdelset((sigset_t *)&sig_to_process, SIGALRM); */
+ signum_to_process[SIGALRM] = 0;
+ switch (ret = sleep_wakeup()) {
+ default:
+ if (pthread_run && (ret > pthread_run->pthread_priority)) {
+ sigvtalrm();
+ }
+ case 0:
+ break;
+ case NOTOK:
+ /* Do the registered action, no threads were sleeping */
+ /* There is a timing window that gets
+ * here when no threads are on the
+ * sleep queue. This is a quick fix.
+ * The real problem is possibly related
+ * to heavy use of condition variables
+ * with time outs.
+ * (mevans)
+ *sigdefault(sig);
+ */
+ break;
+ }
+ break;
+ case SIGCHLD:
+/* sigdelset((sigset_t *)&sig_to_process, SIGCHLD); */
+ signum_to_process[SIGCHLD] = 0;
+ switch (ret = wait_wakeup()) {
+ default:
+ if (pthread_run && (ret > pthread_run->pthread_priority)) {
+ sigvtalrm();
+ }
+ case 0:
+ break;
+ case NOTOK:
+ /* Do the registered action, no threads were waiting */
+ sigdefault(sig);
+ break;
+ }
+ break;
+
+#ifdef SIGINFO
+ case SIGINFO:
+ pthread_dump_info ();
+ /* Then fall through, invoking the application's
+ signal handler after printing our info out.
+
+ I'm not convinced that this is right, but I'm not
+ 100% convinced that it is wrong, and this is how
+ Chris wants it done... */
+#endif
+
+ default:
+ /* Do the registered action */
+ if (!sigismember(uthread_sigmask, sig)) {
+ /*
+ * If the signal isn't masked by the last running thread and
+ * the signal behavior is default or ignore then we can
+ * execute it immediatly. --proven
+ */
+ pthread_sig_default(sig);
}
+ signum_to_process[sig] = 0;
+ sigdefault(sig);
+ break;
}
-
- /*
- * NOW, process signal that just came in, plus any pending on the
- * signal mask. All of these must be resolved.
- */
-sig_handler_top:;
+}
- switch(sig) {
- case 0:
- break;
- case SIGVTALRM:
- if (sig_count) {
- sigset_t sigall;
+/* ==========================================================================
+ * sig_handler()
+ *
+ * Process signal that just came in, plus any pending on the signal mask.
+ * All of these must be resolved.
+ *
+ * Assumes the kernel is locked.
+ */
+static void sig_handler(int sig)
+{
+ if (pthread_kernel_lock != 1) {
+ PANIC();
+ }
- sig_count = 0;
+ if (sig) {
+ sig_handler_switch(sig);
+ }
- /* Unblock all signals */
- sigemptyset(&sigall);
- sigprocmask(SIG_SETMASK, &sigall, NULL);
+ while (sig_to_process) {
+ for (sig_to_process = 0, sig = 1; sig <= SIGMAX; sig++) {
+ if (signum_to_process[sig]) {
+ sig_handler_switch(sig);
+ }
}
- context_switch();
- context_switch_done();
- break;
- case SIGALRM:
- sigdelset(&sig_to_process, SIGALRM);
- switch (sleep_wakeup()) {
- case 1:
- /* Do the default action, no threads were sleeping */
- case OK:
- /* Woke up a sleeping thread */
- break;
- case NOTOK:
- /* Couldn't get appropriate locks, try again later */
- sigaddset(&sig_to_tryagain, SIGALRM);
- break;
- }
- break;
- default:
- PANIC();
}
- /* Determine if there are any other signals */
- if (sig_to_process) {
- for (sig = 1; sig <= SIGMAX; sig++) {
- if (sigismember(&sig_to_process, sig)) {
- /* goto sig_handler_top */
+/*
+ if (SIG_ANY(sig_to_process)) {
+ for (sig = 1; sig <= SIGMAX; sig++) {
+ if (sigismember((sigset_t *)&sig_to_process, sig)) {
goto sig_handler_top;
}
}
}
+*/
}
/* ==========================================================================
@@ -323,15 +407,37 @@ sig_handler_top:;
*/
void sig_handler_real(int sig)
{
- if (kernel_lock) {
+ /*
+ * Get around systems with BROKEN signal handlers.
+ *
+ * Some systems will reissue SIGCHLD if the handler explicitly
+ * clear the signal pending by either doing a wait() or
+ * ignoring the signal.
+ */
+#if defined BROKEN_SIGNALS
+ if (sig == SIGCHLD) {
+ sigignore(SIGCHLD);
+ signal(SIGCHLD, sig_handler_real);
+ }
+#endif
+
+ if (pthread_kernel_lock) {
+ /* sigaddset((sigset_t *)&sig_to_process, sig); */
__fd_kern_wait_timeout.tv_sec = 0;
- sigaddset(&sig_to_process, sig);
+ signum_to_process[sig] = 1;
+ sig_to_process = 1;
return;
}
- sig_prevent();
+ pthread_kernel_lock++;
+
sig_count++;
sig_handler(sig);
- sig_resume();
+
+ /* Handle any signals the current thread might have just gotten */
+ if (pthread_run && pthread_run->sigcount) {
+ pthread_sig_process();
+ }
+ pthread_kernel_lock--;
}
/* ==========================================================================
@@ -339,73 +445,144 @@ void sig_handler_real(int sig)
*/
void sig_handler_fake(int sig)
{
- if (kernel_lock) {
- /* Currently this should be impossible */
- PANIC();
+ if (pthread_kernel_lock) {
+ /* sigaddset((sigset_t *)&sig_to_process, sig); */
+ signum_to_process[sig] = 1;
+ sig_to_process = 1;
+ return;
}
- sig_prevent();
+ pthread_kernel_lock++;
sig_handler(sig);
- sig_resume();
+ while (!(--pthread_kernel_lock)) {
+ if (sig_to_process) {
+ /* if (SIG_ANY(sig_to_process)) { */
+ pthread_kernel_lock++;
+ sig_handler(0);
+ } else {
+ break;
+ }
+ }
}
/* ==========================================================================
- * reschedule()
+ * __pthread_signal_delete(int sig)
*
- * This routine assumes that the caller is the current pthread, pthread_run
- * and that it has a lock on itself and that it wants to reschedule itself.
+ * Assumes the kernel is locked.
*/
-void reschedule(enum pthread_state state)
+void __pthread_signal_delete(int sig)
{
- semaphore *plock;
-
- if (kernel_lock) {
- /* Currently this should be impossible */
- PANIC();
- }
- sig_prevent();
- pthread_run->state = state;
- SEMAPHORE_RESET((plock = &(pthread_run->lock)));
- sig_handler(SIGVTALRM);
- sig_resume();
+ signum_to_process[sig] = 0;
}
/* ==========================================================================
- * sig_prevent()
+ * pthread_sched_other_resume()
+ *
+ * Check if thread to be resumed is of higher priority and if so
+ * stop current thread and start new thread.
*/
-void sig_prevent(void)
+pthread_sched_other_resume(struct pthread * pthread)
{
- kernel_lock++;
+ pthread->state = PS_RUNNING;
+ pthread_prio_queue_enq(pthread_current_prio_queue, pthread);
+
+ if (pthread->pthread_priority > pthread_run->pthread_priority) {
+ if (pthread_kernel_lock == 1) {
+ sig_handler(SIGVTALRM);
+ }
+ }
+
+ __cleanup_after_resume();
}
/* ==========================================================================
- * sig_resume()
+ * pthread_resched_resume()
+ *
+ * This routine assumes that the caller is the current pthread, pthread_run
+ * and that it has a lock the kernel thread and it wants to reschedule itself.
*/
-void sig_resume()
+void pthread_resched_resume(enum pthread_state state)
{
- kernel_lock--;
+ pthread_run->state = state;
+
+ /* Since we are about to block this thread, lets see if we are
+ * at a cancel point and if we've been cancelled.
+ * Avoid cancelling dead or unalloced threads.
+ */
+ if( ! TEST_PF_RUNNING_TO_CANCEL(pthread_run) &&
+ TEST_PTHREAD_IS_CANCELLABLE(pthread_run) &&
+ state != PS_DEAD && state != PS_UNALLOCED ) {
+
+ /* Set this flag to avoid recursively calling pthread_exit */
+ /* We have to set this flag here because we will unlock the
+ * kernel prior to calling pthread_cancel_internal.
+ */
+ SET_PF_RUNNING_TO_CANCEL(pthread_run);
+
+ pthread_run->old_state = state; /* unlock needs this data */
+ pthread_sched_resume(); /* Unlock kernel before cancel */
+ pthread_cancel_internal( 1 ); /* free locks and exit */
+ }
+
+ sig_handler(SIGVTALRM);
+
+ __cleanup_after_resume();
}
/* ==========================================================================
- * sig_check_and_resume()
+ * pthread_sched_resume()
*/
-void sig_check_and_resume()
+void pthread_sched_resume()
{
- /* Some routine name that is yet to be determined. */
-
- /* Only bother if we are truely unlocking the kernel */
- while (!(--kernel_lock)) {
+ __cleanup_after_resume();
+}
- /* Assume sigset_t is not a struct or union */
+/*----------------------------------------------------------------------
+ * Function: __cleanup_after_resume
+ * Purpose: cleanup kernel locks after a resume
+ * Args: void
+ * Returns: void
+ * Notes:
+ *----------------------------------------------------------------------*/
+static void
+__cleanup_after_resume( void )
+{
+ /* Only bother if we are truely unlocking the kernel */
+ while (!(--pthread_kernel_lock)) {
+ /* if (SIG_ANY(sig_to_process)) { */
if (sig_to_process) {
- kernel_lock++;
+ pthread_kernel_lock++;
sig_handler(0);
- } else {
- break;
+ continue;
+ }
+ if (pthread_run && pthread_run->sigcount) {
+ pthread_kernel_lock++;
+ pthread_sig_process();
+ continue;
}
+ break;
+ }
+
+ if( pthread_run == NULL )
+ return; /* Must be during init processing */
+
+ /* Test for cancel that should be handled now */
+
+ if( ! TEST_PF_RUNNING_TO_CANCEL(pthread_run) &&
+ TEST_PTHREAD_IS_CANCELLABLE(pthread_run) ) {
+ /* Kernel is already unlocked */
+ pthread_cancel_internal( 1 ); /* free locks and exit */
}
}
/* ==========================================================================
+ * pthread_sched_prevent()
+ */
+void pthread_sched_prevent(void)
+{
+ pthread_kernel_lock++;
+}
+
+/* ==========================================================================
* sig_init()
*
* SIGVTALRM (NOT POSIX) needed for thread timeslice timeouts.
@@ -414,32 +591,63 @@ void sig_check_and_resume()
* SIGALRM (IS POSIX) so some special handling will be
* necessary to fake SIGALRM signals
*/
+#ifndef SIGINFO
+#define SIGINFO 0
+#endif
void sig_init(void)
{
- int sig_to_init[] = { SIGVTALRM, SIGALRM, 0 };
+ static const int signum_to_initialize[] =
+ { SIGCHLD, SIGALRM, SIGVTALRM, SIGINFO, 0 };
+ static const int signum_to_ignore[] = { SIGKILL, SIGSTOP, 0 };
+ int i, j;
-#if defined(SA_RESTART)
+#if defined(HAVE_SYSCALL_SIGACTION) || defined(HAVE_SYSCALL_KSIGACTION)
struct sigaction act;
-#endif
-
- int i;
-#if defined(SA_RESTART)
act.sa_handler = sig_handler_real;
sigemptyset(&(act.sa_mask));
- act.sa_flags = SA_RESTART;
+ act.sa_flags = 0;
#endif
- /* Initialize only the necessary signals */
- for (i = 0; sig_to_init[i]; i++) {
+ /* Initialize the important signals */
+ for (i = 0; signum_to_initialize[i]; i++) {
-#if defined(SA_RESTART)
- if (sigaction(sig_to_init[i], &act, NULL)) {
+#if defined(HAVE_SYSCALL_SIGACTION) || defined(HAVE_SYSCALL_KSIGACTION)
+ if (sigaction(signum_to_initialize[i], &act, NULL)) {
#else
- if (signal(sig_to_init[i], sig_handler_real)) {
+ if (signal(signum_to_initialize[i], sig_handler_real)) {
#endif
PANIC();
}
}
+
+ /* Initialize the rest of the signals */
+ for (j = 1; j < SIGMAX; j++) {
+ for (i = 0; signum_to_initialize[i]; i++) {
+ if (signum_to_initialize[i] == j) {
+ goto sig_next;
+ }
+ }
+ /* Because Solaris 2.4 can't deal -- proven */
+ for (i = 0; signum_to_ignore[i]; i++) {
+ if (signum_to_ignore[i] == j) {
+ goto sig_next;
+ }
+ }
+ pthread_signal(j, SIG_DFL);
+
+#if defined(HAVE_SYSCALL_SIGACTION) || defined(HAVE_SYSCALL_KSIGACTION)
+ sigaction(j, &act, NULL);
+#else
+ signal(j, sig_handler_real);
+#endif
+
+ sig_next:;
+ }
+
+#if defined BROKEN_SIGNALS
+ signal(SIGCHLD, sig_handler_real);
+#endif
+
}
diff --git a/lib/libpthread/pthreads/sleep.c b/lib/libpthread/pthreads/sleep.c
index 865a8627516..0d18a8756c7 100644
--- a/lib/libpthread/pthreads/sleep.c
+++ b/lib/libpthread/pthreads/sleep.c
@@ -29,134 +29,265 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Description : Condition cariable functions.
+ * Description : All the appropriate sleep routines.
*
* 1.00 93/12/28 proven
* -Started coding this file.
+ *
+ * 1.36 94/06/04 proven
+ * -Use new timer structure pthread_timer, that uses seconds
+ * -nano seconds. Rewrite all routines completely.
+ *
+ * 1.38 94/06/13 proven
+ * -switch pthread_timer to timespec
*/
#ifndef lint
-static const char rcsid[] = "$Id: sleep.c,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $ $provenid: sleep.c,v 1.18 1994/02/07 02:19:31 proven Exp $";
+static const char rcsid[] = "$Id: sleep.c,v 1.1.1.2 1998/07/21 13:20:24 peter Exp $";
#endif
#include <pthread.h>
+#include <sys/time.h>
+#include <signal.h>
#include <unistd.h>
+#include <sys/compat.h>
struct pthread * pthread_sleep = NULL;
-semaphore sleep_semaphore = SEMAPHORE_CLEAR;
-
-
-#include <sys/time.h>
-#include <stdio.h>
/* ==========================================================================
- * machdep_start_timer()
+ * sleep_compare_time()
*/
-int machdep_start_timer(struct itimerval *start_time_val)
+/* static inline int sleep_compare_time(struct timespec * time1,
+ struct timespec * time2) */
+static int sleep_compare_time(struct timespec * time1, struct timespec * time2)
{
- setitimer(ITIMER_REAL, start_time_val, NULL);
- return(OK);
+ if ((time1->tv_sec < time2->tv_sec) ||
+ ((time1->tv_sec == time2->tv_sec) && (time1->tv_nsec < time2->tv_nsec))) {
+ return(-1);
+ }
+ if ((time1->tv_sec == time2->tv_sec) && (time1->tv_nsec == time2->tv_nsec)){
+ return(0);
+ }
+ return(1);
}
/* ==========================================================================
* machdep_stop_timer()
+ *
+ * Returns the time left on the timer.
+ */
+static struct itimerval timestop = { { 0, 0 }, { 0, 0 } };
+
+void machdep_stop_timer(struct timespec *current)
+{
+ struct itimerval timenow;
+
+ setitimer(ITIMER_REAL, & timestop, & timenow);
+ __pthread_signal_delete(SIGALRM);
+ if (current) {
+ current->tv_nsec = timenow.it_value.tv_usec * 1000;
+ current->tv_sec = timenow.it_value.tv_sec;
+ }
+}
+
+/* ==========================================================================
+ * machdep_start_timer()
*/
-struct itimerval stop_time_val = { { 0, 0 }, { 0, 0 } };
-int machdep_stop_timer(struct itimerval * current)
+int machdep_start_timer(struct timespec *current, struct timespec *wakeup)
{
- setitimer(ITIMER_REAL, &stop_time_val, current);
+ struct itimerval timeout;
+
+ timeout.it_value.tv_usec = (wakeup->tv_nsec - current->tv_nsec) / 1000;
+ timeout.it_value.tv_sec = wakeup->tv_sec - current->tv_sec;
+ timeout.it_interval.tv_usec = 0;
+ timeout.it_interval.tv_sec = 0;
+ if (timeout.it_value.tv_usec < 0) {
+ timeout.it_value.tv_usec += 1000000;
+ timeout.it_value.tv_sec--;
+ }
+
+ if ((!(timeout.it_value.tv_sec < 0)) &&
+ ((timeout.it_value.tv_usec) || (timeout.it_value.tv_sec))) {
+ if (setitimer(ITIMER_REAL, & timeout, NULL) < 0)
+ PANIC();
+ } else {
+ /*
+ * There is no time on the timer.
+ * This shouldn't happen,
+ * but isn't fatal.
+ */
+ sig_handler_fake(SIGALRM);
+ }
return(OK);
}
/* ==========================================================================
- * machdep_sub_timer()
+ * sleep_schedule()
*
- * formula is: new -= current;
+ * Assumes that the current thread is the thread to be scheduled
+ * and that the kthread is already locked.
*/
-static inline void machdep_sub_timer(struct itimerval * new,
- struct itimerval * current)
+void sleep_schedule(struct timespec *current_time, struct timespec *new_time)
{
- new->it_value.tv_usec -= current->it_value.tv_usec;
- if (new->it_value.tv_usec < 0) {
- new->it_value.tv_usec += 1000000;
- new->it_value.tv_sec--;
+ struct pthread * pthread_sleep_current, * pthread_sleep_prev;
+
+ /* Record the new time as the current thread's wakeup time. */
+ pthread_run->wakeup_time = *new_time;
+
+ /* any threads? */
+ if (pthread_sleep_current = pthread_sleep) {
+ if (sleep_compare_time(&(pthread_sleep_current->wakeup_time),
+ new_time) <= 0) {
+ /* Don't need to restart timer */
+ while (pthread_sleep_current->sll) {
+
+ pthread_sleep_prev = pthread_sleep_current;
+ pthread_sleep_current = pthread_sleep_current->sll;
+
+ if (sleep_compare_time(&(pthread_sleep_current->wakeup_time),
+ new_time) > 0) {
+ pthread_run->sll = pthread_sleep_current;
+ pthread_sleep_prev->sll = pthread_run;
+ return;
+ }
+ }
+
+ /* No more threads in queue, attach pthread_run to end of list */
+ pthread_sleep_current->sll = pthread_run;
+ pthread_run->sll = NULL;
+
+ } else {
+ /* Start timer and enqueue thread */
+ machdep_start_timer(current_time, new_time);
+ pthread_run->sll = pthread_sleep_current;
+ pthread_sleep = pthread_run;
+ }
+ } else {
+ /* Start timer and enqueue thread */
+ machdep_start_timer(current_time, new_time);
+ pthread_sleep = pthread_run;
+ pthread_run->sll = NULL;
}
- new->it_value.tv_sec -= current->it_value.tv_sec;
}
-
/* ==========================================================================
- * sleep_basic_wakeup()
+ * sleep_wakeup()
*
- * The real work of sleep_wakeup is done here.
+ * This routine is called by the interrupt handler, which has already
+ * locked the current kthread. Since all threads on this list are owned
+ * by the current kthread, rescheduling won't be a problem.
*/
-static inline int sleep_basic_wakeup()
+int sleep_spurious_wakeup = 0;
+int sleep_wakeup()
{
struct pthread *pthread_sleep_next;
- struct itimerval current_time;
- semaphore *plock;
+ struct timespec current_time;
+ int ret = 0;
+
+ if (pthread_sleep == NULL) {
+ return(NOTOK);
+ }
+
+ machdep_gettimeofday(&current_time);
+ if (sleep_compare_time(&(pthread_sleep->wakeup_time), &current_time) > 0) {
+ machdep_start_timer(&current_time, &(pthread_sleep->wakeup_time));
+ sleep_spurious_wakeup++;
+ return(OK);
+ }
- machdep_stop_timer(&current_time);
do {
- plock = &(pthread_sleep->lock);
- if (SEMAPHORE_TEST_AND_SET(plock)) {
- return(NOTOK);
+ if (pthread_sleep->pthread_priority > ret) {
+ ret = pthread_sleep->pthread_priority;
}
- /* return remaining time */
- pthread_sleep->time_sec = current_time.it_value.tv_sec;
- pthread_sleep->time_usec = current_time.it_value.tv_usec;
+ /*
+ * Clean up removed thread and start it running again.
+ *
+ * Note: It is VERY important to remove the thread form the
+ * current queue before putting it on the run queue.
+ * Both queues use pthread_sleep->next, and the thread that points
+ * to pthread_sleep should point to pthread_sleep->next then
+ * pthread_sleep should be put on the run queue.
+ */
+ if ((SET_PF_DONE_EVENT(pthread_sleep)) == OK) {
+ if (pthread_sleep->queue)
+ pthread_queue_remove(pthread_sleep->queue, pthread_sleep);
+ pthread_prio_queue_enq(pthread_current_prio_queue, pthread_sleep);
+ pthread_sleep->state = PS_RUNNING;
+ }
+
+ pthread_sleep_next = pthread_sleep->sll;
+ pthread_sleep->sll = NULL;
- if (pthread_sleep_next = pthread_sleep->sll) {
- pthread_sleep_next->time_usec += current_time.it_value.tv_usec;
- current_time.it_value.tv_usec = pthread_sleep_next->time_usec;
- pthread_sleep_next->time_sec += current_time.it_value.tv_sec;
- current_time.it_value.tv_sec = pthread_sleep_next->time_sec;
+ if ((pthread_sleep = pthread_sleep_next) == NULL) {
+ /* No more threads on sleep queue */
+ return(ret);
}
+ } while (sleep_compare_time(&(pthread_sleep->wakeup_time), &(current_time)) <= 0);
+
+ /* Start timer for next time interval */
+ machdep_start_timer(&current_time, &(pthread_sleep->wakeup_time));
+ return(ret);
+}
- /* Clean up removed thread and start it runnng again. */
- pthread_sleep->state = PS_RUNNING;
- pthread_sleep->sll = NULL;
- SEMAPHORE_RESET(plock);
- /* Set top of queue to next queue item */
- pthread_sleep = pthread_sleep_next;
+/* ==========================================================================
+ * __sleep()
+ */
+void __sleep(struct timespec * time_to_sleep)
+{
+ struct pthread *pthread_sleep_prev;
+ struct timespec current_time, wakeup_time;
- if (current_time.it_value.tv_sec || current_time.it_value.tv_usec) {
- machdep_start_timer(&current_time);
- break;
- }
+ pthread_sched_prevent();
- } while(pthread_sleep);
- return(OK);
+ /* Get real time */
+ machdep_gettimeofday(&current_time);
+ wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec;
+ wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec;
+
+ sleep_schedule(&current_time, &wakeup_time);
+
+ /* Reschedule thread */
+ SET_PF_WAIT_EVENT(pthread_run);
+ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ pthread_resched_resume(PS_SLEEP_WAIT);
+ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+ CLEAR_PF_DONE_EVENT(pthread_run);
+
+ /* Return actual time slept */
+ time_to_sleep->tv_sec = pthread_run->wakeup_time.tv_sec;
+ time_to_sleep->tv_nsec = pthread_run->wakeup_time.tv_nsec;
}
/* ==========================================================================
- * sleep_wakeup()
- *
- * This routine is called by the interrupt handler. It cannot call
- * pthread_yield() thenrfore it returns NOTOK to inform the handler
- * that it will have to be called at a later time.
+ * pthread_nanosleep()
*/
-int sleep_wakeup()
+unsigned int pthread_nanosleep(unsigned int nseconds)
{
- semaphore *lock, *plock;
- int ret;
+ struct timespec time_to_sleep;
- /* Lock sleep queue */
- lock = &(sleep_semaphore);
- if (SEMAPHORE_TEST_AND_SET(lock)) {
- return(NOTOK);
+ if (nseconds) {
+ time_to_sleep.tv_nsec = nseconds;
+ time_to_sleep.tv_sec = 0;
+ __sleep(&time_to_sleep);
+ nseconds = time_to_sleep.tv_nsec;
}
+ return(nseconds);
+}
- if (pthread_sleep) {
- ret = sleep_basic_wakeup();
- } else {
- ret = NOTOK;
- }
+/* ==========================================================================
+ * usleep()
+ */
+void usleep(unsigned int useconds)
+{
+ struct timespec time_to_sleep;
- SEMAPHORE_RESET(lock);
- return(ret);
+ if (useconds) {
+ time_to_sleep.tv_nsec = (useconds % 1000000) * 1000;
+ time_to_sleep.tv_sec = useconds / 1000000;
+ __sleep(&time_to_sleep);
+ }
}
/* ==========================================================================
@@ -164,93 +295,61 @@ int sleep_wakeup()
*/
unsigned int sleep(unsigned int seconds)
{
- struct pthread *pthread_sleep_current, *pthread_sleep_prev;
- struct itimerval current_time, new_time;
- semaphore *lock, *plock;
+ struct timespec time_to_sleep;
if (seconds) {
- /* Lock current thread */
- plock = &(pthread_run->lock);
- while (SEMAPHORE_TEST_AND_SET(plock)) {
- pthread_yield();
- }
+ time_to_sleep.tv_sec = seconds;
+ time_to_sleep.tv_nsec = 0;
+ __sleep(&time_to_sleep);
+ seconds = time_to_sleep.tv_sec;
+ }
+ return(seconds);
+}
- /* Set new_time timer value */
- new_time.it_value.tv_usec = 0;
- new_time.it_value.tv_sec = seconds;
- new_time.it_interval.tv_usec = 0;
- new_time.it_interval.tv_sec = 0;
+/* ==========================================================================
+ * sleep_cancel()
+ *
+ * Cannot be called while kernel is locked.
+ * Does not wake sleeping thread up, just remove it from the sleep queue.
+ */
+int sleep_cancel(struct pthread * pthread)
+{
+ struct timespec current_time, delta_time;
+ struct pthread * pthread_last;
+ int rval = NOTOK;
- /* Lock sleep queue */
- lock = &(sleep_semaphore);
- while (SEMAPHORE_TEST_AND_SET(lock)) {
- pthread_yield();
- }
+ /* Lock sleep queue, Note this may be on a different kthread queue */
+ pthread_sched_prevent();
- /* any threads? */
- if (pthread_sleep_current = pthread_sleep) {
-
- machdep_stop_timer(&current_time);
-
- /* Is remaining time left <= new thread time */
- if (current_time.it_value.tv_sec <= new_time.it_value.tv_sec) {
- machdep_sub_timer(&new_time, &current_time);
- machdep_start_timer(&current_time);
-
- while (pthread_sleep_current->sll) {
- pthread_sleep_prev = pthread_sleep_current;
- pthread_sleep_current = pthread_sleep_current->sll;
- current_time.it_value.tv_sec = pthread_sleep_current->time_sec;
-
- if ((current_time.it_value.tv_sec > new_time.it_value.tv_sec) ||
- ((current_time.it_value.tv_sec == new_time.it_value.tv_sec) &&
- (current_time.it_value.tv_usec > new_time.it_value.tv_usec))) {
- pthread_run->time_usec = new_time.it_value.tv_usec;
- pthread_run->time_sec = new_time.it_value.tv_sec;
- machdep_sub_timer(&current_time, &new_time);
- pthread_run->sll = pthread_sleep_current;
- pthread_sleep_prev->sll = pthread_run;
-
- /* Unlock sleep mutex */
- SEMAPHORE_RESET(lock);
-
- /* Reschedule thread */
- reschedule(PS_SLEEP_WAIT);
-
- return(pthread_run->time_sec);
- }
- machdep_sub_timer(&new_time, &current_time);
-
- }
-
- /* No more threads in queue, attach pthread_run to end of list */
- pthread_sleep_current->sll = pthread_run;
- pthread_run->sll = NULL;
-
- } else {
- /* Start timer and enqueue thread */
- machdep_start_timer(&new_time);
- machdep_sub_timer(&current_time, &new_time);
- pthread_run->sll = pthread_sleep_current;
- pthread_sleep = pthread_run;
+ if (pthread_sleep) {
+ if (pthread == pthread_sleep) {
+ rval = OK;
+ machdep_stop_timer(&delta_time);
+ if (pthread_sleep = pthread_sleep->sll) {
+ current_time.tv_sec = delta_time.tv_sec;
+ current_time.tv_nsec = delta_time.tv_nsec;
+ current_time.tv_sec += pthread_sleep->wakeup_time.tv_sec;
+ current_time.tv_nsec += pthread_sleep->wakeup_time.tv_nsec;
+ while (current_time.tv_nsec > 1000000000) {
+ current_time.tv_nsec -= 1000000000;
+ current_time.tv_sec++;
+ }
+ machdep_start_timer(&(current_time),
+ &(pthread_sleep->wakeup_time));
}
} else {
- /* Start timer and enqueue thread */
- machdep_start_timer(&new_time);
- pthread_sleep = pthread_run;
- pthread_run->sll = NULL;
+ for (pthread_last = pthread_sleep; pthread_last;
+ pthread_last = pthread_last->sll) {
+ if (pthread_last->sll == pthread) {
+ pthread_last->sll = pthread->sll;
+ rval = OK;
+ break;
+ }
+ }
}
-
- pthread_run->time_usec = new_time.it_value.tv_usec;
- pthread_run->time_sec = new_time.it_value.tv_sec;
-
- /* Unlock sleep mutex */
- SEMAPHORE_RESET(lock);
-
- /* Reschedule thread */
- reschedule(PS_SLEEP_WAIT);
-
}
- return(pthread_run->time_sec);
-}
+ pthread_sched_resume();
+ pthread->sll = NULL;
+ return(rval);
+}
diff --git a/lib/libpthread/stdio/Makefile.inc b/lib/libpthread/stdio/Makefile.inc
index 0fefa85c6d8..7275e2d3ed7 100644
--- a/lib/libpthread/stdio/Makefile.inc
+++ b/lib/libpthread/stdio/Makefile.inc
@@ -1,18 +1,20 @@
+
# from: @(#)Makefile.inc 5.7 (Berkeley) 6/27/91
-# $Id: Makefile.inc,v 1.1.1.1 1995/10/18 08:43:05 deraadt Exp $
+# $Id: Makefile.inc,v 1.1.1.2 1998/07/21 13:20:28 peter Exp $
# Thread safe stdio sources
-.PATH: ${.CURDIR}/stdio
+.PATH: ${srcdir}/stdio
+
+# SRCS+= tempnam.c tmpfile.c tmpnam.c
SRCS+= clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c fgetc.c \
fgetline.c fgetpos.c fgets.c fileno.c findfp.c flags.c fopen.c \
fprintf.c fpurge.c fputc.c fputs.c fread.c freopen.c fscanf.c \
fseek.c fsetpos.c ftell.c funopen.c fvwrite.c fwalk.c fwrite.c \
- getc.c getchar.c gets.c getw.c makebuf.c perror.c printf.c putc.c \
+ getc.c getchar.c gets.c getw.c makebuf.c perror.c putc.c \
putchar.c puts.c putw.c refill.c remove.c rewind.c rget.c scanf.c \
- setbuf.c setbuffer.c setvbuf.c snprintf.c sprintf.c sscanf.c \
- stdio.c tempnam.c tmpfile.c tmpnam.c ungetc.c vfprintf.c \
- vfscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c vsscanf.c \
+ setbuf.c setbuffer.c setvbuf.c sscanf.c \
+ stdio.c ungetc.c \
+ vfscanf.c vscanf.c vsscanf.c \
wsetup.c putc_unlocked.c putchar_unlocked.c getc_unlocked.c \
- getchar_unlocked.c strerror.c wbuf.c
-
+ getchar_unlocked.c strerror.c wbuf.c xprintf.c
diff --git a/lib/libpthread/stdio/README b/lib/libpthread/stdio/README
index 017f61f1b46..8e4c07909e9 100644
--- a/lib/libpthread/stdio/README
+++ b/lib/libpthread/stdio/README
@@ -1,4 +1,8 @@
+Copyright (c) 1993, 1994 Chris Provenzano. All rights reserved.
+
This is a threadsafe stdio based on the BSD stdio written by Chris Torek.
+This product includes software developed by the Univeristy of California,
+Berkeley and its contributors.
INCLUDE FILES AND PORTING
To continue to make this package portable, some basic rules on includes
@@ -8,11 +12,11 @@ pthread.h should be included first (if it is to be included).
stdio.h should be included.
INTERNAL LOCKING
-1. All functions that can be called by the user must have __flockfile at the
- begining and a __funlockfile at the end. __Flockfile is a counting mutex,
- The thread that owns the lock can call __flockfile as many times as
- it wants, but must call an equal number of __funlockfile before the
- lock will be released.
+1. All functions that can be called by the user must have flockfile() at the
+ begining and a funlockfile() at the end. The routine flockfile() is a
+ counting mutex, The thread that owns the lock can call flockfile() as
+ many times as it wants, but must call an equal number of funlockfile()
+ before the lock will be released.
2. All functions starting with __ shouldn't need addtional locking.
3. Anything that writes the variable __sglue should lock __sfp_mutex,
check __sfp_state, and do a condion wait if it is set.
@@ -30,11 +34,8 @@ INTERNAL LOCKING
tries to lock fp->_file and close it.
9. __sinit is done with a pthread_once routine.
-Copyright (c) 1993 Chris Provenzano. All rights reserved.
-
-This product includes software developed by the Univeristy of California,
-Berkeley and its contributors.
Things to do.
+
Fix printf so it uses the ininf function.
diff --git a/lib/libpthread/stdio/clrerr.c b/lib/libpthread/stdio/clrerr.c
index 1b4e4122c85..ab7047effd5 100644
--- a/lib/libpthread/stdio/clrerr.c
+++ b/lib/libpthread/stdio/clrerr.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clrerr.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: clrerr.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: clrerr.c,v 1.1.1.2 1998/07/21 13:20:32 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/fclose.c b/lib/libpthread/stdio/fclose.c
index d242643b2cd..b163c9aa363 100644
--- a/lib/libpthread/stdio/fclose.c
+++ b/lib/libpthread/stdio/fclose.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fclose.c 5.2 (Berkeley) 2/1/91";*/
-static char *rcsid = "$Id: fclose.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fclose.c,v 1.1.1.2 1998/07/21 13:20:34 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -54,16 +55,17 @@ fclose(fp)
if (fp->_flags) {
flockfile(fp);
r = fp->_flags & __SWR ? __sflush(fp) : 0;
- if (__sclose(fp) < 0)
- r = EOF;
if (fp->_flags & __SMBF)
free((char *)fp->_bf._base);
if (HASUB(fp))
FREEUB(fp);
if (HASLB(fp))
FREELB(fp);
+ if (__sclose(fp) < 0)
+ r = EOF;
+/* funlockfile(fp); Don't unlock. The close() already has. */
+ fp->_file = -1;
fp->_flags = 0; /* release this FILE for reuse, DO THIS LAST */
- funlockfile(fp);
return(r);
}
errno = EBADF;
diff --git a/lib/libpthread/stdio/fdopen.c b/lib/libpthread/stdio/fdopen.c
index 9add139ac91..946db681a45 100644
--- a/lib/libpthread/stdio/fdopen.c
+++ b/lib/libpthread/stdio/fdopen.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fdopen.c 5.6 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: fdopen.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fdopen.c,v 1.1.1.2 1998/07/21 13:20:36 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -68,7 +69,7 @@ FILE *fdopen(int fd, const char *mode)
return (NULL);
}
- pthread_once(&__sdidinit, __sinit);
+ __sinit ();
pthread_mutex_lock(&__sfp_mutex);
while (__sfp_state) {
pthread_cond_wait(&__sfp_cond, &__sfp_mutex);
diff --git a/lib/libpthread/stdio/feof.c b/lib/libpthread/stdio/feof.c
index e9fa87c3192..f850abc4c32 100644
--- a/lib/libpthread/stdio/feof.c
+++ b/lib/libpthread/stdio/feof.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)feof.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: feof.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: feof.c,v 1.1.1.2 1998/07/21 13:20:38 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/ferror.c b/lib/libpthread/stdio/ferror.c
index 6079b74ddd5..159210b2d3d 100644
--- a/lib/libpthread/stdio/ferror.c
+++ b/lib/libpthread/stdio/ferror.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)ferror.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: ferror.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: ferror.c,v 1.1.1.2 1998/07/21 13:20:40 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/fflush.c b/lib/libpthread/stdio/fflush.c
index b774fb3ff82..1d799dad7af 100644
--- a/lib/libpthread/stdio/fflush.c
+++ b/lib/libpthread/stdio/fflush.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,11 +37,11 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fflush.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: fflush.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fflush.c,v 1.1.1.2 1998/07/21 13:20:42 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
-#include <sys/errno.h>
+#include <errno.h>
#include <stdio.h>
#include "local.h"
@@ -51,7 +52,7 @@ fflush(fp)
int retval;
if (fp == NULL)
- return (__swalk_sflush);
+ return (__swalk_sflush());
flockfile(fp);
if ((fp->_flags & (__SWR | __SRW)) == 0) {
diff --git a/lib/libpthread/stdio/fgetc.c b/lib/libpthread/stdio/fgetc.c
index 077f862fd36..a1c6da52f09 100644
--- a/lib/libpthread/stdio/fgetc.c
+++ b/lib/libpthread/stdio/fgetc.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fgetc.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: fgetc.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fgetc.c,v 1.1.1.2 1998/07/21 13:20:44 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -45,7 +46,20 @@ static char *rcsid = "$Id: fgetc.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
fgetc(fp)
FILE *fp;
{
+ int ret;
+
flockfile(fp);
- return (__sgetc(fp));
+ ret = __sgetc(fp);
funlockfile(fp);
+ return(ret);
}
+
+int __getc(FILE *_p)
+{
+ int ret;
+ flockfile(_p);
+ ret = __sgetc(_p);
+ funlockfile(_p);
+ return(ret);
+}
+
diff --git a/lib/libpthread/stdio/fgetline.c b/lib/libpthread/stdio/fgetline.c
index 36c087dffa2..6bd5bd1fae0 100644
--- a/lib/libpthread/stdio/fgetline.c
+++ b/lib/libpthread/stdio/fgetline.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fgetline.c 5.2 (Berkeley) 5/4/91";*/
-static char *rcsid = "$Id: fgetline.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fgetline.c,v 1.1.1.2 1998/07/21 13:20:46 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -135,7 +136,7 @@ fgetline(fp, lenp)
*/
if (__slbexpand(fp, len + OPTIMISTIC))
goto error;
- (void) bcopy((void *)fp->_p, (void *)(fp->_lb._base + off),
+ (void) memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
len - off);
off = len;
if (__srefill(fp))
@@ -149,7 +150,7 @@ fgetline(fp, lenp)
len += diff;
if (__slbexpand(fp, len))
goto error;
- (void) bcopy((void *)fp->_p, (void *)(fp->_lb._base + off), diff);
+ (void) memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, diff);
fp->_r -= diff + 1;
fp->_p = p + 1;
break;
diff --git a/lib/libpthread/stdio/fgetpos.c b/lib/libpthread/stdio/fgetpos.c
index 499c24fdf75..7655928b2e6 100644
--- a/lib/libpthread/stdio/fgetpos.c
+++ b/lib/libpthread/stdio/fgetpos.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,15 +37,49 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fgetpos.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: fgetpos.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fgetpos.c,v 1.1.1.2 1998/07/21 13:20:48 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <pthread.h>
+#include <unistd.h>
#include <stdio.h>
+#include "local.h"
-/* Don't bother locking, ftell does it */
fgetpos(fp, pos)
FILE *fp;
fpos_t *pos;
{
- return ((*pos = ftell(fp)) == (fpos_t)-1);
+ flockfile(fp);
+
+ /*
+ * Find offset of underlying I/O object, then
+ * adjust for buffered bytes.
+ */
+ if (fp->_flags & __SOFF) {
+ *pos = fp->_offset;
+ } else {
+ *pos = __sseek(fp, (off_t)0, SEEK_CUR);
+ }
+
+ if (*pos != (fpos_t)-1) {
+ if (fp->_flags & __SRD) {
+ /*
+ * Reading. Any unread characters (including
+ * those from ungetc) cause the position to be
+ * smaller than that in the underlying object.
+ */
+ *pos -= fp->_r;
+ if (HASUB(fp))
+ *pos -= fp->_ur;
+ } else if (fp->_flags & __SWR && fp->_p != NULL) {
+ /*
+ * Writing. Any buffered characters cause the
+ * position to be greater than that in the
+ * underlying object.
+ */
+ *pos += fp->_p - fp->_bf._base;
+ }
+ }
+ funlockfile(fp);
+ return ((*pos) == (fpos_t)-1);
}
diff --git a/lib/libpthread/stdio/fgets.c b/lib/libpthread/stdio/fgets.c
index f8298ae3245..81e6db25db9 100644
--- a/lib/libpthread/stdio/fgets.c
+++ b/lib/libpthread/stdio/fgets.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,11 +37,12 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fgets.c 5.4 (Berkeley) 5/4/91";*/
-static char *rcsid = "$Id: fgets.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fgets.c,v 1.1.1.2 1998/07/21 13:20:50 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
/*
@@ -92,13 +94,13 @@ fgets(buf, n, fp)
len = ++t - p;
fp->_r -= len;
fp->_p = t;
- (void) bcopy((void *)p, (void *)s, len);
+ (void) memcpy((void *)s, (void *)p, len);
s += len;
break;
}
fp->_r -= len;
fp->_p += len;
- (void) bcopy((void *)p, (void *)s, len);
+ (void) memcpy((void *)s, (void *)p, len);
s += len;
} while ((n -= len) != 0);
diff --git a/lib/libpthread/stdio/fileno.c b/lib/libpthread/stdio/fileno.c
index 29e0de1306f..16eb04bd57b 100644
--- a/lib/libpthread/stdio/fileno.c
+++ b/lib/libpthread/stdio/fileno.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fileno.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: fileno.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fileno.c,v 1.1.1.2 1998/07/21 13:20:52 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/findfp.c b/lib/libpthread/stdio/findfp.c
index 2367a7bae4d..1a61ca44687 100644
--- a/lib/libpthread/stdio/findfp.c
+++ b/lib/libpthread/stdio/findfp.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,14 +37,14 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)findfp.c 5.10 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: findfp.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: findfp.c,v 1.1.1.2 1998/07/21 13:20:53 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
+#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
-#include <posix.h>
#include "local.h"
#include "glue.h"
@@ -64,10 +65,11 @@ FILE __sF[3] = {
std(__SWR|__SNBF, 2) /* stderr */
};
struct glue __sglue = { &uglue, 3, __sF };
+FILE *__iob = __sF;
+FILE *_iob = __sF;
pthread_mutex_t __sfp_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t __sfp_cond = PTHREAD_COND_INITIALIZER;
-pthread_once_t __sdidinit = PTHREAD_ONCE_INIT;
/*
* __sfp_state = 0, when free, > 0 when in _fwalk
* This allows multiple readers in _fwalk, but only one writer __sfp,
@@ -81,7 +83,7 @@ static struct glue *moreglue(register int n)
register FILE *p;
static FILE empty;
- g = (struct glue *)malloc(sizeof(*g) + n * sizeof(FILE));
+ g = (struct glue *)malloc(sizeof(struct glue) + n * sizeof(FILE));
if (g == NULL)
return (NULL);
p = (FILE *)(g + 1);
@@ -137,15 +139,23 @@ __sfp_done:;
*/
void _cleanup()
{
- (void) __swalk_sflush;
+ (void) __swalk_sflush();
}
/*
* __sinit() is called whenever stdio's internal variables must be set up.
+ * Do the pthread_once stuff here to keep pthread_once_t out of the
+ * header files. No reason sprintf.c &c should need to include pthread.h...
*/
-void __sinit()
+static void __s_real_init ()
{
- /* make sure we clean up on exit */
- __cleanup = _cleanup;
- __sdidinit = 1;
+ /* make sure we clean up on exit */
+ __cleanup = _cleanup;
+}
+
+static pthread_once_t sdidinit = PTHREAD_ONCE_INIT;
+
+void __sinit ()
+{
+ pthread_once (&sdidinit, __s_real_init);
}
diff --git a/lib/libpthread/stdio/flags.c b/lib/libpthread/stdio/flags.c
index dfcce47687e..9217f1abf6c 100644
--- a/lib/libpthread/stdio/flags.c
+++ b/lib/libpthread/stdio/flags.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,13 +37,15 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)flags.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: flags.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: flags.c,v 1.1.1.2 1998/07/21 13:20:55 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <pthread.h>
#include <sys/types.h>
-#include <sys/file.h>
#include <stdio.h>
+#include <fcntl.h>
#include <errno.h>
+#include <unistd.h>
/*
* Return the (stdio) flags for a given mode. Store the flags
diff --git a/lib/libpthread/stdio/floatio.h b/lib/libpthread/stdio/floatio.h
index 13daa9b3a09..606146dc219 100644
--- a/lib/libpthread/stdio/floatio.h
+++ b/lib/libpthread/stdio/floatio.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)floatio.h 5.1 (Berkeley) 1/20/91
- * $Id: floatio.h,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $
+ * $Id: floatio.h,v 1.1.1.2 1998/07/21 13:20:56 peter Exp $
*/
/*
diff --git a/lib/libpthread/stdio/fopen.c b/lib/libpthread/stdio/fopen.c
index 5e9f7274505..ace901a7e37 100644
--- a/lib/libpthread/stdio/fopen.c
+++ b/lib/libpthread/stdio/fopen.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fopen.c 5.5 (Berkeley) 2/5/91";*/
-static char *rcsid = "$Id: fopen.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fopen.c,v 1.1.1.2 1998/07/21 13:20:57 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -63,7 +64,7 @@ FILE *fopen(const char *file, const char *mode)
return (NULL);
}
- pthread_once(&__sdidinit, __sinit);
+ __sinit ();
pthread_mutex_lock(&__sfp_mutex);
while (__sfp_state) {
pthread_cond_wait(&__sfp_cond, &__sfp_mutex);
@@ -82,7 +83,7 @@ FILE *fopen(const char *file, const char *mode)
* fseek and ftell.)
*/
if (oflags & O_APPEND)
- (void) __sseek((void *)fp, (fpos_t)0, SEEK_END);
+ (void) __sseek((void *)fp, (off_t)0, SEEK_END);
}
pthread_mutex_unlock(&__sfp_mutex);
return (fp);
diff --git a/lib/libpthread/stdio/fpurge.c b/lib/libpthread/stdio/fpurge.c
index 0b77e42156f..fb8901be7a4 100644
--- a/lib/libpthread/stdio/fpurge.c
+++ b/lib/libpthread/stdio/fpurge.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fpurge.c 5.2 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: fpurge.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fpurge.c,v 1.1.1.2 1998/07/21 13:21:00 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/fputc.c b/lib/libpthread/stdio/fputc.c
index 9807ea95b8c..2f0a68bba59 100644
--- a/lib/libpthread/stdio/fputc.c
+++ b/lib/libpthread/stdio/fputc.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fputc.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: fputc.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fputc.c,v 1.1.1.2 1998/07/21 13:21:02 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -52,3 +53,21 @@ fputc(c, fp)
funlockfile(fp);
return(ret);
}
+
+int __putc(int _c, FILE *_p)
+{
+ int ret;
+ flockfile(_p);
+ ret = __sputc(_c, _p);
+ funlockfile(_p);
+ return(ret);
+}
+
+int __sputc(int _c, FILE *_p)
+{
+ if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
+ return (*_p->_p++ = _c);
+ else
+ return (__swbuf(_c, _p));
+}
+
diff --git a/lib/libpthread/stdio/fputs.c b/lib/libpthread/stdio/fputs.c
index 7833ed12238..c18ae25cb75 100644
--- a/lib/libpthread/stdio/fputs.c
+++ b/lib/libpthread/stdio/fputs.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fputs.c 5.6 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: fputs.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fputs.c,v 1.1.1.2 1998/07/21 13:21:03 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/fread.c b/lib/libpthread/stdio/fread.c
index f6515ccc048..fa7c3aa3c56 100644
--- a/lib/libpthread/stdio/fread.c
+++ b/lib/libpthread/stdio/fread.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fread.c 5.4 (Berkeley) 5/4/91";*/
-static char *rcsid = "$Id: fread.c,v 1.1.1.1 1995/10/18 08:43:06 deraadt Exp $";
+static char *rcsid = "$Id: fread.c,v 1.1.1.2 1998/07/21 13:21:04 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -63,7 +64,7 @@ fread(buf, size, count, fp)
total = resid;
p = buf;
while (resid > (r = fp->_r)) {
- (void) bcopy((void *)fp->_p, (void *)p, (size_t)r);
+ (void) memcpy((void *)p, (void *)fp->_p, (size_t)r);
fp->_p += r;
/* fp->_r = 0 ... done in __srefill */
p += r;
@@ -74,7 +75,7 @@ fread(buf, size, count, fp)
goto done_fread;
}
}
- (void) bcopy((void *)fp->_p, (void *)p, resid);
+ (void) memcpy((void *)p, (void *)fp->_p, resid);
fp->_r -= resid;
fp->_p += resid;
done_fread:;
diff --git a/lib/libpthread/stdio/freopen.c b/lib/libpthread/stdio/freopen.c
index a7f98535f8b..d743c657c75 100644
--- a/lib/libpthread/stdio/freopen.c
+++ b/lib/libpthread/stdio/freopen.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)freopen.c 5.6 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: freopen.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: freopen.c,v 1.1.1.2 1998/07/21 13:21:06 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -71,7 +72,7 @@ freopen(file, mode, fp)
return (NULL);
}
- pthread_once(&__sdidinit, __sinit);
+ __sinit ();
/*
* There are actually programs that depend on being able to "freopen"
@@ -118,7 +119,8 @@ freopen(file, mode, fp)
/*
* If reopening something that was open before on a real file, try
* to maintain the descriptor. Various C library routines (perror)
- * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
+ * assume stderr is always fd STDERR_FILENO, even if being
+ * freopen'd.
*/
/* Testing f == fp->_file may no longer be necessary */
if (fp->_file >= 0 && f != fp->_file) {
@@ -130,13 +132,14 @@ freopen(file, mode, fp)
fp->_flags = flags;
fp->_file = f;
ret = fp;
- break;
} else {
/* unlock __sfp_mutex, and try again later */
pthread_mutex_unlock(&__sfp_mutex);
pthread_yield();
continue;
}
+ /* @@ Yo, Chris! Between the "break" and "continue" statements
+ above, the program will never get here. What gives? */
pthread_mutex_unlock(&__sfp_mutex);
funlockfile(fp);
return(ret);
diff --git a/lib/libpthread/stdio/fsetpos.c b/lib/libpthread/stdio/fsetpos.c
index 68866bfb345..df04aebed38 100644
--- a/lib/libpthread/stdio/fsetpos.c
+++ b/lib/libpthread/stdio/fsetpos.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fsetpos.c 5.2 (Berkeley) 2/5/91";*/
-static char *rcsid = "$Id: fsetpos.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: fsetpos.c,v 1.1.1.2 1998/07/21 13:21:10 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
diff --git a/lib/libpthread/stdio/fvwrite.c b/lib/libpthread/stdio/fvwrite.c
index a1a7a9f4a62..4e475d672bf 100644
--- a/lib/libpthread/stdio/fvwrite.c
+++ b/lib/libpthread/stdio/fvwrite.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,12 +37,13 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fvwrite.c 5.3 (Berkeley) 5/4/91";*/
-static char *rcsid = "$Id: fvwrite.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: fvwrite.c,v 1.1.1.2 1998/07/21 13:21:14 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
-#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include "local.h"
#include "fvwrite.h"
@@ -69,7 +71,7 @@ __sfvwrite(fp, uio)
return (EOF);
#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define COPY(n) (void) bcopy((void *)p, (void *)fp->_p, (size_t)(n));
+#define COPY(n) (void) memcpy((void *)fp->_p, (void *)p, (size_t)(n));
iov = uio->uio_iov;
p = iov->iov_base;
diff --git a/lib/libpthread/stdio/fvwrite.h b/lib/libpthread/stdio/fvwrite.h
index 3ee8c474465..33dc4bd72d5 100644
--- a/lib/libpthread/stdio/fvwrite.h
+++ b/lib/libpthread/stdio/fvwrite.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)fvwrite.h 5.1 (Berkeley) 1/20/91
- * $Id: fvwrite.h,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $
+ * $Id: fvwrite.h,v 1.1.1.2 1998/07/21 13:21:15 peter Exp $
*/
/*
@@ -51,4 +51,4 @@ struct __suio {
int uio_resid;
};
-extern int __sfvwrite __P(( FILE *, struct __suio *));
+extern int __sfvwrite __P_(( FILE *, struct __suio *));
diff --git a/lib/libpthread/stdio/fwalk.c b/lib/libpthread/stdio/fwalk.c
index 317f817a60f..45372f8d8f2 100644
--- a/lib/libpthread/stdio/fwalk.c
+++ b/lib/libpthread/stdio/fwalk.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fwalk.c 5.2 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: fwalk.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: fwalk.c,v 1.1.1.2 1998/07/21 13:21:17 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -91,13 +92,15 @@ int __swalk_sflush()
/* Is there anything to flush? */
if (fp->_bf._base && (fp->_bf._base - fp->_p)) {
if (ftrylockfile(fp)) { /* Can we flush it */
- if (!saven) { /* No, save first fp we can't flush */
- saven;
+ if (!saven) { /* No, save first fp we can't flush */
+ saven = n;
saveg = g;
savefp = fp;
continue;
}
+ } else {
ret |= __sflush(fp);
+ funlockfile(fp);
}
}
}
@@ -109,11 +112,9 @@ int __swalk_sflush()
if (fp->_flags != 0) {
/* Anything to flush */
while (fp->_bf._base && (fp->_bf._base - fp->_p)) {
- if (ftrylockfile(fp)) { /* Can we flush it */
- pthread_yield();
- continue;
- }
+ flockfile(fp);
ret |= __sflush(fp);
+ funlockfile(fp);
}
}
}
diff --git a/lib/libpthread/stdio/fwrite.c b/lib/libpthread/stdio/fwrite.c
index 69e691599de..4f621d04b86 100644
--- a/lib/libpthread/stdio/fwrite.c
+++ b/lib/libpthread/stdio/fwrite.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)fwrite.c 5.5 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: fwrite.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: fwrite.c,v 1.1.1.2 1998/07/21 13:21:18 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -62,6 +63,8 @@ fwrite(buf, size, count, fp)
uio.uio_resid = iov.iov_len = n = count * size;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
+ if (! n)
+ return(0);
flockfile(fp);
diff --git a/lib/libpthread/stdio/getc.c b/lib/libpthread/stdio/getc.c
index d14d2f19318..bb3a8306e6c 100644
--- a/lib/libpthread/stdio/getc.c
+++ b/lib/libpthread/stdio/getc.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)getc.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: getc.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: getc.c,v 1.1.1.2 1998/07/21 13:21:19 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
diff --git a/lib/libpthread/stdio/getc_unlocked.c b/lib/libpthread/stdio/getc_unlocked.c
index f55100aa98d..a10120b7672 100644
--- a/lib/libpthread/stdio/getc_unlocked.c
+++ b/lib/libpthread/stdio/getc_unlocked.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)getc.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: getc_unlocked.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: getc_unlocked.c,v 1.1.1.2 1998/07/21 13:21:21 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/getchar.c b/lib/libpthread/stdio/getchar.c
index b75de451c6a..1d5d66530e1 100644
--- a/lib/libpthread/stdio/getchar.c
+++ b/lib/libpthread/stdio/getchar.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)getchar.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: getchar.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: getchar.c,v 1.1.1.2 1998/07/21 13:21:22 peter Exp $";
#endif /* LIBC_SCCS and not lint */
/*
diff --git a/lib/libpthread/stdio/getchar_unlocked.c b/lib/libpthread/stdio/getchar_unlocked.c
index 552ba1c9c46..e66b20f0e9c 100644
--- a/lib/libpthread/stdio/getchar_unlocked.c
+++ b/lib/libpthread/stdio/getchar_unlocked.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)getchar.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: getchar_unlocked.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: getchar_unlocked.c,v 1.1.1.2 1998/07/21 13:21:24 peter Exp $";
#endif /* LIBC_SCCS and not lint */
/*
diff --git a/lib/libpthread/stdio/gets.c b/lib/libpthread/stdio/gets.c
index dc04f6176d4..7130b029c69 100644
--- a/lib/libpthread/stdio/gets.c
+++ b/lib/libpthread/stdio/gets.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,9 +37,10 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)gets.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: gets.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: gets.c,v 1.1.1.2 1998/07/21 13:21:25 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
diff --git a/lib/libpthread/stdio/getw.c b/lib/libpthread/stdio/getw.c
index 3315135244e..3f9d4962e6a 100644
--- a/lib/libpthread/stdio/getw.c
+++ b/lib/libpthread/stdio/getw.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)getw.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: getw.c,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $";
+static char *rcsid = "$Id: getw.c,v 1.1.1.2 1998/07/21 13:21:26 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
diff --git a/lib/libpthread/stdio/glue.h b/lib/libpthread/stdio/glue.h
index 32564499028..7f153a4f30d 100644
--- a/lib/libpthread/stdio/glue.h
+++ b/lib/libpthread/stdio/glue.h
@@ -34,15 +34,16 @@
* SUCH DAMAGE.
*
* from: @(#)glue.h 5.1 (Berkeley) 1/20/91
- * $Id: glue.h,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $
+ * $Id: glue.h,v 1.1.1.2 1998/07/21 13:21:28 peter Exp $
*/
/*
* The first few FILEs are statically allocated; others are dynamically
* allocated and linked in via this glue structure.
*/
-struct glue {
+typedef struct glue {
struct glue *next;
int niobs;
FILE *iobs;
-} __sglue;
+} __sglue_type;
+extern struct glue __sglue;
diff --git a/lib/libpthread/stdio/local.h b/lib/libpthread/stdio/local.h
index cdcab1c32fe..f8621727e21 100644
--- a/lib/libpthread/stdio/local.h
+++ b/lib/libpthread/stdio/local.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)local.h 5.3 (Berkeley) 5/6/93
- * $Id: local.h,v 1.1.1.1 1995/10/18 08:43:07 deraadt Exp $
+ * $Id: local.h,v 1.1.1.2 1998/07/21 13:21:29 peter Exp $
*/
/*
@@ -42,23 +42,25 @@
* in particular, macros and private variables.
*/
-FILE *__sfp __P((void));
-int __sflush __P((FILE *));
-int __srefill __P((FILE *));
-int __swrite __P((FILE *, const char *, int));
-int __sread __P((FILE *, char *, int));
-fpos_t __sseek __P((FILE *, fpos_t, int));
-int __sclose __P((FILE *));
-void __sinit __P((void));
-void _cleanup __P((void));
-void (*__cleanup) __P((void));
-void __smakebuf __P((FILE *));
-int __swhatbuf __P((FILE *, size_t *, int *));
-int __swalk_sflush __P(());
-int __swsetup __P((FILE *));
-int __sflags __P((const char *, int *));
+#include <sys/types.h>
+#include <stddef.h>
-extern int __sdidinit;
+extern FILE *__sfp __P_((void));
+extern int __sflush __P_((FILE *));
+extern int __srefill __P_((FILE *));
+extern int __swrite __P_((FILE *, const char *, int));
+extern int __sread __P_((FILE *, char *, int));
+extern fpos_t __sseek __P_((FILE *, off_t, int));
+extern int __sclose __P_((FILE *));
+extern void __sinit __P_((void));
+extern void _cleanup __P_((void));
+extern void __smakebuf __P_((FILE *));
+extern int __swhatbuf __P_((FILE *, size_t *, int *));
+extern int __swalk_sflush __P_(());
+extern int __swsetup __P_((FILE *));
+extern int __sflags __P_((const char *, int *));
+
+extern void (*__cleanup) __P_((void));
/*
* Return true iff the given FILE cannot be written now.
diff --git a/lib/libpthread/stdio/makebuf.c b/lib/libpthread/stdio/makebuf.c
index df132e23dfe..e748084d130 100644
--- a/lib/libpthread/stdio/makebuf.c
+++ b/lib/libpthread/stdio/makebuf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)makebuf.c 5.3 (Berkeley) 5/6/93";*/
-static char *rcsid = "$Id: makebuf.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: makebuf.c,v 1.1.1.2 1998/07/21 13:21:30 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -47,6 +48,8 @@ static char *rcsid = "$Id: makebuf.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $
#include <stdlib.h>
#include "local.h"
+void (*__cleanup) __P_((void));
+
/*
* Allocate a file buffer, or switch to unbuffered I/O.
* Per the ANSI C standard, ALL tty devices default to line buffered.
diff --git a/lib/libpthread/stdio/mktemp.c b/lib/libpthread/stdio/mktemp.c
index 616a094bc6a..be193109adc 100644
--- a/lib/libpthread/stdio/mktemp.c
+++ b/lib/libpthread/stdio/mktemp.c
@@ -33,7 +33,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)mktemp.c 5.10 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: mktemp.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: mktemp.c,v 1.1.1.2 1998/07/21 13:21:32 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
diff --git a/lib/libpthread/stdio/perror.c b/lib/libpthread/stdio/perror.c
index c4cb0154da2..19fe52f5010 100644
--- a/lib/libpthread/stdio/perror.c
+++ b/lib/libpthread/stdio/perror.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1988 Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano proven@mit.edu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,33 +36,32 @@
static char sccsid[] = "@(#)perror.c 5.11 (Berkeley) 2/24/91";
#endif /* LIBC_SCCS and not lint */
-#include <sys/types.h>
-#include <sys/uio.h>
+#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
+char *strerror(int); /* For systems that don't prototype it in string.h */
+
void
perror(s)
const char *s;
{
- register struct iovec *v;
- struct iovec iov[4];
+ char * e;
- v = iov;
- if (s && *s) {
- v->iov_base = (char *)s;
- v->iov_len = strlen(s);
- v++;
- v->iov_base = ": ";
- v->iov_len = 2;
- v++;
+ if (fd_lock(STDERR_FILENO, FD_WRITE, NULL) == OK) {
+ if (s && *s) {
+ fd_table[STDERR_FILENO]->ops->write(fd_table[STDERR_FILENO]->fd,
+ fd_table[STDERR_FILENO]->flags, s, strlen(s), NULL);
+ fd_table[STDERR_FILENO]->ops->write(fd_table[STDERR_FILENO]->fd,
+ fd_table[STDERR_FILENO]->flags, ": ", 2, NULL);
+ }
+ e = strerror(errno);
+ fd_table[STDERR_FILENO]->ops->write(fd_table[STDERR_FILENO]->fd,
+ fd_table[STDERR_FILENO]->flags, e, strlen(e), NULL);
+ fd_table[STDERR_FILENO]->ops->write(fd_table[STDERR_FILENO]->fd,
+ fd_table[STDERR_FILENO]->flags, "\n", 1, NULL);
+ fd_unlock(STDERR_FILENO, FD_WRITE);
}
- v->iov_base = strerror(errno);
- v->iov_len = strlen(v->iov_base);
- v++;
- v->iov_base = "\n";
- v->iov_len = 1;
- (void)writev(STDERR_FILENO, iov, (v - iov) + 1);
}
diff --git a/lib/libpthread/stdio/printf.c b/lib/libpthread/stdio/printf.c
index 741121f1192..b9ca52e3510 100644
--- a/lib/libpthread/stdio/printf.c
+++ b/lib/libpthread/stdio/printf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,9 +37,10 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)printf.c 5.6 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: printf.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: printf.c,v 1.1.1.2 1998/07/21 13:21:35 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <stdarg.h>
#include <pthread.h>
#include <stdio.h>
diff --git a/lib/libpthread/stdio/putc.c b/lib/libpthread/stdio/putc.c
index 38e1f4df148..e7a1bcaf8c4 100644
--- a/lib/libpthread/stdio/putc.c
+++ b/lib/libpthread/stdio/putc.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)putc.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: putc.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: putc.c,v 1.1.1.2 1998/07/21 13:21:36 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/putc_unlocked.c b/lib/libpthread/stdio/putc_unlocked.c
index a443ffc1d04..b73518af6d4 100644
--- a/lib/libpthread/stdio/putc_unlocked.c
+++ b/lib/libpthread/stdio/putc_unlocked.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)putc.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: putc_unlocked.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: putc_unlocked.c,v 1.1.1.2 1998/07/21 13:21:37 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/putchar.c b/lib/libpthread/stdio/putchar.c
index 097ded6e840..da2d16dc2bc 100644
--- a/lib/libpthread/stdio/putchar.c
+++ b/lib/libpthread/stdio/putchar.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)putchar.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: putchar.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: putchar.c,v 1.1.1.2 1998/07/21 13:21:39 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
diff --git a/lib/libpthread/stdio/putchar_unlocked.c b/lib/libpthread/stdio/putchar_unlocked.c
index a0a3b50e690..9fa08418a76 100644
--- a/lib/libpthread/stdio/putchar_unlocked.c
+++ b/lib/libpthread/stdio/putchar_unlocked.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)putchar.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: putchar_unlocked.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: putchar_unlocked.c,v 1.1.1.2 1998/07/21 13:21:40 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/puts.c b/lib/libpthread/stdio/puts.c
index c1df5f95190..ac4cbc359a9 100644
--- a/lib/libpthread/stdio/puts.c
+++ b/lib/libpthread/stdio/puts.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)puts.c 5.6 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: puts.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: puts.c,v 1.1.1.2 1998/07/21 13:21:41 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/putw.c b/lib/libpthread/stdio/putw.c
index 949df43036b..775afed1020 100644
--- a/lib/libpthread/stdio/putw.c
+++ b/lib/libpthread/stdio/putw.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)putw.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: putw.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: putw.c,v 1.1.1.2 1998/07/21 13:21:43 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
diff --git a/lib/libpthread/stdio/refill.c b/lib/libpthread/stdio/refill.c
index b0db1bbc203..8cea23e51d8 100644
--- a/lib/libpthread/stdio/refill.c
+++ b/lib/libpthread/stdio/refill.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)refill.c 5.3 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: refill.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: refill.c,v 1.1.1.2 1998/07/21 13:21:44 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -68,17 +69,19 @@ static void __swalk_lflush()
savefp = NULL;
for (g = &__sglue; g != NULL; g = g->next) {
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) {
- if ((fp->_flags & (__SLBF|__SWR)) == __SLBF|__SWR) {
+ if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) {
/* Is there anything to flush? */
if (fp->_bf._base && (fp->_bf._base - fp->_p)) {
if (ftrylockfile(fp)) { /* Can we flush it */
if (!saven) { /* No, save first fp we can't flush */
- saven;
+ saven = n;
saveg = g;
savefp = fp;
continue;
}
+ } else {
(void) __sflush(fp);
+ funlockfile(fp);
}
}
}
@@ -87,14 +90,12 @@ static void __swalk_lflush()
if (savefp) {
for (g = saveg; g != NULL; g = g->next) {
for (fp = savefp, n = saven + 1; --n >= 0; fp++) {
- if ((fp->_flags & (__SLBF|__SWR)) == __SLBF|__SWR) {
+ if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) {
/* Anything to flush */
while (fp->_bf._base && (fp->_bf._base - fp->_p)) {
- if (ftrylockfile(fp)) { /* Can we flush it */
- pthread_yield();
- continue;
- }
- (void) __sflush(fp);
+ flockfile(fp);
+ (void) __sflush(fp);
+ funlockfile(fp);
}
}
}
@@ -118,7 +119,7 @@ __srefill(fp)
{
/* make sure stdio is set up */
- pthread_once(&__sdidinit, __sinit);
+ __sinit ();
fp->_r = 0; /* largely a convenience for callers */
@@ -157,6 +158,11 @@ __srefill(fp)
}
}
+ if (fp->_file == -1) {
+ fp->_flags |= __SEOF;
+ return(EOF);
+ }
+
if (fp->_bf._base == NULL)
__smakebuf(fp);
diff --git a/lib/libpthread/stdio/remove.c b/lib/libpthread/stdio/remove.c
index 0c41b0dd9b6..c41c4f3b370 100644
--- a/lib/libpthread/stdio/remove.c
+++ b/lib/libpthread/stdio/remove.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,9 +37,10 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)remove.c 5.3 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: remove.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: remove.c,v 1.1.1.2 1998/07/21 13:21:45 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <pthread.h>
#include <unistd.h>
remove(file)
diff --git a/lib/libpthread/stdio/rewind.c b/lib/libpthread/stdio/rewind.c
index 05f85c3a423..9464f9f7eaf 100644
--- a/lib/libpthread/stdio/rewind.c
+++ b/lib/libpthread/stdio/rewind.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)rewind.c 5.6 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: rewind.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: rewind.c,v 1.1.1.2 1998/07/21 13:21:47 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <errno.h>
diff --git a/lib/libpthread/stdio/rget.c b/lib/libpthread/stdio/rget.c
index 6145e753e28..d84cb7d8c77 100644
--- a/lib/libpthread/stdio/rget.c
+++ b/lib/libpthread/stdio/rget.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)rget.c 5.1 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: rget.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: rget.c,v 1.1.1.2 1998/07/21 13:21:48 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
diff --git a/lib/libpthread/stdio/setbuf.c b/lib/libpthread/stdio/setbuf.c
index c334dbebd51..4313a8481de 100644
--- a/lib/libpthread/stdio/setbuf.c
+++ b/lib/libpthread/stdio/setbuf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)setbuf.c 5.3 (Berkeley) 1/20/91";*/
-static char *rcsid = "$Id: setbuf.c,v 1.1.1.1 1995/10/18 08:43:08 deraadt Exp $";
+static char *rcsid = "$Id: setbuf.c,v 1.1.1.2 1998/07/21 13:21:51 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
diff --git a/lib/libpthread/stdio/setbuffer.c b/lib/libpthread/stdio/setbuffer.c
index 58c35ca9642..bd7db6a6ac4 100644
--- a/lib/libpthread/stdio/setbuffer.c
+++ b/lib/libpthread/stdio/setbuffer.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)setbuffer.c 5.5 (Berkeley) 3/18/91";*/
-static char *rcsid = "$Id: setbuffer.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: setbuffer.c,v 1.1.1.2 1998/07/21 13:21:52 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
diff --git a/lib/libpthread/stdio/setvbuf.c b/lib/libpthread/stdio/setvbuf.c
index 4bf9324419a..b2df334f3b3 100644
--- a/lib/libpthread/stdio/setvbuf.c
+++ b/lib/libpthread/stdio/setvbuf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)setvbuf.c 5.5 (Berkeley) 5/6/93";*/
-static char *rcsid = "$Id: setvbuf.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: setvbuf.c,v 1.1.1.2 1998/07/21 13:21:54 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -141,7 +142,7 @@ nbf:
flags |= __SLBF;
if (flags & __SRW)
flags &= ~(__SRD | __SWR);
- fp->_w = 0;
+ fp->_w = size; /* Was 0 (mevans) */
fp->_flags = flags;
fp->_bf._base = fp->_p = (unsigned char *)buf;
fp->_bf._size = size;
diff --git a/lib/libpthread/stdio/stdio.c b/lib/libpthread/stdio/stdio.c
index f5825298262..c27531b3674 100644
--- a/lib/libpthread/stdio/stdio.c
+++ b/lib/libpthread/stdio/stdio.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)stdio.c 5.3 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: stdio.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: stdio.c,v 1.1.1.2 1998/07/21 13:21:59 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -54,8 +55,14 @@ int __sread(FILE *fp, char *buf, int n)
register int ret;
/* if the read succeeded, update the current offset */
- if ((ret = fd_table[fp->_file]->ops->read(fd_table[fp->_file]->fd,
- fd_table[fp->_file]->flags, buf, n)) >= 0) {
+ if (fd_table[fp->_file]->ops->use_kfds < 2) {
+ ret = fd_table[fp->_file]->ops->read(fd_table[fp->_file]->fd,
+ fd_table[fp->_file]->flags, buf, n, NULL);
+ } else {
+ pthread_ssize_t (*readfn)() = fd_table[fp->_file]->ops->read;
+ ret = readfn(fd_table[fp->_file]->fd, buf, n);
+ }
+ if (ret >= 0) {
fp->_offset += ret;
} else {
fp->_flags &= ~__SOFF; /* paranoia */
@@ -68,15 +75,20 @@ int __swrite(FILE *fp, const char *buf, int n)
if (fp->_flags & __SAPP)
(void) lseek(fp->_file, (off_t)0, SEEK_END);
fp->_flags &= ~__SOFF; /* in case FAPPEND mode is set */
- return(fd_table[fp->_file]->ops->write(fd_table[fp->_file]->fd,
- fd_table[fp->_file]->flags, buf, n));
+ if (fd_table[fp->_file]->ops->use_kfds < 2) {
+ return(fd_table[fp->_file]->ops->write(fd_table[fp->_file]->fd,
+ fd_table[fp->_file]->flags, buf, n, NULL));
+ } else {
+ pthread_ssize_t (*writefn)() = fd_table[fp->_file]->ops->write;
+ return(writefn(fd_table[fp->_file]->fd,buf,n));
+ }
}
-fpos_t __sseek(FILE *fp, fpos_t offset, int whence)
+fpos_t __sseek(FILE *fp, off_t offset, int whence)
{
- register off_t ret;
+ register fpos_t ret;
- ret = lseek(fp->_file, (off_t)offset, whence);
+ ret = (fpos_t)lseek(fp->_file, offset, whence);
if (ret == -1L)
fp->_flags &= ~__SOFF;
else {
diff --git a/lib/libpthread/stdio/tmpfile.c b/lib/libpthread/stdio/tmpfile.c
index f8a7eefbc76..f76c68fcad7 100644
--- a/lib/libpthread/stdio/tmpfile.c
+++ b/lib/libpthread/stdio/tmpfile.c
@@ -36,7 +36,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)tmpfile.c 5.4 (Berkeley) 5/27/91";*/
-static char *rcsid = "$Id: tmpfile.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: tmpfile.c,v 1.1.1.2 1998/07/21 13:22:02 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -55,8 +55,8 @@ tmpfile()
#define TRAILER "tmp.XXXXXX"
char buf[sizeof(_PATH_TMP) + sizeof(TRAILER)];
- bcopy(_PATH_TMP, buf, sizeof(_PATH_TMP) - 1);
- bcopy(TRAILER, buf + sizeof(_PATH_TMP) - 1, sizeof(TRAILER));
+ memcpy(buf, _PATH_TMP, sizeof(_PATH_TMP) - 1);
+ memcpy( buf + sizeof(_PATH_TMP) - 1, TRAILER, sizeof(TRAILER));
sigfillset(&set);
(void)sigprocmask(SIG_BLOCK, &set, &oset);
diff --git a/lib/libpthread/stdio/tmpnam.c b/lib/libpthread/stdio/tmpnam.c
index 75fa267963f..ca6e6a2efbe 100644
--- a/lib/libpthread/stdio/tmpnam.c
+++ b/lib/libpthread/stdio/tmpnam.c
@@ -36,7 +36,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)tmpnam.c 5.3 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: tmpnam.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: tmpnam.c,v 1.1.1.2 1998/07/21 13:22:03 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <unistd.h>
diff --git a/lib/libpthread/stdio/ungetc.c b/lib/libpthread/stdio/ungetc.c
index 3497011767b..0da73f30c15 100644
--- a/lib/libpthread/stdio/ungetc.c
+++ b/lib/libpthread/stdio/ungetc.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)ungetc.c 5.6 (Berkeley) 5/4/91";*/
-static char *rcsid = "$Id: ungetc.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: ungetc.c,v 1.1.1.2 1998/07/21 13:22:05 peter Exp $";
#endif /* LIBC_SCCS and not lint */
#include <pthread.h>
@@ -76,7 +77,7 @@ __submore(fp)
p = realloc(fp->_ub._base, i << 1);
if (p == NULL)
return (EOF);
- (void) bcopy((void *)p, (void *)(p + i), (size_t)i);
+ (void) memcpy((void *)(p + i), (void *)p, (size_t)i);
fp->_p = p + i;
fp->_ub._base = p;
fp->_ub._size = i << 1;
@@ -89,7 +90,7 @@ ungetc(c, fp)
{
if (c == EOF)
return (EOF);
- pthread_once(&__sdidinit, __sinit);
+ __sinit ();
flockfile(fp);
if ((fp->_flags & __SRD) == 0) {
diff --git a/lib/libpthread/stdio/vfprintf.c b/lib/libpthread/stdio/vfprintf.c
index 23662e945a1..a612a1f9bef 100644
--- a/lib/libpthread/stdio/vfprintf.c
+++ b/lib/libpthread/stdio/vfprintf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +37,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
-static char *rcsid = "$Id: vfprintf.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: vfprintf.c,v 1.1.1.2 1998/07/21 13:22:06 peter Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -49,6 +50,7 @@ static char *rcsid = "$Id: vfprintf.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp
#include <sys/types.h>
#include <stdio.h>
+#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@@ -88,7 +90,7 @@ static int
__sbprintf(fp, fmt, ap)
FILE *fp;
const char *fmt;
- va_list ap;
+ pthread_va_list ap;
{
unsigned char buf[BUFSIZ];
FILE fake;
@@ -121,8 +123,8 @@ __sbprintf(fp, fmt, ap)
#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
#define DEFPREC 6
-static char *cvt __P((double, int, int, char *, int *, int, int *));
-static int exponent __P((char *, int, int));
+static char *cvt __P_((double, int, int, char *, int *, int, int *));
+static int exponent __P_((char *, int, int));
#else /* no FLOATING_POINT */
@@ -154,7 +156,7 @@ int
vfprintf(fp, fmt0, ap)
FILE *fp;
const char *fmt0;
- va_list ap;
+ pthread_va_list ap;
{
register char *fmt; /* format string */
register int ch; /* character from fmt */
@@ -175,7 +177,10 @@ vfprintf(fp, fmt0, ap)
char expstr[7]; /* buffer for exponent string */
#endif
-#ifdef __GNUC__ /* gcc has builtin quad type (long long) SOS */
+#if defined (__alpha) && !defined(_GNUC_)
+#define quad_t long
+#define u_quad_t unsigned long
+#else /* gcc has builtin quad type (long long) SOS */
#define quad_t long long
#define u_quad_t unsigned long long
#endif
@@ -473,7 +478,7 @@ reswitch: switch (ch) {
* -- ANSI X3J11
*/
/* NOSTRICT */
- _uquad = (u_quad_t)va_arg(ap, void *);
+ _uquad = (u_quad_t)(size_t)va_arg(ap, void *);
base = HEX;
xdigs = "0123456789abcdef";
flags |= HEXPREFIX;
@@ -695,7 +700,7 @@ error:
#ifdef FLOATING_POINT
-extern char *__dtoa __P((double, int, int, int *, int *, char **));
+extern char *__dtoa __P_((double, int, int, int *, int *, char **));
static char *
cvt(value, ndigits, flags, sign, decpt, ch, length)
@@ -724,7 +729,16 @@ cvt(value, ndigits, flags, sign, decpt, ch, length)
*sign = '-';
} else
*sign = '\000';
+/* #if !defined(__alpha__) && !defined(hpux) */
+#ifndef THIS_IS_NEVER_DEFINED
digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
+#else
+ { char *ecvt(double,int,int*,int*);
+
+ digits = ecvt(value, ndigits, decpt, &dsgn);
+ rve = (digits + (int)strlen(digits));
+ }
+#endif
if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */
bp = digits + ndigits;
if (ch == 'f') {
diff --git a/lib/libpthread/stdio/vprintf.c b/lib/libpthread/stdio/vprintf.c
index d919b19b33d..4462d7ece6c 100644
--- a/lib/libpthread/stdio/vprintf.c
+++ b/lib/libpthread/stdio/vprintf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,14 +37,15 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)vprintf.c 5.6 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: vprintf.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: vprintf.c,v 1.1.1.2 1998/07/21 13:22:09 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <stdarg.h>
#include <stdio.h>
vprintf(fmt, ap)
char const *fmt;
- va_list ap;
+ pthread_va_list ap;
{
return (vfprintf(stdout, fmt, ap));
}
diff --git a/lib/libpthread/stdio/vscanf.c b/lib/libpthread/stdio/vscanf.c
index 009dce24948..7a0b6f2129d 100644
--- a/lib/libpthread/stdio/vscanf.c
+++ b/lib/libpthread/stdio/vscanf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,14 +37,15 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)vscanf.c 5.1 (Berkeley) 4/15/91";*/
-static char *rcsid = "$Id: vscanf.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: vscanf.c,v 1.1.1.2 1998/07/21 13:22:10 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <stdarg.h>
#include <stdio.h>
vscanf(fmt, ap)
const char *fmt;
- va_list ap;
+ pthread_va_list ap;
{
int r;
flockfile(stdin);
diff --git a/lib/libpthread/stdio/vsnprintf.c b/lib/libpthread/stdio/vsnprintf.c
index 1d16123a3c2..1796ae1ad9c 100644
--- a/lib/libpthread/stdio/vsnprintf.c
+++ b/lib/libpthread/stdio/vsnprintf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,22 +37,25 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)vsnprintf.c 5.2 (Berkeley) 2/5/91";*/
-static char *rcsid = "$Id: vsnprintf.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: vsnprintf.c,v 1.1.1.2 1998/07/21 13:22:12 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <stdarg.h>
+#include <stddef.h>
#include <stdio.h>
vsnprintf(str, n, fmt, ap)
char *str;
size_t n;
const char *fmt;
- va_list ap;
+ pthread_va_list ap;
{
int ret;
FILE f;
if ((int)n < 1)
return (EOF);
+ f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = n - 1;
diff --git a/lib/libpthread/stdio/vsprintf.c b/lib/libpthread/stdio/vsprintf.c
index 88a50f90c6a..e66a383d195 100644
--- a/lib/libpthread/stdio/vsprintf.c
+++ b/lib/libpthread/stdio/vsprintf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,20 +37,22 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)vsprintf.c 5.5 (Berkeley) 2/5/91";*/
-static char *rcsid = "$Id: vsprintf.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: vsprintf.c,v 1.1.1.2 1998/07/21 13:22:13 peter Exp $";
#endif /* LIBC_SCCS and not lint */
-#include <stdio.h>
+#include <stdarg.h>
#include <limits.h>
+#include <stdio.h>
vsprintf(str, fmt, ap)
char *str;
const char *fmt;
- va_list ap;
+ pthread_va_list ap;
{
int ret;
FILE f;
+ f._file = -1;
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
f._bf._size = f._w = INT_MAX;
diff --git a/lib/libpthread/stdio/vsscanf.c b/lib/libpthread/stdio/vsscanf.c
index 66859145bab..ca3845506cb 100644
--- a/lib/libpthread/stdio/vsscanf.c
+++ b/lib/libpthread/stdio/vsscanf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,16 +37,17 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)vsscanf.c 5.1 (Berkeley) 4/15/91";*/
-static char *rcsid = "$Id: vsscanf.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: vsscanf.c,v 1.1.1.2 1998/07/21 13:22:14 peter Exp $";
#endif /* LIBC_SCCS and not lint */
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
vsscanf(str, fmt, ap)
const char *str;
const char *fmt;
- va_list ap;
+ pthread_va_list ap;
{
int ret;
FILE f;
diff --git a/lib/libpthread/stdio/wbuf.c b/lib/libpthread/stdio/wbuf.c
index 63d8f9e3648..58cb9ad058e 100644
--- a/lib/libpthread/stdio/wbuf.c
+++ b/lib/libpthread/stdio/wbuf.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
diff --git a/lib/libpthread/stdio/wsetup.c b/lib/libpthread/stdio/wsetup.c
index 3ec1e786ecb..71616b1c8c9 100644
--- a/lib/libpthread/stdio/wsetup.c
+++ b/lib/libpthread/stdio/wsetup.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1993, 1994 Chris Provenzano.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,10 +37,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)wsetup.c 5.2 (Berkeley) 2/24/91";*/
-static char *rcsid = "$Id: wsetup.c,v 1.1.1.1 1995/10/18 08:43:09 deraadt Exp $";
+static char *rcsid = "$Id: wsetup.c,v 1.1.1.2 1998/07/21 13:22:17 peter Exp $";
#endif /* LIBC_SCCS and not lint */
-#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "local.h"
@@ -53,8 +53,7 @@ __swsetup(fp)
register FILE *fp;
{
/* make sure stdio is set up */
- if (!__sdidinit)
- __sinit();
+ __sinit ();
/*
* If we are not writing, we had better be reading and writing.