summaryrefslogtreecommitdiffstats
path: root/lib/libc_r
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1996-01-22 00:23:58 +0000
committerjulian <julian@FreeBSD.org>1996-01-22 00:23:58 +0000
commit529743d354ac402b1302b397159146fa46c180c5 (patch)
treed93df8a19a0cab699bfc2c0b9e4bc691251efa16 /lib/libc_r
parent619b731f5bb5e09dcf1eaf1fbd96383ca64398fd (diff)
downloadFreeBSD-src-529743d354ac402b1302b397159146fa46c180c5.zip
FreeBSD-src-529743d354ac402b1302b397159146fa46c180c5.tar.gz
Reviewed by: julian
Submitted by: john birrel One version of the pthreads library another will follow with differnt actions under some cases.. not QUITE complete
Diffstat (limited to 'lib/libc_r')
-rw-r--r--lib/libc_r/Makefile66
-rw-r--r--lib/libc_r/compat-43/Makefile.inc7
-rw-r--r--lib/libc_r/db/Makefile.inc9
-rw-r--r--lib/libc_r/db/btree/Makefile.inc7
-rw-r--r--lib/libc_r/db/db/Makefile.inc5
-rw-r--r--lib/libc_r/db/hash/Makefile.inc6
-rw-r--r--lib/libc_r/db/mpool/Makefile.inc5
-rw-r--r--lib/libc_r/db/recno/Makefile.inc6
-rw-r--r--lib/libc_r/gen/Makefile.inc29
-rw-r--r--lib/libc_r/gmon/Makefile.inc10
-rw-r--r--lib/libc_r/i386/gen/Makefile.inc5
-rw-r--r--lib/libc_r/i386/net/Makefile.inc4
-rw-r--r--lib/libc_r/i386/stdlib/Makefile.inc4
-rw-r--r--lib/libc_r/i386/string/Makefile.inc8
-rw-r--r--lib/libc_r/i386/sys/Makefile.inc6
-rw-r--r--lib/libc_r/locale/Makefile.inc8
-rw-r--r--lib/libc_r/net/Makefile.inc16
-rw-r--r--lib/libc_r/nls/Makefile.inc5
-rw-r--r--lib/libc_r/quad/Makefile.inc20
-rw-r--r--lib/libc_r/regex/Makefile.inc8
-rw-r--r--lib/libc_r/rpc/Makefile.inc10
-rw-r--r--lib/libc_r/stdio/Makefile.inc15
-rw-r--r--lib/libc_r/stdlib/Makefile.inc13
-rw-r--r--lib/libc_r/stdtime/Makefile.inc5
-rw-r--r--lib/libc_r/string/Makefile.inc81
-rw-r--r--lib/libc_r/sys/Makefile.inc107
-rw-r--r--lib/libc_r/uthread/Makefile.inc75
-rw-r--r--lib/libc_r/uthread/pthread_private.h629
-rw-r--r--lib/libc_r/uthread/uthread_accept.c94
-rw-r--r--lib/libc_r/uthread/uthread_attr_setcreatesuspend.c43
-rw-r--r--lib/libc_r/uthread/uthread_bind.c50
-rw-r--r--lib/libc_r/uthread/uthread_clean.c73
-rw-r--r--lib/libc_r/uthread/uthread_close.c48
-rw-r--r--lib/libc_r/uthread/uthread_cond.c293
-rw-r--r--lib/libc_r/uthread/uthread_connect.c76
-rw-r--r--lib/libc_r/uthread/uthread_create.c277
-rw-r--r--lib/libc_r/uthread/uthread_detach.c83
-rw-r--r--lib/libc_r/uthread/uthread_dup.c37
-rw-r--r--lib/libc_r/uthread/uthread_dup2.c74
-rw-r--r--lib/libc_r/uthread/uthread_equal.c43
-rw-r--r--lib/libc_r/uthread/uthread_execve.c87
-rw-r--r--lib/libc_r/uthread/uthread_exit.c167
-rw-r--r--lib/libc_r/uthread/uthread_fchmod.c50
-rw-r--r--lib/libc_r/uthread/uthread_fchown.c51
-rw-r--r--lib/libc_r/uthread/uthread_fcntl.c115
-rw-r--r--lib/libc_r/uthread/uthread_fd.c364
-rw-r--r--lib/libc_r/uthread/uthread_file.c125
-rw-r--r--lib/libc_r/uthread/uthread_flock.c49
-rw-r--r--lib/libc_r/uthread/uthread_fork.c90
-rw-r--r--lib/libc_r/uthread/uthread_fstat.c57
-rw-r--r--lib/libc_r/uthread/uthread_fstatfs.c57
-rw-r--r--lib/libc_r/uthread/uthread_fsync.c49
-rw-r--r--lib/libc_r/uthread/uthread_getdirentries.c50
-rw-r--r--lib/libc_r/uthread/uthread_getpeername.c50
-rw-r--r--lib/libc_r/uthread/uthread_getprio.c73
-rw-r--r--lib/libc_r/uthread/uthread_getsockname.c50
-rw-r--r--lib/libc_r/uthread/uthread_getsockopt.c50
-rw-r--r--lib/libc_r/uthread/uthread_info.c175
-rw-r--r--lib/libc_r/uthread/uthread_init.c214
-rw-r--r--lib/libc_r/uthread/uthread_ioctl.c53
-rw-r--r--lib/libc_r/uthread/uthread_join.c90
-rw-r--r--lib/libc_r/uthread/uthread_kern.c1581
-rw-r--r--lib/libc_r/uthread/uthread_listen.c50
-rw-r--r--lib/libc_r/uthread/uthread_longjmp.c45
-rw-r--r--lib/libc_r/uthread/uthread_mutex.c360
-rw-r--r--lib/libc_r/uthread/uthread_nanosleep.c87
-rw-r--r--lib/libc_r/uthread/uthread_once.c50
-rw-r--r--lib/libc_r/uthread/uthread_open.c82
-rw-r--r--lib/libc_r/uthread/uthread_pipe.c58
-rw-r--r--lib/libc_r/uthread/uthread_queue.c124
-rw-r--r--lib/libc_r/uthread/uthread_read.c74
-rw-r--r--lib/libc_r/uthread/uthread_readv.c74
-rw-r--r--lib/libc_r/uthread/uthread_recvfrom.c70
-rw-r--r--lib/libc_r/uthread/uthread_resume.c70
-rw-r--r--lib/libc_r/uthread/uthread_select.c179
-rw-r--r--lib/libc_r/uthread/uthread_self.c43
-rw-r--r--lib/libc_r/uthread/uthread_sendto.c63
-rw-r--r--lib/libc_r/uthread/uthread_seterrno.c61
-rw-r--r--lib/libc_r/uthread/uthread_setjmp.c44
-rw-r--r--lib/libc_r/uthread/uthread_setprio.c80
-rw-r--r--lib/libc_r/uthread/uthread_setsockopt.c50
-rw-r--r--lib/libc_r/uthread/uthread_shutdown.c71
-rw-r--r--lib/libc_r/uthread/uthread_sig.c128
-rw-r--r--lib/libc_r/uthread/uthread_sigaction.c82
-rw-r--r--lib/libc_r/uthread/uthread_sigblock.c48
-rw-r--r--lib/libc_r/uthread/uthread_signal.c57
-rw-r--r--lib/libc_r/uthread/uthread_sigprocmask.c92
-rw-r--r--lib/libc_r/uthread/uthread_sigsetmask.c48
-rw-r--r--lib/libc_r/uthread/uthread_sigsuspend.c63
-rw-r--r--lib/libc_r/uthread/uthread_socket.c57
-rw-r--r--lib/libc_r/uthread/uthread_socketpair.c59
-rw-r--r--lib/libc_r/uthread/uthread_spec.c237
-rw-r--r--lib/libc_r/uthread/uthread_suspend.c67
-rw-r--r--lib/libc_r/uthread/uthread_wait4.c61
-rw-r--r--lib/libc_r/uthread/uthread_write.c74
-rw-r--r--lib/libc_r/uthread/uthread_writev.c74
-rw-r--r--lib/libc_r/uthread/uthread_yield.c49
-rw-r--r--lib/libc_r/xdr/Makefile.inc5
-rw-r--r--lib/libc_r/yp/Makefile.inc8
99 files changed, 8951 insertions, 0 deletions
diff --git a/lib/libc_r/Makefile b/lib/libc_r/Makefile
new file mode 100644
index 0000000..c0fd385
--- /dev/null
+++ b/lib/libc_r/Makefile
@@ -0,0 +1,66 @@
+# @(#)Makefile 8.2 (Berkeley) 2/3/94
+#
+# All library objects contain rcsid strings by default; they may be
+# excluded as a space-saving measure. To produce a library that does
+# not contain these strings, delete -DLIBC_RCS and -DSYSLIBC_RCS
+# from CFLAGS below. To remove these strings from just the system call
+# stubs, remove just -DSYSLIBC_RCS from CFLAGS.
+LIB=c_r
+SHLIB_MAJOR= 2
+SHLIB_MINOR= 2
+CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS
+CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE -I${.CURDIR}/uthread
+AINC= -I${.CURDIR}/../libc/${MACHINE} -I${.CURDIR}/uthread
+CLEANFILES+=tags
+INSTALL_PIC_ARCHIVE= yes
+PRECIOUSLIB= yes
+
+.include "${.CURDIR}/db/Makefile.inc"
+.include "${.CURDIR}/compat-43/Makefile.inc"
+.include "${.CURDIR}/gen/Makefile.inc"
+.include "${.CURDIR}/gmon/Makefile.inc"
+.include "${.CURDIR}/locale/Makefile.inc"
+.include "${.CURDIR}/net/Makefile.inc"
+.include "${.CURDIR}/nls/Makefile.inc"
+.include "${.CURDIR}/quad/Makefile.inc"
+.include "${.CURDIR}/regex/Makefile.inc"
+.include "${.CURDIR}/stdio/Makefile.inc"
+.include "${.CURDIR}/stdlib/Makefile.inc"
+.include "${.CURDIR}/stdtime/Makefile.inc"
+.include "${.CURDIR}/string/Makefile.inc"
+.include "${.CURDIR}/sys/Makefile.inc"
+.include "${.CURDIR}/rpc/Makefile.inc"
+.include "${.CURDIR}/uthread/Makefile.inc"
+.include "${.CURDIR}/xdr/Makefile.inc"
+.if !defined(NO_YP_LIBC)
+CFLAGS+= -DYP
+.include "${.CURDIR}/yp/Makefile.inc"
+.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
+
+tags: ${SRCS}
+ ctags ${.ALLSRC:M*.c}
+ egrep -o "^ENTRY(.*)|^FUNC(.*)|^SYSCALL(.*)" ${.ALLSRC:M*.s} | \
+ sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+ >> tags; sort -o tags tags
+
+.include <bsd.lib.mk>
diff --git a/lib/libc_r/compat-43/Makefile.inc b/lib/libc_r/compat-43/Makefile.inc
new file mode 100644
index 0000000..633f6dc
--- /dev/null
+++ b/lib/libc_r/compat-43/Makefile.inc
@@ -0,0 +1,7 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/2/93
+
+# compat-43 sources
+.PATH: ${.CURDIR}/../libc/${MACHINE}/compat-43 ${.CURDIR}/../libc/compat-43
+
+SRCS+= creat.c gethostid.c getwd.c killpg.c sethostid.c setpgrp.c \
+ setrgid.c setruid.c sigcompat.c
diff --git a/lib/libc_r/db/Makefile.inc b/lib/libc_r/db/Makefile.inc
new file mode 100644
index 0000000..dd09d32
--- /dev/null
+++ b/lib/libc_r/db/Makefile.inc
@@ -0,0 +1,9 @@
+# @(#)Makefile.inc 8.2 (Berkeley) 2/21/94
+#
+CFLAGS+=-D__DBINTERFACE_PRIVATE
+
+.include "${.CURDIR}/db/btree/Makefile.inc"
+.include "${.CURDIR}/db/db/Makefile.inc"
+.include "${.CURDIR}/db/hash/Makefile.inc"
+.include "${.CURDIR}/db/mpool/Makefile.inc"
+.include "${.CURDIR}/db/recno/Makefile.inc"
diff --git a/lib/libc_r/db/btree/Makefile.inc b/lib/libc_r/db/btree/Makefile.inc
new file mode 100644
index 0000000..6e91b46
--- /dev/null
+++ b/lib/libc_r/db/btree/Makefile.inc
@@ -0,0 +1,7 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/../libc/db/btree
+
+SRCS+= bt_close.c bt_conv.c bt_debug.c bt_delete.c bt_get.c bt_open.c \
+ bt_overflow.c bt_page.c bt_put.c bt_search.c bt_seq.c bt_split.c \
+ bt_stack.c bt_utils.c
diff --git a/lib/libc_r/db/db/Makefile.inc b/lib/libc_r/db/db/Makefile.inc
new file mode 100644
index 0000000..8f16baa
--- /dev/null
+++ b/lib/libc_r/db/db/Makefile.inc
@@ -0,0 +1,5 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/../libc/db/db
+
+SRCS+= db.c
diff --git a/lib/libc_r/db/hash/Makefile.inc b/lib/libc_r/db/hash/Makefile.inc
new file mode 100644
index 0000000..f0c8585
--- /dev/null
+++ b/lib/libc_r/db/hash/Makefile.inc
@@ -0,0 +1,6 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/../libc/db/hash
+
+SRCS+= hash.c hash_bigkey.c hash_buf.c hash_func.c hash_log2.c \
+ hash_page.c hsearch.c ndbm.c
diff --git a/lib/libc_r/db/mpool/Makefile.inc b/lib/libc_r/db/mpool/Makefile.inc
new file mode 100644
index 0000000..6179487
--- /dev/null
+++ b/lib/libc_r/db/mpool/Makefile.inc
@@ -0,0 +1,5 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/../libc/db/mpool
+
+SRCS+= mpool.c
diff --git a/lib/libc_r/db/recno/Makefile.inc b/lib/libc_r/db/recno/Makefile.inc
new file mode 100644
index 0000000..1549993
--- /dev/null
+++ b/lib/libc_r/db/recno/Makefile.inc
@@ -0,0 +1,6 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/../libc/db/recno
+
+SRCS+= rec_close.c rec_delete.c rec_get.c rec_open.c rec_put.c rec_search.c \
+ rec_seq.c rec_utils.c
diff --git a/lib/libc_r/gen/Makefile.inc b/lib/libc_r/gen/Makefile.inc
new file mode 100644
index 0000000..2bfe3cd
--- /dev/null
+++ b/lib/libc_r/gen/Makefile.inc
@@ -0,0 +1,29 @@
+# From: @(#)Makefile.inc 8.3 (Berkeley) 4/16/94
+# $Id: Makefile.inc,v 1.16 1995/05/30 05:40:08 rgrimes Exp $
+
+# machine-independent gen sources
+.PATH: ${.CURDIR}/../libc/${MACHINE}/gen ${.CURDIR}/../libc/gen
+
+SRCS+= alarm.c assert.c clock.c closedir.c config.c confstr.c crypt.c \
+ ctermid.c daemon.c devname.c disklabel.c err.c errlst.c \
+ exec.c fnmatch.c frexp.c fstab.c fts.c getbootfile.c getbsize.c \
+ getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \
+ gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \
+ getosreldate.c getpagesize.c getpass.c getpwent.c getttyent.c \
+ getusershell.c getvfsent.c glob.c initgroups.c isatty.c msgctl.c \
+ msgget.c msgrcv.c msgsnd.c nice.c nlist.c ntp_gettime.c opendir.c \
+ pause.c popen.c psignal.c pwcache.c raise.c readdir.c rewinddir.c \
+ scandir.c seekdir.c semconfig.c semctl.c semget.c semop.c \
+ setdomainname.c sethostname.c setjmperr.c setmode.c shmat.c \
+ shmctl.c shmdt.c shmget.c siginterrupt.c siglist.c signal.c \
+ sigsetops.c sleep.c sysconf.c sysctl.c syslog.c \
+ telldir.c termios.c time.c times.c timezone.c ttyname.c ttyslot.c \
+ ualarm.c uname.c unvis.c usleep.c utime.c valloc.c vis.c wait.c \
+ wait3.c waitpid.c
+
+# *rand48 family, from 1.1.5
+SRCS+= _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \
+ mrand48.c nrand48.c seed48.c srand48.c
+
+# machine-dependent gen sources
+.include "${.CURDIR}/${MACHINE}/gen/Makefile.inc"
diff --git a/lib/libc_r/gmon/Makefile.inc b/lib/libc_r/gmon/Makefile.inc
new file mode 100644
index 0000000..f0cc7e5
--- /dev/null
+++ b/lib/libc_r/gmon/Makefile.inc
@@ -0,0 +1,10 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+# gmon sources
+.PATH: ${.CURDIR}/../libc/gmon
+
+SRCS+= gmon.c mcount.c
+
+# mcount cannot be compiled with profiling
+mcount.po: mcount.o
+ cp mcount.o mcount.po
diff --git a/lib/libc_r/i386/gen/Makefile.inc b/lib/libc_r/i386/gen/Makefile.inc
new file mode 100644
index 0000000..e27d9fc
--- /dev/null
+++ b/lib/libc_r/i386/gen/Makefile.inc
@@ -0,0 +1,5 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id: Makefile.inc,v 1.6 1995/10/05 10:24:57 phk Exp $
+
+SRCS+= isinf.c infinity.c
+SRCS+= _setjmp.S alloca.S fabs.S ldexp.c modf.S setjmp.S sigsetjmp.S
diff --git a/lib/libc_r/i386/net/Makefile.inc b/lib/libc_r/i386/net/Makefile.inc
new file mode 100644
index 0000000..c53f780
--- /dev/null
+++ b/lib/libc_r/i386/net/Makefile.inc
@@ -0,0 +1,4 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id: Makefile.inc,v 1.3 1995/01/23 01:27:57 davidg Exp $
+
+SRCS+= htonl.S htons.S ntohl.S ntohs.S
diff --git a/lib/libc_r/i386/stdlib/Makefile.inc b/lib/libc_r/i386/stdlib/Makefile.inc
new file mode 100644
index 0000000..8b544af
--- /dev/null
+++ b/lib/libc_r/i386/stdlib/Makefile.inc
@@ -0,0 +1,4 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id: Makefile.inc,v 1.3 1995/01/23 01:28:28 davidg Exp $
+
+SRCS+= abs.S
diff --git a/lib/libc_r/i386/string/Makefile.inc b/lib/libc_r/i386/string/Makefile.inc
new file mode 100644
index 0000000..df9bf98
--- /dev/null
+++ b/lib/libc_r/i386/string/Makefile.inc
@@ -0,0 +1,8 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id: Makefile.inc,v 1.4 1995/01/23 01:28:45 davidg Exp $
+
+SRCS+= bcmp.S bcopy.S bzero.S ffs.S index.S memchr.S memcmp.S \
+ memmove.S memset.S \
+ rindex.S strcat.S strchr.S strcmp.S strcpy.S strcspn.c \
+ strlen.S strncat.c strncmp.S strncpy.c strpbrk.c strsep.c \
+ strspn.c strrchr.S strstr.c swab.S
diff --git a/lib/libc_r/i386/sys/Makefile.inc b/lib/libc_r/i386/sys/Makefile.inc
new file mode 100644
index 0000000..fdeba08
--- /dev/null
+++ b/lib/libc_r/i386/sys/Makefile.inc
@@ -0,0 +1,6 @@
+# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp
+# $Id: Makefile.inc,v 1.2 1994/02/21 05:19:06 rgrimes Exp $
+
+.PATH: ${.CURDIR}/../libc/${MACHINE}/sys
+
+SRCS+= i386_get_ldt.c i386_set_ldt.c
diff --git a/lib/libc_r/locale/Makefile.inc b/lib/libc_r/locale/Makefile.inc
new file mode 100644
index 0000000..eae25a0
--- /dev/null
+++ b/lib/libc_r/locale/Makefile.inc
@@ -0,0 +1,8 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+# locale sources
+.PATH: ${.CURDIR}/../libc/${MACHINE}/locale ${.CURDIR}/../libc/locale
+
+SRCS+= ansi.c ctype.c euc.c frune.c isctype.c lconv.c localeconv.c \
+ mbrune.c none.c rune.c setlocale.c table.c utf2.c setrunelocale.c \
+ runetype.c tolower.c toupper.c nomacros.c collate.c setinvalidrune.c
diff --git a/lib/libc_r/net/Makefile.inc b/lib/libc_r/net/Makefile.inc
new file mode 100644
index 0000000..fd3ee75
--- /dev/null
+++ b/lib/libc_r/net/Makefile.inc
@@ -0,0 +1,16 @@
+# @(#)Makefile.inc 8.2 (Berkeley) 9/5/93
+
+# machine-independent net sources
+.PATH: ${.CURDIR}/../libc/${MACHINE}/net ${.CURDIR}/../libc/net
+
+SRCS+= gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \
+ getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \
+ getproto.c getprotoent.c getprotoname.c getservbyname.c \
+ getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \
+ inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c \
+ iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c rcmd.c recv.c res_comp.c \
+ res_debug.c res_init.c res_mkquery.c res_query.c res_send.c \
+ send.c ether_addr.c
+
+# machine-dependent net sources
+.include "${.CURDIR}/${MACHINE}/net/Makefile.inc"
diff --git a/lib/libc_r/nls/Makefile.inc b/lib/libc_r/nls/Makefile.inc
new file mode 100644
index 0000000..6c2c51a
--- /dev/null
+++ b/lib/libc_r/nls/Makefile.inc
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile.inc,v 1.7 1995/02/27 13:06:20 cgd Exp $
+
+.PATH: ${.CURDIR}/../libc/nls
+
+SRCS+= catclose.c catgets.c catopen.c msgcat.c
diff --git a/lib/libc_r/quad/Makefile.inc b/lib/libc_r/quad/Makefile.inc
new file mode 100644
index 0000000..33ffeed
--- /dev/null
+++ b/lib/libc_r/quad/Makefile.inc
@@ -0,0 +1,20 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+# Quad support, if needed
+
+.if ${MACHINE} == "i386"
+
+SRCS+= cmpdi2.c \
+ divdi3.c moddi3.c udivdi3.c umoddi3.c qdivrem.c
+
+.else
+
+SRCS+= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c fixdfdi.c \
+ fixsfdi.c fixunsdfdi.c fixunssfdi.c floatdidf.c floatdisf.c \
+ floatunsdidf.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
+
+.endif
+
+.PATH: ${.CURDIR}/../libc/${MACHINE}/quad ${.CURDIR}/../libc/quad
diff --git a/lib/libc_r/regex/Makefile.inc b/lib/libc_r/regex/Makefile.inc
new file mode 100644
index 0000000..dd98c9e
--- /dev/null
+++ b/lib/libc_r/regex/Makefile.inc
@@ -0,0 +1,8 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+# regex sources
+.PATH: ${.CURDIR}/../libc/regex
+
+CFLAGS+=-DPOSIX_MISTAKE
+
+SRCS+= regcomp.c regerror.c regexec.c regfree.c
diff --git a/lib/libc_r/rpc/Makefile.inc b/lib/libc_r/rpc/Makefile.inc
new file mode 100644
index 0000000..b000942
--- /dev/null
+++ b/lib/libc_r/rpc/Makefile.inc
@@ -0,0 +1,10 @@
+# @(#)Makefile 5.11 (Berkeley) 9/6/90
+
+.PATH: ${.CURDIR}/../libc/rpc ${.CURDIR}/../libc
+SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
+ clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
+ clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \
+ pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
+ pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \
+ svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \
+ svc_tcp.c svc_udp.c
diff --git a/lib/libc_r/stdio/Makefile.inc b/lib/libc_r/stdio/Makefile.inc
new file mode 100644
index 0000000..c534a5c
--- /dev/null
+++ b/lib/libc_r/stdio/Makefile.inc
@@ -0,0 +1,15 @@
+# @(#)Makefile.inc 8.3 (Berkeley) 4/17/94
+
+# stdio sources
+.PATH: ${.CURDIR}/../libc/stdio
+
+SRCS+= clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c fgetc.c \
+ fgetln.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 mktemp.c perror.c \
+ printf.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 \
+ wbuf.c wsetup.c
diff --git a/lib/libc_r/stdlib/Makefile.inc b/lib/libc_r/stdlib/Makefile.inc
new file mode 100644
index 0000000..90582f7
--- /dev/null
+++ b/lib/libc_r/stdlib/Makefile.inc
@@ -0,0 +1,13 @@
+# @(#)Makefile.inc 8.2 (Berkeley) 2/16/94
+
+# machine-independent stdlib sources
+.PATH: ${.CURDIR}/../libc/${MACHINE}/stdlib ${.CURDIR}/../libc/stdlib
+
+SRCS+= abort.c atexit.c atof.c atoi.c atol.c bsearch.c calloc.c div.c \
+ exit.c getenv.c getopt.c getsubopt.c strhash.c heapsort.c labs.c \
+ ldiv.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c random.c \
+ realpath.c setenv.c strtod.c strtol.c strtoq.c strtoul.c \
+ strtouq.c system.c
+
+# machine-dependent stdlib sources
+.include "${.CURDIR}/${MACHINE}/stdlib/Makefile.inc"
diff --git a/lib/libc_r/stdtime/Makefile.inc b/lib/libc_r/stdtime/Makefile.inc
new file mode 100644
index 0000000..c6c8591
--- /dev/null
+++ b/lib/libc_r/stdtime/Makefile.inc
@@ -0,0 +1,5 @@
+# $Id: Makefile.inc,v 1.2 1994/09/13 21:26:01 wollman Exp $
+
+.PATH: ${.CURDIR}/../libc/stdtime
+
+SRCS+= asctime.c localtime.c strftime.c difftime.c
diff --git a/lib/libc_r/string/Makefile.inc b/lib/libc_r/string/Makefile.inc
new file mode 100644
index 0000000..861fdf7
--- /dev/null
+++ b/lib/libc_r/string/Makefile.inc
@@ -0,0 +1,81 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+
+.PATH: ${.CURDIR}/../libc/${MACHINE}/string ${.CURDIR}/../libc/string
+
+CFLAGS += -I${.CURDIR}/../libc/locale
+# machine-independent string sources
+SRCS+= memccpy.c strcasecmp.c strcoll.c strdup.c strerror.c \
+ strmode.c strtok.c strxfrm.c
+
+# machine-dependent string sources
+.include "${.CURDIR}/${MACHINE}/string/Makefile.inc"
+
+# If no machine specific bzero(3), build one out of memset(3).
+.if empty(SRCS:Mbzero.S)
+OBJS+= bzero.o
+bzero.o: memset.c
+ ${CC} -DBZERO ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
+ @${LD} -x -r ${.TARGET}
+ @mv a.out ${.TARGET}
+
+bzero.po: memset.c
+ ${CC} -DBZERO ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
+ @${LD} -X -r ${.TARGET}
+ @mv a.out ${.TARGET}
+.endif
+
+# If no machine specific memmove(3), build one out of bcopy(3).
+.if empty(SRCS:Mmemmove.S)
+OBJS+= memmove.o
+memmove.o: bcopy.c
+ ${CC} -DMEMMOVE ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
+ @${LD} -x -r ${.TARGET}
+ @mv a.out ${.TARGET}
+
+memmove.po: bcopy.c
+ ${CC} -DMEMMOVE ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
+ @${LD} -X -r ${.TARGET}
+ @mv a.out ${.TARGET}
+.endif
+
+# If no machine specific memcpy(3), build one out of bcopy(3).
+.if empty(SRCS:Mmemmove.S)
+OBJS+= memcpy.o
+memcpy.o: bcopy.c
+ ${CC} -DMEMCOPY ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
+ @${LD} -x -r ${.TARGET}
+ @mv a.out ${.TARGET}
+
+memcpy.po: bcopy.c
+ ${CC} -DMEMCOPY ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
+ @${LD} -X -r ${.TARGET}
+ @mv a.out ${.TARGET}
+.endif
+
+# If no machine specific strchr(3), build one out of index(3).
+.if empty(SRCS:Mstrchr.S)
+OBJS+= strchr.o
+strchr.o: index.c
+ ${CC} -DSTRCHR ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
+ @${LD} -x -r ${.TARGET}
+ @mv a.out ${.TARGET}
+
+strchr.po: index.c
+ ${CC} -DSTRCHR ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
+ @${LD} -X -r ${.TARGET}
+ @mv a.out ${.TARGET}
+.endif
+
+# If no machine specific strrchr(3), build one out of rindex(3).
+.if empty(SRCS:Mstrrchr.S)
+OBJS+= strrchr.o
+strrchr.o: rindex.c
+ ${CC} -DSTRRCHR ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET}
+ @${LD} -x -r ${.TARGET}
+ @mv a.out ${.TARGET}
+
+strrchr.po: rindex.c
+ ${CC} -DSTRRCHR ${CFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
+ @${LD} -X -r ${.TARGET}
+ @mv a.out ${.TARGET}
+.endif
diff --git a/lib/libc_r/sys/Makefile.inc b/lib/libc_r/sys/Makefile.inc
new file mode 100644
index 0000000..2b22537
--- /dev/null
+++ b/lib/libc_r/sys/Makefile.inc
@@ -0,0 +1,107 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/17/93
+
+# sys sources
+.PATH: ${.CURDIR}/../libc/${MACHINE}/sys ${.CURDIR}/../libc/sys \
+ ${.CURDIR}/sys
+
+# modules with non-default implementations on at least one architecture:
+SRCS+= Ovfork.S brk.S cerror.S exect.S fork.S pipe.S ptrace.S reboot.S \
+ sbrk.S setlogin.S sigpending.S sigprocmask.S sigreturn.S \
+ sigsuspend.S syscall.S __error.c
+
+# glue to provide compatibility between GCC 1.X and 2.X
+SRCS+= ftruncate.c lseek.c mmap.c truncate.c
+
+# modules with default implementations on all architectures:
+ASM= access.o acct.o adjtime.o chdir.o chflags.o chmod.o \
+ chown.o chroot.o getdtablesize.o getegid.o geteuid.o \
+ getfh.o getfsstat.o getgid.o getgroups.o getitimer.o \
+ getpgrp.o getpid.o getppid.o getpriority.o \
+ getrlimit.o getrusage.o gettimeofday.o getuid.o kill.o \
+ ktrace.o lfs_bmapv.o lfs_markv.o lfs_segclean.o \
+ lfs_segwait.o link.o lstat.o madvise.o mincore.o \
+ mkdir.o mlock.o mount.o mprotect.o msgsys.o msync.o \
+ munlock.o munmap.o ntp_adjtime.o pathconf.o profil.o \
+ quotactl.o readlink.o rename.o revoke.o rmdir.o rtprio.o \
+ semsys.o setegid.o seteuid.o setgid.o setgroups.o setitimer.o \
+ setpgid.o setpriority.o setregid.o setreuid.o setrlimit.o \
+ setsid.o settimeofday.o setuid.o shmsys.o stat.o statfs.o \
+ swapon.o symlink.o sync.o sysarch.o umask.o unlink.o \
+ unmount.o utimes.o vadvise.o __syscall.o __sysctl.o
+
+# Syscalls renamed as _thread_sys_{syscall}.
+THREADASM= accept.o bind.o close.o connect.o dup.o dup2.o \
+ execve.o fchdir.o fchflags.o fchmod.o fchown.o fcntl.o \
+ flock.o fpathconf.o fstat.o fstatfs.o fsync.o getdirentries.o \
+ getpeername.o getsockname.o getsockopt.o ioctl.o listen.o \
+ mkfifo.o mknod.o nfssvc.o open.o read.o readv.o recvfrom.o \
+ recvmsg.o select.o sendmsg.o sendto.o setsockopt.o \
+ shutdown.o sigaction.o sigaltstack.o socket.o socketpair.o \
+ wait4.o write.o writev.o
+
+PSEUDO= _exit.o _getlogin.o
+
+OBJS+= ${ASM} ${THREADASM} ${PSEUDO}
+
+${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 a.out ${.PREFIX}.o
+
+PASM= ${ASM:.o=.po}
+${PASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
+ @${ECHO} creating ${.PREFIX}.po
+ @printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
+ ${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
+ @${LD} -x -r ${.PREFIX}.po
+ @mv a.out ${.PREFIX}.po
+
+SASM= ${ASM:.o=.so}
+${SASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
+ @${ECHO} creating ${.PREFIX}.so
+ @printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
+ ${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
+
+${THREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
+ @${ECHO} creating ${.PREFIX}.o
+ @printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
+ ${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
+ @${LD} -x -r ${.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})\n' | \
+ ${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
+ @${LD} -x -r ${.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})\n' | \
+ ${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
+
+${PSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
+ @${ECHO} creating ${.PREFIX}.o
+ @printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
+ ${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
+ @${LD} -x -r ${.PREFIX}.o
+ @mv a.out ${.PREFIX}.o
+
+PPSEUDO=${PSEUDO:.o=.po}
+${PPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
+ @${ECHO} creating ${.PREFIX}.po
+ @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 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
diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc
new file mode 100644
index 0000000..a3f6ff9
--- /dev/null
+++ b/lib/libc_r/uthread/Makefile.inc
@@ -0,0 +1,75 @@
+# $Id$
+
+# uthread sources
+.PATH: ${.CURDIR}/uthread
+
+SRCS+= \
+ uthread_accept.c \
+ uthread_attr_setcreatesuspend.c \
+ uthread_bind.c \
+ uthread_clean.c \
+ uthread_close.c \
+ uthread_cond.c \
+ uthread_connect.c \
+ uthread_create.c \
+ uthread_detach.c \
+ uthread_dup.c \
+ uthread_dup2.c \
+ uthread_equal.c \
+ uthread_execve.c \
+ uthread_exit.c \
+ uthread_fchmod.c \
+ uthread_fchown.c \
+ uthread_fcntl.c \
+ uthread_fd.c \
+ uthread_file.c \
+ uthread_flock.c \
+ uthread_fork.c \
+ uthread_fstat.c \
+ uthread_fstatfs.c \
+ uthread_fsync.c \
+ uthread_getdirentries.c \
+ uthread_getpeername.c \
+ uthread_getprio.c \
+ uthread_getsockname.c \
+ uthread_getsockopt.c \
+ uthread_info.c \
+ uthread_init.c \
+ uthread_ioctl.c \
+ uthread_join.c \
+ uthread_kern.c \
+ uthread_listen.c \
+ uthread_longjmp.c \
+ uthread_mutex.c \
+ uthread_nanosleep.c \
+ uthread_once.c \
+ uthread_open.c \
+ uthread_pipe.c \
+ uthread_queue.c \
+ uthread_read.c \
+ uthread_readv.c \
+ uthread_recvfrom.c \
+ uthread_resume.c \
+ uthread_select.c \
+ uthread_self.c \
+ uthread_sendto.c \
+ uthread_seterrno.c \
+ uthread_setjmp.c \
+ uthread_setprio.c \
+ uthread_setsockopt.c \
+ uthread_shutdown.c \
+ uthread_sig.c \
+ uthread_sigaction.c \
+ uthread_sigblock.c \
+ uthread_signal.c \
+ uthread_sigprocmask.c \
+ uthread_sigsetmask.c \
+ uthread_sigsuspend.c \
+ uthread_socket.c \
+ uthread_socketpair.c \
+ uthread_spec.c \
+ uthread_suspend.c \
+ uthread_wait4.c \
+ uthread_write.c \
+ uthread_writev.c \
+ uthread_yield.c
diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h
new file mode 100644
index 0000000..fc8ba27
--- /dev/null
+++ b/lib/libc_r/uthread/pthread_private.h
@@ -0,0 +1,629 @@
+/*
+ * 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.
+ *
+ * Private thread definitions for the uthread kernel.
+ *
+ */
+
+#ifndef _PTHREAD_PRIVATE_H
+#define _PTHREAD_PRIVATE_H
+
+/*
+ * Evaluate the storage class specifier.
+ */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+#define SCLASS
+#else
+#define SCLASS extern
+#endif
+
+/*
+ * Include files.
+ */
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+/*
+ * Kernel fatal error handler macro.
+ */
+#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
+
+/*
+ * Thread creation state attributes.
+ */
+#define PTHREAD_CREATE_RUNNING 0
+#define PTHREAD_CREATE_SUSPENDED 1
+
+/*
+ * 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.
+ */
+#define CLOCK_RES_NSEC 10000000
+
+/*
+ * Number of microseconds between incremental priority updates for
+ * threads that are ready to run, but denied being run.
+ */
+#define INC_PRIO_USEC 500000
+
+/*
+ * Time slice period in microseconds.
+ */
+#define TIMESLICE_USEC 100000
+
+/*
+ * Flags.
+ */
+#define PTHREAD_DETACHED 0x1
+#define PTHREAD_SCOPE_SYSTEM 0x2
+#define PTHREAD_INHERIT_SCHED 0x4
+#define PTHREAD_NOFLOAT 0x8
+
+#define PTHREAD_CREATE_DETACHED PTHREAD_DETACHED
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_SCOPE_PROCESS 0
+#define PTHREAD_EXPLICIT_SCHED 0
+
+struct pthread_key {
+ pthread_mutex_t mutex;
+ long count;
+ void (*destructor) ();
+};
+
+/*
+ * Thread states.
+ */
+enum pthread_state {
+ PS_RUNNING,
+ PS_SIGTHREAD,
+ PS_MUTEX_WAIT,
+ PS_COND_WAIT,
+ PS_FDLR_WAIT,
+ PS_FDLW_WAIT,
+ PS_FDR_WAIT,
+ PS_FDW_WAIT,
+ PS_SELECT_WAIT,
+ PS_SLEEP_WAIT,
+ PS_WAIT_WAIT,
+ PS_SIGWAIT,
+ PS_JOIN,
+ PS_SUSPENDED,
+ PS_DEAD,
+ PS_STATE_MAX
+};
+
+
+/*
+ * File descriptor locking definitions.
+ */
+#define FD_READ 0x1
+#define FD_WRITE 0x2
+#define FD_RDWR (FD_READ | FD_WRITE)
+
+/*
+ * File descriptor table structure.
+ */
+struct fd_table_entry {
+ struct pthread_queue r_queue; /* Read queue. */
+ struct pthread_queue w_queue; /* Write queue. */
+ struct pthread *r_owner; /* Ptr to thread owning read lock. */
+ struct pthread *w_owner; /* Ptr to thread owning write lock. */
+ char *r_fname; /* Ptr to read lock source file name */
+ int r_lineno; /* Read lock source line number. */
+ char *w_fname; /* Ptr to write lock source file name */
+ int w_lineno; /* Write lock source line number. */
+ int r_lockcount; /* Count for FILE read locks. */
+ int w_lockcount; /* Count for FILE write locks. */
+ int flags; /* Flags used in open. */
+};
+
+struct pthread_select_data {
+ int nfds;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+};
+
+union pthread_wait_data {
+ pthread_mutex_t *mutex;
+ pthread_cond_t *cond;
+ const sigset_t *sigwait; /* Waiting on a signal in sigwait */
+ struct {
+ short fd; /* Used when thread waiting on fd */
+ short branch; /* Line number, for debugging. */
+ char *fname; /* Source file name for debugging.*/
+ } fd;
+ struct pthread_select_data * select_data;
+};
+
+/*
+ * Thread structure.
+ */
+struct pthread {
+ /*
+ * Pointer to the next thread in the thread linked list.
+ */
+ struct pthread *nxt;
+
+ /*
+ * Thread start routine, argument, stack pointer and thread
+ * attributes.
+ */
+ void *(*start_routine)(void *);
+ void *arg;
+ void *stack;
+ pthread_attr_t attr;
+
+ /*
+ * Thread-specific signal handler interface:
+ *
+ * Array of signal actions for this thread.
+ */
+ struct sigaction act[NSIG];
+
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__)
+ /*
+ * Saved floating point registers on systems where they are not
+ * saved in the signal context.
+ */
+ char saved_fp[108];
+#endif
+
+ /*
+ * Saved signal context used in call to sigreturn by
+ * _thread_kern_sched if sig_saved is TRUE.
+ */
+ struct sigcontext saved_sigcontext;
+
+ /*
+ * Saved jump buffer used in call to longjmp by _thread_kern_sched
+ * if sig_saved is FALSE.
+ */
+ jmp_buf saved_jmp_buf;
+
+ /*
+ * TRUE if the last state saved was a signal context. FALSE if the
+ * last state saved was a jump buffer.
+ */
+ int sig_saved;
+
+ /*
+ * Current signal mask and array of pending signals.
+ */
+ sigset_t sigmask;
+ int sigpend[NSIG];
+
+ /*
+ * Pointer to the parent thread for which the current thread is
+ * a signal handler thread, otherwise NULL if the current thread
+ * is not a signal handler thread.
+ */
+ struct pthread *parent_thread;
+
+ /* Thread state: */
+ enum pthread_state state;
+
+ /* Time that this thread was last made active. */
+ struct timeval last_active;
+
+ /* Time that this thread was last made inactive. */
+ struct timeval last_inactive;
+
+ /*
+ * Number of microseconds accumulated by this thread when
+ * time slicing is active.
+ */
+ long slice_usec;
+
+ /*
+ * Incremental priority accumulated by thread while it is ready to
+ * run but is denied being run.
+ */
+ int inc_prio;
+
+ /*
+ * Time to wake up thread. This is used for sleeping threads and
+ * for any operation which may time out (such as select).
+ */
+ struct timespec wakeup_time;
+
+ /* TRUE if operation has timed out. */
+ int timeout;
+
+ /*
+ * Error variable used instead of errno. The function __error()
+ * returns a pointer to this.
+ */
+ int error;
+
+ /* Join queue for waiting threads: */
+ struct pthread_queue join_queue;
+
+ /*
+ * The current thread can belong to only one queue at a time.
+ *
+ * Pointer to queue (if any) on which the current thread is waiting.
+ */
+ struct pthread_queue *queue;
+
+ /* Pointer to next element in queue. */
+ struct pthread *qnxt;
+
+ /* Wait data. */
+ union pthread_wait_data data;
+
+ /* Miscellaneous data. */
+ char flags;
+ char pthread_priority;
+ void *ret;
+ const void **specific_data;
+ int specific_data_count;
+
+ /* Cleanup handlers Link List */
+ struct pthread_cleanup *cleanup;
+};
+
+/*
+ * Global variables for the uthread kernel.
+ */
+
+/* Kernel thread structure used when there are no running threads: */
+SCLASS struct pthread _thread_kern_thread;
+
+/* Ptr to the thread structure for the running thread: */
+SCLASS struct pthread *_thread_run
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= &_thread_kern_thread;
+#else
+;
+#endif
+
+/* Ptr to the first thread in the thread linked list: */
+SCLASS struct pthread *_thread_link_list
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/*
+ * Array of kernel pipe file descriptors that are used to ensure that
+ * no signals are missed in calls to _thread_sys_select.
+ */
+SCLASS int _thread_kern_pipe[2]
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= {
+ -1,
+ -1
+};
+#else
+;
+#endif
+SCLASS int _thread_kern_in_select
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 0;
+#else
+;
+#endif
+
+/* Last time that an incremental priority update was performed: */
+SCLASS struct timeval kern_inc_prio_time
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { 0, 0 };
+#else
+;
+#endif
+
+/* Dead threads: */
+SCLASS struct pthread *_thread_dead
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Initial thread: */
+SCLASS struct pthread *_thread_initial
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+/* Default thread attributes: */
+SCLASS pthread_attr_t pthread_attr_default
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= { SCHED_RR, PTHREAD_DEFAULT_PRIORITY, PTHREAD_CREATE_RUNNING,
+ PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, PTHREAD_STACK_DEFAULT };
+#else
+;
+#endif
+
+/* File table information: */
+SCLASS struct fd_table_entry **_thread_fd_table
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL;
+#else
+;
+#endif
+
+SCLASS const int dtablecount
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 4096/sizeof(struct fd_table_entry);
+#else
+;
+#endif
+SCLASS int _thread_dtablesize /* Descriptor table size. */
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= 1024;
+#else
+;
+#endif
+
+/* Undefine the storage class specifier: */
+#undef SCLASS
+
+/*
+ * Function prototype definitions.
+ */
+__BEGIN_DECLS
+char *__ttyname_basic(int);
+char *__ttyname_r_basic(int, char *, size_t);
+char *ttyname_r(int, char *, size_t);
+int _thread_create(pthread_t *,const pthread_attr_t *,void *(*start_routine)(void *),void *,pthread_t);
+int _thread_fd_lock(int, int, struct timespec *,char *fname,int lineno);
+int nanosleep(struct timespec *, struct timespec *);
+void _thread_exit(char *, int, char *);
+void _thread_fd_unlock(int, int);
+void *_thread_cleanup(pthread_t);
+void _thread_cleanupspecific(void);
+void _thread_dump_info(void);
+void _thread_init(void);
+void _thread_kern_sched(struct sigcontext *);
+void _thread_kern_sched_state(enum pthread_state,char *fname,int lineno);
+void _thread_kern_set_timeout(struct timespec *);
+void _thread_kern_sig_block(int *);
+void _thread_kern_sig_unblock(int);
+void _thread_cleanup_pop(int);
+void _thread_sig_handler(int, int, struct sigcontext *);
+void _thread_start(void);
+void _thread_start_sig_handler(void);
+void _thread_seterrno(pthread_t,int);
+void _thread_queue_init(struct pthread_queue *);
+void _thread_queue_enq(struct pthread_queue *, struct pthread *);
+int _thread_queue_remove(struct pthread_queue *, struct pthread *);
+int _thread_fd_table_init(int fd);
+struct pthread *_thread_queue_get(struct pthread_queue *);
+struct pthread *_thread_queue_deq(struct pthread_queue *);
+
+/* #include <signal.h> */
+int _thread_sys_sigaction(int, const struct sigaction *, struct sigaction *);
+int _thread_sys_sigpending(sigset_t *);
+int _thread_sys_sigprocmask(int, const sigset_t *, sigset_t *);
+int _thread_sys_sigsuspend(const sigset_t *);
+int _thread_sys_sigblock(int);
+int _thread_sys_siginterrupt(int, int);
+int _thread_sys_sigpause(int);
+int _thread_sys_sigreturn(struct sigcontext *);
+int _thread_sys_sigsetmask(int);
+int _thread_sys_sigstack(const struct sigstack *, struct sigstack *);
+int _thread_sys_sigvec(int, struct sigvec *, struct sigvec *);
+void _thread_sys_psignal(unsigned int, const char *);
+void (*_thread_sys_signal(int, void (*)(int)))(int);
+
+/* #include <sys/stat.h> */
+#ifdef _SYS_STAT_H_
+int _thread_sys_fchmod(int, mode_t);
+int _thread_sys_fstat(int, struct stat *);
+int _thread_sys_fchflags(int, u_long);
+#endif
+
+/* #include <sys/mount.h> */
+#ifdef _SYS_MOUNT_H_
+int _thread_sys_fstatfs(int, struct statfs *);
+#endif
+int _thread_sys_pipe(int *);
+
+/* #include <sys/socket.h> */
+#ifdef _SYS_SOCKET_H_
+int _thread_sys_accept(int, struct sockaddr *, int *);
+int _thread_sys_bind(int, const struct sockaddr *, int);
+int _thread_sys_connect(int, const struct sockaddr *, int);
+int _thread_sys_getpeername(int, struct sockaddr *, int *);
+int _thread_sys_getsockname(int, struct sockaddr *, int *);
+int _thread_sys_getsockopt(int, int, int, void *, int *);
+int _thread_sys_listen(int, int);
+int _thread_sys_setsockopt(int, int, int, const void *, int);
+int _thread_sys_shutdown(int, int);
+int _thread_sys_socket(int, int, int);
+int _thread_sys_socketpair(int, int, int, int *);
+ssize_t _thread_sys_recv(int, void *, size_t, int);
+ssize_t _thread_sys_recvfrom(int, void *, size_t, int, struct sockaddr *, int *);
+ssize_t _thread_sys_recvmsg(int, struct msghdr *, int);
+ssize_t _thread_sys_send(int, const void *, size_t, int);
+ssize_t _thread_sys_sendmsg(int, const struct msghdr *, int);
+ssize_t _thread_sys_sendto(int, const void *,size_t, int, const struct sockaddr *, int);
+#endif
+
+/* #include <stdio.h> */
+#ifdef _STDIO_H_
+void _thread_flockfile(FILE *fp,char *fname,int lineno);
+void _thread_funlockfile(FILE *fp);
+FILE *_thread_sys_fdopen(int, const char *);
+FILE *_thread_sys_fopen(const char *, const char *);
+FILE *_thread_sys_freopen(const char *, const char *, FILE *);
+FILE *_thread_sys_popen(const char *, const char *);
+FILE *_thread_sys_tmpfile(void);
+char *_thread_sys_ctermid(char *);
+char *_thread_sys_cuserid(char *);
+char *_thread_sys_fgetln(FILE *, size_t *);
+char *_thread_sys_fgets(char *, int, FILE *);
+char *_thread_sys_gets(char *);
+char *_thread_sys_tempnam(const char *, const char *);
+char *_thread_sys_tmpnam(char *);
+int _thread_sys_fclose(FILE *);
+int _thread_sys_feof(FILE *);
+int _thread_sys_ferror(FILE *);
+int _thread_sys_fflush(FILE *);
+int _thread_sys_fgetc(FILE *);
+int _thread_sys_fgetpos(FILE *, fpos_t *);
+int _thread_sys_fileno(FILE *);
+int _thread_sys_fprintf(FILE *, const char *, ...);
+int _thread_sys_fpurge(FILE *);
+int _thread_sys_fputc(int, FILE *);
+int _thread_sys_fputs(const char *, FILE *);
+int _thread_sys_fscanf(FILE *, const char *, ...);
+int _thread_sys_fseek(FILE *, long, int);
+int _thread_sys_fsetpos(FILE *, const fpos_t *);
+int _thread_sys_getc(FILE *);
+int _thread_sys_getchar(void);
+int _thread_sys_getw(FILE *);
+int _thread_sys_pclose(FILE *);
+int _thread_sys_printf(const char *, ...);
+int _thread_sys_putc(int, FILE *);
+int _thread_sys_putchar(int);
+int _thread_sys_puts(const char *);
+int _thread_sys_putw(int, FILE *);
+int _thread_sys_remove(const char *);
+int _thread_sys_rename (const char *, const char *);
+int _thread_sys_scanf(const char *, ...);
+int _thread_sys_setlinebuf(FILE *);
+int _thread_sys_setvbuf(FILE *, char *, int, size_t);
+int _thread_sys_snprintf(char *, size_t, const char *, ...);
+int _thread_sys_sprintf(char *, const char *, ...);
+int _thread_sys_sscanf(const char *, const char *, ...);
+int _thread_sys_ungetc(int, FILE *);
+int _thread_sys_vfprintf(FILE *, const char *, _BSD_VA_LIST_);
+int _thread_sys_vprintf(const char *, _BSD_VA_LIST_);
+int _thread_sys_vscanf(const char *, _BSD_VA_LIST_);
+int _thread_sys_vsnprintf(char *, size_t, const char *, _BSD_VA_LIST_);
+int _thread_sys_vsprintf(char *, const char *, _BSD_VA_LIST_);
+int _thread_sys_vsscanf(const char *, const char *, _BSD_VA_LIST_);
+long _thread_sys_ftell(FILE *);
+size_t _thread_sys_fread(void *, size_t, size_t, FILE *);
+size_t _thread_sys_fwrite(const void *, size_t, size_t, FILE *);
+void _thread_sys_clearerr(FILE *);
+void _thread_sys_perror(const char *);
+void _thread_sys_rewind(FILE *);
+void _thread_sys_setbuf(FILE *, char *);
+void _thread_sys_setbuffer(FILE *, char *, int);
+#endif
+
+/* #include <unistd.h> */
+#ifdef _UNISTD_H_
+char *_thread_sys_ttyname(int);
+int _thread_sys_close(int);
+int _thread_sys_dup(int);
+int _thread_sys_dup2(int, int);
+int _thread_sys_exect(const char *, char * const *, char * const *);
+int _thread_sys_execve(const char *, char * const *, char * const *);
+int _thread_sys_fchdir(int);
+int _thread_sys_fchown(int, uid_t, gid_t);
+int _thread_sys_fsync(int);
+int _thread_sys_ftruncate(int, off_t);
+int _thread_sys_pause(void);
+int _thread_sys_pipe(int *);
+int _thread_sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+off_t _thread_sys_lseek(int, off_t, int);
+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);
+#endif
+
+/* #include <fcntl.h> */
+#ifdef _SYS_FCNTL_H_
+int _thread_sys_creat(const char *, mode_t);
+int _thread_sys_fcntl(int, int, ...);
+int _thread_sys_flock(int, int);
+int _thread_sys_open(const char *, int, ...);
+#endif
+
+/* #include <setjmp.h> */
+#ifdef _SETJMP_H_
+int __thread_sys_setjmp(jmp_buf);
+int _thread_sys_setjmp(jmp_buf);
+int _thread_sys_sigsetjmp(sigjmp_buf, int);
+void __thread_sys_longjmp(jmp_buf, int);
+void _thread_sys_longjmp(jmp_buf, int);
+void _thread_sys_longjmperror(void);
+void _thread_sys_siglongjmp(sigjmp_buf, int);
+#endif
+
+/* #include <sys/ioctl.h> */
+#ifdef _SYS_IOCTL_H_
+int _thread_sys_ioctl(int, unsigned long, ...);
+#endif
+
+/* #include <dirent.h> */
+#ifdef _DIRENT_H_
+DIR *___thread_sys_opendir2(const char *, int);
+DIR *_thread_sys_opendir(const char *);
+int _thread_sys_alphasort(const void *, const void *);
+int _thread_sys_scandir(const char *, struct dirent ***,
+ int (*)(struct dirent *), int (*)(const void *, const void *));
+int _thread_sys_closedir(DIR *);
+int _thread_sys_getdirentries(int, char *, int, long *);
+long _thread_sys_telldir(const DIR *);
+struct dirent *_thread_sys_readdir(DIR *);
+void _thread_sys_rewinddir(DIR *);
+void _thread_sys_seekdir(DIR *, long);
+#endif
+
+/* #include <sys/uio.h> */
+#ifdef _SYS_UIO_H_
+ssize_t _thread_sys_readv(int, const struct iovec *, int);
+ssize_t _thread_sys_writev(int, const struct iovec *, int);
+#endif
+
+/* #include <sys/wait.h> */
+#ifdef WNOHANG
+pid_t _thread_sys_wait(int *);
+pid_t _thread_sys_waitpid(pid_t, int *, int);
+pid_t _thread_sys_wait3(int *, int, struct rusage *);
+pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *);
+#endif
+__END_DECLS
+
+#endif /* !_PTHREAD_PRIVATE_H */
diff --git a/lib/libc_r/uthread/uthread_accept.c b/lib/libc_r/uthread/uthread_accept.c
new file mode 100644
index 0000000..e885057
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_accept.c
@@ -0,0 +1,94 @@
+/*
+ * 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>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+accept(int fd, struct sockaddr * name, int *namelen)
+{
+ int ret;
+
+ /* Lock teh file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Enter a loop to wait for a connection request: */
+ while ((ret = _thread_sys_accept(fd, name, namelen)) < 0) {
+ /* Check if the socket is to block: */
+ if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ /* Save the socket file descriptor: */
+ _thread_run->data.fd.fd = fd;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(NULL);
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
+
+ /* Check if the wait was interrupted: */
+ if (errno == EINTR) {
+ /* Return an error status: */
+ ret = -1;
+ break;
+ }
+ } else {
+ /*
+ * Another error has occurred, so exit the
+ * loop here:
+ */
+ break;
+ }
+ }
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+
+ /* Check for errors: */
+ if (ret < 0) {
+ }
+ /* Initialise the file descriptor table for the new socket: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the socket: */
+ _thread_sys_close(ret);
+
+ /* Return an error: */
+ ret = -1;
+ }
+ }
+ /* Return the socket file descriptor or -1 on error: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_attr_setcreatesuspend.c b/lib/libc_r/uthread/uthread_attr_setcreatesuspend.c
new file mode 100644
index 0000000..99d9177
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_attr_setcreatesuspend.c
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_attr_setcreatesuspend(pthread_attr_t *attr)
+{
+ attr->suspend = PTHREAD_CREATE_SUSPENDED;
+ return(0);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_bind.c b/lib/libc_r/uthread/uthread_bind.c
new file mode 100644
index 0000000..1f7bbec
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_bind.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+bind(int fd, const struct sockaddr * name, int namelen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_bind(fd, name, namelen);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_clean.c b/lib/libc_r/uthread/uthread_clean.c
new file mode 100644
index 0000000..99893f6
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_clean.c
@@ -0,0 +1,73 @@
+/*
+ * 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 <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_cleanup_push(void (*routine) (void *), void *routine_arg)
+{
+ struct pthread_cleanup *new;
+ int ret;
+
+ if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) {
+ new->routine = routine;
+ new->routine_arg = routine_arg;
+ new->next = _thread_run->cleanup;
+
+ _thread_run->cleanup = new;
+ ret = 0;
+ } else {
+ ret = ENOMEM;
+ }
+ return (ret);
+}
+
+void
+_thread_cleanup_pop(int execute)
+{
+ struct pthread_cleanup *old;
+
+ if ((old = _thread_run->cleanup) != NULL) {
+ _thread_run->cleanup = old->next;
+ if (execute) {
+ old->routine(old->routine_arg);
+ }
+ free(old);
+ }
+}
+
+#endif
diff --git a/lib/libc_r/uthread/uthread_close.c b/lib/libc_r/uthread/uthread_close.c
new file mode 100644
index 0000000..f98e056
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_close.c
@@ -0,0 +1,48 @@
+/*
+ * 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+close(int fd)
+{
+ int ret;
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_close(fd);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_cond.c b/lib/libc_r/uthread/uthread_cond.c
new file mode 100644
index 0000000..930f31a
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_cond.c
@@ -0,0 +1,293 @@
+/*
+ * 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr)
+{
+ enum pthread_cond_type type;
+ 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;
+ } 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;
+
+ /* Trap invalid condition variable types: */
+ default:
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, 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;
+ }
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+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);
+ 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;
+ }
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_wait(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:
+ /* Queue the running thread for the condition variable: */
+ _thread_queue_enq(&cond->c_queue, _thread_run);
+
+ /* Unlock the mutex: */
+ pthread_mutex_unlock(mutex);
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Lock the mutex: */
+ rval = pthread_mutex_lock(mutex);
+ 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);
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
+ const struct timespec * abstime)
+{
+ 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);
+
+ /* 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;
+ }
+ }
+ 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);
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_signal(pthread_cond_t * cond)
+{
+ int rval = 0;
+ 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;
+ }
+ 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);
+
+ /* Return the completion status: */
+ return (rval);
+}
+
+int
+pthread_cond_broadcast(pthread_cond_t * cond)
+{
+ int rval = 0;
+ 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:
+ /* Enter a loop to bring all threads off the condition queue: */
+ while ((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: */
+ _thread_seterrno(_thread_run, EINVAL);
+ rval = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_connect.c b/lib/libc_r/uthread/uthread_connect.c
new file mode 100644
index 0000000..bf42db3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_connect.c
@@ -0,0 +1,76 @@
+/*
+ * 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>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+connect(int fd, const struct sockaddr * name, int namelen)
+{
+ struct sockaddr tmpname;
+ int ret, tmpnamelen;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ if ((ret = _thread_sys_connect(fd, name, namelen)) < 0) {
+ if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) &&
+ ((errno == EWOULDBLOCK) || (errno == EINPROGRESS) ||
+ (errno == EALREADY) || (errno == EAGAIN))) {
+ _thread_run->data.fd.fd = fd;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
+
+ tmpnamelen = sizeof(tmpname);
+ /* 0 now lets see if it really worked */
+ if (((ret = _thread_sys_getpeername(fd, &tmpname, &tmpnamelen)) < 0) && (errno == ENOTCONN)) {
+
+ /*
+ * Get the error, this function
+ * should not fail
+ */
+ _thread_sys_getsockopt(fd, SOL_SOCKET, SO_ERROR, &errno, &tmpnamelen);
+ }
+ } else {
+ ret = -1;
+ }
+ }
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_create.c b/lib/libc_r/uthread/uthread_create.c
new file mode 100644
index 0000000..e6db381
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_create.c
@@ -0,0 +1,277 @@
+/*
+ * 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>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <machine/reg.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_create(pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg, pthread_t parent)
+{
+ int i;
+ int ret = 0;
+ int status;
+ pthread_t new_thread;
+ void *stack;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Allocate memory for the thread structure: */
+ if ((new_thread = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
+ /* Insufficient memory to create a thread: */
+ ret = EAGAIN;
+ } else {
+ /* Check if default thread attributes are required: */
+ if (attr == NULL) {
+ /* Use the default thread attributes: */
+ attr = &pthread_attr_default;
+ }
+ /* Check if a stack was specified in the thread attributes: */
+ if ((stack = attr->stackaddr_attr) != NULL) {
+ }
+ /* Allocate memory for the stack: */
+ else if ((stack = (void *) malloc(attr->stacksize_attr)) == NULL) {
+ /* Insufficient memory to create a thread: */
+ ret = EAGAIN;
+ free(new_thread);
+ }
+ /* Check for errors: */
+ if (ret != 0) {
+ } else {
+ /* Initialise the thread structure: */
+ memset(new_thread, 0, sizeof(struct pthread));
+ new_thread->slice_usec = -1;
+ new_thread->sig_saved = 0;
+ new_thread->stack = stack;
+ new_thread->start_routine = start_routine;
+ new_thread->arg = arg;
+ if (attr->suspend == PTHREAD_CREATE_SUSPENDED) {
+ new_thread->state = PS_SUSPENDED;
+ } else {
+ new_thread->state = PS_RUNNING;
+ }
+
+ /* Initialise the thread for signals: */
+ new_thread->sigmask = _thread_run->sigmask;
+
+ /*
+ * Enter a loop to initialise the signal handler
+ * array:
+ */
+ for (i = 1; i < NSIG; i++) {
+ /* Default the signal handler: */
+ sigfillset(&new_thread->act[i - 1].sa_mask);
+ new_thread->act[i - 1].sa_handler = _thread_run->act[i - 1].sa_handler;
+ new_thread->act[i - 1].sa_flags = _thread_run->act[i - 1].sa_flags;
+ }
+
+ /* Initialise the jump buffer: */
+ _thread_sys_setjmp(new_thread->saved_jmp_buf);
+
+ /*
+ * Set up new stack frame so that it looks like it
+ * returned from a longjmp() to the beginning of
+ * _thread_start(). Check if this is a user thread:
+ */
+ if (parent == NULL) {
+ /* Use the user start function: */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[0] = (long) _thread_start;
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[2] = (long) _thread_start;
+ new_thread->saved_jmp_buf[4 + R_RA] = 0;
+ new_thread->saved_jmp_buf[4 + R_T12] = (long) _thread_start;
+#else
+ new_thread->saved_jmp_buf[0] = (long) _thread_start;
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+ } else {
+ /*
+ * Use the (funny) signal handler start
+ * function:
+ */
+#if defined(__FreeBSD__)
+ new_thread->saved_jmp_buf[0]._jb[0] = (int) _thread_start_sig_handler;
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[2] = (long) _thread_start_sig_handler;
+ new_thread->saved_jmp_buf[4 + R_RA] = 0;
+ new_thread->saved_jmp_buf[4 + R_T12] = (long) _thread_start_sig_handler;
+#else
+ new_thread->saved_jmp_buf[0] = (long) _thread_start_sig_handler;
+#endif
+#else
+#error "Don't recognize this operating system!"
+#endif
+ }
+
+ /* 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));
+#elif defined(__NetBSD__)
+#if defined(__alpha)
+ new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + attr->stacksize_attr - sizeof(double);
+#else
+ new_thread->saved_jmp_buf[2] = (long) new_thread->stack + attr->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));
+
+ /*
+ * Check if this thread is to inherit the scheduling
+ * attributes from its parent:
+ */
+ if (new_thread->attr.flags & PTHREAD_INHERIT_SCHED) {
+ /* Copy the scheduling attributes: */
+ new_thread->pthread_priority = _thread_run->pthread_priority;
+ new_thread->attr.prio = _thread_run->pthread_priority;
+ new_thread->attr.schedparam_policy = _thread_run->attr.schedparam_policy;
+ } else {
+ /*
+ * Use just the thread priority, leaving the
+ * other scheduling attributes as their
+ * default values:
+ */
+ new_thread->pthread_priority = new_thread->attr.prio;
+ }
+
+ /* Initialise the join queue for the new thread: */
+ _thread_queue_init(&(new_thread->join_queue));
+
+ /* Initialise hooks in the thread structure: */
+ new_thread->specific_data = NULL;
+ new_thread->cleanup = NULL;
+ new_thread->queue = NULL;
+ new_thread->qnxt = NULL;
+ new_thread->parent_thread = parent;
+ new_thread->flags = 0;
+
+ /* Add the thread to the linked list of all threads: */
+ new_thread->nxt = _thread_link_list;
+ _thread_link_list = new_thread;
+
+ /* Return a pointer to the thread structure: */
+ (*thread) = new_thread;
+
+ /* Check if a parent thread was specified: */
+ if (parent != NULL) {
+ /*
+ * A parent thread was specified, so this is
+ * a signal handler thread which must now
+ * wait for the signal handler to complete:
+ */
+ parent->state = PS_SIGTHREAD;
+ } else {
+ /* Schedule the new user thread: */
+ _thread_kern_sched(NULL);
+ }
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the status: */
+ return (ret);
+}
+
+int
+pthread_create(pthread_t * thread, const pthread_attr_t * attr,
+ void *(*start_routine) (void *), void *arg)
+{
+ int ret = 0;
+
+ /*
+ * Call the low level thread creation function which allows a parent
+ * thread to be specified:
+ */
+ ret = _thread_create(thread, attr, start_routine, arg, NULL);
+
+ /* Return the status: */
+ return (ret);
+}
+
+void
+_thread_start(void)
+{
+ /* Run the current thread's start routine with argument: */
+ pthread_exit(_thread_run->start_routine(_thread_run->arg));
+
+ /* This point should never be reached. */
+ PANIC("Thread has resumed after exit");
+}
+
+void
+_thread_start_sig_handler(void)
+{
+ int sig;
+ long arg;
+ void (*sig_routine) (int);
+
+ /*
+ * Cast the argument from 'void *' to a variable that is NO SMALLER
+ * than a pointer (otherwise gcc under NetBSD/Alpha will complain):
+ */
+ arg = (long) _thread_run->arg;
+
+ /* Cast the argument as a signal number: */
+ sig = (int) arg;
+
+ /* Cast a pointer to the signal handler function: */
+ sig_routine = (void (*) (int)) _thread_run->start_routine;
+
+ /* Call the signal handler function: */
+ (*sig_routine) (sig);
+
+ /* Exit the signal handler thread: */
+ pthread_exit(&arg);
+
+ /* This point should never be reached. */
+ PANIC("Signal handler thread has resumed after exit");
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_detach.c b/lib/libc_r/uthread/uthread_detach.c
new file mode 100644
index 0000000..f24d16f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_detach.c
@@ -0,0 +1,83 @@
+/*
+ * 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_detach(pthread_t * p_pthread)
+{
+ int rval = 0;
+ int status;
+ pthread_t next_thread;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check for invalid calling parameters: */
+ if (p_pthread == NULL || (pthread = *p_pthread) == NULL) {
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, EINVAL);
+ rval = -1;
+ }
+ /* Check if the thread has not been detached: */
+ else if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+ /* Flag the thread as detached: */
+ pthread->attr.flags |= PTHREAD_DETACHED;
+
+ /* Enter a loop to bring all threads off the join queue: */
+ while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) {
+ /* Make the thread run: */
+ next_thread->state = PS_RUNNING;
+ }
+
+ /*
+ * NULL the thread pointer now that the thread has been
+ * detached:
+ */
+ *p_pthread = NULL;
+ } else {
+ /* Return an error: */
+ _thread_seterrno(_thread_run, ESRCH);
+ rval = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_dup.c b/lib/libc_r/uthread/uthread_dup.c
new file mode 100644
index 0000000..e6c4598
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_dup.c
@@ -0,0 +1,37 @@
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+dup(int fd)
+{
+ int ret;
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Perform the 'dup' syscall: */
+ if ((ret = _thread_sys_dup(fd)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(ret);
+
+ /* Reset the file descriptor: */
+ ret = -1;
+ } else {
+ /*
+ * Save the file open flags so that they can be
+ * checked later:
+ */
+ _thread_fd_table[ret]->flags = _thread_fd_table[fd]->flags;
+ }
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_dup2.c b/lib/libc_r/uthread/uthread_dup2.c
new file mode 100644
index 0000000..6da78f7
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_dup2.c
@@ -0,0 +1,74 @@
+/*
+ * 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+dup2(int fd, int newfd)
+{
+ int ret;
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(newfd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Perform the 'dup2' syscall: */
+ if ((ret = _thread_sys_dup2(fd, newfd)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(ret);
+
+ /* Reset the file descriptor: */
+ ret = -1;
+ } else {
+ /*
+ * Save the file open flags so that they can
+ * be checked later:
+ */
+ _thread_fd_table[ret]->flags = _thread_fd_table[fd]->flags;
+ }
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(newfd, FD_RDWR);
+ }
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_equal.c b/lib/libc_r/uthread/uthread_equal.c
new file mode 100644
index 0000000..99ffb5d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_equal.c
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_equal(pthread_t t1, pthread_t t2)
+{
+ /* Compare the two thread pointers: */
+ return (t1 == t2);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_execve.c b/lib/libc_r/uthread/uthread_execve.c
new file mode 100644
index 0000000..6e1fda5
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_execve.c
@@ -0,0 +1,87 @@
+/*
+ * 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>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+execve(const char *name, char *const * argv, char *const * envp)
+{
+ int i;
+ int ret;
+ struct sigaction act;
+ struct sigaction oact;
+
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /* Enter a loop to adopt the signal actions for the running thread: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be caught: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ /* Don't do anything with these signals. */
+ } else {
+ /*
+ * Check if the running thread is ignoring this
+ * signal:
+ */
+ if (_thread_run->act[i - 1].sa_handler == SIG_IGN) {
+ /* Continue to ignore this signal: */
+ act.sa_handler = SIG_IGN;
+ } else {
+ /* Use the default handler for this signal: */
+ act.sa_handler = SIG_DFL;
+ }
+
+ /* Copy the mask and flags for this signal: */
+ act.sa_mask = _thread_run->act[i - 1].sa_mask;
+ act.sa_flags = _thread_run->act[i - 1].sa_flags;
+
+ /* Change the signal action for the process: */
+ _thread_sys_sigaction(i, &act, &oact);
+ }
+ }
+
+ /* Execute the process: */
+ _thread_sys_sigprocmask(SIG_SETMASK, &_thread_run->sigmask, NULL);
+
+ /* Execute the process: */
+ ret = _thread_sys_execve(name, argv, envp);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_exit.c b/lib/libc_r/uthread/uthread_exit.c
new file mode 100644
index 0000000..292fce9
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_exit.c
@@ -0,0 +1,167 @@
+/*
+ * 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>
+#include <string.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_exit(char *fname, int lineno, char *string)
+{
+ char s[256];
+
+ /* Prepare an error message string: */
+ strcpy(s, "Fatal error '");
+ strcat(s, string);
+ strcat(s, "' at line ? ");
+ strcat(s, "in file ");
+ strcat(s, fname);
+ strcat(s, " (errno = ?");
+ strcat(s, ")\n");
+
+ /* Write the string to the standard error file descriptor: */
+ _thread_sys_write(2, s, strlen(s));
+
+ /* Force this process to exit: */
+ _exit(1);
+}
+
+void
+pthread_exit(void *status)
+{
+ int sig;
+ long l;
+ pthread_t pthread;
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Save the return value: */
+ _thread_run->ret = status;
+
+ while (_thread_run->cleanup != NULL) {
+ _thread_cleanup_pop(1);
+ }
+
+ if (_thread_run->attr.cleanup_attr != NULL) {
+ _thread_run->attr.cleanup_attr(_thread_run->attr.arg_attr);
+ }
+ /* Check if there is thread specific data: */
+ if (_thread_run->specific_data != NULL) {
+ /* Run the thread-specific data destructors: */
+ _thread_cleanupspecific();
+ }
+ /* Check if there are any threads joined to this one: */
+ while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) {
+ /* Wake the joined thread and let it detach this thread: */
+ pthread->state = PS_RUNNING;
+ }
+
+ /* Check if the running thread is at the head of the linked list: */
+ if (_thread_link_list == _thread_run) {
+ /* There is no previous thread: */
+ _thread_link_list = _thread_run->nxt;
+ } else {
+ /* Point to the first thread in the list: */
+ pthread = _thread_link_list;
+
+ /*
+ * Enter a loop to find the thread in the linked list before
+ * the running thread:
+ */
+ while (pthread != NULL && pthread->nxt != _thread_run) {
+ /* Point to the next thread: */
+ pthread = pthread->nxt;
+ }
+
+ /* Check that a previous thread was found: */
+ if (pthread != NULL) {
+ /*
+ * Point the previous thread to the one after the
+ * running thread:
+ */
+ pthread->nxt = _thread_run->nxt;
+ }
+ }
+
+ /* Check if this is a signal handler thread: */
+ if (_thread_run->parent_thread != NULL) {
+ /*
+ * Enter a loop to search for other threads with the same
+ * parent:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Compare the parent thread pointers: */
+ if (pthread->parent_thread == _thread_run->parent_thread) {
+ /*
+ * The parent thread is waiting on at least
+ * one other signal handler. Exit the loop
+ * now that this is known.
+ */
+ break;
+ }
+ }
+
+ /*
+ * Check if the parent is not waiting on any other signal
+ * handler threads:
+ */
+ if (pthread == NULL) {
+ /* Allow the parent thread to run again: */
+ _thread_run->parent_thread->state = PS_RUNNING;
+ }
+ /* Get the signal number: */
+ l = (long) _thread_run->arg;
+ sig = (int) l;
+
+ /* Unblock the signal from the parent thread: */
+ sigdelset(&_thread_run->parent_thread->sigmask, sig);
+ }
+ /*
+ * This thread will never run again. Add it to the list of dead
+ * threads:
+ */
+ _thread_run->nxt = _thread_dead;
+ _thread_dead = _thread_run;
+
+ /*
+ * The running thread is no longer in the thread link list so it will
+ * now die:
+ */
+ _thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__);
+
+ /* This point should not be reached. */
+ PANIC("Dead thread has resumed");
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fchmod.c b/lib/libc_r/uthread/uthread_fchmod.c
new file mode 100644
index 0000000..ee5dfde
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fchmod.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fchmod(int fd, mode_t mode)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_fchmod(fd, mode);
+ _thread_fd_unlock(fd, FD_WRITE);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fchown.c b/lib/libc_r/uthread/uthread_fchown.c
new file mode 100644
index 0000000..52f65b8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fchown.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 <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fchown(int fd, uid_t owner, gid_t group)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_fchown(fd, owner, group);
+ _thread_fd_unlock(fd, FD_WRITE);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fcntl.c b/lib/libc_r/uthread/uthread_fcntl.c
new file mode 100644
index 0000000..ae069b8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fcntl.c
@@ -0,0 +1,115 @@
+/*
+ * 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 <stdarg.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fcntl(int fd, int cmd,...)
+{
+ int flags = 0;
+ int oldfd;
+ int ret;
+ int status;
+ va_list ap;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Lock the file descriptor: */
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ /* Initialise the variable argument list: */
+ va_start(ap, cmd);
+
+ /* Process according to file control command type: */
+ switch (cmd) {
+ /* Duplicate a file descriptor: */
+ case F_DUPFD:
+ /*
+ * Get the file descriptor that the caller wants to
+ * use:
+ */
+ oldfd = va_arg(ap, int);
+
+ /* Initialise the file descriptor table entry: */
+ if ((ret = _thread_sys_fcntl(fd, cmd, oldfd)) < 0) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(ret) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(ret);
+
+ /* Reset the file descriptor: */
+ ret = -1;
+ } else {
+ /*
+ * Save the file open flags so that they can
+ * be checked later:
+ */
+ _thread_fd_table[ret]->flags = _thread_fd_table[fd]->flags;
+ }
+ break;
+ case F_SETFD:
+ break;
+ case F_GETFD:
+ break;
+ case F_GETFL:
+ ret = _thread_fd_table[fd]->flags;
+ break;
+ case F_SETFL:
+ flags = va_arg(ap, int);
+ if ((ret = _thread_sys_fcntl(fd, cmd, flags | O_NONBLOCK)) == 0) {
+ _thread_fd_table[fd]->flags = flags;
+ }
+ break;
+ default:
+ /* Might want to make va_arg use a union */
+ ret = _thread_sys_fcntl(fd, cmd, va_arg(ap, void *));
+ break;
+ }
+
+ /* Free variable arguments: */
+ va_end(ap);
+
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fd.c b/lib/libc_r/uthread/uthread_fd.c
new file mode 100644
index 0000000..b41631a
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fd.c
@@ -0,0 +1,364 @@
+/*
+ * 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>
+#include <stdlib.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_fd_table_init(int fd)
+{
+ int ret = 0;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check if the file descriptor is out of range: */
+ if (fd < 0 || fd >= _thread_dtablesize) {
+ /* Return a bad file descriptor error: */
+ _thread_seterrno(_thread_run, EBADF);
+ ret = -1;
+ }
+ /*
+ * Check if memory has already been allocated for this file
+ * descriptor:
+ */
+ else if (_thread_fd_table[fd] != NULL) {
+ }
+ /* Allocate memory for the file descriptor table entry: */
+ else if ((_thread_fd_table[fd] = (struct fd_table_entry *) malloc(sizeof(struct fd_table_entry))) == NULL) {
+ /* Return a bad file descriptor error: */
+ _thread_seterrno(_thread_run, EBADF);
+ ret = -1;
+ } else {
+ /* Initialise the file locks: */
+ _thread_fd_table[fd]->r_owner = NULL;
+ _thread_fd_table[fd]->w_owner = NULL;
+ _thread_fd_table[fd]->r_fname = NULL;
+ _thread_fd_table[fd]->w_fname = NULL;
+ _thread_fd_table[fd]->r_lineno = 0;;
+ _thread_fd_table[fd]->w_lineno = 0;;
+ _thread_fd_table[fd]->r_lockcount = 0;;
+ _thread_fd_table[fd]->w_lockcount = 0;;
+
+ /* Default the flags: */
+ _thread_fd_table[fd]->flags = 0;
+
+ /* Initialise the read/write queues: */
+ _thread_queue_init(&_thread_fd_table[fd]->r_queue);
+ _thread_queue_init(&_thread_fd_table[fd]->w_queue);
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+void
+_thread_fd_unlock(int fd, int lock_type)
+{
+ int ret;
+ int status;
+
+ /* Block signals while the file descriptor lock is tested: */
+ _thread_kern_sig_block(&status);
+
+ /*
+ * Check that the file descriptor table is initialised for this
+ * entry:
+ */
+ if ((ret = _thread_fd_table_init(fd)) != 0) {
+ } else {
+ /* Check if the running thread owns the read lock: */
+ if (_thread_fd_table[fd]->r_owner == _thread_run) {
+ /* Check the file descriptor and lock types: */
+ if (lock_type == FD_READ || lock_type == FD_RDWR) {
+ /*
+ * Decrement the read lock count for the
+ * running thread:
+ */
+ _thread_fd_table[fd]->r_lockcount--;
+
+ /*
+ * Check if the running thread still has read
+ * locks on this file descriptor:
+ */
+ if (_thread_fd_table[fd]->r_lockcount != 0) {
+ }
+ /*
+ * Get the next thread in the queue for a
+ * read lock on this file descriptor:
+ */
+ else if ((_thread_fd_table[fd]->r_owner = _thread_queue_deq(&_thread_fd_table[fd]->r_queue)) == NULL) {
+ } else {
+ /*
+ * Set the state of the new owner of
+ * the thread to running:
+ */
+ _thread_fd_table[fd]->r_owner->state = PS_RUNNING;
+
+ /*
+ * Reset the number of read locks.
+ * This will be incremented by the
+ * new owner of the lock when it sees
+ * that it has the lock.
+ */
+ _thread_fd_table[fd]->r_lockcount = 0;
+ }
+ }
+ }
+ /* Check if the running thread owns the write lock: */
+ if (_thread_fd_table[fd]->w_owner == _thread_run) {
+ /* Check the file descriptor and lock types: */
+ if (lock_type == FD_WRITE || lock_type == FD_RDWR) {
+ /*
+ * Decrement the write lock count for the
+ * running thread:
+ */
+ _thread_fd_table[fd]->w_lockcount--;
+
+ /*
+ * Check if the running thread still has
+ * write locks on this file descriptor:
+ */
+ if (_thread_fd_table[fd]->w_lockcount != 0) {
+ }
+ /*
+ * Get the next thread in the queue for a
+ * write lock on this file descriptor:
+ */
+ else if ((_thread_fd_table[fd]->w_owner = _thread_queue_deq(&_thread_fd_table[fd]->w_queue)) == NULL) {
+ } else {
+ /*
+ * Set the state of the new owner of
+ * the thread to running:
+ */
+ _thread_fd_table[fd]->w_owner->state = PS_RUNNING;
+
+ /*
+ * Reset the number of write locks.
+ * This will be incremented by the
+ * new owner of the lock when it
+ * sees that it has the lock.
+ */
+ _thread_fd_table[fd]->w_lockcount = 0;
+ }
+ }
+ }
+ }
+
+ /* Unblock signals again: */
+ _thread_kern_sig_unblock(status);
+
+ /* Nothing to return. */
+ return;
+}
+
+int
+_thread_fd_lock(int fd, int lock_type, struct timespec * timeout,
+ char *fname, int lineno)
+{
+ int ret;
+ int status;
+
+ /* Block signals while the file descriptor lock is tested: */
+ _thread_kern_sig_block(&status);
+
+ /*
+ * Check that the file descriptor table is initialised for this
+ * entry:
+ */
+ if ((ret = _thread_fd_table_init(fd)) != 0) {
+ } else {
+ /* Check the file descriptor and lock types: */
+ if (lock_type == FD_READ || lock_type == FD_RDWR) {
+ /*
+ * Enter a loop to wait for the file descriptor to be
+ * locked for read for the current thread:
+ */
+ while (_thread_fd_table[fd]->r_owner != _thread_run) {
+ /*
+ * Check if the file descriptor is locked by
+ * another thread:
+ */
+ if (_thread_fd_table[fd]->r_owner != NULL) {
+ /*
+ * Another thread has locked the file
+ * descriptor for read, so join the
+ * queue of threads waiting for a
+ * read lock on this file descriptor:
+ */
+ _thread_queue_enq(&_thread_fd_table[fd]->r_queue, _thread_run);
+
+ /*
+ * Save the file descriptor details
+ * in the thread structure for the
+ * running thread:
+ */
+ _thread_run->data.fd.fd = fd;
+ _thread_run->data.fd.branch = lineno;
+ _thread_run->data.fd.fname = fname;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(timeout);
+
+ /*
+ * Schedule this thread to wait on
+ * the read lock. It will only be
+ * woken when it becomes the next in
+ * the queue and is granted access
+ * to the lock by the thread
+ * that is unlocking the file
+ * descriptor.
+ */
+ _thread_kern_sched_state(PS_FDLR_WAIT, __FILE__, __LINE__);
+
+ /*
+ * Block signals so that the file
+ * descriptor lock can again be
+ * tested:
+ */
+ _thread_kern_sig_block(NULL);
+ } else {
+ /*
+ * The running thread now owns the
+ * read lock on this file descriptor:
+ */
+ _thread_fd_table[fd]->r_owner = _thread_run;
+
+ /*
+ * Reset the number of read locks for
+ * this file descriptor:
+ */
+ _thread_fd_table[fd]->r_lockcount = 0;
+
+ /*
+ * Save the source file details for
+ * debugging:
+ */
+ _thread_fd_table[fd]->r_fname = fname;
+ _thread_fd_table[fd]->r_lineno = lineno;
+ }
+ }
+
+ /* Increment the read lock count: */
+ _thread_fd_table[fd]->r_lockcount++;
+ }
+ /* Check the file descriptor and lock types: */
+ if (lock_type == FD_WRITE || lock_type == FD_RDWR) {
+ /*
+ * Enter a loop to wait for the file descriptor to be
+ * locked for write for the current thread:
+ */
+ while (_thread_fd_table[fd]->w_owner != _thread_run) {
+ /*
+ * Check if the file descriptor is locked by
+ * another thread:
+ */
+ if (_thread_fd_table[fd]->w_owner != NULL) {
+ /*
+ * Another thread has locked the file
+ * descriptor for write, so join the
+ * queue of threads waiting for a
+ * write lock on this file
+ * descriptor:
+ */
+ _thread_queue_enq(&_thread_fd_table[fd]->w_queue, _thread_run);
+
+ /*
+ * Save the file descriptor details
+ * in the thread structure for the
+ * running thread:
+ */
+ _thread_run->data.fd.fd = fd;
+ _thread_run->data.fd.branch = lineno;
+ _thread_run->data.fd.fname = fname;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(timeout);
+
+ /*
+ * Schedule this thread to wait on
+ * the write lock. It will only be
+ * woken when it becomes the next in
+ * the queue and is granted access to
+ * the lock by the thread that is
+ * unlocking the file descriptor.
+ */
+ _thread_kern_sched_state(PS_FDLW_WAIT, __FILE__, __LINE__);
+
+ /*
+ * Block signals so that the file
+ * descriptor lock can again be
+ * tested:
+ */
+ _thread_kern_sig_block(NULL);
+ } else {
+ /*
+ * The running thread now owns the
+ * write lock on this file
+ * descriptor:
+ */
+ _thread_fd_table[fd]->w_owner = _thread_run;
+
+ /*
+ * Reset the number of write locks
+ * for this file descriptor:
+ */
+ _thread_fd_table[fd]->w_lockcount = 0;
+
+ /*
+ * Save the source file details for
+ * debugging:
+ */
+ _thread_fd_table[fd]->w_fname = fname;
+ _thread_fd_table[fd]->w_lineno = lineno;
+ }
+ }
+
+ /* Increment the write lock count: */
+ _thread_fd_table[fd]->w_lockcount++;
+ }
+ }
+
+ /* Unblock signals again: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_file.c b/lib/libc_r/uthread/uthread_file.c
new file mode 100644
index 0000000..0d8e9a3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_file.c
@@ -0,0 +1,125 @@
+/*
+ * 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 <signal.h>
+#include <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_flockfile(FILE * fp, char *fname, int lineno)
+{
+ int fd, flags;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if ((fd = fileno(fp)) >= 0) {
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else {
+ if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
+ }
+
+ /* This might fail but POSIX doesn't give a damn. */
+ _thread_fd_lock(fd, flags, NULL, fname, lineno);
+ }
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return;
+}
+
+int
+_thread_ftrylockfile(FILE * fp)
+{
+ int fd = 0;
+ int flags;
+ int status;
+
+ if ((fd = fileno(fp)) >= 0) {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else {
+ if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
+ }
+ if (!(_thread_fd_table[fd]->r_owner && _thread_fd_table[fd]->w_owner)) {
+ _thread_fd_lock(fd, flags, NULL, __FILE__, __LINE__);
+ fd = 0;
+ } else {
+ fd = -1;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+ return (fd);
+}
+
+void
+_thread_funlockfile(FILE * fp)
+{
+ int fd, flags;
+ int status;
+
+ if ((fd = fileno(fp)) >= 0) {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if (fp->_flags & __SRW) {
+ flags = FD_READ | FD_WRITE;
+ } else if (fp->_flags & __SWR) {
+ flags = FD_WRITE;
+ } else {
+ flags = FD_READ;
+ }
+ _thread_fd_unlock(fd, flags);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+ return;
+}
+
+#endif
diff --git a/lib/libc_r/uthread/uthread_flock.c b/lib/libc_r/uthread/uthread_flock.c
new file mode 100644
index 0000000..4071b54
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_flock.c
@@ -0,0 +1,49 @@
+/*
+ * 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 <sys/file.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+flock(int fd, int operation)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_flock(fd, operation);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fork.c b/lib/libc_r/uthread/uthread_fork.c
new file mode 100644
index 0000000..6e7ca0d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fork.c
@@ -0,0 +1,90 @@
+/*
+ * 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>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pid_t
+fork(void)
+{
+ int flags;
+ pid_t ret;
+
+ /* Fork a new process: */
+ if ((ret = _thread_sys_fork()) <= 0) {
+ /* Parent process or error. Nothing to do here. */
+ } else {
+ /* Close the pthread kernel pipe: */
+ _thread_sys_close(_thread_kern_pipe[0]);
+ _thread_sys_close(_thread_kern_pipe[1]);
+
+ /* Reset signals pending for the running thread: */
+ memset(_thread_run->sigpend, 0, sizeof(_thread_run->sigpend));
+
+ /*
+ * Create a pipe that is written to by the signal handler to
+ * prevent signals being missed in calls to
+ * _thread_sys_select:
+ */
+ if (_thread_sys_pipe(_thread_kern_pipe) != 0) {
+ /* Cannot create pipe, so abort: */
+ PANIC("Cannot create pthread kernel pipe for forked process");
+ }
+ /* Get the flags for the read pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Make the read pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Get the flags for the write pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ /* Make the write pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ abort();
+ }
+ }
+
+ /* Return the process ID: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fstat.c b/lib/libc_r/uthread/uthread_fstat.c
new file mode 100644
index 0000000..fc29e66
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fstat.c
@@ -0,0 +1,57 @@
+/*
+ * 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 <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fstat(int fd, struct stat * buf)
+{
+ int ret;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ /* Get the file status: */
+ ret = _thread_sys_fstat(fd, buf);
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fstatfs.c b/lib/libc_r/uthread/uthread_fstatfs.c
new file mode 100644
index 0000000..252c8b1
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fstatfs.c
@@ -0,0 +1,57 @@
+/*
+ * 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 <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fstatfs(int fd, struct statfs * buf)
+{
+ int ret;
+
+ /* Lock the file descriptor for read: */
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ /* Get the file system status: */
+ ret = _thread_sys_fstatfs(fd, buf);
+ /* Unlock the file descriptor: */
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_fsync.c b/lib/libc_r/uthread/uthread_fsync.c
new file mode 100644
index 0000000..51078e5
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_fsync.c
@@ -0,0 +1,49 @@
+/*
+ * 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+fsync(int fd)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_fsync(fd);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getdirentries.c b/lib/libc_r/uthread/uthread_getdirentries.c
new file mode 100644
index 0000000..b75e804
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getdirentries.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <sys/types.h>
+#include <dirent.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+getdirentries(int fd, char *buf, int nbytes, long *basep)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_getdirentries(fd, buf, nbytes, basep);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getpeername.c b/lib/libc_r/uthread/uthread_getpeername.c
new file mode 100644
index 0000000..d3bb4e1
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getpeername.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+getpeername(int fd, struct sockaddr * peer, int *paddrlen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_getpeername(fd, peer, paddrlen);
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getprio.c b/lib/libc_r/uthread/uthread_getprio.c
new file mode 100644
index 0000000..345f6ce
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getprio.c
@@ -0,0 +1,73 @@
+/*
+ * 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_getprio(pthread_t pthread)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread_p;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread_p = _thread_link_list;
+
+ /* Enter a loop to search for the thread: */
+ while (pthread_p != NULL && pthread_p != pthread) {
+ /* Point to the next thread: */
+ pthread_p = pthread_p->nxt;
+ }
+
+ /* Check if the thread pointer is NULL: */
+ if (pthread == NULL || pthread_p == NULL) {
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, EINVAL);
+ rval = -1;
+ } else {
+ /* Get the thread priority: */
+ rval = pthread->pthread_priority;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the thread priority or an error status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getsockname.c b/lib/libc_r/uthread/uthread_getsockname.c
new file mode 100644
index 0000000..5a8466b
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getsockname.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+getsockname(int s, struct sockaddr * name, int *namelen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(s, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_getsockname(s, name, namelen);
+ _thread_fd_unlock(s, FD_READ);
+ }
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_getsockopt.c b/lib/libc_r/uthread/uthread_getsockopt.c
new file mode 100644
index 0000000..fdedd90
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_getsockopt.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+getsockopt(int fd, int level, int optname, void *optval, int *optlen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_getsockopt(fd, level, optname, optval, optlen);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_info.c b/lib/libc_r/uthread/uthread_info.c
new file mode 100644
index 0000000..e69145f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_info.c
@@ -0,0 +1,175 @@
+/*
+ * 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 <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+struct s_thread_info {
+ enum pthread_state state;
+ char *name;
+};
+
+/* Static variables: */
+static const struct s_thread_info thread_info[] = {
+ {PS_RUNNING , "Running"},
+ {PS_SIGTHREAD , "Waiting on signal thread"},
+ {PS_MUTEX_WAIT , "Waiting on a mutex"},
+ {PS_COND_WAIT , "Waiting on a condition variable"},
+ {PS_FDLR_WAIT , "Waiting for a file read lock"},
+ {PS_FDLW_WAIT , "Waiting for a file write lock"},
+ {PS_FDR_WAIT , "Waiting for read"},
+ {PS_FDW_WAIT , "Waitingfor write"},
+ {PS_SELECT_WAIT , "Waiting on select"},
+ {PS_SLEEP_WAIT , "Sleeping"},
+ {PS_WAIT_WAIT , "Waiting process"},
+ {PS_SIGWAIT , "Waiting for a signal"},
+ {PS_JOIN , "Waiting to join"},
+ {PS_SUSPENDED , "Suspended"},
+ {PS_DEAD , "Dead"},
+ {PS_STATE_MAX , "Not a real state!"}
+};
+
+void
+_thread_dump_info(void)
+{
+ char s[128];
+ int fd;
+ int i;
+ int j;
+ pthread_t pthread;
+
+ /* Open the dump file for append and create it if necessary: */
+ if ((fd = _thread_sys_open("/tmp/uthread.dump", O_RDWR | O_CREAT | O_APPEND, 0666)) < 0) {
+ /* Can't open the dump file. */
+ } else {
+ /* Output a header for active threads: */
+ strcpy(s, "\n\n=============\nACTIVE THREADS\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Enter a loop to report each thread in the global list: */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Find the state: */
+ for (j = 0; j < (sizeof(thread_info) / sizeof(struct s_thread_info)) - 1; j++)
+ if (thread_info[j].state == pthread->state)
+ break;
+ /* Output a record for the current thread: */
+ sprintf(s, "--------------------\nThread %p prio %3d state %s\n",
+ pthread, pthread->pthread_priority, thread_info[j].name);
+ _thread_sys_write(fd, s, strlen(s));
+
+ /* Check if this is the running thread: */
+ if (pthread == _thread_run) {
+ /* Output a record for the running thread: */
+ strcpy(s, "This is the running thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Check if this is the initial thread: */
+ if (pthread == _thread_initial) {
+ /* Output a record for the initial thread: */
+ strcpy(s, "This is the initial thread\n");
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* File descriptor read lock wait: */
+ case PS_FDLR_WAIT:
+ /* Write the lock details: */
+ sprintf(s, "fd %d[%s:%d]", pthread->data.fd.fd, pthread->data.fd.fname, pthread->data.fd.branch);
+ _thread_sys_write(fd, s, strlen(s));
+ sprintf(s, "owner %pr/%pw\n", _thread_fd_table[pthread->data.fd.fd]->r_owner, _thread_fd_table[pthread->data.fd.fd]->w_owner);
+ _thread_sys_write(fd, s, strlen(s));
+ break;
+
+ /*
+ * Trap other states that are not explicitly
+ * coded to dump information:
+ */
+ default:
+ /* Nothing to do here. */
+ break;
+ }
+ }
+
+ /* Check if there are no dead threads: */
+ if (_thread_dead == NULL) {
+ /* Output a record: */
+ strcpy(s, "\n\nTHERE ARE NO DEAD THREADS\n");
+ _thread_sys_write(fd, s, strlen(s));
+ } else {
+ /* Output a header for dead threads: */
+ strcpy(s, "\n\nDEAD THREADS\n\n");
+ _thread_sys_write(fd, s, strlen(s));
+
+ /*
+ * Enter a loop to report each thread in the global
+ * dead thread list:
+ */
+ for (pthread = _thread_dead; pthread != NULL; pthread = pthread->nxt) {
+ /* Output a record for the current thread: */
+ sprintf(s, "Thread %p prio %3d\n", pthread, pthread->pthread_priority);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ }
+
+ /* Enter a loop to report file descriptor lock usage: */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /*
+ * Check if memory is allocated for this file
+ * descriptor:
+ */
+ if (_thread_fd_table[i] != NULL) {
+ /* Report the file descriptor lock status: */
+ sprintf(s, "fd[%3d] read owner %p count %d [%s:%d]\n write owner %p count %d [%s:%d]\n",
+ i,
+ _thread_fd_table[i]->r_owner,
+ _thread_fd_table[i]->r_lockcount,
+ _thread_fd_table[i]->r_fname,
+ _thread_fd_table[i]->r_lineno,
+ _thread_fd_table[i]->w_owner,
+ _thread_fd_table[i]->w_lockcount,
+ _thread_fd_table[i]->w_fname,
+ _thread_fd_table[i]->w_lineno);
+ _thread_sys_write(fd, s, strlen(s));
+ }
+ }
+
+ /* Close the dump file: */
+ _thread_sys_close(fd);
+ }
+ return;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c
new file mode 100644
index 0000000..d044063
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_init.c
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ *
+ */
+
+/* Allocate space for global thread variables here: */
+#define GLOBAL_PTHREAD_PRIVATE
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <machine/reg.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_init(void)
+{
+ int flags;
+ int i;
+ struct sigaction act;
+
+ /* Check if this function has already been called: */
+ if (_thread_initial) {
+ /* Only initialise the threaded application once. */
+ }
+ /*
+ * Create a pipe that is written to by the signal handler to prevent
+ * signals being missed in calls to _thread_sys_select:
+ */
+ else if (_thread_sys_pipe(_thread_kern_pipe) != 0) {
+ /* Cannot create pipe, so abort: */
+ PANIC("Cannot create kernel pipe");
+ }
+ /* Get the flags for the read pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel read pipe flags");
+ }
+ /* Make the read pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[0], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot make kernel read pipe non-blocking");
+ }
+ /* Get the flags for the write pipe: */
+ else if ((flags = _thread_sys_fcntl(_thread_kern_pipe[1], F_GETFL, NULL)) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel write pipe flags");
+ }
+ /* Make the write pipe non-blocking: */
+ else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) {
+ /* Abort this application: */
+ PANIC("Cannot get kernel write pipe flags");
+ }
+ /* Allocate memory for the thread structure of the initial thread: */
+ else if ((_thread_initial = (pthread_t) malloc(sizeof(struct pthread))) == NULL) {
+ /*
+ * Insufficient memory to initialise this application, so
+ * abort:
+ */
+ PANIC("Cannot allocate memory for initial thread");
+ } else {
+ /* Zero the global kernel thread structure: */
+ memset(&_thread_kern_thread, 0, sizeof(struct pthread));
+ memset(_thread_initial, 0, sizeof(struct pthread));
+
+ /* Default the priority of the initial thread: */
+ _thread_initial->pthread_priority = PTHREAD_DEFAULT_PRIORITY;
+
+ /* Initialise the state of the initial thread: */
+ _thread_initial->state = PS_RUNNING;
+
+ /* Initialise the queue: */
+ _thread_queue_init(&(_thread_initial->join_queue));
+
+ /* Initialise the rest of the fields: */
+ _thread_initial->parent_thread = NULL;
+ _thread_initial->specific_data = NULL;
+ _thread_initial->cleanup = NULL;
+ _thread_initial->queue = NULL;
+ _thread_initial->qnxt = NULL;
+ _thread_initial->nxt = NULL;
+ _thread_initial->flags = 0;
+ _thread_initial->error = 0;
+ _thread_link_list = _thread_initial;
+ _thread_run = _thread_initial;
+
+ /* Enter a loop to get the existing signal status: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be trapped: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ }
+ /* Get the signal handler details: */
+ else if (_thread_sys_sigaction(i, NULL, &act) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot read signal handler info");
+ }
+ /* Set the signal handler for the initial thread: */
+ else if (sigaction(i, &act, NULL) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot initialise signal handler for initial thread");
+ }
+ }
+
+ /* Initialise the global signal action structure: */
+ sigfillset(&act.sa_mask);
+ act.sa_handler = (void (*) ()) _thread_sig_handler;
+ act.sa_flags = SA_RESTART;
+
+ /* Enter a loop to initialise the rest of the signals: */
+ for (i = 1; i < NSIG; i++) {
+ /* Check for signals which cannot be trapped: */
+ if (i == SIGKILL || i == SIGSTOP) {
+ }
+ /* Initialise the signal for default handling: */
+ else if (_thread_sys_sigaction(i, &act, NULL) != 0) {
+ /*
+ * Abort this process if signal
+ * initialisation fails:
+ */
+ PANIC("Cannot initialise signal handler");
+ }
+ }
+
+ /* Get the table size: */
+ if ((_thread_dtablesize = getdtablesize()) < 0) {
+ /*
+ * Cannot get the system defined table size, so abort
+ * this process.
+ */
+ PANIC("Cannot get dtablesize");
+ }
+ /* Allocate memory for the file descriptor table: */
+ if ((_thread_fd_table = (struct fd_table_entry **) malloc(sizeof(struct fd_table_entry) * _thread_dtablesize)) == NULL) {
+ /*
+ * Cannot allocate memory for the file descriptor
+ * table, so abort this process.
+ */
+ PANIC("Cannot allocate memory for file descriptor table");
+ } else {
+ /*
+ * Enter a loop to initialise the file descriptor
+ * table:
+ */
+ for (i = 0; i < _thread_dtablesize; i++) {
+ /* Initialise the file descriptor table: */
+ _thread_fd_table[i] = NULL;
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Special start up code for NetBSD/Alpha
+ */
+#if defined(__NetBSD__) && defined(__alpha__)
+int
+main(int argc, char *argv[], char *env);
+
+int
+_thread_main(int argc, char *argv[], char *env)
+{
+ _thread_init();
+ return (main(argc, argv, env));
+}
+#endif
+#else
+/*
+ * A stub for non-threaded programs.
+ */
+void
+_thread_init(void)
+{
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_ioctl.c b/lib/libc_r/uthread/uthread_ioctl.c
new file mode 100644
index 0000000..69df24d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_ioctl.c
@@ -0,0 +1,53 @@
+/*
+ * 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 <stdarg.h>
+#include <sys/ioctl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+ioctl(int fd, unsigned long request,...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, request);
+ if (fd < 0 || fd >= _thread_dtablesize)
+ ret = -1;
+ else
+ ret = _thread_sys_ioctl(fd, request, va_arg(ap, char *));
+ va_end(ap);
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_join.c b/lib/libc_r/uthread/uthread_join.c
new file mode 100644
index 0000000..d0093ae
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_join.c
@@ -0,0 +1,90 @@
+/*
+ * 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_join(pthread_t pthread, void **thread_return)
+{
+ int rval = 0;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check if this thread has been detached: */
+ if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
+ /* Return an error: */
+ _thread_seterrno(_thread_run, ESRCH);
+ rval = -1;
+ }
+ /* Check if the thread is not dead: */
+ else if (pthread->state != PS_DEAD) {
+ /* Add the running thread to the join queue: */
+ _thread_queue_enq(&(pthread->join_queue), _thread_run);
+
+ /* Schedule the next thread: */
+ _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__);
+
+ /* Block signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Check if the thread is not detached: */
+ if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+ /* Check if the return value is required: */
+ if (thread_return) {
+ /* Return the thread's return value: */
+ *thread_return = pthread->ret;
+ }
+ } else {
+ /* Return an error: */
+ _thread_seterrno(_thread_run, ESRCH);
+ rval = -1;
+ }
+ } else {
+ /* Check if the return value is required: */
+ if (thread_return != NULL) {
+ /* Return the thread's return value: */
+ *thread_return = pthread->ret;
+ }
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_kern.c b/lib/libc_r/uthread/uthread_kern.c
new file mode 100644
index 0000000..35e8e29
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_kern.c
@@ -0,0 +1,1581 @@
+/*
+ * 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>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* Static variables: */
+static sigset_t sig_to_block = 0xffffffff;
+static sigset_t sig_to_unblock = 0;
+
+/* Static function prototype definitions: */
+static void
+_thread_kern_select(int wait_reqd);
+static void
+_thread_signal(pthread_t pthread, int sig);
+
+void
+_thread_kern_sched(struct sigcontext * scp)
+{
+#ifndef __alpha
+ char *fdata;
+#endif
+ int i;
+ int prio = -1;
+ pthread_t pthread;
+ pthread_t pthread_h = NULL;
+ pthread_t pthread_nxt = NULL;
+ pthread_t pthread_prv = NULL;
+ pthread_t pthread_s = NULL;
+ struct itimerval itimer;
+ struct timespec ts;
+ struct timespec ts1;
+ struct timeval tv;
+ struct timeval tv1;
+
+ /* Block signals: */
+ _thread_kern_sig_block(NULL);
+
+ /* Check if this function was called from the signal handler: */
+ if (scp != NULL) {
+ /*
+ * Copy the signal context to the current thread's jump
+ * buffer:
+ */
+ memcpy(&_thread_run->saved_sigcontext, scp, sizeof(_thread_run->saved_sigcontext));
+
+#ifndef __alpha
+ /* Point to the floating point data in the running thread: */
+ fdata = _thread_run->saved_fp;
+
+ /* Save the floating point data: */
+__asm__("fnsave %0": :"m"(*fdata));
+#endif
+
+ /* Flag the signal context as the last state saved: */
+ _thread_run->sig_saved = 1;
+ }
+ /* Save the state of the current thread: */
+ else if (_thread_sys_setjmp(_thread_run->saved_jmp_buf) != 0) {
+ /* Unblock signals (just in case): */
+ _thread_kern_sig_unblock(0);
+
+ /*
+ * This point is reached when a longjmp() is called to
+ * restore the state of a thread.
+ */
+ return;
+ } else {
+ /* Flag the jump buffer was the last state saved: */
+ _thread_run->sig_saved = 0;
+ }
+
+ /* Point to the first dead thread (if there are any): */
+ pthread = _thread_dead;
+
+ /* There is no previous dead thread: */
+ pthread_prv = NULL;
+
+ /* Enter a loop to cleanup after dead threads: */
+ while (pthread != NULL) {
+ /* Save a pointer to the next thread: */
+ pthread_nxt = pthread->nxt;
+
+ /* Check if this thread is one which is running: */
+ if (pthread == _thread_run || pthread == _thread_initial) {
+ /*
+ * Don't destroy the running thread or the initial
+ * thread.
+ */
+ pthread_prv = pthread;
+ }
+ /*
+ * Check if this thread has detached or if it is a signal
+ * handler thread:
+ */
+ else if (((pthread->attr.flags & PTHREAD_DETACHED) != 0) || pthread->parent_thread != NULL) {
+ /* Check if there is no previous dead thread: */
+ if (pthread_prv == NULL) {
+ /*
+ * The dead thread is at the head of the
+ * list:
+ */
+ _thread_dead = pthread_nxt;
+ } else {
+ /*
+ * The dead thread is not at the head of the
+ * list:
+ */
+ pthread_prv->nxt = pthread->nxt;
+ }
+
+ /*
+ * Check if the stack was not specified by the caller
+ * to pthread_create and has not been destroyed yet:
+ */
+ if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
+ /* Free the stack of the dead thread: */
+ free(pthread->stack);
+ }
+ /* Free the memory allocated to the thread structure: */
+ free(pthread);
+ } else {
+ /*
+ * This thread has not detached, so do not destroy
+ * it:
+ */
+ pthread_prv = pthread;
+
+ /*
+ * Check if the stack was not specified by the caller
+ * to pthread_create and has not been destroyed yet:
+ */
+ if (pthread->attr.stackaddr_attr == NULL && pthread->stack != NULL) {
+ /* Free the stack of the dead thread: */
+ free(pthread->stack);
+
+ /*
+ * NULL the stack pointer now that the memory
+ * has been freed:
+ */
+ pthread->stack = NULL;
+ }
+ }
+
+ /* Point to the next thread: */
+ pthread = pthread_nxt;
+ }
+
+ /*
+ * Enter a the scheduling loop that finds the next thread that is
+ * ready to run. This loop completes when there are no more threads
+ * in the global list or when a thread has its state restored by
+ * either a sigreturn (if the state was saved as a sigcontext) or a
+ * longjmp (if the state was saved by a setjmp).
+ */
+ while (_thread_link_list != NULL) {
+ /* Get the current time of day: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+
+ /*
+ * Poll file descriptors to update the state of threads
+ * waiting on file I/O where data may be available:
+ */
+ _thread_kern_select(0);
+
+ /*
+ * Enter a loop to look for sleeping threads that are ready
+ * or threads with pending signals that are no longer
+ * blocked:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Enter a loop to process the sending signals: */
+ for (i = 1; i < NSIG; i++) {
+ /*
+ * Check if there are no pending signals of
+ * this type:
+ */
+ if (pthread->sigpend[i] == 0) {
+ }
+ /* Check if this signal type is not masked: */
+ else if (sigismember(&pthread->sigmask, i) == 0) {
+ /*
+ * Delete the signal from the set of
+ * pending signals for this thread:
+ */
+ pthread->sigpend[i] -= 1;
+
+ /*
+ * Act on the signal for the current
+ * thread:
+ */
+ _thread_signal(pthread, i);
+ } else {
+ /*
+ * This signal is masked, so make
+ * sure the count does not exceed 1:
+ */
+ pthread->sigpend[i] = 1;
+ }
+ }
+
+ /* Check if this thread is to timeout: */
+ if (pthread->state == PS_COND_WAIT ||
+ pthread->state == PS_SLEEP_WAIT ||
+ pthread->state == PS_FDR_WAIT ||
+ pthread->state == PS_FDW_WAIT ||
+ pthread->state == PS_SELECT_WAIT) {
+ /* Check if this thread is to wait forever: */
+ if (pthread->wakeup_time.ts_sec == -1) {
+ }
+ /*
+ * Check if this thread is to wakeup
+ * immediately or if it is past its wakeup
+ * time:
+ */
+ 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))) {
+ /*
+ * Check if this thread is waiting on
+ * select:
+ */
+ if (pthread->state == PS_SELECT_WAIT) {
+ /*
+ * The select has timed out,
+ * so zero the file
+ * descriptor sets:
+ */
+ FD_ZERO(&pthread->data.select_data->readfds);
+ FD_ZERO(&pthread->data.select_data->writefds);
+ FD_ZERO(&pthread->data.select_data->exceptfds);
+ pthread->data.select_data->nfds = 0;
+ }
+ /*
+ * Return an error as an interrupted
+ * wait:
+ */
+ _thread_seterrno(pthread, EINTR);
+
+ /*
+ * Flag the timeout in the thread
+ * structure:
+ */
+ pthread->timeout = 1;
+
+ /*
+ * Change the threads state to allow
+ * it to be restarted:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ }
+ }
+
+ /* Check if there is a current thread: */
+ if (_thread_run != &_thread_kern_thread) {
+ /*
+ * Save the current time as the time that the thread
+ * became inactive:
+ */
+ _thread_run->last_inactive.tv_sec = tv.tv_sec;
+ _thread_run->last_inactive.tv_usec = tv.tv_usec;
+
+ /*
+ * Accumulate the number of microseconds that this
+ * thread has run for:
+ */
+ _thread_run->slice_usec += (_thread_run->last_inactive.tv_sec -
+ _thread_run->last_active.tv_sec) * 1000000 +
+ _thread_run->last_inactive.tv_usec -
+ _thread_run->last_active.tv_usec;
+
+ /*
+ * Check if this thread has reached its allocated
+ * time slice period:
+ */
+ if (_thread_run->slice_usec > TIMESLICE_USEC) {
+ /*
+ * Flag the allocated time slice period as
+ * up:
+ */
+ _thread_run->slice_usec = -1;
+ }
+ }
+ /* Check if an incremental priority update is required: */
+ if (((tv.tv_sec - kern_inc_prio_time.tv_sec) * 1000000 +
+ tv.tv_usec - kern_inc_prio_time.tv_usec) > INC_PRIO_USEC) {
+ /*
+ * Enter a loop to look for run-enabled threads that
+ * have not run since the last time that an
+ * incremental priority update was performed:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if this thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ }
+ /*
+ * Check if the last time that this thread
+ * was run (as indicated by the last time it
+ * became inactive) is before the time that
+ * the last incremental priority check was
+ * made:
+ */
+ else if (timercmp(&_thread_run->last_inactive, &kern_inc_prio_time, >)) {
+ /*
+ * Increment the incremental priority
+ * for this thread in the hope that
+ * it will eventually get a chance to
+ * run:
+ */
+ (pthread->inc_prio)++;
+ }
+ }
+
+ /* Save the new incremental priority update time: */
+ kern_inc_prio_time.tv_sec = tv.tv_sec;
+ kern_inc_prio_time.tv_usec = tv.tv_usec;
+ }
+ /*
+ * Enter a loop to look for the first thread of the highest
+ * priority:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if the current thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ }
+ /*
+ * Check if no run-enabled thread has been seen or if
+ * the current thread has a priority higher than the
+ * highest seen so far:
+ */
+ else if (pthread_h == NULL || (pthread->pthread_priority + pthread->inc_prio) > prio) {
+ /*
+ * Save this thread as the highest priority
+ * thread seen so far:
+ */
+ pthread_h = pthread;
+ prio = pthread->pthread_priority + pthread->inc_prio;
+ }
+ }
+
+ /*
+ * Enter a loop to look for a thread that: 1. Is run-enabled.
+ * 2. Has the required agregate priority. 3. Has not been
+ * allocated its allocated time slice. 4. Became inactive
+ * least recently.
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Check if the current thread is unable to run: */
+ if (pthread->state != PS_RUNNING) {
+ /* Ignore threads that are not ready to run. */
+ }
+ /*
+ * Check if the current thread as an agregate
+ * priority not equal to the highest priority found
+ * above:
+ */
+ else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
+ /*
+ * Ignore threads which have lower agregate
+ * priority.
+ */
+ }
+ /*
+ * Check if the current thread reached its time slice
+ * allocation last time it ran (or if it has not run
+ * yet):
+ */
+ else if (pthread->slice_usec == -1) {
+ }
+ /*
+ * Check if an eligible thread has not been found
+ * yet, or if the current thread has an inactive time
+ * earlier than the last one seen:
+ */
+ else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
+ /*
+ * Save the pointer to the current thread as
+ * the most eligible thread seen so far:
+ */
+ pthread_s = pthread;
+
+ /*
+ * Save the time that the selected thread
+ * became inactive:
+ */
+ tv1.tv_sec = pthread->last_inactive.tv_sec;
+ tv1.tv_usec = pthread->last_inactive.tv_usec;
+ }
+ }
+
+ /*
+ * Check if no thread was selected according to incomplete
+ * time slice allocation:
+ */
+ if (pthread_s == NULL) {
+ /*
+ * Enter a loop to look for any other thread that: 1.
+ * Is run-enabled. 2. Has the required agregate
+ * priority. 3. Became inactive least recently.
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /*
+ * Check if the current thread is unable to
+ * run:
+ */
+ if (pthread->state != PS_RUNNING) {
+ /*
+ * Ignore threads that are not ready
+ * to run.
+ */
+ }
+ /*
+ * Check if the current thread as an agregate
+ * priority not equal to the highest priority
+ * found above:
+ */
+ else if ((pthread->pthread_priority + pthread->inc_prio) != prio) {
+ /*
+ * Ignore threads which have lower
+ * agregate priority.
+ */
+ }
+ /*
+ * Check if an eligible thread has not been
+ * found yet, or if the current thread has an
+ * inactive time earlier than the last one
+ * seen:
+ */
+ else if (pthread_s == NULL || timercmp(&pthread->last_inactive, &tv1, <)) {
+ /*
+ * Save the pointer to the current
+ * thread as the most eligible thread
+ * seen so far:
+ */
+ pthread_s = pthread;
+
+ /*
+ * Save the time that the selected
+ * thread became inactive:
+ */
+ tv1.tv_sec = pthread->last_inactive.tv_sec;
+ tv1.tv_usec = pthread->last_inactive.tv_usec;
+ }
+ }
+ }
+ /* Check if there are no threads ready to run: */
+ if (pthread_s == NULL) {
+ /*
+ * Lock the pthread kernel by changing the pointer to
+ * the running thread to point to the global kernel
+ * thread structure:
+ */
+ _thread_run = &_thread_kern_thread;
+
+ /*
+ * There are no threads ready to run, so wait until
+ * something happens that changes this condition:
+ */
+ _thread_kern_select(1);
+ } else {
+ /* Make the selected thread the current thread: */
+ _thread_run = pthread_s;
+
+ /*
+ * Save the current time as the time that the thread
+ * became active:
+ */
+ _thread_run->last_active.tv_sec = tv.tv_sec;
+ _thread_run->last_active.tv_usec = tv.tv_usec;
+
+ /*
+ * Check if this thread is running for the first time
+ * or running again after using its full time slice
+ * allocation:
+ */
+ if (_thread_run->slice_usec == -1) {
+ /* Reset the accumulated time slice period: */
+ _thread_run->slice_usec = 0;
+ }
+ /*
+ * Reset the incremental priority now that this
+ * thread has been given the chance to run:
+ */
+ _thread_run->inc_prio = 0;
+
+ /* Check if there is more than one thread: */
+ if (_thread_run != _thread_link_list || _thread_run->nxt != NULL) {
+ /*
+ * Define the maximum time before a SIGVTALRM
+ * is required:
+ */
+ itimer.it_value.tv_sec = 0;
+ itimer.it_value.tv_usec = TIMESLICE_USEC;
+
+ /*
+ * The interval timer is not reloaded when it
+ * times out. The interval time needs to be
+ * calculated every time.
+ */
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+
+ /*
+ * Enter a loop to look for threads waiting
+ * for a time:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /*
+ * Check if this thread is to
+ * timeout:
+ */
+ if (pthread->state == PS_COND_WAIT ||
+ pthread->state == PS_SLEEP_WAIT ||
+ pthread->state == PS_FDR_WAIT ||
+ pthread->state == PS_FDW_WAIT ||
+ pthread->state == PS_SELECT_WAIT) {
+ /*
+ * Check if this thread is to
+ * wait forever:
+ */
+ if (pthread->wakeup_time.ts_sec == -1) {
+ }
+ /*
+ * Check if this thread is to
+ * wakeup immediately:
+ */
+ else if (pthread->wakeup_time.ts_sec == 0 &&
+ pthread->wakeup_time.ts_nsec == 0) {
+ }
+ /*
+ * Check if the current time
+ * is after the wakeup time:
+ */
+ 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 {
+ /*
+ * Calculate the time
+ * until this thread
+ * is ready, allowing
+ * for the clock
+ * resolution:
+ */
+ 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;
+
+ /*
+ * Check for
+ * underflow of the
+ * nanosecond field:
+ */
+ if (ts1.ts_nsec < 0) {
+ /*
+ * Allow for
+ * the
+ * underflow
+ * of the
+ * nanosecond
+ * field:
+ */
+ ts1.ts_sec--;
+ ts1.ts_nsec += 1000000000;
+ }
+ /*
+ * Check for overflow
+ * of the nanosecond
+ * field:
+ */
+ if (ts1.ts_nsec >= 1000000000) {
+ /*
+ * Allow for
+ * the
+ * overflow
+ * of the
+ * nanosecond
+ * field:
+ */
+ ts1.ts_sec++;
+ ts1.ts_nsec -= 1000000000;
+ }
+ /*
+ * Convert the
+ * timespec structure
+ * to a timeval
+ * structure:
+ */
+ TIMESPEC_TO_TIMEVAL(&tv, &ts1);
+
+ /*
+ * Check if the
+ * thread will be
+ * ready sooner than
+ * the earliest one
+ * found so far:
+ */
+ if (timercmp(&tv, &itimer.it_value, <)) {
+ /*
+ * Update the
+ * time
+ * value:
+ */
+ itimer.it_value.tv_sec = tv.tv_sec;
+ itimer.it_value.tv_usec = tv.tv_usec;
+ }
+ }
+ }
+ }
+
+ /*
+ * Start the interval timer for the
+ * calculated time interval:
+ */
+ if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) != 0) {
+ /*
+ * Cannot initialise the timer, so
+ * abort this process:
+ */
+ PANIC("Cannot set virtual timer");
+ }
+ }
+ /* Check if a signal context was saved: */
+ if (_thread_run->sig_saved == 1) {
+#ifndef __alpha
+ /*
+ * Point to the floating point data in the
+ * running thread:
+ */
+ fdata = _thread_run->saved_fp;
+
+ /* Restore the floating point state: */
+ __asm__("frstor %0": :"m"(*fdata));
+#endif
+
+ /*
+ * Do a sigreturn to restart the thread that
+ * was interrupted by a signal:
+ */
+ _thread_sys_sigreturn(&_thread_run->saved_sigcontext);
+ } else {
+ /*
+ * Do a longjmp to restart the thread that
+ * was context switched out (by a longjmp to
+ * a different thread):
+ */
+ _thread_sys_longjmp(_thread_run->saved_jmp_buf, 1);
+ }
+
+ /* This point should not be reached. */
+ PANIC("Thread has returned from sigreturn or longjmp");
+ }
+ }
+
+ /* There are no more threads, so exit this process: */
+ exit(0);
+}
+
+static void
+_thread_signal(pthread_t pthread, int sig)
+{
+ long l;
+ pthread_t new_pthread;
+ struct sigaction act;
+ void *arg;
+
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /* States which do not change when a signal is trapped: */
+ case PS_COND_WAIT:
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_RUNNING:
+ case PS_STATE_MAX:
+ case PS_SIGTHREAD:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* Wait for child: */
+ case PS_WAIT_WAIT:
+ /* Check if the signal is from a child exiting: */
+ if (sig == SIGCHLD) {
+ /* Reset the error: */
+ _thread_seterrno(pthread, 0);
+
+ /* Change the state of the thread to run: */
+ pthread->state = PS_RUNNING;
+ } else {
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+
+ /* Change the state of the thread to run: */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /*
+ * States that are interrupted by the occurrence of a signal
+ * other than the scheduling alarm:
+ */
+ case PS_FDR_WAIT:
+ case PS_FDW_WAIT:
+ case PS_SELECT_WAIT:
+ case PS_SLEEP_WAIT:
+ case PS_SIGWAIT:
+ /* Return the 'interrupted' error: */
+ _thread_seterrno(pthread, EINTR);
+
+ /* Change the state of the thread to run: */
+ pthread->state = PS_RUNNING;
+ break;
+ }
+
+ /* Check if this signal is being ignored: */
+ if (pthread->act[sig - 1].sa_handler == SIG_IGN) {
+ /* Ignore the signal for this thread. */
+ }
+ /* Check if this signal is to use the default handler: */
+ else if (pthread->act[sig - 1].sa_handler == SIG_DFL) {
+ /* Process according to signal type: */
+ switch (sig) {
+ /* Signals which cause core dumps: */
+ case SIGQUIT:
+ case SIGILL:
+ case SIGTRAP:
+ case SIGABRT:
+ case SIGEMT:
+ case SIGFPE:
+ case SIGBUS:
+ case SIGSEGV:
+ case SIGSYS:
+ /* Clear the signal action: */
+ sigfillset(&act.sa_mask);
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = SA_RESTART;
+ _thread_sys_sigaction(sig, &act, NULL);
+
+ /*
+ * Do a sigreturn back to where the signal was
+ * detected and a core dump should occur:
+ */
+ _thread_sys_sigreturn(&pthread->saved_sigcontext);
+ break;
+
+ /* Default processing for other signals: */
+ default:
+ /*
+ * ### Default processing is a problem to resolve!
+ * ###
+ */
+ break;
+ }
+ } else {
+ /*
+ * Cast the signal number as a long and then to a void
+ * pointer. Sigh. This is POSIX.
+ */
+ l = (long) sig;
+ arg = (void *) l;
+
+ /* Create a signal handler thread, but don't run it yet: */
+ if (_thread_create(&new_pthread, NULL, (void *) pthread->act[sig - 1].sa_handler, arg, pthread) != 0) {
+ /*
+ * Error creating signal handler thread, so abort
+ * this process:
+ */
+ PANIC("Cannot create signal handler thread");
+ }
+ }
+
+ /* Nothing to return. */
+ return;
+}
+
+void
+_thread_kern_sig_block(int *status)
+{
+ sigset_t oset;
+
+ /*
+ * Block all signals so that the process will not be interrupted by
+ * signals:
+ */
+ _thread_sys_sigprocmask(SIG_SETMASK, &sig_to_block, &oset);
+
+ /* Check if the caller wants the current block status returned: */
+ if (status != NULL) {
+ /* Return the previous signal block status: */
+ *status = (oset != 0);
+ }
+ return;
+}
+
+void
+_thread_kern_sig_unblock(int status)
+{
+ sigset_t oset;
+
+ /*
+ * Check if the caller thinks that signals weren't blocked when it
+ * called _thread_kern_sig_block:
+ */
+ if (status == 0) {
+ /*
+ * Unblock all signals so that the process will be
+ * interrupted when a signal occurs:
+ */
+ _thread_sys_sigprocmask(SIG_SETMASK, &sig_to_unblock, &oset);
+ }
+ return;
+}
+
+void
+_thread_kern_sched_state(enum pthread_state state, char *fname, int lineno)
+{
+ /* Change the state of the current thread: */
+ _thread_run->state = state;
+
+ /* Schedule the next thread that is ready: */
+ _thread_kern_sched(NULL);
+ return;
+}
+
+static void
+_thread_kern_select(int wait_reqd)
+{
+ char bufr[128];
+ fd_set fd_set_except;
+ fd_set fd_set_read;
+ fd_set fd_set_write;
+ int count = 0;
+ int count_dec;
+ int found_one;
+ int i;
+ int nfds = -1;
+ int settimeout;
+ pthread_t pthread;
+ ssize_t num;
+ struct timespec ts;
+ struct timespec ts1;
+ struct timeval *p_tv;
+ struct timeval tv;
+ struct timeval tv1;
+
+ /* Zero the file descriptor sets: */
+ FD_ZERO(&fd_set_read);
+ FD_ZERO(&fd_set_write);
+ FD_ZERO(&fd_set_except);
+
+ /* Check if the caller wants to wait: */
+ if (wait_reqd) {
+ /*
+ * Add the pthread kernel pipe file descriptor to the read
+ * set:
+ */
+ FD_SET(_thread_kern_pipe[0], &fd_set_read);
+ nfds = _thread_kern_pipe[0];
+
+ /* Get the current time of day: */
+ gettimeofday(&tv, NULL);
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ }
+ /* Initialise the time value structure: */
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ /*
+ * Enter a loop to process threads waiting on either file descriptors
+ * or times:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Assume that this state does not time out: */
+ settimeout = 0;
+
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /*
+ * States which do not depend on file descriptor I/O
+ * operations or timeouts:
+ */
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_RUNNING:
+ case PS_SIGTHREAD:
+ case PS_SIGWAIT:
+ case PS_STATE_MAX:
+ case PS_WAIT_WAIT:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* File descriptor read wait: */
+ case PS_FDR_WAIT:
+ /* Add the file descriptor to the read set: */
+ FD_SET(pthread->data.fd.fd, &fd_set_read);
+
+ /*
+ * Check if this file descriptor is greater than any
+ * of those seen so far:
+ */
+ if (pthread->data.fd.fd > nfds) {
+ /* Remember this file descriptor: */
+ nfds = pthread->data.fd.fd;
+ }
+ /* Increment the file descriptor count: */
+ count++;
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+
+ /* File descriptor write wait: */
+ case PS_FDW_WAIT:
+ /* Add the file descriptor to the write set: */
+ FD_SET(pthread->data.fd.fd, &fd_set_write);
+
+ /*
+ * Check if this file descriptor is greater than any
+ * of those seen so far:
+ */
+ if (pthread->data.fd.fd > nfds) {
+ /* Remember this file descriptor: */
+ nfds = pthread->data.fd.fd;
+ }
+ /* Increment the file descriptor count: */
+ count++;
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+
+ /* States that time out: */
+ case PS_SLEEP_WAIT:
+ case PS_COND_WAIT:
+ /* Flag a timeout as required: */
+ settimeout = 1;
+ break;
+
+ /* Select wait: */
+ case PS_SELECT_WAIT:
+ /*
+ * Enter a loop to process each file descriptor in
+ * the thread-specific file descriptor sets:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ /*
+ * Check if this file descriptor is set for
+ * exceptions:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
+ /*
+ * Add the file descriptor to the
+ * exception set:
+ */
+ FD_SET(i, &fd_set_except);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ /*
+ * Check if this file descriptor is set for
+ * write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
+ /*
+ * Add the file descriptor to the
+ * write set:
+ */
+ FD_SET(i, &fd_set_write);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ /*
+ * Check if this file descriptor is set for
+ * read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
+ /*
+ * Add the file descriptor to the
+ * read set:
+ */
+ FD_SET(i, &fd_set_read);
+
+ /*
+ * Increment the file descriptor
+ * count:
+ */
+ count++;
+
+ /*
+ * Check if this file descriptor is
+ * greater than any of those seen so
+ * far:
+ */
+ if (i > nfds) {
+ /*
+ * Remember this file
+ * descriptor:
+ */
+ nfds = i;
+ }
+ }
+ }
+
+ /* This state can time out: */
+ settimeout = 1;
+ break;
+ }
+
+ /*
+ * Check if the caller wants to wait and if the thread state
+ * is one that times out:
+ */
+ if (wait_reqd && settimeout) {
+ /* Check if this thread wants to wait forever: */
+ if (pthread->wakeup_time.ts_sec == -1) {
+ }
+ /* Check if this thread doesn't want to wait at all: */
+ else if (pthread->wakeup_time.ts_sec == 0 &&
+ pthread->wakeup_time.ts_nsec == 0) {
+ /* Override the caller's request to wait: */
+ wait_reqd = 0;
+ } else {
+ /*
+ * Calculate the time until this thread is
+ * ready, allowing for the clock resolution:
+ */
+ 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;
+
+ /*
+ * Check for underflow of the nanosecond
+ * field:
+ */
+ if (ts1.ts_nsec < 0) {
+ /*
+ * Allow for the underflow of the
+ * nanosecond field:
+ */
+ ts1.ts_sec--;
+ ts1.ts_nsec += 1000000000;
+ }
+ /*
+ * Check for overflow of the nanosecond
+ * field:
+ */
+ if (ts1.ts_nsec >= 1000000000) {
+ /*
+ * Allow for the overflow of the
+ * nanosecond field:
+ */
+ ts1.ts_sec++;
+ ts1.ts_nsec -= 1000000000;
+ }
+ /*
+ * Convert the timespec structure to a
+ * timeval structure:
+ */
+ TIMESPEC_TO_TIMEVAL(&tv1, &ts1);
+
+ /*
+ * Check if no time value has been found yet,
+ * or if the thread will be ready sooner that
+ * the earliest one found so far:
+ */
+ if ((tv.tv_sec == 0 && tv.tv_usec == 0) || timercmp(&tv1, &tv, <)) {
+ /* Update the time value: */
+ tv.tv_sec = tv1.tv_sec;
+ tv.tv_usec = tv1.tv_usec;
+ }
+ }
+ }
+ }
+
+ /* Check if the caller wants to wait: */
+ if (wait_reqd) {
+ /* Check if no threads were found with timeouts: */
+ if (tv.tv_sec == 0 && tv.tv_usec == 0) {
+ /* Wait forever: */
+ p_tv = NULL;
+ } else {
+ /*
+ * Point to the time value structure which contains
+ * the earliest time that a thread will be ready:
+ */
+ p_tv = &tv;
+ }
+
+ /*
+ * Flag the pthread kernel as in a select. This is to avoid
+ * the window between the next statement that unblocks
+ * signals and the select statement which follows.
+ */
+ _thread_kern_in_select = 1;
+
+ /* Unblock all signals: */
+ _thread_kern_sig_unblock(0);
+
+ /*
+ * Wait for a file descriptor to be ready for read, write, or
+ * an exception, or a timeout to occur:
+ */
+ count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
+
+ /* Block all signals again: */
+ _thread_kern_sig_block(NULL);
+
+ /* Reset the kernel in select flag: */
+ _thread_kern_in_select = 0;
+
+ /*
+ * Check if it is possible that there are bytes in the kernel
+ * read pipe waiting to be read:
+ */
+ if (count < 0 || FD_ISSET(_thread_kern_pipe[0], &fd_set_read)) {
+ /*
+ * Check if the kernel read pipe was included in the
+ * count:
+ */
+ if (count > 0) {
+ /*
+ * Remove the kernel read pipe from the
+ * count:
+ */
+ FD_CLR(_thread_kern_pipe[0], &fd_set_read);
+
+ /* Decrement the count of file descriptors: */
+ count--;
+ }
+ /*
+ * Enter a loop to read (and trash) bytes from the
+ * pthread kernel pipe:
+ */
+ while ((num = _thread_sys_read(_thread_kern_pipe[0], bufr, sizeof(bufr))) > 0) {
+ /*
+ * The buffer read contains one byte per
+ * signal and each byte is the signal number.
+ * This data is not used, but the fact that
+ * the signal handler wrote to the pipe *is*
+ * used to cause the _thread_sys_select call
+ * to complete if the signal occurred between
+ * the time when signals were unblocked and
+ * the _thread_sys_select select call being
+ * made.
+ */
+ }
+ }
+ }
+ /* Check if there are file descriptors to poll: */
+ else if (count > 0) {
+ /*
+ * Point to the time value structure which has been zeroed so
+ * that the call to _thread_sys_select will not wait:
+ */
+ p_tv = &tv;
+
+ /* Poll file descrptors without wait: */
+ count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv);
+ }
+ /*
+ * Check if the select call was interrupted, or some other error
+ * occurred:
+ */
+ if (count < 0) {
+ /* Check if the select call was interrupted: */
+ if (errno == EINTR) {
+ /*
+ * Interrupted calls are expected. The interrupting
+ * signal will be in the sigpend array.
+ */
+ } else {
+ /* This should not occur: */
+ }
+ }
+ /* Check if no file descriptors are ready: */
+ else if (count == 0) {
+ /* Nothing to do here. */
+ } else {
+ /*
+ * Enter a loop to look for threads waiting on file
+ * descriptors that are flagged as available by the
+ * _thread_sys_select syscall:
+ */
+ for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
+ /* Process according to thread state: */
+ switch (pthread->state) {
+ /*
+ * States which do not depend on file
+ * descriptor I/O operations:
+ */
+ case PS_RUNNING:
+ case PS_COND_WAIT:
+ case PS_DEAD:
+ case PS_FDLR_WAIT:
+ case PS_FDLW_WAIT:
+ case PS_JOIN:
+ case PS_MUTEX_WAIT:
+ case PS_SIGWAIT:
+ case PS_SLEEP_WAIT:
+ case PS_WAIT_WAIT:
+ case PS_SIGTHREAD:
+ case PS_STATE_MAX:
+ case PS_SUSPENDED:
+ /* Nothing to do here. */
+ break;
+
+ /* File descriptor read wait: */
+ case PS_FDR_WAIT:
+ /*
+ * Check if the file descriptor is available
+ * for read:
+ */
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_read)) {
+ /*
+ * Change the thread state to allow
+ * it to read from the file when it
+ * is scheduled next:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* File descriptor write wait: */
+ case PS_FDW_WAIT:
+ /*
+ * Check if the file descriptor is available
+ * for write:
+ */
+ if (FD_ISSET(pthread->data.fd.fd, &fd_set_write)) {
+ /*
+ * Change the thread state to allow
+ * it to write to the file when it is
+ * scheduled next:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+
+ /* Select wait: */
+ case PS_SELECT_WAIT:
+ /*
+ * Reset the flag that indicates if a file
+ * descriptor is ready for some type of
+ * operation:
+ */
+ count_dec = 0;
+
+ /*
+ * Enter a loop to search though the
+ * thread-specific select file descriptors
+ * for the first descriptor that is ready:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds && count_dec == 0; i++) {
+ /*
+ * Check if this file descriptor does
+ * not have an exception:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds) && FD_ISSET(i, &fd_set_except)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ /*
+ * Check if this file descriptor is
+ * not ready for write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds) && FD_ISSET(i, &fd_set_write)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ /*
+ * Check if this file descriptor is
+ * not ready for read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds) && FD_ISSET(i, &fd_set_read)) {
+ /*
+ * Flag this file descriptor
+ * as ready:
+ */
+ count_dec = 1;
+ }
+ }
+
+ /*
+ * Check if any file descriptors are ready
+ * for the current thread:
+ */
+ if (count_dec) {
+ /*
+ * Reset the count of file
+ * descriptors that are ready for
+ * this thread:
+ */
+ found_one = 0;
+
+ /*
+ * Enter a loop to search though the
+ * thread-specific select file
+ * descriptors:
+ */
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ /*
+ * Reset the count of
+ * operations for which the
+ * current file descriptor is
+ * ready:
+ */
+ count_dec = 0;
+
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * exceptions:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) {
+ /*
+ * Check if this file
+ * descriptor has an
+ * exception:
+ */
+ if (FD_ISSET(i, &fd_set_except)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->exceptfds);
+ }
+ }
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * write:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->writefds)) {
+ /*
+ * Check if this file
+ * descriptor is
+ * ready for write:
+ */
+ if (FD_ISSET(i, &fd_set_write)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->writefds);
+ }
+ }
+ /*
+ * Check if this file
+ * descriptor is selected for
+ * read:
+ */
+ if (FD_ISSET(i, &pthread->data.select_data->readfds)) {
+ /*
+ * Check if this file
+ * descriptor is
+ * ready for read:
+ */
+ if (FD_ISSET(i, &fd_set_read)) {
+ /*
+ * Increment
+ * the count
+ * for this
+ * file:
+ */
+ count_dec++;
+ } else {
+ /*
+ * Clear the
+ * file
+ * descriptor
+ * in the
+ * thread-spec
+ * ific file
+ * descriptor
+ * set:
+ */
+ FD_CLR(i, &pthread->data.select_data->readfds);
+ }
+ }
+ /*
+ * Check if the current file
+ * descriptor is ready for
+ * any one of the operations:
+ */
+ if (count_dec > 0) {
+ /*
+ * Increment the
+ * count of file
+ * descriptors that
+ * are ready for the
+ * current thread:
+ */
+ found_one++;
+ }
+ }
+
+ /*
+ * Return the number of file
+ * descriptors that are ready:
+ */
+ pthread->data.select_data->nfds = found_one;
+
+ /*
+ * Change the state of the current
+ * thread to run:
+ */
+ pthread->state = PS_RUNNING;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Nothing to return. */
+ return;
+}
+
+void
+_thread_kern_set_timeout(struct timespec * timeout)
+{
+ struct timespec current_time;
+ struct timeval tv;
+
+ /* Reset the timeout flag for the running thread: */
+ _thread_run->timeout = 0;
+
+ /* Check if the thread is to wait forever: */
+ if (timeout == NULL) {
+ /*
+ * Set the wakeup time to something that can be recognised as
+ * different to an actual time of day:
+ */
+ _thread_run->wakeup_time.ts_sec = -1;
+ _thread_run->wakeup_time.ts_nsec = -1;
+ }
+ /* Check if no waiting is required: */
+ else if (timeout->ts_sec == 0 && timeout->ts_nsec == 0) {
+ /* Set the wake up time to 'immediately': */
+ _thread_run->wakeup_time.ts_sec = 0;
+ _thread_run->wakeup_time.ts_nsec = 0;
+ } 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 + timeout->ts_sec;
+ _thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + timeout->ts_nsec;
+
+ /* Check if the nanosecond field needs to wrap: */
+ 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;
+ }
+ }
+ return;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_listen.c b/lib/libc_r/uthread/uthread_listen.c
new file mode 100644
index 0000000..453f25e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_listen.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+listen(int fd, int backlog)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_listen(fd, backlog);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_longjmp.c b/lib/libc_r/uthread/uthread_longjmp.c
new file mode 100644
index 0000000..435f3cf
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_longjmp.c
@@ -0,0 +1,45 @@
+/*
+ * 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* ### This function needs to do something special with signals? ### */
+void
+longjmp(jmp_buf env, int val)
+{
+ _thread_sys_longjmp(env, val);
+ abort();
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_mutex.c b/lib/libc_r/uthread/uthread_mutex.c
new file mode 100644
index 0000000..0fc9fbb
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_mutex.c
@@ -0,0 +1,360 @@
+/*
+ * 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 <stdlib.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_mutex_init(pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * mutex_attr)
+{
+ enum pthread_mutextype type;
+ 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) {
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, EINVAL);
+ ret = -1;
+ } else {
+ /* Use the requested mutex type: */
+ type = mutex_attr->m_type;
+ }
+ } else {
+ /* Default to a fast mutex: */
+ type = MUTEX_TYPE_FAST;
+ }
+
+ /* Check no errors so far: */
+ if (ret == 0) {
+ /* Reset the mutex flags: */
+ mutex->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: */
+ mutex->m_data.m_count = 0;
+ break;
+
+ /* Trap invalid mutex types: */
+ default:
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, 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;
+
+ /* 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);
+}
+
+int
+pthread_mutex_trylock(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:
+ /* 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++;
+ } else {
+ /* Return a busy error: */
+ _thread_seterrno(_thread_run, 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;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_lock(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 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);
+ }
+ }
+ 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);
+ }
+ }
+
+ /* 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;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+
+int
+pthread_mutex_unlock(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 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;
+
+ /* 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) {
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, 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);
+ ret = -1;
+ break;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_nanosleep.c b/lib/libc_r/uthread/uthread_nanosleep.c
new file mode 100644
index 0000000..e91ca57
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_nanosleep.c
@@ -0,0 +1,87 @@
+/*
+ * 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 <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+nanosleep(struct timespec * time_to_sleep, struct timespec * time_remaining)
+{
+ struct timespec current_time;
+ struct timespec current_time1;
+ struct timeval tv;
+
+ /* 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;
+
+ /* 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 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;
+
+ /* Check if the nanosecond field has underflowed: */
+ if (time_remaining->ts_nsec < 0) {
+ /* Handle the underflow: */
+ time_remaining->ts_sec -= 1;
+ time_remaining->ts_nsec += 1000000000;
+ }
+ /* 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;
+ }
+ }
+ return (0);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_once.c b/lib/libc_r/uthread/uthread_once.c
new file mode 100644
index 0000000..c55ba9e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_once.c
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pthread_once(pthread_once_t * once_control, void (*init_routine) (void))
+{
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ pthread_mutex_lock(&(once_control->mutex));
+ if (once_control->state == PTHREAD_NEEDS_INIT) {
+ init_routine();
+ once_control->state = PTHREAD_DONE_INIT;
+ }
+ pthread_mutex_unlock(&(once_control->mutex));
+ }
+ return (0);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_open.c b/lib/libc_r/uthread/uthread_open.c
new file mode 100644
index 0000000..ead651e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_open.c
@@ -0,0 +1,82 @@
+/*
+ * 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 <stdarg.h>
+#include <fcntl.h>
+#include <dirent.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+open(const char *path, int flags,...)
+{
+ int fd;
+ int mode = 0;
+ int status;
+ va_list ap;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Check if the file is being created: */
+ if (flags & O_CREAT) {
+ /* Get the creation mode: */
+ va_start(ap, 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) {
+ }
+ /* Initialise the file descriptor table entry: */
+ else if (_thread_fd_table_init(fd) != 0) {
+ /* Quietly close the file: */
+ _thread_sys_close(fd);
+
+ /* 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: */
+ _thread_kern_sig_unblock(status);
+
+ /* Return the file descriptor or -1 on error: */
+ return (fd);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_pipe.c b/lib/libc_r/uthread/uthread_pipe.c
new file mode 100644
index 0000000..925bbe3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_pipe.c
@@ -0,0 +1,58 @@
+/*
+ * 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 <unistd.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+pipe(int fds[2])
+{
+ int ret;
+ if ((ret = _thread_sys_pipe(fds)) >= 0) {
+ if (_thread_fd_table_init(fds[0]) != 0 ||
+ _thread_fd_table_init(fds[1]) != 0) {
+ _thread_sys_close(fds[0]);
+ _thread_sys_close(fds[1]);
+ ret = -1;
+ } else {
+ _thread_fd_table[fds[0]]->flags = _thread_sys_fcntl(fds[0], F_GETFL, NULL);
+ _thread_sys_fcntl(fds[0], F_SETFL, _thread_fd_table[fds[0]]->flags | O_NONBLOCK);
+ _thread_fd_table[fds[1]]->flags = _thread_sys_fcntl(fds[1], F_GETFL, NULL);
+ _thread_sys_fcntl(fds[1], F_SETFL, _thread_fd_table[fds[1]]->flags | O_NONBLOCK);
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_queue.c b/lib/libc_r/uthread/uthread_queue.c
new file mode 100644
index 0000000..5225ab8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_queue.c
@@ -0,0 +1,124 @@
+/*
+ * 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 <stdio.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_queue_init(struct pthread_queue * queue)
+{
+ /* Initialise the pointers in the queue structure: */
+ queue->q_next = NULL;
+ queue->q_last = NULL;
+ queue->q_data = NULL;
+ return;
+}
+
+void
+_thread_queue_enq(struct pthread_queue * queue, struct pthread * thread)
+{
+ if (queue->q_last) {
+ queue->q_last->qnxt = thread;
+ } else {
+ queue->q_next = thread;
+ }
+ queue->q_last = thread;
+ thread->queue = queue;
+ thread->qnxt = NULL;
+ return;
+}
+
+struct pthread *
+_thread_queue_get(struct pthread_queue * queue)
+{
+ /* Return the pointer to the next thread in the queue: */
+ return (queue->q_next);
+}
+
+struct pthread *
+_thread_queue_deq(struct pthread_queue * queue)
+{
+ struct pthread *thread = NULL;
+
+ if (queue->q_next) {
+ thread = queue->q_next;
+ if (!(queue->q_next = queue->q_next->qnxt)) {
+ queue->q_last = NULL;
+ }
+ thread->queue = NULL;
+ thread->qnxt = NULL;
+ }
+ return (thread);
+}
+
+int
+_thread_queue_remove(struct pthread_queue * queue, struct pthread * thread)
+{
+ struct pthread **current = &(queue->q_next);
+ struct pthread *prev = NULL;
+ int ret = -1;
+
+ while (*current) {
+ if (*current == thread) {
+ if ((*current)->qnxt) {
+ *current = (*current)->qnxt;
+ } else {
+ queue->q_last = prev;
+ *current = NULL;
+ }
+ ret = 0;
+ break;
+ }
+ prev = *current;
+ current = &((*current)->qnxt);
+ }
+ thread->queue = NULL;
+ thread->qnxt = NULL;
+ return (ret);
+}
+
+int
+pthread_llist_remove(struct pthread ** llist, struct pthread * thread)
+{
+ while (*llist) {
+ if (*llist == thread) {
+ *llist = thread->qnxt;
+ return (0);
+ }
+ llist = &(*llist)->qnxt;
+ }
+ return (-1);
+}
+
+#endif
diff --git a/lib/libc_r/uthread/uthread_read.c b/lib/libc_r/uthread/uthread_read.c
new file mode 100644
index 0000000..9158844
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_read.c
@@ -0,0 +1,74 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+read(int fd, void *buf, size_t nbytes)
+{
+ int nonblock;
+ int ret;
+ int status;
+ if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) {
+ _thread_seterrno(_thread_run, EBADF);
+ ret = -1;
+ } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) {
+ /* Cannot lock file descriptor. */
+ } else {
+ while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) {
+ if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
+ if (errno == EINTR) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (nonblock == 0) {
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_readv.c b/lib/libc_r/uthread/uthread_readv.c
new file mode 100644
index 0000000..acb72ac
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_readv.c
@@ -0,0 +1,74 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+readv(int fd, const struct iovec * iov, int iovcnt)
+{
+ int nonblock;
+ int ret;
+ int status;
+ if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) {
+ _thread_seterrno(_thread_run, EBADF);
+ ret = -1;
+ } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) {
+ /* Cannot lock file descriptor. */
+ } else {
+ while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) {
+ if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
+ if (errno == EINTR) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (nonblock == 0) {
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_recvfrom.c b/lib/libc_r/uthread/uthread_recvfrom.c
new file mode 100644
index 0000000..a3d6a7d
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_recvfrom.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>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, int *from_len)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ while ((ret = _thread_sys_recvfrom(fd, buf, len, flags, from, from_len)) < 0) {
+ if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ _thread_run->data.fd.fd = fd;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__);
+
+ /* Check if the wait was interrupted: */
+ if (errno == EINTR) {
+ /* Return an error status: */
+ ret = -1;
+ break;
+ }
+ } else {
+ ret = -1;
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_resume.c b/lib/libc_r/uthread/uthread_resume.c
new file mode 100644
index 0000000..4c5298e
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_resume.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(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/libc_r/uthread/uthread_select.c b/lib/libc_r/uthread/uthread_select.c
new file mode 100644
index 0000000..b3f5483
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_select.c
@@ -0,0 +1,179 @@
+/*
+ * 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 <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+select(int numfds, fd_set * readfds, fd_set * writefds,
+ fd_set * exceptfds, struct timeval * timeout)
+{
+ fd_set read_locks, write_locks, rdwr_locks;
+ struct timespec ts;
+ struct timeval zero_timeout = {0, 0};
+ int i, ret = 0, got_all_locks = 1;
+ struct pthread_select_data data;
+
+ if (numfds > _thread_dtablesize) {
+ numfds = _thread_dtablesize;
+ }
+ /* Check if a timeout was specified: */
+ if (timeout) {
+ /* Convert the timeval to a timespec: */
+ TIMEVAL_TO_TIMESPEC(timeout, &ts);
+
+ /* Set the wake up time: */
+ _thread_kern_set_timeout(&ts);
+ } else {
+ /* Wait for ever: */
+ _thread_kern_set_timeout(NULL);
+ }
+
+ FD_ZERO(&read_locks);
+ FD_ZERO(&write_locks);
+ FD_ZERO(&rdwr_locks);
+
+ /* lock readfds */
+ if (readfds || writefds || exceptfds) {
+ for (i = 0; i < numfds; i++) {
+ if ((readfds && (FD_ISSET(i, readfds))) || (exceptfds && FD_ISSET(i, exceptfds))) {
+ if (writefds && FD_ISSET(i, writefds)) {
+ if ((ret = _thread_fd_lock(i, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &rdwr_locks);
+ } else {
+ if ((ret = _thread_fd_lock(i, FD_READ, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &read_locks);
+ }
+ } else {
+ if (writefds && FD_ISSET(i, writefds)) {
+ if ((ret = _thread_fd_lock(i, FD_WRITE, NULL, __FILE__, __LINE__)) != 0) {
+ got_all_locks = 0;
+ break;
+ }
+ FD_SET(i, &write_locks);
+ }
+ }
+ }
+ }
+ if (got_all_locks) {
+ data.nfds = numfds;
+ FD_ZERO(&data.readfds);
+ FD_ZERO(&data.writefds);
+ FD_ZERO(&data.exceptfds);
+ if (readfds != NULL) {
+ memcpy(&data.readfds, readfds, sizeof(data.readfds));
+ }
+ if (writefds != NULL) {
+ memcpy(&data.writefds, writefds, sizeof(data.writefds));
+ }
+ if (exceptfds != NULL) {
+ memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds));
+ }
+ if ((ret = _thread_sys_select(data.nfds, &data.readfds, &data.writefds, &data.exceptfds, &zero_timeout)) == 0) {
+ data.nfds = numfds;
+ FD_ZERO(&data.readfds);
+ FD_ZERO(&data.writefds);
+ FD_ZERO(&data.exceptfds);
+ if (readfds != NULL) {
+ memcpy(&data.readfds, readfds, sizeof(data.readfds));
+ }
+ if (writefds != NULL) {
+ memcpy(&data.writefds, writefds, sizeof(data.writefds));
+ }
+ if (exceptfds != NULL) {
+ memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds));
+ }
+ _thread_run->data.select_data = &data;
+ _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__);
+ ret = data.nfds;
+ }
+ }
+ /* clean up the locks */
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &read_locks))
+ _thread_fd_unlock(i, FD_READ);
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &rdwr_locks))
+ _thread_fd_unlock(i, FD_RDWR);
+ for (i = 0; i < numfds; i++)
+ if (FD_ISSET(i, &write_locks))
+ _thread_fd_unlock(i, FD_WRITE);
+
+ 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 (writefds != NULL) {
+ FD_ZERO(writefds);
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, &data.writefds)) {
+ FD_SET(i, writefds);
+ }
+ }
+ }
+ if (exceptfds != NULL) {
+ FD_ZERO(exceptfds);
+ for (i = 0; i < numfds; i++) {
+ if (FD_ISSET(i, &data.exceptfds)) {
+ FD_SET(i, exceptfds);
+ }
+ }
+ }
+ } else {
+ if (exceptfds != NULL)
+ FD_ZERO(exceptfds);
+ if (writefds != NULL)
+ FD_ZERO(writefds);
+ if (readfds != NULL)
+ FD_ZERO(readfds);
+ }
+
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_self.c b/lib/libc_r/uthread/uthread_self.c
new file mode 100644
index 0000000..a0a2d2a
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_self.c
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pthread_t
+pthread_self(void)
+{
+ /* Return the running thread pointer: */
+ return (_thread_run);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sendto.c b/lib/libc_r/uthread/uthread_sendto.c
new file mode 100644
index 0000000..c7155c8
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sendto.c
@@ -0,0 +1,63 @@
+/*
+ * 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>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * to, int to_len)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) {
+ while ((ret = _thread_sys_sendto(fd, msg, len, flags, to, to_len)) < 0) {
+ if (!(_thread_fd_table[fd]->flags & O_NONBLOCK) && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
+ _thread_run->data.fd.fd = fd;
+
+ /* Set the timeout: */
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
+ } else {
+ ret = -1;
+ break;
+ }
+ }
+ _thread_fd_unlock(fd, FD_WRITE);
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_seterrno.c b/lib/libc_r/uthread/uthread_seterrno.c
new file mode 100644
index 0000000..c4fe08b6
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_seterrno.c
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/*
+ * This function needs to reference the global error variable which is
+ * normally hidden from the user.
+ */
+#ifdef errno
+#undef errno;
+#endif
+extern int errno;
+
+void
+_thread_seterrno(pthread_t thread, int error)
+{
+ /* Check for the initial thread: */
+ if (thread == _thread_initial) {
+ /* The initial thread always uses the global error variable: */
+ errno = error;
+ } else {
+ /*
+ * Threads other than the initial thread always use the error
+ * field in the thread structureL
+ */
+ thread->error = error;
+ }
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_setjmp.c b/lib/libc_r/uthread/uthread_setjmp.c
new file mode 100644
index 0000000..7820466
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_setjmp.c
@@ -0,0 +1,44 @@
+/*
+ * 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 <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* ### This function needs to do something special with signals? ### */
+int
+setjmp(jmp_buf env)
+{
+ return (_thread_sys_setjmp(env));
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_setprio.c b/lib/libc_r/uthread/uthread_setprio.c
new file mode 100644
index 0000000..e052ec3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_setprio.c
@@ -0,0 +1,80 @@
+/*
+ * 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_setprio(pthread_t pthread, int prio)
+{
+ int rval = 0;
+ int status;
+ pthread_t pthread_p;
+
+ /* Check if the priority is invalid: */
+ if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) {
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, EINVAL);
+ rval = -1;
+ } else {
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the first thread in the list: */
+ pthread_p = _thread_link_list;
+
+ /* Enter a loop to search for the thread: */
+ while (pthread_p != NULL && pthread_p != pthread) {
+ /* Point to the next thread: */
+ pthread_p = pthread_p->nxt;
+ }
+
+ /* Check if the thread pointer is NULL: */
+ if (pthread == NULL || pthread_p == NULL) {
+ /* Return a 'search' error: */
+ _thread_seterrno(_thread_run, ESRCH);
+ rval = -1;
+ } else {
+ /* Set the thread priority: */
+ pthread->pthread_priority = prio;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ }
+
+ /* Return the error status: */
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_setsockopt.c b/lib/libc_r/uthread/uthread_setsockopt.c
new file mode 100644
index 0000000..be004a3
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_setsockopt.c
@@ -0,0 +1,50 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+setsockopt(int fd, int level, int optname, const void *optval, int optlen)
+{
+ int ret;
+
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_setsockopt(fd, level, optname, optval, optlen);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ return ret;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_shutdown.c b/lib/libc_r/uthread/uthread_shutdown.c
new file mode 100644
index 0000000..b2e7eac
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_shutdown.c
@@ -0,0 +1,71 @@
+/*
+ * 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>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+shutdown(int fd, int how)
+{
+ int ret;
+
+ switch (how) {
+ case 0:
+ if ((ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_shutdown(fd, how);
+ _thread_fd_unlock(fd, FD_READ);
+ }
+ break;
+ case 1:
+ if ((ret = _thread_fd_lock(fd, FD_WRITE, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_shutdown(fd, how);
+ _thread_fd_unlock(fd, FD_WRITE);
+ }
+ break;
+ case 2:
+ if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
+ ret = _thread_sys_shutdown(fd, how);
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ break;
+ default:
+ _thread_seterrno(_thread_run, EBADF);
+ ret = -1;
+ break;
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sig.c b/lib/libc_r/uthread/uthread_sig.c
new file mode 100644
index 0000000..77ec713
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sig.c
@@ -0,0 +1,128 @@
+/*
+ * 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+_thread_sig_handler(int sig, int code, struct sigcontext * scp)
+{
+ char c;
+ pthread_t pthread;
+
+ /*
+ * Check if the pthread kernel has unblocked signals (or is about to)
+ * and was on its way into a _thread_sys_select when the current
+ * signal interrupted it:
+ */
+ if (_thread_kern_in_select) {
+ /* Cast the signal number to a character variable: */
+ c = sig;
+
+ /*
+ * Write the signal number to the kernel pipe so that it will
+ * be ready to read when this signal handler returns. This
+ * means that the _thread_sys_select call will complete
+ * immediately.
+ */
+ if (_thread_sys_write(_thread_kern_pipe[1], &c, 1) != 1) {
+ }
+ }
+ /* Check if the signal requires a dump of thread information: */
+ if (sig == SIGINFO) {
+ /* Dump thread information to file: */
+ _thread_dump_info();
+ } else {
+ /* Handle depending on signal type: */
+ switch (sig) {
+ /* Interval timer used for timeslicing: */
+ case SIGVTALRM:
+ /*
+ * Don't add the signal to any thread. Just want to
+ * call
+ */
+ /* the scheduler: */
+ break;
+
+ /* Signals specific to the running thread: */
+ case SIGBUS:
+ case SIGEMT:
+ case SIGFPE:
+ case SIGILL:
+ case SIGPIPE:
+ case SIGSEGV:
+ case SIGSYS:
+ /* Add the signal to the set of pending signals: */
+ _thread_run->sigpend[sig] += 1;
+ break;
+
+ /* Signals to send to all threads: */
+ default:
+ /*
+ * 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;
+ }
+ break;
+ }
+
+ /* Check if the kernel is not locked: */
+ if (_thread_run != &_thread_kern_thread) {
+ /*
+ * Schedule the next thread. This function is not
+ * expected to return because it will do a longjmp
+ * instead.
+ */
+ _thread_kern_sched(scp);
+
+ /*
+ * This point should not be reached, so abort the
+ * process:
+ */
+ PANIC("Returned to signal function from scheduler");
+ }
+ }
+
+ /* Returns nothing. */
+ return;
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigaction.c b/lib/libc_r/uthread/uthread_sigaction.c
new file mode 100644
index 0000000..c733667
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigaction.c
@@ -0,0 +1,82 @@
+/*
+ * 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the signal number is out of range: */
+ if (sig < 1 || sig > NSIG) {
+ /* Return an invalid argument: */
+ _thread_seterrno(_thread_run, EINVAL);
+ ret = -1;
+ } else {
+ /*
+ * Check if the existing signal action structure contents are
+ * to be returned:
+ */
+ if (oact != NULL) {
+ /* Return the existing signal action contents: */
+ oact->sa_handler = _thread_run->act[sig - 1].sa_handler;
+ oact->sa_mask = _thread_run->act[sig - 1].sa_mask;
+ oact->sa_flags = _thread_run->act[sig - 1].sa_flags;
+ }
+ /* Check if a signal action was supplied: */
+ if (act != NULL) {
+ /* Block signals while the signal handler is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Set the new signal handler: */
+ _thread_run->act[sig - 1].sa_handler = act->sa_handler;
+ _thread_run->act[sig - 1].sa_mask = act->sa_mask;
+ _thread_run->act[sig - 1].sa_flags = act->sa_flags;
+
+ /*
+ * Unblock signals to allow the new signal handler to
+ * take effect:
+ */
+ _thread_kern_sig_unblock(status);
+ }
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigblock.c b/lib/libc_r/uthread/uthread_sigblock.c
new file mode 100644
index 0000000..bca32e1
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigblock.c
@@ -0,0 +1,48 @@
+/*
+ * 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 <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_sys_sigblock(int mask)
+{
+ int omask, n;
+
+ n = _thread_sys_sigprocmask(SIG_BLOCK, (sigset_t *) & mask, (sigset_t *) & omask);
+ if (n)
+ return (n);
+ return (omask);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_signal.c b/lib/libc_r/uthread/uthread_signal.c
new file mode 100644
index 0000000..cef725f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_signal.c
@@ -0,0 +1,57 @@
+/*
+ * 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 <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+sig_t
+_thread_sys_signal(int s, sig_t a)
+{
+ struct sigaction sa;
+ struct sigaction osa;
+
+ /* Initialise the signal action structure: */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = a;
+ sa.sa_flags = SA_RESTART;
+
+ /* Perform the sigaction syscall: */
+ if (_thread_sys_sigaction(s, &sa, &osa) < 0) {
+ /* Return an error: */
+ return (SIG_ERR);
+ }
+ /* Return a pointer to the old signal handler: */
+ return (osa.sa_handler);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigprocmask.c b/lib/libc_r/uthread/uthread_sigprocmask.c
new file mode 100644
index 0000000..d6e3197
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigprocmask.c
@@ -0,0 +1,92 @@
+/*
+ * 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigprocmask(int how, const sigset_t * set, sigset_t * oset)
+{
+ int ret = 0;
+ int status;
+
+ /* Check if the existing signal process mask is to be returned: */
+ if (oset != NULL) {
+ /* Return the current mask: */
+ *oset = _thread_run->sigmask;
+ }
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Block signals while the signal mask is changed: */
+ _thread_kern_sig_block(&status);
+
+ /* Process according to what to do: */
+ switch (how) {
+ /* Block signals: */
+ case SIG_BLOCK:
+ /* Add signals to the existing mask: */
+ _thread_run->sigmask |= *set;
+ break;
+
+ /* Unblock signals: */
+ case SIG_UNBLOCK:
+ /* Clear signals from the existing mask: */
+ _thread_run->sigmask &= ~(*set);
+ break;
+
+ /* Set the signal process mask: */
+ case SIG_SETMASK:
+ /* Set the new mask: */
+ _thread_run->sigmask = *set;
+ break;
+
+ /* Trap invalid actions: */
+ default:
+ /* Return an invalid argument: */
+ _thread_seterrno(_thread_run, EINVAL);
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Schedule the next thread in case there are signals that
+ * now need to be acted on:
+ */
+ _thread_kern_sched(NULL);
+ }
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigsetmask.c b/lib/libc_r/uthread/uthread_sigsetmask.c
new file mode 100644
index 0000000..2780670
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigsetmask.c
@@ -0,0 +1,48 @@
+/*
+ * 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 <signal.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+_thread_sys_sigsetmask(int mask)
+{
+ int omask, n;
+
+ n = _thread_sys_sigprocmask(SIG_SETMASK, (sigset_t *) & mask, (sigset_t *) & omask);
+ if (n)
+ return (n);
+ return (omask);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_sigsuspend.c b/lib/libc_r/uthread/uthread_sigsuspend.c
new file mode 100644
index 0000000..ee2d0b5
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_sigsuspend.c
@@ -0,0 +1,63 @@
+/*
+ * 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 <signal.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+sigsuspend(const sigset_t * set)
+{
+ int ret = -1;
+ sigset_t oset;
+
+ /* Check if a new signal set was provided by the caller: */
+ if (set != NULL) {
+ /* Save the current sigmal mask: */
+ oset = _thread_run->sigmask;
+
+ /* Wait for a signal: */
+ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
+
+ /* Restore the signal mask: */
+ _thread_run->sigmask = oset;
+ } else {
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, EINVAL);
+ }
+
+ /* Return the completion status: */
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_socket.c b/lib/libc_r/uthread/uthread_socket.c
new file mode 100644
index 0000000..6265a05
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_socket.c
@@ -0,0 +1,57 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+socket(int af, int type, int protocol)
+{
+ int fd;
+ int tmp_flags;
+
+ if ((fd = _thread_sys_socket(af, type, protocol)) < 0) {
+ } else if (_thread_fd_table_init(fd) != 0) {
+ _thread_sys_close(fd);
+ fd = -1;
+ } else {
+ tmp_flags = _thread_sys_fcntl(fd, F_GETFL, 0);
+ _thread_sys_fcntl(fd, F_SETFL, tmp_flags | O_NONBLOCK);
+ _thread_fd_table[fd]->flags = tmp_flags;
+ }
+ return (fd);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_socketpair.c b/lib/libc_r/uthread/uthread_socketpair.c
new file mode 100644
index 0000000..61da7ae
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_socketpair.c
@@ -0,0 +1,59 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+int
+socketpair(int af, int type, int protocol, int pair[2])
+{
+ int ret;
+ if (!((ret = _thread_sys_socketpair(af, type, protocol, pair)) < 0)) {
+ int tmp_flags;
+
+ tmp_flags = _thread_sys_fcntl(pair[0], F_GETFL, 0);
+ _thread_sys_fcntl(pair[0], F_SETFL, tmp_flags | O_NONBLOCK);
+ _thread_fd_table[pair[0]]->flags = tmp_flags;
+
+ tmp_flags = _thread_sys_fcntl(pair[1], F_GETFL, 0);
+ _thread_sys_fcntl(pair[1], F_SETFL, tmp_flags | O_NONBLOCK);
+ _thread_fd_table[pair[1]]->flags = tmp_flags;
+
+ return (ret);
+ }
+ return (-1);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_spec.c b/lib/libc_r/uthread/uthread_spec.c
new file mode 100644
index 0000000..e7c45d2
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_spec.c
@@ -0,0 +1,237 @@
+/*
+ * 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 <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+/* Static variables: */
+static struct pthread_key key_table[PTHREAD_DATAKEYS_MAX];
+
+int
+pthread_keycreate(pthread_key_t * key, void (*destructor) (void *))
+{
+ for ((*key) = 0; (*key) < PTHREAD_DATAKEYS_MAX; (*key)++) {
+ if (key_table[(*key)].count == 0) {
+ key_table[(*key)].count++;
+ key_table[(*key)].destructor = destructor;
+ return (0);
+ }
+ }
+ return (EAGAIN);
+}
+
+int
+pthread_key_delete(pthread_key_t key)
+{
+ int ret;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ if (key < PTHREAD_DATAKEYS_MAX) {
+ switch (key_table[key].count) {
+ case 1:
+ key_table[key].destructor = NULL;
+ key_table[key].count = 0;
+ case 0:
+ ret = 0;
+ break;
+ default:
+ ret = EBUSY;
+ }
+ } else {
+ ret = EINVAL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+
+void
+_thread_cleanupspecific(void)
+{
+ void *data;
+ int key;
+ int itr;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ for (itr = 0; itr < _POSIX_THREAD_DESTRUTOR_ITERATIONS; itr++) {
+ for (key = 0; key < PTHREAD_DATAKEYS_MAX; key++) {
+ if (_thread_run->specific_data_count) {
+ if (_thread_run->specific_data[key]) {
+ data = (void *) _thread_run->specific_data[key];
+ _thread_run->specific_data[key] = NULL;
+ _thread_run->specific_data_count--;
+ if (key_table[key].destructor) {
+ key_table[key].destructor(data);
+ }
+ key_table[key].count--;
+ }
+ } else {
+ free(_thread_run->specific_data);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return;
+ }
+ }
+ }
+ free(_thread_run->specific_data);
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+}
+
+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);
+ }
+ return (new_data);
+}
+
+int
+pthread_setspecific(pthread_key_t key, const void *value)
+{
+ pthread_t pthread;
+ int ret = 0;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the running thread: */
+ pthread = _thread_run;
+
+ /*
+ * Enter a loop for signal handler threads to find the parent thread
+ * which has the specific data associated with it:
+ */
+ while (pthread->parent_thread != NULL) {
+ /* Point to the parent thread: */
+ pthread = pthread->parent_thread;
+ }
+
+ if ((pthread->specific_data) || (pthread->specific_data = pthread_key_allocate_data())) {
+ if ((key < PTHREAD_DATAKEYS_MAX) && (key_table)) {
+ if (key_table[key].count) {
+ if (pthread->specific_data[key] == NULL) {
+ if (value != NULL) {
+ pthread->specific_data_count++;
+ key_table[key].count++;
+ }
+ } else {
+ if (value == NULL) {
+ pthread->specific_data_count--;
+ key_table[key].count--;
+ }
+ }
+ pthread->specific_data[key] = value;
+ ret = 0;
+ } else {
+ ret = EINVAL;
+ }
+ } else {
+ ret = EINVAL;
+ }
+ } else {
+ ret = ENOMEM;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+
+int
+pthread_getspecific(pthread_key_t key, void **p_data)
+{
+ pthread_t pthread;
+ int rval = 0;
+ int status;
+
+ /* Block signals: */
+ _thread_kern_sig_block(&status);
+
+ /* Point to the running thread: */
+ pthread = _thread_run;
+
+ /*
+ * Enter a loop for signal handler threads to find the parent thread
+ * which has the specific data associated with it:
+ */
+ while (pthread->parent_thread != NULL) {
+ /* Point to the parent thread: */
+ pthread = pthread->parent_thread;
+ }
+
+ /* Check for errors: */
+ if (pthread == NULL || p_data == NULL) {
+ /* Return an invalid argument error: */
+ _thread_seterrno(_thread_run, EINVAL);
+ rval = -1;
+ }
+ /* Check if there is specific data: */
+ else if (pthread->specific_data != NULL && (key < PTHREAD_DATAKEYS_MAX) && (key_table)) {
+ /* Check if this key has been used before: */
+ if (key_table[key].count) {
+ /* Return the value: */
+ *p_data = (void *) pthread->specific_data[key];
+ } else {
+ /*
+ * This key has not been used before, so return NULL
+ * instead:
+ */
+ *p_data = NULL;
+ }
+ } else {
+ /* No specific data has been created, so just return NULL: */
+ *p_data = NULL;
+ }
+
+ /* Unblock signals: */
+ _thread_kern_sig_unblock(status);
+ return (rval);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_suspend.c b/lib/libc_r/uthread/uthread_suspend.c
new file mode 100644
index 0000000..d53e130
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_suspend.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(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
diff --git a/lib/libc_r/uthread/uthread_wait4.c b/lib/libc_r/uthread/uthread_wait4.c
new file mode 100644
index 0000000..0a721af4f
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_wait4.c
@@ -0,0 +1,61 @@
+/*
+ * 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>
+#include <sys/wait.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+pid_t
+wait4(pid_t pid, int *istat, int options, struct rusage * rusage)
+{
+ int status;
+ pid_t ret;
+ _thread_kern_sig_block(&status);
+
+ /* Perform a non-blocking wait4 syscall: */
+ while ((ret = _thread_sys_wait4(pid, istat, options | WNOHANG, rusage)) == 0 && (options & WNOHANG) == 0) {
+ /* Schedule the next thread while this one waits: */
+ _thread_kern_sched_state(PS_WAIT_WAIT, __FILE__, __LINE__);
+
+ /* Check if this call was interrupted by a signal: */
+ if (errno == EINTR) {
+ ret = -1;
+ break;
+ }
+ _thread_kern_sig_block(NULL);
+ }
+ _thread_kern_sig_unblock(status);
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_write.c b/lib/libc_r/uthread/uthread_write.c
new file mode 100644
index 0000000..fb69129
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_write.c
@@ -0,0 +1,74 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+write(int fd, const void *buf, size_t nbytes)
+{
+ int nonblock;
+ int ret;
+ int status;
+ if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) {
+ _thread_seterrno(_thread_run, EBADF);
+ ret = -1;
+ } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) {
+ /* Cannot lock file descriptor. */
+ } else {
+ while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) {
+ if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
+ if (errno == EINTR) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (nonblock == 0) {
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_writev.c b/lib/libc_r/uthread/uthread_writev.c
new file mode 100644
index 0000000..f40e611
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_writev.c
@@ -0,0 +1,74 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+ssize_t
+writev(int fd, const struct iovec * iov, int iovcnt)
+{
+ int nonblock;
+ int ret;
+ int status;
+ if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) {
+ _thread_seterrno(_thread_run, EBADF);
+ ret = -1;
+ } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) {
+ /* Cannot lock file descriptor. */
+ } else {
+ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) {
+ if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ _thread_kern_sig_block(&status);
+ _thread_run->data.fd.fd = fd;
+ _thread_kern_set_timeout(NULL);
+ _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__);
+ if (errno == EINTR) {
+ ret = -1;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ if (nonblock == 0) {
+ _thread_fd_unlock(fd, FD_RDWR);
+ }
+ }
+ return (ret);
+}
+#endif
diff --git a/lib/libc_r/uthread/uthread_yield.c b/lib/libc_r/uthread/uthread_yield.c
new file mode 100644
index 0000000..a88a948
--- /dev/null
+++ b/lib/libc_r/uthread/uthread_yield.c
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ */
+#ifdef _THREAD_SAFE
+#include <pthread.h>
+#include "pthread_private.h"
+
+void
+pthread_yield(void)
+{
+ /* Reset the accumulated time slice value for the current thread: */
+ _thread_run->slice_usec = -1;
+
+ /* Schedule the next thread: */
+ _thread_kern_sched(NULL);
+
+ /* Nothing to return. */
+ return;
+}
+#endif
diff --git a/lib/libc_r/xdr/Makefile.inc b/lib/libc_r/xdr/Makefile.inc
new file mode 100644
index 0000000..cdf7ab1
--- /dev/null
+++ b/lib/libc_r/xdr/Makefile.inc
@@ -0,0 +1,5 @@
+# @(#)Makefile 5.11 (Berkeley) 9/6/90
+
+.PATH: ${.CURDIR}/../libc/xdr ${.CURDIR}/../libc
+SRCS+= xdr.c xdr_array.c xdr_float.c xdr_mem.c \
+ xdr_rec.c xdr_reference.c xdr_stdio.c
diff --git a/lib/libc_r/yp/Makefile.inc b/lib/libc_r/yp/Makefile.inc
new file mode 100644
index 0000000..3e8540d
--- /dev/null
+++ b/lib/libc_r/yp/Makefile.inc
@@ -0,0 +1,8 @@
+# from: @(#)Makefile.inc 5.3 (Berkeley) 2/20/91
+# $Id: Makefile.inc,v 1.1 1994/08/07 23:04:53 wollman Exp $
+
+# yp sources
+.PATH: ${.CURDIR}/../libc/yp
+
+SRCS+= xdryp.c yplib.c
+
OpenPOWER on IntegriCloud