aboutsummaryrefslogtreecommitdiff
path: root/lib/libkse
diff options
context:
space:
mode:
authorJulian Elischer <julian@FreeBSD.org>1996-08-20 08:22:01 +0000
committerJulian Elischer <julian@FreeBSD.org>1996-08-20 08:22:01 +0000
commit0f7d684755aefbcfd70b45d24efc2d39bc505c4c (patch)
treeb14348030d1048f8628b798374a8a061a990aae3 /lib/libkse
parent1bbb22c82e47dbc805e523be5e2fe3d4436761e0 (diff)
downloadsrc-0f7d684755aefbcfd70b45d24efc2d39bc505c4c.tar.gz
src-0f7d684755aefbcfd70b45d24efc2d39bc505c4c.zip
Submitted by: John Birrell <cimaxp1!jb@werple.net.au>
Here are the diffs for libc_r to get it one step closer to P1003.1c These make most of the thread/mutex/condvar structures opaque to the user. There are three functions which have been renamed with _np suffixes because they are extensions to P1003.1c (I did them for JAVA, which needs to suspend/resume threads and also start threads suspended). I've created a new header (pthread_np.h) for the non-POSIX stuff. The egrep tags stuff in /usr/src/lib/libc_r/Makefile that I uncommented doesn't work. I think its best to delete it. I don't think libc_r needs tags anyway, 'cause most of the source is in libc which does have tags. also: Here's the first batch of man pages for the thread functions. The diff to /usr/src/lib/libc_r/Makefile removes some stuff that was inherited from /usr/src/lib/libc/Makefile that should only be done with libc. also: I should have sent this diff with the pthread(3) man page. It allows people to type make -DWANT_LIBC_R world to get libc_r built with the rest of the world. I put this in the pthread(3) man page. The default is still not to build libc_r. also: The diff attached adds a pthread(3) man page to /usr/src/share/man/man3. The idea is that without libc_r installed, this man page will give people enough info to know that they have to build libc_r.
Notes
Notes: svn path=/head/; revision=17706
Diffstat (limited to 'lib/libkse')
-rw-r--r--lib/libkse/Makefile21
-rw-r--r--lib/libkse/sys/Makefile.inc46
-rw-r--r--lib/libkse/thread/Makefile.inc8
-rw-r--r--lib/libkse/thread/thr_attr_destroy.c52
-rw-r--r--lib/libkse/thread/thr_attr_init.c54
-rw-r--r--lib/libkse/thread/thr_attr_setcreatesuspend_np.c51
-rw-r--r--lib/libkse/thread/thr_attr_setstacksize.c50
-rw-r--r--lib/libkse/thread/thr_close.c52
-rw-r--r--lib/libkse/thread/thr_cond.c334
-rw-r--r--lib/libkse/thread/thr_create.c21
-rw-r--r--lib/libkse/thread/thr_exit.c38
-rw-r--r--lib/libkse/thread/thr_fcntl.c1
-rw-r--r--lib/libkse/thread/thr_fork.c2
-rw-r--r--lib/libkse/thread/thr_init.c12
-rw-r--r--lib/libkse/thread/thr_kern.c231
-rw-r--r--lib/libkse/thread/thr_multi_np.c44
-rw-r--r--lib/libkse/thread/thr_mutex.c465
-rw-r--r--lib/libkse/thread/thr_nanosleep.c143
-rw-r--r--lib/libkse/thread/thr_open.c11
-rw-r--r--lib/libkse/thread/thr_private.h148
-rw-r--r--lib/libkse/thread/thr_resume_np.c70
-rw-r--r--lib/libkse/thread/thr_select.c25
-rw-r--r--lib/libkse/thread/thr_sig.c49
-rw-r--r--lib/libkse/thread/thr_sigsuspend.c3
-rw-r--r--lib/libkse/thread/thr_single_np.c44
-rw-r--r--lib/libkse/thread/thr_spec.c20
-rw-r--r--lib/libkse/thread/thr_suspend_np.c67
27 files changed, 1568 insertions, 494 deletions
diff --git a/lib/libkse/Makefile b/lib/libkse/Makefile
index 3fd14d80844a..373fe6592b22 100644
--- a/lib/libkse/Makefile
+++ b/lib/libkse/Makefile
@@ -20,6 +20,7 @@ PRECIOUSLIB= yes
.include "${.CURDIR}/gen/Makefile.inc"
.include "${.CURDIR}/gmon/Makefile.inc"
.include "${.CURDIR}/locale/Makefile.inc"
+.include "${.CURDIR}/man/Makefile.inc"
.include "${.CURDIR}/net/Makefile.inc"
.include "${.CURDIR}/nls/Makefile.inc"
.include "${.CURDIR}/quad/Makefile.inc"
@@ -38,24 +39,8 @@ CFLAGS+= -DYP
.endif
.include "${.CURDIR}/${MACHINE}/sys/Makefile.inc"
-KQSRCS= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \
- lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \
- subdi3.c ucmpdi2.c udivdi3.c umoddi3.c xordi3.c
-KSRCS= bcmp.c ffs.c index.c mcount.c rindex.c strcat.c strcmp.c strcpy.c \
- strlen.c strncpy.c
-
-libkern: libkern.gen libkern.${MACHINE}
-
-libkern.gen: ${KQSRCS} ${KSRCS}
- cp -p ${.CURDIR}/quad/quad.h ${.ALLSRC} /sys/libkern
-
-libkern.${MACHINE}:: ${KMSRCS}
-.if defined(KMSRCS) && !empty(KMSRCS)
- cp -p ${.ALLSRC} /sys/libkern/${MACHINE}
-.endif
-
-#beforeinstall: tags
-# ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc.tags
+beforeinstall: tags
+ ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc_r.tags
tags: ${SRCS}
ctags ${.ALLSRC:M*.c}
diff --git a/lib/libkse/sys/Makefile.inc b/lib/libkse/sys/Makefile.inc
index 3aa9a003e3e1..bca46e44f510 100644
--- a/lib/libkse/sys/Makefile.inc
+++ b/lib/libkse/sys/Makefile.inc
@@ -1,5 +1,4 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/17/93
-# $Id: $
# sys sources
.PATH: ${.CURDIR}/../libc/${MACHINE}/sys ${.CURDIR}/../libc/sys \
@@ -40,16 +39,18 @@ THREADASM= accept.o bind.o close.o connect.o dup.o dup2.o \
shutdown.o sigaction.o sigaltstack.o socket.o socketpair.o \
wait4.o write.o writev.o
-PSEUDO= _exit.o _getlogin.o
+PSEUDO= _getlogin.o
-OBJS+= ${ASM} ${THREADASM} ${PSEUDO}
+THREADPSEUDO= _exit.o
+
+OBJS+= ${ASM} ${THREADASM} ${PSEUDO} ${THREADPSEUDO}
${ASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@${ECHO} creating ${.PREFIX}.o
@printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
@${LD} -x -r ${.PREFIX}.o
- @mv -f a.out ${.PREFIX}.o
+ @mv a.out ${.PREFIX}.o
PASM= ${ASM:.o=.po}
${PASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@@ -57,7 +58,7 @@ ${PASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
@${LD} -x -r ${.PREFIX}.po
- @mv -f a.out ${.PREFIX}.po
+ @mv a.out ${.PREFIX}.po
SASM= ${ASM:.o=.so}
${SASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@@ -67,23 +68,23 @@ ${SASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
${THREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@${ECHO} creating ${.PREFIX}.o
- @printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
+ @printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
@${LD} -x -r ${.PREFIX}.o
- @mv -f a.out ${.PREFIX}.o
+ @mv a.out ${.PREFIX}.o
PTHREADASM= ${THREADASM:.o=.po}
${PTHREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@${ECHO} creating ${.PREFIX}.po
- @printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
+ @printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
@${LD} -x -r ${.PREFIX}.po
- @mv -f a.out ${.PREFIX}.po
+ @mv a.out ${.PREFIX}.po
STHREADASM= ${THREADASM:.o=.so}
${STHREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@${ECHO} creating ${.PREFIX}.so
- @printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
+ @printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
${PSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@@ -91,7 +92,7 @@ ${PSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
@${LD} -x -r ${.PREFIX}.o
- @mv -f a.out ${.PREFIX}.o
+ @mv a.out ${.PREFIX}.o
PPSEUDO=${PSEUDO:.o=.po}
${PPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@@ -99,10 +100,31 @@ ${PPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
@${LD} -x -r ${.PREFIX}.po
- @mv -f a.out ${.PREFIX}.po
+ @mv a.out ${.PREFIX}.po
SPSEUDO=${PSEUDO:.o=.so}
${SPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
@${ECHO} creating ${.PREFIX}.so
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
+
+${THREADPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
+ @${ECHO} creating ${.PREFIX}.o
+ @printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
+ ${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
+ @${LD} -x -r ${.PREFIX}.o
+ @mv a.out ${.PREFIX}.o
+
+THREADPPSEUDO=${THREADPSEUDO:.o=.po}
+${THREADPPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
+ @${ECHO} creating ${.PREFIX}.po
+ @printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
+ ${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
+ @${LD} -x -r ${.PREFIX}.po
+ @mv a.out ${.PREFIX}.po
+
+THREADSPSEUDO=${THREADPSEUDO:.o=.so}
+${THREADSPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
+ @${ECHO} creating ${.PREFIX}.so
+ @printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
+ ${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
diff --git a/lib/libkse/thread/Makefile.inc b/lib/libkse/thread/Makefile.inc
index f37a21fbc58a..72a6e57a56c5 100644
--- a/lib/libkse/thread/Makefile.inc
+++ b/lib/libkse/thread/Makefile.inc
@@ -1,4 +1,4 @@
-# $Id: Makefile.inc,v 1.1 1996/01/22 00:23:03 julian Exp $
+# $Id: Makefile.inc,v 1.2 1996/02/17 02:19:35 jdp Exp $
CPLUSPLUSLIB= cpluspluslib
@@ -7,7 +7,7 @@ CPLUSPLUSLIB= cpluspluslib
SRCS+= \
uthread_accept.c \
- uthread_attr_setcreatesuspend.c \
+ uthread_attr_setcreatesuspend_np.c \
uthread_autoinit.cc \
uthread_bind.c \
uthread_clean.c \
@@ -52,7 +52,7 @@ SRCS+= \
uthread_read.c \
uthread_readv.c \
uthread_recvfrom.c \
- uthread_resume.c \
+ uthread_resume_np.c \
uthread_select.c \
uthread_self.c \
uthread_sendto.c \
@@ -71,7 +71,7 @@ SRCS+= \
uthread_socket.c \
uthread_socketpair.c \
uthread_spec.c \
- uthread_suspend.c \
+ uthread_suspend_np.c \
uthread_wait4.c \
uthread_write.c \
uthread_writev.c \
diff --git a/lib/libkse/thread/thr_attr_destroy.c b/lib/libkse/thread/thr_attr_destroy.c
new file mode 100644
index 000000000000..be6b2a2d7dcb
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_destroy.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_destroy(pthread_attr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ free(*attr);
+ *attr = NULL;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_init.c b/lib/libkse/thread/thr_attr_init.c
new file mode 100644
index 000000000000..7dade978a48f
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_init.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_init(pthread_attr_t *attr)
+{
+ int ret;
+ pthread_attr_t pattr;
+ if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr));
+ *attr = pattr;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_setcreatesuspend_np.c b/lib/libkse/thread/thr_attr_setcreatesuspend_np.c
new file mode 100644
index 000000000000..afe6b23c3cb2
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_setcreatesuspend_np.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->suspend = PTHREAD_CREATE_SUSPENDED;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_attr_setstacksize.c b/lib/libkse/thread/thr_attr_setstacksize.c
new file mode 100644
index 000000000000..5e59798f579b
--- /dev/null
+++ b/lib/libkse/thread/thr_attr_setstacksize.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
+{
+ int ret;
+ if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ (*attr)->stacksize_attr = stacksize;
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_close.c b/lib/libkse/thread/thr_close.c
index f98e056aaab3..26a8fbfd5904 100644
--- a/lib/libkse/thread/thr_close.c
+++ b/lib/libkse/thread/thr_close.c
@@ -30,7 +30,10 @@
* SUCH DAMAGE.
*
*/
+#include <stdlib.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
#include "pthread_private.h"
@@ -38,10 +41,55 @@
int
close(int fd)
{
- int ret;
+ int flags;
+ int ret;
+ int status;
+ struct stat sb;
+
+ /* Lock the file descriptor while the file is closed: */
if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Get file descriptor status. */
+ fstat(fd, &sb);
+
+ /*
+ * Check if the file should be left as blocking.
+ *
+ * This is so that the file descriptors shared with a parent
+ * process aren't left set to non-blocking if the child
+ * closes them prior to exit. An example where this causes
+ * problems with /bin/sh is when a child closes stdin.
+ *
+ * Setting a file as blocking causes problems if a threaded
+ * parent accesses the file descriptor before the child exits.
+ * Once the threaded parent receives a SIGCHLD then it resets
+ * all of its files to non-blocking, and so it is then safe
+ * to access them.
+ *
+ * Pipes are not set to blocking when they are closed, as
+ * the parent and child will normally close the file
+ * descriptor of the end of the pipe that they are not
+ * using, which would then cause any reads to block
+ * indefinitely.
+ */
+ if ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ }
+
+ /* Close the file descriptor: */
ret = _thread_sys_close(fd);
- _thread_fd_unlock(fd, FD_RDWR);
+
+ /* Free the file descriptor table entry: */
+ free(_thread_fd_table[fd]);
+ _thread_fd_table[fd] = NULL;
+
+ /* Unblock signals again: */
+ _thread_kern_sig_unblock(status);
}
return (ret);
}
diff --git a/lib/libkse/thread/thr_cond.c b/lib/libkse/thread/thr_cond.c
index 930f31aea623..0f9f30230ba0 100644
--- a/lib/libkse/thread/thr_cond.c
+++ b/lib/libkse/thread/thr_cond.c
@@ -40,41 +40,56 @@ int
pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr)
{
enum pthread_cond_type type;
+ pthread_cond_t pcond;
int rval = 0;
- /*
- * Check if a pointer to a condition variable attribute structure was
- * passed by the caller:
- */
- if (cond_attr != NULL) {
- /* Default to a fast condition variable: */
- type = cond_attr->c_type;
+ if (cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
} else {
- /* Default to a fast condition variable: */
- type = COND_TYPE_FAST;
- }
-
- /* Process according to condition variable type: */
- switch (type) {
- /* Fast condition variable: */
- case COND_TYPE_FAST:
- /* Nothing to do here. */
- break;
+ /*
+ * Check if a pointer to a condition variable attribute structure was
+ * passed by the caller:
+ */
+ if (cond_attr != NULL && *cond_attr != NULL) {
+ /* Default to a fast condition variable: */
+ type = (*cond_attr)->c_type;
+ } else {
+ /* Default to a fast condition variable: */
+ type = COND_TYPE_FAST;
+ }
- /* Trap invalid condition variable types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- rval = -1;
- break;
- }
+ /* Process according to condition variable type: */
+ switch (type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
- /* Check for no errors: */
- if (rval == 0) {
- /* Initialise the condition variable structure: */
- _thread_queue_init(&cond->c_queue);
- cond->c_flags |= COND_FLAGS_INITED;
- cond->c_type = type;
+ /* Check for no errors: */
+ if (rval == 0) {
+ if ((pcond = (pthread_cond_t) malloc(sizeof(struct pthread_cond))) == NULL) {
+ errno = ENOMEM;
+ rval = -1;
+ } else {
+ /*
+ * Initialise the condition variable
+ * structure:
+ */
+ _thread_queue_init(&pcond->c_queue);
+ pcond->c_flags |= COND_FLAGS_INITED;
+ pcond->c_type = type;
+ *cond = pcond;
+ }
+ }
}
/* Return the completion status: */
return (rval);
@@ -85,26 +100,33 @@ pthread_cond_destroy(pthread_cond_t * cond)
{
int rval = 0;
- /* Process according to condition variable type: */
- switch (cond->c_type) {
- /* Fast condition variable: */
- case COND_TYPE_FAST:
- /* Nothing to do here. */
- break;
-
- /* Trap invalid condition variable types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
rval = -1;
- break;
- }
+ } else {
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
- /* Check for errors: */
- if (rval == 0) {
- /* Destroy the contents of the condition structure: */
- _thread_queue_init(&cond->c_queue);
- cond->c_flags = 0;
+ /* Check for errors: */
+ if (rval == 0) {
+ /* Destroy the contents of the condition structure: */
+ _thread_queue_init(&(*cond)->c_queue);
+ (*cond)->c_flags = 0;
+ free(*cond);
+ *cond = NULL;
+ }
}
/* Return the completion status: */
return (rval);
@@ -116,40 +138,45 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
int rval = 0;
int status;
- /* Block signals: */
- _thread_kern_sig_block(&status);
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
- /* Process according to condition variable type: */
- switch (cond->c_type) {
- /* Fast condition variable: */
- case COND_TYPE_FAST:
- /* Queue the running thread for the condition variable: */
- _thread_queue_enq(&cond->c_queue, _thread_run);
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Queue the running thread for the condition variable: */
+ _thread_queue_enq(&(*cond)->c_queue, _thread_run);
- /* Unlock the mutex: */
- pthread_mutex_unlock(mutex);
+ /* Unlock the mutex: */
+ pthread_mutex_unlock(mutex);
- /* Schedule the next thread: */
- _thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
- /* Block signals: */
- _thread_kern_sig_block(NULL);
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
- /* Lock the mutex: */
- rval = pthread_mutex_lock(mutex);
- break;
+ /* Lock the mutex: */
+ rval = pthread_mutex_lock(mutex);
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
+ }
- /* Trap invalid condition variable types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- rval = -1;
- break;
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
}
- /* Unblock signals: */
- _thread_kern_sig_unblock(status);
-
/* Return the completion status: */
return (rval);
}
@@ -161,60 +188,70 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
int rval = 0;
int status;
- /* Block signals: */
- _thread_kern_sig_block(&status);
-
- /* Process according to condition variable type: */
- switch (cond->c_type) {
- /* Fast condition variable: */
- case COND_TYPE_FAST:
- /* Set the wakeup time: */
- _thread_run->wakeup_time.ts_sec = abstime->ts_sec;
- _thread_run->wakeup_time.ts_nsec = abstime->ts_nsec;
-
- /* Reset the timeout flag: */
- _thread_run->timeout = 0;
-
- /* Queue the running thread for the condition variable: */
- _thread_queue_enq(&cond->c_queue, _thread_run);
-
- /* Unlock the mutex: */
- if ((rval = pthread_mutex_unlock(mutex)) != 0) {
- /*
- * Cannot unlock the mutex, so remove the running
- * thread from the condition variable queue:
- */
- _thread_queue_deq(&cond->c_queue);
- } else {
- /* Schedule the next thread: */
- _thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
-
- /* Block signals: */
- _thread_kern_sig_block(NULL);
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Set the wakeup time: */
+#if defined(__FreeBSD__)
+ _thread_run->wakeup_time.ts_sec = abstime->ts_sec;
+ _thread_run->wakeup_time.ts_nsec = abstime->ts_nsec;
+#else
+ _thread_run->wakeup_time.tv_sec = abstime->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = abstime->tv_nsec;
+#endif
- /* Lock the mutex: */
- if ((rval = pthread_mutex_lock(mutex)) != 0) {
- }
- /* Check if the wait timed out: */
- else if (_thread_run->timeout) {
- /* Return a timeout error: */
- _thread_seterrno(_thread_run, EAGAIN);
- rval = -1;
+ /* Reset the timeout flag: */
+ _thread_run->timeout = 0;
+
+ /* Queue the running thread for the condition variable: */
+ _thread_queue_enq(&(*cond)->c_queue, _thread_run);
+
+ /* Unlock the mutex: */
+ if ((rval = pthread_mutex_unlock(mutex)) != 0) {
+ /*
+ * Cannot unlock the mutex, so remove the running
+ * thread from the condition variable queue:
+ */
+ _thread_queue_deq(&(*cond)->c_queue);
+ } else {
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Lock the mutex: */
+ if ((rval = pthread_mutex_lock(mutex)) != 0) {
+ }
+ /* Check if the wait timed out: */
+ else if (_thread_run->timeout) {
+ /* Return a timeout error: */
+ errno = EAGAIN;
+ rval = -1;
+ }
}
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
}
- break;
- /* Trap invalid condition variable types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- rval = -1;
- break;
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
}
- /* Unblock signals: */
- _thread_kern_sig_unblock(status);
-
/* Return the completion status: */
return (rval);
}
@@ -226,31 +263,36 @@ pthread_cond_signal(pthread_cond_t * cond)
int status;
pthread_t pthread;
- /* Block signals: */
- _thread_kern_sig_block(&status);
-
- /* Process according to condition variable type: */
- switch (cond->c_type) {
- /* Fast condition variable: */
- case COND_TYPE_FAST:
- /* Bring the next thread off the condition queue: */
- if ((pthread = _thread_queue_deq(&cond->c_queue)) != NULL) {
- /* Allow the thread to run: */
- pthread->state = PS_RUNNING;
+ if (cond == NULL || *cond == NULL) {
+ errno = EINVAL;
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to condition variable type: */
+ switch ((*cond)->c_type) {
+ /* Fast condition variable: */
+ case COND_TYPE_FAST:
+ /* Bring the next thread off the condition queue: */
+ if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
+ /* Allow the thread to run: */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ rval = -1;
+ break;
}
- break;
- /* Trap invalid condition variable types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- rval = -1;
- break;
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
}
- /* Unblock signals: */
- _thread_kern_sig_unblock(status);
-
/* Return the completion status: */
return (rval);
}
@@ -266,11 +308,11 @@ pthread_cond_broadcast(pthread_cond_t * cond)
_thread_kern_sig_block(&status);
/* Process according to condition variable type: */
- switch (cond->c_type) {
+ switch ((*cond)->c_type) {
/* Fast condition variable: */
case COND_TYPE_FAST:
/* Enter a loop to bring all threads off the condition queue: */
- while ((pthread = _thread_queue_deq(&cond->c_queue)) != NULL) {
+ while ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
/* Allow the thread to run: */
pthread->state = PS_RUNNING;
}
@@ -279,7 +321,7 @@ pthread_cond_broadcast(pthread_cond_t * cond)
/* Trap invalid condition variable types: */
default:
/* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
+ errno = EINVAL;
rval = -1;
break;
}
diff --git a/lib/libkse/thread/thr_create.c b/lib/libkse/thread/thr_create.c
index e6db38144f64..1d57f8a1626d 100644
--- a/lib/libkse/thread/thr_create.c
+++ b/lib/libkse/thread/thr_create.c
@@ -49,6 +49,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
int ret = 0;
int status;
pthread_t new_thread;
+ pthread_attr_t pattr;
void *stack;
/* Block signals: */
@@ -60,15 +61,17 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
ret = EAGAIN;
} else {
/* Check if default thread attributes are required: */
- if (attr == NULL) {
+ if (attr == NULL || *attr == NULL) {
/* Use the default thread attributes: */
- attr = &pthread_attr_default;
+ pattr = &pthread_attr_default;
+ } else {
+ pattr = *attr;
}
/* Check if a stack was specified in the thread attributes: */
- if ((stack = attr->stackaddr_attr) != NULL) {
+ if ((stack = pattr->stackaddr_attr) != NULL) {
}
/* Allocate memory for the stack: */
- else if ((stack = (void *) malloc(attr->stacksize_attr)) == NULL) {
+ else if ((stack = (void *) malloc(pattr->stacksize_attr)) == NULL) {
/* Insufficient memory to create a thread: */
ret = EAGAIN;
free(new_thread);
@@ -83,7 +86,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
new_thread->stack = stack;
new_thread->start_routine = start_routine;
new_thread->arg = arg;
- if (attr->suspend == PTHREAD_CREATE_SUSPENDED) {
+ if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) {
new_thread->state = PS_SUSPENDED;
} else {
new_thread->state = PS_RUNNING;
@@ -148,19 +151,19 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
/* The stack starts high and builds down: */
#if defined(__FreeBSD__)
- new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + attr->stacksize_attr - sizeof(double));
+ new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + pattr->stacksize_attr - sizeof(double));
#elif defined(__NetBSD__)
#if defined(__alpha)
- new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + attr->stacksize_attr - sizeof(double);
+ new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
#else
- new_thread->saved_jmp_buf[2] = (long) new_thread->stack + attr->stacksize_attr - sizeof(double);
+ new_thread->saved_jmp_buf[2] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
#endif
#else
#error "Don't recognize this operating system!"
#endif
/* Copy the thread attributes: */
- memcpy(&new_thread->attr, attr, sizeof(pthread_attr_t));
+ memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
/*
* Check if this thread is to inherit the scheduling
diff --git a/lib/libkse/thread/thr_exit.c b/lib/libkse/thread/thr_exit.c
index 292fce9c0fb8..60662060e01e 100644
--- a/lib/libkse/thread/thr_exit.c
+++ b/lib/libkse/thread/thr_exit.c
@@ -31,11 +31,49 @@
*
*/
#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
#include <string.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
#include "pthread_private.h"
+void _exit(int status)
+{
+ int flags;
+ int i;
+ struct itimerval itimer;
+
+ /* Disable the interval timer: */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = 0;
+ setitimer(ITIMER_VIRTUAL, &itimer, NULL);
+
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /*
+ * Enter a loop to set all file descriptors to blocking
+ * if they were not created as non-blocking:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file descriptor is in use: */
+ if (_thread_fd_table[i] != NULL &&
+ !(_thread_fd_table[i]->flags & O_NONBLOCK)) {
+ /* Get the current flags: */
+ flags = _thread_sys_fcntl(i, F_GETFL, NULL);
+ /* Clear the nonblocking file descriptor flag: */
+ _thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
+ }
+ }
+
+ /* Call the _exit syscall: */
+ _thread_sys__exit(status);
+}
+
void
_thread_exit(char *fname, int lineno, char *string)
{
diff --git a/lib/libkse/thread/thr_fcntl.c b/lib/libkse/thread/thr_fcntl.c
index ae069b8e36a9..f83ee5098f37 100644
--- a/lib/libkse/thread/thr_fcntl.c
+++ b/lib/libkse/thread/thr_fcntl.c
@@ -31,6 +31,7 @@
*
*/
#include <stdarg.h>
+#include <unistd.h>
#include <fcntl.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
diff --git a/lib/libkse/thread/thr_fork.c b/lib/libkse/thread/thr_fork.c
index 6e7ca0d43b44..19f674d39552 100644
--- a/lib/libkse/thread/thr_fork.c
+++ b/lib/libkse/thread/thr_fork.c
@@ -31,6 +31,8 @@
*
*/
#include <errno.h>
+#include <string.h>
+#include <unistd.h>
#include <fcntl.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
diff --git a/lib/libkse/thread/thr_init.c b/lib/libkse/thread/thr_init.c
index 6139935176e1..d044063ce9d4 100644
--- a/lib/libkse/thread/thr_init.c
+++ b/lib/libkse/thread/thr_init.c
@@ -202,18 +202,6 @@ _thread_main(int argc, char *argv[], char *env)
_thread_init();
return (main(argc, argv, env));
}
-#else
-/*
- * Force our auto-initialization module to be pulled in from the library,
- * by referencing a symbol that is defined in it.
- *
- * The auto-initialization module is a small C++ module. It has a static
- * constructor that calls _thread_init() automatically, at the beginning
- * of program execution. That eliminates the need for any special hooks
- * in crt0.o.
- */
-extern int _thread_autoinit_dummy_decl;
-static int *_thread_autoinit_dummy_ref = &_thread_autoinit_dummy_decl;
#endif
#else
/*
diff --git a/lib/libkse/thread/thr_kern.c b/lib/libkse/thread/thr_kern.c
index 35e8e29b9711..c6759cfe3b3d 100644
--- a/lib/libkse/thread/thr_kern.c
+++ b/lib/libkse/thread/thr_kern.c
@@ -250,18 +250,30 @@ __asm__("fnsave %0": :"m"(*fdata));
pthread->state == PS_FDW_WAIT ||
pthread->state == PS_SELECT_WAIT) {
/* Check if this thread is to wait forever: */
+#if defined(__FreeBSD__)
if (pthread->wakeup_time.ts_sec == -1) {
+#else
+ if (pthread->wakeup_time.tv_sec == -1) {
+#endif
}
/*
* Check if this thread is to wakeup
* immediately or if it is past its wakeup
* time:
*/
+#if defined(__FreeBSD__)
else if ((pthread->wakeup_time.ts_sec == 0 &&
pthread->wakeup_time.ts_nsec == 0) ||
(ts.ts_sec > pthread->wakeup_time.ts_sec) ||
((ts.ts_sec == pthread->wakeup_time.ts_sec) &&
(ts.ts_nsec >= pthread->wakeup_time.ts_nsec))) {
+#else
+ else if ((pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) ||
+ (ts.tv_sec > pthread->wakeup_time.tv_sec) ||
+ ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
+ (ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) {
+#endif
/*
* Check if this thread is waiting on
* select:
@@ -364,9 +376,48 @@ __asm__("fnsave %0": :"m"(*fdata));
}
/*
* Enter a loop to look for the first thread of the highest
- * priority:
+ * priority that is ready to run:
*/
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
/* Check if the current thread is unable to run: */
if (pthread->state != PS_RUNNING) {
}
@@ -392,6 +443,45 @@ __asm__("fnsave %0": :"m"(*fdata));
* least recently.
*/
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
/* Check if the current thread is unable to run: */
if (pthread->state != PS_RUNNING) {
/* Ignore threads that are not ready to run. */
@@ -446,6 +536,45 @@ __asm__("fnsave %0": :"m"(*fdata));
* priority. 3. Became inactive least recently.
*/
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if in single-threaded mode: */
+ if (_thread_single != NULL) {
+ /*
+ * Check if the current thread is
+ * the thread for which single-threaded
+ * mode is enabled:
+ */
+ if (pthread == _thread_single) {
+ /*
+ * This thread is allowed
+ * to run.
+ */
+ } else {
+ /*
+ * Walk up the signal handler
+ * parent thread tree to see
+ * if the current thread is
+ * descended from the thread
+ * for which single-threaded
+ * mode is enabled.
+ */
+ pthread_nxt = pthread;
+ while(pthread_nxt != NULL &&
+ pthread_nxt != _thread_single) {
+ pthread_nxt = pthread->parent_thread;
+ }
+ /*
+ * Check if the current
+ * thread is not descended
+ * from the thread for which
+ * single-threaded mode is
+ * enabled.
+ */
+ if (pthread_nxt == NULL)
+ /* Ignore this thread. */
+ continue;
+ }
+ }
+
/*
* Check if the current thread is unable to
* run:
@@ -565,22 +694,37 @@ __asm__("fnsave %0": :"m"(*fdata));
* Check if this thread is to
* wait forever:
*/
+#if defined(__FreeBSD__)
if (pthread->wakeup_time.ts_sec == -1) {
+#else
+ if (pthread->wakeup_time.tv_sec == -1) {
+#endif
}
/*
* Check if this thread is to
* wakeup immediately:
*/
+#if defined(__FreeBSD__)
else if (pthread->wakeup_time.ts_sec == 0 &&
pthread->wakeup_time.ts_nsec == 0) {
+#else
+ else if (pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) {
+#endif
}
/*
* Check if the current time
* is after the wakeup time:
*/
+#if defined(__FreeBSD__)
else if ((ts.ts_sec > pthread->wakeup_time.ts_sec) ||
((ts.ts_sec == pthread->wakeup_time.ts_sec) &&
(ts.ts_nsec > pthread->wakeup_time.ts_nsec))) {
+#else
+ else if ((ts.tv_sec > pthread->wakeup_time.tv_sec) ||
+ ((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
+ (ts.tv_nsec > pthread->wakeup_time.tv_nsec))) {
+#endif
} else {
/*
* Calculate the time
@@ -589,16 +733,26 @@ __asm__("fnsave %0": :"m"(*fdata));
* for the clock
* resolution:
*/
+#if defined(__FreeBSD__)
ts1.ts_sec = pthread->wakeup_time.ts_sec - ts.ts_sec;
ts1.ts_nsec = pthread->wakeup_time.ts_nsec - ts.ts_nsec +
CLOCK_RES_NSEC;
+#else
+ ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
+ ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
+ CLOCK_RES_NSEC;
+#endif
/*
* Check for
* underflow of the
* nanosecond field:
*/
+#if defined(__FreeBSD__)
if (ts1.ts_nsec < 0) {
+#else
+ if (ts1.tv_nsec < 0) {
+#endif
/*
* Allow for
* the
@@ -607,15 +761,24 @@ __asm__("fnsave %0": :"m"(*fdata));
* nanosecond
* field:
*/
+#if defined(__FreeBSD__)
ts1.ts_sec--;
ts1.ts_nsec += 1000000000;
+#else
+ ts1.tv_sec--;
+ ts1.tv_nsec += 1000000000;
+#endif
}
/*
* Check for overflow
* of the nanosecond
* field:
*/
+#if defined(__FreeBSD__)
if (ts1.ts_nsec >= 1000000000) {
+#else
+ if (ts1.tv_nsec >= 1000000000) {
+#endif
/*
* Allow for
* the
@@ -624,8 +787,13 @@ __asm__("fnsave %0": :"m"(*fdata));
* nanosecond
* field:
*/
+#if defined(__FreeBSD__)
ts1.ts_sec++;
ts1.ts_nsec -= 1000000000;
+#else
+ ts1.tv_sec++;
+ ts1.tv_nsec -= 1000000000;
+#endif
}
/*
* Convert the
@@ -1100,11 +1268,20 @@ _thread_kern_select(int wait_reqd)
*/
if (wait_reqd && settimeout) {
/* Check if this thread wants to wait forever: */
+#if defined(__FreeBSD__)
if (pthread->wakeup_time.ts_sec == -1) {
+#else
+ if (pthread->wakeup_time.tv_sec == -1) {
+#endif
}
/* Check if this thread doesn't want to wait at all: */
+#if defined(__FreeBSD__)
else if (pthread->wakeup_time.ts_sec == 0 &&
pthread->wakeup_time.ts_nsec == 0) {
+#else
+ else if (pthread->wakeup_time.tv_sec == 0 &&
+ pthread->wakeup_time.tv_nsec == 0) {
+#endif
/* Override the caller's request to wait: */
wait_reqd = 0;
} else {
@@ -1112,33 +1289,57 @@ _thread_kern_select(int wait_reqd)
* Calculate the time until this thread is
* ready, allowing for the clock resolution:
*/
+#if defined(__FreeBSD__)
ts1.ts_sec = pthread->wakeup_time.ts_sec - ts.ts_sec;
ts1.ts_nsec = pthread->wakeup_time.ts_nsec - ts.ts_nsec +
CLOCK_RES_NSEC;
+#else
+ ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
+ ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
+ CLOCK_RES_NSEC;
+#endif
/*
* Check for underflow of the nanosecond
* field:
*/
+#if defined(__FreeBSD__)
if (ts1.ts_nsec < 0) {
+#else
+ if (ts1.tv_nsec < 0) {
+#endif
/*
* Allow for the underflow of the
* nanosecond field:
*/
+#if defined(__FreeBSD__)
ts1.ts_sec--;
ts1.ts_nsec += 1000000000;
+#else
+ ts1.tv_sec--;
+ ts1.tv_nsec += 1000000000;
+#endif
}
/*
* Check for overflow of the nanosecond
* field:
*/
+#if defined(__FreeBSD__)
if (ts1.ts_nsec >= 1000000000) {
+#else
+ if (ts1.tv_nsec >= 1000000000) {
+#endif
/*
* Allow for the overflow of the
* nanosecond field:
*/
+#if defined(__FreeBSD__)
ts1.ts_sec++;
ts1.ts_nsec -= 1000000000;
+#else
+ ts1.tv_sec++;
+ ts1.tv_nsec -= 1000000000;
+#endif
}
/*
* Convert the timespec structure to a
@@ -1552,28 +1753,56 @@ _thread_kern_set_timeout(struct timespec * timeout)
* Set the wakeup time to something that can be recognised as
* different to an actual time of day:
*/
+#if defined(__FreeBSD__)
_thread_run->wakeup_time.ts_sec = -1;
_thread_run->wakeup_time.ts_nsec = -1;
+#else
+ _thread_run->wakeup_time.tv_sec = -1;
+ _thread_run->wakeup_time.tv_nsec = -1;
+#endif
}
/* Check if no waiting is required: */
+#if defined(__FreeBSD__)
else if (timeout->ts_sec == 0 && timeout->ts_nsec == 0) {
+#else
+ else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
+#endif
/* Set the wake up time to 'immediately': */
+#if defined(__FreeBSD__)
_thread_run->wakeup_time.ts_sec = 0;
_thread_run->wakeup_time.ts_nsec = 0;
+#else
+ _thread_run->wakeup_time.tv_sec = 0;
+ _thread_run->wakeup_time.tv_nsec = 0;
+#endif
} else {
/* Get the current time: */
gettimeofday(&tv, NULL);
TIMEVAL_TO_TIMESPEC(&tv, &current_time);
/* Calculate the time for the current thread to wake up: */
+#if defined(__FreeBSD__)
_thread_run->wakeup_time.ts_sec = current_time.ts_sec + timeout->ts_sec;
_thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + timeout->ts_nsec;
+#else
+ _thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec;
+#endif
/* Check if the nanosecond field needs to wrap: */
+#if defined(__FreeBSD__)
if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
+#else
+ if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
+#endif
/* Wrap the nanosecond field: */
+#if defined(__FreeBSD__)
_thread_run->wakeup_time.ts_sec += 1;
_thread_run->wakeup_time.ts_nsec -= 1000000000;
+#else
+ _thread_run->wakeup_time.tv_sec += 1;
+ _thread_run->wakeup_time.tv_nsec -= 1000000000;
+#endif
}
}
return;
diff --git a/lib/libkse/thread/thr_multi_np.c b/lib/libkse/thread/thr_multi_np.c
new file mode 100644
index 000000000000..64f360fdacfe
--- /dev/null
+++ b/lib/libkse/thread/thr_multi_np.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_multi_np()
+{
+ /* Return to multi-threaded scheduling mode: */
+ _thread_single = NULL;
+ return(0);
+}
+#endif
diff --git a/lib/libkse/thread/thr_mutex.c b/lib/libkse/thread/thr_mutex.c
index 0fc9fbba3e50..dc9be3c5ff78 100644
--- a/lib/libkse/thread/thr_mutex.c
+++ b/lib/libkse/thread/thr_mutex.c
@@ -41,35 +41,95 @@ pthread_mutex_init(pthread_mutex_t * mutex,
const pthread_mutexattr_t * mutex_attr)
{
enum pthread_mutextype type;
+ pthread_mutex_t pmutex;
int ret = 0;
int status;
- /* Check if the mutex attributes specify some mutex other than fast: */
- if (mutex_attr != NULL && mutex_attr->m_type != MUTEX_TYPE_FAST) {
- /* Check if the mutex type is out of range: */
- if (mutex_attr->m_type >= MUTEX_TYPE_MAX) {
+ if (mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Check if default mutex attributes: */
+ if (mutex_attr == NULL || *mutex_attr == NULL) {
+ /* Default to a fast mutex: */
+ type = MUTEX_TYPE_FAST;
+ } else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) {
/* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
+ errno = EINVAL;
ret = -1;
} else {
/* Use the requested mutex type: */
- type = mutex_attr->m_type;
+ type = (*mutex_attr)->m_type;
+ }
+
+ /* Check no errors so far: */
+ if (ret == 0) {
+ if ((pmutex = (pthread_mutex_t) malloc(sizeof(struct pthread_mutex))) == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ /* Reset the mutex flags: */
+ pmutex->m_flags = 0;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to mutex type: */
+ switch (type) {
+ /* Fast mutex: */
+ case MUTEX_TYPE_FAST:
+ /* Nothing to do here. */
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Reset the mutex count: */
+ pmutex->m_data.m_count = 0;
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+ if (ret == 0) {
+ /* Initialise the rest of the mutex: */
+ _thread_queue_init(&pmutex->m_queue);
+ pmutex->m_flags |= MUTEX_FLAGS_INITED;
+ pmutex->m_owner = NULL;
+ pmutex->m_type = type;
+ *mutex = pmutex;
+ } else {
+ free(pmutex);
+ *mutex = NULL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
}
- } else {
- /* Default to a fast mutex: */
- type = MUTEX_TYPE_FAST;
}
+ /* Return the completion status: */
+ return (ret);
+}
- /* Check no errors so far: */
- if (ret == 0) {
- /* Reset the mutex flags: */
- mutex->m_flags = 0;
+int
+pthread_mutex_destroy(pthread_mutex_t * mutex)
+{
+ int ret = 0;
+ int status;
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
/* Block signals: */
_thread_kern_sig_block(&status);
/* Process according to mutex type: */
- switch (type) {
+ switch ((*mutex)->m_type) {
/* Fast mutex: */
case MUTEX_TYPE_FAST:
/* Nothing to do here. */
@@ -78,67 +138,25 @@ pthread_mutex_init(pthread_mutex_t * mutex,
/* Counting mutex: */
case MUTEX_TYPE_COUNTING_FAST:
/* Reset the mutex count: */
- mutex->m_data.m_count = 0;
+ (*mutex)->m_data.m_count = 0;
break;
- /* Trap invalid mutex types: */
+ /* Trap undefined mutex types: */
default:
/* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
+ errno = EINVAL;
ret = -1;
break;
}
- /* Initialise the rest of the mutex: */
- _thread_queue_init(&mutex->m_queue);
- mutex->m_flags |= MUTEX_FLAGS_INITED;
- mutex->m_owner = NULL;
- mutex->m_type = type;
+ /* Clean up the mutex in case that others want to use it: */
+ _thread_queue_init(&(*mutex)->m_queue);
+ (*mutex)->m_owner = NULL;
+ (*mutex)->m_flags = 0;
/* Unblock signals: */
_thread_kern_sig_unblock(status);
}
- /* Return the completion status: */
- return (ret);
-}
-
-int
-pthread_mutex_destroy(pthread_mutex_t * mutex)
-{
- int ret = 0;
- int status;
-
- /* Block signals: */
- _thread_kern_sig_block(&status);
-
- /* Process according to mutex type: */
- switch (mutex->m_type) {
- /* Fast mutex: */
- case MUTEX_TYPE_FAST:
- /* Nothing to do here. */
- break;
-
- /* Counting mutex: */
- case MUTEX_TYPE_COUNTING_FAST:
- /* Reset the mutex count: */
- mutex->m_data.m_count = 0;
- break;
-
- /* Trap undefined mutex types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- ret = -1;
- break;
- }
-
- /* Clean up the mutex in case that others want to use it: */
- _thread_queue_init(&mutex->m_queue);
- mutex->m_owner = NULL;
- mutex->m_flags = 0;
-
- /* Unblock signals: */
- _thread_kern_sig_unblock(status);
/* Return the completion status: */
return (ret);
@@ -150,56 +168,61 @@ pthread_mutex_trylock(pthread_mutex_t * mutex)
int ret = 0;
int status;
- /* Block signals: */
- _thread_kern_sig_block(&status);
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
- /* Process according to mutex type: */
- switch (mutex->m_type) {
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
/* Fast mutex: */
- case MUTEX_TYPE_FAST:
- /* Check if this mutex is not locked: */
- if (mutex->m_owner == NULL) {
- /* Lock the mutex for the running thread: */
- mutex->m_owner = _thread_run;
- } else {
- /* Return a busy error: */
- _thread_seterrno(_thread_run, EBUSY);
- ret = -1;
- }
- break;
-
- /* Counting mutex: */
- case MUTEX_TYPE_COUNTING_FAST:
- /* Check if this mutex is locked: */
- if (mutex->m_owner != NULL) {
- /*
- * Check if the mutex is locked by the running
- * thread:
- */
- if (mutex->m_owner == _thread_run) {
- /* Increment the lock count: */
- mutex->m_data.m_count++;
+ case MUTEX_TYPE_FAST:
+ /* Check if this mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for the running thread: */
+ (*mutex)->m_owner = _thread_run;
} else {
/* Return a busy error: */
- _thread_seterrno(_thread_run, EBUSY);
+ errno = EBUSY;
ret = -1;
}
- } else {
- /* Lock the mutex for the running thread: */
- mutex->m_owner = _thread_run;
- }
- break;
+ break;
+
+ /* Counting mutex: */
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Check if this mutex is locked: */
+ if ((*mutex)->m_owner != NULL) {
+ /*
+ * Check if the mutex is locked by the running
+ * thread:
+ */
+ if ((*mutex)->m_owner == _thread_run) {
+ /* Increment the lock count: */
+ (*mutex)->m_data.m_count++;
+ } else {
+ /* Return a busy error: */
+ errno = EBUSY;
+ ret = -1;
+ }
+ } else {
+ /* Lock the mutex for the running thread: */
+ (*mutex)->m_owner = _thread_run;
+ }
+ break;
/* Trap invalid mutex types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- ret = -1;
- break;
- }
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
- /* Unblock signals: */
- _thread_kern_sig_unblock(status);
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
/* Return the completion status: */
return (ret);
@@ -211,81 +234,86 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
int ret = 0;
int status;
- /* Block signals: */
- _thread_kern_sig_block(&status);
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
- /* Process according to mutex type: */
- switch (mutex->m_type) {
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
/* Fast mutexes do not check for any error conditions: */
- case MUTEX_TYPE_FAST:
- /*
- * Enter a loop to wait for the mutex to be locked by the
- * current thread:
- */
- while (mutex->m_owner != _thread_run) {
- /* Check if the mutex is not locked: */
- if (mutex->m_owner == NULL) {
- /* Lock the mutex for this thread: */
- mutex->m_owner = _thread_run;
- } else {
- /*
- * Join the queue of threads waiting to lock
- * the mutex:
- */
- _thread_queue_enq(&mutex->m_queue, _thread_run);
-
- /* Block signals: */
- _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
-
- /* Block signals: */
- _thread_kern_sig_block(NULL);
+ case MUTEX_TYPE_FAST:
+ /*
+ * Enter a loop to wait for the mutex to be locked by the
+ * current thread:
+ */
+ while ((*mutex)->m_owner != _thread_run) {
+ /* Check if the mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for this thread: */
+ (*mutex)->m_owner = _thread_run;
+ } else {
+ /*
+ * Join the queue of threads waiting to lock
+ * the mutex:
+ */
+ _thread_queue_enq(&(*mutex)->m_queue, _thread_run);
+
+ /* Block signals: */
+ _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+ }
}
- }
- break;
+ break;
/* Counting mutex: */
- case MUTEX_TYPE_COUNTING_FAST:
- /*
- * Enter a loop to wait for the mutex to be locked by the
- * current thread:
- */
- while (mutex->m_owner != _thread_run) {
- /* Check if the mutex is not locked: */
- if (mutex->m_owner == NULL) {
- /* Lock the mutex for this thread: */
- mutex->m_owner = _thread_run;
-
- /* Reset the lock count for this mutex: */
- mutex->m_data.m_count = 0;
- } else {
- /*
- * Join the queue of threads waiting to lock
- * the mutex:
- */
- _thread_queue_enq(&mutex->m_queue, _thread_run);
-
- /* Block signals: */
- _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
-
- /* Block signals: */
- _thread_kern_sig_block(NULL);
+ case MUTEX_TYPE_COUNTING_FAST:
+ /*
+ * Enter a loop to wait for the mutex to be locked by the
+ * current thread:
+ */
+ while ((*mutex)->m_owner != _thread_run) {
+ /* Check if the mutex is not locked: */
+ if ((*mutex)->m_owner == NULL) {
+ /* Lock the mutex for this thread: */
+ (*mutex)->m_owner = _thread_run;
+
+ /* Reset the lock count for this mutex: */
+ (*mutex)->m_data.m_count = 0;
+ } else {
+ /*
+ * Join the queue of threads waiting to lock
+ * the mutex:
+ */
+ _thread_queue_enq(&(*mutex)->m_queue, _thread_run);
+
+ /* Block signals: */
+ _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+ }
}
- }
- /* Increment the lock count for this mutex: */
- mutex->m_data.m_count++;
- break;
+ /* Increment the lock count for this mutex: */
+ (*mutex)->m_data.m_count++;
+ break;
/* Trap invalid mutex types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- ret = -1;
- break;
- }
+ default:
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
- /* Unblock signals: */
- _thread_kern_sig_unblock(status);
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
/* Return the completion status: */
return (ret);
@@ -297,63 +325,68 @@ pthread_mutex_unlock(pthread_mutex_t * mutex)
int ret = 0;
int status;
- /* Block signals: */
- _thread_kern_sig_block(&status);
+ if (mutex == NULL || *mutex == NULL) {
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
- /* Process according to mutex type: */
- switch (mutex->m_type) {
+ /* Process according to mutex type: */
+ switch ((*mutex)->m_type) {
/* Fast mutexes do not check for any error conditions: */
- case MUTEX_TYPE_FAST:
- /* Check if the running thread is not the owner of the mutex: */
- if (mutex->m_owner != _thread_run) {
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- ret = -1;
- }
- /*
- * Get the next thread from the queue of threads waiting on
- * the mutex:
- */
- else if ((mutex->m_owner = _thread_queue_deq(&mutex->m_queue)) != NULL) {
- /* Allow the new owner of the mutex to run: */
- mutex->m_owner->state = PS_RUNNING;
- }
- break;
+ case MUTEX_TYPE_FAST:
+ /* Check if the running thread is not the owner of the mutex: */
+ if ((*mutex)->m_owner != _thread_run) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ }
+ /*
+ * Get the next thread from the queue of threads waiting on
+ * the mutex:
+ */
+ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
+ /* Allow the new owner of the mutex to run: */
+ (*mutex)->m_owner->state = PS_RUNNING;
+ }
+ break;
/* Counting mutex: */
- case MUTEX_TYPE_COUNTING_FAST:
- /* Check if the running thread is not the owner of the mutex: */
- if (mutex->m_owner != _thread_run) {
+ case MUTEX_TYPE_COUNTING_FAST:
+ /* Check if the running thread is not the owner of the mutex: */
+ if ((*mutex)->m_owner != _thread_run) {
+ /* Return an invalid argument error: */
+ errno = EINVAL;
+ ret = -1;
+ }
+ /* Check if there are still counts: */
+ else if ((*mutex)->m_data.m_count) {
+ /* Decrement the count: */
+ (*mutex)->m_data.m_count--;
+ }
+ /*
+ * Get the next thread from the queue of threads waiting on
+ * the mutex:
+ */
+ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
+ /* Allow the new owner of the mutex to run: */
+ (*mutex)->m_owner->state = PS_RUNNING;
+ }
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
/* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
+ errno = EINVAL;
ret = -1;
+ break;
}
- /* Check if there are still counts: */
- else if (mutex->m_data.m_count) {
- /* Decrement the count: */
- mutex->m_data.m_count--;
- }
- /*
- * Get the next thread from the queue of threads waiting on
- * the mutex:
- */
- else if ((mutex->m_owner = _thread_queue_deq(&mutex->m_queue)) != NULL) {
- /* Allow the new owner of the mutex to run: */
- mutex->m_owner->state = PS_RUNNING;
- }
- break;
- /* Trap invalid mutex types: */
- default:
- /* Return an invalid argument error: */
- _thread_seterrno(_thread_run, EINVAL);
- ret = -1;
- break;
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
}
- /* Unblock signals: */
- _thread_kern_sig_unblock(status);
-
/* Return the completion status: */
return (ret);
}
diff --git a/lib/libkse/thread/thr_nanosleep.c b/lib/libkse/thread/thr_nanosleep.c
index e91ca5765113..58ade9888c35 100644
--- a/lib/libkse/thread/thr_nanosleep.c
+++ b/lib/libkse/thread/thr_nanosleep.c
@@ -31,6 +31,7 @@
*
*/
#include <stdio.h>
+#include <errno.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
#include "pthread_private.h"
@@ -38,50 +39,138 @@
int
nanosleep(struct timespec * time_to_sleep, struct timespec * time_remaining)
{
+ int ret = 0;
struct timespec current_time;
struct timespec current_time1;
+ struct timespec remaining_time;
struct timeval tv;
- /* Get the current time: */
- gettimeofday(&tv, NULL);
- TIMEVAL_TO_TIMESPEC(&tv, &current_time);
+ /* Check if the time to sleep is legal: */
+#if defined(__FreeBSD__)
+ if (time_to_sleep == NULL || time_to_sleep->ts_nsec < 0 || time_to_sleep->ts_nsec > 1000000000) {
+#else
+ if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000) {
+#endif
+ /* Return an EINVAL error : */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ /* Get the current time: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &current_time);
- /* Calculate the time for the current thread to wake up: */
- _thread_run->wakeup_time.ts_sec = current_time.ts_sec + time_to_sleep->ts_sec;
- _thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + time_to_sleep->ts_nsec;
+ /* Calculate the time for the current thread to wake up: */
+#if defined(__FreeBSD__)
+ _thread_run->wakeup_time.ts_sec = current_time.ts_sec + time_to_sleep->ts_sec;
+ _thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + time_to_sleep->ts_nsec;
+#else
+ _thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec;
+ _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec;
+#endif
- /* Check if the nanosecond field has overflowed: */
- if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
- /* Wrap the nanosecond field: */
- _thread_run->wakeup_time.ts_sec += 1;
- _thread_run->wakeup_time.ts_nsec -= 1000000000;
- }
- /* Reschedule the current thread to sleep: */
- _thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
+ /* Check if the nanosecond field has overflowed: */
+#if defined(__FreeBSD__)
+ if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
+#else
+ if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
+#endif
+ /* Wrap the nanosecond field: */
+#if defined(__FreeBSD__)
+ _thread_run->wakeup_time.ts_sec += 1;
+ _thread_run->wakeup_time.ts_nsec -= 1000000000;
+#else
+ _thread_run->wakeup_time.tv_sec += 1;
+ _thread_run->wakeup_time.tv_nsec -= 1000000000;
+#endif
+ }
+
+ /* Reschedule the current thread to sleep: */
+ _thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
- /* Check if the time remaining is to be returned: */
- if (time_remaining != NULL) {
/* Get the current time: */
gettimeofday(&tv, NULL);
TIMEVAL_TO_TIMESPEC(&tv, &current_time1);
- /* Return the actual time slept: */
- time_remaining->ts_sec = time_to_sleep->ts_sec + current_time1.ts_sec - current_time.ts_sec;
- time_remaining->ts_nsec = time_to_sleep->ts_nsec + current_time1.ts_nsec - current_time.ts_nsec;
+ /* Calculate the remaining time to sleep: */
+#if defined(__FreeBSD__)
+ remaining_time.ts_sec = time_to_sleep->ts_sec + current_time.ts_sec - current_time1.ts_sec;
+ remaining_time.ts_nsec = time_to_sleep->ts_nsec + current_time.ts_nsec - current_time1.ts_nsec;
+#else
+ remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec;
+ remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec;
+#endif
/* Check if the nanosecond field has underflowed: */
- if (time_remaining->ts_nsec < 0) {
+#if defined(__FreeBSD__)
+ if (remaining_time.ts_nsec < 0) {
+#else
+ if (remaining_time.tv_nsec < 0) {
+#endif
/* Handle the underflow: */
- time_remaining->ts_sec -= 1;
- time_remaining->ts_nsec += 1000000000;
+#if defined(__FreeBSD__)
+ remaining_time.ts_sec -= 1;
+ remaining_time.ts_nsec += 1000000000;
+#else
+ remaining_time.tv_sec -= 1;
+ remaining_time.tv_nsec += 1000000000;
+#endif
}
+
+ /* Check if the nanosecond field has overflowed: */
+#if defined(__FreeBSD__)
+ if (remaining_time.ts_nsec >= 1000000000) {
+#else
+ if (remaining_time.tv_nsec >= 1000000000) {
+#endif
+ /* Handle the overflow: */
+#if defined(__FreeBSD__)
+ remaining_time.ts_sec += 1;
+ remaining_time.ts_nsec -= 1000000000;
+#else
+ remaining_time.tv_sec += 1;
+ remaining_time.tv_nsec -= 1000000000;
+#endif
+ }
+
/* Check if the sleep was longer than the required time: */
- if (time_remaining->ts_sec < 0) {
- /* Reset the time teft: */
- time_remaining->ts_sec = 0;
- time_remaining->ts_nsec = 0;
+#if defined(__FreeBSD__)
+ if (remaining_time.ts_sec < 0) {
+#else
+ if (remaining_time.tv_sec < 0) {
+#endif
+ /* Reset the time left: */
+#if defined(__FreeBSD__)
+ remaining_time.ts_sec = 0;
+ remaining_time.ts_nsec = 0;
+#else
+ remaining_time.tv_sec = 0;
+ remaining_time.tv_nsec = 0;
+#endif
+ }
+
+ /* Check if the time remaining is to be returned: */
+ if (time_remaining != NULL) {
+ /* Return the actual time slept: */
+#if defined(__FreeBSD__)
+ time_remaining->ts_sec = remaining_time.ts_sec;
+ time_remaining->ts_nsec = remaining_time.ts_nsec;
+#else
+ time_remaining->tv_sec = remaining_time.tv_sec;
+ time_remaining->tv_nsec = remaining_time.tv_nsec;
+#endif
+ }
+
+ /* Check if the entire sleep was not completed: */
+#if defined(__FreeBSD__)
+ if (remaining_time.ts_nsec != 0 || remaining_time.ts_sec != 0) {
+#else
+ if (remaining_time.tv_nsec != 0 || remaining_time.tv_sec != 0) {
+#endif
+ /* Return an EINTR error : */
+ errno = EINTR;
+ ret = -1;
}
}
- return (0);
+ return (ret);
}
#endif
diff --git a/lib/libkse/thread/thr_open.c b/lib/libkse/thread/thr_open.c
index ead651ea3d9e..00bb91335755 100644
--- a/lib/libkse/thread/thr_open.c
+++ b/lib/libkse/thread/thr_open.c
@@ -31,6 +31,7 @@
*
*/
#include <stdarg.h>
+#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#ifdef _THREAD_SAFE
@@ -55,8 +56,8 @@ open(const char *path, int flags,...)
mode = va_arg(ap, int);
va_end(ap);
}
- /* Open the file, forcing it to use non-blocking I/O operations: */
- if ((fd = _thread_sys_open(path, flags | O_NONBLOCK, mode)) < 0) {
+ /* Open the file: */
+ if ((fd = _thread_sys_open(path, flags, mode)) < 0) {
}
/* Initialise the file descriptor table entry: */
else if (_thread_fd_table_init(fd) != 0) {
@@ -65,12 +66,6 @@ open(const char *path, int flags,...)
/* Reset the file descriptor: */
fd = -1;
- } else {
- /*
- * Save the file open flags so that they can be checked
- * later:
- */
- _thread_fd_table[fd]->flags = flags;
}
/* Unblock signals: */
diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h
index fc8ba276a42c..48e70ce00d1e 100644
--- a/lib/libkse/thread/thr_private.h
+++ b/lib/libkse/thread/thr_private.h
@@ -59,6 +59,129 @@
#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
/*
+ * Queue definitions.
+ */
+struct pthread_queue {
+ struct pthread *q_next;
+ struct pthread *q_last;
+ void *q_data;
+};
+
+/*
+ * Static queue initialization values.
+ */
+#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL }
+
+/*
+ * Mutex definitions.
+ */
+enum pthread_mutextype {
+ MUTEX_TYPE_FAST = 1,
+ MUTEX_TYPE_COUNTING_FAST = 2, /* Recursive */
+ MUTEX_TYPE_MAX
+};
+
+union pthread_mutex_data {
+ void *m_ptr;
+ int m_count;
+};
+
+struct pthread_mutex {
+ enum pthread_mutextype m_type;
+ struct pthread_queue m_queue;
+ struct pthread *m_owner;
+ union pthread_mutex_data m_data;
+ long m_flags;
+};
+
+/*
+ * Flags for mutexes.
+ */
+#define MUTEX_FLAGS_PRIVATE 0x01
+#define MUTEX_FLAGS_INITED 0x02
+#define MUTEX_FLAGS_BUSY 0x04
+
+/*
+ * Static mutex initialization values.
+ */
+#define PTHREAD_MUTEX_INITIALIZER \
+ { MUTEX_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, \
+ NULL, { NULL }, MUTEX_FLAGS_INITED }
+
+struct pthread_mutex_attr {
+ enum pthread_mutextype m_type;
+ long m_flags;
+};
+
+/*
+ * Condition variable definitions.
+ */
+enum pthread_cond_type {
+ COND_TYPE_FAST,
+ COND_TYPE_MAX
+};
+
+struct pthread_cond {
+ enum pthread_cond_type c_type;
+ struct pthread_queue c_queue;
+ void *c_data;
+ long c_flags;
+};
+
+struct pthread_cond_attr {
+ enum pthread_cond_type c_type;
+ long c_flags;
+};
+
+/*
+ * Flags for condition variables.
+ */
+#define COND_FLAGS_PRIVATE 0x01
+#define COND_FLAGS_INITED 0x02
+#define COND_FLAGS_BUSY 0x04
+
+/*
+ * Static cond initialization values.
+ */
+#define PTHREAD_COND_INITIALIZER \
+ { COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, COND_FLAGS_INITED }
+
+/*
+ * Cleanup definitions.
+ */
+struct pthread_cleanup {
+ struct pthread_cleanup *next;
+ void (*routine) ();
+ void *routine_arg;
+};
+
+/*
+ * Scheduling definitions.
+ */
+enum schedparam_policy {
+ SCHED_RR,
+ SCHED_IO,
+ SCHED_FIFO,
+ SCHED_OTHER
+};
+
+struct pthread_attr {
+ enum schedparam_policy schedparam_policy;
+ int prio;
+ int suspend;
+ int flags;
+ void *arg_attr;
+ void (*cleanup_attr) ();
+ void *stackaddr_attr;
+ size_t stacksize_attr;
+};
+
+struct sched_param {
+ int prio;
+ void *no_data;
+};
+
+/*
* Thread creation state attributes.
*/
#define PTHREAD_CREATE_RUNNING 0
@@ -67,14 +190,11 @@
/*
* Miscellaneous definitions.
*/
-#define PTHREAD_STACK_MIN 1024
#define PTHREAD_STACK_DEFAULT 65536
-#define PTHREAD_DATAKEYS_MAX 256
#define PTHREAD_DEFAULT_PRIORITY 64
#define PTHREAD_MAX_PRIORITY 126
#define PTHREAD_MIN_PRIORITY 0
#define _POSIX_THREAD_ATTR_STACKSIZE
-#define _POSIX_THREAD_DESTRUTOR_ITERATIONS 4
/*
* Clock resolution in nanoseconds.
@@ -190,10 +310,10 @@ struct pthread {
* Thread start routine, argument, stack pointer and thread
* attributes.
*/
- void *(*start_routine)(void *);
- void *arg;
- void *stack;
- pthread_attr_t attr;
+ void *(*start_routine)(void *);
+ void *arg;
+ void *stack;
+ struct pthread_attr attr;
/*
* Thread-specific signal handler interface:
@@ -319,6 +439,17 @@ SCLASS struct pthread *_thread_run
;
#endif
+/*
+ * Ptr to the thread running in single-threaded mode or NULL if
+ * running multi-threaded (default POSIX behaviour).
+ */
+SCLASS struct pthread *_thread_single
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
/* Ptr to the first thread in the thread linked list: */
SCLASS struct pthread *_thread_link_list
#ifdef GLOBAL_PTHREAD_PRIVATE
@@ -372,7 +503,7 @@ SCLASS struct pthread *_thread_initial
#endif
/* Default thread attributes: */
-SCLASS pthread_attr_t pthread_attr_default
+SCLASS struct pthread_attr pthread_attr_default
#ifdef GLOBAL_PTHREAD_PRIVATE
= { SCHED_RR, PTHREAD_DEFAULT_PRIORITY, PTHREAD_CREATE_RUNNING,
PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, PTHREAD_STACK_DEFAULT };
@@ -570,6 +701,7 @@ pid_t _thread_sys_fork(void);
pid_t _thread_sys_tcgetpgrp(int);
ssize_t _thread_sys_read(int, void *, size_t);
ssize_t _thread_sys_write(int, const void *, size_t);
+void _thread_sys__exit(int);
#endif
/* #include <fcntl.h> */
diff --git a/lib/libkse/thread/thr_resume_np.c b/lib/libkse/thread/thr_resume_np.c
new file mode 100644
index 000000000000..a254814163af
--- /dev/null
+++ b/lib/libkse/thread/thr_resume_np.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_resume_np(pthread_t thread)
+{
+ int ret = -1;
+ pthread_t pthread;
+ /*
+ * Search for the thread in the linked list.
+ */
+ for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
+ /* Is this the thread? */
+ if (pthread == thread) {
+ /* Found the thread. Is it suspended? */
+ if (pthread->state == PS_SUSPENDED) {
+ /* Allow the thread to run. */
+ pthread->state = PS_RUNNING;
+ ret = 0;
+ } else if (pthread->state == PS_RUNNING) {
+ /* Thread is already running. */
+ ret = 0;
+ } else {
+ /* Thread is in some other state. */
+ _thread_seterrno(_thread_run,EINVAL);
+ }
+ }
+ }
+ /* Check if thread was not found. */
+ if (ret == -1) {
+ /* No such thread */
+ _thread_seterrno(_thread_run,ESRCH);
+ }
+ return(ret);
+}
+#endif
diff --git a/lib/libkse/thread/thr_select.c b/lib/libkse/thread/thr_select.c
index b3f548373e99..7db3ed2f2444 100644
--- a/lib/libkse/thread/thr_select.c
+++ b/lib/libkse/thread/thr_select.c
@@ -142,36 +142,29 @@ select(int numfds, fd_set * readfds, fd_set * writefds,
if (ret > 0) {
if (readfds != NULL) {
- FD_ZERO(readfds);
for (i = 0; i < numfds; i++) {
- if (FD_ISSET(i, &data.readfds)) {
- FD_SET(i, readfds);
+ if (FD_ISSET(i, readfds) &&
+ !FD_ISSET(i, &data.readfds)) {
+ FD_CLR(i, readfds);
}
}
}
if (writefds != NULL) {
- FD_ZERO(writefds);
for (i = 0; i < numfds; i++) {
- if (FD_ISSET(i, &data.writefds)) {
- FD_SET(i, writefds);
+ if (FD_ISSET(i, writefds) &&
+ !FD_ISSET(i, &data.writefds)) {
+ FD_CLR(i, writefds);
}
}
}
if (exceptfds != NULL) {
- FD_ZERO(exceptfds);
for (i = 0; i < numfds; i++) {
- if (FD_ISSET(i, &data.exceptfds)) {
- FD_SET(i, exceptfds);
+ if (FD_ISSET(i, exceptfds) &&
+ !FD_ISSET(i, &data.exceptfds)) {
+ FD_CLR(i, exceptfds);
}
}
}
- } else {
- if (exceptfds != NULL)
- FD_ZERO(exceptfds);
- if (writefds != NULL)
- FD_ZERO(writefds);
- if (readfds != NULL)
- FD_ZERO(readfds);
}
return (ret);
diff --git a/lib/libkse/thread/thr_sig.c b/lib/libkse/thread/thr_sig.c
index 77ec713b63d9..c3ec1919077e 100644
--- a/lib/libkse/thread/thr_sig.c
+++ b/lib/libkse/thread/thr_sig.c
@@ -31,6 +31,8 @@
*
*/
#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
#include <errno.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
@@ -40,6 +42,7 @@ void
_thread_sig_handler(int sig, int code, struct sigcontext * scp)
{
char c;
+ int i;
pthread_t pthread;
/*
@@ -67,16 +70,52 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp)
} else {
/* Handle depending on signal type: */
switch (sig) {
- /* Interval timer used for timeslicing: */
+ /* Interval timer used for timeslicing: */
case SIGVTALRM:
/*
* Don't add the signal to any thread. Just want to
- * call
+ * call the scheduler:
*/
- /* the scheduler: */
break;
- /* Signals specific to the running thread: */
+ /* Child termination: */
+ case SIGCHLD:
+ /*
+ * Enter a loop to process each thread in the linked
+ * list:
+ */
+ for (pthread = _thread_link_list; pthread != NULL;
+ pthread = pthread->nxt) {
+ /*
+ * Add the signal to the set of pending
+ * signals:
+ */
+ pthread->sigpend[sig] += 1;
+ if (pthread->state == PS_WAIT_WAIT) {
+ /* Reset the error: */
+ /* There should be another flag so that this is not required! ### */
+ _thread_seterrno(pthread, 0);
+
+ /* Change the state of the thread to run: */
+ pthread->state = PS_RUNNING;
+ }
+ }
+
+ /*
+ * Go through the file list and set all files
+ * to non-blocking again in case the child
+ * set some of them to block. Sigh.
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Check if this file is used: */
+ if (_thread_fd_table[i] != NULL) {
+ /* Set the file descriptor to non-blocking: */
+ _thread_sys_fcntl(i, F_SETFL, _thread_fd_table[i]->flags | O_NONBLOCK);
+ }
+ }
+ break;
+
+ /* Signals specific to the running thread: */
case SIGBUS:
case SIGEMT:
case SIGFPE:
@@ -88,7 +127,7 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp)
_thread_run->sigpend[sig] += 1;
break;
- /* Signals to send to all threads: */
+ /* Signals to send to all threads: */
default:
/*
* Enter a loop to process each thread in the linked
diff --git a/lib/libkse/thread/thr_sigsuspend.c b/lib/libkse/thread/thr_sigsuspend.c
index ee2d0b5671df..a26b6b99bf4b 100644
--- a/lib/libkse/thread/thr_sigsuspend.c
+++ b/lib/libkse/thread/thr_sigsuspend.c
@@ -47,6 +47,9 @@ sigsuspend(const sigset_t * set)
/* Save the current sigmal mask: */
oset = _thread_run->sigmask;
+ /* Combine the caller's mask with the current one: */
+ _thread_run->sigmask |= *set;
+
/* Wait for a signal: */
_thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
diff --git a/lib/libkse/thread/thr_single_np.c b/lib/libkse/thread/thr_single_np.c
new file mode 100644
index 000000000000..e36c856c6376
--- /dev/null
+++ b/lib/libkse/thread/thr_single_np.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int pthread_single_np()
+{
+ /* Enter single-threaded (non-POSIX) scheduling mode: */
+ _thread_single = _thread_run;
+ return(0);
+}
+#endif
diff --git a/lib/libkse/thread/thr_spec.c b/lib/libkse/thread/thr_spec.c
index e7c45d2953c7..cc83c6066ee0 100644
--- a/lib/libkse/thread/thr_spec.c
+++ b/lib/libkse/thread/thr_spec.c
@@ -39,12 +39,12 @@
#include "pthread_private.h"
/* Static variables: */
-static struct pthread_key key_table[PTHREAD_DATAKEYS_MAX];
+static struct pthread_key key_table[PTHREAD_KEYS_MAX];
int
-pthread_keycreate(pthread_key_t * key, void (*destructor) (void *))
+pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
{
- for ((*key) = 0; (*key) < PTHREAD_DATAKEYS_MAX; (*key)++) {
+ for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
if (key_table[(*key)].count == 0) {
key_table[(*key)].count++;
key_table[(*key)].destructor = destructor;
@@ -63,7 +63,7 @@ pthread_key_delete(pthread_key_t key)
/* Block signals: */
_thread_kern_sig_block(&status);
- if (key < PTHREAD_DATAKEYS_MAX) {
+ if (key < PTHREAD_KEYS_MAX) {
switch (key_table[key].count) {
case 1:
key_table[key].destructor = NULL;
@@ -94,8 +94,8 @@ _thread_cleanupspecific(void)
/* Block signals: */
_thread_kern_sig_block(&status);
- for (itr = 0; itr < _POSIX_THREAD_DESTRUTOR_ITERATIONS; itr++) {
- for (key = 0; key < PTHREAD_DATAKEYS_MAX; key++) {
+ for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) {
+ for (key = 0; key < PTHREAD_KEYS_MAX; key++) {
if (_thread_run->specific_data_count) {
if (_thread_run->specific_data[key]) {
data = (void *) _thread_run->specific_data[key];
@@ -125,8 +125,8 @@ static inline const void **
pthread_key_allocate_data(void)
{
const void **new_data;
- if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_DATAKEYS_MAX)) != NULL) {
- memset((void *) new_data, 0, sizeof(void *) * PTHREAD_DATAKEYS_MAX);
+ if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX)) != NULL) {
+ memset((void *) new_data, 0, sizeof(void *) * PTHREAD_KEYS_MAX);
}
return (new_data);
}
@@ -154,7 +154,7 @@ pthread_setspecific(pthread_key_t key, const void *value)
}
if ((pthread->specific_data) || (pthread->specific_data = pthread_key_allocate_data())) {
- if ((key < PTHREAD_DATAKEYS_MAX) && (key_table)) {
+ if ((key < PTHREAD_KEYS_MAX) && (key_table)) {
if (key_table[key].count) {
if (pthread->specific_data[key] == NULL) {
if (value != NULL) {
@@ -213,7 +213,7 @@ pthread_getspecific(pthread_key_t key, void **p_data)
rval = -1;
}
/* Check if there is specific data: */
- else if (pthread->specific_data != NULL && (key < PTHREAD_DATAKEYS_MAX) && (key_table)) {
+ else if (pthread->specific_data != NULL && (key < PTHREAD_KEYS_MAX) && (key_table)) {
/* Check if this key has been used before: */
if (key_table[key].count) {
/* Return the value: */
diff --git a/lib/libkse/thread/thr_suspend_np.c b/lib/libkse/thread/thr_suspend_np.c
new file mode 100644
index 000000000000..fb90c1d494d2
--- /dev/null
+++ b/lib/libkse/thread/thr_suspend_np.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by John Birrell.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_suspend_np(pthread_t thread)
+{
+ int ret = -1;
+ pthread_t pthread;
+ /*
+ * Search for the thread in the linked list.
+ */
+ for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
+ /* Is this the thread? */
+ if (pthread == thread) {
+ /* Found the thread. Is it running? */
+ if (pthread->state != PS_RUNNING &&
+ pthread->state != PS_SUSPENDED) {
+ /* The thread operation has been interrupted */
+ _thread_seterrno(pthread,EINTR);
+ }
+ /* Suspend the thread. */
+ pthread->state = PS_SUSPENDED;
+ ret = 0;
+ }
+ }
+ /* Check if thread was not found. */
+ if (ret == -1) {
+ /* No such thread */
+ _thread_seterrno(_thread_run,ESRCH);
+ }
+ return(ret);
+}
+#endif