mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-27 13:32:45 +00:00
Submitted by: John Birrell <cimaxp1!jb@werple.net.au>
Here are the diffs for libc_r to get it one step closer to P1003.1c These make most of the thread/mutex/condvar structures opaque to the user. There are three functions which have been renamed with _np suffixes because they are extensions to P1003.1c (I did them for JAVA, which needs to suspend/resume threads and also start threads suspended). I've created a new header (pthread_np.h) for the non-POSIX stuff. The egrep tags stuff in /usr/src/lib/libc_r/Makefile that I uncommented doesn't work. I think its best to delete it. I don't think libc_r needs tags anyway, 'cause most of the source is in libc which does have tags. also: Here's the first batch of man pages for the thread functions. The diff to /usr/src/lib/libc_r/Makefile removes some stuff that was inherited from /usr/src/lib/libc/Makefile that should only be done with libc. also: I should have sent this diff with the pthread(3) man page. It allows people to type make -DWANT_LIBC_R world to get libc_r built with the rest of the world. I put this in the pthread(3) man page. The default is still not to build libc_r. also: The diff attached adds a pthread(3) man page to /usr/src/share/man/man3. The idea is that without libc_r installed, this man page will give people enough info to know that they have to build libc_r.
This commit is contained in:
parent
1bbb22c82e
commit
0f7d684755
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=17706
@ -1,5 +1,5 @@
|
||||
# From: @(#)Makefile 8.2 (Berkeley) 1/4/94
|
||||
# $Id: Makefile,v 1.38 1996/07/09 15:48:20 ache Exp $
|
||||
# $Id: Makefile,v 1.39 1996/08/04 22:34:23 wosch Exp $
|
||||
#
|
||||
# Doing a make install builds /usr/include
|
||||
#
|
||||
@ -13,10 +13,10 @@ SUBDIR= rpcsvc
|
||||
FILES= a.out.h ar.h assert.h bitstring.h ctype.h db.h dirent.h disktab.h \
|
||||
err.h f2c.h fnmatch.h fstab.h fts.h glob.h grp.h strhash.h histedit.h \
|
||||
kvm.h limits.h link.h locale.h malloc.h memory.h mpool.h ndbm.h \
|
||||
netdb.h nl_types.h nlist.h paths.h pthread.h pwd.h ranlib.h regex.h \
|
||||
regexp.h resolv.h rune.h runetype.h setjmp.h sgtty.h signal.h \
|
||||
stab.h stddef.h stdio.h stdlib.h string.h strings.h struct.h \
|
||||
sysexits.h tar.h time.h timers.h ttyent.h unistd.h utime.h \
|
||||
netdb.h nl_types.h nlist.h paths.h pthread.h pthread_np.h pwd.h \
|
||||
ranlib.h regex.h regexp.h resolv.h rune.h runetype.h setjmp.h sgtty.h \
|
||||
signal.h stab.h stddef.h stdio.h stdlib.h string.h strings.h \
|
||||
struct.h sysexits.h tar.h time.h timers.h ttyent.h unistd.h utime.h \
|
||||
utmp.h vis.h
|
||||
.if defined(WANT_CSRG_LIBM)
|
||||
FILES+= math.h
|
||||
|
@ -40,141 +40,77 @@
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/signal.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
* Forward thread structure definition. This is opaque to the user.
|
||||
* Run-time invariant values:
|
||||
*/
|
||||
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
|
||||
#define PTHREAD_KEYS_MAX 256
|
||||
#define PTHREAD_STACK_MIN 1024
|
||||
#define PTHREAD_THREADS_MAX ULONG_MAX
|
||||
|
||||
/*
|
||||
* Compile time symbolic constants for portability specifications:
|
||||
*
|
||||
* Note that those commented out are not currently supported by the
|
||||
* implementation.
|
||||
*/
|
||||
#define _POSIX_THREADS
|
||||
#define _POSIX_THREAD_ATTR_STACKADDR
|
||||
#define _POSIX_THREAD_ATTR_STACKSIZE
|
||||
#define _POSIX_THREAD_PRIORITY_SCHEDULING
|
||||
/* #define _POSIX_THREAD_PRIO_INHERIT */
|
||||
/* #define _POSIX_THREAD_PRIO_PROTECT */
|
||||
/* #define _POSIX_THREAD_PROCESS_SHARED */
|
||||
#define _POSIX_THREAD_SAFE_FUNCTIONS
|
||||
|
||||
/*
|
||||
* Forward structure definitions.
|
||||
*
|
||||
* These are mostly opaque to the user.
|
||||
*/
|
||||
struct pthread;
|
||||
struct pthread_attr;
|
||||
struct pthread_cond;
|
||||
struct pthread_cond_attr;
|
||||
struct pthread_mutex;
|
||||
struct pthread_mutex_attr;
|
||||
struct pthread_once;
|
||||
struct sched_param;
|
||||
|
||||
/*
|
||||
* Queue definitions.
|
||||
* Primitive system data type definitions required by P1003.1c.
|
||||
*
|
||||
* Note that P1003.1c specifies that there are no defined comparison
|
||||
* or assignment operators for the types pthread_attr_t, pthread_cond_t,
|
||||
* pthread_condattr_t, pthread_mutex_t, pthread_mutexattr_t.
|
||||
*/
|
||||
struct pthread_queue {
|
||||
struct pthread *q_next;
|
||||
struct pthread *q_last;
|
||||
void *q_data;
|
||||
};
|
||||
typedef struct pthread *pthread_t;
|
||||
typedef struct pthread_attr *pthread_attr_t;
|
||||
typedef struct pthread_mutex *pthread_mutex_t;
|
||||
typedef struct pthread_mutex_attr *pthread_mutexattr_t;
|
||||
typedef struct pthread_cond *pthread_cond_t;
|
||||
typedef struct pthread_cond_attr *pthread_condattr_t;
|
||||
typedef int pthread_key_t;
|
||||
typedef struct pthread_once pthread_once_t;
|
||||
|
||||
/*
|
||||
* Static queue initialization values.
|
||||
* Additional type definitions:
|
||||
*
|
||||
* Note that P1003.1c reserves the prefixes pthread_ and PTHREAD_ for
|
||||
* use in header symbols.
|
||||
*/
|
||||
#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL }
|
||||
|
||||
/*
|
||||
* Mutex definitions.
|
||||
*/
|
||||
enum pthread_mutextype {
|
||||
MUTEX_TYPE_FAST = 1,
|
||||
MUTEX_TYPE_COUNTING_FAST = 2, /* Recursive */
|
||||
MUTEX_TYPE_MAX
|
||||
};
|
||||
|
||||
union pthread_mutex_data {
|
||||
void *m_ptr;
|
||||
int m_count;
|
||||
};
|
||||
|
||||
struct pthread_mutex {
|
||||
enum pthread_mutextype m_type;
|
||||
struct pthread_queue m_queue;
|
||||
struct pthread *m_owner;
|
||||
union pthread_mutex_data m_data;
|
||||
long m_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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_INITIALIZER \
|
||||
{ MUTEX_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, \
|
||||
NULL, { NULL }, MUTEX_FLAGS_INITED }
|
||||
|
||||
struct pthread_mutex_attr {
|
||||
enum pthread_mutextype m_type;
|
||||
long m_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Condition variable definitions.
|
||||
*/
|
||||
enum pthread_cond_type {
|
||||
COND_TYPE_FAST,
|
||||
COND_TYPE_MAX
|
||||
};
|
||||
|
||||
struct pthread_cond {
|
||||
enum pthread_cond_type c_type;
|
||||
struct pthread_queue c_queue;
|
||||
void *c_data;
|
||||
long c_flags;
|
||||
};
|
||||
|
||||
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_INITIALIZER \
|
||||
{ COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, COND_FLAGS_INITED }
|
||||
|
||||
/*
|
||||
* Cleanup definitions.
|
||||
*/
|
||||
struct pthread_cleanup {
|
||||
struct pthread_cleanup *next;
|
||||
void (*routine) ();
|
||||
void *routine_arg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Scheduling definitions.
|
||||
*/
|
||||
enum schedparam_policy {
|
||||
SCHED_RR,
|
||||
SCHED_IO,
|
||||
SCHED_FIFO,
|
||||
SCHED_OTHER
|
||||
};
|
||||
|
||||
struct pthread_attr {
|
||||
enum schedparam_policy schedparam_policy;
|
||||
int prio;
|
||||
int suspend;
|
||||
int flags;
|
||||
void *arg_attr;
|
||||
void (*cleanup_attr) ();
|
||||
void *stackaddr_attr;
|
||||
size_t stacksize_attr;
|
||||
};
|
||||
|
||||
struct sched_param {
|
||||
int prio;
|
||||
void *no_data;
|
||||
};
|
||||
typedef void *pthread_addr_t;
|
||||
typedef void *(*pthread_startroutine_t) (void *);
|
||||
|
||||
/*
|
||||
* Once definitions.
|
||||
*/
|
||||
struct pthread_once {
|
||||
int state;
|
||||
struct pthread_mutex mutex;
|
||||
int state;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -186,21 +122,7 @@ struct pthread_once {
|
||||
/*
|
||||
* Static once initialization values.
|
||||
*/
|
||||
#define PTHREAD_ONCE_INIT { PTHREAD_NEEDS_INIT, PTHREAD_MUTEX_INITIALIZER }
|
||||
|
||||
/*
|
||||
* Type definitions.
|
||||
*/
|
||||
typedef int pthread_key_t;
|
||||
typedef struct pthread *pthread_t;
|
||||
typedef struct pthread_attr pthread_attr_t;
|
||||
typedef struct pthread_cond pthread_cond_t;
|
||||
typedef struct pthread_cond_attr pthread_condattr_t;
|
||||
typedef struct pthread_mutex pthread_mutex_t;
|
||||
typedef struct pthread_mutex_attr pthread_mutexattr_t;
|
||||
typedef struct pthread_once pthread_once_t;
|
||||
typedef void *pthread_addr_t;
|
||||
typedef void *(*pthread_startroutine_t) (void *);
|
||||
#define PTHREAD_ONCE_INIT { PTHREAD_NEEDS_INIT, NULL }
|
||||
|
||||
/*
|
||||
* Default attribute arguments.
|
||||
@ -215,62 +137,95 @@ typedef void *(*pthread_startroutine_t) (void *);
|
||||
* Thread function prototype definitions:
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
int pthread_create __P((pthread_t *, const pthread_attr_t *,
|
||||
void *(*start_routine) (void *), void *));
|
||||
void pthread_exit __P((void *));
|
||||
pthread_t pthread_self __P((void));
|
||||
int pthread_equal __P((pthread_t, pthread_t));
|
||||
int pthread_getprio __P((pthread_t));
|
||||
int pthread_setprio __P((pthread_t, int));
|
||||
int pthread_join __P((pthread_t, void **));
|
||||
int pthread_detach __P((pthread_t *));
|
||||
int pthread_resume __P((pthread_t));
|
||||
int pthread_suspend __P((pthread_t));
|
||||
void pthread_yield __P((void));
|
||||
int pthread_setschedparam __P((pthread_t pthread, int policy,
|
||||
struct sched_param * param));
|
||||
int pthread_getschedparam __P((pthread_t pthread, int *policy,
|
||||
struct sched_param * param));
|
||||
int pthread_kill __P((struct pthread *, int));
|
||||
int pthread_cleanup_push __P((void (*routine) (void *), void *routine_arg));
|
||||
void pthread_cleanup_pop __P((int execute));
|
||||
int pthread_cond_init __P((pthread_cond_t *, const pthread_condattr_t *));
|
||||
int pthread_cond_timedwait __P((pthread_cond_t *, pthread_mutex_t *,
|
||||
const struct timespec * abstime));
|
||||
int pthread_cond_wait __P((pthread_cond_t *, pthread_mutex_t *));
|
||||
int pthread_cond_signal __P((pthread_cond_t *));
|
||||
int pthread_cond_broadcast __P((pthread_cond_t *));
|
||||
int pthread_cond_destroy __P((pthread_cond_t *));
|
||||
int pthread_mutex_init __P((pthread_mutex_t *, const pthread_mutexattr_t *));
|
||||
int pthread_mutex_lock __P((pthread_mutex_t *));
|
||||
int pthread_mutex_unlock __P((pthread_mutex_t *));
|
||||
int pthread_mutex_trylock __P((pthread_mutex_t *));
|
||||
int pthread_mutex_destroy __P((pthread_mutex_t *));
|
||||
int pthread_attr_init __P((pthread_attr_t *));
|
||||
int pthread_attr_destroy __P((pthread_attr_t *));
|
||||
int pthread_attr_setstacksize __P((pthread_attr_t *, size_t));
|
||||
int pthread_attr_getstacksize __P((pthread_attr_t *, size_t *));
|
||||
int pthread_attr_setstackaddr __P((pthread_attr_t *, void *));
|
||||
int pthread_attr_getstackaddr __P((pthread_attr_t *, void **));
|
||||
int pthread_attr_setdetachstate __P((pthread_attr_t *, int));
|
||||
int pthread_attr_getdetachstate __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_setscope __P((pthread_attr_t *, int));
|
||||
int pthread_attr_getscope __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_setinheritsched __P((pthread_attr_t *, int));
|
||||
int pthread_attr_getinheritsched __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_setschedpolicy __P((pthread_attr_t *, int));
|
||||
int pthread_attr_getschedpolicy __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_setschedparam __P((pthread_attr_t *, struct sched_param *));
|
||||
int pthread_attr_getschedparam __P((pthread_attr_t *, struct sched_param *));
|
||||
int pthread_attr_setfloatstate __P((pthread_attr_t *, int));
|
||||
int pthread_attr_getfloatstate __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_setcleanup __P((pthread_attr_t *, void (*routine) (void *), void *));
|
||||
int pthread_attr_setcreatesuspend __P((pthread_attr_t *));
|
||||
int pthread_once __P((pthread_once_t *, void (*init_routine) (void)));
|
||||
int pthread_keycreate __P((pthread_key_t *, void (*routine) (void *)));
|
||||
int pthread_setspecific __P((pthread_key_t, const void *));
|
||||
int pthread_getspecific __P((pthread_key_t, void **));
|
||||
int pthread_key_delete __P((pthread_key_t));
|
||||
int pthread_attr_destroy __P((pthread_attr_t *));
|
||||
int pthread_attr_getinheritsched __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_getschedparam __P((pthread_attr_t *,
|
||||
struct sched_param *));
|
||||
int pthread_attr_getschedpolicy __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_getscope __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_getstacksize __P((pthread_attr_t *, size_t *));
|
||||
int pthread_attr_getstackaddr __P((pthread_attr_t *, void **));
|
||||
int pthread_attr_getdetachstate __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_init __P((pthread_attr_t *));
|
||||
int pthread_attr_setinheritsched __P((pthread_attr_t *, int));
|
||||
int pthread_attr_setschedparam __P((pthread_attr_t *,
|
||||
struct sched_param *));
|
||||
int pthread_attr_setschedpolicy __P((pthread_attr_t *, int));
|
||||
int pthread_attr_setscope __P((pthread_attr_t *, int));
|
||||
int pthread_attr_setstacksize __P((pthread_attr_t *, size_t));
|
||||
int pthread_attr_setstackaddr __P((pthread_attr_t *, void *));
|
||||
int pthread_attr_setdetachstate __P((pthread_attr_t *, int));
|
||||
void pthread_cleanup_pop __P((int execute));
|
||||
int pthread_cleanup_push __P((void (*routine) (void *),
|
||||
void *routine_arg));
|
||||
int pthread_condattr_destroy __P((pthread_condattr_t *attr));
|
||||
int pthread_condattr_init __P((pthread_condattr_t *attr));
|
||||
int pthread_condattr_getpshared __P((pthread_condattr_t *attr,
|
||||
int *pshared));
|
||||
int pthread_condattr_setpshared __P((pthread_condattr_t *attr,
|
||||
int pshared));
|
||||
int pthread_cond_broadcast __P((pthread_cond_t *));
|
||||
int pthread_cond_destroy __P((pthread_cond_t *));
|
||||
int pthread_cond_init __P((pthread_cond_t *,
|
||||
const pthread_condattr_t *));
|
||||
int pthread_cond_signal __P((pthread_cond_t *));
|
||||
int pthread_cond_timedwait __P((pthread_cond_t *,
|
||||
pthread_mutex_t *, const struct timespec * abstime));
|
||||
int pthread_cond_wait __P((pthread_cond_t *, pthread_mutex_t *));
|
||||
int pthread_create __P((pthread_t *, const pthread_attr_t *,
|
||||
void *(*start_routine) (void *), void *));
|
||||
int pthread_detach __P((pthread_t *));
|
||||
int pthread_equal __P((pthread_t, pthread_t));
|
||||
void pthread_exit __P((void *));
|
||||
int pthread_getspecific __P((pthread_key_t, void **));
|
||||
int pthread_join __P((pthread_t, void **));
|
||||
int pthread_key_create __P((pthread_key_t *,
|
||||
void (*routine) (void *)));
|
||||
int pthread_key_delete __P((pthread_key_t));
|
||||
int pthread_kill __P((struct pthread *, int));
|
||||
int pthread_mutexattr_destroy __P((pthread_mutexattr_t *));
|
||||
int pthread_mutexattr_getprioceiling __P((pthread_mutexattr_t *,
|
||||
int *prioceiling));
|
||||
int pthread_mutexattr_getprotocol __P((pthread_mutexattr_t *,
|
||||
int *protocol));
|
||||
int pthread_mutexattr_getpshared __P((pthread_mutexattr_t *,
|
||||
int *pshared));
|
||||
int pthread_mutexattr_init __P((pthread_mutexattr_t *));
|
||||
int pthread_mutexattr_setprioceiling __P((pthread_mutexattr_t *,
|
||||
int prioceiling));
|
||||
int pthread_mutexattr_setprotocol __P((pthread_mutexattr_t *,
|
||||
int protocol));
|
||||
int pthread_mutexattr_setpshared __P((pthread_mutexattr_t *,
|
||||
int pshared));
|
||||
int pthread_mutex_destroy __P((pthread_mutex_t *));
|
||||
int pthread_mutex_getprioceiling __P((pthread_mutex_t *));
|
||||
int pthread_mutex_init __P((pthread_mutex_t *,
|
||||
const pthread_mutexattr_t *));
|
||||
int pthread_mutex_lock __P((pthread_mutex_t *));
|
||||
int pthread_mutex_setprioceiling __P((pthread_mutex_t *));
|
||||
int pthread_mutex_trylock __P((pthread_mutex_t *));
|
||||
int pthread_mutex_unlock __P((pthread_mutex_t *));
|
||||
int pthread_once __P((pthread_once_t *,
|
||||
void (*init_routine) (void)));
|
||||
pthread_t pthread_self __P((void));
|
||||
int pthread_setcancelstate __P((int, int *));
|
||||
int pthread_setcanceltype __P((int, int *));
|
||||
int pthread_setspecific __P((pthread_key_t, const void *));
|
||||
int pthread_sigmask __P((int, const sigset_t *, sigset_t *));
|
||||
int pthread_testcancel __P((void));
|
||||
|
||||
|
||||
int pthread_getprio __P((pthread_t));
|
||||
int pthread_setprio __P((pthread_t, int));
|
||||
void pthread_yield __P((void));
|
||||
int pthread_setschedparam __P((pthread_t pthread, int policy,
|
||||
struct sched_param * param));
|
||||
int pthread_getschedparam __P((pthread_t pthread, int *policy,
|
||||
struct sched_param * param));
|
||||
int pthread_attr_setfloatstate __P((pthread_attr_t *, int));
|
||||
int pthread_attr_getfloatstate __P((pthread_attr_t *, int *));
|
||||
int pthread_attr_setcleanup __P((pthread_attr_t *,
|
||||
void (*routine) (void *), void *));
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
|
47
include/pthread_np.h
Normal file
47
include/pthread_np.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef _PTHREAD_NP_H_
|
||||
#define _PTHREAD_NP_H_
|
||||
|
||||
/*
|
||||
* Non-POSIX thread function prototype definitions:
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
int pthread_attr_setcreatesuspend_np __P((pthread_attr_t *));
|
||||
int pthread_multi_np __P((void));
|
||||
int pthread_resume_np __P((pthread_t));
|
||||
int pthread_single_np __P((void));
|
||||
int pthread_suspend_np __P((pthread_t));
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
@ -16,6 +16,10 @@ SUBDIR+=libc libcompat libcom_err libcurses libdisk libedit \
|
||||
libscsi libskey libss libtcl libtermcap libutil libxpg4 liby libz
|
||||
|
||||
|
||||
.if defined(WANT_LIBC_R)
|
||||
SUBDIR+= libc_r
|
||||
.endif
|
||||
|
||||
.if !exists(../secure) || defined(NOSECURE) || defined(NOCRYPT)
|
||||
SUBDIR+= libcrypt
|
||||
.else
|
||||
|
@ -35,7 +35,7 @@
|
||||
*
|
||||
* from: @(#)SYS.h 5.5 (Berkeley) 5/7/91
|
||||
*
|
||||
* $Id: SYS.h,v 1.3 1996/01/22 00:00:51 julian Exp $
|
||||
* $Id: SYS.h,v 1.4 1996/05/05 07:56:03 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
@ -64,20 +64,38 @@
|
||||
#define SYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); ENTRY(x); lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
|
||||
#define RSYSCALL(x) SYSCALL(x); ret
|
||||
|
||||
/*
|
||||
* For the thread_safe versions, we prepend _thread_sys_ to the function
|
||||
* name so that the 'C' wrapper can go around the real name.
|
||||
*/
|
||||
#ifdef _THREAD_SAFE /* in case */
|
||||
#define PSYSCALL(x,y) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); ENTRY(y); lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
|
||||
#define PRSYSCALL(x,y) PSYSCALL(x,y); ret
|
||||
#endif
|
||||
|
||||
#define PSEUDO(x,y) ENTRY(x); lea __CONCAT(SYS_,y), %eax; KERNCALL; ret
|
||||
#define CALL(x,y) call CNAME(y); addl $4*x,%esp
|
||||
/* gas fucks up offset -- although we don't currently need it, do for BCS */
|
||||
#define LCALL(x,y) .byte 0x9a ; .long y; .word x
|
||||
|
||||
/*
|
||||
* Design note:
|
||||
*
|
||||
* The macros PSYSCALL() and PRSYSCALL() are intended for use where a
|
||||
* syscall needs to be renamed in the threaded library. When building
|
||||
* a normal library, they default to the traditional SYSCALL() and
|
||||
* RSYSCALL(). This avoids the need to #ifdef _THREAD_SAFE everywhere
|
||||
* that the renamed function needs to be called.
|
||||
*/
|
||||
#ifdef _THREAD_SAFE /* in case */
|
||||
/*
|
||||
* For the thread_safe versions, we prepend _thread_sys_ to the function
|
||||
* name so that the 'C' wrapper can go around the real name.
|
||||
*/
|
||||
#define PSYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); ENTRY(_thread_sys_/**/x); lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
|
||||
#define PRSYSCALL(x) PSYSCALL(x); ret
|
||||
#define PPSEUDO(x,y) ENTRY(_thread_sys_/**/x); lea __CONCAT(SYS_,y), %eax; KERNCALL; ret
|
||||
#else
|
||||
/*
|
||||
* The non-threaded library defaults to traditional syscalls where
|
||||
* the function name matches the syscall name.
|
||||
*/
|
||||
#define PSYSCALL(x) SYSCALL(x)
|
||||
#define PRSYSCALL(x) RSYSCALL(x)
|
||||
#define PPSEUDO(x,y) PSEUDO(x,y)
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
#define KERNCALL int $0x80 /* Faster */
|
||||
#else
|
||||
|
@ -33,21 +33,17 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: pipe.S,v 1.3 1996/01/22 00:00:58 julian Exp $
|
||||
* $Id: pipe.S,v 1.4 1996/05/05 07:56:13 peter Exp $
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_RCS) && !defined(lint)
|
||||
.text
|
||||
.asciz "$Id: pipe.S,v 1.3 1996/01/22 00:00:58 julian Exp $"
|
||||
.asciz "$Id: pipe.S,v 1.4 1996/05/05 07:56:13 peter Exp $"
|
||||
#endif /* SYSLIBC_RCS and not lint */
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
#ifdef _THREAD_SAFE
|
||||
PSYSCALL(pipe,_thread_sys_pipe)
|
||||
#else
|
||||
SYSCALL(pipe)
|
||||
#endif
|
||||
PSYSCALL(pipe)
|
||||
movl 4(%esp),%ecx
|
||||
movl %eax,(%ecx)
|
||||
movl %edx,4(%ecx)
|
||||
|
@ -33,12 +33,12 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: sigreturn.S,v 1.3 1996/01/22 00:01:00 julian Exp $
|
||||
* $Id: sigreturn.S,v 1.4 1996/05/05 07:56:19 peter Exp $
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_RCS) && !defined(lint)
|
||||
.text
|
||||
.asciz "$Id: sigreturn.S,v 1.3 1996/01/22 00:01:00 julian Exp $"
|
||||
.asciz "$Id: sigreturn.S,v 1.4 1996/05/05 07:56:19 peter Exp $"
|
||||
#endif /* SYSLIBC_RCS and not lint */
|
||||
|
||||
#include "SYS.h"
|
||||
@ -48,9 +48,5 @@
|
||||
* must be saved. On FreeBSD, this is not the case.
|
||||
*/
|
||||
|
||||
#ifdef _THREAD_SAFE
|
||||
PSYSCALL(sigreturn,_thread_sys_sigreturn)
|
||||
#else
|
||||
SYSCALL(sigreturn)
|
||||
#endif
|
||||
PSYSCALL(sigreturn)
|
||||
ret
|
||||
|
@ -49,7 +49,8 @@ static char sccsid[] = "@(#)ttyname.c 8.2 (Berkeley) 1/27/94";
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
static pthread_mutex_t ttyname_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct pthread_mutex _ttyname_lockd = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t ttyname_lock = &_ttyname_lockd;
|
||||
static pthread_key_t ttyname_key;
|
||||
static int ttyname_init = 0;
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
*
|
||||
* from: @(#)SYS.h 5.5 (Berkeley) 5/7/91
|
||||
*
|
||||
* $Id: SYS.h,v 1.3 1996/01/22 00:00:51 julian Exp $
|
||||
* $Id: SYS.h,v 1.4 1996/05/05 07:56:03 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
@ -64,20 +64,38 @@
|
||||
#define SYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); ENTRY(x); lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
|
||||
#define RSYSCALL(x) SYSCALL(x); ret
|
||||
|
||||
/*
|
||||
* For the thread_safe versions, we prepend _thread_sys_ to the function
|
||||
* name so that the 'C' wrapper can go around the real name.
|
||||
*/
|
||||
#ifdef _THREAD_SAFE /* in case */
|
||||
#define PSYSCALL(x,y) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); ENTRY(y); lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
|
||||
#define PRSYSCALL(x,y) PSYSCALL(x,y); ret
|
||||
#endif
|
||||
|
||||
#define PSEUDO(x,y) ENTRY(x); lea __CONCAT(SYS_,y), %eax; KERNCALL; ret
|
||||
#define CALL(x,y) call CNAME(y); addl $4*x,%esp
|
||||
/* gas fucks up offset -- although we don't currently need it, do for BCS */
|
||||
#define LCALL(x,y) .byte 0x9a ; .long y; .word x
|
||||
|
||||
/*
|
||||
* Design note:
|
||||
*
|
||||
* The macros PSYSCALL() and PRSYSCALL() are intended for use where a
|
||||
* syscall needs to be renamed in the threaded library. When building
|
||||
* a normal library, they default to the traditional SYSCALL() and
|
||||
* RSYSCALL(). This avoids the need to #ifdef _THREAD_SAFE everywhere
|
||||
* that the renamed function needs to be called.
|
||||
*/
|
||||
#ifdef _THREAD_SAFE /* in case */
|
||||
/*
|
||||
* For the thread_safe versions, we prepend _thread_sys_ to the function
|
||||
* name so that the 'C' wrapper can go around the real name.
|
||||
*/
|
||||
#define PSYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); ENTRY(_thread_sys_/**/x); lea __CONCAT(SYS_,x),%eax; KERNCALL; jb 2b
|
||||
#define PRSYSCALL(x) PSYSCALL(x); ret
|
||||
#define PPSEUDO(x,y) ENTRY(_thread_sys_/**/x); lea __CONCAT(SYS_,y), %eax; KERNCALL; ret
|
||||
#else
|
||||
/*
|
||||
* The non-threaded library defaults to traditional syscalls where
|
||||
* the function name matches the syscall name.
|
||||
*/
|
||||
#define PSYSCALL(x) SYSCALL(x)
|
||||
#define PRSYSCALL(x) RSYSCALL(x)
|
||||
#define PPSEUDO(x,y) PSEUDO(x,y)
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
#define KERNCALL int $0x80 /* Faster */
|
||||
#else
|
||||
|
@ -33,21 +33,17 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: fork.S,v 1.3 1996/01/22 00:00:57 julian Exp $
|
||||
* $Id: fork.S,v 1.4 1996/05/05 07:56:13 peter Exp $
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_RCS) && !defined(lint)
|
||||
.text
|
||||
.asciz "$Id: fork.S,v 1.3 1996/01/22 00:00:57 julian Exp $"
|
||||
.asciz "$Id: fork.S,v 1.4 1996/05/05 07:56:13 peter Exp $"
|
||||
#endif /* SYSLIBC_RCS and not lint */
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
#ifdef _THREAD_SAFE
|
||||
PSYSCALL(fork,_thread_sys_fork)
|
||||
#else
|
||||
SYSCALL(fork)
|
||||
#endif
|
||||
PSYSCALL(fork)
|
||||
cmpl $0,%edx /* parent, since %edx == 0 in parent, 1 in child */
|
||||
je 1f
|
||||
movl $0,%eax
|
||||
|
@ -33,21 +33,17 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: pipe.S,v 1.3 1996/01/22 00:00:58 julian Exp $
|
||||
* $Id: pipe.S,v 1.4 1996/05/05 07:56:13 peter Exp $
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_RCS) && !defined(lint)
|
||||
.text
|
||||
.asciz "$Id: pipe.S,v 1.3 1996/01/22 00:00:58 julian Exp $"
|
||||
.asciz "$Id: pipe.S,v 1.4 1996/05/05 07:56:13 peter Exp $"
|
||||
#endif /* SYSLIBC_RCS and not lint */
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
#ifdef _THREAD_SAFE
|
||||
PSYSCALL(pipe,_thread_sys_pipe)
|
||||
#else
|
||||
SYSCALL(pipe)
|
||||
#endif
|
||||
PSYSCALL(pipe)
|
||||
movl 4(%esp),%ecx
|
||||
movl %eax,(%ecx)
|
||||
movl %edx,4(%ecx)
|
||||
|
@ -33,21 +33,17 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: rfork.S,v 1.1 1996/02/23 19:56:47 peter Exp $
|
||||
* $Id: rfork.S,v 1.2 1996/05/05 07:56:15 peter Exp $
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_RCS) && !defined(lint)
|
||||
.text
|
||||
.asciz "$Id: rfork.S,v 1.1 1996/02/23 19:56:47 peter Exp $"
|
||||
.asciz "$Id: rfork.S,v 1.2 1996/05/05 07:56:15 peter Exp $"
|
||||
#endif /* SYSLIBC_RCS and not lint */
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
#ifdef _THREAD_SAFE
|
||||
PSYSCALL(rfork,_thread_sys_rfork)
|
||||
#else
|
||||
SYSCALL(rfork)
|
||||
#endif
|
||||
PSYSCALL(rfork)
|
||||
cmpl $0,%edx /* parent, since %edx == 0 in parent, 1 in child */
|
||||
je 1f
|
||||
movl $0,%eax
|
||||
|
@ -33,21 +33,17 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: sigpending.S,v 1.3 1996/01/22 00:00:59 julian Exp $
|
||||
* $Id: sigpending.S,v 1.4 1996/05/05 07:56:18 peter Exp $
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_RCS) && !defined(lint)
|
||||
.text
|
||||
.asciz "$Id: sigpending.S,v 1.3 1996/01/22 00:00:59 julian Exp $"
|
||||
.asciz "$Id: sigpending.S,v 1.4 1996/05/05 07:56:18 peter Exp $"
|
||||
#endif /* SYSLIBC_RCS and not lint */
|
||||
|
||||
#include "SYS.h"
|
||||
|
||||
#ifdef _THREAD_SAFE
|
||||
PSYSCALL(sigpending,_thread_sys_sigpending)
|
||||
#else
|
||||
SYSCALL(sigpending)
|
||||
#endif
|
||||
PSYSCALL(sigpending)
|
||||
movl 4(%esp),%ecx # fetch pointer to...
|
||||
movl %eax,(%ecx) # store old mask
|
||||
xorl %eax,%eax
|
||||
|
@ -33,12 +33,12 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: sigreturn.S,v 1.3 1996/01/22 00:01:00 julian Exp $
|
||||
* $Id: sigreturn.S,v 1.4 1996/05/05 07:56:19 peter Exp $
|
||||
*/
|
||||
|
||||
#if defined(SYSLIBC_RCS) && !defined(lint)
|
||||
.text
|
||||
.asciz "$Id: sigreturn.S,v 1.3 1996/01/22 00:01:00 julian Exp $"
|
||||
.asciz "$Id: sigreturn.S,v 1.4 1996/05/05 07:56:19 peter Exp $"
|
||||
#endif /* SYSLIBC_RCS and not lint */
|
||||
|
||||
#include "SYS.h"
|
||||
@ -48,9 +48,5 @@
|
||||
* must be saved. On FreeBSD, this is not the case.
|
||||
*/
|
||||
|
||||
#ifdef _THREAD_SAFE
|
||||
PSYSCALL(sigreturn,_thread_sys_sigreturn)
|
||||
#else
|
||||
SYSCALL(sigreturn)
|
||||
#endif
|
||||
PSYSCALL(sigreturn)
|
||||
ret
|
||||
|
@ -24,8 +24,8 @@
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)$Id: gethostnamadr.c,v 1.7 1995/05/30 05:40:45 rgrimes Exp $";
|
||||
static char rcsid[] = "$Id: gethostnamadr.c,v 1.7 1995/05/30 05:40:45 rgrimes Exp $";
|
||||
static char sccsid[] = "@(#)$Id: gethostnamadr.c,v 1.8 1996/07/12 18:54:36 jkh Exp $";
|
||||
static char rcsid[] = "$Id: gethostnamadr.c,v 1.8 1996/07/12 18:54:36 jkh Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -184,6 +184,27 @@ gethostbyaddr(const char *addr, int len, int type)
|
||||
return hp;
|
||||
}
|
||||
|
||||
#ifdef _THREAD_SAFE
|
||||
struct hostent_data;
|
||||
|
||||
/*
|
||||
* Temporary function (not thread safe)
|
||||
*/
|
||||
int gethostbyaddr_r(const char *addr, int len, int type,
|
||||
struct hostent *result, struct hostent_data *buffer)
|
||||
{
|
||||
struct hostent *hp = 0;
|
||||
int ret;
|
||||
if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
|
||||
ret = -1;
|
||||
} else {
|
||||
memcpy(result, hp, sizeof(struct hostent));
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
sethostent(stayopen)
|
||||
int stayopen;
|
||||
|
@ -168,8 +168,10 @@ static char lcl_TZname[TZ_STRLEN_MAX + 1];
|
||||
static int lcl_is_set;
|
||||
static int gmt_is_set;
|
||||
#ifdef _THREAD_SAFE
|
||||
static pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct pthread_mutex _lcl_mutexd = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct pthread_mutex _gmt_mutexd = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t lcl_mutex = &_lcl_mutexd;
|
||||
static pthread_mutex_t gmt_mutex = &_gmt_mutexd;
|
||||
#endif
|
||||
|
||||
char * tzname[2] = {
|
||||
@ -1087,7 +1089,8 @@ localtime(timep)
|
||||
const time_t * const timep;
|
||||
{
|
||||
#ifdef _THREAD_SAFE
|
||||
static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct pthread_mutex _localtime_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t localtime_mutex = &_localtime_mutex;
|
||||
static pthread_key_t localtime_key = -1;
|
||||
struct tm *p_tm;
|
||||
|
||||
@ -1170,7 +1173,8 @@ gmtime(timep)
|
||||
const time_t * const timep;
|
||||
{
|
||||
#ifdef _THREAD_SAFE
|
||||
static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct pthread_mutex _gmtime_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t gmtime_mutex = &_gmtime_mutex;
|
||||
static pthread_key_t gmtime_key = -1;
|
||||
struct tm *p_tm;
|
||||
|
||||
|
@ -20,6 +20,7 @@ PRECIOUSLIB= yes
|
||||
.include "${.CURDIR}/gen/Makefile.inc"
|
||||
.include "${.CURDIR}/gmon/Makefile.inc"
|
||||
.include "${.CURDIR}/locale/Makefile.inc"
|
||||
.include "${.CURDIR}/man/Makefile.inc"
|
||||
.include "${.CURDIR}/net/Makefile.inc"
|
||||
.include "${.CURDIR}/nls/Makefile.inc"
|
||||
.include "${.CURDIR}/quad/Makefile.inc"
|
||||
@ -38,24 +39,8 @@ CFLAGS+= -DYP
|
||||
.endif
|
||||
.include "${.CURDIR}/${MACHINE}/sys/Makefile.inc"
|
||||
|
||||
KQSRCS= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \
|
||||
lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \
|
||||
subdi3.c ucmpdi2.c udivdi3.c umoddi3.c xordi3.c
|
||||
KSRCS= bcmp.c ffs.c index.c mcount.c rindex.c strcat.c strcmp.c strcpy.c \
|
||||
strlen.c strncpy.c
|
||||
|
||||
libkern: libkern.gen libkern.${MACHINE}
|
||||
|
||||
libkern.gen: ${KQSRCS} ${KSRCS}
|
||||
cp -p ${.CURDIR}/quad/quad.h ${.ALLSRC} /sys/libkern
|
||||
|
||||
libkern.${MACHINE}:: ${KMSRCS}
|
||||
.if defined(KMSRCS) && !empty(KMSRCS)
|
||||
cp -p ${.ALLSRC} /sys/libkern/${MACHINE}
|
||||
.endif
|
||||
|
||||
#beforeinstall: tags
|
||||
# ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc.tags
|
||||
beforeinstall: tags
|
||||
${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc_r.tags
|
||||
|
||||
tags: ${SRCS}
|
||||
ctags ${.ALLSRC:M*.c}
|
||||
|
17
lib/libc_r/man/Makefile.inc
Normal file
17
lib/libc_r/man/Makefile.inc
Normal file
@ -0,0 +1,17 @@
|
||||
# $Id$
|
||||
|
||||
# POSIX thread man files
|
||||
|
||||
.PATH: ${.CURDIR}/man
|
||||
|
||||
MAN3+= 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_once.3 \
|
||||
pthread_self.3 \
|
||||
pthread_setspecific.3
|
109
lib/libc_r/man/pthread_create.3
Normal file
109
lib/libc_r/man/pthread_create.3
Normal file
@ -0,0 +1,109 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_CREATE 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_create
|
||||
.Nd create a new thread
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_create "pthread_t *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_create
|
||||
function is used to create a new thread, with attributes specified by
|
||||
.Fa attr ,
|
||||
within a process. If
|
||||
.Fa attr
|
||||
is NULL, the default attributes are used. If the attributes specified by
|
||||
.Fa attr
|
||||
are modified later, the thread's attributes are not affected. Upon
|
||||
successful completion
|
||||
.Fn pthread_create
|
||||
will store the ID of the created thread in the location specified by
|
||||
.Fa thread .
|
||||
.Pp
|
||||
The thread is created executing
|
||||
.Fa start_routine
|
||||
with
|
||||
.Fa arg
|
||||
as its sole argument. If the
|
||||
.Fa start_routine
|
||||
returns, the effect is as if there was an implicit call to
|
||||
.Fn pthread_exit
|
||||
using the return value of
|
||||
.Fa start_toutine
|
||||
as the exit status. Note that the thread in which
|
||||
.Fn main
|
||||
was originally invoked differs from this. When it returns from
|
||||
.Fn main ,
|
||||
the effect is as if there was an implicit call to
|
||||
.Fn exit using the return value of
|
||||
.Fn main
|
||||
as the exit status.
|
||||
.Pp
|
||||
The signal state of the new thread is initialized as:
|
||||
.Bl -bullet -offset indent
|
||||
.It
|
||||
The signal mask is inherited from the creating thread.
|
||||
.It
|
||||
The set of signals pending for the new thread is empty.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_create
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_create
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EAGAIN
|
||||
The system lacked the necessary resources to create another thread, or
|
||||
the system-imposed limit on the total number of threads in a process
|
||||
[PTHREAD_THREADS_MAX] would be exceeded.
|
||||
.It Bq Er EINVAL
|
||||
The value specified by
|
||||
.Fa attr
|
||||
is invalid.
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_exit 3 ,
|
||||
.Xr pthread_join 3 ,
|
||||
.Xr fork 2
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_create
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
79
lib/libc_r/man/pthread_detach.3
Normal file
79
lib/libc_r/man/pthread_detach.3
Normal file
@ -0,0 +1,79 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_DETACH 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_detach
|
||||
.Nd detach a thread
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_detach "pthread_t thread"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_detach
|
||||
function is used to indicate to the implementation that storage for the
|
||||
thread
|
||||
.Fa thread
|
||||
can be reclaimed when the thread terminates. If
|
||||
.Fa thread
|
||||
has not terminated,
|
||||
.Fn pthread_detach
|
||||
will not cause it to terminate. The effect of multiple
|
||||
.Fn pthread_detach
|
||||
calls on the same target thread is unspecified.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_detach
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_detach
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The implementation has detected that the value specified by
|
||||
.Fa thread
|
||||
does not refer to a joinable thread.
|
||||
.It Bq Er ESRCH
|
||||
No thread could be found corresponding to that specified by the given
|
||||
thread ID,
|
||||
.Fa thread .
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_join 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_detach
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
66
lib/libc_r/man/pthread_equal.3
Normal file
66
lib/libc_r/man/pthread_equal.3
Normal file
@ -0,0 +1,66 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_EQUAL 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_equal
|
||||
.Nd compare thread IDs
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_equal "pthread_t t1" "pthread_t t2"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_equal
|
||||
function compares the thread IDs
|
||||
.Fa t1
|
||||
and
|
||||
.Fa t2 .
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn pthread_equal
|
||||
function will non-zero if the thread IDs
|
||||
.Fa t1
|
||||
and
|
||||
.Fa t2
|
||||
correspond to the same thread, otherwise it will return zero.
|
||||
.Sh ERRORS
|
||||
None.
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_create 3 ,
|
||||
.Xr pthread_exit 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_equal
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
99
lib/libc_r/man/pthread_exit.3
Normal file
99
lib/libc_r/man/pthread_exit.3
Normal file
@ -0,0 +1,99 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_EXIT 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_exit
|
||||
.Nd terminate the calling thread
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft void
|
||||
.Fn pthread_exit "void *value_ptr"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_exit
|
||||
function terminates the calling thread and makes the value
|
||||
.Fa value_ptr
|
||||
available to any successful join with the terminating thread. Any
|
||||
cancellation cleanup handlers that have been pushed and are not yet popped
|
||||
are popped in the reverse order that they were pushed and then executed.
|
||||
After all cancellation handlers have been executed, if the thread has any
|
||||
thread-specific data, appropriate destructor functions are called in an
|
||||
unspecified order. Thread termination does not release any application
|
||||
visible process resources, including, but not limited to, mutexes and
|
||||
file descriptors, nor does it perform any process level cleanup
|
||||
actions, including, but not limited to, calling
|
||||
.Fn atexit
|
||||
routines that may exist.
|
||||
.Pp
|
||||
An implicit call to
|
||||
.Fn pthread_exit
|
||||
is made when a thread other than the thread in which
|
||||
.Fn main
|
||||
was first invoked returns from the start routine that was used to create
|
||||
it. The function's return value serves as the thread's exit status.
|
||||
.Pp
|
||||
The behavior of
|
||||
.Fn pthread_exit
|
||||
is undefied if called from a cancellation handler or destructor function
|
||||
that was invoked as the result of an implicit or explicit call to
|
||||
.Fn pthread_exit .
|
||||
.Pp
|
||||
After a thread has terminated, the result of access to local (auto)
|
||||
variables of the thread is undefined. Thus, references to local variables
|
||||
of the exiting thread should not be used for the
|
||||
.Fn pthread_exit
|
||||
.Fa value_ptr
|
||||
parameter value.
|
||||
.Pp
|
||||
The process will exit with an exit status of 0 after the last thread has
|
||||
been terminated. The behavior is as if the implementation called
|
||||
.Fn exit
|
||||
with a zero argument at thread termination time.
|
||||
.Pp
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn pthread_exit
|
||||
function cannot return to its caller.
|
||||
.Sh ERRORS
|
||||
None.
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_create 3 ,
|
||||
.Xr pthread_join 3 ,
|
||||
.Xr exit 2,
|
||||
.Xr _exit 2
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_exit
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
80
lib/libc_r/man/pthread_getspecific.3
Normal file
80
lib/libc_r/man/pthread_getspecific.3
Normal file
@ -0,0 +1,80 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_GETSPECIFIC 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_getspecific
|
||||
.Nd get a thread-specific data value
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft void *
|
||||
.Fn pthread_getspecific "pthread_key_t key"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_getspecific
|
||||
function returns the value currently bound to the specified
|
||||
.Fa key
|
||||
on behalf of the calling thread.
|
||||
.Pp
|
||||
The effect of calling
|
||||
.Fn pthread_getspecific
|
||||
with a
|
||||
.Fa key
|
||||
value not obtained from
|
||||
.Fn pthread_key_create
|
||||
or after
|
||||
.Fa key
|
||||
has been deleted with
|
||||
.Fn pthread_key_delete
|
||||
is undefined.
|
||||
.Pp
|
||||
.Fn pthread_getspecific
|
||||
may be called from a thread-specific data destructor function.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn pthread_getspecific
|
||||
function will return the thread-specific data value associated with the given
|
||||
.Fa key .
|
||||
If no thread-specific data value is associated with
|
||||
.Fa key ,
|
||||
then the value NULL is returned.
|
||||
.Sh ERRORS
|
||||
None.
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_key_create 3 ,
|
||||
.Xr pthread_key_delete 3
|
||||
.Xr pthread_setspecific 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_getspecific
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
100
lib/libc_r/man/pthread_join.3
Normal file
100
lib/libc_r/man/pthread_join.3
Normal file
@ -0,0 +1,100 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_JOIN 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_join
|
||||
.Nd wait for thread termination
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_join "pthread_t thread" "void **value_ptr"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_join
|
||||
function suspends execution of the calling thread until the target
|
||||
.Fa thread
|
||||
terminates unless the target
|
||||
.Fa thread
|
||||
has already terminated.
|
||||
.Pp
|
||||
On return from a successful
|
||||
.Fn pthread_join
|
||||
call with a non-NULL
|
||||
.Fa value_ptr
|
||||
argument, the value passed to
|
||||
.Fn pthread_exit
|
||||
by the terminating thread is stored in the location referenced by
|
||||
.Fa value_ptr .
|
||||
When a
|
||||
.Fn pthread_join
|
||||
returns successfully, the target thread has been terminated. The results
|
||||
of multiple simultaneous calls to
|
||||
.Fn pthread_join
|
||||
specifying the same target thread are undefined. If the thread calling
|
||||
.Fn pthread_join
|
||||
is cancelled, then the target thread is not detached.
|
||||
.Pp
|
||||
A thread that has exited but remains unjoined counts against
|
||||
[_POSIX_THREAD_THREADS_MAX].
|
||||
.Pp
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_join
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_join
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The implementation has detected that the value specified by
|
||||
.Fa thread
|
||||
does not refer to a joinable thread.
|
||||
.It Bq Er ESRCH
|
||||
No thread could be found corresponding to that specified by the given
|
||||
thread ID,
|
||||
.Fa thread .
|
||||
.It Bq Er EDEADLK
|
||||
A deadlock was detected or the value of
|
||||
.Fa thread
|
||||
specifies the calling thread.
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_create 3 ,
|
||||
.Xr wait 2
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_join
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
98
lib/libc_r/man/pthread_key_create.3
Normal file
98
lib/libc_r/man/pthread_key_create.3
Normal file
@ -0,0 +1,98 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_KEY_CREATE 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_key_create
|
||||
.Nd thread-specific data key creation
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_key_create "pthread_key_t *key" "void (*destructor)(void *)"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_key_create
|
||||
function creates a thread-specific data key visible to all threads in the
|
||||
process. Key values provided by
|
||||
.Fn pthread_key_create
|
||||
are opaque objects used to locate thread-specific data. Although the same
|
||||
key value may be used by different threads, the values bound to the key
|
||||
by
|
||||
.Fn pthread_setspecific
|
||||
are maintained on a per-thread basis and persist for the life of the calling
|
||||
thread.
|
||||
.Pp
|
||||
Upon key creation, the value NULL is associated with the new key in all
|
||||
active threads. Upon thread creation, the value NULL is associated with all
|
||||
defined keys in the new thread.
|
||||
.Pp
|
||||
An optional destructor function may be associated with each key value. At
|
||||
thread exit, if a key value has a non-NULL destructor pointer, and the
|
||||
thread has a non-NULL value associated with the key, the function pointed
|
||||
to is called with the current associated value as its sole argument. The
|
||||
order of destructor calls is unspecified if more than one destructor exists
|
||||
for a thread when it exits.
|
||||
.Pp
|
||||
If, after all the destructors have been called for all non-NULL values
|
||||
with associated destructors, there are still some non-NULL values with
|
||||
associated destructors, then the process is repeated. If, after at least
|
||||
[PTHREAD_DESTRUCTOR_ITERATIONS] iterations of destructor calls for
|
||||
outstanding non-NULL values, there are still some non-NULL values with
|
||||
associated destructors, the implementation stops calling destructors.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_key_create
|
||||
function will store the newly created key value at the location specified by
|
||||
.Fa key
|
||||
and returns zero. Otherwise an error number will be returned to indicate
|
||||
the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_key_create
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EAGAIN
|
||||
The system lacked the necessary resources to create another thread-specific
|
||||
data key, or the system-imposed limit on the total number of keys per process
|
||||
[PTHREAD_KEYS_MAX] would be exceeded.
|
||||
.It Bq Er ENOMEM
|
||||
Insufficient memory exists to create the key.
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_getspecific 3 ,
|
||||
.Xr pthread_setspecific 3 ,
|
||||
.Xr pthread_key_delete 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_key_create
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
92
lib/libc_r/man/pthread_key_delete.3
Normal file
92
lib/libc_r/man/pthread_key_delete.3
Normal file
@ -0,0 +1,92 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_KEY_DELETE 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_key_delete
|
||||
.Nd delete a thread-specific data key
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_key_delete "pthread_key_t key"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_key_delete
|
||||
function deletes a thread-specific data key previously returned by
|
||||
.Fn pthread_key_create .
|
||||
The thread-specific data values associated with
|
||||
.Fa key
|
||||
need not be NULL at the time that
|
||||
.Fn pthread_key_delete
|
||||
is called. It is the responsibility of the application to free any
|
||||
application storage or perform any cleanup actions for data structures
|
||||
related to the deleted key or associated thread-specific data in any threads;
|
||||
this cleanup can be done either before or after
|
||||
.Fn pthread_key_delete
|
||||
is called. Any attempt to use
|
||||
.Fa key
|
||||
following the call to
|
||||
.Fn pthread_key_delete
|
||||
results in undefined behavior.
|
||||
.Pp
|
||||
The
|
||||
.Fn pthread_key_delete
|
||||
function is callable from within destructor functions. Destructor functions
|
||||
are not invoked by
|
||||
.Fn pthread_key_delete .
|
||||
Any destructor function that may have been associated with
|
||||
.Fa key
|
||||
will no longer be called upon thread exit.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_key_delete
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_key_delete
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The
|
||||
.Fa key
|
||||
value is invalid.
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_key_create 3 ,
|
||||
.Xr pthread_getspecific 3 ,
|
||||
.Xr pthread_setspecific 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_key_delete
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
100
lib/libc_r/man/pthread_once.3
Normal file
100
lib/libc_r/man/pthread_once.3
Normal file
@ -0,0 +1,100 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_ONCE 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_once
|
||||
.Nd dynamic package initialization
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Pp
|
||||
pthread_once
|
||||
.Fa once_control
|
||||
= PTHREAD_ONCE_INIT;
|
||||
.Ft int
|
||||
.Fn pthread_once "pthread_once_t *once_control" "void *(*init_routine)(void)"
|
||||
.Sh DESCRIPTION
|
||||
The first call to
|
||||
.Fn pthread_once
|
||||
by any thread in a process, with a given
|
||||
.Fa once_control ,
|
||||
will call the
|
||||
.Fn init_routine
|
||||
with no arguments. Subsequent calls to
|
||||
.Fn pthread_once
|
||||
with the same
|
||||
.Fa once_control
|
||||
will not call the
|
||||
.Fn init_routine .
|
||||
On return from
|
||||
.Fn pthread_once ,
|
||||
it is guaranteed that
|
||||
.Fn init_routine
|
||||
has completed. The
|
||||
.Fa once_control
|
||||
parameter is used to determine whether the associated initialization
|
||||
routine has been called.
|
||||
.Pp
|
||||
The function
|
||||
.Fn pthread_once
|
||||
is not a cancellation point. However, if
|
||||
.Fn init_routine
|
||||
is a cancellation point and is cancelled, the effect on
|
||||
.Fa once_control is as if
|
||||
.Fn pthread_once
|
||||
was never called.
|
||||
.Pp
|
||||
The constant
|
||||
.Fa PTHREAD_ONCE_INIT
|
||||
is defined by header
|
||||
.Aq Pa pthread.h .
|
||||
.Pp
|
||||
The behavior of
|
||||
.Fn pthread_once
|
||||
is undefined if
|
||||
.Fa once_control
|
||||
has automatic storage duration or is not initialized by
|
||||
.Fa PTHREAD_ONCE_INIT .
|
||||
.Pp
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_once
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
None.
|
||||
.Pp
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_once
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
59
lib/libc_r/man/pthread_self.3
Normal file
59
lib/libc_r/man/pthread_self.3
Normal file
@ -0,0 +1,59 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_SELF 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_self
|
||||
.Nd get the calling thread's ID
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft pthread_t
|
||||
.Fn pthread_self "void"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_self
|
||||
function returns the thread ID of the calling thread.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn pthread_self
|
||||
function returns the thread ID of the calling thread.
|
||||
.Sh ERRORS
|
||||
None.
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_create 3 ,
|
||||
.Xr pthread_equal 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_self
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
91
lib/libc_r/man/pthread_setspecific.3
Normal file
91
lib/libc_r/man/pthread_setspecific.3
Normal file
@ -0,0 +1,91 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_SETSPECIFIC 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_setspecific
|
||||
.Nd set a thread-specific data value
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_setspecific "pthread_key_t key" "const void *value"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_setspecific
|
||||
function associates a thread-specific value with a
|
||||
.Fa key
|
||||
obtained via a previous call to
|
||||
.Fn pthread_key_create .
|
||||
Different threads man bind different values to the same key. These values are
|
||||
typically pointers to blocks of dynamically allocated memory that have been
|
||||
reserved for use by the calling thread.
|
||||
.Pp
|
||||
The effect of calling
|
||||
.Fn pthread_setspecific
|
||||
with a key value not obtained from
|
||||
.Fn pthread_key_create
|
||||
or after
|
||||
.Fa key
|
||||
has been deleted with
|
||||
.Fn pthread_key_delete
|
||||
is undefined.
|
||||
.Pp
|
||||
.Fn pthread_setspecific
|
||||
may be called from a thread-specific data destructor function, however this
|
||||
may result in lost storage or infinite loops.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_setspecific
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_setspecific
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er ENOMEM
|
||||
Insufficient memory exists to associate the value with the
|
||||
.Fa key .
|
||||
.It Bq Er EINVAL
|
||||
The
|
||||
.Fa key
|
||||
value is invalid.
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_key_create 3 ,
|
||||
.Xr pthread_key_delete 3 ,
|
||||
.Xr pthread_getspecific 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_setspecific
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
@ -1,5 +1,4 @@
|
||||
# @(#)Makefile.inc 8.1 (Berkeley) 6/17/93
|
||||
# $Id: $
|
||||
|
||||
# sys sources
|
||||
.PATH: ${.CURDIR}/../libc/${MACHINE}/sys ${.CURDIR}/../libc/sys \
|
||||
@ -40,16 +39,18 @@ THREADASM= accept.o bind.o close.o connect.o dup.o dup2.o \
|
||||
shutdown.o sigaction.o sigaltstack.o socket.o socketpair.o \
|
||||
wait4.o write.o writev.o
|
||||
|
||||
PSEUDO= _exit.o _getlogin.o
|
||||
PSEUDO= _getlogin.o
|
||||
|
||||
OBJS+= ${ASM} ${THREADASM} ${PSEUDO}
|
||||
THREADPSEUDO= _exit.o
|
||||
|
||||
OBJS+= ${ASM} ${THREADASM} ${PSEUDO} ${THREADPSEUDO}
|
||||
|
||||
${ASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.o
|
||||
@printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
|
||||
@${LD} -x -r ${.PREFIX}.o
|
||||
@mv -f a.out ${.PREFIX}.o
|
||||
@mv a.out ${.PREFIX}.o
|
||||
|
||||
PASM= ${ASM:.o=.po}
|
||||
${PASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@ -57,7 +58,7 @@ ${PASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
|
||||
@${LD} -x -r ${.PREFIX}.po
|
||||
@mv -f a.out ${.PREFIX}.po
|
||||
@mv a.out ${.PREFIX}.po
|
||||
|
||||
SASM= ${ASM:.o=.so}
|
||||
${SASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@ -67,23 +68,23 @@ ${SASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
|
||||
${THREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.o
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
|
||||
@${LD} -x -r ${.PREFIX}.o
|
||||
@mv -f a.out ${.PREFIX}.o
|
||||
@mv a.out ${.PREFIX}.o
|
||||
|
||||
PTHREADASM= ${THREADASM:.o=.po}
|
||||
${PTHREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.po
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
|
||||
@${LD} -x -r ${.PREFIX}.po
|
||||
@mv -f a.out ${.PREFIX}.po
|
||||
@mv a.out ${.PREFIX}.po
|
||||
|
||||
STHREADASM= ${THREADASM:.o=.so}
|
||||
${STHREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.so
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
|
||||
|
||||
${PSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@ -91,7 +92,7 @@ ${PSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
|
||||
@${LD} -x -r ${.PREFIX}.o
|
||||
@mv -f a.out ${.PREFIX}.o
|
||||
@mv a.out ${.PREFIX}.o
|
||||
|
||||
PPSEUDO=${PSEUDO:.o=.po}
|
||||
${PPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@ -99,10 +100,31 @@ ${PPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
|
||||
@${LD} -x -r ${.PREFIX}.po
|
||||
@mv -f a.out ${.PREFIX}.po
|
||||
@mv a.out ${.PREFIX}.po
|
||||
|
||||
SPSEUDO=${PSEUDO:.o=.so}
|
||||
${SPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.so
|
||||
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
|
||||
|
||||
${THREADPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.o
|
||||
@printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
|
||||
@${LD} -x -r ${.PREFIX}.o
|
||||
@mv a.out ${.PREFIX}.o
|
||||
|
||||
THREADPPSEUDO=${THREADPSEUDO:.o=.po}
|
||||
${THREADPPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.po
|
||||
@printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
|
||||
@${LD} -x -r ${.PREFIX}.po
|
||||
@mv a.out ${.PREFIX}.po
|
||||
|
||||
THREADSPSEUDO=${THREADPSEUDO:.o=.so}
|
||||
${THREADSPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.so
|
||||
@printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile.inc,v 1.1 1996/01/22 00:23:03 julian Exp $
|
||||
# $Id: Makefile.inc,v 1.2 1996/02/17 02:19:35 jdp Exp $
|
||||
|
||||
CPLUSPLUSLIB= cpluspluslib
|
||||
|
||||
@ -7,7 +7,7 @@ CPLUSPLUSLIB= cpluspluslib
|
||||
|
||||
SRCS+= \
|
||||
uthread_accept.c \
|
||||
uthread_attr_setcreatesuspend.c \
|
||||
uthread_attr_setcreatesuspend_np.c \
|
||||
uthread_autoinit.cc \
|
||||
uthread_bind.c \
|
||||
uthread_clean.c \
|
||||
@ -52,7 +52,7 @@ SRCS+= \
|
||||
uthread_read.c \
|
||||
uthread_readv.c \
|
||||
uthread_recvfrom.c \
|
||||
uthread_resume.c \
|
||||
uthread_resume_np.c \
|
||||
uthread_select.c \
|
||||
uthread_self.c \
|
||||
uthread_sendto.c \
|
||||
@ -71,7 +71,7 @@ SRCS+= \
|
||||
uthread_socket.c \
|
||||
uthread_socketpair.c \
|
||||
uthread_spec.c \
|
||||
uthread_suspend.c \
|
||||
uthread_suspend_np.c \
|
||||
uthread_wait4.c \
|
||||
uthread_write.c \
|
||||
uthread_writev.c \
|
||||
|
@ -58,6 +58,129 @@
|
||||
*/
|
||||
#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
|
||||
|
||||
/*
|
||||
* Queue definitions.
|
||||
*/
|
||||
struct pthread_queue {
|
||||
struct pthread *q_next;
|
||||
struct pthread *q_last;
|
||||
void *q_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Static queue initialization values.
|
||||
*/
|
||||
#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL }
|
||||
|
||||
/*
|
||||
* Mutex definitions.
|
||||
*/
|
||||
enum pthread_mutextype {
|
||||
MUTEX_TYPE_FAST = 1,
|
||||
MUTEX_TYPE_COUNTING_FAST = 2, /* Recursive */
|
||||
MUTEX_TYPE_MAX
|
||||
};
|
||||
|
||||
union pthread_mutex_data {
|
||||
void *m_ptr;
|
||||
int m_count;
|
||||
};
|
||||
|
||||
struct pthread_mutex {
|
||||
enum pthread_mutextype m_type;
|
||||
struct pthread_queue m_queue;
|
||||
struct pthread *m_owner;
|
||||
union pthread_mutex_data m_data;
|
||||
long m_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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_INITIALIZER \
|
||||
{ MUTEX_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, \
|
||||
NULL, { NULL }, MUTEX_FLAGS_INITED }
|
||||
|
||||
struct pthread_mutex_attr {
|
||||
enum pthread_mutextype m_type;
|
||||
long m_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Condition variable definitions.
|
||||
*/
|
||||
enum pthread_cond_type {
|
||||
COND_TYPE_FAST,
|
||||
COND_TYPE_MAX
|
||||
};
|
||||
|
||||
struct pthread_cond {
|
||||
enum pthread_cond_type c_type;
|
||||
struct pthread_queue c_queue;
|
||||
void *c_data;
|
||||
long c_flags;
|
||||
};
|
||||
|
||||
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_INITIALIZER \
|
||||
{ COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, COND_FLAGS_INITED }
|
||||
|
||||
/*
|
||||
* Cleanup definitions.
|
||||
*/
|
||||
struct pthread_cleanup {
|
||||
struct pthread_cleanup *next;
|
||||
void (*routine) ();
|
||||
void *routine_arg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Scheduling definitions.
|
||||
*/
|
||||
enum schedparam_policy {
|
||||
SCHED_RR,
|
||||
SCHED_IO,
|
||||
SCHED_FIFO,
|
||||
SCHED_OTHER
|
||||
};
|
||||
|
||||
struct pthread_attr {
|
||||
enum schedparam_policy schedparam_policy;
|
||||
int prio;
|
||||
int suspend;
|
||||
int flags;
|
||||
void *arg_attr;
|
||||
void (*cleanup_attr) ();
|
||||
void *stackaddr_attr;
|
||||
size_t stacksize_attr;
|
||||
};
|
||||
|
||||
struct sched_param {
|
||||
int prio;
|
||||
void *no_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Thread creation state attributes.
|
||||
*/
|
||||
@ -67,14 +190,11 @@
|
||||
/*
|
||||
* Miscellaneous definitions.
|
||||
*/
|
||||
#define PTHREAD_STACK_MIN 1024
|
||||
#define PTHREAD_STACK_DEFAULT 65536
|
||||
#define PTHREAD_DATAKEYS_MAX 256
|
||||
#define PTHREAD_DEFAULT_PRIORITY 64
|
||||
#define PTHREAD_MAX_PRIORITY 126
|
||||
#define PTHREAD_MIN_PRIORITY 0
|
||||
#define _POSIX_THREAD_ATTR_STACKSIZE
|
||||
#define _POSIX_THREAD_DESTRUTOR_ITERATIONS 4
|
||||
|
||||
/*
|
||||
* Clock resolution in nanoseconds.
|
||||
@ -190,10 +310,10 @@ struct pthread {
|
||||
* Thread start routine, argument, stack pointer and thread
|
||||
* attributes.
|
||||
*/
|
||||
void *(*start_routine)(void *);
|
||||
void *arg;
|
||||
void *stack;
|
||||
pthread_attr_t attr;
|
||||
void *(*start_routine)(void *);
|
||||
void *arg;
|
||||
void *stack;
|
||||
struct pthread_attr attr;
|
||||
|
||||
/*
|
||||
* Thread-specific signal handler interface:
|
||||
@ -319,6 +439,17 @@ SCLASS struct pthread *_thread_run
|
||||
;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ptr to the thread running in single-threaded mode or NULL if
|
||||
* running multi-threaded (default POSIX behaviour).
|
||||
*/
|
||||
SCLASS struct pthread *_thread_single
|
||||
#ifdef GLOBAL_PTHREAD_PRIVATE
|
||||
= NULL;
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
|
||||
/* Ptr to the first thread in the thread linked list: */
|
||||
SCLASS struct pthread *_thread_link_list
|
||||
#ifdef GLOBAL_PTHREAD_PRIVATE
|
||||
@ -372,7 +503,7 @@ SCLASS struct pthread *_thread_initial
|
||||
#endif
|
||||
|
||||
/* Default thread attributes: */
|
||||
SCLASS pthread_attr_t pthread_attr_default
|
||||
SCLASS struct pthread_attr pthread_attr_default
|
||||
#ifdef GLOBAL_PTHREAD_PRIVATE
|
||||
= { SCHED_RR, PTHREAD_DEFAULT_PRIORITY, PTHREAD_CREATE_RUNNING,
|
||||
PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, PTHREAD_STACK_DEFAULT };
|
||||
@ -570,6 +701,7 @@ pid_t _thread_sys_fork(void);
|
||||
pid_t _thread_sys_tcgetpgrp(int);
|
||||
ssize_t _thread_sys_read(int, void *, size_t);
|
||||
ssize_t _thread_sys_write(int, const void *, size_t);
|
||||
void _thread_sys__exit(int);
|
||||
#endif
|
||||
|
||||
/* #include <fcntl.h> */
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
|
52
lib/libc_r/uthread/uthread_attr_destroy.c
Normal file
52
lib/libc_r/uthread/uthread_attr_destroy.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_attr_destroy(pthread_attr_t *attr)
|
||||
{
|
||||
int ret;
|
||||
if (attr == NULL || *attr == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
free(*attr);
|
||||
*attr = NULL;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
54
lib/libc_r/uthread/uthread_attr_init.c
Normal file
54
lib/libc_r/uthread/uthread_attr_init.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_attr_init(pthread_attr_t *attr)
|
||||
{
|
||||
int ret;
|
||||
pthread_attr_t pattr;
|
||||
if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
ret = -1;
|
||||
} else {
|
||||
memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr));
|
||||
*attr = pattr;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_attr_setcreatesuspend(pthread_attr_t *attr)
|
||||
{
|
||||
attr->suspend = PTHREAD_CREATE_SUSPENDED;
|
||||
return(0);
|
||||
}
|
||||
#endif
|
51
lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c
Normal file
51
lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
|
||||
{
|
||||
int ret;
|
||||
if (attr == NULL || *attr == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
(*attr)->suspend = PTHREAD_CREATE_SUSPENDED;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
50
lib/libc_r/uthread/uthread_attr_setprio.c
Normal file
50
lib/libc_r/uthread/uthread_attr_setprio.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_attr_setprio(pthread_attr_t *attr, int priority)
|
||||
{
|
||||
int ret;
|
||||
if (attr == NULL || *attr == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
(*attr)->prio = priority;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
50
lib/libc_r/uthread/uthread_attr_setstacksize.c
Normal file
50
lib/libc_r/uthread/uthread_attr_setstacksize.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
|
||||
{
|
||||
int ret;
|
||||
if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
(*attr)->stacksize_attr = stacksize;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
@ -30,7 +30,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
@ -38,10 +41,55 @@
|
||||
int
|
||||
close(int fd)
|
||||
{
|
||||
int ret;
|
||||
int flags;
|
||||
int ret;
|
||||
int status;
|
||||
struct stat sb;
|
||||
|
||||
/* Lock the file descriptor while the file is closed: */
|
||||
if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Get file descriptor status. */
|
||||
fstat(fd, &sb);
|
||||
|
||||
/*
|
||||
* Check if the file should be left as blocking.
|
||||
*
|
||||
* This is so that the file descriptors shared with a parent
|
||||
* process aren't left set to non-blocking if the child
|
||||
* closes them prior to exit. An example where this causes
|
||||
* problems with /bin/sh is when a child closes stdin.
|
||||
*
|
||||
* Setting a file as blocking causes problems if a threaded
|
||||
* parent accesses the file descriptor before the child exits.
|
||||
* Once the threaded parent receives a SIGCHLD then it resets
|
||||
* all of its files to non-blocking, and so it is then safe
|
||||
* to access them.
|
||||
*
|
||||
* Pipes are not set to blocking when they are closed, as
|
||||
* the parent and child will normally close the file
|
||||
* descriptor of the end of the pipe that they are not
|
||||
* using, which would then cause any reads to block
|
||||
* indefinitely.
|
||||
*/
|
||||
if ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0) {
|
||||
/* Get the current flags: */
|
||||
flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
|
||||
/* Clear the nonblocking file descriptor flag: */
|
||||
_thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
/* Close the file descriptor: */
|
||||
ret = _thread_sys_close(fd);
|
||||
_thread_fd_unlock(fd, FD_RDWR);
|
||||
|
||||
/* Free the file descriptor table entry: */
|
||||
free(_thread_fd_table[fd]);
|
||||
_thread_fd_table[fd] = NULL;
|
||||
|
||||
/* Unblock signals again: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
@ -40,41 +40,56 @@ 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;
|
||||
|
||||
/*
|
||||
* Check if a pointer to a condition variable attribute structure was
|
||||
* passed by the caller:
|
||||
*/
|
||||
if (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: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
/* Check for no errors: */
|
||||
if (rval == 0) {
|
||||
/* Initialise the condition variable structure: */
|
||||
_thread_queue_init(&cond->c_queue);
|
||||
cond->c_flags |= COND_FLAGS_INITED;
|
||||
cond->c_type = type;
|
||||
/* 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: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for no errors: */
|
||||
if (rval == 0) {
|
||||
if ((pcond = (pthread_cond_t) malloc(sizeof(struct pthread_cond))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
rval = -1;
|
||||
} else {
|
||||
/*
|
||||
* Initialise the condition variable
|
||||
* structure:
|
||||
*/
|
||||
_thread_queue_init(&pcond->c_queue);
|
||||
pcond->c_flags |= COND_FLAGS_INITED;
|
||||
pcond->c_type = type;
|
||||
*cond = pcond;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -85,26 +100,33 @@ pthread_cond_destroy(pthread_cond_t * cond)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL || *cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Process according to condition variable type: */
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Check for errors: */
|
||||
if (rval == 0) {
|
||||
/* Destroy the contents of the condition structure: */
|
||||
_thread_queue_init(&cond->c_queue);
|
||||
cond->c_flags = 0;
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for errors: */
|
||||
if (rval == 0) {
|
||||
/* Destroy the contents of the condition structure: */
|
||||
_thread_queue_init(&(*cond)->c_queue);
|
||||
(*cond)->c_flags = 0;
|
||||
free(*cond);
|
||||
*cond = NULL;
|
||||
}
|
||||
}
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -116,39 +138,44 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
|
||||
int rval = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Queue the running thread for the condition variable: */
|
||||
_thread_queue_enq(&cond->c_queue, _thread_run);
|
||||
|
||||
/* Unlock the mutex: */
|
||||
pthread_mutex_unlock(mutex);
|
||||
|
||||
/* Schedule the next thread: */
|
||||
_thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
|
||||
/* Lock the mutex: */
|
||||
rval = pthread_mutex_lock(mutex);
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL || *cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Process according to condition variable type: */
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Queue the running thread for the condition variable: */
|
||||
_thread_queue_enq(&(*cond)->c_queue, _thread_run);
|
||||
|
||||
/* Unlock the mutex: */
|
||||
pthread_mutex_unlock(mutex);
|
||||
|
||||
/* Schedule the next thread: */
|
||||
_thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
|
||||
/* Lock the mutex: */
|
||||
rval = pthread_mutex_lock(mutex);
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -161,59 +188,69 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||
int rval = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Set the wakeup time: */
|
||||
_thread_run->wakeup_time.ts_sec = abstime->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = abstime->ts_nsec;
|
||||
|
||||
/* Reset the timeout flag: */
|
||||
_thread_run->timeout = 0;
|
||||
|
||||
/* Queue the running thread for the condition variable: */
|
||||
_thread_queue_enq(&cond->c_queue, _thread_run);
|
||||
|
||||
/* Unlock the mutex: */
|
||||
if ((rval = pthread_mutex_unlock(mutex)) != 0) {
|
||||
/*
|
||||
* Cannot unlock the mutex, so remove the running
|
||||
* thread from the condition variable queue:
|
||||
*/
|
||||
_thread_queue_deq(&cond->c_queue);
|
||||
} else {
|
||||
/* Schedule the next thread: */
|
||||
_thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
|
||||
/* Lock the mutex: */
|
||||
if ((rval = pthread_mutex_lock(mutex)) != 0) {
|
||||
}
|
||||
/* Check if the wait timed out: */
|
||||
else if (_thread_run->timeout) {
|
||||
/* Return a timeout error: */
|
||||
_thread_seterrno(_thread_run, EAGAIN);
|
||||
rval = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL || *cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Process according to condition variable type: */
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Set the wakeup time: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = abstime->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = abstime->ts_nsec;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = abstime->tv_sec;
|
||||
_thread_run->wakeup_time.tv_nsec = abstime->tv_nsec;
|
||||
#endif
|
||||
|
||||
/* Reset the timeout flag: */
|
||||
_thread_run->timeout = 0;
|
||||
|
||||
/* Queue the running thread for the condition variable: */
|
||||
_thread_queue_enq(&(*cond)->c_queue, _thread_run);
|
||||
|
||||
/* Unlock the mutex: */
|
||||
if ((rval = pthread_mutex_unlock(mutex)) != 0) {
|
||||
/*
|
||||
* Cannot unlock the mutex, so remove the running
|
||||
* thread from the condition variable queue:
|
||||
*/
|
||||
_thread_queue_deq(&(*cond)->c_queue);
|
||||
} else {
|
||||
/* Schedule the next thread: */
|
||||
_thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
|
||||
/* Lock the mutex: */
|
||||
if ((rval = pthread_mutex_lock(mutex)) != 0) {
|
||||
}
|
||||
/* Check if the wait timed out: */
|
||||
else if (_thread_run->timeout) {
|
||||
/* Return a timeout error: */
|
||||
errno = EAGAIN;
|
||||
rval = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -226,30 +263,35 @@ pthread_cond_signal(pthread_cond_t * cond)
|
||||
int status;
|
||||
pthread_t pthread;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Bring the next thread off the condition queue: */
|
||||
if ((pthread = _thread_queue_deq(&cond->c_queue)) != NULL) {
|
||||
/* Allow the thread to run: */
|
||||
pthread->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL || *cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Process according to condition variable type: */
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Bring the next thread off the condition queue: */
|
||||
if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
|
||||
/* Allow the thread to run: */
|
||||
pthread->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -266,11 +308,11 @@ pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Enter a loop to bring all threads off the condition queue: */
|
||||
while ((pthread = _thread_queue_deq(&cond->c_queue)) != NULL) {
|
||||
while ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
|
||||
/* Allow the thread to run: */
|
||||
pthread->state = PS_RUNNING;
|
||||
}
|
||||
@ -279,7 +321,7 @@ pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
int ret = 0;
|
||||
int status;
|
||||
pthread_t new_thread;
|
||||
pthread_attr_t pattr;
|
||||
void *stack;
|
||||
|
||||
/* Block signals: */
|
||||
@ -60,15 +61,17 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
ret = EAGAIN;
|
||||
} else {
|
||||
/* Check if default thread attributes are required: */
|
||||
if (attr == NULL) {
|
||||
if (attr == NULL || *attr == NULL) {
|
||||
/* Use the default thread attributes: */
|
||||
attr = &pthread_attr_default;
|
||||
pattr = &pthread_attr_default;
|
||||
} else {
|
||||
pattr = *attr;
|
||||
}
|
||||
/* Check if a stack was specified in the thread attributes: */
|
||||
if ((stack = attr->stackaddr_attr) != NULL) {
|
||||
if ((stack = pattr->stackaddr_attr) != NULL) {
|
||||
}
|
||||
/* Allocate memory for the stack: */
|
||||
else if ((stack = (void *) malloc(attr->stacksize_attr)) == NULL) {
|
||||
else if ((stack = (void *) malloc(pattr->stacksize_attr)) == NULL) {
|
||||
/* Insufficient memory to create a thread: */
|
||||
ret = EAGAIN;
|
||||
free(new_thread);
|
||||
@ -83,7 +86,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
new_thread->stack = stack;
|
||||
new_thread->start_routine = start_routine;
|
||||
new_thread->arg = arg;
|
||||
if (attr->suspend == PTHREAD_CREATE_SUSPENDED) {
|
||||
if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) {
|
||||
new_thread->state = PS_SUSPENDED;
|
||||
} else {
|
||||
new_thread->state = PS_RUNNING;
|
||||
@ -148,19 +151,19 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
|
||||
/* The stack starts high and builds down: */
|
||||
#if defined(__FreeBSD__)
|
||||
new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + attr->stacksize_attr - sizeof(double));
|
||||
new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + pattr->stacksize_attr - sizeof(double));
|
||||
#elif defined(__NetBSD__)
|
||||
#if defined(__alpha)
|
||||
new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + attr->stacksize_attr - sizeof(double);
|
||||
new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
|
||||
#else
|
||||
new_thread->saved_jmp_buf[2] = (long) new_thread->stack + attr->stacksize_attr - sizeof(double);
|
||||
new_thread->saved_jmp_buf[2] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
|
||||
#endif
|
||||
#else
|
||||
#error "Don't recognize this operating system!"
|
||||
#endif
|
||||
|
||||
/* Copy the thread attributes: */
|
||||
memcpy(&new_thread->attr, attr, sizeof(pthread_attr_t));
|
||||
memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
|
||||
|
||||
/*
|
||||
* Check if this thread is to inherit the scheduling
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
@ -39,15 +40,39 @@
|
||||
int
|
||||
execve(const char *name, char *const * argv, char *const * envp)
|
||||
{
|
||||
int flags;
|
||||
int i;
|
||||
int ret;
|
||||
struct sigaction act;
|
||||
struct sigaction oact;
|
||||
struct itimerval itimer;
|
||||
|
||||
/* Disable the interval timer: */
|
||||
itimer.it_interval.tv_sec = 0;
|
||||
itimer.it_interval.tv_usec = 0;
|
||||
itimer.it_value.tv_sec = 0;
|
||||
itimer.it_value.tv_usec = 0;
|
||||
setitimer(ITIMER_VIRTUAL, &itimer, NULL);
|
||||
|
||||
/* Close the pthread kernel pipe: */
|
||||
_thread_sys_close(_thread_kern_pipe[0]);
|
||||
_thread_sys_close(_thread_kern_pipe[1]);
|
||||
|
||||
/*
|
||||
* Enter a loop to set all file descriptors to blocking
|
||||
* if they were not created as non-blocking:
|
||||
*/
|
||||
for (i = 0; i < _thread_dtablesize; i++) {
|
||||
/* Check if this file descriptor is in use: */
|
||||
if (_thread_fd_table[i] != NULL &&
|
||||
!(_thread_fd_table[i]->flags & O_NONBLOCK)) {
|
||||
/* Get the current flags: */
|
||||
flags = _thread_sys_fcntl(i, F_GETFL, NULL);
|
||||
/* Clear the nonblocking file descriptor flag: */
|
||||
_thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter a loop to adopt the signal actions for the running thread: */
|
||||
for (i = 1; i < NSIG; i++) {
|
||||
/* Check for signals which cannot be caught: */
|
||||
|
@ -31,11 +31,49 @@
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
void _exit(int status)
|
||||
{
|
||||
int flags;
|
||||
int i;
|
||||
struct itimerval itimer;
|
||||
|
||||
/* Disable the interval timer: */
|
||||
itimer.it_interval.tv_sec = 0;
|
||||
itimer.it_interval.tv_usec = 0;
|
||||
itimer.it_value.tv_sec = 0;
|
||||
itimer.it_value.tv_usec = 0;
|
||||
setitimer(ITIMER_VIRTUAL, &itimer, NULL);
|
||||
|
||||
/* Close the pthread kernel pipe: */
|
||||
_thread_sys_close(_thread_kern_pipe[0]);
|
||||
_thread_sys_close(_thread_kern_pipe[1]);
|
||||
|
||||
/*
|
||||
* Enter a loop to set all file descriptors to blocking
|
||||
* if they were not created as non-blocking:
|
||||
*/
|
||||
for (i = 0; i < _thread_dtablesize; i++) {
|
||||
/* Check if this file descriptor is in use: */
|
||||
if (_thread_fd_table[i] != NULL &&
|
||||
!(_thread_fd_table[i]->flags & O_NONBLOCK)) {
|
||||
/* Get the current flags: */
|
||||
flags = _thread_sys_fcntl(i, F_GETFL, NULL);
|
||||
/* Clear the nonblocking file descriptor flag: */
|
||||
_thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the _exit syscall: */
|
||||
_thread_sys__exit(status);
|
||||
}
|
||||
|
||||
void
|
||||
_thread_exit(char *fname, int lineno, char *string)
|
||||
{
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
@ -48,7 +49,7 @@ _thread_fd_table_init(int fd)
|
||||
/* Check if the file descriptor is out of range: */
|
||||
if (fd < 0 || fd >= _thread_dtablesize) {
|
||||
/* Return a bad file descriptor error: */
|
||||
_thread_seterrno(_thread_run, EBADF);
|
||||
errno = EBADF;
|
||||
ret = -1;
|
||||
}
|
||||
/*
|
||||
@ -60,7 +61,7 @@ _thread_fd_table_init(int fd)
|
||||
/* Allocate memory for the file descriptor table entry: */
|
||||
else if ((_thread_fd_table[fd] = (struct fd_table_entry *) malloc(sizeof(struct fd_table_entry))) == NULL) {
|
||||
/* Return a bad file descriptor error: */
|
||||
_thread_seterrno(_thread_run, EBADF);
|
||||
errno = EBADF;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Initialise the file locks: */
|
||||
@ -73,12 +74,25 @@ _thread_fd_table_init(int fd)
|
||||
_thread_fd_table[fd]->r_lockcount = 0;;
|
||||
_thread_fd_table[fd]->w_lockcount = 0;;
|
||||
|
||||
/* Default the flags: */
|
||||
_thread_fd_table[fd]->flags = 0;
|
||||
|
||||
/* Initialise the read/write queues: */
|
||||
_thread_queue_init(&_thread_fd_table[fd]->r_queue);
|
||||
_thread_queue_init(&_thread_fd_table[fd]->w_queue);
|
||||
|
||||
/* Get the flags for the file: */
|
||||
if ((_thread_fd_table[fd]->flags = _thread_sys_fcntl(fd, F_GETFL, 0)) == -1) {
|
||||
ret = -1;
|
||||
|
||||
/* Make the file descriptor non-blocking: */
|
||||
} else {
|
||||
_thread_sys_fcntl(fd, F_SETFL, _thread_fd_table[fd]->flags | O_NONBLOCK);
|
||||
}
|
||||
|
||||
/* Check if one of the fcntl calls failed: */
|
||||
if (ret == -1) {
|
||||
/* Free the file descriptor table entry: */
|
||||
free(_thread_fd_table[fd]);
|
||||
_thread_fd_table[fd] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
|
@ -31,6 +31,8 @@
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
|
@ -202,18 +202,6 @@ _thread_main(int argc, char *argv[], char *env)
|
||||
_thread_init();
|
||||
return (main(argc, argv, env));
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Force our auto-initialization module to be pulled in from the library,
|
||||
* by referencing a symbol that is defined in it.
|
||||
*
|
||||
* The auto-initialization module is a small C++ module. It has a static
|
||||
* constructor that calls _thread_init() automatically, at the beginning
|
||||
* of program execution. That eliminates the need for any special hooks
|
||||
* in crt0.o.
|
||||
*/
|
||||
extern int _thread_autoinit_dummy_decl;
|
||||
static int *_thread_autoinit_dummy_ref = &_thread_autoinit_dummy_decl;
|
||||
#endif
|
||||
#else
|
||||
/*
|
||||
|
@ -250,18 +250,30 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
pthread->state == PS_FDW_WAIT ||
|
||||
pthread->state == PS_SELECT_WAIT) {
|
||||
/* Check if this thread is to wait forever: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (pthread->wakeup_time.ts_sec == -1) {
|
||||
#else
|
||||
if (pthread->wakeup_time.tv_sec == -1) {
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check if this thread is to wakeup
|
||||
* immediately or if it is past its wakeup
|
||||
* time:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
else if ((pthread->wakeup_time.ts_sec == 0 &&
|
||||
pthread->wakeup_time.ts_nsec == 0) ||
|
||||
(ts.ts_sec > pthread->wakeup_time.ts_sec) ||
|
||||
((ts.ts_sec == pthread->wakeup_time.ts_sec) &&
|
||||
(ts.ts_nsec >= pthread->wakeup_time.ts_nsec))) {
|
||||
#else
|
||||
else if ((pthread->wakeup_time.tv_sec == 0 &&
|
||||
pthread->wakeup_time.tv_nsec == 0) ||
|
||||
(ts.tv_sec > pthread->wakeup_time.tv_sec) ||
|
||||
((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
|
||||
(ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) {
|
||||
#endif
|
||||
/*
|
||||
* Check if this thread is waiting on
|
||||
* select:
|
||||
@ -364,9 +376,48 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
}
|
||||
/*
|
||||
* Enter a loop to look for the first thread of the highest
|
||||
* priority:
|
||||
* priority that is ready to run:
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
|
||||
/* Check if in single-threaded mode: */
|
||||
if (_thread_single != NULL) {
|
||||
/*
|
||||
* Check if the current thread is
|
||||
* the thread for which single-threaded
|
||||
* mode is enabled:
|
||||
*/
|
||||
if (pthread == _thread_single) {
|
||||
/*
|
||||
* This thread is allowed
|
||||
* to run.
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* Walk up the signal handler
|
||||
* parent thread tree to see
|
||||
* if the current thread is
|
||||
* descended from the thread
|
||||
* for which single-threaded
|
||||
* mode is enabled.
|
||||
*/
|
||||
pthread_nxt = pthread;
|
||||
while(pthread_nxt != NULL &&
|
||||
pthread_nxt != _thread_single) {
|
||||
pthread_nxt = pthread->parent_thread;
|
||||
}
|
||||
/*
|
||||
* Check if the current
|
||||
* thread is not descended
|
||||
* from the thread for which
|
||||
* single-threaded mode is
|
||||
* enabled.
|
||||
*/
|
||||
if (pthread_nxt == NULL)
|
||||
/* Ignore this thread. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the current thread is unable to run: */
|
||||
if (pthread->state != PS_RUNNING) {
|
||||
}
|
||||
@ -392,6 +443,45 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* least recently.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
|
||||
/* Check if in single-threaded mode: */
|
||||
if (_thread_single != NULL) {
|
||||
/*
|
||||
* Check if the current thread is
|
||||
* the thread for which single-threaded
|
||||
* mode is enabled:
|
||||
*/
|
||||
if (pthread == _thread_single) {
|
||||
/*
|
||||
* This thread is allowed
|
||||
* to run.
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* Walk up the signal handler
|
||||
* parent thread tree to see
|
||||
* if the current thread is
|
||||
* descended from the thread
|
||||
* for which single-threaded
|
||||
* mode is enabled.
|
||||
*/
|
||||
pthread_nxt = pthread;
|
||||
while(pthread_nxt != NULL &&
|
||||
pthread_nxt != _thread_single) {
|
||||
pthread_nxt = pthread->parent_thread;
|
||||
}
|
||||
/*
|
||||
* Check if the current
|
||||
* thread is not descended
|
||||
* from the thread for which
|
||||
* single-threaded mode is
|
||||
* enabled.
|
||||
*/
|
||||
if (pthread_nxt == NULL)
|
||||
/* Ignore this thread. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the current thread is unable to run: */
|
||||
if (pthread->state != PS_RUNNING) {
|
||||
/* Ignore threads that are not ready to run. */
|
||||
@ -446,6 +536,45 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* priority. 3. Became inactive least recently.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
|
||||
/* Check if in single-threaded mode: */
|
||||
if (_thread_single != NULL) {
|
||||
/*
|
||||
* Check if the current thread is
|
||||
* the thread for which single-threaded
|
||||
* mode is enabled:
|
||||
*/
|
||||
if (pthread == _thread_single) {
|
||||
/*
|
||||
* This thread is allowed
|
||||
* to run.
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* Walk up the signal handler
|
||||
* parent thread tree to see
|
||||
* if the current thread is
|
||||
* descended from the thread
|
||||
* for which single-threaded
|
||||
* mode is enabled.
|
||||
*/
|
||||
pthread_nxt = pthread;
|
||||
while(pthread_nxt != NULL &&
|
||||
pthread_nxt != _thread_single) {
|
||||
pthread_nxt = pthread->parent_thread;
|
||||
}
|
||||
/*
|
||||
* Check if the current
|
||||
* thread is not descended
|
||||
* from the thread for which
|
||||
* single-threaded mode is
|
||||
* enabled.
|
||||
*/
|
||||
if (pthread_nxt == NULL)
|
||||
/* Ignore this thread. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the current thread is unable to
|
||||
* run:
|
||||
@ -565,22 +694,37 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* Check if this thread is to
|
||||
* wait forever:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (pthread->wakeup_time.ts_sec == -1) {
|
||||
#else
|
||||
if (pthread->wakeup_time.tv_sec == -1) {
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check if this thread is to
|
||||
* wakeup immediately:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
else if (pthread->wakeup_time.ts_sec == 0 &&
|
||||
pthread->wakeup_time.ts_nsec == 0) {
|
||||
#else
|
||||
else if (pthread->wakeup_time.tv_sec == 0 &&
|
||||
pthread->wakeup_time.tv_nsec == 0) {
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check if the current time
|
||||
* is after the wakeup time:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
else if ((ts.ts_sec > pthread->wakeup_time.ts_sec) ||
|
||||
((ts.ts_sec == pthread->wakeup_time.ts_sec) &&
|
||||
(ts.ts_nsec > pthread->wakeup_time.ts_nsec))) {
|
||||
#else
|
||||
else if ((ts.tv_sec > pthread->wakeup_time.tv_sec) ||
|
||||
((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
|
||||
(ts.tv_nsec > pthread->wakeup_time.tv_nsec))) {
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* Calculate the time
|
||||
@ -589,16 +733,26 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* for the clock
|
||||
* resolution:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec = pthread->wakeup_time.ts_sec - ts.ts_sec;
|
||||
ts1.ts_nsec = pthread->wakeup_time.ts_nsec - ts.ts_nsec +
|
||||
CLOCK_RES_NSEC;
|
||||
#else
|
||||
ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
|
||||
ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
|
||||
CLOCK_RES_NSEC;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for
|
||||
* underflow of the
|
||||
* nanosecond field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (ts1.ts_nsec < 0) {
|
||||
#else
|
||||
if (ts1.tv_nsec < 0) {
|
||||
#endif
|
||||
/*
|
||||
* Allow for
|
||||
* the
|
||||
@ -607,15 +761,24 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec--;
|
||||
ts1.ts_nsec += 1000000000;
|
||||
#else
|
||||
ts1.tv_sec--;
|
||||
ts1.tv_nsec += 1000000000;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check for overflow
|
||||
* of the nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (ts1.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (ts1.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/*
|
||||
* Allow for
|
||||
* the
|
||||
@ -624,8 +787,13 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec++;
|
||||
ts1.ts_nsec -= 1000000000;
|
||||
#else
|
||||
ts1.tv_sec++;
|
||||
ts1.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Convert the
|
||||
@ -1100,11 +1268,20 @@ _thread_kern_select(int wait_reqd)
|
||||
*/
|
||||
if (wait_reqd && settimeout) {
|
||||
/* Check if this thread wants to wait forever: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (pthread->wakeup_time.ts_sec == -1) {
|
||||
#else
|
||||
if (pthread->wakeup_time.tv_sec == -1) {
|
||||
#endif
|
||||
}
|
||||
/* Check if this thread doesn't want to wait at all: */
|
||||
#if defined(__FreeBSD__)
|
||||
else if (pthread->wakeup_time.ts_sec == 0 &&
|
||||
pthread->wakeup_time.ts_nsec == 0) {
|
||||
#else
|
||||
else if (pthread->wakeup_time.tv_sec == 0 &&
|
||||
pthread->wakeup_time.tv_nsec == 0) {
|
||||
#endif
|
||||
/* Override the caller's request to wait: */
|
||||
wait_reqd = 0;
|
||||
} else {
|
||||
@ -1112,33 +1289,57 @@ _thread_kern_select(int wait_reqd)
|
||||
* Calculate the time until this thread is
|
||||
* ready, allowing for the clock resolution:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec = pthread->wakeup_time.ts_sec - ts.ts_sec;
|
||||
ts1.ts_nsec = pthread->wakeup_time.ts_nsec - ts.ts_nsec +
|
||||
CLOCK_RES_NSEC;
|
||||
#else
|
||||
ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
|
||||
ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
|
||||
CLOCK_RES_NSEC;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for underflow of the nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (ts1.ts_nsec < 0) {
|
||||
#else
|
||||
if (ts1.tv_nsec < 0) {
|
||||
#endif
|
||||
/*
|
||||
* Allow for the underflow of the
|
||||
* nanosecond field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec--;
|
||||
ts1.ts_nsec += 1000000000;
|
||||
#else
|
||||
ts1.tv_sec--;
|
||||
ts1.tv_nsec += 1000000000;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check for overflow of the nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (ts1.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (ts1.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/*
|
||||
* Allow for the overflow of the
|
||||
* nanosecond field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec++;
|
||||
ts1.ts_nsec -= 1000000000;
|
||||
#else
|
||||
ts1.tv_sec++;
|
||||
ts1.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Convert the timespec structure to a
|
||||
@ -1552,28 +1753,56 @@ _thread_kern_set_timeout(struct timespec * timeout)
|
||||
* Set the wakeup time to something that can be recognised as
|
||||
* different to an actual time of day:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = -1;
|
||||
_thread_run->wakeup_time.ts_nsec = -1;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = -1;
|
||||
_thread_run->wakeup_time.tv_nsec = -1;
|
||||
#endif
|
||||
}
|
||||
/* Check if no waiting is required: */
|
||||
#if defined(__FreeBSD__)
|
||||
else if (timeout->ts_sec == 0 && timeout->ts_nsec == 0) {
|
||||
#else
|
||||
else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
|
||||
#endif
|
||||
/* Set the wake up time to 'immediately': */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = 0;
|
||||
_thread_run->wakeup_time.ts_nsec = 0;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = 0;
|
||||
_thread_run->wakeup_time.tv_nsec = 0;
|
||||
#endif
|
||||
} else {
|
||||
/* Get the current time: */
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ¤t_time);
|
||||
|
||||
/* Calculate the time for the current thread to wake up: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = current_time.ts_sec + timeout->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + timeout->ts_nsec;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
|
||||
_thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec;
|
||||
#endif
|
||||
|
||||
/* Check if the nanosecond field needs to wrap: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/* Wrap the nanosecond field: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec += 1;
|
||||
_thread_run->wakeup_time.ts_nsec -= 1000000000;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec += 1;
|
||||
_thread_run->wakeup_time.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
44
lib/libc_r/uthread/uthread_multi_np.c
Normal file
44
lib/libc_r/uthread/uthread_multi_np.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_multi_np()
|
||||
{
|
||||
/* Return to multi-threaded scheduling mode: */
|
||||
_thread_single = NULL;
|
||||
return(0);
|
||||
}
|
||||
#endif
|
@ -41,62 +41,75 @@ pthread_mutex_init(pthread_mutex_t * mutex,
|
||||
const pthread_mutexattr_t * mutex_attr)
|
||||
{
|
||||
enum pthread_mutextype type;
|
||||
pthread_mutex_t pmutex;
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Check if the mutex attributes specify some mutex other than fast: */
|
||||
if (mutex_attr != NULL && mutex_attr->m_type != MUTEX_TYPE_FAST) {
|
||||
/* Check if the mutex type is out of range: */
|
||||
if (mutex_attr->m_type >= MUTEX_TYPE_MAX) {
|
||||
if (mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Check if default mutex attributes: */
|
||||
if (mutex_attr == NULL || *mutex_attr == NULL) {
|
||||
/* Default to a fast mutex: */
|
||||
type = MUTEX_TYPE_FAST;
|
||||
} else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) {
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Use the requested mutex type: */
|
||||
type = mutex_attr->m_type;
|
||||
}
|
||||
} else {
|
||||
/* Default to a fast mutex: */
|
||||
type = MUTEX_TYPE_FAST;
|
||||
}
|
||||
|
||||
/* Check no errors so far: */
|
||||
if (ret == 0) {
|
||||
/* Reset the mutex flags: */
|
||||
mutex->m_flags = 0;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Reset the mutex count: */
|
||||
mutex->m_data.m_count = 0;
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
type = (*mutex_attr)->m_type;
|
||||
}
|
||||
|
||||
/* Initialise the rest of the mutex: */
|
||||
_thread_queue_init(&mutex->m_queue);
|
||||
mutex->m_flags |= MUTEX_FLAGS_INITED;
|
||||
mutex->m_owner = NULL;
|
||||
mutex->m_type = type;
|
||||
/* Check no errors so far: */
|
||||
if (ret == 0) {
|
||||
if ((pmutex = (pthread_mutex_t) malloc(sizeof(struct pthread_mutex))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Reset the mutex flags: */
|
||||
pmutex->m_flags = 0;
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Reset the mutex count: */
|
||||
pmutex->m_data.m_count = 0;
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Initialise the rest of the mutex: */
|
||||
_thread_queue_init(&pmutex->m_queue);
|
||||
pmutex->m_flags |= MUTEX_FLAGS_INITED;
|
||||
pmutex->m_owner = NULL;
|
||||
pmutex->m_type = type;
|
||||
*mutex = pmutex;
|
||||
} else {
|
||||
free(pmutex);
|
||||
*mutex = NULL;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
@ -108,38 +121,43 @@ pthread_mutex_destroy(pthread_mutex_t * mutex)
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (mutex->m_type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Reset the mutex count: */
|
||||
mutex->m_data.m_count = 0;
|
||||
break;
|
||||
|
||||
/* Trap undefined mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch ((*mutex)->m_type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Reset the mutex count: */
|
||||
(*mutex)->m_data.m_count = 0;
|
||||
break;
|
||||
|
||||
/* Trap undefined mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clean up the mutex in case that others want to use it: */
|
||||
_thread_queue_init(&(*mutex)->m_queue);
|
||||
(*mutex)->m_owner = NULL;
|
||||
(*mutex)->m_flags = 0;
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Clean up the mutex in case that others want to use it: */
|
||||
_thread_queue_init(&mutex->m_queue);
|
||||
mutex->m_owner = NULL;
|
||||
mutex->m_flags = 0;
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
}
|
||||
@ -150,56 +168,61 @@ pthread_mutex_trylock(pthread_mutex_t * mutex)
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (mutex->m_type) {
|
||||
/* Process according to mutex type: */
|
||||
switch ((*mutex)->m_type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Check if this mutex is not locked: */
|
||||
if (mutex->m_owner == NULL) {
|
||||
/* Lock the mutex for the running thread: */
|
||||
mutex->m_owner = _thread_run;
|
||||
} else {
|
||||
/* Return a busy error: */
|
||||
_thread_seterrno(_thread_run, EBUSY);
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Check if this mutex is locked: */
|
||||
if (mutex->m_owner != NULL) {
|
||||
/*
|
||||
* Check if the mutex is locked by the running
|
||||
* thread:
|
||||
*/
|
||||
if (mutex->m_owner == _thread_run) {
|
||||
/* Increment the lock count: */
|
||||
mutex->m_data.m_count++;
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Check if this mutex is not locked: */
|
||||
if ((*mutex)->m_owner == NULL) {
|
||||
/* Lock the mutex for the running thread: */
|
||||
(*mutex)->m_owner = _thread_run;
|
||||
} else {
|
||||
/* Return a busy error: */
|
||||
_thread_seterrno(_thread_run, EBUSY);
|
||||
errno = EBUSY;
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
/* Lock the mutex for the running thread: */
|
||||
mutex->m_owner = _thread_run;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Check if this mutex is locked: */
|
||||
if ((*mutex)->m_owner != NULL) {
|
||||
/*
|
||||
* Check if the mutex is locked by the running
|
||||
* thread:
|
||||
*/
|
||||
if ((*mutex)->m_owner == _thread_run) {
|
||||
/* Increment the lock count: */
|
||||
(*mutex)->m_data.m_count++;
|
||||
} else {
|
||||
/* Return a busy error: */
|
||||
errno = EBUSY;
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
/* Lock the mutex for the running thread: */
|
||||
(*mutex)->m_owner = _thread_run;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
@ -211,81 +234,86 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (mutex->m_type) {
|
||||
/* Process according to mutex type: */
|
||||
switch ((*mutex)->m_type) {
|
||||
/* Fast mutexes do not check for any error conditions: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/*
|
||||
* Enter a loop to wait for the mutex to be locked by the
|
||||
* current thread:
|
||||
*/
|
||||
while (mutex->m_owner != _thread_run) {
|
||||
/* Check if the mutex is not locked: */
|
||||
if (mutex->m_owner == NULL) {
|
||||
/* Lock the mutex for this thread: */
|
||||
mutex->m_owner = _thread_run;
|
||||
} else {
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex:
|
||||
*/
|
||||
_thread_queue_enq(&mutex->m_queue, _thread_run);
|
||||
case MUTEX_TYPE_FAST:
|
||||
/*
|
||||
* Enter a loop to wait for the mutex to be locked by the
|
||||
* current thread:
|
||||
*/
|
||||
while ((*mutex)->m_owner != _thread_run) {
|
||||
/* Check if the mutex is not locked: */
|
||||
if ((*mutex)->m_owner == NULL) {
|
||||
/* Lock the mutex for this thread: */
|
||||
(*mutex)->m_owner = _thread_run;
|
||||
} else {
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex:
|
||||
*/
|
||||
_thread_queue_enq(&(*mutex)->m_queue, _thread_run);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
|
||||
/* Block signals: */
|
||||
_thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/*
|
||||
* Enter a loop to wait for the mutex to be locked by the
|
||||
* current thread:
|
||||
*/
|
||||
while (mutex->m_owner != _thread_run) {
|
||||
/* Check if the mutex is not locked: */
|
||||
if (mutex->m_owner == NULL) {
|
||||
/* Lock the mutex for this thread: */
|
||||
mutex->m_owner = _thread_run;
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/*
|
||||
* Enter a loop to wait for the mutex to be locked by the
|
||||
* current thread:
|
||||
*/
|
||||
while ((*mutex)->m_owner != _thread_run) {
|
||||
/* Check if the mutex is not locked: */
|
||||
if ((*mutex)->m_owner == NULL) {
|
||||
/* Lock the mutex for this thread: */
|
||||
(*mutex)->m_owner = _thread_run;
|
||||
|
||||
/* Reset the lock count for this mutex: */
|
||||
mutex->m_data.m_count = 0;
|
||||
} else {
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex:
|
||||
*/
|
||||
_thread_queue_enq(&mutex->m_queue, _thread_run);
|
||||
/* Reset the lock count for this mutex: */
|
||||
(*mutex)->m_data.m_count = 0;
|
||||
} else {
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex:
|
||||
*/
|
||||
_thread_queue_enq(&(*mutex)->m_queue, _thread_run);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
|
||||
/* Block signals: */
|
||||
_thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment the lock count for this mutex: */
|
||||
mutex->m_data.m_count++;
|
||||
break;
|
||||
/* Increment the lock count for this mutex: */
|
||||
(*mutex)->m_data.m_count++;
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
@ -297,62 +325,67 @@ pthread_mutex_unlock(pthread_mutex_t * mutex)
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (mutex->m_type) {
|
||||
/* Process according to mutex type: */
|
||||
switch ((*mutex)->m_type) {
|
||||
/* Fast mutexes do not check for any error conditions: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Check if the running thread is not the owner of the mutex: */
|
||||
if (mutex->m_owner != _thread_run) {
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
}
|
||||
/*
|
||||
* Get the next thread from the queue of threads waiting on
|
||||
* the mutex:
|
||||
*/
|
||||
else if ((mutex->m_owner = _thread_queue_deq(&mutex->m_queue)) != NULL) {
|
||||
/* Allow the new owner of the mutex to run: */
|
||||
mutex->m_owner->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Check if the running thread is not the owner of the mutex: */
|
||||
if ((*mutex)->m_owner != _thread_run) {
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
}
|
||||
/*
|
||||
* Get the next thread from the queue of threads waiting on
|
||||
* the mutex:
|
||||
*/
|
||||
else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
|
||||
/* Allow the new owner of the mutex to run: */
|
||||
(*mutex)->m_owner->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Check if the running thread is not the owner of the mutex: */
|
||||
if (mutex->m_owner != _thread_run) {
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
}
|
||||
/* Check if there are still counts: */
|
||||
else if (mutex->m_data.m_count) {
|
||||
/* Decrement the count: */
|
||||
mutex->m_data.m_count--;
|
||||
}
|
||||
/*
|
||||
* Get the next thread from the queue of threads waiting on
|
||||
* the mutex:
|
||||
*/
|
||||
else if ((mutex->m_owner = _thread_queue_deq(&mutex->m_queue)) != NULL) {
|
||||
/* Allow the new owner of the mutex to run: */
|
||||
mutex->m_owner->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Check if the running thread is not the owner of the mutex: */
|
||||
if ((*mutex)->m_owner != _thread_run) {
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
}
|
||||
/* Check if there are still counts: */
|
||||
else if ((*mutex)->m_data.m_count) {
|
||||
/* Decrement the count: */
|
||||
(*mutex)->m_data.m_count--;
|
||||
}
|
||||
/*
|
||||
* Get the next thread from the queue of threads waiting on
|
||||
* the mutex:
|
||||
*/
|
||||
else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
|
||||
/* Allow the new owner of the mutex to run: */
|
||||
(*mutex)->m_owner->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
@ -38,50 +39,138 @@
|
||||
int
|
||||
nanosleep(struct timespec * time_to_sleep, struct timespec * time_remaining)
|
||||
{
|
||||
int ret = 0;
|
||||
struct timespec current_time;
|
||||
struct timespec current_time1;
|
||||
struct timespec remaining_time;
|
||||
struct timeval tv;
|
||||
|
||||
/* Get the current time: */
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ¤t_time);
|
||||
/* Check if the time to sleep is legal: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (time_to_sleep == NULL || time_to_sleep->ts_nsec < 0 || time_to_sleep->ts_nsec > 1000000000) {
|
||||
#else
|
||||
if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000) {
|
||||
#endif
|
||||
/* Return an EINVAL error : */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Get the current time: */
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ¤t_time);
|
||||
|
||||
/* Calculate the time for the current thread to wake up: */
|
||||
_thread_run->wakeup_time.ts_sec = current_time.ts_sec + time_to_sleep->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + time_to_sleep->ts_nsec;
|
||||
/* Calculate the time for the current thread to wake up: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = current_time.ts_sec + time_to_sleep->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + time_to_sleep->ts_nsec;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec;
|
||||
_thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec;
|
||||
#endif
|
||||
|
||||
/* Check if the nanosecond field has overflowed: */
|
||||
if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
|
||||
/* Wrap the nanosecond field: */
|
||||
_thread_run->wakeup_time.ts_sec += 1;
|
||||
_thread_run->wakeup_time.ts_nsec -= 1000000000;
|
||||
}
|
||||
/* Reschedule the current thread to sleep: */
|
||||
_thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
|
||||
/* Check if the nanosecond field has overflowed: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/* Wrap the nanosecond field: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec += 1;
|
||||
_thread_run->wakeup_time.ts_nsec -= 1000000000;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec += 1;
|
||||
_thread_run->wakeup_time.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Reschedule the current thread to sleep: */
|
||||
_thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Check if the time remaining is to be returned: */
|
||||
if (time_remaining != NULL) {
|
||||
/* Get the current time: */
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ¤t_time1);
|
||||
|
||||
/* Return the actual time slept: */
|
||||
time_remaining->ts_sec = time_to_sleep->ts_sec + current_time1.ts_sec - current_time.ts_sec;
|
||||
time_remaining->ts_nsec = time_to_sleep->ts_nsec + current_time1.ts_nsec - current_time.ts_nsec;
|
||||
/* Calculate the remaining time to sleep: */
|
||||
#if defined(__FreeBSD__)
|
||||
remaining_time.ts_sec = time_to_sleep->ts_sec + current_time.ts_sec - current_time1.ts_sec;
|
||||
remaining_time.ts_nsec = time_to_sleep->ts_nsec + current_time.ts_nsec - current_time1.ts_nsec;
|
||||
#else
|
||||
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;
|
||||
#endif
|
||||
|
||||
/* Check if the nanosecond field has underflowed: */
|
||||
if (time_remaining->ts_nsec < 0) {
|
||||
#if defined(__FreeBSD__)
|
||||
if (remaining_time.ts_nsec < 0) {
|
||||
#else
|
||||
if (remaining_time.tv_nsec < 0) {
|
||||
#endif
|
||||
/* Handle the underflow: */
|
||||
time_remaining->ts_sec -= 1;
|
||||
time_remaining->ts_nsec += 1000000000;
|
||||
#if defined(__FreeBSD__)
|
||||
remaining_time.ts_sec -= 1;
|
||||
remaining_time.ts_nsec += 1000000000;
|
||||
#else
|
||||
remaining_time.tv_sec -= 1;
|
||||
remaining_time.tv_nsec += 1000000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the nanosecond field has overflowed: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (remaining_time.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (remaining_time.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/* Handle the overflow: */
|
||||
#if defined(__FreeBSD__)
|
||||
remaining_time.ts_sec += 1;
|
||||
remaining_time.ts_nsec -= 1000000000;
|
||||
#else
|
||||
remaining_time.tv_sec += 1;
|
||||
remaining_time.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the sleep was longer than the required time: */
|
||||
if (time_remaining->ts_sec < 0) {
|
||||
/* Reset the time teft: */
|
||||
time_remaining->ts_sec = 0;
|
||||
time_remaining->ts_nsec = 0;
|
||||
#if defined(__FreeBSD__)
|
||||
if (remaining_time.ts_sec < 0) {
|
||||
#else
|
||||
if (remaining_time.tv_sec < 0) {
|
||||
#endif
|
||||
/* Reset the time left: */
|
||||
#if defined(__FreeBSD__)
|
||||
remaining_time.ts_sec = 0;
|
||||
remaining_time.ts_nsec = 0;
|
||||
#else
|
||||
remaining_time.tv_sec = 0;
|
||||
remaining_time.tv_nsec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the time remaining is to be returned: */
|
||||
if (time_remaining != NULL) {
|
||||
/* Return the actual time slept: */
|
||||
#if defined(__FreeBSD__)
|
||||
time_remaining->ts_sec = remaining_time.ts_sec;
|
||||
time_remaining->ts_nsec = remaining_time.ts_nsec;
|
||||
#else
|
||||
time_remaining->tv_sec = remaining_time.tv_sec;
|
||||
time_remaining->tv_nsec = remaining_time.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the entire sleep was not completed: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (remaining_time.ts_nsec != 0 || remaining_time.ts_sec != 0) {
|
||||
#else
|
||||
if (remaining_time.tv_nsec != 0 || remaining_time.tv_sec != 0) {
|
||||
#endif
|
||||
/* Return an EINTR error : */
|
||||
errno = EINTR;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
@ -55,8 +56,8 @@ open(const char *path, int flags,...)
|
||||
mode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
}
|
||||
/* Open the file, forcing it to use non-blocking I/O operations: */
|
||||
if ((fd = _thread_sys_open(path, flags | O_NONBLOCK, mode)) < 0) {
|
||||
/* Open the file: */
|
||||
if ((fd = _thread_sys_open(path, flags, mode)) < 0) {
|
||||
}
|
||||
/* Initialise the file descriptor table entry: */
|
||||
else if (_thread_fd_table_init(fd) != 0) {
|
||||
@ -65,12 +66,6 @@ open(const char *path, int flags,...)
|
||||
|
||||
/* Reset the file descriptor: */
|
||||
fd = -1;
|
||||
} else {
|
||||
/*
|
||||
* Save the file open flags so that they can be checked
|
||||
* later:
|
||||
*/
|
||||
_thread_fd_table[fd]->flags = flags;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
|
@ -46,11 +46,6 @@ pipe(int fds[2])
|
||||
_thread_sys_close(fds[0]);
|
||||
_thread_sys_close(fds[1]);
|
||||
ret = -1;
|
||||
} else {
|
||||
_thread_fd_table[fds[0]]->flags = _thread_sys_fcntl(fds[0], F_GETFL, NULL);
|
||||
_thread_sys_fcntl(fds[0], F_SETFL, _thread_fd_table[fds[0]]->flags | O_NONBLOCK);
|
||||
_thread_fd_table[fds[1]]->flags = _thread_sys_fcntl(fds[1], F_GETFL, NULL);
|
||||
_thread_sys_fcntl(fds[1], F_SETFL, _thread_fd_table[fds[1]]->flags | O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_resume(pthread_t thread)
|
||||
{
|
||||
int ret = -1;
|
||||
pthread_t pthread;
|
||||
/*
|
||||
* Search for the thread in the linked list.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
|
||||
/* Is this the thread? */
|
||||
if (pthread == thread) {
|
||||
/* Found the thread. Is it suspended? */
|
||||
if (pthread->state == PS_SUSPENDED) {
|
||||
/* Allow the thread to run. */
|
||||
pthread->state = PS_RUNNING;
|
||||
ret = 0;
|
||||
} else if (pthread->state == PS_RUNNING) {
|
||||
/* Thread is already running. */
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Thread is in some other state. */
|
||||
_thread_seterrno(_thread_run,EINVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if thread was not found. */
|
||||
if (ret == -1) {
|
||||
/* No such thread */
|
||||
_thread_seterrno(_thread_run,ESRCH);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
70
lib/libc_r/uthread/uthread_resume_np.c
Normal file
70
lib/libc_r/uthread/uthread_resume_np.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_resume_np(pthread_t thread)
|
||||
{
|
||||
int ret = -1;
|
||||
pthread_t pthread;
|
||||
/*
|
||||
* Search for the thread in the linked list.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
|
||||
/* Is this the thread? */
|
||||
if (pthread == thread) {
|
||||
/* Found the thread. Is it suspended? */
|
||||
if (pthread->state == PS_SUSPENDED) {
|
||||
/* Allow the thread to run. */
|
||||
pthread->state = PS_RUNNING;
|
||||
ret = 0;
|
||||
} else if (pthread->state == PS_RUNNING) {
|
||||
/* Thread is already running. */
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Thread is in some other state. */
|
||||
_thread_seterrno(_thread_run,EINVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if thread was not found. */
|
||||
if (ret == -1) {
|
||||
/* No such thread */
|
||||
_thread_seterrno(_thread_run,ESRCH);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
@ -142,36 +142,29 @@ select(int numfds, fd_set * readfds, fd_set * writefds,
|
||||
|
||||
if (ret > 0) {
|
||||
if (readfds != NULL) {
|
||||
FD_ZERO(readfds);
|
||||
for (i = 0; i < numfds; i++) {
|
||||
if (FD_ISSET(i, &data.readfds)) {
|
||||
FD_SET(i, readfds);
|
||||
if (FD_ISSET(i, readfds) &&
|
||||
!FD_ISSET(i, &data.readfds)) {
|
||||
FD_CLR(i, readfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writefds != NULL) {
|
||||
FD_ZERO(writefds);
|
||||
for (i = 0; i < numfds; i++) {
|
||||
if (FD_ISSET(i, &data.writefds)) {
|
||||
FD_SET(i, writefds);
|
||||
if (FD_ISSET(i, writefds) &&
|
||||
!FD_ISSET(i, &data.writefds)) {
|
||||
FD_CLR(i, writefds);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exceptfds != NULL) {
|
||||
FD_ZERO(exceptfds);
|
||||
for (i = 0; i < numfds; i++) {
|
||||
if (FD_ISSET(i, &data.exceptfds)) {
|
||||
FD_SET(i, exceptfds);
|
||||
if (FD_ISSET(i, exceptfds) &&
|
||||
!FD_ISSET(i, &data.exceptfds)) {
|
||||
FD_CLR(i, exceptfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (exceptfds != NULL)
|
||||
FD_ZERO(exceptfds);
|
||||
if (writefds != NULL)
|
||||
FD_ZERO(writefds);
|
||||
if (readfds != NULL)
|
||||
FD_ZERO(readfds);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
|
@ -31,6 +31,8 @@
|
||||
*
|
||||
*/
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
@ -40,6 +42,7 @@ void
|
||||
_thread_sig_handler(int sig, int code, struct sigcontext * scp)
|
||||
{
|
||||
char c;
|
||||
int i;
|
||||
pthread_t pthread;
|
||||
|
||||
/*
|
||||
@ -67,16 +70,52 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp)
|
||||
} else {
|
||||
/* Handle depending on signal type: */
|
||||
switch (sig) {
|
||||
/* Interval timer used for timeslicing: */
|
||||
/* Interval timer used for timeslicing: */
|
||||
case SIGVTALRM:
|
||||
/*
|
||||
* Don't add the signal to any thread. Just want to
|
||||
* call
|
||||
* call the scheduler:
|
||||
*/
|
||||
/* the scheduler: */
|
||||
break;
|
||||
|
||||
/* Signals specific to the running thread: */
|
||||
/* Child termination: */
|
||||
case SIGCHLD:
|
||||
/*
|
||||
* Enter a loop to process each thread in the linked
|
||||
* list:
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL;
|
||||
pthread = pthread->nxt) {
|
||||
/*
|
||||
* Add the signal to the set of pending
|
||||
* signals:
|
||||
*/
|
||||
pthread->sigpend[sig] += 1;
|
||||
if (pthread->state == PS_WAIT_WAIT) {
|
||||
/* Reset the error: */
|
||||
/* There should be another flag so that this is not required! ### */
|
||||
_thread_seterrno(pthread, 0);
|
||||
|
||||
/* Change the state of the thread to run: */
|
||||
pthread->state = PS_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through the file list and set all files
|
||||
* to non-blocking again in case the child
|
||||
* set some of them to block. Sigh.
|
||||
*/
|
||||
for (i = 0; i < _thread_dtablesize; i++) {
|
||||
/* Check if this file is used: */
|
||||
if (_thread_fd_table[i] != NULL) {
|
||||
/* Set the file descriptor to non-blocking: */
|
||||
_thread_sys_fcntl(i, F_SETFL, _thread_fd_table[i]->flags | O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Signals specific to the running thread: */
|
||||
case SIGBUS:
|
||||
case SIGEMT:
|
||||
case SIGFPE:
|
||||
@ -88,7 +127,7 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp)
|
||||
_thread_run->sigpend[sig] += 1;
|
||||
break;
|
||||
|
||||
/* Signals to send to all threads: */
|
||||
/* Signals to send to all threads: */
|
||||
default:
|
||||
/*
|
||||
* Enter a loop to process each thread in the linked
|
||||
|
@ -47,6 +47,9 @@ sigsuspend(const sigset_t * set)
|
||||
/* Save the current sigmal mask: */
|
||||
oset = _thread_run->sigmask;
|
||||
|
||||
/* Combine the caller's mask with the current one: */
|
||||
_thread_run->sigmask |= *set;
|
||||
|
||||
/* Wait for a signal: */
|
||||
_thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
|
||||
|
||||
|
44
lib/libc_r/uthread/uthread_single_np.c
Normal file
44
lib/libc_r/uthread/uthread_single_np.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_single_np()
|
||||
{
|
||||
/* Enter single-threaded (non-POSIX) scheduling mode: */
|
||||
_thread_single = _thread_run;
|
||||
return(0);
|
||||
}
|
||||
#endif
|
@ -33,6 +33,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
@ -40,17 +41,16 @@
|
||||
int
|
||||
socket(int af, int type, int protocol)
|
||||
{
|
||||
int fd;
|
||||
int tmp_flags;
|
||||
int fd;
|
||||
|
||||
/* Create a socket: */
|
||||
if ((fd = _thread_sys_socket(af, type, protocol)) < 0) {
|
||||
/* Error creating socket. */
|
||||
|
||||
/* Initialise the entry in the file descriptor table: */
|
||||
} else if (_thread_fd_table_init(fd) != 0) {
|
||||
_thread_sys_close(fd);
|
||||
fd = -1;
|
||||
} else {
|
||||
tmp_flags = _thread_sys_fcntl(fd, F_GETFL, 0);
|
||||
_thread_sys_fcntl(fd, F_SETFL, tmp_flags | O_NONBLOCK);
|
||||
_thread_fd_table[fd]->flags = tmp_flags;
|
||||
}
|
||||
return (fd);
|
||||
}
|
||||
|
@ -39,12 +39,12 @@
|
||||
#include "pthread_private.h"
|
||||
|
||||
/* Static variables: */
|
||||
static struct pthread_key key_table[PTHREAD_DATAKEYS_MAX];
|
||||
static struct pthread_key key_table[PTHREAD_KEYS_MAX];
|
||||
|
||||
int
|
||||
pthread_keycreate(pthread_key_t * key, void (*destructor) (void *))
|
||||
pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
|
||||
{
|
||||
for ((*key) = 0; (*key) < PTHREAD_DATAKEYS_MAX; (*key)++) {
|
||||
for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
|
||||
if (key_table[(*key)].count == 0) {
|
||||
key_table[(*key)].count++;
|
||||
key_table[(*key)].destructor = destructor;
|
||||
@ -63,7 +63,7 @@ pthread_key_delete(pthread_key_t key)
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
if (key < PTHREAD_DATAKEYS_MAX) {
|
||||
if (key < PTHREAD_KEYS_MAX) {
|
||||
switch (key_table[key].count) {
|
||||
case 1:
|
||||
key_table[key].destructor = NULL;
|
||||
@ -94,8 +94,8 @@ _thread_cleanupspecific(void)
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
for (itr = 0; itr < _POSIX_THREAD_DESTRUTOR_ITERATIONS; itr++) {
|
||||
for (key = 0; key < PTHREAD_DATAKEYS_MAX; key++) {
|
||||
for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) {
|
||||
for (key = 0; key < PTHREAD_KEYS_MAX; key++) {
|
||||
if (_thread_run->specific_data_count) {
|
||||
if (_thread_run->specific_data[key]) {
|
||||
data = (void *) _thread_run->specific_data[key];
|
||||
@ -125,8 +125,8 @@ static inline const void **
|
||||
pthread_key_allocate_data(void)
|
||||
{
|
||||
const void **new_data;
|
||||
if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_DATAKEYS_MAX)) != NULL) {
|
||||
memset((void *) new_data, 0, sizeof(void *) * PTHREAD_DATAKEYS_MAX);
|
||||
if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX)) != NULL) {
|
||||
memset((void *) new_data, 0, sizeof(void *) * PTHREAD_KEYS_MAX);
|
||||
}
|
||||
return (new_data);
|
||||
}
|
||||
@ -154,7 +154,7 @@ pthread_setspecific(pthread_key_t key, const void *value)
|
||||
}
|
||||
|
||||
if ((pthread->specific_data) || (pthread->specific_data = pthread_key_allocate_data())) {
|
||||
if ((key < PTHREAD_DATAKEYS_MAX) && (key_table)) {
|
||||
if ((key < PTHREAD_KEYS_MAX) && (key_table)) {
|
||||
if (key_table[key].count) {
|
||||
if (pthread->specific_data[key] == NULL) {
|
||||
if (value != NULL) {
|
||||
@ -213,7 +213,7 @@ pthread_getspecific(pthread_key_t key, void **p_data)
|
||||
rval = -1;
|
||||
}
|
||||
/* Check if there is specific data: */
|
||||
else if (pthread->specific_data != NULL && (key < PTHREAD_DATAKEYS_MAX) && (key_table)) {
|
||||
else if (pthread->specific_data != NULL && (key < PTHREAD_KEYS_MAX) && (key_table)) {
|
||||
/* Check if this key has been used before: */
|
||||
if (key_table[key].count) {
|
||||
/* Return the value: */
|
||||
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_suspend(pthread_t thread)
|
||||
{
|
||||
int ret = -1;
|
||||
pthread_t pthread;
|
||||
/*
|
||||
* Search for the thread in the linked list.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
|
||||
/* Is this the thread? */
|
||||
if (pthread == thread) {
|
||||
/* Found the thread. Is it running? */
|
||||
if (pthread->state != PS_RUNNING &&
|
||||
pthread->state != PS_SUSPENDED) {
|
||||
/* The thread operation has been interrupted */
|
||||
_thread_seterrno(pthread,EINTR);
|
||||
}
|
||||
/* Suspend the thread. */
|
||||
pthread->state = PS_SUSPENDED;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
/* Check if thread was not found. */
|
||||
if (ret == -1) {
|
||||
/* No such thread */
|
||||
_thread_seterrno(_thread_run,ESRCH);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
67
lib/libc_r/uthread/uthread_suspend_np.c
Normal file
67
lib/libc_r/uthread/uthread_suspend_np.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_suspend_np(pthread_t thread)
|
||||
{
|
||||
int ret = -1;
|
||||
pthread_t pthread;
|
||||
/*
|
||||
* Search for the thread in the linked list.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
|
||||
/* Is this the thread? */
|
||||
if (pthread == thread) {
|
||||
/* Found the thread. Is it running? */
|
||||
if (pthread->state != PS_RUNNING &&
|
||||
pthread->state != PS_SUSPENDED) {
|
||||
/* The thread operation has been interrupted */
|
||||
_thread_seterrno(pthread,EINTR);
|
||||
}
|
||||
/* Suspend the thread. */
|
||||
pthread->state = PS_SUSPENDED;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
/* Check if thread was not found. */
|
||||
if (ret == -1) {
|
||||
/* No such thread */
|
||||
_thread_seterrno(_thread_run,ESRCH);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
@ -20,6 +20,7 @@ PRECIOUSLIB= yes
|
||||
.include "${.CURDIR}/gen/Makefile.inc"
|
||||
.include "${.CURDIR}/gmon/Makefile.inc"
|
||||
.include "${.CURDIR}/locale/Makefile.inc"
|
||||
.include "${.CURDIR}/man/Makefile.inc"
|
||||
.include "${.CURDIR}/net/Makefile.inc"
|
||||
.include "${.CURDIR}/nls/Makefile.inc"
|
||||
.include "${.CURDIR}/quad/Makefile.inc"
|
||||
@ -38,24 +39,8 @@ CFLAGS+= -DYP
|
||||
.endif
|
||||
.include "${.CURDIR}/${MACHINE}/sys/Makefile.inc"
|
||||
|
||||
KQSRCS= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \
|
||||
lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \
|
||||
subdi3.c ucmpdi2.c udivdi3.c umoddi3.c xordi3.c
|
||||
KSRCS= bcmp.c ffs.c index.c mcount.c rindex.c strcat.c strcmp.c strcpy.c \
|
||||
strlen.c strncpy.c
|
||||
|
||||
libkern: libkern.gen libkern.${MACHINE}
|
||||
|
||||
libkern.gen: ${KQSRCS} ${KSRCS}
|
||||
cp -p ${.CURDIR}/quad/quad.h ${.ALLSRC} /sys/libkern
|
||||
|
||||
libkern.${MACHINE}:: ${KMSRCS}
|
||||
.if defined(KMSRCS) && !empty(KMSRCS)
|
||||
cp -p ${.ALLSRC} /sys/libkern/${MACHINE}
|
||||
.endif
|
||||
|
||||
#beforeinstall: tags
|
||||
# ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc.tags
|
||||
beforeinstall: tags
|
||||
${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc_r.tags
|
||||
|
||||
tags: ${SRCS}
|
||||
ctags ${.ALLSRC:M*.c}
|
||||
|
@ -1,5 +1,4 @@
|
||||
# @(#)Makefile.inc 8.1 (Berkeley) 6/17/93
|
||||
# $Id: $
|
||||
|
||||
# sys sources
|
||||
.PATH: ${.CURDIR}/../libc/${MACHINE}/sys ${.CURDIR}/../libc/sys \
|
||||
@ -40,16 +39,18 @@ THREADASM= accept.o bind.o close.o connect.o dup.o dup2.o \
|
||||
shutdown.o sigaction.o sigaltstack.o socket.o socketpair.o \
|
||||
wait4.o write.o writev.o
|
||||
|
||||
PSEUDO= _exit.o _getlogin.o
|
||||
PSEUDO= _getlogin.o
|
||||
|
||||
OBJS+= ${ASM} ${THREADASM} ${PSEUDO}
|
||||
THREADPSEUDO= _exit.o
|
||||
|
||||
OBJS+= ${ASM} ${THREADASM} ${PSEUDO} ${THREADPSEUDO}
|
||||
|
||||
${ASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.o
|
||||
@printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
|
||||
@${LD} -x -r ${.PREFIX}.o
|
||||
@mv -f a.out ${.PREFIX}.o
|
||||
@mv a.out ${.PREFIX}.o
|
||||
|
||||
PASM= ${ASM:.o=.po}
|
||||
${PASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@ -57,7 +58,7 @@ ${PASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
|
||||
@${LD} -x -r ${.PREFIX}.po
|
||||
@mv -f a.out ${.PREFIX}.po
|
||||
@mv a.out ${.PREFIX}.po
|
||||
|
||||
SASM= ${ASM:.o=.so}
|
||||
${SASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@ -67,23 +68,23 @@ ${SASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
|
||||
${THREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.o
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
|
||||
@${LD} -x -r ${.PREFIX}.o
|
||||
@mv -f a.out ${.PREFIX}.o
|
||||
@mv a.out ${.PREFIX}.o
|
||||
|
||||
PTHREADASM= ${THREADASM:.o=.po}
|
||||
${PTHREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.po
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
|
||||
@${LD} -x -r ${.PREFIX}.po
|
||||
@mv -f a.out ${.PREFIX}.po
|
||||
@mv a.out ${.PREFIX}.po
|
||||
|
||||
STHREADASM= ${THREADASM:.o=.so}
|
||||
${STHREADASM}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.so
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX},_thread_sys_${.PREFIX})\n' | \
|
||||
@printf '#include "SYS.h"\nPRSYSCALL(${.PREFIX})\n' | \
|
||||
${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
|
||||
|
||||
${PSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@ -91,7 +92,7 @@ ${PSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
|
||||
@${LD} -x -r ${.PREFIX}.o
|
||||
@mv -f a.out ${.PREFIX}.o
|
||||
@mv a.out ${.PREFIX}.o
|
||||
|
||||
PPSEUDO=${PSEUDO:.o=.po}
|
||||
${PPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@ -99,10 +100,31 @@ ${PPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
|
||||
@${LD} -x -r ${.PREFIX}.po
|
||||
@mv -f a.out ${.PREFIX}.po
|
||||
@mv a.out ${.PREFIX}.po
|
||||
|
||||
SPSEUDO=${PSEUDO:.o=.so}
|
||||
${SPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.so
|
||||
@printf '#include "SYS.h"\nPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
|
||||
|
||||
${THREADPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.o
|
||||
@printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.o
|
||||
@${LD} -x -r ${.PREFIX}.o
|
||||
@mv a.out ${.PREFIX}.o
|
||||
|
||||
THREADPPSEUDO=${THREADPSEUDO:.o=.po}
|
||||
${THREADPPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.po
|
||||
@printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} -DPROF ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -o ${.PREFIX}.po
|
||||
@${LD} -x -r ${.PREFIX}.po
|
||||
@mv a.out ${.PREFIX}.po
|
||||
|
||||
THREADSPSEUDO=${THREADPSEUDO:.o=.so}
|
||||
${THREADSPSEUDO}: ${.CURDIR}/../libc/${MACHINE}/SYS.h /usr/include/sys/syscall.h
|
||||
@${ECHO} creating ${.PREFIX}.so
|
||||
@printf '#include "SYS.h"\nPPSEUDO(${.PREFIX},${.PREFIX:S/_//})\n' | \
|
||||
${CPP} -DPIC ${CFLAGS:M-[ID]*} ${AINC} | ${AS} -k -o ${.PREFIX}.so
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile.inc,v 1.1 1996/01/22 00:23:03 julian Exp $
|
||||
# $Id: Makefile.inc,v 1.2 1996/02/17 02:19:35 jdp Exp $
|
||||
|
||||
CPLUSPLUSLIB= cpluspluslib
|
||||
|
||||
@ -7,7 +7,7 @@ CPLUSPLUSLIB= cpluspluslib
|
||||
|
||||
SRCS+= \
|
||||
uthread_accept.c \
|
||||
uthread_attr_setcreatesuspend.c \
|
||||
uthread_attr_setcreatesuspend_np.c \
|
||||
uthread_autoinit.cc \
|
||||
uthread_bind.c \
|
||||
uthread_clean.c \
|
||||
@ -52,7 +52,7 @@ SRCS+= \
|
||||
uthread_read.c \
|
||||
uthread_readv.c \
|
||||
uthread_recvfrom.c \
|
||||
uthread_resume.c \
|
||||
uthread_resume_np.c \
|
||||
uthread_select.c \
|
||||
uthread_self.c \
|
||||
uthread_sendto.c \
|
||||
@ -71,7 +71,7 @@ SRCS+= \
|
||||
uthread_socket.c \
|
||||
uthread_socketpair.c \
|
||||
uthread_spec.c \
|
||||
uthread_suspend.c \
|
||||
uthread_suspend_np.c \
|
||||
uthread_wait4.c \
|
||||
uthread_write.c \
|
||||
uthread_writev.c \
|
||||
|
52
lib/libkse/thread/thr_attr_destroy.c
Normal file
52
lib/libkse/thread/thr_attr_destroy.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_attr_destroy(pthread_attr_t *attr)
|
||||
{
|
||||
int ret;
|
||||
if (attr == NULL || *attr == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
free(*attr);
|
||||
*attr = NULL;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
54
lib/libkse/thread/thr_attr_init.c
Normal file
54
lib/libkse/thread/thr_attr_init.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_attr_init(pthread_attr_t *attr)
|
||||
{
|
||||
int ret;
|
||||
pthread_attr_t pattr;
|
||||
if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
ret = -1;
|
||||
} else {
|
||||
memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr));
|
||||
*attr = pattr;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
51
lib/libkse/thread/thr_attr_setcreatesuspend_np.c
Normal file
51
lib/libkse/thread/thr_attr_setcreatesuspend_np.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
|
||||
{
|
||||
int ret;
|
||||
if (attr == NULL || *attr == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
(*attr)->suspend = PTHREAD_CREATE_SUSPENDED;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
50
lib/libkse/thread/thr_attr_setstacksize.c
Normal file
50
lib/libkse/thread/thr_attr_setstacksize.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
|
||||
{
|
||||
int ret;
|
||||
if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
(*attr)->stacksize_attr = stacksize;
|
||||
ret = 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
@ -30,7 +30,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
@ -38,10 +41,55 @@
|
||||
int
|
||||
close(int fd)
|
||||
{
|
||||
int ret;
|
||||
int flags;
|
||||
int ret;
|
||||
int status;
|
||||
struct stat sb;
|
||||
|
||||
/* Lock the file descriptor while the file is closed: */
|
||||
if ((ret = _thread_fd_lock(fd, FD_RDWR, NULL, __FILE__, __LINE__)) == 0) {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Get file descriptor status. */
|
||||
fstat(fd, &sb);
|
||||
|
||||
/*
|
||||
* Check if the file should be left as blocking.
|
||||
*
|
||||
* This is so that the file descriptors shared with a parent
|
||||
* process aren't left set to non-blocking if the child
|
||||
* closes them prior to exit. An example where this causes
|
||||
* problems with /bin/sh is when a child closes stdin.
|
||||
*
|
||||
* Setting a file as blocking causes problems if a threaded
|
||||
* parent accesses the file descriptor before the child exits.
|
||||
* Once the threaded parent receives a SIGCHLD then it resets
|
||||
* all of its files to non-blocking, and so it is then safe
|
||||
* to access them.
|
||||
*
|
||||
* Pipes are not set to blocking when they are closed, as
|
||||
* the parent and child will normally close the file
|
||||
* descriptor of the end of the pipe that they are not
|
||||
* using, which would then cause any reads to block
|
||||
* indefinitely.
|
||||
*/
|
||||
if ((S_ISREG(sb.st_mode) || S_ISCHR(sb.st_mode)) && (_thread_fd_table[fd]->flags & O_NONBLOCK) == 0) {
|
||||
/* Get the current flags: */
|
||||
flags = _thread_sys_fcntl(fd, F_GETFL, NULL);
|
||||
/* Clear the nonblocking file descriptor flag: */
|
||||
_thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
|
||||
/* Close the file descriptor: */
|
||||
ret = _thread_sys_close(fd);
|
||||
_thread_fd_unlock(fd, FD_RDWR);
|
||||
|
||||
/* Free the file descriptor table entry: */
|
||||
free(_thread_fd_table[fd]);
|
||||
_thread_fd_table[fd] = NULL;
|
||||
|
||||
/* Unblock signals again: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
@ -40,41 +40,56 @@ 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;
|
||||
|
||||
/*
|
||||
* Check if a pointer to a condition variable attribute structure was
|
||||
* passed by the caller:
|
||||
*/
|
||||
if (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: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
/* Check for no errors: */
|
||||
if (rval == 0) {
|
||||
/* Initialise the condition variable structure: */
|
||||
_thread_queue_init(&cond->c_queue);
|
||||
cond->c_flags |= COND_FLAGS_INITED;
|
||||
cond->c_type = type;
|
||||
/* 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: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for no errors: */
|
||||
if (rval == 0) {
|
||||
if ((pcond = (pthread_cond_t) malloc(sizeof(struct pthread_cond))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
rval = -1;
|
||||
} else {
|
||||
/*
|
||||
* Initialise the condition variable
|
||||
* structure:
|
||||
*/
|
||||
_thread_queue_init(&pcond->c_queue);
|
||||
pcond->c_flags |= COND_FLAGS_INITED;
|
||||
pcond->c_type = type;
|
||||
*cond = pcond;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -85,26 +100,33 @@ pthread_cond_destroy(pthread_cond_t * cond)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL || *cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Process according to condition variable type: */
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Check for errors: */
|
||||
if (rval == 0) {
|
||||
/* Destroy the contents of the condition structure: */
|
||||
_thread_queue_init(&cond->c_queue);
|
||||
cond->c_flags = 0;
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for errors: */
|
||||
if (rval == 0) {
|
||||
/* Destroy the contents of the condition structure: */
|
||||
_thread_queue_init(&(*cond)->c_queue);
|
||||
(*cond)->c_flags = 0;
|
||||
free(*cond);
|
||||
*cond = NULL;
|
||||
}
|
||||
}
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -116,39 +138,44 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
|
||||
int rval = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Queue the running thread for the condition variable: */
|
||||
_thread_queue_enq(&cond->c_queue, _thread_run);
|
||||
|
||||
/* Unlock the mutex: */
|
||||
pthread_mutex_unlock(mutex);
|
||||
|
||||
/* Schedule the next thread: */
|
||||
_thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
|
||||
/* Lock the mutex: */
|
||||
rval = pthread_mutex_lock(mutex);
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL || *cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Process according to condition variable type: */
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Queue the running thread for the condition variable: */
|
||||
_thread_queue_enq(&(*cond)->c_queue, _thread_run);
|
||||
|
||||
/* Unlock the mutex: */
|
||||
pthread_mutex_unlock(mutex);
|
||||
|
||||
/* Schedule the next thread: */
|
||||
_thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
|
||||
/* Lock the mutex: */
|
||||
rval = pthread_mutex_lock(mutex);
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -161,59 +188,69 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||
int rval = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Set the wakeup time: */
|
||||
_thread_run->wakeup_time.ts_sec = abstime->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = abstime->ts_nsec;
|
||||
|
||||
/* Reset the timeout flag: */
|
||||
_thread_run->timeout = 0;
|
||||
|
||||
/* Queue the running thread for the condition variable: */
|
||||
_thread_queue_enq(&cond->c_queue, _thread_run);
|
||||
|
||||
/* Unlock the mutex: */
|
||||
if ((rval = pthread_mutex_unlock(mutex)) != 0) {
|
||||
/*
|
||||
* Cannot unlock the mutex, so remove the running
|
||||
* thread from the condition variable queue:
|
||||
*/
|
||||
_thread_queue_deq(&cond->c_queue);
|
||||
} else {
|
||||
/* Schedule the next thread: */
|
||||
_thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
|
||||
/* Lock the mutex: */
|
||||
if ((rval = pthread_mutex_lock(mutex)) != 0) {
|
||||
}
|
||||
/* Check if the wait timed out: */
|
||||
else if (_thread_run->timeout) {
|
||||
/* Return a timeout error: */
|
||||
_thread_seterrno(_thread_run, EAGAIN);
|
||||
rval = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL || *cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Process according to condition variable type: */
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Set the wakeup time: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = abstime->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = abstime->ts_nsec;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = abstime->tv_sec;
|
||||
_thread_run->wakeup_time.tv_nsec = abstime->tv_nsec;
|
||||
#endif
|
||||
|
||||
/* Reset the timeout flag: */
|
||||
_thread_run->timeout = 0;
|
||||
|
||||
/* Queue the running thread for the condition variable: */
|
||||
_thread_queue_enq(&(*cond)->c_queue, _thread_run);
|
||||
|
||||
/* Unlock the mutex: */
|
||||
if ((rval = pthread_mutex_unlock(mutex)) != 0) {
|
||||
/*
|
||||
* Cannot unlock the mutex, so remove the running
|
||||
* thread from the condition variable queue:
|
||||
*/
|
||||
_thread_queue_deq(&(*cond)->c_queue);
|
||||
} else {
|
||||
/* Schedule the next thread: */
|
||||
_thread_kern_sched_state(PS_COND_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
|
||||
/* Lock the mutex: */
|
||||
if ((rval = pthread_mutex_lock(mutex)) != 0) {
|
||||
}
|
||||
/* Check if the wait timed out: */
|
||||
else if (_thread_run->timeout) {
|
||||
/* Return a timeout error: */
|
||||
errno = EAGAIN;
|
||||
rval = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -226,30 +263,35 @@ pthread_cond_signal(pthread_cond_t * cond)
|
||||
int status;
|
||||
pthread_t pthread;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Bring the next thread off the condition queue: */
|
||||
if ((pthread = _thread_queue_deq(&cond->c_queue)) != NULL) {
|
||||
/* Allow the thread to run: */
|
||||
pthread->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (cond == NULL || *cond == NULL) {
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Process according to condition variable type: */
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Bring the next thread off the condition queue: */
|
||||
if ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
|
||||
/* Allow the thread to run: */
|
||||
pthread->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (rval);
|
||||
@ -266,11 +308,11 @@ pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to condition variable type: */
|
||||
switch (cond->c_type) {
|
||||
switch ((*cond)->c_type) {
|
||||
/* Fast condition variable: */
|
||||
case COND_TYPE_FAST:
|
||||
/* Enter a loop to bring all threads off the condition queue: */
|
||||
while ((pthread = _thread_queue_deq(&cond->c_queue)) != NULL) {
|
||||
while ((pthread = _thread_queue_deq(&(*cond)->c_queue)) != NULL) {
|
||||
/* Allow the thread to run: */
|
||||
pthread->state = PS_RUNNING;
|
||||
}
|
||||
@ -279,7 +321,7 @@ pthread_cond_broadcast(pthread_cond_t * cond)
|
||||
/* Trap invalid condition variable types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
errno = EINVAL;
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
int ret = 0;
|
||||
int status;
|
||||
pthread_t new_thread;
|
||||
pthread_attr_t pattr;
|
||||
void *stack;
|
||||
|
||||
/* Block signals: */
|
||||
@ -60,15 +61,17 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
ret = EAGAIN;
|
||||
} else {
|
||||
/* Check if default thread attributes are required: */
|
||||
if (attr == NULL) {
|
||||
if (attr == NULL || *attr == NULL) {
|
||||
/* Use the default thread attributes: */
|
||||
attr = &pthread_attr_default;
|
||||
pattr = &pthread_attr_default;
|
||||
} else {
|
||||
pattr = *attr;
|
||||
}
|
||||
/* Check if a stack was specified in the thread attributes: */
|
||||
if ((stack = attr->stackaddr_attr) != NULL) {
|
||||
if ((stack = pattr->stackaddr_attr) != NULL) {
|
||||
}
|
||||
/* Allocate memory for the stack: */
|
||||
else if ((stack = (void *) malloc(attr->stacksize_attr)) == NULL) {
|
||||
else if ((stack = (void *) malloc(pattr->stacksize_attr)) == NULL) {
|
||||
/* Insufficient memory to create a thread: */
|
||||
ret = EAGAIN;
|
||||
free(new_thread);
|
||||
@ -83,7 +86,7 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
new_thread->stack = stack;
|
||||
new_thread->start_routine = start_routine;
|
||||
new_thread->arg = arg;
|
||||
if (attr->suspend == PTHREAD_CREATE_SUSPENDED) {
|
||||
if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) {
|
||||
new_thread->state = PS_SUSPENDED;
|
||||
} else {
|
||||
new_thread->state = PS_RUNNING;
|
||||
@ -148,19 +151,19 @@ _thread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
|
||||
/* The stack starts high and builds down: */
|
||||
#if defined(__FreeBSD__)
|
||||
new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + attr->stacksize_attr - sizeof(double));
|
||||
new_thread->saved_jmp_buf[0]._jb[2] = (int) (new_thread->stack + pattr->stacksize_attr - sizeof(double));
|
||||
#elif defined(__NetBSD__)
|
||||
#if defined(__alpha)
|
||||
new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + attr->stacksize_attr - sizeof(double);
|
||||
new_thread->saved_jmp_buf[4 + R_SP] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
|
||||
#else
|
||||
new_thread->saved_jmp_buf[2] = (long) new_thread->stack + attr->stacksize_attr - sizeof(double);
|
||||
new_thread->saved_jmp_buf[2] = (long) new_thread->stack + pattr->stacksize_attr - sizeof(double);
|
||||
#endif
|
||||
#else
|
||||
#error "Don't recognize this operating system!"
|
||||
#endif
|
||||
|
||||
/* Copy the thread attributes: */
|
||||
memcpy(&new_thread->attr, attr, sizeof(pthread_attr_t));
|
||||
memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
|
||||
|
||||
/*
|
||||
* Check if this thread is to inherit the scheduling
|
||||
|
@ -31,11 +31,49 @@
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
void _exit(int status)
|
||||
{
|
||||
int flags;
|
||||
int i;
|
||||
struct itimerval itimer;
|
||||
|
||||
/* Disable the interval timer: */
|
||||
itimer.it_interval.tv_sec = 0;
|
||||
itimer.it_interval.tv_usec = 0;
|
||||
itimer.it_value.tv_sec = 0;
|
||||
itimer.it_value.tv_usec = 0;
|
||||
setitimer(ITIMER_VIRTUAL, &itimer, NULL);
|
||||
|
||||
/* Close the pthread kernel pipe: */
|
||||
_thread_sys_close(_thread_kern_pipe[0]);
|
||||
_thread_sys_close(_thread_kern_pipe[1]);
|
||||
|
||||
/*
|
||||
* Enter a loop to set all file descriptors to blocking
|
||||
* if they were not created as non-blocking:
|
||||
*/
|
||||
for (i = 0; i < _thread_dtablesize; i++) {
|
||||
/* Check if this file descriptor is in use: */
|
||||
if (_thread_fd_table[i] != NULL &&
|
||||
!(_thread_fd_table[i]->flags & O_NONBLOCK)) {
|
||||
/* Get the current flags: */
|
||||
flags = _thread_sys_fcntl(i, F_GETFL, NULL);
|
||||
/* Clear the nonblocking file descriptor flag: */
|
||||
_thread_sys_fcntl(i, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the _exit syscall: */
|
||||
_thread_sys__exit(status);
|
||||
}
|
||||
|
||||
void
|
||||
_thread_exit(char *fname, int lineno, char *string)
|
||||
{
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
|
@ -31,6 +31,8 @@
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
|
@ -202,18 +202,6 @@ _thread_main(int argc, char *argv[], char *env)
|
||||
_thread_init();
|
||||
return (main(argc, argv, env));
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Force our auto-initialization module to be pulled in from the library,
|
||||
* by referencing a symbol that is defined in it.
|
||||
*
|
||||
* The auto-initialization module is a small C++ module. It has a static
|
||||
* constructor that calls _thread_init() automatically, at the beginning
|
||||
* of program execution. That eliminates the need for any special hooks
|
||||
* in crt0.o.
|
||||
*/
|
||||
extern int _thread_autoinit_dummy_decl;
|
||||
static int *_thread_autoinit_dummy_ref = &_thread_autoinit_dummy_decl;
|
||||
#endif
|
||||
#else
|
||||
/*
|
||||
|
@ -250,18 +250,30 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
pthread->state == PS_FDW_WAIT ||
|
||||
pthread->state == PS_SELECT_WAIT) {
|
||||
/* Check if this thread is to wait forever: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (pthread->wakeup_time.ts_sec == -1) {
|
||||
#else
|
||||
if (pthread->wakeup_time.tv_sec == -1) {
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check if this thread is to wakeup
|
||||
* immediately or if it is past its wakeup
|
||||
* time:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
else if ((pthread->wakeup_time.ts_sec == 0 &&
|
||||
pthread->wakeup_time.ts_nsec == 0) ||
|
||||
(ts.ts_sec > pthread->wakeup_time.ts_sec) ||
|
||||
((ts.ts_sec == pthread->wakeup_time.ts_sec) &&
|
||||
(ts.ts_nsec >= pthread->wakeup_time.ts_nsec))) {
|
||||
#else
|
||||
else if ((pthread->wakeup_time.tv_sec == 0 &&
|
||||
pthread->wakeup_time.tv_nsec == 0) ||
|
||||
(ts.tv_sec > pthread->wakeup_time.tv_sec) ||
|
||||
((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
|
||||
(ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) {
|
||||
#endif
|
||||
/*
|
||||
* Check if this thread is waiting on
|
||||
* select:
|
||||
@ -364,9 +376,48 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
}
|
||||
/*
|
||||
* Enter a loop to look for the first thread of the highest
|
||||
* priority:
|
||||
* priority that is ready to run:
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
|
||||
/* Check if in single-threaded mode: */
|
||||
if (_thread_single != NULL) {
|
||||
/*
|
||||
* Check if the current thread is
|
||||
* the thread for which single-threaded
|
||||
* mode is enabled:
|
||||
*/
|
||||
if (pthread == _thread_single) {
|
||||
/*
|
||||
* This thread is allowed
|
||||
* to run.
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* Walk up the signal handler
|
||||
* parent thread tree to see
|
||||
* if the current thread is
|
||||
* descended from the thread
|
||||
* for which single-threaded
|
||||
* mode is enabled.
|
||||
*/
|
||||
pthread_nxt = pthread;
|
||||
while(pthread_nxt != NULL &&
|
||||
pthread_nxt != _thread_single) {
|
||||
pthread_nxt = pthread->parent_thread;
|
||||
}
|
||||
/*
|
||||
* Check if the current
|
||||
* thread is not descended
|
||||
* from the thread for which
|
||||
* single-threaded mode is
|
||||
* enabled.
|
||||
*/
|
||||
if (pthread_nxt == NULL)
|
||||
/* Ignore this thread. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the current thread is unable to run: */
|
||||
if (pthread->state != PS_RUNNING) {
|
||||
}
|
||||
@ -392,6 +443,45 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* least recently.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
|
||||
/* Check if in single-threaded mode: */
|
||||
if (_thread_single != NULL) {
|
||||
/*
|
||||
* Check if the current thread is
|
||||
* the thread for which single-threaded
|
||||
* mode is enabled:
|
||||
*/
|
||||
if (pthread == _thread_single) {
|
||||
/*
|
||||
* This thread is allowed
|
||||
* to run.
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* Walk up the signal handler
|
||||
* parent thread tree to see
|
||||
* if the current thread is
|
||||
* descended from the thread
|
||||
* for which single-threaded
|
||||
* mode is enabled.
|
||||
*/
|
||||
pthread_nxt = pthread;
|
||||
while(pthread_nxt != NULL &&
|
||||
pthread_nxt != _thread_single) {
|
||||
pthread_nxt = pthread->parent_thread;
|
||||
}
|
||||
/*
|
||||
* Check if the current
|
||||
* thread is not descended
|
||||
* from the thread for which
|
||||
* single-threaded mode is
|
||||
* enabled.
|
||||
*/
|
||||
if (pthread_nxt == NULL)
|
||||
/* Ignore this thread. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the current thread is unable to run: */
|
||||
if (pthread->state != PS_RUNNING) {
|
||||
/* Ignore threads that are not ready to run. */
|
||||
@ -446,6 +536,45 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* priority. 3. Became inactive least recently.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL; pthread = pthread->nxt) {
|
||||
/* Check if in single-threaded mode: */
|
||||
if (_thread_single != NULL) {
|
||||
/*
|
||||
* Check if the current thread is
|
||||
* the thread for which single-threaded
|
||||
* mode is enabled:
|
||||
*/
|
||||
if (pthread == _thread_single) {
|
||||
/*
|
||||
* This thread is allowed
|
||||
* to run.
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* Walk up the signal handler
|
||||
* parent thread tree to see
|
||||
* if the current thread is
|
||||
* descended from the thread
|
||||
* for which single-threaded
|
||||
* mode is enabled.
|
||||
*/
|
||||
pthread_nxt = pthread;
|
||||
while(pthread_nxt != NULL &&
|
||||
pthread_nxt != _thread_single) {
|
||||
pthread_nxt = pthread->parent_thread;
|
||||
}
|
||||
/*
|
||||
* Check if the current
|
||||
* thread is not descended
|
||||
* from the thread for which
|
||||
* single-threaded mode is
|
||||
* enabled.
|
||||
*/
|
||||
if (pthread_nxt == NULL)
|
||||
/* Ignore this thread. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the current thread is unable to
|
||||
* run:
|
||||
@ -565,22 +694,37 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* Check if this thread is to
|
||||
* wait forever:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (pthread->wakeup_time.ts_sec == -1) {
|
||||
#else
|
||||
if (pthread->wakeup_time.tv_sec == -1) {
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check if this thread is to
|
||||
* wakeup immediately:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
else if (pthread->wakeup_time.ts_sec == 0 &&
|
||||
pthread->wakeup_time.ts_nsec == 0) {
|
||||
#else
|
||||
else if (pthread->wakeup_time.tv_sec == 0 &&
|
||||
pthread->wakeup_time.tv_nsec == 0) {
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check if the current time
|
||||
* is after the wakeup time:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
else if ((ts.ts_sec > pthread->wakeup_time.ts_sec) ||
|
||||
((ts.ts_sec == pthread->wakeup_time.ts_sec) &&
|
||||
(ts.ts_nsec > pthread->wakeup_time.ts_nsec))) {
|
||||
#else
|
||||
else if ((ts.tv_sec > pthread->wakeup_time.tv_sec) ||
|
||||
((ts.tv_sec == pthread->wakeup_time.tv_sec) &&
|
||||
(ts.tv_nsec > pthread->wakeup_time.tv_nsec))) {
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* Calculate the time
|
||||
@ -589,16 +733,26 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* for the clock
|
||||
* resolution:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec = pthread->wakeup_time.ts_sec - ts.ts_sec;
|
||||
ts1.ts_nsec = pthread->wakeup_time.ts_nsec - ts.ts_nsec +
|
||||
CLOCK_RES_NSEC;
|
||||
#else
|
||||
ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
|
||||
ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
|
||||
CLOCK_RES_NSEC;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for
|
||||
* underflow of the
|
||||
* nanosecond field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (ts1.ts_nsec < 0) {
|
||||
#else
|
||||
if (ts1.tv_nsec < 0) {
|
||||
#endif
|
||||
/*
|
||||
* Allow for
|
||||
* the
|
||||
@ -607,15 +761,24 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec--;
|
||||
ts1.ts_nsec += 1000000000;
|
||||
#else
|
||||
ts1.tv_sec--;
|
||||
ts1.tv_nsec += 1000000000;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check for overflow
|
||||
* of the nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (ts1.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (ts1.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/*
|
||||
* Allow for
|
||||
* the
|
||||
@ -624,8 +787,13 @@ __asm__("fnsave %0": :"m"(*fdata));
|
||||
* nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec++;
|
||||
ts1.ts_nsec -= 1000000000;
|
||||
#else
|
||||
ts1.tv_sec++;
|
||||
ts1.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Convert the
|
||||
@ -1100,11 +1268,20 @@ _thread_kern_select(int wait_reqd)
|
||||
*/
|
||||
if (wait_reqd && settimeout) {
|
||||
/* Check if this thread wants to wait forever: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (pthread->wakeup_time.ts_sec == -1) {
|
||||
#else
|
||||
if (pthread->wakeup_time.tv_sec == -1) {
|
||||
#endif
|
||||
}
|
||||
/* Check if this thread doesn't want to wait at all: */
|
||||
#if defined(__FreeBSD__)
|
||||
else if (pthread->wakeup_time.ts_sec == 0 &&
|
||||
pthread->wakeup_time.ts_nsec == 0) {
|
||||
#else
|
||||
else if (pthread->wakeup_time.tv_sec == 0 &&
|
||||
pthread->wakeup_time.tv_nsec == 0) {
|
||||
#endif
|
||||
/* Override the caller's request to wait: */
|
||||
wait_reqd = 0;
|
||||
} else {
|
||||
@ -1112,33 +1289,57 @@ _thread_kern_select(int wait_reqd)
|
||||
* Calculate the time until this thread is
|
||||
* ready, allowing for the clock resolution:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec = pthread->wakeup_time.ts_sec - ts.ts_sec;
|
||||
ts1.ts_nsec = pthread->wakeup_time.ts_nsec - ts.ts_nsec +
|
||||
CLOCK_RES_NSEC;
|
||||
#else
|
||||
ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec;
|
||||
ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec +
|
||||
CLOCK_RES_NSEC;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check for underflow of the nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (ts1.ts_nsec < 0) {
|
||||
#else
|
||||
if (ts1.tv_nsec < 0) {
|
||||
#endif
|
||||
/*
|
||||
* Allow for the underflow of the
|
||||
* nanosecond field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec--;
|
||||
ts1.ts_nsec += 1000000000;
|
||||
#else
|
||||
ts1.tv_sec--;
|
||||
ts1.tv_nsec += 1000000000;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Check for overflow of the nanosecond
|
||||
* field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
if (ts1.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (ts1.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/*
|
||||
* Allow for the overflow of the
|
||||
* nanosecond field:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
ts1.ts_sec++;
|
||||
ts1.ts_nsec -= 1000000000;
|
||||
#else
|
||||
ts1.tv_sec++;
|
||||
ts1.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Convert the timespec structure to a
|
||||
@ -1552,28 +1753,56 @@ _thread_kern_set_timeout(struct timespec * timeout)
|
||||
* Set the wakeup time to something that can be recognised as
|
||||
* different to an actual time of day:
|
||||
*/
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = -1;
|
||||
_thread_run->wakeup_time.ts_nsec = -1;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = -1;
|
||||
_thread_run->wakeup_time.tv_nsec = -1;
|
||||
#endif
|
||||
}
|
||||
/* Check if no waiting is required: */
|
||||
#if defined(__FreeBSD__)
|
||||
else if (timeout->ts_sec == 0 && timeout->ts_nsec == 0) {
|
||||
#else
|
||||
else if (timeout->tv_sec == 0 && timeout->tv_nsec == 0) {
|
||||
#endif
|
||||
/* Set the wake up time to 'immediately': */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = 0;
|
||||
_thread_run->wakeup_time.ts_nsec = 0;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = 0;
|
||||
_thread_run->wakeup_time.tv_nsec = 0;
|
||||
#endif
|
||||
} else {
|
||||
/* Get the current time: */
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ¤t_time);
|
||||
|
||||
/* Calculate the time for the current thread to wake up: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = current_time.ts_sec + timeout->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + timeout->ts_nsec;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
|
||||
_thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + timeout->tv_nsec;
|
||||
#endif
|
||||
|
||||
/* Check if the nanosecond field needs to wrap: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/* Wrap the nanosecond field: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec += 1;
|
||||
_thread_run->wakeup_time.ts_nsec -= 1000000000;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec += 1;
|
||||
_thread_run->wakeup_time.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
44
lib/libkse/thread/thr_multi_np.c
Normal file
44
lib/libkse/thread/thr_multi_np.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_multi_np()
|
||||
{
|
||||
/* Return to multi-threaded scheduling mode: */
|
||||
_thread_single = NULL;
|
||||
return(0);
|
||||
}
|
||||
#endif
|
@ -41,62 +41,75 @@ pthread_mutex_init(pthread_mutex_t * mutex,
|
||||
const pthread_mutexattr_t * mutex_attr)
|
||||
{
|
||||
enum pthread_mutextype type;
|
||||
pthread_mutex_t pmutex;
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Check if the mutex attributes specify some mutex other than fast: */
|
||||
if (mutex_attr != NULL && mutex_attr->m_type != MUTEX_TYPE_FAST) {
|
||||
/* Check if the mutex type is out of range: */
|
||||
if (mutex_attr->m_type >= MUTEX_TYPE_MAX) {
|
||||
if (mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Check if default mutex attributes: */
|
||||
if (mutex_attr == NULL || *mutex_attr == NULL) {
|
||||
/* Default to a fast mutex: */
|
||||
type = MUTEX_TYPE_FAST;
|
||||
} else if ((*mutex_attr)->m_type >= MUTEX_TYPE_MAX) {
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Use the requested mutex type: */
|
||||
type = mutex_attr->m_type;
|
||||
}
|
||||
} else {
|
||||
/* Default to a fast mutex: */
|
||||
type = MUTEX_TYPE_FAST;
|
||||
}
|
||||
|
||||
/* Check no errors so far: */
|
||||
if (ret == 0) {
|
||||
/* Reset the mutex flags: */
|
||||
mutex->m_flags = 0;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Reset the mutex count: */
|
||||
mutex->m_data.m_count = 0;
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
type = (*mutex_attr)->m_type;
|
||||
}
|
||||
|
||||
/* Initialise the rest of the mutex: */
|
||||
_thread_queue_init(&mutex->m_queue);
|
||||
mutex->m_flags |= MUTEX_FLAGS_INITED;
|
||||
mutex->m_owner = NULL;
|
||||
mutex->m_type = type;
|
||||
/* Check no errors so far: */
|
||||
if (ret == 0) {
|
||||
if ((pmutex = (pthread_mutex_t) malloc(sizeof(struct pthread_mutex))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Reset the mutex flags: */
|
||||
pmutex->m_flags = 0;
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Reset the mutex count: */
|
||||
pmutex->m_data.m_count = 0;
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* Initialise the rest of the mutex: */
|
||||
_thread_queue_init(&pmutex->m_queue);
|
||||
pmutex->m_flags |= MUTEX_FLAGS_INITED;
|
||||
pmutex->m_owner = NULL;
|
||||
pmutex->m_type = type;
|
||||
*mutex = pmutex;
|
||||
} else {
|
||||
free(pmutex);
|
||||
*mutex = NULL;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
@ -108,38 +121,43 @@ pthread_mutex_destroy(pthread_mutex_t * mutex)
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (mutex->m_type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Reset the mutex count: */
|
||||
mutex->m_data.m_count = 0;
|
||||
break;
|
||||
|
||||
/* Trap undefined mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch ((*mutex)->m_type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Nothing to do here. */
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Reset the mutex count: */
|
||||
(*mutex)->m_data.m_count = 0;
|
||||
break;
|
||||
|
||||
/* Trap undefined mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clean up the mutex in case that others want to use it: */
|
||||
_thread_queue_init(&(*mutex)->m_queue);
|
||||
(*mutex)->m_owner = NULL;
|
||||
(*mutex)->m_flags = 0;
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Clean up the mutex in case that others want to use it: */
|
||||
_thread_queue_init(&mutex->m_queue);
|
||||
mutex->m_owner = NULL;
|
||||
mutex->m_flags = 0;
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
}
|
||||
@ -150,56 +168,61 @@ pthread_mutex_trylock(pthread_mutex_t * mutex)
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (mutex->m_type) {
|
||||
/* Process according to mutex type: */
|
||||
switch ((*mutex)->m_type) {
|
||||
/* Fast mutex: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Check if this mutex is not locked: */
|
||||
if (mutex->m_owner == NULL) {
|
||||
/* Lock the mutex for the running thread: */
|
||||
mutex->m_owner = _thread_run;
|
||||
} else {
|
||||
/* Return a busy error: */
|
||||
_thread_seterrno(_thread_run, EBUSY);
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Check if this mutex is locked: */
|
||||
if (mutex->m_owner != NULL) {
|
||||
/*
|
||||
* Check if the mutex is locked by the running
|
||||
* thread:
|
||||
*/
|
||||
if (mutex->m_owner == _thread_run) {
|
||||
/* Increment the lock count: */
|
||||
mutex->m_data.m_count++;
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Check if this mutex is not locked: */
|
||||
if ((*mutex)->m_owner == NULL) {
|
||||
/* Lock the mutex for the running thread: */
|
||||
(*mutex)->m_owner = _thread_run;
|
||||
} else {
|
||||
/* Return a busy error: */
|
||||
_thread_seterrno(_thread_run, EBUSY);
|
||||
errno = EBUSY;
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
/* Lock the mutex for the running thread: */
|
||||
mutex->m_owner = _thread_run;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Check if this mutex is locked: */
|
||||
if ((*mutex)->m_owner != NULL) {
|
||||
/*
|
||||
* Check if the mutex is locked by the running
|
||||
* thread:
|
||||
*/
|
||||
if ((*mutex)->m_owner == _thread_run) {
|
||||
/* Increment the lock count: */
|
||||
(*mutex)->m_data.m_count++;
|
||||
} else {
|
||||
/* Return a busy error: */
|
||||
errno = EBUSY;
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
/* Lock the mutex for the running thread: */
|
||||
(*mutex)->m_owner = _thread_run;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
@ -211,81 +234,86 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (mutex->m_type) {
|
||||
/* Process according to mutex type: */
|
||||
switch ((*mutex)->m_type) {
|
||||
/* Fast mutexes do not check for any error conditions: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/*
|
||||
* Enter a loop to wait for the mutex to be locked by the
|
||||
* current thread:
|
||||
*/
|
||||
while (mutex->m_owner != _thread_run) {
|
||||
/* Check if the mutex is not locked: */
|
||||
if (mutex->m_owner == NULL) {
|
||||
/* Lock the mutex for this thread: */
|
||||
mutex->m_owner = _thread_run;
|
||||
} else {
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex:
|
||||
*/
|
||||
_thread_queue_enq(&mutex->m_queue, _thread_run);
|
||||
case MUTEX_TYPE_FAST:
|
||||
/*
|
||||
* Enter a loop to wait for the mutex to be locked by the
|
||||
* current thread:
|
||||
*/
|
||||
while ((*mutex)->m_owner != _thread_run) {
|
||||
/* Check if the mutex is not locked: */
|
||||
if ((*mutex)->m_owner == NULL) {
|
||||
/* Lock the mutex for this thread: */
|
||||
(*mutex)->m_owner = _thread_run;
|
||||
} else {
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex:
|
||||
*/
|
||||
_thread_queue_enq(&(*mutex)->m_queue, _thread_run);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
|
||||
/* Block signals: */
|
||||
_thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/*
|
||||
* Enter a loop to wait for the mutex to be locked by the
|
||||
* current thread:
|
||||
*/
|
||||
while (mutex->m_owner != _thread_run) {
|
||||
/* Check if the mutex is not locked: */
|
||||
if (mutex->m_owner == NULL) {
|
||||
/* Lock the mutex for this thread: */
|
||||
mutex->m_owner = _thread_run;
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/*
|
||||
* Enter a loop to wait for the mutex to be locked by the
|
||||
* current thread:
|
||||
*/
|
||||
while ((*mutex)->m_owner != _thread_run) {
|
||||
/* Check if the mutex is not locked: */
|
||||
if ((*mutex)->m_owner == NULL) {
|
||||
/* Lock the mutex for this thread: */
|
||||
(*mutex)->m_owner = _thread_run;
|
||||
|
||||
/* Reset the lock count for this mutex: */
|
||||
mutex->m_data.m_count = 0;
|
||||
} else {
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex:
|
||||
*/
|
||||
_thread_queue_enq(&mutex->m_queue, _thread_run);
|
||||
/* Reset the lock count for this mutex: */
|
||||
(*mutex)->m_data.m_count = 0;
|
||||
} else {
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex:
|
||||
*/
|
||||
_thread_queue_enq(&(*mutex)->m_queue, _thread_run);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
|
||||
/* Block signals: */
|
||||
_thread_kern_sched_state(PS_MUTEX_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment the lock count for this mutex: */
|
||||
mutex->m_data.m_count++;
|
||||
break;
|
||||
/* Increment the lock count for this mutex: */
|
||||
(*mutex)->m_data.m_count++;
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
@ -297,62 +325,67 @@ pthread_mutex_unlock(pthread_mutex_t * mutex)
|
||||
int ret = 0;
|
||||
int status;
|
||||
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
if (mutex == NULL || *mutex == NULL) {
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
/* Process according to mutex type: */
|
||||
switch (mutex->m_type) {
|
||||
/* Process according to mutex type: */
|
||||
switch ((*mutex)->m_type) {
|
||||
/* Fast mutexes do not check for any error conditions: */
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Check if the running thread is not the owner of the mutex: */
|
||||
if (mutex->m_owner != _thread_run) {
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
}
|
||||
/*
|
||||
* Get the next thread from the queue of threads waiting on
|
||||
* the mutex:
|
||||
*/
|
||||
else if ((mutex->m_owner = _thread_queue_deq(&mutex->m_queue)) != NULL) {
|
||||
/* Allow the new owner of the mutex to run: */
|
||||
mutex->m_owner->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
case MUTEX_TYPE_FAST:
|
||||
/* Check if the running thread is not the owner of the mutex: */
|
||||
if ((*mutex)->m_owner != _thread_run) {
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
}
|
||||
/*
|
||||
* Get the next thread from the queue of threads waiting on
|
||||
* the mutex:
|
||||
*/
|
||||
else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
|
||||
/* Allow the new owner of the mutex to run: */
|
||||
(*mutex)->m_owner->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Counting mutex: */
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Check if the running thread is not the owner of the mutex: */
|
||||
if (mutex->m_owner != _thread_run) {
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
}
|
||||
/* Check if there are still counts: */
|
||||
else if (mutex->m_data.m_count) {
|
||||
/* Decrement the count: */
|
||||
mutex->m_data.m_count--;
|
||||
}
|
||||
/*
|
||||
* Get the next thread from the queue of threads waiting on
|
||||
* the mutex:
|
||||
*/
|
||||
else if ((mutex->m_owner = _thread_queue_deq(&mutex->m_queue)) != NULL) {
|
||||
/* Allow the new owner of the mutex to run: */
|
||||
mutex->m_owner->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
case MUTEX_TYPE_COUNTING_FAST:
|
||||
/* Check if the running thread is not the owner of the mutex: */
|
||||
if ((*mutex)->m_owner != _thread_run) {
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
}
|
||||
/* Check if there are still counts: */
|
||||
else if ((*mutex)->m_data.m_count) {
|
||||
/* Decrement the count: */
|
||||
(*mutex)->m_data.m_count--;
|
||||
}
|
||||
/*
|
||||
* Get the next thread from the queue of threads waiting on
|
||||
* the mutex:
|
||||
*/
|
||||
else if (((*mutex)->m_owner = _thread_queue_deq(&(*mutex)->m_queue)) != NULL) {
|
||||
/* Allow the new owner of the mutex to run: */
|
||||
(*mutex)->m_owner->state = PS_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Trap invalid mutex types: */
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
_thread_seterrno(_thread_run, EINVAL);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Return an invalid argument error: */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
/* Unblock signals: */
|
||||
_thread_kern_sig_unblock(status);
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
@ -38,50 +39,138 @@
|
||||
int
|
||||
nanosleep(struct timespec * time_to_sleep, struct timespec * time_remaining)
|
||||
{
|
||||
int ret = 0;
|
||||
struct timespec current_time;
|
||||
struct timespec current_time1;
|
||||
struct timespec remaining_time;
|
||||
struct timeval tv;
|
||||
|
||||
/* Get the current time: */
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ¤t_time);
|
||||
/* Check if the time to sleep is legal: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (time_to_sleep == NULL || time_to_sleep->ts_nsec < 0 || time_to_sleep->ts_nsec > 1000000000) {
|
||||
#else
|
||||
if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000) {
|
||||
#endif
|
||||
/* Return an EINVAL error : */
|
||||
errno = EINVAL;
|
||||
ret = -1;
|
||||
} else {
|
||||
/* Get the current time: */
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ¤t_time);
|
||||
|
||||
/* Calculate the time for the current thread to wake up: */
|
||||
_thread_run->wakeup_time.ts_sec = current_time.ts_sec + time_to_sleep->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + time_to_sleep->ts_nsec;
|
||||
/* Calculate the time for the current thread to wake up: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec = current_time.ts_sec + time_to_sleep->ts_sec;
|
||||
_thread_run->wakeup_time.ts_nsec = current_time.ts_nsec + time_to_sleep->ts_nsec;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec;
|
||||
_thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec;
|
||||
#endif
|
||||
|
||||
/* Check if the nanosecond field has overflowed: */
|
||||
if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
|
||||
/* Wrap the nanosecond field: */
|
||||
_thread_run->wakeup_time.ts_sec += 1;
|
||||
_thread_run->wakeup_time.ts_nsec -= 1000000000;
|
||||
}
|
||||
/* Reschedule the current thread to sleep: */
|
||||
_thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
|
||||
/* Check if the nanosecond field has overflowed: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (_thread_run->wakeup_time.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (_thread_run->wakeup_time.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/* Wrap the nanosecond field: */
|
||||
#if defined(__FreeBSD__)
|
||||
_thread_run->wakeup_time.ts_sec += 1;
|
||||
_thread_run->wakeup_time.ts_nsec -= 1000000000;
|
||||
#else
|
||||
_thread_run->wakeup_time.tv_sec += 1;
|
||||
_thread_run->wakeup_time.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Reschedule the current thread to sleep: */
|
||||
_thread_kern_sched_state(PS_SLEEP_WAIT, __FILE__, __LINE__);
|
||||
|
||||
/* Check if the time remaining is to be returned: */
|
||||
if (time_remaining != NULL) {
|
||||
/* Get the current time: */
|
||||
gettimeofday(&tv, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&tv, ¤t_time1);
|
||||
|
||||
/* Return the actual time slept: */
|
||||
time_remaining->ts_sec = time_to_sleep->ts_sec + current_time1.ts_sec - current_time.ts_sec;
|
||||
time_remaining->ts_nsec = time_to_sleep->ts_nsec + current_time1.ts_nsec - current_time.ts_nsec;
|
||||
/* Calculate the remaining time to sleep: */
|
||||
#if defined(__FreeBSD__)
|
||||
remaining_time.ts_sec = time_to_sleep->ts_sec + current_time.ts_sec - current_time1.ts_sec;
|
||||
remaining_time.ts_nsec = time_to_sleep->ts_nsec + current_time.ts_nsec - current_time1.ts_nsec;
|
||||
#else
|
||||
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;
|
||||
#endif
|
||||
|
||||
/* Check if the nanosecond field has underflowed: */
|
||||
if (time_remaining->ts_nsec < 0) {
|
||||
#if defined(__FreeBSD__)
|
||||
if (remaining_time.ts_nsec < 0) {
|
||||
#else
|
||||
if (remaining_time.tv_nsec < 0) {
|
||||
#endif
|
||||
/* Handle the underflow: */
|
||||
time_remaining->ts_sec -= 1;
|
||||
time_remaining->ts_nsec += 1000000000;
|
||||
#if defined(__FreeBSD__)
|
||||
remaining_time.ts_sec -= 1;
|
||||
remaining_time.ts_nsec += 1000000000;
|
||||
#else
|
||||
remaining_time.tv_sec -= 1;
|
||||
remaining_time.tv_nsec += 1000000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the nanosecond field has overflowed: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (remaining_time.ts_nsec >= 1000000000) {
|
||||
#else
|
||||
if (remaining_time.tv_nsec >= 1000000000) {
|
||||
#endif
|
||||
/* Handle the overflow: */
|
||||
#if defined(__FreeBSD__)
|
||||
remaining_time.ts_sec += 1;
|
||||
remaining_time.ts_nsec -= 1000000000;
|
||||
#else
|
||||
remaining_time.tv_sec += 1;
|
||||
remaining_time.tv_nsec -= 1000000000;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the sleep was longer than the required time: */
|
||||
if (time_remaining->ts_sec < 0) {
|
||||
/* Reset the time teft: */
|
||||
time_remaining->ts_sec = 0;
|
||||
time_remaining->ts_nsec = 0;
|
||||
#if defined(__FreeBSD__)
|
||||
if (remaining_time.ts_sec < 0) {
|
||||
#else
|
||||
if (remaining_time.tv_sec < 0) {
|
||||
#endif
|
||||
/* Reset the time left: */
|
||||
#if defined(__FreeBSD__)
|
||||
remaining_time.ts_sec = 0;
|
||||
remaining_time.ts_nsec = 0;
|
||||
#else
|
||||
remaining_time.tv_sec = 0;
|
||||
remaining_time.tv_nsec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the time remaining is to be returned: */
|
||||
if (time_remaining != NULL) {
|
||||
/* Return the actual time slept: */
|
||||
#if defined(__FreeBSD__)
|
||||
time_remaining->ts_sec = remaining_time.ts_sec;
|
||||
time_remaining->ts_nsec = remaining_time.ts_nsec;
|
||||
#else
|
||||
time_remaining->tv_sec = remaining_time.tv_sec;
|
||||
time_remaining->tv_nsec = remaining_time.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the entire sleep was not completed: */
|
||||
#if defined(__FreeBSD__)
|
||||
if (remaining_time.ts_nsec != 0 || remaining_time.ts_sec != 0) {
|
||||
#else
|
||||
if (remaining_time.tv_nsec != 0 || remaining_time.tv_sec != 0) {
|
||||
#endif
|
||||
/* Return an EINTR error : */
|
||||
errno = EINTR;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
@ -55,8 +56,8 @@ open(const char *path, int flags,...)
|
||||
mode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
}
|
||||
/* Open the file, forcing it to use non-blocking I/O operations: */
|
||||
if ((fd = _thread_sys_open(path, flags | O_NONBLOCK, mode)) < 0) {
|
||||
/* Open the file: */
|
||||
if ((fd = _thread_sys_open(path, flags, mode)) < 0) {
|
||||
}
|
||||
/* Initialise the file descriptor table entry: */
|
||||
else if (_thread_fd_table_init(fd) != 0) {
|
||||
@ -65,12 +66,6 @@ open(const char *path, int flags,...)
|
||||
|
||||
/* Reset the file descriptor: */
|
||||
fd = -1;
|
||||
} else {
|
||||
/*
|
||||
* Save the file open flags so that they can be checked
|
||||
* later:
|
||||
*/
|
||||
_thread_fd_table[fd]->flags = flags;
|
||||
}
|
||||
|
||||
/* Unblock signals: */
|
||||
|
@ -58,6 +58,129 @@
|
||||
*/
|
||||
#define PANIC(string) _thread_exit(__FILE__,__LINE__,string)
|
||||
|
||||
/*
|
||||
* Queue definitions.
|
||||
*/
|
||||
struct pthread_queue {
|
||||
struct pthread *q_next;
|
||||
struct pthread *q_last;
|
||||
void *q_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Static queue initialization values.
|
||||
*/
|
||||
#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL }
|
||||
|
||||
/*
|
||||
* Mutex definitions.
|
||||
*/
|
||||
enum pthread_mutextype {
|
||||
MUTEX_TYPE_FAST = 1,
|
||||
MUTEX_TYPE_COUNTING_FAST = 2, /* Recursive */
|
||||
MUTEX_TYPE_MAX
|
||||
};
|
||||
|
||||
union pthread_mutex_data {
|
||||
void *m_ptr;
|
||||
int m_count;
|
||||
};
|
||||
|
||||
struct pthread_mutex {
|
||||
enum pthread_mutextype m_type;
|
||||
struct pthread_queue m_queue;
|
||||
struct pthread *m_owner;
|
||||
union pthread_mutex_data m_data;
|
||||
long m_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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_INITIALIZER \
|
||||
{ MUTEX_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, \
|
||||
NULL, { NULL }, MUTEX_FLAGS_INITED }
|
||||
|
||||
struct pthread_mutex_attr {
|
||||
enum pthread_mutextype m_type;
|
||||
long m_flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Condition variable definitions.
|
||||
*/
|
||||
enum pthread_cond_type {
|
||||
COND_TYPE_FAST,
|
||||
COND_TYPE_MAX
|
||||
};
|
||||
|
||||
struct pthread_cond {
|
||||
enum pthread_cond_type c_type;
|
||||
struct pthread_queue c_queue;
|
||||
void *c_data;
|
||||
long c_flags;
|
||||
};
|
||||
|
||||
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_INITIALIZER \
|
||||
{ COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, COND_FLAGS_INITED }
|
||||
|
||||
/*
|
||||
* Cleanup definitions.
|
||||
*/
|
||||
struct pthread_cleanup {
|
||||
struct pthread_cleanup *next;
|
||||
void (*routine) ();
|
||||
void *routine_arg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Scheduling definitions.
|
||||
*/
|
||||
enum schedparam_policy {
|
||||
SCHED_RR,
|
||||
SCHED_IO,
|
||||
SCHED_FIFO,
|
||||
SCHED_OTHER
|
||||
};
|
||||
|
||||
struct pthread_attr {
|
||||
enum schedparam_policy schedparam_policy;
|
||||
int prio;
|
||||
int suspend;
|
||||
int flags;
|
||||
void *arg_attr;
|
||||
void (*cleanup_attr) ();
|
||||
void *stackaddr_attr;
|
||||
size_t stacksize_attr;
|
||||
};
|
||||
|
||||
struct sched_param {
|
||||
int prio;
|
||||
void *no_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Thread creation state attributes.
|
||||
*/
|
||||
@ -67,14 +190,11 @@
|
||||
/*
|
||||
* Miscellaneous definitions.
|
||||
*/
|
||||
#define PTHREAD_STACK_MIN 1024
|
||||
#define PTHREAD_STACK_DEFAULT 65536
|
||||
#define PTHREAD_DATAKEYS_MAX 256
|
||||
#define PTHREAD_DEFAULT_PRIORITY 64
|
||||
#define PTHREAD_MAX_PRIORITY 126
|
||||
#define PTHREAD_MIN_PRIORITY 0
|
||||
#define _POSIX_THREAD_ATTR_STACKSIZE
|
||||
#define _POSIX_THREAD_DESTRUTOR_ITERATIONS 4
|
||||
|
||||
/*
|
||||
* Clock resolution in nanoseconds.
|
||||
@ -190,10 +310,10 @@ struct pthread {
|
||||
* Thread start routine, argument, stack pointer and thread
|
||||
* attributes.
|
||||
*/
|
||||
void *(*start_routine)(void *);
|
||||
void *arg;
|
||||
void *stack;
|
||||
pthread_attr_t attr;
|
||||
void *(*start_routine)(void *);
|
||||
void *arg;
|
||||
void *stack;
|
||||
struct pthread_attr attr;
|
||||
|
||||
/*
|
||||
* Thread-specific signal handler interface:
|
||||
@ -319,6 +439,17 @@ SCLASS struct pthread *_thread_run
|
||||
;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ptr to the thread running in single-threaded mode or NULL if
|
||||
* running multi-threaded (default POSIX behaviour).
|
||||
*/
|
||||
SCLASS struct pthread *_thread_single
|
||||
#ifdef GLOBAL_PTHREAD_PRIVATE
|
||||
= NULL;
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
|
||||
/* Ptr to the first thread in the thread linked list: */
|
||||
SCLASS struct pthread *_thread_link_list
|
||||
#ifdef GLOBAL_PTHREAD_PRIVATE
|
||||
@ -372,7 +503,7 @@ SCLASS struct pthread *_thread_initial
|
||||
#endif
|
||||
|
||||
/* Default thread attributes: */
|
||||
SCLASS pthread_attr_t pthread_attr_default
|
||||
SCLASS struct pthread_attr pthread_attr_default
|
||||
#ifdef GLOBAL_PTHREAD_PRIVATE
|
||||
= { SCHED_RR, PTHREAD_DEFAULT_PRIORITY, PTHREAD_CREATE_RUNNING,
|
||||
PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, PTHREAD_STACK_DEFAULT };
|
||||
@ -570,6 +701,7 @@ pid_t _thread_sys_fork(void);
|
||||
pid_t _thread_sys_tcgetpgrp(int);
|
||||
ssize_t _thread_sys_read(int, void *, size_t);
|
||||
ssize_t _thread_sys_write(int, const void *, size_t);
|
||||
void _thread_sys__exit(int);
|
||||
#endif
|
||||
|
||||
/* #include <fcntl.h> */
|
||||
|
70
lib/libkse/thread/thr_resume_np.c
Normal file
70
lib/libkse/thread/thr_resume_np.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_resume_np(pthread_t thread)
|
||||
{
|
||||
int ret = -1;
|
||||
pthread_t pthread;
|
||||
/*
|
||||
* Search for the thread in the linked list.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
|
||||
/* Is this the thread? */
|
||||
if (pthread == thread) {
|
||||
/* Found the thread. Is it suspended? */
|
||||
if (pthread->state == PS_SUSPENDED) {
|
||||
/* Allow the thread to run. */
|
||||
pthread->state = PS_RUNNING;
|
||||
ret = 0;
|
||||
} else if (pthread->state == PS_RUNNING) {
|
||||
/* Thread is already running. */
|
||||
ret = 0;
|
||||
} else {
|
||||
/* Thread is in some other state. */
|
||||
_thread_seterrno(_thread_run,EINVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check if thread was not found. */
|
||||
if (ret == -1) {
|
||||
/* No such thread */
|
||||
_thread_seterrno(_thread_run,ESRCH);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
@ -142,36 +142,29 @@ select(int numfds, fd_set * readfds, fd_set * writefds,
|
||||
|
||||
if (ret > 0) {
|
||||
if (readfds != NULL) {
|
||||
FD_ZERO(readfds);
|
||||
for (i = 0; i < numfds; i++) {
|
||||
if (FD_ISSET(i, &data.readfds)) {
|
||||
FD_SET(i, readfds);
|
||||
if (FD_ISSET(i, readfds) &&
|
||||
!FD_ISSET(i, &data.readfds)) {
|
||||
FD_CLR(i, readfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writefds != NULL) {
|
||||
FD_ZERO(writefds);
|
||||
for (i = 0; i < numfds; i++) {
|
||||
if (FD_ISSET(i, &data.writefds)) {
|
||||
FD_SET(i, writefds);
|
||||
if (FD_ISSET(i, writefds) &&
|
||||
!FD_ISSET(i, &data.writefds)) {
|
||||
FD_CLR(i, writefds);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exceptfds != NULL) {
|
||||
FD_ZERO(exceptfds);
|
||||
for (i = 0; i < numfds; i++) {
|
||||
if (FD_ISSET(i, &data.exceptfds)) {
|
||||
FD_SET(i, exceptfds);
|
||||
if (FD_ISSET(i, exceptfds) &&
|
||||
!FD_ISSET(i, &data.exceptfds)) {
|
||||
FD_CLR(i, exceptfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (exceptfds != NULL)
|
||||
FD_ZERO(exceptfds);
|
||||
if (writefds != NULL)
|
||||
FD_ZERO(writefds);
|
||||
if (readfds != NULL)
|
||||
FD_ZERO(readfds);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
|
@ -31,6 +31,8 @@
|
||||
*
|
||||
*/
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
@ -40,6 +42,7 @@ void
|
||||
_thread_sig_handler(int sig, int code, struct sigcontext * scp)
|
||||
{
|
||||
char c;
|
||||
int i;
|
||||
pthread_t pthread;
|
||||
|
||||
/*
|
||||
@ -67,16 +70,52 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp)
|
||||
} else {
|
||||
/* Handle depending on signal type: */
|
||||
switch (sig) {
|
||||
/* Interval timer used for timeslicing: */
|
||||
/* Interval timer used for timeslicing: */
|
||||
case SIGVTALRM:
|
||||
/*
|
||||
* Don't add the signal to any thread. Just want to
|
||||
* call
|
||||
* call the scheduler:
|
||||
*/
|
||||
/* the scheduler: */
|
||||
break;
|
||||
|
||||
/* Signals specific to the running thread: */
|
||||
/* Child termination: */
|
||||
case SIGCHLD:
|
||||
/*
|
||||
* Enter a loop to process each thread in the linked
|
||||
* list:
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL;
|
||||
pthread = pthread->nxt) {
|
||||
/*
|
||||
* Add the signal to the set of pending
|
||||
* signals:
|
||||
*/
|
||||
pthread->sigpend[sig] += 1;
|
||||
if (pthread->state == PS_WAIT_WAIT) {
|
||||
/* Reset the error: */
|
||||
/* There should be another flag so that this is not required! ### */
|
||||
_thread_seterrno(pthread, 0);
|
||||
|
||||
/* Change the state of the thread to run: */
|
||||
pthread->state = PS_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through the file list and set all files
|
||||
* to non-blocking again in case the child
|
||||
* set some of them to block. Sigh.
|
||||
*/
|
||||
for (i = 0; i < _thread_dtablesize; i++) {
|
||||
/* Check if this file is used: */
|
||||
if (_thread_fd_table[i] != NULL) {
|
||||
/* Set the file descriptor to non-blocking: */
|
||||
_thread_sys_fcntl(i, F_SETFL, _thread_fd_table[i]->flags | O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Signals specific to the running thread: */
|
||||
case SIGBUS:
|
||||
case SIGEMT:
|
||||
case SIGFPE:
|
||||
@ -88,7 +127,7 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp)
|
||||
_thread_run->sigpend[sig] += 1;
|
||||
break;
|
||||
|
||||
/* Signals to send to all threads: */
|
||||
/* Signals to send to all threads: */
|
||||
default:
|
||||
/*
|
||||
* Enter a loop to process each thread in the linked
|
||||
|
@ -47,6 +47,9 @@ sigsuspend(const sigset_t * set)
|
||||
/* Save the current sigmal mask: */
|
||||
oset = _thread_run->sigmask;
|
||||
|
||||
/* Combine the caller's mask with the current one: */
|
||||
_thread_run->sigmask |= *set;
|
||||
|
||||
/* Wait for a signal: */
|
||||
_thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
|
||||
|
||||
|
44
lib/libkse/thread/thr_single_np.c
Normal file
44
lib/libkse/thread/thr_single_np.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int pthread_single_np()
|
||||
{
|
||||
/* Enter single-threaded (non-POSIX) scheduling mode: */
|
||||
_thread_single = _thread_run;
|
||||
return(0);
|
||||
}
|
||||
#endif
|
@ -39,12 +39,12 @@
|
||||
#include "pthread_private.h"
|
||||
|
||||
/* Static variables: */
|
||||
static struct pthread_key key_table[PTHREAD_DATAKEYS_MAX];
|
||||
static struct pthread_key key_table[PTHREAD_KEYS_MAX];
|
||||
|
||||
int
|
||||
pthread_keycreate(pthread_key_t * key, void (*destructor) (void *))
|
||||
pthread_key_create(pthread_key_t * key, void (*destructor) (void *))
|
||||
{
|
||||
for ((*key) = 0; (*key) < PTHREAD_DATAKEYS_MAX; (*key)++) {
|
||||
for ((*key) = 0; (*key) < PTHREAD_KEYS_MAX; (*key)++) {
|
||||
if (key_table[(*key)].count == 0) {
|
||||
key_table[(*key)].count++;
|
||||
key_table[(*key)].destructor = destructor;
|
||||
@ -63,7 +63,7 @@ pthread_key_delete(pthread_key_t key)
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
if (key < PTHREAD_DATAKEYS_MAX) {
|
||||
if (key < PTHREAD_KEYS_MAX) {
|
||||
switch (key_table[key].count) {
|
||||
case 1:
|
||||
key_table[key].destructor = NULL;
|
||||
@ -94,8 +94,8 @@ _thread_cleanupspecific(void)
|
||||
/* Block signals: */
|
||||
_thread_kern_sig_block(&status);
|
||||
|
||||
for (itr = 0; itr < _POSIX_THREAD_DESTRUTOR_ITERATIONS; itr++) {
|
||||
for (key = 0; key < PTHREAD_DATAKEYS_MAX; key++) {
|
||||
for (itr = 0; itr < PTHREAD_DESTRUCTOR_ITERATIONS; itr++) {
|
||||
for (key = 0; key < PTHREAD_KEYS_MAX; key++) {
|
||||
if (_thread_run->specific_data_count) {
|
||||
if (_thread_run->specific_data[key]) {
|
||||
data = (void *) _thread_run->specific_data[key];
|
||||
@ -125,8 +125,8 @@ static inline const void **
|
||||
pthread_key_allocate_data(void)
|
||||
{
|
||||
const void **new_data;
|
||||
if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_DATAKEYS_MAX)) != NULL) {
|
||||
memset((void *) new_data, 0, sizeof(void *) * PTHREAD_DATAKEYS_MAX);
|
||||
if ((new_data = (const void **) malloc(sizeof(void *) * PTHREAD_KEYS_MAX)) != NULL) {
|
||||
memset((void *) new_data, 0, sizeof(void *) * PTHREAD_KEYS_MAX);
|
||||
}
|
||||
return (new_data);
|
||||
}
|
||||
@ -154,7 +154,7 @@ pthread_setspecific(pthread_key_t key, const void *value)
|
||||
}
|
||||
|
||||
if ((pthread->specific_data) || (pthread->specific_data = pthread_key_allocate_data())) {
|
||||
if ((key < PTHREAD_DATAKEYS_MAX) && (key_table)) {
|
||||
if ((key < PTHREAD_KEYS_MAX) && (key_table)) {
|
||||
if (key_table[key].count) {
|
||||
if (pthread->specific_data[key] == NULL) {
|
||||
if (value != NULL) {
|
||||
@ -213,7 +213,7 @@ pthread_getspecific(pthread_key_t key, void **p_data)
|
||||
rval = -1;
|
||||
}
|
||||
/* Check if there is specific data: */
|
||||
else if (pthread->specific_data != NULL && (key < PTHREAD_DATAKEYS_MAX) && (key_table)) {
|
||||
else if (pthread->specific_data != NULL && (key < PTHREAD_KEYS_MAX) && (key_table)) {
|
||||
/* Check if this key has been used before: */
|
||||
if (key_table[key].count) {
|
||||
/* Return the value: */
|
||||
|
67
lib/libkse/thread/thr_suspend_np.c
Normal file
67
lib/libkse/thread/thr_suspend_np.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by John Birrell.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <errno.h>
|
||||
#ifdef _THREAD_SAFE
|
||||
#include <pthread.h>
|
||||
#include "pthread_private.h"
|
||||
|
||||
int
|
||||
pthread_suspend_np(pthread_t thread)
|
||||
{
|
||||
int ret = -1;
|
||||
pthread_t pthread;
|
||||
/*
|
||||
* Search for the thread in the linked list.
|
||||
*/
|
||||
for (pthread = _thread_link_list; pthread != NULL && ret == -1; pthread = pthread->nxt) {
|
||||
/* Is this the thread? */
|
||||
if (pthread == thread) {
|
||||
/* Found the thread. Is it running? */
|
||||
if (pthread->state != PS_RUNNING &&
|
||||
pthread->state != PS_SUSPENDED) {
|
||||
/* The thread operation has been interrupted */
|
||||
_thread_seterrno(pthread,EINTR);
|
||||
}
|
||||
/* Suspend the thread. */
|
||||
pthread->state = PS_SUSPENDED;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
/* Check if thread was not found. */
|
||||
if (ret == -1) {
|
||||
/* No such thread */
|
||||
_thread_seterrno(_thread_run,ESRCH);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
@ -20,6 +20,7 @@ PRECIOUSLIB= yes
|
||||
.include "${.CURDIR}/gen/Makefile.inc"
|
||||
.include "${.CURDIR}/gmon/Makefile.inc"
|
||||
.include "${.CURDIR}/locale/Makefile.inc"
|
||||
.include "${.CURDIR}/man/Makefile.inc"
|
||||
.include "${.CURDIR}/net/Makefile.inc"
|
||||
.include "${.CURDIR}/nls/Makefile.inc"
|
||||
.include "${.CURDIR}/quad/Makefile.inc"
|
||||
@ -38,24 +39,8 @@ CFLAGS+= -DYP
|
||||
.endif
|
||||
.include "${.CURDIR}/${MACHINE}/sys/Makefile.inc"
|
||||
|
||||
KQSRCS= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \
|
||||
lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \
|
||||
subdi3.c ucmpdi2.c udivdi3.c umoddi3.c xordi3.c
|
||||
KSRCS= bcmp.c ffs.c index.c mcount.c rindex.c strcat.c strcmp.c strcpy.c \
|
||||
strlen.c strncpy.c
|
||||
|
||||
libkern: libkern.gen libkern.${MACHINE}
|
||||
|
||||
libkern.gen: ${KQSRCS} ${KSRCS}
|
||||
cp -p ${.CURDIR}/quad/quad.h ${.ALLSRC} /sys/libkern
|
||||
|
||||
libkern.${MACHINE}:: ${KMSRCS}
|
||||
.if defined(KMSRCS) && !empty(KMSRCS)
|
||||
cp -p ${.ALLSRC} /sys/libkern/${MACHINE}
|
||||
.endif
|
||||
|
||||
#beforeinstall: tags
|
||||
# ${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc.tags
|
||||
beforeinstall: tags
|
||||
${INSTALL} ${COPY} -o bin -g bin -m 444 tags /var/db/libc_r.tags
|
||||
|
||||
tags: ${SRCS}
|
||||
ctags ${.ALLSRC:M*.c}
|
||||
|
17
lib/libpthread/man/Makefile.inc
Normal file
17
lib/libpthread/man/Makefile.inc
Normal file
@ -0,0 +1,17 @@
|
||||
# $Id$
|
||||
|
||||
# POSIX thread man files
|
||||
|
||||
.PATH: ${.CURDIR}/man
|
||||
|
||||
MAN3+= 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_once.3 \
|
||||
pthread_self.3 \
|
||||
pthread_setspecific.3
|
109
lib/libpthread/man/pthread_create.3
Normal file
109
lib/libpthread/man/pthread_create.3
Normal file
@ -0,0 +1,109 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_CREATE 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_create
|
||||
.Nd create a new thread
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_create "pthread_t *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_create
|
||||
function is used to create a new thread, with attributes specified by
|
||||
.Fa attr ,
|
||||
within a process. If
|
||||
.Fa attr
|
||||
is NULL, the default attributes are used. If the attributes specified by
|
||||
.Fa attr
|
||||
are modified later, the thread's attributes are not affected. Upon
|
||||
successful completion
|
||||
.Fn pthread_create
|
||||
will store the ID of the created thread in the location specified by
|
||||
.Fa thread .
|
||||
.Pp
|
||||
The thread is created executing
|
||||
.Fa start_routine
|
||||
with
|
||||
.Fa arg
|
||||
as its sole argument. If the
|
||||
.Fa start_routine
|
||||
returns, the effect is as if there was an implicit call to
|
||||
.Fn pthread_exit
|
||||
using the return value of
|
||||
.Fa start_toutine
|
||||
as the exit status. Note that the thread in which
|
||||
.Fn main
|
||||
was originally invoked differs from this. When it returns from
|
||||
.Fn main ,
|
||||
the effect is as if there was an implicit call to
|
||||
.Fn exit using the return value of
|
||||
.Fn main
|
||||
as the exit status.
|
||||
.Pp
|
||||
The signal state of the new thread is initialized as:
|
||||
.Bl -bullet -offset indent
|
||||
.It
|
||||
The signal mask is inherited from the creating thread.
|
||||
.It
|
||||
The set of signals pending for the new thread is empty.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_create
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_create
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EAGAIN
|
||||
The system lacked the necessary resources to create another thread, or
|
||||
the system-imposed limit on the total number of threads in a process
|
||||
[PTHREAD_THREADS_MAX] would be exceeded.
|
||||
.It Bq Er EINVAL
|
||||
The value specified by
|
||||
.Fa attr
|
||||
is invalid.
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_exit 3 ,
|
||||
.Xr pthread_join 3 ,
|
||||
.Xr fork 2
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_create
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
79
lib/libpthread/man/pthread_detach.3
Normal file
79
lib/libpthread/man/pthread_detach.3
Normal file
@ -0,0 +1,79 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_DETACH 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_detach
|
||||
.Nd detach a thread
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_detach "pthread_t thread"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_detach
|
||||
function is used to indicate to the implementation that storage for the
|
||||
thread
|
||||
.Fa thread
|
||||
can be reclaimed when the thread terminates. If
|
||||
.Fa thread
|
||||
has not terminated,
|
||||
.Fn pthread_detach
|
||||
will not cause it to terminate. The effect of multiple
|
||||
.Fn pthread_detach
|
||||
calls on the same target thread is unspecified.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_detach
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_detach
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The implementation has detected that the value specified by
|
||||
.Fa thread
|
||||
does not refer to a joinable thread.
|
||||
.It Bq Er ESRCH
|
||||
No thread could be found corresponding to that specified by the given
|
||||
thread ID,
|
||||
.Fa thread .
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_join 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_detach
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
66
lib/libpthread/man/pthread_equal.3
Normal file
66
lib/libpthread/man/pthread_equal.3
Normal file
@ -0,0 +1,66 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_EQUAL 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_equal
|
||||
.Nd compare thread IDs
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_equal "pthread_t t1" "pthread_t t2"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_equal
|
||||
function compares the thread IDs
|
||||
.Fa t1
|
||||
and
|
||||
.Fa t2 .
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn pthread_equal
|
||||
function will non-zero if the thread IDs
|
||||
.Fa t1
|
||||
and
|
||||
.Fa t2
|
||||
correspond to the same thread, otherwise it will return zero.
|
||||
.Sh ERRORS
|
||||
None.
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_create 3 ,
|
||||
.Xr pthread_exit 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_equal
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
99
lib/libpthread/man/pthread_exit.3
Normal file
99
lib/libpthread/man/pthread_exit.3
Normal file
@ -0,0 +1,99 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_EXIT 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_exit
|
||||
.Nd terminate the calling thread
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft void
|
||||
.Fn pthread_exit "void *value_ptr"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_exit
|
||||
function terminates the calling thread and makes the value
|
||||
.Fa value_ptr
|
||||
available to any successful join with the terminating thread. Any
|
||||
cancellation cleanup handlers that have been pushed and are not yet popped
|
||||
are popped in the reverse order that they were pushed and then executed.
|
||||
After all cancellation handlers have been executed, if the thread has any
|
||||
thread-specific data, appropriate destructor functions are called in an
|
||||
unspecified order. Thread termination does not release any application
|
||||
visible process resources, including, but not limited to, mutexes and
|
||||
file descriptors, nor does it perform any process level cleanup
|
||||
actions, including, but not limited to, calling
|
||||
.Fn atexit
|
||||
routines that may exist.
|
||||
.Pp
|
||||
An implicit call to
|
||||
.Fn pthread_exit
|
||||
is made when a thread other than the thread in which
|
||||
.Fn main
|
||||
was first invoked returns from the start routine that was used to create
|
||||
it. The function's return value serves as the thread's exit status.
|
||||
.Pp
|
||||
The behavior of
|
||||
.Fn pthread_exit
|
||||
is undefied if called from a cancellation handler or destructor function
|
||||
that was invoked as the result of an implicit or explicit call to
|
||||
.Fn pthread_exit .
|
||||
.Pp
|
||||
After a thread has terminated, the result of access to local (auto)
|
||||
variables of the thread is undefined. Thus, references to local variables
|
||||
of the exiting thread should not be used for the
|
||||
.Fn pthread_exit
|
||||
.Fa value_ptr
|
||||
parameter value.
|
||||
.Pp
|
||||
The process will exit with an exit status of 0 after the last thread has
|
||||
been terminated. The behavior is as if the implementation called
|
||||
.Fn exit
|
||||
with a zero argument at thread termination time.
|
||||
.Pp
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn pthread_exit
|
||||
function cannot return to its caller.
|
||||
.Sh ERRORS
|
||||
None.
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_create 3 ,
|
||||
.Xr pthread_join 3 ,
|
||||
.Xr exit 2,
|
||||
.Xr _exit 2
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_exit
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
80
lib/libpthread/man/pthread_getspecific.3
Normal file
80
lib/libpthread/man/pthread_getspecific.3
Normal file
@ -0,0 +1,80 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_GETSPECIFIC 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_getspecific
|
||||
.Nd get a thread-specific data value
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft void *
|
||||
.Fn pthread_getspecific "pthread_key_t key"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_getspecific
|
||||
function returns the value currently bound to the specified
|
||||
.Fa key
|
||||
on behalf of the calling thread.
|
||||
.Pp
|
||||
The effect of calling
|
||||
.Fn pthread_getspecific
|
||||
with a
|
||||
.Fa key
|
||||
value not obtained from
|
||||
.Fn pthread_key_create
|
||||
or after
|
||||
.Fa key
|
||||
has been deleted with
|
||||
.Fn pthread_key_delete
|
||||
is undefined.
|
||||
.Pp
|
||||
.Fn pthread_getspecific
|
||||
may be called from a thread-specific data destructor function.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn pthread_getspecific
|
||||
function will return the thread-specific data value associated with the given
|
||||
.Fa key .
|
||||
If no thread-specific data value is associated with
|
||||
.Fa key ,
|
||||
then the value NULL is returned.
|
||||
.Sh ERRORS
|
||||
None.
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_key_create 3 ,
|
||||
.Xr pthread_key_delete 3
|
||||
.Xr pthread_setspecific 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_getspecific
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
100
lib/libpthread/man/pthread_join.3
Normal file
100
lib/libpthread/man/pthread_join.3
Normal file
@ -0,0 +1,100 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_JOIN 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_join
|
||||
.Nd wait for thread termination
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_join "pthread_t thread" "void **value_ptr"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_join
|
||||
function suspends execution of the calling thread until the target
|
||||
.Fa thread
|
||||
terminates unless the target
|
||||
.Fa thread
|
||||
has already terminated.
|
||||
.Pp
|
||||
On return from a successful
|
||||
.Fn pthread_join
|
||||
call with a non-NULL
|
||||
.Fa value_ptr
|
||||
argument, the value passed to
|
||||
.Fn pthread_exit
|
||||
by the terminating thread is stored in the location referenced by
|
||||
.Fa value_ptr .
|
||||
When a
|
||||
.Fn pthread_join
|
||||
returns successfully, the target thread has been terminated. The results
|
||||
of multiple simultaneous calls to
|
||||
.Fn pthread_join
|
||||
specifying the same target thread are undefined. If the thread calling
|
||||
.Fn pthread_join
|
||||
is cancelled, then the target thread is not detached.
|
||||
.Pp
|
||||
A thread that has exited but remains unjoined counts against
|
||||
[_POSIX_THREAD_THREADS_MAX].
|
||||
.Pp
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_join
|
||||
function will return zero. Otherwise an error number will be returned to
|
||||
indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_join
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The implementation has detected that the value specified by
|
||||
.Fa thread
|
||||
does not refer to a joinable thread.
|
||||
.It Bq Er ESRCH
|
||||
No thread could be found corresponding to that specified by the given
|
||||
thread ID,
|
||||
.Fa thread .
|
||||
.It Bq Er EDEADLK
|
||||
A deadlock was detected or the value of
|
||||
.Fa thread
|
||||
specifies the calling thread.
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_create 3 ,
|
||||
.Xr wait 2
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_join
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
98
lib/libpthread/man/pthread_key_create.3
Normal file
98
lib/libpthread/man/pthread_key_create.3
Normal file
@ -0,0 +1,98 @@
|
||||
.\" Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by John Birrell.
|
||||
.\" 4. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 4, 1996
|
||||
.Dt PTHREAD_KEY_CREATE 3
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm pthread_key_create
|
||||
.Nd thread-specific data key creation
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <pthread.h>
|
||||
.Ft int
|
||||
.Fn pthread_key_create "pthread_key_t *key" "void (*destructor)(void *)"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn pthread_key_create
|
||||
function creates a thread-specific data key visible to all threads in the
|
||||
process. Key values provided by
|
||||
.Fn pthread_key_create
|
||||
are opaque objects used to locate thread-specific data. Although the same
|
||||
key value may be used by different threads, the values bound to the key
|
||||
by
|
||||
.Fn pthread_setspecific
|
||||
are maintained on a per-thread basis and persist for the life of the calling
|
||||
thread.
|
||||
.Pp
|
||||
Upon key creation, the value NULL is associated with the new key in all
|
||||
active threads. Upon thread creation, the value NULL is associated with all
|
||||
defined keys in the new thread.
|
||||
.Pp
|
||||
An optional destructor function may be associated with each key value. At
|
||||
thread exit, if a key value has a non-NULL destructor pointer, and the
|
||||
thread has a non-NULL value associated with the key, the function pointed
|
||||
to is called with the current associated value as its sole argument. The
|
||||
order of destructor calls is unspecified if more than one destructor exists
|
||||
for a thread when it exits.
|
||||
.Pp
|
||||
If, after all the destructors have been called for all non-NULL values
|
||||
with associated destructors, there are still some non-NULL values with
|
||||
associated destructors, then the process is repeated. If, after at least
|
||||
[PTHREAD_DESTRUCTOR_ITERATIONS] iterations of destructor calls for
|
||||
outstanding non-NULL values, there are still some non-NULL values with
|
||||
associated destructors, the implementation stops calling destructors.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_key_create
|
||||
function will store the newly created key value at the location specified by
|
||||
.Fa key
|
||||
and returns zero. Otherwise an error number will be returned to indicate
|
||||
the error.
|
||||
.Sh ERRORS
|
||||
.Fn pthread_key_create
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EAGAIN
|
||||
The system lacked the necessary resources to create another thread-specific
|
||||
data key, or the system-imposed limit on the total number of keys per process
|
||||
[PTHREAD_KEYS_MAX] would be exceeded.
|
||||
.It Bq Er ENOMEM
|
||||
Insufficient memory exists to create the key.
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr pthread_getspecific 3 ,
|
||||
.Xr pthread_setspecific 3 ,
|
||||
.Xr pthread_key_delete 3
|
||||
.Sh STANDARDS
|
||||
.Fn pthread_key_create
|
||||
is expected to conform to IEEE
|
||||
.Pq Dq Tn POSIX
|
||||
Std 1003.1c when it is published.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user