Submitted by: John Birrell

uthreads update from the author.
This commit is contained in:
Julian Elischer 1997-02-05 23:26:09 +00:00
parent 3b576b3e5e
commit c840cec7c5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=22315
128 changed files with 3061 additions and 569 deletions

View File

@ -66,6 +66,19 @@
/* #define _POSIX_THREAD_PROCESS_SHARED */
#define _POSIX_THREAD_SAFE_FUNCTIONS
/*
* Flags for threads and thread attributes.
*/
#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
/*
* Forward structure definitions.
*
@ -127,8 +140,8 @@ struct pthread_once {
/*
* Default attribute arguments.
*/
#define pthread_condattr_default NULL
#ifndef PTHREAD_KERNEL
#define pthread_condattr_default NULL
#define pthread_mutexattr_default NULL
#define pthread_attr_default NULL
#endif
@ -162,7 +175,7 @@ int pthread_attr_setstacksize __P((pthread_attr_t *, size_t));
int pthread_attr_setstackaddr __P((pthread_attr_t *, void *));
int pthread_attr_setdetachstate __P((pthread_attr_t *, int));
void pthread_cleanup_pop __P((int execute));
int pthread_cleanup_push __P((void (*routine) (void *),
void pthread_cleanup_push __P((void (*routine) (void *),
void *routine_arg));
int pthread_condattr_destroy __P((pthread_condattr_t *attr));
int pthread_condattr_init __P((pthread_condattr_t *attr));

View File

@ -117,7 +117,7 @@ __ttyname_basic(int fd)
pthread_mutex_lock(&ttyname_lock);
if (ttyname_init == 0) {
if (pthread_keycreate(&ttyname_key, free)) {
if (pthread_key_create(&ttyname_key, free)) {
pthread_mutex_unlock(&ttyname_lock);
return (NULL);
}

View File

@ -1109,12 +1109,10 @@ const time_t * const timep;
}
}
pthread_mutex_unlock(&localtime_mutex);
if ((p_tm = pthread_getspecific(localtime_key)) != 0) {
return(NULL);
} else if (p_tm == NULL) {
if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) == NULL) {
p_tm = pthread_getspecific(localtime_key);
if (p_tm == NULL) {
if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) == NULL)
return(NULL);
}
pthread_setspecific(localtime_key, p_tm);
}
pthread_mutex_lock(&lcl_mutex);

View File

@ -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>

View File

@ -3,18 +3,18 @@
# machine-independent net sources
.PATH: ${.CURDIR}/../libc/${MACHINE}/net ${.CURDIR}/../libc/net
SRCS+= addr2ascii.c ascii2addr.c \
SRCS+= addr2ascii.c ascii2addr.c base64.c \
gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \
getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \
getproto.c getprotoent.c getprotoname.c getservbyname.c \
getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \
inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \
inet_net_ntop.c inet_net_pton.c inet_neta.c \
inet_pton.c linkaddr.c map_v4v6.c nsap_addr.c \
rcmd.c recv.c res_comp.c res_data.c res_debug.c \
res_init.c res_mkquery.c res_query.c res_send.c send.c ether_addr.c \
# iso_addr.c
# ns_addr.c ns_ntoa.c
res_init.c res_mkquery.c res_query.c res_send.c res_stubs.c \
send.c ether_addr.c \
ns_addr.c ns_ntoa.c
# machine-dependent net sources
.include "${.CURDIR}/../libc/${MACHINE}/net/Makefile.inc"

View File

@ -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 \

View File

@ -58,6 +58,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.
*/
@ -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);

View File

@ -44,7 +44,7 @@ accept(int fd, struct sockaddr * name, int *namelen)
{
int ret;
/* Lock teh file descriptor: */
/* Lock the file descriptor: */
if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
/* Enter a loop to wait for a connection request: */
while ((ret = _thread_sys_accept(fd, name, namelen)) < 0) {
@ -52,6 +52,8 @@ accept(int fd, struct sockaddr * name, int *namelen)
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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -47,23 +47,26 @@ _thread_fd_table_init(int fd)
_thread_kern_sig_block(&status);
/* Check if the file descriptor is out of range: */
if (fd < 0 || fd >= _thread_dtablesize) {
if (fd < 0 || fd >= _thread_dtablesize)
/* Return a bad file descriptor error: */
errno = EBADF;
ret = -1;
}
ret = EBADF;
/*
* 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 ((_thread_fd_table[fd] = (struct fd_table_entry *) malloc(sizeof(struct fd_table_entry))) == NULL) {
else if ((_thread_fd_table[fd] = (struct fd_table_entry *)
malloc(sizeof(struct fd_table_entry))) == NULL)
/* Return a bad file descriptor error: */
errno = EBADF;
ret = -1;
} else {
ret = EBADF;
else {
/* Assume that the operation will succeed: */
ret = 0;
/* Initialise the file locks: */
_thread_fd_table[fd]->r_owner = NULL;
_thread_fd_table[fd]->w_owner = NULL;
@ -79,16 +82,32 @@ _thread_fd_table_init(int fd)
_thread_queue_init(&_thread_fd_table[fd]->w_queue);
/* Get the flags for the file: */
if ((_thread_fd_table[fd]->flags = _thread_sys_fcntl(fd, F_GETFL, 0)) == -1) {
ret = -1;
if (fd >= 3 && (_thread_fd_table[fd]->flags =
_thread_sys_fcntl(fd, F_GETFL, 0)) == -1)
ret = errno;
/* Make the file descriptor non-blocking: */
} else {
_thread_sys_fcntl(fd, F_SETFL, _thread_fd_table[fd]->flags | O_NONBLOCK);
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.
*/
_thread_fd_table[fd]->flags =
_pthread_stdio_flags[fd];
/* Make the file descriptor non-blocking: */
if (_thread_sys_fcntl(fd, F_SETFL,
_thread_fd_table[fd]->flags | O_NONBLOCK) == -1)
ret = errno;
}
/* Check if one of the fcntl calls failed: */
if (ret == -1) {
if (ret != 0) {
/* Free the file descriptor table entry: */
free(_thread_fd_table[fd]);
_thread_fd_table[fd] = NULL;
@ -143,7 +162,7 @@ _thread_fd_unlock(int fd, int lock_type)
* Set the state of the new owner of
* the thread to running:
*/
_thread_fd_table[fd]->r_owner->state = PS_RUNNING;
PTHREAD_NEW_STATE(_thread_fd_table[fd]->r_owner,PS_RUNNING);
/*
* Reset the number of read locks.
@ -181,7 +200,7 @@ _thread_fd_unlock(int fd, int lock_type)
* Set the state of the new owner of
* the thread to running:
*/
_thread_fd_table[fd]->w_owner->state = PS_RUNNING;
PTHREAD_NEW_STATE(_thread_fd_table[fd]->w_owner,PS_RUNNING);
/*
* Reset the number of write locks.

View File

@ -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: */

View File

@ -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++) {
/*

View File

@ -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");
}

View File

@ -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);
/* Check if this thread has been detached: */
if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
/* 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: */
_thread_seterrno(_thread_run, ESRCH);
errno = ESRCH;
rval = -1;
/* Check if this thread has been detached: */
} else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
/* Return an error: */
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 {

View File

@ -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:
*/
case PS_FDR_WAIT:
case PS_FDW_WAIT:
/* Waiting on I/O for zero or more file descriptors: */
case PS_SELECT_WAIT:
case PS_SLEEP_WAIT:
case PS_SIGWAIT:
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->state = PS_RUNNING;
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_SLEEP_WAIT:
/* 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);
/* 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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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: */

View File

@ -62,7 +62,7 @@ shutdown(int fd, int how)
}
break;
default:
_thread_seterrno(_thread_run, EBADF);
errno = EBADF;
ret = -1;
break;
}

View File

@ -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);
}
}

View File

@ -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 {
/*

View File

@ -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

View File

@ -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;
}

View File

@ -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: */

View File

@ -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

View File

@ -41,19 +41,13 @@ int
socketpair(int af, int type, int protocol, int pair[2])
{
int ret;
if (!((ret = _thread_sys_socketpair(af, type, protocol, pair)) < 0)) {
int tmp_flags;
tmp_flags = _thread_sys_fcntl(pair[0], F_GETFL, 0);
_thread_sys_fcntl(pair[0], F_SETFL, tmp_flags | O_NONBLOCK);
_thread_fd_table[pair[0]]->flags = tmp_flags;
tmp_flags = _thread_sys_fcntl(pair[1], F_GETFL, 0);
_thread_sys_fcntl(pair[1], F_SETFL, tmp_flags | O_NONBLOCK);
_thread_fd_table[pair[1]]->flags = tmp_flags;
return (ret);
}
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 (-1);
}
#endif

View File

@ -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: */

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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>

View File

@ -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 \

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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: */

View File

@ -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++) {
/*

View File

@ -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");
}

View File

@ -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);
/* Check if this thread has been detached: */
if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
/* 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: */
_thread_seterrno(_thread_run, ESRCH);
errno = ESRCH;
rval = -1;
/* Check if this thread has been detached: */
} else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
/* Return an error: */
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 {

View File

@ -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:
*/
case PS_FDR_WAIT:
case PS_FDW_WAIT:
/* Waiting on I/O for zero or more file descriptors: */
case PS_SELECT_WAIT:
case PS_SLEEP_WAIT:
case PS_SIGWAIT:
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->state = PS_RUNNING;
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_SLEEP_WAIT:
/* 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);
/* 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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -58,6 +58,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.
*/
@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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: */

View File

@ -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);
}
}

View File

@ -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 {
/*

View File

@ -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

View File

@ -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;
}

View File

@ -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: */

View File

@ -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

View File

@ -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: */

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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>

View File

@ -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 \

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

Some files were not shown because too many files have changed in this diff Show More