diff options
author | julian <julian@FreeBSD.org> | 1997-02-05 23:26:09 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 1997-02-05 23:26:09 +0000 |
commit | c2f7c3e4893b6b5c4494d549b3645e06664bc1b1 (patch) | |
tree | b2e6d3017e236268263978b585f2150cd10b1689 /lib/libpthread | |
parent | 321f03c8eddd8cf5aa81836ff1932a74156d30cb (diff) | |
download | FreeBSD-src-c2f7c3e4893b6b5c4494d549b3645e06664bc1b1.zip FreeBSD-src-c2f7c3e4893b6b5c4494d549b3645e06664bc1b1.tar.gz |
Submitted by: John Birrell
uthreads update from the author.
Diffstat (limited to 'lib/libpthread')
40 files changed, 994 insertions, 172 deletions
diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile index f1584ff..dab6210 100644 --- a/lib/libpthread/Makefile +++ b/lib/libpthread/Makefile @@ -11,7 +11,6 @@ SHLIB_MINOR= 0 CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE -I${.CURDIR}/uthread AINC= -I${.CURDIR}/../libc/${MACHINE} -I${.CURDIR}/uthread -CLEANFILES+=tags PRECIOUSLIB= yes .include "${.CURDIR}/db/Makefile.inc" @@ -38,13 +37,4 @@ CFLAGS+= -DYP .endif .include "${.CURDIR}/${MACHINE}/sys/Makefile.inc" -beforeinstall: tags - ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc_r.tags - -tags: ${SRCS} - ctags ${.ALLSRC:M*.c} - egrep -o "^ENTRY(.*)|^FUNC(.*)|^SYSCALL(.*)" ${.ALLSRC:M*.s} | \ - sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \ - >> tags; sort -o tags tags - .include <bsd.lib.mk> diff --git a/lib/libpthread/thread/Makefile.inc b/lib/libpthread/thread/Makefile.inc index c275b5f..cd85700 100644 --- a/lib/libpthread/thread/Makefile.inc +++ b/lib/libpthread/thread/Makefile.inc @@ -9,13 +9,20 @@ 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_autoinit.cc \ 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 \ @@ -44,12 +51,14 @@ SRCS+= \ uthread_ioctl.c \ uthread_join.c \ uthread_kern.c \ + uthread_kill.c \ uthread_listen.c \ uthread_longjmp.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 \ @@ -71,6 +80,7 @@ SRCS+= \ uthread_sigaction.c \ uthread_sigblock.c \ uthread_single_np.c \ + uthread_sigmask.c \ uthread_signal.c \ uthread_sigprocmask.c \ uthread_sigsetmask.c \ diff --git a/lib/libpthread/thread/thr_attr_destroy.c b/lib/libpthread/thread/thr_attr_destroy.c index be6b2a2..1f4b2c8 100644 --- a/lib/libpthread/thread/thr_attr_destroy.c +++ b/lib/libpthread/thread/thr_attr_destroy.c @@ -39,11 +39,19 @@ int pthread_attr_destroy(pthread_attr_t *attr) { int ret; - if (attr == NULL || *attr == NULL) { - errno = EINVAL; - ret = -1; - } else { + + /* 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; } diff --git a/lib/libpthread/thread/thr_attr_getdetachstate.c b/lib/libpthread/thread/thr_attr_getdetachstate.c new file mode 100644 index 0000000..4715cb6 --- /dev/null +++ b/lib/libpthread/thread/thr_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/libpthread/thread/thr_attr_getstackaddr.c b/lib/libpthread/thread/thr_attr_getstackaddr.c new file mode 100644 index 0000000..1850a32 --- /dev/null +++ b/lib/libpthread/thread/thr_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/libpthread/thread/thr_attr_getstacksize.c b/lib/libpthread/thread/thr_attr_getstacksize.c new file mode 100644 index 0000000..de81106 --- /dev/null +++ b/lib/libpthread/thread/thr_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/libpthread/thread/thr_attr_init.c b/lib/libpthread/thread/thr_attr_init.c index 7dade97..c64e29f 100644 --- a/lib/libpthread/thread/thr_attr_init.c +++ b/lib/libpthread/thread/thr_attr_init.c @@ -41,11 +41,16 @@ int pthread_attr_init(pthread_attr_t *attr) { int ret; pthread_attr_t pattr; - if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) { - errno = ENOMEM; - ret = -1; - } else { + + /* 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; } diff --git a/lib/libpthread/thread/thr_attr_setdetachstate.c b/lib/libpthread/thread/thr_attr_setdetachstate.c new file mode 100644 index 0000000..6ec0dbc --- /dev/null +++ b/lib/libpthread/thread/thr_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/libpthread/thread/thr_attr_setstackaddr.c b/lib/libpthread/thread/thr_attr_setstackaddr.c new file mode 100644 index 0000000..ce54915 --- /dev/null +++ b/lib/libpthread/thread/thr_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/libpthread/thread/thr_attr_setstacksize.c b/lib/libpthread/thread/thr_attr_setstacksize.c index 5e59798..94e575e 100644 --- a/lib/libpthread/thread/thr_attr_setstacksize.c +++ b/lib/libpthread/thread/thr_attr_setstacksize.c @@ -38,10 +38,12 @@ int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { int ret; - if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) { - errno = EINVAL; - ret = -1; - } else { + + /* 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; } diff --git a/lib/libpthread/thread/thr_clean.c b/lib/libpthread/thread/thr_clean.c index 99893f6..9319f85 100644 --- a/lib/libpthread/thread/thr_clean.c +++ b/lib/libpthread/thread/thr_clean.c @@ -37,11 +37,10 @@ #include <pthread.h> #include "pthread_private.h" -int -_thread_cleanup_push(void (*routine) (void *), void *routine_arg) +void +pthread_cleanup_push(void (*routine) (void *), void *routine_arg) { struct pthread_cleanup *new; - int ret; if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) { new->routine = routine; @@ -49,15 +48,11 @@ _thread_cleanup_push(void (*routine) (void *), void *routine_arg) new->next = _thread_run->cleanup; _thread_run->cleanup = new; - ret = 0; - } else { - ret = ENOMEM; } - return (ret); } void -_thread_cleanup_pop(int execute) +pthread_cleanup_pop(int execute) { struct pthread_cleanup *old; diff --git a/lib/libpthread/thread/thr_cond.c b/lib/libpthread/thread/thr_cond.c index 4395380..2fe4532 100644 --- a/lib/libpthread/thread/thr_cond.c +++ b/lib/libpthread/thread/thr_cond.c @@ -272,7 +272,7 @@ pthread_cond_signal(pthread_cond_t * cond) /* Bring the next thread off the condition queue: */ if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) { /* Allow the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } break; @@ -309,7 +309,7 @@ pthread_cond_broadcast(pthread_cond_t * cond) /* Enter a loop to bring all threads off the condition queue: */ while ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) { /* Allow the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } break; diff --git a/lib/libpthread/thread/thr_condattr_destroy.c b/lib/libpthread/thread/thr_condattr_destroy.c new file mode 100644 index 0000000..b20f183 --- /dev/null +++ b/lib/libpthread/thread/thr_condattr_destroy.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 <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) { + errno = EINVAL; + ret = -1; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_condattr_init.c b/lib/libpthread/thread/thr_condattr_init.c new file mode 100644 index 0000000..f94e438 --- /dev/null +++ b/lib/libpthread/thread/thr_condattr_init.c @@ -0,0 +1,58 @@ +/* + * 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) { + errno = ENOMEM; + ret = -1; + } else { + memcpy(pattr, &pthread_condattr_default, + sizeof(struct pthread_cond_attr)); + *attr = pattr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_create.c b/lib/libpthread/thread/thr_create.c index 1d57f8a..e4925a9 100644 --- a/lib/libpthread/thread/thr_create.c +++ b/lib/libpthread/thread/thr_create.c @@ -87,9 +87,9 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr, new_thread->start_routine = start_routine; new_thread->arg = arg; if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { - new_thread->state = PS_SUSPENDED; + PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED); } else { - new_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(new_thread,PS_RUNNING); } /* Initialise the thread for signals: */ @@ -208,7 +208,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr, * a signal handler thread which must now * wait for the signal handler to complete: */ - parent->state = PS_SIGTHREAD; + PTHREAD_NEW_STATE(parent,PS_SIGTHREAD); } else { /* Schedule the new user thread: */ _thread_kern_sched(NULL); diff --git a/lib/libpthread/thread/thr_detach.c b/lib/libpthread/thread/thr_detach.c index f24d16f..08cace4 100644 --- a/lib/libpthread/thread/thr_detach.c +++ b/lib/libpthread/thread/thr_detach.c @@ -49,7 +49,7 @@ pthread_detach(pthread_t * p_pthread) /* Check for invalid calling parameters: */ if (p_pthread == NULL || (pthread = *p_pthread) == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } /* Check if the thread has not been detached: */ @@ -60,7 +60,7 @@ pthread_detach(pthread_t * p_pthread) /* Enter a loop to bring all threads off the join queue: */ while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) { /* Make the thread run: */ - next_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(next_thread,PS_RUNNING); } /* @@ -70,7 +70,7 @@ pthread_detach(pthread_t * p_pthread) *p_pthread = NULL; } else { /* Return an error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } diff --git a/lib/libpthread/thread/thr_exit.c b/lib/libpthread/thread/thr_exit.c index 6066206..15bcfa3 100644 --- a/lib/libpthread/thread/thr_exit.c +++ b/lib/libpthread/thread/thr_exit.c @@ -109,7 +109,7 @@ pthread_exit(void *status) _thread_run->ret = status; while (_thread_run->cleanup != NULL) { - _thread_cleanup_pop(1); + pthread_cleanup_pop(1); } if (_thread_run->attr.cleanup_attr != NULL) { @@ -123,7 +123,7 @@ pthread_exit(void *status) /* Check if there are any threads joined to this one: */ while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) { /* Wake the joined thread and let it detach this thread: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } /* Check if the running thread is at the head of the linked list: */ @@ -173,11 +173,11 @@ pthread_exit(void *status) /* * Check if the parent is not waiting on any other signal - * handler threads: + * handler threads and if it hasn't died in the meantime: */ - if (pthread == NULL) { + if (pthread == NULL && _thread_run->parent_thread->state != PS_DEAD) { /* Allow the parent thread to run again: */ - _thread_run->parent_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(_thread_run->parent_thread,PS_RUNNING); } /* Get the signal number: */ l = (long) _thread_run->arg; diff --git a/lib/libpthread/thread/thr_getprio.c b/lib/libpthread/thread/thr_getprio.c index 345f6ce..85bd261 100644 --- a/lib/libpthread/thread/thr_getprio.c +++ b/lib/libpthread/thread/thr_getprio.c @@ -57,7 +57,7 @@ pthread_getprio(pthread_t pthread) /* Check if the thread pointer is NULL: */ if (pthread == NULL || pthread_p == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } else { /* Get the thread priority: */ diff --git a/lib/libpthread/thread/thr_info.c b/lib/libpthread/thread/thr_info.c index e69145f..be25d45 100644 --- a/lib/libpthread/thread/thr_info.c +++ b/lib/libpthread/thread/thr_info.c @@ -87,8 +87,8 @@ _thread_dump_info(void) if (thread_info[j].state == pthread->state) break; /* Output a record for the current thread: */ - sprintf(s, "--------------------\nThread %p prio %3d state %s\n", - pthread, pthread->pthread_priority, thread_info[j].name); + sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n", + pthread, 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: */ @@ -107,6 +107,9 @@ _thread_dump_info(void) 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)); @@ -140,11 +143,15 @@ _thread_dump_info(void) */ for (pthread = _thread_dead; pthread != NULL; pthread = pthread->nxt) { /* Output a record for the current thread: */ - sprintf(s, "Thread %p prio %3d\n", pthread, pthread->pthread_priority); + 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: */ + strcpy(s, "\n\n=============\nFILE DESCRIPTOR TABLE\n\n"); + _thread_sys_write(fd, s, strlen(s)); + /* Enter a loop to report file descriptor lock usage: */ for (i = 0; i < _thread_dtablesize; i++) { /* diff --git a/lib/libpthread/thread/thr_init.c b/lib/libpthread/thread/thr_init.c index d044063..2adc34f 100644 --- a/lib/libpthread/thread/thr_init.c +++ b/lib/libpthread/thread/thr_init.c @@ -44,7 +44,11 @@ #include <machine/reg.h> #include <pthread.h> #include "pthread_private.h" +extern int _thread_autoinit_dummy_decl; +/* + * Threaded process initialization + */ void _thread_init(void) { @@ -52,15 +56,25 @@ _thread_init(void) int i; struct sigaction act; + /* Ensure that the auto-initialization routine is linked in: */ + _thread_autoinit_dummy_decl = 1; + /* Check if this function has already been called: */ - if (_thread_initial) { + if (_thread_initial) /* Only initialise the threaded application once. */ - } + return; + + /* 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 _thread_sys_select: */ - else if (_thread_sys_pipe(_thread_kern_pipe) != 0) { + if (_thread_sys_pipe(_thread_kern_pipe) != 0) { /* Cannot create pipe, so abort: */ PANIC("Cannot create kernel pipe"); } diff --git a/lib/libpthread/thread/thr_join.c b/lib/libpthread/thread/thr_join.c index d0093ae..161482e 100644 --- a/lib/libpthread/thread/thr_join.c +++ b/lib/libpthread/thread/thr_join.c @@ -40,14 +40,40 @@ pthread_join(pthread_t pthread, void **thread_return) { int rval = 0; int status; + pthread_t pthread1; /* Block signals: */ _thread_kern_sig_block(&status); + /* 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; + } + + if (pthread1 == NULL) { + /* Point to the first thread in the dead thread list: */ + pthread1 = _thread_dead; + + /* Search for the thread to join to: */ + while (pthread1 != NULL && pthread1 != pthread) { + /* Point to the next thread: */ + pthread1 = pthread1->nxt; + } + } + + if (pthread1 == NULL) { + /* Return an error: */ + errno = ESRCH; + rval = -1; + /* Check if this thread has been detached: */ - if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) { + } else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) { /* Return an error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } /* Check if the thread is not dead: */ @@ -70,7 +96,7 @@ pthread_join(pthread_t pthread, void **thread_return) } } else { /* Return an error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } } else { diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c index 1db4da6..679b315 100644 --- a/lib/libpthread/thread/thr_kern.c +++ b/lib/libpthread/thread/thr_kern.c @@ -293,7 +293,7 @@ __asm__("fnsave %0": :"m"(*fdata)); * Change the threads state to allow * it to be restarted: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } } } @@ -823,14 +823,21 @@ __asm__("fnsave %0": :"m"(*fdata)); static void _thread_signal(pthread_t pthread, int sig) { + int done; long l; pthread_t new_pthread; struct sigaction act; void *arg; + /* + * Assume that the signal will not be dealt with according + * to the thread state: + */ + done = 0; + /* Process according to thread state: */ switch (pthread->state) { - /* States which do not change when a signal is trapped: */ + /* States which do not change when a signal is trapped: */ case PS_COND_WAIT: case PS_DEAD: case PS_FDLR_WAIT: @@ -844,7 +851,7 @@ _thread_signal(pthread_t pthread, int sig) /* Nothing to do here. */ break; - /* Wait for child: */ + /* Wait for child: */ case PS_WAIT_WAIT: /* Check if the signal is from a child exiting: */ if (sig == SIGCHLD) { @@ -852,42 +859,72 @@ _thread_signal(pthread_t pthread, int sig) _thread_seterrno(pthread, 0); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } else { /* Return the 'interrupted' error: */ _thread_seterrno(pthread, EINTR); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } + pthread->interrupted = 1; break; - /* - * States that are interrupted by the occurrence of a signal - * other than the scheduling alarm: - */ + /* Waiting on I/O for zero or more file descriptors: */ + case PS_SELECT_WAIT: + pthread->data.select_data->nfds = -1; + + /* Return the 'interrupted' error: */ + _thread_seterrno(pthread, EINTR); + pthread->interrupted = 1; + + /* Change the state of the thread to run: */ + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + break; + + /* + * States that are interrupted by the occurrence of a signal + * other than the scheduling alarm: + */ case PS_FDR_WAIT: case PS_FDW_WAIT: - case PS_SELECT_WAIT: case PS_SLEEP_WAIT: - case PS_SIGWAIT: /* Return the 'interrupted' error: */ _thread_seterrno(pthread, EINTR); + pthread->interrupted = 1; /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + + /* Return the signal number: */ + pthread->signo = sig; + break; + + /* Waiting on a signal: */ + case PS_SIGWAIT: + /* Change the state of the thread to run: */ + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + + /* Return the signal number: */ + pthread->signo = sig; + + /* Flag the signal as dealt with: */ + done = 1; break; } - /* Check if this signal is being ignored: */ - if (pthread->act[sig - 1].sa_handler == SIG_IGN) { + /* + * Check if this signal has been dealt with, or is being + * ignored: + */ + if (done || pthread->act[sig - 1].sa_handler == SIG_IGN) { /* Ignore the signal for this thread. */ } /* Check if this signal is to use the default handler: */ else if (pthread->act[sig - 1].sa_handler == SIG_DFL) { /* Process according to signal type: */ switch (sig) { - /* Signals which cause core dumps: */ + /* Signals which cause core dumps: */ case SIGQUIT: case SIGILL: case SIGTRAP: @@ -910,7 +947,7 @@ _thread_signal(pthread_t pthread, int sig) _thread_sys_sigreturn(&pthread->saved_sigcontext); break; - /* Default processing for other signals: */ + /* Default processing for other signals: */ default: /* * ### Default processing is a problem to resolve! @@ -983,6 +1020,8 @@ _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); diff --git a/lib/libpthread/thread/thr_kill.c b/lib/libpthread/thread/thr_kill.c new file mode 100644 index 0000000..eb2c6b7 --- /dev/null +++ b/lib/libpthread/thread/thr_kill.c @@ -0,0 +1,78 @@ +/* + * 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 rval = 0; + int status; + pthread_t p_pthread; + + /* Check for invalid signal numbers: */ + if (sig < 0 || sig >= NSIG) + /* Invalid signal: */ + rval = EINVAL; + else { + /* Assume that the search will succeed: */ + rval = 0; + + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* Search for the thread: */ + p_pthread = _thread_link_list; + while (p_pthread != NULL && p_pthread != pthread) { + p_pthread = p_pthread->nxt; + } + + /* Check if the thread was not found: */ + if (p_pthread == NULL) + /* Can't find the thread: */ + rval = ESRCH; + else + /* Increment the pending signal count: */ + p_pthread->sigpend[sig] += 1; + + /* Unblock signals: */ + _thread_kern_sig_unblock(status); + } + + /* Return the completion status: */ + return (rval); +} +#endif diff --git a/lib/libpthread/thread/thr_mutex.c b/lib/libpthread/thread/thr_mutex.c index dc9be3c..82a26e8 100644 --- a/lib/libpthread/thread/thr_mutex.c +++ b/lib/libpthread/thread/thr_mutex.c @@ -76,18 +76,18 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Process according to mutex type: */ switch (type) { - /* Fast mutex: */ + /* Fast mutex: */ case MUTEX_TYPE_FAST: /* Nothing to do here. */ break; - /* Counting mutex: */ + /* Counting mutex: */ case MUTEX_TYPE_COUNTING_FAST: /* Reset the mutex count: */ pmutex->m_data.m_count = 0; break; - /* Trap invalid mutex types: */ + /* Trap invalid mutex types: */ default: /* Return an invalid argument error: */ errno = EINVAL; @@ -130,18 +130,18 @@ pthread_mutex_destroy(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { - /* Fast mutex: */ + /* Fast mutex: */ case MUTEX_TYPE_FAST: /* Nothing to do here. */ break; - /* Counting mutex: */ + /* Counting mutex: */ case MUTEX_TYPE_COUNTING_FAST: /* Reset the mutex count: */ (*mutex)->m_data.m_count = 0; break; - /* Trap undefined mutex types: */ + /* Trap undefined mutex types: */ default: /* Return an invalid argument error: */ errno = EINVAL; @@ -348,7 +348,7 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) */ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { /* Allow the new owner of the mutex to run: */ - (*mutex)->m_owner->state = PS_RUNNING; + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); } break; @@ -371,7 +371,7 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) */ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { /* Allow the new owner of the mutex to run: */ - (*mutex)->m_owner->state = PS_RUNNING; + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); } break; diff --git a/lib/libpthread/thread/thr_mutexattr_destroy.c b/lib/libpthread/thread/thr_mutexattr_destroy.c new file mode 100644 index 0000000..cf2e09f --- /dev/null +++ b/lib/libpthread/thread/thr_mutexattr_destroy.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 <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) { + errno = EINVAL; + ret = -1; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h index a16bdea..064888f 100644 --- a/lib/libpthread/thread/thr_private.h +++ b/lib/libpthread/thread/thr_private.h @@ -59,6 +59,15 @@ #define PANIC(string) _thread_exit(__FILE__,__LINE__,string) /* + * State change macro: + */ +#define PTHREAD_NEW_STATE(thrd, newstate) { \ + (thrd)->state = newstate; \ + (thrd)->fname = __FILE__; \ + (thrd)->lineno = __LINE__; \ +} + +/* * Queue definitions. */ struct pthread_queue { @@ -206,19 +215,6 @@ struct sched_param { */ #define TIMESLICE_USEC 100000 -/* - * Flags. - */ -#define PTHREAD_DETACHED 0x1 -#define PTHREAD_SCOPE_SYSTEM 0x2 -#define PTHREAD_INHERIT_SCHED 0x4 -#define PTHREAD_NOFLOAT 0x8 - -#define PTHREAD_CREATE_DETACHED PTHREAD_DETACHED -#define PTHREAD_CREATE_JOINABLE 0 -#define PTHREAD_SCOPE_PROCESS 0 -#define PTHREAD_EXPLICIT_SCHED 0 - struct pthread_key { pthread_mutex_t mutex; long count; @@ -407,6 +403,15 @@ struct pthread { /* 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; char pthread_priority; @@ -416,6 +421,8 @@ struct pthread { /* Cleanup handlers Link List */ struct pthread_cleanup *cleanup; + char *fname; /* Ptr to source file name */ + int lineno; /* Source line number. */ }; /* @@ -426,7 +433,7 @@ struct pthread { SCLASS struct pthread _thread_kern_thread; /* Ptr to the thread structure for the running thread: */ -SCLASS struct pthread *_thread_run +SCLASS struct pthread * volatile _thread_run #ifdef GLOBAL_PTHREAD_PRIVATE = &_thread_kern_thread; #else @@ -437,7 +444,7 @@ SCLASS struct pthread *_thread_run * Ptr to the thread running in single-threaded mode or NULL if * running multi-threaded (default POSIX behaviour). */ -SCLASS struct pthread *_thread_single +SCLASS struct pthread * volatile _thread_single #ifdef GLOBAL_PTHREAD_PRIVATE = NULL; #else @@ -445,7 +452,7 @@ SCLASS struct pthread *_thread_single #endif /* Ptr to the first thread in the thread linked list: */ -SCLASS struct pthread *_thread_link_list +SCLASS struct pthread * volatile _thread_link_list #ifdef GLOBAL_PTHREAD_PRIVATE = NULL; #else @@ -481,7 +488,7 @@ SCLASS struct timeval kern_inc_prio_time #endif /* Dead threads: */ -SCLASS struct pthread *_thread_dead +SCLASS struct pthread * volatile _thread_dead #ifdef GLOBAL_PTHREAD_PRIVATE = NULL; #else @@ -505,7 +512,7 @@ SCLASS struct pthread_attr pthread_attr_default ; #endif -/* Default thread attributes: */ +/* Default mutex attributes: */ SCLASS struct pthread_mutex_attr pthread_mutexattr_default #ifdef GLOBAL_PTHREAD_PRIVATE = { MUTEX_TYPE_FAST, 0 }; @@ -513,6 +520,21 @@ SCLASS struct pthread_mutex_attr pthread_mutexattr_default ; #endif +/* Default condition variable attributes: */ +SCLASS struct pthread_cond_attr pthread_condattr_default +#ifdef GLOBAL_PTHREAD_PRIVATE += { COND_TYPE_FAST, 0 }; +#else +; +#endif + +/* + * 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. + */ +SCLASS int _pthread_stdio_flags[3]; + /* File table information: */ SCLASS struct fd_table_entry **_thread_fd_table #ifdef GLOBAL_PTHREAD_PRIVATE @@ -558,7 +580,6 @@ void _thread_kern_sched_state(enum pthread_state,char *fname,int lineno); void _thread_kern_set_timeout(struct timespec *); void _thread_kern_sig_block(int *); void _thread_kern_sig_unblock(int); -void _thread_cleanup_pop(int); void _thread_sig_handler(int, int, struct sigcontext *); void _thread_start(void); void _thread_start_sig_handler(void); diff --git a/lib/libpthread/thread/thr_read.c b/lib/libpthread/thread/thr_read.c index 9158844..504143d 100644 --- a/lib/libpthread/thread/thr_read.c +++ b/lib/libpthread/thread/thr_read.c @@ -42,22 +42,31 @@ ssize_t read(int fd, void *buf, size_t nbytes) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read: */ + if ((ret = _thread_fd_lock(fd, FD_READ, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking read syscall: */ while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* 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) { ret = -1; break; } @@ -65,9 +74,7 @@ read(int fd, void *buf, size_t nbytes) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_READ); - } + _thread_fd_unlock(fd, FD_READ); } return (ret); } diff --git a/lib/libpthread/thread/thr_readv.c b/lib/libpthread/thread/thr_readv.c index acb72ac..fed418b 100644 --- a/lib/libpthread/thread/thr_readv.c +++ b/lib/libpthread/thread/thr_readv.c @@ -42,22 +42,31 @@ ssize_t readv(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read: */ + if ((ret = _thread_fd_lock(fd, FD_READ, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking readv syscall: */ while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* 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) { ret = -1; break; } @@ -65,9 +74,7 @@ readv(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_READ); - } + _thread_fd_unlock(fd, FD_READ); } return (ret); } diff --git a/lib/libpthread/thread/thr_resume_np.c b/lib/libpthread/thread/thr_resume_np.c index a254814..934df58 100644 --- a/lib/libpthread/thread/thr_resume_np.c +++ b/lib/libpthread/thread/thr_resume_np.c @@ -49,21 +49,21 @@ pthread_resume_np(pthread_t thread) /* Found the thread. Is it suspended? */ if (pthread->state == PS_SUSPENDED) { /* Allow the thread to run. */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); ret = 0; } else if (pthread->state == PS_RUNNING) { /* Thread is already running. */ ret = 0; } else { /* Thread is in some other state. */ - _thread_seterrno(_thread_run,EINVAL); + errno = EINVAL; } } } /* Check if thread was not found. */ if (ret == -1) { /* No such thread */ - _thread_seterrno(_thread_run,ESRCH); + errno = ESRCH; } return(ret); } diff --git a/lib/libpthread/thread/thr_setprio.c b/lib/libpthread/thread/thr_setprio.c index e052ec3..4b49ed0 100644 --- a/lib/libpthread/thread/thr_setprio.c +++ b/lib/libpthread/thread/thr_setprio.c @@ -45,7 +45,7 @@ pthread_setprio(pthread_t pthread, int prio) /* Check if the priority is invalid: */ if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } else { /* Block signals: */ @@ -63,7 +63,7 @@ pthread_setprio(pthread_t pthread, int prio) /* Check if the thread pointer is NULL: */ if (pthread == NULL || pthread_p == NULL) { /* Return a 'search' error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } else { /* Set the thread priority: */ diff --git a/lib/libpthread/thread/thr_sig.c b/lib/libpthread/thread/thr_sig.c index c3ec191..e73d5a2 100644 --- a/lib/libpthread/thread/thr_sig.c +++ b/lib/libpthread/thread/thr_sig.c @@ -97,7 +97,7 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) _thread_seterrno(pthread, 0); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } } diff --git a/lib/libpthread/thread/thr_sigaction.c b/lib/libpthread/thread/thr_sigaction.c index c733667..dd08405 100644 --- a/lib/libpthread/thread/thr_sigaction.c +++ b/lib/libpthread/thread/thr_sigaction.c @@ -45,7 +45,7 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact) /* Check if the signal number is out of range: */ if (sig < 1 || sig > NSIG) { /* Return an invalid argument: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; ret = -1; } else { /* diff --git a/lib/libpthread/thread/thr_sigmask.c b/lib/libpthread/thread/thr_sigmask.c new file mode 100644 index 0000000..94f64cb --- /dev/null +++ b/lib/libpthread/thread/thr_sigmask.c @@ -0,0 +1,92 @@ +/* + * 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; + int status; + + /* Check if the existing signal process mask is to be returned: */ + if (oset != NULL) { + /* Return the current mask: */ + *oset = _thread_run->sigmask; + } + /* Check if a new signal set was provided by the caller: */ + if (set != NULL) { + /* Block signals while the signal mask is changed: */ + _thread_kern_sig_block(&status); + + /* Process according to what to do: */ + switch (how) { + /* Block signals: */ + case SIG_BLOCK: + /* Add signals to the existing mask: */ + _thread_run->sigmask |= *set; + break; + + /* Unblock signals: */ + case SIG_UNBLOCK: + /* Clear signals from the existing mask: */ + _thread_run->sigmask &= ~(*set); + break; + + /* Set the signal process mask: */ + case SIG_SETMASK: + /* Set the new mask: */ + _thread_run->sigmask = *set; + break; + + /* Trap invalid actions: */ + default: + /* Return an invalid argument: */ + errno = EINVAL; + ret = -1; + break; + } + + /* + * Schedule the next thread in case there are signals that + * now need to be acted on: + */ + _thread_kern_sched(NULL); + } + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libpthread/thread/thr_sigprocmask.c b/lib/libpthread/thread/thr_sigprocmask.c index d6e3197..b4a8d84 100644 --- a/lib/libpthread/thread/thr_sigprocmask.c +++ b/lib/libpthread/thread/thr_sigprocmask.c @@ -54,28 +54,28 @@ sigprocmask(int how, const sigset_t * set, sigset_t * oset) /* Process according to what to do: */ switch (how) { - /* Block signals: */ + /* Block signals: */ case SIG_BLOCK: /* Add signals to the existing mask: */ _thread_run->sigmask |= *set; break; - /* Unblock signals: */ + /* Unblock signals: */ case SIG_UNBLOCK: /* Clear signals from the existing mask: */ _thread_run->sigmask &= ~(*set); break; - /* Set the signal process mask: */ + /* Set the signal process mask: */ case SIG_SETMASK: /* Set the new mask: */ _thread_run->sigmask = *set; break; - /* Trap invalid actions: */ + /* Trap invalid actions: */ default: /* Return an invalid argument: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; ret = -1; break; } diff --git a/lib/libpthread/thread/thr_sigsuspend.c b/lib/libpthread/thread/thr_sigsuspend.c index a26b6b9..14cf74b 100644 --- a/lib/libpthread/thread/thr_sigsuspend.c +++ b/lib/libpthread/thread/thr_sigsuspend.c @@ -57,7 +57,7 @@ sigsuspend(const sigset_t * set) _thread_run->sigmask = oset; } else { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; } /* Return the completion status: */ diff --git a/lib/libpthread/thread/thr_sigwait.c b/lib/libpthread/thread/thr_sigwait.c new file mode 100644 index 0000000..4f95190 --- /dev/null +++ b/lib/libpthread/thread/thr_sigwait.c @@ -0,0 +1,73 @@ +/* + * 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; + int status; + sigset_t oset; + + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* 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__); + + /* Block signals again: */ + _thread_kern_sig_block(NULL); + + /* Return the signal number to the caller: */ + *sig = _thread_run->signo; + + /* Restore the signal mask: */ + _thread_run->sigmask = oset; + + /* Unblock signals: */ + _thread_kern_sig_unblock(status); + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libpthread/thread/thr_spec.c b/lib/libpthread/thread/thr_spec.c index 4447a75..8d06c52 100644 --- a/lib/libpthread/thread/thr_spec.c +++ b/lib/libpthread/thread/thr_spec.c @@ -209,7 +209,7 @@ pthread_getspecific(pthread_key_t key) /* Check for errors: */ if (pthread == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; data = NULL; } /* Check if there is specific data: */ diff --git a/lib/libpthread/thread/thr_suspend_np.c b/lib/libpthread/thread/thr_suspend_np.c index fb90c1d..d065b73 100644 --- a/lib/libpthread/thread/thr_suspend_np.c +++ b/lib/libpthread/thread/thr_suspend_np.c @@ -53,14 +53,14 @@ pthread_suspend_np(pthread_t thread) _thread_seterrno(pthread,EINTR); } /* Suspend the thread. */ - pthread->state = PS_SUSPENDED; + PTHREAD_NEW_STATE(pthread,PS_SUSPENDED); ret = 0; } } /* Check if thread was not found. */ if (ret == -1) { /* No such thread */ - _thread_seterrno(_thread_run,ESRCH); + errno = ESRCH; } return(ret); } diff --git a/lib/libpthread/thread/thr_write.c b/lib/libpthread/thread/thr_write.c index fb69129..2baa19f 100644 --- a/lib/libpthread/thread/thr_write.c +++ b/lib/libpthread/thread/thr_write.c @@ -42,22 +42,31 @@ ssize_t write(int fd, const void *buf, size_t nbytes) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking write syscall: */ while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* 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) { ret = -1; break; } @@ -65,9 +74,7 @@ write(int fd, const void *buf, size_t nbytes) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); } diff --git a/lib/libpthread/thread/thr_writev.c b/lib/libpthread/thread/thr_writev.c index f40e611..2a3c0c8 100644 --- a/lib/libpthread/thread/thr_writev.c +++ b/lib/libpthread/thread/thr_writev.c @@ -42,22 +42,31 @@ ssize_t writev(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking writev syscall: */ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* 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) { ret = -1; break; } @@ -65,9 +74,7 @@ writev(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); } |