bionic/libc/bionic/pthread_internal.h
Elliott Hughes 2a1bb4e646 More pthreads cleanup.
POSIX says pthread_create returns EAGAIN, not ENOMEM.

Also pull pthread_attr_t functions into their own file.

Also pull pthread_setname_np into its own file.

Also remove unnecessary #includes from pthread_key.cpp.

Also account for those pthread keys used internally by bionic,
so they don't count against the number of keys available to user
code. (They do with glibc, but glibc's limit is the much more
generous 1024.)

Also factor out the common errno-restoring idiom to reduce gotos.

Bug: 6702535
Change-Id: I555e66efffcf2c1b5a2873569e91489156efca42
2013-02-11 14:56:39 -08:00

140 lines
4.7 KiB
C

/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
* COPYRIGHT OWNER 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_INTERNAL_H_
#define _PTHREAD_INTERNAL_H_
#include <pthread.h>
#include <stdbool.h>
__BEGIN_DECLS
typedef struct pthread_internal_t
{
struct pthread_internal_t* next;
struct pthread_internal_t* prev;
pthread_attr_t attr;
pid_t kernel_id;
bool allocated_on_heap;
pthread_cond_t join_cond;
int join_count;
void* return_value;
int internal_flags;
__pthread_cleanup_t* cleanup_stack;
void** tls; /* thread-local storage area */
/*
* The dynamic linker implements dlerror(3), which makes it hard for us to implement this
* per-thread buffer by simply using malloc(3) and free(3).
*/
#define __BIONIC_DLERROR_BUFFER_SIZE 512
char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
} pthread_internal_t;
int _init_thread(pthread_internal_t* thread, pid_t kernel_id, const pthread_attr_t* attr,
void* stack_base, bool add_to_thread_list);
void _pthread_internal_add( pthread_internal_t* thread );
pthread_internal_t* __get_thread(void);
__LIBC_HIDDEN__ void pthread_key_clean_all(void);
#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
#define PTHREAD_ATTR_FLAG_USER_STACK 0x00000002
extern __LIBC_HIDDEN__ const pthread_attr_t gDefaultPthreadAttr;
extern pthread_internal_t* gThreadList;
extern pthread_mutex_t gThreadListLock;
/* needed by posix-timers.c */
static __inline__ void timespec_add( struct timespec* a, const struct timespec* b )
{
a->tv_sec += b->tv_sec;
a->tv_nsec += b->tv_nsec;
if (a->tv_nsec >= 1000000000) {
a->tv_nsec -= 1000000000;
a->tv_sec += 1;
}
}
static __inline__ void timespec_sub( struct timespec* a, const struct timespec* b )
{
a->tv_sec -= b->tv_sec;
a->tv_nsec -= b->tv_nsec;
if (a->tv_nsec < 0) {
a->tv_nsec += 1000000000;
a->tv_sec -= 1;
}
}
static __inline__ void timespec_zero( struct timespec* a )
{
a->tv_sec = a->tv_nsec = 0;
}
static __inline__ int timespec_is_zero( const struct timespec* a )
{
return (a->tv_sec == 0 && a->tv_nsec == 0);
}
static __inline__ int timespec_cmp( const struct timespec* a, const struct timespec* b )
{
if (a->tv_sec < b->tv_sec) return -1;
if (a->tv_sec > b->tv_sec) return +1;
if (a->tv_nsec < b->tv_nsec) return -1;
if (a->tv_nsec > b->tv_nsec) return +1;
return 0;
}
static __inline__ int timespec_cmp0( const struct timespec* a )
{
if (a->tv_sec < 0) return -1;
if (a->tv_sec > 0) return +1;
if (a->tv_nsec < 0) return -1;
if (a->tv_nsec > 0) return +1;
return 0;
}
extern int __pthread_cond_timedwait(pthread_cond_t*,
pthread_mutex_t*,
const struct timespec*,
clockid_t);
extern int __pthread_cond_timedwait_relative(pthread_cond_t*,
pthread_mutex_t*,
const struct timespec*);
/* needed by fork.c */
extern void __timer_table_start_stop(int stop);
extern void __bionic_atfork_run_prepare();
extern void __bionic_atfork_run_child();
extern void __bionic_atfork_run_parent();
__END_DECLS
#endif /* _PTHREAD_INTERNAL_H_ */