diff options
Diffstat (limited to 'lib/libc_r')
126 files changed, 13681 insertions, 0 deletions
diff --git a/lib/libc_r/Makefile b/lib/libc_r/Makefile new file mode 100644 index 00000000000..f3f5b76049d --- /dev/null +++ b/lib/libc_r/Makefile @@ -0,0 +1,61 @@ +# $OpenBSD: Makefile,v 1.1 1998/08/27 09:00:32 d Exp $ +# +# All library objects contain sccsid strings by default; they may be +# excluded as a space-saving measure. To produce a library that does +# not contain these strings, delete -DLIBC_SCCS and -DSYSLIBC_SCCS +# from CFLAGS below. To remove these strings from just the system call +# stubs, remove just -DSYSLIBC_SCCS from CFLAGS. +# +# The NLS (message catalog) functions are always in libc. To choose that +# strerror(), perror(), strsignal(), psignal(), etc. actually call the NLS +# functions, put -DNLS on the CFLAGS line below. +# +# The YP functions are always in libc. To choose that getpwent() and friends +# actually call the YP functions, put -DYP on the CFLAGS line below. + +.include <bsd.own.mk> + +NOPIC= pic seems to be busted at the moment + +LIB= c_r +LINTFLAGS= -z +CFLAGS+= -DPTHREAD_KERNEL -D_POSIX_THREADS -D_THREAD_SAFE +CFLAGS+= -DNOPOLL -I${.CURDIR}/uthread +CFLAGS+= -I${.CURDIR}/include +DEBUG= -ggdb -Wall + +# Uncomment this if you want libc_r to contain debug information for +# thread locking. +CFLAGS+= -D_LOCK_DEBUG + +# +# This is a list of syscalls that are renamed as _thread_sys_{syscall} +# so that libc_r can provide replacement functions. +# +HIDDEN_SYSCALLS= accept.o bind.o close.o connect.o dup.o dup2.o \ + execve.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 \ + mknod.o nanosleep.o nfssvc.o open.o poll.o read.o readv.o recvfrom.o \ + recvmsg.o sched_yield.o select.o sendmsg.o sendto.o \ + setsockopt.o shutdown.o sigaction.o sigaltstack.o \ + signanosleep.o socket.o socketpair.o wait4.o write.o writev.o \ + _exit.o + +.include "${.CURDIR}/../libc/Makefile.inc" +# let manual pages be built/installed from libc +MAN= +MLINKS= + +.include "${.CURDIR}/man/Makefile.inc" +.include "${.CURDIR}/uthread/Makefile.inc" +.include "${.CURDIR}/sys/Makefile.inc" + +AINC+= -I${.CURDIR}/uthread + +SHLIB_MAJOR != . ${LIBCSRCDIR}/shlib_version ; echo $$major +SHLIB_MINOR != . ${LIBCSRCDIR}/shlib_version ; echo $$minor + +.include "${.CURDIR}/include/Makefile.inc" + +.include <bsd.lib.mk> diff --git a/lib/libc_r/NOTES b/lib/libc_r/NOTES new file mode 100644 index 00000000000..938de76867a --- /dev/null +++ b/lib/libc_r/NOTES @@ -0,0 +1,125 @@ + +Notes on the OpenBSD threaded C library (-lc_r) +================================================ + +Sources + + The main bulk of this library came from: + . FreeBSD's libc_r (John Birrell) + - The scheduler and locking code in the uthread directory. + - Some of the manual pages in the man directory. + - <pthreads.h> + . MIT pthreads (Chris Provenzano) + - The test code in the TEST directory + + I'm mainly tracking changes in FreeBSD's libc_r and integrating them + as I can. The major changes to Birrell's code involved making the + context switching a bit more architecture-independent. + +Standards + + This implementation has also been mindful of: + . Posix Threads[1] + . Single Unix Specification[2] + +Header files + + Only the absolutely required re-entrant functions have been added to + the C library interface headers in /usr/src/include. + + The new functions are: + readdir_r() <dirent.h> + sigwait() <signal.h> + flockfile() <stdio.h> + ftrylockfile() <stdio.h> + funclockfile() <stdio.h> + getc_unlocked() <stdio.h> + getchar_unlocked() <stdio.h> + putc_unlocked() <stdio.h> + putchar_unlocked() <stdio.h> + rand_r() <stdlib.h> + strtok_r() <string.h> + asctime_r() <time.h> + ctime_r() <time.h> + gmtime_r() <time.h> + localtime_r() <time.h> + + The widely used, but non-standard, gethostbyname_r() needs thought. + + These functions are available even when not using the thread package; + i.e., they are also in the non-threaded libc.a. + + See below why <sys/errno.h> has not been changed. + +Changes to libc sources + + The approach taken to making the libc functions re-entrant was to + develop some macros that handle: + . file locking + . monitors (thread-shared data structure locking) + . per-thread private data structure allocation + + Macros were used to avoid copious amounts of #ifdef statements[3]. + + In the non-threaded libc, file locking and the monitors are no-ops; + the per-thread private data structures were previously declared static + and the macros maintain this. + + In the threaded libc_r, file locking is as per the FreeBSD file + descriptor locking, and the monitors are pthread_mutex operations. + Per-thread private data structures use the pthread_specific functions + to dynamically allocate memory on their first use, initialising + them from the static (and hidden) per-compilation-unit data structures. + +Errno + + Unlike the FreeBSD and MIT pthreads package, errno is not a macro; + instead it is part of the per-thread context and saved and restored like + a register. This has several advantages over the errno-as-a-macro method: + + - The syscall/cerror code does not have to be re-written + - Libraries compiled without thread support will still work + - Easier to port packages that use errno, but don't include <errno.h> + + The overhead of saving and restoring an integer was considered too tiny + to worry about in comparison to the huge penalty hit of handling a + signal and restoring the rest of a thread's context. + +Compiler Support + + The in-tree gcc had its config/openbsd.h modified to support a + `-pthread' switch. Using this switch defines _POSIX_THREADS for cpp, and + replaces the normal -lc linker option with -lc_r. + + The objective-C component was also made aware of posix threads, via + the configure switch --enable-threads=posix. + +Caveats + + Not everything above is working right now: read the TODO file. + +Standard disclaimer + + This software is made available by the author to the public for free + and "as is". All users of this free software are solely and entirely + responsible for their own choice and use of this software for their + own purposes. By using this software, each user agrees that the + author shall not be liable for damages of any kind in relation to + its use or performance. + + Some parts of this software bear a copyright. + +References + + [1] P1003.1c/D10 IEEE Draft Standard for Information Technology-- + Portable Operating System Interface (POSIX) -- Part 1: System + Application Program Interface (API) -- Ammendment 2: Threads + Extension [C Language]. IEEE Standards, September 1994. + [2] T912, The Single UNIX(R) Specification, Version 2. The Open + Group, February 1997. http://www.opengroup.org/pubs/catalog/t912.htm + [3] #ifdef Considered Harmful, or Portability Experience with C News. + H. Spencer and G. Collyer, Proc. of the Summer 1992 USENIX Conference, + San Antionio, Texas, 1992. pp. 185-198 + +David Leonard <leonard@csee.uq.edu.au> +$OpenBSD: NOTES,v 1.1 1998/08/27 09:00:32 d Exp $ diff --git a/lib/libc_r/TODO b/lib/libc_r/TODO new file mode 100644 index 00000000000..72921df1f8e --- /dev/null +++ b/lib/libc_r/TODO @@ -0,0 +1,56 @@ + +This is a list of things that still need to be done: + +* Add thread stuff to the other archs in libc/arch/; ie change + some usages of ENTRY to SYSENTRY in some .S files and add + the new macros to their SYS.h. Only the i386 arch is working. + +* Find a better way of doing the _sys_aliases stuff; ideally by + using the linker. jmp's (current implementation) are ugly, but + I don't want to have to hack ../libc/sys/Makefile.inc just to + partition the syscalls into wrapped and non-wrapped. The `.set' + assembler directive just doesn't work as I thought it would. + +* Fix the bug where _thread_init() isn't called when libc_r.so is used + instead of libc_r.a ... some kind of shlib common problem? may + need to use crt0 instead? __CTOR_LIST__ is just not being updated by ld. + Frankly this one is driving me nuts. Maybe <bsd.lib.mk> is wrong. + +* Signals seem to cause busy-hangs. SIGINFO especially. test_sock_2 + fails because of its use of signals. still dumps /tmp/uthread.dump + though - needs debugging. + +* gethostbyname_r is not standard ... but is important - decide what to + do about this. The POSIX 'system databases' style of extra parameters is + probably the best way to go. + +* Modify gcc (or configure it) so that it understands a -thread option + and uses -lc_r automatically. I think the _PTHREADS flag is wrong, + and need to check the posix draft. + +* Test the objective-C compiler to see if it can use threads. + +* Find all the static buffers in libc and make them per-thread. This + is not absolutely necessary but incurs no penalty for single-threaded + operation, and makes life easier & safer for when threads are used. + +* Look into how netbsd are going with their kernel threads + +* Look into how asynchronous I/O can help us. In particular, the + (unimplemented) aio*() functions. + +* Write manual pages for all the pthread functions. + +* Update the libc manual pages to describe the posix re-entrant functions. + Although this is actually trivial to do, I have to decide on a + consistent way of adding them - maybe `.Sh THREAD-SAFE FUNCTIONS' ? + Should look into standards to see what they suggest/did.. + May also need to document "This is not thread-safe" for some library + functions (yet to be identified). + +* Talk to Birrell about what he wants to do with the _np extensions, + since the SUSv2 mentions extra standards to support things like + scheduling policy and so forth. + +$OpenBSD: TODO,v 1.1 1998/08/27 09:00:32 d Exp $ + diff --git a/lib/libc_r/man/Makefile.inc b/lib/libc_r/man/Makefile.inc new file mode 100644 index 00000000000..2cae3f76800 --- /dev/null +++ b/lib/libc_r/man/Makefile.inc @@ -0,0 +1,39 @@ +# $Id: Makefile.inc,v 1.1 1998/08/27 09:00:33 d Exp $ +# $OpenBSD: Makefile.inc,v 1.1 1998/08/27 09:00:33 d Exp $ + +# POSIX thread man files + +.PATH: ${.CURDIR}/man + +MAN+= pthread_cleanup_pop.3 \ + pthread_cleanup_push.3 \ + pthread_cond_broadcast.3 \ + pthread_cond_destroy.3 \ + pthread_cond_init.3 \ + pthread_cond_signal.3 \ + pthread_cond_timedwait.3 \ + pthread_cond_wait.3 \ + pthread_create.3 \ + pthread_detach.3 \ + pthread_equal.3 \ + pthread_exit.3 \ + pthread_getspecific.3 \ + pthread_join.3 \ + pthread_key_create.3 \ + pthread_key_delete.3 \ + pthread_mutex_destroy.3 \ + pthread_mutex_init.3 \ + pthread_mutex_lock.3 \ + pthread_mutex_trylock.3 \ + pthread_mutex_unlock.3 \ + pthread_once.3 \ + pthread_self.3 \ + pthread_setspecific.3 + +MAN+= pthreads.3 \ + flockfile.3 \ + sigwait.3 + +MLINKS+=flockfile.3 funlockfile.3 \ + flockfile.3 ftrylockfile.3 + diff --git a/lib/libc_r/man/flockfile.3 b/lib/libc_r/man/flockfile.3 new file mode 100644 index 00000000000..80602c5584b --- /dev/null +++ b/lib/libc_r/man/flockfile.3 @@ -0,0 +1,112 @@ +.\" $OpenBSD: flockfile.3,v 1.1 1998/08/27 09:00:34 d Exp $ +.Dd August 20, 1998 +.Os Ox +.Dt FLOCKFILE 3 +.Sh NAME +.Nm flockfile , +.Nm ftrylockfile , +.Nm funlockfile +.Nd application level locking of stdio files +.Sh SYNOPSIS +.Fd #include <stdio.h> +.Ft void +.Fn flockfile "FILE *file" +.Ft int +.Fn ftrylockfile "FILE *file" +.Ft void +.Fn funlockfile "FILE *file" +.Sh DESCRIPTION +The +.Fn flockfile , +.Fn ftrylockfile , +and +.Fn funlockfile +functions provide for explicit application-level locking of stdio +.Ft "FILE *" +objects. These functions can be used by a thread to delineate a sequence +of I/O statements that are to be executed as a unit. +.Pp +The +.Fn flockfile +function is used by a thread to acquire ownership of a +.Ft "FILE *" +object. +.Pp +The +.Fn ftrylockfile +function is used by a thread to acquire ownership of a +.Ft "FILE *" +object if the object is available; +.Fn ftrylockfile +is a non-blocking version of +.Fn flockfile . +.Pp +The +.Fn funlockfile +function is used to relinquish the ownership granted to the thread. +The behaviour is undefined if a thread other than the current owner calls the +.Fn funlockfile +function. +.Pp +Logically, there is a lock count associated with each +.Ft "FILE *" +object. This count is implicitly intialized to zero when the +.Ft "FILE *" +object is created. The +.Ft "FILE *" +object is unlocked when the count is zero. +When the count is positive, a single thread owns the +.Ft "FILE *" +object. When the +.Fn flockfile +function is called, if the count is zero or if the count is positive and +the caller owns the +.Ft "FILE *" +object, the count is incremented. +Otherwise, the calling thread is suspended, waiting for the count to +return to zero. +Each call to +.Fn funlockfile +decrements the count. This allows matching calls to +.Fn flockfile +(or sucessful calls to +.Fn ftrylockfile ) +and +.Fn funlockfile +to be nested. +.Pp +Library functions that reference +.Ft "FILE *" +behave as if they use +.Fn flockfile +and +.Fn funlockfile +internally to obtain ownership of these +.Ft "FILE *" +objects. +.Sh RETURN VALUES +None for +.Fn flockfile +and +.Fn funlockfile . +The function +.Fn ftrylock +returns zero for success and non-zero to indicate that the lock cannot +be acquired. +.Sh ERRORS +None. +.Sh SEE ALSO +.Xr getc_unlocked 3 , +.Xr getchar_unlocked 3 , +.Xr putc_unlocked 3 , +.Xr putchar_unlocked 3 , +.Xr pthreads 3 +.Sh STANDARDS +.Fn flockfile , +.Fn ftrylockfile +and +.Fn funlockfile +conform to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1c/D10. +.\" Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_cleanup_pop.3 b/lib/libc_r/man/pthread_cleanup_pop.3 new file mode 100644 index 00000000000..a244f9441e1 --- /dev/null +++ b/lib/libc_r/man/pthread_cleanup_pop.3 @@ -0,0 +1,61 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 30, 1998 +.Dt PTHREAD_CLEANUP_POP 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_cleanup_pop +.Nd call the first cleanup routine +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft void +.Fn pthread_cleanup_pop "int execute" +.Sh DESCRIPTION +The +.Fn pthread_cleanup_pop +function pops the top cleanup routine off of the current threads cleanup +routine stack, and, if +.Fa execute +is non-zero, it will execute the function. If there is no cleanup routine +then +.Fn pthread_cleanup_pop +does nothing. +.Sh RETURN VALUES +.Fn pthread_cleanup_pop +does not return any value. +.Sh ERRORS +None +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_cleanup_push 3 , +.Xr pthread_exit 3 +.Sh STANDARDS +.Fn pthread_cleanup_pop +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_cleanup_push.3 b/lib/libc_r/man/pthread_cleanup_push.3 new file mode 100644 index 00000000000..4a4b876ee4f --- /dev/null +++ b/lib/libc_r/man/pthread_cleanup_push.3 @@ -0,0 +1,64 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 30, 1998 +.Dt PTHREAD_CLEANUP_PUSH 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_cleanup_push +.Nd add a cleanup function for thread exit +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft void +.Fn pthread_cleanup_push "void (*cleanup_routine)(void *)" "void *arg" +.Sh DESCRIPTION +The +.Fn pthread_cleanup_push +function adds +.Fa cleanup_routine +to the top of the stack of cleanup handlers that +get called when the current thread exits. +.Pp +When +.Fn pthread_cleanup_push +is called, it is passed +.Fa arg +as its only argument. +.Sh RETURN VALUES +.Fn pthread_cleanup_push +does not return any value. +.Sh ERRORS +None +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_cleanup_pop 3 , +.Xr pthread_exit 3 +.Sh STANDARDS +.Fn pthread_cleanup_push +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_cond_broadcast.3 b/lib/libc_r/man/pthread_cond_broadcast.3 new file mode 100644 index 00000000000..25f00950db0 --- /dev/null +++ b/lib/libc_r/man/pthread_cond_broadcast.3 @@ -0,0 +1,69 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 28, 1998 +.Dt PTHREAD_COND_BROADCAST 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_cond_broadcast +.Nd unblock all threads waiting for a condition variable +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_cond_broadcast "pthread_cond_t *cond" +.Sh DESCRIPTION +The +.Fn pthread_cond_broadcast +function unblocks all threads waiting for the condition variable +.Fa cond . +.Sh RETURN VALUES +If successful, the +.Fn pthread_cond_broadcast +function will return zero, otherwise an error number will be returned +to indicate the error. +.Sh ERRORS +.Fn pthread_cond_broadcast +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa cond +is invalid. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_cond_init 3 , +.Xr pthread_cond_destroy 3 , +.Xr pthread_cond_wait 3 , +.Xr pthread_cond_timedwait 3 , +.Xr pthread_cond_signal 3 +.Sh STANDARDS +.Fn pthread_cond_broadcast +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_cond_destroy.3 b/lib/libc_r/man/pthread_cond_destroy.3 new file mode 100644 index 00000000000..94f2b4210f5 --- /dev/null +++ b/lib/libc_r/man/pthread_cond_destroy.3 @@ -0,0 +1,73 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 28, 1998 +.Dt PTHREAD_COND_DESTROY 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_cond_destroy +.Nd destroy a condition variable +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_cond_destroy "pthread_cond_t *cond" +.Sh DESCRIPTION +The +.Fn pthread_cond_destroy +function frees the resources allocated by the condition variable +.Fa cond . +.Sh RETURN VALUES +If successful, the +.Fn pthread_cond_init +function will return zero, otherwise an error number will be returned +to indicate the error. +.Sh ERRORS +.Fn pthread_cond_destroy +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa cond +is invalid. +.It Bq Er EBUSY +The variable +.Fa cond +is locked by another thread. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_cond_init 3 , +.Xr pthread_cond_wait 3 , +.Xr pthread_cond_timedwait 3 , +.Xr pthread_cond_signal 3 , +.Xr pthread_cond_broadcast 3 +.Sh STANDARDS +.Fn pthread_cond_destroy +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_cond_init.3 b/lib/libc_r/man/pthread_cond_init.3 new file mode 100644 index 00000000000..f8c16f49b21 --- /dev/null +++ b/lib/libc_r/man/pthread_cond_init.3 @@ -0,0 +1,78 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 28, 1998 +.Dt PTHREAD_COND_INIT 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_cond_init +.Nd create a condition variable +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_cond_init "pthread_cond_t *cond" "const pthread_condattr_t *attr" +.Sh DESCRIPTION +The +.Fn pthread_cond_init +function creates a new condition variable, with attributes specified with +.Fa attr . +If +.Fa attr +is NULL the default attributes are used. +.Sh RETURN VALUES +If successful, the +.Fn pthread_cond_init +function will return zero and put the new condition variable id into +.Fa cond , +otherwise an error number will be returned to indicate the error. +.Sh ERRORS +.Fn pthread_cond_init +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.It Bq Er ENOMEM +The process cannot allocate enough memory to create another condition +variable. +.It Bq Er EAGAIN +The temporarily lacks the resources to create another condition variable. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_cond_destroy 3 , +.Xr pthread_cond_wait 3 , +.Xr pthread_cond_timedwait 3 , +.Xr pthread_cond_signal 3 , +.Xr pthread_cond_broadcast 3 +.Sh STANDARDS +.Fn pthread_cond_init +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_cond_signal.3 b/lib/libc_r/man/pthread_cond_signal.3 new file mode 100644 index 00000000000..ebfd6561f4c --- /dev/null +++ b/lib/libc_r/man/pthread_cond_signal.3 @@ -0,0 +1,69 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 28, 1998 +.Dt PTHREAD_COND_SIGNAL 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_cond_signal +.Nd unblock a thread waiting for a condition variable +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_cond_signal "pthread_cond_t *cond" +.Sh DESCRIPTION +The +.Fn pthread_cond_signal +function unblocks one thread waiting for the condition variable +.Fa cond . +.Sh RETURN VALUES +If successful, the +.Fn pthread_cond_signal +function will return zero, otherwise an error number will be returned +to indicate the error. +.Sh ERRORS +.Fn pthread_cond_signal +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa cond +is invalid. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_cond_init 3 , +.Xr pthread_cond_destroy 3 , +.Xr pthread_cond_wait 3 , +.Xr pthread_cond_timedwait 3 , +.Xr pthread_cond_broadcast 3 +.Sh STANDARDS +.Fn pthread_cond_signal +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_cond_timedwait.3 b/lib/libc_r/man/pthread_cond_timedwait.3 new file mode 100644 index 00000000000..111a3fb117a --- /dev/null +++ b/lib/libc_r/man/pthread_cond_timedwait.3 @@ -0,0 +1,86 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 28, 1998 +.Dt PTHREAD_COND_TIMEDWAIT 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_cond_timedwait +.Nd wait on a condition variable for a specific amount of time +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_cond_timedwait "pthread_cond_t *cond" "pthread_mutex_t *mutex" "const struct timespec *abstime" +.Sh DESCRIPTION +The +.Fn pthread_cond_timedwait +function atomically blocks the current thread waiting on the condition +variable specified by +.Fa cond , +and unblocks the mutex specified by +.Fa mutex . +The waiting thread unblocks only after another thread calls +.Xr pthread_cond_signal 3 , +or +.Xr pthread_cond_broadcast 3 +with the same condition variable, or if the system time reaches the +time specified in +.Fa abstime , +and the current thread reaquires the lock on +.Fa mutex . +.Sh RETURN VALUES +If successful, the +.Fn pthread_cond_timedwait +function will return zero. Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_cond_timedwait +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa cond +or the value specified by +.Fa attr +is invalid. +.It Bq Er ETIMEDOUT +The system time has reached or exceeded the time specified in +.Fa abstime . +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_cond_init 3 , +.Xr pthread_cond_destroy 3 , +.Xr pthread_cond_wait 3 , +.Xr pthread_cond_signal 3 , +.Xr pthread_cond_broadcast 3 +.Sh STANDARDS +.Fn pthread_cond_timedwait +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_cond_wait.3 b/lib/libc_r/man/pthread_cond_wait.3 new file mode 100644 index 00000000000..69d9257cadf --- /dev/null +++ b/lib/libc_r/man/pthread_cond_wait.3 @@ -0,0 +1,80 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 28, 1998 +.Dt PTHREAD_COND_WAIT 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_cond_wait +.Nd wait on a condition variable +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_cond_wait "pthread_cond_t *cond" "pthread_mutex_t *mutex" +.Sh DESCRIPTION +The +.Fn pthread_cond_wait +function atomically blocks the current thread waiting on the condition +variable specified by +.Fa cond , +and unblocks the mutex specified by +.Fa mutex . +The waiting thread unblocks only after another thread calls +.Xr pthread_cond_signal 3 , or +.Xr pthread_cond_broadcast 3 +with the same condition variable, and the current thread reaquires the lock +on +.Fa mutex . +.Sh RETURN VALUES +If successful, the +.Fn pthread_cond_wait +function will return zero. Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_cond_wait +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa cond +or the value specified by +.Fa attr +is invalid. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_cond_init 3 , +.Xr pthread_cond_destroy 3 , +.Xr pthread_cond_timedwait 3 , +.Xr pthread_cond_signal 3 , +.Xr pthread_cond_broadcast 3 +.Sh STANDARDS +.Fn pthread_cond_wait +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_create.3 b/lib/libc_r/man/pthread_create.3 new file mode 100644 index 00000000000..7f94ffa0183 --- /dev/null +++ b/lib/libc_r/man/pthread_create.3 @@ -0,0 +1,113 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_CREATE 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_create +.Nd create a new thread +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_create "pthread_t *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg" +.Sh DESCRIPTION +The +.Fn pthread_create +function is used to create a new thread, with attributes specified by +.Fa attr , +within a process. If +.Fa attr +is NULL, the default attributes are used. If the attributes specified by +.Fa attr +are modified later, the thread's attributes are not affected. Upon +successful completion +.Fn pthread_create +will store the ID of the created thread in the location specified by +.Fa thread . +.Pp +The thread is created executing +.Fa start_routine +with +.Fa arg +as its sole argument. If the +.Fa start_routine +returns, the effect is as if there was an implicit call to +.Fn pthread_exit +using the return value of +.Fa start_routine +as the exit status. Note that the thread in which +.Fn main +was originally invoked differs from this. When it returns from +.Fn main , +the effect is as if there was an implicit call to +.Fn exit +using the return value of +.Fn main +as the exit status. +.Pp +The signal state of the new thread is initialized as: +.Bl -bullet -offset indent +.It +The signal mask is inherited from the creating thread. +.It +The set of signals pending for the new thread is empty. +.El +.Sh RETURN VALUES +If successful, the +.Fn pthread_create +function will return zero. Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_create +will fail if: +.Bl -tag -width Er +.It Bq Er EAGAIN +The system lacked the necessary resources to create another thread, or +the system-imposed limit on the total number of threads in a process +[PTHREAD_THREADS_MAX] would be exceeded. +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr fork 2 , +.Xr pthread_exit 3 , +.Xr pthread_cleanup_push 3 , +.Xr pthread_cleanup_pop 3 , +.Xr pthread_join 3 +.Sh STANDARDS +.Fn pthread_create +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_detach.3 b/lib/libc_r/man/pthread_detach.3 new file mode 100644 index 00000000000..a917d632e24 --- /dev/null +++ b/lib/libc_r/man/pthread_detach.3 @@ -0,0 +1,82 @@ +.\" Copyright (c) 1996-1998 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. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_DETACH 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_detach +.Nd detach a thread +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_detach "pthread_t thread" +.Sh DESCRIPTION +The +.Fn pthread_detach +function is used to indicate to the implementation that storage for the +thread +.Fa thread +can be reclaimed when the thread terminates. If +.Fa thread +has not terminated, +.Fn pthread_detach +will not cause it to terminate. The effect of multiple +.Fn pthread_detach +calls on the same target thread is unspecified. +.Sh RETURN VALUES +If successful, the +.Fn pthread_detach +function will return zero. Otherwise an error number will be returned to +indicate the error. Note that the function does not change the value +of errno as it did for some drafts of the standard. These early drafts +also passed a pointer to pthread_t as the argument. Beware! +.Sh ERRORS +.Fn pthread_detach +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The implementation has detected that the value specified by +.Fa thread +does not refer to a joinable thread. +.It Bq Er ESRCH +No thread could be found corresponding to that specified by the given +thread ID, +.Fa thread . +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_join 3 +.Sh STANDARDS +.Fn pthread_detach +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_equal.3 b/lib/libc_r/man/pthread_equal.3 new file mode 100644 index 00000000000..976d2881602 --- /dev/null +++ b/lib/libc_r/man/pthread_equal.3 @@ -0,0 +1,67 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_EQUAL 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_equal +.Nd compare thread IDs +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_equal "pthread_t t1" "pthread_t t2" +.Sh DESCRIPTION +The +.Fn pthread_equal +function compares the thread IDs +.Fa t1 +and +.Fa t2 . +.Sh RETURN VALUES +The +.Fn pthread_equal +function will non-zero if the thread IDs +.Fa t1 +and +.Fa t2 +correspond to the same thread, otherwise it will return zero. +.Sh ERRORS +None. +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_create 3 , +.Xr pthread_exit 3 +.Sh STANDARDS +.Fn pthread_equal +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_exit.3 b/lib/libc_r/man/pthread_exit.3 new file mode 100644 index 00000000000..b2fa8f2119b --- /dev/null +++ b/lib/libc_r/man/pthread_exit.3 @@ -0,0 +1,100 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_EXIT 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_exit +.Nd terminate the calling thread +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft void +.Fn pthread_exit "void *value_ptr" +.Sh DESCRIPTION +The +.Fn pthread_exit +function terminates the calling thread and makes the value +.Fa value_ptr +available to any successful join with the terminating thread. Any +cancellation cleanup handlers that have been pushed and are not yet popped +are popped in the reverse order that they were pushed and then executed. +After all cancellation handlers have been executed, if the thread has any +thread-specific data, appropriate destructor functions are called in an +unspecified order. Thread termination does not release any application +visible process resources, including, but not limited to, mutexes and +file descriptors, nor does it perform any process level cleanup +actions, including, but not limited to, calling +.Fn atexit +routines that may exist. +.Pp +An implicit call to +.Fn pthread_exit +is made when a thread other than the thread in which +.Fn main +was first invoked returns from the start routine that was used to create +it. The function's return value serves as the thread's exit status. +.Pp +The behavior of +.Fn pthread_exit +is undefied if called from a cancellation handler or destructor function +that was invoked as the result of an implicit or explicit call to +.Fn pthread_exit . +.Pp +After a thread has terminated, the result of access to local (auto) +variables of the thread is undefined. Thus, references to local variables +of the exiting thread should not be used for the +.Fn pthread_exit +.Fa value_ptr +parameter value. +.Pp +The process will exit with an exit status of 0 after the last thread has +been terminated. The behavior is as if the implementation called +.Fn exit +with a zero argument at thread termination time. +.Pp +.Sh RETURN VALUES +The +.Fn pthread_exit +function cannot return to its caller. +.Sh ERRORS +None. +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr _exit 2 , +.Xr exit 2 , +.Xr pthread_create 3 , +.Xr pthread_join 3 +.Sh STANDARDS +.Fn pthread_exit +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_getspecific.3 b/lib/libc_r/man/pthread_getspecific.3 new file mode 100644 index 00000000000..73490ae1d5b --- /dev/null +++ b/lib/libc_r/man/pthread_getspecific.3 @@ -0,0 +1,84 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: pthread_getspecific.3,v 1.1 1998/08/27 09:00:42 d Exp $ +.\" $OpenBSD: pthread_getspecific.3,v 1.1 1998/08/27 09:00:42 d Exp $ +.\" +.Dd April 4, 1996 +.Dt PTHREAD_GETSPECIFIC 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_getspecific +.Nd get a thread-specific data value +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft void * +.Fn pthread_getspecific "pthread_key_t key" +.Sh DESCRIPTION +The +.Fn pthread_getspecific +function returns the value currently bound to the specified +.Fa key +on behalf of the calling thread. +.Pp +The effect of calling +.Fn pthread_getspecific +with a +.Fa key +value not obtained from +.Fn pthread_key_create +or after +.Fa key +has been deleted with +.Fn pthread_key_delete +is undefined. +.Pp +.Fn pthread_getspecific +may be called from a thread-specific data destructor function. +.Sh RETURN VALUES +The +.Fn pthread_getspecific +function will return the thread-specific data value associated with the given +.Fa key . +If no thread-specific data value is associated with +.Fa key , +then the value NULL is returned. +.Sh ERRORS +None. +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_key_create 3 , +.Xr pthread_key_delete 3 , +.Xr pthread_setspecific 3 +.Sh STANDARDS +.Fn pthread_getspecific +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_join.3 b/lib/libc_r/man/pthread_join.3 new file mode 100644 index 00000000000..a89878c33f2 --- /dev/null +++ b/lib/libc_r/man/pthread_join.3 @@ -0,0 +1,101 @@ +.\" Copyright (c) 1996-1998 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. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_JOIN 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_join +.Nd wait for thread termination +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_join "pthread_t thread" "void **value_ptr" +.Sh DESCRIPTION +The +.Fn pthread_join +function suspends execution of the calling thread until the target +.Fa thread +terminates unless the target +.Fa thread +has already terminated. +.Pp +On return from a successful +.Fn pthread_join +call with a non-NULL +.Fa value_ptr +argument, the value passed to +.Fn pthread_exit +by the terminating thread is stored in the location referenced by +.Fa value_ptr . +When a +.Fn pthread_join +returns successfully, the target thread has been terminated. The results +of multiple simultaneous calls to +.Fn pthread_join +specifying the same target thread are undefined. If the thread calling +.Fn pthread_join +is cancelled, then the target thread is not detached. +.Pp +A thread that has exited but remains unjoined counts against +[_POSIX_THREAD_THREADS_MAX]. +.Pp +.Sh RETURN VALUES +If successful, the +.Fn pthread_join +function will return zero. Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_join +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The implementation has detected that the value specified by +.Fa thread +does not refer to a joinable thread. +.It Bq Er ESRCH +No thread could be found corresponding to that specified by the given +thread ID, +.Fa thread . +.It Bq Er EDEADLK +A deadlock was detected or the value of +.Fa thread +specifies the calling thread. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr wait 2 , +.Xr pthread_create 3 +.Sh STANDARDS +.Fn pthread_join +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_key_create.3 b/lib/libc_r/man/pthread_key_create.3 new file mode 100644 index 00000000000..2d29d10128b --- /dev/null +++ b/lib/libc_r/man/pthread_key_create.3 @@ -0,0 +1,99 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_KEY_CREATE 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_key_create +.Nd thread-specific data key creation +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_key_create "pthread_key_t *key" "void (*destructor)(void *)" +.Sh DESCRIPTION +The +.Fn pthread_key_create +function creates a thread-specific data key visible to all threads in the +process. Key values provided by +.Fn pthread_key_create +are opaque objects used to locate thread-specific data. Although the same +key value may be used by different threads, the values bound to the key +by +.Fn pthread_setspecific +are maintained on a per-thread basis and persist for the life of the calling +thread. +.Pp +Upon key creation, the value NULL is associated with the new key in all +active threads. Upon thread creation, the value NULL is associated with all +defined keys in the new thread. +.Pp +An optional destructor function may be associated with each key value. At +thread exit, if a key value has a non-NULL destructor pointer, and the +thread has a non-NULL value associated with the key, the function pointed +to is called with the current associated value as its sole argument. The +order of destructor calls is unspecified if more than one destructor exists +for a thread when it exits. +.Pp +If, after all the destructors have been called for all non-NULL values +with associated destructors, there are still some non-NULL values with +associated destructors, then the process is repeated. If, after at least +[PTHREAD_DESTRUCTOR_ITERATIONS] iterations of destructor calls for +outstanding non-NULL values, there are still some non-NULL values with +associated destructors, the implementation stops calling destructors. +.Sh RETURN VALUES +If successful, the +.Fn pthread_key_create +function will store the newly created key value at the location specified by +.Fa key +and returns zero. Otherwise an error number will be returned to indicate +the error. +.Sh ERRORS +.Fn pthread_key_create +will fail if: +.Bl -tag -width Er +.It Bq Er EAGAIN +The system lacked the necessary resources to create another thread-specific +data key, or the system-imposed limit on the total number of keys per process +[PTHREAD_KEYS_MAX] would be exceeded. +.It Bq Er ENOMEM +Insufficient memory exists to create the key. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_getspecific 3 , +.Xr pthread_key_delete 3 , +.Xr pthread_setspecific 3 +.Sh STANDARDS +.Fn pthread_key_create +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_key_delete.3 b/lib/libc_r/man/pthread_key_delete.3 new file mode 100644 index 00000000000..6ef3aef9b0b --- /dev/null +++ b/lib/libc_r/man/pthread_key_delete.3 @@ -0,0 +1,93 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_KEY_DELETE 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_key_delete +.Nd delete a thread-specific data key +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_key_delete "pthread_key_t key" +.Sh DESCRIPTION +The +.Fn pthread_key_delete +function deletes a thread-specific data key previously returned by +.Fn pthread_key_create . +The thread-specific data values associated with +.Fa key +need not be NULL at the time that +.Fn pthread_key_delete +is called. It is the responsibility of the application to free any +application storage or perform any cleanup actions for data structures +related to the deleted key or associated thread-specific data in any threads; +this cleanup can be done either before or after +.Fn pthread_key_delete +is called. Any attempt to use +.Fa key +following the call to +.Fn pthread_key_delete +results in undefined behavior. +.Pp +The +.Fn pthread_key_delete +function is callable from within destructor functions. Destructor functions +are not invoked by +.Fn pthread_key_delete . +Any destructor function that may have been associated with +.Fa key +will no longer be called upon thread exit. +.Sh RETURN VALUES +If successful, the +.Fn pthread_key_delete +function will return zero. Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_key_delete +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Fa key +value is invalid. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_getspecific 3 , +.Xr pthread_key_create 3 , +.Xr pthread_setspecific 3 +.Sh STANDARDS +.Fn pthread_key_delete +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_mutex_destroy.3 b/lib/libc_r/man/pthread_mutex_destroy.3 new file mode 100644 index 00000000000..aa9837c4732 --- /dev/null +++ b/lib/libc_r/man/pthread_mutex_destroy.3 @@ -0,0 +1,71 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 29, 1998 +.Dt PTHREAD_MUTEX_DESTROY 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_mutex_destroy +.Nd free resources allocated for a mutex +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_mutex_destroy "pthread_mutex_t *mutex" +.Sh DESCRIPTION +The +.Fn pthread_mutex_destroy +function frees the resources allocated for +.Fa mutex . +.Sh RETURN VALUES +If successful, +.Fn pthread_mutex_destroy +will return zero, otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_mutex_destroy +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa mutex +is invalid. +.It Bq Er EBUSY +.Fa Mutex +is locked by another thread. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_mutex_init 3 , +.Xr pthread_mutex_lock 3 , +.Xr pthread_mutex_unlock 3 , +.Xr pthread_mutex_trylock 3 +.Sh STANDARDS +.Fn pthread_mutex_destroy +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_mutex_init.3 b/lib/libc_r/man/pthread_mutex_init.3 new file mode 100644 index 00000000000..9966e16f6be --- /dev/null +++ b/lib/libc_r/man/pthread_mutex_init.3 @@ -0,0 +1,76 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 29, 1998 +.Dt PTHREAD_MUTEX_INIT 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_mutex_init +.Nd create a mutex +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_mutex_init "pthread_mutex_t *mutex" "const pthread_mutexattr_t *attr" +.Sh DESCRIPTION +The +.Fn pthread_mutex_init +function creates a new mutex, with attributes specified with +.Fa attr . +If +.Fa attr +is NULL the default attributes are used. +.Sh RETURN VALUES +If successful, +.Fn pthread_mutex_init +will return zero and put the new mutex id into +.Fa mutex , +otherwise an error number will be returned to indicate the error. +.Sh ERRORS +.Fn pthread_mutex_init +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.It Bq Er ENOMEM +The process cannot allocate enough memory to create another mutex. +.It Bq Er EAGAIN +The temporarily lacks the resources to create another mutex. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_mutex_destroy 3 , +.Xr pthread_mutex_lock 3 , +.Xr pthread_mutex_unlock 3 , +.Xr pthread_mutex_trylock 3 +.Sh STANDARDS +.Fn pthread_mutex_init +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_mutex_lock.3 b/lib/libc_r/man/pthread_mutex_lock.3 new file mode 100644 index 00000000000..d8cbe96314a --- /dev/null +++ b/lib/libc_r/man/pthread_mutex_lock.3 @@ -0,0 +1,73 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 30, 1998 +.Dt PTHREAD_MUTEX_LOCK 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_mutex_lock +.Nd lock a mutex +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_mutex_lock "pthread_mutex_t *mutex" +.Sh DESCRIPTION +The +.Fn pthread_mutex_lock +function locks +.Fa mutex . +If the mutex is already locked, the calling thread will block until the +mutex becomes available. +.Sh RETURN VALUES +If successful, +.Fn pthread_mutex_lock +will return zero, otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_mutex_lock +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa mutex +is invalid. +.It Bq Er EDEADLK +A deadlock would occur if the thread blocked waiting for +.Fa mutex . +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_mutex_unlock 3 , +.Xr pthread_mutex_trylock 3 , +.Xr pthread_mutex_init 3 , +.Xr pthread_mutex_destroy 3 +.Sh STANDARDS +.Fn pthread_mutex_lock +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_mutex_trylock.3 b/lib/libc_r/man/pthread_mutex_trylock.3 new file mode 100644 index 00000000000..81d2a4dc7e5 --- /dev/null +++ b/lib/libc_r/man/pthread_mutex_trylock.3 @@ -0,0 +1,74 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 30, 1998 +.Dt PTHREAD_MUTEX_TRYLOCK 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_mutex_trylock +.Nd attempt to lock a mutex without blocking +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_mutex_trylock "pthread_mutex_t *mutex" +.Sh DESCRIPTION +The +.Fn pthread_mutex_trylock +function locks +.Fa mutex . +If the mutex is already locked, +.Fn pthread_mutex_trylock +will not block waiting for the mutex, but will return an error condition. +.Sh RETURN VALUES +If successful, +.Fn pthread_mutex_trylock +will return zero, otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_mutex_trylock +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa mutex +is invalid. +.It Bq Er EBUSY +.Fa Mutex +is already locked. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_mutex_lock 3 , +.Xr pthread_mutex_unlock 3 , +.Xr pthread_mutex_init 3 , +.Xr pthread_mutex_destroy 3 +.Sh STANDARDS +.Fn pthread_mutex_trylock +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_mutex_unlock.3 b/lib/libc_r/man/pthread_mutex_unlock.3 new file mode 100644 index 00000000000..04fb06832d4 --- /dev/null +++ b/lib/libc_r/man/pthread_mutex_unlock.3 @@ -0,0 +1,73 @@ +.\" Copyright (c) 1997 Brian Cully <shmit@kublai.com> +.\" 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. 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. +.\" +.Dd July 30, 1998 +.Dt PTHREAD_MUTEX_UNLOCK 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_mutex_unlock +.Nd unlock a mutex +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_mutex_unlock "pthread_mutex_t *mutex" +.Sh DESCRIPTION +If the current thread holds the lock on +.Fa mutex , +then the +.Fn pthread_mutex_unlock +function unlocks +.Fa mutex . +.Sh RETURN VALUES +If successful, +.Fn pthread_mutex_unlock +will return zero, otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_mutex_trylock +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa mutex +is invalid. +.It Bq Er EPERM +The current thread does not hold a lock on +.Fa mutex . +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_mutex_lock 3 , +.Xr pthread_mutex_trylock 3 , +.Xr pthread_mutex_init 3 , +.Xr pthread_mutex_destroy 3 +.Sh STANDARDS +.Fn pthread_mutex_unlock +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_once.3 b/lib/libc_r/man/pthread_once.3 new file mode 100644 index 00000000000..c5d0235b41f --- /dev/null +++ b/lib/libc_r/man/pthread_once.3 @@ -0,0 +1,102 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_ONCE 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_once +.Nd dynamic package initialization +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Pp +pthread_once +.Fa once_control += PTHREAD_ONCE_INIT; +.Ft int +.Fn pthread_once "pthread_once_t *once_control" "void (*init_routine)(void)" +.Sh DESCRIPTION +The first call to +.Fn pthread_once +by any thread in a process, with a given +.Fa once_control , +will call the +.Fn init_routine +with no arguments. Subsequent calls to +.Fn pthread_once +with the same +.Fa once_control +will not call the +.Fn init_routine . +On return from +.Fn pthread_once , +it is guaranteed that +.Fn init_routine +has completed. The +.Fa once_control +parameter is used to determine whether the associated initialization +routine has been called. +.Pp +The function +.Fn pthread_once +is not a cancellation point. However, if +.Fn init_routine +is a cancellation point and is cancelled, the effect on +.Fa once_control is as if +.Fn pthread_once +was never called. +.Pp +The constant +.Fa PTHREAD_ONCE_INIT +is defined by header +.Aq Pa pthread.h . +.Pp +The behavior of +.Fn pthread_once +is undefined if +.Fa once_control +has automatic storage duration or is not initialized by +.Fa PTHREAD_ONCE_INIT . +.Pp +.Sh RETURN VALUES +If successful, the +.Fn pthread_once +function will return zero. Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +None. +.Pp +.Sh SEE ALSO +.Xr pthreads 3 +.Sh STANDARDS +.Fn pthread_once +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_self.3 b/lib/libc_r/man/pthread_self.3 new file mode 100644 index 00000000000..63cf2dfdafb --- /dev/null +++ b/lib/libc_r/man/pthread_self.3 @@ -0,0 +1,60 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_SELF 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_self +.Nd get the calling thread's ID +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft pthread_t +.Fn pthread_self "void" +.Sh DESCRIPTION +The +.Fn pthread_self +function returns the thread ID of the calling thread. +.Sh RETURN VALUES +The +.Fn pthread_self +function returns the thread ID of the calling thread. +.Sh ERRORS +None. +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_create 3 , +.Xr pthread_equal 3 +.Sh STANDARDS +.Fn pthread_self +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthread_setspecific.3 b/lib/libc_r/man/pthread_setspecific.3 new file mode 100644 index 00000000000..448e1872f58 --- /dev/null +++ b/lib/libc_r/man/pthread_setspecific.3 @@ -0,0 +1,92 @@ +.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd April 4, 1996 +.Dt PTHREAD_SETSPECIFIC 3 +.Os BSD 4 +.Sh NAME +.Nm pthread_setspecific +.Nd set a thread-specific data value +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_setspecific "pthread_key_t key" "const void *value" +.Sh DESCRIPTION +The +.Fn pthread_setspecific +function associates a thread-specific value with a +.Fa key +obtained via a previous call to +.Fn pthread_key_create . +Different threads man bind different values to the same key. These values are +typically pointers to blocks of dynamically allocated memory that have been +reserved for use by the calling thread. +.Pp +The effect of calling +.Fn pthread_setspecific +with a key value not obtained from +.Fn pthread_key_create +or after +.Fa key +has been deleted with +.Fn pthread_key_delete +is undefined. +.Pp +.Fn pthread_setspecific +may be called from a thread-specific data destructor function, however this +may result in lost storage or infinite loops. +.Sh RETURN VALUES +If successful, the +.Fn pthread_setspecific +function will return zero. Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_setspecific +will fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +Insufficient memory exists to associate the value with the +.Fa key . +.It Bq Er EINVAL +The +.Fa key +value is invalid. +.El +.Pp +.Sh SEE ALSO +.Xr pthreads 3 , +.Xr pthread_getspecific 3 , +.Xr pthread_key_create 3 , +.Xr pthread_key_delete 3 +.Sh STANDARDS +.Fn pthread_setspecific +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/pthreads.3 b/lib/libc_r/man/pthreads.3 new file mode 100644 index 00000000000..a36c6a05754 --- /dev/null +++ b/lib/libc_r/man/pthreads.3 @@ -0,0 +1,91 @@ +.Dd August 17, 1998 +.Dt PTHREADS 3 +.Os BSD 4 +.Sh NAME +.Nm pthreads +.Nd POSIX 1003.1c thread interface +.Sh SYNOPSIS +.Fd #include <pthread.h> +.Ft int +.Fn pthread_create "pthread_t *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg" +.Ft void +.Fn pthread_cleanup_pop "int execute" +.Ft void +.Fn pthread_cleanup_push "void (*cleanup_routine)(void *)" "void *arg" +.Ft int +.Fn pthread_cond_broadcast "pthread_cond_t *cond" +.Ft int +.Fn pthread_cond_destroy "pthread_cond_t *cond" +.Ft int +.Fn pthread_cond_init "pthread_cond_t *cond" "const pthread_condattr_t *attr" +.Ft int +.Fn pthread_cond_signal "pthread_cond_t *cond" +.Ft int +.Fn pthread_cond_timedwait "pthread_cond_t *cond" "pthread_mutex_t *mutex" "const struct timespec *abstime" +.Ft int +.Fn pthread_cond_wait "pthread_cond_t *cond" "pthread_mutex_t *mutex" +.Ft int +.Fn pthread_create "pthread_t *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg" +.Fn pthread_exit +.Ft int +.Fn pthread_detach "pthread_t thread" +.Ft int +.Fn pthread_equal "pthread_t t1" "pthread_t t2" +.Ft void +.Fn pthread_exit "void *value_ptr" +.Ft void * +.Fn pthread_getspecific "pthread_key_t key" +.Ft int +.Fn pthread_join "pthread_t thread" "void **value_ptr" +.Ft int +.Fn pthread_key_create "pthread_key_t *key" "void (*destructor)(void *)" +.Ft int +.Fn pthread_key_delete "pthread_key_t key" +.Ft int +.Fn pthread_mutex_destroy "pthread_mutex_t *mutex" +.Ft int +.Fn pthread_mutex_init "pthread_mutex_t *mutex" "const pthread_mutexattr_t *attr" +.Ft int +.Fn pthread_mutex_lock "pthread_mutex_t *mutex" +.Ft int +.Fn pthread_mutex_trylock "pthread_mutex_t *mutex" +.Ft int +.Fn pthread_mutex_unlock "pthread_mutex_t *mutex" +.Ft int +.Fn pthread_once "pthread_once_t *once_control" "void (*init_routine)(void)" +.Ft pthread_t +.Fn pthread_self "void" +.Ft int +.Fn pthread_setspecific "pthread_key_t key" "const void *value" +.Sh DESCRIPTION +Steal something from the posix specs to describe what a thread is. +.Sh SEE ALSO +.Xr pthread_cleanup_pop 3 , +.Xr pthread_cleanup_push 3 , +.Xr pthread_cond_broadcast 3 , +.Xr pthread_cond_destroy 3 , +.Xr pthread_cond_init 3 , +.Xr pthread_cond_signal 3 , +.Xr pthread_cond_timedwait 3 , +.Xr pthread_cond_wait 3 , +.Xr pthread_create 3 , +.Xr pthread_detach 3 , +.Xr pthread_equal 3 , +.Xr pthread_exit 3 , +.Xr pthread_getspecific 3 , +.Xr pthread_join 3 , +.Xr pthread_key_create 3 , +.Xr pthread_key_delete 3 , +.Xr pthread_mutex_destroy 3 , +.Xr pthread_mutex_init 3 , +.Xr pthread_mutex_lock 3 , +.Xr pthread_mutex_trylock 3 , +.Xr pthread_mutex_unlock 3 , +.Xr pthread_once 3 , +.Xr pthread_self 3 , +.Xr pthread_setspecific 3 +.Sh STANDARDS +.Fn pthread_create +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/man/sigwait.3 b/lib/libc_r/man/sigwait.3 new file mode 100644 index 00000000000..159ea408120 --- /dev/null +++ b/lib/libc_r/man/sigwait.3 @@ -0,0 +1,76 @@ +.\" $OpenBSD: sigwait.3,v 1.1 1998/08/27 09:00:48 d Exp $ +.Dd August 20, 1998 +.Os Ox +.Dt SIGWAIT 3 +.Sh NAME +.Nm sigwait +.Nd synchonously accept a signal +.Sh SYNOPSIS +.Fd #include <signal.h> +.Ft int +.Fn sigwait "sont sigset_t *set" "int *sig" +.Sh DESCRIPTION +The +.Fn sigwait +function selects a pending signal from +.Fa set , +atomically clears it from the system's set of pending signals, and returns +that signal number in the location referenced by +.Fa sig . +If prior to the call to +.Fn sigwait +there are multiple pending instances of a single signal number, +it is undefined whether upon successful return there are any remaining pending signals for that signal number. +If no signal in +.Fa set +is pending at the time of the call, +the thread shall be suspended until one or more becomes pending. +The signals defined by +.Fa set +should have been blocked at the time of the call to +.Fn sigwait ; +otherwise the behaviour is undefined. +The effect of +.Fn sigwait +on the signal actions for the signals in +.Fa set +is unspecified. +.Pp +If more than one thread is using +.Fn sigwait +to wait for the same signal, +no more than one of these threads shall return from +.Fn sigwait +with the signal number. +Which thread returns from +.Fn sigwait +if more than a single thread is waiting is unspecified. +.Sh RETURN VALUES +Upon successful completion, +.Fn sigwait +stores the signal number of the recived signal at the location referenced by +.Fa sig +and returns zero. +.Sh ERRORS +On error, +.Fn Sigwait +returns one of these error values: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Fa set +argument contains an invalid or unsupported signal number +.El +.Sh SEE ALSO +.Xr pause +.Xr sigaction +.Xr sigpending +.Xr sigsuspend +.Xr pthreads +.Xr pthread_sigmask +.Sh STANDARDS +.Fn sigwait +conforms to ISO/IEC 9945-1 ANSI/IEEE +.Pq Dq Tn POSIX +Std 1003.1c/D10. +.\" Std 1003.1 Second Edition 1996-07-12. diff --git a/lib/libc_r/shlib_version b/lib/libc_r/shlib_version new file mode 100644 index 00000000000..97c9f92d6b8 --- /dev/null +++ b/lib/libc_r/shlib_version @@ -0,0 +1,2 @@ +major=0 +minor=0 diff --git a/lib/libc_r/sys/Makefile.inc b/lib/libc_r/sys/Makefile.inc new file mode 100644 index 00000000000..bf19b6dd111 --- /dev/null +++ b/lib/libc_r/sys/Makefile.inc @@ -0,0 +1,16 @@ +# $Id: Makefile.inc,v 1.1 1998/08/27 09:00:48 d Exp $ +# $OpenBSD: Makefile.inc,v 1.1 1998/08/27 09:00:48 d Exp $ + +.PATH: ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH} + +SRCS+= uthread_error.c _atomic_lock.S _sys_aliases.S + +_sys_aliases.S: ${.CURDIR}/Makefile ${LIBCSRCDIR}/sys/Makefile.inc + (echo '#include "SYS.h"'; \ + for fn in ${ASM:R} ${PSEUDO:R} ""; do \ + case $$fn in ${HIDDEN_SYSCALLS:.o=|}"") : stays hidden ;; \ + *) echo "PASSTHRU($$fn)";; \ + esac; \ + done ) > ${.TARGET} + +CLEANFILES += _sys_aliases.S diff --git a/lib/libc_r/sys/uthread_error.c b/lib/libc_r/sys/uthread_error.c new file mode 100644 index 00000000000..545dfb06652 --- /dev/null +++ b/lib/libc_r/sys/uthread_error.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. + * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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 + * and Chris Provenzano. + * 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" +extern int errno; + +int * __error() +{ + int *p_errno; + if (_thread_run == _thread_initial) { + p_errno = &errno; + } else { + p_errno = &_thread_run->error; + } + return(p_errno); +} +#endif diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc new file mode 100644 index 00000000000..0e285297a0b --- /dev/null +++ b/lib/libc_r/uthread/Makefile.inc @@ -0,0 +1,97 @@ +# $Id: Makefile.inc,v 1.1 1998/08/27 09:00:49 d Exp $ +# $OpenBSD: Makefile.inc,v 1.1 1998/08/27 09:00:49 d Exp $ + +# uthread sources +.PATH: ${.CURDIR}/uthread + +CFLAGS += -I${.CURDIR}/arch/${MACHINE_ARCH} + +SRCS+= \ + uthread_accept.c \ + uthread_attr_destroy.c \ + uthread_attr_init.c \ + uthread_attr_getdetachstate.c \ + uthread_attr_getstackaddr.c \ + uthread_attr_getstacksize.c \ + uthread_attr_setcreatesuspend_np.c \ + uthread_attr_setdetachstate.c \ + uthread_attr_setstackaddr.c \ + uthread_attr_setstacksize.c \ + uthread_bind.c \ + uthread_clean.c \ + uthread_close.c \ + uthread_cond.c \ + uthread_condattr_destroy.c \ + uthread_condattr_init.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_find_thread.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_kill.c \ + uthread_listen.c \ + uthread_mattr_init.c \ + uthread_mattr_kind_np.c \ + uthread_multi_np.c \ + uthread_mutex.c \ + uthread_mutexattr_destroy.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_recvmsg.c \ + uthread_resume_np.c \ + uthread_select.c \ + uthread_self.c \ + uthread_sendmsg.c \ + uthread_sendto.c \ + uthread_seterrno.c \ + uthread_setprio.c \ + uthread_setsockopt.c \ + uthread_shutdown.c \ + uthread_sig.c \ + uthread_sigaction.c \ + uthread_sigblock.c \ + uthread_sigmask.c \ + uthread_sigprocmask.c \ + uthread_sigsetmask.c \ + uthread_sigsuspend.c \ + uthread_sigwait.c \ + uthread_single_np.c \ + uthread_socket.c \ + uthread_socketpair.c \ + uthread_spec.c \ + uthread_spinlock.c \ + uthread_suspend_np.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 00000000000..ce7da3da5c4 --- /dev/null +++ b/lib/libc_r/uthread/pthread_private.h @@ -0,0 +1,725 @@ +/* + * Copyright (c) 1995-1998 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 + +#include <paths.h> + +/* + * Include files. + */ +#include <setjmp.h> +#include <signal.h> +#include <sys/queue.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sched.h> +#include <spinlock.h> +#include "uthread_machdep.h" + +/* + * Kernel fatal error handler macro. + */ +#define PANIC(string) _thread_exit(__FILE__,__LINE__,string) + +/* Output debug messages like this: */ +#define stdout_debug(_x) _write(1,_x,strlen(_x)); +#define stderr_debug(_x) _write(2,_x,strlen(_x)); + +/* + * State change macro: + */ +#define PTHREAD_NEW_STATE(thrd, newstate) { \ + (thrd)->state = newstate; \ + (thrd)->fname = __FILE__; \ + (thrd)->lineno = __LINE__; \ +} + +/* + * Queue definitions. + */ +struct pthread_queue { + struct pthread *q_next; + struct pthread *q_last; + void *q_data; +}; + +/* + * Static queue initialization values. + */ +#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL } + +/* + * Mutex definitions. + */ +union pthread_mutex_data { + void *m_ptr; + int m_count; +}; + +struct pthread_mutex { + enum pthread_mutextype m_type; + struct pthread_queue m_queue; + struct pthread *m_owner; + union pthread_mutex_data m_data; + long m_flags; + + /* + * Lock for accesses to this structure. + */ + spinlock_t lock; +}; + +/* + * Flags for mutexes. + */ +#define MUTEX_FLAGS_PRIVATE 0x01 +#define MUTEX_FLAGS_INITED 0x02 +#define MUTEX_FLAGS_BUSY 0x04 + +/* + * Static mutex initialization values. + */ +#define PTHREAD_MUTEX_STATIC_INITIALIZER \ + { MUTEX_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, \ + NULL, { NULL }, MUTEX_FLAGS_INITED } + +struct pthread_mutex_attr { + enum pthread_mutextype m_type; + long m_flags; +}; + +/* + * Condition variable definitions. + */ +enum pthread_cond_type { + COND_TYPE_FAST, + COND_TYPE_MAX +}; + +struct pthread_cond { + enum pthread_cond_type c_type; + struct pthread_queue c_queue; + void *c_data; + long c_flags; + + /* + * Lock for accesses to this structure. + */ + spinlock_t lock; +}; + +struct pthread_cond_attr { + enum pthread_cond_type c_type; + long c_flags; +}; + +/* + * Flags for condition variables. + */ +#define COND_FLAGS_PRIVATE 0x01 +#define COND_FLAGS_INITED 0x02 +#define COND_FLAGS_BUSY 0x04 + +/* + * Static cond initialization values. + */ +#define PTHREAD_COND_STATIC_INITIALIZER \ + { COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, COND_FLAGS_INITED } + +/* + * Cleanup definitions. + */ +struct pthread_cleanup { + struct pthread_cleanup *next; + void (*routine) (); + void *routine_arg; +}; + +struct pthread_attr { + int schedparam_policy; + int prio; + int suspend; + int flags; + void *arg_attr; + void (*cleanup_attr) (); + void *stackaddr_attr; + size_t stacksize_attr; +}; + +/* + * Thread creation state attributes. + */ +#define PTHREAD_CREATE_RUNNING 0 +#define PTHREAD_CREATE_SUSPENDED 1 + +/* + * Miscellaneous definitions. + */ +#define PTHREAD_STACK_DEFAULT 65536 +#define PTHREAD_DEFAULT_PRIORITY 64 +#define PTHREAD_MAX_PRIORITY 126 +#define PTHREAD_MIN_PRIORITY 0 +#define _POSIX_THREAD_ATTR_STACKSIZE + +/* + * 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 + +struct pthread_key { + spinlock_t lock; + volatile int allocated; + volatile int 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_FILE_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 { + /* + * Lock for accesses to this file descriptor table + * entry. This is passed to _spinlock() to provide atomic + * access to this structure. It does *not* represent the + * state of the lock on the file descriptor. + */ + spinlock_t lock; + 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 { + /* + * Magic value to help recognize a valid thread structure + * from an invalid one: + */ +#define PTHREAD_MAGIC ((u_int32_t) 0xd09ba115) + u_int32_t magic; + char *name; + + /* + * Lock for accesses to this thread structure. + */ + spinlock_t lock; + + /* + * 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; + struct pthread_attr attr; + + struct _machdep_struct _machdep; + + /* + * 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 pending signals. + */ + sigset_t sigmask; + sigset_t sigpend; + + /* 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. + * + * XXX The queuing should be changed to use the TAILQ entry below. + * XXX For the time being, it's hybrid. + */ + struct pthread_queue *queue; + + /* Pointer to next element in queue. */ + struct pthread *qnxt; + + /* Queue entry for this thread: */ + TAILQ_ENTRY(pthread) qe; + + /* Wait data. */ + union pthread_wait_data data; + + /* + * Set to TRUE if a blocking operation was + * interrupted by a signal: + */ + int interrupted; + + /* Signal number when in state PS_SIGWAIT: */ + int signo; + + /* Miscellaneous data. */ + char flags; +#define PTHREAD_EXITING 0x0100 + char pthread_priority; + void *ret; + const void **specific_data; + int specific_data_count; + + /* Cleanup handlers Link List */ + struct pthread_cleanup *cleanup; + char *fname; /* Ptr to source file name */ + int lineno; /* Source line number. */ +}; + +/* + * Global variables for the uthread kernel. + */ + +/* Kernel thread structure used when there are no running threads: */ +extern struct pthread _thread_kern_thread; + +/* Ptr to the thread structure for the running thread: */ +extern struct pthread * volatile _thread_run; + +/* + * Ptr to the thread running in single-threaded mode or NULL if + * running multi-threaded (default POSIX behaviour). + */ +extern struct pthread * volatile _thread_single; + +/* Ptr to the first thread in the thread linked list: */ +extern struct pthread * volatile _thread_link_list; + +/* + * Array of kernel pipe file descriptors that are used to ensure that + * no signals are missed in calls to _select. + */ +extern int _thread_kern_pipe[2]; +extern int _thread_kern_in_select; +extern int _thread_kern_in_sched; + +/* Last time that an incremental priority update was performed: */ +extern struct timeval kern_inc_prio_time; + +/* Dead threads: */ +extern struct pthread * volatile _thread_dead; + +/* Initial thread: */ +extern struct pthread *_thread_initial; + +/* Default thread attributes: */ +extern struct pthread_attr pthread_attr_default; + +/* Default mutex attributes: */ +extern struct pthread_mutex_attr pthread_mutexattr_default; + +/* Default condition variable attributes: */ +extern struct pthread_cond_attr pthread_condattr_default; + +/* + * Standard I/O file descriptors need special flag treatment since + * setting one to non-blocking does all on *BSD. Sigh. This array + * is used to store the initial flag settings. + */ +extern int _pthread_stdio_flags[3]; + +/* File table information: */ +extern struct fd_table_entry **_thread_fd_table; +extern int _thread_dtablesize; + +/* + * Array of signal actions for this process. + */ +extern struct sigaction _thread_sigact[NSIG]; + +/* + * Where SIGINFO writes thread states when /dev/tty cannot be opened + */ +#define INFO_DUMP_FILE "/tmp/uthread.dump" + +#ifdef _LOCK_DEBUG +#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock_debug(_fd, _type, \ + _ts, __FILE__, __LINE__) +#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock_debug(_fd, _type, \ + __FILE__, __LINE__) +#else +#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts) +#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type) +#endif + +/* + * Function prototype definitions. + */ +__BEGIN_DECLS +int _find_dead_thread(pthread_t); +int _find_thread(pthread_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 *); +int _thread_fd_lock_debug(int, int, struct timespec *,char *fname,int lineno); +void _dispatch_signals(void); +void _thread_signal(pthread_t, int); +void _lock_dead_thread_list(void); +void _lock_thread(void); +void _lock_thread_list(void); +void _unlock_dead_thread_list(void); +void _unlock_thread(void); +void _unlock_thread_list(void); +void _thread_exit(char *, int, char *); +void _thread_fd_unlock(int, int); +void _thread_fd_unlock_debug(int, int, char *, int); +void *_thread_cleanup(pthread_t); +void _thread_cleanupspecific(void); +void _thread_dump_info(void); +void _thread_init(void) __attribute__((constructor)); +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_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> */ +#ifdef _USER_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_siginterrupt(int, int); +int _thread_sys_sigpause(int); +int _thread_sys_sigreturn(struct sigcontext *); +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); +#endif + +/* #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_ +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); +void _thread_sys__exit(int); +#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 <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 _SYS_WAIT_H_ +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 00000000000..371da568bf0 --- /dev/null +++ b/lib/libc_r/uthread/uthread_accept.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1995-1998 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> +#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 the file descriptor: */ + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 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; + _thread_run->data.fd.fname = __FILE__; + _thread_run->data.fd.branch = __LINE__; + + /* Set the timeout: */ + _thread_kern_set_timeout(NULL); + _thread_run->interrupted = 0; + + /* Schedule the next thread: */ + _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); + + /* Check if the wait was interrupted: */ + if (_thread_run->interrupted) { + /* Return an error status: */ + errno = EINTR; + ret = -1; + break; + } + } else { + /* + * Another error has occurred, so exit the + * loop here: + */ + break; + } + } + + /* 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; + } + /* + * If the parent socket was blocking, make sure that + * the new socket is also set blocking here (as the + * call to _thread_fd_table_init() above will always + * set the new socket flags to non-blocking, as that + * will be the inherited state of the new socket. + */ + if((ret > 0) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0) + _thread_fd_table[ret]->flags &= ~O_NONBLOCK; + + /* Unlock the file descriptor: */ + _FD_UNLOCK(fd, FD_RDWR); + } + /* Return the socket file descriptor or -1 on error: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_destroy.c b/lib/libc_r/uthread/uthread_attr_destroy.c new file mode 100644 index 00000000000..1f4b2c8523c --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_destroy.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <stdlib.h> +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_destroy(pthread_attr_t *attr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL) + /* Invalid argument: */ + ret = EINVAL; + else { + /* Free the memory allocated to the attribute object: */ + free(*attr); + + /* + * Leave the attribute pointer NULL now that the memory + * has been freed: + */ + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_getdetachstate.c b/lib/libc_r/uthread/uthread_attr_getdetachstate.c new file mode 100644 index 00000000000..4715cb6f242 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_getdetachstate.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || detachstate == NULL) + ret = EINVAL; + else { + /* Check if the detached flag is set: */ + if ((*attr)->flags & PTHREAD_DETACHED) + /* Return detached: */ + *detachstate = PTHREAD_CREATE_DETACHED; + else + /* Return joinable: */ + *detachstate = PTHREAD_CREATE_JOINABLE; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_getstackaddr.c b/lib/libc_r/uthread/uthread_attr_getstackaddr.c new file mode 100644 index 00000000000..1850a324c61 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_getstackaddr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + ret = EINVAL; + else { + /* Return the stack address: */ + *stackaddr = (*attr)->stackaddr_attr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_getstacksize.c b/lib/libc_r/uthread/uthread_attr_getstacksize.c new file mode 100644 index 00000000000..de81106083d --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_getstacksize.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize == NULL) + ret = EINVAL; + else { + /* Return the stack size: */ + *stacksize = (*attr)->stacksize_attr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_init.c b/lib/libc_r/uthread/uthread_attr_init.c new file mode 100644 index 00000000000..c64e29fed11 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_init.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_init(pthread_attr_t *attr) +{ + int ret; + pthread_attr_t pattr; + + /* Allocate memory for the attribute object: */ + if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) + /* Insufficient memory: */ + ret = ENOMEM; + else { + /* Initialise the attribute object with the defaults: */ + memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr)); + + /* Return a pointer to the attribute object: */ + *attr = pattr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c b/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c new file mode 100644 index 00000000000..afe6b23c3cb --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->suspend = PTHREAD_CREATE_SUSPENDED; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_setdetachstate.c b/lib/libc_r/uthread/uthread_attr_setdetachstate.c new file mode 100644 index 00000000000..6ec0dbc1c58 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_setdetachstate.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || + (detachstate != PTHREAD_CREATE_DETACHED && + detachstate != PTHREAD_CREATE_JOINABLE)) + ret = EINVAL; + else { + /* Check if detached state: */ + if (detachstate == PTHREAD_CREATE_DETACHED) + /* Set the detached flag: */ + (*attr)->flags |= PTHREAD_DETACHED; + else + /* Reset the detached flag: */ + (*attr)->flags &= ~PTHREAD_DETACHED; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_setprio.c b/lib/libc_r/uthread/uthread_attr_setprio.c new file mode 100644 index 00000000000..f6d54fcac16 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_setprio.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_setprio(pthread_attr_t *attr, int priority) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->prio = priority; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_setstackaddr.c b/lib/libc_r/uthread/uthread_attr_setstackaddr.c new file mode 100644 index 00000000000..ce54915d096 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_setstackaddr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + ret = EINVAL; + else { + /* Save the stack address: */ + (*attr)->stackaddr_attr = stackaddr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_setstacksize.c b/lib/libc_r/uthread/uthread_attr_setstacksize.c new file mode 100644 index 00000000000..94e575e0dde --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_setstacksize.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) + ret = EINVAL; + else { + /* Save the stack size: */ + (*attr)->stacksize_attr = stacksize; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_bind.c b/lib/libc_r/uthread/uthread_bind.c new file mode 100644 index 00000000000..11edfbbe3d8 --- /dev/null +++ b/lib/libc_r/uthread/uthread_bind.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + ret = _thread_sys_bind(fd, name, namelen); + _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 00000000000..9319f85efbe --- /dev/null +++ b/lib/libc_r/uthread/uthread_clean.c @@ -0,0 +1,68 @@ +/* + * 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" + +void +pthread_cleanup_push(void (*routine) (void *), void *routine_arg) +{ + struct pthread_cleanup *new; + + 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; + } +} + +void +pthread_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 00000000000..7e21853223e --- /dev/null +++ b/lib/libc_r/uthread/uthread_close.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1995-1998 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 <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +close(int fd) +{ + int flags; + int ret; + int status; + struct stat sb; + + /* Lock the file descriptor while the file is closed: */ + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + /* Get file descriptor status. */ + _thread_sys_fstat(fd, &sb); + + /* + * Check if the file should be left as blocking. + * + * This is so that the file descriptors shared with a parent + * process aren't left set to non-blocking if the child + * closes them prior to exit. An example where this causes + * problems with /bin/sh is when a child closes stdin. + * + * Setting a file as blocking causes problems if a threaded + * parent accesses the file descriptor before the child exits. + * Once the threaded parent receives a SIGCHLD then it resets + * all of its files to non-blocking, and so it is then safe + * to access them. + * + * Pipes are not set to blocking when they are closed, as + * the parent and child will normally close the file + * descriptor of the end of the pipe that they are not + * using, which would then cause any reads to block + * indefinitely. + */ + if ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0) { + /* Get the current flags: */ + flags = _thread_sys_fcntl(fd, F_GETFL, NULL); + /* Clear the nonblocking file descriptor flag: */ + _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + } + + /* Close the file descriptor: */ + ret = _thread_sys_close(fd); + + free(_thread_fd_table[fd]); + _thread_fd_table[fd] = NULL; + } + 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 00000000000..fae12ebb68b --- /dev/null +++ b/lib/libc_r/uthread/uthread_cond.c @@ -0,0 +1,350 @@ +/* + * 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> +#include <string.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; + pthread_cond_t pcond; + int rval = 0; + + if (cond == NULL) + rval = EINVAL; + else { + /* + * Check if a pointer to a condition variable attribute + * structure was passed by the caller: + */ + if (cond_attr != NULL && *cond_attr != NULL) { + /* Default to a fast condition variable: */ + type = (*cond_attr)->c_type; + } else { + /* Default to a fast condition variable: */ + type = COND_TYPE_FAST; + } + + /* 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: */ + rval = EINVAL; + break; + } + + /* Check for no errors: */ + if (rval == 0) { + if ((pcond = (pthread_cond_t) + malloc(sizeof(struct pthread_cond))) == NULL) { + rval = ENOMEM; + } else { + /* + * Initialise the condition variable + * structure: + */ + _thread_queue_init(&pcond->c_queue); + pcond->c_flags |= COND_FLAGS_INITED; + pcond->c_type = type; + memset(&pcond->lock,0,sizeof(pcond->lock)); + *cond = pcond; + } + } + } + /* Return the completion status: */ + return (rval); +} + +int +pthread_cond_destroy(pthread_cond_t * cond) +{ + int rval = 0; + + if (cond == NULL || *cond == NULL) + rval = EINVAL; + else { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* + * Free the memory allocated for the condition + * variable structure: + */ + free(*cond); + + /* + * NULL the caller's pointer now that the condition + * variable has been destroyed: + */ + *cond = NULL; + } + /* Return the completion status: */ + return (rval); +} + +int +pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) +{ + int rval = 0; + int status; + + if (cond == NULL) + rval = EINVAL; + + /* + * If the condition variable is statically initialized, + * perform the dynamic initialization: + */ + else if (*cond != NULL || + (rval = pthread_cond_init(cond,NULL)) == 0) { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* 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); + + /* Wait forever: */ + _thread_run->wakeup_time.tv_sec = -1; + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + + /* Schedule the next thread: */ + _thread_kern_sched_state(PS_COND_WAIT, + __FILE__, __LINE__); + + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* Lock the mutex: */ + rval = pthread_mutex_lock(mutex); + break; + + /* Trap invalid condition variable types: */ + default: + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + } + + /* 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; + + if (cond == NULL) + rval = EINVAL; + + /* + * If the condition variable is statically initialized, + * perform the dynamic initialization: + */ + else if (*cond != NULL || + (rval = pthread_cond_init(cond,NULL)) == 0) { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* 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.tv_sec = abstime->tv_sec; + _thread_run->wakeup_time.tv_nsec = abstime->tv_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 { + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + + /* Schedule the next thread: */ + _thread_kern_sched_state(PS_COND_WAIT, + __FILE__, __LINE__); + + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* 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: */ + rval = ETIMEDOUT; + } + } + break; + + /* Trap invalid condition variable types: */ + default: + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + } + + /* Return the completion status: */ + return (rval); +} + +int +pthread_cond_signal(pthread_cond_t * cond) +{ + int rval = 0; + int status; + pthread_t pthread; + + if (cond == NULL || *cond == NULL) + rval = EINVAL; + else { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* 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_NEW_STATE(pthread,PS_RUNNING); + } + break; + + /* Trap invalid condition variable types: */ + default: + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + } + + /* Return the completion status: */ + return (rval); +} + +int +pthread_cond_broadcast(pthread_cond_t * cond) +{ + int rval = 0; + int status; + pthread_t pthread; + + if (cond == NULL || *cond == NULL) + rval = EINVAL; + else { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* 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_NEW_STATE(pthread,PS_RUNNING); + } + break; + + /* Trap invalid condition variable types: */ + default: + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + } + + /* Return the completion status: */ + return (rval); +} +#endif diff --git a/lib/libc_r/uthread/uthread_condattr_destroy.c b/lib/libc_r/uthread/uthread_condattr_destroy.c new file mode 100644 index 00000000000..4179970ad9d --- /dev/null +++ b/lib/libc_r/uthread/uthread_condattr_destroy.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1997 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_condattr_destroy(pthread_condattr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + ret = EINVAL; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_condattr_init.c b/lib/libc_r/uthread/uthread_condattr_init.c new file mode 100644 index 00000000000..c87323dc197 --- /dev/null +++ b/lib/libc_r/uthread/uthread_condattr_init.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +pthread_condattr_init(pthread_condattr_t *attr) +{ + int ret; + pthread_condattr_t pattr; + + if ((pattr = (pthread_condattr_t) + malloc(sizeof(struct pthread_cond_attr))) == NULL) { + ret = ENOMEM; + } else { + memcpy(pattr, &pthread_condattr_default, + sizeof(struct pthread_cond_attr)); + *attr = pattr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_connect.c b/lib/libc_r/uthread/uthread_connect.c new file mode 100644 index 00000000000..37ed517ca4b --- /dev/null +++ b/lib/libc_r/uthread/uthread_connect.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $OpenBSD: uthread_connect.c,v 1.1 1998/08/27 09:00:58 d Exp $ + */ +#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 errnolen, ret, tmpnamelen; + + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 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 + */ + errnolen = sizeof(errno); + _thread_sys_getsockopt(fd, SOL_SOCKET, SO_ERROR, &errno, &errnolen); + } + } else { + ret = -1; + } + } + _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 00000000000..53759d8f440 --- /dev/null +++ b/lib/libc_r/uthread/uthread_create.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1995-1998 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 "thread_private.h" + +int +pthread_create(pthread_t * thread, const pthread_attr_t * attr, + void *(*start_routine) (void *), void *arg) +{ + int i; + int ret = 0; + int status; + pthread_t new_thread; + pthread_attr_t pattr; + void *stack; + + /* + * Locking functions in libc are required when there are + * threads other than the initial thread. + */ + __isthreaded = 1; + + /* 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 || *attr == NULL) { + /* Use the default thread attributes: */ + pattr = &pthread_attr_default; + } else { + pattr = *attr; + } + /* Check if a stack was specified in the thread attributes: */ + if ((stack = pattr->stackaddr_attr) != NULL) { + } + /* Allocate memory for the stack: */ + else if ((stack = (void *) malloc(pattr->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; + + /* + * Write a magic value to the thread structure + * to help identify valid ones: + */ + new_thread->magic = PTHREAD_MAGIC; + + if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { + PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED); + } else { + PTHREAD_NEW_STATE(new_thread,PS_RUNNING); + } + + /* Initialise the thread for signals: */ + new_thread->sigmask = _thread_run->sigmask; + + /* Initialise the jump buffer: */ + 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(). + */ + + _thread_machdep_thread_create(new_thread, _thread_start, pattr); + + /* Copy the thread attributes: */ + memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr)); + + /* + * 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->flags = 0; + + /* Lock the thread list: */ + _lock_thread_list(); + + /* Add the thread to the linked list of all threads: */ + new_thread->nxt = _thread_link_list; + _thread_link_list = new_thread; + + /* Unlock the thread list: */ + _unlock_thread_list(); + + /* Return a pointer to the thread structure: */ + (*thread) = new_thread; + + /* Schedule the new user thread: */ + _thread_kern_sched(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"); +} +#endif diff --git a/lib/libc_r/uthread/uthread_detach.c b/lib/libc_r/uthread/uthread_detach.c new file mode 100644 index 00000000000..da456bfbab9 --- /dev/null +++ b/lib/libc_r/uthread/uthread_detach.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_detach(pthread_t pthread) +{ + int rval = 0; + int status; + pthread_t next_thread; + + /* Check for invalid calling parameters: */ + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) + /* Return an invalid argument error: */ + rval = EINVAL; + + /* 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: */ + PTHREAD_NEW_STATE(next_thread,PS_RUNNING); + } + } else + /* Return an error: */ + rval = EINVAL; + + /* 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 00000000000..39d262d170b --- /dev/null +++ b/lib/libc_r/uthread/uthread_dup.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1995-1998 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 +dup(int fd) +{ + int ret; + + /* Lock the file descriptor: */ + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 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: */ + _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 00000000000..e9edddd35c1 --- /dev/null +++ b/lib/libc_r/uthread/uthread_dup2.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + /* Lock the file descriptor: */ + if ((ret = _FD_LOCK(newfd, FD_RDWR, NULL)) == 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: */ + _FD_UNLOCK(newfd, FD_RDWR); + } + /* Unlock the file descriptor: */ + _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 00000000000..99ffb5d8b7d --- /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 00000000000..5f40e1c560e --- /dev/null +++ b/lib/libc_r/uthread/uthread_execve.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1995-1998 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> +#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 flags; + int i; + int ret; + struct sigaction act; + struct sigaction oact; + struct itimerval itimer; + + /* Disable the interval timer: */ + itimer.it_interval.tv_sec = 0; + itimer.it_interval.tv_usec = 0; + itimer.it_value.tv_sec = 0; + itimer.it_value.tv_usec = 0; + setitimer(ITIMER_VIRTUAL, &itimer, NULL); + + /* Close the pthread kernel pipe: */ + _thread_sys_close(_thread_kern_pipe[0]); + _thread_sys_close(_thread_kern_pipe[1]); + + /* + * Enter a loop to set all file descriptors to blocking + * if they were not created as non-blocking: + */ + for (i = 0; i < _thread_dtablesize; i++) { + /* Check if this file descriptor is in use: */ + if (_thread_fd_table[i] != NULL && + !(_thread_fd_table[i]->flags & O_NONBLOCK)) { + /* Get the current flags: */ + flags = _thread_sys_fcntl(i, F_GETFL, NULL); + /* Clear the nonblocking file descriptor flag: */ + _thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK); + } + } + + /* 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 ignoring this signal: */ + if (_thread_sigact[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_sigact[i - 1].sa_mask; + act.sa_flags = _thread_sigact[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 00000000000..0083f2b0169 --- /dev/null +++ b/lib/libc_r/uthread/uthread_exit.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1995-1998 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> +#include <fcntl.h> +#include <string.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +void _exit(int status) +{ + int flags; + int i; + struct itimerval itimer; + + /* Disable the interval timer: */ + itimer.it_interval.tv_sec = 0; + itimer.it_interval.tv_usec = 0; + itimer.it_value.tv_sec = 0; + itimer.it_value.tv_usec = 0; + setitimer(ITIMER_VIRTUAL, &itimer, NULL); + + /* Close the pthread kernel pipe: */ + _thread_sys_close(_thread_kern_pipe[0]); + _thread_sys_close(_thread_kern_pipe[1]); + + /* + * Enter a loop to set all file descriptors to blocking + * if they were not created as non-blocking: + */ + for (i = 0; i < _thread_dtablesize; i++) { + /* Check if this file descriptor is in use: */ + if (_thread_fd_table[i] != NULL && + !(_thread_fd_table[i]->flags & O_NONBLOCK)) { + /* Get the current flags: */ + flags = _thread_sys_fcntl(i, F_GETFL, NULL); + /* Clear the nonblocking file descriptor flag: */ + _thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK); + } + } + + /* Call the _exit syscall: */ + _thread_sys__exit(status); +} + +void +_thread_exit(char *fname, int lineno, char *string) +{ + 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; + + /* Check if this thread is already in the process of exiting: */ + if ((_thread_run->flags & PTHREAD_EXITING) != 0) { + char msg[128]; + snprintf(msg,"Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",_thread_run); + PANIC(msg); + } + + /* Flag this thread as exiting: */ + _thread_run->flags |= PTHREAD_EXITING; + + /* Save the return value: */ + _thread_run->ret = status; + + while (_thread_run->cleanup != NULL) { + pthread_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_NEW_STATE(pthread,PS_RUNNING); + } + + /* Lock the thread list: */ + _lock_thread_list(); + + /* 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; + } + } + + /* Unlock the thread list: */ + _unlock_thread_list(); + + /* Lock the dead thread list: */ + _lock_dead_thread_list(); + + /* + * This thread will never run again. Add it to the list of dead + * threads: + */ + _thread_run->nxt = _thread_dead; + _thread_dead = _thread_run; + + /* Unlock the dead thread list: */ + _unlock_dead_thread_list(); + + /* + * 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 00000000000..2156eeeb355 --- /dev/null +++ b/lib/libc_r/uthread/uthread_fchmod.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { + ret = _thread_sys_fchmod(fd, mode); + _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 00000000000..ee3ca40d3b7 --- /dev/null +++ b/lib/libc_r/uthread/uthread_fchown.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { + ret = _thread_sys_fchown(fd, owner, group); + _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 00000000000..eecda60d8ae --- /dev/null +++ b/lib/libc_r/uthread/uthread_fcntl.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1995-1998 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 <unistd.h> +#include <fcntl.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +fcntl(int fd, int cmd,...) +{ + int flags = 0; + int nonblock; + int oldfd; + int ret; + int status; + va_list ap; + + /* Lock the file descriptor: */ + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 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: + flags = va_arg(ap, int); + ret = _thread_sys_fcntl(fd, cmd, flags); + break; + case F_GETFD: + ret = _thread_sys_fcntl(fd, cmd, 0); + break; + case F_GETFL: + ret = _thread_fd_table[fd]->flags; + break; + case F_SETFL: + /* + * Get the file descriptor flags passed by the + * caller: + */ + flags = va_arg(ap, int); + + /* + * Check if the user wants a non-blocking file + * descriptor: + */ + nonblock = flags & O_NONBLOCK; + + /* Set the file descriptor flags: */ + if ((ret = _thread_sys_fcntl(fd, cmd, flags | O_NONBLOCK)) != 0) { + + /* Get the flags so that we behave like the kernel: */ + } else if ((flags = _thread_sys_fcntl(fd, + F_GETFL, 0)) == -1) { + /* Error getting flags: */ + ret = -1; + + /* + * Check if the file descriptor is non-blocking + * with respect to the user: + */ + } else if (nonblock) + /* A non-blocking descriptor: */ + _thread_fd_table[fd]->flags = flags | O_NONBLOCK; + else + /* Save the flags: */ + _thread_fd_table[fd]->flags = flags & ~O_NONBLOCK; + 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: */ + _FD_UNLOCK(fd, FD_RDWR); + } + + /* 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 00000000000..1e4495e6ef9 --- /dev/null +++ b/lib/libc_r/uthread/uthread_fd.c @@ -0,0 +1,719 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $Id: uthread_fd.c,v 1.1 1998/08/27 09:01:01 d Exp $ + * $OpenBSD: uthread_fd.c,v 1.1 1998/08/27 09:01:01 d Exp $ + * + */ +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +/* Static variables: */ +static spinlock_t fd_table_lock = _SPINLOCK_INITIALIZER; + +/* + * This function *must* return -1 and set the thread specific errno + * as a system call. This is because the error return from this + * function is propagated directly back from thread-wrapped system + * calls. + */ + +int +_thread_fd_table_init(int fd) +{ + int ret = 0; + struct fd_table_entry *entry; + + /* Check if the file descriptor is out of range: */ + if (fd < 0 || fd >= _thread_dtablesize) { + /* Return a bad file descriptor error: */ + errno = EBADF; + ret = -1; + } + + /* + * Check if memory has already been allocated for this file + * descriptor: + */ + else if (_thread_fd_table[fd] != NULL) { + /* Memory has already been allocated. */ + + /* Allocate memory for the file descriptor table entry: */ + } else if ((entry = (struct fd_table_entry *) + malloc(sizeof(struct fd_table_entry))) == NULL) { + /* Return an insufficient memory error: */ + errno = ENOMEM; + ret = -1; + } else { + /* Initialise the file locks: */ + memset(&entry->lock, 0, sizeof(entry->lock)); + entry->r_owner = NULL; + entry->w_owner = NULL; + entry->r_fname = NULL; + entry->w_fname = NULL; + entry->r_lineno = 0;; + entry->w_lineno = 0;; + entry->r_lockcount = 0;; + entry->w_lockcount = 0;; + + /* Initialise the read/write queues: */ + _thread_queue_init(&entry->r_queue); + _thread_queue_init(&entry->w_queue); + + /* Get the flags for the file: */ + if (fd >= 3 && (entry->flags = + _thread_sys_fcntl(fd, F_GETFL, 0)) == -1) { + ret = -1; + } + else { + /* Check if a stdio descriptor: */ + if (fd < 3) + /* + * Use the stdio flags read by + * _pthread_init() to avoid + * mistaking the non-blocking + * flag that, when set on one + * stdio fd, is set on all stdio + * fds. + */ + entry->flags = _pthread_stdio_flags[fd]; + + /* + * Make the file descriptor non-blocking. + * This might fail if the device driver does + * not support non-blocking calls, or if the + * driver is naturally non-blocking. + */ + _thread_sys_fcntl(fd, F_SETFL, + entry->flags | O_NONBLOCK); + + /* Lock the file descriptor table: */ + _SPINLOCK(&fd_table_lock); + + /* + * Check if another thread allocated the + * file descriptor entry while this thread + * was doing the same thing. The table wasn't + * kept locked during this operation because + * it has the potential to recurse. + */ + if (_thread_fd_table[fd] == NULL) { + /* This thread wins: */ + _thread_fd_table[fd] = entry; + entry = NULL; + } + + /* Unlock the file descriptor table: */ + _SPINUNLOCK(&fd_table_lock); + } + + /* + * Check if another thread initialised the table entry + * before this one could: + */ + if (entry != NULL) + /* + * Throw away the table entry that this thread + * prepared. The other thread wins. + */ + free(entry); + } + + /* Return the completion status: */ + return (ret); +} + +void +_thread_fd_unlock(int fd, int lock_type) +{ + int ret; + + /* + * Check that the file descriptor table is initialised for this + * entry: + */ + if ((ret = _thread_fd_table_init(fd)) == 0) { + /* + * Lock the file descriptor table entry to prevent + * other threads for clashing with the current + * thread's accesses: + */ + _SPINLOCK(&_thread_fd_table[fd]->lock); + + /* 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: + */ + PTHREAD_NEW_STATE(_thread_fd_table[fd]->r_owner,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: + */ + PTHREAD_NEW_STATE(_thread_fd_table[fd]->w_owner,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; + } + } + } + + /* Unlock the file descriptor table entry: */ + _SPINUNLOCK(&_thread_fd_table[fd]->lock); + } + + /* Nothing to return. */ + return; +} + +int +_thread_fd_lock(int fd, int lock_type, struct timespec * timeout) +{ + int ret; + + /* + * Check that the file descriptor table is initialised for this + * entry: + */ + if ((ret = _thread_fd_table_init(fd)) == 0) { + /* + * Lock the file descriptor table entry to prevent + * other threads for clashing with the current + * thread's accesses: + */ + _SPINLOCK(&_thread_fd_table[fd]->lock); + + /* 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; + + /* Set the timeout: */ + _thread_kern_set_timeout(timeout); + + /* + * Unlock the file descriptor + * table entry: + */ + _SPINUNLOCK(&_thread_fd_table[fd]->lock); + + /* + * 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__); + + /* + * Lock the file descriptor + * table entry again: + */ + _SPINLOCK(&_thread_fd_table[fd]->lock); + + } 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; + } + } + + /* 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; + + /* Set the timeout: */ + _thread_kern_set_timeout(timeout); + + /* + * Unlock the file descriptor + * table entry: + */ + _SPINUNLOCK(&_thread_fd_table[fd]->lock); + + /* + * 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__); + + /* + * Lock the file descriptor + * table entry again: + */ + _SPINLOCK(&_thread_fd_table[fd]->lock); + } 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; + } + } + + /* Increment the write lock count: */ + _thread_fd_table[fd]->w_lockcount++; + } + + /* Unlock the file descriptor table entry: */ + _SPINUNLOCK(&_thread_fd_table[fd]->lock); + } + + /* Return the completion status: */ + return (ret); +} + +void +_thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) +{ + int ret; + + /* + * Check that the file descriptor table is initialised for this + * entry: + */ + if ((ret = _thread_fd_table_init(fd)) == 0) { + /* + * Lock the file descriptor table entry to prevent + * other threads for clashing with the current + * thread's accesses: + */ + _spinlock_debug(&_thread_fd_table[fd]->lock, fname, lineno); + + /* 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: + */ + PTHREAD_NEW_STATE(_thread_fd_table[fd]->r_owner,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: + */ + PTHREAD_NEW_STATE(_thread_fd_table[fd]->w_owner,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; + } + } + } + + /* Unlock the file descriptor table entry: */ + _SPINUNLOCK(&_thread_fd_table[fd]->lock); + } + + /* Nothing to return. */ + return; +} + +int +_thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout, + char *fname, int lineno) +{ + int ret; + + /* + * Check that the file descriptor table is initialised for this + * entry: + */ + if ((ret = _thread_fd_table_init(fd)) == 0) { + /* + * Lock the file descriptor table entry to prevent + * other threads for clashing with the current + * thread's accesses: + */ + _spinlock_debug(&_thread_fd_table[fd]->lock, fname, lineno); + + /* 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); + + /* + * Unlock the file descriptor + * table entry: + */ + _SPINUNLOCK(&_thread_fd_table[fd]->lock); + + /* + * 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__); + + /* + * Lock the file descriptor + * table entry again: + */ + _SPINLOCK(&_thread_fd_table[fd]->lock); + + } 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); + + /* + * Unlock the file descriptor + * table entry: + */ + _SPINUNLOCK(&_thread_fd_table[fd]->lock); + + /* + * 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__); + + /* + * Lock the file descriptor + * table entry again: + */ + _SPINLOCK(&_thread_fd_table[fd]->lock); + } 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++; + } + + /* Unlock the file descriptor table entry: */ + _SPINUNLOCK(&_thread_fd_table[fd]->lock); + } + + /* 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 00000000000..71fecfea217 --- /dev/null +++ b/lib/libc_r/uthread/uthread_file.c @@ -0,0 +1,367 @@ +/* + * 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. + * + * $Id: uthread_file.c,v 1.1 1998/08/27 09:01:02 d Exp $ + * $OpenBSD: uthread_file.c,v 1.1 1998/08/27 09:01:02 d Exp $ + * + * POSIX stdio FILE locking functions. These assume that the locking + * is only required at FILE structure level, not at file descriptor + * level too. + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/queue.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +/* + * Weak symbols for externally visible functions in this file: + */ +#pragma weak flockfile=_flockfile +#pragma weak ftrylockfile=_ftrylockfile +#pragma weak funlockfile=_funlockfile + +/* + * The FILE lock structure. The FILE *fp is locked if the owner is + * not NULL. If not locked, the file lock structure can be + * reassigned to a different file by setting fp. + */ +struct file_lock { + LIST_ENTRY(file_lock) entry; /* Entry if file list. */ + TAILQ_HEAD(lock_head, pthread) + l_head; /* Head of queue for threads */ + /* waiting on this lock. */ + FILE *fp; /* The target file. */ + pthread_t owner; /* Thread that owns lock. */ + int count; /* Lock count for owner. */ +}; + +/* + * The number of file lock lists into which the file pointer is + * hashed. Ideally, the FILE structure size would have been increased, + * but this causes incompatibility, so separate data structures are + * required. + */ +#define NUM_HEADS 128 + +/* + * This macro casts a file pointer to a long integer and right + * shifts this by the number of bytes in a pointer. The shifted + * value is then remaindered using the maximum number of hash + * entries to produce and index into the array of static lock + * structures. If there is a collision, a linear search of the + * dynamic list of locks linked to each static lock is perfomed. + */ +#define file_idx(_p) ((((long) _p) >> sizeof(void *)) % NUM_HEADS) + +/* + * Global array of file locks. The first lock for each hash bucket is + * allocated statically in the hope that there won't be too many + * collisions that require a malloc and an element added to the list. + */ +struct static_file_lock { + LIST_HEAD(file_list_head, file_lock) head; + struct file_lock fl; +} flh[NUM_HEADS]; + +/* Set to non-zero when initialisation is complete: */ +static int init_done = 0; + +/* Lock for accesses to the hash table: */ +static spinlock_t hash_lock = _SPINLOCK_INITIALIZER; + +/* + * Find a lock structure for a FILE, return NULL if the file is + * not locked: + */ +static +struct file_lock * +find_lock(int idx, FILE *fp) +{ + struct file_lock *p; + + /* Check if the file is locked using the static structure: */ + if (flh[idx].fl.fp == fp && flh[idx].fl.owner != NULL) + /* Return a pointer to the static lock: */ + p = &flh[idx].fl; + else { + /* Point to the first dynamic lock: */ + p = flh[idx].head.lh_first; + + /* + * Loop through the dynamic locks looking for the + * target file: + */ + while (p != NULL && p->fp != fp && p->owner != NULL) + /* Not this file, try the next: */ + p = p->entry.le_next; + } + return(p); +} + +/* + * Lock a file, assuming that there is no lock structure currently + * assigned to it. + */ +static +struct file_lock * +do_lock(int idx, FILE *fp) +{ + struct file_lock *p; + + /* Check if the static structure is not being used: */ + if (flh[idx].fl.owner == NULL) { + /* Return a pointer to the static lock: */ + p = &flh[idx].fl; + } + else { + /* Point to the first dynamic lock: */ + p = flh[idx].head.lh_first; + + /* + * Loop through the dynamic locks looking for a + * lock structure that is not being used: + */ + while (p != NULL && p->owner != NULL) + /* This one is used, try the next: */ + p = p->entry.le_next; + } + + /* + * If an existing lock structure has not been found, + * allocate memory for a new one: + */ + if (p == NULL && (p = (struct file_lock *) + malloc(sizeof(struct file_lock))) != NULL) { + /* Add the new element to the list: */ + LIST_INSERT_HEAD(&flh[idx].head, p, entry); + } + + /* Check if there is a lock structure to acquire: */ + if (p != NULL) { + /* Acquire the lock for the running thread: */ + p->fp = fp; + p->owner = _thread_run; + p->count = 1; + TAILQ_INIT(&p->l_head); + } + return(p); +} + +void +_flockfile_debug(FILE * fp, char *fname, int lineno) +{ + int fd, flags; + int status; + int idx = file_idx(fp); + struct file_lock *p; + + /* Check if this is a real file: */ + if (fp->_file >= 0) { + /* Lock the hash table: */ + _SPINLOCK(&hash_lock); + + /* Check if the static array has not been initialised: */ + if (!init_done) { + /* Initialise the global array: */ + memset(flh,0,sizeof(flh)); + + /* Flag the initialisation as complete: */ + init_done = 1; + } + + /* Get a pointer to any existing lock for the file: */ + if ((p = find_lock(idx, fp)) == NULL) { + /* + * The file is not locked, so this thread can + * grab the lock: + */ + p = do_lock(idx, fp); + + /* Unlock the hash table: */ + _SPINUNLOCK(&hash_lock); + + /* + * The file is already locked, so check if the + * running thread is the owner: + */ + } else if (p->owner == _thread_run) { + /* + * The running thread is already the + * owner, so increment the count of + * the number of times it has locked + * the file: + */ + p->count++; + + /* Unlock the hash table: */ + _SPINUNLOCK(&hash_lock); + } else { + /* + * The file is locked for another thread. + * Append this thread to the queue of + * threads waiting on the lock. + */ + TAILQ_INSERT_TAIL(&p->l_head,_thread_run,qe); + + /* Unlock the hash table: */ + _SPINUNLOCK(&hash_lock); + + /* Wait on the FILE lock: */ + _thread_kern_sched_state(PS_FILE_WAIT, fname, lineno); + } + } + return; +} + +void +_flockfile(FILE * fp) +{ + _flockfile_debug(fp, __FILE__, __LINE__); + return; +} + +int +_ftrylockfile(FILE * fp) +{ + int ret = -1; + int status; + int idx = file_idx(fp); + struct file_lock *p; + + /* Check if this is a real file: */ + if (fp->_file >= 0) { + /* Lock the hash table: */ + _SPINLOCK(&hash_lock); + + /* Get a pointer to any existing lock for the file: */ + if ((p = find_lock(idx, fp)) == NULL) { + /* + * The file is not locked, so this thread can + * grab the lock: + */ + p = do_lock(idx, fp); + + /* + * The file is already locked, so check if the + * running thread is the owner: + */ + } else if (p->owner == _thread_run) { + /* + * The running thread is already the + * owner, so increment the count of + * the number of times it has locked + * the file: + */ + p->count++; + } else { + /* + * The file is locked for another thread, + * so this try fails. + */ + p = NULL; + } + + /* Check if the lock was obtained: */ + if (p != NULL) + /* Return success: */ + ret = 0; + + /* Unlock the hash table: */ + _SPINUNLOCK(&hash_lock); + + } + return (ret); +} + +void +_funlockfile(FILE * fp) +{ + int status; + int idx = file_idx(fp); + struct file_lock *p; + + /* Check if this is a real file: */ + if (fp->_file >= 0) { + /* Lock the hash table: */ + _SPINLOCK(&hash_lock); + + /* + * Get a pointer to the lock for the file and check that + * the running thread is the one with the lock: + */ + if ((p = find_lock(idx, fp)) != NULL && + p->owner == _thread_run) { + /* + * Check if this thread has locked the FILE + * more than once: + */ + if (p->count > 1) + /* + * Decrement the count of the number of + * times the running thread has locked this + * file: + */ + p->count--; + else { + /* + * The running thread will release the + * lock now: + */ + p->count = 0; + + /* Get the new owner of the lock: */ + if ((p->owner = TAILQ_FIRST(&p->l_head)) != NULL) { + /* Pop the thread off the queue: */ + TAILQ_REMOVE(&p->l_head,p->owner,qe); + + /* + * This is the first lock for the new + * owner: + */ + p->count = 1; + + /* Allow the new owner to run: */ + PTHREAD_NEW_STATE(p->owner,PS_RUNNING); + } + } + } + + /* Unlock the hash table: */ + _SPINUNLOCK(&hash_lock); + } + return; +} + +#endif diff --git a/lib/libc_r/uthread/uthread_find_thread.c b/lib/libc_r/uthread/uthread_find_thread.c new file mode 100644 index 00000000000..99e302306d2 --- /dev/null +++ b/lib/libc_r/uthread/uthread_find_thread.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1998 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" + +/* Find a thread in the linked list of active threads: */ +int +_find_thread(pthread_t pthread) +{ + pthread_t pthread1; + + /* Check if the caller has specified an invalid thread: */ + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) + /* Invalid thread: */ + return(EINVAL); + + /* Lock the thread list: */ + _lock_thread_list(); + + /* Point to the first thread in the list: */ + pthread1 = _thread_link_list; + + /* Search for the thread to join to: */ + while (pthread1 != NULL && pthread1 != pthread) { + /* Point to the next thread: */ + pthread1 = pthread1->nxt; + } + + /* Unlock the thread list: */ + _unlock_thread_list(); + + /* Return zero if the thread exists: */ + return ((pthread1 != NULL) ? 0:ESRCH); +} + +/* Find a thread in the linked list of dead threads: */ +int +_find_dead_thread(pthread_t pthread) +{ + pthread_t pthread1; + + /* Check if the caller has specified an invalid thread: */ + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) + /* Invalid thread: */ + return(EINVAL); + + /* Lock the dead thread list: */ + _lock_dead_thread_list(); + + /* Point to the first thread in the list: */ + pthread1 = _thread_dead; + + /* Search for the thread to join to: */ + while (pthread1 != NULL && pthread1 != pthread) { + /* Point to the next thread: */ + pthread1 = pthread1->nxt; + } + + /* Unlock the dead thread list: */ + _unlock_dead_thread_list(); + + /* Return zero if the thread exists: */ + return ((pthread1 != NULL) ? 0:ESRCH); +} +#endif diff --git a/lib/libc_r/uthread/uthread_flock.c b/lib/libc_r/uthread/uthread_flock.c new file mode 100644 index 00000000000..de5b61d91a9 --- /dev/null +++ b/lib/libc_r/uthread/uthread_flock.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + ret = _thread_sys_flock(fd, operation); + _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 00000000000..b62990a1a50 --- /dev/null +++ b/lib/libc_r/uthread/uthread_fork.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1995-1998 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> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +pid_t +fork(void) +{ + int flags; + int status; + pid_t ret; + pthread_t pthread; + pthread_t pthread_next; + + /* Lock the thread list: */ + _lock_thread_list(); + + /* 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: */ + _thread_run->sigpend = 0; + + /* + * 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(); + } else { + /* Point to the first thread in the list: */ + pthread = _thread_link_list; + + /* + * Enter a loop to remove all threads other than + * the running thread from the thread list: + */ + while (pthread != NULL) { + pthread_next = pthread->nxt; + if (pthread == _thread_run) { + _thread_link_list = pthread; + pthread->nxt = NULL; + } else { + if (pthread->attr.stackaddr_attr == + NULL && pthread->stack != NULL) { + /* + * Free the stack of the + * dead thread: + */ + free(pthread->stack); + } + if (pthread->specific_data != NULL) + free(pthread->specific_data); + free(pthread); + } + + /* Point to the next thread: */ + pthread = pthread_next; + } + } + } + + /* Unock the thread list: */ + _unlock_thread_list(); + + /* 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 00000000000..20dac73fd72 --- /dev/null +++ b/lib/libc_r/uthread/uthread_fstat.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + /* Get the file status: */ + ret = _thread_sys_fstat(fd, buf); + /* Unlock the file descriptor: */ + _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 00000000000..f236fef967d --- /dev/null +++ b/lib/libc_r/uthread/uthread_fstatfs.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + /* Get the file system status: */ + ret = _thread_sys_fstatfs(fd, buf); + /* Unlock the file descriptor: */ + _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 00000000000..9141d47119e --- /dev/null +++ b/lib/libc_r/uthread/uthread_fsync.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + ret = _thread_sys_fsync(fd); + _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 00000000000..44e7520dce2 --- /dev/null +++ b/lib/libc_r/uthread/uthread_getdirentries.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + ret = _thread_sys_getdirentries(fd, buf, nbytes, basep); + _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 00000000000..7b2cd03eb17 --- /dev/null +++ b/lib/libc_r/uthread/uthread_getpeername.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + ret = _thread_sys_getpeername(fd, peer, paddrlen); + _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 00000000000..708b8f1adf7 --- /dev/null +++ b/lib/libc_r/uthread/uthread_getprio.c @@ -0,0 +1,56 @@ +/* + * 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 ret; + + /* Find the thread in the list of active threads: */ + if ((ret = _find_thread(pthread)) == 0) + /* Get the thread priority: */ + ret = pthread->pthread_priority; + else { + /* Invalid thread: */ + errno = ret; + ret = -1; + } + + /* Return the thread priority or an error status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_getsockname.c b/lib/libc_r/uthread/uthread_getsockname.c new file mode 100644 index 00000000000..0b40fc585d8 --- /dev/null +++ b/lib/libc_r/uthread/uthread_getsockname.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(s, FD_READ, NULL)) == 0) { + ret = _thread_sys_getsockname(s, name, namelen); + _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 00000000000..fe3478b1015 --- /dev/null +++ b/lib/libc_r/uthread/uthread_getsockopt.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + ret = _thread_sys_getsockopt(fd, level, optname, optval, optlen); + _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 00000000000..bd829e8be55 --- /dev/null +++ b/lib/libc_r/uthread/uthread_info.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 1995-1998 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 , "Waiting for write"}, + {PS_FILE_WAIT , "Waiting for FILE lock"}, + {PS_SELECT_WAIT , "Waiting on select"}, + {PS_SLEEP_WAIT , "Sleeping"}, + {PS_WAIT_WAIT , "Waiting process"}, + {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 either the controlling tty or the dump file */ + + fd = _thread_sys_open(_PATH_TTY, O_WRONLY | O_APPEND); + if (fd < 0) + fd = _thread_sys_open(INFO_DUMP_FILE, + O_WRONLY | O_APPEND | O_CREAT, 0666); + if (fd >= 0) { + /* 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 (%s) prio %3d state %s [%s:%d]\n", + pthread, (pthread->name == NULL) ? "":pthread->name, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); + _thread_sys_write(fd, s, strlen(s)); + + /* Check if this is the running thread: */ + 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: + case PS_FDLW_WAIT: + case PS_FDR_WAIT: + case PS_FDW_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; + case PS_SIGWAIT: + sprintf(s, "sigmask 0x%08lx\n", (unsigned long)pthread->sigmask); + _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 [%s:%d]\n", pthread, pthread->pthread_priority,pthread->fname,pthread->lineno); + _thread_sys_write(fd, s, strlen(s)); + } + } + + /* Output a header for file descriptors: */ + snprintf(s, sizeof(s), "\n\n=============\nFILE DESCRIPTOR TABLE (table size %d)\n\n",_thread_dtablesize); + _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; +} + +/* Set the thread name for debug: */ +void +pthread_set_name_np(pthread_t thread, char *name) +{ + /* Check if the caller has specified a valid thread: */ + if (thread != NULL && thread->magic == PTHREAD_MAGIC) + thread->name = strdup(name); + return; +} +#endif diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c new file mode 100644 index 00000000000..40922f5b64b --- /dev/null +++ b/lib/libc_r/uthread/uthread_init.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 1995-1998 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> +#include <paths.h> +#include <sys/param.h> +#include <signal.h> +#ifdef _THREAD_SAFE +#include <machine/reg.h> +#include <pthread.h> +#include "pthread_private.h" + +/* Allocate space for global thread variables here: */ + +struct pthread _thread_kern_thread; +struct pthread * volatile _thread_run = &_thread_kern_thread; +struct pthread * volatile _thread_single = NULL; +struct pthread * volatile _thread_link_list = NULL; +int _thread_kern_pipe[2] = { -1, -1 }; +int _thread_kern_in_select = 0; +int _thread_kern_in_sched = 0; +struct timeval kern_inc_prio_time = { 0, 0 }; +struct pthread * volatile _thread_dead = NULL; +struct pthread * _thread_initial = NULL; +struct pthread_attr pthread_attr_default = { + SCHED_RR, /* schedparam_policy */ + PTHREAD_DEFAULT_PRIORITY, /* prio */ + PTHREAD_CREATE_RUNNING, /* suspend */ + PTHREAD_CREATE_JOINABLE, /* flags */ + NULL, /* arg_attr */ + NULL, /* cleanup_attr */ + NULL, /* stackaddr_attr */ + PTHREAD_STACK_DEFAULT /* stacksize_attr */ +}; +struct pthread_mutex_attr pthread_mutexattr_default = { + MUTEX_TYPE_FAST, /* m_type */ + 0 /* m_flags */ +}; +struct pthread_cond_attr pthread_condattr_default = { + COND_TYPE_FAST, /* c_type */ + 0 /* c_flags */ +}; +int _pthread_stdio_flags[3]; +struct fd_table_entry ** _thread_fd_table = NULL; +int _thread_dtablesize = NOFILE_MAX; +struct sigaction _thread_sigact[NSIG]; + +#ifdef GCC_2_8_MADE_THREAD_AWARE +/* see src/gnu/usr.bin/gcc/libgcc2.c */ +typedef void *** (*dynamic_handler_allocator)(); +extern void __set_dynamic_handler_allocator(dynamic_handler_allocator); + +static pthread_key_t except_head_key; + +typedef struct { + void **__dynamic_handler_chain; + void *top_elt[2]; +} except_struct; + +static void ***dynamic_allocator_handler_fn() +{ + except_struct *dh = (except_struct *)pthread_getspecific(except_head_key); + + if(dh == NULL) { + dh = (except_struct *)malloc( sizeof(except_struct) ); + memset(dh, '\0', sizeof(except_struct)); + dh->__dynamic_handler_chain= dh->top_elt; + pthread_setspecific(except_head_key, (void *)dh); + } + return &dh->__dynamic_handler_chain; +} +#endif /* GCC_2_8_MADE_THREAD_AWARE */ + +/* + * Threaded process initialization + */ +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. */ + return; + +#ifdef __FreeBSD__ + /* + * Check for the special case of this process running as + * or in place of init as pid = 1: + */ + if (getpid() == 1) { + int fd; + /* + * Setup a new session for this process which is + * assumed to be running as root. + */ + if (setsid() == -1) + PANIC("Can't set session ID"); + if (revoke(_PATH_CONSOLE) != 0) + PANIC("Can't revoke console"); + if ((fd = _thread_sys_open(_PATH_CONSOLE, O_RDWR)) < 0) + PANIC("Can't open console"); + if (setlogin("root") == -1) + PANIC("Can't set login to root"); + if (_thread_sys_ioctl(fd,TIOCSCTTY, (char *) NULL) == -1) + PANIC("Can't set controlling terminal"); + if (_thread_sys_dup2(fd,0) == -1 || + _thread_sys_dup2(fd,1) == -1 || + _thread_sys_dup2(fd,2) == -1) + PANIC("Can't dup2"); + } +#endif __FreeBSD__ + + /* Get the standard I/O flags before messing with them : */ + for (i = 0; i < 3; i++) + if ((_pthread_stdio_flags[i] = + _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) + PANIC("Cannot get stdio flags"); + + /* + * Create a pipe that is written to by the signal handler to prevent + * signals being missed in calls to _select: + */ + 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->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; + + /* Initialise the global signal action structure: */ + sigfillset(&act.sa_mask); + act.sa_handler = (void (*) ()) _thread_sig_handler; + act.sa_flags = 0; + + /* 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, + &_thread_sigact[i - 1]) != 0) { + /* + * Abort this process if signal + * initialisation fails: + */ + PANIC("Cannot read signal handler info"); + } + } + + /* + * Install the signal handler for the most important + * signals that the user-thread kernel needs. Actually + * SIGINFO isn't really needed, but it is nice to have. + */ + if (_thread_sys_sigaction(SIGVTALRM, &act, NULL) != 0 || + _thread_sys_sigaction(SIGINFO , &act, NULL) != 0 || + _thread_sys_sigaction(SIGCHLD , &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; + } + } + } + +#ifdef GCC_2_8_MADE_THREAD_AWARE + /* Create the thread-specific data for the exception linked list. */ + if(pthread_key_create(&except_head_key, NULL) != 0) + PANIC("Failed to create thread specific execption head"); + + /* Setup the gcc exception handler per thread. */ + __set_dynamic_handler_allocator( dynamic_allocator_handler_fn ); +#endif /* GCC_2_8_MADE_THREAD_AWARE */ + + return; +} + +#if 0 +/* + * Special start up code for NetBSD/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 alpha_special_code + +#endif _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_ioctl.c b/lib/libc_r/uthread/uthread_ioctl.c new file mode 100644 index 00000000000..79f075a2aff --- /dev/null +++ b/lib/libc_r/uthread/uthread_ioctl.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1995-1998 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 <sys/fcntl.h> /* O_NONBLOCK*/ +#include <pthread.h> +#include "pthread_private.h" + +int +ioctl(int fd, unsigned long request,...) +{ + int ret; + int *op; + va_list ap; + + /* Lock the file descriptor: */ + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + /* Initialise the variable argument list: */ + va_start(ap, request); + + switch( request) { + case FIONBIO: + /* + * descriptors must be non-blocking; we are only + * twiddling the flag based on the request + */ + op = va_arg(ap, int *); + _thread_fd_table[fd]->flags &= ~O_NONBLOCK; + _thread_fd_table[fd]->flags |= ((*op) ? O_NONBLOCK : 0); + ret = 0; + break; + default: + ret = _thread_sys_ioctl(fd, request, va_arg(ap, char *)); + break; + } + + /* Free variable arguments: */ + va_end(ap); + + /* Unlock the file descriptor: */ + _FD_UNLOCK(fd, FD_RDWR); + } + + /* Return the completion status: */ + 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 00000000000..2043b76f5d2 --- /dev/null +++ b/lib/libc_r/uthread/uthread_join.c @@ -0,0 +1,98 @@ +/* + * 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 ret = 0; + pthread_t pthread1 = NULL; + + /* Check if the caller has specified an invalid thread: */ + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) + /* Invalid thread: */ + return(EINVAL); + + /* Check if the caller has specified itself: */ + if (pthread == _thread_run) + /* Avoid a deadlock condition: */ + return(EDEADLK); + + /* + * Find the thread in the list of active threads or in the + * list of dead threads: + */ + if (_find_thread(pthread) == 0 || + _find_dead_thread(pthread) == 0) + pthread1 = pthread; + + if (pthread1 == NULL) + /* Return an error: */ + ret = ESRCH; + + /* Check if this thread has been detached: */ + else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) + /* Return an error: */ + ret = ESRCH; + + /* 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__); + + /* 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: */ + ret = ESRCH; + + /* Check if the return value is required: */ + } else if (thread_return != NULL) + /* Return the thread's return value: */ + *thread_return = pthread->ret; + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_kern.c b/lib/libc_r/uthread/uthread_kern.c new file mode 100644 index 00000000000..9a0f7828f7e --- /dev/null +++ b/lib/libc_r/uthread/uthread_kern.c @@ -0,0 +1,1372 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $Id: uthread_kern.c,v 1.1 1998/08/27 09:01:08 d Exp $ + * $OpenBSD: uthread_kern.c,v 1.1 1998/08/27 09:01:08 d Exp $ + * + */ +#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 function prototype definitions: */ +static void +_thread_kern_select(int wait_reqd); + +void +_thread_kern_sched(struct sigcontext * scp) +{ + 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; + + /* + * Flag the pthread kernel as executing scheduler code + * to avoid a scheduler signal from interrupting this + * execution and calling the scheduler again. + */ + _thread_kern_in_sched = 1; + + /* 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)); + + /* Save the floating point data: */ + _thread_machdep_save_float_state(_thread_run); + + /* Flag the signal context as the last state saved: */ + _thread_run->sig_saved = 1; + } + /* Save the state of the current thread: */ + else if (setjmp(_thread_run->saved_jmp_buf) != 0) { + /* + * This point is reached when a longjmp() is called to + * restore the state of a thread. + * + * This is the normal way out of the scheduler. + */ + _thread_kern_in_sched = 0; + + /* + * There might be pending signals for this thread, so + * dispatch any that aren't blocked: + */ + _dispatch_signals(); + return; + } else { + /* Flag the jump buffer was the last state saved: */ + _thread_run->sig_saved = 0; + } + + /* Save errno. */ + _thread_run->error = errno; + + /* 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: + */ + else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) { + /* 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: + */ + 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.tv_sec == -1) { + } + /* + * Check if this thread is to wakeup + * immediately or if it is past its wakeup + * time: + */ + else if ((pthread->wakeup_time.tv_sec == 0 && + pthread->wakeup_time.tv_nsec == 0) || + (ts.tv_sec > pthread->wakeup_time.tv_sec) || + ((ts.tv_sec == pthread->wakeup_time.tv_sec) && + (ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) { + /* + * 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_NEW_STATE(pthread,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 that is ready to run: + */ + 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.tv_sec == -1) { + } + /* + * Check if this thread is to + * wakeup immediately: + */ + else if (pthread->wakeup_time.tv_sec == 0 && + pthread->wakeup_time.tv_nsec == 0) { + } + /* + * Check if the current time + * is after the wakeup time: + */ + else if ((ts.tv_sec > pthread->wakeup_time.tv_sec) || + ((ts.tv_sec == pthread->wakeup_time.tv_sec) && + (ts.tv_nsec > pthread->wakeup_time.tv_nsec))) { + } else { + /* + * Calculate the time + * until this thread + * is ready, allowing + * for the clock + * resolution: + */ + ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec; + ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec + + CLOCK_RES_NSEC; + + /* + * Check for + * underflow of the + * nanosecond field: + */ + if (ts1.tv_nsec < 0) { + /* + * Allow for + * the + * underflow + * of the + * nanosecond + * field: + */ + ts1.tv_sec--; + ts1.tv_nsec += 1000000000; + } + /* + * Check for overflow + * of the nanosecond + * field: + */ + if (ts1.tv_nsec >= 1000000000) { + /* + * Allow for + * the + * overflow + * of the + * nanosecond + * field: + */ + ts1.tv_sec++; + ts1.tv_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"); + } + } + /* Restore errno. */ + errno = _thread_run->error; + /* Check if a signal context was saved: */ + if (_thread_run->sig_saved == 1) { + + /* Restore the floating point state: */ + _thread_machdep_restore_float_state(_thread_run); + /* + * 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): + */ + 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); +} + +void +_thread_kern_sched_state(enum pthread_state state, char *fname, int lineno) +{ + /* Change the state of the current thread: */ + _thread_run->state = state; + _thread_run->fname = fname; + _thread_run->lineno = lineno; + + /* 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_FILE_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.tv_sec == -1) { + } + /* Check if this thread doesn't want to wait at all: */ + else if (pthread->wakeup_time.tv_sec == 0 && + pthread->wakeup_time.tv_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.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec; + ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec + + CLOCK_RES_NSEC; + + /* + * Check for underflow of the nanosecond + * field: + */ + if (ts1.tv_nsec < 0) { + /* + * Allow for the underflow of the + * nanosecond field: + */ + ts1.tv_sec--; + ts1.tv_nsec += 1000000000; + } + /* + * Check for overflow of the nanosecond + * field: + */ + if (ts1.tv_nsec >= 1000000000) { + /* + * Allow for the overflow of the + * nanosecond field: + */ + ts1.tv_sec++; + ts1.tv_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; + + /* + * 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); + + /* 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 _select call + * to complete if the signal occurred between + * the time when signals were unblocked and + * the _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 _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 any file descriptors are ready: + */ + if (count > 0) { + /* + * Enter a loop to look for threads waiting on file + * descriptors that are flagged as available by the + * _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_FILE_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.tv_sec = -1; + _thread_run->wakeup_time.tv_nsec = -1; + } + /* Check if no waiting is required: */ + else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) { + /* Set the wake up time to 'immediately': */ + _thread_run->wakeup_time.tv_sec = 0; + _thread_run->wakeup_time.tv_nsec = 0; + } else { + /* Get the current time: */ + gettimeofday(&tv, NULL); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); + + /* Calculate the time for the current thread to wake up: */ + _thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec; + _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec; + + /* Check if the nanosecond field needs to wrap: */ + if (_thread_run->wakeup_time.tv_nsec >= 1000000000) { + /* Wrap the nanosecond field: */ + _thread_run->wakeup_time.tv_sec += 1; + _thread_run->wakeup_time.tv_nsec -= 1000000000; + } + } + return; +} +#endif diff --git a/lib/libc_r/uthread/uthread_kill.c b/lib/libc_r/uthread/uthread_kill.c new file mode 100644 index 00000000000..98b3a2d39b9 --- /dev/null +++ b/lib/libc_r/uthread/uthread_kill.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1997 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 <signal.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +pthread_kill(pthread_t pthread, int sig) +{ + int ret; + + /* Check for invalid signal numbers: */ + if (sig < 0 || sig >= NSIG) + /* Invalid signal: */ + ret = EINVAL; + + /* Find the thread in the list of active threads: */ + else if ((ret = _find_thread(pthread)) == 0) { + if ((pthread->state == PS_SIGWAIT) && + sigismember(&pthread->sigmask, sig)) { + /* Change the state of the thread to run: */ + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + + /* Return the signal number: */ + pthread->signo = sig; + } else + /* Increment the pending signal count: */ + sigaddset(&pthread->sigpend,sig); + } + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_listen.c b/lib/libc_r/uthread/uthread_listen.c new file mode 100644 index 00000000000..58d96dcbe44 --- /dev/null +++ b/lib/libc_r/uthread/uthread_listen.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + ret = _thread_sys_listen(fd, backlog); + _FD_UNLOCK(fd, FD_RDWR); + } + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_mattr_init.c b/lib/libc_r/uthread/uthread_mattr_init.c new file mode 100644 index 00000000000..73226a6b471 --- /dev/null +++ b/lib/libc_r/uthread/uthread_mattr_init.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1996 Jeffrey Hsu <hsu@freebsd.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + int ret; + pthread_mutexattr_t pattr; + + if ((pattr = (pthread_mutexattr_t) + malloc(sizeof(struct pthread_mutex_attr))) == NULL) { + ret = ENOMEM; + } else { + memcpy(pattr, &pthread_mutexattr_default, + sizeof(struct pthread_mutex_attr)); + *attr = pattr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_mattr_kind_np.c b/lib/libc_r/uthread/uthread_mattr_kind_np.c new file mode 100644 index 00000000000..3eeabff038a --- /dev/null +++ b/lib/libc_r/uthread/uthread_mattr_kind_np.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1996 Jeffrey Hsu <hsu@freebsd.org>. + * 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_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->m_type = kind; + ret = 0; + } + return(ret); +} + +int +pthread_mutexattr_getkind_np(pthread_mutexattr_t attr) +{ + int ret; + if (attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + ret = attr->m_type; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_multi_np.c b/lib/libc_r/uthread/uthread_multi_np.c new file mode 100644 index 00000000000..64f360fdacf --- /dev/null +++ b/lib/libc_r/uthread/uthread_multi_np.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <string.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_multi_np() +{ + /* Return to multi-threaded scheduling mode: */ + _thread_single = NULL; + return(0); +} +#endif diff --git a/lib/libc_r/uthread/uthread_mutex.c b/lib/libc_r/uthread/uthread_mutex.c new file mode 100644 index 00000000000..4f4aa8af041 --- /dev/null +++ b/lib/libc_r/uthread/uthread_mutex.c @@ -0,0 +1,389 @@ +/* + * 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> +#include <string.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +static spinlock_t static_init_lock = _SPINLOCK_INITIALIZER; + +int +pthread_mutex_init(pthread_mutex_t * mutex, + const pthread_mutexattr_t * mutex_attr) +{ + enum pthread_mutextype type; + pthread_mutex_t pmutex; + int ret = 0; + + if (mutex == NULL) { + ret = EINVAL; + } else { + /* Check if default mutex attributes: */ + if (mutex_attr == NULL || *mutex_attr == NULL) + /* Default to a fast mutex: */ + type = MUTEX_TYPE_FAST; + + else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) + /* Return an invalid argument error: */ + ret = EINVAL; + else + /* Use the requested mutex type: */ + type = (*mutex_attr)->m_type; + + /* Check no errors so far: */ + if (ret == 0) { + if ((pmutex = (pthread_mutex_t) + malloc(sizeof(struct pthread_mutex))) == NULL) + ret = ENOMEM; + else { + /* Reset the mutex flags: */ + pmutex->m_flags = 0; + + /* Process according to mutex type: */ + switch (type) { + /* Fast mutex: */ + case MUTEX_TYPE_FAST: + /* Nothing to do here. */ + break; + + /* Counting mutex: */ + case MUTEX_TYPE_COUNTING_FAST: + /* Reset the mutex count: */ + pmutex->m_data.m_count = 0; + break; + + /* Trap invalid mutex types: */ + default: + /* Return an invalid argument error: */ + ret = EINVAL; + break; + } + if (ret == 0) { + /* Initialise the rest of the mutex: */ + _thread_queue_init(&pmutex->m_queue); + pmutex->m_flags |= MUTEX_FLAGS_INITED; + pmutex->m_owner = NULL; + pmutex->m_type = type; + memset(&pmutex->lock, 0, + sizeof(pmutex->lock)); + *mutex = pmutex; + } else { + free(pmutex); + *mutex = NULL; + } + } + } + } + /* Return the completion status: */ + return (ret); +} + +int +pthread_mutex_destroy(pthread_mutex_t * mutex) +{ + int ret = 0; + + if (mutex == NULL || *mutex == NULL) + ret = EINVAL; + else { + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* + * Free the memory allocated for the mutex + * structure: + */ + free(*mutex); + + /* + * Leave the caller's pointer NULL now that + * the mutex has been destroyed: + */ + *mutex = NULL; + } + + /* Return the completion status: */ + return (ret); +} + +static int +init_static (pthread_mutex_t *mutex) +{ + int ret; + + _SPINLOCK(&static_init_lock); + + if (*mutex == NULL) + ret = pthread_mutex_init(mutex, NULL); + else + ret = 0; + + _SPINUNLOCK(&static_init_lock); + + return(ret); +} + +int +pthread_mutex_trylock(pthread_mutex_t * mutex) +{ + int ret = 0; + + if (mutex == NULL) + ret = EINVAL; + + /* + * If the mutex is statically initialized, perform the dynamic + * initialization: + */ + else if (*mutex != NULL || (ret = init_static(mutex)) == 0) { + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* 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: */ + ret = EBUSY; + } + 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: */ + ret = EBUSY; + } + } else { + /* Lock the mutex for the running thread: */ + (*mutex)->m_owner = _thread_run; + } + break; + + /* Trap invalid mutex types: */ + default: + /* Return an invalid argument error: */ + ret = EINVAL; + break; + } + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + } + + /* Return the completion status: */ + return (ret); +} + +int +pthread_mutex_lock(pthread_mutex_t * mutex) +{ + int ret = 0; + + if (mutex == NULL) + ret = EINVAL; + + /* + * If the mutex is statically initialized, perform the dynamic + * initialization: + */ + else if (*mutex != NULL || (ret = init_static(mutex)) == 0) { + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* 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); + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + + /* Block signals: */ + _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__); + + /* Lock the mutex again: */ + _SPINLOCK(&(*mutex)->lock); + } + } + 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); + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + + /* Block signals: */ + _thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__); + + /* Lock the mutex again: */ + _SPINLOCK(&(*mutex)->lock); + } + } + + /* Increment the lock count for this mutex: */ + (*mutex)->m_data.m_count++; + break; + + /* Trap invalid mutex types: */ + default: + /* Return an invalid argument error: */ + ret = EINVAL; + break; + } + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + } + + /* Return the completion status: */ + return (ret); +} + +int +pthread_mutex_unlock(pthread_mutex_t * mutex) +{ + int ret = 0; + + if (mutex == NULL || *mutex == NULL) { + ret = EINVAL; + } else { + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* 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: */ + ret = EINVAL; + } + /* + * 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: */ + PTHREAD_NEW_STATE((*mutex)->m_owner,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: */ + ret = EINVAL; + } + /* 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: */ + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); + } + break; + + /* Trap invalid mutex types: */ + default: + /* Return an invalid argument error: */ + ret = EINVAL; + break; + } + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + } + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_mutexattr_destroy.c b/lib/libc_r/uthread/uthread_mutexattr_destroy.c new file mode 100644 index 00000000000..5642cbef589 --- /dev/null +++ b/lib/libc_r/uthread/uthread_mutexattr_destroy.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1997 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_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + ret = EINVAL; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + 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 00000000000..4ec7d3f3172 --- /dev/null +++ b/lib/libc_r/uthread/uthread_nanosleep.c @@ -0,0 +1,119 @@ +/* + * 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 <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +nanosleep(const struct timespec * time_to_sleep, + struct timespec * time_remaining) +{ + int ret = 0; + struct timespec current_time; + struct timespec current_time1; + struct timespec remaining_time; + struct timeval tv; + + /* Check if the time to sleep is legal: */ + if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000) { + /* Return an EINVAL error : */ + errno = EINVAL; + ret = -1; + } else { + /* Get the current time: */ + gettimeofday(&tv, NULL); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); + + /* Calculate the time for the current thread to wake up: */ + _thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec; + _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec; + + /* Check if the nanosecond field has overflowed: */ + if (_thread_run->wakeup_time.tv_nsec >= 1000000000) { + /* Wrap the nanosecond field: */ + _thread_run->wakeup_time.tv_sec += 1; + _thread_run->wakeup_time.tv_nsec -= 1000000000; + } + _thread_run->interrupted = 0; + + /* Reschedule the current thread to sleep: */ + _thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__); + + /* Get the current time: */ + gettimeofday(&tv, NULL); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time1); + + /* Calculate the remaining time to sleep: */ + remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec; + remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec; + + /* Check if the nanosecond field has underflowed: */ + if (remaining_time.tv_nsec < 0) { + /* Handle the underflow: */ + remaining_time.tv_sec -= 1; + remaining_time.tv_nsec += 1000000000; + } + + /* Check if the nanosecond field has overflowed: */ + if (remaining_time.tv_nsec >= 1000000000) { + /* Handle the overflow: */ + remaining_time.tv_sec += 1; + remaining_time.tv_nsec -= 1000000000; + } + + /* Check if the sleep was longer than the required time: */ + if (remaining_time.tv_sec < 0) { + /* Reset the time left: */ + remaining_time.tv_sec = 0; + remaining_time.tv_nsec = 0; + } + + /* Check if the time remaining is to be returned: */ + if (time_remaining != NULL) { + /* Return the actual time slept: */ + time_remaining->tv_sec = remaining_time.tv_sec; + time_remaining->tv_nsec = remaining_time.tv_nsec; + } + + /* Check if the sleep was interrupted: */ + if (_thread_run->interrupted) { + /* Return an EINTR error : */ + errno = EINTR; + ret = -1; + } + } + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_once.c b/lib/libc_r/uthread/uthread_once.c new file mode 100644 index 00000000000..c55ba9eaf74 --- /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 00000000000..c89129bc959 --- /dev/null +++ b/lib/libc_r/uthread/uthread_open.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $Id: uthread_open.c,v 1.1 1998/08/27 09:01:15 d Exp $ + * $OpenBSD: uthread_open.c,v 1.1 1998/08/27 09:01:15 d Exp $ + * + */ +#include <stdarg.h> +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +open(const char *path, int flags,...) +{ + int fd; + int mode = 0; + va_list ap; + + /* 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: */ + if ((fd = _thread_sys_open(path, flags, 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; + } + + /* 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 00000000000..48ef8ed9886 --- /dev/null +++ b/lib/libc_r/uthread/uthread_pipe.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1995-1998 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; + } + } + 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 00000000000..5225ab8838e --- /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 00000000000..e84b52cbae4 --- /dev/null +++ b/lib/libc_r/uthread/uthread_read.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $Id: uthread_read.c,v 1.1 1998/08/27 09:01:16 d Exp $ + * $OpenBSD: uthread_read.c,v 1.1 1998/08/27 09:01:16 d Exp $ + * + */ +#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 ret; + int type; + + /* POSIX says to do just this: */ + if (nbytes == 0) + return (0); + + /* Lock the file descriptor for read: */ + if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + /* Get the read/write mode type: */ + type = _thread_fd_table[fd]->flags & O_ACCMODE; + + /* Check if the file is not open for read: */ + if (type != O_RDONLY && type != O_RDWR) { + /* File is not open for read: */ + errno = EBADF; + _FD_UNLOCK(fd, FD_READ); + return (-1); + } + + /* Perform a non-blocking read syscall: */ + while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { + if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { + _thread_run->data.fd.fd = fd; + _thread_kern_set_timeout(NULL); + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDR_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + break; + } + } else { + break; + } + } + _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 00000000000..77fbf60fd03 --- /dev/null +++ b/lib/libc_r/uthread/uthread_readv.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $Id: uthread_readv.c,v 1.1 1998/08/27 09:01:16 d Exp $ + * $OpenBSD: uthread_readv.c,v 1.1 1998/08/27 09:01:16 d Exp $ + * + */ +#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 ret; + int type; + + /* Lock the file descriptor for read: */ + if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + /* Get the read/write mode type: */ + type = _thread_fd_table[fd]->flags & O_ACCMODE; + + /* Check if the file is not open for read: */ + if (type != O_RDONLY && type != O_RDWR) { + /* File is not open for read: */ + errno = EBADF; + _FD_UNLOCK(fd, FD_READ); + return (-1); + } + + /* Perform a non-blocking readv syscall: */ + while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) { + if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { + _thread_run->data.fd.fd = fd; + _thread_kern_set_timeout(NULL); + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDR_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + break; + } + } else { + break; + } + } + _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 00000000000..e8a374160b1 --- /dev/null +++ b/lib/libc_r/uthread/uthread_recvfrom.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_READ, NULL)) == 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_run->interrupted = 0; + _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); + + /* Check if the wait was interrupted: */ + if (_thread_run->interrupted) { + /* Return an error status: */ + errno = EINTR; + ret = -1; + break; + } + } else { + ret = -1; + break; + } + } + _FD_UNLOCK(fd, FD_READ); + } + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_recvmsg.c b/lib/libc_r/uthread/uthread_recvmsg.c new file mode 100644 index 00000000000..44a4a6552cc --- /dev/null +++ b/lib/libc_r/uthread/uthread_recvmsg.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1998 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 +recvmsg(int fd, struct msghdr *msg, int flags) +{ + int ret; + + if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + while ((ret = _thread_sys_recvmsg(fd, msg, flags)) < 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_run->interrupted = 0; + _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); + + /* Check if the wait was interrupted: */ + if (_thread_run->interrupted) { + /* Return an error status: */ + errno = EINTR; + ret = -1; + break; + } + } else { + ret = -1; + break; + } + } + _FD_UNLOCK(fd, FD_READ); + } + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_resume_np.c b/lib/libc_r/uthread/uthread_resume_np.c new file mode 100644 index 00000000000..7c5f46adfce --- /dev/null +++ b/lib/libc_r/uthread/uthread_resume_np.c @@ -0,0 +1,54 @@ +/* + * 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" + +/* Resume a thread: */ +int +pthread_resume_np(pthread_t thread) +{ + int ret; + + /* Find the thread in the list of active threads: */ + if ((ret = _find_thread(thread)) == 0) { + /* The thread exists. Is it suspended? */ + if (thread->state != PS_SUSPENDED) { + /* Allow the thread to run. */ + PTHREAD_NEW_STATE(thread,PS_RUNNING); + } + } + 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 00000000000..d6202db0140 --- /dev/null +++ b/lib/libc_r/uthread/uthread_select.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(i, FD_RDWR, NULL)) != 0) { + got_all_locks = 0; + break; + } + FD_SET(i, &rdwr_locks); + } else { + if ((ret = _FD_LOCK(i, FD_READ, NULL)) != 0) { + got_all_locks = 0; + break; + } + FD_SET(i, &read_locks); + } + } else { + if (writefds && FD_ISSET(i, writefds)) { + if ((ret = _FD_LOCK(i, FD_WRITE, NULL)) != 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_run->interrupted = 0; + _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + } else + ret = data.nfds; + } + } + /* clean up the locks */ + for (i = 0; i < numfds; i++) + if (FD_ISSET(i, &read_locks)) + _FD_UNLOCK(i, FD_READ); + for (i = 0; i < numfds; i++) + if (FD_ISSET(i, &rdwr_locks)) + _FD_UNLOCK(i, FD_RDWR); + for (i = 0; i < numfds; i++) + if (FD_ISSET(i, &write_locks)) + _FD_UNLOCK(i, FD_WRITE); + + if (ret >= 0) { + if (readfds != NULL) { + for (i = 0; i < numfds; i++) { + if (FD_ISSET(i, readfds) && + !FD_ISSET(i, &data.readfds)) { + FD_CLR(i, readfds); + } + } + } + if (writefds != NULL) { + for (i = 0; i < numfds; i++) { + if (FD_ISSET(i, writefds) && + !FD_ISSET(i, &data.writefds)) { + FD_CLR(i, writefds); + } + } + } + if (exceptfds != NULL) { + for (i = 0; i < numfds; i++) { + if (FD_ISSET(i, exceptfds) && + !FD_ISSET(i, &data.exceptfds)) { + FD_CLR(i, exceptfds); + } + } + } + } + + 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 00000000000..a0a2d2aded6 --- /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_sendmsg.c b/lib/libc_r/uthread/uthread_sendmsg.c new file mode 100644 index 00000000000..9d97c121dcf --- /dev/null +++ b/lib/libc_r/uthread/uthread_sendmsg.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1998 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 +sendmsg(int fd, const struct msghdr *msg, int flags) +{ + int ret; + + if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { + while ((ret = _thread_sys_sendmsg(fd, msg, flags)) < 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_run->interrupted = 0; + _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); + + /* Check if the operation was interrupted: */ + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + break; + } + } else { + ret = -1; + break; + } + } + _FD_UNLOCK(fd, FD_WRITE); + } + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_sendto.c b/lib/libc_r/uthread/uthread_sendto.c new file mode 100644 index 00000000000..7dedaaa496c --- /dev/null +++ b/lib/libc_r/uthread/uthread_sendto.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_WRITE, NULL)) == 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_run->interrupted = 0; + _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); + + /* Check if the operation was interrupted: */ + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + break; + } + } else { + ret = -1; + break; + } + } + _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 00000000000..570807f1fc7 --- /dev/null +++ b/lib/libc_r/uthread/uthread_seterrno.c @@ -0,0 +1,60 @@ +/* + * 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_setprio.c b/lib/libc_r/uthread/uthread_setprio.c new file mode 100644 index 00000000000..dd89f156a50 --- /dev/null +++ b/lib/libc_r/uthread/uthread_setprio.c @@ -0,0 +1,56 @@ +/* + * 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 ret; + + /* Check if the priority is invalid: */ + if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) + /* Return an invalid argument error: */ + ret = EINVAL; + + /* Find the thread in the list of active threads: */ + else if ((ret = _find_thread(pthread)) == 0) + /* Set the thread priority: */ + pthread->pthread_priority = prio; + + /* Return the error status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_setsockopt.c b/lib/libc_r/uthread/uthread_setsockopt.c new file mode 100644 index 00000000000..a14b338eecd --- /dev/null +++ b/lib/libc_r/uthread/uthread_setsockopt.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + ret = _thread_sys_setsockopt(fd, level, optname, optval, optlen); + _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 00000000000..855be90368a --- /dev/null +++ b/lib/libc_r/uthread/uthread_shutdown.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1995-1998 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 = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + ret = _thread_sys_shutdown(fd, how); + _FD_UNLOCK(fd, FD_READ); + } + break; + case 1: + if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { + ret = _thread_sys_shutdown(fd, how); + _FD_UNLOCK(fd, FD_WRITE); + } + break; + case 2: + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { + ret = _thread_sys_shutdown(fd, how); + _FD_UNLOCK(fd, FD_RDWR); + } + break; + default: + errno = 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 00000000000..7f13cd6dde1 --- /dev/null +++ b/lib/libc_r/uthread/uthread_sig.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 1995-1998 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 <fcntl.h> +#include <unistd.h> +#include <errno.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +/* Static variables: */ +static int volatile yield_on_unlock_dead = 0; +static int volatile yield_on_unlock_thread = 0; +static spinlock_t thread_dead_lock = _SPINLOCK_INITIALIZER; +static spinlock_t thread_link_list_lock = _SPINLOCK_INITIALIZER; + +/* Lock the thread list: */ +void +_lock_thread_list() +{ + /* Lock the thread list: */ + _SPINLOCK(&thread_link_list_lock); +} + +/* Lock the dead thread list: */ +void +_lock_dead_thread_list() +{ + /* Lock the dead thread list: */ + _SPINLOCK(&thread_dead_lock); +} + +/* Lock the thread list: */ +void +_unlock_thread_list() +{ + /* Unlock the thread list: */ + _SPINUNLOCK(&thread_link_list_lock); + + /* + * Check if a scheduler interrupt occurred while the thread + * list was locked: + */ + if (yield_on_unlock_thread) { + /* Reset the interrupt flag: */ + yield_on_unlock_thread = 0; + + /* This thread has overstayed it's welcome: */ + sched_yield(); + } +} + +/* Lock the dead thread list: */ +void +_unlock_dead_thread_list() +{ + /* Unlock the dead thread list: */ + _SPINUNLOCK(&thread_dead_lock); + + /* + * Check if a scheduler interrupt occurred while the dead + * thread list was locked: + */ + if (yield_on_unlock_dead) { + /* Reset the interrupt flag: */ + yield_on_unlock_dead = 0; + + /* This thread has overstayed it's welcome: */ + sched_yield(); + } +} + +void +_thread_sig_handler(int sig, int code, struct sigcontext * scp) +{ + char c; + int i; + pthread_t pthread; + + /* + * Check if the pthread kernel has unblocked signals (or is about to) + * and was on its way into a _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 _select call will complete + * immediately. + */ + _thread_sys_write(_thread_kern_pipe[1], &c, 1); + } + + /* Check if the signal requires a dump of thread information: */ + if (sig == SIGINFO) + /* Dump thread information to file: */ + _thread_dump_info(); + + /* Check if an interval timer signal: */ + else if (sig == SIGVTALRM) { + /* Check if the scheduler interrupt has come at an + * unfortunate time which one of the threads is + * modifying the thread list: + */ + if (thread_link_list_lock.access_lock) + /* + * Set a flag so that the thread that has + * the lock yields when it unlocks the + * thread list: + */ + yield_on_unlock_thread = 1; + + /* Check if the scheduler interrupt has come at an + * unfortunate time which one of the threads is + * modifying the dead thread list: + */ + if (thread_dead_lock.access_lock) + /* + * Set a flag so that the thread that has + * the lock yields when it unlocks the + * dead thread list: + */ + yield_on_unlock_dead = 1; + + /* + * Check if the kernel has not been interrupted while + * executing scheduler code: + */ + else if (!_thread_kern_in_sched) { + /* + * 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"); + } + } else { + /* Check if a child has terminated: */ + if (sig == SIGCHLD) { + /* + * Go through the file list and set all files + * to non-blocking again in case the child + * set some of them to block. Sigh. + */ + for (i = 0; i < _thread_dtablesize; i++) { + /* Check if this file is used: */ + if (_thread_fd_table[i] != NULL) { + /* + * Set the file descriptor to + * non-blocking: + */ + _thread_sys_fcntl(i, F_SETFL, + _thread_fd_table[i]->flags | + O_NONBLOCK); + } + } + } + + /* + * POSIX says that pending SIGCONT signals are + * discarded when one of there signals occurs. + */ + if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) { + /* + * Enter a loop to discard pending SIGCONT + * signals: + */ + for (pthread = _thread_link_list; + pthread != NULL; + pthread = pthread->nxt) + sigdelset(&pthread->sigpend,SIGCONT); + } + + /* + * Enter a loop to process each thread in the linked + * list that is sigwait-ing on a signal. Since POSIX + * doesn't specify which thread will get the signal + * if there are multiple waiters, we'll give it to the + * first one we find. + */ + for (pthread = _thread_link_list; pthread != NULL; + pthread = pthread->nxt) { + if ((pthread->state == PS_SIGWAIT) && + sigismember(&pthread->sigmask, sig)) { + /* Change the state of the thread to run: */ + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + + /* Return the signal number: */ + pthread->signo = sig; + + /* + * Do not attempt to deliver this signal + * to other threads. + */ + return; + } + } + + /* Check if the signal is not being ignored: */ + if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) + /* + * Enter a loop to process each thread in the linked + * list: + */ + for (pthread = _thread_link_list; pthread != NULL; + pthread = pthread->nxt) + _thread_signal(pthread,sig); + + /* Dispatch pending signals to the running thread: */ + _dispatch_signals(); + } + + /* Returns nothing. */ + return; +} + +/* Perform thread specific actions in response to a signal: */ +void +_thread_signal(pthread_t pthread, int sig) +{ + /* + * Flag the signal as pending. It will be dispatched later. + */ + sigaddset(&pthread->sigpend,sig); + + /* + * 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_FILE_WAIT: + case PS_JOIN: + case PS_MUTEX_WAIT: + case PS_RUNNING: + case PS_STATE_MAX: + case PS_SIGTHREAD: + case PS_SIGWAIT: + case PS_SUSPENDED: + /* Nothing to do here. */ + break; + + /* + * The wait state is a special case due to the handling of + * SIGCHLD signals. + */ + case PS_WAIT_WAIT: + /* + * Check for signals other than the death of a child + * process: + */ + if (sig != SIGCHLD) + /* Flag the operation as interrupted: */ + pthread->interrupted = 1; + + /* Change the state of the thread to run: */ + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + + /* Return the signal number: */ + pthread->signo = sig; + 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_SLEEP_WAIT: + case PS_SELECT_WAIT: + if (sig != SIGCHLD || + _thread_sigact[sig - 1].sa_handler != SIG_DFL) { + /* Flag the operation as interrupted: */ + pthread->interrupted = 1; + + /* Change the state of the thread to run: */ + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + + /* Return the signal number: */ + pthread->signo = sig; + } + break; + } +} + +/* Dispatch pending signals to the running thread: */ +void +_dispatch_signals() +{ + int i; + + /* + * Check if there are pending signals for the running + * thread that aren't blocked: + */ + if ((_thread_run->sigpend & ~_thread_run->sigmask) != 0) + /* Look for all possible pending signals: */ + for (i = 1; i < NSIG; i++) + /* + * Check that a custom handler is installed + * and if the signal is not blocked: + */ + if (_thread_sigact[i - 1].sa_handler != SIG_DFL && + _thread_sigact[i - 1].sa_handler != SIG_IGN && + sigismember(&_thread_run->sigpend,i) && + !sigismember(&_thread_run->sigmask,i)) { + /* Clear the pending signal: */ + sigdelset(&_thread_run->sigpend,i); + + /* + * Dispatch the signal via the custom signal + * handler: + */ + (*(_thread_sigact[i - 1].sa_handler))(i); + } +} +#endif diff --git a/lib/libc_r/uthread/uthread_sigaction.c b/lib/libc_r/uthread/uthread_sigaction.c new file mode 100644 index 00000000000..3538f276eba --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigaction.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1995-1998 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; + struct sigaction gact; + + /* Check if the signal number is out of range: */ + if (sig < 1 || sig > NSIG) { + /* Return an invalid argument: */ + errno = 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_sigact[sig - 1].sa_handler; + oact->sa_mask = _thread_sigact[sig - 1].sa_mask; + oact->sa_flags = _thread_sigact[sig - 1].sa_flags; + } + + /* Check if a signal action was supplied: */ + if (act != NULL) { + /* Set the new signal handler: */ + _thread_sigact[sig - 1].sa_mask = act->sa_mask; + _thread_sigact[sig - 1].sa_flags = act->sa_flags; + _thread_sigact[sig - 1].sa_handler = act->sa_handler; + } + + /* + * Check if the kernel needs to be advised of a change + * in signal action: + */ + if (act != NULL && sig != SIGVTALRM && sig != SIGCHLD && + sig != SIGINFO) { + /* Initialise the global signal action structure: */ + gact.sa_mask = act->sa_mask; + gact.sa_flags = act->sa_flags | SA_RESTART; + + /* + * Check if the signal handler is being set to + * the default or ignore handlers: + */ + if (act->sa_handler == SIG_DFL || + act->sa_handler == SIG_IGN) + /* Specify the built in handler: */ + gact.sa_handler = act->sa_handler; + else + /* + * Specify the thread kernel signal + * handler: + */ + gact.sa_handler = (void (*) ()) _thread_sig_handler; + + /* Change the signal action in the kernel: */ + if (_thread_sys_sigaction(sig,&gact,NULL) != 0) + ret = -1; + } + } + + /* 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 00000000000..fb1e0850128 --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigblock.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1995-1998 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_sigmask.c b/lib/libc_r/uthread/uthread_sigmask.c new file mode 100644 index 00000000000..23d6b7ff2a3 --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigmask.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1997 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 <signal.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) +{ + int ret = 0; + + /* 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) { + /* 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: */ + errno = EINVAL; + ret = -1; + break; + } + + /* + * Dispatch signals to the running thread that are pending + * and now unblocked: + */ + _dispatch_signals(); + } + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_signal.c b/lib/libc_r/uthread/uthread_signal.c new file mode 100644 index 00000000000..cef725f7360 --- /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 00000000000..81b602f581c --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigprocmask.c @@ -0,0 +1,88 @@ +/* + * 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; + + /* 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) { + /* 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: */ + errno = EINVAL; + ret = -1; + break; + } + + /* + * Dispatch signals to the running thread that are pending + * and now unblocked: + */ + _dispatch_signals(); + } + /* 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 00000000000..bf48d7b4fa0 --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigsetmask.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1995-1998 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 00000000000..f7a7b123e34 --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigsuspend.c @@ -0,0 +1,69 @@ +/* + * 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; + + /* Combine the caller's mask with the current one: */ + _thread_run->sigmask |= *set; + + /* Wait for a signal: */ + _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__); + + /* Always return an interrupted error: */ + errno = EINTR; + + /* Restore the signal mask: */ + _thread_run->sigmask = oset; + } else { + /* Return an invalid argument error: */ + errno = EINVAL; + } + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_sigwait.c b/lib/libc_r/uthread/uthread_sigwait.c new file mode 100644 index 00000000000..f441fa3b731 --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigwait.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1997 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 +sigwait(const sigset_t * set, int *sig) +{ + int ret = 0; + int i; + sigset_t oset; + struct sigaction act; + + /* + * Specify the thread kernel signal handler. + */ + act.sa_handler = (void (*) ()) _thread_sig_handler; + act.sa_flags = SA_RESTART; + act.sa_mask = *set; + + /* + * These signals can't be waited on. + */ + sigdelset(&act.sa_mask, SIGKILL); + sigdelset(&act.sa_mask, SIGSTOP); + sigdelset(&act.sa_mask, SIGVTALRM); + sigdelset(&act.sa_mask, SIGCHLD); + sigdelset(&act.sa_mask, SIGINFO); + + /* + * Enter a loop to find the signals that are SIG_DFL. For + * these signals we must install a dummy signal handler in + * order for the kernel to pass them in to us. POSIX says + * that the application must explicitly install a dummy + * handler for signals that are SIG_IGN in order to sigwait + * on them, so we ignore SIG_IGN signals. + */ + for (i = 1; i < NSIG; i++) { + if (sigismember(&act.sa_mask, i)) { + if (_thread_sigact[i - 1].sa_handler == SIG_DFL) { + if (_thread_sys_sigaction(i,&act,NULL) != 0) + ret = -1; + } + else if (_thread_sigact[i - 1].sa_handler == SIG_IGN) + sigdelset(&act.sa_mask, i); + } + } + if (ret == 0) { + + /* Save the current signal mask: */ + oset = _thread_run->sigmask; + + /* Combine the caller's mask with the current one: */ + _thread_run->sigmask |= act.sa_mask; + + /* Wait for a signal: */ + _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__); + + /* Return the signal number to the caller: */ + *sig = _thread_run->signo; + + /* Restore the signal mask: */ + _thread_run->sigmask = oset; + } + + /* Restore the sigactions: */ + act.sa_handler = SIG_DFL; + for (i = 1; i < NSIG; i++) { + if (sigismember(&act.sa_mask, i) && + (_thread_sigact[i - 1].sa_handler == SIG_DFL)) { + if (_thread_sys_sigaction(i,&act,NULL) != 0) + ret = -1; + } + } + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_single_np.c b/lib/libc_r/uthread/uthread_single_np.c new file mode 100644 index 00000000000..e36c856c637 --- /dev/null +++ b/lib/libc_r/uthread/uthread_single_np.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <string.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int pthread_single_np() +{ + /* Enter single-threaded (non-POSIX) scheduling mode: */ + _thread_single = _thread_run; + return(0); +} +#endif diff --git a/lib/libc_r/uthread/uthread_socket.c b/lib/libc_r/uthread/uthread_socket.c new file mode 100644 index 00000000000..7b5fe00dd2a --- /dev/null +++ b/lib/libc_r/uthread/uthread_socket.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1995-1998 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> +#include <unistd.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +socket(int af, int type, int protocol) +{ + int fd; + + /* Create a socket: */ + if ((fd = _thread_sys_socket(af, type, protocol)) < 0) { + /* Error creating socket. */ + + /* Initialise the entry in the file descriptor table: */ + } else if (_thread_fd_table_init(fd) != 0) { + _thread_sys_close(fd); + fd = -1; + } + 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 00000000000..65a772ff3ec --- /dev/null +++ b/lib/libc_r/uthread/uthread_socketpair.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $Id: uthread_socketpair.c,v 1.1 1998/08/27 09:01:25 d Exp $ + * $OpenBSD: uthread_socketpair.c,v 1.1 1998/08/27 09:01:25 d Exp $ + * + */ +#include <sys/types.h> +#include <sys/socket.h> +#include <fcntl.h> +#include <unistd.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)) + if (_thread_fd_table_init(pair[0]) != 0 || + _thread_fd_table_init(pair[1]) != 0) { + _thread_sys_close(pair[0]); + _thread_sys_close(pair[1]); + ret = -1; + } + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_spec.c b/lib/libc_r/uthread/uthread_spec.c new file mode 100644 index 00000000000..081a000788d --- /dev/null +++ b/lib/libc_r/uthread/uthread_spec.c @@ -0,0 +1,197 @@ +/* + * 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_KEYS_MAX]; + +int +pthread_key_create(pthread_key_t * key, void (*destructor) (void *)) +{ + for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) { + /* Lock the key table entry: */ + _SPINLOCK(&key_table[*key].lock); + + if (key_table[(*key)].allocated == 0) { + key_table[(*key)].allocated = 1; + key_table[(*key)].destructor = destructor; + + /* Unlock the key table entry: */ + _SPINUNLOCK(&key_table[*key].lock); + return (0); + } + + /* Unlock the key table entry: */ + _SPINUNLOCK(&key_table[*key].lock); + } + return (EAGAIN); +} + +int +pthread_key_delete(pthread_key_t key) +{ + int ret = 0; + + if (key < PTHREAD_KEYS_MAX) { + /* Lock the key table entry: */ + _SPINLOCK(&key_table[key].lock); + + if (key_table[key].allocated) + key_table[key].allocated = 0; + else + ret = EINVAL; + + /* Unlock the key table entry: */ + _SPINUNLOCK(&key_table[key].lock); + } else + ret = EINVAL; + return (ret); +} + +void +_thread_cleanupspecific(void) +{ + void *data; + int key; + int itr; + void (*destructor)( void *); + + for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) { + for (key = 0; key < PTHREAD_KEYS_MAX; key++) { + if (_thread_run->specific_data_count) { + destructor = data = NULL; + + /* Lock the key table entry: */ + _SPINLOCK(&key_table[key].lock); + if (key_table[key].allocated) { + if (_thread_run->specific_data[key]) { + data = (void *) _thread_run->specific_data[key]; + _thread_run->specific_data[key] = NULL; + _thread_run->specific_data_count--; + destructor = key_table[key].destructor; + } + } + + /* Unlock the key table entry: */ + _SPINUNLOCK(&key_table[key].lock); + + /* + * If there is a destructor, call it + * with the key table entry unlocked: + */ + if (destructor) + destructor(data); + } else { + free(_thread_run->specific_data); + return; + } + } + } + free(_thread_run->specific_data); +} + +static inline const void ** +pthread_key_allocate_data(void) +{ + const void **new_data; + if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX)) != NULL) { + memset((void *) new_data, 0, sizeof(void *) * PTHREAD_KEYS_MAX); + } + return (new_data); +} + +int +pthread_setspecific(pthread_key_t key, const void *value) +{ + pthread_t pthread; + int ret = 0; + + /* Point to the running thread: */ + pthread = _thread_run; + + if ((pthread->specific_data) || + (pthread->specific_data = pthread_key_allocate_data())) { + if (key < PTHREAD_KEYS_MAX) { + if (key_table[key].allocated) { + if (pthread->specific_data[key] == NULL) { + if (value != NULL) + pthread->specific_data_count++; + } else { + if (value == NULL) + pthread->specific_data_count--; + } + pthread->specific_data[key] = value; + ret = 0; + } else + ret = EINVAL; + } else + ret = EINVAL; + } else + ret = ENOMEM; + return (ret); +} + +void * +pthread_getspecific(pthread_key_t key) +{ + pthread_t pthread; + void *data; + + /* Point to the running thread: */ + pthread = _thread_run; + + /* Check if there is specific data: */ + if (pthread->specific_data != NULL && key < PTHREAD_KEYS_MAX) { + /* Check if this key has been used before: */ + if (key_table[key].allocated) { + /* Return the value: */ + data = (void *) pthread->specific_data[key]; + } else { + /* + * This key has not been used before, so return NULL + * instead: + */ + data = NULL; + } + } else + /* No specific data has been created, so just return NULL: */ + data = NULL; + return (data); +} +#endif diff --git a/lib/libc_r/uthread/uthread_spinlock.c b/lib/libc_r/uthread/uthread_spinlock.c new file mode 100644 index 00000000000..1863bdfef9a --- /dev/null +++ b/lib/libc_r/uthread/uthread_spinlock.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1997 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. + * + * $Id: uthread_spinlock.c,v 1.1 1998/08/27 09:01:25 d Exp $ + * $OpenBSD: uthread_spinlock.c,v 1.1 1998/08/27 09:01:25 d Exp $ + * + */ + +#include <stdio.h> +#include <sched.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include "pthread_private.h" + +extern char *__progname; + +/* + * Lock a location for the running thread. Yield to allow other + * threads to run if this thread is blocked because the lock is + * not available. Note that this function does not sleep. It + * assumes that the lock will be available very soon. + */ +void +_spinlock(spinlock_t *lck) +{ + /* + * Try to grab the lock and loop if another thread grabs + * it before we do. + */ + while(_atomic_lock(&lck->access_lock)) { + /* Give up the time slice: */ + sched_yield(); + + /* Check if already locked by the running thread: */ + if (lck->lock_owner == (long) _thread_run) + return; + } + + /* The running thread now owns the lock: */ + lck->lock_owner = (long) _thread_run; +} + +/* + * Lock a location for the running thread. Yield to allow other + * threads to run if this thread is blocked because the lock is + * not available. Note that this function does not sleep. It + * assumes that the lock will be available very soon. + * + * This function checks if the running thread has already locked the + * location, warns if this occurs and creates a thread dump before + * returning. + */ +void +_spinlock_debug(spinlock_t *lck, char *fname, int lineno) +{ + /* + * Try to grab the lock and loop if another thread grabs + * it before we do. + */ + while(_atomic_lock(&lck->access_lock)) { + /* Give up the time slice: */ + sched_yield(); + + /* Check if already locked by the running thread: */ + if (lck->lock_owner == (long) _thread_run) { + char str[256]; + snprintf(str, sizeof(str), "%s - Warning: Thread %p attempted to lock %p from %s (%d) which it had already locked in %s (%d)\n", __progname, _thread_run, lck, fname, lineno, lck->fname, lck->lineno); + _thread_sys_write(2,str,strlen(str)); + + /* Create a thread dump to help debug this problem: */ + _thread_dump_info(); + return; + } + } + + /* The running thread now owns the lock: */ + lck->lock_owner = (long) _thread_run; + lck->fname = fname; + lck->lineno = lineno; +} diff --git a/lib/libc_r/uthread/uthread_suspend_np.c b/lib/libc_r/uthread/uthread_suspend_np.c new file mode 100644 index 00000000000..871683ad92a --- /dev/null +++ b/lib/libc_r/uthread/uthread_suspend_np.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1995-1998 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" + +/* Suspend a thread: */ +int +pthread_suspend_np(pthread_t thread) +{ + int ret; + + /* Find the thread in the list of active threads: */ + if ((ret = _find_thread(thread)) == 0) { + /* The thread exists. Is it running? */ + if (thread->state != PS_RUNNING && + thread->state != PS_SUSPENDED) { + /* The thread operation has been interrupted */ + _thread_seterrno(thread,EINTR); + thread->interrupted = 1; + } + + /* Suspend the thread. */ + PTHREAD_NEW_STATE(thread,PS_SUSPENDED); + } + 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 00000000000..dda8aeea61c --- /dev/null +++ b/lib/libc_r/uthread/uthread_wait4.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1995-1998 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) +{ + pid_t ret; + + /* Perform a non-blocking wait4 syscall: */ + while ((ret = _thread_sys_wait4(pid, istat, options | WNOHANG, rusage)) == 0 && (options & WNOHANG) == 0) { + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 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 (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + break; + } + } + 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 00000000000..6c243d594eb --- /dev/null +++ b/lib/libc_r/uthread/uthread_write.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $Id: uthread_write.c,v 1.1 1998/08/27 09:01:29 d Exp $ + * $OpenBSD: uthread_write.c,v 1.1 1998/08/27 09:01:29 d Exp $ + * + */ +#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 blocking; + int type; + ssize_t n; + ssize_t num = 0; + ssize_t ret; + + /* POSIX says to do just this: */ + if (nbytes == 0) + return (0); + + /* Lock the file descriptor for write: */ + if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { + /* Get the read/write mode type: */ + type = _thread_fd_table[fd]->flags & O_ACCMODE; + + /* Check if the file is not open for write: */ + if (type != O_WRONLY && type != O_RDWR) { + /* File is not open for write: */ + errno = EBADF; + _FD_UNLOCK(fd, FD_WRITE); + return (-1); + } + + /* Check if file operations are to block */ + blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0); + + /* + * Loop while no error occurs and until the expected number + * of bytes are written if performing a blocking write: + */ + while (ret == 0) { + /* Perform a non-blocking write syscall: */ + n = _thread_sys_write(fd, buf + num, nbytes - num); + + /* Check if one or more bytes were written: */ + if (n > 0) + /* + * Keep a count of the number of bytes + * written: + */ + num += n; + + /* + * If performing a blocking write, check if the + * write would have blocked or if some bytes + * were written but there are still more to + * write: + */ + if (blocking && ((n < 0 && (errno == EWOULDBLOCK || + errno == EAGAIN)) || (n >= 0 && num < nbytes))) { + _thread_run->data.fd.fd = fd; + _thread_kern_set_timeout(NULL); + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { + /* Return an error: */ + ret = -1; + } + + /* + * If performing a non-blocking write or if an + * error occurred, just return whatever the write + * syscall did: + */ + } else if (!blocking || n < 0) { + /* A non-blocking call might return zero: */ + ret = n; + break; + + /* Check if the write has completed: */ + } else if (num >= nbytes) + /* Return the number of bytes written: */ + ret = num; + } + _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 00000000000..92c10e94b8e --- /dev/null +++ b/lib/libc_r/uthread/uthread_writev.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 1995-1998 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. + * + * $Id: uthread_writev.c,v 1.1 1998/08/27 09:01:30 d Exp $ + * $OpenBSD: uthread_writev.c,v 1.1 1998/08/27 09:01:30 d Exp $ + * + */ +#include <sys/types.h> +#include <sys/fcntl.h> +#include <sys/uio.h> +#include <errno.h> +#include <stdlib.h> +#include <string.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 blocking; + int idx = 0; + int type; + ssize_t cnt; + ssize_t n; + ssize_t num = 0; + ssize_t ret; + struct iovec liov[20]; + struct iovec *p_iov = liov; + + /* Check if the array size exceeds to compiled in size: */ + if (iovcnt > (sizeof(liov) / sizeof(struct iovec))) { + /* Allocate memory for the local array: */ + if ((p_iov = (struct iovec *) + malloc(iovcnt * sizeof(struct iovec))) == NULL) { + /* Insufficient memory: */ + errno = ENOMEM; + return (-1); + } + } + + /* Copy the caller's array so that it can be modified locally: */ + memcpy(p_iov,iov,iovcnt * sizeof(struct iovec)); + + /* Lock the file descriptor for write: */ + if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { + /* Get the read/write mode type: */ + type = _thread_fd_table[fd]->flags & O_ACCMODE; + + /* Check if the file is not open for write: */ + if (type != O_WRONLY && type != O_RDWR) { + /* File is not open for write: */ + errno = EBADF; + _FD_UNLOCK(fd, FD_WRITE); + return (-1); + } + + /* Check if file operations are to block */ + blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0); + + /* + * Loop while no error occurs and until the expected number + * of bytes are written if performing a blocking write: + */ + while (ret == 0) { + /* Perform a non-blocking write syscall: */ + n = _thread_sys_writev(fd, &p_iov[idx], iovcnt - idx); + + /* Check if one or more bytes were written: */ + if (n > 0) { + /* + * Keep a count of the number of bytes + * written: + */ + num += n; + + /* + * Enter a loop to check if a short write + * occurred and move the index to the + * array entry where the short write + * ended: + */ + cnt = n; + while (cnt > 0 && idx < iovcnt) { + /* + * If the residual count exceeds + * the size of this vector, then + * it was completely written: + */ + if (cnt >= p_iov[idx].iov_len) + /* + * Decrement the residual + * count and increment the + * index to the next array + * entry: + */ + cnt -= p_iov[idx++].iov_len; + else { + /* + * This entry was only + * partially written, so + * adjust it's length + * and base pointer ready + * for the next write: + */ + p_iov[idx].iov_len -= cnt; + p_iov[idx].iov_base += cnt; + cnt = 0; + } + } + } + + /* + * If performing a blocking write, check if the + * write would have blocked or if some bytes + * were written but there are still more to + * write: + */ + if (blocking && ((n < 0 && (errno == EWOULDBLOCK || + errno == EAGAIN)) || (n >= 0 && idx < iovcnt))) { + _thread_run->data.fd.fd = fd; + _thread_kern_set_timeout(NULL); + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { + /* Return an error: */ + ret = -1; + } + + /* + * If performing a non-blocking write or if an + * error occurred, just return whatever the write + * syscall did: + */ + } else if (!blocking || n < 0) { + /* A non-blocking call might return zero: */ + ret = n; + break; + + /* Check if the write has completed: */ + } else if (idx == iovcnt) + /* Return the number of bytes written: */ + ret = num; + } + _FD_UNLOCK(fd, FD_RDWR); + } + + /* If memory was allocated for the array, free it: */ + if (p_iov != liov) + free(p_iov); + + 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 00000000000..877f5e6b0e8 --- /dev/null +++ b/lib/libc_r/uthread/uthread_yield.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. + * + */ +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +int +sched_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); + + /* Always return no error. */ + return(0); +} + +/* Draft 4 yield */ +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 |