Index: bin/miniuts/Makefile =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- bin/miniuts/Makefile Sun Sep 15 21:38:20 2002 *************** *** 0 **** --- 1,4 ---- + PROG= uts + NOMAN= + + .include Index: lib/libc/gen/swapcontext.c =========================================================================== --- lib/libc/gen/swapcontext.c 2002/09/15 21:37:55 #2 +++ lib/libc/gen/swapcontext.c 2002/09/15 21:37:55 @@ -27,29 +27,33 @@ #include __FBSDID("$FreeBSD: src/lib/libc/gen/swapcontext.c,v 1.2 2002/01/11 19:46:08 deischen Exp $"); +#include +#include +#include + #include -#include #include -#include __weak_reference(__swapcontext, swapcontext); int __swapcontext(ucontext_t *oucp, const ucontext_t *ucp) { - volatile int swapping; int ret; - if (oucp == NULL || ucp == NULL) { + + if ((oucp == NULL) || + (oucp->uc_mcontext.mc_len != sizeof(mcontext_t)) || + (ucp == NULL) || + (ucp->uc_mcontext.mc_len != sizeof(mcontext_t))) { errno = EINVAL; - ret = -1; - } else { - swapping = 0; - ret = getcontext(oucp); - if (ret == 0 && swapping == 0) { - swapping = 1; - ret = setcontext(ucp); - } + return (-1); + } + oucp->uc_flags &= ~UCF_SWAPPED; + ret = getcontext(oucp); + if ((ret == 0) && !(oucp->uc_flags & UCF_SWAPPED)) { + oucp->uc_flags |= UCF_SWAPPED; + ret = setcontext(ucp); } return (ret); } Index: lib/libc/i386/gen/Makefile.inc =========================================================================== --- lib/libc/i386/gen/Makefile.inc 2002/09/15 21:37:55 #4 +++ lib/libc/i386/gen/Makefile.inc 2002/09/15 21:37:55 @@ -3,4 +3,4 @@ SRCS+= _ctx_start.S _setjmp.S alloca.S getcontext.S fabs.S frexp.c \ infinity.c isinf.c ldexp.c makecontext.c modf.S \ - rfork_thread.S setjmp.S sigsetjmp.S swapcontext.c + rfork_thread.S setjmp.S sigsetjmp.S swapcontext.c signalcontext.c Index: lib/libc/i386/gen/getcontext.S =========================================================================== --- lib/libc/i386/gen/getcontext.S 2002/09/15 21:37:55 #2 +++ lib/libc/i386/gen/getcontext.S 2002/09/15 21:37:55 @@ -30,14 +30,13 @@ /* * Where do we define these? */ -#define UC_MC_VALID 0x0001 /* __UC_MC_VALID */ -#define UC_FP_VALID 0x0002 /* __UC_FP_VALID */ -#define MC_FP_VALID UC_MC_VALID | UC_FP_VALID +#define MC_SIZE 640 /* sizeof mcontext_t */ #define UC_MC_OFFSET 16 /* offset to mcontext from ucontext */ -#define UC_FLAGS_OFFSET 208 /* offset to flags from ucontext */ -#define MC_FLAGS_OFFSET 192 /* offset to flags from mcontext */ -#define MC_FP_REGS_OFFSET 80 /* offset to FP regs from mcontext */ -#define MC_FP_CW_OFFSET 80 /* offset to FP control word */ +#define UC_MC_LEN_OFFSET 96 /* offset to mc_len from mcontext */ +#define MC_LEN_OFFSET 80 /* offset to mc_len from mcontext */ +#define MC_FP_REGS_OFFSET 96 /* offset to FP regs from mcontext */ +#define MC_FP_CW_OFFSET 96 /* offset to FP control word */ +#define MC_OWNEDFP_OFFSET 88 /* offset to mc_ownedfp from mcontext */ /* * int setcontext(ucontext_t *ucp); @@ -54,8 +53,8 @@ jne 1f movl $-1, %eax jmp 5f -1: testl $UC_MC_VALID, UC_FLAGS_OFFSET(%eax) /* is context valid? */ - jnz 2f +1: cmpl $MC_SIZE, UC_MC_LEN_OFFSET(%eax) /* is context valid? */ + je 2f movl $-1, %eax /* bzzzt, invalid context */ jmp 5f 2: PIC_PROLOGUE @@ -73,6 +72,7 @@ movl 8(%edx), %fs movl 12(%edx), %es movl 16(%edx), %ds + movl 76(%edx), %ss movl 20(%edx), %edi movl 24(%edx), %esi movl 28(%edx), %ebp @@ -80,18 +80,19 @@ subl $4, %esp /* leave space for the return address */ movl 60(%edx), %eax /* put return address at top of stack */ movl %eax, (%esp) - testl $UC_FP_VALID, MC_FLAGS_OFFSET(%edx) /* are FP regs valid? */ + cmpl $0, MC_OWNEDFP_OFFSET(%edx) /* are FP regs valid? */ jz 3f frstor MC_FP_REGS_OFFSET(%edx) /* restore FP regs */ jmp 4f 3: fninit fldcw MC_FP_CW_OFFSET(%edx) -4: movl 68(%edx), %eax /* restore flags register */ - sahf - movl 48(%edx), %eax /* restore ax, bx, cx, and dx last */ +4: movl 48(%edx), %eax /* restore ax, bx, cx */ movl 36(%edx), %ebx movl 44(%edx), %ecx - movl 40(%edx), %edx + pushl 68(%edx) /* flags on stack */ + pushl 40(%edx) /* %edx on stack */ + popl %edx /* %edx off stack */ + popf /* flags off stack */ 5: ret /* @@ -109,8 +110,8 @@ jne 1f movl $-1, %eax jmp 2f - movl 4(%esp), %eax /* get address of context and sigset */ -1: PIC_PROLOGUE +1: movl 4(%esp), %eax /* get address of context and sigset */ + PIC_PROLOGUE pushl %eax /* oset = &ucp->uc_sigmask */ pushl $0 /* set = NULL */ pushl $3 /* how = SIG_SETMASK */ @@ -136,30 +137,23 @@ movl %ecx, 44(%edx) movl (%esp), %eax /* get return address */ movl %eax, 60(%edx) /* save return address */ + movl %ss, 76(%edx) /* - * XXX - Do we really need to save floating point registers? + * Don't save floating point registers here. * * This is an explicit call to get the current context, so - * shouldn't the caller be done with the floating point registers? + * the caller is done with the floating point registers. * Contexts formed by involuntary switches, such as signal delivery, - * should have floating point registers saved by the kernel. - * - * As of this writing, the kernel doesn't yet save the FPU state - * on signal delivery, so a setcontext on the interrupted context - * may yield incorrect results regardless. + * have floating point registers saved by the kernel. */ -#if 1 fnstcw MC_FP_CW_OFFSET(%edx) - movl $UC_MC_VALID, MC_FLAGS_OFFSET(%edx) /* mcontext valid, no FP */ -#else - fnsave MC_FP_REGS_OFFSET(%edx) /* save FP regs */ - movl $MC_FP_VALID, MC_FLAGS_OFFSET(%edx) /* mcontext and FP valid */ -#endif + movl $0, MC_OWNEDFP_OFFSET(%edx) /* no FP */ lahf /* get eflags */ movl %eax, 68(%edx) /* store eflags */ movl %esp, %eax /* setcontext pushes the return */ addl $4, %eax /* address onto the top of the */ movl %eax, 72(%edx) /* stack; account for this */ + movl $MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */ movl 40(%edx), %edx /* restore edx -- is this needed? */ xorl %eax, %eax /* return 0 */ 2: ret Index: lib/libc/i386/gen/makecontext.c =========================================================================== --- lib/libc/i386/gen/makecontext.c 2002/09/15 21:37:55 #2 +++ lib/libc/i386/gen/makecontext.c 2002/09/15 21:37:55 @@ -29,11 +29,11 @@ #include #include +#include #include #include #include -#include #include /* Prototypes */ @@ -53,7 +53,7 @@ * to be restarted without being reinitialized (via * setcontext or swapcontext). */ - ucp->uc_mcontext.mc_flags = 0; + ucp->uc_mcontext.mc_len = 0; /* Set context to next one in link */ /* XXX - what to do for error, abort? */ @@ -80,14 +80,14 @@ * a void function. At least make sure that the context * isn't valid so it can't be used without an error. */ - ucp->uc_mcontext.mc_flags = 0; + ucp->uc_mcontext.mc_len = 0; } /* XXX - Do we want to sanity check argc? */ else if ((argc < 0) || (argc > NCARGS)) { - ucp->uc_mcontext.mc_flags = 0; + ucp->uc_mcontext.mc_len = 0; } /* Make sure the context is valid. */ - else if ((ucp->uc_mcontext.mc_flags & __UC_MC_VALID) != 0) { + else if (ucp->uc_mcontext.mc_len == sizeof(mcontext_t)) { /* * Arrange the stack as follows: * Index: lib/libc/i386/gen/signalcontext.c =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libc/i386/gen/signalcontext.c Sun Sep 15 21:38:20 2002 *************** *** 0 **** --- 1,80 ---- + /*- + * Copyright (c) 2002 Jonathan Mini + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + + #include + __FBSDID("$FreeBSD"); + + #include + #include + #include + #include + #include + #include + + extern void _ctx_start(ucontext_t *, int argc, ...); + + int + signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func) + { + struct sigframe *sfp; + int *p; + + /* + * Set up stack. + * (n = sizeof(int)) + * 2n+sizeof(struct sigframe) ucp + * 2n struct sigframe + * 1n &func + * 0n &_ctx_start + */ + p = (int *)ucp->uc_mcontext.mc_esp; + *--p = (int)ucp; + p -= sizeof(struct sigframe); + sfp = (struct sigframe *)p; + bzero(sfp, sizeof(struct sigframe)); + sfp->sf_signum = sig; + sfp->sf_siginfo = (int)&sfp->sf_si; + sfp->sf_ucontext = (int)&sfp->sf_uc; + sfp->sf_ahu.sf_action = (__siginfohandler_t *)func; + bcopy(ucp, &sfp->sf_uc, sizeof(ucontext_t)); + sfp->sf_si.si_signo = sig; + + *--p = (int)func; + + /* + * Set up ucontext_t. + */ + ucp->uc_mcontext.mc_ebp = ucp->uc_mcontext.mc_esp - sizeof(int); + ucp->uc_mcontext.mc_esp = (int)p; + ucp->uc_mcontext.mc_eip = (int)_ctx_start; + ucp->uc_mcontext.mc_eflags &= ~PSL_T; + ucp->uc_link = &sfp->sf_uc; + SIGDELSET(ucp->uc_sigmask, sig); + return (0); + } + ==== //depot/vendor/freebsd/src/lib/libc_r/Makefile#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/arch/alpha/_atomic_lock.S#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/arch/i386/_atomic_lock.S#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/arch/ia64/_atomic_lock.S#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/Makefile.inc#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_attr.3#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cancel.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cleanup_pop.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cleanup_push.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cond_broadcast.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cond_destroy.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cond_init.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cond_signal.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cond_timedwait.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_cond_wait.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_condattr.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_create.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_detach.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_equal.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_exit.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_getspecific.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_join.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_key_create.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_key_delete.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_kill.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_mutex_destroy.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_mutex_init.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_mutex_lock.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_mutex_trylock.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_mutex_unlock.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_mutexattr.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_once.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlock_destroy.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlock_init.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlock_rdlock.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlock_unlock.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlock_wrlock.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlockattr_destroy.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlockattr_getpshared.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlockattr_init.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_rwlockattr_setpshared.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_schedparam.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_self.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_setspecific.3#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_sigmask.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/pthread_testcancel.3#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/sem_destroy.3#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/sem_getvalue.3#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/sem_init.3#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/sem_open.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/sem_post.3#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/sem_wait.3#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/man/sigwait.3#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/sys/Makefile.inc#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/sys/uthread_error.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/Makefile#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/README#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/guard_b.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/guard_b.exp#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/guard_s.pl#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/hello_b.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/hello_d.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/hello_d.exp#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/hello_s.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/join_leak_d.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/join_leak_d.exp#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/mutex_d.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/mutex_d.exp#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/propagate_s.pl#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/sem_d.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/sem_d.exp#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/sigsuspend_d.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/sigsuspend_d.exp#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/sigwait_d.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/sigwait_d.exp#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/test/verify#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/Makefile.inc#6 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/pthread_private.h#16 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_accept.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_acl_aclcheck_fd.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_acl_delete_fd.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_acl_get_fd.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_acl_set_fd.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_aio_suspend.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_destroy.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_getdetachstate.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_getguardsize.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_getinheritsched.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_getschedparam.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_getschedpolicy.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_getscope.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_getstackaddr.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_getstacksize.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_init.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setdetachstate.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setguardsize.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setinheritsched.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setschedparam.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setschedpolicy.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setscope.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setstackaddr.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_attr_setstacksize.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_autoinit.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_bind.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_cancel.c#7 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_clean.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_close.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_cond.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_condattr_destroy.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_condattr_init.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_connect.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_creat.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_create.c#5 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_detach.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_dup.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_dup2.c#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_equal.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_execve.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_exit.c#5 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fchflags.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fchmod.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fchown.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fcntl.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fd.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_file.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_find_thread.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_flock.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fork.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fpathconf.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fstat.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fstatfs.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_fsync.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_gc.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_getdirentries.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_getpeername.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_getprio.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_getschedparam.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_getsockname.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_getsockopt.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_info.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_init.c#10 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_ioctl.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_jmp.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_join.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_kern.c#5 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_kevent.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_kill.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_listen.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_main_np.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_mattr_init.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_mattr_kind_np.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_msync.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_multi_np.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_mutex.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_mutex_prioceiling.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_mutex_protocol.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_mutexattr_destroy.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_nanosleep.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_once.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_open.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_pause.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_pipe.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_poll.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_priority_queue.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_pselect.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_read.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_readv.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_recvfrom.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_recvmsg.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_resume_np.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_rwlock.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_rwlockattr.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_select.c#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_self.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sem.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sendfile.c#6 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sendmsg.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sendto.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_seterrno.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_setprio.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_setschedparam.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_setsockopt.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_shutdown.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sig.c#5 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sigaction.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sigmask.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sigpending.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sigprocmask.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sigsuspend.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sigwait.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_single_np.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_sleep.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_socket.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_socketpair.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_spec.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_spinlock.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_stack.c#4 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_suspend_np.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_switch_np.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_system.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_tcdrain.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_vfork.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_wait.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_wait4.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_waitpid.c#1 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_write.c#2 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_writev.c#3 - === ==== //depot/vendor/freebsd/src/lib/libc_r/uthread/uthread_yield.c#1 - === Index: lib/libpthread/Makefile =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/Makefile Sun Sep 15 21:38:21 2002 *************** *** 0 **** --- 1,31 ---- + # $FreeBSD: src/lib/libc_r/Makefile,v 1.31 2002/04/15 20:22:28 obrien Exp $ + # + # All library objects contain FreeBSD revision strings by default; they may be + # excluded as a space-saving measure. To produce a library that does + # not contain these strings, add -DSTRIP_FBSDID (see ) to CFLAGS + # below. Note, there are no IDs for syscall stubs whose sources are generated. + # To included legacy CSRG sccsid strings, add -DLIBC_SCCS and -DSYSLIBC_SCCS + # (for system call stubs) to CFLAGS below. -DSYSLIBC_SCCS affects just the + # system call stubs. + LIB=kse + SHLIB_MAJOR= 5 + SHLIB_MINOR= 0 + CFLAGS+=-DPTHREAD_KERNEL -D_THREAD_SAFE + CFLAGS+=-I${.CURDIR}/../libc/include -I${.CURDIR}/uthread \ + -I${.CURDIR}/../../include + + # Uncomment this if you want libpthread to contain debug information for + # thread locking. + CFLAGS+=-D_LOCK_DEBUG + + # enable extra internal consistancy checks + CFLAGS+=-D_PTHREADS_INVARIANTS + + AINC= -I${.CURDIR}/../libc/${MACHINE_ARCH} -I${.CURDIR}/uthread + PRECIOUSLIB= yes + + .include "${.CURDIR}/man/Makefile.inc" + .include "${.CURDIR}/uthread/Makefile.inc" + .include "${.CURDIR}/sys/Makefile.inc" + + .include Index: lib/libpthread/arch/alpha/_atomic_lock.S =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/arch/alpha/_atomic_lock.S Sun Sep 15 21:38:21 2002 *************** *** 0 **** --- 1,45 ---- + /* + * Copyright (c) 1998 John Birrell . + * All rights reserved. + * copyright Douglas Santry 1996 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the above copyright is retained + * in the source form. + * + * THIS SOFTWARE IS PROVIDED BY Douglas Santry 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 Douglas Santry 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. + * + * $FreeBSD: src/lib/libc_r/arch/alpha/_atomic_lock.S,v 1.3 1999/08/28 00:03:00 peter Exp $ + * + */ + + #include "SYS.h" + + /* + * Atomicly lock a location with an identifier provided the location + * is not currently locked. + * + * long _atomic_lock(long *); + * v0 will contain the return value (zero if lock obtained). + */ + LEAF(_atomic_lock,0) + LDGP(pv) + + 0: ldq_l v0, 0(a0) /* read existing lock value */ + mov 1, t0 /* locked value to store */ + stq_c t0, 0(a0) /* attempt to store, status in t0 */ + beq t0, 1f /* branch foward to optimise prediction */ + mb /* sync with other processors */ + RET /* return with v0==0 if lock obtained */ + 1: br 0b /* loop to try again */ + END(_atomic_lock) Index: lib/libpthread/arch/i386/_atomic_lock.S =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/arch/i386/_atomic_lock.S Sun Sep 15 21:38:21 2002 *************** *** 0 **** --- 1,42 ---- + /* + * Copyright (c) 1995-1998 John Birrell . + * All rights reserved. + * copyright Douglas Santry 1996 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the above copyright is retained + * in the source form. + * + * THIS SOFTWARE IS PROVIDED BY Douglas Santry 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 Douglas Santry 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. + */ + + #if defined(LIBC_RCS) && !defined(lint) + .text + .asciz "$FreeBSD: src/lib/libc_r/arch/i386/_atomic_lock.S,v 1.5 2001/10/25 01:30:54 peter Exp $" + #endif /* LIBC_RCS and not lint */ + + #include + + /* + * Atomicly lock a location with an identifier provided the location + * is not currently locked. + * + * long _atomic_lock(long *); + * eax will contain the return value (zero if lock obtained). + */ + ENTRY(_atomic_lock) + movl 4(%esp), %ecx + movl $1, %eax + xchg %eax, (%ecx) + ret + Index: lib/libpthread/arch/i386/_thread_enter_uts.S =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/arch/i386/_thread_enter_uts.S Sun Sep 15 21:38:21 2002 *************** *** 0 **** --- 1,96 ---- + /* + * Copyright (c) 2002 Jonathan Mini . + * Copyright (c) 2001 Daniel Eischen . + * 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. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN 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 AUTHOR 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 + __FBSDID("$FreeBSD$"); + + /* + * Where do we define these? + */ + #define MC_SIZE 640 /* sizeof mcontext_t */ + #define UC_MC_OFFSET 16 /* offset to mcontext from ucontext */ + #define MC_LEN_OFFSET 80 /* offset to mc_len from mcontext */ + #define MC_FP_CW_OFFSET 96 /* offset to FP control word */ + #define MC_OWNEDFP_OFFSET 88 /* offset to mc_ownedfp from mcontext */ + #define KM_STACK_SP_OFFSET 32 /* offset to km_stack.ss_sp */ + #define KM_STACK_SIZE_OFFSET 36 /* offset to km_stack.ss_sp */ + #define KM_FUNC_OFFSET 28 /* offset to km_func */ + + /* + * int _thread_enter_uts(thread_mailbox *tm, kse_mailbox *km); + * + * Returns 0 on success, -1 otherwise. + */ + ENTRY(_thread_enter_uts) + movl 4(%esp), %eax /* get address of context */ + cmpl $0, %eax /* check for null pointer */ + jne 1f + movl $-1, %eax + jmp 2f + 1: pushl %edx /* save value of edx */ + movl %eax, %edx /* get address of context */ + addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ + movl %gs, 4(%edx) + movl %fs, 8(%edx) + movl %es, 12(%edx) + movl %ds, 16(%edx) + movl %edi, 20(%edx) + movl %esi, 24(%edx) + movl %ebp, 28(%edx) + movl %ebx, 36(%edx) + movl $0, 48(%edx) /* store successful return in eax */ + popl %eax /* get saved value of edx */ + movl %eax, 40(%edx) /* save edx */ + movl %ecx, 44(%edx) + movl (%esp), %eax /* get return address */ + movl %eax, 60(%edx) /* save return address */ + movl %ss, 76(%edx) + /* + * Don't save floating point registers here. + * + * This is an explicit call to get the current context, so + * the caller is done with the floating point registers. + * Contexts formed by involuntary switches, such as signal delivery, + * have floating point registers saved by the kernel. + */ + fnstcw MC_FP_CW_OFFSET(%edx) + movl $0, MC_OWNEDFP_OFFSET(%edx) /* no FP */ + lahf /* get eflags */ + movl %eax, 68(%edx) /* store eflags */ + movl %esp, %eax /* setcontext pushes the return */ + addl $4, %eax /* address onto the top of the */ + movl %eax, 72(%edx) /* stack; account for this */ + movl $MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */ + movl 8(%esp), %edx /* get address of mailbox */ + movl KM_STACK_SP_OFFSET(%edx), %eax /* get bottom of stack */ + addl KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */ + movl %eax, %esp /* switch to the uts's stack */ + pushl %edx /* push the address of the mailbox */ + pushl KM_FUNC_OFFSET(%edx) /* .. the uts can return to itself */ + pushl KM_FUNC_OFFSET(%edx) /* push the address of the uts func */ + 2: ret + Index: lib/libpthread/arch/i386/_thread_switch.S =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/arch/i386/_thread_switch.S Sun Sep 15 21:38:21 2002 *************** *** 0 **** --- 1,89 ---- + /* + * Copyright (c) 2002 Jonathan Mini . + * Copyright (c) 2001 Daniel Eischen . + * 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. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN 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 AUTHOR 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 + __FBSDID("$FreeBSD$"); + + /* + * Where do we define these? + */ + #define MC_SIZE 640 /* sizeof mcontext_t */ + #define UC_MC_OFFSET 16 /* offset to mcontext from ucontext */ + #define UC_MC_LEN_OFFSET 96 /* offset to mc_len from mcontext */ + #define MC_FP_REGS_OFFSET 96 /* offset to FP regs from mcontext */ + #define MC_FP_CW_OFFSET 96 /* offset to FP control word */ + #define MC_OWNEDFP_OFFSET 88 /* offset to mc_ownedfp from mcontext */ + + /* + * int _thread_switch(thread_mailbox *td, thread_mailbox **curthreadp); + * + * Does not return on success, returns -1 otherwise. + */ + ENTRY(_thread_switch) + movl 4(%esp), %edx /* get address of thread_mailbox */ + /* .. ucontext_t is at offset 0 */ + cmpl $0, %edx /* check for null pointer */ + jne 1f + movl $-1, %eax + jmp 5f + 1: cmpl $MC_SIZE, UC_MC_LEN_OFFSET(%edx) /* is context valid? */ + je 2f + movl $-1, %eax /* bzzzt, invalid context */ + jmp 5f + 2: movl 8(%esp), %eax /* get address of curthreadp */ + movl %edx, (%eax) /* we're now the current thread */ + /* + * From here on, we don't touch the old stack. + */ + addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ + movl 4(%edx), %gs + movl 8(%edx), %fs + movl 12(%edx), %es + movl 16(%edx), %ds + movl 76(%edx), %ss + movl 20(%edx), %edi + movl 24(%edx), %esi + movl 28(%edx), %ebp + movl 72(%edx), %esp /* switch to context defined stack */ + subl $4, %esp /* leave space for the return address */ + movl 60(%edx), %eax /* put return address at top of stack */ + movl %eax, (%esp) + cmpl $0, MC_OWNEDFP_OFFSET(%edx) /* are FP regs valid? */ + jz 3f + frstor MC_FP_REGS_OFFSET(%edx) /* restore FP regs */ + jmp 4f + 3: fninit + fldcw MC_FP_CW_OFFSET(%edx) + 4: movl 48(%edx), %eax /* restore ax, bx, cx */ + movl 36(%edx), %ebx + movl 44(%edx), %ecx + pushl 68(%edx) /* flags on stack */ + pushl 40(%edx) /* %edx on stack */ + popl %edx /* %edx off stack */ + popf /* flags off stack */ + 5: ret /* %eip off stack */ + Index: lib/libpthread/arch/ia64/_atomic_lock.S =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/arch/ia64/_atomic_lock.S Sun Sep 15 21:38:22 2002 *************** *** 0 **** --- 1,48 ---- + /* + * Copyright (c) 2002 Marcel Moolenaar + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/arch/ia64/_atomic_lock.S,v 1.1 2002/07/20 19:22:10 peter Exp $ + */ + + #if defined(LIBC_RCS) && !defined(lint) + .text + .asciz "$FreeBSD: src/lib/libc_r/arch/ia64/_atomic_lock.S,v 1.1 2002/07/20 19:22:10 peter Exp $" + #endif /* LIBC_RCS and not lint */ + + #include + + /* + * Atomicly lock a location with an identifier provided the location + * is not currently locked. + * + * long _atomic_lock(long *); + * eax will contain the return value (zero if lock obtained). + */ + ENTRY(_atomic_lock, 1) + add r14 = 1, r0 + ;; + xchg8 r8 = [r32], r14 + br.ret.sptk rp + END(_atomic_lock) Index: lib/libpthread/man/Makefile.inc =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/Makefile.inc Sun Sep 15 21:38:22 2002 *************** *** 0 **** --- 1,96 ---- + # $FreeBSD: src/lib/libc_r/man/Makefile.inc,v 1.15 2001/07/20 04:23:09 jasone Exp $ + + # POSIX thread man files + + .PATH: ${.CURDIR}/man + + MAN+= pthread_attr.3 \ + pthread_cancel.3 \ + pthread_cleanup_pop.3 \ + pthread_cleanup_push.3 \ + pthread_condattr.3 \ + pthread_cond_broadcast.3 \ + pthread_cond_destroy.3 \ + pthread_cond_init.3 \ + pthread_cond_signal.3 \ + pthread_cond_timedwait.3 \ + pthread_cond_wait.3 \ + pthread_create.3 \ + pthread_detach.3 \ + pthread_equal.3 \ + pthread_exit.3 \ + pthread_getspecific.3 \ + pthread_join.3 \ + pthread_key_create.3 \ + pthread_key_delete.3 \ + pthread_kill.3 \ + pthread_mutexattr.3 \ + pthread_mutex_destroy.3 \ + pthread_mutex_init.3 \ + pthread_mutex_lock.3 \ + pthread_mutex_trylock.3 \ + pthread_mutex_unlock.3 \ + pthread_once.3 \ + pthread_rwlock_destroy.3 \ + pthread_rwlock_init.3 \ + pthread_rwlock_rdlock.3 \ + pthread_rwlock_unlock.3 \ + pthread_rwlock_wrlock.3 \ + pthread_rwlockattr_destroy.3 \ + pthread_rwlockattr_getpshared.3 \ + pthread_rwlockattr_init.3 \ + pthread_rwlockattr_setpshared.3 \ + pthread_schedparam.3 \ + pthread_self.3 \ + pthread_setspecific.3 \ + pthread_sigmask.3 \ + pthread_testcancel.3 \ + sem_destroy.3 \ + sem_getvalue.3 \ + sem_init.3 \ + sem_open.3 \ + sem_post.3 \ + sem_wait.3 \ + sigwait.3 + + MLINKS+= \ + pthread_attr.3 pthread_attr_destroy.3 \ + pthread_attr.3 pthread_attr_getdetachstate.3 \ + pthread_attr.3 pthread_attr_getguardsize.3 \ + pthread_attr.3 pthread_attr_getinheritsched.3 \ + pthread_attr.3 pthread_attr_getschedparam.3 \ + pthread_attr.3 pthread_attr_getschedpolicy.3 \ + pthread_attr.3 pthread_attr_getscope.3 \ + pthread_attr.3 pthread_attr_getstackaddr.3 \ + pthread_attr.3 pthread_attr_getstacksize.3 \ + pthread_attr.3 pthread_attr_init.3 \ + pthread_attr.3 pthread_attr_setdetachstate.3 \ + pthread_attr.3 pthread_attr_setguardsize.3 \ + pthread_attr.3 pthread_attr_setinheritsched.3 \ + pthread_attr.3 pthread_attr_setschedparam.3 \ + pthread_attr.3 pthread_attr_setschedpolicy.3 \ + pthread_attr.3 pthread_attr_setscope.3 \ + pthread_attr.3 pthread_attr_setstackaddr.3 \ + pthread_attr.3 pthread_attr_setstacksize.3 \ + pthread_condattr.3 pthread_condattr_init.3 \ + pthread_condattr.3 pthread_condattr_destroy.3 \ + pthread_mutexattr.3 pthread_mutexattr_init.3 \ + pthread_mutexattr.3 pthread_mutexattr_destroy.3 \ + pthread_mutexattr.3 pthread_mutexattr_getprioceiling.3 \ + pthread_mutexattr.3 pthread_mutexattr_getprotocol.3 \ + pthread_mutexattr.3 pthread_mutexattr_getpshared.3 \ + pthread_mutexattr.3 pthread_mutexattr_gettype.3 \ + pthread_mutexattr.3 pthread_mutexattr_setprioceiling.3 \ + pthread_mutexattr.3 pthread_mutexattr_setprotocol.3 \ + pthread_mutexattr.3 pthread_mutexattr_setpshared.3 \ + pthread_mutexattr.3 pthread_mutexattr_settype.3 \ + pthread_rwlock_rdlock.3 pthread_rwlock_tryrdlock.3 \ + pthread_rwlock_wrlock.3 pthread_rwlock_trywrlock.3 \ + pthread_schedparam.3 pthread_getschedparam.3 \ + pthread_schedparam.3 pthread_setschedparam.3 \ + pthread_testcancel.3 pthread_getcancelstate.3 \ + pthread_testcancel.3 pthread_setcancelstate.3 \ + pthread_testcancel.3 pthread_setcanceltype.3 \ + sem_open.3 sem_close.3 \ + sem_open.3 sem_unlink.3 \ + sem_wait.3 sem_trywait.3 Index: lib/libpthread/man/pthread_attr.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_attr.3 Sun Sep 15 21:38:22 2002 *************** *** 0 **** --- 1,219 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_attr.3,v 1.10 2001/10/01 16:09:08 ru Exp $ + .Dd April 28, 2000 + .Dt PTHREAD_ATTR 3 + .Os + .Sh NAME + .Nm pthread_attr_init , + .Nm pthread_attr_destroy , + .Nm pthread_attr_setstacksize , + .Nm pthread_attr_getstacksize , + .Nm pthread_attr_setguardsize , + .Nm pthread_attr_getguardsize , + .Nm pthread_attr_setstackaddr , + .Nm pthread_attr_getstackaddr , + .Nm pthread_attr_setdetachstate , + .Nm pthread_attr_getdetachstate , + .Nm pthread_attr_setinheritsched , + .Nm pthread_attr_getinheritsched , + .Nm pthread_attr_setschedparam , + .Nm pthread_attr_getschedparam , + .Nm pthread_attr_setschedpolicy , + .Nm pthread_attr_getschedpolicy , + .Nm pthread_attr_setscope , + .Nm pthread_attr_getscope + .Nd thread attribute operations + .Sh LIBRARY + .Lb libpthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_attr_init "pthread_attr_t *attr" + .Ft int + .Fn pthread_attr_destroy "pthread_attr_t *attr" + .Ft int + .Fn pthread_attr_setstacksize "pthread_attr_t *attr" "size_t stacksize" + .Ft int + .Fn pthread_attr_getstacksize "const pthread_attr_t *attr" "size_t *stacksize" + .Ft int + .Fn pthread_attr_setguardsize "pthread_attr_t *attr" "size_t guardsize" + .Ft int + .Fn pthread_attr_getguardsize "const pthread_attr_t *attr" "size_t *guardsize" + .Ft int + .Fn pthread_attr_setstackaddr "pthread_attr_t *attr" "void *stackaddr" + .Ft int + .Fn pthread_attr_getstackaddr "const pthread_attr_t *attr" "void **stackaddr" + .Ft int + .Fn pthread_attr_setdetachstate "pthread_attr_t *attr" "int detachstate" + .Ft int + .Fn pthread_attr_getdetachstate "const pthread_attr_t *attr" "int *detachstate" + .Ft int + .Fn pthread_attr_setinheritsched "pthread_attr_t *attr" "int inheritsched" + .Ft int + .Fn pthread_attr_getinheritsched "const pthread_attr_t *attr" "int *inheritsched" + .Ft int + .Fn pthread_attr_setschedparam "pthread_attr_t *attr" "const struct sched_param *param" + .Ft int + .Fn pthread_attr_getschedparam "const pthread_attr_t *attr" "struct sched_param *param" + .Ft int + .Fn pthread_attr_setschedpolicy "pthread_attr_t *attr" "int policy" + .Ft int + .Fn pthread_attr_getschedpolicy "const pthread_attr_t *attr" "int *policy" + .Ft int + .Fn pthread_attr_setscope "pthread_attr_t *attr" "int contentionscope" + .Ft int + .Fn pthread_attr_getscope "const pthread_attr_t *attr" "int *contentionscope" + .Sh DESCRIPTION + Thread attributes are used to specify parameters to + .Fn pthread_create . + One attribute object can be used in multiple calls to + .Fn pthread_create , + with or without modifications between calls. + .Pp + The + .Fn pthread_attr_init + function initializes + .Fa attr + with all the default thread attributes. + .Pp + The + .Fn pthread_attr_destroy + function destroys + .Fa attr . + .Pp + The + .Fn pthread_attr_set* + functions set the attribute that corresponds to each function name. + .Pp + The + .Fn pthread_attr_get* + functions copy the value of the attribute that corresponds to each function name + to the location pointed to by the second function parameter. + .Sh RETURN VALUES + If successful, these functions return 0. + Otherwise, an error number is returned to indicate the error. + .Sh ERRORS + .Fn pthread_attr_init + will fail if: + .Bl -tag -width Er + .It Bq Er ENOMEM + Out of memory. + .El + .Pp + .Fn pthread_attr_destroy + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .El + .Pp + .Fn pthread_attr_setstacksize + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + .Fa stacksize + is less than + .Dv PTHREAD_STACK_MIN . + .El + .Pp + .Fn pthread_attr_setdetachstate + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa detachstate . + .El + .Pp + .Fn pthread_attr_setinheritsched + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .El + .Pp + .Fn pthread_attr_setschedparam + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .It Bq Er ENOTSUP + Invalid value for + .Fa param . + .El + .Pp + .Fn pthread_attr_setschedpolicy + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .It Bq Er ENOTSUP + Invalid or unsupported value for + .Fa policy . + .El + .Pp + .Fn pthread_attr_setscope + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .It Bq Er ENOTSUP + Invalid or unsupported value for + .Fa contentionscope . + .El + .Sh SEE ALSO + .Xr pthread_create 3 + .Sh STANDARDS + .Fn pthread_attr_init , + .Fn pthread_attr_destroy , + .Fn pthread_attr_setstacksize , + .Fn pthread_attr_getstacksize , + .Fn pthread_attr_setstackaddr , + .Fn pthread_attr_getstackaddr , + .Fn pthread_attr_setdetachstate , + and + .Fn pthread_attr_getdetachstate + conform to + .St -p1003.1-96 + .Pp + .Fn pthread_attr_setinheritsched , + .Fn pthread_attr_getinheritsched , + .Fn pthread_attr_setschedparam , + .Fn pthread_attr_getschedparam , + .Fn pthread_attr_setschedpolicy , + .Fn pthread_attr_getschedpolicy , + .Fn pthread_attr_setscope , + and + .Fn pthread_attr_getscope + conform to + .St -susv2 Index: lib/libpthread/man/pthread_cancel.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cancel.3 Sun Sep 15 21:38:22 2002 *************** *** 0 **** --- 1,79 ---- + .\" $FreeBSD: src/lib/libc_r/man/pthread_cancel.3,v 1.6 2001/10/01 16:09:08 ru Exp $ + .Dd January 17, 1999 + .Dt PTHREAD_CANCEL 3 + .Os + .Sh NAME + .Nm pthread_cancel + .Nd cancel execution of a thread + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_cancel "pthread_t thread" + .Sh DESCRIPTION + The + .Fn pthread_cancel + function requests that + .Fa thread + be canceled. + The target thread's cancelability state and type determines + when the cancellation takes effect. + When the cancellation is acted on, + the cancellation cleanup handlers for + .Fa thread + are called. + When the last cancellation cleanup handler returns, + the thread-specific data destructor functions will be called for + .Fa thread . + When the last destructor function returns, + .Fa thread + will be terminated. + .Pp + The cancellation processing in the target thread runs asynchronously with + respect to the calling thread returning from + .Fn pthread_cancel . + .Pp + A status of + .Dv PTHREAD_CANCELED + is made available to any threads joining with the target. + The symbolic + constant + .Dv PTHREAD_CANCELED + expands to a constant expression of type + .Ft "(void *)" , + whose value matches no pointer to an object in memory nor the value + .Dv NULL . + .Sh RETURN VALUES + If successful, the + .Fn pthread_cancel + functions will return zero. + Otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_cancel + will fail if: + .Bl -tag -width Er + .It Bq Er ESRCH + No thread could be found corresponding to that specified by the given + thread ID. + .El + .Sh SEE ALSO + .Xr pthread_cleanup_pop 3 , + .Xr pthread_cleanup_push 3 , + .Xr pthread_exit 3 , + .Xr pthread_join 3 , + .Xr pthread_setcancelstate 3 , + .Xr pthread_setcanceltype 3 , + .Xr pthread_testcancel 3 + .Sh STANDARDS + .Fn pthread_cancel + conforms to + .St -p1003.1-96 . + .Sh AUTHORS + This man page was written by + .An David Leonard Aq d@openbsd.org + for the + .Ox + implementation of + .Fn pthread_cancel . Index: lib/libpthread/man/pthread_cleanup_pop.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cleanup_pop.3 Sun Sep 15 21:38:22 2002 *************** *** 0 **** --- 1,64 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_cleanup_pop.3,v 1.9 2001/10/01 16:09:08 ru Exp $ + .\" + .Dd July 30, 1998 + .Dt PTHREAD_CLEANUP_POP 3 + .Os + .Sh NAME + .Nm pthread_cleanup_pop + .Nd call the first cleanup routine + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft void + .Fn pthread_cleanup_pop "int execute" + .Sh DESCRIPTION + The + .Fn pthread_cleanup_pop + function pops the top cleanup routine off of the current threads cleanup + routine stack, and, if + .Fa execute + is non-zero, it will execute the function. + If there is no cleanup routine + then + .Fn pthread_cleanup_pop + does nothing. + .Sh RETURN VALUES + .Fn pthread_cleanup_pop + does not return any value. + .Sh ERRORS + None + .Sh SEE ALSO + .Xr pthread_cleanup_push 3 , + .Xr pthread_exit 3 + .Sh STANDARDS + .Fn pthread_cleanup_pop + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_cleanup_push.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cleanup_push.3 Sun Sep 15 21:38:23 2002 *************** *** 0 **** --- 1,66 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_cleanup_push.3,v 1.10 2001/10/01 16:09:08 ru Exp $ + .\" + .Dd July 30, 1998 + .Dt PTHREAD_CLEANUP_PUSH 3 + .Os + .Sh NAME + .Nm pthread_cleanup_push + .Nd add a cleanup function for thread exit + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft void + .Fn pthread_cleanup_push "void \*[lp]*cleanup_routine\*[rp]\*[lp]void *\*[rp]" "void *arg" + .Sh DESCRIPTION + The + .Fn pthread_cleanup_push + function adds + .Fa cleanup_routine + to the top of the stack of cleanup handlers that + get called when the current thread exits. + .Pp + When + .Fa cleanup_routine + is called, it is passed + .Fa arg + as its only argument. + .Sh RETURN VALUES + .Fn pthread_cleanup_push + does not return any value. + .Sh ERRORS + None + .Sh SEE ALSO + .Xr pthread_cleanup_pop 3 , + .Xr pthread_exit 3 + .Sh STANDARDS + .Fn pthread_cleanup_push + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_cond_broadcast.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cond_broadcast.3 Sun Sep 15 21:38:23 2002 *************** *** 0 **** --- 1,70 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_cond_broadcast.3,v 1.10 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 28, 1998 + .Dt PTHREAD_COND_BROADCAST 3 + .Os + .Sh NAME + .Nm pthread_cond_broadcast + .Nd unblock all threads waiting for a condition variable + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_cond_broadcast "pthread_cond_t *cond" + .Sh DESCRIPTION + The + .Fn pthread_cond_broadcast + function unblocks all threads waiting for the condition variable + .Fa cond . + .Sh RETURN VALUES + If successful, the + .Fn pthread_cond_broadcast + function will return zero, otherwise an error number will be returned + to indicate the error. + .Sh ERRORS + .Fn pthread_cond_broadcast + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa cond + is invalid. + .El + .Sh SEE ALSO + .Xr pthread_cond_destroy 3 , + .Xr pthread_cond_init 3 , + .Xr pthread_cond_signal 3 , + .Xr pthread_cond_timedwait 3 , + .Xr pthread_cond_wait 3 + .Sh STANDARDS + .Fn pthread_cond_broadcast + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_cond_destroy.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cond_destroy.3 Sun Sep 15 21:38:23 2002 *************** *** 0 **** --- 1,74 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_cond_destroy.3,v 1.11 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 28, 1998 + .Dt PTHREAD_COND_DESTROY 3 + .Os + .Sh NAME + .Nm pthread_cond_destroy + .Nd destroy a condition variable + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_cond_destroy "pthread_cond_t *cond" + .Sh DESCRIPTION + The + .Fn pthread_cond_destroy + function frees the resources allocated by the condition variable + .Fa cond . + .Sh RETURN VALUES + If successful, the + .Fn pthread_cond_destroy + function will return zero, otherwise an error number will be returned + to indicate the error. + .Sh ERRORS + .Fn pthread_cond_destroy + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa cond + is invalid. + .It Bq Er EBUSY + The variable + .Fa cond + is locked by another thread. + .El + .Sh SEE ALSO + .Xr pthread_cond_broadcast 3 , + .Xr pthread_cond_init 3 , + .Xr pthread_cond_signal 3 , + .Xr pthread_cond_timedwait 3 , + .Xr pthread_cond_wait 3 + .Sh STANDARDS + .Fn pthread_cond_destroy + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_cond_init.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cond_init.3 Sun Sep 15 21:38:23 2002 *************** *** 0 **** --- 1,80 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_cond_init.3,v 1.12 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 28, 1998 + .Dt PTHREAD_COND_INIT 3 + .Os + .Sh NAME + .Nm pthread_cond_init + .Nd create a condition variable + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_cond_init "pthread_cond_t *cond" "const pthread_condattr_t *attr" + .Sh DESCRIPTION + The + .Fn pthread_cond_init + function creates a new condition variable, with attributes specified with + .Fa attr . + If + .Fa attr + is NULL the default attributes are used. + .Sh RETURN VALUES + If successful, the + .Fn pthread_cond_init + function will return zero and put the new condition variable id into + .Fa cond , + otherwise an error number will be returned to indicate the error. + .Sh ERRORS + .Fn pthread_cond_init + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa attr + is invalid. + .It Bq Er ENOMEM + The process cannot allocate enough memory to create another condition + variable. + .It Bq Er EAGAIN + The system temporarily lacks the resources to create another condition + variable. + .El + .Sh SEE ALSO + .Xr pthread_cond_broadcast 3 , + .Xr pthread_cond_destroy 3 , + .Xr pthread_cond_signal 3 , + .Xr pthread_cond_timedwait 3 , + .Xr pthread_cond_wait 3 + .Sh STANDARDS + .Fn pthread_cond_init + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_cond_signal.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cond_signal.3 Sun Sep 15 21:38:24 2002 *************** *** 0 **** --- 1,70 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_cond_signal.3,v 1.10 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 28, 1998 + .Dt PTHREAD_COND_SIGNAL 3 + .Os + .Sh NAME + .Nm pthread_cond_signal + .Nd unblock a thread waiting for a condition variable + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_cond_signal "pthread_cond_t *cond" + .Sh DESCRIPTION + The + .Fn pthread_cond_signal + function unblocks one thread waiting for the condition variable + .Fa cond . + .Sh RETURN VALUES + If successful, the + .Fn pthread_cond_signal + function will return zero, otherwise an error number will be returned + to indicate the error. + .Sh ERRORS + .Fn pthread_cond_signal + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa cond + is invalid. + .El + .Sh SEE ALSO + .Xr pthread_cond_broadcast 3 , + .Xr pthread_cond_destroy 3 , + .Xr pthread_cond_init 3 , + .Xr pthread_cond_timedwait 3 , + .Xr pthread_cond_wait 3 + .Sh STANDARDS + .Fn pthread_cond_signal + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_cond_timedwait.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cond_timedwait.3 Sun Sep 15 21:38:24 2002 *************** *** 0 **** --- 1,89 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_cond_timedwait.3,v 1.15 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 28, 1998 + .Dt PTHREAD_COND_TIMEDWAIT 3 + .Os + .Sh NAME + .Nm pthread_cond_timedwait + .Nd "wait on a condition variable for a specific amount of time" + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_cond_timedwait "pthread_cond_t *cond" "pthread_mutex_t *mutex" "const struct timespec *abstime" + .Sh DESCRIPTION + The + .Fn pthread_cond_timedwait + function atomically blocks the current thread waiting on the condition + variable specified by + .Fa cond , + and unblocks the mutex specified by + .Fa mutex . + The waiting thread unblocks only after another thread calls + .Xr pthread_cond_signal 3 , + or + .Xr pthread_cond_broadcast 3 + with the same condition variable, or if the system time reaches the + time specified in + .Fa abstime , + and the current thread reacquires the lock on + .Fa mutex . + .Sh RETURN VALUES + If successful, the + .Fn pthread_cond_timedwait + function will return zero. + Otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_cond_timedwait + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa cond , + .Fa mutex + or + .Fa abstime + is invalid. + .It Bq Er ETIMEDOUT + The system time has reached or exceeded the time specified in + .Fa abstime . + .El + .Sh SEE ALSO + .Xr pthread_cond_broadcast 3 , + .Xr pthread_cond_destroy 3 , + .Xr pthread_cond_init 3 , + .Xr pthread_cond_signal 3 , + .Xr pthread_cond_wait 3 + .Sh STANDARDS + .Fn pthread_cond_timedwait + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_cond_wait.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_cond_wait.3 Sun Sep 15 21:38:24 2002 *************** *** 0 **** --- 1,83 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_cond_wait.3,v 1.15 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 28, 1998 + .Dt PTHREAD_COND_WAIT 3 + .Os + .Sh NAME + .Nm pthread_cond_wait + .Nd wait on a condition variable + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_cond_wait "pthread_cond_t *cond" "pthread_mutex_t *mutex" + .Sh DESCRIPTION + The + .Fn pthread_cond_wait + function atomically blocks the current thread waiting on the condition + variable specified by + .Fa cond , + and unblocks the mutex specified by + .Fa mutex . + The waiting thread unblocks only after another thread calls + .Xr pthread_cond_signal 3 , + or + .Xr pthread_cond_broadcast 3 + with the same condition variable, and the current thread reacquires the lock + on + .Fa mutex . + .Sh RETURN VALUES + If successful, the + .Fn pthread_cond_wait + function will return zero. + Otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_cond_wait + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa cond + or the value specified by + .Fa mutex + is invalid. + .El + .Sh SEE ALSO + .Xr pthread_cond_broadcast 3 , + .Xr pthread_cond_destroy 3 , + .Xr pthread_cond_init 3 , + .Xr pthread_cond_signal 3 , + .Xr pthread_cond_timedwait 3 + .Sh STANDARDS + .Fn pthread_cond_wait + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_condattr.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_condattr.3 Sun Sep 15 21:38:26 2002 *************** *** 0 **** --- 1,85 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_condattr.3,v 1.9 2001/10/01 16:09:09 ru Exp $ + .Dd April 28, 2000 + .Dt PTHREAD_CONDATTR 3 + .Os + .Sh NAME + .Nm pthread_condattr_init , + .Nm pthread_condattr_destroy + .Nd condition attribute operations + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_condattr_init "pthread_condattr_t *attr" + .Ft int + .Fn pthread_condattr_destroy "pthread_condattr_t *attr" + .Sh DESCRIPTION + Condition attribute objects are used to specify parameters to + .Fn pthread_cond_init . + .Fx Ns 's + implementation of conditions does not support any non-default + attributes, so these functions are not very useful, though they are required to + to be present by + .Tn POSIX . + .Pp + The + .Fn pthread_condattr_init + function initializes a condition attribute object with the default attributes. + .Pp + The + .Fn pthread_condattr_destroy + function destroys a condition attribute object. + .Sh RETURN VALUES + If successful, these functions return 0. + Otherwise, an error number is returned to indicate the error. + .Sh ERRORS + .Fn pthread_condattr_init + will fail if: + .Bl -tag -width Er + .It Bq Er ENOMEM + Out of memory. + .El + .Pp + .Fn pthread_condattr_destroy + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .El + .Sh SEE ALSO + .Xr pthread_cond_init 3 + .Sh STANDARDS + .Fn pthread_condattr_init + and + .Fn pthread_condattr_destroy + conform to + .St -p1003.1-96 Index: lib/libpthread/man/pthread_create.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_create.3 Sun Sep 15 21:38:26 2002 *************** *** 0 **** --- 1,123 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_create.3,v 1.15 2001/11/04 23:13:03 dd Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_CREATE 3 + .Os + .Sh NAME + .Nm pthread_create + .Nd create a new thread + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_create "pthread_t *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg" + .Sh DESCRIPTION + The + .Fn pthread_create + function is used to create a new thread, with attributes specified by + .Fa attr , + within a process. + If + .Fa attr + is + .Dv NULL , + the default attributes are used. + If the attributes specified by + .Fa attr + are modified later, the thread's attributes are not affected. + Upon + successful completion + .Fn pthread_create + will store the ID of the created thread in the location specified by + .Fa thread . + .Pp + The thread is created executing + .Fa start_routine + with + .Fa arg + as its sole argument. + If the + .Fa start_routine + returns, the effect is as if there was an implicit call to + .Fn pthread_exit + using the return value of + .Fa start_routine + as the exit status. + Note that the thread in which + .Fn main + was originally invoked differs from this. + When it returns from + .Fn main , + the effect is as if there was an implicit call to + .Fn exit + using the return value of + .Fn main + as the exit status. + .Pp + The signal state of the new thread is initialized as: + .Bl -bullet -offset indent + .It + The signal mask is inherited from the creating thread. + .It + The set of signals pending for the new thread is empty. + .El + .Sh RETURN VALUES + If successful, the + .Fn pthread_create + function will return zero. + Otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_create + will fail if: + .Bl -tag -width Er + .It Bq Er EAGAIN + The system lacked the necessary resources to create another thread, or + the system-imposed limit on the total number of threads in a process + [PTHREAD_THREADS_MAX] would be exceeded. + .It Bq Er EINVAL + The value specified by + .Fa attr + is invalid. + .El + .Sh SEE ALSO + .Xr fork 2 , + .Xr pthread_cleanup_pop 3 , + .Xr pthread_cleanup_push 3 , + .Xr pthread_exit 3 , + .Xr pthread_join 3 + .Sh STANDARDS + .Fn pthread_create + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_detach.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_detach.3 Sun Sep 15 21:38:26 2002 *************** *** 0 **** --- 1,89 ---- + .\" Copyright (c) 1996-1998 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_detach.3,v 1.12 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_DETACH 3 + .Os + .Sh NAME + .Nm pthread_detach + .Nd detach a thread + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_detach "pthread_t thread" + .Sh DESCRIPTION + The + .Fn pthread_detach + function is used to indicate to the implementation that storage for the + thread + .Fa thread + can be reclaimed when the thread terminates. + If + .Fa thread + has not terminated, + .Fn pthread_detach + will not cause it to terminate. + The effect of multiple + .Fn pthread_detach + calls on the same target thread is unspecified. + .Sh RETURN VALUES + If successful, the + .Fn pthread_detach + function will return zero. + Otherwise an error number will be returned to + indicate the error. + Note that the function does not change the value + of errno as it did for some drafts of the standard. + These early drafts + also passed a pointer to pthread_t as the argument. + Beware! + .Sh ERRORS + .Fn pthread_detach + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The implementation has detected that the value specified by + .Fa thread + does not refer to a joinable thread. + .It Bq Er ESRCH + No thread could be found corresponding to that specified by the given + thread ID, + .Fa thread . + .El + .Sh SEE ALSO + .Xr pthread_join 3 + .Sh STANDARDS + .Fn pthread_detach + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_equal.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_equal.3 Sun Sep 15 21:38:26 2002 *************** *** 0 **** --- 1,68 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_equal.3,v 1.10 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_EQUAL 3 + .Os + .Sh NAME + .Nm pthread_equal + .Nd compare thread IDs + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_equal "pthread_t t1" "pthread_t t2" + .Sh DESCRIPTION + The + .Fn pthread_equal + function compares the thread IDs + .Fa t1 + and + .Fa t2 . + .Sh RETURN VALUES + The + .Fn pthread_equal + function will return non-zero if the thread IDs + .Fa t1 + and + .Fa t2 + correspond to the same thread, otherwise it will return zero. + .Sh ERRORS + None. + .Sh SEE ALSO + .Xr pthread_create 3 , + .Xr pthread_exit 3 + .Sh STANDARDS + .Fn pthread_equal + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_exit.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_exit.3 Sun Sep 15 21:38:26 2002 *************** *** 0 **** --- 1,104 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_exit.3,v 1.15 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_EXIT 3 + .Os + .Sh NAME + .Nm pthread_exit + .Nd terminate the calling thread + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft void + .Fn pthread_exit "void *value_ptr" + .Sh DESCRIPTION + The + .Fn pthread_exit + function terminates the calling thread and makes the value + .Fa value_ptr + available to any successful join with the terminating thread. + Any + cancellation cleanup handlers that have been pushed and are not yet popped + are popped in the reverse order that they were pushed and then executed. + After all cancellation handlers have been executed, if the thread has any + thread-specific data, appropriate destructor functions are called in an + unspecified order. + Thread termination does not release any application + visible process resources, including, but not limited to, mutexes and + file descriptors, nor does it perform any process level cleanup + actions, including, but not limited to, calling + .Fn atexit + routines that may exist. + .Pp + An implicit call to + .Fn pthread_exit + is made when a thread other than the thread in which + .Fn main + was first invoked returns from the start routine that was used to create + it. The function's return value serves as the thread's exit status. + .Pp + The behavior of + .Fn pthread_exit + is undefined if called from a cancellation handler or destructor function + that was invoked as the result of an implicit or explicit call to + .Fn pthread_exit . + .Pp + After a thread has terminated, the result of access to local (auto) + variables of the thread is undefined. + Thus, references to local variables + of the exiting thread should not be used for the + .Fn pthread_exit + .Fa value_ptr + parameter value. + .Pp + The process will exit with an exit status of 0 after the last thread has + been terminated. + The behavior is as if the implementation called + .Fn exit + with a zero argument at thread termination time. + .Sh RETURN VALUES + The + .Fn pthread_exit + function cannot return to its caller. + .Sh ERRORS + None. + .Sh SEE ALSO + .Xr _exit 2 , + .Xr exit 3 , + .Xr pthread_create 3 , + .Xr pthread_join 3 + .Sh STANDARDS + .Fn pthread_exit + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_getspecific.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_getspecific.3 Sun Sep 15 21:38:27 2002 *************** *** 0 **** --- 1,83 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_getspecific.3,v 1.10 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_GETSPECIFIC 3 + .Os + .Sh NAME + .Nm pthread_getspecific + .Nd get a thread-specific data value + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft void * + .Fn pthread_getspecific "pthread_key_t key" + .Sh DESCRIPTION + The + .Fn pthread_getspecific + function returns the value currently bound to the specified + .Fa key + on behalf of the calling thread. + .Pp + The effect of calling + .Fn pthread_getspecific + with a + .Fa key + value not obtained from + .Fn pthread_key_create + or after + .Fa key + has been deleted with + .Fn pthread_key_delete + is undefined. + .Pp + .Fn pthread_getspecific + may be called from a thread-specific data destructor function. + .Sh RETURN VALUES + The + .Fn pthread_getspecific + function will return the thread-specific data value associated with the given + .Fa key . + If no thread-specific data value is associated with + .Fa key , + then the value NULL is returned. + .Sh ERRORS + None. + .Sh SEE ALSO + .Xr pthread_key_create 3 , + .Xr pthread_key_delete 3 , + .Xr pthread_setspecific 3 + .Sh STANDARDS + .Fn pthread_getspecific + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_join.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_join.3 Sun Sep 15 21:38:27 2002 *************** *** 0 **** --- 1,104 ---- + .\" Copyright (c) 1996-1998 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_join.3,v 1.12 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_JOIN 3 + .Os + .Sh NAME + .Nm pthread_join + .Nd wait for thread termination + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_join "pthread_t thread" "void **value_ptr" + .Sh DESCRIPTION + The + .Fn pthread_join + function suspends execution of the calling thread until the target + .Fa thread + terminates unless the target + .Fa thread + has already terminated. + .Pp + On return from a successful + .Fn pthread_join + call with a non-NULL + .Fa value_ptr + argument, the value passed to + .Fn pthread_exit + by the terminating thread is stored in the location referenced by + .Fa value_ptr . + When a + .Fn pthread_join + returns successfully, the target thread has been terminated. + The results + of multiple simultaneous calls to + .Fn pthread_join + specifying the same target thread are undefined. + If the thread calling + .Fn pthread_join + is cancelled, then the target thread is not detached. + .Pp + A thread that has exited but remains unjoined counts against + [_POSIX_THREAD_THREADS_MAX]. + .Sh RETURN VALUES + If successful, the + .Fn pthread_join + function will return zero. + Otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_join + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The implementation has detected that the value specified by + .Fa thread + does not refer to a joinable thread. + .It Bq Er ESRCH + No thread could be found corresponding to that specified by the given + thread ID, + .Fa thread . + .It Bq Er EDEADLK + A deadlock was detected or the value of + .Fa thread + specifies the calling thread. + .El + .Sh SEE ALSO + .Xr wait 2 , + .Xr pthread_create 3 + .Sh STANDARDS + .Fn pthread_join + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_key_create.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_key_create.3 Sun Sep 15 21:38:27 2002 *************** *** 0 **** --- 1,107 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_key_create.3,v 1.11 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_KEY_CREATE 3 + .Os + .Sh NAME + .Nm pthread_key_create + .Nd thread-specific data key creation + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_key_create "pthread_key_t *key" "void (*destructor)(void *)" + .Sh DESCRIPTION + The + .Fn pthread_key_create + function creates a thread-specific data key visible to all threads in the + process. + Key values provided by + .Fn pthread_key_create + are opaque objects used to locate thread-specific data. + Although the same + key value may be used by different threads, the values bound to the key + by + .Fn pthread_setspecific + are maintained on a per-thread basis and persist for the life of the calling + thread. + .Pp + Upon key creation, the value NULL is associated with the new key in all + active threads. + Upon thread creation, the value NULL is associated with all + defined keys in the new thread. + .Pp + An optional destructor function may be associated with each key value. + At + thread exit, if a key value has a non-NULL destructor pointer, and the + thread has a non-NULL value associated with the key, the function pointed + to is called with the current associated value as its sole argument. + The + order of destructor calls is unspecified if more than one destructor exists + for a thread when it exits. + .Pp + If, after all the destructors have been called for all non-NULL values + with associated destructors, there are still some non-NULL values with + associated destructors, then the process is repeated. + If, after at least + [PTHREAD_DESTRUCTOR_ITERATIONS] iterations of destructor calls for + outstanding non-NULL values, there are still some non-NULL values with + associated destructors, the implementation stops calling destructors. + .Sh RETURN VALUES + If successful, the + .Fn pthread_key_create + function will store the newly created key value at the location specified by + .Fa key + and returns zero. + Otherwise an error number will be returned to indicate + the error. + .Sh ERRORS + .Fn pthread_key_create + will fail if: + .Bl -tag -width Er + .It Bq Er EAGAIN + The system lacked the necessary resources to create another thread-specific + data key, or the system-imposed limit on the total number of keys per process + [PTHREAD_KEYS_MAX] would be exceeded. + .It Bq Er ENOMEM + Insufficient memory exists to create the key. + .El + .Sh SEE ALSO + .Xr pthread_getspecific 3 , + .Xr pthread_key_delete 3 , + .Xr pthread_setspecific 3 + .Sh STANDARDS + .Fn pthread_key_create + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_key_delete.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_key_delete.3 Sun Sep 15 21:38:27 2002 *************** *** 0 **** --- 1,98 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_key_delete.3,v 1.11 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_KEY_DELETE 3 + .Os + .Sh NAME + .Nm pthread_key_delete + .Nd delete a thread-specific data key + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_key_delete "pthread_key_t key" + .Sh DESCRIPTION + The + .Fn pthread_key_delete + function deletes a thread-specific data key previously returned by + .Fn pthread_key_create . + The thread-specific data values associated with + .Fa key + need not be NULL at the time that + .Fn pthread_key_delete + is called. + It is the responsibility of the application to free any + application storage or perform any cleanup actions for data structures + related to the deleted key or associated thread-specific data in any threads; + this cleanup can be done either before or after + .Fn pthread_key_delete + is called. + Any attempt to use + .Fa key + following the call to + .Fn pthread_key_delete + results in undefined behavior. + .Pp + The + .Fn pthread_key_delete + function is callable from within destructor functions. + Destructor functions + are not invoked by + .Fn pthread_key_delete . + Any destructor function that may have been associated with + .Fa key + will no longer be called upon thread exit. + .Sh RETURN VALUES + If successful, the + .Fn pthread_key_delete + function will return zero. + Otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_key_delete + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The + .Fa key + value is invalid. + .El + .Sh SEE ALSO + .Xr pthread_getspecific 3 , + .Xr pthread_key_create 3 , + .Xr pthread_setspecific 3 + .Sh STANDARDS + .Fn pthread_key_delete + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_kill.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_kill.3 Sun Sep 15 21:38:28 2002 *************** *** 0 **** --- 1,75 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_kill.3,v 1.8 2001/10/01 16:09:09 ru Exp $ + .Dd April 27, 2000 + .Dt PTHREAD_KILL 3 + .Os + .Sh NAME + .Nm pthread_kill + .Nd send a signal to a specified thread + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .In signal.h + .Ft int + .Fn pthread_kill "pthread_t thread" "int sig" + .Sh DESCRIPTION + The + .Fn pthread_kill + function sends a signal, specified by + .Fa sig , + to a thread, specified by + .Fa thread . + If + .Fa sig + is 0, error checking is performed, but no signal is actually sent. + .Sh RETURN VALUES + If successful, + .Fn pthread_kill + returns 0. + Otherwise, an error number is returned. + .Sh ERRORS + .Fn pthread_kill + will fail if: + .Bl -tag -width Er + .It Bq Er ESRCH + .Fa thread + is an invalid thread ID. + .It Bq Er EINVAL + .Fa sig + is an invalid or unsupported signal number. + .El + .Sh SEE ALSO + .Xr kill 2 , + .Xr pthread_self 3 , + .Xr raise 3 + .Sh STANDARDS + .Fn pthread_kill + conforms to + .St -p1003.1-96 Index: lib/libpthread/man/pthread_mutex_destroy.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_mutex_destroy.3 Sun Sep 15 21:38:28 2002 *************** *** 0 **** --- 1,72 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_mutex_destroy.3,v 1.10 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 29, 1998 + .Dt PTHREAD_MUTEX_DESTROY 3 + .Os + .Sh NAME + .Nm pthread_mutex_destroy + .Nd free resources allocated for a mutex + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_mutex_destroy "pthread_mutex_t *mutex" + .Sh DESCRIPTION + The + .Fn pthread_mutex_destroy + function frees the resources allocated for + .Fa mutex . + .Sh RETURN VALUES + If successful, + .Fn pthread_mutex_destroy + will return zero, otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_mutex_destroy + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa mutex + is invalid. + .It Bq Er EBUSY + .Fa Mutex + is locked by another thread. + .El + .Sh SEE ALSO + .Xr pthread_mutex_init 3 , + .Xr pthread_mutex_lock 3 , + .Xr pthread_mutex_trylock 3 , + .Xr pthread_mutex_unlock 3 + .Sh STANDARDS + .Fn pthread_mutex_destroy + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_mutex_init.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_mutex_init.3 Sun Sep 15 21:38:28 2002 *************** *** 0 **** --- 1,77 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_mutex_init.3,v 1.11 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 29, 1998 + .Dt PTHREAD_MUTEX_INIT 3 + .Os + .Sh NAME + .Nm pthread_mutex_init + .Nd create a mutex + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_mutex_init "pthread_mutex_t *mutex" "const pthread_mutexattr_t *attr" + .Sh DESCRIPTION + The + .Fn pthread_mutex_init + function creates a new mutex, with attributes specified with + .Fa attr . + If + .Fa attr + is NULL the default attributes are used. + .Sh RETURN VALUES + If successful, + .Fn pthread_mutex_init + will return zero and put the new mutex id into + .Fa mutex , + otherwise an error number will be returned to indicate the error. + .Sh ERRORS + .Fn pthread_mutex_init + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa attr + is invalid. + .It Bq Er ENOMEM + The process cannot allocate enough memory to create another mutex. + .It Bq Er EAGAIN + The temporarily lacks the resources to create another mutex. + .El + .Sh SEE ALSO + .Xr pthread_mutex_destroy 3 , + .Xr pthread_mutex_lock 3 , + .Xr pthread_mutex_trylock 3 , + .Xr pthread_mutex_unlock 3 + .Sh STANDARDS + .Fn pthread_mutex_init + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_mutex_lock.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_mutex_lock.3 Sun Sep 15 21:38:28 2002 *************** *** 0 **** --- 1,74 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_mutex_lock.3,v 1.10 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 30, 1998 + .Dt PTHREAD_MUTEX_LOCK 3 + .Os + .Sh NAME + .Nm pthread_mutex_lock + .Nd lock a mutex + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_mutex_lock "pthread_mutex_t *mutex" + .Sh DESCRIPTION + The + .Fn pthread_mutex_lock + function locks + .Fa mutex . + If the mutex is already locked, the calling thread will block until the + mutex becomes available. + .Sh RETURN VALUES + If successful, + .Fn pthread_mutex_lock + will return zero, otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_mutex_lock + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa mutex + is invalid. + .It Bq Er EDEADLK + A deadlock would occur if the thread blocked waiting for + .Fa mutex . + .El + .Sh SEE ALSO + .Xr pthread_mutex_destroy 3 , + .Xr pthread_mutex_init 3 , + .Xr pthread_mutex_trylock 3 , + .Xr pthread_mutex_unlock 3 + .Sh STANDARDS + .Fn pthread_mutex_lock + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_mutex_trylock.3 =========================================================================== *** /dev/null Sun Sep 15 21:37:11 2002 --- lib/libpthread/man/pthread_mutex_trylock.3 Sun Sep 15 21:38:29 2002 *************** *** 0 **** --- 1,75 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_mutex_trylock.3,v 1.10 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd July 30, 1998 + .Dt PTHREAD_MUTEX_TRYLOCK 3 + .Os + .Sh NAME + .Nm pthread_mutex_trylock + .Nd attempt to lock a mutex without blocking + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_mutex_trylock "pthread_mutex_t *mutex" + .Sh DESCRIPTION + The + .Fn pthread_mutex_trylock + function locks + .Fa mutex . + If the mutex is already locked, + .Fn pthread_mutex_trylock + will not block waiting for the mutex, but will return an error condition. + .Sh RETURN VALUES + If successful, + .Fn pthread_mutex_trylock + will return zero, otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_mutex_trylock + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa mutex + is invalid. + .It Bq Er EBUSY + .Fa Mutex + is already locked. + .El + .Sh SEE ALSO + .Xr pthread_mutex_destroy 3 , + .Xr pthread_mutex_init 3 , + .Xr pthread_mutex_lock 3 , + .Xr pthread_mutex_unlock 3 + .Sh STANDARDS + .Fn pthread_mutex_trylock + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_mutex_unlock.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_mutex_unlock.3 Sun Sep 15 21:38:29 2002 *************** *** 0 **** --- 1,74 ---- + .\" Copyright (c) 1997 Brian Cully + .\" All rights reserved. + .\" + .\" Redistribution and use in source and binary forms, with or without + .\" modification, are permitted provided that the following conditions + .\" are met: + .\" 1. Redistributions of source code must retain the above copyright + .\" notice, this list of conditions and the following disclaimer. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice, this list of conditions and the following disclaimer in the + .\" documentation and/or other materials provided with the distribution. + .\" 3. Neither the name of the author nor the names of any co-contributors + .\" may be used to endorse or promote products derived from this software + .\" without specific prior written permission. + .\" + .\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + .\" SUCH DAMAGE. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_mutex_unlock.3,v 1.11 2002/07/10 09:06:42 maxim Exp $ + .\" + .Dd July 30, 1998 + .Dt PTHREAD_MUTEX_UNLOCK 3 + .Os + .Sh NAME + .Nm pthread_mutex_unlock + .Nd unlock a mutex + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_mutex_unlock "pthread_mutex_t *mutex" + .Sh DESCRIPTION + If the current thread holds the lock on + .Fa mutex , + then the + .Fn pthread_mutex_unlock + function unlocks + .Fa mutex . + .Sh RETURN VALUES + If successful, + .Fn pthread_mutex_unlock + will return zero, otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_mutex_unlock + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa mutex + is invalid. + .It Bq Er EPERM + The current thread does not hold a lock on + .Fa mutex . + .El + .Sh SEE ALSO + .Xr pthread_mutex_destroy 3 , + .Xr pthread_mutex_init 3 , + .Xr pthread_mutex_lock 3 , + .Xr pthread_mutex_trylock 3 + .Sh STANDARDS + .Fn pthread_mutex_unlock + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_mutexattr.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_mutexattr.3 Sun Sep 15 21:38:29 2002 *************** *** 0 **** --- 1,177 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_mutexattr.3,v 1.7 2001/10/01 16:09:09 ru Exp $ + .Dd May 1, 2000 + .Dt PTHREAD_MUTEXATTR 3 + .Os + .Sh NAME + .Nm pthread_mutexattr_init , + .Nm pthread_mutexattr_destroy , + .Nm pthread_mutexattr_setprioceiling , + .Nm pthread_mutexattr_getprioceiling , + .Nm pthread_mutexattr_setprotocol , + .Nm pthread_mutexattr_getprotocol , + .Nm pthread_mutexattr_settype , + .Nm pthread_mutexattr_gettype + .Nd mutex attribute operations + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_mutexattr_init "pthread_mutexattr_t *attr" + .Ft int + .Fn pthread_mutexattr_destroy "pthread_mutexattr_t *attr" + .Ft int + .Fn pthread_mutexattr_setprioceiling "pthread_mutexattr_t *attr" "int prioceiling" + .Ft int + .Fn pthread_mutexattr_getprioceiling "pthread_mutexattr_t *attr" "int *prioceiling" + .Ft int + .Fn pthread_mutexattr_setprotocol "pthread_mutexattr_t *attr" "int protocol" + .Ft int + .Fn pthread_mutexattr_getprotocol "pthread_mutexattr_t *attr" "int *protocol" + .Ft int + .Fn pthread_mutexattr_settype "pthread_mutexattr_t *attr" "int type" + .Ft int + .Fn pthread_mutexattr_gettype "pthread_mutexattr_t *attr" "int *type" + .Sh DESCRIPTION + Mutex attributes are used to specify parameters to + .Fn pthread_mutex_init . + One attribute object can be used in multiple calls to + .Fn pthread_mutex_init , + with or without modifications between calls. + .Pp + The + .Fn pthread_mutexattr_init + function initializes + .Fa attr + with all the default mutex attributes. + .Pp + The + .Fn pthread_mutexattr_destroy + function destroys + .Fa attr . + .Pp + The + .Fn pthread_mutexattr_set* + functions set the attribute that corresponds to each function name. + .Pp + The + .Fn pthread_mutexattr_get* + functions copy the value of the attribute that corresponds to each function name + to the location pointed to by the second function parameter. + .Sh RETURN VALUES + If successful, these functions return 0. + Otherwise, an error number is returned to indicacte the error. + .Sh ERRORS + .Fn pthread_mutexattr_init + will fail if: + .Bl -tag -width Er + .It Bq Er ENOMEM + Out of memory. + .El + .Pp + .Fn pthread_mutexattr_destroy + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .El + .Pp + .Fn pthread_mutexattr_setprioceiling + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr , + or invalid value for + .Fa prioceiling . + .El + .Pp + .Fn pthread_mutexattr_getprioceiling + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .El + .Pp + .Fn pthread_mutexattr_setprotocol + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr , + or invalid value for + .Fa protocol . + .El + .Pp + .Fn pthread_mutexattr_getprotocol + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .El + .Pp + .Fn pthread_mutexattr_settype + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr , + or invalid value for + .Fa type . + .El + .Pp + .Fn pthread_mutexattr_gettype + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Fa attr . + .El + .Sh SEE ALSO + .Xr pthread_mutex_init 3 + .Sh STANDARDS + .Fn pthread_mutexattr_init + and + .Fn pthread_mutexattr_destroy + conform to + .St -p1003.1-96 + .Pp + .Fn pthread_mutexattr_setprioceiling , + .Fn pthread_mutexattr_getprioceiling , + .Fn pthread_mutexattr_setprotocol , + .Fn pthread_mutexattr_getprotocol , + .Fn pthread_mutexattr_settype , + and + .Fn pthread_mutexattr_gettype + conform to + .St -susv2 Index: lib/libpthread/man/pthread_once.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_once.3 Sun Sep 15 21:38:29 2002 *************** *** 0 **** --- 1,105 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_once.3,v 1.13 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_ONCE 3 + .Os + .Sh NAME + .Nm pthread_once + .Nd dynamic package initialization + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Pp + pthread_once_t + .Fa once_control + = PTHREAD_ONCE_INIT; + .Ft int + .Fn pthread_once "pthread_once_t *once_control" "void (*init_routine)(void)" + .Sh DESCRIPTION + The first call to + .Fn pthread_once + by any thread in a process, with a given + .Fa once_control , + will call the + .Fn init_routine + with no arguments. + Subsequent calls to + .Fn pthread_once + with the same + .Fa once_control + will not call the + .Fn init_routine . + On return from + .Fn pthread_once , + it is guaranteed that + .Fn init_routine + has completed. + The + .Fa once_control + parameter is used to determine whether the associated initialization + routine has been called. + .Pp + The function + .Fn pthread_once + is not a cancellation point. + However, if + .Fn init_routine + is a cancellation point and is cancelled, the effect on + .Fa once_control is as if + .Fn pthread_once + was never called. + .Pp + The constant + .Fa PTHREAD_ONCE_INIT + is defined by header + .Aq Pa pthread.h . + .Pp + The behavior of + .Fn pthread_once + is undefined if + .Fa once_control + has automatic storage duration or is not initialized by + .Fa PTHREAD_ONCE_INIT . + .Sh RETURN VALUES + If successful, the + .Fn pthread_once + function will return zero. + Otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + None. + .Sh STANDARDS + .Fn pthread_once + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_rwlock_destroy.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlock_destroy.3 Sun Sep 15 21:38:30 2002 *************** *** 0 **** --- 1,82 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlock_destroy.3,v 1.6 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd August 4, 1998 + .Dt PTHREAD_RWLOCK_DESTROY 3 + .Os + .Sh NAME + .Nm pthread_rwlock_destroy + .Nd destroy a read/write lock + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlock_destroy "pthread_rwlock_t *lock" + .Sh DESCRIPTION + The + .Fn pthread_rwlock_destroy + function is used to destroy a read/write lock previously created with + .Fn pthread_rwlock_init . + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlock_destroy + function will return zero. Otherwise an error number will be returned + to indicate the error. + .Sh SEE ALSO + .Xr pthread_rwlock_init 3 + .Sh STANDARDS + The + .Fn pthread_rwlock_destroy + function is expected to conform to + .St -susv2 . + .Sh ERRORS + The + .Fn pthread_rwlock_destroy + function will fail if: + .Bl -tag -width Er + .It Bq Er EPERM + The caller does not have the privilege to perform the operation. + .El + .Pp + The + .Fn pthread_rwlock_destroy + function may fail if: + .Bl -tag -width Er + .It Bq Er EBUSY + The system has detected an attempt to destroy the object referenced by + .Fa lock + while it is locked. + .It Bq Er EINVAL + The value specified by + .Fa lock + is invalid. + .El + .Sh HISTORY + The + .Fn pthread_rwlock_destroy + function first appeared in + .Fx 3.0 . Index: lib/libpthread/man/pthread_rwlock_init.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlock_init.3 Sun Sep 15 21:38:30 2002 *************** *** 0 **** --- 1,101 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlock_init.3,v 1.5 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd August 4, 1998 + .Dt PTHREAD_RWLOCK_INIT 3 + .Os + .Sh NAME + .Nm pthread_rwlock_init + .Nd initialize a read/write lock + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlock_init "pthread_rwlock_t *lock" "const pthread_rwlockattr_t *attr" + .Sh DESCRIPTION + The + .Fn pthread_rwlock_init + function is used to initialize a read/write lock, with attributes + specified by + .Fa attr . + If + .Fa attr + is NULL, the default read/write lock attributes are used. + .Pp + The results of calling + .Fn pthread_rwlock_init + with an already initialized lock are undefined. + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlock_init + function will return zero. Otherwise an error number will be returned + to indicate the error. + .Sh SEE ALSO + .Xr pthread_rwlockattr_init 3 , + .Xr pthread_rwlockattr_setpshared 3 , + .Xr pthread_rwlock_destroy 3 + .Sh STANDARDS + The + .Fn pthread_rwlock_init + function is expected to conform to + .St -susv2 . + .Sh ERRORS + The + .Fn pthread_rwlock_init + function will fail if: + .Bl -tag -width Er + .It Bq Er EAGAIN + The system lacked the necessary resources (other than memory) to + initialize the lock. + .It Bq Er ENOMEM + Insufficient memory exists to initialize the lock. + .It Bq Er EPERM + The caller does not have sufficient privilege to perform the + operation. + .El + .Pp + The + .Fn pthread_rwlock_init + function may fail if: + .Bl -tag -width Er + .It Bq Er EBUSY + The system has detected an attempt to re-initialize the object + referenced by + .Fa lock , + a previously initialized but not yet destroyed read/write lock. + .It Bq Er EINVAL + The value specified by + .Fa attr + is invalid. + .El + .Sh HISTORY + The + .Fn pthread_rwlock_init + function first appeared in + .Fx 3.0 . + .Sh BUGS + The PTHREAD_PROCESS_SHARED attribute is not supported. Index: lib/libpthread/man/pthread_rwlock_rdlock.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlock_rdlock.3 Sun Sep 15 21:38:30 2002 *************** *** 0 **** --- 1,124 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlock_rdlock.3,v 1.4 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd August 4, 1998 + .Dt PTHREAD_RWLOCK_RDLOCK 3 + .Os + .Sh NAME + .Nm pthread_rwlock_rdlock , + .Nm pthread_rwlock_tryrdlock + .Nd acquire a read/write lock for reading + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlock_rdlock "pthread_rwlock_t *lock" + .Ft int + .Fn pthread_rwlock_tryrdlock "pthread_rwlock_t *lock" + .Sh DESCRIPTION + The + .Fn pthread_rwlock_rdlock + function acquires a read lock on + .Fa lock + provided that + .Fa lock + is not presently held for writing and no writer threads are + presently blocked on the lock. If the read lock cannot be + immediately acquired, the calling thread blocks until it can + acquire the lock. + .Pp + The + .Fn pthread_rwlock_tryrdlock + function performs the same action, but does not block if the lock + cannot be immediately obtained (i.e. the lock is held for writing + or there are waiting writers). + .Pp + A thread may hold multiple concurrent read locks. If so, + .Fn pthread_rwlock_unlock + must be called once for each lock obtained. + .Pp + The results of acquiring a read lock while the calling thread holds + a write lock are undefined. + .Sh IMPLEMENTATION NOTES + To prevent writer starvation, writers are favored over readers. + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlock_rdlock + and + .Fn pthread_rwlock_tryrdlock + functions will return zero. Otherwise an error number will be returned + to indicate the error. + .Sh SEE ALSO + .Xr pthread_rwlock_init 3 , + .Xr pthread_rwlock_trywrlock 3 , + .Xr pthread_rwlock_unlock 3 , + .Xr pthread_rwlock_wrlock 3 + .Sh STANDARDS + The + .Fn pthread_rwlock_rdlock + and + .Fn pthread_rwlock_tryrdlock + functions are expected to conform to + .St -susv2 . + .Sh ERRORS + The + .Fn pthread_rwlock_tryrdlock + function will fail if: + .Bl -tag -width Er + .It Bq Er EBUSY + The lock could not be acquired because a writer holds the lock or + was blocked on it. + .El + .Pp + The + .Fn pthread_rwlock_rdlock + and + .Fn pthread_rwlock_tryrdlock + functions may fail if: + .Bl -tag -width Er + .It Bq Er EAGAIN + The lock could not be acquired because the maximum number of read locks + against + .Fa lock + has been exceeded. + .It Bq Er EDEADLK + The current thread already owns + .Fa lock + for writing. + .It Bq Er EINVAL + The value specified by + .Fa lock + is invalid. + .It Bq Er ENOMEM + Insufficient memory exists to initialize the lock (applies to + statically initialized locks only). + .El + .Sh HISTORY + The + .Fn pthread_rwlock_rdlock + function first appeared in + .Fx 3.0 . Index: lib/libpthread/man/pthread_rwlock_unlock.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlock_unlock.3 Sun Sep 15 21:38:30 2002 *************** *** 0 **** --- 1,81 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlock_unlock.3,v 1.4 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd August 4, 1998 + .Dt PTHREAD_RWLOCK_UNLOCK 3 + .Os + .Sh NAME + .Nm pthread_rwlock_unlock + .Nd release a read/write lock + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlock_unlock "pthread_rwlock_t *lock" + .Sh DESCRIPTION + The + .Fn pthread_rwlock_unlock + function is used to release the read/write lock previously obtained by + .Fn pthread_rwlock_rdlock , + .Fn pthread_rwlock_wrlock , + .Fn pthread_rwlock_tryrdlock , + or + .Fn pthread_rwlock_trywrlock . + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlock_unlock + function will return zero. Otherwise an error number will be returned + to indicate the error. + .Pp + The results are undefined if + .Fa lock + is not held by the calling thread. + .Sh SEE ALSO + .Xr pthread_rwlock_rdlock 3 , + .Xr pthread_rwlock_wrlock 3 + .Sh STANDARDS + The + .Fn pthread_rwlock_unlock + function is expected to conform to + .St -susv2 . + .Sh ERRORS + The + .Fn pthread_rwlock_unlock + function may fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa lock + is invalid. + .It Bq Er EPERM + The current thread does not own the read/write lock. + .El + .Sh HISTORY + The + .Fn pthread_rwlock_unlock + function first appeared in + .Fx 3.0 . Index: lib/libpthread/man/pthread_rwlock_wrlock.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlock_wrlock.3 Sun Sep 15 21:38:30 2002 *************** *** 0 **** --- 1,104 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlock_wrlock.3,v 1.4 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd August 4, 1998 + .Dt PTHREAD_RWLOCK_WRLOCK 3 + .Os + .Sh NAME + .Nm pthread_rwlock_wrlock , + .Nm pthread_rwlock_trywrlock + .Nd acquire a read/write lock for writing + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlock_wrlock "pthread_rwlock_t *lock" + .Ft int + .Fn pthread_rwlock_trywrlock "pthread_rwlock_t *lock" + .Sh DESCRIPTION + The + .Fn pthread_rwlock_wrlock + function blocks until a write lock can be acquired against + .Fa lock . + The + .Fn pthread_rwlock_trywrlock + function performs the same action, but does not block if the lock + cannot be immediately obtained. + .Pp + The results are undefined if the calling thread already holds the + lock at the time the call is made. + .Sh IMPLEMENTATION NOTES + To prevent writer starvation, writers are favored over readers. + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlock_wrlock + and + .Fn pthread_rwlock_trywrlock + functions will return zero. Otherwise an error number will be returned + to indicate the error. + .Sh SEE ALSO + .Xr pthread_rwlock_trywrlock 3 , + .Xr pthread_rwlock_unlock 3 , + .Xr pthread_rwlock_wrlock 3 + .Sh STANDARDS + The + .Fn pthread_rwlock_wrlock + and + .Fn pthread_rwlock_trywrlock + functions are expected to conform to + .St -susv2 . + .Sh ERRORS + The + .Fn pthread_rwlock_trywrlock + function will fail if: + .Bl -tag -width Er + .It Bq Er EBUSY + The calling thread is not able to acquire the lock without blocking. + .El + .Pp + The + .Fn pthread_rwlock_wrlock + and + .Fn pthread_rwlock_trywrlock + functions may fail if: + .Bl -tag -width Er + .It Bq Er EDEADLK + The calling thread already owns the read/write lock (for reading + or writing). + .It Bq Er EINVAL + The value specified by + .Fa lock + is invalid. + .It Bq Er ENOMEM + Insufficient memory exists to initialize the lock (applies to + statically initialized locks only). + .El + .Sh HISTORY + The + .Fn pthread_rwlock_wrlock + function first appeared in + .Fx 3.0 . Index: lib/libpthread/man/pthread_rwlockattr_destroy.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlockattr_destroy.3 Sun Sep 15 21:38:31 2002 *************** *** 0 **** --- 1,70 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlockattr_destroy.3,v 1.6 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd August 4, 1998 + .Dt PTHREAD_RWLOCKATTR_DESTROY 3 + .Os + .Sh NAME + .Nm pthread_rwlockattr_destroy + .Nd destroy a read/write lock + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlockattr_destroy "pthread_rwlockattr_t *attr" + .Sh DESCRIPTION + The + .Fn pthread_rwlockattr_destroy + function is used to destroy a read/write lock attribute object + previously created with + .Fn pthread_rwlockattr_init . + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlockattr_destroy + function will return zero. Otherwise an error number will be returned + to indicate the error. + .Sh SEE ALSO + .Xr pthread_rwlockattr_init 3 + .Sh STANDARDS + The + .Fn pthread_rwlockattr_destroy + function is expected to conform to + .St -susv2 . + .Sh ERRORS + .Fn pthread_rwlockattr_destroy + may fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa attr + is invalid. + .El + .Sh HISTORY + The + .Fn pthread_rwlockattr_destroy + function first appeared in + .Fx 3.0 . Index: lib/libpthread/man/pthread_rwlockattr_getpshared.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlockattr_getpshared.3 Sun Sep 15 21:38:31 2002 *************** *** 0 **** --- 1,82 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlockattr_getpshared.3,v 1.8 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd March 22, 1999 + .Dt PTHREAD_RWLOCKATTR_GETPSHARED 3 + .Os + .Sh NAME + .Nm pthread_rwlockattr_getpshared + .Nd get the process shared attribute + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlockattr_getpshared "const pthread_rwlockattr_t *attr" "int *pshared" + .Sh DESCRIPTION + The + .Fn pthread_rwlockattr_getpshared + function is used to get the process shared setting of a read/write + lock attribute object. The setting is returned via + .Fa pshared , + and may be one of two values: + .Bl -tag -width PTHREAD_PROCESS_PRIVATE + .It Dv PTHREAD_PROCESS_SHARED + Any thread of any process that has access to the memory where the + read/write lock resides can manipulate the lock. + .It Dv PTHREAD_PROCESS_PRIVATE + Only threads created within the same process as the thread that + initialized the read/write lock can manipulate the lock. This is + the default value. + .El + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlockattr_getpshared + function will return zero. Otherwise an error number will be returned + to indicate the error. + .Sh SEE ALSO + .Xr pthread_rwlockattr_init 3 , + .Xr pthread_rwlockattr_setpshared 3 , + .Xr pthread_rwlock_init 3 + .Sh STANDARDS + The + .Fn pthread_rwlockattr_getpshared + function is expected to conform to + .St -susv2 . + .Sh ERRORS + .Fn pthread_rwlockattr_getpshared + may fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa attr + is invalid. + .El + .Sh HISTORY + The + .Fn pthread_rwlockattr_getpshared + function first appeared in + .Fx 3.0 . Index: lib/libpthread/man/pthread_rwlockattr_init.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlockattr_init.3 Sun Sep 15 21:38:31 2002 *************** *** 0 **** --- 1,69 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlockattr_init.3,v 1.6 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd August 4, 1998 + .Dt PTHREAD_RWLOCKATTR_INIT 3 + .Os + .Sh NAME + .Nm pthread_rwlockattr_init + .Nd initialize a read/write lock + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlockattr_init "pthread_rwlockattr_t *attr" + .Sh DESCRIPTION + The + .Fn pthread_rwlockattr_init + function is used to initialize a read/write lock attributes object. + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlockattr_init + function will return zero. Otherwise an error number will be returned + to indicate the error. + .Sh SEE ALSO + .Xr pthread_rwlockattr_destroy 3 , + .Xr pthread_rwlockattr_getpshared 3 , + .Xr pthread_rwlockattr_setpshared 3 , + .Xr pthread_rwlock_init 3 + .Sh STANDARDS + The + .Fn pthread_rwlockattr_init + function is expected to conform to + .St -susv2 . + .Sh ERRORS + .Fn pthread_rwlockattr_init + will fail if: + .Bl -tag -width Er + .It Bq Er ENOMEM + Insufficient memory exists to initialize the attribute object. + .El + .Sh HISTORY + The + .Fn pthread_rwlockattr_init + function first appeared in + .Fx 3.0 . Index: lib/libpthread/man/pthread_rwlockattr_setpshared.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_rwlockattr_setpshared.3 Sun Sep 15 21:38:31 2002 *************** *** 0 **** --- 1,90 ---- + .\" Copyright (c) 1998 Alex Nash + .\" 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. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_rwlockattr_setpshared.3,v 1.7 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd August 4, 1998 + .Dt PTHREAD_RWLOCKATTR_SETPSHARED 3 + .Os + .Sh NAME + .Nm pthread_rwlockattr_setpshared + .Nd set the process shared attribute + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_rwlockattr_setpshared "pthread_rwlockattr_t *attr" "int pshared" + .Sh DESCRIPTION + The + .Fn pthread_rwlockattr_setpshared + function sets the process shared attribute of + .Fa attr + to the value referenced by + .Fa pshared . + .Fa pshared + may be one of two values: + .Bl -tag -width PTHREAD_PROCESS_PRIVATE + .It Dv PTHREAD_PROCESS_SHARED + Any thread of any process that has access to the memory where the + read/write lock resides can manipulate the lock. + .It Dv PTHREAD_PROCESS_PRIVATE + Only threads created within the same process as the thread that + initialized the read/write lock can manipulate the lock. This is + the default value. + .El + .Sh RETURN VALUES + If successful, the + .Fn pthread_rwlockattr_setpshared + function will return zero. Otherwise an error number will be returned + to indicate the error. + .Sh SEE ALSO + .Xr pthread_rwlockattr_init 3 , + .Xr pthread_rwlockattr_setpshared 3 , + .Xr pthread_rwlock_init 3 + .Sh STANDARDS + The + .Fn pthread_rwlockattr_setpshared + function is expected to conform to + .St -susv2 . + .Sh ERRORS + .Fn pthread_rwlockattr_setpshared + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + The value specified by + .Fa attr + or + .Fa pshared + is invalid. + .El + .Sh HISTORY + The + .Fn pthread_rwlockattr_setpshared + function first appeared in + .Fx 3.0 . + .Sh BUGS + The + .Dv PTHREAD_PROCESS_SHARED + attribute is not supported. Index: lib/libpthread/man/pthread_schedparam.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_schedparam.3 Sun Sep 15 21:38:32 2002 *************** *** 0 **** --- 1,90 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_schedparam.3,v 1.6 2001/10/01 16:09:09 ru Exp $ + .Dd May 1, 2000 + .Dt PTHREAD_SCHEDPARAM 3 + .Os + .Sh NAME + .Nm pthread_setschedparam , + .Nm pthread_getschedparam + .Nd thread scheduling parameter manipulation + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_setschedparam "pthread_t thread" "int policy" "const struct sched_param *param" + .Ft int + .Fn pthread_getschedparam "pthread_t thread" "int *policy" "struct sched_param *param" + .Sh DESCRIPTION + The + .Fn pthread_setschedparam + and + .Fn pthread_getschedparam + functions set and get the scheduling parameters of individual threads. + The scheduling policy for a thread can either be + .Dv SCHED_FIFO + (first in, first out) or + .Dv SCHED_RR + (round-robin). + The thread priority (accessed via + .Va param->sched_priority ) + must be at least + .Dv PTHREAD_MIN_PRIORITY + and no more than + .Dv PTHREAD_MAX_PRIORITY . + .Sh RETURN VALUES + If successful, these functions return 0. + Otherwise, an error number is returned to indicate the error. + .Sh ERRORS + .Fn pthread_setschedparam + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + Invalid value for + .Va policy . + .It Bq Er ENOTSUP + Invalid value for scheduling parameters. + .It Bq Er ESRCH + Non-existent thread + .Va thread . + .El + .Pp + .Fn pthread_getschedparam + will fail if: + .Bl -tag -width Er + .It Bq Er ESRCH + Non-existent thread + .Va thread . + .El + .Sh STANDARDS + .Fn pthread_setschedparam + and + .Fn pthread_getschedparam + conform to + .St -susv2 Index: lib/libpthread/man/pthread_self.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_self.3 Sun Sep 15 21:38:32 2002 *************** *** 0 **** --- 1,61 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_self.3,v 1.9 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_SELF 3 + .Os + .Sh NAME + .Nm pthread_self + .Nd get the calling thread's ID + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft pthread_t + .Fn pthread_self "void" + .Sh DESCRIPTION + The + .Fn pthread_self + function returns the thread ID of the calling thread. + .Sh RETURN VALUES + The + .Fn pthread_self + function returns the thread ID of the calling thread. + .Sh ERRORS + None. + .Sh SEE ALSO + .Xr pthread_create 3 , + .Xr pthread_equal 3 + .Sh STANDARDS + .Fn pthread_self + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_setspecific.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_setspecific.3 Sun Sep 15 21:38:32 2002 *************** *** 0 **** --- 1,95 ---- + .\" Copyright (c) 1996 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_setspecific.3,v 1.11 2001/10/01 16:09:09 ru Exp $ + .\" + .Dd April 4, 1996 + .Dt PTHREAD_SETSPECIFIC 3 + .Os + .Sh NAME + .Nm pthread_setspecific + .Nd set a thread-specific data value + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_setspecific "pthread_key_t key" "const void *value" + .Sh DESCRIPTION + The + .Fn pthread_setspecific + function associates a thread-specific value with a + .Fa key + obtained via a previous call to + .Fn pthread_key_create . + Different threads man bind different values to the same key. + These values are + typically pointers to blocks of dynamically allocated memory that have been + reserved for use by the calling thread. + .Pp + The effect of calling + .Fn pthread_setspecific + with a key value not obtained from + .Fn pthread_key_create + or after + .Fa key + has been deleted with + .Fn pthread_key_delete + is undefined. + .Pp + .Fn pthread_setspecific + may be called from a thread-specific data destructor function, however this + may result in lost storage or infinite loops. + .Sh RETURN VALUES + If successful, the + .Fn pthread_setspecific + function will return zero. + Otherwise an error number will be returned to + indicate the error. + .Sh ERRORS + .Fn pthread_setspecific + will fail if: + .Bl -tag -width Er + .It Bq Er ENOMEM + Insufficient memory exists to associate the value with the + .Fa key . + .It Bq Er EINVAL + The + .Fa key + value is invalid. + .El + .Sh SEE ALSO + .Xr pthread_getspecific 3 , + .Xr pthread_key_create 3 , + .Xr pthread_key_delete 3 + .Sh STANDARDS + .Fn pthread_setspecific + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/pthread_sigmask.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_sigmask.3 Sun Sep 15 21:38:32 2002 *************** *** 0 **** --- 1,96 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/pthread_sigmask.3,v 1.9 2001/10/01 16:09:09 ru Exp $ + .Dd April 27, 2000 + .Dt PTHREAD_SIGMASK 3 + .Os + .Sh NAME + .Nm pthread_sigmask + .Nd examine and/or change a thread's signal mask + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .In signal.h + .Ft int + .Fn pthread_sigmask "int how" "const sigset_t *set" "sigset_t *oset" + .Sh DESCRIPTION + The + .Fn pthread_sigmask + function examines and/or changes the calling thread's signal mask. + .Pp + If + .Fa set + is not + .Dv NULL , + it specifies a set of signals to be modified, and + .Fa how + specifies what to set the signal mask to: + .Bl -tag -width SIG_UNBLOCK + .It Dv SIG_BLOCK + Union of the current mask and + .Fa set . + .It Dv SIG_UNBLOCK + Intersection of the current mask and the complement of + .Fa set . + .It Dv SIG_SETMASK + .Fa set . + .El + .Pp + If + .Fa oset + is not NULL, the previous signal mask is stored in the location pointed to by + .Fa oset . + .Pp + .Dv SIGKILL + and + .Dv SIGSTOP + cannot be blocked, and will be silently ignored if included in the signal mask. + .Sh RETURN VALUES + If successful, + .Fn pthread_sigmask + returns 0. + Otherwise, an error is returned. + .Sh ERRORS + .Fn pthread_sigmask + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + .Fa how + is not one of the defined values. + .El + .Sh SEE ALSO + .Xr sigaction 2 , + .Xr sigpending 2 , + .Xr sigprocmask 2 , + .Xr sigsuspend 2 , + .Xr sigsetops 3 + .Sh STANDARDS + .Fn pthread_sigmask + conforms to + .St -p1003.1-96 Index: lib/libpthread/man/pthread_testcancel.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/pthread_testcancel.3 Sun Sep 15 21:38:32 2002 *************** *** 0 **** --- 1,209 ---- + .\" $FreeBSD: src/lib/libc_r/man/pthread_testcancel.3,v 1.8 2001/11/05 08:21:32 murray Exp $ + .Dd January 17, 1999 + .Dt PTHREAD_TESTCANCEL 3 + .Os + .Sh NAME + .Nm pthread_setcancelstate , + .Nm pthread_setcanceltype , + .Nm pthread_testcancel + .Nd set cancelability state + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In pthread.h + .Ft int + .Fn pthread_setcancelstate "int state" "int *oldstate" + .Ft int + .Fn pthread_setcanceltype "int type" "int *oldtype" + .Ft void + .Fn pthread_testcancel "void" + .Sh DESCRIPTION + The + .Fn pthread_setcancelstate + function atomically both sets the calling thread's cancelability state + to the indicated + .Fa state + and, if + .Fa oldstate + is not + .Dv NULL , + returns the previous cancelability state at the location referenced by + .Fa oldstate . + Legal values for + .Fa state + are + .Dv PTHREAD_CANCEL_ENABLE + and + .Dv PTHREAD_CANCEL_DISABLE . + .Pp + The + .Fn pthread_setcanceltype + function atomically both sets the calling thread's cancelability type + to the indicated + .Fa type + and, if + .Fa oldtype + is not + .Dv NULL , + returns the previous cancelability type at the location referenced by + .Fa oldtype . + Legal values for + .Fa type + are + .Dv PTHREAD_CANCEL_DEFERRED + and + .Dv PTHREAD_CANCEL_ASYNCHRONOUS . + .Pp + The cancelability state and type of any newly created threads, including the + thread in which + .Fn main + was first invoked, are + .Dv PTHREAD_CANCEL_ENABLE + and + .Dv PTHREAD_CANCEL_DEFERRED + respectively. + .Pp + The + .Fn pthread_testcancel + function creates a cancellation point in the calling thread. + The + .Fn pthread_testcancel + function has no effect if cancelability is disabled. + .Pp + .Ss Cancelability States + The cancelability state of a thread determines the action taken upon + receipt of a cancellation request. + The thread may control cancellation in + a number of ways. + .Pp + Each thread maintains its own + .Dq cancelability state + which may be encoded in two bits: + .Bl -hang + .It Em Cancelability Enable + When cancelability is + .Dv PTHREAD_CANCEL_DISABLE , + cancellation requests against the target thread are held pending. + .It Em Cancelability Type + When cancelability is enabled and the cancelability type is + .Dv PTHREAD_CANCEL_ASYNCHRONOUS , + new or pending cancellation requests may be acted upon at any time. + When cancelability is enabled and the cancelability type is + .Dv PTHREAD_CANCEL_DEFERRED , + cancellation requests are held pending until a cancellation point (see + below) is reached. + If cancelability is disabled, the setting of the + cancelability type has no immediate effect as all cancellation requests + are held pending; however, once cancelability is enabled again the new + type will be in effect. + .El + .Ss Cancellation Points + Cancellation points will occur when a thread is executing the following + functions: + .Fn close , + .Fn creat , + .Fn fcntl , + .Fn fsync , + .Fn msync , + .Fn nanosleep , + .Fn open , + .Fn pause , + .Fn pthread_cond_timedwait , + .Fn pthread_cond_wait , + .Fn pthread_join , + .Fn pthread_testcancel , + .Fn read , + .Fn sigwaitinfo , + .Fn sigsuspend , + .Fn sigwait , + .Fn sleep , + .Fn system , + .Fn tcdrain , + .Fn wait , + .Fn waitpid , + .Fn write . + .Sh RETURN VALUES + If successful, the + .Fn pthread_setcancelstate + and + .Fn pthread_setcanceltype + functions will return zero. + Otherwise, an error number shall be returned to + indicate the error. + .Pp + The + .Fn pthread_setcancelstate + and + .Fn pthread_setcanceltype + functions are used to control the points at which a thread may be + asynchronously canceled. + For cancellation control to be usable in modular + fashion, some rules must be followed. + .Pp + For purposes of this discussion, consider an object to be a generalization + of a procedure. + It is a set of procedures and global variables written as + a unit and called by clients not known by the object. + Objects may depend + on other objects. + .Pp + First, cancelability should only be disabled on entry to an object, never + explicitly enabled. + On exit from an object, the cancelability state should + always be restored to its value on entry to the object. + .Pp + This follows from a modularity argument: if the client of an object (or the + client of an object that uses that object) has disabled cancelability, it is + because the client doesn't want to have to worry about how to clean up if the + thread is canceled while executing some sequence of actions. + If an object + is called in such a state and it enables cancelability and a cancellation + request is pending for that thread, then the thread will be canceled, + contrary to the wish of the client that disabled. + .Pp + Second, the cancelability type may be explicitly set to either + .Em deferred + or + .Em asynchronous + upon entry to an object. + But as with the cancelability state, on exit from + an object that cancelability type should always be restored to its value on + entry to the object. + .Pp + Finally, only functions that are cancel-safe may be called from a thread that + is asynchronously cancelable. + .Sh ERRORS + The function + .Fn pthread_setcancelstate + may fail with: + .Bl -tag -width Er + .It Bq Er EINVAL + The specified state is not + .Dv PTHREAD_CANCEL_ENABLE + or + .Dv PTHREAD_CANCEL_DISABLE . + .El + .Pp + The function + .Fn pthread_setcanceltype + may fail with: + .Bl -tag -width Er + .It Bq Er EINVAL + The specified state is not + .Dv PTHREAD_CANCEL_DEFERRED + or + .Dv PTHREAD_CANCEL_ASYNCHRONOUS . + .El + .Sh SEE ALSO + .Xr pthread_cancel 3 + .Sh STANDARDS + .Fn pthread_testcancel + conforms to + .St -p1003.1-96 . + .Sh AUTHORS + This man page was written by + .An David Leonard Aq d@openbsd.org + for the + .Ox + implementation of + .Xr pthread_cancel 3 . Index: lib/libpthread/man/sem_destroy.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/sem_destroy.3 Sun Sep 15 21:38:33 2002 *************** *** 0 **** --- 1,81 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/sem_destroy.3,v 1.9 2001/10/01 16:09:09 ru Exp $ + .Dd February 15, 2000 + .Dt SEM_DESTROY 3 + .Os + .Sh NAME + .Nm sem_destroy + .Nd destroy an unnamed semaphore + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In semaphore.h + .Ft int + .Fn sem_destroy "sem_t *sem" + .Sh DESCRIPTION + The + .Fn sem_destroy + function destroys the unnamed semaphore pointed to by + .Fa sem . + After a successful call to + .Fn sem_destroy , + .Fa sem + is unuseable until re-initialized by another call to + .Fn sem_init . + .Sh RETURN VALUES + .Rv -std sem_destroy + .Sh ERRORS + .Fn sem_destroy + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + .Fa sem + points to an invalid semaphore. + .It Bq Er EBUSY + There are currently threads blocked on the semaphore that + .Fa sem + points to. + .El + .Sh SEE ALSO + .Xr sem_init 3 + .Sh STANDARDS + .Fn sem_destroy + conforms to + .St -p1003.1-96 . + .Pp + POSIX does not define the behavior of + .Fn sem_destroy + if called while there are threads blocked on + .Fa sem , + but this implementation is guaranteed to return -1 and set + .Va errno + to + .Er EBUSY + if there are threads blocked on + .Fa sem . Index: lib/libpthread/man/sem_getvalue.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/sem_getvalue.3 Sun Sep 15 21:38:33 2002 *************** *** 0 **** --- 1,73 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/sem_getvalue.3,v 1.9 2001/10/01 16:09:09 ru Exp $ + .Dd February 15, 2000 + .Dt SEM_GETVALUE 3 + .Os + .Sh NAME + .Nm sem_getvalue + .Nd get the value of a semaphore + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In semaphore.h + .Ft int + .Fn sem_getvalue "sem_t *sem" "int *sval" + .Sh DESCRIPTION + The + .Fn sem_getvalue + function sets the variable pointed to by + .Fa sval + to the current value of the semaphore pointed to by + .Fa sem , + as of the time that the call to + .Fn sem_getvalue + is actually run. + .Sh RETURN VALUES + .Rv -std sem_getvalue + .Sh ERRORS + .Fn sem_getvalue + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + .Fa sem + points to an invalid semaphore. + .El + .Sh SEE ALSO + .Xr sem_post 3 , + .Xr sem_trywait 3 , + .Xr sem_wait 3 + .Sh STANDARDS + .Fn sem_getvalue + conforms to + .St -p1003.1-96 . + .Pp + The value of the semaphore is never negative, even if there are threads blocked + on the semaphore. POSIX is somewhat ambiguous in its wording with regard to + what the value of the semaphore should be if there are blocked waiting threads, + but this behavior is conformant, given the wording of the specification. Index: lib/libpthread/man/sem_init.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/sem_init.3 Sun Sep 15 21:38:33 2002 *************** *** 0 **** --- 1,98 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/sem_init.3,v 1.11 2001/10/01 16:09:09 ru Exp $ + .Dd February 15, 2000 + .Dt SEM_INIT 3 + .Os + .Sh NAME + .Nm sem_init + .Nd initialize an unnamed semaphore + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In semaphore.h + .Ft int + .Fn sem_init "sem_t *sem" "int pshared" "unsigned int value" + .Sh DESCRIPTION + The + .Fn sem_init + function initializes the unnamed semaphore pointed to by + .Fa sem + to have the value + .Fa value . + A non-zero value for + .Fa pshared + specifies a shared semaphore that can be used by multiple processes, which this + implementation is not capable of. + .Pp + Following a successful call to + .Fn sem_init , + .Fa sem + can be used as an argument in subsequent calls to + .Fa sem_wait , + .Fa sem_trywait , + .Fa sem_post , + and + .Fa sem_destroy . + .Fa sem + is no longer valid after a successful call to + .Fa sem_destroy . + .Sh RETURN VALUES + .Rv -std sem_init + .Sh ERRORS + .Fn sem_init + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + .Fa value + exceeds SEM_VALUE_MAX. + .It Bq Er ENOSPC + Memory allocation error. + .It Bq Er EPERM + Unable to initialize a shared semaphore. + .El + .Sh SEE ALSO + .Xr sem_destroy 3 , + .Xr sem_post 3 , + .Xr sem_trywait 3 , + .Xr sem_wait 3 + .Sh STANDARDS + .Fn sem_init + conforms to + .St -p1003.1-96 . + .Pp + This implementation does not support shared semaphores, and reports this fact + by setting + .Va errno + to + .Er EPERM . + This is perhaps a stretch of the intention of POSIX, but is + compliant, with the caveat that + .Fn sem_init + always reports a permissions error when an attempt to create a shared semaphore + is made. Index: lib/libpthread/man/sem_open.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/sem_open.3 Sun Sep 15 21:38:33 2002 *************** *** 0 **** --- 1,81 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/sem_open.3,v 1.7 2001/10/01 16:09:09 ru Exp $ + .Dd February 15, 2000 + .Dt SEM_OPEN 3 + .Os + .Sh NAME + .Nm sem_open , + .Nm sem_close , + .Nm sem_unlink + .Nd named semaphore operations + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In semaphore.h + .Ft sem_t * + .Fn sem_open "const char *name" "int oflag" "..." + .Ft int + .Fn sem_close "sem_t *sem" + .Ft int + .Fn sem_unlink "const char *name" + .Sh DESCRIPTION + The + .Fn sem_open , + .Fn sem_close , + and + .Fn sem_unlink + functions are not supported by this implementation. + .Sh RETURN VALUES + .Fn sem_open + returns SEM_FAILED and sets + .Va errno + to indicate an error. + .Fn sem_close + and + .Fn sem_unlink + return -1 and set + .Va errno + to indicate an error. + .Sh ERRORS + .Fn sem_open , + .Fn sem_close , + and + .Fn sem_unlink + will fail: + .Bl -tag -width Er + .It Bq Er ENOSYS + Function not supported by this implementation. + .El + .Sh STANDARDS + .Fn sem_open , + .Fn sem_close , + and + .Fn sem_unlink + conform to + .St -p1003.1-96 . Index: lib/libpthread/man/sem_post.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/sem_post.3 Sun Sep 15 21:38:33 2002 *************** *** 0 **** --- 1,70 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/sem_post.3,v 1.10 2001/10/01 16:09:09 ru Exp $ + .Dd February 15, 2000 + .Dt SEM_POST 3 + .Os + .Sh NAME + .Nm sem_post + .Nd increment (unlock) a semaphore + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In semaphore.h + .Ft int + .Fn sem_post "sem_t *sem" + .Sh DESCRIPTION + The + .Fn sem_post + function increments (unlocks) the semaphore pointed to by + .Fa sem . + If there are threads blocked on the semaphore when + .Fn sem_post + is called, then the highest priority thread that has been blocked the longest on + the semaphore will be allowed to return from + .Fn sem_wait . + .Pp + .Fn sem_post + is signal-reentrant and may be called within signal handlers. + .Sh RETURN VALUES + .Rv -std sem_post + .Sh ERRORS + .Fn sem_post + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + .Fa sem + points to an invalid semaphore. + .El + .Sh SEE ALSO + .Xr sem_trywait 3 , + .Xr sem_wait 3 + .Sh STANDARDS + .Fn sem_post + conforms to + .St -p1003.1-96 . Index: lib/libpthread/man/sem_wait.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/sem_wait.3 Sun Sep 15 21:38:34 2002 *************** *** 0 **** --- 1,86 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/sem_wait.3,v 1.8 2001/10/01 16:09:09 ru Exp $ + .Dd February 15, 2000 + .Dt SEM_WAIT 3 + .Os + .Sh NAME + .Nm sem_wait , + .Nm sem_trywait + .Nd decrement (lock) a semaphore + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In semaphore.h + .Ft int + .Fn sem_wait "sem_t *sem" + .Ft int + .Fn sem_trywait "sem_t *sem" + .Sh DESCRIPTION + The + .Fn sem_wait + function decrements (locks) the semaphore pointed to by + .Fa sem , + but blocks if the value of + .Fa sem + is zero, until the value is non-zero and the value can be decremented. + .Pp + The + .Fn sem_trywait + function decrements (locks) the semaphore pointed to by + .Fa sem + only if the value is non-zero. Otherwise, the semaphore is not decremented and + an error is returned. + .Sh RETURN VALUES + .Rv -std + .Sh ERRORS + .Fn sem_wait + and + .Fn sem_trywait + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + .Fa sem + points to an invalid semaphore. + .El + .Pp + Additionally, + .Fn sem_trywait + will fail if: + .Bl -tag -width Er + .It Bq Er EAGAIN + The semaphore value was zero, and thus could not be decremented. + .El + .Sh SEE ALSO + .Xr sem_post 3 + .Sh STANDARDS + .Fn sem_wait + and + .Fn sem_trywait + conform to + .St -p1003.1-96 . Index: lib/libpthread/man/sigwait.3 =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/man/sigwait.3 Sun Sep 15 21:38:34 2002 *************** *** 0 **** --- 1,84 ---- + .\" Copyright (C) 2000 Jason Evans . + .\" 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(s), this list of conditions and the following disclaimer as + .\" the first lines of this file unmodified other than the possible + .\" addition of one or more copyright notices. + .\" 2. Redistributions in binary form must reproduce the above copyright + .\" notice(s), this list of conditions and the following disclaimer in + .\" the documentation and/or other materials provided with the + .\" distribution. + .\" + .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + .\" + .\" $FreeBSD: src/lib/libc_r/man/sigwait.3,v 1.7 2001/10/01 16:09:09 ru Exp $ + .Dd April 27, 2000 + .Dt SIGWAIT 3 + .Os + .Sh NAME + .Nm sigwait + .Nd select a set of signals + .Sh LIBRARY + .Lb pthread + .Sh SYNOPSIS + .In signal.h + .Ft int + .Fn sigwait "const sigset_t *set" "int *sig" + .Sh DESCRIPTION + The + .Fn sigwait + function selects a set of signals, specified by + .Fa set . + If none of the selected signals are pending, + .Fn sigwait + waits until one or more of the selected signals has been generated. + Then + .Fn sigwait + atomically clears one of the selected signals from the set of pending signals + for the process and sets the location pointed to by + .Fa sig + to the signal number that was cleared. + .Pp + The signals specified by + .Fa set + should be blocked at the time of the call to + .Fn sigwait . + .Sh RETURN VALUES + If successful, + .Fn sigwait + returns 0 and sets the location pointed to by + .Fa sig + to the cleared signal number. + Otherwise, an error number is returned. + .Sh ERRORS + .Fn sigwait + will fail if: + .Bl -tag -width Er + .It Bq Er EINVAL + .Fa set + specifies one or more invalid signal numbers. + .El + .Sh SEE ALSO + .Xr sigaction 2 , + .Xr sigpending 2 , + .Xr sigsuspend 2 , + .Xr pause 3 , + .Xr pthread_sigmask 3 + .Sh STANDARDS + .Fn sigwait + conforms to + .St -p1003.1-96 Index: lib/libpthread/sys/Makefile.inc =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/sys/Makefile.inc Sun Sep 15 21:38:34 2002 *************** *** 0 **** --- 1,6 ---- + # $FreeBSD: src/lib/libc_r/sys/Makefile.inc,v 1.10 1999/08/28 00:03:13 peter Exp $ + + .PATH: ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH} + + SRCS+= uthread_error.c _atomic_lock.S _thread_enter_uts.S _thread_switch.S + Index: lib/libpthread/sys/uthread_error.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/sys/uthread_error.c Sun Sep 15 21:38:34 2002 *************** *** 0 **** --- 1,51 ---- + /* + * Copyright (c) 1995 John Birrell . + * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell + * and Chris Provenzano. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc_r/sys/uthread_error.c,v 1.3 1999/08/28 00:03:14 peter Exp $ + */ + #ifdef _THREAD_SAFE + #include + #include "pthread_private.h" + extern int errno; + + int * __error() + { + int *p_errno; + if (_thread_run == _thread_initial) { + p_errno = &errno; + } else { + p_errno = &_thread_run->error; + } + return(p_errno); + } + #endif Index: lib/libpthread/test/Makefile =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/Makefile Sun Sep 15 21:38:34 2002 *************** *** 0 **** --- 1,115 ---- + # + # $FreeBSD: src/lib/libc_r/test/Makefile,v 1.9 2001/07/20 04:23:10 jasone Exp $ + # + # Automated test suite for pthread (pthreads). + # + + # File lists. + + # Tests written in C. + CTESTS := hello_d.c hello_s.c join_leak_d.c mutex_d.c sem_d.c sigsuspend_d.c \ + sigwait_d.c + + # C programs that are used internally by the tests. The build system merely + # compiles these. + BTESTS := guard_b.c hello_b.c + + # Tests written in perl. + PTESTS := guard_s.pl propagate_s.pl + + # Munge the file lists to their final executable names (strip the .c). + CTESTS := $(CTESTS:R) + BTESTS := $(BTESTS:R) + + CPPFLAGS := -D_LIBC_R_ -D_REENTRANT + CFLAGS := -Wall -pipe -g3 + LDFLAGS_A := -static + LDFLAGS_P := -pg + LDFLAGS_S := + LIBS := -lpthread + + # Flags passed to verify. "-v" or "-u" may be useful. + VFLAGS := + + all : default + + # Only use the following suffixes, in order to avoid any strange built-in rules. + .SUFFIXES : + .SUFFIXES : .c .o .d .pl + + # Clear out all paths, then set just one (default path) for the main build + # directory. + .PATH : + .PATH : . + + # Build the C programs. + .for bin in $(CTESTS) $(BTESTS) + $(bin)_a : $(bin:S/$/&.c/) + $(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/) + $(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_A) $(LIBS) + @$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_a.o \2/g\" > $(@:R:S/$/&.d/)" + + $(bin)_p : $(bin:S/$/&.c/) + $(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/) + $(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_P) $(LIBS) + @$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_p.o \2/g\" > $(@:R:S/$/&.d/)" + + $(bin)_s : $(bin:S/$/&.c/) + $(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/) + $(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_S) $(LIBS) + @$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_s.o \2/g\" > $(@:R:S/$/&.d/)" + .endfor + + # Dependency file inclusion. + .for depfile in $(CTESTS:R:S/$/&_a.d/) $(BTESTS:R:S/$/&_a.d/) \ + $(CTESTS:R:S/$/&_p.d/) $(BTESTS:R:S/$/&_p.d/) \ + $(CTESTS:R:S/$/&_s.d/) $(BTESTS:R:S/$/&_s.d/) + .if exists($(depfile)) + .include "$(depfile)" + .endif + .endfor + + default : check + + tests_a : $(CTESTS:S/$/&_a/) $(BTESTS:S/$/&_a/) + tests_p : $(CTESTS:S/$/&_p/) $(BTESTS:S/$/&_p/) + tests_s : $(CTESTS:S/$/&_s/) $(BTESTS:S/$/&_s/) + + tests : tests_a tests_p tests_s + + check_a : tests_a + .for bin in $(CTESTS) $(BTESTS) + @cp $(bin)_a $(bin) + .endfor + @echo "Test static library:" + @./verify $(VFLAGS) $(CTESTS) $(PTESTS) + + check_p : tests_p + .for bin in $(CTESTS) $(BTESTS) + @cp $(bin)_p $(bin) + .endfor + @echo "Test profile library:" + @./verify $(VFLAGS) $(CTESTS) $(PTESTS) + + check_s : tests_s + .for bin in $(CTESTS) $(BTESTS) + @cp $(bin)_s $(bin) + .endfor + @echo "Test shared library:" + @./verify $(VFLAGS) $(CTESTS) $(PTESTS) + + check : check_a check_p check_s + + clean : + rm -f *~ + rm -f *.core + rm -f *.out + rm -f *.perf + rm -f *.diff + rm -f *.gmon + rm -f $(CTESTS) $(BTESTS) + rm -f $(CTESTS:S/$/&_a/) $(BTESTS:S/$/&_a/) + rm -f $(CTESTS:S/$/&_p/) $(BTESTS:S/$/&_p/) + rm -f $(CTESTS:S/$/&_s/) $(BTESTS:S/$/&_s/) + rm -f *.d + rm -f *.o Index: lib/libpthread/test/README =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/README Sun Sep 15 21:38:36 2002 *************** *** 0 **** --- 1,28 ---- + $FreeBSD: src/lib/libc_r/test/README,v 1.1 2000/04/24 21:07:36 jasone Exp $ + + This test suite is meant to test general functionality of pthreads, as well as + provide a simple framework for regression tests. In general, this test suite + can be used with any pthreads library, but in reality there are a number of + libpthread-specific aspects to this test suite which would require some effort + to get around if testing another pthreads library. + + This test suite assumes that pthread is installed. + + There are two forms of test that the 'verify' script understands. The simpler + form is the diff format, where the output of the test program is diff'ed with + the correspondingly named .exp file. If there is diff output, the test fails. + The sequence test format is somewhat more complex, and is documented in the + command line usage output for verify. The advantage of this format is that it + allows multiple tests to pass/fail within one program. + + There is no driving need for test naming consistency, but the existing tests + generally follow these conventions: + + _d.c _d.exp : Diff mode C test and expected output file. + _s.c : Sequence mode C test. + _b*.c : Back end C program used by perl tests. + _d.pl _d.pl.exp : Diff mode perl test and expected output file. + _s.pl : Sequence mode perl test. + + is something descriptive, such as "pr14685" in the case of a PR-related + regression test, or "mutex" in the case of a test of mutexes. Index: lib/libpthread/test/guard_b.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/guard_b.c Sun Sep 15 21:38:36 2002 *************** *** 0 **** --- 1,150 ---- + /* + * Copyright (C) 2001 Jason Evans . + * 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(s), this list of conditions and the following disclaimer + * unmodified other than the allowable addition of one or more + * copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/test/guard_b.c,v 1.2 2002/04/22 13:44:24 des Exp $ + * + * Test thread stack guard functionality. + */ + + #include + #include + #include + #include + #include + #include + + #define FRAME_SIZE 1024 + #define FRAME_OVERHEAD 40 + + struct args + { + void *top; /* Top of thread's initial stack frame. */ + int cur; /* Recursion depth. */ + int max; /* Maximum recursion depth. */ + }; + + void * + recurse(void *args) + { + int top; + struct args *parms = (struct args *)args; + char filler[FRAME_SIZE - FRAME_OVERHEAD]; + + /* Touch the memory in this stack frame. */ + top = 0xa5; + memset(filler, 0xa5, sizeof(filler)); + + if (parms->top == NULL) { + /* Initial stack frame. */ + parms->top = (void*)⊤ + } + + /* + * Make sure frame size is what we expect. Getting this right involves + * hand tweaking, so just print a warning rather than aborting. + */ + if (parms->top - (void *)&top != FRAME_SIZE * parms->cur) { + fprintf(stderr, "Stack size (%d) != expected (%d), frame %d\n", + parms->top - (void *)&top, FRAME_SIZE * parms->cur, + parms->cur); + } + + parms->cur++; + if (parms->cur < parms->max) + recurse(args); + + return NULL; + } + + + int + main(int argc, char **argv) + { + size_t def_stacksize, def_guardsize; + size_t stacksize, guardsize; + pthread_t thread; + pthread_attr_t attr; + struct args args; + + if (argc != 3) { + fprintf(stderr, "usage: guard_b \n"); + exit(1); + } + fprintf(stderr, "Test begin\n"); + + stacksize = strtoul(argv[1], NULL, 10); + guardsize = strtoul(argv[2], NULL, 10); + + assert(pthread_attr_init(&attr) == 0); + /* + * Exercise the attribute APIs more thoroughly than is strictly + * necessary for the meat of this test program. + */ + assert(pthread_attr_getstacksize(&attr, &def_stacksize) == 0); + assert(pthread_attr_getguardsize(&attr, &def_guardsize) == 0); + if (def_stacksize != stacksize) { + assert(pthread_attr_setstacksize(&attr, stacksize) == 0); + assert(pthread_attr_getstacksize(&attr, &def_stacksize) == 0); + assert(def_stacksize == stacksize); + } + if (def_guardsize != guardsize) { + assert(pthread_attr_setguardsize(&attr, guardsize) == 0); + assert(pthread_attr_getguardsize(&attr, &def_guardsize) == 0); + assert(def_guardsize >= guardsize); + } + + /* + * Create a thread that will come just short of overflowing the thread + * stack. We need to leave a bit of breathing room in case the thread + * is context switched, and we also have to take care not to call any + * functions in the deepest stack frame. + */ + args.top = NULL; + args.cur = 0; + args.max = (stacksize / FRAME_SIZE) - 1; + fprintf(stderr, "No overflow:\n"); + assert(pthread_create(&thread, &attr, recurse, &args) == 0); + assert(pthread_join(thread, NULL) == 0); + + /* + * Create a thread that will barely of overflow the thread stack. This + * should cause a segfault. + */ + args.top = NULL; + args.cur = 0; + args.max = (stacksize / FRAME_SIZE) + 1; + fprintf(stderr, "Overflow:\n"); + assert(pthread_create(&thread, &attr, recurse, &args) == 0); + assert(pthread_join(thread, NULL) == 0); + + /* Not reached. */ + fprintf(stderr, "Unexpected success\n"); + abort(); + + return 0; + } Index: lib/libpthread/test/guard_b.exp =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/guard_b.exp Sun Sep 15 21:38:37 2002 *************** *** 0 **** --- 1,3 ---- + Test begin + No overflow: + Overflow: Index: lib/libpthread/test/guard_s.pl =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/guard_s.pl Sun Sep 15 21:38:37 2002 *************** *** 0 **** --- 1,69 ---- + #!/usr/bin/perl -w + # + # Copyright (C) 2001 Jason Evans . + # 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(s), this list of conditions and the following disclaimer + # unmodified other than the allowable addition of one or more + # copyright notices. + # 2. Redistributions in binary form must reproduce the above copyright + # notice(s), this list of conditions and the following disclaimer in + # the documentation and/or other materials provided with the + # distribution. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + # + # $FreeBSD: src/lib/libc_r/test/guard_s.pl,v 1.1 2001/07/20 04:23:10 jasone Exp $ + # + # Test thread stack guard functionality. The C test program needs to be driven + # by this script because it segfaults when the stack guard is hit. + # + + print "1..30\n"; + + $i = 0; + # Iterates 10 times. + for ($stacksize = 65536; $stacksize < 131072; $stacksize += 7168) + { + # Iterates 3 times (1024, 4096, 7168). + for ($guardsize = 1024; $guardsize < 8192; $guardsize += 3072) + { + $i++; + + print "stacksize: $stacksize, guardsize: $guardsize\n"; + + `./guard_b $stacksize $guardsize >guard_b.out 2>&1`; + + if (! -f "./guard_b.out") + { + print "not ok $i\n"; + } + else + { + `diff guard_b.exp guard_b.out >guard_b.diff 2>&1`; + if ($?) + { + # diff returns non-zero if there is a difference. + print "not ok $i\n"; + } + else + { + print "ok $i\n"; + } + } + } + } Index: lib/libpthread/test/hello_b.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/hello_b.c Sun Sep 15 21:38:37 2002 *************** *** 0 **** --- 1,13 ---- + /**************************************************************************** + * + * Back end C programs can be anything compilable. + * + * $FreeBSD: src/lib/libc_r/test/hello_b.c,v 1.1 2000/04/24 21:07:37 jasone Exp $ + * + ****************************************************************************/ + + int + main() + { + return 0; + } Index: lib/libpthread/test/hello_d.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/hello_d.c Sun Sep 15 21:38:37 2002 *************** *** 0 **** --- 1,38 ---- + /**************************************************************************** + * + * Simple diff mode test. + * + * $FreeBSD: src/lib/libc_r/test/hello_d.c,v 1.1 2000/04/24 21:07:37 jasone Exp $ + * + ****************************************************************************/ + + #include + #include + #include + + void * + entry(void * a_arg) + { + fprintf(stderr, "Hello world\n"); + + return NULL; + } + + int + main() + { + pthread_t thread; + int error; + + error = pthread_create(&thread, NULL, entry, NULL); + if (error) + fprintf(stderr, "Error in pthread_create(): %s\n", + strerror(error)); + + error = pthread_join(thread, NULL); + if (error) + fprintf(stderr, "Error in pthread_join(): %s\n", + strerror(error)); + + return 0; + } Index: lib/libpthread/test/hello_d.exp =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/hello_d.exp Sun Sep 15 21:38:37 2002 *************** *** 0 **** --- 1 ---- + Hello world Index: lib/libpthread/test/hello_s.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/hello_s.c Sun Sep 15 21:38:38 2002 *************** *** 0 **** --- 1,47 ---- + /**************************************************************************** + * + * Simple sequence mode test. + * + * $FreeBSD: src/lib/libc_r/test/hello_s.c,v 1.1 2000/04/24 21:07:37 jasone Exp $ + * + ****************************************************************************/ + + #include + #include + #include + + void * + entry(void * a_arg) + { + fprintf(stderr, "ok 1\n"); + fprintf(stderr, "ok \n"); + fprintf(stderr, "ok 3\n"); + + return NULL; + } + + int + main() + { + pthread_t thread; + int error; + + fprintf(stderr, "1..3\n"); + + fprintf(stderr, "Some random text\n"); + + error = pthread_create(&thread, NULL, entry, NULL); + fprintf(stderr, "More unimportant text\n"); + if (error) + fprintf(stderr,"Error in pthread_create(): %s\n", + strerror(error)); + + error = pthread_join(thread, NULL); + if (error) + fprintf(stderr, "Error in pthread_join(): %s\n", + strerror(error)); + + fprintf(stderr, "Hello world\n"); + + return 0; + } Index: lib/libpthread/test/join_leak_d.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/join_leak_d.c Sun Sep 15 21:38:38 2002 *************** *** 0 **** --- 1,108 ---- + /* + * Copyright (C) 2001 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/test/join_leak_d.c,v 1.1 2001/05/20 23:12:13 jasone Exp $ + * + * Test for leaked joined threads. + */ + + #include + #include + #include + + #include + #include + #include + + #define NITERATIONS 16384 + #define MAXGROWTH 16384 + + void * + thread_entry(void *a_arg) + { + return NULL; + } + + int + main(void) + { + pthread_t thread; + int i, error; + char *brk, *nbrk; + unsigned growth; + + fprintf(stderr, "Test begin\n"); + + /* Get an initial brk value. */ + brk = sbrk(0); + + /* Create threads and join them, one at a time. */ + for (i = 0; i < NITERATIONS; i++) { + if ((error = pthread_create(&thread, NULL, thread_entry, NULL)) + != 0) { + fprintf(stderr, "Error in pthread_create(): %s\n", + strerror(error)); + exit(1); + } + if ((error = pthread_join(thread, NULL)) != 0) { + fprintf(stderr, "Error in pthread_join(): %s\n", + strerror(error)); + exit(1); + } + } + + /* Get a final brk value. */ + nbrk = sbrk(0); + + /* + * Check that the amount of heap space allocated is below an acceptable + * threshold. We could just compare brk and nbrk, but the test could + * conceivably break if the internals of the threads library changes. + */ + if (nbrk > brk) { + /* Heap grows up. */ + growth = nbrk - brk; + } else if (nbrk <= brk) { + /* Heap grows down, or no growth. */ + growth = brk - nbrk; + } + + if (growth > MAXGROWTH) { + fprintf(stderr, "Heap growth exceeded maximum (%u > %u)\n", + growth, MAXGROWTH); + } + #if (0) + else { + fprintf(stderr, "Heap growth acceptable (%u <= %u)\n", + growth, MAXGROWTH); + } + #endif + + fprintf(stderr, "Test end\n"); + return 0; + } Index: lib/libpthread/test/join_leak_d.exp =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/join_leak_d.exp Sun Sep 15 21:38:38 2002 *************** *** 0 **** --- 1,2 ---- + Test begin + Test end Index: lib/libpthread/test/mutex_d.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/mutex_d.c Sun Sep 15 21:38:38 2002 *************** *** 0 **** --- 1,1554 ---- + /* + * Copyright (c) 1998 Daniel M. Eischen + * 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 Daniel M. Eischen. + * 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 DANIEL M. EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/test/mutex_d.c,v 1.3 2002/07/02 01:26:16 deischen Exp $ + */ + #include + #include + + #include + #include + #include + #include "pthread.h" + #include + #include + #include + #include + #include + #include + + #if defined(_LIBC_R_) + #include + #endif + + #ifndef NELEMENTS + #define NELEMENTS(arr) (sizeof (arr) / sizeof (arr[0])) + #endif + + #ifndef NUM_THREADS + #define NUM_THREADS 10 + #endif + + #define MAX_THREAD_CMDS 10 + + static void log_error(const char *, ...) __printflike(1, 2); + static void log_trace (const char *, ...) __printflike(1, 2); + static void log (const char *, ...) __printflike(1, 2); + + /*------------------------------------------------------------ + * Types + *----------------------------------------------------------*/ + + typedef enum { + STAT_INITIAL, /* initial state */ + STAT_WAITCONDVAR, /* waiting for condition variable signal */ + STAT_WAITMUTEX /* waiting for mutex lock */ + } thread_status_t; + + typedef enum { + FLAGS_REPORT_WAITCONDMUTEX = 0x01, + FLAGS_REPORT_WAITCONDVAR = 0x02, + FLAGS_REPORT_WAITMUTEX = 0x04, + FLAGS_REPORT_BUSY_LOOP = 0x08, + FLAGS_IS_BUSY = 0x10, + FLAGS_WAS_BUSY = 0x20 + } thread_flags_t; + + typedef enum { + CMD_NONE, + CMD_TAKE_MUTEX, + CMD_RELEASE_MUTEX, + CMD_WAIT_FOR_SIGNAL, + CMD_BUSY_LOOP, + CMD_PROTECTED_OP, + CMD_RELEASE_ALL + } thread_cmd_id_t; + + typedef struct { + thread_cmd_id_t cmd_id; + pthread_mutex_t *mutex; + pthread_cond_t *cond; + } thread_cmd_t; + + typedef struct { + pthread_cond_t cond_var; + thread_status_t status; + thread_cmd_t cmd; + int flags; + int priority; + int ret; + pthread_t tid; + u_int8_t id; + } thread_state_t; + + typedef enum { + M_POSIX, + M_SS2_DEFAULT, + M_SS2_ERRORCHECK, + M_SS2_NORMAL, + M_SS2_RECURSIVE + } mutex_kind_t; + + + /*------------------------------------------------------------ + * Constants + *----------------------------------------------------------*/ + + const char *protocol_strs[] = { + "PTHREAD_PRIO_NONE", + "PTHREAD_PRIO_INHERIT", + "PTHREAD_PRIO_PROTECT" + }; + + const int protocols[] = { + PTHREAD_PRIO_NONE, + PTHREAD_PRIO_INHERIT, + PTHREAD_PRIO_PROTECT + }; + + const char *mutextype_strs[] = { + "POSIX (type not specified)", + "SS2 PTHREAD_MUTEX_DEFAULT", + "SS2 PTHREAD_MUTEX_ERRORCHECK", + "SS2 PTHREAD_MUTEX_NORMAL", + "SS2 PTHREAD_MUTEX_RECURSIVE" + }; + + const int mutex_types[] = { + 0, /* M_POSIX */ + PTHREAD_MUTEX_DEFAULT, /* M_SS2_DEFAULT */ + PTHREAD_MUTEX_ERRORCHECK, /* M_SS2_ERRORCHECK */ + PTHREAD_MUTEX_NORMAL, /* M_SS2_NORMAL */ + PTHREAD_MUTEX_RECURSIVE /* M_SS2_RECURSIVE */ + }; + + + /*------------------------------------------------------------ + * Objects + *----------------------------------------------------------*/ + + static int done = 0; + static int trace_enabled = 0; + static int use_global_condvar = 0; + static thread_state_t states[NUM_THREADS]; + static int pipefd[2]; + + static pthread_mutex_t waiter_mutex; + static pthread_mutex_t cond_mutex; + static pthread_cond_t cond_var; + + static FILE *logfile; + static int error_count = 0, pass_count = 0, total = 0; + + + /*------------------------------------------------------------ + * Prototypes + *----------------------------------------------------------*/ + extern char *strtok_r(char *str, const char *sep, char **last); + + + /*------------------------------------------------------------ + * Functions + *----------------------------------------------------------*/ + + #ifdef DEBUG + static void + kern_switch (pthread_t pthread_out, pthread_t pthread_in) + { + if (pthread_out != NULL) + printf ("Swapping out thread 0x%x, ", (int) pthread_out); + else + printf ("Swapping out kernel thread, "); + + if (pthread_in != NULL) + printf ("swapping in thread 0x%x\n", (int) pthread_in); + else + printf ("swapping in kernel thread.\n"); + } + #endif + + + static void + log_error (const char *fmt, ...) + { + va_list ap; + + va_start (ap, fmt); + fprintf (logfile, "FAIL: "); + vfprintf (logfile, fmt, ap); + error_count = error_count + 1; + total = total + 1; + } + + + static void + log_pass (void) + { + fprintf (logfile, "PASS\n"); + pass_count = pass_count + 1; + total = total + 1; + } + + + static void + log_trace (const char *fmt, ...) + { + va_list ap; + + if (trace_enabled) { + va_start (ap, fmt); + vfprintf (logfile, fmt, ap); + } + } + + + static void + log (const char *fmt, ...) + { + va_list ap; + + va_start (ap, fmt); + vfprintf (logfile, fmt, ap); + } + + + static void + check_result (int expected, int actual) + { + if (expected != actual) + log_error ("expected %d, returned %d\n", expected, actual); + else + log_pass (); + } + + + /* + * Check to see that the threads ran in the specified order. + */ + static void + check_run_order (char *order) + { + const char *sep = ":,"; + char *tok, *last, *idstr, *endptr; + int expected_id, bytes, count = 0, errors = 0; + u_int8_t id; + + assert ((tok = (char *) malloc (strlen(order) + 1)) != NULL); + strcpy (tok, order); /* tok has to be larger than order */ + assert (ioctl (pipefd[0], FIONREAD, &bytes) == 0); + log_trace ("%d bytes read from FIFO.\n", bytes); + + for (idstr = strtok_r (tok, sep, &last); + (idstr != NULL) && (count < bytes); + idstr = strtok_r (NULL, sep, &last)) { + + /* Get the expected id: */ + expected_id = (int) strtol (idstr, &endptr, 10); + assert ((endptr != NULL) && (*endptr == '\0')); + + /* Read the actual id from the pipe: */ + assert (read (pipefd[0], &id, sizeof (id)) == sizeof (id)); + count = count + sizeof (id); + + if (id != expected_id) { + log_trace ("Thread %d ran out of order.\n", id); + errors = errors + 1; + } + else { + log_trace ("Thread %d at priority %d reporting.\n", + (int) id, states[id].priority); + } + } + + if (count < bytes) { + /* Clear the pipe: */ + while (count < bytes) { + read (pipefd[0], &id, sizeof (id)); + count = count + 1; + errors = errors + 1; + } + } + else if (bytes < count) + errors = errors + count - bytes; + + if (errors == 0) + log_pass (); + else + log_error ("%d threads ran out of order", errors); + } + + + static void * + waiter (void *arg) + { + thread_state_t *statep = (thread_state_t *) arg; + pthread_mutex_t *held_mutex[MAX_THREAD_CMDS]; + int held_mutex_owned[MAX_THREAD_CMDS]; + sigset_t mask; + struct timeval tv1, tv2; + thread_cmd_t cmd; + int i, mutex_count = 0; + + statep->status = STAT_INITIAL; + + /* Block all signals except for interrupt.*/ + sigfillset (&mask); + sigdelset (&mask, SIGINT); + sigprocmask (SIG_BLOCK, &mask, NULL); + + while (done == 0) { + /* Wait for signal from the main thread to continue. */ + statep->status = STAT_WAITMUTEX; + log_trace ("Thread %d: locking cond_mutex.\n", + (int) statep->id); + pthread_mutex_lock (&cond_mutex); + + /* Do we report our status. */ + if (statep->flags & FLAGS_REPORT_WAITCONDMUTEX) + write (pipefd[1], &statep->id, sizeof (statep->id)); + log_trace ("Thread %d: waiting for cond_var.\n", + (int) statep->id); + + /* Wait for a command. */ + statep->status = STAT_WAITCONDVAR; + + /* + * The threads are allowed commanded to wait either on + * their own unique condition variable (so they may be + * separately signaled) or on one global condition variable + * (so they may be signaled together). + */ + if (use_global_condvar != 0) + pthread_cond_wait (&cond_var, &cond_mutex); + else + pthread_cond_wait (&statep->cond_var, &cond_mutex); + + /* Do we report our status? */ + if (statep->flags & FLAGS_REPORT_WAITCONDVAR) { + write (pipefd[1], &statep->id, sizeof (statep->id)); + log_trace ("Thread %d: wrote to pipe.\n", + (int) statep->id); + } + log_trace ("Thread %d: received cond_var signal.\n", + (int) statep->id); + + /* Get a copy of the command before releasing the mutex. */ + cmd = statep->cmd; + + /* Clear the command after copying it. */ + statep->cmd.cmd_id = CMD_NONE; + + /* Unlock the condition variable mutex. */ + assert (pthread_mutex_unlock (&cond_mutex) == 0); + + /* Peform the command.*/ + switch (cmd.cmd_id) { + case CMD_TAKE_MUTEX: + statep->ret = pthread_mutex_lock (cmd.mutex); + if (statep->ret == 0) { + assert (mutex_count < sizeof (held_mutex)); + held_mutex[mutex_count] = cmd.mutex; + held_mutex_owned[mutex_count] = 1; + mutex_count++; + } + else { + held_mutex_owned[mutex_count] = 0; + log_trace ("Thread id %d unable to lock mutex, " + "error = %d\n", (int) statep->id, + statep->ret); + } + break; + + case CMD_RELEASE_MUTEX: + assert ((mutex_count <= sizeof (held_mutex)) && + (mutex_count > 0)); + mutex_count--; + if (held_mutex_owned[mutex_count] != 0) + assert (pthread_mutex_unlock + (held_mutex[mutex_count]) == 0); + break; + + case CMD_WAIT_FOR_SIGNAL: + assert (pthread_mutex_lock (cmd.mutex) == 0); + assert (pthread_cond_wait (cmd.cond, cmd.mutex) == 0); + assert (pthread_mutex_unlock (cmd.mutex) == 0); + break; + + case CMD_BUSY_LOOP: + log_trace ("Thread %d: Entering busy loop.\n", + (int) statep->id); + /* Spin for 15 seconds. */ + assert (gettimeofday (&tv2, NULL) == 0); + tv1.tv_sec = tv2.tv_sec + 5; + tv1.tv_usec = tv2.tv_usec; + statep->flags |= FLAGS_IS_BUSY; + while (timercmp (&tv2, &tv1,<)) { + assert (gettimeofday (&tv2, NULL) == 0); + } + statep->flags &= ~FLAGS_IS_BUSY; + statep->flags |= FLAGS_WAS_BUSY; + + /* Do we report our status? */ + if (statep->flags & FLAGS_REPORT_BUSY_LOOP) + write (pipefd[1], &statep->id, + sizeof (statep->id)); + + log_trace ("Thread %d: Leaving busy loop.\n", + (int) statep->id); + break; + + case CMD_PROTECTED_OP: + assert (pthread_mutex_lock (cmd.mutex) == 0); + statep->flags |= FLAGS_WAS_BUSY; + /* Do we report our status? */ + if (statep->flags & FLAGS_REPORT_BUSY_LOOP) + write (pipefd[1], &statep->id, + sizeof (statep->id)); + + assert (pthread_mutex_unlock (cmd.mutex) == 0); + break; + + case CMD_RELEASE_ALL: + assert ((mutex_count <= sizeof (held_mutex)) && + (mutex_count > 0)); + for (i = mutex_count - 1; i >= 0; i--) { + if (held_mutex_owned[i] != 0) + assert (pthread_mutex_unlock + (held_mutex[i]) == 0); + } + mutex_count = 0; + break; + + case CMD_NONE: + default: + break; + } + + /* Wait for the big giant waiter lock. */ + statep->status = STAT_WAITMUTEX; + log_trace ("Thread %d: waiting for big giant lock.\n", + (int) statep->id); + pthread_mutex_lock (&waiter_mutex); + if (statep->flags & FLAGS_REPORT_WAITMUTEX) + write (pipefd[1], &statep->id, sizeof (statep->id)); + log_trace ("Thread %d: got big giant lock.\n", + (int) statep->id); + statep->status = STAT_INITIAL; + pthread_mutex_unlock (&waiter_mutex); + } + + log_trace ("Thread %d: Exiting thread 0x%x\n", (int) statep->id, + (int) pthread_self()); + pthread_exit (arg); + return (NULL); + } + + + static void * + lock_twice (void *arg) + { + thread_state_t *statep = (thread_state_t *) arg; + sigset_t mask; + + statep->status = STAT_INITIAL; + + /* Block all signals except for interrupt.*/ + sigfillset (&mask); + sigdelset (&mask, SIGINT); + sigprocmask (SIG_BLOCK, &mask, NULL); + + /* Wait for a signal to continue. */ + log_trace ("Thread %d: locking cond_mutex.\n", (int) statep->id); + pthread_mutex_lock (&cond_mutex); + + log_trace ("Thread %d: waiting for cond_var.\n", (int) statep->id); + statep->status = STAT_WAITCONDVAR; + pthread_cond_wait (&cond_var, &cond_mutex); + + log_trace ("Thread %d: received cond_var signal.\n", (int) statep->id); + + /* Unlock the condition variable mutex. */ + assert (pthread_mutex_unlock (&cond_mutex) == 0); + + statep->status = STAT_WAITMUTEX; + /* Lock the mutex once. */ + assert (pthread_mutex_lock (statep->cmd.mutex) == 0); + + /* Lock it again and capture the error. */ + statep->ret = pthread_mutex_lock (statep->cmd.mutex); + statep->status = 0; + + assert (pthread_mutex_unlock (statep->cmd.mutex) == 0); + + /* Unlock it again if it is locked recursively. */ + if (statep->ret == 0) + pthread_mutex_unlock (statep->cmd.mutex); + + log_trace ("Thread %d: Exiting thread 0x%x\n", (int) statep->id, + (int) pthread_self()); + pthread_exit (arg); + return (NULL); + } + + + static void + sighandler (int signo) + { + log ("Signal handler caught signal %d, thread id 0x%x\n", + signo, (int) pthread_self()); + + if (signo == SIGINT) + done = 1; + } + + + static void + send_cmd (int id, thread_cmd_id_t cmd) + { + assert (pthread_mutex_lock (&cond_mutex) == 0); + assert (states[id].status == STAT_WAITCONDVAR); + states[id].cmd.cmd_id = cmd; + states[id].cmd.mutex = NULL; + states[id].cmd.cond = NULL; + /* Clear the busy flags. */ + states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); + assert (pthread_cond_signal (&states[id].cond_var) == 0); + assert (pthread_mutex_unlock (&cond_mutex) == 0); + } + + + static void + send_mutex_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m) + { + assert (pthread_mutex_lock (&cond_mutex) == 0); + assert (states[id].status == STAT_WAITCONDVAR); + states[id].cmd.cmd_id = cmd; + states[id].cmd.mutex = m; + states[id].cmd.cond = NULL; + /* Clear the busy flags. */ + states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); + assert (pthread_cond_signal (&states[id].cond_var) == 0); + assert (pthread_mutex_unlock (&cond_mutex) == 0); + } + + + static void + send_mutex_cv_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m, + pthread_cond_t *cv) + { + assert (pthread_mutex_lock (&cond_mutex) == 0); + assert (states[id].status == STAT_WAITCONDVAR); + states[id].cmd.cmd_id = cmd; + states[id].cmd.mutex = m; + states[id].cmd.cond = cv; + /* Clear the busy flags. */ + states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); + assert (pthread_cond_signal (&states[id].cond_var) == 0); + assert (pthread_mutex_unlock (&cond_mutex) == 0); + } + + + static void + mutex_init_test (void) + { + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + mutex_kind_t mkind; + int mproto, ret; + + /* + * Initialize a mutex attribute. + * + * pthread_mutexattr_init not tested for: ENOMEM + */ + assert (pthread_mutexattr_init (&mattr) == 0); + + /* + * Initialize a mutex. + * + * pthread_mutex_init not tested for: EAGAIN ENOMEM EPERM EBUSY + */ + log ("Testing pthread_mutex_init\n"); + log ("--------------------------\n"); + + for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { + for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { + /* Initialize the mutex attribute. */ + assert (pthread_mutexattr_init (&mattr) == 0); + assert (pthread_mutexattr_setprotocol (&mattr, + protocols[mproto]) == 0); + + /* + * Ensure that the first mutex type is a POSIX + * compliant mutex. + */ + if (mkind != M_POSIX) { + assert (pthread_mutexattr_settype (&mattr, + mutex_types[mkind]) == 0); + } + + log (" Protocol %s, Type %s - ", + protocol_strs[mproto], mutextype_strs[mkind]); + ret = pthread_mutex_init (&mutex, &mattr); + check_result (/* expected */ 0, ret); + assert (pthread_mutex_destroy (&mutex) == 0); + + /* + * Destroy a mutex attribute. + * + * XXX - There should probably be a magic number + * associated with a mutex attribute so that + * destroy can be reasonably sure the attribute + * is valid. + * + * pthread_mutexattr_destroy not tested for: EINVAL + */ + assert (pthread_mutexattr_destroy (&mattr) == 0); + } + } + } + + + static void + mutex_destroy_test (void) + { + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + pthread_condattr_t cattr; + pthread_cond_t cv; + pthread_attr_t pattr; + int mproto, ret; + mutex_kind_t mkind; + thread_state_t state; + + /* + * Destroy a mutex. + * + * XXX - There should probably be a magic number associated + * with a mutex so that destroy can be reasonably sure + * the mutex is valid. + * + * pthread_mutex_destroy not tested for: + */ + log ("Testing pthread_mutex_destroy\n"); + log ("-----------------------------\n"); + + assert (pthread_attr_init (&pattr) == 0); + assert (pthread_attr_setdetachstate (&pattr, + PTHREAD_CREATE_DETACHED) == 0); + state.flags = 0; /* No flags yet. */ + + for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { + for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { + /* Initialize the mutex attribute. */ + assert (pthread_mutexattr_init (&mattr) == 0); + assert (pthread_mutexattr_setprotocol (&mattr, + protocols[mproto]) == 0); + + /* + * Ensure that the first mutex type is a POSIX + * compliant mutex. + */ + if (mkind != M_POSIX) { + assert (pthread_mutexattr_settype (&mattr, + mutex_types[mkind]) == 0); + } + + /* Create the mutex. */ + assert (pthread_mutex_init (&mutex, &mattr) == 0); + + log (" Protocol %s, Type %s\n", + protocol_strs[mproto], mutextype_strs[mkind]); + + log (" Destruction of unused mutex - "); + assert (pthread_mutex_init (&mutex, &mattr) == 0); + ret = pthread_mutex_destroy (&mutex); + check_result (/* expected */ 0, ret); + + log (" Destruction of mutex locked by self - "); + assert (pthread_mutex_init (&mutex, &mattr) == 0); + assert (pthread_mutex_lock (&mutex) == 0); + ret = pthread_mutex_destroy (&mutex); + check_result (/* expected */ EBUSY, ret); + assert (pthread_mutex_unlock (&mutex) == 0); + assert (pthread_mutex_destroy (&mutex) == 0); + + log (" Destruction of mutex locked by another " + "thread - "); + assert (pthread_mutex_init (&mutex, &mattr) == 0); + send_mutex_cmd (0, CMD_TAKE_MUTEX, &mutex); + sleep (1); + ret = pthread_mutex_destroy (&mutex); + check_result (/* expected */ EBUSY, ret); + send_cmd (0, CMD_RELEASE_ALL); + sleep (1); + assert (pthread_mutex_destroy (&mutex) == 0); + + log (" Destruction of mutex while being used in " + "cond_wait - "); + assert (pthread_mutex_init (&mutex, &mattr) == 0); + assert (pthread_condattr_init (&cattr) == 0); + assert (pthread_cond_init (&cv, &cattr) == 0); + send_mutex_cv_cmd (0, CMD_WAIT_FOR_SIGNAL, &mutex, &cv); + sleep (1); + ret = pthread_mutex_destroy (&mutex); + check_result (/* expected */ EBUSY, ret); + pthread_cond_signal (&cv); + sleep (1); + assert (pthread_mutex_destroy (&mutex) == 0); + } + } + } + + + static void + mutex_lock_test (void) + { + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + pthread_attr_t pattr; + int mproto, ret; + mutex_kind_t mkind; + thread_state_t state; + + /* + * Lock a mutex. + * + * pthread_lock not tested for: + */ + log ("Testing pthread_mutex_lock\n"); + log ("--------------------------\n"); + + assert (pthread_attr_init (&pattr) == 0); + assert (pthread_attr_setdetachstate (&pattr, + PTHREAD_CREATE_DETACHED) == 0); + state.flags = 0; /* No flags yet. */ + + for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { + for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { + /* Initialize the mutex attribute. */ + assert (pthread_mutexattr_init (&mattr) == 0); + assert (pthread_mutexattr_setprotocol (&mattr, + protocols[mproto]) == 0); + + /* + * Ensure that the first mutex type is a POSIX + * compliant mutex. + */ + if (mkind != M_POSIX) { + assert (pthread_mutexattr_settype (&mattr, + mutex_types[mkind]) == 0); + } + + /* Create the mutex. */ + assert (pthread_mutex_init (&mutex, &mattr) == 0); + + log (" Protocol %s, Type %s\n", + protocol_strs[mproto], mutextype_strs[mkind]); + + log (" Lock on unlocked mutex - "); + ret = pthread_mutex_lock (&mutex); + check_result (/* expected */ 0, ret); + pthread_mutex_unlock (&mutex); + + log (" Lock on invalid mutex - "); + ret = pthread_mutex_lock (NULL); + check_result (/* expected */ EINVAL, ret); + + log (" Lock on mutex held by self - "); + assert (pthread_create (&state.tid, &pattr, lock_twice, + (void *) &state) == 0); + /* Let the thread start. */ + sleep (1); + state.cmd.mutex = &mutex; + state.ret = 0xdeadbeef; + assert (pthread_mutex_lock (&cond_mutex) == 0); + assert (pthread_cond_signal (&cond_var) == 0); + assert (pthread_mutex_unlock (&cond_mutex) == 0); + /* Let the thread receive and process the command. */ + sleep (1); + + switch (mkind) { + case M_POSIX: + check_result (/* expected */ EDEADLK, + state.ret); + break; + case M_SS2_DEFAULT: + check_result (/* expected */ EDEADLK, + state.ret); + break; + case M_SS2_ERRORCHECK: + check_result (/* expected */ EDEADLK, + state.ret); + break; + case M_SS2_NORMAL: + check_result (/* expected */ 0xdeadbeef, + state.ret); + break; + case M_SS2_RECURSIVE: + check_result (/* expected */ 0, state.ret); + break; + } + pthread_mutex_destroy (&mutex); + pthread_mutexattr_destroy (&mattr); + } + } + } + + + static void + mutex_unlock_test (void) + { + const int test_thread_id = 0; /* ID of test thread */ + pthread_mutexattr_t mattr; + pthread_mutex_t mutex; + int mproto, ret; + mutex_kind_t mkind; + + /* + * Unlock a mutex. + * + * pthread_unlock not tested for: + */ + log ("Testing pthread_mutex_unlock\n"); + log ("----------------------------\n"); + + for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { + for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { + /* Initialize the mutex attribute. */ + assert (pthread_mutexattr_init (&mattr) == 0); + assert (pthread_mutexattr_setprotocol (&mattr, + protocols[mproto]) == 0); + + /* + * Ensure that the first mutex type is a POSIX + * compliant mutex. + */ + if (mkind != M_POSIX) { + assert (pthread_mutexattr_settype (&mattr, + mutex_types[mkind]) == 0); + } + + /* Create the mutex. */ + assert (pthread_mutex_init (&mutex, &mattr) == 0); + + log (" Protocol %s, Type %s\n", + protocol_strs[mproto], mutextype_strs[mkind]); + + log (" Unlock on mutex held by self - "); + assert (pthread_mutex_lock (&mutex) == 0); + ret = pthread_mutex_unlock (&mutex); + check_result (/* expected */ 0, ret); + + log (" Unlock on invalid mutex - "); + ret = pthread_mutex_unlock (NULL); + check_result (/* expected */ EINVAL, ret); + + log (" Unlock on mutex locked by another thread - "); + send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &mutex); + sleep (1); + ret = pthread_mutex_unlock (&mutex); + switch (mkind) { + case M_POSIX: + check_result (/* expected */ EPERM, ret); + break; + case M_SS2_DEFAULT: + check_result (/* expected */ EPERM, ret); + break; + case M_SS2_ERRORCHECK: + check_result (/* expected */ EPERM, ret); + break; + case M_SS2_NORMAL: + check_result (/* expected */ EPERM, ret); + break; + case M_SS2_RECURSIVE: + check_result (/* expected */ EPERM, ret); + break; + } + if (ret == 0) { + /* + * If for some reason we were able to unlock + * the mutex, relock it so that the test + * thread has no problems releasing the mutex. + */ + pthread_mutex_lock (&mutex); + } + send_cmd (test_thread_id, CMD_RELEASE_ALL); + sleep (1); + + pthread_mutex_destroy (&mutex); + pthread_mutexattr_destroy (&mattr); + } + } + } + + + static void + queueing_order_test (void) + { + int i; + + log ("Testing queueing order\n"); + log ("----------------------\n"); + assert (pthread_mutex_lock (&waiter_mutex) == 0); + /* + * Tell the threads to report when they take the waiters mutex. + */ + assert (pthread_mutex_lock (&cond_mutex) == 0); + for (i = 0; i < NUM_THREADS; i++) { + states[i].flags = FLAGS_REPORT_WAITMUTEX; + assert (pthread_cond_signal (&states[i].cond_var) == 0); + } + assert (pthread_mutex_unlock (&cond_mutex) == 0); + + /* Signal the threads to continue. */ + sleep (1); + + /* Use the global condition variable next time. */ + use_global_condvar = 1; + + /* Release the waiting threads and allow them to run again. */ + assert (pthread_mutex_unlock (&waiter_mutex) == 0); + sleep (1); + + log (" Queueing order on a mutex - "); + check_run_order ("9,8,7,6,5,4,3,2,1,0"); + for (i = 0; i < NUM_THREADS; i = i + 1) { + /* Tell the threads to report when they've been signaled. */ + states[i].flags = FLAGS_REPORT_WAITCONDVAR; + } + + /* + * Prevent the threads from continuing their loop after we + * signal them. + */ + assert (pthread_mutex_lock (&waiter_mutex) == 0); + + + log (" Queueing order on a condition variable - "); + /* + * Signal one thread to run and see that the highest priority + * thread executes. + */ + assert (pthread_mutex_lock (&cond_mutex) == 0); + assert (pthread_cond_signal (&cond_var) == 0); + assert (pthread_mutex_unlock (&cond_mutex) == 0); + sleep (1); + if (states[NUM_THREADS - 1].status != STAT_WAITMUTEX) + log_error ("highest priority thread does not run.\n"); + + /* Signal the remaining threads. */ + assert (pthread_mutex_lock (&cond_mutex) == 0); + assert (pthread_cond_broadcast (&cond_var) == 0); + assert (pthread_mutex_unlock (&cond_mutex) == 0); + sleep (1); + + check_run_order ("9,8,7,6,5,4,3,2,1,0"); + for (i = 0; i < NUM_THREADS; i = i + 1) { + /* Tell the threads not to report anything. */ + states[i].flags = 0; + } + + /* Use the thread unique condition variable next time. */ + use_global_condvar = 0; + + /* Allow the threads to continue their loop. */ + assert (pthread_mutex_unlock (&waiter_mutex) == 0); + sleep (1); + } + + + static void + mutex_prioceiling_test (void) + { + const int test_thread_id = 0; /* ID of test thread */ + pthread_mutexattr_t mattr; + struct sched_param param; + pthread_mutex_t m[3]; + mutex_kind_t mkind; + int i, ret, policy, my_prio, old_ceiling; + + log ("Testing priority ceilings\n"); + log ("-------------------------\n"); + for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { + + log (" Protype PTHREAD_PRIO_PROTECT, Type %s\n", + mutextype_strs[mkind]); + + /* + * Initialize and create a mutex. + */ + assert (pthread_mutexattr_init (&mattr) == 0); + + /* Get this threads current priority. */ + assert (pthread_getschedparam (pthread_self(), &policy, + ¶m) == 0); + my_prio = param.sched_priority; /* save for later use */ + log_trace ("Current scheduling policy %d, priority %d\n", + policy, my_prio); + + /* + * Initialize and create 3 priority protection mutexes with + * default (max priority) ceilings. + */ + assert (pthread_mutexattr_setprotocol(&mattr, + PTHREAD_PRIO_PROTECT) == 0); + + /* + * Ensure that the first mutex type is a POSIX + * compliant mutex. + */ + if (mkind != M_POSIX) { + assert (pthread_mutexattr_settype (&mattr, + mutex_types[mkind]) == 0); + } + + for (i = 0; i < 3; i++) + assert (pthread_mutex_init (&m[i], &mattr) == 0); + + /* + * Set the ceiling priorities for the 3 priority protection + * mutexes to, 5 less than, equal to, and 5 greater than, + * this threads current priority. + */ + for (i = 0; i < 3; i++) + assert (pthread_mutex_setprioceiling (&m[i], + my_prio - 5 + 5*i, &old_ceiling) == 0); + + /* + * Check that if we attempt to take a mutex whose priority + * ceiling is lower than our priority, we get an error. + */ + log (" Lock with ceiling priority < thread priority - "); + ret = pthread_mutex_lock (&m[0]); + check_result (/* expected */ EINVAL, ret); + if (ret == 0) + pthread_mutex_unlock (&m[0]); + + /* + * Check that we can take a mutex whose priority ceiling + * is equal to our priority. + */ + log (" Lock with ceiling priority = thread priority - "); + ret = pthread_mutex_lock (&m[1]); + check_result (/* expected */ 0, ret); + if (ret == 0) + pthread_mutex_unlock (&m[1]); + + /* + * Check that we can take a mutex whose priority ceiling + * is higher than our priority. + */ + log (" Lock with ceiling priority > thread priority - "); + ret = pthread_mutex_lock (&m[2]); + check_result (/* expected */ 0, ret); + if (ret == 0) + pthread_mutex_unlock (&m[2]); + + /* + * Have the test thread go into a busy loop for 5 seconds + * and see that it doesn't block this thread (since the + * priority ceiling of mutex 0 and the priority of the test + * thread are both less than the priority of this thread). + */ + log (" Preemption with ceiling priority < thread " + "priority - "); + /* Have the test thread take mutex 0. */ + send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[0]); + sleep (1); + + log_trace ("Sending busy command.\n"); + send_cmd (test_thread_id, CMD_BUSY_LOOP); + log_trace ("Busy sent, yielding\n"); + pthread_yield (); + log_trace ("Returned from yield.\n"); + if (states[test_thread_id].flags & + (FLAGS_IS_BUSY | FLAGS_WAS_BUSY)) + log_error ("test thread inproperly preempted us.\n"); + else { + /* Let the thread finish its busy loop. */ + sleep (6); + if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) + log_error ("test thread never finished.\n"); + else + log_pass (); + } + states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; + + /* Have the test thread release mutex 0. */ + send_cmd (test_thread_id, CMD_RELEASE_ALL); + sleep (1); + + /* + * Have the test thread go into a busy loop for 5 seconds + * and see that it preempts this thread (since the priority + * ceiling of mutex 1 is the same as the priority of this + * thread). The test thread should not run to completion + * as its time quantum should expire before the 5 seconds + * are up. + */ + log (" Preemption with ceiling priority = thread " + "priority - "); + + /* Have the test thread take mutex 1. */ + send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]); + sleep (1); + + log_trace ("Sending busy\n"); + send_cmd (test_thread_id, CMD_BUSY_LOOP); + log_trace ("Busy sent, yielding\n"); + pthread_yield (); + log_trace ("Returned from yield.\n"); + if ((states[test_thread_id].flags & FLAGS_IS_BUSY) == 0) + log_error ("test thread did not switch in on yield.\n"); + else if (states[test_thread_id].flags & FLAGS_WAS_BUSY) + log_error ("test thread ran to completion.\n"); + else { + /* Let the thread finish its busy loop. */ + sleep (6); + if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) + log_error ("test thread never finished.\n"); + else + log_pass (); + } + states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; + + /* Have the test thread release mutex 1. */ + send_cmd (test_thread_id, CMD_RELEASE_ALL); + sleep (1); + + /* + * Set the scheduling policy of the test thread to SCHED_FIFO + * and have it go into a busy loop for 5 seconds. This + * thread is SCHED_RR, and since the priority ceiling of + * mutex 1 is the same as the priority of this thread, the + * test thread should run to completion once it is switched + * in. + */ + log (" SCHED_FIFO scheduling and ceiling priority = " + "thread priority - "); + param.sched_priority = states[test_thread_id].priority; + assert (pthread_setschedparam (states[test_thread_id].tid, + SCHED_FIFO, ¶m) == 0); + + /* Have the test thread take mutex 1. */ + send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]); + sleep (1); + + log_trace ("Sending busy\n"); + send_cmd (test_thread_id, CMD_BUSY_LOOP); + log_trace ("Busy sent, yielding\n"); + pthread_yield (); + log_trace ("Returned from yield.\n"); + if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) { + log_error ("test thread did not run to completion.\n"); + /* Let the thread finish it's busy loop. */ + sleep (6); + } + else + log_pass (); + states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; + + /* Restore the test thread scheduling parameters. */ + param.sched_priority = states[test_thread_id].priority; + assert (pthread_setschedparam (states[test_thread_id].tid, + SCHED_RR, ¶m) == 0); + + /* Have the test thread release mutex 1. */ + send_cmd (test_thread_id, CMD_RELEASE_ALL); + sleep (1); + + /* + * Have the test thread go into a busy loop for 5 seconds + * and see that it preempts this thread (since the priority + * ceiling of mutex 2 is the greater than the priority of + * this thread). The test thread should run to completion + * and block this thread because its active priority is + * higher. + */ + log (" SCHED_FIFO scheduling and ceiling priority > " + "thread priority - "); + /* Have the test thread take mutex 2. */ + send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[2]); + sleep (1); + + log_trace ("Sending busy\n"); + send_cmd (test_thread_id, CMD_BUSY_LOOP); + log_trace ("Busy sent, yielding\n"); + pthread_yield (); + log_trace ("Returned from yield.\n"); + if ((states[test_thread_id].flags & FLAGS_IS_BUSY) != 0) { + log_error ("test thread did not run to completion.\n"); + /* Let the thread finish it's busy loop. */ + sleep (6); + } + else if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) + log_error ("test thread never finished.\n"); + else + log_pass (); + states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; + + /* Have the test thread release mutex 2. */ + send_cmd (test_thread_id, CMD_RELEASE_ALL); + sleep (1); + + /* Destroy the mutexes. */ + for (i = 0; i < 3; i++) + assert (pthread_mutex_destroy (&m[i]) == 0); + } + } + + + static void + mutex_prioinherit_test (void) + { + pthread_mutexattr_t mattr; + struct sched_param param; + pthread_mutex_t m[3]; + mutex_kind_t mkind; + int i, policy, my_prio; + + /* Get this threads current priority. */ + assert (pthread_getschedparam (pthread_self(), &policy, + ¶m) == 0); + my_prio = param.sched_priority; /* save for later use */ + log_trace ("Current scheduling policy %d, priority %d\n", + policy, my_prio); + + log ("Testing priority inheritence\n"); + log ("----------------------------\n"); + for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { + + log (" Protype PTHREAD_PRIO_INHERIT, Type %s\n", + mutextype_strs[mkind]); + + /* + * Initialize and create a mutex. + */ + assert (pthread_mutexattr_init (&mattr) == 0); + + /* + * Initialize and create 3 priority inheritence mutexes with + * default (max priority) ceilings. + */ + assert (pthread_mutexattr_setprotocol(&mattr, + PTHREAD_PRIO_INHERIT) == 0); + + /* + * Ensure that the first mutex type is a POSIX + * compliant mutex. + */ + if (mkind != M_POSIX) { + assert (pthread_mutexattr_settype (&mattr, + mutex_types[mkind]) == 0); + } + + for (i = 0; i < 3; i++) + assert (pthread_mutex_init (&m[i], &mattr) == 0); + + /* + * Test setup: + * Thread 4 - take mutex 0, 1 + * Thread 2 - enter protected busy loop with mutex 0 + * Thread 3 - enter protected busy loop with mutex 1 + * Thread 4 - enter protected busy loop with mutex 2 + * Thread 5 - enter busy loop + * Thread 6 - enter protected busy loop with mutex 0 + * Thread 4 - releases mutexes 1 and 0. + * + * Expected results: + * Threads complete in order 4, 6, 5, 3, 2 + */ + log (" Simple inheritence test - "); + + /* + * Command thread 4 to take mutexes 0 and 1. + */ + send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]); + sleep (1); /* Allow command to be received. */ + send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[1]); + sleep (1); + + /* + * Tell the threads to report themselves when they are + * at the bottom of their loop (waiting on wait_mutex). + */ + for (i = 0; i < NUM_THREADS; i++) + states[i].flags |= FLAGS_REPORT_WAITMUTEX; + + /* + * Command thread 2 to take mutex 0 and thread 3 to take + * mutex 1, both via a protected operation command. Since + * thread 4 owns mutexes 0 and 1, both threads 2 and 3 + * will block until the mutexes are released by thread 4. + */ + log_trace ("Commanding protected operation to thread 2.\n"); + send_mutex_cmd (2, CMD_PROTECTED_OP, &m[0]); + log_trace ("Commanding protected operation to thread 3.\n"); + send_mutex_cmd (3, CMD_PROTECTED_OP, &m[1]); + sleep (1); + + /* + * Command thread 4 to take mutex 2 via a protected operation + * and thread 5 to enter a busy loop for 5 seconds. Since + * thread 5 has higher priority than thread 4, thread 5 will + * enter the busy loop before thread 4 is activated. + */ + log_trace ("Commanding protected operation to thread 4.\n"); + send_mutex_cmd (4, CMD_PROTECTED_OP, &m[2]); + log_trace ("Commanding busy loop to thread 5.\n"); + send_cmd (5, CMD_BUSY_LOOP); + sleep (1); + if ((states[5].flags & FLAGS_IS_BUSY) == 0) + log_error ("thread 5 is not running.\n"); + log_trace ("Commanding protected operation thread 6.\n"); + send_mutex_cmd (6, CMD_PROTECTED_OP, &m[0]); + sleep (1); + if ((states[4].flags & FLAGS_WAS_BUSY) == 0) + log_error ("thread 4 failed to inherit priority.\n"); + states[4].flags = 0; + send_cmd (4, CMD_RELEASE_ALL); + sleep (5); + check_run_order ("4,6,5,3,2"); + + /* + * Clear the flags. + */ + for (i = 0; i < NUM_THREADS; i++) + states[i].flags = 0; + + /* + * Test setup: + * Thread 2 - enter busy loop (SCHED_FIFO) + * Thread 4 - take mutex 0 + * Thread 4 - priority change to same priority as thread 2 + * Thread 4 - release mutex 0 + * + * Expected results: + * Since thread 4 owns a priority mutex, it should be + * placed at the front of the run queue (for its new + * priority slot) when its priority is lowered to the + * same priority as thread 2. If thread 4 did not own + * a priority mutex, then it would have been added to + * the end of the run queue and thread 2 would have + * executed until it blocked (because it's scheduling + * policy is SCHED_FIFO). + * + */ + log (" Inheritence test with change of priority - "); + + /* + * Change threads 2 and 4 scheduling policies to be + * SCHED_FIFO. + */ + param.sched_priority = states[2].priority; + assert (pthread_setschedparam (states[2].tid, SCHED_FIFO, + ¶m) == 0); + param.sched_priority = states[4].priority; + assert (pthread_setschedparam (states[4].tid, SCHED_FIFO, + ¶m) == 0); + + /* + * Command thread 4 to take mutex 0. + */ + send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]); + sleep (1); + + /* + * Command thread 2 to enter busy loop. + */ + send_cmd (2, CMD_BUSY_LOOP); + sleep (1); /* Allow command to be received. */ + + /* + * Command thread 4 to enter busy loop. + */ + send_cmd (4, CMD_BUSY_LOOP); + sleep (1); /* Allow command to be received. */ + + /* Have threads 2 and 4 report themselves. */ + states[2].flags = FLAGS_REPORT_WAITMUTEX; + states[4].flags = FLAGS_REPORT_WAITMUTEX; + + /* Change the priority of thread 4. */ + param.sched_priority = states[2].priority; + assert (pthread_setschedparam (states[4].tid, SCHED_FIFO, + ¶m) == 0); + sleep (5); + check_run_order ("4,2"); + + /* Clear the flags */ + states[2].flags = 0; + states[4].flags = 0; + + /* Reset the policies. */ + param.sched_priority = states[2].priority; + assert (pthread_setschedparam (states[2].tid, SCHED_RR, + ¶m) == 0); + param.sched_priority = states[4].priority; + assert (pthread_setschedparam (states[4].tid, SCHED_RR, + ¶m) == 0); + + send_cmd (4, CMD_RELEASE_MUTEX); + sleep (1); + + /* Destroy the mutexes. */ + for (i = 0; i < 3; i++) + assert (pthread_mutex_destroy (&m[i]) == 0); + } + } + + + int main (int argc, char *argv[]) + { + pthread_mutexattr_t mattr; + pthread_condattr_t cattr; + pthread_attr_t pattr; + int i, policy, main_prio; + void * exit_status; + sigset_t mask; + struct sigaction act; + struct sched_param param; + + logfile = stdout; + + assert (pthread_getschedparam (pthread_self (), &policy, ¶m) == 0); + main_prio = param.sched_priority; + + /* Setupt our signal mask. */ + sigfillset (&mask); + sigdelset (&mask, SIGINT); + sigprocmask (SIG_SETMASK, &mask, NULL); + + /* Install a signal handler for SIGINT */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGINT); + act.sa_handler = sighandler; + act.sa_flags = SA_RESTART; + sigaction (SIGINT, &act, NULL); + + /* + * Initialize the thread attribute. + */ + assert (pthread_attr_init (&pattr) == 0); + assert (pthread_attr_setdetachstate (&pattr, + PTHREAD_CREATE_JOINABLE) == 0); + + /* + * Initialize and create the waiter and condvar mutexes. + */ + assert (pthread_mutexattr_init (&mattr) == 0); + assert (pthread_mutex_init (&waiter_mutex, &mattr) == 0); + assert (pthread_mutex_init (&cond_mutex, &mattr) == 0); + + /* + * Initialize and create a condition variable. + */ + assert (pthread_condattr_init (&cattr) == 0); + assert (pthread_cond_init (&cond_var, &cattr) == 0); + + /* Create a pipe to catch the results of thread wakeups. */ + assert (pipe (pipefd) == 0); + + #ifdef DEBUG + assert (pthread_switch_add_np (kern_switch) == 0); + #endif + + /* + * Create the waiting threads. + */ + for (i = 0; i < NUM_THREADS; i++) { + assert (pthread_cond_init (&states[i].cond_var, &cattr) == 0); + states[i].id = (u_int8_t) i; /* NUM_THREADS must be <= 256 */ + states[i].status = 0; + states[i].cmd.cmd_id = CMD_NONE; + states[i].flags = 0; /* No flags yet. */ + assert (pthread_create (&states[i].tid, &pattr, waiter, + (void *) &states[i]) == 0); + param.sched_priority = main_prio - 10 + i; + states[i].priority = param.sched_priority; + assert (pthread_setschedparam (states[i].tid, SCHED_OTHER, + ¶m) == 0); + #if defined(_LIBC_R_) + { + char buf[30]; + + snprintf (buf, sizeof(buf), "waiter_%d", i); + pthread_set_name_np (states[i].tid, buf); + } + #endif + } + + /* Allow the threads to start. */ + sleep (1); + log_trace ("Done creating threads.\n"); + + log ("\n"); + mutex_init_test (); + log ("\n"); + mutex_destroy_test (); + log ("\n"); + mutex_lock_test (); + log ("\n"); + mutex_unlock_test (); + log ("\n"); + queueing_order_test (); + log ("\n"); + mutex_prioinherit_test (); + log ("\n"); + mutex_prioceiling_test (); + log ("\n"); + + log ("Total tests %d, passed %d, failed %d\n", + total, pass_count, error_count); + + /* Set the done flag and signal the threads to exit. */ + log_trace ("Setting done flag.\n"); + done = 1; + + /* + * Wait for the threads to finish. + */ + log_trace ("Trying to join threads.\n"); + for (i = 0; i < NUM_THREADS; i++) { + send_cmd (i, CMD_NONE); + assert (pthread_join (states[i].tid, &exit_status) == 0); + } + + /* Clean up after ourselves. */ + close (pipefd[0]); + close (pipefd[1]); + + if (error_count != 0) + exit (EX_OSERR); /* any better ideas??? */ + else + exit (EX_OK); + } Index: lib/libpthread/test/mutex_d.exp =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/mutex_d.exp Sun Sep 15 21:38:38 2002 *************** *** 0 **** --- 1,290 ---- + + Testing pthread_mutex_init + -------------------------- + Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified) - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS + Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified) - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS + Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified) - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS + + Testing pthread_mutex_destroy + ----------------------------- + Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified) + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified) + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified) + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE + Destruction of unused mutex - PASS + Destruction of mutex locked by self - PASS + Destruction of mutex locked by another thread - PASS + Destruction of mutex while being used in cond_wait - PASS + + Testing pthread_mutex_lock + -------------------------- + Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified) + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified) + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified) + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE + Lock on unlocked mutex - PASS + Lock on invalid mutex - PASS + Lock on mutex held by self - PASS + + Testing pthread_mutex_unlock + ---------------------------- + Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified) + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified) + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified) + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE + Unlock on mutex held by self - PASS + Unlock on invalid mutex - PASS + Unlock on mutex locked by another thread - PASS + + Testing queueing order + ---------------------- + Queueing order on a mutex - PASS + Queueing order on a condition variable - PASS + + Testing priority inheritence + ---------------------------- + Protype PTHREAD_PRIO_INHERIT, Type POSIX (type not specified) + Simple inheritence test - PASS + Inheritence test with change of priority - PASS + Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT + Simple inheritence test - PASS + Inheritence test with change of priority - PASS + Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Simple inheritence test - PASS + Inheritence test with change of priority - PASS + Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL + Simple inheritence test - PASS + Inheritence test with change of priority - PASS + Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE + Simple inheritence test - PASS + Inheritence test with change of priority - PASS + + Testing priority ceilings + ------------------------- + Protype PTHREAD_PRIO_PROTECT, Type POSIX (type not specified) + Lock with ceiling priority < thread priority - PASS + Lock with ceiling priority = thread priority - PASS + Lock with ceiling priority > thread priority - PASS + Preemption with ceiling priority < thread priority - PASS + Preemption with ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority > thread priority - PASS + Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT + Lock with ceiling priority < thread priority - PASS + Lock with ceiling priority = thread priority - PASS + Lock with ceiling priority > thread priority - PASS + Preemption with ceiling priority < thread priority - PASS + Preemption with ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority > thread priority - PASS + Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK + Lock with ceiling priority < thread priority - PASS + Lock with ceiling priority = thread priority - PASS + Lock with ceiling priority > thread priority - PASS + Preemption with ceiling priority < thread priority - PASS + Preemption with ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority > thread priority - PASS + Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL + Lock with ceiling priority < thread priority - PASS + Lock with ceiling priority = thread priority - PASS + Lock with ceiling priority > thread priority - PASS + Preemption with ceiling priority < thread priority - PASS + Preemption with ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority > thread priority - PASS + Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE + Lock with ceiling priority < thread priority - PASS + Lock with ceiling priority = thread priority - PASS + Lock with ceiling priority > thread priority - PASS + Preemption with ceiling priority < thread priority - PASS + Preemption with ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority = thread priority - PASS + SCHED_FIFO scheduling and ceiling priority > thread priority - PASS + + Total tests 212, passed 212, failed 0 Index: lib/libpthread/test/propagate_s.pl =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/propagate_s.pl Sun Sep 15 21:38:39 2002 *************** *** 0 **** --- 1,74 ---- + #!/usr/bin/perl -w + # + # Copyright (C) 2000 Jason Evans . + # 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(s), this list of conditions and the following disclaimer as + # the first lines of this file unmodified other than the possible + # addition of one or more copyright notices. + # 2. Redistributions in binary form must reproduce the above copyright + # notice(s), this list of conditions and the following disclaimer in + # the documentation and/or other materials provided with the + # distribution. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + # + ########################################################################### + # + # Verify that no cancellation points are propagated inside of pthread. + # + # $FreeBSD: src/lib/libc_r/test/propagate_s.pl,v 1.1 2000/04/26 23:25:58 jasone Exp $ + # + + @CPOINTS = ("aio_suspend", "close", "creat", "fcntl", "fsync", "mq_receive", + "mq_send", "msync", "nanosleep", "open", "pause", + "pthread_cond_timedwait", "pthread_cond_wait", "pthread_join", + "pthread_testcancel", "read", "sem_wait", "sigsuspend", + "sigtimedwait", "sigwait", "sigwaitinfo", "sleep", "system", + "tcdrain", "wait", "waitpid", "write"); + + print "1..1\n"; + + $cpoints = join '\|', @CPOINTS; + $regexp = "\" U \\(" . $cpoints . "\\\)\$\""; + + `nm -a /usr/lib/libc.a |grep $regexp >propagate_s.out`; + if (!open (NMOUT, "<./propagate_s.out")) + { + print "not ok 1\n"; + } + else + { + $propagations = 0; + + while () + { + $propagations++; + print "$_\n"; + } + if ($propagations != 0) + { + print "$propagations propagation(s)\n"; + print "not ok 1\n"; + } + else + { + print "ok 1\n"; + } + close NMOUT; + unlink "propagate_s.out"; + } Index: lib/libpthread/test/sem_d.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/sem_d.c Sun Sep 15 21:38:39 2002 *************** *** 0 **** --- 1,133 ---- + /**************************************************************************** + * + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + **************************************************************************** + * + * sem test. + * + * $FreeBSD: src/lib/libc_r/test/sem_d.c,v 1.2 2001/05/20 23:11:09 jasone Exp $ + * + ****************************************************************************/ + + #include + #include + #include + #include + #include + #include + + #define NTHREADS 10 + + void * + entry(void * a_arg) + { + sem_t * sem = (sem_t *) a_arg; + + sem_wait(sem); + fprintf(stderr, "Got semaphore\n"); + + return NULL; + } + + int + main() + { + sem_t sem_a, sem_b; + pthread_t threads[NTHREADS]; + unsigned i; + int val; + + fprintf(stderr, "Test begin\n"); + + #ifdef _LIBC_R_ + assert(-1 == sem_init(&sem_b, 1, 0)); + assert(EPERM == errno); + #endif + + assert(0 == sem_init(&sem_b, 0, 0)); + assert(0 == sem_getvalue(&sem_b, &val)); + assert(0 == val); + + assert(0 == sem_post(&sem_b)); + assert(0 == sem_getvalue(&sem_b, &val)); + assert(1 == val); + + assert(0 == sem_wait(&sem_b)); + assert(-1 == sem_trywait(&sem_b)); + assert(EAGAIN == errno); + assert(0 == sem_post(&sem_b)); + assert(0 == sem_trywait(&sem_b)); + assert(0 == sem_post(&sem_b)); + assert(0 == sem_wait(&sem_b)); + assert(0 == sem_post(&sem_b)); + + #ifdef _LIBC_R_ + assert(SEM_FAILED == sem_open("/foo", O_CREAT | O_EXCL, 0644, 0)); + assert(ENOSYS == errno); + + assert(-1 == sem_close(&sem_b)); + assert(ENOSYS == errno); + + assert(-1 == sem_unlink("/foo")); + assert(ENOSYS == errno); + #endif + + assert(0 == sem_destroy(&sem_b)); + + assert(0 == sem_init(&sem_a, 0, 0)); + + for (i = 0; i < NTHREADS; i++) { + pthread_create(&threads[i], NULL, entry, (void *) &sem_a); + } + + for (i = 0; i < NTHREADS; i++) { + assert(0 == sem_post(&sem_a)); + } + + for (i = 0; i < NTHREADS; i++) { + pthread_join(threads[i], NULL); + } + + for (i = 0; i < NTHREADS; i++) { + pthread_create(&threads[i], NULL, entry, (void *) &sem_a); + } + + for (i = 0; i < NTHREADS; i++) { + assert(0 == sem_post(&sem_a)); + } + + for (i = 0; i < NTHREADS; i++) { + pthread_join(threads[i], NULL); + } + + assert(0 == sem_destroy(&sem_a)); + + fprintf(stderr, "Test end\n"); + return 0; + } Index: lib/libpthread/test/sem_d.exp =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/sem_d.exp Sun Sep 15 21:38:39 2002 *************** *** 0 **** --- 1,22 ---- + Test begin + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Got semaphore + Test end Index: lib/libpthread/test/sigsuspend_d.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/sigsuspend_d.c Sun Sep 15 21:38:39 2002 *************** *** 0 **** --- 1,288 ---- + /* + * Copyright (c) 1998 Daniel M. Eischen + * 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 Daniel M. Eischen. + * 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 DANIEL M. EISCHEN 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. + * + * $FreeBSD: src/lib/libc_r/test/sigsuspend_d.c,v 1.1 2000/04/24 21:07:39 jasone Exp $ + */ + #include + #include + + #include + #include + #include + #include + #include + + #if defined(_LIBC_R_) + #include + #endif + + static int sigcounts[NSIG + 1]; + static int sigfifo[NSIG + 1]; + static int fifo_depth = 0; + static sigset_t suspender_mask; + static pthread_t suspender_tid; + + + static void * + sigsuspender (void *arg) + { + int save_count, status, i; + sigset_t run_mask; + + /* Run with all signals blocked. */ + sigfillset (&run_mask); + sigprocmask (SIG_SETMASK, &run_mask, NULL); + + /* Allow these signals to wake us up during a sigsuspend. */ + sigfillset (&suspender_mask); /* Default action */ + sigdelset (&suspender_mask, SIGINT); /* terminate */ + sigdelset (&suspender_mask, SIGHUP); /* terminate */ + sigdelset (&suspender_mask, SIGQUIT); /* create core image */ + sigdelset (&suspender_mask, SIGURG); /* ignore */ + sigdelset (&suspender_mask, SIGIO); /* ignore */ + sigdelset (&suspender_mask, SIGUSR2); /* terminate */ + + while (sigcounts[SIGINT] == 0) { + save_count = sigcounts[SIGUSR2]; + + status = sigsuspend (&suspender_mask); + if ((status == 0) || (errno != EINTR)) { + fprintf (stderr, "Unable to suspend for signals, " + "errno %d, return value %d\n", + errno, status); + exit (1); + } + for (i = 0; i < fifo_depth; i++) + fprintf (stderr, "Sigsuspend woke up by signal %d\n", + sigfifo[i]); + fifo_depth = 0; + } + + pthread_exit (arg); + return (NULL); + } + + + static void + sighandler (int signo) + { + sigset_t set, suspend_set; + pthread_t self; + + if ((signo >= 0) && (signo <= NSIG)) + sigcounts[signo]++; + + /* + * If we are running on behalf of the suspender thread, + * ensure that we have the correct mask set. + */ + self = pthread_self (); + if (self == suspender_tid) { + sigfifo[fifo_depth] = signo; + fifo_depth++; + fprintf (stderr, + " -> Suspender thread signal handler caught signal %d\n", + signo); + + /* Get the current signal mask. */ + sigprocmask (SIG_SETMASK, NULL, &set); + + /* The handler should run with the current signal masked. */ + suspend_set = suspender_mask; + sigaddset(&suspend_set, signo); + + if (memcmp(&set, &suspend_set, sizeof(set))) + fprintf (stderr, + " >>> FAIL: sigsuspender signal handler running " + "with incorrect mask.\n"); + } + else + fprintf (stderr, + " -> Main thread signal handler caught signal %d\n", + signo); + } + + + static void + send_thread_signal (pthread_t tid, int signo) + { + if (pthread_kill (tid, signo) != 0) { + fprintf (stderr, "Unable to send thread signal, errno %d.\n", + errno); + exit (1); + } + } + + + static void + send_process_signal (int signo) + { + if (kill (getpid (), signo) != 0) { + fprintf (stderr, "Unable to send process signal, errno %d.\n", + errno); + exit (1); + } + } + + + int main (int argc, char *argv[]) + { + pthread_attr_t pattr; + void * exit_status; + struct sigaction act; + sigset_t oldset; + sigset_t newset; + + /* Initialize our signal counts. */ + memset ((void *) sigcounts, 0, NSIG * sizeof (int)); + + /* Ignore signal SIGIO. */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGIO); + act.sa_handler = SIG_IGN; + act.sa_flags = 0; + sigaction (SIGIO, &act, NULL); + + /* Install a signal handler for SIGURG. */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGURG); + act.sa_handler = sighandler; + act.sa_flags = SA_RESTART; + sigaction (SIGURG, &act, NULL); + + /* Install a signal handler for SIGXCPU */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGXCPU); + sigaction (SIGXCPU, &act, NULL); + + /* Get our current signal mask. */ + sigprocmask (SIG_SETMASK, NULL, &oldset); + + /* Mask out SIGUSR1 and SIGUSR2. */ + newset = oldset; + sigaddset (&newset, SIGUSR1); + sigaddset (&newset, SIGUSR2); + sigprocmask (SIG_SETMASK, &newset, NULL); + + /* Install a signal handler for SIGUSR1 */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGUSR1); + sigaction (SIGUSR1, &act, NULL); + + /* Install a signal handler for SIGUSR2 */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGUSR2); + sigaction (SIGUSR2, &act, NULL); + + /* + * Initialize the thread attribute. + */ + if ((pthread_attr_init (&pattr) != 0) || + (pthread_attr_setdetachstate (&pattr, + PTHREAD_CREATE_JOINABLE) != 0)) { + fprintf (stderr, "Unable to initialize thread attributes.\n"); + exit (1); + } + + /* + * Create the sigsuspender thread. + */ + if (pthread_create (&suspender_tid, &pattr, sigsuspender, NULL) != 0) { + fprintf (stderr, "Unable to create thread, errno %d.\n", errno); + exit (1); + } + #if defined(_LIBC_R) + pthread_set_name_np (suspender_tid, "sigsuspender"); + #endif + + /* + * Verify that an ignored signal doesn't cause a wakeup. + * We don't have a handler installed for SIGIO. + */ + send_thread_signal (suspender_tid, SIGIO); + sleep (1); + send_process_signal (SIGIO); + sleep (1); + if (sigcounts[SIGIO] != 0) + fprintf (stderr, "FAIL: sigsuspend wakes up for ignored signal " + "SIGIO.\n"); + + /* + * Verify that a signal with a default action of ignore, for + * which we have a signal handler installed, will release a + * sigsuspend. + */ + send_thread_signal (suspender_tid, SIGURG); + sleep (1); + send_process_signal (SIGURG); + sleep (1); + if (sigcounts[SIGURG] != 2) + fprintf (stderr, + "FAIL: sigsuspend doesn't wake up for SIGURG.\n"); + + /* + * Verify that a SIGUSR2 signal will release a sigsuspended + * thread. + */ + send_thread_signal (suspender_tid, SIGUSR2); + sleep (1); + send_process_signal (SIGUSR2); + sleep (1); + if (sigcounts[SIGUSR2] != 2) + fprintf (stderr, + "FAIL: sigsuspend doesn't wake up for SIGUSR2.\n"); + + /* + * Verify that a signal, blocked in both the main and + * sigsuspender threads, does not cause the signal handler + * to be called. + */ + send_thread_signal (suspender_tid, SIGUSR1); + sleep (1); + send_process_signal (SIGUSR1); + sleep (1); + if (sigcounts[SIGUSR1] != 0) + fprintf (stderr, "FAIL: signal hander called for SIGUSR1.\n"); + + /* + * Verify that we can still kill the process for a signal + * not being waited on by sigwait. + */ + send_process_signal (SIGPIPE); + fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n"); + + /* + * Wait for the thread to finish. + */ + pthread_join (suspender_tid, &exit_status); + + return (0); + } Index: lib/libpthread/test/sigsuspend_d.exp =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/sigsuspend_d.exp Sun Sep 15 21:38:39 2002 *************** *** 0 **** --- 1,8 ---- + -> Suspender thread signal handler caught signal 16 + Sigsuspend woke up by signal 16 + -> Suspender thread signal handler caught signal 16 + Sigsuspend woke up by signal 16 + -> Suspender thread signal handler caught signal 31 + Sigsuspend woke up by signal 31 + -> Suspender thread signal handler caught signal 31 + Sigsuspend woke up by signal 31 Index: lib/libpthread/test/sigwait_d.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/sigwait_d.c Sun Sep 15 21:38:40 2002 *************** *** 0 **** --- 1,304 ---- + /* + * Copyright (c) 1998 Daniel M. Eischen + * 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 Daniel M. Eischen. + * 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 DANIEL M. EISCHEN 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. + * + * $FreeBSD: src/lib/libc_r/test/sigwait_d.c,v 1.2 2001/05/20 23:10:30 jasone Exp $ + */ + #include + #include + + #include + #include + #include + #include + #include + + #if defined(_LIBC_R_) + #include + #endif + + static int sigcounts[NSIG + 1]; + static sigset_t wait_mask; + static pthread_mutex_t waiter_mutex; + + + static void * + sigwaiter (void *arg) + { + int signo; + sigset_t mask; + + /* Block SIGHUP */ + sigemptyset (&mask); + sigaddset (&mask, SIGHUP); + sigprocmask (SIG_BLOCK, &mask, NULL); + + while (sigcounts[SIGINT] == 0) { + if (sigwait (&wait_mask, &signo) != 0) { + fprintf (stderr, + "Unable to wait for signal, errno %d\n", + errno); + exit (1); + } + sigcounts[signo]++; + fprintf (stderr, "Sigwait caught signal %d\n", signo); + + /* Allow the main thread to prevent the sigwait. */ + pthread_mutex_lock (&waiter_mutex); + pthread_mutex_unlock (&waiter_mutex); + } + + pthread_exit (arg); + return (NULL); + } + + + static void + sighandler (int signo) + { + fprintf (stderr, " -> Signal handler caught signal %d\n", signo); + + if ((signo >= 0) && (signo <= NSIG)) + sigcounts[signo]++; + } + + static void + send_thread_signal (pthread_t tid, int signo) + { + if (pthread_kill (tid, signo) != 0) { + fprintf (stderr, "Unable to send thread signal, errno %d.\n", + errno); + exit (1); + } + } + + static void + send_process_signal (int signo) + { + if (kill (getpid (), signo) != 0) { + fprintf (stderr, "Unable to send process signal, errno %d.\n", + errno); + exit (1); + } + } + + + int main (int argc, char *argv[]) + { + pthread_mutexattr_t mattr; + pthread_attr_t pattr; + pthread_t tid; + void * exit_status; + struct sigaction act; + + /* Initialize our signal counts. */ + memset ((void *) sigcounts, 0, NSIG * sizeof (int)); + + /* Setup our wait mask. */ + sigemptyset (&wait_mask); /* Default action */ + sigaddset (&wait_mask, SIGHUP); /* terminate */ + sigaddset (&wait_mask, SIGINT); /* terminate */ + sigaddset (&wait_mask, SIGQUIT); /* create core image */ + sigaddset (&wait_mask, SIGURG); /* ignore */ + sigaddset (&wait_mask, SIGIO); /* ignore */ + sigaddset (&wait_mask, SIGUSR1); /* terminate */ + + /* Ignore signals SIGHUP and SIGIO. */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGHUP); + sigaddset (&act.sa_mask, SIGIO); + act.sa_handler = SIG_IGN; + act.sa_flags = 0; + sigaction (SIGHUP, &act, NULL); + sigaction (SIGIO, &act, NULL); + + /* Install a signal handler for SIGURG */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGURG); + act.sa_handler = sighandler; + act.sa_flags = SA_RESTART; + sigaction (SIGURG, &act, NULL); + + /* Install a signal handler for SIGXCPU */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGXCPU); + sigaction (SIGXCPU, &act, NULL); + + /* + * Initialize the thread attribute. + */ + if ((pthread_attr_init (&pattr) != 0) || + (pthread_attr_setdetachstate (&pattr, + PTHREAD_CREATE_JOINABLE) != 0)) { + fprintf (stderr, "Unable to initialize thread attributes.\n"); + exit (1); + } + + /* + * Initialize and create a mutex. + */ + if ((pthread_mutexattr_init (&mattr) != 0) || + (pthread_mutex_init (&waiter_mutex, &mattr) != 0)) { + fprintf (stderr, "Unable to create waiter mutex.\n"); + exit (1); + } + + /* + * Create the sigwaiter thread. + */ + if (pthread_create (&tid, &pattr, sigwaiter, NULL) != 0) { + fprintf (stderr, "Unable to create thread.\n"); + exit (1); + } + #if defined(_LIBC_R_) + pthread_set_name_np (tid, "sigwaiter"); + #endif + + /* + * Verify that an ignored signal doesn't cause a wakeup. + * We don't have a handler installed for SIGIO. + */ + send_thread_signal (tid, SIGIO); + sleep (1); + send_process_signal (SIGIO); + sleep (1); + if (sigcounts[SIGIO] != 0) + fprintf (stderr, + "FAIL: sigwait wakes up for ignored signal SIGIO.\n"); + + /* + * Verify that a signal with a default action of ignore, for + * which we have a signal handler installed, will release a sigwait. + */ + send_thread_signal (tid, SIGURG); + sleep (1); + send_process_signal (SIGURG); + sleep (1); + if (sigcounts[SIGURG] != 2) + fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGURG.\n"); + + /* + * Verify that a signal with a default action that terminates + * the process will release a sigwait. + */ + send_thread_signal (tid, SIGUSR1); + sleep (1); + send_process_signal (SIGUSR1); + sleep (1); + if (sigcounts[SIGUSR1] != 2) + fprintf (stderr, + "FAIL: sigwait doesn't wake up for SIGUSR1.\n"); + + /* + * Verify that if we install a signal handler for a previously + * ignored signal, an occurrence of this signal will release + * the (already waiting) sigwait. + */ + + /* Install a signal handler for SIGHUP. */ + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SIGHUP); + act.sa_handler = sighandler; + act.sa_flags = SA_RESTART; + sigaction (SIGHUP, &act, NULL); + + /* Sending SIGHUP should release the sigwait. */ + send_process_signal (SIGHUP); + sleep (1); + send_thread_signal (tid, SIGHUP); + sleep (1); + if (sigcounts[SIGHUP] != 2) + fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n"); + + /* + * Verify that a pending signal in the waiters mask will + * cause sigwait to return the pending signal. We do this + * by taking the waiters mutex and signaling the waiter to + * release him from the sigwait. The waiter will block + * on taking the mutex, and we can then send the waiter a + * signal which should be added to his pending signals. + * The next time the waiter does a sigwait, he should + * return with the pending signal. + */ + sigcounts[SIGHUP] = 0; + pthread_mutex_lock (&waiter_mutex); + /* Release the waiter from sigwait. */ + send_process_signal (SIGHUP); + sleep (1); + if (sigcounts[SIGHUP] != 1) + fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n"); + /* + * Add SIGHUP to the process pending signals. Since there is + * a signal handler installed for SIGHUP and this signal is + * blocked from the waiter thread and unblocked in the main + * thread, the signal handler should be called once for SIGHUP. + */ + send_process_signal (SIGHUP); + /* Release the waiter thread and allow him to run. */ + pthread_mutex_unlock (&waiter_mutex); + sleep (1); + if (sigcounts[SIGHUP] != 2) + fprintf (stderr, + "FAIL: sigwait doesn't return for pending SIGHUP.\n"); + + /* + * Repeat the above test using pthread_kill and SIGUSR1. + */ + sigcounts[SIGUSR1] = 0; + pthread_mutex_lock (&waiter_mutex); + /* Release the waiter from sigwait. */ + send_thread_signal (tid, SIGUSR1); + sleep (1); + if (sigcounts[SIGUSR1] != 1) + fprintf (stderr, + "FAIL: sigwait doesn't wake up for SIGUSR1.\n"); + /* Add SIGUSR1 to the waiters pending signals. */ + send_thread_signal (tid, SIGUSR1); + /* Release the waiter thread and allow him to run. */ + pthread_mutex_unlock (&waiter_mutex); + sleep (1); + if (sigcounts[SIGUSR1] != 2) + fprintf (stderr, + "FAIL: sigwait doesn't return for pending SIGUSR1.\n"); + + /* + * Verify that we can still kill the process for a signal + * not being waited on by sigwait. + */ + send_process_signal (SIGPIPE); + fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n"); + + /* + * Wait for the thread to finish. + */ + pthread_join (tid, &exit_status); + + return (0); + } Index: lib/libpthread/test/sigwait_d.exp =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/sigwait_d.exp Sun Sep 15 21:38:40 2002 *************** *** 0 **** --- 1,10 ---- + Sigwait caught signal 16 + Sigwait caught signal 16 + Sigwait caught signal 30 + Sigwait caught signal 30 + Sigwait caught signal 1 + Sigwait caught signal 1 + Sigwait caught signal 1 + -> Signal handler caught signal 1 + Sigwait caught signal 30 + Sigwait caught signal 30 Index: lib/libpthread/test/verify =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/test/verify Sun Sep 15 21:38:40 2002 *************** *** 0 **** --- 1,474 ---- + #!/usr/bin/perl -w + #-*-mode:perl-*- + ############################################################################# + # + # Copyright (C) 1999-2001 Jason Evans . + # 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(s), this list of conditions and the following disclaimer as + # the first lines of this file unmodified other than the possible + # addition of one or more copyright notices. + # 2. Redistributions in binary form must reproduce the above copyright + # notice(s), this list of conditions and the following disclaimer in + # the documentation and/or other materials provided with the + # distribution. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + # + ############################################################################# + # + # Test harness. + # + # $FreeBSD: src/lib/libc_r/test/verify,v 1.2 2001/05/20 23:11:54 jasone Exp $ + # + ############################################################################# + + # Shut off buffering. + select(STDOUT); + $| = 1; + + # + # Parse command-line arguments. + # + use Getopt::Long; + Getopt::Long::config("bundling"); # Allow -hv rather than forcing -h -v. + + # Set option defaults for optional arguments. + $opt_help = 0; + $opt_verbose = 0; + $opt_quiet = 0; + $opt_srcdir = "."; + $opt_objdir = "."; + $opt_ustats = 0; + $opt_zero = 0; + + $opt_retval = + &GetOptions("h|help" => \$opt_help, + "v|verbose" => \$opt_verbose, + "q|quiet" => \$opt_quiet, + "s|srcdir=s" => \$opt_srcdir, + "o|objdir=s" => \$opt_objdir, + "u|ustats" => \$opt_ustats, + "z|zero" => \$opt_zero + ); + + if ($opt_help) + { + &usage(); + exit(0); + } + + if ($opt_retval == 0) + { + &usage(); + exit 1; + } + + if ($opt_verbose && $opt_quiet) + { + print STDERR "-v and -q are incompatible\n"; + &usage(); + exit 1; + } + + if ($#ARGV + 1 == 0) + { + print STDERR "No tests specified\n"; + &usage(); + exit 1; + } + + if ($opt_verbose) + { + print STDERR "Option values: h:$opt_help, v:$opt_verbose, " + . "s:\"$opt_srcdir\", o:\"$opt_objdir\" " + . "q:$opt_quiet, u:$opt_ustats, z:$opt_zero\n"; + printf STDERR "Tests (%d total): @ARGV\n", $#ARGV + 1; + } + + # + # Create and print header. + # + @TSTATS = + ( + "--------------------------------------------------------------------------\n", + "Test c_user c_system c_total chng\n", + " passed/FAILED h_user h_system h_total %% chng\n" + ); + + if (!$opt_quiet) + { + foreach $line (@TSTATS) + { + printf STDOUT "$line"; + } + } + + # + # Run sequence test(s). + # + $total_utime = 0.0; # Total user time. + $total_stime = 0.0; # Total system time. + $total_hutime = 0.0; # Total historical user time. + $total_hstime = 0.0; # Total historical system time. + $total_ntime = 0.0; # Total time for tests that have historical data. + + foreach $test (@ARGV) + { + # Strip out any whitespace in $test. + $test =~ s/^\s*(.*)\s*$/$1/; + + $okay = 1; + + if (-e "$opt_srcdir/$test.exp") + { + # Diff mode. + + ($okay, $utime, $stime) = &run_test($test); + + if (-e "$opt_objdir/$test.out") + { + `diff $opt_srcdir/$test.exp $opt_objdir/$test.out > $opt_objdir/$test.diff 2>&1`; + if ($?) + { + # diff returns non-zero if there is a difference. + $okay = 0; + } + } + else + { + $okay = 0; + if ($opt_verbose) + { + print STDERR + "Nonexistent output file \"$opt_objdir/$test.out\"\n"; + } + } + + ($hutime, $hstime) = &print_stats($test, $okay, 0, 0, $utime, $stime); + } + else + { + # Sequence mode. + + ($okay, $utime, $stime) = &run_test($test); + + if (open (STEST_OUT, "<$opt_objdir/$test.out")) + { + $num_subtests = 0; + $num_failed_subtests = 0; + + while (defined($line = )) + { + if ($line =~ /1\.\.(\d+)/) + { + $num_subtests = $1; + last; + } + } + if ($num_subtests == 0) + { + $okay = 0; + if ($opt_verbose) + { + print STDERR "Malformed or missing 1..n line\n"; + } + } + else + { + for ($subtest = 1; $subtest <= $num_subtests; $subtest++) + { + while (defined($line = )) + { + if ($line =~ /^not\s+ok\s+(\d+)?/) + { + $not = 1; + $test_num = $1; + last; + } + elsif ($line =~ /^ok\s+(\d+)?/) + { + $not = 0; + $test_num = $1; + last; + } + } + if (defined($line)) + { + if (defined($test_num) && ($test_num != $subtest)) + { + # There was no output printed for one or more tests. + for (; $subtest < $test_num; $subtest++) + { + $num_failed_subtests++; + } + } + if ($not) + { + $num_failed_subtests++; + } + } + else + { + for (; $subtest <= $num_subtests; $subtest++) + { + $num_failed_subtests++; + } + } + } + + if (0 < $num_failed_subtests) + { + $okay = 0; + } + } + } + else + { + if (!$opt_quiet) + { + print STDERR "Cannot open output file \"$opt_objdir/$test.out\"\n"; + } + exit 1; + } + + ($hutime, $hstime) = &print_stats($test, $okay, + $num_failed_subtests, $num_subtests, + $utime, $stime); + } + + $total_hutime += $hutime; + $total_hstime += $hstime; + + if ($okay) + { + $total_utime += $utime; + $total_stime += $stime; + } + else + { + @FAILED_TESTS = (@FAILED_TESTS, $test); + } + + # If there were historical data, add the run time to the total time to + # compare against the historical run time. + if (0 < ($hutime + $hstime)) + { + $total_ntime += $utime + $stime; + } + } + + # Print summary stats. + $tt_str = sprintf ("%d / %d passed (%5.2f%%%%)", + ($#ARGV + 1) - ($#FAILED_TESTS + 1), + $#ARGV + 1, + (($#ARGV + 1) - ($#FAILED_TESTS + 1)) + / ($#ARGV + 1) * 100); + + $t_str = sprintf ("Totals %7.2f %7.2f %7.2f" + . " %7.2f\n" + . " %s %7.2f %7.2f %7.2f %7.2f%%%%\n", + $total_utime, $total_stime, $total_utime + $total_stime, + ($total_ntime - ($total_hutime + $total_hstime)), + $tt_str . ' ' x (40 - length($tt_str)), + $total_hutime, $total_hstime, $total_hutime + $total_hstime, + ($total_hutime + $total_hstime == 0.0) ? 0.0 : + (($total_ntime + - ($total_hutime + $total_hstime)) + / ($total_hutime + $total_hstime) * 100)); + + @TSTATS = ("--------------------------------------------------------------------------\n", + $t_str, + "--------------------------------------------------------------------------\n" + ); + if (!$opt_quiet) + { + foreach $line (@TSTATS) + { + printf STDOUT "$line"; + } + } + + if ($#FAILED_TESTS >= 0) + { + # One or more tests failed, so return an error. + exit 1; + } + # End of main execution. + + sub run_test + { + my ($test) = @_; + my ($okay) = 1; + my ($tutime, $tstime); + my ($utime, $stime, $cutime, $cstime); + my (@TSTATS, @TPATH); + my ($t_str); + my ($srcdir, $objdir); + + # Get the path component of $test, if any. + @TPATH = split(/\//, $test); + pop(@TPATH); + $srcdir = join('/', ($opt_srcdir, @TPATH)); + $objdir = join('/', ($opt_objdir, @TPATH)); + + @TSTATS = ("--------------------------------------------------------------------------\n"); + + $t_str = sprintf ("%s%s", $test, ' ' x (40 - length($test))); + @TSTATS = (@TSTATS, $t_str); + @STATS = (@STATS, @TSTATS); + if (!$opt_quiet) + { + foreach $line (@TSTATS) + { + printf STDOUT "$line"; + } + } + + ($utime, $stime, $cutime, $cstime) = times; + `$opt_objdir/$test $srcdir $objdir > $opt_objdir/$test.out 2>&1`; + ($utime, $stime, $tutime, $tstime) = times; + + # Subtract the before time from the after time. + $tutime -= $cutime; + $tstime -= $cstime; + + if ($opt_zero) + { + if ($?) + { + $okay = 0; + if ($opt_verbose) + { + print STDERR + "\"$opt_objdir/$test > $opt_objdir/$test.out 2>&1\" returned $?\n"; + } + } + } + + return ($okay, $tutime, $tstime); + } + + sub print_stats + { + my ($test, $okay, $failed_subtests, $subtests, $utime, $stime) = @_; + my ($hutime, $hstime); + # my (TEST_PERF); + my (@TSTATS); + my ($t_str, $pass_str); + + $pass_str = $okay ? "passed" : "*** FAILED ***"; + if ((0 != $subtests) && (!$okay)) + { + $pass_str = $pass_str . " ($failed_subtests/$subtests failed)"; + } + $pass_str = $pass_str . ' ' x (39 - length($pass_str)); + + if (-r "$test.perf") + { + if (!open (TEST_PERF, "<$opt_objdir/$test.perf")) + { + print STDERR "Unable to open \"$opt_objdir/$test.perf\"\n"; + exit 1; + } + $_ = ; + + ($hutime, $hstime) = split; + close TEST_PERF; + + $t_str = sprintf (" %7.2f %7.2f %7.2f %7.2f\n" + . " %s %7.2f %7.2f %7.2f %7.2f%%%%\n", + $utime, $stime, $utime + $stime, + ($utime + $stime) - ($hutime + $hstime), + $pass_str, + $hutime, $hstime, $hutime + $hstime, + (($hutime + $hstime) == 0.0) ? 0.0 : + ((($utime + $stime) - ($hutime + $hstime)) + / ($hutime + $hstime) * 100)); + } + else + { + $hutime = 0.0; + $hstime = 0.0; + + $t_str = sprintf (" %7.2f %7.2f %7.2f \n" + . " %s\n", + $utime, $stime, $utime + $stime, + $pass_str); + } + @TSTATS = ($t_str); + if (!$opt_quiet) + { + foreach $line (@TSTATS) + { + printf STDOUT "$line"; + } + } + + if ($okay && $opt_ustats) + { + if (!open (TEST_PERF, ">$opt_objdir/$test.perf")) + { + if (!$opt_quiet) + { + print STDERR "Unable to update \"$opt_objdir/$test.perf\"\n"; + } + } + else + { + print TEST_PERF "$utime $stime\n"; + close TEST_PERF; + } + } + + return ($hutime, $hstime); + } + + sub usage + { + print <] + + + Option | Description + --------------+------------------------------------------------------------- + -h --help | Print usage and exit. + -v --verbose | Verbose (incompatible with quiet). + -q --quiet | Quiet (incompatible with verbose). + -s --srcdir | Path to source tree (default is "."). + -o --objdir | Path to object tree (default is "."). + -u --ustats | Update historical statistics (stored in ".perf". + -z --zero | Consider non-zero exit code to be an error. + --------------+------------------------------------------------------------- + + If .exp exists, 's output is diff'ed with .exp. Any + difference is considered failure. + + If .exp does not exist, output to stdout of the following form is + expected: + + 1.. + {not }ok[ 1] + {not }ok[ 2] + ... + {not }ok[ n] + + 1 <= < 2^31 + + Lines which do not match the patterns shown above are ignored. + EOF + } Index: lib/libpthread/uthread/Makefile.inc =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/Makefile.inc Sun Sep 15 21:38:40 2002 *************** *** 0 **** --- 1,97 ---- + # $FreeBSD: src/lib/libc_r/uthread/Makefile.inc,v 1.33 2002/06/28 13:26:02 deischen Exp $ + + # uthread sources + .PATH: ${.CURDIR}/uthread + + SRCS+= \ + uthread_aio_suspend.c \ + uthread_attr_destroy.c \ + uthread_attr_init.c \ + uthread_attr_getdetachstate.c \ + uthread_attr_getguardsize.c \ + uthread_attr_getinheritsched.c \ + uthread_attr_getschedparam.c \ + uthread_attr_getschedpolicy.c \ + uthread_attr_getscope.c \ + uthread_attr_getstackaddr.c \ + uthread_attr_getstacksize.c \ + uthread_attr_setcreatesuspend_np.c \ + uthread_attr_setdetachstate.c \ + uthread_attr_setguardsize.c \ + uthread_attr_setinheritsched.c \ + uthread_attr_setschedparam.c \ + uthread_attr_setschedpolicy.c \ + uthread_attr_setscope.c \ + uthread_attr_setstackaddr.c \ + uthread_attr_setstacksize.c \ + uthread_autoinit.c \ + uthread_cancel.c \ + uthread_clean.c \ + uthread_close.c \ + uthread_cond.c \ + uthread_condattr_destroy.c \ + uthread_condattr_init.c \ + uthread_creat.c \ + uthread_create.c \ + uthread_detach.c \ + uthread_equal.c \ + uthread_exit.c \ + uthread_fcntl.c \ + uthread_find_thread.c \ + uthread_fork.c \ + uthread_fsync.c \ + uthread_gc.c \ + uthread_getprio.c \ + uthread_getschedparam.c \ + uthread_info.c \ + uthread_init.c \ + uthread_join.c \ + uthread_kern.c \ + uthread_kill.c \ + uthread_main_np.c \ + uthread_mattr_init.c \ + uthread_mattr_kind_np.c \ + uthread_msync.c \ + uthread_multi_np.c \ + uthread_mutex.c \ + uthread_mutex_prioceiling.c \ + uthread_mutex_protocol.c \ + uthread_mutexattr_destroy.c \ + uthread_nanosleep.c \ + uthread_once.c \ + uthread_open.c \ + uthread_pause.c \ + uthread_poll.c \ + uthread_priority_queue.c \ + uthread_printf.c \ + uthread_pselect.c \ + uthread_read.c \ + uthread_readv.c \ + uthread_resume_np.c \ + uthread_rwlock.c \ + uthread_rwlockattr.c \ + uthread_select.c \ + uthread_self.c \ + uthread_sem.c \ + uthread_seterrno.c \ + uthread_setprio.c \ + uthread_setschedparam.c \ + uthread_sigmask.c \ + uthread_sigsuspend.c \ + uthread_sigwait.c \ + uthread_single_np.c \ + uthread_sleep.c \ + uthread_spec.c \ + uthread_spinlock.c \ + uthread_stack.c \ + uthread_suspend_np.c \ + uthread_switch_np.c \ + uthread_system.c \ + uthread_tcdrain.c \ + uthread_vfork.c \ + uthread_wait.c \ + uthread_wait4.c \ + uthread_waitpid.c \ + uthread_write.c \ + uthread_writev.c \ + uthread_yield.c Index: lib/libpthread/uthread/pthread_private.h =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/pthread_private.h Sun Sep 15 21:38:41 2002 *************** *** 0 **** --- 1,1002 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Private thread definitions for the uthread kernel. + * + * $FreeBSD: src/lib/libc_r/uthread/pthread_private.h,v 1.73 2002/08/29 23:06:06 deischen Exp $ + */ + + #ifndef _PTHREAD_PRIVATE_H + #define _PTHREAD_PRIVATE_H + + /* + * Evaluate the storage class specifier. + */ + #ifdef GLOBAL_PTHREAD_PRIVATE + #define SCLASS + #else + #define SCLASS extern + #endif + + /* + * Include files. + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + /* + * Kernel fatal error handler macro. + */ + #define PANIC(string) _thread_exit(__FILE__,__LINE__,string) + + + /* Output debug messages like this: */ + #define stdout_debug(args...) _thread_printf( args ) + #define stderr_debug(args...) _thread_printf( args ) + + /* + * Priority queue manipulation macros (using pqe link): + */ + #define PTHREAD_PRIOQ_INSERT_HEAD(thrd) _pq_insert_head(&_readyq,thrd) + #define PTHREAD_PRIOQ_INSERT_TAIL(thrd) _pq_insert_tail(&_readyq,thrd) + #define PTHREAD_PRIOQ_REMOVE(thrd) _pq_remove(&_readyq,thrd) + #define PTHREAD_PRIOQ_FIRST() _pq_first(&_readyq) + + /* + * Waiting queue manipulation macros (using pqe link): + */ + #define PTHREAD_WAITQ_REMOVE(thrd) _waitq_remove(thrd) + #define PTHREAD_WAITQ_INSERT(thrd) _waitq_insert(thrd) + + #if defined(_PTHREADS_INVARIANTS) + #define PTHREAD_WAITQ_CLEARACTIVE() _waitq_clearactive() + #define PTHREAD_WAITQ_SETACTIVE() _waitq_setactive() + #else + #define PTHREAD_WAITQ_CLEARACTIVE() + #define PTHREAD_WAITQ_SETACTIVE() + #endif + + /* + * Work queue manipulation macros (using qe link): + */ + #define PTHREAD_WORKQ_INSERT(thrd) do { \ + TAILQ_INSERT_TAIL(&_workq,thrd,qe); \ + (thrd)->flags |= PTHREAD_FLAGS_IN_WORKQ; \ + } while (0) + #define PTHREAD_WORKQ_REMOVE(thrd) do { \ + TAILQ_REMOVE(&_workq,thrd,qe); \ + (thrd)->flags &= ~PTHREAD_FLAGS_IN_WORKQ; \ + } while (0) + + + /* + * State change macro without scheduling queue change: + */ + #define PTHREAD_SET_STATE(thrd, newstate) do { \ + (thrd)->state = newstate; \ + (thrd)->fname = __FILE__; \ + (thrd)->lineno = __LINE__; \ + } while (0) + + /* + * State change macro with scheduling queue change - This must be + * called with preemption deferred (see thread_kern_sched_[un]defer). + */ + #if defined(_PTHREADS_INVARIANTS) + #include + #define PTHREAD_ASSERT(cond, msg) do { \ + if (!(cond)) \ + PANIC(msg); \ + } while (0) + #define PTHREAD_ASSERT_NOT_IN_SYNCQ(thrd) \ + PTHREAD_ASSERT((((thrd)->flags & PTHREAD_FLAGS_IN_SYNCQ) == 0), \ + "Illegal call from signal handler"); + #define PTHREAD_NEW_STATE(thrd, newstate) do { \ + if (_thread_kern_new_state != 0) \ + PANIC("Recursive PTHREAD_NEW_STATE"); \ + _thread_kern_new_state = 1; \ + if ((thrd)->state != newstate) { \ + if ((thrd)->state == PS_RUNNING) { \ + PTHREAD_PRIOQ_REMOVE(thrd); \ + PTHREAD_SET_STATE(thrd, newstate); \ + PTHREAD_WAITQ_INSERT(thrd); \ + } else if (newstate == PS_RUNNING) { \ + PTHREAD_WAITQ_REMOVE(thrd); \ + PTHREAD_SET_STATE(thrd, newstate); \ + PTHREAD_PRIOQ_INSERT_TAIL(thrd); \ + } \ + } \ + _thread_kern_new_state = 0; \ + } while (0) + #else + #define PTHREAD_ASSERT(cond, msg) + #define PTHREAD_ASSERT_NOT_IN_SYNCQ(thrd) + #define PTHREAD_NEW_STATE(thrd, newstate) do { \ + if ((thrd)->state != newstate) { \ + if ((thrd)->state == PS_RUNNING) { \ + PTHREAD_PRIOQ_REMOVE(thrd); \ + PTHREAD_WAITQ_INSERT(thrd); \ + } else if (newstate == PS_RUNNING) { \ + PTHREAD_WAITQ_REMOVE(thrd); \ + PTHREAD_PRIOQ_INSERT_TAIL(thrd); \ + } \ + } \ + PTHREAD_SET_STATE(thrd, newstate); \ + } while (0) + #endif + + /* + * Priority queues. + * + * XXX It'd be nice if these were contained in uthread_priority_queue.[ch]. + */ + typedef struct pq_list { + TAILQ_HEAD(, pthread) pl_head; /* list of threads at this priority */ + TAILQ_ENTRY(pq_list) pl_link; /* link for queue of priority lists */ + int pl_prio; /* the priority of this list */ + int pl_queued; /* is this in the priority queue */ + } pq_list_t; + + typedef struct pq_queue { + TAILQ_HEAD(, pq_list) pq_queue; /* queue of priority lists */ + pq_list_t *pq_lists; /* array of all priority lists */ + int pq_size; /* number of priority lists */ + } pq_queue_t; + + + /* + * TailQ initialization values. + */ + #define TAILQ_INITIALIZER { NULL, NULL } + + /* + * Mutex definitions. + */ + union pthread_mutex_data { + void *m_ptr; + int m_count; + }; + + struct pthread_mutex { + enum pthread_mutextype m_type; + int m_protocol; + TAILQ_HEAD(mutex_head, pthread) m_queue; + struct pthread *m_owner; + union pthread_mutex_data m_data; + long m_flags; + int m_refcount; + + /* + * Used for priority inheritence and protection. + * + * m_prio - For priority inheritence, the highest active + * priority (threads locking the mutex inherit + * this priority). For priority protection, the + * ceiling priority of this mutex. + * m_saved_prio - mutex owners inherited priority before + * taking the mutex, restored when the owner + * unlocks the mutex. + */ + int m_prio; + int m_saved_prio; + + /* + * Link for list of all mutexes a thread currently owns. + */ + TAILQ_ENTRY(pthread_mutex) m_qe; + + /* + * Lock for accesses to this structure. + */ + spinlock_t lock; + }; + + /* + * Flags for mutexes. + */ + #define MUTEX_FLAGS_PRIVATE 0x01 + #define MUTEX_FLAGS_INITED 0x02 + #define MUTEX_FLAGS_BUSY 0x04 + + /* + * Static mutex initialization values. + */ + #define PTHREAD_MUTEX_STATIC_INITIALIZER \ + { PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, TAILQ_INITIALIZER, \ + NULL, { NULL }, MUTEX_FLAGS_PRIVATE, 0, 0, 0, TAILQ_INITIALIZER, \ + _SPINLOCK_INITIALIZER } + + struct pthread_mutex_attr { + enum pthread_mutextype m_type; + int m_protocol; + int m_ceiling; + long m_flags; + }; + + #define PTHREAD_MUTEXATTR_STATIC_INITIALIZER \ + { PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, MUTEX_FLAGS_PRIVATE } + + /* + * Condition variable definitions. + */ + enum pthread_cond_type { + COND_TYPE_FAST, + COND_TYPE_MAX + }; + + struct pthread_cond { + enum pthread_cond_type c_type; + TAILQ_HEAD(cond_head, pthread) c_queue; + pthread_mutex_t c_mutex; + void *c_data; + long c_flags; + int c_seqno; + + /* + * Lock for accesses to this structure. + */ + spinlock_t lock; + }; + + struct pthread_cond_attr { + enum pthread_cond_type c_type; + long c_flags; + }; + + /* + * Flags for condition variables. + */ + #define COND_FLAGS_PRIVATE 0x01 + #define COND_FLAGS_INITED 0x02 + #define COND_FLAGS_BUSY 0x04 + + /* + * Static cond initialization values. + */ + #define PTHREAD_COND_STATIC_INITIALIZER \ + { COND_TYPE_FAST, TAILQ_INITIALIZER, NULL, NULL, \ + 0, 0, _SPINLOCK_INITIALIZER } + + /* + * Semaphore definitions. + */ + struct sem { + #define SEM_MAGIC ((u_int32_t) 0x09fa4012) + u_int32_t magic; + pthread_mutex_t lock; + pthread_cond_t gtzero; + u_int32_t count; + u_int32_t nwaiters; + }; + + /* + * Cleanup definitions. + */ + struct pthread_cleanup { + struct pthread_cleanup *next; + void (*routine) (); + void *routine_arg; + }; + + struct pthread_attr { + int sched_policy; + int sched_inherit; + int sched_interval; + int prio; + int suspend; + int flags; + void *arg_attr; + void (*cleanup_attr) (); + void *stackaddr_attr; + size_t stacksize_attr; + size_t guardsize_attr; + }; + + /* + * Thread creation state attributes. + */ + #define PTHREAD_CREATE_RUNNING 0 + #define PTHREAD_CREATE_SUSPENDED 1 + + /* + * Miscellaneous definitions. + */ + #define PTHREAD_STACK_DEFAULT 65536 + /* + * Size of default red zone at the end of each stack. In actuality, this "red + * zone" is merely an unmapped region, except in the case of the initial stack. + * Since mmap() makes it possible to specify the maximum growth of a MAP_STACK + * region, an unmapped gap between thread stacks achieves the same effect as + * explicitly mapped red zones. + * This is declared and initialized in uthread_init.c. + */ + extern int _pthread_guard_default; + + extern int _pthread_page_size; + + /* + * Maximum size of initial thread's stack. This perhaps deserves to be larger + * than the stacks of other threads, since many applications are likely to run + * almost entirely on this stack. + */ + #define PTHREAD_STACK_INITIAL 0x100000 + + /* + * Define the different priority ranges. All applications have thread + * priorities constrained within 0-31. The threads library raises the + * priority when delivering signals in order to ensure that signal + * delivery happens (from the POSIX spec) "as soon as possible". + * In the future, the threads library will also be able to map specific + * threads into real-time (cooperating) processes or kernel threads. + * The RT and SIGNAL priorities will be used internally and added to + * thread base priorities so that the scheduling queue can handle both + * normal and RT priority threads with and without signal handling. + * + * The approach taken is that, within each class, signal delivery + * always has priority over thread execution. + */ + #define PTHREAD_DEFAULT_PRIORITY 15 + #define PTHREAD_MIN_PRIORITY 0 + #define PTHREAD_MAX_PRIORITY 31 /* 0x1F */ + #define PTHREAD_SIGNAL_PRIORITY 32 /* 0x20 */ + #define PTHREAD_RT_PRIORITY 64 /* 0x40 */ + #define PTHREAD_FIRST_PRIORITY PTHREAD_MIN_PRIORITY + #define PTHREAD_LAST_PRIORITY \ + (PTHREAD_MAX_PRIORITY + PTHREAD_SIGNAL_PRIORITY + PTHREAD_RT_PRIORITY) + #define PTHREAD_BASE_PRIORITY(prio) ((prio) & PTHREAD_MAX_PRIORITY) + + /* + * Clock resolution in microseconds. + */ + #define CLOCK_RES_USEC 10000 + #define CLOCK_RES_USEC_MIN 1000 + + /* + * Time slice period in microseconds. + */ + #define TIMESLICE_USEC 20000 + + /* + * Define a thread-safe macro to get the current time of day + * which is updated at regular intervals by the scheduling signal + * handler. + */ + #define GET_CURRENT_TOD(tv) \ + do { \ + tv.tv_sec = _sched_tod.tv_sec; \ + tv.tv_usec = _sched_tod.tv_usec; \ + } while (tv.tv_sec != _sched_tod.tv_sec) + + + struct pthread_rwlockattr { + int pshared; + }; + + struct pthread_rwlock { + pthread_mutex_t lock; /* monitor lock */ + int state; /* 0 = idle >0 = # of readers -1 = writer */ + pthread_cond_t read_signal; + pthread_cond_t write_signal; + int blocked_writers; + }; + + /* + * Thread states. + */ + enum pthread_state { + PS_RUNNING, + PS_MUTEX_WAIT, + PS_COND_WAIT, + PS_SLEEP_WAIT, + PS_WAIT_WAIT, + PS_SPINBLOCK, + PS_JOIN, + PS_SUSPENDED, + PS_DEAD, + PS_DEADLOCK, + PS_STATE_MAX + }; + + + /* + * File descriptor locking definitions. + */ + #define FD_READ 0x1 + #define FD_WRITE 0x2 + #define FD_RDWR (FD_READ | FD_WRITE) + + union pthread_wait_data { + pthread_mutex_t mutex; + pthread_cond_t cond; + spinlock_t *spinlock; + struct pthread *thread; + }; + + /* + * Define a continuation routine that can be used to perform a + * transfer of control: + */ + typedef void (*thread_continuation_t) (void *); + + struct join_status { + struct pthread *thread; + void *ret; + int error; + }; + + struct pthread_specific_elem { + const void *data; + int seqno; + }; + + /* + * Thread structure. + */ + struct pthread { + /* + * Magic value to help recognize a valid thread structure + * from an invalid one: + */ + #define PTHREAD_MAGIC ((u_int32_t) 0xd09ba115) + u_int32_t magic; + char *name; + u_int64_t uniqueid; /* for gdb */ + + /* + * Lock for accesses to this thread structure. + */ + spinlock_t lock; + + /* Queue entry for list of all threads: */ + TAILQ_ENTRY(pthread) tle; + + /* Queue entry for list of dead threads: */ + TAILQ_ENTRY(pthread) dle; + + /* + * Thread start routine, argument, stack pointer and thread + * attributes. + */ + void *(*start_routine)(void *); + void *arg; + void *stack; + struct pthread_attr attr; + + /* + * Machine context, including signal state. + */ + struct thread_mailbox mailbox; + + /* + * Cancelability flags - the lower 2 bits are used by cancel + * definitions in pthread.h + */ + #define PTHREAD_AT_CANCEL_POINT 0x0004 + #define PTHREAD_CANCELLING 0x0008 + #define PTHREAD_CANCEL_NEEDED 0x0010 + int cancelflags; + + thread_continuation_t continuation; + + /* Thread state: */ + enum pthread_state state; + + /* Scheduling clock when this thread was last made active. */ + long last_active; + + /* Scheduling clock when this thread was last made inactive. */ + long last_inactive; + + /* + * Number of microseconds accumulated by this thread when + * time slicing is active. + */ + long slice_usec; + + /* + * Time to wake up thread. This is used for sleeping threads and + * for any operation which may time out. + */ + struct timespec wakeup_time; + + /* TRUE if operation has timed out. */ + int timeout; + + /* + * Error variable used instead of errno. The function __error() + * returns a pointer to this. + */ + int error; + + /* + * The joiner is the thread that is joining to this thread. The + * join status keeps track of a join operation to another thread. + */ + struct pthread *joiner; + struct join_status join_status; + + /* + * The current thread can belong to only one scheduling queue at + * a time (ready or waiting queue). It can also belong to: + * + * o A queue of threads waiting for a mutex + * o A queue of threads waiting for a condition variable + * o A queue of threads waiting for a file descriptor lock + * o A queue of threads needing work done by the kernel thread + * (waiting for a spinlock or file I/O) + * + * A thread can also be joining a thread (the joiner field above). + * + * It must not be possible for a thread to belong to any of the + * above queues while it is handling a signal. Signal handlers + * may longjmp back to previous stack frames circumventing normal + * control flow. This could corrupt queue integrity if the thread + * retains membership in the queue. Therefore, if a thread is a + * member of one of these queues when a signal handler is invoked, + * it must remove itself from the queue before calling the signal + * handler and reinsert itself after normal return of the handler. + * + * Use pqe for the scheduling queue link (both ready and waiting), + * sqe for synchronization (mutex and condition variable) queue + * links, and qe for all other links. + */ + TAILQ_ENTRY(pthread) pqe; /* priority queue link */ + TAILQ_ENTRY(pthread) sqe; /* synchronization queue link */ + TAILQ_ENTRY(pthread) qe; /* all other queues link */ + + /* Wait data. */ + union pthread_wait_data data; + + /* + * Set to TRUE if a blocking operation was + * interrupted by a signal: + */ + int interrupted; + + /* + * Set to non-zero when this thread has deferred signals. + * We allow for recursive deferral. + */ + int sig_defer_count; + + /* Miscellaneous flags; only set with signals deferred. */ + int flags; + #define PTHREAD_FLAGS_PRIVATE 0x0001 + #define PTHREAD_EXITING 0x0002 + #define PTHREAD_FLAGS_IN_WAITQ 0x0004 /* in waiting queue using pqe link */ + #define PTHREAD_FLAGS_IN_PRIOQ 0x0008 /* in priority queue using pqe link */ + #define PTHREAD_FLAGS_IN_WORKQ 0x0010 /* in work queue using qe link */ + #define PTHREAD_FLAGS_IN_FILEQ 0x0020 /* in file lock queue using qe link */ + /* 0x0040 Unused. */ + #define PTHREAD_FLAGS_IN_CONDQ 0x0080 /* in condition queue using sqe link*/ + #define PTHREAD_FLAGS_IN_MUTEXQ 0x0100 /* in mutex queue using sqe link */ + #define PTHREAD_FLAGS_SUSPENDED 0x0200 /* thread is suspended */ + #define PTHREAD_FLAGS_TRACE 0x0400 /* for debugging purposes */ + #define PTHREAD_FLAGS_IN_SYNCQ \ + (PTHREAD_FLAGS_IN_CONDQ | PTHREAD_FLAGS_IN_MUTEXQ) + + /* + * Base priority is the user setable and retrievable priority + * of the thread. It is only affected by explicit calls to + * set thread priority and upon thread creation via a thread + * attribute or default priority. + */ + char base_priority; + + /* + * Inherited priority is the priority a thread inherits by + * taking a priority inheritence or protection mutex. It + * is not affected by base priority changes. Inherited + * priority defaults to and remains 0 until a mutex is taken + * that is being waited on by any other thread whose priority + * is non-zero. + */ + char inherited_priority; + + /* + * Active priority is always the maximum of the threads base + * priority and inherited priority. When there is a change + * in either the base or inherited priority, the active + * priority must be recalculated. + */ + char active_priority; + + /* Number of priority ceiling or protection mutexes owned. */ + int priority_mutex_count; + + /* + * Queue of currently owned mutexes. + */ + TAILQ_HEAD(, pthread_mutex) mutexq; + + void *ret; + struct pthread_specific_elem *specific; + int specific_data_count; + + /* Cleanup handlers Link List */ + struct pthread_cleanup *cleanup; + char *fname; /* Ptr to source file name */ + int lineno; /* Source line number. */ + }; + + /* + * Global variables for the uthread kernel. + */ + + SCLASS void *_usrstack + #ifdef GLOBAL_PTHREAD_PRIVATE + = (void *) USRSTACK; + #else + ; + #endif + + /* Kernel thread structure used when there are no running threads: */ + SCLASS struct pthread _thread_kern_thread; + + /* Ptr to the thread structure for the running thread: */ + SCLASS struct pthread * volatile _thread_run + #ifdef GLOBAL_PTHREAD_PRIVATE + = &_thread_kern_thread; + #else + ; + #endif + + /* Ptr to the thread structure for the last user thread to run: */ + SCLASS struct pthread * volatile _last_user_thread + #ifdef GLOBAL_PTHREAD_PRIVATE + = &_thread_kern_thread; + #else + ; + #endif + + /* List of all threads: */ + SCLASS TAILQ_HEAD(, pthread) _thread_list + #ifdef GLOBAL_PTHREAD_PRIVATE + = TAILQ_HEAD_INITIALIZER(_thread_list); + #else + ; + #endif + + /* Time of day at last scheduling timer signal: */ + SCLASS struct timeval volatile _sched_tod + #ifdef GLOBAL_PTHREAD_PRIVATE + = { 0, 0 }; + #else + ; + #endif + + /* + * Current scheduling timer ticks; used as resource usage. + */ + SCLASS unsigned int volatile _sched_ticks + #ifdef GLOBAL_PTHREAD_PRIVATE + = 0; + #else + ; + #endif + + /* Dead threads: */ + SCLASS TAILQ_HEAD(, pthread) _dead_list + #ifdef GLOBAL_PTHREAD_PRIVATE + = TAILQ_HEAD_INITIALIZER(_dead_list); + #else + ; + #endif + + /* Initial thread: */ + SCLASS struct pthread *_thread_initial + #ifdef GLOBAL_PTHREAD_PRIVATE + = NULL; + #else + ; + #endif + + /* Default thread attributes: */ + SCLASS struct pthread_attr pthread_attr_default + #ifdef GLOBAL_PTHREAD_PRIVATE + = { SCHED_RR, 0, TIMESLICE_USEC, PTHREAD_DEFAULT_PRIORITY, + PTHREAD_CREATE_RUNNING, PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, + PTHREAD_STACK_DEFAULT, -1 }; + #else + ; + #endif + + /* Default mutex attributes: */ + SCLASS struct pthread_mutex_attr pthread_mutexattr_default + #ifdef GLOBAL_PTHREAD_PRIVATE + = { PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, 0 }; + #else + ; + #endif + + /* Default condition variable attributes: */ + SCLASS struct pthread_cond_attr pthread_condattr_default + #ifdef GLOBAL_PTHREAD_PRIVATE + = { COND_TYPE_FAST, 0 }; + #else + ; + #endif + + SCLASS int _clock_res_usec /* Clock resolution in usec. */ + #ifdef GLOBAL_PTHREAD_PRIVATE + = CLOCK_RES_USEC; + #else + ; + #endif + + /* Garbage collector mutex and condition variable. */ + SCLASS pthread_mutex_t _gc_mutex + #ifdef GLOBAL_PTHREAD_PRIVATE + = NULL + #endif + ; + SCLASS pthread_cond_t _gc_cond + #ifdef GLOBAL_PTHREAD_PRIVATE + = NULL + #endif + ; + + /* + * Scheduling queues: + */ + SCLASS pq_queue_t _readyq; + SCLASS TAILQ_HEAD(, pthread) _waitingq; + + /* + * Work queue: + */ + SCLASS TAILQ_HEAD(, pthread) _workq; + + /* Tracks the number of threads blocked while waiting for a spinlock. */ + SCLASS volatile int _spinblock_count + #ifdef GLOBAL_PTHREAD_PRIVATE + = 0 + #endif + ; + + /* Thread switch hook. */ + SCLASS pthread_switch_routine_t _sched_switch_hook + #ifdef GLOBAL_PTHREAD_PRIVATE + = NULL + #endif + ; + + /* + * Declare the kernel scheduler jump buffer and stack: + */ + SCLASS struct kse_mailbox _thread_kern_kse_mailbox; + + SCLASS void * _thread_kern_sched_stack + #ifdef GLOBAL_PTHREAD_PRIVATE + = NULL + #endif + ; + + + /* Used for _PTHREADS_INVARIANTS checking. */ + SCLASS int _thread_kern_new_state + #ifdef GLOBAL_PTHREAD_PRIVATE + = 0 + #endif + ; + + /* Undefine the storage class specifier: */ + #undef SCLASS + + /* + * Function prototype definitions. + */ + __BEGIN_DECLS + char *__ttyname_basic(int); + char *__ttyname_r_basic(int, char *, size_t); + char *ttyname_r(int, char *, size_t); + void _cond_wait_backout(pthread_t); + int _find_thread(pthread_t); + struct pthread *_get_curthread(void); + void _set_curthread(struct pthread *); + void *_thread_stack_alloc(size_t, size_t); + void _thread_stack_free(void *, size_t, size_t); + int _thread_create(pthread_t *,const pthread_attr_t *,void *(*start_routine)(void *),void *,pthread_t); + int _mutex_cv_lock(pthread_mutex_t *); + int _mutex_cv_unlock(pthread_mutex_t *); + void _mutex_lock_backout(pthread_t); + void _mutex_notify_priochange(pthread_t); + int _mutex_reinit(pthread_mutex_t *); + void _mutex_unlock_private(pthread_t); + int _cond_reinit(pthread_cond_t *); + int _pq_alloc(struct pq_queue *, int, int); + int _pq_init(struct pq_queue *); + void _pq_remove(struct pq_queue *pq, struct pthread *); + void _pq_insert_head(struct pq_queue *pq, struct pthread *); + void _pq_insert_tail(struct pq_queue *pq, struct pthread *); + struct pthread *_pq_first(struct pq_queue *pq); + void *_pthread_getspecific(pthread_key_t); + int _pthread_key_create(pthread_key_t *, void (*) (void *)); + int _pthread_key_delete(pthread_key_t); + int _pthread_mutex_destroy(pthread_mutex_t *); + int _pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *); + int _pthread_mutex_lock(pthread_mutex_t *); + int _pthread_mutex_trylock(pthread_mutex_t *); + int _pthread_mutex_unlock(pthread_mutex_t *); + int _pthread_mutexattr_init(pthread_mutexattr_t *); + int _pthread_mutexattr_destroy(pthread_mutexattr_t *); + int _pthread_mutexattr_settype(pthread_mutexattr_t *, int); + int _pthread_once(pthread_once_t *, void (*) (void)); + pthread_t _pthread_self(void); + int _pthread_setspecific(pthread_key_t, const void *); + void _waitq_insert(pthread_t pthread); + void _waitq_remove(pthread_t pthread); + #if defined(_PTHREADS_INVARIANTS) + void _waitq_setactive(void); + void _waitq_clearactive(void); + #endif + void _thread_exit(char *, int, char *); + void _thread_exit_cleanup(void); + void *_thread_cleanup(pthread_t); + void _thread_cleanupspecific(void); + void _thread_dump_info(void); + void _thread_init(void); + void _thread_kern_sched(void); + void _thread_kern_scheduler(struct kse_mailbox *); + void _thread_kern_sched_state(enum pthread_state, char *fname, int lineno); + void _thread_kern_sched_state_unlock(enum pthread_state state, + spinlock_t *lock, char *fname, int lineno); + void _thread_kern_set_timeout(const struct timespec *); + void _thread_kern_sig_defer(void); + void _thread_kern_sig_undefer(void); + void _thread_printf(const char *, ...); + void _thread_start(void); + void _thread_seterrno(pthread_t, int); + int _thread_enter_uts(struct thread_mailbox *tm, struct kse_mailbox *km); + int _thread_switch(struct thread_mailbox *, struct thread_mailbox **); + pthread_addr_t _thread_gc(pthread_addr_t); + void _thread_enter_cancellation_point(void); + void _thread_leave_cancellation_point(void); + void _thread_cancellation_point(void); + + + /* #include */ + #ifdef _SYS_AIO_H_ + int __sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *); + #endif + + /* #include */ + #ifdef _SYS_EVENT_H_ + int __sys_kevent(int, const struct kevent *, int, struct kevent *, + int, const struct timespec *); + #endif + + /* #include */ + #ifdef _SYS_IOCTL_H_ + int __sys_ioctl(int, unsigned long, ...); + #endif + + /* #include */ + #ifdef _SYS_MMAN_H_ + int __sys_msync(void *, size_t, int); + #endif + + /* #include */ + #ifdef _SYS_MOUNT_H_ + int __sys_fstatfs(int, struct statfs *); + #endif + + /* #include */ + #ifdef _SYS_SOCKET_H_ + int __sys_accept(int, struct sockaddr *, socklen_t *); + int __sys_bind(int, const struct sockaddr *, socklen_t); + int __sys_connect(int, const struct sockaddr *, socklen_t); + int __sys_getpeername(int, struct sockaddr *, socklen_t *); + int __sys_getsockname(int, struct sockaddr *, socklen_t *); + int __sys_getsockopt(int, int, int, void *, socklen_t *); + int __sys_listen(int, int); + ssize_t __sys_recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *); + ssize_t __sys_recvmsg(int, struct msghdr *, int); + int __sys_sendfile(int, int, off_t, size_t, struct sf_hdtr *, off_t *, int); + ssize_t __sys_sendmsg(int, const struct msghdr *, int); + ssize_t __sys_sendto(int, const void *,size_t, int, const struct sockaddr *, socklen_t); + int __sys_setsockopt(int, int, int, const void *, socklen_t); + int __sys_shutdown(int, int); + int __sys_socket(int, int, int); + int __sys_socketpair(int, int, int, int *); + #endif + + /* #include */ + #ifdef _SYS_STAT_H_ + int __sys_fchflags(int, u_long); + int __sys_fchmod(int, mode_t); + int __sys_fstat(int, struct stat *); + #endif + + /* #include */ + #ifdef _SYS_UIO_H_ + ssize_t __sys_readv(int, const struct iovec *, int); + ssize_t __sys_writev(int, const struct iovec *, int); + #endif + + /* #include */ + #ifdef WNOHANG + pid_t __sys_wait4(pid_t, int *, int, struct rusage *); + #endif + + /* #include */ + #ifdef _DIRENT_H_ + int __sys_getdirentries(int, char *, int, long *); + #endif + + /* #include */ + #ifdef _SYS_FCNTL_H_ + int __sys_fcntl(int, int, ...); + int __sys_flock(int, int); + int __sys_open(const char *, int, ...); + #endif + + /* #include */ + #ifdef _SYS_POLL_H_ + int __sys_poll(struct pollfd *, unsigned, int); + #endif + + /* #include */ + #ifdef _SIGNAL_H_ + int __sys_sigaction(int, const struct sigaction *, struct sigaction *); + int __sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *); + int __sys_sigprocmask(int, const sigset_t *, sigset_t *); + int __sys_sigreturn(ucontext_t *); + #endif + + /* #include */ + #ifdef _UNISTD_H_ + int __sys_close(int); + int __sys_dup(int); + int __sys_dup2(int, int); + int __sys_execve(const char *, char * const *, char * const *); + void __sys_exit(int); + int __sys_fchown(int, uid_t, gid_t); + pid_t __sys_fork(void); + long __sys_fpathconf(int, int); + int __sys_fsync(int); + int __sys_pipe(int *); + ssize_t __sys_read(int, void *, size_t); + ssize_t __sys_write(int, const void *, size_t); + #endif + + __END_DECLS + + #endif /* !_PTHREAD_PRIVATE_H */ Index: lib/libpthread/uthread/uthread_aio_suspend.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_aio_suspend.c Sun Sep 15 21:38:41 2002 *************** *** 0 **** --- 1,50 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_aio_suspend.c,v 1.5 2001/04/10 04:19:19 deischen Exp $ + */ + + #include + #include + #include "pthread_private.h" + + __weak_reference(_aio_suspend, aio_suspend); + + int + _aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct + timespec *timeout) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __sys_aio_suspend(iocbs, niocb, timeout); + _thread_leave_cancellation_point(); + + return ret; + } + Index: lib/libpthread/uthread/uthread_attr_destroy.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_destroy.c Sun Sep 15 21:38:41 2002 *************** *** 0 **** --- 1,62 ---- + /* + * Copyright (c) 1996 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_destroy.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_destroy, pthread_attr_destroy); + + int + _pthread_attr_destroy(pthread_attr_t *attr) + { + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL) + /* Invalid argument: */ + ret = EINVAL; + else { + /* Free the memory allocated to the attribute object: */ + free(*attr); + + /* + * Leave the attribute pointer NULL now that the memory + * has been freed: + */ + *attr = NULL; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_getdetachstate.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_getdetachstate.c Sun Sep 15 21:38:41 2002 *************** *** 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_getdetachstate.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); + + int + _pthread_attr_getdetachstate(const 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); + } Index: lib/libpthread/uthread/uthread_attr_getguardsize.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_getguardsize.c Sun Sep 15 21:38:41 2002 *************** *** 0 **** --- 1,52 ---- + /* + * Copyright (C) 2001 Jason Evans . + * 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(s), this list of conditions and the following disclaimer + * unmodified other than the allowable addition of one or more + * copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_getguardsize.c,v 1.1 2001/07/20 04:23:10 jasone Exp $ + */ + + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); + + int + _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) + { + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || guardsize == NULL) + ret = EINVAL; + else { + /* Return the guard size: */ + *guardsize = (*attr)->guardsize_attr; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_getinheritsched.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_getinheritsched.c Sun Sep 15 21:38:42 2002 *************** *** 0 **** --- 1,51 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_getinheritsched.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); + + int + _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) + { + int ret = 0; + + if ((attr == NULL) || (*attr == NULL)) + ret = EINVAL; + else + *sched_inherit = (*attr)->sched_inherit; + + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_getschedparam.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_getschedparam.c Sun Sep 15 21:38:42 2002 *************** *** 0 **** --- 1,51 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_getschedparam.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); + + int + _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) + { + int ret = 0; + + if ((attr == NULL) || (*attr == NULL) || (param == NULL)) + ret = EINVAL; + else + param->sched_priority = (*attr)->prio; + + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_getschedpolicy.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_getschedpolicy.c Sun Sep 15 21:38:42 2002 *************** *** 0 **** --- 1,51 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_getschedpolicy.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); + + int + _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) + { + int ret = 0; + + if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) + ret = EINVAL; + else + *policy = (*attr)->sched_policy; + + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_getscope.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_getscope.c Sun Sep 15 21:38:42 2002 *************** *** 0 **** --- 1,54 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_getscope.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_getscope, pthread_attr_getscope); + + int + _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) + { + int ret = 0; + + if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) + /* Return an invalid argument: */ + ret = EINVAL; + + else + *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? + PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; + + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_getstackaddr.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_getstackaddr.c Sun Sep 15 21:38:42 2002 *************** *** 0 **** --- 1,54 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_getstackaddr.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); + + int + _pthread_attr_getstackaddr(const 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); + } Index: lib/libpthread/uthread/uthread_attr_getstacksize.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_getstacksize.c Sun Sep 15 21:38:43 2002 *************** *** 0 **** --- 1,54 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_getstacksize.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); + + int + _pthread_attr_getstacksize(const 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); + } Index: lib/libpthread/uthread/uthread_attr_init.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_init.c Sun Sep 15 21:38:43 2002 *************** *** 0 **** --- 1,61 ---- + /* + * Copyright (c) 1996 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_init.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_init, pthread_attr_init); + + int + _pthread_attr_init(pthread_attr_t *attr) + { + int ret; + pthread_attr_t pattr; + + /* Allocate memory for the attribute object: */ + if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) + /* Insufficient memory: */ + ret = ENOMEM; + else { + /* Initialise the attribute object with the defaults: */ + memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr)); + + /* Return a pointer to the attribute object: */ + *attr = pattr; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_setcreatesuspend_np.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setcreatesuspend_np.c Sun Sep 15 21:38:43 2002 *************** *** 0 **** --- 1,52 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c,v 1.5 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); + + int + _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) + { + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->suspend = PTHREAD_CREATE_SUSPENDED; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_setdetachstate.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setdetachstate.c Sun Sep 15 21:38:43 2002 *************** *** 0 **** --- 1,61 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setdetachstate.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); + + 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); + } Index: lib/libpthread/uthread/uthread_attr_setguardsize.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setguardsize.c Sun Sep 15 21:38:44 2002 *************** *** 0 **** --- 1,61 ---- + /* + * Copyright (C) 2001 Jason Evans . + * 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(s), this list of conditions and the following disclaimer + * unmodified other than the allowable addition of one or more + * copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setguardsize.c,v 1.3 2002/05/15 05:37:48 alfred Exp $ + */ + + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); + + int + _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) + { + int ret; + + /* Check for invalid arguments. */ + if (attr == NULL || *attr == NULL) + ret = EINVAL; + else { + /* + * Round guardsize up to the nearest multiple of + * _pthread_page_size. + */ + if (guardsize % _pthread_page_size != 0) + guardsize = ((guardsize / _pthread_page_size) + 1) * + _pthread_page_size; + + /* Save the stack size. */ + (*attr)->guardsize_attr = guardsize; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_setinheritsched.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setinheritsched.c Sun Sep 15 21:38:44 2002 *************** *** 0 **** --- 1,51 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setinheritsched.c,v 1.5 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); + + int + _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) + { + int ret = 0; + + if ((attr == NULL) || (*attr == NULL)) + ret = EINVAL; + else + (*attr)->sched_inherit = sched_inherit; + + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_setschedparam.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setschedparam.c Sun Sep 15 21:38:44 2002 *************** *** 0 **** --- 1,57 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setschedparam.c,v 1.8 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); + + int + _pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) + { + int ret = 0; + + if ((attr == NULL) || (*attr == NULL)) + ret = EINVAL; + else if (param == NULL) { + ret = ENOTSUP; + } else if ((param->sched_priority < PTHREAD_MIN_PRIORITY) || + (param->sched_priority > PTHREAD_MAX_PRIORITY)) { + /* Return an unsupported value error. */ + ret = ENOTSUP; + } else + (*attr)->prio = param->sched_priority; + + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_setschedpolicy.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setschedpolicy.c Sun Sep 15 21:38:44 2002 *************** *** 0 **** --- 1,53 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setschedpolicy.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); + + int + _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) + { + int ret = 0; + + if ((attr == NULL) || (*attr == NULL)) + ret = EINVAL; + else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { + ret = ENOTSUP; + } else + (*attr)->sched_policy = policy; + + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_setscope.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setscope.c Sun Sep 15 21:38:44 2002 *************** *** 0 **** --- 1,56 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setscope.c,v 1.7 2002/02/14 15:20:36 maxim Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setscope, pthread_attr_setscope); + + int + _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) + { + int ret = 0; + + if ((attr == NULL) || (*attr == NULL)) { + /* Return an invalid argument: */ + ret = EINVAL; + } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) || + (contentionscope == PTHREAD_SCOPE_SYSTEM)) { + /* We don't support PTHREAD_SCOPE_SYSTEM. */ + ret = ENOTSUP; + } else + (*attr)->flags |= contentionscope; + + return(ret); + } Index: lib/libpthread/uthread/uthread_attr_setstackaddr.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setstackaddr.c Sun Sep 15 21:38:45 2002 *************** *** 0 **** --- 1,54 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setstackaddr.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); + + 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); + } Index: lib/libpthread/uthread/uthread_attr_setstacksize.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_attr_setstacksize.c Sun Sep 15 21:38:45 2002 *************** *** 0 **** --- 1,54 ---- + /* + * Copyright (c) 1996 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_attr_setstacksize.c,v 1.7 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); + + int + _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) + { + int ret; + + /* Check for invalid arguments: */ + if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) + ret = EINVAL; + else { + /* Save the stack size: */ + (*attr)->stacksize_attr = stacksize; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_autoinit.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_autoinit.c Sun Sep 15 21:38:45 2002 *************** *** 0 **** --- 1,61 ---- + /* + * Copyright (c) 2002 Alfred Perlstein . + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_autoinit.c,v 1.1 2002/05/11 08:13:42 alfred Exp $ + */ + + /* + * This module uses GCC extentions to initialize the + * threads package at program start-up time. + */ + + void _thread_init_hack(void) __attribute__ ((constructor)); + + void + _thread_init_hack(void) + { + + _thread_init(); + } + + /* + * For the shared version of the threads library, the above is sufficient. + * But for the archive version of the library, we need a little bit more. + * Namely, we must arrange for this particular module to be pulled in from + * the archive library at link time. To accomplish that, we define and + * initialize a variable, "_thread_autoinit_dummy_decl". This variable is + * referenced (as an extern) from libc/stdlib/exit.c. This will always + * create a need for this module, ensuring that it is present in the + * executable. + */ + extern int _thread_autoinit_dummy_decl; + int _thread_autoinit_dummy_decl = 0; Index: lib/libpthread/uthread/uthread_cancel.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_cancel.c Sun Sep 15 21:38:45 2002 *************** *** 0 **** --- 1,221 ---- + /* + * David Leonard , 1999. Public domain. + * $FreeBSD: src/lib/libc_r/uthread/uthread_cancel.c,v 1.14 2002/05/24 04:32:28 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + static void finish_cancellation(void *arg); + + __weak_reference(_pthread_cancel, pthread_cancel); + __weak_reference(_pthread_setcancelstate, pthread_setcancelstate); + __weak_reference(_pthread_setcanceltype, pthread_setcanceltype); + __weak_reference(_pthread_testcancel, pthread_testcancel); + + int + _pthread_cancel(pthread_t pthread) + { + int ret; + + if ((ret = _find_thread(pthread)) != 0) { + /* NOTHING */ + } else if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK + || (pthread->flags & PTHREAD_EXITING) != 0) { + ret = 0; + } else { + /* Protect the scheduling queues: */ + _thread_kern_sig_defer(); + + if (((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) || + (((pthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) == 0) && + ((pthread->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0))) + /* Just mark it for cancellation: */ + pthread->cancelflags |= PTHREAD_CANCELLING; + else { + /* + * Check if we need to kick it back into the + * run queue: + */ + switch (pthread->state) { + case PS_RUNNING: + /* No need to resume: */ + pthread->cancelflags |= PTHREAD_CANCELLING; + break; + + case PS_SPINBLOCK: + /* Remove these threads from the work queue: */ + if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + != 0) + PTHREAD_WORKQ_REMOVE(pthread); + /* Fall through: */ + case PS_SLEEP_WAIT: + case PS_WAIT_WAIT: + /* Interrupt and resume: */ + pthread->interrupted = 1; + pthread->cancelflags |= PTHREAD_CANCELLING; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + break; + + case PS_JOIN: + /* + * Disconnect the thread from the joinee: + */ + if (pthread->join_status.thread != NULL) { + pthread->join_status.thread->joiner + = NULL; + pthread->join_status.thread = NULL; + } + pthread->cancelflags |= PTHREAD_CANCELLING; + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + break; + + case PS_SUSPENDED: + case PS_MUTEX_WAIT: + case PS_COND_WAIT: + /* + * Threads in these states may be in queues. + * In order to preserve queue integrity, the + * cancelled thread must remove itself from the + * queue. Mark the thread as interrupted and + * needing cancellation, and set the state to + * running. When the thread resumes, it will + * remove itself from the queue and call the + * cancellation completion routine. + */ + pthread->interrupted = 1; + pthread->cancelflags |= PTHREAD_CANCEL_NEEDED; + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + pthread->continuation = finish_cancellation; + break; + + case PS_DEAD: + case PS_DEADLOCK: + case PS_STATE_MAX: + /* Ignore - only here to silence -Wall: */ + break; + } + } + + /* Unprotect the scheduling queues: */ + _thread_kern_sig_undefer(); + + ret = 0; + } + return (ret); + } + + int + _pthread_setcancelstate(int state, int *oldstate) + { + struct pthread *curthread = _get_curthread(); + int ostate; + int ret; + + ostate = curthread->cancelflags & PTHREAD_CANCEL_DISABLE; + + switch (state) { + case PTHREAD_CANCEL_ENABLE: + if (oldstate != NULL) + *oldstate = ostate; + curthread->cancelflags &= ~PTHREAD_CANCEL_DISABLE; + if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0) + pthread_testcancel(); + ret = 0; + break; + case PTHREAD_CANCEL_DISABLE: + if (oldstate != NULL) + *oldstate = ostate; + curthread->cancelflags |= PTHREAD_CANCEL_DISABLE; + ret = 0; + break; + default: + ret = EINVAL; + } + + return (ret); + } + + int + _pthread_setcanceltype(int type, int *oldtype) + { + struct pthread *curthread = _get_curthread(); + int otype; + int ret; + + otype = curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS; + switch (type) { + case PTHREAD_CANCEL_ASYNCHRONOUS: + if (oldtype != NULL) + *oldtype = otype; + curthread->cancelflags |= PTHREAD_CANCEL_ASYNCHRONOUS; + pthread_testcancel(); + ret = 0; + break; + case PTHREAD_CANCEL_DEFERRED: + if (oldtype != NULL) + *oldtype = otype; + curthread->cancelflags &= ~PTHREAD_CANCEL_ASYNCHRONOUS; + ret = 0; + break; + default: + ret = EINVAL; + } + + return (ret); + } + + void + _pthread_testcancel(void) + { + struct pthread *curthread = _get_curthread(); + + if (((curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) && + ((curthread->cancelflags & PTHREAD_CANCELLING) != 0) && + ((curthread->flags & PTHREAD_EXITING) == 0)) { + /* + * It is possible for this thread to be swapped out + * while performing cancellation; do not allow it + * to be cancelled again. + */ + curthread->cancelflags &= ~PTHREAD_CANCELLING; + _thread_exit_cleanup(); + pthread_exit(PTHREAD_CANCELED); + PANIC("cancel"); + } + } + + void + _thread_enter_cancellation_point(void) + { + struct pthread *curthread = _get_curthread(); + + /* Look for a cancellation before we block: */ + pthread_testcancel(); + curthread->cancelflags |= PTHREAD_AT_CANCEL_POINT; + } + + void + _thread_leave_cancellation_point(void) + { + struct pthread *curthread = _get_curthread(); + + curthread->cancelflags &= ~PTHREAD_AT_CANCEL_POINT; + /* Look for a cancellation after we unblock: */ + pthread_testcancel(); + } + + static void + finish_cancellation(void *arg) + { + struct pthread *curthread = _get_curthread(); + + curthread->continuation = NULL; + curthread->interrupted = 0; + + if ((curthread->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) { + curthread->cancelflags &= ~PTHREAD_CANCEL_NEEDED; + _thread_exit_cleanup(); + pthread_exit(PTHREAD_CANCELED); + } + } Index: lib/libpthread/uthread/uthread_clean.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_clean.c Sun Sep 15 21:38:45 2002 *************** *** 0 **** --- 1,72 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_clean.c,v 1.6 2001/04/10 04:19:19 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_cleanup_push, pthread_cleanup_push); + __weak_reference(_pthread_cleanup_pop, pthread_cleanup_pop); + + void + _pthread_cleanup_push(void (*routine) (void *), void *routine_arg) + { + struct pthread *curthread = _get_curthread(); + struct pthread_cleanup *new; + + if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) { + new->routine = routine; + new->routine_arg = routine_arg; + new->next = curthread->cleanup; + + curthread->cleanup = new; + } + } + + void + _pthread_cleanup_pop(int execute) + { + struct pthread *curthread = _get_curthread(); + struct pthread_cleanup *old; + + if ((old = curthread->cleanup) != NULL) { + curthread->cleanup = old->next; + if (execute) { + old->routine(old->routine_arg); + } + free(old); + } + } + Index: lib/libpthread/uthread/uthread_close.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_close.c Sun Sep 15 21:38:46 2002 *************** *** 0 **** --- 1,54 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_close.c,v 1.13 2002/08/29 23:06:06 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__close, close); + + int + __close(int fd) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __sys_close(fd); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_cond.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_cond.c Sun Sep 15 21:38:46 2002 *************** *** 0 **** --- 1,735 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_cond.c,v 1.33 2002/05/24 04:32:28 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + /* + * Prototypes + */ + static inline pthread_t cond_queue_deq(pthread_cond_t); + static inline void cond_queue_remove(pthread_cond_t, pthread_t); + static inline void cond_queue_enq(pthread_cond_t, pthread_t); + + __weak_reference(_pthread_cond_init, pthread_cond_init); + __weak_reference(_pthread_cond_destroy, pthread_cond_destroy); + __weak_reference(_pthread_cond_wait, pthread_cond_wait); + __weak_reference(_pthread_cond_timedwait, pthread_cond_timedwait); + __weak_reference(_pthread_cond_signal, pthread_cond_signal); + __weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast); + + + /* Reinitialize a condition variable to defaults. */ + int + _cond_reinit(pthread_cond_t *cond) + { + int ret = 0; + + if (cond == NULL) + ret = EINVAL; + else if (*cond == NULL) + ret = pthread_cond_init(cond, NULL); + else { + /* + * Initialize the condition variable structure: + */ + TAILQ_INIT(&(*cond)->c_queue); + (*cond)->c_flags = COND_FLAGS_INITED; + (*cond)->c_type = COND_TYPE_FAST; + (*cond)->c_mutex = NULL; + (*cond)->c_seqno = 0; + memset(&(*cond)->lock, 0, sizeof((*cond)->lock)); + } + return (ret); + } + + int + _pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) + { + enum pthread_cond_type type; + pthread_cond_t pcond; + int rval = 0; + + if (cond == NULL) + rval = EINVAL; + else { + /* + * Check if a pointer to a condition variable attribute + * structure was passed by the caller: + */ + if (cond_attr != NULL && *cond_attr != NULL) { + /* Default to a fast condition variable: */ + type = (*cond_attr)->c_type; + } else { + /* Default to a fast condition variable: */ + type = COND_TYPE_FAST; + } + + /* Process according to condition variable type: */ + switch (type) { + /* Fast condition variable: */ + case COND_TYPE_FAST: + /* Nothing to do here. */ + break; + + /* Trap invalid condition variable types: */ + default: + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + /* Check for no errors: */ + if (rval == 0) { + if ((pcond = (pthread_cond_t) + malloc(sizeof(struct pthread_cond))) == NULL) { + rval = ENOMEM; + } else { + /* + * Initialise the condition variable + * structure: + */ + TAILQ_INIT(&pcond->c_queue); + pcond->c_flags |= COND_FLAGS_INITED; + pcond->c_type = type; + pcond->c_mutex = NULL; + pcond->c_seqno = 0; + memset(&pcond->lock,0,sizeof(pcond->lock)); + *cond = pcond; + } + } + } + /* Return the completion status: */ + return (rval); + } + + int + _pthread_cond_destroy(pthread_cond_t *cond) + { + int rval = 0; + + if (cond == NULL || *cond == NULL) + rval = EINVAL; + else { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* + * Free the memory allocated for the condition + * variable structure: + */ + free(*cond); + + /* + * NULL the caller's pointer now that the condition + * variable has been destroyed: + */ + *cond = NULL; + } + /* Return the completion status: */ + return (rval); + } + + int + _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) + { + struct pthread *curthread = _get_curthread(); + int rval = 0; + int done = 0; + int interrupted = 0; + int seqno; + + _thread_enter_cancellation_point(); + + if (cond == NULL) + return (EINVAL); + + /* + * If the condition variable is statically initialized, + * perform the dynamic initialization: + */ + if (*cond == NULL && + (rval = pthread_cond_init(cond, NULL)) != 0) + return (rval); + + /* + * Enter a loop waiting for a condition signal or broadcast + * to wake up this thread. A loop is needed in case the waiting + * thread is interrupted by a signal to execute a signal handler. + * It is not (currently) possible to remain in the waiting queue + * while running a handler. Instead, the thread is interrupted + * and backed out of the waiting queue prior to executing the + * signal handler. + */ + do { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* + * If the condvar was statically allocated, properly + * initialize the tail queue. + */ + if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) { + TAILQ_INIT(&(*cond)->c_queue); + (*cond)->c_flags |= COND_FLAGS_INITED; + } + + /* Process according to condition variable type: */ + switch ((*cond)->c_type) { + /* Fast condition variable: */ + case COND_TYPE_FAST: + if ((mutex == NULL) || (((*cond)->c_mutex != NULL) && + ((*cond)->c_mutex != *mutex))) { + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + + /* Return invalid argument error: */ + rval = EINVAL; + } else { + /* Reset the timeout and interrupted flags: */ + curthread->timeout = 0; + curthread->interrupted = 0; + + /* + * Queue the running thread for the condition + * variable: + */ + cond_queue_enq(*cond, curthread); + + /* Remember the mutex and sequence number: */ + (*cond)->c_mutex = *mutex; + seqno = (*cond)->c_seqno; + + /* Wait forever: */ + curthread->wakeup_time.tv_sec = -1; + + /* Unlock the mutex: */ + if ((rval = _mutex_cv_unlock(mutex)) != 0) { + /* + * Cannot unlock the mutex, so remove + * the running thread from the condition + * variable queue: + */ + cond_queue_remove(*cond, curthread); + + /* Check for no more waiters: */ + if (TAILQ_FIRST(&(*cond)->c_queue) == + NULL) + (*cond)->c_mutex = NULL; + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + } else { + /* + * Schedule the next thread and unlock + * the condition variable structure: + */ + _thread_kern_sched_state_unlock(PS_COND_WAIT, + &(*cond)->lock, __FILE__, __LINE__); + + done = (seqno != (*cond)->c_seqno); + + interrupted = curthread->interrupted; + + /* + * Check if the wait was interrupted + * (canceled) or needs to be resumed + * after handling a signal. + */ + if (interrupted != 0) { + /* + * Lock the mutex and ignore any + * errors. Note that even + * though this thread may have + * been canceled, POSIX requires + * that the mutex be reaquired + * prior to cancellation. + */ + (void)_mutex_cv_lock(mutex); + } else { + /* + * Lock the condition variable + * while removing the thread. + */ + _SPINLOCK(&(*cond)->lock); + + cond_queue_remove(*cond, + curthread); + + /* Check for no more waiters: */ + if (TAILQ_FIRST(&(*cond)->c_queue) == NULL) + (*cond)->c_mutex = NULL; + + _SPINUNLOCK(&(*cond)->lock); + + /* Lock the mutex: */ + rval = _mutex_cv_lock(mutex); + } + } + } + break; + + /* Trap invalid condition variable types: */ + default: + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + if ((interrupted != 0) && (curthread->continuation != NULL)) + curthread->continuation((void *) curthread); + } while ((done == 0) && (rval == 0)); + + _thread_leave_cancellation_point(); + + /* Return the completion status: */ + return (rval); + } + + int + _pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, + const struct timespec * abstime) + { + struct pthread *curthread = _get_curthread(); + int rval = 0; + int done = 0; + int interrupted = 0; + int seqno; + + _thread_enter_cancellation_point(); + + if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 || + abstime->tv_nsec >= 1000000000) + return (EINVAL); + /* + * If the condition variable is statically initialized, perform dynamic + * initialization. + */ + if (*cond == NULL && (rval = pthread_cond_init(cond, NULL)) != 0) + return (rval); + + /* + * Enter a loop waiting for a condition signal or broadcast + * to wake up this thread. A loop is needed in case the waiting + * thread is interrupted by a signal to execute a signal handler. + * It is not (currently) possible to remain in the waiting queue + * while running a handler. Instead, the thread is interrupted + * and backed out of the waiting queue prior to executing the + * signal handler. + */ + do { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* + * If the condvar was statically allocated, properly + * initialize the tail queue. + */ + if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) { + TAILQ_INIT(&(*cond)->c_queue); + (*cond)->c_flags |= COND_FLAGS_INITED; + } + + /* Process according to condition variable type: */ + switch ((*cond)->c_type) { + /* Fast condition variable: */ + case COND_TYPE_FAST: + if ((mutex == NULL) || (((*cond)->c_mutex != NULL) && + ((*cond)->c_mutex != *mutex))) { + /* Return invalid argument error: */ + rval = EINVAL; + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + } else { + /* Set the wakeup time: */ + curthread->wakeup_time.tv_sec = + abstime->tv_sec; + curthread->wakeup_time.tv_nsec = + abstime->tv_nsec; + + /* Reset the timeout and interrupted flags: */ + curthread->timeout = 0; + curthread->interrupted = 0; + + /* + * Queue the running thread for the condition + * variable: + */ + cond_queue_enq(*cond, curthread); + + /* Remember the mutex and sequence number: */ + (*cond)->c_mutex = *mutex; + seqno = (*cond)->c_seqno; + + /* Unlock the mutex: */ + if ((rval = _mutex_cv_unlock(mutex)) != 0) { + /* + * Cannot unlock the mutex, so remove + * the running thread from the condition + * variable queue: + */ + cond_queue_remove(*cond, curthread); + + /* Check for no more waiters: */ + if (TAILQ_FIRST(&(*cond)->c_queue) == NULL) + (*cond)->c_mutex = NULL; + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + } else { + /* + * Schedule the next thread and unlock + * the condition variable structure: + */ + _thread_kern_sched_state_unlock(PS_COND_WAIT, + &(*cond)->lock, __FILE__, __LINE__); + + done = (seqno != (*cond)->c_seqno); + + interrupted = curthread->interrupted; + + /* + * Check if the wait was interrupted + * (canceled) or needs to be resumed + * after handling a signal. + */ + if (interrupted != 0) { + /* + * Lock the mutex and ignore any + * errors. Note that even + * though this thread may have + * been canceled, POSIX requires + * that the mutex be reaquired + * prior to cancellation. + */ + (void)_mutex_cv_lock(mutex); + } else { + /* + * Lock the condition variable + * while removing the thread. + */ + _SPINLOCK(&(*cond)->lock); + + cond_queue_remove(*cond, + curthread); + + /* Check for no more waiters: */ + if (TAILQ_FIRST(&(*cond)->c_queue) == NULL) + (*cond)->c_mutex = NULL; + + _SPINUNLOCK(&(*cond)->lock); + + /* Lock the mutex: */ + rval = _mutex_cv_lock(mutex); + + /* + * Return ETIMEDOUT if the wait + * timed out and there wasn't an + * error locking the mutex: + */ + if ((curthread->timeout != 0) + && rval == 0) + rval = ETIMEDOUT; + + } + } + } + break; + + /* Trap invalid condition variable types: */ + default: + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + if ((interrupted != 0) && (curthread->continuation != NULL)) + curthread->continuation((void *) curthread); + } while ((done == 0) && (rval == 0)); + + _thread_leave_cancellation_point(); + + /* Return the completion status: */ + return (rval); + } + + int + _pthread_cond_signal(pthread_cond_t * cond) + { + int rval = 0; + pthread_t pthread; + + if (cond == NULL) + rval = EINVAL; + /* + * If the condition variable is statically initialized, perform dynamic + * initialization. + */ + else if (*cond != NULL || (rval = pthread_cond_init(cond, NULL)) == 0) { + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* Process according to condition variable type: */ + switch ((*cond)->c_type) { + /* Fast condition variable: */ + case COND_TYPE_FAST: + /* Increment the sequence number: */ + (*cond)->c_seqno++; + + if ((pthread = cond_queue_deq(*cond)) != NULL) { + /* + * Wake up the signaled thread: + */ + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + } + + /* Check for no more waiters: */ + if (TAILQ_FIRST(&(*cond)->c_queue) == NULL) + (*cond)->c_mutex = NULL; + break; + + /* Trap invalid condition variable types: */ + default: + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + + /* Return the completion status: */ + return (rval); + } + + int + _pthread_cond_broadcast(pthread_cond_t * cond) + { + int rval = 0; + pthread_t pthread; + + if (cond == NULL) + rval = EINVAL; + /* + * If the condition variable is statically initialized, perform dynamic + * initialization. + */ + else if (*cond != NULL || (rval = pthread_cond_init(cond, NULL)) == 0) { + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + + /* Process according to condition variable type: */ + switch ((*cond)->c_type) { + /* Fast condition variable: */ + case COND_TYPE_FAST: + /* Increment the sequence number: */ + (*cond)->c_seqno++; + + /* + * Enter a loop to bring all threads off the + * condition queue: + */ + while ((pthread = cond_queue_deq(*cond)) != NULL) { + /* + * Wake up the signaled thread: + */ + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + } + + /* There are no more waiting threads: */ + (*cond)->c_mutex = NULL; + break; + + /* Trap invalid condition variable types: */ + default: + /* Return an invalid argument error: */ + rval = EINVAL; + break; + } + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&(*cond)->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + + /* Return the completion status: */ + return (rval); + } + + void + _cond_wait_backout(pthread_t pthread) + { + pthread_cond_t cond; + + cond = pthread->data.cond; + if (cond != NULL) { + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the condition variable structure: */ + _SPINLOCK(&cond->lock); + + /* Process according to condition variable type: */ + switch (cond->c_type) { + /* Fast condition variable: */ + case COND_TYPE_FAST: + cond_queue_remove(cond, pthread); + + /* Check for no more waiters: */ + if (TAILQ_FIRST(&cond->c_queue) == NULL) + cond->c_mutex = NULL; + break; + + default: + break; + } + + /* Unlock the condition variable structure: */ + _SPINUNLOCK(&cond->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + } + + /* + * Dequeue a waiting thread from the head of a condition queue in + * descending priority order. + */ + static inline pthread_t + cond_queue_deq(pthread_cond_t cond) + { + pthread_t pthread; + + while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) { + TAILQ_REMOVE(&cond->c_queue, pthread, sqe); + pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ; + if ((pthread->timeout == 0) && (pthread->interrupted == 0)) + /* + * Only exit the loop when we find a thread + * that hasn't timed out or been canceled; + * those threads are already running and don't + * need their run state changed. + */ + break; + } + + return(pthread); + } + + /* + * Remove a waiting thread from a condition queue in descending priority + * order. + */ + static inline void + cond_queue_remove(pthread_cond_t cond, pthread_t pthread) + { + /* + * Because pthread_cond_timedwait() can timeout as well + * as be signaled by another thread, it is necessary to + * guard against removing the thread from the queue if + * it isn't in the queue. + */ + if (pthread->flags & PTHREAD_FLAGS_IN_CONDQ) { + TAILQ_REMOVE(&cond->c_queue, pthread, sqe); + pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ; + } + } + + /* + * Enqueue a waiting thread to a condition queue in descending priority + * order. + */ + static inline void + cond_queue_enq(pthread_cond_t cond, pthread_t pthread) + { + pthread_t tid = TAILQ_LAST(&cond->c_queue, cond_head); + + PTHREAD_ASSERT_NOT_IN_SYNCQ(pthread); + + /* + * For the common case of all threads having equal priority, + * we perform a quick check against the priority of the thread + * at the tail of the queue. + */ + if ((tid == NULL) || (pthread->active_priority <= tid->active_priority)) + TAILQ_INSERT_TAIL(&cond->c_queue, pthread, sqe); + else { + tid = TAILQ_FIRST(&cond->c_queue); + while (pthread->active_priority <= tid->active_priority) + tid = TAILQ_NEXT(tid, sqe); + TAILQ_INSERT_BEFORE(tid, pthread, sqe); + } + pthread->flags |= PTHREAD_FLAGS_IN_CONDQ; + pthread->data.cond = cond; + } Index: lib/libpthread/uthread/uthread_condattr_destroy.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_condattr_destroy.c Sun Sep 15 21:38:46 2002 *************** *** 0 **** --- 1,53 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_condattr_destroy.c,v 1.6 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_condattr_destroy, pthread_condattr_destroy); + + int + _pthread_condattr_destroy(pthread_condattr_t *attr) + { + int ret; + if (attr == NULL || *attr == NULL) { + ret = EINVAL; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_condattr_init.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_condattr_init.c Sun Sep 15 21:38:46 2002 *************** *** 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_condattr_init.c,v 1.6 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_condattr_init, pthread_condattr_init); + + int + _pthread_condattr_init(pthread_condattr_t *attr) + { + int ret; + pthread_condattr_t pattr; + + if ((pattr = (pthread_condattr_t) + malloc(sizeof(struct pthread_cond_attr))) == NULL) { + ret = ENOMEM; + } else { + memcpy(pattr, &pthread_condattr_default, + sizeof(struct pthread_cond_attr)); + *attr = pattr; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_creat.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_creat.c Sun Sep 15 21:38:47 2002 *************** *** 0 **** --- 1,48 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_creat.c,v 1.4 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include + #include "pthread_private.h" + + __weak_reference(___creat, creat); + + int + ___creat(const char *path, mode_t mode) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __creat(path, mode); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_create.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_create.c Sun Sep 15 21:38:47 2002 *************** *** 0 **** --- 1,240 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_create.c,v 1.34 2002/07/09 13:24:52 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + #include "libc_private.h" + + static u_int64_t next_uniqueid = 1; + + #define OFF(f) offsetof(struct pthread, f) + int _thread_next_offset = OFF(tle.tqe_next); + int _thread_uniqueid_offset = OFF(uniqueid); + int _thread_state_offset = OFF(state); + int _thread_name_offset = OFF(name); + int _thread_ctx_offset = OFF(mailbox.tm_context); + #undef OFF + + int _thread_PS_RUNNING_value = PS_RUNNING; + int _thread_PS_DEAD_value = PS_DEAD; + + __weak_reference(_pthread_create, pthread_create); + + int + _pthread_create(pthread_t * thread, const pthread_attr_t * attr, + void *(*start_routine) (void *), void *arg) + { + struct pthread *curthread = _get_curthread(); + struct itimerval itimer; + int f_gc = 0; + int ret = 0; + pthread_t gc_thread; + pthread_t new_thread; + pthread_attr_t pattr; + void *stack; + + /* + * Locking functions in libc are required when there are + * threads other than the initial thread. + */ + __isthreaded = 1; + + /* Allocate memory for the thread structure: */ + if ((new_thread = (pthread_t) malloc(sizeof(struct pthread))) == NULL) { + /* Insufficient memory to create a thread: */ + ret = EAGAIN; + } else { + /* Check if default thread attributes are required: */ + if (attr == NULL || *attr == NULL) { + /* Use the default thread attributes: */ + pattr = &pthread_attr_default; + } else { + pattr = *attr; + } + /* Check if a stack was specified in the thread attributes: */ + if ((stack = pattr->stackaddr_attr) != NULL) { + } + /* Allocate a stack: */ + else { + stack = _thread_stack_alloc(pattr->stacksize_attr, + pattr->guardsize_attr); + if (stack == NULL) { + ret = EAGAIN; + free(new_thread); + } + } + + /* Check for errors: */ + if (ret != 0) { + } else { + /* Initialise the thread structure: */ + memset(new_thread, 0, sizeof(struct pthread)); + new_thread->slice_usec = -1; + new_thread->stack = stack; + new_thread->start_routine = start_routine; + new_thread->arg = arg; + + new_thread->cancelflags = PTHREAD_CANCEL_ENABLE | + PTHREAD_CANCEL_DEFERRED; + + /* + * Write a magic value to the thread structure + * to help identify valid ones: + */ + new_thread->magic = PTHREAD_MAGIC; + + /* Initialise the machine context: */ + getcontext(&new_thread->mailbox.tm_context); + new_thread->mailbox.tm_context.uc_stack.ss_sp = new_thread->stack; + new_thread->mailbox.tm_context.uc_stack.ss_size = + pattr->stacksize_attr; + makecontext(&new_thread->mailbox.tm_context, + _thread_start, 1); + new_thread->mailbox.tm_udata = (void *)new_thread; + + /* Copy the thread attributes: */ + memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr)); + + /* + * Check if this thread is to inherit the scheduling + * attributes from its parent: + */ + if (new_thread->attr.flags & PTHREAD_INHERIT_SCHED) { + /* Copy the scheduling attributes: */ + new_thread->base_priority = + curthread->base_priority & + ~PTHREAD_SIGNAL_PRIORITY; + new_thread->attr.prio = + curthread->base_priority & + ~PTHREAD_SIGNAL_PRIORITY; + new_thread->attr.sched_policy = + curthread->attr.sched_policy; + } else { + /* + * Use just the thread priority, leaving the + * other scheduling attributes as their + * default values: + */ + new_thread->base_priority = + new_thread->attr.prio; + } + new_thread->active_priority = new_thread->base_priority; + new_thread->inherited_priority = 0; + + /* Initialize joiner to NULL (no joiner): */ + new_thread->joiner = NULL; + + /* Initialize the mutex queue: */ + TAILQ_INIT(&new_thread->mutexq); + + /* Initialise hooks in the thread structure: */ + new_thread->specific = NULL; + new_thread->cleanup = NULL; + new_thread->flags = 0; + new_thread->continuation = NULL; + + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* + * Initialise the unique id which GDB uses to + * track threads. + */ + new_thread->uniqueid = next_uniqueid++; + + /* + * Check if the garbage collector thread + * needs to be started. + */ + f_gc = (TAILQ_FIRST(&_thread_list) == _thread_initial); + + /* Add the thread to the linked list of all threads: */ + TAILQ_INSERT_HEAD(&_thread_list, new_thread, tle); + + if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { + new_thread->flags |= PTHREAD_FLAGS_SUSPENDED; + new_thread->state = PS_SUSPENDED; + } else { + new_thread->state = PS_RUNNING; + PTHREAD_PRIOQ_INSERT_TAIL(new_thread); + } + + /* + * Undefer and handle pending signals, yielding + * if necessary. + */ + _thread_kern_sig_undefer(); + + /* Return a pointer to the thread structure: */ + (*thread) = new_thread; + + /* Schedule the new user thread: */ + _thread_kern_sched(); + + /* + * Start a garbage collector thread + * if necessary. + */ + if (f_gc && pthread_create(&gc_thread,NULL, + _thread_gc,NULL) != 0) + PANIC("Can't create gc thread"); + + } + } + + /* Return the status: */ + return (ret); + } + + void + _thread_start(void) + { + struct pthread *curthread = _get_curthread(); + + /* Run the current thread's start routine with argument: */ + pthread_exit(curthread->start_routine(curthread->arg)); + + /* This point should never be reached. */ + PANIC("Thread has resumed after exit"); + } Index: lib/libpthread/uthread/uthread_detach.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_detach.c Sun Sep 15 21:38:47 2002 *************** *** 0 **** --- 1,90 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_detach.c,v 1.17 2002/03/06 19:28:41 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_detach, pthread_detach); + + int + _pthread_detach(pthread_t pthread) + { + int rval = 0; + + /* Check for invalid calling parameters: */ + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) + /* Return an invalid argument error: */ + rval = EINVAL; + + /* Check if the thread has not been detached: */ + else if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) { + /* Flag the thread as detached: */ + pthread->attr.flags |= PTHREAD_DETACHED; + + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Check if there is a joiner: */ + if (pthread->joiner != NULL) { + struct pthread *joiner = pthread->joiner; + + /* Make the thread runnable: */ + PTHREAD_NEW_STATE(joiner, PS_RUNNING); + + /* Set the return value for the woken thread: */ + joiner->join_status.error = ESRCH; + joiner->join_status.ret = NULL; + joiner->join_status.thread = NULL; + + /* + * Disconnect the joiner from the thread being detached: + */ + pthread->joiner = NULL; + } + + /* + * Undefer and handle pending signals, yielding if a + * scheduling signal occurred while in the critical region. + */ + _thread_kern_sig_undefer(); + } else + /* Return an error: */ + rval = EINVAL; + + /* Return the completion status: */ + return (rval); + } Index: lib/libpthread/uthread/uthread_equal.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_equal.c Sun Sep 15 21:38:47 2002 *************** *** 0 **** --- 1,44 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_equal.c,v 1.5 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include "pthread_private.h" + + __weak_reference(_pthread_equal, pthread_equal); + + int + _pthread_equal(pthread_t t1, pthread_t t2) + { + /* Compare the two thread pointers: */ + return (t1 == t2); + } Index: lib/libpthread/uthread/uthread_exit.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_exit.c Sun Sep 15 21:38:47 2002 *************** *** 0 **** --- 1,182 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_exit.c,v 1.27 2002/08/29 23:06:07 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + #define FLAGS_IN_SCHEDQ \ + (PTHREAD_FLAGS_IN_PRIOQ|PTHREAD_FLAGS_IN_WAITQ|PTHREAD_FLAGS_IN_WORKQ) + + __weak_reference(_pthread_exit, pthread_exit); + + void + _thread_exit(char *fname, int lineno, char *string) + { + char s[256]; + + /* Prepare an error message string: */ + snprintf(s, sizeof(s), + "Fatal error '%s' at line %d in file %s (errno = %d)\n", + string, lineno, fname, errno); + + /* Write the string to the standard error file descriptor: */ + __sys_write(2, s, strlen(s)); + + /* Force this process to exit: */ + /* XXX - Do we want abort to be conditional on _PTHREADS_INVARIANTS? */ + #if defined(_PTHREADS_INVARIANTS) + abort(); + #else + __sys_exit(1); + #endif + } + + /* + * Only called when a thread is cancelled. It may be more useful + * to call it from pthread_exit() if other ways of asynchronous or + * abnormal thread termination can be found. + */ + void + _thread_exit_cleanup(void) + { + struct pthread *curthread = _get_curthread(); + + /* + * POSIX states that cancellation/termination of a thread should + * not release any visible resources (such as mutexes) and that + * it is the applications responsibility. Resources that are + * internal to the threads library, including file and fd locks, + * are not visible to the application and need to be released. + */ + /* Unlock all private mutexes: */ + _mutex_unlock_private(curthread); + + /* + * This still isn't quite correct because we don't account + * for held spinlocks (see libc/stdlib/malloc.c). + */ + } + + void + _pthread_exit(void *status) + { + struct pthread *curthread = _get_curthread(); + pthread_t pthread; + + /* Check if this thread is already in the process of exiting: */ + if ((curthread->flags & PTHREAD_EXITING) != 0) { + char msg[128]; + snprintf(msg, sizeof(msg), "Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",curthread); + PANIC(msg); + } + + /* Flag this thread as exiting: */ + curthread->flags |= PTHREAD_EXITING; + + /* Save the return value: */ + curthread->ret = status; + + while (curthread->cleanup != NULL) { + pthread_cleanup_pop(1); + } + if (curthread->attr.cleanup_attr != NULL) { + curthread->attr.cleanup_attr(curthread->attr.arg_attr); + } + /* Check if there is thread specific data: */ + if (curthread->specific != NULL) { + /* Run the thread-specific data destructors: */ + _thread_cleanupspecific(); + } + + /* + * Lock the garbage collector mutex to ensure that the garbage + * collector is not using the dead thread list. + */ + if (pthread_mutex_lock(&_gc_mutex) != 0) + PANIC("Cannot lock gc mutex"); + + /* Add this thread to the list of dead threads. */ + TAILQ_INSERT_HEAD(&_dead_list, curthread, dle); + + /* + * Signal the garbage collector thread that there is something + * to clean up. + */ + if (pthread_cond_signal(&_gc_cond) != 0) + PANIC("Cannot signal gc cond"); + + /* + * Avoid a race condition where a scheduling signal can occur + * causing the garbage collector thread to run. If this happens, + * the current thread can be cleaned out from under us. + */ + _thread_kern_sig_defer(); + + /* Unlock the garbage collector mutex: */ + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot unlock gc mutex"); + + /* Check if there is a thread joining this one: */ + if (curthread->joiner != NULL) { + pthread = curthread->joiner; + curthread->joiner = NULL; + + /* Make the joining thread runnable: */ + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + + /* Set the return value for the joining thread: */ + pthread->join_status.ret = curthread->ret; + pthread->join_status.error = 0; + pthread->join_status.thread = NULL; + + /* Make this thread collectable by the garbage collector. */ + PTHREAD_ASSERT(((curthread->attr.flags & PTHREAD_DETACHED) == + 0), "Cannot join a detached thread"); + curthread->attr.flags |= PTHREAD_DETACHED; + } + + /* Remove this thread from the thread list: */ + TAILQ_REMOVE(&_thread_list, curthread, tle); + + /* This thread will never be re-scheduled. */ + _thread_kern_sched_state(PS_DEAD, __FILE__, __LINE__); + + /* This point should not be reached. */ + PANIC("Dead thread has resumed"); + } Index: lib/libpthread/uthread/uthread_fcntl.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_fcntl.c Sun Sep 15 21:38:48 2002 *************** *** 0 **** --- 1,69 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_fcntl.c,v 1.15 2002/08/29 23:06:07 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__fcntl, fcntl); + + int + __fcntl(int fd, int cmd,...) + { + int ret; + va_list ap; + + _thread_enter_cancellation_point(); + + va_start(ap, cmd); + switch (cmd) { + case F_DUPFD: + case F_SETFD: + case F_SETFL: + ret = __sys_fcntl(fd, cmd, va_arg(ap, int)); + break; + case F_GETFD: + case F_GETFL: + ret = __sys_fcntl(fd, cmd); + break; + default: + ret = __sys_fcntl(fd, cmd, va_arg(ap, void *)); + } + va_end(ap); + + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_find_thread.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_find_thread.c Sun Sep 15 21:38:48 2002 *************** *** 0 **** --- 1,66 ---- + /* + * Copyright (c) 1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_find_thread.c,v 1.7 2001/06/27 11:41:13 jasone Exp $ + */ + #include + #include + #include "pthread_private.h" + + /* Find a thread in the linked list of active threads: */ + int + _find_thread(pthread_t pthread) + { + pthread_t pthread1; + + /* Check if the caller has specified an invalid thread: */ + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) + /* Invalid thread: */ + return(EINVAL); + + /* + * Defer signals to protect the thread list from access + * by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Search for the specified thread: */ + TAILQ_FOREACH(pthread1, &_thread_list, tle) { + if (pthread == pthread1) + break; + } + + /* Undefer and handle pending signals, yielding if necessary: */ + _thread_kern_sig_undefer(); + + /* Return zero if the thread exists: */ + return ((pthread1 != NULL) ? 0:ESRCH); + } Index: lib/libpthread/uthread/uthread_fork.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_fork.c Sun Sep 15 21:38:48 2002 *************** *** 0 **** --- 1,180 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_fork.c,v 1.27 2002/03/19 22:58:56 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + static void free_thread_resources(struct pthread *thread); + + __weak_reference(_fork, fork); + + pid_t + _fork(void) + { + struct pthread *curthread = _get_curthread(); + int i, flags, use_deadlist = 0; + pid_t ret; + pthread_t pthread; + pthread_t pthread_save; + + /* + * Defer signals to protect the scheduling queues from access + * by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Fork a new process: */ + if ((ret = __sys_fork()) != 0) { + /* Parent process or error. Nothing to do here. */ + } else { + /* Reinitialize the GC mutex: */ + if (_mutex_reinit(&_gc_mutex) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize GC mutex for forked process"); + } + /* Reinitialize the GC condition variable: */ + else if (_cond_reinit(&_gc_cond) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize GC condvar for forked process"); + } + /* Initialize the ready queue: */ + else if (_pq_init(&_readyq) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize priority ready queue."); + } else { + /* + * Enter a loop to remove all threads other than + * the running thread from the thread list: + */ + if ((pthread = TAILQ_FIRST(&_thread_list)) == NULL) { + pthread = TAILQ_FIRST(&_dead_list); + use_deadlist = 1; + } + while (pthread != NULL) { + /* Save the thread to be freed: */ + pthread_save = pthread; + + /* + * Advance to the next thread before + * destroying the current thread: + */ + if (use_deadlist != 0) + pthread = TAILQ_NEXT(pthread, dle); + else + pthread = TAILQ_NEXT(pthread, tle); + + /* Make sure this isn't the running thread: */ + if (pthread_save != curthread) { + /* + * Remove this thread from the + * appropriate list: + */ + if (use_deadlist != 0) + TAILQ_REMOVE(&_thread_list, + pthread_save, dle); + else + TAILQ_REMOVE(&_thread_list, + pthread_save, tle); + + free_thread_resources(pthread_save); + } + + /* + * Switch to the deadlist when the active + * thread list has been consumed. This can't + * be at the top of the loop because it is + * used to determine to which list the thread + * belongs (when it is removed from the list). + */ + if (pthread == NULL) { + pthread = TAILQ_FIRST(&_dead_list); + use_deadlist = 1; + } + } + + /* Treat the current thread as the initial thread: */ + _thread_initial = curthread; + + /* Re-init the dead thread list: */ + TAILQ_INIT(&_dead_list); + + /* Re-init the waiting and work queues. */ + TAILQ_INIT(&_waitingq); + TAILQ_INIT(&_workq); + + /* Re-init the threads mutex queue: */ + TAILQ_INIT(&curthread->mutexq); + + /* No spinlocks yet: */ + _spinblock_count = 0; + + /* Initialize the scheduling switch hook routine: */ + _sched_switch_hook = NULL; + } + } + + /* + * Undefer and handle pending signals, yielding if necessary: + */ + _thread_kern_sig_undefer(); + + /* Return the process ID: */ + return (ret); + } + + static void + free_thread_resources(struct pthread *thread) + { + + /* Check to see if the threads library allocated the stack. */ + if ((thread->attr.stackaddr_attr == NULL) && (thread->stack != NULL)) { + /* + * Since this is being called from fork, we are currently single + * threaded so there is no need to protect the call to + * _thread_stack_free() with _gc_mutex. + */ + _thread_stack_free(thread->stack, thread->attr.stacksize_attr, + thread->attr.guardsize_attr); + } + + if (thread->specific != NULL) + free(thread->specific); + + free(thread); + } Index: lib/libpthread/uthread/uthread_fsync.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_fsync.c Sun Sep 15 21:38:48 2002 *************** *** 0 **** --- 1,50 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_fsync.c,v 1.10 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(__fsync, fsync); + + int + __fsync(int fd) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __sys_fsync(fd); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_gc.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_gc.c Sun Sep 15 21:38:48 2002 *************** *** 0 **** --- 1,219 ---- + /* + * Copyright (c) 1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_gc.c,v 1.16 2001/07/20 04:23:11 jasone Exp $ + * + * Garbage collector thread. Frees memory allocated for dead threads. + * + */ + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + pthread_addr_t + _thread_gc(pthread_addr_t arg) + { + struct pthread *curthread = _get_curthread(); + int f_debug; + int f_done = 0; + int ret; + sigset_t mask; + pthread_t pthread; + pthread_t pthread_cln; + struct timespec abstime; + void *p_stack; + + /* Block all signals */ + sigfillset(&mask); + pthread_sigmask(SIG_BLOCK, &mask, NULL); + + /* Mark this thread as a library thread (not a user thread). */ + curthread->flags |= PTHREAD_FLAGS_PRIVATE; + + /* Set a debug flag based on an environment variable. */ + f_debug = (getenv("LIBC_R_DEBUG") != NULL); + + /* Set the name of this thread. */ + pthread_set_name_np(curthread,"GC"); + + while (!f_done) { + /* Check if debugging this application. */ + if (f_debug) + /* Dump thread info to file. */ + _thread_dump_info(); + + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Check if this is the last running thread: */ + if (TAILQ_FIRST(&_thread_list) == curthread && + TAILQ_NEXT(curthread, tle) == NULL) + /* + * This is the last thread, so it can exit + * now. + */ + f_done = 1; + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + + /* No stack of thread structure to free yet: */ + p_stack = NULL; + pthread_cln = NULL; + + /* + * Lock the garbage collector mutex which ensures that + * this thread sees another thread exit: + */ + if (pthread_mutex_lock(&_gc_mutex) != 0) + PANIC("Cannot lock gc mutex"); + + /* + * Enter a loop to search for the first dead thread that + * has memory to free. + */ + for (pthread = TAILQ_FIRST(&_dead_list); + p_stack == NULL && pthread_cln == NULL && pthread != NULL; + pthread = TAILQ_NEXT(pthread, dle)) { + /* Check if the initial thread: */ + if (pthread == _thread_initial) { + /* Don't destroy the initial thread. */ + } + /* + * Check if this thread has detached: + */ + else if ((pthread->attr.flags & + PTHREAD_DETACHED) != 0) { + /* Remove this thread from the dead list: */ + TAILQ_REMOVE(&_dead_list, pthread, dle); + + /* + * Check if the stack was not specified by + * the caller to pthread_create() and has not + * been destroyed yet: + */ + if (pthread->attr.stackaddr_attr == NULL && + pthread->stack != NULL) { + _thread_stack_free(pthread->stack, + pthread->attr.stacksize_attr, + pthread->attr.guardsize_attr); + } + + /* + * Point to the thread structure that must + * be freed outside the locks: + */ + pthread_cln = pthread; + + } else { + /* + * This thread has not detached, so do + * not destroy it. + * + * Check if the stack was not specified by + * the caller to pthread_create() and has not + * been destroyed yet: + */ + if (pthread->attr.stackaddr_attr == NULL && + pthread->stack != NULL) { + _thread_stack_free(pthread->stack, + pthread->attr.stacksize_attr, + pthread->attr.guardsize_attr); + + /* + * NULL the stack pointer now that the + * memory has been freed: + */ + pthread->stack = NULL; + } + } + } + + /* + * Check if this is not the last thread and there is no + * memory to free this time around. + */ + if (!f_done && p_stack == NULL && pthread_cln == NULL) { + /* Get the current time. */ + if (clock_gettime(CLOCK_REALTIME,&abstime) != 0) + PANIC("gc cannot get time"); + + /* + * Do a backup poll in 10 seconds if no threads + * die before then. + */ + abstime.tv_sec += 10; + + /* + * Wait for a signal from a dying thread or a + * timeout (for a backup poll). + */ + if ((ret = pthread_cond_timedwait(&_gc_cond, + &_gc_mutex, &abstime)) != 0 && ret != ETIMEDOUT) + PANIC("gc cannot wait for a signal"); + } + + /* Unlock the garbage collector mutex: */ + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot unlock gc mutex"); + + /* + * If there is memory to free, do it now. The call to + * free() might block, so this must be done outside the + * locks. + */ + if (p_stack != NULL) + free(p_stack); + if (pthread_cln != NULL) { + if (pthread_cln->name != NULL) { + /* Free the thread name string. */ + free(pthread_cln->name); + } + /* + * Free the memory allocated for the thread + * structure. + */ + free(pthread_cln); + } + } + return (NULL); + } Index: lib/libpthread/uthread/uthread_getprio.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_getprio.c Sun Sep 15 21:38:49 2002 *************** *** 0 **** --- 1,56 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_getprio.c,v 1.8 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_getprio, pthread_getprio); + + int + _pthread_getprio(pthread_t pthread) + { + int policy, ret; + struct sched_param param; + + if ((ret = pthread_getschedparam(pthread, &policy, ¶m)) == 0) + ret = param.sched_priority; + else { + /* Invalid thread: */ + errno = ret; + ret = -1; + } + + /* Return the thread priority or an error status: */ + return (ret); + } Index: lib/libpthread/uthread/uthread_getschedparam.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_getschedparam.c Sun Sep 15 21:38:49 2002 *************** *** 0 **** --- 1,59 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_getschedparam.c,v 1.7 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_getschedparam, pthread_getschedparam); + + int + _pthread_getschedparam(pthread_t pthread, int *policy, + struct sched_param *param) + { + int ret; + + if ((param == NULL) || (policy == NULL)) + /* Return an invalid argument error: */ + ret = EINVAL; + + /* Find the thread in the list of active threads: */ + else if ((ret = _find_thread(pthread)) == 0) { + /* Return the threads base priority and scheduling policy: */ + param->sched_priority = + PTHREAD_BASE_PRIORITY(pthread->base_priority); + *policy = pthread->attr.sched_policy; + } + + return(ret); + } Index: lib/libpthread/uthread/uthread_info.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_info.c Sun Sep 15 21:38:49 2002 *************** *** 0 **** --- 1,225 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_info.c,v 1.20 2001/08/11 05:16:00 imp Exp $ + */ + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + #ifndef NELEMENTS + #define NELEMENTS(arr) (sizeof(arr) / sizeof(arr[0])) + #endif + + static void dump_thread(int fd, pthread_t pthread, int long_version); + + __weak_reference(_pthread_set_name_np, pthread_set_name_np); + + struct s_thread_info { + enum pthread_state state; + char *name; + }; + + /* Static variables: */ + static const struct s_thread_info thread_info[] = { + {PS_RUNNING , "Running"}, + {PS_MUTEX_WAIT , "Waiting on a mutex"}, + {PS_COND_WAIT , "Waiting on a condition variable"}, + {PS_SLEEP_WAIT , "Sleeping"}, + {PS_WAIT_WAIT , "Waiting process"}, + {PS_SPINBLOCK , "Waiting for a spinlock"}, + {PS_JOIN , "Waiting to join"}, + {PS_SUSPENDED , "Suspended"}, + {PS_DEAD , "Dead"}, + {PS_DEADLOCK , "Deadlocked"}, + {PS_STATE_MAX , "Not a real state!"} + }; + + void + _thread_dump_info(void) + { + char s[512]; + int fd; + int i; + pthread_t pthread; + char tmpfile[128]; + pq_list_t *pq_list; + + for (i = 0; i < 100000; i++) { + snprintf(tmpfile, sizeof(tmpfile), "/tmp/uthread.dump.%u.%i", + getpid(), i); + /* Open the dump file for append and create it if necessary: */ + if ((fd = __sys_open(tmpfile, O_RDWR | O_CREAT | O_EXCL, + 0666)) < 0) { + /* Can't open the dump file. */ + if (errno == EEXIST) + continue; + /* + * We only need to continue in case of + * EEXIT error. Most other error + * codes means that we will fail all + * the times. + */ + return; + } else { + break; + } + } + if (i==100000) { + /* all 100000 possibilities are in use :( */ + return; + } else { + /* Output a header for active threads: */ + strcpy(s, "\n\n=============\nACTIVE THREADS\n\n"); + __sys_write(fd, s, strlen(s)); + + /* Enter a loop to report each thread in the global list: */ + TAILQ_FOREACH(pthread, &_thread_list, tle) { + dump_thread(fd, pthread, /*long_verson*/ 1); + } + + /* Output a header for ready threads: */ + strcpy(s, "\n\n=============\nREADY THREADS\n\n"); + __sys_write(fd, s, strlen(s)); + + /* Enter a loop to report each thread in the ready queue: */ + TAILQ_FOREACH (pq_list, &_readyq.pq_queue, pl_link) { + TAILQ_FOREACH(pthread, &pq_list->pl_head, pqe) { + dump_thread(fd, pthread, /*long_version*/ 0); + } + } + + /* Output a header for waiting threads: */ + strcpy(s, "\n\n=============\nWAITING THREADS\n\n"); + __sys_write(fd, s, strlen(s)); + + /* Enter a loop to report each thread in the waiting queue: */ + TAILQ_FOREACH (pthread, &_waitingq, pqe) { + dump_thread(fd, pthread, /*long_version*/ 0); + } + + /* Output a header for threads in the work queue: */ + strcpy(s, "\n\n=============\nTHREADS IN WORKQ\n\n"); + __sys_write(fd, s, strlen(s)); + + /* Enter a loop to report each thread in the waiting queue: */ + TAILQ_FOREACH (pthread, &_workq, qe) { + dump_thread(fd, pthread, /*long_version*/ 0); + } + + /* Check if there are no dead threads: */ + if (TAILQ_FIRST(&_dead_list) == NULL) { + /* Output a record: */ + strcpy(s, "\n\nTHERE ARE NO DEAD THREADS\n"); + __sys_write(fd, s, strlen(s)); + } else { + /* Output a header for dead threads: */ + strcpy(s, "\n\nDEAD THREADS\n\n"); + __sys_write(fd, s, strlen(s)); + + /* + * Enter a loop to report each thread in the global + * dead thread list: + */ + TAILQ_FOREACH(pthread, &_dead_list, dle) { + dump_thread(fd, pthread, /*long_version*/ 0); + } + } + + /* Close the dump file: */ + __sys_close(fd); + } + } + + static void + dump_thread(int fd, pthread_t pthread, int long_version) + { + struct pthread *curthread = _get_curthread(); + char s[512]; + int i; + + /* Find the state: */ + for (i = 0; i < NELEMENTS(thread_info) - 1; i++) + if (thread_info[i].state == pthread->state) + break; + + /* Output a record for the thread: */ + snprintf(s, sizeof(s), + "--------------------\nThread %p (%s) prio %3d state %s [%s:%d]\n", + pthread, (pthread->name == NULL) ? "" : pthread->name, + pthread->active_priority, thread_info[i].name, pthread->fname, + pthread->lineno); + __sys_write(fd, s, strlen(s)); + + if (long_version != 0) { + /* Check if this is the running thread: */ + if (pthread == curthread) { + /* Output a record for the running thread: */ + strcpy(s, "This is the running thread\n"); + __sys_write(fd, s, strlen(s)); + } + /* Check if this is the initial thread: */ + if (pthread == _thread_initial) { + /* Output a record for the initial thread: */ + strcpy(s, "This is the initial thread\n"); + __sys_write(fd, s, strlen(s)); + } + /* Process according to thread state: */ + switch (pthread->state) { + /* + * Trap other states that are not explicitly + * coded to dump information: + */ + default: + /* Nothing to do here. */ + break; + } + } + } + + /* Set the thread name for debug: */ + void + _pthread_set_name_np(pthread_t thread, const char *name) + { + /* Check if the caller has specified a valid thread: */ + if (thread != NULL && thread->magic == PTHREAD_MAGIC) { + if (thread->name != NULL) { + /* Free space for previous name. */ + free(thread->name); + } + thread->name = strdup(name); + } + } Index: lib/libpthread/uthread/uthread_init.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_init.c Sun Sep 15 21:38:49 2002 *************** *** 0 **** --- 1,363 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_init.c,v 1.41 2002/05/24 04:32:28 deischen Exp $ + */ + + /* Allocate space for global thread variables here: */ + #define GLOBAL_PTHREAD_PRIVATE + + #include "namespace.h" + #include + #include + #include + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "un-namespace.h" + + #include "pthread_private.h" + + /* + * All weak references used within libc should be in this table. + * This will is so that static libraries will work. + */ + static void *references[] = { + &_accept, + &_bind, + &_close, + &_connect, + &_dup, + &_dup2, + &_execve, + &_fcntl, + &_flock, + &_flockfile, + &_fstat, + &_fstatfs, + &_fsync, + &_funlockfile, + &_getdirentries, + &_getlogin, + &_getpeername, + &_getsockname, + &_getsockopt, + &_ioctl, + &_kevent, + &_listen, + &_nanosleep, + &_open, + &_pthread_getspecific, + &_pthread_key_create, + &_pthread_key_delete, + &_pthread_mutex_destroy, + &_pthread_mutex_init, + &_pthread_mutex_lock, + &_pthread_mutex_trylock, + &_pthread_mutex_unlock, + &_pthread_mutexattr_init, + &_pthread_mutexattr_destroy, + &_pthread_mutexattr_settype, + &_pthread_once, + &_pthread_setspecific, + &_read, + &_readv, + &_recvfrom, + &_recvmsg, + &_select, + &_sendmsg, + &_sendto, + &_setsockopt, + &_sigaction, + &_sigprocmask, + &_sigsuspend, + &_socket, + &_socketpair, + &_wait4, + &_write, + &_writev + }; + + /* + * These are needed when linking statically. All references within + * libgcc (and in the future libc) to these routines are weak, but + * if they are not (strongly) referenced by the application or other + * libraries, then the actual functions will not be loaded. + */ + static void *libgcc_references[] = { + &_pthread_once, + &_pthread_key_create, + &_pthread_key_delete, + &_pthread_getspecific, + &_pthread_setspecific, + &_pthread_mutex_init, + &_pthread_mutex_destroy, + &_pthread_mutex_lock, + &_pthread_mutex_trylock, + &_pthread_mutex_unlock + }; + + int _pthread_guard_default; + int _pthread_page_size; + + /* + * Threaded process initialization + */ + void + _thread_init(void) + { + int fd; + int flags; + int i; + size_t len; + int mib[2]; + int sched_stack_size; /* Size of scheduler stack. */ + + struct clockinfo clockinfo; + + _pthread_page_size = getpagesize(); + _pthread_guard_default = getpagesize(); + sched_stack_size = getpagesize(); + + pthread_attr_default.guardsize_attr = _pthread_guard_default; + + + /* Check if this function has already been called: */ + if (_thread_initial) + /* Only initialise the threaded application once. */ + return; + + /* + * Make gcc quiescent about {,libgcc_}references not being + * referenced: + */ + if ((references[0] == NULL) || (libgcc_references[0] == NULL)) + PANIC("Failed loading mandatory references in _thread_init"); + + /* + * Check for the special case of this process running as + * or in place of init as pid = 1: + */ + if (getpid() == 1) { + /* + * Setup a new session for this process which is + * assumed to be running as root. + */ + if (setsid() == -1) + PANIC("Can't set session ID"); + if (revoke(_PATH_CONSOLE) != 0) + PANIC("Can't revoke console"); + if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0) + PANIC("Can't open console"); + if (setlogin("root") == -1) + PANIC("Can't set login to root"); + if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1) + PANIC("Can't set controlling terminal"); + if (__sys_dup2(fd, 0) == -1 || + __sys_dup2(fd, 1) == -1 || + __sys_dup2(fd, 2) == -1) + PANIC("Can't dup2"); + } + + /* Allocate and initialize the ready queue: */ + if (_pq_alloc(&_readyq, PTHREAD_MIN_PRIORITY, PTHREAD_LAST_PRIORITY) != + 0) { + /* Abort this application: */ + PANIC("Cannot allocate priority ready queue."); + } + /* Allocate memory for the thread structure of the initial thread: */ + else if ((_thread_initial = (pthread_t) malloc(sizeof(struct pthread))) == NULL) { + /* + * Insufficient memory to initialise this application, so + * abort: + */ + PANIC("Cannot allocate memory for initial thread"); + } + /* Allocate memory for the scheduler stack: */ + else if ((_thread_kern_sched_stack = malloc(sched_stack_size)) == NULL) + PANIC("Failed to allocate stack for scheduler"); + else { + /* Zero the global kernel thread structure: */ + memset(&_thread_kern_thread, 0, sizeof(struct pthread)); + _thread_kern_thread.flags = PTHREAD_FLAGS_PRIVATE; + memset(_thread_initial, 0, sizeof(struct pthread)); + + /* Initialize the waiting and work queues: */ + TAILQ_INIT(&_waitingq); + TAILQ_INIT(&_workq); + + /* Initialize the scheduling switch hook routine: */ + _sched_switch_hook = NULL; + + /* Give this thread default attributes: */ + memcpy((void *) &_thread_initial->attr, &pthread_attr_default, + sizeof(struct pthread_attr)); + + /* Find the stack top */ + mib[0] = CTL_KERN; + mib[1] = KERN_USRSTACK; + len = sizeof (_usrstack); + if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1) + _usrstack = (void *)USRSTACK; + /* + * Create a red zone below the main stack. All other stacks are + * constrained to a maximum size by the paramters passed to + * mmap(), but this stack is only limited by resource limits, so + * this stack needs an explicitly mapped red zone to protect the + * thread stack that is just beyond. + */ + if (mmap(_usrstack - PTHREAD_STACK_INITIAL - + _pthread_guard_default, _pthread_guard_default, 0, + MAP_ANON, -1, 0) == MAP_FAILED) + PANIC("Cannot allocate red zone for initial thread"); + + /* Set the main thread stack pointer. */ + _thread_initial->stack = _usrstack - PTHREAD_STACK_INITIAL; + + /* Set the stack attributes. */ + _thread_initial->attr.stackaddr_attr = _thread_initial->stack; + _thread_initial->attr.stacksize_attr = PTHREAD_STACK_INITIAL; + + /* Setup the context for the scheduler. */ + _thread_kern_kse_mailbox.km_stack.ss_sp = + _thread_kern_sched_stack; + _thread_kern_kse_mailbox.km_stack.ss_size = sched_stack_size; + _thread_kern_kse_mailbox.km_func = + (void *)_thread_kern_scheduler; + + /* + * Write a magic value to the thread structure + * to help identify valid ones: + */ + _thread_initial->magic = PTHREAD_MAGIC; + + /* Set the initial cancel state */ + _thread_initial->cancelflags = PTHREAD_CANCEL_ENABLE | + PTHREAD_CANCEL_DEFERRED; + + /* Setup the context for initial thread. */ + getcontext(&_thread_initial->mailbox.tm_context); + _thread_initial->mailbox.tm_context.uc_stack.ss_sp = + _thread_initial->stack; + _thread_initial->mailbox.tm_context.uc_stack.ss_size = + PTHREAD_STACK_INITIAL; + _thread_initial->mailbox.tm_udata = (void *)_thread_initial; + + /* Default the priority of the initial thread: */ + _thread_initial->base_priority = PTHREAD_DEFAULT_PRIORITY; + _thread_initial->active_priority = PTHREAD_DEFAULT_PRIORITY; + _thread_initial->inherited_priority = 0; + + /* Initialise the state of the initial thread: */ + _thread_initial->state = PS_RUNNING; + + /* Set the name of the thread: */ + _thread_initial->name = strdup("_thread_initial"); + + /* Initialize joiner to NULL (no joiner): */ + _thread_initial->joiner = NULL; + + /* Initialize the owned mutex queue and count: */ + TAILQ_INIT(&(_thread_initial->mutexq)); + _thread_initial->priority_mutex_count = 0; + + /* Initialize the global scheduling time: */ + _sched_ticks = 0; + gettimeofday((struct timeval *) &_sched_tod, NULL); + + /* Initialize last active: */ + _thread_initial->last_active = (long) _sched_ticks; + + /* Initialise the rest of the fields: */ + _thread_initial->sig_defer_count = 0; + _thread_initial->specific = NULL; + _thread_initial->cleanup = NULL; + _thread_initial->flags = 0; + _thread_initial->error = 0; + TAILQ_INIT(&_thread_list); + TAILQ_INSERT_HEAD(&_thread_list, _thread_initial, tle); + _set_curthread(_thread_initial); + + /* Get the kernel clockrate: */ + mib[0] = CTL_KERN; + mib[1] = KERN_CLOCKRATE; + len = sizeof (struct clockinfo); + if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0) + _clock_res_usec = clockinfo.tick > CLOCK_RES_USEC_MIN ? + clockinfo.tick : CLOCK_RES_USEC_MIN; + + /* Start KSE. */ + _thread_kern_kse_mailbox.km_curthread = + &_thread_initial->mailbox; + if (kse_new(&_thread_kern_kse_mailbox, 0) != 0) + PANIC("kse_new failed"); + } + + /* Initialise the garbage collector mutex and condition variable. */ + if (_pthread_mutex_init(&_gc_mutex,NULL) != 0 || + pthread_cond_init(&_gc_cond,NULL) != 0) + PANIC("Failed to initialise garbage collector mutex or condvar"); + } + + /* + * Special start up code for NetBSD/Alpha + */ + #if defined(__NetBSD__) && defined(__alpha__) + int + main(int argc, char *argv[], char *env); + + int + _thread_main(int argc, char *argv[], char *env) + { + _thread_init(); + return (main(argc, argv, env)); + } + #endif Index: lib/libpthread/uthread/uthread_join.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_join.c Sun Sep 15 21:38:49 2002 *************** *** 0 **** --- 1,162 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_join.c,v 1.20 2001/11/17 14:28:39 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_join, pthread_join); + + int + _pthread_join(pthread_t pthread, void **thread_return) + { + struct pthread *curthread = _get_curthread(); + int ret = 0; + pthread_t thread; + + _thread_enter_cancellation_point(); + + /* Check if the caller has specified an invalid thread: */ + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) { + /* Invalid thread: */ + _thread_leave_cancellation_point(); + return(EINVAL); + } + + /* Check if the caller has specified itself: */ + if (pthread == curthread) { + /* Avoid a deadlock condition: */ + _thread_leave_cancellation_point(); + return(EDEADLK); + } + + /* + * Lock the garbage collector mutex to ensure that the garbage + * collector is not using the dead thread list. + */ + if (pthread_mutex_lock(&_gc_mutex) != 0) + PANIC("Cannot lock gc mutex"); + + /* + * Defer signals to protect the thread list from access + * by the signal handler: + */ + _thread_kern_sig_defer(); + + /* + * Unlock the garbage collector mutex, now that the garbage collector + * can't be run: + */ + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot lock gc mutex"); + + /* + * Search for the specified thread in the list of active threads. This + * is done manually here rather than calling _find_thread() because + * the searches in _thread_list and _dead_list (as well as setting up + * join/detach state) have to be done atomically. + */ + TAILQ_FOREACH(thread, &_thread_list, tle) { + if (thread == pthread) + break; + } + if (thread == NULL) { + /* + * Search for the specified thread in the list of dead threads: + */ + TAILQ_FOREACH(thread, &_dead_list, dle) { + if (thread == pthread) + break; + } + } + + /* Check if the thread was not found or has been detached: */ + if (thread == NULL || + ((pthread->attr.flags & PTHREAD_DETACHED) != 0)) { + /* Undefer and handle pending signals, yielding if necessary: */ + _thread_kern_sig_undefer(); + + /* Return an error: */ + ret = ESRCH; + + } else if (pthread->joiner != NULL) { + /* Undefer and handle pending signals, yielding if necessary: */ + _thread_kern_sig_undefer(); + + /* Multiple joiners are not supported. */ + ret = ENOTSUP; + + /* Check if the thread is not dead: */ + } else if (pthread->state != PS_DEAD) { + /* Set the running thread to be the joiner: */ + pthread->joiner = curthread; + + /* Keep track of which thread we're joining to: */ + curthread->join_status.thread = pthread; + + while (curthread->join_status.thread == pthread) { + /* Schedule the next thread: */ + _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); + } + + /* + * The thread return value and error are set by the thread we're + * joining to when it exits or detaches: + */ + ret = curthread->join_status.error; + if ((ret == 0) && (thread_return != NULL)) + *thread_return = curthread->join_status.ret; + } else { + /* + * The thread exited (is dead) without being detached, and no + * thread has joined it. + */ + + /* Check if the return value is required: */ + if (thread_return != NULL) { + /* Return the thread's return value: */ + *thread_return = pthread->ret; + } + + /* Make the thread collectable by the garbage collector. */ + pthread->attr.flags |= PTHREAD_DETACHED; + + /* Undefer and handle pending signals, yielding if necessary: */ + _thread_kern_sig_undefer(); + } + + _thread_leave_cancellation_point(); + + /* Return the completion status: */ + return (ret); + } Index: lib/libpthread/uthread/uthread_kern.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_kern.c Sun Sep 15 21:38:50 2002 *************** *** 0 **** --- 1,632 ---- + /* + * Copyright (c) 2002 Jonathan Mini + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_kern.c,v 1.42 2002/08/29 00:44:11 archie Exp $ + * + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + /* #define DEBUG_THREAD_KERN */ + #ifdef DEBUG_THREAD_KERN + #define DBG_MSG stdout_debug + #else + #define DBG_MSG(x...) + #endif + + + /* Static function prototype definitions: */ + static void + thread_kern_idle(void); + + static void + dequeue_signals(void); + + static inline void + thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in); + + /* Static variables: */ + static int last_tick = 0; + + void + _thread_kern_sched(void) + { + struct timespec ts; + struct timeval tv; + struct pthread *curthread = _get_curthread(); + unsigned int current_tick; + + /* Get the current time of day. */ + GET_CURRENT_TOD(tv); + TIMEVAL_TO_TIMESPEC(&tv, &ts); + current_tick = _sched_ticks; + + /* + * Enter a critical section. + */ + _thread_kern_kse_mailbox.km_curthread = NULL; + + /* + * If this thread is becoming inactive, make note of the + * time. + */ + if (curthread->state != PS_RUNNING) { + /* + * Save the current time as the time that the + * thread became inactive: + */ + curthread->last_inactive = (long)current_tick; + if (curthread->last_inactive < + curthread->last_active) { + /* Account for a rollover: */ + curthread->last_inactive =+ + UINT_MAX + 1; + } + } + + /* + * Place this thread into the appropriate queue(s). + */ + switch (curthread->state) { + case PS_DEAD: + case PS_STATE_MAX: /* XXX: silences -Wall */ + case PS_SUSPENDED: + /* Dead or suspended threads are not placed in any queue. */ + break; + case PS_RUNNING: + /* + * Save the current time as the time that the + * thread became inactive: + */ + current_tick = _sched_ticks; + curthread->last_inactive = (long)current_tick; + if (curthread->last_inactive < + curthread->last_active) { + /* Account for a rollover: */ + curthread->last_inactive =+ UINT_MAX + 1; + } + + if ((curthread->slice_usec != -1) && + (curthread->attr.sched_policy != SCHED_FIFO)) { + /* + * Accumulate the number of microseconds for + * which the current thread has run: + */ + curthread->slice_usec += + (curthread->last_inactive - + curthread->last_active) * + (long)_clock_res_usec; + /* Check for time quantum exceeded: */ + if (curthread->slice_usec > TIMESLICE_USEC) + curthread->slice_usec = -1; + } + + if (curthread->slice_usec == -1) { + /* + * The thread exceeded its time + * quantum or it yielded the CPU; + * place it at the tail of the + * queue for its priority. + */ + PTHREAD_PRIOQ_INSERT_TAIL(curthread); + } else { + /* + * The thread hasn't exceeded its + * interval. Place it at the head + * of the queue for its priority. + */ + PTHREAD_PRIOQ_INSERT_HEAD(curthread); + } + break; + case PS_SPINBLOCK: + /* Increment spinblock count. */ + _spinblock_count++; + /*FALLTHROUGH*/ + case PS_DEADLOCK: + case PS_JOIN: + case PS_MUTEX_WAIT: + case PS_WAIT_WAIT: + /* No timeouts for these states. */ + curthread->wakeup_time.tv_sec = -1; + curthread->wakeup_time.tv_nsec = -1; + + /* Restart the time slice. */ + curthread->slice_usec = -1; + + /* Insert into the waiting queue. */ + PTHREAD_WAITQ_INSERT(curthread); + break; + + case PS_COND_WAIT: + case PS_SLEEP_WAIT: + /* These states can timeout. */ + /* Restart the time slice. */ + curthread->slice_usec = -1; + + /* Insert into the waiting queue. */ + PTHREAD_WAITQ_INSERT(curthread); + break; + } + + /* Switch into the scheduler's context. */ + DBG_MSG("Calling _thread_enter_uts()\n"); + _thread_enter_uts(&curthread->mailbox, &_thread_kern_kse_mailbox); + DBG_MSG("Returned from _thread_enter_uts, thread %p\n", curthread); + + /* + * This point is reached when _thread_switch() is called + * to restore the state of a thread. + * + * This is the normal way out of the scheduler (for synchronous + * switches). + */ + + /* XXXKSE: Do this inside _thread_kern_scheduler() */ + if (curthread->sig_defer_count == 0) { + if (((curthread->cancelflags & + PTHREAD_AT_CANCEL_POINT) == 0) && + ((curthread->cancelflags & + PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) + /* + * Stick a cancellation point at the + * start of each async-cancellable + * thread's resumption. + * + * We allow threads woken at cancel + * points to do their own checks. + */ + pthread_testcancel(); + } + + if (_sched_switch_hook != NULL) { + /* Run the installed switch hook: */ + thread_run_switch_hook(_last_user_thread, curthread); + } + DBG_MSG("Fuck me\n"); + } + + void + _thread_kern_scheduler(struct kse_mailbox *km) + { + struct timespec ts; + struct timeval tv; + pthread_t td, pthread, pthread_h; + unsigned int current_tick; + struct thread_mailbox *tm, *p; + + DBG_MSG("entering\n"); + while (!TAILQ_EMPTY(&_thread_list)) { + + /* Get the current time of day. */ + GET_CURRENT_TOD(tv); + TIMEVAL_TO_TIMESPEC(&tv, &ts); + current_tick = _sched_ticks; + + /* + * Pick up threads that had blocked in the kernel and + * have now completed their trap (syscall, vm fault, etc). + * These threads were PS_RUNNING (and still are), but they + * need to be added to the run queue so that they can be + * scheduled again. + */ + DBG_MSG("Picking up km_completed\n"); + p = km->km_completed; + km->km_completed = NULL; /* XXX: Atomic xchg here. */ + while ((tm = p) != NULL) { + p = tm->tm_next; + tm->tm_next = NULL; + DBG_MSG("\tmailbox=%p pthread=%p\n", tm, tm->tm_udata); + PTHREAD_PRIOQ_INSERT_TAIL((pthread_t)tm->tm_udata); + } + + /* Deliver posted signals. */ + /* XXX: Not yet. */ + DBG_MSG("Picking up signals\n"); + + /* Wake up threads that have timed out. */ + DBG_MSG("setactive\n"); + PTHREAD_WAITQ_SETACTIVE(); + DBG_MSG("Picking up timeouts (%x)\n", TAILQ_FIRST(&_waitingq)); + while (((pthread = TAILQ_FIRST(&_waitingq)) != NULL) && + (pthread->wakeup_time.tv_sec != -1) && + (((pthread->wakeup_time.tv_sec == 0) && + (pthread->wakeup_time.tv_nsec == 0)) || + (pthread->wakeup_time.tv_sec < ts.tv_sec) || + ((pthread->wakeup_time.tv_sec == ts.tv_sec) && + (pthread->wakeup_time.tv_nsec <= ts.tv_nsec)))) { + DBG_MSG("\t...\n"); + /* + * Remove this thread from the waiting queue + * (and work queue if necessary) and place it + * in the ready queue. + */ + PTHREAD_WAITQ_CLEARACTIVE(); + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); + DBG_MSG("\twaking thread\n"); + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); + /* + * Flag the timeout in the thread structure: + */ + pthread->timeout = 1; + } + DBG_MSG("clearactive\n"); + PTHREAD_WAITQ_CLEARACTIVE(); + + /* + * Get the highest priority thread in the ready queue. + */ + DBG_MSG("Selecting thread\n"); + pthread_h = PTHREAD_PRIOQ_FIRST(); + + /* Check if there are no threads ready to run: */ + if (pthread_h) { + DBG_MSG("Scheduling thread\n"); + /* Remove the thread from the ready queue: */ + PTHREAD_PRIOQ_REMOVE(pthread_h); + + /* Make the selected thread the current thread: */ + _set_curthread(pthread_h); + + /* + * Save the current time as the time that the thread + * became active: + */ + current_tick = _sched_ticks; + pthread_h->last_active = (long) current_tick; + + /* + * Check if this thread is running for the first time + * or running again after using its full time slice + * allocation: + */ + if (pthread_h->slice_usec == -1) { + /* Reset the accumulated time slice period: */ + pthread_h->slice_usec = 0; + } + + /* + * If we had a context switch, run any + * installed switch hooks. + */ + if ((_sched_switch_hook != NULL) && + (_last_user_thread != pthread_h)) { + thread_run_switch_hook(_last_user_thread, + pthread_h); + } + /* + * Continue the thread at its current frame: + */ + _last_user_thread = td; + DBG_MSG("switch in\n"); + _thread_switch(&pthread_h->mailbox, + &_thread_kern_kse_mailbox.km_curthread); + DBG_MSG("switch out\n"); + } else { + /* + * There is nothing for us to do. Either + * yield, or idle until something wakes up. + */ + DBG_MSG("No runnable threads, idling.\n"); + + /* + * kse_yield() only returns if we are the + * only thread in this process. If so, then + * we drop into an idle loop. + */ + kse_yield(); + thread_kern_idle(); + + /* + * This thread's usage will likely be very small + * while waiting in a poll. Since the scheduling + * clock is based on the profiling timer, it is + * unlikely that the profiling timer will fire + * and update the time of day. To account for this, + * get the time of day after polling with a timeout. + */ + gettimeofday((struct timeval *) &_sched_tod, NULL); + } + DBG_MSG("looping\n"); + } + /* There are no threads; exit. */ + DBG_MSG("No threads, exiting.\n"); + exit(0); + } + + void + _thread_kern_sched_state(enum pthread_state state, char *fname, int lineno) + { + struct pthread *curthread = _get_curthread(); + + /* + * Flag the pthread kernel as executing scheduler code + * to avoid an upcall from interrupting this execution + * and calling the scheduler again. + */ + _thread_kern_kse_mailbox.km_curthread = NULL; + + /* Change the state of the current thread: */ + curthread->state = state; + curthread->fname = fname; + curthread->lineno = lineno; + + /* Schedule the next thread that is ready: */ + _thread_kern_sched(); + } + + void + _thread_kern_sched_state_unlock(enum pthread_state state, + spinlock_t *lock, char *fname, int lineno) + { + struct pthread *curthread = _get_curthread(); + + /* + * Flag the pthread kernel as executing scheduler code + * to avoid an upcall from interrupting this execution + * and calling the scheduler again. + */ + _thread_kern_kse_mailbox.km_curthread = NULL; + + /* Change the state of the current thread: */ + curthread->state = state; + curthread->fname = fname; + curthread->lineno = lineno; + + _SPINUNLOCK(lock); + + /* Schedule the next thread that is ready: */ + _thread_kern_sched(); + } + + /* + * XXX - What we need to do here is schedule ourselves an idle thread, + * which does the poll()/nanosleep()/whatever, and then will cause an + * upcall when it expires. This thread never gets inserted into the + * run_queue (in fact, there's no need for it to be a thread at all). + * timeout period has arrived. + */ + static void + thread_kern_idle() + { + int i, found; + int kern_pipe_added = 0; + int nfds = 0; + int timeout_ms = 0; + struct pthread *pthread; + struct timespec ts; + struct timeval tv; + + /* Get the current time of day: */ + GET_CURRENT_TOD(tv); + TIMEVAL_TO_TIMESPEC(&tv, &ts); + + pthread = TAILQ_FIRST(&_waitingq); + + if ((pthread == NULL) || (pthread->wakeup_time.tv_sec == -1)) { + /* + * Either there are no threads in the waiting queue, + * or there are no threads that can timeout. + * + * XXX: kse_yield() here, maybe? + */ + PANIC("Would idle forever"); + } + else if (pthread->wakeup_time.tv_sec - ts.tv_sec > 60000) + /* Limit maximum timeout to prevent rollover. */ + timeout_ms = 60000; + else { + /* + * Calculate the time left for the next thread to + * timeout: + */ + timeout_ms = ((pthread->wakeup_time.tv_sec - ts.tv_sec) * + 1000) + ((pthread->wakeup_time.tv_nsec - ts.tv_nsec) / + 1000000); + /* + * Only idle if we would be. + */ + if (timeout_ms <= 0) + return; + } + + /* + * Check for a thread that became runnable due to a signal: + */ + if (PTHREAD_PRIOQ_FIRST() != NULL) { + /* + * Since there is at least one runnable thread, + * disable the wait. + */ + timeout_ms = 0; + } + + /* + * Idle. + */ + __sys_poll(NULL, 0, timeout_ms); + + if (_spinblock_count != 0) { + /* + * Enter a loop to look for threads waiting on a spinlock + * that is now available. + */ + PTHREAD_WAITQ_SETACTIVE(); + TAILQ_FOREACH(pthread, &_workq, qe) { + if (pthread->state == PS_SPINBLOCK) { + /* + * If the lock is available, let the thread run. + */ + if (pthread->data.spinlock->access_lock == 0) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); + + /* + * One less thread in a spinblock state: + */ + _spinblock_count--; + } + } + } + PTHREAD_WAITQ_CLEARACTIVE(); + } + } + + void + _thread_kern_set_timeout(const struct timespec * timeout) + { + struct pthread *curthread = _get_curthread(); + struct timespec current_time; + struct timeval tv; + + /* Reset the timeout flag for the running thread: */ + curthread->timeout = 0; + + /* Check if the thread is to wait forever: */ + if (timeout == NULL) { + /* + * Set the wakeup time to something that can be recognised as + * different to an actual time of day: + */ + curthread->wakeup_time.tv_sec = -1; + curthread->wakeup_time.tv_nsec = -1; + } + /* Check if no waiting is required: */ + else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) { + /* Set the wake up time to 'immediately': */ + curthread->wakeup_time.tv_sec = 0; + curthread->wakeup_time.tv_nsec = 0; + } else { + /* Get the current time: */ + GET_CURRENT_TOD(tv); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); + + /* Calculate the time for the current thread to wake up: */ + curthread->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec; + curthread->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec; + + /* Check if the nanosecond field needs to wrap: */ + if (curthread->wakeup_time.tv_nsec >= 1000000000) { + /* Wrap the nanosecond field: */ + curthread->wakeup_time.tv_sec += 1; + curthread->wakeup_time.tv_nsec -= 1000000000; + } + } + } + + void + _thread_kern_sig_defer(void) + { + struct pthread *curthread = _get_curthread(); + + /* Allow signal deferral to be recursive. */ + curthread->sig_defer_count++; + } + + void + _thread_kern_sig_undefer(void) + { + struct pthread *curthread = _get_curthread(); + + /* + * Perform checks to yield only if we are about to undefer + * signals. + */ + if (curthread->sig_defer_count > 1) { + /* Decrement the signal deferral count. */ + curthread->sig_defer_count--; + } + else if (curthread->sig_defer_count == 1) { + /* Reenable signals: */ + curthread->sig_defer_count = 0; + + /* + * Check for asynchronous cancellation before delivering any + * pending signals: + */ + if (((curthread->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0) && + ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) + pthread_testcancel(); + } + } + + static inline void + thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in) + { + pthread_t tid_out = thread_out; + pthread_t tid_in = thread_in; + + if ((tid_out != NULL) && + (tid_out->flags & PTHREAD_FLAGS_PRIVATE) != 0) + tid_out = NULL; + if ((tid_in != NULL) && + (tid_in->flags & PTHREAD_FLAGS_PRIVATE) != 0) + tid_in = NULL; + + if ((_sched_switch_hook != NULL) && (tid_out != tid_in)) { + /* Run the scheduler switch hook: */ + _sched_switch_hook(tid_out, tid_in); + } + } + + struct pthread * + _get_curthread(void) + { + if (_thread_initial == NULL) + _thread_init(); + + return (_thread_run); + } + + void + _set_curthread(struct pthread *newthread) + { + _thread_run = newthread; + } Index: lib/libpthread/uthread/uthread_kill.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_kill.c Sun Sep 15 21:38:50 2002 *************** *** 0 **** --- 1,48 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_kill.c,v 1.12 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_kill, pthread_kill); + + int + _pthread_kill(pthread_t pthread, int sig) + { + /* + * All signals are unsupported. + */ + return (EINVAL); + } Index: lib/libpthread/uthread/uthread_main_np.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_main_np.c Sun Sep 15 21:38:50 2002 *************** *** 0 **** --- 1,47 ---- + /* + * Copyright (c) 2001 Alfred Perlstein + * Author: Alfred Perlstein + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_main_np.c,v 1.3 2002/04/15 23:11:38 obrien Exp $ + */ + + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_main_np, pthread_main_np); + + /* + * Provide the equivelant to Solaris thr_main() function + */ + int + _pthread_main_np() + { + + if (!_thread_initial) + return (-1); + else + return (pthread_equal(pthread_self(), _thread_initial) ? 1 : 0); + } Index: lib/libpthread/uthread/uthread_mattr_init.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_mattr_init.c Sun Sep 15 21:38:50 2002 *************** *** 0 **** --- 1,58 ---- + /* + * Copyright (c) 1996 Jeffrey Hsu . + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_mattr_init.c,v 1.7 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_mutexattr_init, pthread_mutexattr_init); + + int + _pthread_mutexattr_init(pthread_mutexattr_t *attr) + { + int ret; + pthread_mutexattr_t pattr; + + if ((pattr = (pthread_mutexattr_t) + malloc(sizeof(struct pthread_mutex_attr))) == NULL) { + ret = ENOMEM; + } else { + memcpy(pattr, &pthread_mutexattr_default, + sizeof(struct pthread_mutex_attr)); + *attr = pattr; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_mattr_kind_np.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_mattr_kind_np.c Sun Sep 15 21:38:50 2002 *************** *** 0 **** --- 1,97 ---- + /* + * Copyright (c) 1996 Jeffrey Hsu . + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_mattr_kind_np.c,v 1.7 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np); + __weak_reference(_pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np); + __weak_reference(_pthread_mutexattr_gettype, pthread_mutexattr_gettype); + __weak_reference(_pthread_mutexattr_settype, pthread_mutexattr_settype); + + int + _pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind) + { + int ret; + if (attr == NULL || *attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->m_type = kind; + ret = 0; + } + return(ret); + } + + int + _pthread_mutexattr_getkind_np(pthread_mutexattr_t attr) + { + int ret; + if (attr == NULL) { + errno = EINVAL; + ret = -1; + } else { + ret = attr->m_type; + } + return(ret); + } + + int + _pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) + { + int ret; + if (attr == NULL || *attr == NULL || type >= MUTEX_TYPE_MAX) { + errno = EINVAL; + ret = -1; + } else { + (*attr)->m_type = type; + ret = 0; + } + return(ret); + } + + int + _pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *type) + { + int ret; + + if (attr == NULL || *attr == NULL || (*attr)->m_type >= + MUTEX_TYPE_MAX) { + ret = EINVAL; + } else { + *type = (*attr)->m_type; + ret = 0; + } + return ret; + } Index: lib/libpthread/uthread/uthread_msync.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_msync.c Sun Sep 15 21:38:51 2002 *************** *** 0 **** --- 1,32 ---- + /* + * David Leonard , 1999. Public Domain. + * + * $OpenBSD: uthread_msync.c,v 1.2 1999/06/09 07:16:17 d Exp $ + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_msync.c,v 1.5 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__msync, msync); + + int + __msync(void *addr, size_t len, int flags) + { + int ret; + + /* + * XXX This is quite pointless unless we know how to get the + * file descriptor associated with the memory, and lock it for + * write. The only real use of this wrapper is to guarantee + * a cancellation point, as per the standard. sigh. + */ + _thread_enter_cancellation_point(); + ret = __sys_msync(addr, len, flags); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_multi_np.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_multi_np.c Sun Sep 15 21:38:51 2002 *************** *** 0 **** --- 1,50 ---- + /* + * Copyright (c) 1996 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_multi_np.c,v 1.7 2002/05/24 04:32:28 deischen Exp $ + */ + #include + #include + + __weak_reference(_pthread_multi_np, pthread_multi_np); + + int + _pthread_multi_np() + { + + /* Return to multi-threaded scheduling mode: */ + /* + * XXX - Do we want to do this? + * __is_threaded = 1; + */ + pthread_resume_all_np(); + return (0); + } Index: lib/libpthread/uthread/uthread_mutex.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_mutex.c Sun Sep 15 21:38:51 2002 *************** *** 0 **** --- 1,1544 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_mutex.c,v 1.31 2002/05/24 04:32:28 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + #if defined(_PTHREADS_INVARIANTS) + #define _MUTEX_INIT_LINK(m) do { \ + (m)->m_qe.tqe_prev = NULL; \ + (m)->m_qe.tqe_next = NULL; \ + } while (0) + #define _MUTEX_ASSERT_IS_OWNED(m) do { \ + if ((m)->m_qe.tqe_prev == NULL) \ + PANIC("mutex is not on list"); \ + } while (0) + #define _MUTEX_ASSERT_NOT_OWNED(m) do { \ + if (((m)->m_qe.tqe_prev != NULL) || \ + ((m)->m_qe.tqe_next != NULL)) \ + PANIC("mutex is on list"); \ + } while (0) + #else + #define _MUTEX_INIT_LINK(m) + #define _MUTEX_ASSERT_IS_OWNED(m) + #define _MUTEX_ASSERT_NOT_OWNED(m) + #endif + + /* + * Prototypes + */ + static inline int mutex_self_trylock(pthread_mutex_t); + static inline int mutex_self_lock(pthread_mutex_t); + static inline int mutex_unlock_common(pthread_mutex_t *, int); + static void mutex_priority_adjust(pthread_mutex_t); + static void mutex_rescan_owned (pthread_t, pthread_mutex_t); + static inline pthread_t mutex_queue_deq(pthread_mutex_t); + static inline void mutex_queue_remove(pthread_mutex_t, pthread_t); + static inline void mutex_queue_enq(pthread_mutex_t, pthread_t); + + + static spinlock_t static_init_lock = _SPINLOCK_INITIALIZER; + + static struct pthread_mutex_attr static_mutex_attr = + PTHREAD_MUTEXATTR_STATIC_INITIALIZER; + static pthread_mutexattr_t static_mattr = &static_mutex_attr; + + /* Single underscore versions provided for libc internal usage: */ + __weak_reference(__pthread_mutex_trylock, pthread_mutex_trylock); + __weak_reference(__pthread_mutex_lock, pthread_mutex_lock); + + /* No difference between libc and application usage of these: */ + __weak_reference(_pthread_mutex_init, pthread_mutex_init); + __weak_reference(_pthread_mutex_destroy, pthread_mutex_destroy); + __weak_reference(_pthread_mutex_unlock, pthread_mutex_unlock); + + + /* Reinitialize a mutex to defaults. */ + int + _mutex_reinit(pthread_mutex_t * mutex) + { + int ret = 0; + + if (mutex == NULL) + ret = EINVAL; + else if (*mutex == NULL) + ret = pthread_mutex_init(mutex, NULL); + else { + /* + * Initialize the mutex structure: + */ + (*mutex)->m_type = PTHREAD_MUTEX_DEFAULT; + (*mutex)->m_protocol = PTHREAD_PRIO_NONE; + TAILQ_INIT(&(*mutex)->m_queue); + (*mutex)->m_owner = NULL; + (*mutex)->m_data.m_count = 0; + (*mutex)->m_flags &= MUTEX_FLAGS_PRIVATE; + (*mutex)->m_flags |= MUTEX_FLAGS_INITED; + (*mutex)->m_refcount = 0; + (*mutex)->m_prio = 0; + (*mutex)->m_saved_prio = 0; + _MUTEX_INIT_LINK(*mutex); + memset(&(*mutex)->lock, 0, sizeof((*mutex)->lock)); + } + return (ret); + } + + int + _pthread_mutex_init(pthread_mutex_t * mutex, + const pthread_mutexattr_t * mutex_attr) + { + enum pthread_mutextype type; + int protocol; + int ceiling; + int flags; + pthread_mutex_t pmutex; + int ret = 0; + + if (mutex == NULL) + ret = EINVAL; + + /* Check if default mutex attributes: */ + else if (mutex_attr == NULL || *mutex_attr == NULL) { + /* Default to a (error checking) POSIX mutex: */ + type = PTHREAD_MUTEX_ERRORCHECK; + protocol = PTHREAD_PRIO_NONE; + ceiling = PTHREAD_MAX_PRIORITY; + flags = 0; + } + + /* Check mutex type: */ + else if (((*mutex_attr)->m_type < PTHREAD_MUTEX_ERRORCHECK) || + ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX)) + /* Return an invalid argument error: */ + ret = EINVAL; + + /* Check mutex protocol: */ + else if (((*mutex_attr)->m_protocol < PTHREAD_PRIO_NONE) || + ((*mutex_attr)->m_protocol > PTHREAD_MUTEX_RECURSIVE)) + /* Return an invalid argument error: */ + ret = EINVAL; + + else { + /* Use the requested mutex type and protocol: */ + type = (*mutex_attr)->m_type; + protocol = (*mutex_attr)->m_protocol; + ceiling = (*mutex_attr)->m_ceiling; + flags = (*mutex_attr)->m_flags; + } + + /* Check no errors so far: */ + if (ret == 0) { + if ((pmutex = (pthread_mutex_t) + malloc(sizeof(struct pthread_mutex))) == NULL) + ret = ENOMEM; + else { + /* Set the mutex flags: */ + pmutex->m_flags = flags; + + /* Process according to mutex type: */ + switch (type) { + /* case PTHREAD_MUTEX_DEFAULT: */ + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_NORMAL: + /* Nothing to do here. */ + break; + + /* Single UNIX Spec 2 recursive mutex: */ + case PTHREAD_MUTEX_RECURSIVE: + /* Reset the mutex count: */ + pmutex->m_data.m_count = 0; + break; + + /* Trap invalid mutex types: */ + default: + /* Return an invalid argument error: */ + ret = EINVAL; + break; + } + if (ret == 0) { + /* Initialise the rest of the mutex: */ + TAILQ_INIT(&pmutex->m_queue); + pmutex->m_flags |= MUTEX_FLAGS_INITED; + pmutex->m_owner = NULL; + pmutex->m_type = type; + pmutex->m_protocol = protocol; + pmutex->m_refcount = 0; + if (protocol == PTHREAD_PRIO_PROTECT) + pmutex->m_prio = ceiling; + else + pmutex->m_prio = 0; + pmutex->m_saved_prio = 0; + _MUTEX_INIT_LINK(pmutex); + memset(&pmutex->lock, 0, sizeof(pmutex->lock)); + *mutex = pmutex; + } else { + free(pmutex); + *mutex = NULL; + } + } + } + /* Return the completion status: */ + return(ret); + } + + int + _pthread_mutex_destroy(pthread_mutex_t * mutex) + { + int ret = 0; + + if (mutex == NULL || *mutex == NULL) + ret = EINVAL; + else { + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* + * Check to see if this mutex is in use: + */ + if (((*mutex)->m_owner != NULL) || + (TAILQ_FIRST(&(*mutex)->m_queue) != NULL) || + ((*mutex)->m_refcount != 0)) { + ret = EBUSY; + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + } + else { + /* + * Free the memory allocated for the mutex + * structure: + */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); + free(*mutex); + + /* + * Leave the caller's pointer NULL now that + * the mutex has been destroyed: + */ + *mutex = NULL; + } + } + + /* Return the completion status: */ + return (ret); + } + + static int + init_static(pthread_mutex_t *mutex) + { + int ret; + + _SPINLOCK(&static_init_lock); + + if (*mutex == NULL) + ret = pthread_mutex_init(mutex, NULL); + else + ret = 0; + + _SPINUNLOCK(&static_init_lock); + + return(ret); + } + + static int + init_static_private(pthread_mutex_t *mutex) + { + int ret; + + _SPINLOCK(&static_init_lock); + + if (*mutex == NULL) + ret = pthread_mutex_init(mutex, &static_mattr); + else + ret = 0; + + _SPINUNLOCK(&static_init_lock); + + return(ret); + } + + static int + mutex_trylock_common(pthread_mutex_t *mutex) + { + struct pthread *curthread = _get_curthread(); + int ret = 0; + + PTHREAD_ASSERT((mutex != NULL) && (*mutex != NULL), + "Uninitialized mutex in pthread_mutex_trylock_basic"); + + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* + * If the mutex was statically allocated, properly + * initialize the tail queue. + */ + if (((*mutex)->m_flags & MUTEX_FLAGS_INITED) == 0) { + TAILQ_INIT(&(*mutex)->m_queue); + _MUTEX_INIT_LINK(*mutex); + (*mutex)->m_flags |= MUTEX_FLAGS_INITED; + } + + /* Process according to mutex type: */ + switch ((*mutex)->m_protocol) { + /* Default POSIX mutex: */ + case PTHREAD_PRIO_NONE: + /* Check if this mutex is not locked: */ + if ((*mutex)->m_owner == NULL) { + /* Lock the mutex for the running thread: */ + (*mutex)->m_owner = curthread; + + /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); + TAILQ_INSERT_TAIL(&curthread->mutexq, + (*mutex), m_qe); + } else if ((*mutex)->m_owner == curthread) + ret = mutex_self_trylock(*mutex); + else + /* Return a busy error: */ + ret = EBUSY; + break; + + /* POSIX priority inheritence mutex: */ + case PTHREAD_PRIO_INHERIT: + /* Check if this mutex is not locked: */ + if ((*mutex)->m_owner == NULL) { + /* Lock the mutex for the running thread: */ + (*mutex)->m_owner = curthread; + + /* Track number of priority mutexes owned: */ + curthread->priority_mutex_count++; + + /* + * The mutex takes on the attributes of the + * running thread when there are no waiters. + */ + (*mutex)->m_prio = curthread->active_priority; + (*mutex)->m_saved_prio = + curthread->inherited_priority; + + /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); + TAILQ_INSERT_TAIL(&curthread->mutexq, + (*mutex), m_qe); + } else if ((*mutex)->m_owner == curthread) + ret = mutex_self_trylock(*mutex); + else + /* Return a busy error: */ + ret = EBUSY; + break; + + /* POSIX priority protection mutex: */ + case PTHREAD_PRIO_PROTECT: + /* Check for a priority ceiling violation: */ + if (curthread->active_priority > (*mutex)->m_prio) + ret = EINVAL; + + /* Check if this mutex is not locked: */ + else if ((*mutex)->m_owner == NULL) { + /* Lock the mutex for the running thread: */ + (*mutex)->m_owner = curthread; + + /* Track number of priority mutexes owned: */ + curthread->priority_mutex_count++; + + /* + * The running thread inherits the ceiling + * priority of the mutex and executes at that + * priority. + */ + curthread->active_priority = (*mutex)->m_prio; + (*mutex)->m_saved_prio = + curthread->inherited_priority; + curthread->inherited_priority = + (*mutex)->m_prio; + + /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); + TAILQ_INSERT_TAIL(&curthread->mutexq, + (*mutex), m_qe); + } else if ((*mutex)->m_owner == curthread) + ret = mutex_self_trylock(*mutex); + else + /* Return a busy error: */ + ret = EBUSY; + break; + + /* Trap invalid mutex types: */ + default: + /* Return an invalid argument error: */ + ret = EINVAL; + break; + } + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + + /* Return the completion status: */ + return (ret); + } + + int + __pthread_mutex_trylock(pthread_mutex_t *mutex) + { + int ret = 0; + + if (mutex == NULL) + ret = EINVAL; + + /* + * If the mutex is statically initialized, perform the dynamic + * initialization: + */ + else if ((*mutex != NULL) || (ret = init_static(mutex)) == 0) + ret = mutex_trylock_common(mutex); + + return (ret); + } + + int + _pthread_mutex_trylock(pthread_mutex_t *mutex) + { + int ret = 0; + + if (mutex == NULL) + ret = EINVAL; + + /* + * If the mutex is statically initialized, perform the dynamic + * initialization marking the mutex private (delete safe): + */ + else if ((*mutex != NULL) || (ret = init_static_private(mutex)) == 0) + ret = mutex_trylock_common(mutex); + + return (ret); + } + + static int + mutex_lock_common(pthread_mutex_t * mutex) + { + struct pthread *curthread = _get_curthread(); + int ret = 0; + + PTHREAD_ASSERT((mutex != NULL) && (*mutex != NULL), + "Uninitialized mutex in pthread_mutex_trylock_basic"); + + /* Reset the interrupted flag: */ + curthread->interrupted = 0; + + /* + * Enter a loop waiting to become the mutex owner. We need a + * loop in case the waiting thread is interrupted by a signal + * to execute a signal handler. It is not (currently) possible + * to remain in the waiting queue while running a handler. + * Instead, the thread is interrupted and backed out of the + * waiting queue prior to executing the signal handler. + */ + do { + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* + * If the mutex was statically allocated, properly + * initialize the tail queue. + */ + if (((*mutex)->m_flags & MUTEX_FLAGS_INITED) == 0) { + TAILQ_INIT(&(*mutex)->m_queue); + (*mutex)->m_flags |= MUTEX_FLAGS_INITED; + _MUTEX_INIT_LINK(*mutex); + } + + /* Process according to mutex type: */ + switch ((*mutex)->m_protocol) { + /* Default POSIX mutex: */ + case PTHREAD_PRIO_NONE: + if ((*mutex)->m_owner == NULL) { + /* Lock the mutex for this thread: */ + (*mutex)->m_owner = curthread; + + /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); + TAILQ_INSERT_TAIL(&curthread->mutexq, + (*mutex), m_qe); + + } else if ((*mutex)->m_owner == curthread) + ret = mutex_self_lock(*mutex); + else { + /* + * Join the queue of threads waiting to lock + * the mutex: + */ + mutex_queue_enq(*mutex, curthread); + + /* + * Keep a pointer to the mutex this thread + * is waiting on: + */ + curthread->data.mutex = *mutex; + + /* + * Unlock the mutex structure and schedule the + * next thread: + */ + _thread_kern_sched_state_unlock(PS_MUTEX_WAIT, + &(*mutex)->lock, __FILE__, __LINE__); + + /* Lock the mutex structure again: */ + _SPINLOCK(&(*mutex)->lock); + } + break; + + /* POSIX priority inheritence mutex: */ + case PTHREAD_PRIO_INHERIT: + /* Check if this mutex is not locked: */ + if ((*mutex)->m_owner == NULL) { + /* Lock the mutex for this thread: */ + (*mutex)->m_owner = curthread; + + /* Track number of priority mutexes owned: */ + curthread->priority_mutex_count++; + + /* + * The mutex takes on attributes of the + * running thread when there are no waiters. + */ + (*mutex)->m_prio = curthread->active_priority; + (*mutex)->m_saved_prio = + curthread->inherited_priority; + curthread->inherited_priority = + (*mutex)->m_prio; + + /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); + TAILQ_INSERT_TAIL(&curthread->mutexq, + (*mutex), m_qe); + + } else if ((*mutex)->m_owner == curthread) + ret = mutex_self_lock(*mutex); + else { + /* + * Join the queue of threads waiting to lock + * the mutex: + */ + mutex_queue_enq(*mutex, curthread); + + /* + * Keep a pointer to the mutex this thread + * is waiting on: + */ + curthread->data.mutex = *mutex; + + if (curthread->active_priority > + (*mutex)->m_prio) + /* Adjust priorities: */ + mutex_priority_adjust(*mutex); + + /* + * Unlock the mutex structure and schedule the + * next thread: + */ + _thread_kern_sched_state_unlock(PS_MUTEX_WAIT, + &(*mutex)->lock, __FILE__, __LINE__); + + /* Lock the mutex structure again: */ + _SPINLOCK(&(*mutex)->lock); + } + break; + + /* POSIX priority protection mutex: */ + case PTHREAD_PRIO_PROTECT: + /* Check for a priority ceiling violation: */ + if (curthread->active_priority > (*mutex)->m_prio) + ret = EINVAL; + + /* Check if this mutex is not locked: */ + else if ((*mutex)->m_owner == NULL) { + /* + * Lock the mutex for the running + * thread: + */ + (*mutex)->m_owner = curthread; + + /* Track number of priority mutexes owned: */ + curthread->priority_mutex_count++; + + /* + * The running thread inherits the ceiling + * priority of the mutex and executes at that + * priority: + */ + curthread->active_priority = (*mutex)->m_prio; + (*mutex)->m_saved_prio = + curthread->inherited_priority; + curthread->inherited_priority = + (*mutex)->m_prio; + + /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); + TAILQ_INSERT_TAIL(&curthread->mutexq, + (*mutex), m_qe); + } else if ((*mutex)->m_owner == curthread) + ret = mutex_self_lock(*mutex); + else { + /* + * Join the queue of threads waiting to lock + * the mutex: + */ + mutex_queue_enq(*mutex, curthread); + + /* + * Keep a pointer to the mutex this thread + * is waiting on: + */ + curthread->data.mutex = *mutex; + + /* Clear any previous error: */ + curthread->error = 0; + + /* + * Unlock the mutex structure and schedule the + * next thread: + */ + _thread_kern_sched_state_unlock(PS_MUTEX_WAIT, + &(*mutex)->lock, __FILE__, __LINE__); + + /* Lock the mutex structure again: */ + _SPINLOCK(&(*mutex)->lock); + + /* + * The threads priority may have changed while + * waiting for the mutex causing a ceiling + * violation. + */ + ret = curthread->error; + curthread->error = 0; + } + break; + + /* Trap invalid mutex types: */ + default: + /* Return an invalid argument error: */ + ret = EINVAL; + break; + } + + /* + * Check to see if this thread was interrupted and + * is still in the mutex queue of waiting threads: + */ + if (curthread->interrupted != 0) + mutex_queue_remove(*mutex, curthread); + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } while (((*mutex)->m_owner != curthread) && (ret == 0) && + (curthread->interrupted == 0)); + + if (curthread->interrupted != 0 && + curthread->continuation != NULL) + curthread->continuation((void *) curthread); + + /* Return the completion status: */ + return (ret); + } + + int + __pthread_mutex_lock(pthread_mutex_t *mutex) + { + int ret = 0; + + if (_thread_initial == NULL) + _thread_init(); + + if (mutex == NULL) + ret = EINVAL; + + /* + * If the mutex is statically initialized, perform the dynamic + * initialization: + */ + else if ((*mutex != NULL) || ((ret = init_static(mutex)) == 0)) + ret = mutex_lock_common(mutex); + + return (ret); + } + + int + _pthread_mutex_lock(pthread_mutex_t *mutex) + { + int ret = 0; + + if (_thread_initial == NULL) + _thread_init(); + + if (mutex == NULL) + ret = EINVAL; + + /* + * If the mutex is statically initialized, perform the dynamic + * initialization marking it private (delete safe): + */ + else if ((*mutex != NULL) || ((ret = init_static_private(mutex)) == 0)) + ret = mutex_lock_common(mutex); + + return (ret); + } + + int + _pthread_mutex_unlock(pthread_mutex_t * mutex) + { + return (mutex_unlock_common(mutex, /* add reference */ 0)); + } + + int + _mutex_cv_unlock(pthread_mutex_t * mutex) + { + return (mutex_unlock_common(mutex, /* add reference */ 1)); + } + + int + _mutex_cv_lock(pthread_mutex_t * mutex) + { + int ret; + if ((ret = pthread_mutex_lock(mutex)) == 0) + (*mutex)->m_refcount--; + return (ret); + } + + static inline int + mutex_self_trylock(pthread_mutex_t mutex) + { + int ret = 0; + + switch (mutex->m_type) { + + /* case PTHREAD_MUTEX_DEFAULT: */ + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_NORMAL: + /* + * POSIX specifies that mutexes should return EDEADLK if a + * recursive lock is detected. + */ + ret = EBUSY; + break; + + case PTHREAD_MUTEX_RECURSIVE: + /* Increment the lock count: */ + mutex->m_data.m_count++; + break; + + default: + /* Trap invalid mutex types; */ + ret = EINVAL; + } + + return(ret); + } + + static inline int + mutex_self_lock(pthread_mutex_t mutex) + { + int ret = 0; + + switch (mutex->m_type) { + /* case PTHREAD_MUTEX_DEFAULT: */ + case PTHREAD_MUTEX_ERRORCHECK: + /* + * POSIX specifies that mutexes should return EDEADLK if a + * recursive lock is detected. + */ + ret = EDEADLK; + break; + + case PTHREAD_MUTEX_NORMAL: + /* + * What SS2 define as a 'normal' mutex. Intentionally + * deadlock on attempts to get a lock you already own. + */ + _thread_kern_sched_state_unlock(PS_DEADLOCK, + &mutex->lock, __FILE__, __LINE__); + break; + + case PTHREAD_MUTEX_RECURSIVE: + /* Increment the lock count: */ + mutex->m_data.m_count++; + break; + + default: + /* Trap invalid mutex types; */ + ret = EINVAL; + } + + return(ret); + } + + static inline int + mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) + { + struct pthread *curthread = _get_curthread(); + int ret = 0; + + if (mutex == NULL || *mutex == NULL) { + ret = EINVAL; + } else { + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* Process according to mutex type: */ + switch ((*mutex)->m_protocol) { + /* Default POSIX mutex: */ + case PTHREAD_PRIO_NONE: + /* + * Check if the running thread is not the owner of the + * mutex: + */ + if ((*mutex)->m_owner != curthread) { + /* + * Return an invalid argument error for no + * owner and a permission error otherwise: + */ + ret = (*mutex)->m_owner == NULL ? EINVAL : EPERM; + } + else if (((*mutex)->m_type == PTHREAD_MUTEX_RECURSIVE) && + ((*mutex)->m_data.m_count > 0)) { + /* Decrement the count: */ + (*mutex)->m_data.m_count--; + } else { + /* + * Clear the count in case this is recursive + * mutex. + */ + (*mutex)->m_data.m_count = 0; + + /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); + TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, + (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); + + /* + * Get the next thread from the queue of + * threads waiting on the mutex: + */ + if (((*mutex)->m_owner = + mutex_queue_deq(*mutex)) != NULL) { + /* Make the new owner runnable: */ + PTHREAD_NEW_STATE((*mutex)->m_owner, + PS_RUNNING); + + /* + * Add the mutex to the threads list of + * owned mutexes: + */ + TAILQ_INSERT_TAIL(&(*mutex)->m_owner->mutexq, + (*mutex), m_qe); + + /* + * The owner is no longer waiting for + * this mutex: + */ + (*mutex)->m_owner->data.mutex = NULL; + } + } + break; + + /* POSIX priority inheritence mutex: */ + case PTHREAD_PRIO_INHERIT: + /* + * Check if the running thread is not the owner of the + * mutex: + */ + if ((*mutex)->m_owner != curthread) { + /* + * Return an invalid argument error for no + * owner and a permission error otherwise: + */ + ret = (*mutex)->m_owner == NULL ? EINVAL : EPERM; + } + else if (((*mutex)->m_type == PTHREAD_MUTEX_RECURSIVE) && + ((*mutex)->m_data.m_count > 0)) { + /* Decrement the count: */ + (*mutex)->m_data.m_count--; + } else { + /* + * Clear the count in case this is recursive + * mutex. + */ + (*mutex)->m_data.m_count = 0; + + /* + * Restore the threads inherited priority and + * recompute the active priority (being careful + * not to override changes in the threads base + * priority subsequent to locking the mutex). + */ + curthread->inherited_priority = + (*mutex)->m_saved_prio; + curthread->active_priority = + MAX(curthread->inherited_priority, + curthread->base_priority); + + /* + * This thread now owns one less priority mutex. + */ + curthread->priority_mutex_count--; + + /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); + TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, + (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); + + /* + * Get the next thread from the queue of threads + * waiting on the mutex: + */ + if (((*mutex)->m_owner = + mutex_queue_deq(*mutex)) == NULL) + /* This mutex has no priority. */ + (*mutex)->m_prio = 0; + else { + /* + * Track number of priority mutexes owned: + */ + (*mutex)->m_owner->priority_mutex_count++; + + /* + * Add the mutex to the threads list + * of owned mutexes: + */ + TAILQ_INSERT_TAIL(&(*mutex)->m_owner->mutexq, + (*mutex), m_qe); + + /* + * The owner is no longer waiting for + * this mutex: + */ + (*mutex)->m_owner->data.mutex = NULL; + + /* + * Set the priority of the mutex. Since + * our waiting threads are in descending + * priority order, the priority of the + * mutex becomes the active priority of + * the thread we just dequeued. + */ + (*mutex)->m_prio = + (*mutex)->m_owner->active_priority; + + /* + * Save the owning threads inherited + * priority: + */ + (*mutex)->m_saved_prio = + (*mutex)->m_owner->inherited_priority; + + /* + * The owning threads inherited priority + * now becomes his active priority (the + * priority of the mutex). + */ + (*mutex)->m_owner->inherited_priority = + (*mutex)->m_prio; + + /* + * Make the new owner runnable: + */ + PTHREAD_NEW_STATE((*mutex)->m_owner, + PS_RUNNING); + } + } + break; + + /* POSIX priority ceiling mutex: */ + case PTHREAD_PRIO_PROTECT: + /* + * Check if the running thread is not the owner of the + * mutex: + */ + if ((*mutex)->m_owner != curthread) { + /* + * Return an invalid argument error for no + * owner and a permission error otherwise: + */ + ret = (*mutex)->m_owner == NULL ? EINVAL : EPERM; + } + else if (((*mutex)->m_type == PTHREAD_MUTEX_RECURSIVE) && + ((*mutex)->m_data.m_count > 0)) { + /* Decrement the count: */ + (*mutex)->m_data.m_count--; + } else { + /* + * Clear the count in case this is recursive + * mutex. + */ + (*mutex)->m_data.m_count = 0; + + /* + * Restore the threads inherited priority and + * recompute the active priority (being careful + * not to override changes in the threads base + * priority subsequent to locking the mutex). + */ + curthread->inherited_priority = + (*mutex)->m_saved_prio; + curthread->active_priority = + MAX(curthread->inherited_priority, + curthread->base_priority); + + /* + * This thread now owns one less priority mutex. + */ + curthread->priority_mutex_count--; + + /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); + TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, + (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); + + /* + * Enter a loop to find a waiting thread whose + * active priority will not cause a ceiling + * violation: + */ + while ((((*mutex)->m_owner = + mutex_queue_deq(*mutex)) != NULL) && + ((*mutex)->m_owner->active_priority > + (*mutex)->m_prio)) { + /* + * Either the mutex ceiling priority + * been lowered and/or this threads + * priority has been raised subsequent + * to this thread being queued on the + * waiting list. + */ + (*mutex)->m_owner->error = EINVAL; + PTHREAD_NEW_STATE((*mutex)->m_owner, + PS_RUNNING); + /* + * The thread is no longer waiting for + * this mutex: + */ + (*mutex)->m_owner->data.mutex = NULL; + } + + /* Check for a new owner: */ + if ((*mutex)->m_owner != NULL) { + /* + * Track number of priority mutexes owned: + */ + (*mutex)->m_owner->priority_mutex_count++; + + /* + * Add the mutex to the threads list + * of owned mutexes: + */ + TAILQ_INSERT_TAIL(&(*mutex)->m_owner->mutexq, + (*mutex), m_qe); + + /* + * The owner is no longer waiting for + * this mutex: + */ + (*mutex)->m_owner->data.mutex = NULL; + + /* + * Save the owning threads inherited + * priority: + */ + (*mutex)->m_saved_prio = + (*mutex)->m_owner->inherited_priority; + + /* + * The owning thread inherits the + * ceiling priority of the mutex and + * executes at that priority: + */ + (*mutex)->m_owner->inherited_priority = + (*mutex)->m_prio; + (*mutex)->m_owner->active_priority = + (*mutex)->m_prio; + + /* + * Make the new owner runnable: + */ + PTHREAD_NEW_STATE((*mutex)->m_owner, + PS_RUNNING); + } + } + break; + + /* Trap invalid mutex types: */ + default: + /* Return an invalid argument error: */ + ret = EINVAL; + break; + } + + if ((ret == 0) && (add_reference != 0)) { + /* Increment the reference count: */ + (*mutex)->m_refcount++; + } + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&(*mutex)->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + + /* Return the completion status: */ + return (ret); + } + + + /* + * This function is called when a change in base priority occurs for + * a thread that is holding or waiting for a priority protection or + * inheritence mutex. A change in a threads base priority can effect + * changes to active priorities of other threads and to the ordering + * of mutex locking by waiting threads. + * + * This must be called while thread scheduling is deferred. + */ + void + _mutex_notify_priochange(pthread_t pthread) + { + /* Adjust the priorites of any owned priority mutexes: */ + if (pthread->priority_mutex_count > 0) { + /* + * Rescan the mutexes owned by this thread and correct + * their priorities to account for this threads change + * in priority. This has the side effect of changing + * the threads active priority. + */ + mutex_rescan_owned(pthread, /* rescan all owned */ NULL); + } + + /* + * If this thread is waiting on a priority inheritence mutex, + * check for priority adjustments. A change in priority can + * also effect a ceiling violation(*) for a thread waiting on + * a priority protection mutex; we don't perform the check here + * as it is done in pthread_mutex_unlock. + * + * (*) It should be noted that a priority change to a thread + * _after_ taking and owning a priority ceiling mutex + * does not affect ownership of that mutex; the ceiling + * priority is only checked before mutex ownership occurs. + */ + if (pthread->state == PS_MUTEX_WAIT) { + /* Lock the mutex structure: */ + _SPINLOCK(&pthread->data.mutex->lock); + + /* + * Check to make sure this thread is still in the same state + * (the spinlock above can yield the CPU to another thread): + */ + if (pthread->state == PS_MUTEX_WAIT) { + /* + * Remove and reinsert this thread into the list of + * waiting threads to preserve decreasing priority + * order. + */ + mutex_queue_remove(pthread->data.mutex, pthread); + mutex_queue_enq(pthread->data.mutex, pthread); + + if (pthread->data.mutex->m_protocol == + PTHREAD_PRIO_INHERIT) { + /* Adjust priorities: */ + mutex_priority_adjust(pthread->data.mutex); + } + } + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&pthread->data.mutex->lock); + } + } + + /* + * Called when a new thread is added to the mutex waiting queue or + * when a threads priority changes that is already in the mutex + * waiting queue. + */ + static void + mutex_priority_adjust(pthread_mutex_t mutex) + { + pthread_t pthread_next, pthread = mutex->m_owner; + int temp_prio; + pthread_mutex_t m = mutex; + + /* + * Calculate the mutex priority as the maximum of the highest + * active priority of any waiting threads and the owning threads + * active priority(*). + * + * (*) Because the owning threads current active priority may + * reflect priority inherited from this mutex (and the mutex + * priority may have changed) we must recalculate the active + * priority based on the threads saved inherited priority + * and its base priority. + */ + pthread_next = TAILQ_FIRST(&m->m_queue); /* should never be NULL */ + temp_prio = MAX(pthread_next->active_priority, + MAX(m->m_saved_prio, pthread->base_priority)); + + /* See if this mutex really needs adjusting: */ + if (temp_prio == m->m_prio) + /* No need to propagate the priority: */ + return; + + /* Set new priority of the mutex: */ + m->m_prio = temp_prio; + + while (m != NULL) { + /* + * Save the threads priority before rescanning the + * owned mutexes: + */ + temp_prio = pthread->active_priority; + + /* + * Fix the priorities for all the mutexes this thread has + * locked since taking this mutex. This also has a + * potential side-effect of changing the threads priority. + */ + mutex_rescan_owned(pthread, m); + + /* + * If the thread is currently waiting on a mutex, check + * to see if the threads new priority has affected the + * priority of the mutex. + */ + if ((temp_prio != pthread->active_priority) && + (pthread->state == PS_MUTEX_WAIT) && + (pthread->data.mutex->m_protocol == PTHREAD_PRIO_INHERIT)) { + /* Grab the mutex this thread is waiting on: */ + m = pthread->data.mutex; + + /* + * The priority for this thread has changed. Remove + * and reinsert this thread into the list of waiting + * threads to preserve decreasing priority order. + */ + mutex_queue_remove(m, pthread); + mutex_queue_enq(m, pthread); + + /* Grab the waiting thread with highest priority: */ + pthread_next = TAILQ_FIRST(&m->m_queue); + + /* + * Calculate the mutex priority as the maximum of the + * highest active priority of any waiting threads and + * the owning threads active priority. + */ + temp_prio = MAX(pthread_next->active_priority, + MAX(m->m_saved_prio, m->m_owner->base_priority)); + + if (temp_prio != m->m_prio) { + /* + * The priority needs to be propagated to the + * mutex this thread is waiting on and up to + * the owner of that mutex. + */ + m->m_prio = temp_prio; + pthread = m->m_owner; + } + else + /* We're done: */ + m = NULL; + + } + else + /* We're done: */ + m = NULL; + } + } + + static void + mutex_rescan_owned(pthread_t pthread, pthread_mutex_t mutex) + { + int active_prio, inherited_prio; + pthread_mutex_t m; + pthread_t pthread_next; + + /* + * Start walking the mutexes the thread has taken since + * taking this mutex. + */ + if (mutex == NULL) { + /* + * A null mutex means start at the beginning of the owned + * mutex list. + */ + m = TAILQ_FIRST(&pthread->mutexq); + + /* There is no inherited priority yet. */ + inherited_prio = 0; + } + else { + /* + * The caller wants to start after a specific mutex. It + * is assumed that this mutex is a priority inheritence + * mutex and that its priority has been correctly + * calculated. + */ + m = TAILQ_NEXT(mutex, m_qe); + + /* Start inheriting priority from the specified mutex. */ + inherited_prio = mutex->m_prio; + } + active_prio = MAX(inherited_prio, pthread->base_priority); + + while (m != NULL) { + /* + * We only want to deal with priority inheritence + * mutexes. This might be optimized by only placing + * priority inheritence mutexes into the owned mutex + * list, but it may prove to be useful having all + * owned mutexes in this list. Consider a thread + * exiting while holding mutexes... + */ + if (m->m_protocol == PTHREAD_PRIO_INHERIT) { + /* + * Fix the owners saved (inherited) priority to + * reflect the priority of the previous mutex. + */ + m->m_saved_prio = inherited_prio; + + if ((pthread_next = TAILQ_FIRST(&m->m_queue)) != NULL) + /* Recalculate the priority of the mutex: */ + m->m_prio = MAX(active_prio, + pthread_next->active_priority); + else + m->m_prio = active_prio; + + /* Recalculate new inherited and active priorities: */ + inherited_prio = m->m_prio; + active_prio = MAX(m->m_prio, pthread->base_priority); + } + + /* Advance to the next mutex owned by this thread: */ + m = TAILQ_NEXT(m, m_qe); + } + + /* + * Fix the threads inherited priority and recalculate its + * active priority. + */ + pthread->inherited_priority = inherited_prio; + active_prio = MAX(inherited_prio, pthread->base_priority); + + if (active_prio != pthread->active_priority) { + /* + * If this thread is in the priority queue, it must be + * removed and reinserted for its new priority. + */ + if (pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) { + /* + * Remove the thread from the priority queue + * before changing its priority: + */ + PTHREAD_PRIOQ_REMOVE(pthread); + + /* + * POSIX states that if the priority is being + * lowered, the thread must be inserted at the + * head of the queue for its priority if it owns + * any priority protection or inheritence mutexes. + */ + if ((active_prio < pthread->active_priority) && + (pthread->priority_mutex_count > 0)) { + /* Set the new active priority. */ + pthread->active_priority = active_prio; + + PTHREAD_PRIOQ_INSERT_HEAD(pthread); + } + else { + /* Set the new active priority. */ + pthread->active_priority = active_prio; + + PTHREAD_PRIOQ_INSERT_TAIL(pthread); + } + } + else { + /* Set the new active priority. */ + pthread->active_priority = active_prio; + } + } + } + + void + _mutex_unlock_private(pthread_t pthread) + { + struct pthread_mutex *m, *m_next; + + for (m = TAILQ_FIRST(&pthread->mutexq); m != NULL; m = m_next) { + m_next = TAILQ_NEXT(m, m_qe); + if ((m->m_flags & MUTEX_FLAGS_PRIVATE) != 0) + pthread_mutex_unlock(&m); + } + } + + void + _mutex_lock_backout(pthread_t pthread) + { + struct pthread_mutex *mutex; + + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + if ((pthread->flags & PTHREAD_FLAGS_IN_MUTEXQ) != 0) { + mutex = pthread->data.mutex; + + /* Lock the mutex structure: */ + _SPINLOCK(&mutex->lock); + + mutex_queue_remove(mutex, pthread); + + /* This thread is no longer waiting for the mutex: */ + pthread->data.mutex = NULL; + + /* Unlock the mutex structure: */ + _SPINUNLOCK(&mutex->lock); + + } + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + + /* + * Dequeue a waiting thread from the head of a mutex queue in descending + * priority order. + */ + static inline pthread_t + mutex_queue_deq(pthread_mutex_t mutex) + { + pthread_t pthread; + + while ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL) { + TAILQ_REMOVE(&mutex->m_queue, pthread, sqe); + pthread->flags &= ~PTHREAD_FLAGS_IN_MUTEXQ; + + /* + * Only exit the loop if the thread hasn't been + * cancelled. + */ + if (pthread->interrupted == 0) + break; + } + + return(pthread); + } + + /* + * Remove a waiting thread from a mutex queue in descending priority order. + */ + static inline void + mutex_queue_remove(pthread_mutex_t mutex, pthread_t pthread) + { + if ((pthread->flags & PTHREAD_FLAGS_IN_MUTEXQ) != 0) { + TAILQ_REMOVE(&mutex->m_queue, pthread, sqe); + pthread->flags &= ~PTHREAD_FLAGS_IN_MUTEXQ; + } + } + + /* + * Enqueue a waiting thread to a queue in descending priority order. + */ + static inline void + mutex_queue_enq(pthread_mutex_t mutex, pthread_t pthread) + { + pthread_t tid = TAILQ_LAST(&mutex->m_queue, mutex_head); + + PTHREAD_ASSERT_NOT_IN_SYNCQ(pthread); + /* + * For the common case of all threads having equal priority, + * we perform a quick check against the priority of the thread + * at the tail of the queue. + */ + if ((tid == NULL) || (pthread->active_priority <= tid->active_priority)) + TAILQ_INSERT_TAIL(&mutex->m_queue, pthread, sqe); + else { + tid = TAILQ_FIRST(&mutex->m_queue); + while (pthread->active_priority <= tid->active_priority) + tid = TAILQ_NEXT(tid, sqe); + TAILQ_INSERT_BEFORE(tid, pthread, sqe); + } + pthread->flags |= PTHREAD_FLAGS_IN_MUTEXQ; + } + Index: lib/libpthread/uthread/uthread_mutex_prioceiling.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_mutex_prioceiling.c Sun Sep 15 21:38:51 2002 *************** *** 0 **** --- 1,113 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_mutex_prioceiling.c,v 1.5 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_mutexattr_getprioceiling, pthread_mutexattr_getprioceiling); + __weak_reference(_pthread_mutexattr_setprioceiling, pthread_mutexattr_setprioceiling); + __weak_reference(_pthread_mutex_getprioceiling, pthread_mutex_getprioceiling); + __weak_reference(_pthread_mutex_setprioceiling, pthread_mutex_setprioceiling); + + int + _pthread_mutexattr_getprioceiling(pthread_mutexattr_t *mattr, int *prioceiling) + { + int ret = 0; + + if ((mattr == NULL) || (*mattr == NULL)) + ret = EINVAL; + else if ((*mattr)->m_protocol != PTHREAD_PRIO_PROTECT) + ret = EINVAL; + else + *prioceiling = (*mattr)->m_ceiling; + + return(ret); + } + + int + _pthread_mutexattr_setprioceiling(pthread_mutexattr_t *mattr, int prioceiling) + { + int ret = 0; + + if ((mattr == NULL) || (*mattr == NULL)) + ret = EINVAL; + else if ((*mattr)->m_protocol != PTHREAD_PRIO_PROTECT) + ret = EINVAL; + else + (*mattr)->m_ceiling = prioceiling; + + return(ret); + } + + int + _pthread_mutex_getprioceiling(pthread_mutex_t *mutex, + int *prioceiling) + { + int ret; + + if ((mutex == NULL) || (*mutex == NULL)) + ret = EINVAL; + else if ((*mutex)->m_protocol != PTHREAD_PRIO_PROTECT) + ret = EINVAL; + else + ret = (*mutex)->m_prio; + + return(ret); + } + + int + _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, + int prioceiling, int *old_ceiling) + { + int ret = 0; + + if ((mutex == NULL) || (*mutex == NULL)) + ret = EINVAL; + else if ((*mutex)->m_protocol != PTHREAD_PRIO_PROTECT) + ret = EINVAL; + else { + /* Lock the mutex: */ + if ((ret = pthread_mutex_lock(mutex)) == 0) { + /* Return the old ceiling and set the new ceiling: */ + *old_ceiling = (*mutex)->m_prio; + (*mutex)->m_prio = prioceiling; + + /* Unlock the mutex: */ + ret = pthread_mutex_unlock(mutex); + } + } + return(ret); + } Index: lib/libpthread/uthread/uthread_mutex_protocol.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_mutex_protocol.c Sun Sep 15 21:38:51 2002 *************** *** 0 **** --- 1,70 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_mutex_protocol.c,v 1.5 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_mutexattr_getprotocol, pthread_mutexattr_getprotocol); + __weak_reference(_pthread_mutexattr_setprotocol, pthread_mutexattr_setprotocol); + + int + _pthread_mutexattr_getprotocol(pthread_mutexattr_t *mattr, int *protocol) + { + int ret = 0; + + if ((mattr == NULL) || (*mattr == NULL)) + ret = EINVAL; + else + *protocol = (*mattr)->m_protocol; + + return(ret); + } + + int + _pthread_mutexattr_setprotocol(pthread_mutexattr_t *mattr, int protocol) + { + int ret = 0; + + if ((mattr == NULL) || (*mattr == NULL) || + (protocol < PTHREAD_PRIO_NONE) || (protocol > PTHREAD_PRIO_PROTECT)) + ret = EINVAL; + else { + (*mattr)->m_protocol = protocol; + (*mattr)->m_ceiling = PTHREAD_MAX_PRIORITY; + } + return(ret); + } + Index: lib/libpthread/uthread/uthread_mutexattr_destroy.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_mutexattr_destroy.c Sun Sep 15 21:38:52 2002 *************** *** 0 **** --- 1,53 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_mutexattr_destroy.c,v 1.7 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_mutexattr_destroy, pthread_mutexattr_destroy); + + int + _pthread_mutexattr_destroy(pthread_mutexattr_t *attr) + { + int ret; + if (attr == NULL || *attr == NULL) { + ret = EINVAL; + } else { + free(*attr); + *attr = NULL; + ret = 0; + } + return(ret); + } Index: lib/libpthread/uthread/uthread_nanosleep.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_nanosleep.c Sun Sep 15 21:38:52 2002 *************** *** 0 **** --- 1,143 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_nanosleep.c,v 1.16 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__nanosleep, nanosleep); + + int + _nanosleep(const struct timespec * time_to_sleep, + struct timespec * time_remaining) + { + struct pthread *curthread = _get_curthread(); + int ret = 0; + struct timespec current_time; + struct timespec current_time1; + struct timespec remaining_time; + struct timeval tv; + + /* Check if the time to sleep is legal: */ + if (time_to_sleep == NULL || time_to_sleep->tv_sec < 0 || + time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec >= 1000000000) { + /* Return an EINVAL error : */ + errno = EINVAL; + ret = -1; + } else { + /* + * As long as we're going to get the time of day, we + * might as well store it in the global time of day: + */ + gettimeofday((struct timeval *) &_sched_tod, NULL); + GET_CURRENT_TOD(tv); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); + + /* Calculate the time for the current thread to wake up: */ + curthread->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec; + curthread->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec; + + /* Check if the nanosecond field has overflowed: */ + if (curthread->wakeup_time.tv_nsec >= 1000000000) { + /* Wrap the nanosecond field: */ + curthread->wakeup_time.tv_sec += 1; + curthread->wakeup_time.tv_nsec -= 1000000000; + } + curthread->interrupted = 0; + + /* Reschedule the current thread to sleep: */ + _thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__); + + /* + * As long as we're going to get the time of day, we + * might as well store it in the global time of day: + */ + gettimeofday((struct timeval *) &_sched_tod, NULL); + GET_CURRENT_TOD(tv); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time1); + + /* Calculate the remaining time to sleep: */ + remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec; + remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec; + + /* Check if the nanosecond field has underflowed: */ + if (remaining_time.tv_nsec < 0) { + /* Handle the underflow: */ + remaining_time.tv_sec -= 1; + remaining_time.tv_nsec += 1000000000; + } + + /* Check if the nanosecond field has overflowed: */ + if (remaining_time.tv_nsec >= 1000000000) { + /* Handle the overflow: */ + remaining_time.tv_sec += 1; + remaining_time.tv_nsec -= 1000000000; + } + + /* Check if the sleep was longer than the required time: */ + if (remaining_time.tv_sec < 0) { + /* Reset the time left: */ + remaining_time.tv_sec = 0; + remaining_time.tv_nsec = 0; + } + + /* Check if the time remaining is to be returned: */ + if (time_remaining != NULL) { + /* Return the actual time slept: */ + time_remaining->tv_sec = remaining_time.tv_sec; + time_remaining->tv_nsec = remaining_time.tv_nsec; + } + + /* Check if the sleep was interrupted: */ + if (curthread->interrupted) { + /* Return an EINTR error : */ + errno = EINTR; + ret = -1; + } + } + return (ret); + } + + int + __nanosleep(const struct timespec * time_to_sleep, struct timespec * + time_remaining) + { + int ret; + + _thread_enter_cancellation_point(); + ret = _nanosleep(time_to_sleep, time_remaining); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_once.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_once.c Sun Sep 15 21:38:52 2002 *************** *** 0 **** --- 1,53 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_once.c,v 1.6 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include "pthread_private.h" + + __weak_reference(_pthread_once, pthread_once); + + int + _pthread_once(pthread_once_t * once_control, void (*init_routine) (void)) + { + if (once_control->state == PTHREAD_NEEDS_INIT) { + if (_thread_initial == NULL) + _thread_init(); + pthread_mutex_lock(&(once_control->mutex)); + if (once_control->state == PTHREAD_NEEDS_INIT) { + init_routine(); + once_control->state = PTHREAD_DONE_INIT; + } + pthread_mutex_unlock(&(once_control->mutex)); + } + return (0); + } Index: lib/libpthread/uthread/uthread_open.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_open.c Sun Sep 15 21:38:55 2002 *************** *** 0 **** --- 1,66 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_open.c,v 1.12 2001/04/18 12:42:11 deischen Exp $ + * + */ + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__open, open); + + int + __open(const char *path, int flags,...) + { + int ret; + int mode = 0; + va_list ap; + + _thread_enter_cancellation_point(); + + /* Check if the file is being created: */ + if (flags & O_CREAT) { + /* Get the creation mode: */ + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + } + + ret = __sys_open(path, flags, mode); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_pause.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_pause.c Sun Sep 15 21:38:55 2002 *************** *** 0 **** --- 1,48 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_pause.c,v 1.4 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include + #include "pthread_private.h" + + __weak_reference(_pause, pause); + + int + _pause(void) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __pause(); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_poll.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_poll.c Sun Sep 15 21:38:56 2002 *************** *** 0 **** --- 1,56 ---- + /* + * Copyright (c) 1999 Daniel Eischen + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_poll.c,v 1.12 2002/05/02 19:58:43 archie Exp $ + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__poll, poll); + + int + __poll(struct pollfd *fds, unsigned int nfds, int timeout) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __sys_poll(fds, nfds, timeout); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_printf.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_printf.c Sun Sep 15 21:38:56 2002 *************** *** 0 **** --- 1,124 ---- + /*- + * Copyright (c) 2002 Jonathan Mini + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + + #include + __FBSDID("$FreeBSD$"); + + #include + #include + #include + #include + #include + #include + #include + + #include "pthread_private.h" + + static void pchar(char c); + static void pstr(const char *s); + + /* + * Write formatted output to stdout, in a thread-safe manner. + * + * Recognises the following conversions: + * %c -> char + * %d -> signed int (base 10) + * %s -> string + * %u -> unsigned int (base 10) + * %x -> unsigned int (base 16) + * %p -> unsigned int (base 16) + */ + void + _thread_printf(const char *fmt, ...) + { + static const char digits[16] = "0123456789abcdef"; + va_list ap; + char buf[10]; + char *s; + unsigned r, u; + int c, d; + + va_start(ap, fmt); + while ((c = *fmt++)) { + if (c == '%') { + c = *fmt++; + switch (c) { + case 'c': + pchar(va_arg(ap, int)); + continue; + case 's': + pstr(va_arg(ap, char *)); + continue; + case 'd': + case 'u': + case 'p': + case 'x': + r = ((c == 'u') || (c == 'd')) ? 10 : 16; + if (c == 'd') { + d = va_arg(ap, unsigned); + if (d < 0) { + pchar('-'); + u = (unsigned)(d * -1); + } else + u = (unsigned)d; + } else + u = va_arg(ap, unsigned); + s = buf; + do { + *s++ = digits[u % r]; + } while (u /= r); + while (--s >= buf) + pchar(*s); + continue; + } + } + pchar(c); + } + va_end(ap); + } + + /* + * Write a single character to stdout, in a thread-safe manner. + */ + static void + pchar(char c) + { + + write(STDOUT_FILENO, &c, 1); + } + + /* + * Write a string to stdout, in a thread-safe manner. + */ + static void + pstr(const char *s) + { + + write(STDOUT_FILENO, s, strlen(s)); + } + Index: lib/libpthread/uthread/uthread_priority_queue.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_priority_queue.c Sun Sep 15 21:38:56 2002 *************** *** 0 **** --- 1,370 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_priority_queue.c,v 1.8 2002/05/24 04:32:28 deischen Exp $ + */ + #include + #include + #include + #include + #include "pthread_private.h" + + /* Prototypes: */ + static void pq_insert_prio_list(pq_queue_t *pq, int prio); + + #if defined(_PTHREADS_INVARIANTS) + + static int _pq_active = 0; + + #define _PQ_IN_SCHEDQ (PTHREAD_FLAGS_IN_PRIOQ | PTHREAD_FLAGS_IN_WAITQ | PTHREAD_FLAGS_IN_WORKQ) + + #define _PQ_SET_ACTIVE() _pq_active = 1 + #define _PQ_CLEAR_ACTIVE() _pq_active = 0 + #define _PQ_ASSERT_ACTIVE(msg) do { \ + if (_pq_active == 0) \ + PANIC(msg); \ + } while (0) + #define _PQ_ASSERT_INACTIVE(msg) do { \ + if (_pq_active != 0) \ + PANIC(msg); \ + } while (0) + #define _PQ_ASSERT_IN_WAITQ(thrd, msg) do { \ + if (((thrd)->flags & PTHREAD_FLAGS_IN_WAITQ) == 0) \ + PANIC(msg); \ + } while (0) + #define _PQ_ASSERT_IN_PRIOQ(thrd, msg) do { \ + if (((thrd)->flags & PTHREAD_FLAGS_IN_PRIOQ) == 0) \ + PANIC(msg); \ + } while (0) + #define _PQ_ASSERT_NOT_QUEUED(thrd, msg) do { \ + if (((thrd)->flags & _PQ_IN_SCHEDQ) != 0) \ + PANIC(msg); \ + } while (0) + #define _PQ_ASSERT_PROTECTED(msg) \ + PTHREAD_ASSERT((_thread_kern_kse_mailbox.km_curthread == NULL) || \ + ((_get_curthread())->sig_defer_count > 0), \ + msg); + + #else + + #define _PQ_SET_ACTIVE() + #define _PQ_CLEAR_ACTIVE() + #define _PQ_ASSERT_ACTIVE(msg) + #define _PQ_ASSERT_INACTIVE(msg) + #define _PQ_ASSERT_IN_WAITQ(thrd, msg) + #define _PQ_ASSERT_IN_PRIOQ(thrd, msg) + #define _PQ_ASSERT_NOT_QUEUED(thrd, msg) + #define _PQ_ASSERT_PROTECTED(msg) + + #endif + + int + _pq_alloc(pq_queue_t *pq, int minprio, int maxprio) + { + int ret = 0; + int prioslots = maxprio - minprio + 1; + + if (pq == NULL) + ret = -1; + + /* Create the priority queue with (maxprio - minprio + 1) slots: */ + else if ((pq->pq_lists = + (pq_list_t *) malloc(sizeof(pq_list_t) * prioslots)) == NULL) + ret = -1; + + else { + /* Remember the queue size: */ + pq->pq_size = prioslots; + ret = _pq_init(pq); + } + return (ret); + } + + int + _pq_init(pq_queue_t *pq) + { + int i, ret = 0; + + if ((pq == NULL) || (pq->pq_lists == NULL)) + ret = -1; + + else { + /* Initialize the queue for each priority slot: */ + for (i = 0; i < pq->pq_size; i++) { + TAILQ_INIT(&pq->pq_lists[i].pl_head); + pq->pq_lists[i].pl_prio = i; + pq->pq_lists[i].pl_queued = 0; + } + + /* Initialize the priority queue: */ + TAILQ_INIT(&pq->pq_queue); + _PQ_CLEAR_ACTIVE(); + } + return (ret); + } + + void + _pq_remove(pq_queue_t *pq, pthread_t pthread) + { + int prio = pthread->active_priority; + + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_remove: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_IN_PRIOQ(pthread, "_pq_remove: Not in priority queue"); + _PQ_ASSERT_PROTECTED("_pq_remove: prioq not protected!"); + + /* + * Remove this thread from priority list. Note that if + * the priority list becomes empty, it is not removed + * from the priority queue because another thread may be + * added to the priority list (resulting in a needless + * removal/insertion). Priority lists are only removed + * from the priority queue when _pq_first is called. + */ + TAILQ_REMOVE(&pq->pq_lists[prio].pl_head, pthread, pqe); + + /* This thread is now longer in the priority queue. */ + pthread->flags &= ~PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); + } + + + void + _pq_insert_head(pq_queue_t *pq, pthread_t pthread) + { + int prio; + + /* + * Don't insert suspended threads into the priority queue. + * The caller is responsible for setting the threads state. + */ + if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0) { + /* Make sure the threads state is suspended. */ + if (pthread->state != PS_SUSPENDED) + PTHREAD_SET_STATE(pthread, PS_SUSPENDED); + } else { + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_insert_head: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, + "_pq_insert_head: Already in priority queue"); + _PQ_ASSERT_PROTECTED("_pq_insert_head: prioq not protected!"); + + prio = pthread->active_priority; + TAILQ_INSERT_HEAD(&pq->pq_lists[prio].pl_head, pthread, pqe); + if (pq->pq_lists[prio].pl_queued == 0) + /* Insert the list into the priority queue: */ + pq_insert_prio_list(pq, prio); + + /* Mark this thread as being in the priority queue. */ + pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); + } + } + + + void + _pq_insert_tail(pq_queue_t *pq, pthread_t pthread) + { + int prio; + + /* + * Don't insert suspended threads into the priority queue. + * The caller is responsible for setting the threads state. + */ + if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0) { + /* Make sure the threads state is suspended. */ + if (pthread->state != PS_SUSPENDED) + PTHREAD_SET_STATE(pthread, PS_SUSPENDED); + } else { + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_insert_tail: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, + "_pq_insert_tail: Already in priority queue"); + _PQ_ASSERT_PROTECTED("_pq_insert_tail: prioq not protected!"); + + prio = pthread->active_priority; + TAILQ_INSERT_TAIL(&pq->pq_lists[prio].pl_head, pthread, pqe); + if (pq->pq_lists[prio].pl_queued == 0) + /* Insert the list into the priority queue: */ + pq_insert_prio_list(pq, prio); + + /* Mark this thread as being in the priority queue. */ + pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); + } + } + + + pthread_t + _pq_first(pq_queue_t *pq) + { + pq_list_t *pql; + pthread_t pthread = NULL; + + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_first: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_PROTECTED("_pq_first: prioq not protected!"); + + while (((pql = TAILQ_FIRST(&pq->pq_queue)) != NULL) && + (pthread == NULL)) { + if ((pthread = TAILQ_FIRST(&pql->pl_head)) == NULL) { + /* + * The priority list is empty; remove the list + * from the queue. + */ + TAILQ_REMOVE(&pq->pq_queue, pql, pl_link); + + /* Mark the list as not being in the queue: */ + pql->pl_queued = 0; + } else if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0) { + /* + * This thread is suspended; remove it from the + * list and ensure its state is suspended. + */ + TAILQ_REMOVE(&pql->pl_head, pthread, pqe); + PTHREAD_SET_STATE(pthread, PS_SUSPENDED); + + /* This thread is now longer in the priority queue. */ + pthread->flags &= ~PTHREAD_FLAGS_IN_PRIOQ; + pthread = NULL; + } + } + + _PQ_CLEAR_ACTIVE(); + return (pthread); + } + + + static void + pq_insert_prio_list(pq_queue_t *pq, int prio) + { + pq_list_t *pql; + + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_ACTIVE("pq_insert_prio_list: pq_active"); + _PQ_ASSERT_PROTECTED("_pq_insert_prio_list: prioq not protected!"); + + /* + * The priority queue is in descending priority order. Start at + * the beginning of the queue and find the list before which the + * new list should be inserted. + */ + pql = TAILQ_FIRST(&pq->pq_queue); + while ((pql != NULL) && (pql->pl_prio > prio)) + pql = TAILQ_NEXT(pql, pl_link); + + /* Insert the list: */ + if (pql == NULL) + TAILQ_INSERT_TAIL(&pq->pq_queue, &pq->pq_lists[prio], pl_link); + else + TAILQ_INSERT_BEFORE(pql, &pq->pq_lists[prio], pl_link); + + /* Mark this list as being in the queue: */ + pq->pq_lists[prio].pl_queued = 1; + } + + void + _waitq_insert(pthread_t pthread) + { + pthread_t tid; + + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_waitq_insert: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, "_waitq_insert: Already in queue"); + + if (pthread->wakeup_time.tv_sec == -1) + TAILQ_INSERT_TAIL(&_waitingq, pthread, pqe); + else { + tid = TAILQ_FIRST(&_waitingq); + while ((tid != NULL) && (tid->wakeup_time.tv_sec != -1) && + ((tid->wakeup_time.tv_sec < pthread->wakeup_time.tv_sec) || + ((tid->wakeup_time.tv_sec == pthread->wakeup_time.tv_sec) && + (tid->wakeup_time.tv_nsec <= pthread->wakeup_time.tv_nsec)))) + tid = TAILQ_NEXT(tid, pqe); + if (tid == NULL) + TAILQ_INSERT_TAIL(&_waitingq, pthread, pqe); + else + TAILQ_INSERT_BEFORE(tid, pthread, pqe); + } + pthread->flags |= PTHREAD_FLAGS_IN_WAITQ; + + _PQ_CLEAR_ACTIVE(); + } + + void + _waitq_remove(pthread_t pthread) + { + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_waitq_remove: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_IN_WAITQ(pthread, "_waitq_remove: Not in queue"); + + TAILQ_REMOVE(&_waitingq, pthread, pqe); + pthread->flags &= ~PTHREAD_FLAGS_IN_WAITQ; + + _PQ_CLEAR_ACTIVE(); + } + + void + _waitq_setactive(void) + { + _PQ_ASSERT_INACTIVE("_waitq_setactive: pq_active"); + _PQ_SET_ACTIVE(); + } + + void + _waitq_clearactive(void) + { + _PQ_ASSERT_ACTIVE("_waitq_clearactive: ! pq_active"); + _PQ_CLEAR_ACTIVE(); + } Index: lib/libpthread/uthread/uthread_pselect.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_pselect.c Sun Sep 15 21:38:56 2002 *************** *** 0 **** --- 1,54 ---- + /*- + * Copyright (c) 2002 Daniel M. Eischen + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 + __FBSDID("$FreeBSD: src/lib/libc_r/uthread/uthread_pselect.c,v 1.1 2002/06/28 13:26:02 deischen Exp $"); + + #include + #include + + #include + #include + #include + + #include "pthread_private.h" + + extern int __pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, + const struct timespec *timo, const sigset_t *mask); + + int + pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, + const struct timespec *timo, const sigset_t *mask) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __pselect(count, rfds, wfds, efds, timo, mask); + _thread_leave_cancellation_point(); + + return (ret); + } Index: lib/libpthread/uthread/uthread_read.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_read.c Sun Sep 15 21:38:57 2002 *************** *** 0 **** --- 1,55 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_read.c,v 1.14 2002/08/29 23:06:07 deischen Exp $ + * + */ + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__read, read); + + ssize_t + __read(int fd, void *buf, size_t nbytes) + { + ssize_t ret; + + _thread_enter_cancellation_point(); + ret = __sys_read(fd, buf, nbytes); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_readv.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_readv.c Sun Sep 15 21:38:57 2002 *************** *** 0 **** --- 1,55 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_readv.c,v 1.15 2002/08/29 23:06:07 deischen Exp $ + * + */ + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__readv, readv); + + ssize_t + __readv(int fd, const struct iovec *iov, int iovcnt) + { + ssize_t ret; + + _thread_enter_cancellation_point(); + ret = __sys_readv(fd, iov, iovcnt); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_resume_np.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_resume_np.c Sun Sep 15 21:38:57 2002 *************** *** 0 **** --- 1,111 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_resume_np.c,v 1.13 2002/05/24 04:32:28 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + static void resume_common(struct pthread *); + + __weak_reference(_pthread_resume_np, pthread_resume_np); + __weak_reference(_pthread_resume_all_np, pthread_resume_all_np); + + /* Resume a thread: */ + int + _pthread_resume_np(pthread_t thread) + { + int ret; + + /* Find the thread in the list of active threads: */ + if ((ret = _find_thread(thread)) == 0) { + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); + + if ((thread->flags & PTHREAD_FLAGS_SUSPENDED) != 0) + resume_common(thread); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + return (ret); + } + + void + _pthread_resume_all_np(void) + { + struct pthread *curthread = _get_curthread(); + struct pthread *thread; + + /* + * Defer signals to protect the scheduling queues from access + * by the signal handler: + */ + _thread_kern_sig_defer(); + + TAILQ_FOREACH(thread, &_thread_list, tle) { + if ((thread != curthread) && + ((thread->flags & PTHREAD_FLAGS_SUSPENDED) != 0)) + resume_common(thread); + } + + /* + * Undefer and handle pending signals, yielding if necessary: + */ + _thread_kern_sig_undefer(); + } + + static void + resume_common(struct pthread *thread) + { + /* Clear the suspend flag: */ + thread->flags &= ~PTHREAD_FLAGS_SUSPENDED; + + /* + * If the thread's state is suspended, that means it is + * now runnable but not in any scheduling queue. Set the + * state to running and insert it into the run queue. + */ + if (thread->state == PS_SUSPENDED) { + PTHREAD_SET_STATE(thread, PS_RUNNING); + if (thread->priority_mutex_count > 0) + PTHREAD_PRIOQ_INSERT_HEAD(thread); + else + PTHREAD_PRIOQ_INSERT_TAIL(thread); + } + } Index: lib/libpthread/uthread/uthread_rwlock.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_rwlock.c Sun Sep 15 21:38:57 2002 *************** *** 0 **** --- 1,341 ---- + /*- + * Copyright (c) 1998 Alex Nash + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_rwlock.c,v 1.7 2002/03/15 18:27:58 bsd Exp $ + */ + + #include + #include + #include + + #include + #include "pthread_private.h" + + /* maximum number of times a read lock may be obtained */ + #define MAX_READ_LOCKS (INT_MAX - 1) + + __weak_reference(_pthread_rwlock_destroy, pthread_rwlock_destroy); + __weak_reference(_pthread_rwlock_init, pthread_rwlock_init); + __weak_reference(_pthread_rwlock_rdlock, pthread_rwlock_rdlock); + __weak_reference(_pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); + __weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); + __weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock); + __weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock); + + static int init_static (pthread_rwlock_t *rwlock); + + static spinlock_t static_init_lock = _SPINLOCK_INITIALIZER; + + static int + init_static (pthread_rwlock_t *rwlock) + { + int ret; + + _SPINLOCK(&static_init_lock); + + if (*rwlock == NULL) + ret = pthread_rwlock_init(rwlock, NULL); + else + ret = 0; + + _SPINUNLOCK(&static_init_lock); + + return(ret); + } + + int + _pthread_rwlock_destroy (pthread_rwlock_t *rwlock) + { + int ret; + + if (rwlock == NULL) + ret = EINVAL; + else { + pthread_rwlock_t prwlock; + + prwlock = *rwlock; + + pthread_mutex_destroy(&prwlock->lock); + pthread_cond_destroy(&prwlock->read_signal); + pthread_cond_destroy(&prwlock->write_signal); + free(prwlock); + + *rwlock = NULL; + + ret = 0; + } + + return(ret); + } + + int + _pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) + { + pthread_rwlock_t prwlock; + int ret; + + /* allocate rwlock object */ + prwlock = (pthread_rwlock_t)malloc(sizeof(struct pthread_rwlock)); + + if (prwlock == NULL) + return(ENOMEM); + + /* initialize the lock */ + if ((ret = pthread_mutex_init(&prwlock->lock, NULL)) != 0) + free(prwlock); + else { + /* initialize the read condition signal */ + ret = pthread_cond_init(&prwlock->read_signal, NULL); + + if (ret != 0) { + pthread_mutex_destroy(&prwlock->lock); + free(prwlock); + } else { + /* initialize the write condition signal */ + ret = pthread_cond_init(&prwlock->write_signal, NULL); + + if (ret != 0) { + pthread_cond_destroy(&prwlock->read_signal); + pthread_mutex_destroy(&prwlock->lock); + free(prwlock); + } else { + /* success */ + prwlock->state = 0; + prwlock->blocked_writers = 0; + + *rwlock = prwlock; + } + } + } + + return(ret); + } + + int + _pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) + { + pthread_rwlock_t prwlock; + int ret; + + if (rwlock == NULL) + return(EINVAL); + + prwlock = *rwlock; + + /* check for static initialization */ + if (prwlock == NULL) { + if ((ret = init_static(rwlock)) != 0) + return(ret); + + prwlock = *rwlock; + } + + /* grab the monitor lock */ + if ((ret = pthread_mutex_lock(&prwlock->lock)) != 0) + return(ret); + + /* give writers priority over readers */ + while (prwlock->blocked_writers || prwlock->state < 0) { + ret = pthread_cond_wait(&prwlock->read_signal, &prwlock->lock); + + if (ret != 0) { + /* can't do a whole lot if this fails */ + pthread_mutex_unlock(&prwlock->lock); + return(ret); + } + } + + /* check lock count */ + if (prwlock->state == MAX_READ_LOCKS) + ret = EAGAIN; + else + ++prwlock->state; /* indicate we are locked for reading */ + + /* + * Something is really wrong if this call fails. Returning + * error won't do because we've already obtained the read + * lock. Decrementing 'state' is no good because we probably + * don't have the monitor lock. + */ + pthread_mutex_unlock(&prwlock->lock); + + return(ret); + } + + int + _pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) + { + pthread_rwlock_t prwlock; + int ret; + + if (rwlock == NULL) + return(EINVAL); + + prwlock = *rwlock; + + /* check for static initialization */ + if (prwlock == NULL) { + if ((ret = init_static(rwlock)) != 0) + return(ret); + + prwlock = *rwlock; + } + + /* grab the monitor lock */ + if ((ret = pthread_mutex_lock(&prwlock->lock)) != 0) + return(ret); + + /* give writers priority over readers */ + if (prwlock->blocked_writers || prwlock->state < 0) + ret = EBUSY; + else if (prwlock->state == MAX_READ_LOCKS) + ret = EAGAIN; /* too many read locks acquired */ + else + ++prwlock->state; /* indicate we are locked for reading */ + + /* see the comment on this in pthread_rwlock_rdlock */ + pthread_mutex_unlock(&prwlock->lock); + + return(ret); + } + + int + _pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) + { + pthread_rwlock_t prwlock; + int ret; + + if (rwlock == NULL) + return(EINVAL); + + prwlock = *rwlock; + + /* check for static initialization */ + if (prwlock == NULL) { + if ((ret = init_static(rwlock)) != 0) + return(ret); + + prwlock = *rwlock; + } + + /* grab the monitor lock */ + if ((ret = pthread_mutex_lock(&prwlock->lock)) != 0) + return(ret); + + if (prwlock->state != 0) + ret = EBUSY; + else + /* indicate we are locked for writing */ + prwlock->state = -1; + + /* see the comment on this in pthread_rwlock_rdlock */ + pthread_mutex_unlock(&prwlock->lock); + + return(ret); + } + + int + _pthread_rwlock_unlock (pthread_rwlock_t *rwlock) + { + pthread_rwlock_t prwlock; + int ret; + + if (rwlock == NULL) + return(EINVAL); + + prwlock = *rwlock; + + if (prwlock == NULL) + return(EINVAL); + + /* grab the monitor lock */ + if ((ret = pthread_mutex_lock(&prwlock->lock)) != 0) + return(ret); + + if (prwlock->state > 0) { + if (--prwlock->state == 0 && prwlock->blocked_writers) + ret = pthread_cond_signal(&prwlock->write_signal); + } else if (prwlock->state < 0) { + prwlock->state = 0; + + if (prwlock->blocked_writers) + ret = pthread_cond_signal(&prwlock->write_signal); + else + ret = pthread_cond_broadcast(&prwlock->read_signal); + } else + ret = EINVAL; + + /* see the comment on this in pthread_rwlock_rdlock */ + pthread_mutex_unlock(&prwlock->lock); + + return(ret); + } + + int + _pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) + { + pthread_rwlock_t prwlock; + int ret; + + if (rwlock == NULL) + return(EINVAL); + + prwlock = *rwlock; + + /* check for static initialization */ + if (prwlock == NULL) { + if ((ret = init_static(rwlock)) != 0) + return(ret); + + prwlock = *rwlock; + } + + /* grab the monitor lock */ + if ((ret = pthread_mutex_lock(&prwlock->lock)) != 0) + return(ret); + + while (prwlock->state != 0) { + ++prwlock->blocked_writers; + + ret = pthread_cond_wait(&prwlock->write_signal, &prwlock->lock); + + if (ret != 0) { + --prwlock->blocked_writers; + pthread_mutex_unlock(&prwlock->lock); + return(ret); + } + + --prwlock->blocked_writers; + } + + /* indicate we are locked for writing */ + prwlock->state = -1; + + /* see the comment on this in pthread_rwlock_rdlock */ + pthread_mutex_unlock(&prwlock->lock); + + return(ret); + } + Index: lib/libpthread/uthread/uthread_rwlockattr.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_rwlockattr.c Sun Sep 15 21:38:57 2002 *************** *** 0 **** --- 1,98 ---- + /*- + * Copyright (c) 1998 Alex Nash + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_rwlockattr.c,v 1.7 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include + + #include + #include "pthread_private.h" + + __weak_reference(_pthread_rwlockattr_destroy, pthread_rwlockattr_destroy); + __weak_reference(_pthread_rwlockattr_getpshared, pthread_rwlockattr_getpshared); + __weak_reference(_pthread_rwlockattr_init, pthread_rwlockattr_init); + __weak_reference(_pthread_rwlockattr_setpshared, pthread_rwlockattr_setpshared); + + int + _pthread_rwlockattr_destroy(pthread_rwlockattr_t *rwlockattr) + { + pthread_rwlockattr_t prwlockattr; + + if (rwlockattr == NULL) + return(EINVAL); + + prwlockattr = *rwlockattr; + + if (prwlockattr == NULL) + return(EINVAL); + + free(prwlockattr); + + return(0); + } + + int + _pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *rwlockattr, + int *pshared) + { + *pshared = (*rwlockattr)->pshared; + + return(0); + } + + int + _pthread_rwlockattr_init(pthread_rwlockattr_t *rwlockattr) + { + pthread_rwlockattr_t prwlockattr; + + if (rwlockattr == NULL) + return(EINVAL); + + prwlockattr = (pthread_rwlockattr_t) + malloc(sizeof(struct pthread_rwlockattr)); + + if (prwlockattr == NULL) + return(ENOMEM); + + prwlockattr->pshared = PTHREAD_PROCESS_PRIVATE; + *rwlockattr = prwlockattr; + + return(0); + } + + int + _pthread_rwlockattr_setpshared(pthread_rwlockattr_t *rwlockattr, int pshared) + { + /* Only PTHREAD_PROCESS_PRIVATE is supported. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return(EINVAL); + + (*rwlockattr)->pshared = pshared; + + return(0); + } + Index: lib/libpthread/uthread/uthread_select.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_select.c Sun Sep 15 21:38:58 2002 *************** *** 0 **** --- 1,59 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_select.c,v 1.21 2002/08/29 21:39:19 archie Exp $ + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__select, select); + + int + __select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_self.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_self.c Sun Sep 15 21:38:58 2002 *************** *** 0 **** --- 1,44 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_self.c,v 1.5 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include "pthread_private.h" + + __weak_reference(_pthread_self, pthread_self); + + pthread_t + _pthread_self(void) + { + /* Return the running thread pointer: */ + return (_get_curthread()); + } Index: lib/libpthread/uthread/uthread_sem.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_sem.c Sun Sep 15 21:38:58 2002 *************** *** 0 **** --- 1,254 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_sem.c,v 1.10 2001/05/18 00:36:05 jasone Exp $ + */ + + #include + #include + #include + #include + #include "pthread_private.h" + + #define _SEM_CHECK_VALIDITY(sem) \ + if ((*(sem))->magic != SEM_MAGIC) { \ + errno = EINVAL; \ + retval = -1; \ + goto RETURN; \ + } + + __weak_reference(_sem_init, sem_init); + __weak_reference(_sem_destroy, sem_destroy); + __weak_reference(_sem_open, sem_open); + __weak_reference(_sem_close, sem_close); + __weak_reference(_sem_unlink, sem_unlink); + __weak_reference(_sem_wait, sem_wait); + __weak_reference(_sem_trywait, sem_trywait); + __weak_reference(_sem_post, sem_post); + __weak_reference(_sem_getvalue, sem_getvalue); + + + int + _sem_init(sem_t *sem, int pshared, unsigned int value) + { + int retval; + + /* + * Range check the arguments. + */ + if (pshared != 0) { + /* + * The user wants a semaphore that can be shared among + * processes, which this implementation can't do. Sounds like a + * permissions problem to me (yeah right). + */ + errno = EPERM; + retval = -1; + goto RETURN; + } + + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + retval = -1; + goto RETURN; + } + + *sem = (sem_t)malloc(sizeof(struct sem)); + if (*sem == NULL) { + errno = ENOSPC; + retval = -1; + goto RETURN; + } + + /* + * Initialize the semaphore. + */ + if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) { + free(*sem); + errno = ENOSPC; + retval = -1; + goto RETURN; + } + + if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) { + pthread_mutex_destroy(&(*sem)->lock); + free(*sem); + errno = ENOSPC; + retval = -1; + goto RETURN; + } + + (*sem)->count = (u_int32_t)value; + (*sem)->nwaiters = 0; + (*sem)->magic = SEM_MAGIC; + + retval = 0; + RETURN: + return retval; + } + + int + _sem_destroy(sem_t *sem) + { + int retval; + + _SEM_CHECK_VALIDITY(sem); + + /* Make sure there are no waiters. */ + pthread_mutex_lock(&(*sem)->lock); + if ((*sem)->nwaiters > 0) { + pthread_mutex_unlock(&(*sem)->lock); + errno = EBUSY; + retval = -1; + goto RETURN; + } + pthread_mutex_unlock(&(*sem)->lock); + + pthread_mutex_destroy(&(*sem)->lock); + pthread_cond_destroy(&(*sem)->gtzero); + (*sem)->magic = 0; + + free(*sem); + + retval = 0; + RETURN: + return retval; + } + + sem_t * + _sem_open(const char *name, int oflag, ...) + { + errno = ENOSYS; + return SEM_FAILED; + } + + int + _sem_close(sem_t *sem) + { + errno = ENOSYS; + return -1; + } + + int + _sem_unlink(const char *name) + { + errno = ENOSYS; + return -1; + } + + int + _sem_wait(sem_t *sem) + { + int retval; + + _thread_enter_cancellation_point(); + + _SEM_CHECK_VALIDITY(sem); + + pthread_mutex_lock(&(*sem)->lock); + + while ((*sem)->count == 0) { + (*sem)->nwaiters++; + pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock); + (*sem)->nwaiters--; + } + (*sem)->count--; + + pthread_mutex_unlock(&(*sem)->lock); + + retval = 0; + RETURN: + _thread_leave_cancellation_point(); + return retval; + } + + int + _sem_trywait(sem_t *sem) + { + int retval; + + _SEM_CHECK_VALIDITY(sem); + + pthread_mutex_lock(&(*sem)->lock); + + if ((*sem)->count > 0) { + (*sem)->count--; + retval = 0; + } else { + errno = EAGAIN; + retval = -1; + } + + pthread_mutex_unlock(&(*sem)->lock); + + RETURN: + return retval; + } + + int + _sem_post(sem_t *sem) + { + int retval; + + _SEM_CHECK_VALIDITY(sem); + + /* + * sem_post() is required to be safe to call from within signal + * handlers. Thus, we must defer signals. + */ + _thread_kern_sig_defer(); + + pthread_mutex_lock(&(*sem)->lock); + + (*sem)->count++; + if ((*sem)->nwaiters > 0) + pthread_cond_signal(&(*sem)->gtzero); + + pthread_mutex_unlock(&(*sem)->lock); + + _thread_kern_sig_undefer(); + retval = 0; + RETURN: + return retval; + } + + int + _sem_getvalue(sem_t *sem, int *sval) + { + int retval; + + _SEM_CHECK_VALIDITY(sem); + + pthread_mutex_lock(&(*sem)->lock); + *sval = (int)(*sem)->count; + pthread_mutex_unlock(&(*sem)->lock); + + retval = 0; + RETURN: + return retval; + } Index: lib/libpthread/uthread/uthread_seterrno.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_seterrno.c Sun Sep 15 21:38:58 2002 *************** *** 0 **** --- 1,59 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_seterrno.c,v 1.5 2001/01/24 13:03:35 deischen Exp $ + */ + #include + #include "pthread_private.h" + + /* + * This function needs to reference the global error variable which is + * normally hidden from the user. + */ + #ifdef errno + #undef errno; + #endif + extern int errno; + + void + _thread_seterrno(pthread_t thread, int error) + { + /* Check for the initial thread: */ + if (thread == _thread_initial) + /* The initial thread always uses the global error variable: */ + errno = error; + else + /* + * Threads other than the initial thread always use the error + * field in the thread structureL + */ + thread->error = error; + } Index: lib/libpthread/uthread/uthread_setprio.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_setprio.c Sun Sep 15 21:38:58 2002 *************** *** 0 **** --- 1,52 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_setprio.c,v 1.9 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include "pthread_private.h" + + __weak_reference(_pthread_setprio, pthread_setprio); + + int + _pthread_setprio(pthread_t pthread, int prio) + { + int ret, policy; + struct sched_param param; + + if ((ret = pthread_getschedparam(pthread, &policy, ¶m)) == 0) { + param.sched_priority = prio; + ret = pthread_setschedparam(pthread, policy, ¶m); + } + + /* Return the error status: */ + return (ret); + } Index: lib/libpthread/uthread/uthread_setschedparam.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_setschedparam.c Sun Sep 15 21:38:59 2002 *************** *** 0 **** --- 1,119 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_setschedparam.c,v 1.9 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_setschedparam, pthread_setschedparam); + + int + _pthread_setschedparam(pthread_t pthread, int policy, + const struct sched_param *param) + { + int old_prio, in_readyq = 0, ret = 0; + + if ((param == NULL) || (policy < SCHED_FIFO) || (policy > SCHED_RR)) { + /* Return an invalid argument error: */ + ret = EINVAL; + } else if ((param->sched_priority < PTHREAD_MIN_PRIORITY) || + (param->sched_priority > PTHREAD_MAX_PRIORITY)) { + /* Return an unsupported value error. */ + ret = ENOTSUP; + + /* Find the thread in the list of active threads: */ + } else if ((ret = _find_thread(pthread)) == 0) { + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + if (param->sched_priority != + PTHREAD_BASE_PRIORITY(pthread->base_priority)) { + /* + * Remove the thread from its current priority + * queue before any adjustments are made to its + * active priority: + */ + old_prio = pthread->active_priority; + if ((pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) != 0) { + in_readyq = 1; + PTHREAD_PRIOQ_REMOVE(pthread); + } + + /* Set the thread base priority: */ + pthread->base_priority &= + (PTHREAD_SIGNAL_PRIORITY | PTHREAD_RT_PRIORITY); + pthread->base_priority = param->sched_priority; + + /* Recalculate the active priority: */ + pthread->active_priority = MAX(pthread->base_priority, + pthread->inherited_priority); + + if (in_readyq) { + if ((pthread->priority_mutex_count > 0) && + (old_prio > pthread->active_priority)) { + /* + * POSIX states that if the priority is + * being lowered, the thread must be + * inserted at the head of the queue for + * its priority if it owns any priority + * protection or inheritence mutexes. + */ + PTHREAD_PRIOQ_INSERT_HEAD(pthread); + } + else + PTHREAD_PRIOQ_INSERT_TAIL(pthread); + } + + /* + * Check for any mutex priority adjustments. This + * includes checking for a priority mutex on which + * this thread is waiting. + */ + _mutex_notify_priochange(pthread); + } + + /* Set the scheduling policy: */ + pthread->attr.sched_policy = policy; + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + return(ret); + } Index: lib/libpthread/uthread/uthread_sigmask.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_sigmask.c Sun Sep 15 21:38:59 2002 *************** *** 0 **** --- 1,49 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_sigmask.c,v 1.9 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_pthread_sigmask, pthread_sigmask); + + int + _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) + { + + return (sigprocmask(how, set, oset)); + } Index: lib/libpthread/uthread/uthread_sigsuspend.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_sigsuspend.c Sun Sep 15 21:38:59 2002 *************** *** 0 **** --- 1,53 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_sigsuspend.c,v 1.12 2002/06/28 13:28:41 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__sigsuspend, sigsuspend); + + int + __sigsuspend(const sigset_t * set) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __sys_sigsuspend(set); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_sigwait.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_sigwait.c Sun Sep 15 21:38:59 2002 *************** *** 0 **** --- 1,51 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_sigwait.c,v 1.18 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_sigwait, sigwait); + + int + _sigwait(const sigset_t *set, int *sig) + { + + /* + * All signals are invalid for waiting. + */ + return (EINVAL); + } Index: lib/libpthread/uthread/uthread_single_np.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_single_np.c Sun Sep 15 21:39:00 2002 *************** *** 0 **** --- 1,49 ---- + /* + * Copyright (c) 1996 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_single_np.c,v 1.6 2002/05/24 04:32:28 deischen Exp $ + */ + #include + #include + + __weak_reference(_pthread_single_np, pthread_single_np); + + int _pthread_single_np() + { + + /* Enter single-threaded (non-POSIX) scheduling mode: */ + pthread_suspend_all_np(); + /* + * XXX - Do we want to do this? + * __is_threaded = 0; + */ + return (0); + } Index: lib/libpthread/uthread/uthread_sleep.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_sleep.c Sun Sep 15 21:39:00 2002 *************** *** 0 **** --- 1,48 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_sleep.c,v 1.4 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include + #include "pthread_private.h" + + __weak_reference(_sleep, sleep); + + unsigned int + _sleep(unsigned int seconds) + { + unsigned int ret; + + _thread_enter_cancellation_point(); + ret = __sleep(seconds); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_spec.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_spec.c Sun Sep 15 21:39:00 2002 *************** *** 0 **** --- 1,225 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_spec.c,v 1.17 2002/03/19 22:58:56 deischen Exp $ + */ + #include + #include + #include + #include + #include + #include "pthread_private.h" + + struct pthread_key { + spinlock_t lock; + volatile int allocated; + volatile int count; + int seqno; + void (*destructor) (); + }; + + /* Static variables: */ + static struct pthread_key key_table[PTHREAD_KEYS_MAX]; + + __weak_reference(_pthread_key_create, pthread_key_create); + __weak_reference(_pthread_key_delete, pthread_key_delete); + __weak_reference(_pthread_getspecific, pthread_getspecific); + __weak_reference(_pthread_setspecific, pthread_setspecific); + + + int + _pthread_key_create(pthread_key_t * key, void (*destructor) (void *)) + { + for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) { + /* Lock the key table entry: */ + _SPINLOCK(&key_table[*key].lock); + + if (key_table[(*key)].allocated == 0) { + key_table[(*key)].allocated = 1; + key_table[(*key)].destructor = destructor; + key_table[(*key)].seqno++; + + /* Unlock the key table entry: */ + _SPINUNLOCK(&key_table[*key].lock); + return (0); + } + + /* Unlock the key table entry: */ + _SPINUNLOCK(&key_table[*key].lock); + } + return (EAGAIN); + } + + int + _pthread_key_delete(pthread_key_t key) + { + int ret = 0; + + if (key < PTHREAD_KEYS_MAX) { + /* Lock the key table entry: */ + _SPINLOCK(&key_table[key].lock); + + if (key_table[key].allocated) + key_table[key].allocated = 0; + else + ret = EINVAL; + + /* Unlock the key table entry: */ + _SPINUNLOCK(&key_table[key].lock); + } else + ret = EINVAL; + return (ret); + } + + void + _thread_cleanupspecific(void) + { + struct pthread *curthread = _get_curthread(); + void *data = NULL; + int key; + int itr; + void (*destructor)( void *); + + for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) { + for (key = 0; key < PTHREAD_KEYS_MAX; key++) { + if (curthread->specific_data_count > 0) { + /* Lock the key table entry: */ + _SPINLOCK(&key_table[key].lock); + destructor = NULL; + + if (key_table[key].allocated && + (curthread->specific[key].data != NULL)) { + if (curthread->specific[key].seqno == + key_table[key].seqno) { + data = (void *) curthread->specific[key].data; + destructor = key_table[key].destructor; + } + curthread->specific[key].data = NULL; + curthread->specific_data_count--; + } + + /* Unlock the key table entry: */ + _SPINUNLOCK(&key_table[key].lock); + + /* + * If there is a destructore, call it + * with the key table entry unlocked: + */ + if (destructor) + destructor(data); + } else { + free(curthread->specific); + curthread->specific = NULL; + return; + } + } + } + if (curthread->specific != NULL) { + free(curthread->specific); + curthread->specific = NULL; + } + } + + static inline struct pthread_specific_elem * + pthread_key_allocate_data(void) + { + struct pthread_specific_elem *new_data; + + new_data = (struct pthread_specific_elem *) + malloc(sizeof(struct pthread_specific_elem) * PTHREAD_KEYS_MAX); + if (new_data != NULL) { + memset((void *) new_data, 0, + sizeof(struct pthread_specific_elem) * PTHREAD_KEYS_MAX); + } + return (new_data); + } + + int + _pthread_setspecific(pthread_key_t key, const void *value) + { + struct pthread *pthread; + int ret = 0; + + /* Point to the running thread: */ + pthread = _get_curthread(); + + if ((pthread->specific) || + (pthread->specific = pthread_key_allocate_data())) { + if (key < PTHREAD_KEYS_MAX) { + if (key_table[key].allocated) { + if (pthread->specific[key].data == NULL) { + if (value != NULL) + pthread->specific_data_count++; + } else { + if (value == NULL) + pthread->specific_data_count--; + } + pthread->specific[key].data = value; + pthread->specific[key].seqno = + key_table[key].seqno; + ret = 0; + } else + ret = EINVAL; + } else + ret = EINVAL; + } else + ret = ENOMEM; + return (ret); + } + + void * + _pthread_getspecific(pthread_key_t key) + { + struct pthread *pthread; + void *data; + + /* Point to the running thread: */ + pthread = _get_curthread(); + + /* Check if there is specific data: */ + if (pthread->specific != NULL && key < PTHREAD_KEYS_MAX) { + /* Check if this key has been used before: */ + if (key_table[key].allocated && + (pthread->specific[key].seqno == key_table[key].seqno)) { + /* Return the value: */ + data = (void *) pthread->specific[key].data; + } else { + /* + * This key has not been used before, so return NULL + * instead: + */ + data = NULL; + } + } else + /* No specific data has been created, so just return NULL: */ + data = NULL; + return (data); + } Index: lib/libpthread/uthread/uthread_spinlock.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_spinlock.c Sun Sep 15 21:39:00 2002 *************** *** 0 **** --- 1,111 ---- + /* + * 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_spinlock.c,v 1.11 2002/05/24 04:32:28 deischen Exp $ + * + */ + + #include + #include + #include + #include + #include + #include + + #include + + #include "pthread_private.h" + + /* + * Lock a location for the running thread. Yield to allow other + * threads to run if this thread is blocked because the lock is + * not available. Note that this function does not sleep. It + * assumes that the lock will be available very soon. + */ + void + _spinlock(spinlock_t *lck) + { + struct pthread *curthread = _get_curthread(); + + /* + * Try to grab the lock and loop if another thread grabs + * it before we do. + */ + while(_atomic_lock(&lck->access_lock)) { + /* Block the thread until the lock. */ + curthread->data.spinlock = lck; + _thread_kern_sched_state(PS_SPINBLOCK, __FILE__, __LINE__); + } + + /* The running thread now owns the lock: */ + lck->lock_owner = (long) curthread; + } + + /* + * Lock a location for the running thread. Yield to allow other + * threads to run if this thread is blocked because the lock is + * not available. Note that this function does not sleep. It + * assumes that the lock will be available very soon. + * + * This function checks if the running thread has already locked the + * location, warns if this occurs and creates a thread dump before + * returning. + */ + void + _spinlock_debug(spinlock_t *lck, char *fname, int lineno) + { + struct pthread *curthread = _get_curthread(); + int cnt = 0; + + /* + * Try to grab the lock and loop if another thread grabs + * it before we do. + */ + while(_atomic_lock(&lck->access_lock)) { + cnt++; + if (cnt > 100) { + char str[256]; + snprintf(str, sizeof(str), "%s - Warning: Thread %p attempted to lock %p from %s (%d) was left locked from %s (%d)\n", getprogname(), curthread, lck, fname, lineno, lck->fname, lck->lineno); + __sys_write(2,str,strlen(str)); + __sleep(1); + cnt = 0; + } + + /* Block the thread until the lock. */ + curthread->data.spinlock = lck; + _thread_kern_sched_state(PS_SPINBLOCK, fname, lineno); + } + + /* The running thread now owns the lock: */ + lck->lock_owner = (long) curthread; + lck->fname = fname; + lck->lineno = lineno; + } Index: lib/libpthread/uthread/uthread_stack.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_stack.c Sun Sep 15 21:39:00 2002 *************** *** 0 **** --- 1,240 ---- + /* + * Copyright (c) 2001 Daniel Eischen + * Copyright (c) 2000-2001 Jason Evans + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_stack.c,v 1.4 2002/05/15 05:37:48 alfred Exp $ + */ + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + /* Spare thread stack. */ + struct stack { + LIST_ENTRY(stack) qe; /* Stack queue linkage. */ + size_t stacksize; /* Stack size (rounded up). */ + size_t guardsize; /* Guard size. */ + void *stackaddr; /* Stack address. */ + }; + + /* + * Default sized (stack and guard) spare stack queue. Stacks are cached to + * avoid additional complexity managing mmap()ed stack regions. Spare stacks + * are used in LIFO order to increase cache locality. + */ + static LIST_HEAD(, stack) _dstackq = LIST_HEAD_INITIALIZER(_dstackq); + + /* + * Miscellaneous sized (non-default stack and/or guard) spare stack queue. + * Stacks are cached to avoid additional complexity managing mmap()ed stack + * regions. This list is unordered, since ordering on both stack size and guard + * size would be more trouble than it's worth. Stacks are allocated from this + * cache on a first size match basis. + */ + static LIST_HEAD(, stack) _mstackq = LIST_HEAD_INITIALIZER(_mstackq); + + /** + * Base address of the last stack allocated (including its red zone, if there is + * one). Stacks are allocated contiguously, starting beyond the top of the main + * stack. When a new stack is created, a red zone is typically created + * (actually, the red zone is simply left unmapped) above the top of the stack, + * such that the stack will not be able to grow all the way to the bottom of the + * next stack. This isn't fool-proof. It is possible for a stack to grow by a + * large amount, such that it grows into the next stack, and as long as the + * memory within the red zone is never accessed, nothing will prevent one thread + * stack from trouncing all over the next. + * + * low memory + * . . . . . . . . . . . . . . . . . . + * | | + * | stack 3 | start of 3rd thread stack + * +-----------------------------------+ + * | | + * | Red Zone (guard page) | red zone for 2nd thread + * | | + * +-----------------------------------+ + * | stack 2 - PTHREAD_STACK_DEFAULT | top of 2nd thread stack + * | | + * | | + * | | + * | | + * | stack 2 | + * +-----------------------------------+ <-- start of 2nd thread stack + * | | + * | Red Zone | red zone for 1st thread + * | | + * +-----------------------------------+ + * | stack 1 - PTHREAD_STACK_DEFAULT | top of 1st thread stack + * | | + * | | + * | | + * | | + * | stack 1 | + * +-----------------------------------+ <-- start of 1st thread stack + * | | (initial value of last_stack) + * | Red Zone | + * | | red zone for main thread + * +-----------------------------------+ + * | USRSTACK - PTHREAD_STACK_INITIAL | top of main thread stack + * | | ^ + * | | | + * | | | + * | | | stack growth + * | | + * +-----------------------------------+ <-- start of main thread stack + * (USRSTACK) + * high memory + * + */ + static void * last_stack; + + void * + _thread_stack_alloc(size_t stacksize, size_t guardsize) + { + void *stack = NULL; + struct stack *spare_stack; + size_t stack_size; + + /* + * Round up stack size to nearest multiple of _pthread_page_size, + * so that mmap() * will work. If the stack size is not an even + * multiple, we end up initializing things such that there is unused + * space above the beginning of the stack, so the stack sits snugly + * against its guard. + */ + if (stacksize % _pthread_page_size != 0) + stack_size = ((stacksize / _pthread_page_size) + 1) * + _pthread_page_size; + else + stack_size = stacksize; + + /* + * If the stack and guard sizes are default, try to allocate a stack + * from the default-size stack cache: + */ + if (stack_size == PTHREAD_STACK_DEFAULT && + guardsize == _pthread_guard_default) { + /* + * Use the garbage collector mutex for synchronization of the + * spare stack list. + */ + if (pthread_mutex_lock(&_gc_mutex) != 0) + PANIC("Cannot lock gc mutex"); + + if ((spare_stack = LIST_FIRST(&_dstackq)) != NULL) { + /* Use the spare stack. */ + LIST_REMOVE(spare_stack, qe); + stack = spare_stack->stackaddr; + } + + /* Unlock the garbage collector mutex. */ + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot unlock gc mutex"); + } + /* + * The user specified a non-default stack and/or guard size, so try to + * allocate a stack from the non-default size stack cache, using the + * rounded up stack size (stack_size) in the search: + */ + else { + /* + * Use the garbage collector mutex for synchronization of the + * spare stack list. + */ + if (pthread_mutex_lock(&_gc_mutex) != 0) + PANIC("Cannot lock gc mutex"); + + LIST_FOREACH(spare_stack, &_mstackq, qe) { + if (spare_stack->stacksize == stack_size && + spare_stack->guardsize == guardsize) { + LIST_REMOVE(spare_stack, qe); + stack = spare_stack->stackaddr; + break; + } + } + + /* Unlock the garbage collector mutex. */ + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot unlock gc mutex"); + } + + /* Check if a stack was not allocated from a stack cache: */ + if (stack == NULL) { + + if (last_stack == NULL) + last_stack = _usrstack - PTHREAD_STACK_INITIAL - + _pthread_guard_default; + + /* Allocate a new stack. */ + stack = last_stack - stack_size; + + /* + * Even if stack allocation fails, we don't want to try to use + * this location again, so unconditionally decrement + * last_stack. Under normal operating conditions, the most + * likely reason for an mmap() error is a stack overflow of the + * adjacent thread stack. + */ + last_stack -= (stack_size + guardsize); + + /* Stack: */ + if (mmap(stack, stack_size, PROT_READ | PROT_WRITE, MAP_STACK, + -1, 0) == MAP_FAILED) + stack = NULL; + } + + return (stack); + } + + /* This function must be called with _gc_mutex held. */ + void + _thread_stack_free(void *stack, size_t stacksize, size_t guardsize) + { + struct stack *spare_stack; + + spare_stack = (stack + stacksize - sizeof(struct stack)); + /* Round stacksize up to nearest multiple of _pthread_page_size. */ + if (stacksize % _pthread_page_size != 0) { + spare_stack->stacksize = + ((stacksize / _pthread_page_size) + 1) * + _pthread_page_size; + } else + spare_stack->stacksize = stacksize; + spare_stack->guardsize = guardsize; + spare_stack->stackaddr = stack; + + if (spare_stack->stacksize == PTHREAD_STACK_DEFAULT && + spare_stack->guardsize == _pthread_guard_default) { + /* Default stack/guard size. */ + LIST_INSERT_HEAD(&_dstackq, spare_stack, qe); + } else { + /* Non-default stack/guard size. */ + LIST_INSERT_HEAD(&_mstackq, spare_stack, qe); + } + } Index: lib/libpthread/uthread/uthread_suspend_np.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_suspend_np.c Sun Sep 15 21:39:01 2002 *************** *** 0 **** --- 1,104 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_suspend_np.c,v 1.14 2002/05/24 04:32:28 deischen Exp $ + */ + #include + #include + #include "pthread_private.h" + + static void suspend_common(struct pthread *thread); + + __weak_reference(_pthread_suspend_np, pthread_suspend_np); + __weak_reference(_pthread_suspend_all_np, pthread_suspend_all_np); + + /* Suspend a thread: */ + int + _pthread_suspend_np(pthread_t thread) + { + int ret; + + /* Suspending the current thread doesn't make sense. */ + if (thread == _get_curthread()) + ret = EDEADLK; + + /* Find the thread in the list of active threads: */ + else if ((ret = _find_thread(thread)) == 0) { + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + suspend_common(thread); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + return (ret); + } + + void + _pthread_suspend_all_np(void) + { + struct pthread *curthread = _get_curthread(); + struct pthread *thread; + + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + TAILQ_FOREACH(thread, &_thread_list, tle) { + if (thread != curthread) + suspend_common(thread); + } + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); + } + + void + suspend_common(struct pthread *thread) + { + thread->flags |= PTHREAD_FLAGS_SUSPENDED; + if (thread->flags & PTHREAD_FLAGS_IN_PRIOQ) { + PTHREAD_PRIOQ_REMOVE(thread); + PTHREAD_SET_STATE(thread, PS_SUSPENDED); + } + } Index: lib/libpthread/uthread/uthread_switch_np.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_switch_np.c Sun Sep 15 21:39:01 2002 *************** *** 0 **** --- 1,71 ---- + /* + * Copyright (c) 1998 Daniel Eischen . + * 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 Daniel Eischen. + * 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 DANIEL EISCHEN 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_switch_np.c,v 1.5 2001/04/10 04:19:20 deischen Exp $ + */ + #include + #include + #include + #include "pthread_private.h" + + + __weak_reference(_pthread_switch_add_np, pthread_switch_add_np); + __weak_reference(_pthread_switch_delete_np, pthread_switch_delete_np); + + int + _pthread_switch_add_np(pthread_switch_routine_t routine) + { + int ret = 0; + + if (routine == NULL) + /* Return an invalid argument error: */ + ret = EINVAL; + else + /* Shouldn't need a lock to protect this assigment. */ + _sched_switch_hook = routine; + + return(ret); + } + + int + _pthread_switch_delete_np(pthread_switch_routine_t routine) + { + int ret = 0; + + if (routine != _sched_switch_hook) + /* Return an invalid argument error: */ + ret = EINVAL; + else + /* Shouldn't need a lock to protect this assigment. */ + _sched_switch_hook = NULL; + + return(ret); + } Index: lib/libpthread/uthread/uthread_system.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_system.c Sun Sep 15 21:39:01 2002 *************** *** 0 **** --- 1,48 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_system.c,v 1.4 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include + #include "pthread_private.h" + + __weak_reference(_system, system); + + int + _system(const char *string) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __system(string); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_tcdrain.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_tcdrain.c Sun Sep 15 21:39:01 2002 *************** *** 0 **** --- 1,48 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_tcdrain.c,v 1.4 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include + #include "pthread_private.h" + + __weak_reference(_tcdrain, tcdrain); + + int + _tcdrain(int fd) + { + int ret; + + _thread_enter_cancellation_point(); + ret = __tcdrain(fd); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_vfork.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_vfork.c Sun Sep 15 21:39:01 2002 *************** *** 0 **** --- 1,12 ---- + /* + * $FreeBSD: src/lib/libc_r/uthread/uthread_vfork.c,v 1.3 2001/04/10 04:19:20 deischen Exp $ + */ + #include + + __weak_reference(_vfork, vfork); + + int + _vfork(void) + { + return (fork()); + } Index: lib/libpthread/uthread/uthread_wait.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_wait.c Sun Sep 15 21:39:02 2002 *************** *** 0 **** --- 1,47 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_wait.c,v 1.4 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include "pthread_private.h" + + __weak_reference(_wait, wait); + + pid_t + _wait(int *istat) + { + pid_t ret; + + _thread_enter_cancellation_point(); + ret = __wait(istat); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_wait4.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_wait4.c Sun Sep 15 21:39:02 2002 *************** *** 0 **** --- 1,53 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_wait4.c,v 1.14 2002/05/02 19:58:43 archie Exp $ + */ + #include + + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__wait4, wait4); + + pid_t + __wait4(pid_t pid, int *istat, int options, struct rusage *rusage) + { + pid_t ret; + + _thread_enter_cancellation_point(); + ret = _wait4(pid, istat, options, rusage); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_waitpid.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_waitpid.c Sun Sep 15 21:39:02 2002 *************** *** 0 **** --- 1,49 ---- + /* + * Copyright (C) 2000 Jason Evans . + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_waitpid.c,v 1.4 2001/04/10 04:19:20 deischen Exp $ + */ + + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(_waitpid, waitpid); + + pid_t + _waitpid(pid_t wpid, int *status, int options) + { + pid_t ret; + + _thread_enter_cancellation_point(); + ret = __waitpid(wpid, status, options); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_write.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_write.c Sun Sep 15 21:39:02 2002 *************** *** 0 **** --- 1,55 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_write.c,v 1.20 2002/08/29 23:06:07 deischen Exp $ + * + */ + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__write, write); + + ssize_t + __write(int fd, const void *buf, size_t nbytes) + { + ssize_t ret; + + _thread_enter_cancellation_point(); + ret = __sys_write(fd, buf, nbytes); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_writev.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_writev.c Sun Sep 15 21:39:03 2002 *************** *** 0 **** --- 1,57 ---- + /* + * Copyright (c) 1995-1998 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_writev.c,v 1.20 2002/08/29 23:06:07 deischen Exp $ + * + */ + #include + #include + #include + #include + #include + #include + #include + #include + #include "pthread_private.h" + + __weak_reference(__writev, writev); + + ssize_t + __writev(int fd, const struct iovec *iov, int iovcnt) + { + ssize_t ret; + + _thread_enter_cancellation_point(); + ret = __sys_writev(fd, iov, iovcnt); + _thread_leave_cancellation_point(); + + return ret; + } Index: lib/libpthread/uthread/uthread_yield.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- lib/libpthread/uthread/uthread_yield.c Sun Sep 15 21:39:03 2002 *************** *** 0 **** --- 1,66 ---- + /* + * Copyright (c) 1995 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 AUTHOR 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. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_yield.c,v 1.7 2001/04/10 04:19:21 deischen Exp $ + */ + #include + #include "pthread_private.h" + + __weak_reference(_sched_yield, sched_yield); + __weak_reference(_pthread_yield, pthread_yield); + + int + _sched_yield(void) + { + struct pthread *curthread = _get_curthread(); + + /* Reset the accumulated time slice value for the current thread: */ + curthread->slice_usec = -1; + + /* Schedule the next thread: */ + _thread_kern_sched(); + + /* Always return no error. */ + return(0); + } + + /* Draft 4 yield */ + void + _pthread_yield(void) + { + struct pthread *curthread = _get_curthread(); + + /* Reset the accumulated time slice value for the current thread: */ + curthread->slice_usec = -1; + + /* Schedule the next thread: */ + _thread_kern_sched(); + } Index: sys/i386/i386/genassym.c =========================================================================== --- sys/i386/i386/genassym.c 2002/09/15 21:37:55 #17 +++ sys/i386/i386/genassym.c 2002/09/15 21:37:55 @@ -142,7 +142,6 @@ ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_save)); ASSYM(PCB_SAVEFPU_SIZE, sizeof(union savefpu)); -ASSYM(PCB_SAVE87_SIZE, sizeof(struct save87)); ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); ASSYM(PCB_SIZE, sizeof(struct pcb)); Index: sys/i386/i386/machdep.c =========================================================================== --- sys/i386/i386/machdep.c 2002/09/15 21:37:55 #71 +++ sys/i386/i386/machdep.c 2002/09/15 21:37:55 @@ -138,6 +138,9 @@ #endif static void cpu_startup(void *); +static void fpstate_drop(struct thread *td); +static void get_fpcontext(struct thread *td, mcontext_t *mcp); +static int set_fpcontext(struct thread *td, const mcontext_t *mcp); #ifdef CPU_ENABLE_SSE static void set_fpregs_xmm(struct save87 *, struct savexmm *); static void fill_fpregs_xmm(struct savexmm *, struct save87 *); @@ -440,8 +443,10 @@ ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; sf.sf_uc.uc_mcontext.mc_gs = rgs(); - sf.sf_uc.uc_mcontext.mc_flags = __UC_MC_VALID; /* no FP regs */ bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs)); + sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ + get_fpcontext(td, &sf.sf_uc.uc_mcontext); + fpstate_drop(td); /* Allocate space for the signal handler context. */ if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && @@ -675,7 +680,7 @@ struct proc *p = td->td_proc; struct trapframe *regs; const ucontext_t *ucp; - int cs, eflags, error; + int cs, eflags, error, ret; error = copyin(uap->sigcntxp, &uc, sizeof(uc)); if (error != 0) @@ -749,6 +754,9 @@ return (EINVAL); } + ret = set_fpcontext(td, &ucp->uc_mcontext); + if (ret != 0) + return (ret); bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs)); } @@ -909,10 +917,19 @@ */ load_cr0(rcr0() | CR0_MP | CR0_TS); -#ifdef DEV_NPX /* Initialize the npx (if any) for the current process. */ - npxinit(__INITIAL_NPXCW__); -#endif + /* + * XXX the above load_cr0() also initializes it and is a layering + * violation if NPX is configured. It drops the npx partially + * and this would be fatal if we were interrupted now, and decided + * to force the state to the pcb, and checked the invariant + * (CR0_TS clear) if and only if PCPU_GET(fpcurthread) != NULL). + * ALL of this can happen except the check. The check used to + * happen and be fatal later when we didn't complete the drop + * before returning to user mode. This should be fixed properly + * soon. + */ + fpstate_drop(td); /* * XXX - Linux emulator @@ -2003,8 +2020,6 @@ /* FPU registers */ for (i = 0; i < 8; ++i) sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc; - - sv_87->sv_ex_sw = sv_xmm->sv_ex_sw; } static void @@ -2029,8 +2044,6 @@ /* FPU registers */ for (i = 0; i < 8; ++i) sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i]; - - sv_xmm->sv_ex_sw = sv_87->sv_ex_sw; } #endif /* CPU_ENABLE_SSE */ @@ -2062,6 +2075,179 @@ return (0); } +/* + * Get machine context. + */ +void +get_mcontext(struct thread *td, mcontext_t *mcp) +{ + struct trapframe *tp; + + tp = td->td_frame; + + mcp->mc_onstack = sigonstack(tp->tf_esp); + mcp->mc_gs = td->td_pcb->pcb_gs; + mcp->mc_fs = tp->tf_fs; + mcp->mc_es = tp->tf_es; + mcp->mc_ds = tp->tf_ds; + mcp->mc_edi = tp->tf_edi; + mcp->mc_esi = tp->tf_esi; + mcp->mc_ebp = tp->tf_ebp; + mcp->mc_isp = tp->tf_isp; + mcp->mc_ebx = tp->tf_ebx; + mcp->mc_edx = tp->tf_edx; + mcp->mc_ecx = tp->tf_ecx; + mcp->mc_eax = tp->tf_eax; + mcp->mc_eip = tp->tf_eip; + mcp->mc_cs = tp->tf_cs; + mcp->mc_eflags = tp->tf_eflags; + mcp->mc_esp = tp->tf_esp; + mcp->mc_ss = tp->tf_ss; + mcp->mc_len = sizeof(*mcp); + get_fpcontext(td, mcp); +} + +/* + * Set machine context. + * + * However, we don't set any but the user modifyable flags, and + * we we won't touch the cs selector. + */ +int +set_mcontext(struct thread *td, const mcontext_t *mcp) +{ + struct trapframe *tp; + int ret; + int eflags; + + tp = td->td_frame; + if (mcp->mc_len != sizeof(*mcp)) + return (EINVAL); + eflags = (mcp->mc_eflags & PSL_USERCHANGE) | + (tp->tf_eflags & ~PSL_USERCHANGE); + if ((ret = set_fpcontext(td, mcp)) == 0) { + tp->tf_fs = mcp->mc_fs; + tp->tf_es = mcp->mc_es; + tp->tf_ds = mcp->mc_ds; + tp->tf_edi = mcp->mc_edi; + tp->tf_esi = mcp->mc_esi; + tp->tf_ebp = mcp->mc_ebp; + tp->tf_ebx = mcp->mc_ebx; + tp->tf_edx = mcp->mc_edx; + tp->tf_ecx = mcp->mc_ecx; + tp->tf_eax = mcp->mc_eax; + tp->tf_eip = mcp->mc_eip; + tp->tf_eflags = eflags; + tp->tf_esp = mcp->mc_esp; + tp->tf_ss = mcp->mc_ss; + td->td_pcb->pcb_gs = mcp->mc_gs; + ret = 0; + } + return (ret); +} + +static void +get_fpcontext(struct thread *td, mcontext_t *mcp) +{ +#ifndef DEV_NPX + mcp->mc_fpformat = _MC_FPFMT_NODEV; + mcp->mc_ownedfp = _MC_FPOWNED_NONE; +#else + union savefpu *addr; + + /* + * XXX mc_fpstate might be misaligned, since its declaration is not + * unportabilized using __attribute__((aligned(16))) like the + * declaration of struct savemm, and anyway, alignment doesn't work + * for auto variables since we don't use gcc's pessimal stack + * alignment. Work around this by abusing the spare fields after + * mcp->mc_fpstate. + * + * XXX unpessimize most cases by only aligning when fxsave might be + * called, although this requires knowing too much about + * npxgetregs()'s internals. + */ + addr = (union savefpu *)&mcp->mc_fpstate; + if (td == PCPU_GET(fpcurthread) && cpu_fxsr && + ((uintptr_t)(void *)addr & 0xF)) { + do + addr = (void *)((char *)addr + 4); + while ((uintptr_t)(void *)addr & 0xF); + } + mcp->mc_ownedfp = npxgetregs(td, addr); + if (addr != (union savefpu *)&mcp->mc_fpstate) { + bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); + bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); + } + mcp->mc_fpformat = npxformat(); +#endif +} + +static int +set_fpcontext(struct thread *td, const mcontext_t *mcp) +{ + union savefpu *addr; + + if (mcp->mc_fpformat == _MC_FPFMT_NODEV) + return (0); + else if (mcp->mc_fpformat != _MC_FPFMT_387 && + mcp->mc_fpformat != _MC_FPFMT_XMM) + return (EINVAL); + else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) + /* We don't care what state is left in the FPU or PCB. */ + fpstate_drop(td); + else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || + mcp->mc_ownedfp == _MC_FPOWNED_PCB) { + /* XXX align as above. */ + addr = (union savefpu *)&mcp->mc_fpstate; + if (td == PCPU_GET(fpcurthread) && cpu_fxsr && + ((uintptr_t)(void *)addr & 0xF)) { + do + addr = (void *)((char *)addr + 4); + while ((uintptr_t)(void *)addr & 0xF); + bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate)); + } +#ifdef DEV_NPX + /* + * XXX we violate the dubious requirement that npxsetregs() + * be called with interrupts disabled. + */ + npxsetregs(td, addr); +#endif + /* + * Don't bother putting things back where they were in the + * misaligned case, since we know that the caller won't use + * them again. + */ + } else + return (EINVAL); + return (0); +} + +static void +fpstate_drop(struct thread *td) +{ + register_t s; + + s = intr_disable(); +#ifdef DEV_NPX + if (PCPU_GET(fpcurthread) == td) + npxdrop(); +#endif + /* + * XXX force a full drop of the npx. The above only drops it if we + * owned it. npxgetregs() has the same bug in the !cpu_fxsr case. + * + * XXX I don't much like npxgetregs()'s semantics of doing a full + * drop. Dropping only to the pcb matches fnsave's behaviour. + * We only need to drop to !PCB_INITDONE in sendsig(). But + * sendsig() is the only caller of npxgetregs()... perhaps we just + * have too many layers. + */ + curthread->td_pcb->pcb_flags &= ~PCB_NPXINITDONE; + intr_restore(s); +} + int fill_dbregs(struct thread *td, struct dbreg *dbregs) { Index: sys/i386/i386/support.s =========================================================================== --- sys/i386/i386/support.s 2002/09/15 21:37:55 #8 +++ sys/i386/i386/support.s 2002/09/15 21:37:55 @@ -976,7 +976,7 @@ ENTRY(fastmove) pushl %ebp movl %esp,%ebp - subl $PCB_SAVE87_SIZE+3*4,%esp + subl $PCB_SAVEFPU_SIZE+3*4,%esp movl 8(%ebp),%ecx cmpl $63,%ecx @@ -1018,7 +1018,7 @@ movl PCPU(CURPCB),%esi addl $PCB_SAVEFPU,%esi cld - movl $PCB_SAVE87_SIZE>>2,%ecx + movl $PCB_SAVEFPU_SIZE>>2,%ecx rep movsl movl -12(%ebp),%ecx @@ -1102,7 +1102,7 @@ addl $PCB_SAVEFPU,%edi movl %esp,%esi cld - movl $PCB_SAVE87_SIZE>>2,%ecx + movl $PCB_SAVEFPU_SIZE>>2,%ecx rep movsl movl -12(%ebp),%ecx @@ -1147,7 +1147,7 @@ addl $PCB_SAVEFPU,%edi movl %esp,%esi cld - movl $PCB_SAVE87_SIZE>>2,%ecx + movl $PCB_SAVEFPU_SIZE>>2,%ecx rep movsl Index: sys/i386/i386/trap.c =========================================================================== --- sys/i386/i386/trap.c 2002/09/15 21:37:55 #35 +++ sys/i386/i386/trap.c 2002/09/15 21:37:55 @@ -971,7 +971,7 @@ * but for now do it every time. */ td->td_mailbox = (void *)fuword((caddr_t)td->td_kse->ke_mailbox - + offsetof(struct kse_mailbox, kmbx_current_thread)); + + offsetof(struct kse_mailbox, km_curthread)); if ((td->td_mailbox == NULL) || (td->td_mailbox == (void *)-1)) { td->td_mailbox = NULL; /* single thread it.. */ Index: sys/i386/i386/vm_machdep.c =========================================================================== --- sys/i386/i386/vm_machdep.c 2002/09/15 21:37:55 #25 +++ sys/i386/i386/vm_machdep.c 2002/09/15 21:37:55 @@ -307,44 +307,11 @@ td->td_frame = (struct trapframe *)((caddr_t)td->td_pcb - 16) - 1; } -struct md_store { - struct pcb mds_pcb; - struct trapframe mds_frame; -}; - +/* + * Initialize machine state (pcb and trap frame) for a new thread about to + * upcall. + */ void -cpu_save_upcall(struct thread *td, struct kse *newkse) -{ - struct trapframe *tf; - - newkse->ke_mdstorage = malloc(sizeof(struct md_store), M_TEMP, - M_WAITOK); - /* Note: use of M_WAITOK means it won't fail. */ - /* set up shortcuts in MI section */ - newkse->ke_pcb = - &(((struct md_store *)(newkse->ke_mdstorage))->mds_pcb); - newkse->ke_frame = - &(((struct md_store *)(newkse->ke_mdstorage))->mds_frame); - tf = newkse->ke_frame; - - /* Copy the upcall pcb. Kernel mode & fp regs are here. */ - /* XXXKSE this may be un-needed */ - bcopy(td->td_pcb, newkse->ke_pcb, sizeof(struct pcb)); - - /* - * This initialises most of the user mode register values - * to good values. Eventually set them explicitly to know values - */ - bcopy(td->td_frame, newkse->ke_frame, sizeof(struct trapframe)); - tf->tf_edi = 0; - tf->tf_esi = 0; /* trampoline arg */ - tf->tf_ebp = 0; - tf->tf_esp = (int)newkse->ke_stackbase + newkse->ke_stacksize - 16; - tf->tf_ebx = 0; /* trampoline arg */ - tf->tf_eip = (int)newkse->ke_upcall; -} - -void cpu_set_upcall(struct thread *td, void *pcb) { struct pcb *pcb2; @@ -401,41 +368,28 @@ pcb2->pcb_ext = NULL; } +/* + * Set the machine state for performing an upcall that had to + * wait until we selected a KSE to perform the upcall on. + */ void -cpu_set_args(struct thread *td, struct kse *ke) +cpu_set_upcall_kse(struct thread *td, struct kse *ke) { - suword((void *)(ke->ke_frame->tf_esp + sizeof(void *)), - (int)ke->ke_mailbox); -} -void -cpu_free_kse_mdstorage(struct kse *kse) -{ + /* + * Set the trap frame to point at the beginning of the uts + * function. + */ + td->td_frame->tf_esp = + (int)ke->ke_stack.ss_sp + ke->ke_stack.ss_size - 16; + td->td_frame->tf_eip = (int)ke->ke_upcall; - free(kse->ke_mdstorage, M_TEMP); - kse->ke_mdstorage = NULL; - kse->ke_pcb = NULL; - kse->ke_frame = NULL; -} - -int -cpu_export_context(struct thread *td) -{ - struct trapframe *frame; - struct thread_mailbox *tm; - struct trapframe *uframe; - int error; - - frame = td->td_frame; - tm = td->td_mailbox; - uframe = &tm->ctx.tfrm.tf_tf; - error = copyout(frame, uframe, sizeof(*frame)); /* - * "What about the fp regs?" I hear you ask.... XXXKSE - * Don't know where gs and "onstack" come from. - * May need to fiddle a few other values too. + * Pass the address of the mailbox for this kse to the uts + * function as a parameter on the stack. */ - return (error); + suword((void *)(td->td_frame->tf_esp + sizeof(void *)), + (int)ke->ke_mailbox); } void Index: sys/i386/include/npx.h =========================================================================== --- sys/i386/include/npx.h 2002/09/15 21:37:55 #4 +++ sys/i386/include/npx.h 2002/09/15 21:37:55 @@ -73,7 +73,7 @@ struct save87 { struct env87 sv_env; /* floating point control/status */ struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */ - u_long sv_ex_sw; /* status word for last exception */ + u_char sv_pad0[4]; /* padding for (now unused) saved status word */ /* * Bogus padding for emulators. Emulators should use their own * struct and arrange to store into this struct (ending here) @@ -112,8 +112,7 @@ u_char fp_pad[6]; /* padding */ } sv_fp[8]; struct xmmacc sv_xmm[8]; - u_long sv_ex_sw; /* status word for last exception */ - u_char sv_pad[220]; + u_char sv_pad[224]; } __attribute__((aligned(16))); union savefpu { @@ -142,9 +141,13 @@ #ifdef _KERNEL int npxdna(void); +void npxdrop(void); void npxexit(struct thread *td); -void npxinit(int control); +int npxformat(void); +int npxgetregs(struct thread *td, union savefpu *addr); +void npxinit(u_short control); void npxsave(union savefpu *addr); +void npxsetregs(struct thread *td, union savefpu *addr); int npxtrap(void); #endif Index: sys/i386/include/pcb.h =========================================================================== --- sys/i386/include/pcb.h 2002/09/15 21:37:55 #7 +++ sys/i386/include/pcb.h 2002/09/15 21:37:55 @@ -66,6 +66,7 @@ #define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */ #define PCB_DBREGS 0x02 /* process using debug registers */ #define PCB_NPXTRAP 0x04 /* npx trap pending */ +#define PCB_NPXINITDONE 0x08 /* fpu state is initialized */ caddr_t pcb_onfault; /* copyin/out fault recovery */ int pcb_gs; struct pcb_ext *pcb_ext; /* optional pcb extension */ Index: sys/i386/include/signal.h =========================================================================== --- sys/i386/include/signal.h 2002/09/15 21:37:55 #3 +++ sys/i386/include/signal.h 2002/09/15 21:37:55 @@ -117,13 +117,16 @@ int sc_efl; int sc_esp; int sc_ss; + int sc_len; /* sizeof(struct mcontext_t) */ /* - * XXX FPU state is 27 * 4 bytes h/w, 1 * 4 bytes s/w (probably not - * needed here), or that + 16 * 4 bytes for emulators (probably all - * needed here). The "spare" bytes are mostly not spare. + * XXX - See and for + * the following fields. */ - int sc_fpregs[28]; /* machine state (FPU): */ - int sc_spare[17]; + int sc_fpformat; + int sc_ownedfp; + int sc_spare1[1]; + int sc_fpregs[128]; + int sc_spare2[8]; }; #define sc_sp sc_esp Index: sys/i386/include/ucontext.h =========================================================================== --- sys/i386/include/ucontext.h 2002/09/15 21:37:55 #2 +++ sys/i386/include/ucontext.h 2002/09/15 21:37:55 @@ -58,11 +58,25 @@ int mc_esp; /* machine state */ int mc_ss; - int mc_fpregs[28]; /* env87 + fpacc87 + u_long */ -#define __UC_MC_VALID 0x0001 /* mcontext register state is valid */ -#define __UC_FP_VALID 0x0002 /* FP registers have been saved */ - int mc_flags; - int __spare__[16]; + int mc_len; /* sizeof(mcontext_t) */ +#define _MC_FPFMT_NODEV 0 /* device not present or configured */ +#define _MC_FPFMT_387 1 +#define _MC_FPFMT_XMM 2 + int mc_fpformat; +#define _MC_FPOWNED_NONE 0 /* FP state not used */ +#define _MC_FPOWNED_FPU 1 /* FP state came from FPU */ +#define _MC_FPOWNED_PCB 2 /* FP state came from PCB */ + int mc_ownedfp; + int mc_spare1[1]; /* align next field to 16 bytes */ + int mc_fpstate[128]; /* must be multiple of 16 bytes */ + int mc_spare2[8]; } mcontext_t; +#ifdef _KERNEL +struct thread; + +void get_mcontext(struct thread *td, mcontext_t *mcp); +int set_mcontext(struct thread *td, const mcontext_t *mcp); +#endif + #endif /* !_MACHINE_UCONTEXT_H_ */ Index: sys/i386/isa/npx.c =========================================================================== --- sys/i386/isa/npx.c 2002/09/15 21:37:55 #25 +++ sys/i386/isa/npx.c 2002/09/15 21:37:55 @@ -74,6 +74,7 @@ #include #include #include +#include #ifndef SMP #include @@ -151,17 +152,11 @@ (cpu_fxsr ? \ (thread)->td_pcb->pcb_save.sv_xmm.sv_env.en_sw : \ (thread)->td_pcb->pcb_save.sv_87.sv_env.en_sw) -#define GET_FPU_EXSW_PTR(pcb) \ - (cpu_fxsr ? \ - &(pcb)->pcb_save.sv_xmm.sv_ex_sw : \ - &(pcb)->pcb_save.sv_87.sv_ex_sw) #else /* CPU_ENABLE_SSE */ #define GET_FPU_CW(thread) \ (thread->td_pcb->pcb_save.sv_87.sv_env.en_cw) #define GET_FPU_SW(thread) \ (thread->td_pcb->pcb_save.sv_87.sv_env.en_sw) -#define GET_FPU_EXSW_PTR(pcb) \ - (&(pcb)->pcb_save.sv_87.sv_ex_sw) #endif /* CPU_ENABLE_SSE */ typedef u_char bool_t; @@ -190,6 +185,8 @@ static volatile u_int npx_traps_while_probing; #endif +static union savefpu npx_cleanstate; +static bool_t npx_cleanstate_ready; static bool_t npx_ex16; static bool_t npx_exists; static bool_t npx_irq13; @@ -461,6 +458,7 @@ device_t dev; { int flags; + register_t s; if (resource_int_value("npx", 0, "flags", &flags) != 0) flags = 0; @@ -497,6 +495,14 @@ } npxinit(__INITIAL_NPXCW__); + if (npx_cleanstate_ready == 0) { + s = intr_disable(); + stop_emulating(); + fpusave(&npx_cleanstate); + start_emulating(); + npx_cleanstate_ready = 1; + intr_restore(s); + } #ifdef I586_CPU_XXX if (cpu_class == CPUCLASS_586 && npx_ex16 && npx_exists && timezero("i586_bzero()", i586_bzero) < @@ -543,8 +549,6 @@ fninit(); #endif fldcw(&control); - if (PCPU_GET(curpcb) != NULL) - fpusave(&PCPU_GET(curpcb)->pcb_save); start_emulating(); intr_restore(savecrit); } @@ -559,15 +563,14 @@ register_t savecrit; savecrit = intr_disable(); - if (td == PCPU_GET(fpcurthread)) + if (curthread == PCPU_GET(fpcurthread)) npxsave(&PCPU_GET(curpcb)->pcb_save); intr_restore(savecrit); #ifdef NPX_DEBUG if (npx_exists) { u_int masked_exceptions; - masked_exceptions = PCPU_GET(curpcb)->pcb_save.sv_87.sv_env.en_cw - & PCPU_GET(curpcb)->pcb_save.sv_87.sv_env.en_sw & 0x7f; + masked_exceptions = GET_FPU_CW(td) & GET_FPU_SW(td) & 0x7f; /* * Log exceptions that would have trapped with the old * control word (overflow, divide by 0, and invalid operand). @@ -581,6 +584,19 @@ #endif } +int +npxformat() +{ + + if (!npx_exists) + return (_MC_FPFMT_NODEV); +#ifdef CPU_ENABLE_SSE + if (cpu_fxsr) + return (_MC_FPFMT_XMM); +#endif + return (_MC_FPFMT_387); +} + /* * The following mechanism is used to ensure that the FPE_... value * that is passed as a trapcode to the signal handler of the user @@ -774,7 +790,6 @@ { register_t savecrit; u_short control, status; - u_long *exstat; if (!npx_exists) { printf("npxtrap: fpcurthread = %p, curthread = %p, npx_exists = %d\n", @@ -796,11 +811,7 @@ fnstsw(&status); } - exstat = GET_FPU_EXSW_PTR(curthread->td_pcb); - *exstat = status; - if (PCPU_GET(fpcurthread) != curthread) - GET_FPU_SW(curthread) &= ~0x80bf; - else + if (PCPU_GET(fpcurthread) == curthread) fnclex(); intr_restore(savecrit); return (fpetable[status & ((~control & 0x3f) | 0x40)]); @@ -813,17 +824,29 @@ * and not necessarily for every context switch, but it is too hard to * access foreign pcb's. */ + +static int err_count = 0; + int npxdna() { - u_long *exstat; + struct pcb *pcb; register_t s; + u_short control; if (!npx_exists) return (0); + if (PCPU_GET(fpcurthread) == curthread) { + printf("npxdna: fpcurthread == curthread %d times\n", + ++err_count); + stop_emulating(); + return (1); + } if (PCPU_GET(fpcurthread) != NULL) { - printf("npxdna: fpcurthread = %p, curthread = %p\n", - PCPU_GET(fpcurthread), curthread); + printf("npxdna: fpcurthread = %p (%d), curthread = %p (%d)\n", + PCPU_GET(fpcurthread), + PCPU_GET(fpcurthread)->td_proc->p_pid, + curthread, curthread->td_proc->p_pid); panic("npxdna"); } s = intr_disable(); @@ -832,22 +855,35 @@ * Record new context early in case frstor causes an IRQ13. */ PCPU_SET(fpcurthread, curthread); + pcb = PCPU_GET(curpcb); - exstat = GET_FPU_EXSW_PTR(PCPU_GET(curpcb)); - *exstat = 0; - /* - * The following frstor may cause an IRQ13 when the state being - * restored has a pending error. The error will appear to have been - * triggered by the current (npx) user instruction even when that - * instruction is a no-wait instruction that should not trigger an - * error (e.g., fnclex). On at least one 486 system all of the - * no-wait instructions are broken the same as frstor, so our - * treatment does not amplify the breakage. On at least one - * 386/Cyrix 387 system, fnclex works correctly while frstor and - * fnsave are broken, so our treatment breaks fnclex if it is the - * first FPU instruction after a context switch. - */ - fpurstor(&PCPU_GET(curpcb)->pcb_save); + if ((pcb->pcb_flags & PCB_NPXINITDONE) == 0) { + /* + * This is the first time this thread has used the FPU or + * the PCB doesn't contain a clean FPU state. Explicitly + * initialize the FPU and load the default control word. + */ + fninit(); + control = __INITIAL_NPXCW__; + fldcw(&control); + pcb->pcb_flags |= PCB_NPXINITDONE; + } else { + /* + * The following frstor may cause an IRQ13 when the state + * being restored has a pending error. The error will + * appear to have been triggered by the current (npx) user + * instruction even when that instruction is a no-wait + * instruction that should not trigger an error (e.g., + * fnclex). On at least one 486 system all of the no-wait + * instructions are broken the same as frstor, so our + * treatment does not amplify the breakage. On at least + * one 386/Cyrix 387 system, fnclex works correctly while + * frstor and fnsave are broken, so our treatment breaks + * fnclex if it is the first FPU instruction after a context + * switch. + */ + fpurstor(&pcb->pcb_save); + } intr_restore(s); return (1); @@ -888,6 +924,87 @@ PCPU_SET(fpcurthread, NULL); } +/* + * This should be called with interrupts disabled and only when the owning + * FPU thread is non-null. + */ +void +npxdrop() +{ + struct thread *td; + + td = PCPU_GET(fpcurthread); + PCPU_SET(fpcurthread, NULL); + td->td_pcb->pcb_flags &= ~PCB_NPXINITDONE; + start_emulating(); +} + +/* + * Get the state of the FPU without dropping ownership (if possible). + * It returns the FPU ownership status. + */ +int +npxgetregs(td, addr) + struct thread *td; + union savefpu *addr; +{ + register_t s; + + if (!npx_exists) + return (_MC_FPOWNED_NONE); + + if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) == 0) { + if (npx_cleanstate_ready) + bcopy(&npx_cleanstate, addr, sizeof(npx_cleanstate)); + else + bzero(addr, sizeof(*addr)); + return (_MC_FPOWNED_NONE); + } + + s = intr_disable(); + if (curthread == PCPU_GET(fpcurthread)) { + fpusave(addr); +#ifdef CPU_ENABLE_SSE + if (!cpu_fxsr) +#endif + /* + * fnsave initializes the FPU and destroys whatever + * context it contains. Make sure the FPU owner + * starts with a clean state next time. + */ + npxdrop(); + intr_restore(s); + return (_MC_FPOWNED_FPU); + } else { + intr_restore(s); + bcopy(&td->td_pcb->pcb_save, addr, sizeof(*addr)); + return (_MC_FPOWNED_PCB); + } +} + +/* + * Set the state of the FPU. + */ +void +npxsetregs(td, addr) + struct thread *td; + union savefpu *addr; +{ + register_t s; + + if (!npx_exists) + return; + + s = intr_disable(); + if (curthread == PCPU_GET(fpcurthread)) { + fpurstor(addr); + intr_restore(s); + } else { + intr_restore(s); + bcopy(addr, &td->td_pcb->pcb_save, sizeof(*addr)); + } +} + static void fpusave(addr) union savefpu *addr; Index: sys/kern/kern_exit.c =========================================================================== --- sys/kern/kern_exit.c 2002/09/15 21:37:55 #45 +++ sys/kern/kern_exit.c 2002/09/15 21:37:55 @@ -204,8 +204,6 @@ p->p_flag |= P_WEXIT; PROC_UNLOCK(p); - if (td->td_kse->ke_mdstorage) - cpu_free_kse_mdstorage(td->td_kse); /* Are we a task leader? */ PROC_LOCK(p); Index: sys/kern/kern_fork.c =========================================================================== --- sys/kern/kern_fork.c 2002/09/15 21:37:55 #47 +++ sys/kern/kern_fork.c 2002/09/15 21:37:55 @@ -488,8 +488,6 @@ bcopy(&p1->p_startcopy, &p2->p_startcopy, (unsigned) RANGEOF(struct proc, p_startcopy, p_endcopy)); - bcopy(&td->td_kse->ke_startcopy, &ke2->ke_startcopy, - (unsigned) RANGEOF(struct kse, ke_startcopy, ke_endcopy)); bcopy(&td->td_startcopy, &td2->td_startcopy, (unsigned) RANGEOF(struct thread, td_startcopy, td_endcopy)); bcopy(&td->td_ksegrp->kg_startcopy, &kg2->kg_startcopy, Index: sys/kern/kern_proc.c =========================================================================== --- sys/kern/kern_proc.c 2002/09/15 21:37:55 #53 +++ sys/kern/kern_proc.c 2002/09/15 21:37:55 @@ -298,12 +298,24 @@ int kse_yield(struct thread *td, struct kse_yield_args *uap) { + struct thread *td2; + + /* KSE-enabled processes only, please. */ + if ((td->td_proc->p_flag & P_KSES) == 0) + return (EINVAL); + + /* Don't discard the last thread. */ + td2 = FIRST_THREAD_IN_PROC(td->td_proc); + KASSERT(td2 != NULL, ("kse_yield: no threads in our proc")); + if (TAILQ_NEXT(td, td_plist) == NULL) + return (EINVAL); + /* Abandon thread. */ PROC_LOCK(td->td_proc); mtx_lock_spin(&sched_lock); thread_exit(); /* NOTREACHED */ - return(0); + return (0); } int kse_wakeup(struct thread *td, struct kse_wakeup_args *uap) @@ -364,11 +376,9 @@ mtx_lock_spin(&sched_lock); mi_switch(); /* Save current registers to PCB. */ mtx_unlock_spin(&sched_lock); - newkse->ke_upcall = mbx.kmbx_upcall; - newkse->ke_stackbase = mbx.kmbx_stackbase; - newkse->ke_stacksize = mbx.kmbx_stacksize; newkse->ke_mailbox = uap->mbx; - cpu_save_upcall(td, newkse); + newkse->ke_upcall = mbx.km_func; + bcopy(&mbx.km_stack, &newkse->ke_stack, sizeof(stack_t)); /* Note that we are the returning syscall */ td->td_retval[0] = 0; td->td_retval[1] = 0; @@ -850,6 +860,13 @@ } if (p->p_state != PRS_ZOMBIE) { td = FIRST_THREAD_IN_PROC(p); + if (td == NULL) { + /* XXXKSE: This should never happen. */ + printf("fill_kinfo_proc(): pid %d has no threads!\n", + p->p_pid); + mtx_unlock_spin(&sched_lock); + return; + } if (!(p->p_flag & P_KSES)) { if (td->td_wmesg != NULL) { strncpy(kp->ki_wmesg, td->td_wmesg, Index: sys/kern/kern_sig.c =========================================================================== --- sys/kern/kern_sig.c 2002/09/15 21:37:55 #65 +++ sys/kern/kern_sig.c 2002/09/15 21:37:55 @@ -1860,6 +1860,9 @@ p->p_code = 0; p->p_sig = 0; } + if (p->p_flag & P_KSES) + if (signal_upcall(p, sig)) + return; (*p->p_sysent->sv_sendsig)(action, sig, &returnmask, code); } } Index: sys/kern/kern_thread.c =========================================================================== --- sys/kern/kern_thread.c 2002/09/15 21:37:55 #25 +++ sys/kern/kern_thread.c 2002/09/15 21:37:55 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -66,7 +67,7 @@ SYSCTL_INT(_kern_threads, OID_AUTO, oiks, CTLFLAG_RW, &oiks_debug, 0, "OIKS thread debug"); -static int max_threads_per_proc = 4; +static int max_threads_per_proc = 10; SYSCTL_INT(_kern_threads, OID_AUTO, max_per_proc, CTLFLAG_RW, &max_threads_per_proc, 0, "Limit on threads per proc"); @@ -162,6 +163,39 @@ } /* + * Fill a ucontext_t with a thread's context information. + * + * This is an analogue to getcontext(3). + */ +void +thread_getcontext(struct thread *td, ucontext_t *uc) +{ + + get_mcontext(td, &uc->uc_mcontext); + uc->uc_sigmask = td->td_proc->p_sigmask; +} + +/* + * Set a thread's context from a ucontext_t. + * + * This is an analogue to setcontext(3). + */ +int +thread_setcontext(struct thread *td, ucontext_t *uc) +{ + int ret; + + ret = set_mcontext(td, &uc->uc_mcontext); + if (ret == 0) { + SIG_CANTMASK(uc->uc_sigmask); + PROC_LOCK(td->td_proc); + td->td_proc->p_sigmask = uc->uc_sigmask; + PROC_UNLOCK(td->td_proc); + } + return (ret); +} + +/* * Initialize global thread allocation resources. */ void @@ -190,8 +224,8 @@ mtx_unlock_spin(&zombie_thread_lock); } -/* - * reap any zombie threads. +/* + * Reap zombie threads. */ void thread_reap(void) @@ -281,18 +315,28 @@ void *addr1; void *addr2; int error; + ucontext_t uc; #ifdef __ia64__ td2_mbx = 0; /* pacify gcc (!) */ #endif - /* Export the register contents. */ - error = cpu_export_context(td); + /* Export the user/machine context. */ + error = copyin((caddr_t)td->td_mailbox + + offsetof(struct thread_mailbox, tm_context), + &uc, + sizeof(ucontext_t)); + if (error == 0) { + thread_getcontext(td, &uc); + error = copyout(&uc, (caddr_t)td->td_mailbox + + offsetof(struct thread_mailbox, tm_context), + sizeof(ucontext_t)); + } ke = td->td_kse; addr1 = (caddr_t)ke->ke_mailbox - + offsetof(struct kse_mailbox, kmbx_completed_threads); + + offsetof(struct kse_mailbox, km_completed); addr2 = (caddr_t)td->td_mailbox - + offsetof(struct thread_mailbox , next_completed); + + offsetof(struct thread_mailbox , tm_next); /* Then link it into it's KSE's list of completed threads. */ if (!error) { error = td2_mbx = fuword(addr1); @@ -422,9 +466,7 @@ } /* - * Set up the upcall pcb in either a given thread or a new one - * if none given. Use the upcall for the given KSE - * XXXKSE possibly fix cpu_set_upcall() to not need td->td_kse set. + * Create a thread and schedule it for upcall on the KSE given. */ struct thread * thread_schedule_upcall(struct thread *td, struct kse *ke) @@ -447,7 +489,18 @@ bcopy(&td->td_startcopy, &td2->td_startcopy, (unsigned) RANGEOF(struct thread, td_startcopy, td_endcopy)); thread_link(td2, ke->ke_ksegrp); - cpu_set_upcall(td2, ke->ke_pcb); + cpu_set_upcall(td2, td->td_pcb); + bcopy(td->td_frame, td2->td_frame, sizeof(struct trapframe)); + /* + * The user context for this thread is selected when we choose + * a KSE and return to userland on it. All we need do here is + * note that the thread exists in order to perform an upcall. + * + * Since selecting a KSE to perform the upcall involves locking + * that KSE's context to our upcall, its best to wait until the + * last possible moment before grabbing a KSE. We do this in + * userret(). + */ td2->td_ucred = crhold(td->td_ucred); td2->td_flags = TDF_UNBOUND|TDF_UPCALLING; TD_SET_CAN_RUN(td2); @@ -456,139 +509,201 @@ } /* - * The extra work we go through if we are a threaded process when we - * return to userland + * Schedule an upcall to notify a KSE process recieved signals. + * + * XXX - Modifying a sigset_t like this is totally bogus. + */ +struct thread * +signal_upcall(struct proc *p, int sig) +{ + struct thread *td, *td2; + struct kse *ke; + sigset_t ss; + int error; + + PROC_LOCK_ASSERT(p, MA_OWNED); + + td = FIRST_THREAD_IN_PROC(p); + ke = td->td_kse; + PROC_UNLOCK(p); + error = copyin(&ke->ke_mailbox->km_sigscaught, &ss, sizeof(sigset_t)); + PROC_LOCK(p); + if (error) + return (NULL); + SIGADDSET(ss, sig); + PROC_UNLOCK(p); + error = copyout(&ss, &ke->ke_mailbox->km_sigscaught, sizeof(sigset_t)); + PROC_LOCK(p); + if (error) + return (NULL); + mtx_lock_spin(&sched_lock); + td2 = thread_schedule_upcall(td, ke); + mtx_unlock_spin(&sched_lock); + return (td2); +} + +/* + * Consider whether or not an upcall should be made, and update the + * TDF_UPCALLING flag appropriately. + * + * This function is called when the current thread had been bound to a user + * thread that performed a syscall that blocked, and is now returning. + * Got that? syscall -> msleep -> wakeup -> syscall_return -> us. + * + * This thread will be returned to the UTS in its mailbox as a completed + * thread. We need to decide whether or not to perform an upcall now, + * or simply queue the thread for later. + * + * XXXKSE Future enhancement: We could also return back to + * the thread if we haven't had to do an upcall since then. + * If the KSE's copy is == the thread's copy, and there are + * no other completed threads. + */ +static int +thread_consider_upcalling(struct proc *p, struct ksegrp *kg, struct kse *ke, + struct thread *td, struct trapframe *frame) +{ + int error; + + /* + * Save the thread's context, and link it + * into the KSE's list of completed threads. + */ + error = thread_export_context(td); + td->td_mailbox = NULL; + if (error) + /* + * Failing to do the KSE operation just defaults + * back to synchonous operation, so just return from + * the syscall. + */ + return (error); + + /* + * Decide whether to perfom an upcall now. + */ + /* Make sure there are no other threads waiting to run. */ + if (TAILQ_FIRST(&kg->kg_runq)) { + /* + * Another thread in this KSEG needs to run. + * Switch to it instead of performing an upcall, + * abondoning this thread. Perform the upcall + * later; discard this thread for now. + * + * XXXKSE - As for the other threads to run; + * we COULD rush through all the threads + * in this KSEG at this priority, or we + * could throw the ball back into the court + * and just run the highest prio kse available. + * What is OUR priority? The priority of the highest + * sycall waiting to be returned? + * For now, just let another KSE run (easiest). + * + * XXXKSE Future enhancement: Shove threads in this + * state onto a list of completed threads hanging + * off the KSEG. Then, collect them before performing + * an upcall. This way, we don't commit to an upcall + * on a particular KSE, but report completed threads on + * the next upcall to any KSE in this KSEG. + * + */ + PROC_LOCK(p); + mtx_lock_spin(&sched_lock); + thread_exit(); /* Abandon current thread. */ + /* NOTREACHED */ + } else + /* + * Perform an upcall now. + * + * XXXKSE - Assumes we are going to userland, and not + * nested in the kernel. + */ + td->td_flags |= TDF_UPCALLING; + return (0); +} + +/* + * The extra work we go through if we are a threaded process when we + * return to userland. * * If we are a KSE process and returning to user mode, check for * extra work to do before we return (e.g. for more syscalls * to complete first). If we were in a critical section, we should * just return to let it finish. Same if we were in the UTS (in - * which case we will have no thread mailbox registered). The only - * traps we suport will have set the mailbox. We will clear it here. + * which case the mailbox's context's busy indicator will be set). + * The only traps we suport will have set the mailbox. + * We will clear it here. */ int thread_userret(struct proc *p, struct ksegrp *kg, struct kse *ke, struct thread *td, struct trapframe *frame) { - int error = 0; + int error; + /* + * Ensure that we have a spare thread available. + */ if (ke->ke_tdspare == NULL) { + mtx_lock(&Giant); ke->ke_tdspare = thread_alloc(); + mtx_unlock(&Giant); + } + + /* + * Bound threads need no additional work. + */ + if ((td->td_flags & TDF_UNBOUND) == 0) + return (0); + error = 0; + + /* + * Decide whether or not we should perform an upcall now. + */ + if (((td->td_flags & TDF_UPCALLING) == 0) && td->td_mailbox) { + error = thread_consider_upcalling(p, kg, ke, td, frame); + if (error != 0) + /* + * Failing to do the KSE operation just defaults + * back to synchonous operation, so just return from + * the syscall. + */ + goto cont; } - if (td->td_flags & TDF_UNBOUND) { + if (td->td_flags & TDF_UPCALLING) { /* - * Are we returning from a thread that had a mailbox? - * - * XXX Maybe this should be in a separate function. + * There is no more work to do and we are going to ride + * this thead/KSE up to userland. */ - if (((td->td_flags & TDF_UPCALLING) == 0) && td->td_mailbox) { - /* - * [XXXKSE Future enhancement] - * We could also go straight back to the syscall - * if we never had to do an upcall since then. - * If the KSE's copy is == the thread's copy.. - * AND there are no other completed threads. - */ - /* - * We will go back as an upcall or go do another thread. - * Either way we need to save the context back to - * the user thread mailbox. - * So the UTS can restart it later. - */ - error = thread_export_context(td); - td->td_mailbox = NULL; - if (error) { - /* - * Failing to do the KSE - * operation just defaults operation - * back to synchonous operation. - */ - goto cont; - } + CTR3(KTR_PROC, "userret: upcall thread %p (pid %d, %s)", + td, p->p_pid, p->p_comm); - if (TAILQ_FIRST(&kg->kg_runq)) { - /* - * Uh-oh.. don't return to the user. - * Instead, switch to the thread that - * needs to run. The question is: - * What do we do with the thread we have now? - * We have put the completion block - * on the kse mailbox. If we had more energy, - * we could lazily do so, assuming someone - * else might get to userland earlier - * and deliver it earlier than we could. - * To do that we could save it off the KSEG. - * An upcalling KSE would 'reap' all completed - * threads. - * Being in a hurry, we'll do nothing and - * leave it on the current KSE for now. - * - * As for the other threads to run; - * we COULD rush through all the threads - * in this KSEG at this priority, or we - * could throw the ball back into the court - * and just run the highest prio kse available. - * What is OUR priority? - * the priority of the highest sycall waiting - * to be returned? - * For now, just let another KSE run (easiest). - */ - PROC_LOCK(p); - mtx_lock_spin(&sched_lock); - thread_exit(); /* Abandon current thread. */ - /* NOTREACHED */ - } else { /* if (number of returning syscalls = 1) */ - /* - * Swap our frame for the upcall frame. - * - * XXXKSE Assumes we are going to user land - * and not nested in the kernel - */ - td->td_flags |= TDF_UPCALLING; - } - } /* - * This is NOT just an 'else' clause for the above test... + * Set user context to the UTS. */ - if (td->td_flags & TDF_UPCALLING) { - CTR3(KTR_PROC, "userret: upcall thread %p (pid %d, %s)", - td, p->p_pid, p->p_comm); + cpu_set_upcall_kse(td, ke); + if (error) /* - * Make sure that it has the correct frame loaded. - * While we know that we are on the same KSEGRP - * as we were created on, we could very easily - * have come in on another KSE. We therefore need - * to do the copy of the frame after the last - * possible switch() (the one above). + * Failing to do the KSE operation just defaults + * back to synchonous operation, so just return from + * the syscall. */ - bcopy(ke->ke_frame, frame, sizeof(struct trapframe)); - - /* - * Decide what we are sending to the user - * upcall sets one argument. The address of the mbox. - */ - cpu_set_args(td, ke); + goto cont; - /* - * There is no more work to do and we are going to ride - * this thead/KSE up to userland. Make sure the user's - * pointer to the thread mailbox is cleared before we - * re-enter the kernel next time for any reason.. - * We might as well do it here. - */ - td->td_flags &= ~TDF_UPCALLING; /* Hmmmm. */ - error = suword((caddr_t)td->td_kse->ke_mailbox + - offsetof(struct kse_mailbox, kmbx_current_thread), - 0); - } /* - * Stop any chance that we may be separated from - * the KSE we are currently on. This is "biting the bullet", - * we are committing to go to user space as as THIS KSE here. + * Set state and mailbox. */ + td->td_flags &= ~TDF_UPCALLING; + error = suword((caddr_t)td->td_kse->ke_mailbox + + offsetof(struct kse_mailbox, km_curthread), + 0); + } cont: - td->td_flags &= ~TDF_UNBOUND; - } + /* + * Stop any chance that we may be separated from + * the KSE we are currently on. This is "biting the bullet", + * we are committing to go to user space as as this KSE here. + */ + td->td_flags &= ~TDF_UNBOUND; /* Bind to this user thread. */ return (error); } Index: sys/notes =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- sys/notes Sun Sep 15 21:39:04 2002 *************** *** 0 **** --- 1,187 ---- + This file is to keep notes on what is going on re: KSEing the kernel. + + [STOPPED/SUSPEND] + When a process is 'stopped', threads that are in a system call + and may hold resources must be allowed to complete, however from the point of + view of the rest of the world, the process is stopped if we do not allow + any threads to go to user land. This means that we can implement 'stop' + by taking any threads that wish to go to userland, and hanging them off a + special suspended queue, and NOT letting them go to userland. + + [done] + + -------------------------------- + More STOPs + There are 4 basic kinds of stop that must be dealt with: + 1/ Job control (e.g. ^Z) a process can be considered stopped if + ((p->p_userthreads == 0) && (p->p_flag & P_STOPPED_SGNL)) + i.e no user threads are allowed and they are presenlty all not there. + + [p_userthreads does not yet exist] + [presently use p_numthreads == p_suspcount] + + 2/ Singlethreading: A process can generally only be considered safely + singlethreaded when the state of all other threads is KNOWN to be + "suspended". This can be needed for safe completion of some + syscalls (e.g. fork) however the variant needed for exit and + exec must force the other threads to actually die. + This actually must occur in a safe place, e.g. the SUSPEND checkpoint. + The singlethreading thread will itself suspend until all other threads + are suspended. thus the completion state is p_numthreads == p_suspcount. + Either p_numthreads or p_suspcount can be chenged to reach this condition. + + It is possible that for fork() a NON_KILLING singlethreading need only + keep the threads out of userspace if there were no effort to + restart the threads in the child. + [no probably they need to be suspended so that the child gets + a consistent image of memeory][hmmm maybe not.. think more] + + The child would need to + complete all the context blocks in it's own space with a + set of known failure codes, before completing the first upcall. + The parent would be allowed to have it's threads in any state, suspended + or otherwise as it wouldn't matter.(Alternatively the states could be put + back to "RESTART" mode (PC backed up). Given this, line of thought, + then the state may be reached when none of the other threads are in + userland. + + 3/ TRACE process suspension. This is required when attaching to a + process or in some debugging situations. All threads must be excluded from + userspace until the state is cleared. It may be that a single thread is + allowed to continue in a single-stepping manner. + + 4/ TRACE thread SSTEP. If the rest of the threads are allowed to continue, + then Only the specified thread is forced to single step. While not exactly a + STOPPING mode, it requires the same notification of the parent that would + occur when the TRACE suspencion is completed + + 4A/ Embedded breakpoint: the thread is stopped. WHether the rest of the + threads are stopped is dependent on what is required. + + ----------------------- + + potential SCREWUP: + an UPCALL MUST be deliverd by the KSE for whome the frame was set up for + this means that ther emust not be another switch() after the frame is loaded + and control passes to userland. As a corollary, threads that are in the UTS + must not lose their KSE if they are pre-empted by an interrupt or something. + Thus they must not take part in the 'assigned thread' system. Such a thread + and KSE combination becomes 'synchronous'. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^VIP + [Done (in part) see "BOUND" mode (TDF_UNBOUND)] + + SWAPPING + In swapping, the function faultin() in vm_glue.c is the + one to start investigations with. + pmap_swapin_proc() and pmap_swapin_thread() are used and are synchronous. + Thus a processes threads are either all-in or potentially all-out + of memory. The act of swapping a process in, ensures that they are + all in memory. [CHECK THIS] + + Note cached threads must be unswapped and in fact I believe that can only + be so in this code. Thread-free() is only called as part of + the thread_exit() sequence and is thus always a 'suicide'. + The thread cannot be swapped out except as part of a process. + + In scheduler() we currently check the kseg's priority + but we should switch this to the thread's priority as soon + as we start using it. It looks like the priority mentioned here has no + relationship to the priority of the thread itself for CPU. + + + SINGLE_THREADING + This is a variant of SSTOP/SUSPEND. where one thread is allowed to continue + operation. (since it will never enter userland in this state + that is normal). The difference is that the master thread is awoken + when all other threads have become suspended (or exited) + PCATCH sleeping threads may be awoken as if by a signal. + In a variant, When all threads are considered blocked for the purposes of + P_STOPPED_TRAP, the parent process needs to be notified. + + EXIT + exit1 needs to set up the single threading. + Set a flag that makes all threads entering or exiting the kernel + abort. Also examined at other points (e.g. tsleep)/wake etc. + Possibly send a signal-like wakeup to all PCATCH sleeping threads. + exiting needs to have a flag rather than be a state. The state is RUNNING + (usually). ALready exists.. P_WEXIT. The single-threading mode may be enough. + **The exit's own KSE should be freed to exit other threads while it waits** + + [This brings up the whole concept of KSE BORROWING or LENDING.. see later] + + FORK. + + The grand plan... + The singlethreading pointer points to the only thread that can act normally + at this time. All other threads will proceed to the userland interface + and write out results and return values asap. They may even abort + their syscall in order to do so. The reason for this is to make it possible for + fork to safely get a state where only the forking thread has kernel state + and all the others are safely 'duplicatable' in userland. This should + allow a threaded process to safely fork(); + Threads already in userland will be interrupted and will be forced to + write their state back. Syscalls that occur will not proceed + but will be written back in a 'restart' form. The fork should WAIT until + there are no userland threads and then continue. There is no need to awake + sleeping threads + + Maybe All threads write out their status and then 'suspend'. No upcalls + are generated while the singlethreading is in progress. This is very similar + to the 'suspended' mode.. maybe they are the same. In fact probably + you want them to suspend BEFORE they write out their status because that + would perterb the parent address space that you are duplicating, + The results of a read() are ok, but the tcbs shouldn't be filled out and + moved to the completed queue, because the child needs to do them differently. + + + + SIGNALS + Signal processing needs to be broken into two parts: + + A part that works per process. It queues the signals, and gets them + when a process passes to userland. + + A part that works per thread. It's job is to wake sleeping threads + and to handle the signal when the thread passes to user land. + In a KSE process, it sets the thread information into the + KSE mailbox, or maybe a process mailbox. + In a KSE system we need to pass signal info to a UTS. + + + ================== == things to look at:== ========================== + + + At the moment the signal code is TOTALLY BROKEN!! + get back to it!!! + + + We need an "adjustrunqueue' call. + + use it whereever you see: + { + remrunqueue(td); + setrunqueue(td); + } + + Usually this is done with a priority change.. + should really take the new peiority as an argument. + + + All the sleeptime stats are screwed up between threads, KSEs and KSEGRPs + + WAKEUP/setrunqueue + in wakeup() + in the !INMEM case, I've probably broken it by + not marking the thread to be runnable. + Need to work out how to label a thread as "Potentially runnable" + or "Wants to run". We no longer set TDS_RUNQ on threads athat ar not + actually on the run queue. This will need to be used for + swapped out processes to decide which threads are to be + restarted. it is still possible that the threads be on the run queu and the + KSEs not.... + + [ke_slptime] + ke_slptime is completely bogus. + cannot be touched during wakeup as the thread may not have a KSE. + find out what it's for and think of a better way of doing it. + Index: sys/sys/kse.h =========================================================================== --- sys/sys/kse.h 2002/09/15 21:37:55 #3 +++ sys/sys/kse.h 2002/09/15 21:37:55 @@ -9,7 +9,7 @@ * are met: * 1. Redistributions of source code must retain the above copyright * notice(s), this list of conditions and the following disclaimer as - * the first lines of this file unmodified other than the possible + * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in the @@ -32,8 +32,11 @@ #ifndef SYS_KSE_H #define SYS_KSE_H + #include -/* +#include + +/* * This file defines the structures needed for communication between * the userland and the kernel when running a KSE-based threading system. * The only programs that should see this file are the UTS and the kernel. @@ -41,38 +44,41 @@ struct kse_mailbox; typedef void kse_fn_t(struct kse_mailbox *mbx); -/* - * Each userland thread has one of these buried in it's - * Thread control structure somewhere. +/* + * Thread mailbox. + * + * This describes a user thread to the kernel scheduler. */ -struct thread_mailbox -{ - struct thread_mailbox *next_completed; - unsigned int flags; - void *UTS_handle; /* The UTS can use this for anything */ - union kse_td_ctx ctx; /* thread's saved context goes here. */ +struct thread_mailbox { + ucontext_t tm_context; /* User and machine context */ + unsigned int tm_flags; /* Thread flags */ + struct thread_mailbox *tm_next; /* Next thread in list */ + void *tm_udata; /* For use by the UTS */ + int tm_spare[8]; }; -/* - * You need to supply one of these as the argument to the - * kse_new() system call. +/* + * KSE mailbox. + * + * Cummunication path between the UTS and the kernel scheduler specific to + * a single KSE. */ -struct kse_mailbox -{ - kse_fn_t *kmbx_upcall; - char *kmbx_stackbase; - unsigned long int kmbx_stacksize; - struct thread_mailbox *kmbx_current_thread; - struct thread_mailbox *kmbx_completed_threads; - unsigned int kmbx_flags; - void *kmbx_UTS_handle; /* UTS can use this for anything */ +struct kse_mailbox { + struct thread_mailbox *km_curthread; /* Currently running thread */ + struct thread_mailbox *km_completed; /* Threads back from kernel */ + sigset_t km_sigscaught; /* Caught signals */ + unsigned int km_flags; /* KSE flags */ + void *km_func; /* UTS function */ + stack_t km_stack; /* UTS context */ + void *km_udata; /* For use by the UTS */ + int tm_spare[8]; }; -#define KEMBXF_CRITICAL 0x00000001 -struct kse_global_mailbox -{ - unsigned int flags; -}; -#define GMBXF_CRITICAL 0x00000001 +#ifndef _KERNEL +int kse_exit(void); +int kse_wakeup(void); +int kse_new(struct kse_mailbox *, int); +int kse_yield(void); +#endif #endif Index: sys/sys/proc.h =========================================================================== --- sys/sys/proc.h 2002/09/15 21:37:55 #78 +++ sys/sys/proc.h 2002/09/15 21:37:55 @@ -55,6 +55,7 @@ #else #include #endif +#include #include #include /* Machine-dependent proc substruct. */ @@ -282,7 +283,7 @@ LIST_HEAD(, mtx) td_contested; /* (j) Contested locks. */ struct lock_list_entry *td_sleeplocks; /* (k) Held sleep locks. */ int td_intr_nesting_level; /* (k) Interrupt recursion. */ - void *td_mailbox; /* The userland mailbox address. */ + struct thread_mailbox *td_mailbox; /* the userland mailbox address */ struct ucred *td_ucred; /* (k) Reference to credentials. */ void (*td_switchin)(void); /* (k) Switchin special func. */ u_int td_critnest; /* (k) Critical section nest level. */ @@ -421,21 +422,13 @@ KES_UNQUEUED, /* in transit */ KES_THREAD /* slaved to thread state */ } ke_state; /* (j) S* process status. */ - void *ke_mailbox; /* the userland mailbox address */ + struct kse_mailbox *ke_mailbox; /* the userland mailbox address */ + stack_t ke_stack; + void *ke_upcall; struct thread *ke_tdspare; /* spare thread for upcalls */ #define ke_endzero ke_dummy -#define ke_startcopy ke_endzero - u_char ke_dummy; -#define ke_endcopy ke_mdstorage - - void *ke_upcall; - void *ke_stackbase; - u_long ke_stacksize; - void *ke_mdstorage; /* where we store the pcb and frame */ - struct pcb *ke_pcb; /* the pcb saved for the upcalls */ - struct trapframe *ke_frame; /* the upcall trapframe */ - void *mdkse; /* eventually you load from this in */ + char ke_dummy; /* switch for our extension PCB x86 */ }; /* flags kept in ke_flags */ @@ -898,11 +891,8 @@ void kse_free(struct kse *td); struct thread *thread_alloc(void); void thread_free(struct thread *td); -int cpu_export_context(struct thread *td); -void cpu_free_kse_mdstorage(struct kse *kse); -void cpu_save_upcall(struct thread *td, struct kse *newkse); -void cpu_set_args(struct thread *, struct kse *); void cpu_set_upcall(struct thread *td, void *pcb); +void cpu_set_upcall_kse(struct thread *td, struct kse *ke); void cpu_thread_exit(struct thread *); void cpu_thread_setup(struct thread *td); void kse_reassign(struct kse *ke); @@ -910,11 +900,14 @@ void ksegrp_link(struct ksegrp *kg, struct proc *p); int kserunnable(void); void make_kse_runnable(struct kse *ke); +struct thread *signal_upcall(struct proc *p, int sig); void thread_exit(void) __dead2; int thread_export_context(struct thread *td); void thread_link(struct thread *td, struct ksegrp *kg); void thread_reap(void); struct thread *thread_schedule_upcall(struct thread *td, struct kse *ke); +int thread_setcontext(struct thread *td, ucontext_t *uc); +void thread_getcontext(struct thread *td, ucontext_t *uc); int thread_single(int how); #define SINGLE_NO_EXIT 0 /* values for 'how' */ #define SINGLE_EXIT 1 Index: sys/sys/ucontext.h =========================================================================== --- sys/sys/ucontext.h 2002/09/15 21:37:55 #3 +++ sys/sys/ucontext.h 2002/09/15 21:37:55 @@ -31,6 +31,7 @@ #ifndef _SYS_UCONTEXT_H_ #define _SYS_UCONTEXT_H_ +#include #include typedef struct __ucontext { @@ -47,7 +48,9 @@ struct __ucontext *uc_link; stack_t uc_stack; - int __spare__[8]; + int uc_flags; +#define UCF_SWAPPED 0x00000001 /* Used by swapcontext(3). */ + int __spare__[4]; } ucontext_t; #ifndef _KERNEL @@ -57,6 +60,7 @@ int getcontext(ucontext_t *); int setcontext(const ucontext_t *); void makecontext(ucontext_t *, void (*)(void), int, ...); +int signalcontext(ucontext_t *, int, __sighandler_t *); int swapcontext(ucontext_t *, const ucontext_t *); __END_DECLS Index: tools/KSE/uts/Makefile =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- tools/KSE/uts/Makefile Sun Sep 15 21:39:04 2002 *************** *** 0 **** --- 1,6 ---- + PROG= uts + NOMAN= + CFLAGS+= -g + SRCS= context.S uts.c + + .include Index: tools/KSE/uts/context.S =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- tools/KSE/uts/context.S Sun Sep 15 21:39:04 2002 *************** *** 0 **** --- 1,146 ---- + /* + * Copyright (c) 2001 Daniel Eischen . + * 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. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN 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 AUTHOR 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 + __FBSDID("$FreeBSD: src/lib/libc/i386/gen/getcontext.S,v 1.2 2002/03/23 02:44:18 obrien Exp $"); + + /* + * Where do we define these? + */ + #define MC_SIZE 640 /* sizeof mcontext_t */ + #define UC_MC_OFFSET 16 /* offset to mcontext from ucontext */ + #define UC_MC_LEN_OFFSET 96 /* offset to mc_len from mcontext */ + #define MC_LEN_OFFSET 80 /* offset to mc_len from mcontext */ + #define MC_FP_REGS_OFFSET 96 /* offset to FP regs from mcontext */ + #define MC_FP_CW_OFFSET 96 /* offset to FP control word */ + #define MC_OWNEDFP_OFFSET 88 /* offset to mc_ownedfp from mcontext */ + #define KM_STACK_SP_OFFSET 32 /* offset to km_stack.ss_sp */ + #define KM_STACK_SIZE_OFFSET 36 /* offset to km_stack.ss_sp */ + #define KM_FUNC_OFFSET 28 /* offset to km_func */ + + /* + * int uts_to_thread(thread_mailbox *tdp, thread_mailbox **curthreadp); + * + * Does not return on success, returns -1 otherwise. + */ + ENTRY(uts_to_thread) + movl 4(%esp), %edx /* get address of thread_mailbox */ + /* .. ucontext_t is at offset 0 */ + cmpl $0, %edx /* check for null pointer */ + jne 1f + movl $-1, %eax + jmp 5f + 1: cmpl $MC_SIZE, UC_MC_LEN_OFFSET(%edx) /* is context valid? */ + je 2f + movl $-1, %eax /* bzzzt, invalid context */ + jmp 5f + 2: movl 8(%esp), %eax /* get address of curthreadp */ + movl %edx, (%eax) /* we're now the current thread */ + /* + * From here on, we don't touch the old stack. + */ + addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ + movl 4(%edx), %gs + movl 8(%edx), %fs + movl 12(%edx), %es + movl 16(%edx), %ds + movl 76(%edx), %ss + movl 20(%edx), %edi + movl 24(%edx), %esi + movl 28(%edx), %ebp + movl 72(%edx), %esp /* switch to context defined stack */ + subl $4, %esp /* leave space for the return address */ + movl 60(%edx), %eax /* put return address at top of stack */ + movl %eax, (%esp) + cmpl $0, MC_OWNEDFP_OFFSET(%edx) /* are FP regs valid? */ + jz 3f + frstor MC_FP_REGS_OFFSET(%edx) /* restore FP regs */ + jmp 4f + 3: fninit + fldcw MC_FP_CW_OFFSET(%edx) + 4: movl 48(%edx), %eax /* restore ax, bx, cx */ + movl 36(%edx), %ebx + movl 44(%edx), %ecx + pushl 68(%edx) /* flags on stack */ + pushl 40(%edx) /* %edx on stack */ + popl %edx /* %edx off stack */ + popf /* flags off stack */ + 5: ret /* %eip off stack */ + + /* + * int thread_to_uts(thread_mailbox *tm, kse_mailbox *km); + * + * Does not return on success, returns -1 otherwise. + */ + ENTRY(thread_to_uts) + movl 4(%esp), %eax /* get address of context */ + cmpl $0, %eax /* check for null pointer */ + jne 1f + movl $-1, %eax + jmp 2f + 1: pushl %edx /* save value of edx */ + movl %eax, %edx /* get address of context */ + addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ + movl %gs, 4(%edx) + movl %fs, 8(%edx) + movl %es, 12(%edx) + movl %ds, 16(%edx) + movl %edi, 20(%edx) + movl %esi, 24(%edx) + movl %ebp, 28(%edx) + movl %ebx, 36(%edx) + movl $0, 48(%edx) /* store successful return in eax */ + popl %eax /* get saved value of edx */ + movl %eax, 40(%edx) /* save edx */ + movl %ecx, 44(%edx) + movl (%esp), %eax /* get return address */ + movl %eax, 60(%edx) /* save return address */ + movl %ss, 76(%edx) + /* + * Don't save floating point registers here. + * + * This is an explicit call to get the current context, so + * the caller is done with the floating point registers. + * Contexts formed by involuntary switches, such as signal delivery, + * have floating point registers saved by the kernel. + */ + fnstcw MC_FP_CW_OFFSET(%edx) + movl $0, MC_OWNEDFP_OFFSET(%edx) /* no FP */ + lahf /* get eflags */ + movl %eax, 68(%edx) /* store eflags */ + movl %esp, %eax /* setcontext pushes the return */ + addl $4, %eax /* address onto the top of the */ + movl %eax, 72(%edx) /* stack; account for this */ + movl $MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */ + movl 8(%esp), %edx /* get address of mailbox */ + movl KM_STACK_SP_OFFSET(%edx), %eax /* get bottom of stack */ + addl KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */ + movl %eax, %esp /* switch to the uts's stack */ + pushl %edx /* push the address of the mailbox */ + pushl KM_FUNC_OFFSET(%edx) /* .. the uts can return to itself */ + pushl KM_FUNC_OFFSET(%edx) /* push the address of the uts func */ + 2: ret + Index: tools/KSE/uts/uts.c =========================================================================== *** /dev/null Sun Sep 15 21:38:29 2002 --- tools/KSE/uts/uts.c Sun Sep 15 21:39:05 2002 *************** *** 0 **** --- 1,390 ---- + /*- + * Copyright (c) 2002 Jonathan Mini. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $P4: //depot/projects/kse/tools/KSE/uts/uts.c#8 $ + */ + + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + #include + + #undef TRACE_UTS + + #ifdef TRACE_UTS + #define UPFMT(fmt...) pfmt(#fmt) + #define UPSTR(s) pstr(s) + #define UPCHAR(c) pchar(c) + #else + #define UPFMT(fmt...) /* Nothing. */ + #define UPSTR(s) /* Nothing. */ + #define UPCHAR(c) /* Nothing. */ + #endif + + #define MAIN_STACK_SIZE (1024 * 1024) + #define THREAD_STACK_SIZE (32 * 1024) + + static struct kse_mailbox uts_mb; + static struct thread_mailbox *run_queue; + static struct thread_mailbox *aa; + + static int progress = 0; + + static void init_uts(void); + static void enter_uts(void); + static void pchar(char c); + static void pfmt(const char *fmt, ...); + static void pstr(const char *s); + static void runq_insert(struct thread_mailbox *tm); + static struct thread_mailbox *runq_remove(void); + static void thread_start(const void *func, int arg); + static void uts(struct kse_mailbox *km); + + extern int uts_to_thread(struct thread_mailbox *tdp, struct thread_mailbox **curthreadp); + + static void + nano(int len) + { + struct timespec time_to_sleep; + struct timespec time_remaining; + + time_to_sleep.tv_sec = 0; + time_to_sleep.tv_nsec = len * 10000; + nanosleep(&time_to_sleep, &time_remaining); + } + + void + aaaa(int c) + { + for (;;) { + pchar(c); + nano(1); + } + } + + static void + foof(int sig) + { + pfmt("\n[%d]\n", sig); + thread_start(aaaa, '0' + progress++); + } + + void + spin(int arg) + { + for (;;) enter_uts(); sched_yield(); + } + + /* + * Test Userland Thread Scheduler (UTS) suite for KSE. + */ + int + main(void) + { + int i; + + thread_start(spin, '.'); + // thread_start(spin); + init_uts(); + for (i = 0;1;i++) { + // if (i < 1000) + // thread_start(aaaa, 'a' + (i % 26)); + pchar('A' + (i % 26)); + nano(5); + } + pstr("\n** main() exiting **\n"); + return (EX_OK); + } + + + /* + * Enter the UTS from a thread. + */ + static void + enter_uts(void) + { + struct thread_mailbox *td; + + /* XXX: We should atomically exchange these two. */ + td = uts_mb.km_curthread; + uts_mb.km_curthread = NULL; + + thread_to_uts(td, &uts_mb); + } + + /* + * Initialise threading. + */ + static void + init_uts(void) + { + struct thread_mailbox *tm; + int mib[2]; + char *p; + size_t len; + + /* + * Create initial thread. + */ + tm = (struct thread_mailbox *)calloc(1, sizeof(struct thread_mailbox)); + + /* Throw us into its context. */ + getcontext(&tm->tm_context); + + /* Find our stack. */ + mib[0] = CTL_KERN; + mib[1] = KERN_USRSTACK; + len = sizeof(p); + if (sysctl(mib, 2, &p, &len, NULL, 0) == -1) + pstr("sysctl(CTL_KER.KERN_USRSTACK) failed.\n"); + pfmt("main() : 0x%x\n", tm); + pfmt("eip -> 0x%x\n", tm->tm_context.uc_mcontext.mc_eip); + tm->tm_context.uc_stack.ss_sp = p - MAIN_STACK_SIZE; + tm->tm_context.uc_stack.ss_size = MAIN_STACK_SIZE; + + /* + * Create KSE mailbox. + */ + p = (char *)malloc(THREAD_STACK_SIZE); + bzero(&uts_mb, sizeof(struct kse_mailbox)); + uts_mb.km_stack.ss_sp = p; + uts_mb.km_stack.ss_size = THREAD_STACK_SIZE; + uts_mb.km_func = (void *)uts; + pfmt("uts() at : 0x%x\n", uts); + pfmt("uts stack at : 0x%x - 0x%x\n", p, p + THREAD_STACK_SIZE); + + /* + * Start KSE scheduling. + */ + pfmt("kse_new() -> %d\n", kse_new(&uts_mb, 0)); + uts_mb.km_curthread = tm; + + /* + * Arrange to deliver signals via KSE. + */ + signal(SIGURG, foof); + } + + /* + * Write a single character to stdout, in a thread-safe manner. + */ + static void + pchar(char c) + { + + write(STDOUT_FILENO, &c, 1); + } + + /* + * Write formatted output to stdout, in a thread-safe manner. + * + * Recognises the following conversions: + * %c -> char + * %d -> signed int (base 10) + * %s -> string + * %u -> unsigned int (base 10) + * %x -> unsigned int (base 16) + */ + static void + pfmt(const char *fmt, ...) + { + static const char digits[16] = "0123456789abcdef"; + va_list ap; + char buf[10]; + char *s; + unsigned r, u; + int c, d; + + va_start(ap, fmt); + while ((c = *fmt++)) { + if (c == '%') { + c = *fmt++; + switch (c) { + case 'c': + pchar(va_arg(ap, int)); + continue; + case 's': + pstr(va_arg(ap, char *)); + continue; + case 'd': + case 'u': + case 'x': + r = ((c == 'u') || (c == 'd')) ? 10 : 16; + if (c == 'd') { + d = va_arg(ap, unsigned); + if (d < 0) { + pchar('-'); + u = (unsigned)(d * -1); + } else + u = (unsigned)d; + } else + u = va_arg(ap, unsigned); + s = buf; + do { + *s++ = digits[u % r]; + } while (u /= r); + while (--s >= buf) + pchar(*s); + continue; + } + } + pchar(c); + } + va_end(ap); + } + + static void + pstr(const char *s) + { + + write(STDOUT_FILENO, s, strlen(s)); + } + + /* + * Insert a thread into the run queue. + */ + static void + runq_insert(struct thread_mailbox *tm) + { + + tm->tm_next = run_queue; + run_queue = tm; + } + + /* + * Select and remove a thread from the run queue. + */ + static struct thread_mailbox * + runq_remove(void) + { + struct thread_mailbox *p, *p1; + + if (run_queue == NULL) + return (NULL); + p1 = NULL; + for (p = run_queue; p->tm_next != NULL; p = p->tm_next) + p1 = p; + if (p1 == NULL) + run_queue = NULL; + else + p1->tm_next = NULL; + return (p); + } + + /* + * Userland thread scheduler. + */ + static void + uts(struct kse_mailbox *km) + { + struct thread_mailbox *tm, *p; + int ret, i; + + UPSTR("\n--uts() start--\n"); + UPFMT("mailbox -> %x\n", km); + + /* + * Insert any processes back from being blocked + * in the kernel into the run queue. + */ + p = km->km_completed; + uts_mb.km_completed = NULL; + UPFMT("km_completed -> 0x%x", p); + while ((tm = p) != NULL) { + p = tm->tm_next; + UPFMT(" 0x%x", p); + runq_insert(tm); + } + UPCHAR('\n'); + + /* + * Process any signals we've recieved (but only if we have + * somewhere to deliver them to). + */ + if ((run_queue != NULL) && SIGNOTEMPTY(km->km_sigscaught)) { + for (i = 0;i < _SIG_MAXSIG;i++) + if (SIGISMEMBER(km->km_sigscaught, i)) { + signalcontext(&run_queue->tm_context, i, foof); + break; + } + bzero(&km->km_sigscaught, sizeof(sigset_t)); + } + + /* + * Pull a thread off the run queue. + */ + p = runq_remove(); + #if 0 + if ((p == aa) && (progress > 0)) { + --progress; + signalcontext(&p->tm_context, 1, foof); + } + #endif + + /* + * Either schedule a thread, or idle if none ready to run. + */ + if (p != NULL) { + UPFMT("\n-- uts() scheduling 0x%x--\n", p); + UPFMT("eip -> 0x%x progress -> %d\n", + p->tm_context.uc_mcontext.mc_eip, progress); + UPSTR("curthread set\n"); + uts_to_thread(p, &km->km_curthread); + UPSTR("\n-- uts_to_thread() failed --\n"); + } + kse_yield(); + pstr("** uts() exiting **\n"); + exit(EX_SOFTWARE); + } + + /* + * Start a thread. + */ + static void + thread_start(const void *func, int arg) + { + struct thread_mailbox *tm; + char *p; + + aa = tm = (struct thread_mailbox *)calloc(1, sizeof(struct thread_mailbox)); + pfmt("thread_start() : 0x%x %x\n", tm, &aa->tm_context); + getcontext(&tm->tm_context); + p = (char *)malloc(THREAD_STACK_SIZE); + tm->tm_context.uc_stack.ss_sp = p; + tm->tm_context.uc_stack.ss_size = THREAD_STACK_SIZE; + makecontext(&tm->tm_context, func, 2, arg); + // setcontext(&tm->tm_context); + runq_insert(tm); + }