From c840cec7c5df4547d37d9ca025553099b834c1aa Mon Sep 17 00:00:00 2001 From: Julian Elischer Date: Wed, 5 Feb 1997 23:26:09 +0000 Subject: [PATCH] Submitted by: John Birrell uthreads update from the author. --- include/pthread.h | 17 +++- lib/libc/gen/ttyname.c | 2 +- lib/libc/stdtime/localtime.c | 8 +- lib/libc_r/Makefile | 10 -- lib/libc_r/net/Makefile.inc | 10 +- lib/libc_r/uthread/Makefile.inc | 10 ++ lib/libc_r/uthread/pthread_private.h | 59 ++++++++---- lib/libc_r/uthread/uthread_accept.c | 4 +- lib/libc_r/uthread/uthread_attr_destroy.c | 16 +++- .../uthread/uthread_attr_getdetachstate.c | 57 ++++++++++++ .../uthread/uthread_attr_getstackaddr.c | 52 +++++++++++ .../uthread/uthread_attr_getstacksize.c | 52 +++++++++++ lib/libc_r/uthread/uthread_attr_init.c | 13 ++- .../uthread/uthread_attr_setdetachstate.c | 59 ++++++++++++ .../uthread/uthread_attr_setstackaddr.c | 52 +++++++++++ .../uthread/uthread_attr_setstacksize.c | 10 +- lib/libc_r/uthread/uthread_clean.c | 11 +-- lib/libc_r/uthread/uthread_cond.c | 4 +- lib/libc_r/uthread/uthread_condattr_destroy.c | 52 +++++++++++ lib/libc_r/uthread/uthread_condattr_init.c | 58 ++++++++++++ lib/libc_r/uthread/uthread_create.c | 6 +- lib/libc_r/uthread/uthread_detach.c | 6 +- lib/libc_r/uthread/uthread_exit.c | 10 +- lib/libc_r/uthread/uthread_fd.c | 51 ++++++---- lib/libc_r/uthread/uthread_getprio.c | 2 +- lib/libc_r/uthread/uthread_info.c | 13 ++- lib/libc_r/uthread/uthread_init.c | 20 +++- lib/libc_r/uthread/uthread_join.c | 34 ++++++- lib/libc_r/uthread/uthread_kern.c | 75 +++++++++++---- lib/libc_r/uthread/uthread_kill.c | 78 ++++++++++++++++ lib/libc_r/uthread/uthread_mutex.c | 16 ++-- .../uthread/uthread_mutexattr_destroy.c | 52 +++++++++++ lib/libc_r/uthread/uthread_read.c | 37 +++++--- lib/libc_r/uthread/uthread_readv.c | 37 +++++--- lib/libc_r/uthread/uthread_resume_np.c | 6 +- lib/libc_r/uthread/uthread_setprio.c | 4 +- lib/libc_r/uthread/uthread_shutdown.c | 2 +- lib/libc_r/uthread/uthread_sig.c | 2 +- lib/libc_r/uthread/uthread_sigaction.c | 2 +- lib/libc_r/uthread/uthread_sigmask.c | 92 +++++++++++++++++++ lib/libc_r/uthread/uthread_sigprocmask.c | 10 +- lib/libc_r/uthread/uthread_sigsuspend.c | 2 +- lib/libc_r/uthread/uthread_sigwait.c | 73 +++++++++++++++ lib/libc_r/uthread/uthread_socketpair.c | 20 ++-- lib/libc_r/uthread/uthread_spec.c | 2 +- lib/libc_r/uthread/uthread_suspend_np.c | 4 +- lib/libc_r/uthread/uthread_write.c | 37 +++++--- lib/libc_r/uthread/uthread_writev.c | 37 +++++--- lib/libkse/Makefile | 10 -- lib/libkse/thread/Makefile.inc | 10 ++ lib/libkse/thread/thr_attr_destroy.c | 16 +++- lib/libkse/thread/thr_attr_getdetachstate.c | 57 ++++++++++++ lib/libkse/thread/thr_attr_getstackaddr.c | 52 +++++++++++ lib/libkse/thread/thr_attr_getstacksize.c | 52 +++++++++++ lib/libkse/thread/thr_attr_init.c | 13 ++- lib/libkse/thread/thr_attr_setdetachstate.c | 59 ++++++++++++ lib/libkse/thread/thr_attr_setstackaddr.c | 52 +++++++++++ lib/libkse/thread/thr_attr_setstacksize.c | 10 +- lib/libkse/thread/thr_clean.c | 11 +-- lib/libkse/thread/thr_cond.c | 4 +- lib/libkse/thread/thr_condattr_destroy.c | 52 +++++++++++ lib/libkse/thread/thr_condattr_init.c | 58 ++++++++++++ lib/libkse/thread/thr_create.c | 6 +- lib/libkse/thread/thr_detach.c | 6 +- lib/libkse/thread/thr_exit.c | 10 +- lib/libkse/thread/thr_getprio.c | 2 +- lib/libkse/thread/thr_info.c | 13 ++- lib/libkse/thread/thr_init.c | 20 +++- lib/libkse/thread/thr_join.c | 34 ++++++- lib/libkse/thread/thr_kern.c | 75 +++++++++++---- lib/libkse/thread/thr_kill.c | 78 ++++++++++++++++ lib/libkse/thread/thr_mutex.c | 16 ++-- lib/libkse/thread/thr_mutexattr_destroy.c | 52 +++++++++++ lib/libkse/thread/thr_private.h | 59 ++++++++---- lib/libkse/thread/thr_read.c | 37 +++++--- lib/libkse/thread/thr_readv.c | 37 +++++--- lib/libkse/thread/thr_resume_np.c | 6 +- lib/libkse/thread/thr_setprio.c | 4 +- lib/libkse/thread/thr_sig.c | 2 +- lib/libkse/thread/thr_sigaction.c | 2 +- lib/libkse/thread/thr_sigmask.c | 92 +++++++++++++++++++ lib/libkse/thread/thr_sigprocmask.c | 10 +- lib/libkse/thread/thr_sigsuspend.c | 2 +- lib/libkse/thread/thr_sigwait.c | 73 +++++++++++++++ lib/libkse/thread/thr_spec.c | 2 +- lib/libkse/thread/thr_suspend_np.c | 4 +- lib/libkse/thread/thr_write.c | 37 +++++--- lib/libkse/thread/thr_writev.c | 37 +++++--- lib/libpthread/Makefile | 10 -- lib/libpthread/thread/Makefile.inc | 10 ++ lib/libpthread/thread/thr_attr_destroy.c | 16 +++- .../thread/thr_attr_getdetachstate.c | 57 ++++++++++++ lib/libpthread/thread/thr_attr_getstackaddr.c | 52 +++++++++++ lib/libpthread/thread/thr_attr_getstacksize.c | 52 +++++++++++ lib/libpthread/thread/thr_attr_init.c | 13 ++- .../thread/thr_attr_setdetachstate.c | 59 ++++++++++++ lib/libpthread/thread/thr_attr_setstackaddr.c | 52 +++++++++++ lib/libpthread/thread/thr_attr_setstacksize.c | 10 +- lib/libpthread/thread/thr_clean.c | 11 +-- lib/libpthread/thread/thr_cond.c | 4 +- lib/libpthread/thread/thr_condattr_destroy.c | 52 +++++++++++ lib/libpthread/thread/thr_condattr_init.c | 58 ++++++++++++ lib/libpthread/thread/thr_create.c | 6 +- lib/libpthread/thread/thr_detach.c | 6 +- lib/libpthread/thread/thr_exit.c | 10 +- lib/libpthread/thread/thr_getprio.c | 2 +- lib/libpthread/thread/thr_info.c | 13 ++- lib/libpthread/thread/thr_init.c | 20 +++- lib/libpthread/thread/thr_join.c | 34 ++++++- lib/libpthread/thread/thr_kern.c | 75 +++++++++++---- lib/libpthread/thread/thr_kill.c | 78 ++++++++++++++++ lib/libpthread/thread/thr_mutex.c | 16 ++-- lib/libpthread/thread/thr_mutexattr_destroy.c | 52 +++++++++++ lib/libpthread/thread/thr_private.h | 59 ++++++++---- lib/libpthread/thread/thr_read.c | 37 +++++--- lib/libpthread/thread/thr_readv.c | 37 +++++--- lib/libpthread/thread/thr_resume_np.c | 6 +- lib/libpthread/thread/thr_setprio.c | 4 +- lib/libpthread/thread/thr_sig.c | 2 +- lib/libpthread/thread/thr_sigaction.c | 2 +- lib/libpthread/thread/thr_sigmask.c | 92 +++++++++++++++++++ lib/libpthread/thread/thr_sigprocmask.c | 10 +- lib/libpthread/thread/thr_sigsuspend.c | 2 +- lib/libpthread/thread/thr_sigwait.c | 73 +++++++++++++++ lib/libpthread/thread/thr_spec.c | 2 +- lib/libpthread/thread/thr_suspend_np.c | 4 +- lib/libpthread/thread/thr_write.c | 37 +++++--- lib/libpthread/thread/thr_writev.c | 37 +++++--- 128 files changed, 3061 insertions(+), 569 deletions(-) create mode 100644 lib/libc_r/uthread/uthread_attr_getdetachstate.c create mode 100644 lib/libc_r/uthread/uthread_attr_getstackaddr.c create mode 100644 lib/libc_r/uthread/uthread_attr_getstacksize.c create mode 100644 lib/libc_r/uthread/uthread_attr_setdetachstate.c create mode 100644 lib/libc_r/uthread/uthread_attr_setstackaddr.c create mode 100644 lib/libc_r/uthread/uthread_condattr_destroy.c create mode 100644 lib/libc_r/uthread/uthread_condattr_init.c create mode 100644 lib/libc_r/uthread/uthread_kill.c create mode 100644 lib/libc_r/uthread/uthread_mutexattr_destroy.c create mode 100644 lib/libc_r/uthread/uthread_sigmask.c create mode 100644 lib/libc_r/uthread/uthread_sigwait.c create mode 100644 lib/libkse/thread/thr_attr_getdetachstate.c create mode 100644 lib/libkse/thread/thr_attr_getstackaddr.c create mode 100644 lib/libkse/thread/thr_attr_getstacksize.c create mode 100644 lib/libkse/thread/thr_attr_setdetachstate.c create mode 100644 lib/libkse/thread/thr_attr_setstackaddr.c create mode 100644 lib/libkse/thread/thr_condattr_destroy.c create mode 100644 lib/libkse/thread/thr_condattr_init.c create mode 100644 lib/libkse/thread/thr_kill.c create mode 100644 lib/libkse/thread/thr_mutexattr_destroy.c create mode 100644 lib/libkse/thread/thr_sigmask.c create mode 100644 lib/libkse/thread/thr_sigwait.c create mode 100644 lib/libpthread/thread/thr_attr_getdetachstate.c create mode 100644 lib/libpthread/thread/thr_attr_getstackaddr.c create mode 100644 lib/libpthread/thread/thr_attr_getstacksize.c create mode 100644 lib/libpthread/thread/thr_attr_setdetachstate.c create mode 100644 lib/libpthread/thread/thr_attr_setstackaddr.c create mode 100644 lib/libpthread/thread/thr_condattr_destroy.c create mode 100644 lib/libpthread/thread/thr_condattr_init.c create mode 100644 lib/libpthread/thread/thr_kill.c create mode 100644 lib/libpthread/thread/thr_mutexattr_destroy.c create mode 100644 lib/libpthread/thread/thr_sigmask.c create mode 100644 lib/libpthread/thread/thr_sigwait.c diff --git a/include/pthread.h b/include/pthread.h index 0b01d8e9d485..8baae8c625d8 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -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)); diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c index 3c87d69239d8..b2f3f79b1570 100644 --- a/lib/libc/gen/ttyname.c +++ b/lib/libc/gen/ttyname.c @@ -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); } diff --git a/lib/libc/stdtime/localtime.c b/lib/libc/stdtime/localtime.c index 5fe9f9845f28..3438cc673e72 100644 --- a/lib/libc/stdtime/localtime.c +++ b/lib/libc/stdtime/localtime.c @@ -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); diff --git a/lib/libc_r/Makefile b/lib/libc_r/Makefile index f1584ff73034..dab62107abaf 100644 --- a/lib/libc_r/Makefile +++ b/lib/libc_r/Makefile @@ -11,7 +11,6 @@ SHLIB_MINOR= 0 CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE -I${.CURDIR}/uthread AINC= -I${.CURDIR}/../libc/${MACHINE} -I${.CURDIR}/uthread -CLEANFILES+=tags PRECIOUSLIB= yes .include "${.CURDIR}/db/Makefile.inc" @@ -38,13 +37,4 @@ CFLAGS+= -DYP .endif .include "${.CURDIR}/${MACHINE}/sys/Makefile.inc" -beforeinstall: tags - ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc_r.tags - -tags: ${SRCS} - ctags ${.ALLSRC:M*.c} - egrep -o "^ENTRY(.*)|^FUNC(.*)|^SYSCALL(.*)" ${.ALLSRC:M*.s} | \ - sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \ - >> tags; sort -o tags tags - .include diff --git a/lib/libc_r/net/Makefile.inc b/lib/libc_r/net/Makefile.inc index 9e41a606d7fa..bb7e4beb075a 100644 --- a/lib/libc_r/net/Makefile.inc +++ b/lib/libc_r/net/Makefile.inc @@ -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" diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc index c275b5f4d092..cd85700d2beb 100644 --- a/lib/libc_r/uthread/Makefile.inc +++ b/lib/libc_r/uthread/Makefile.inc @@ -9,13 +9,20 @@ SRCS+= \ uthread_accept.c \ uthread_attr_destroy.c \ uthread_attr_init.c \ + uthread_attr_getdetachstate.c \ + uthread_attr_getstackaddr.c \ + uthread_attr_getstacksize.c \ uthread_attr_setcreatesuspend_np.c \ + uthread_attr_setdetachstate.c \ + uthread_attr_setstackaddr.c \ uthread_attr_setstacksize.c \ uthread_autoinit.cc \ uthread_bind.c \ uthread_clean.c \ uthread_close.c \ uthread_cond.c \ + uthread_condattr_destroy.c \ + uthread_condattr_init.c \ uthread_connect.c \ uthread_create.c \ uthread_detach.c \ @@ -44,12 +51,14 @@ SRCS+= \ uthread_ioctl.c \ uthread_join.c \ uthread_kern.c \ + uthread_kill.c \ uthread_listen.c \ uthread_longjmp.c \ uthread_mattr_init.c \ uthread_mattr_kind_np.c \ uthread_multi_np.c \ uthread_mutex.c \ + uthread_mutexattr_destroy.c \ uthread_nanosleep.c \ uthread_once.c \ uthread_open.c \ @@ -71,6 +80,7 @@ SRCS+= \ uthread_sigaction.c \ uthread_sigblock.c \ uthread_single_np.c \ + uthread_sigmask.c \ uthread_signal.c \ uthread_sigprocmask.c \ uthread_sigsetmask.c \ diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h index a16bdea0387e..064888f1978e 100644 --- a/lib/libc_r/uthread/pthread_private.h +++ b/lib/libc_r/uthread/pthread_private.h @@ -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); diff --git a/lib/libc_r/uthread/uthread_accept.c b/lib/libc_r/uthread/uthread_accept.c index 2aa206efce66..e240cdecbf43 100644 --- a/lib/libc_r/uthread/uthread_accept.c +++ b/lib/libc_r/uthread/uthread_accept.c @@ -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); diff --git a/lib/libc_r/uthread/uthread_attr_destroy.c b/lib/libc_r/uthread/uthread_attr_destroy.c index be6b2a2d7dcb..1f4b2c8523c3 100644 --- a/lib/libc_r/uthread/uthread_attr_destroy.c +++ b/lib/libc_r/uthread/uthread_attr_destroy.c @@ -39,11 +39,19 @@ int pthread_attr_destroy(pthread_attr_t *attr) { int ret; - if (attr == NULL || *attr == NULL) { - errno = EINVAL; - ret = -1; - } else { + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL) + /* Invalid argument: */ + ret = EINVAL; + else { + /* Free the memory allocated to the attribute object: */ free(*attr); + + /* + * Leave the attribute pointer NULL now that the memory + * has been freed: + */ *attr = NULL; ret = 0; } diff --git a/lib/libc_r/uthread/uthread_attr_getdetachstate.c b/lib/libc_r/uthread/uthread_attr_getdetachstate.c new file mode 100644 index 000000000000..4715cb6f2424 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_getdetachstate.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || detachstate == NULL) + ret = EINVAL; + else { + /* Check if the detached flag is set: */ + if ((*attr)->flags & PTHREAD_DETACHED) + /* Return detached: */ + *detachstate = PTHREAD_CREATE_DETACHED; + else + /* Return joinable: */ + *detachstate = PTHREAD_CREATE_JOINABLE; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_getstackaddr.c b/lib/libc_r/uthread/uthread_attr_getstackaddr.c new file mode 100644 index 000000000000..1850a324c611 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_getstackaddr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + ret = EINVAL; + else { + /* Return the stack address: */ + *stackaddr = (*attr)->stackaddr_attr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_getstacksize.c b/lib/libc_r/uthread/uthread_attr_getstacksize.c new file mode 100644 index 000000000000..de81106083d4 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_getstacksize.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize == NULL) + ret = EINVAL; + else { + /* Return the stack size: */ + *stacksize = (*attr)->stacksize_attr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_init.c b/lib/libc_r/uthread/uthread_attr_init.c index 7dade978a48f..c64e29fed11c 100644 --- a/lib/libc_r/uthread/uthread_attr_init.c +++ b/lib/libc_r/uthread/uthread_attr_init.c @@ -41,11 +41,16 @@ int pthread_attr_init(pthread_attr_t *attr) { int ret; pthread_attr_t pattr; - if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) { - errno = ENOMEM; - ret = -1; - } else { + + /* Allocate memory for the attribute object: */ + if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) + /* Insufficient memory: */ + ret = ENOMEM; + else { + /* Initialise the attribute object with the defaults: */ memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr)); + + /* Return a pointer to the attribute object: */ *attr = pattr; ret = 0; } diff --git a/lib/libc_r/uthread/uthread_attr_setdetachstate.c b/lib/libc_r/uthread/uthread_attr_setdetachstate.c new file mode 100644 index 000000000000..6ec0dbc1c585 --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_setdetachstate.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || + (detachstate != PTHREAD_CREATE_DETACHED && + detachstate != PTHREAD_CREATE_JOINABLE)) + ret = EINVAL; + else { + /* Check if detached state: */ + if (detachstate == PTHREAD_CREATE_DETACHED) + /* Set the detached flag: */ + (*attr)->flags |= PTHREAD_DETACHED; + else + /* Reset the detached flag: */ + (*attr)->flags &= ~PTHREAD_DETACHED; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_setstackaddr.c b/lib/libc_r/uthread/uthread_attr_setstackaddr.c new file mode 100644 index 000000000000..ce54915d096d --- /dev/null +++ b/lib/libc_r/uthread/uthread_attr_setstackaddr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + ret = EINVAL; + else { + /* Save the stack address: */ + (*attr)->stackaddr_attr = stackaddr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_attr_setstacksize.c b/lib/libc_r/uthread/uthread_attr_setstacksize.c index 5e59798f579b..94e575e0dded 100644 --- a/lib/libc_r/uthread/uthread_attr_setstacksize.c +++ b/lib/libc_r/uthread/uthread_attr_setstacksize.c @@ -38,10 +38,12 @@ int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { int ret; - if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) { - errno = EINVAL; - ret = -1; - } else { + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) + ret = EINVAL; + else { + /* Save the stack size: */ (*attr)->stacksize_attr = stacksize; ret = 0; } diff --git a/lib/libc_r/uthread/uthread_clean.c b/lib/libc_r/uthread/uthread_clean.c index 99893f671b1d..9319f85efbea 100644 --- a/lib/libc_r/uthread/uthread_clean.c +++ b/lib/libc_r/uthread/uthread_clean.c @@ -37,11 +37,10 @@ #include #include "pthread_private.h" -int -_thread_cleanup_push(void (*routine) (void *), void *routine_arg) +void +pthread_cleanup_push(void (*routine) (void *), void *routine_arg) { struct pthread_cleanup *new; - int ret; if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) { new->routine = routine; @@ -49,15 +48,11 @@ _thread_cleanup_push(void (*routine) (void *), void *routine_arg) new->next = _thread_run->cleanup; _thread_run->cleanup = new; - ret = 0; - } else { - ret = ENOMEM; } - return (ret); } void -_thread_cleanup_pop(int execute) +pthread_cleanup_pop(int execute) { struct pthread_cleanup *old; diff --git a/lib/libc_r/uthread/uthread_cond.c b/lib/libc_r/uthread/uthread_cond.c index 439538044610..2fe4532ab00a 100644 --- a/lib/libc_r/uthread/uthread_cond.c +++ b/lib/libc_r/uthread/uthread_cond.c @@ -272,7 +272,7 @@ pthread_cond_signal(pthread_cond_t * cond) /* Bring the next thread off the condition queue: */ if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) { /* Allow the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } break; @@ -309,7 +309,7 @@ pthread_cond_broadcast(pthread_cond_t * cond) /* Enter a loop to bring all threads off the condition queue: */ while ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) { /* Allow the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } break; diff --git a/lib/libc_r/uthread/uthread_condattr_destroy.c b/lib/libc_r/uthread/uthread_condattr_destroy.c new file mode 100644 index 000000000000..b20f183bb608 --- /dev/null +++ b/lib/libc_r/uthread/uthread_condattr_destroy.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_condattr_destroy(pthread_condattr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_condattr_init.c b/lib/libc_r/uthread/uthread_condattr_init.c new file mode 100644 index 000000000000..f94e4384b925 --- /dev/null +++ b/lib/libc_r/uthread/uthread_condattr_init.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 John Birrell + * 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 +#include +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_condattr_init(pthread_condattr_t *attr) +{ + int ret; + pthread_condattr_t pattr; + + if ((pattr = (pthread_condattr_t) + malloc(sizeof(struct pthread_cond_attr))) == NULL) { + errno = ENOMEM; + ret = -1; + } else { + memcpy(pattr, &pthread_condattr_default, + sizeof(struct pthread_cond_attr)); + *attr = pattr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_create.c b/lib/libc_r/uthread/uthread_create.c index 1d57f8a1626d..e4925a9c420a 100644 --- a/lib/libc_r/uthread/uthread_create.c +++ b/lib/libc_r/uthread/uthread_create.c @@ -87,9 +87,9 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr, new_thread->start_routine = start_routine; new_thread->arg = arg; if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { - new_thread->state = PS_SUSPENDED; + PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED); } else { - new_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(new_thread,PS_RUNNING); } /* Initialise the thread for signals: */ @@ -208,7 +208,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr, * a signal handler thread which must now * wait for the signal handler to complete: */ - parent->state = PS_SIGTHREAD; + PTHREAD_NEW_STATE(parent,PS_SIGTHREAD); } else { /* Schedule the new user thread: */ _thread_kern_sched(NULL); diff --git a/lib/libc_r/uthread/uthread_detach.c b/lib/libc_r/uthread/uthread_detach.c index f24d16f2dbce..08cace4c0af8 100644 --- a/lib/libc_r/uthread/uthread_detach.c +++ b/lib/libc_r/uthread/uthread_detach.c @@ -49,7 +49,7 @@ pthread_detach(pthread_t * p_pthread) /* Check for invalid calling parameters: */ if (p_pthread == NULL || (pthread = *p_pthread) == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } /* Check if the thread has not been detached: */ @@ -60,7 +60,7 @@ pthread_detach(pthread_t * p_pthread) /* Enter a loop to bring all threads off the join queue: */ while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) { /* Make the thread run: */ - next_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(next_thread,PS_RUNNING); } /* @@ -70,7 +70,7 @@ pthread_detach(pthread_t * p_pthread) *p_pthread = NULL; } else { /* Return an error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } diff --git a/lib/libc_r/uthread/uthread_exit.c b/lib/libc_r/uthread/uthread_exit.c index 60662060e01e..15bcfa36f4f4 100644 --- a/lib/libc_r/uthread/uthread_exit.c +++ b/lib/libc_r/uthread/uthread_exit.c @@ -109,7 +109,7 @@ pthread_exit(void *status) _thread_run->ret = status; while (_thread_run->cleanup != NULL) { - _thread_cleanup_pop(1); + pthread_cleanup_pop(1); } if (_thread_run->attr.cleanup_attr != NULL) { @@ -123,7 +123,7 @@ pthread_exit(void *status) /* Check if there are any threads joined to this one: */ while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) { /* Wake the joined thread and let it detach this thread: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } /* Check if the running thread is at the head of the linked list: */ @@ -173,11 +173,11 @@ pthread_exit(void *status) /* * Check if the parent is not waiting on any other signal - * handler threads: + * handler threads and if it hasn't died in the meantime: */ - if (pthread == NULL) { + if (pthread == NULL && _thread_run->parent_thread->state != PS_DEAD) { /* Allow the parent thread to run again: */ - _thread_run->parent_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(_thread_run->parent_thread,PS_RUNNING); } /* Get the signal number: */ l = (long) _thread_run->arg; diff --git a/lib/libc_r/uthread/uthread_fd.c b/lib/libc_r/uthread/uthread_fd.c index ad6e9f39aec8..4c74080e30aa 100644 --- a/lib/libc_r/uthread/uthread_fd.c +++ b/lib/libc_r/uthread/uthread_fd.c @@ -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. diff --git a/lib/libc_r/uthread/uthread_getprio.c b/lib/libc_r/uthread/uthread_getprio.c index 345f6ce2c888..85bd2616b735 100644 --- a/lib/libc_r/uthread/uthread_getprio.c +++ b/lib/libc_r/uthread/uthread_getprio.c @@ -57,7 +57,7 @@ pthread_getprio(pthread_t pthread) /* Check if the thread pointer is NULL: */ if (pthread == NULL || pthread_p == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } else { /* Get the thread priority: */ diff --git a/lib/libc_r/uthread/uthread_info.c b/lib/libc_r/uthread/uthread_info.c index e69145f8fd4b..be25d45270f1 100644 --- a/lib/libc_r/uthread/uthread_info.c +++ b/lib/libc_r/uthread/uthread_info.c @@ -87,8 +87,8 @@ _thread_dump_info(void) if (thread_info[j].state == pthread->state) break; /* Output a record for the current thread: */ - sprintf(s, "--------------------\nThread %p prio %3d state %s\n", - pthread, pthread->pthread_priority, thread_info[j].name); + sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n", + pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); /* Check if this is the running thread: */ @@ -107,6 +107,9 @@ _thread_dump_info(void) switch (pthread->state) { /* File descriptor read lock wait: */ case PS_FDLR_WAIT: + case PS_FDLW_WAIT: + case PS_FDR_WAIT: + case PS_FDW_WAIT: /* Write the lock details: */ sprintf(s, "fd %d[%s:%d]", pthread->data.fd.fd, pthread->data.fd.fname, pthread->data.fd.branch); _thread_sys_write(fd, s, strlen(s)); @@ -140,11 +143,15 @@ _thread_dump_info(void) */ for (pthread = _thread_dead; pthread != NULL; pthread = pthread->nxt) { /* Output a record for the current thread: */ - sprintf(s, "Thread %p prio %3d\n", pthread, pthread->pthread_priority); + sprintf(s, "Thread %p prio %3d [%s:%d]\n", pthread, pthread->pthread_priority,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); } } + /* Output a header for file descriptors: */ + strcpy(s, "\n\n=============\nFILE DESCRIPTOR TABLE\n\n"); + _thread_sys_write(fd, s, strlen(s)); + /* Enter a loop to report file descriptor lock usage: */ for (i = 0; i < _thread_dtablesize; i++) { /* diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c index d044063ce9d4..2adc34f152c1 100644 --- a/lib/libc_r/uthread/uthread_init.c +++ b/lib/libc_r/uthread/uthread_init.c @@ -44,7 +44,11 @@ #include #include #include "pthread_private.h" +extern int _thread_autoinit_dummy_decl; +/* + * Threaded process initialization + */ void _thread_init(void) { @@ -52,15 +56,25 @@ _thread_init(void) int i; struct sigaction act; + /* Ensure that the auto-initialization routine is linked in: */ + _thread_autoinit_dummy_decl = 1; + /* Check if this function has already been called: */ - if (_thread_initial) { + if (_thread_initial) /* Only initialise the threaded application once. */ - } + return; + + /* Get the standard I/O flags before messing with them : */ + for (i = 0; i < 3; i++) + if ((_pthread_stdio_flags[i] = + _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) + PANIC("Cannot get stdio flags"); + /* * Create a pipe that is written to by the signal handler to prevent * signals being missed in calls to _thread_sys_select: */ - else if (_thread_sys_pipe(_thread_kern_pipe) != 0) { + if (_thread_sys_pipe(_thread_kern_pipe) != 0) { /* Cannot create pipe, so abort: */ PANIC("Cannot create kernel pipe"); } diff --git a/lib/libc_r/uthread/uthread_join.c b/lib/libc_r/uthread/uthread_join.c index d0093ae72f05..161482e289a8 100644 --- a/lib/libc_r/uthread/uthread_join.c +++ b/lib/libc_r/uthread/uthread_join.c @@ -40,14 +40,40 @@ pthread_join(pthread_t pthread, void **thread_return) { int rval = 0; int status; + pthread_t pthread1; /* Block signals: */ _thread_kern_sig_block(&status); - /* 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 { diff --git a/lib/libc_r/uthread/uthread_kern.c b/lib/libc_r/uthread/uthread_kern.c index 1db4da6284fc..679b3158048a 100644 --- a/lib/libc_r/uthread/uthread_kern.c +++ b/lib/libc_r/uthread/uthread_kern.c @@ -293,7 +293,7 @@ __asm__("fnsave %0": :"m"(*fdata)); * Change the threads state to allow * it to be restarted: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } } } @@ -823,14 +823,21 @@ __asm__("fnsave %0": :"m"(*fdata)); static void _thread_signal(pthread_t pthread, int sig) { + int done; long l; pthread_t new_pthread; struct sigaction act; void *arg; + /* + * Assume that the signal will not be dealt with according + * to the thread state: + */ + done = 0; + /* Process according to thread state: */ switch (pthread->state) { - /* States which do not change when a signal is trapped: */ + /* States which do not change when a signal is trapped: */ case PS_COND_WAIT: case PS_DEAD: case PS_FDLR_WAIT: @@ -844,7 +851,7 @@ _thread_signal(pthread_t pthread, int sig) /* Nothing to do here. */ break; - /* Wait for child: */ + /* Wait for child: */ case PS_WAIT_WAIT: /* Check if the signal is from a child exiting: */ if (sig == SIGCHLD) { @@ -852,42 +859,72 @@ _thread_signal(pthread_t pthread, int sig) _thread_seterrno(pthread, 0); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } else { /* Return the 'interrupted' error: */ _thread_seterrno(pthread, EINTR); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } + pthread->interrupted = 1; break; - /* - * States that are interrupted by the occurrence of a signal - * other than the scheduling alarm: - */ - 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); diff --git a/lib/libc_r/uthread/uthread_kill.c b/lib/libc_r/uthread/uthread_kill.c new file mode 100644 index 000000000000..eb2c6b75d740 --- /dev/null +++ b/lib/libc_r/uthread/uthread_kill.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_kill(pthread_t pthread, int sig) +{ + int rval = 0; + int status; + pthread_t p_pthread; + + /* Check for invalid signal numbers: */ + if (sig < 0 || sig >= NSIG) + /* Invalid signal: */ + rval = EINVAL; + else { + /* Assume that the search will succeed: */ + rval = 0; + + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* Search for the thread: */ + p_pthread = _thread_link_list; + while (p_pthread != NULL && p_pthread != pthread) { + p_pthread = p_pthread->nxt; + } + + /* Check if the thread was not found: */ + if (p_pthread == NULL) + /* Can't find the thread: */ + rval = ESRCH; + else + /* Increment the pending signal count: */ + p_pthread->sigpend[sig] += 1; + + /* Unblock signals: */ + _thread_kern_sig_unblock(status); + } + + /* Return the completion status: */ + return (rval); +} +#endif diff --git a/lib/libc_r/uthread/uthread_mutex.c b/lib/libc_r/uthread/uthread_mutex.c index dc9be3c5ff78..82a26e846d5a 100644 --- a/lib/libc_r/uthread/uthread_mutex.c +++ b/lib/libc_r/uthread/uthread_mutex.c @@ -76,18 +76,18 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Process according to mutex type: */ switch (type) { - /* Fast mutex: */ + /* Fast mutex: */ case MUTEX_TYPE_FAST: /* Nothing to do here. */ break; - /* Counting mutex: */ + /* Counting mutex: */ case MUTEX_TYPE_COUNTING_FAST: /* Reset the mutex count: */ pmutex->m_data.m_count = 0; break; - /* Trap invalid mutex types: */ + /* Trap invalid mutex types: */ default: /* Return an invalid argument error: */ errno = EINVAL; @@ -130,18 +130,18 @@ pthread_mutex_destroy(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { - /* Fast mutex: */ + /* Fast mutex: */ case MUTEX_TYPE_FAST: /* Nothing to do here. */ break; - /* Counting mutex: */ + /* Counting mutex: */ case MUTEX_TYPE_COUNTING_FAST: /* Reset the mutex count: */ (*mutex)->m_data.m_count = 0; break; - /* Trap undefined mutex types: */ + /* Trap undefined mutex types: */ default: /* Return an invalid argument error: */ errno = EINVAL; @@ -348,7 +348,7 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) */ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { /* Allow the new owner of the mutex to run: */ - (*mutex)->m_owner->state = PS_RUNNING; + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); } break; @@ -371,7 +371,7 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) */ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { /* Allow the new owner of the mutex to run: */ - (*mutex)->m_owner->state = PS_RUNNING; + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); } break; diff --git a/lib/libc_r/uthread/uthread_mutexattr_destroy.c b/lib/libc_r/uthread/uthread_mutexattr_destroy.c new file mode 100644 index 000000000000..cf2e09f44e23 --- /dev/null +++ b/lib/libc_r/uthread/uthread_mutexattr_destroy.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_read.c b/lib/libc_r/uthread/uthread_read.c index 91588441f8be..504143db9ed5 100644 --- a/lib/libc_r/uthread/uthread_read.c +++ b/lib/libc_r/uthread/uthread_read.c @@ -42,22 +42,31 @@ ssize_t read(int fd, void *buf, size_t nbytes) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read: */ + if ((ret = _thread_fd_lock(fd, FD_READ, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking read syscall: */ while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDR_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ read(int fd, void *buf, size_t nbytes) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_READ); - } + _thread_fd_unlock(fd, FD_READ); } return (ret); } diff --git a/lib/libc_r/uthread/uthread_readv.c b/lib/libc_r/uthread/uthread_readv.c index acb72ac2b1b8..fed418b84229 100644 --- a/lib/libc_r/uthread/uthread_readv.c +++ b/lib/libc_r/uthread/uthread_readv.c @@ -42,22 +42,31 @@ ssize_t readv(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read: */ + if ((ret = _thread_fd_lock(fd, FD_READ, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking readv syscall: */ while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDR_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ readv(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_READ); - } + _thread_fd_unlock(fd, FD_READ); } return (ret); } diff --git a/lib/libc_r/uthread/uthread_resume_np.c b/lib/libc_r/uthread/uthread_resume_np.c index a254814163af..934df58c75a4 100644 --- a/lib/libc_r/uthread/uthread_resume_np.c +++ b/lib/libc_r/uthread/uthread_resume_np.c @@ -49,21 +49,21 @@ pthread_resume_np(pthread_t thread) /* Found the thread. Is it suspended? */ if (pthread->state == PS_SUSPENDED) { /* Allow the thread to run. */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); ret = 0; } else if (pthread->state == PS_RUNNING) { /* Thread is already running. */ ret = 0; } else { /* Thread is in some other state. */ - _thread_seterrno(_thread_run,EINVAL); + errno = EINVAL; } } } /* Check if thread was not found. */ if (ret == -1) { /* No such thread */ - _thread_seterrno(_thread_run,ESRCH); + errno = ESRCH; } return(ret); } diff --git a/lib/libc_r/uthread/uthread_setprio.c b/lib/libc_r/uthread/uthread_setprio.c index e052ec34c5d2..4b49ed096afb 100644 --- a/lib/libc_r/uthread/uthread_setprio.c +++ b/lib/libc_r/uthread/uthread_setprio.c @@ -45,7 +45,7 @@ pthread_setprio(pthread_t pthread, int prio) /* Check if the priority is invalid: */ if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } else { /* Block signals: */ @@ -63,7 +63,7 @@ pthread_setprio(pthread_t pthread, int prio) /* Check if the thread pointer is NULL: */ if (pthread == NULL || pthread_p == NULL) { /* Return a 'search' error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } else { /* Set the thread priority: */ diff --git a/lib/libc_r/uthread/uthread_shutdown.c b/lib/libc_r/uthread/uthread_shutdown.c index b2e7eacee0f6..5e069106ff33 100644 --- a/lib/libc_r/uthread/uthread_shutdown.c +++ b/lib/libc_r/uthread/uthread_shutdown.c @@ -62,7 +62,7 @@ shutdown(int fd, int how) } break; default: - _thread_seterrno(_thread_run, EBADF); + errno = EBADF; ret = -1; break; } diff --git a/lib/libc_r/uthread/uthread_sig.c b/lib/libc_r/uthread/uthread_sig.c index c3ec1919077e..e73d5a21e3af 100644 --- a/lib/libc_r/uthread/uthread_sig.c +++ b/lib/libc_r/uthread/uthread_sig.c @@ -97,7 +97,7 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) _thread_seterrno(pthread, 0); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } } diff --git a/lib/libc_r/uthread/uthread_sigaction.c b/lib/libc_r/uthread/uthread_sigaction.c index c7336677ff9c..dd084056366c 100644 --- a/lib/libc_r/uthread/uthread_sigaction.c +++ b/lib/libc_r/uthread/uthread_sigaction.c @@ -45,7 +45,7 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact) /* Check if the signal number is out of range: */ if (sig < 1 || sig > NSIG) { /* Return an invalid argument: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; ret = -1; } else { /* diff --git a/lib/libc_r/uthread/uthread_sigmask.c b/lib/libc_r/uthread/uthread_sigmask.c new file mode 100644 index 000000000000..94f64cb7991f --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigmask.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) +{ + int ret = 0; + int status; + + /* Check if the existing signal process mask is to be returned: */ + if (oset != NULL) { + /* Return the current mask: */ + *oset = _thread_run->sigmask; + } + /* Check if a new signal set was provided by the caller: */ + if (set != NULL) { + /* Block signals while the signal mask is changed: */ + _thread_kern_sig_block(&status); + + /* Process according to what to do: */ + switch (how) { + /* Block signals: */ + case SIG_BLOCK: + /* Add signals to the existing mask: */ + _thread_run->sigmask |= *set; + break; + + /* Unblock signals: */ + case SIG_UNBLOCK: + /* Clear signals from the existing mask: */ + _thread_run->sigmask &= ~(*set); + break; + + /* Set the signal process mask: */ + case SIG_SETMASK: + /* Set the new mask: */ + _thread_run->sigmask = *set; + break; + + /* Trap invalid actions: */ + default: + /* Return an invalid argument: */ + errno = EINVAL; + ret = -1; + break; + } + + /* + * Schedule the next thread in case there are signals that + * now need to be acted on: + */ + _thread_kern_sched(NULL); + } + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_sigprocmask.c b/lib/libc_r/uthread/uthread_sigprocmask.c index d6e3197d2e40..b4a8d84940eb 100644 --- a/lib/libc_r/uthread/uthread_sigprocmask.c +++ b/lib/libc_r/uthread/uthread_sigprocmask.c @@ -54,28 +54,28 @@ sigprocmask(int how, const sigset_t * set, sigset_t * oset) /* Process according to what to do: */ switch (how) { - /* Block signals: */ + /* Block signals: */ case SIG_BLOCK: /* Add signals to the existing mask: */ _thread_run->sigmask |= *set; break; - /* Unblock signals: */ + /* Unblock signals: */ case SIG_UNBLOCK: /* Clear signals from the existing mask: */ _thread_run->sigmask &= ~(*set); break; - /* Set the signal process mask: */ + /* Set the signal process mask: */ case SIG_SETMASK: /* Set the new mask: */ _thread_run->sigmask = *set; break; - /* Trap invalid actions: */ + /* Trap invalid actions: */ default: /* Return an invalid argument: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; ret = -1; break; } diff --git a/lib/libc_r/uthread/uthread_sigsuspend.c b/lib/libc_r/uthread/uthread_sigsuspend.c index a26b6b99bf4b..14cf74b31ece 100644 --- a/lib/libc_r/uthread/uthread_sigsuspend.c +++ b/lib/libc_r/uthread/uthread_sigsuspend.c @@ -57,7 +57,7 @@ sigsuspend(const sigset_t * set) _thread_run->sigmask = oset; } else { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; } /* Return the completion status: */ diff --git a/lib/libc_r/uthread/uthread_sigwait.c b/lib/libc_r/uthread/uthread_sigwait.c new file mode 100644 index 000000000000..4f95190e4216 --- /dev/null +++ b/lib/libc_r/uthread/uthread_sigwait.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +sigwait(const sigset_t * set, int *sig) +{ + int ret; + int status; + sigset_t oset; + + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* Save the current sigmal mask: */ + oset = _thread_run->sigmask; + + /* Combine the caller's mask with the current one: */ + _thread_run->sigmask |= *set; + + /* Wait for a signal: */ + _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__); + + /* Block signals again: */ + _thread_kern_sig_block(NULL); + + /* Return the signal number to the caller: */ + *sig = _thread_run->signo; + + /* Restore the signal mask: */ + _thread_run->sigmask = oset; + + /* Unblock signals: */ + _thread_kern_sig_unblock(status); + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libc_r/uthread/uthread_socketpair.c b/lib/libc_r/uthread/uthread_socketpair.c index 61da7ae42605..22e40a6d7b7b 100644 --- a/lib/libc_r/uthread/uthread_socketpair.c +++ b/lib/libc_r/uthread/uthread_socketpair.c @@ -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 diff --git a/lib/libc_r/uthread/uthread_spec.c b/lib/libc_r/uthread/uthread_spec.c index 4447a75942ab..8d06c52b8d98 100644 --- a/lib/libc_r/uthread/uthread_spec.c +++ b/lib/libc_r/uthread/uthread_spec.c @@ -209,7 +209,7 @@ pthread_getspecific(pthread_key_t key) /* Check for errors: */ if (pthread == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; data = NULL; } /* Check if there is specific data: */ diff --git a/lib/libc_r/uthread/uthread_suspend_np.c b/lib/libc_r/uthread/uthread_suspend_np.c index fb90c1d494d2..d065b73964e2 100644 --- a/lib/libc_r/uthread/uthread_suspend_np.c +++ b/lib/libc_r/uthread/uthread_suspend_np.c @@ -53,14 +53,14 @@ pthread_suspend_np(pthread_t thread) _thread_seterrno(pthread,EINTR); } /* Suspend the thread. */ - pthread->state = PS_SUSPENDED; + PTHREAD_NEW_STATE(pthread,PS_SUSPENDED); ret = 0; } } /* Check if thread was not found. */ if (ret == -1) { /* No such thread */ - _thread_seterrno(_thread_run,ESRCH); + errno = ESRCH; } return(ret); } diff --git a/lib/libc_r/uthread/uthread_write.c b/lib/libc_r/uthread/uthread_write.c index fb6912997911..2baa19f08426 100644 --- a/lib/libc_r/uthread/uthread_write.c +++ b/lib/libc_r/uthread/uthread_write.c @@ -42,22 +42,31 @@ ssize_t write(int fd, const void *buf, size_t nbytes) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking write syscall: */ while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ write(int fd, const void *buf, size_t nbytes) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); } diff --git a/lib/libc_r/uthread/uthread_writev.c b/lib/libc_r/uthread/uthread_writev.c index f40e611d98fe..2a3c0c84c2d0 100644 --- a/lib/libc_r/uthread/uthread_writev.c +++ b/lib/libc_r/uthread/uthread_writev.c @@ -42,22 +42,31 @@ ssize_t writev(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking writev syscall: */ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ writev(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); } diff --git a/lib/libkse/Makefile b/lib/libkse/Makefile index f1584ff73034..dab62107abaf 100644 --- a/lib/libkse/Makefile +++ b/lib/libkse/Makefile @@ -11,7 +11,6 @@ SHLIB_MINOR= 0 CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE -I${.CURDIR}/uthread AINC= -I${.CURDIR}/../libc/${MACHINE} -I${.CURDIR}/uthread -CLEANFILES+=tags PRECIOUSLIB= yes .include "${.CURDIR}/db/Makefile.inc" @@ -38,13 +37,4 @@ CFLAGS+= -DYP .endif .include "${.CURDIR}/${MACHINE}/sys/Makefile.inc" -beforeinstall: tags - ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc_r.tags - -tags: ${SRCS} - ctags ${.ALLSRC:M*.c} - egrep -o "^ENTRY(.*)|^FUNC(.*)|^SYSCALL(.*)" ${.ALLSRC:M*.s} | \ - sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \ - >> tags; sort -o tags tags - .include diff --git a/lib/libkse/thread/Makefile.inc b/lib/libkse/thread/Makefile.inc index c275b5f4d092..cd85700d2beb 100644 --- a/lib/libkse/thread/Makefile.inc +++ b/lib/libkse/thread/Makefile.inc @@ -9,13 +9,20 @@ SRCS+= \ uthread_accept.c \ uthread_attr_destroy.c \ uthread_attr_init.c \ + uthread_attr_getdetachstate.c \ + uthread_attr_getstackaddr.c \ + uthread_attr_getstacksize.c \ uthread_attr_setcreatesuspend_np.c \ + uthread_attr_setdetachstate.c \ + uthread_attr_setstackaddr.c \ uthread_attr_setstacksize.c \ uthread_autoinit.cc \ uthread_bind.c \ uthread_clean.c \ uthread_close.c \ uthread_cond.c \ + uthread_condattr_destroy.c \ + uthread_condattr_init.c \ uthread_connect.c \ uthread_create.c \ uthread_detach.c \ @@ -44,12 +51,14 @@ SRCS+= \ uthread_ioctl.c \ uthread_join.c \ uthread_kern.c \ + uthread_kill.c \ uthread_listen.c \ uthread_longjmp.c \ uthread_mattr_init.c \ uthread_mattr_kind_np.c \ uthread_multi_np.c \ uthread_mutex.c \ + uthread_mutexattr_destroy.c \ uthread_nanosleep.c \ uthread_once.c \ uthread_open.c \ @@ -71,6 +80,7 @@ SRCS+= \ uthread_sigaction.c \ uthread_sigblock.c \ uthread_single_np.c \ + uthread_sigmask.c \ uthread_signal.c \ uthread_sigprocmask.c \ uthread_sigsetmask.c \ diff --git a/lib/libkse/thread/thr_attr_destroy.c b/lib/libkse/thread/thr_attr_destroy.c index be6b2a2d7dcb..1f4b2c8523c3 100644 --- a/lib/libkse/thread/thr_attr_destroy.c +++ b/lib/libkse/thread/thr_attr_destroy.c @@ -39,11 +39,19 @@ int pthread_attr_destroy(pthread_attr_t *attr) { int ret; - if (attr == NULL || *attr == NULL) { - errno = EINVAL; - ret = -1; - } else { + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL) + /* Invalid argument: */ + ret = EINVAL; + else { + /* Free the memory allocated to the attribute object: */ free(*attr); + + /* + * Leave the attribute pointer NULL now that the memory + * has been freed: + */ *attr = NULL; ret = 0; } diff --git a/lib/libkse/thread/thr_attr_getdetachstate.c b/lib/libkse/thread/thr_attr_getdetachstate.c new file mode 100644 index 000000000000..4715cb6f2424 --- /dev/null +++ b/lib/libkse/thread/thr_attr_getdetachstate.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || detachstate == NULL) + ret = EINVAL; + else { + /* Check if the detached flag is set: */ + if ((*attr)->flags & PTHREAD_DETACHED) + /* Return detached: */ + *detachstate = PTHREAD_CREATE_DETACHED; + else + /* Return joinable: */ + *detachstate = PTHREAD_CREATE_JOINABLE; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libkse/thread/thr_attr_getstackaddr.c b/lib/libkse/thread/thr_attr_getstackaddr.c new file mode 100644 index 000000000000..1850a324c611 --- /dev/null +++ b/lib/libkse/thread/thr_attr_getstackaddr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + ret = EINVAL; + else { + /* Return the stack address: */ + *stackaddr = (*attr)->stackaddr_attr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libkse/thread/thr_attr_getstacksize.c b/lib/libkse/thread/thr_attr_getstacksize.c new file mode 100644 index 000000000000..de81106083d4 --- /dev/null +++ b/lib/libkse/thread/thr_attr_getstacksize.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize == NULL) + ret = EINVAL; + else { + /* Return the stack size: */ + *stacksize = (*attr)->stacksize_attr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libkse/thread/thr_attr_init.c b/lib/libkse/thread/thr_attr_init.c index 7dade978a48f..c64e29fed11c 100644 --- a/lib/libkse/thread/thr_attr_init.c +++ b/lib/libkse/thread/thr_attr_init.c @@ -41,11 +41,16 @@ int pthread_attr_init(pthread_attr_t *attr) { int ret; pthread_attr_t pattr; - if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) { - errno = ENOMEM; - ret = -1; - } else { + + /* Allocate memory for the attribute object: */ + if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) + /* Insufficient memory: */ + ret = ENOMEM; + else { + /* Initialise the attribute object with the defaults: */ memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr)); + + /* Return a pointer to the attribute object: */ *attr = pattr; ret = 0; } diff --git a/lib/libkse/thread/thr_attr_setdetachstate.c b/lib/libkse/thread/thr_attr_setdetachstate.c new file mode 100644 index 000000000000..6ec0dbc1c585 --- /dev/null +++ b/lib/libkse/thread/thr_attr_setdetachstate.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || + (detachstate != PTHREAD_CREATE_DETACHED && + detachstate != PTHREAD_CREATE_JOINABLE)) + ret = EINVAL; + else { + /* Check if detached state: */ + if (detachstate == PTHREAD_CREATE_DETACHED) + /* Set the detached flag: */ + (*attr)->flags |= PTHREAD_DETACHED; + else + /* Reset the detached flag: */ + (*attr)->flags &= ~PTHREAD_DETACHED; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libkse/thread/thr_attr_setstackaddr.c b/lib/libkse/thread/thr_attr_setstackaddr.c new file mode 100644 index 000000000000..ce54915d096d --- /dev/null +++ b/lib/libkse/thread/thr_attr_setstackaddr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + ret = EINVAL; + else { + /* Save the stack address: */ + (*attr)->stackaddr_attr = stackaddr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libkse/thread/thr_attr_setstacksize.c b/lib/libkse/thread/thr_attr_setstacksize.c index 5e59798f579b..94e575e0dded 100644 --- a/lib/libkse/thread/thr_attr_setstacksize.c +++ b/lib/libkse/thread/thr_attr_setstacksize.c @@ -38,10 +38,12 @@ int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { int ret; - if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) { - errno = EINVAL; - ret = -1; - } else { + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) + ret = EINVAL; + else { + /* Save the stack size: */ (*attr)->stacksize_attr = stacksize; ret = 0; } diff --git a/lib/libkse/thread/thr_clean.c b/lib/libkse/thread/thr_clean.c index 99893f671b1d..9319f85efbea 100644 --- a/lib/libkse/thread/thr_clean.c +++ b/lib/libkse/thread/thr_clean.c @@ -37,11 +37,10 @@ #include #include "pthread_private.h" -int -_thread_cleanup_push(void (*routine) (void *), void *routine_arg) +void +pthread_cleanup_push(void (*routine) (void *), void *routine_arg) { struct pthread_cleanup *new; - int ret; if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) { new->routine = routine; @@ -49,15 +48,11 @@ _thread_cleanup_push(void (*routine) (void *), void *routine_arg) new->next = _thread_run->cleanup; _thread_run->cleanup = new; - ret = 0; - } else { - ret = ENOMEM; } - return (ret); } void -_thread_cleanup_pop(int execute) +pthread_cleanup_pop(int execute) { struct pthread_cleanup *old; diff --git a/lib/libkse/thread/thr_cond.c b/lib/libkse/thread/thr_cond.c index 439538044610..2fe4532ab00a 100644 --- a/lib/libkse/thread/thr_cond.c +++ b/lib/libkse/thread/thr_cond.c @@ -272,7 +272,7 @@ pthread_cond_signal(pthread_cond_t * cond) /* Bring the next thread off the condition queue: */ if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) { /* Allow the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } break; @@ -309,7 +309,7 @@ pthread_cond_broadcast(pthread_cond_t * cond) /* Enter a loop to bring all threads off the condition queue: */ while ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) { /* Allow the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } break; diff --git a/lib/libkse/thread/thr_condattr_destroy.c b/lib/libkse/thread/thr_condattr_destroy.c new file mode 100644 index 000000000000..b20f183bb608 --- /dev/null +++ b/lib/libkse/thread/thr_condattr_destroy.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_condattr_destroy(pthread_condattr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libkse/thread/thr_condattr_init.c b/lib/libkse/thread/thr_condattr_init.c new file mode 100644 index 000000000000..f94e4384b925 --- /dev/null +++ b/lib/libkse/thread/thr_condattr_init.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 John Birrell + * 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 +#include +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_condattr_init(pthread_condattr_t *attr) +{ + int ret; + pthread_condattr_t pattr; + + if ((pattr = (pthread_condattr_t) + malloc(sizeof(struct pthread_cond_attr))) == NULL) { + errno = ENOMEM; + ret = -1; + } else { + memcpy(pattr, &pthread_condattr_default, + sizeof(struct pthread_cond_attr)); + *attr = pattr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libkse/thread/thr_create.c b/lib/libkse/thread/thr_create.c index 1d57f8a1626d..e4925a9c420a 100644 --- a/lib/libkse/thread/thr_create.c +++ b/lib/libkse/thread/thr_create.c @@ -87,9 +87,9 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr, new_thread->start_routine = start_routine; new_thread->arg = arg; if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { - new_thread->state = PS_SUSPENDED; + PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED); } else { - new_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(new_thread,PS_RUNNING); } /* Initialise the thread for signals: */ @@ -208,7 +208,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr, * a signal handler thread which must now * wait for the signal handler to complete: */ - parent->state = PS_SIGTHREAD; + PTHREAD_NEW_STATE(parent,PS_SIGTHREAD); } else { /* Schedule the new user thread: */ _thread_kern_sched(NULL); diff --git a/lib/libkse/thread/thr_detach.c b/lib/libkse/thread/thr_detach.c index f24d16f2dbce..08cace4c0af8 100644 --- a/lib/libkse/thread/thr_detach.c +++ b/lib/libkse/thread/thr_detach.c @@ -49,7 +49,7 @@ pthread_detach(pthread_t * p_pthread) /* Check for invalid calling parameters: */ if (p_pthread == NULL || (pthread = *p_pthread) == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } /* Check if the thread has not been detached: */ @@ -60,7 +60,7 @@ pthread_detach(pthread_t * p_pthread) /* Enter a loop to bring all threads off the join queue: */ while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) { /* Make the thread run: */ - next_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(next_thread,PS_RUNNING); } /* @@ -70,7 +70,7 @@ pthread_detach(pthread_t * p_pthread) *p_pthread = NULL; } else { /* Return an error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } diff --git a/lib/libkse/thread/thr_exit.c b/lib/libkse/thread/thr_exit.c index 60662060e01e..15bcfa36f4f4 100644 --- a/lib/libkse/thread/thr_exit.c +++ b/lib/libkse/thread/thr_exit.c @@ -109,7 +109,7 @@ pthread_exit(void *status) _thread_run->ret = status; while (_thread_run->cleanup != NULL) { - _thread_cleanup_pop(1); + pthread_cleanup_pop(1); } if (_thread_run->attr.cleanup_attr != NULL) { @@ -123,7 +123,7 @@ pthread_exit(void *status) /* Check if there are any threads joined to this one: */ while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) { /* Wake the joined thread and let it detach this thread: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } /* Check if the running thread is at the head of the linked list: */ @@ -173,11 +173,11 @@ pthread_exit(void *status) /* * Check if the parent is not waiting on any other signal - * handler threads: + * handler threads and if it hasn't died in the meantime: */ - if (pthread == NULL) { + if (pthread == NULL && _thread_run->parent_thread->state != PS_DEAD) { /* Allow the parent thread to run again: */ - _thread_run->parent_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(_thread_run->parent_thread,PS_RUNNING); } /* Get the signal number: */ l = (long) _thread_run->arg; diff --git a/lib/libkse/thread/thr_getprio.c b/lib/libkse/thread/thr_getprio.c index 345f6ce2c888..85bd2616b735 100644 --- a/lib/libkse/thread/thr_getprio.c +++ b/lib/libkse/thread/thr_getprio.c @@ -57,7 +57,7 @@ pthread_getprio(pthread_t pthread) /* Check if the thread pointer is NULL: */ if (pthread == NULL || pthread_p == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } else { /* Get the thread priority: */ diff --git a/lib/libkse/thread/thr_info.c b/lib/libkse/thread/thr_info.c index e69145f8fd4b..be25d45270f1 100644 --- a/lib/libkse/thread/thr_info.c +++ b/lib/libkse/thread/thr_info.c @@ -87,8 +87,8 @@ _thread_dump_info(void) if (thread_info[j].state == pthread->state) break; /* Output a record for the current thread: */ - sprintf(s, "--------------------\nThread %p prio %3d state %s\n", - pthread, pthread->pthread_priority, thread_info[j].name); + sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n", + pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); /* Check if this is the running thread: */ @@ -107,6 +107,9 @@ _thread_dump_info(void) switch (pthread->state) { /* File descriptor read lock wait: */ case PS_FDLR_WAIT: + case PS_FDLW_WAIT: + case PS_FDR_WAIT: + case PS_FDW_WAIT: /* Write the lock details: */ sprintf(s, "fd %d[%s:%d]", pthread->data.fd.fd, pthread->data.fd.fname, pthread->data.fd.branch); _thread_sys_write(fd, s, strlen(s)); @@ -140,11 +143,15 @@ _thread_dump_info(void) */ for (pthread = _thread_dead; pthread != NULL; pthread = pthread->nxt) { /* Output a record for the current thread: */ - sprintf(s, "Thread %p prio %3d\n", pthread, pthread->pthread_priority); + sprintf(s, "Thread %p prio %3d [%s:%d]\n", pthread, pthread->pthread_priority,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); } } + /* Output a header for file descriptors: */ + strcpy(s, "\n\n=============\nFILE DESCRIPTOR TABLE\n\n"); + _thread_sys_write(fd, s, strlen(s)); + /* Enter a loop to report file descriptor lock usage: */ for (i = 0; i < _thread_dtablesize; i++) { /* diff --git a/lib/libkse/thread/thr_init.c b/lib/libkse/thread/thr_init.c index d044063ce9d4..2adc34f152c1 100644 --- a/lib/libkse/thread/thr_init.c +++ b/lib/libkse/thread/thr_init.c @@ -44,7 +44,11 @@ #include #include #include "pthread_private.h" +extern int _thread_autoinit_dummy_decl; +/* + * Threaded process initialization + */ void _thread_init(void) { @@ -52,15 +56,25 @@ _thread_init(void) int i; struct sigaction act; + /* Ensure that the auto-initialization routine is linked in: */ + _thread_autoinit_dummy_decl = 1; + /* Check if this function has already been called: */ - if (_thread_initial) { + if (_thread_initial) /* Only initialise the threaded application once. */ - } + return; + + /* Get the standard I/O flags before messing with them : */ + for (i = 0; i < 3; i++) + if ((_pthread_stdio_flags[i] = + _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) + PANIC("Cannot get stdio flags"); + /* * Create a pipe that is written to by the signal handler to prevent * signals being missed in calls to _thread_sys_select: */ - else if (_thread_sys_pipe(_thread_kern_pipe) != 0) { + if (_thread_sys_pipe(_thread_kern_pipe) != 0) { /* Cannot create pipe, so abort: */ PANIC("Cannot create kernel pipe"); } diff --git a/lib/libkse/thread/thr_join.c b/lib/libkse/thread/thr_join.c index d0093ae72f05..161482e289a8 100644 --- a/lib/libkse/thread/thr_join.c +++ b/lib/libkse/thread/thr_join.c @@ -40,14 +40,40 @@ pthread_join(pthread_t pthread, void **thread_return) { int rval = 0; int status; + pthread_t pthread1; /* Block signals: */ _thread_kern_sig_block(&status); - /* 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 { diff --git a/lib/libkse/thread/thr_kern.c b/lib/libkse/thread/thr_kern.c index 1db4da6284fc..679b3158048a 100644 --- a/lib/libkse/thread/thr_kern.c +++ b/lib/libkse/thread/thr_kern.c @@ -293,7 +293,7 @@ __asm__("fnsave %0": :"m"(*fdata)); * Change the threads state to allow * it to be restarted: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } } } @@ -823,14 +823,21 @@ __asm__("fnsave %0": :"m"(*fdata)); static void _thread_signal(pthread_t pthread, int sig) { + int done; long l; pthread_t new_pthread; struct sigaction act; void *arg; + /* + * Assume that the signal will not be dealt with according + * to the thread state: + */ + done = 0; + /* Process according to thread state: */ switch (pthread->state) { - /* States which do not change when a signal is trapped: */ + /* States which do not change when a signal is trapped: */ case PS_COND_WAIT: case PS_DEAD: case PS_FDLR_WAIT: @@ -844,7 +851,7 @@ _thread_signal(pthread_t pthread, int sig) /* Nothing to do here. */ break; - /* Wait for child: */ + /* Wait for child: */ case PS_WAIT_WAIT: /* Check if the signal is from a child exiting: */ if (sig == SIGCHLD) { @@ -852,42 +859,72 @@ _thread_signal(pthread_t pthread, int sig) _thread_seterrno(pthread, 0); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } else { /* Return the 'interrupted' error: */ _thread_seterrno(pthread, EINTR); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } + pthread->interrupted = 1; break; - /* - * States that are interrupted by the occurrence of a signal - * other than the scheduling alarm: - */ - 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); diff --git a/lib/libkse/thread/thr_kill.c b/lib/libkse/thread/thr_kill.c new file mode 100644 index 000000000000..eb2c6b75d740 --- /dev/null +++ b/lib/libkse/thread/thr_kill.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_kill(pthread_t pthread, int sig) +{ + int rval = 0; + int status; + pthread_t p_pthread; + + /* Check for invalid signal numbers: */ + if (sig < 0 || sig >= NSIG) + /* Invalid signal: */ + rval = EINVAL; + else { + /* Assume that the search will succeed: */ + rval = 0; + + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* Search for the thread: */ + p_pthread = _thread_link_list; + while (p_pthread != NULL && p_pthread != pthread) { + p_pthread = p_pthread->nxt; + } + + /* Check if the thread was not found: */ + if (p_pthread == NULL) + /* Can't find the thread: */ + rval = ESRCH; + else + /* Increment the pending signal count: */ + p_pthread->sigpend[sig] += 1; + + /* Unblock signals: */ + _thread_kern_sig_unblock(status); + } + + /* Return the completion status: */ + return (rval); +} +#endif diff --git a/lib/libkse/thread/thr_mutex.c b/lib/libkse/thread/thr_mutex.c index dc9be3c5ff78..82a26e846d5a 100644 --- a/lib/libkse/thread/thr_mutex.c +++ b/lib/libkse/thread/thr_mutex.c @@ -76,18 +76,18 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Process according to mutex type: */ switch (type) { - /* Fast mutex: */ + /* Fast mutex: */ case MUTEX_TYPE_FAST: /* Nothing to do here. */ break; - /* Counting mutex: */ + /* Counting mutex: */ case MUTEX_TYPE_COUNTING_FAST: /* Reset the mutex count: */ pmutex->m_data.m_count = 0; break; - /* Trap invalid mutex types: */ + /* Trap invalid mutex types: */ default: /* Return an invalid argument error: */ errno = EINVAL; @@ -130,18 +130,18 @@ pthread_mutex_destroy(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { - /* Fast mutex: */ + /* Fast mutex: */ case MUTEX_TYPE_FAST: /* Nothing to do here. */ break; - /* Counting mutex: */ + /* Counting mutex: */ case MUTEX_TYPE_COUNTING_FAST: /* Reset the mutex count: */ (*mutex)->m_data.m_count = 0; break; - /* Trap undefined mutex types: */ + /* Trap undefined mutex types: */ default: /* Return an invalid argument error: */ errno = EINVAL; @@ -348,7 +348,7 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) */ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { /* Allow the new owner of the mutex to run: */ - (*mutex)->m_owner->state = PS_RUNNING; + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); } break; @@ -371,7 +371,7 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) */ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { /* Allow the new owner of the mutex to run: */ - (*mutex)->m_owner->state = PS_RUNNING; + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); } break; diff --git a/lib/libkse/thread/thr_mutexattr_destroy.c b/lib/libkse/thread/thr_mutexattr_destroy.c new file mode 100644 index 000000000000..cf2e09f44e23 --- /dev/null +++ b/lib/libkse/thread/thr_mutexattr_destroy.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h index a16bdea0387e..064888f1978e 100644 --- a/lib/libkse/thread/thr_private.h +++ b/lib/libkse/thread/thr_private.h @@ -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); diff --git a/lib/libkse/thread/thr_read.c b/lib/libkse/thread/thr_read.c index 91588441f8be..504143db9ed5 100644 --- a/lib/libkse/thread/thr_read.c +++ b/lib/libkse/thread/thr_read.c @@ -42,22 +42,31 @@ ssize_t read(int fd, void *buf, size_t nbytes) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read: */ + if ((ret = _thread_fd_lock(fd, FD_READ, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking read syscall: */ while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDR_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ read(int fd, void *buf, size_t nbytes) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_READ); - } + _thread_fd_unlock(fd, FD_READ); } return (ret); } diff --git a/lib/libkse/thread/thr_readv.c b/lib/libkse/thread/thr_readv.c index acb72ac2b1b8..fed418b84229 100644 --- a/lib/libkse/thread/thr_readv.c +++ b/lib/libkse/thread/thr_readv.c @@ -42,22 +42,31 @@ ssize_t readv(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read: */ + if ((ret = _thread_fd_lock(fd, FD_READ, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking readv syscall: */ while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDR_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ readv(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_READ); - } + _thread_fd_unlock(fd, FD_READ); } return (ret); } diff --git a/lib/libkse/thread/thr_resume_np.c b/lib/libkse/thread/thr_resume_np.c index a254814163af..934df58c75a4 100644 --- a/lib/libkse/thread/thr_resume_np.c +++ b/lib/libkse/thread/thr_resume_np.c @@ -49,21 +49,21 @@ pthread_resume_np(pthread_t thread) /* Found the thread. Is it suspended? */ if (pthread->state == PS_SUSPENDED) { /* Allow the thread to run. */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); ret = 0; } else if (pthread->state == PS_RUNNING) { /* Thread is already running. */ ret = 0; } else { /* Thread is in some other state. */ - _thread_seterrno(_thread_run,EINVAL); + errno = EINVAL; } } } /* Check if thread was not found. */ if (ret == -1) { /* No such thread */ - _thread_seterrno(_thread_run,ESRCH); + errno = ESRCH; } return(ret); } diff --git a/lib/libkse/thread/thr_setprio.c b/lib/libkse/thread/thr_setprio.c index e052ec34c5d2..4b49ed096afb 100644 --- a/lib/libkse/thread/thr_setprio.c +++ b/lib/libkse/thread/thr_setprio.c @@ -45,7 +45,7 @@ pthread_setprio(pthread_t pthread, int prio) /* Check if the priority is invalid: */ if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } else { /* Block signals: */ @@ -63,7 +63,7 @@ pthread_setprio(pthread_t pthread, int prio) /* Check if the thread pointer is NULL: */ if (pthread == NULL || pthread_p == NULL) { /* Return a 'search' error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } else { /* Set the thread priority: */ diff --git a/lib/libkse/thread/thr_sig.c b/lib/libkse/thread/thr_sig.c index c3ec1919077e..e73d5a21e3af 100644 --- a/lib/libkse/thread/thr_sig.c +++ b/lib/libkse/thread/thr_sig.c @@ -97,7 +97,7 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) _thread_seterrno(pthread, 0); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } } diff --git a/lib/libkse/thread/thr_sigaction.c b/lib/libkse/thread/thr_sigaction.c index c7336677ff9c..dd084056366c 100644 --- a/lib/libkse/thread/thr_sigaction.c +++ b/lib/libkse/thread/thr_sigaction.c @@ -45,7 +45,7 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact) /* Check if the signal number is out of range: */ if (sig < 1 || sig > NSIG) { /* Return an invalid argument: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; ret = -1; } else { /* diff --git a/lib/libkse/thread/thr_sigmask.c b/lib/libkse/thread/thr_sigmask.c new file mode 100644 index 000000000000..94f64cb7991f --- /dev/null +++ b/lib/libkse/thread/thr_sigmask.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) +{ + int ret = 0; + int status; + + /* Check if the existing signal process mask is to be returned: */ + if (oset != NULL) { + /* Return the current mask: */ + *oset = _thread_run->sigmask; + } + /* Check if a new signal set was provided by the caller: */ + if (set != NULL) { + /* Block signals while the signal mask is changed: */ + _thread_kern_sig_block(&status); + + /* Process according to what to do: */ + switch (how) { + /* Block signals: */ + case SIG_BLOCK: + /* Add signals to the existing mask: */ + _thread_run->sigmask |= *set; + break; + + /* Unblock signals: */ + case SIG_UNBLOCK: + /* Clear signals from the existing mask: */ + _thread_run->sigmask &= ~(*set); + break; + + /* Set the signal process mask: */ + case SIG_SETMASK: + /* Set the new mask: */ + _thread_run->sigmask = *set; + break; + + /* Trap invalid actions: */ + default: + /* Return an invalid argument: */ + errno = EINVAL; + ret = -1; + break; + } + + /* + * Schedule the next thread in case there are signals that + * now need to be acted on: + */ + _thread_kern_sched(NULL); + } + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libkse/thread/thr_sigprocmask.c b/lib/libkse/thread/thr_sigprocmask.c index d6e3197d2e40..b4a8d84940eb 100644 --- a/lib/libkse/thread/thr_sigprocmask.c +++ b/lib/libkse/thread/thr_sigprocmask.c @@ -54,28 +54,28 @@ sigprocmask(int how, const sigset_t * set, sigset_t * oset) /* Process according to what to do: */ switch (how) { - /* Block signals: */ + /* Block signals: */ case SIG_BLOCK: /* Add signals to the existing mask: */ _thread_run->sigmask |= *set; break; - /* Unblock signals: */ + /* Unblock signals: */ case SIG_UNBLOCK: /* Clear signals from the existing mask: */ _thread_run->sigmask &= ~(*set); break; - /* Set the signal process mask: */ + /* Set the signal process mask: */ case SIG_SETMASK: /* Set the new mask: */ _thread_run->sigmask = *set; break; - /* Trap invalid actions: */ + /* Trap invalid actions: */ default: /* Return an invalid argument: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; ret = -1; break; } diff --git a/lib/libkse/thread/thr_sigsuspend.c b/lib/libkse/thread/thr_sigsuspend.c index a26b6b99bf4b..14cf74b31ece 100644 --- a/lib/libkse/thread/thr_sigsuspend.c +++ b/lib/libkse/thread/thr_sigsuspend.c @@ -57,7 +57,7 @@ sigsuspend(const sigset_t * set) _thread_run->sigmask = oset; } else { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; } /* Return the completion status: */ diff --git a/lib/libkse/thread/thr_sigwait.c b/lib/libkse/thread/thr_sigwait.c new file mode 100644 index 000000000000..4f95190e4216 --- /dev/null +++ b/lib/libkse/thread/thr_sigwait.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +sigwait(const sigset_t * set, int *sig) +{ + int ret; + int status; + sigset_t oset; + + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* Save the current sigmal mask: */ + oset = _thread_run->sigmask; + + /* Combine the caller's mask with the current one: */ + _thread_run->sigmask |= *set; + + /* Wait for a signal: */ + _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__); + + /* Block signals again: */ + _thread_kern_sig_block(NULL); + + /* Return the signal number to the caller: */ + *sig = _thread_run->signo; + + /* Restore the signal mask: */ + _thread_run->sigmask = oset; + + /* Unblock signals: */ + _thread_kern_sig_unblock(status); + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libkse/thread/thr_spec.c b/lib/libkse/thread/thr_spec.c index 4447a75942ab..8d06c52b8d98 100644 --- a/lib/libkse/thread/thr_spec.c +++ b/lib/libkse/thread/thr_spec.c @@ -209,7 +209,7 @@ pthread_getspecific(pthread_key_t key) /* Check for errors: */ if (pthread == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; data = NULL; } /* Check if there is specific data: */ diff --git a/lib/libkse/thread/thr_suspend_np.c b/lib/libkse/thread/thr_suspend_np.c index fb90c1d494d2..d065b73964e2 100644 --- a/lib/libkse/thread/thr_suspend_np.c +++ b/lib/libkse/thread/thr_suspend_np.c @@ -53,14 +53,14 @@ pthread_suspend_np(pthread_t thread) _thread_seterrno(pthread,EINTR); } /* Suspend the thread. */ - pthread->state = PS_SUSPENDED; + PTHREAD_NEW_STATE(pthread,PS_SUSPENDED); ret = 0; } } /* Check if thread was not found. */ if (ret == -1) { /* No such thread */ - _thread_seterrno(_thread_run,ESRCH); + errno = ESRCH; } return(ret); } diff --git a/lib/libkse/thread/thr_write.c b/lib/libkse/thread/thr_write.c index fb6912997911..2baa19f08426 100644 --- a/lib/libkse/thread/thr_write.c +++ b/lib/libkse/thread/thr_write.c @@ -42,22 +42,31 @@ ssize_t write(int fd, const void *buf, size_t nbytes) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking write syscall: */ while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ write(int fd, const void *buf, size_t nbytes) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); } diff --git a/lib/libkse/thread/thr_writev.c b/lib/libkse/thread/thr_writev.c index f40e611d98fe..2a3c0c84c2d0 100644 --- a/lib/libkse/thread/thr_writev.c +++ b/lib/libkse/thread/thr_writev.c @@ -42,22 +42,31 @@ ssize_t writev(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking writev syscall: */ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ writev(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); } diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile index f1584ff73034..dab62107abaf 100644 --- a/lib/libpthread/Makefile +++ b/lib/libpthread/Makefile @@ -11,7 +11,6 @@ SHLIB_MINOR= 0 CFLAGS+=-DLIBC_RCS -DSYSLIBC_RCS CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE -I${.CURDIR}/uthread AINC= -I${.CURDIR}/../libc/${MACHINE} -I${.CURDIR}/uthread -CLEANFILES+=tags PRECIOUSLIB= yes .include "${.CURDIR}/db/Makefile.inc" @@ -38,13 +37,4 @@ CFLAGS+= -DYP .endif .include "${.CURDIR}/${MACHINE}/sys/Makefile.inc" -beforeinstall: tags - ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc_r.tags - -tags: ${SRCS} - ctags ${.ALLSRC:M*.c} - egrep -o "^ENTRY(.*)|^FUNC(.*)|^SYSCALL(.*)" ${.ALLSRC:M*.s} | \ - sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \ - >> tags; sort -o tags tags - .include diff --git a/lib/libpthread/thread/Makefile.inc b/lib/libpthread/thread/Makefile.inc index c275b5f4d092..cd85700d2beb 100644 --- a/lib/libpthread/thread/Makefile.inc +++ b/lib/libpthread/thread/Makefile.inc @@ -9,13 +9,20 @@ SRCS+= \ uthread_accept.c \ uthread_attr_destroy.c \ uthread_attr_init.c \ + uthread_attr_getdetachstate.c \ + uthread_attr_getstackaddr.c \ + uthread_attr_getstacksize.c \ uthread_attr_setcreatesuspend_np.c \ + uthread_attr_setdetachstate.c \ + uthread_attr_setstackaddr.c \ uthread_attr_setstacksize.c \ uthread_autoinit.cc \ uthread_bind.c \ uthread_clean.c \ uthread_close.c \ uthread_cond.c \ + uthread_condattr_destroy.c \ + uthread_condattr_init.c \ uthread_connect.c \ uthread_create.c \ uthread_detach.c \ @@ -44,12 +51,14 @@ SRCS+= \ uthread_ioctl.c \ uthread_join.c \ uthread_kern.c \ + uthread_kill.c \ uthread_listen.c \ uthread_longjmp.c \ uthread_mattr_init.c \ uthread_mattr_kind_np.c \ uthread_multi_np.c \ uthread_mutex.c \ + uthread_mutexattr_destroy.c \ uthread_nanosleep.c \ uthread_once.c \ uthread_open.c \ @@ -71,6 +80,7 @@ SRCS+= \ uthread_sigaction.c \ uthread_sigblock.c \ uthread_single_np.c \ + uthread_sigmask.c \ uthread_signal.c \ uthread_sigprocmask.c \ uthread_sigsetmask.c \ diff --git a/lib/libpthread/thread/thr_attr_destroy.c b/lib/libpthread/thread/thr_attr_destroy.c index be6b2a2d7dcb..1f4b2c8523c3 100644 --- a/lib/libpthread/thread/thr_attr_destroy.c +++ b/lib/libpthread/thread/thr_attr_destroy.c @@ -39,11 +39,19 @@ int pthread_attr_destroy(pthread_attr_t *attr) { int ret; - if (attr == NULL || *attr == NULL) { - errno = EINVAL; - ret = -1; - } else { + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL) + /* Invalid argument: */ + ret = EINVAL; + else { + /* Free the memory allocated to the attribute object: */ free(*attr); + + /* + * Leave the attribute pointer NULL now that the memory + * has been freed: + */ *attr = NULL; ret = 0; } diff --git a/lib/libpthread/thread/thr_attr_getdetachstate.c b/lib/libpthread/thread/thr_attr_getdetachstate.c new file mode 100644 index 000000000000..4715cb6f2424 --- /dev/null +++ b/lib/libpthread/thread/thr_attr_getdetachstate.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || detachstate == NULL) + ret = EINVAL; + else { + /* Check if the detached flag is set: */ + if ((*attr)->flags & PTHREAD_DETACHED) + /* Return detached: */ + *detachstate = PTHREAD_CREATE_DETACHED; + else + /* Return joinable: */ + *detachstate = PTHREAD_CREATE_JOINABLE; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_attr_getstackaddr.c b/lib/libpthread/thread/thr_attr_getstackaddr.c new file mode 100644 index 000000000000..1850a324c611 --- /dev/null +++ b/lib/libpthread/thread/thr_attr_getstackaddr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + ret = EINVAL; + else { + /* Return the stack address: */ + *stackaddr = (*attr)->stackaddr_attr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_attr_getstacksize.c b/lib/libpthread/thread/thr_attr_getstacksize.c new file mode 100644 index 000000000000..de81106083d4 --- /dev/null +++ b/lib/libpthread/thread/thr_attr_getstacksize.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize == NULL) + ret = EINVAL; + else { + /* Return the stack size: */ + *stacksize = (*attr)->stacksize_attr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_attr_init.c b/lib/libpthread/thread/thr_attr_init.c index 7dade978a48f..c64e29fed11c 100644 --- a/lib/libpthread/thread/thr_attr_init.c +++ b/lib/libpthread/thread/thr_attr_init.c @@ -41,11 +41,16 @@ int pthread_attr_init(pthread_attr_t *attr) { int ret; pthread_attr_t pattr; - if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) { - errno = ENOMEM; - ret = -1; - } else { + + /* Allocate memory for the attribute object: */ + if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) + /* Insufficient memory: */ + ret = ENOMEM; + else { + /* Initialise the attribute object with the defaults: */ memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr)); + + /* Return a pointer to the attribute object: */ *attr = pattr; ret = 0; } diff --git a/lib/libpthread/thread/thr_attr_setdetachstate.c b/lib/libpthread/thread/thr_attr_setdetachstate.c new file mode 100644 index 000000000000..6ec0dbc1c585 --- /dev/null +++ b/lib/libpthread/thread/thr_attr_setdetachstate.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || + (detachstate != PTHREAD_CREATE_DETACHED && + detachstate != PTHREAD_CREATE_JOINABLE)) + ret = EINVAL; + else { + /* Check if detached state: */ + if (detachstate == PTHREAD_CREATE_DETACHED) + /* Set the detached flag: */ + (*attr)->flags |= PTHREAD_DETACHED; + else + /* Reset the detached flag: */ + (*attr)->flags &= ~PTHREAD_DETACHED; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_attr_setstackaddr.c b/lib/libpthread/thread/thr_attr_setstackaddr.c new file mode 100644 index 000000000000..ce54915d096d --- /dev/null +++ b/lib/libpthread/thread/thr_attr_setstackaddr.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stackaddr == NULL) + ret = EINVAL; + else { + /* Save the stack address: */ + (*attr)->stackaddr_attr = stackaddr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_attr_setstacksize.c b/lib/libpthread/thread/thr_attr_setstacksize.c index 5e59798f579b..94e575e0dded 100644 --- a/lib/libpthread/thread/thr_attr_setstacksize.c +++ b/lib/libpthread/thread/thr_attr_setstacksize.c @@ -38,10 +38,12 @@ int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { int ret; - if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) { - errno = EINVAL; - ret = -1; - } else { + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) + ret = EINVAL; + else { + /* Save the stack size: */ (*attr)->stacksize_attr = stacksize; ret = 0; } diff --git a/lib/libpthread/thread/thr_clean.c b/lib/libpthread/thread/thr_clean.c index 99893f671b1d..9319f85efbea 100644 --- a/lib/libpthread/thread/thr_clean.c +++ b/lib/libpthread/thread/thr_clean.c @@ -37,11 +37,10 @@ #include #include "pthread_private.h" -int -_thread_cleanup_push(void (*routine) (void *), void *routine_arg) +void +pthread_cleanup_push(void (*routine) (void *), void *routine_arg) { struct pthread_cleanup *new; - int ret; if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) { new->routine = routine; @@ -49,15 +48,11 @@ _thread_cleanup_push(void (*routine) (void *), void *routine_arg) new->next = _thread_run->cleanup; _thread_run->cleanup = new; - ret = 0; - } else { - ret = ENOMEM; } - return (ret); } void -_thread_cleanup_pop(int execute) +pthread_cleanup_pop(int execute) { struct pthread_cleanup *old; diff --git a/lib/libpthread/thread/thr_cond.c b/lib/libpthread/thread/thr_cond.c index 439538044610..2fe4532ab00a 100644 --- a/lib/libpthread/thread/thr_cond.c +++ b/lib/libpthread/thread/thr_cond.c @@ -272,7 +272,7 @@ pthread_cond_signal(pthread_cond_t * cond) /* Bring the next thread off the condition queue: */ if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) { /* Allow the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } break; @@ -309,7 +309,7 @@ pthread_cond_broadcast(pthread_cond_t * cond) /* Enter a loop to bring all threads off the condition queue: */ while ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) { /* Allow the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } break; diff --git a/lib/libpthread/thread/thr_condattr_destroy.c b/lib/libpthread/thread/thr_condattr_destroy.c new file mode 100644 index 000000000000..b20f183bb608 --- /dev/null +++ b/lib/libpthread/thread/thr_condattr_destroy.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_condattr_destroy(pthread_condattr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_condattr_init.c b/lib/libpthread/thread/thr_condattr_init.c new file mode 100644 index 000000000000..f94e4384b925 --- /dev/null +++ b/lib/libpthread/thread/thr_condattr_init.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 John Birrell + * 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 +#include +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_condattr_init(pthread_condattr_t *attr) +{ + int ret; + pthread_condattr_t pattr; + + if ((pattr = (pthread_condattr_t) + malloc(sizeof(struct pthread_cond_attr))) == NULL) { + errno = ENOMEM; + ret = -1; + } else { + memcpy(pattr, &pthread_condattr_default, + sizeof(struct pthread_cond_attr)); + *attr = pattr; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_create.c b/lib/libpthread/thread/thr_create.c index 1d57f8a1626d..e4925a9c420a 100644 --- a/lib/libpthread/thread/thr_create.c +++ b/lib/libpthread/thread/thr_create.c @@ -87,9 +87,9 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr, new_thread->start_routine = start_routine; new_thread->arg = arg; if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { - new_thread->state = PS_SUSPENDED; + PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED); } else { - new_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(new_thread,PS_RUNNING); } /* Initialise the thread for signals: */ @@ -208,7 +208,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr, * a signal handler thread which must now * wait for the signal handler to complete: */ - parent->state = PS_SIGTHREAD; + PTHREAD_NEW_STATE(parent,PS_SIGTHREAD); } else { /* Schedule the new user thread: */ _thread_kern_sched(NULL); diff --git a/lib/libpthread/thread/thr_detach.c b/lib/libpthread/thread/thr_detach.c index f24d16f2dbce..08cace4c0af8 100644 --- a/lib/libpthread/thread/thr_detach.c +++ b/lib/libpthread/thread/thr_detach.c @@ -49,7 +49,7 @@ pthread_detach(pthread_t * p_pthread) /* Check for invalid calling parameters: */ if (p_pthread == NULL || (pthread = *p_pthread) == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } /* Check if the thread has not been detached: */ @@ -60,7 +60,7 @@ pthread_detach(pthread_t * p_pthread) /* Enter a loop to bring all threads off the join queue: */ while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) { /* Make the thread run: */ - next_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(next_thread,PS_RUNNING); } /* @@ -70,7 +70,7 @@ pthread_detach(pthread_t * p_pthread) *p_pthread = NULL; } else { /* Return an error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } diff --git a/lib/libpthread/thread/thr_exit.c b/lib/libpthread/thread/thr_exit.c index 60662060e01e..15bcfa36f4f4 100644 --- a/lib/libpthread/thread/thr_exit.c +++ b/lib/libpthread/thread/thr_exit.c @@ -109,7 +109,7 @@ pthread_exit(void *status) _thread_run->ret = status; while (_thread_run->cleanup != NULL) { - _thread_cleanup_pop(1); + pthread_cleanup_pop(1); } if (_thread_run->attr.cleanup_attr != NULL) { @@ -123,7 +123,7 @@ pthread_exit(void *status) /* Check if there are any threads joined to this one: */ while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) { /* Wake the joined thread and let it detach this thread: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } /* Check if the running thread is at the head of the linked list: */ @@ -173,11 +173,11 @@ pthread_exit(void *status) /* * Check if the parent is not waiting on any other signal - * handler threads: + * handler threads and if it hasn't died in the meantime: */ - if (pthread == NULL) { + if (pthread == NULL && _thread_run->parent_thread->state != PS_DEAD) { /* Allow the parent thread to run again: */ - _thread_run->parent_thread->state = PS_RUNNING; + PTHREAD_NEW_STATE(_thread_run->parent_thread,PS_RUNNING); } /* Get the signal number: */ l = (long) _thread_run->arg; diff --git a/lib/libpthread/thread/thr_getprio.c b/lib/libpthread/thread/thr_getprio.c index 345f6ce2c888..85bd2616b735 100644 --- a/lib/libpthread/thread/thr_getprio.c +++ b/lib/libpthread/thread/thr_getprio.c @@ -57,7 +57,7 @@ pthread_getprio(pthread_t pthread) /* Check if the thread pointer is NULL: */ if (pthread == NULL || pthread_p == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } else { /* Get the thread priority: */ diff --git a/lib/libpthread/thread/thr_info.c b/lib/libpthread/thread/thr_info.c index e69145f8fd4b..be25d45270f1 100644 --- a/lib/libpthread/thread/thr_info.c +++ b/lib/libpthread/thread/thr_info.c @@ -87,8 +87,8 @@ _thread_dump_info(void) if (thread_info[j].state == pthread->state) break; /* Output a record for the current thread: */ - sprintf(s, "--------------------\nThread %p prio %3d state %s\n", - pthread, pthread->pthread_priority, thread_info[j].name); + sprintf(s, "--------------------\nThread %p prio %3d state %s [%s:%d]\n", + pthread, pthread->pthread_priority, thread_info[j].name,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); /* Check if this is the running thread: */ @@ -107,6 +107,9 @@ _thread_dump_info(void) switch (pthread->state) { /* File descriptor read lock wait: */ case PS_FDLR_WAIT: + case PS_FDLW_WAIT: + case PS_FDR_WAIT: + case PS_FDW_WAIT: /* Write the lock details: */ sprintf(s, "fd %d[%s:%d]", pthread->data.fd.fd, pthread->data.fd.fname, pthread->data.fd.branch); _thread_sys_write(fd, s, strlen(s)); @@ -140,11 +143,15 @@ _thread_dump_info(void) */ for (pthread = _thread_dead; pthread != NULL; pthread = pthread->nxt) { /* Output a record for the current thread: */ - sprintf(s, "Thread %p prio %3d\n", pthread, pthread->pthread_priority); + sprintf(s, "Thread %p prio %3d [%s:%d]\n", pthread, pthread->pthread_priority,pthread->fname,pthread->lineno); _thread_sys_write(fd, s, strlen(s)); } } + /* Output a header for file descriptors: */ + strcpy(s, "\n\n=============\nFILE DESCRIPTOR TABLE\n\n"); + _thread_sys_write(fd, s, strlen(s)); + /* Enter a loop to report file descriptor lock usage: */ for (i = 0; i < _thread_dtablesize; i++) { /* diff --git a/lib/libpthread/thread/thr_init.c b/lib/libpthread/thread/thr_init.c index d044063ce9d4..2adc34f152c1 100644 --- a/lib/libpthread/thread/thr_init.c +++ b/lib/libpthread/thread/thr_init.c @@ -44,7 +44,11 @@ #include #include #include "pthread_private.h" +extern int _thread_autoinit_dummy_decl; +/* + * Threaded process initialization + */ void _thread_init(void) { @@ -52,15 +56,25 @@ _thread_init(void) int i; struct sigaction act; + /* Ensure that the auto-initialization routine is linked in: */ + _thread_autoinit_dummy_decl = 1; + /* Check if this function has already been called: */ - if (_thread_initial) { + if (_thread_initial) /* Only initialise the threaded application once. */ - } + return; + + /* Get the standard I/O flags before messing with them : */ + for (i = 0; i < 3; i++) + if ((_pthread_stdio_flags[i] = + _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) + PANIC("Cannot get stdio flags"); + /* * Create a pipe that is written to by the signal handler to prevent * signals being missed in calls to _thread_sys_select: */ - else if (_thread_sys_pipe(_thread_kern_pipe) != 0) { + if (_thread_sys_pipe(_thread_kern_pipe) != 0) { /* Cannot create pipe, so abort: */ PANIC("Cannot create kernel pipe"); } diff --git a/lib/libpthread/thread/thr_join.c b/lib/libpthread/thread/thr_join.c index d0093ae72f05..161482e289a8 100644 --- a/lib/libpthread/thread/thr_join.c +++ b/lib/libpthread/thread/thr_join.c @@ -40,14 +40,40 @@ pthread_join(pthread_t pthread, void **thread_return) { int rval = 0; int status; + pthread_t pthread1; /* Block signals: */ _thread_kern_sig_block(&status); - /* 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 { diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c index 1db4da6284fc..679b3158048a 100644 --- a/lib/libpthread/thread/thr_kern.c +++ b/lib/libpthread/thread/thr_kern.c @@ -293,7 +293,7 @@ __asm__("fnsave %0": :"m"(*fdata)); * Change the threads state to allow * it to be restarted: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } } } @@ -823,14 +823,21 @@ __asm__("fnsave %0": :"m"(*fdata)); static void _thread_signal(pthread_t pthread, int sig) { + int done; long l; pthread_t new_pthread; struct sigaction act; void *arg; + /* + * Assume that the signal will not be dealt with according + * to the thread state: + */ + done = 0; + /* Process according to thread state: */ switch (pthread->state) { - /* States which do not change when a signal is trapped: */ + /* States which do not change when a signal is trapped: */ case PS_COND_WAIT: case PS_DEAD: case PS_FDLR_WAIT: @@ -844,7 +851,7 @@ _thread_signal(pthread_t pthread, int sig) /* Nothing to do here. */ break; - /* Wait for child: */ + /* Wait for child: */ case PS_WAIT_WAIT: /* Check if the signal is from a child exiting: */ if (sig == SIGCHLD) { @@ -852,42 +859,72 @@ _thread_signal(pthread_t pthread, int sig) _thread_seterrno(pthread, 0); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } else { /* Return the 'interrupted' error: */ _thread_seterrno(pthread, EINTR); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } + pthread->interrupted = 1; break; - /* - * States that are interrupted by the occurrence of a signal - * other than the scheduling alarm: - */ - 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); diff --git a/lib/libpthread/thread/thr_kill.c b/lib/libpthread/thread/thr_kill.c new file mode 100644 index 000000000000..eb2c6b75d740 --- /dev/null +++ b/lib/libpthread/thread/thr_kill.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_kill(pthread_t pthread, int sig) +{ + int rval = 0; + int status; + pthread_t p_pthread; + + /* Check for invalid signal numbers: */ + if (sig < 0 || sig >= NSIG) + /* Invalid signal: */ + rval = EINVAL; + else { + /* Assume that the search will succeed: */ + rval = 0; + + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* Search for the thread: */ + p_pthread = _thread_link_list; + while (p_pthread != NULL && p_pthread != pthread) { + p_pthread = p_pthread->nxt; + } + + /* Check if the thread was not found: */ + if (p_pthread == NULL) + /* Can't find the thread: */ + rval = ESRCH; + else + /* Increment the pending signal count: */ + p_pthread->sigpend[sig] += 1; + + /* Unblock signals: */ + _thread_kern_sig_unblock(status); + } + + /* Return the completion status: */ + return (rval); +} +#endif diff --git a/lib/libpthread/thread/thr_mutex.c b/lib/libpthread/thread/thr_mutex.c index dc9be3c5ff78..82a26e846d5a 100644 --- a/lib/libpthread/thread/thr_mutex.c +++ b/lib/libpthread/thread/thr_mutex.c @@ -76,18 +76,18 @@ pthread_mutex_init(pthread_mutex_t * mutex, /* Process according to mutex type: */ switch (type) { - /* Fast mutex: */ + /* Fast mutex: */ case MUTEX_TYPE_FAST: /* Nothing to do here. */ break; - /* Counting mutex: */ + /* Counting mutex: */ case MUTEX_TYPE_COUNTING_FAST: /* Reset the mutex count: */ pmutex->m_data.m_count = 0; break; - /* Trap invalid mutex types: */ + /* Trap invalid mutex types: */ default: /* Return an invalid argument error: */ errno = EINVAL; @@ -130,18 +130,18 @@ pthread_mutex_destroy(pthread_mutex_t * mutex) /* Process according to mutex type: */ switch ((*mutex)->m_type) { - /* Fast mutex: */ + /* Fast mutex: */ case MUTEX_TYPE_FAST: /* Nothing to do here. */ break; - /* Counting mutex: */ + /* Counting mutex: */ case MUTEX_TYPE_COUNTING_FAST: /* Reset the mutex count: */ (*mutex)->m_data.m_count = 0; break; - /* Trap undefined mutex types: */ + /* Trap undefined mutex types: */ default: /* Return an invalid argument error: */ errno = EINVAL; @@ -348,7 +348,7 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) */ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { /* Allow the new owner of the mutex to run: */ - (*mutex)->m_owner->state = PS_RUNNING; + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); } break; @@ -371,7 +371,7 @@ pthread_mutex_unlock(pthread_mutex_t * mutex) */ else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) { /* Allow the new owner of the mutex to run: */ - (*mutex)->m_owner->state = PS_RUNNING; + PTHREAD_NEW_STATE((*mutex)->m_owner,PS_RUNNING); } break; diff --git a/lib/libpthread/thread/thr_mutexattr_destroy.c b/lib/libpthread/thread/thr_mutexattr_destroy.c new file mode 100644 index 000000000000..cf2e09f44e23 --- /dev/null +++ b/lib/libpthread/thread/thr_mutexattr_destroy.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); +} +#endif diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h index a16bdea0387e..064888f1978e 100644 --- a/lib/libpthread/thread/thr_private.h +++ b/lib/libpthread/thread/thr_private.h @@ -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); diff --git a/lib/libpthread/thread/thr_read.c b/lib/libpthread/thread/thr_read.c index 91588441f8be..504143db9ed5 100644 --- a/lib/libpthread/thread/thr_read.c +++ b/lib/libpthread/thread/thr_read.c @@ -42,22 +42,31 @@ ssize_t read(int fd, void *buf, size_t nbytes) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read: */ + if ((ret = _thread_fd_lock(fd, FD_READ, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking read syscall: */ while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDR_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ read(int fd, void *buf, size_t nbytes) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_READ); - } + _thread_fd_unlock(fd, FD_READ); } return (ret); } diff --git a/lib/libpthread/thread/thr_readv.c b/lib/libpthread/thread/thr_readv.c index acb72ac2b1b8..fed418b84229 100644 --- a/lib/libpthread/thread/thr_readv.c +++ b/lib/libpthread/thread/thr_readv.c @@ -42,22 +42,31 @@ ssize_t readv(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_READ, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read: */ + if ((ret = _thread_fd_lock(fd, FD_READ, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking readv syscall: */ while ((ret = _thread_sys_readv(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDR_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDR_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ readv(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_READ); - } + _thread_fd_unlock(fd, FD_READ); } return (ret); } diff --git a/lib/libpthread/thread/thr_resume_np.c b/lib/libpthread/thread/thr_resume_np.c index a254814163af..934df58c75a4 100644 --- a/lib/libpthread/thread/thr_resume_np.c +++ b/lib/libpthread/thread/thr_resume_np.c @@ -49,21 +49,21 @@ pthread_resume_np(pthread_t thread) /* Found the thread. Is it suspended? */ if (pthread->state == PS_SUSPENDED) { /* Allow the thread to run. */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); ret = 0; } else if (pthread->state == PS_RUNNING) { /* Thread is already running. */ ret = 0; } else { /* Thread is in some other state. */ - _thread_seterrno(_thread_run,EINVAL); + errno = EINVAL; } } } /* Check if thread was not found. */ if (ret == -1) { /* No such thread */ - _thread_seterrno(_thread_run,ESRCH); + errno = ESRCH; } return(ret); } diff --git a/lib/libpthread/thread/thr_setprio.c b/lib/libpthread/thread/thr_setprio.c index e052ec34c5d2..4b49ed096afb 100644 --- a/lib/libpthread/thread/thr_setprio.c +++ b/lib/libpthread/thread/thr_setprio.c @@ -45,7 +45,7 @@ pthread_setprio(pthread_t pthread, int prio) /* Check if the priority is invalid: */ if (prio < PTHREAD_MIN_PRIORITY || prio > PTHREAD_MAX_PRIORITY) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; rval = -1; } else { /* Block signals: */ @@ -63,7 +63,7 @@ pthread_setprio(pthread_t pthread, int prio) /* Check if the thread pointer is NULL: */ if (pthread == NULL || pthread_p == NULL) { /* Return a 'search' error: */ - _thread_seterrno(_thread_run, ESRCH); + errno = ESRCH; rval = -1; } else { /* Set the thread priority: */ diff --git a/lib/libpthread/thread/thr_sig.c b/lib/libpthread/thread/thr_sig.c index c3ec1919077e..e73d5a21e3af 100644 --- a/lib/libpthread/thread/thr_sig.c +++ b/lib/libpthread/thread/thr_sig.c @@ -97,7 +97,7 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) _thread_seterrno(pthread, 0); /* Change the state of the thread to run: */ - pthread->state = PS_RUNNING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); } } diff --git a/lib/libpthread/thread/thr_sigaction.c b/lib/libpthread/thread/thr_sigaction.c index c7336677ff9c..dd084056366c 100644 --- a/lib/libpthread/thread/thr_sigaction.c +++ b/lib/libpthread/thread/thr_sigaction.c @@ -45,7 +45,7 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact) /* Check if the signal number is out of range: */ if (sig < 1 || sig > NSIG) { /* Return an invalid argument: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; ret = -1; } else { /* diff --git a/lib/libpthread/thread/thr_sigmask.c b/lib/libpthread/thread/thr_sigmask.c new file mode 100644 index 000000000000..94f64cb7991f --- /dev/null +++ b/lib/libpthread/thread/thr_sigmask.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) +{ + int ret = 0; + int status; + + /* Check if the existing signal process mask is to be returned: */ + if (oset != NULL) { + /* Return the current mask: */ + *oset = _thread_run->sigmask; + } + /* Check if a new signal set was provided by the caller: */ + if (set != NULL) { + /* Block signals while the signal mask is changed: */ + _thread_kern_sig_block(&status); + + /* Process according to what to do: */ + switch (how) { + /* Block signals: */ + case SIG_BLOCK: + /* Add signals to the existing mask: */ + _thread_run->sigmask |= *set; + break; + + /* Unblock signals: */ + case SIG_UNBLOCK: + /* Clear signals from the existing mask: */ + _thread_run->sigmask &= ~(*set); + break; + + /* Set the signal process mask: */ + case SIG_SETMASK: + /* Set the new mask: */ + _thread_run->sigmask = *set; + break; + + /* Trap invalid actions: */ + default: + /* Return an invalid argument: */ + errno = EINVAL; + ret = -1; + break; + } + + /* + * Schedule the next thread in case there are signals that + * now need to be acted on: + */ + _thread_kern_sched(NULL); + } + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libpthread/thread/thr_sigprocmask.c b/lib/libpthread/thread/thr_sigprocmask.c index d6e3197d2e40..b4a8d84940eb 100644 --- a/lib/libpthread/thread/thr_sigprocmask.c +++ b/lib/libpthread/thread/thr_sigprocmask.c @@ -54,28 +54,28 @@ sigprocmask(int how, const sigset_t * set, sigset_t * oset) /* Process according to what to do: */ switch (how) { - /* Block signals: */ + /* Block signals: */ case SIG_BLOCK: /* Add signals to the existing mask: */ _thread_run->sigmask |= *set; break; - /* Unblock signals: */ + /* Unblock signals: */ case SIG_UNBLOCK: /* Clear signals from the existing mask: */ _thread_run->sigmask &= ~(*set); break; - /* Set the signal process mask: */ + /* Set the signal process mask: */ case SIG_SETMASK: /* Set the new mask: */ _thread_run->sigmask = *set; break; - /* Trap invalid actions: */ + /* Trap invalid actions: */ default: /* Return an invalid argument: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; ret = -1; break; } diff --git a/lib/libpthread/thread/thr_sigsuspend.c b/lib/libpthread/thread/thr_sigsuspend.c index a26b6b99bf4b..14cf74b31ece 100644 --- a/lib/libpthread/thread/thr_sigsuspend.c +++ b/lib/libpthread/thread/thr_sigsuspend.c @@ -57,7 +57,7 @@ sigsuspend(const sigset_t * set) _thread_run->sigmask = oset; } else { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; } /* Return the completion status: */ diff --git a/lib/libpthread/thread/thr_sigwait.c b/lib/libpthread/thread/thr_sigwait.c new file mode 100644 index 000000000000..4f95190e4216 --- /dev/null +++ b/lib/libpthread/thread/thr_sigwait.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1997 John Birrell . + * 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 +#include +#ifdef _THREAD_SAFE +#include +#include "pthread_private.h" + +int +sigwait(const sigset_t * set, int *sig) +{ + int ret; + int status; + sigset_t oset; + + /* Block signals: */ + _thread_kern_sig_block(&status); + + /* Save the current sigmal mask: */ + oset = _thread_run->sigmask; + + /* Combine the caller's mask with the current one: */ + _thread_run->sigmask |= *set; + + /* Wait for a signal: */ + _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__); + + /* Block signals again: */ + _thread_kern_sig_block(NULL); + + /* Return the signal number to the caller: */ + *sig = _thread_run->signo; + + /* Restore the signal mask: */ + _thread_run->sigmask = oset; + + /* Unblock signals: */ + _thread_kern_sig_unblock(status); + + /* Return the completion status: */ + return (ret); +} +#endif diff --git a/lib/libpthread/thread/thr_spec.c b/lib/libpthread/thread/thr_spec.c index 4447a75942ab..8d06c52b8d98 100644 --- a/lib/libpthread/thread/thr_spec.c +++ b/lib/libpthread/thread/thr_spec.c @@ -209,7 +209,7 @@ pthread_getspecific(pthread_key_t key) /* Check for errors: */ if (pthread == NULL) { /* Return an invalid argument error: */ - _thread_seterrno(_thread_run, EINVAL); + errno = EINVAL; data = NULL; } /* Check if there is specific data: */ diff --git a/lib/libpthread/thread/thr_suspend_np.c b/lib/libpthread/thread/thr_suspend_np.c index fb90c1d494d2..d065b73964e2 100644 --- a/lib/libpthread/thread/thr_suspend_np.c +++ b/lib/libpthread/thread/thr_suspend_np.c @@ -53,14 +53,14 @@ pthread_suspend_np(pthread_t thread) _thread_seterrno(pthread,EINTR); } /* Suspend the thread. */ - pthread->state = PS_SUSPENDED; + PTHREAD_NEW_STATE(pthread,PS_SUSPENDED); ret = 0; } } /* Check if thread was not found. */ if (ret == -1) { /* No such thread */ - _thread_seterrno(_thread_run,ESRCH); + errno = ESRCH; } return(ret); } diff --git a/lib/libpthread/thread/thr_write.c b/lib/libpthread/thread/thr_write.c index fb6912997911..2baa19f08426 100644 --- a/lib/libpthread/thread/thr_write.c +++ b/lib/libpthread/thread/thr_write.c @@ -42,22 +42,31 @@ ssize_t write(int fd, const void *buf, size_t nbytes) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking write syscall: */ while ((ret = _thread_sys_write(fd, buf, nbytes)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ write(int fd, const void *buf, size_t nbytes) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); } diff --git a/lib/libpthread/thread/thr_writev.c b/lib/libpthread/thread/thr_writev.c index f40e611d98fe..2a3c0c84c2d0 100644 --- a/lib/libpthread/thread/thr_writev.c +++ b/lib/libpthread/thread/thr_writev.c @@ -42,22 +42,31 @@ ssize_t writev(int fd, const struct iovec * iov, int iovcnt) { - int nonblock; - int ret; - int status; - if (fd < 0 || fd > _thread_dtablesize || _thread_fd_table[fd] == NULL) { - _thread_seterrno(_thread_run, EBADF); - ret = -1; - } else if ((nonblock = _thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { - /* Cannot lock file descriptor. */ - } else { + int ret; + int status; + + /* Lock the file descriptor for read and write: */ + if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, + __FILE__, __LINE__)) == 0) { + /* Perform a non-blocking writev syscall: */ while ((ret = _thread_sys_writev(fd, iov, iovcnt)) < 0) { - if (nonblock == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { + if (_thread_fd_table[fd]->flags & O_NONBLOCK == 0 && + (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_kern_sig_block(&status); _thread_run->data.fd.fd = fd; _thread_kern_set_timeout(NULL); - _thread_kern_sched_state(PS_FDW_WAIT, __FILE__, __LINE__); - if (errno == EINTR) { + + /* Reset the interrupted operation flag: */ + _thread_run->interrupted = 0; + + _thread_kern_sched_state(PS_FDW_WAIT, + __FILE__, __LINE__); + + /* + * Check if the operation was + * interrupted by a signal + */ + if (_thread_run->interrupted) { ret = -1; break; } @@ -65,9 +74,7 @@ writev(int fd, const struct iovec * iov, int iovcnt) break; } } - if (nonblock == 0) { - _thread_fd_unlock(fd, FD_RDWR); - } + _thread_fd_unlock(fd, FD_RDWR); } return (ret); }