Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Kevin
bionic
Commits
fcaf4e9f
Commit
fcaf4e9f
authored
12 years ago
by
Elliott Hughes
Committed by
Gerrit Code Review
12 years ago
Browse files
Options
Download
Plain Diff
Merge "Revert "More pthreads cleanup.""
parents
85f491f9
6f94de3c
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
292 additions
and
363 deletions
+292
-363
libc/Android.mk
libc/Android.mk
+0
-2
libc/bionic/dirent.cpp
libc/bionic/dirent.cpp
+3
-3
libc/bionic/pthread.c
libc/bionic/pthread.c
+227
-4
libc/bionic/pthread_attr.cpp
libc/bionic/pthread_attr.cpp
+0
-165
libc/bionic/pthread_internal.h
libc/bionic/pthread_internal.h
+0
-4
libc/bionic/pthread_key.cpp
libc/bionic/pthread_key.cpp
+24
-1
libc/bionic/pthread_setname_np.cpp
libc/bionic/pthread_setname_np.cpp
+0
-79
libc/bionic/pthread_sigmask.cpp
libc/bionic/pthread_sigmask.cpp
+7
-6
libc/bionic/strerror_r.cpp
libc/bionic/strerror_r.cpp
+3
-4
libc/bionic/stubs.cpp
libc/bionic/stubs.cpp
+11
-8
libc/bionic/sysconf.cpp
libc/bionic/sysconf.cpp
+1
-1
libc/bionic/tmpfile.cpp
libc/bionic/tmpfile.cpp
+4
-4
libc/private/ErrnoRestorer.h
libc/private/ErrnoRestorer.h
+0
-43
libc/private/ThreadLocalBuffer.h
libc/private/ThreadLocalBuffer.h
+3
-2
libc/private/bionic_futex.h
libc/private/bionic_futex.h
+0
-4
libc/private/bionic_tls.h
libc/private/bionic_tls.h
+8
-20
tests/pthread_test.cpp
tests/pthread_test.cpp
+1
-13
No files found.
libc/Android.mk
View file @
fcaf4e9f
...
...
@@ -279,8 +279,6 @@ libc_bionic_src_files := \
bionic/__memcpy_chk.cpp
\
bionic/__memmove_chk.cpp
\
bionic/__memset_chk.cpp
\
bionic/pthread_attr.cpp
\
bionic/pthread_setname_np.cpp
\
bionic/pthread_sigmask.cpp
\
bionic/raise.cpp
\
bionic/sbrk.cpp
\
...
...
This diff is collapsed.
Click to expand it.
libc/bionic/dirent.cpp
View file @
fcaf4e9f
...
...
@@ -36,8 +36,7 @@
#include <sys/types.h>
#include <unistd.h>
#include "private/ErrnoRestorer.h"
#include "private/ScopedPthreadMutexLocker.h"
#include <private/ScopedPthreadMutexLocker.h>
struct
DIR
{
int
fd_
;
...
...
@@ -109,7 +108,7 @@ dirent* readdir(DIR* d) {
}
int
readdir_r
(
DIR
*
d
,
dirent
*
entry
,
dirent
**
result
)
{
ErrnoRestorer
errno_restorer
;
int
saved_errno
=
errno
;
*
result
=
NULL
;
errno
=
0
;
...
...
@@ -125,6 +124,7 @@ int readdir_r(DIR* d, dirent* entry, dirent** result) {
memcpy
(
entry
,
next
,
next
->
d_reclen
);
*
result
=
entry
;
}
errno
=
saved_errno
;
return
0
;
}
...
...
This diff is collapsed.
Click to expand it.
libc/bionic/pthread.c
View file @
fcaf4e9f
...
...
@@ -26,12 +26,23 @@
* SUCH DAMAGE.
*/
#include <pthread.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <malloc.h>
#include <memory.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/atomics.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "bionic_atomic_inline.h"
...
...
@@ -73,8 +84,23 @@ void ATTRIBUTES _thread_created_hook(pid_t thread_id);
static
const
int
kPthreadInitFailed
=
1
;
#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
#define PTHREAD_ATTR_FLAG_USER_STACK 0x00000002
#define DEFAULT_STACKSIZE (1024 * 1024)
static
pthread_mutex_t
mmap_lock
=
PTHREAD_MUTEX_INITIALIZER
;
static
const
pthread_attr_t
gDefaultPthreadAttr
=
{
.
flags
=
0
,
.
stack_base
=
NULL
,
.
stack_size
=
DEFAULT_STACKSIZE
,
.
guard_size
=
PAGE_SIZE
,
.
sched_policy
=
SCHED_NORMAL
,
.
sched_priority
=
0
};
__LIBC_HIDDEN__
pthread_internal_t
*
gThreadList
=
NULL
;
__LIBC_HIDDEN__
pthread_mutex_t
gThreadListLock
=
PTHREAD_MUTEX_INITIALIZER
;
static
pthread_mutex_t
gDebuggerNotificationLock
=
PTHREAD_MUTEX_INITIALIZER
;
...
...
@@ -280,7 +306,7 @@ int pthread_create(pthread_t *thread_out, pthread_attr_t const * attr,
pthread_internal_t
*
thread
=
calloc
(
sizeof
(
*
thread
),
1
);
if
(
thread
==
NULL
)
{
return
E
AGAIN
;
return
E
NOMEM
;
}
thread
->
allocated_on_heap
=
true
;
...
...
@@ -295,7 +321,7 @@ int pthread_create(pthread_t *thread_out, pthread_attr_t const * attr,
stack
=
mkstack
(
stack_size
,
attr
->
guard_size
);
if
(
stack
==
NULL
)
{
free
(
thread
);
return
E
AGAIN
;
return
E
NOMEM
;
}
}
...
...
@@ -353,6 +379,152 @@ int pthread_create(pthread_t *thread_out, pthread_attr_t const * attr,
}
int
pthread_attr_init
(
pthread_attr_t
*
attr
)
{
*
attr
=
gDefaultPthreadAttr
;
return
0
;
}
int
pthread_attr_destroy
(
pthread_attr_t
*
attr
)
{
memset
(
attr
,
0x42
,
sizeof
(
pthread_attr_t
));
return
0
;
}
int
pthread_attr_setdetachstate
(
pthread_attr_t
*
attr
,
int
state
)
{
if
(
state
==
PTHREAD_CREATE_DETACHED
)
{
attr
->
flags
|=
PTHREAD_ATTR_FLAG_DETACHED
;
}
else
if
(
state
==
PTHREAD_CREATE_JOINABLE
)
{
attr
->
flags
&=
~
PTHREAD_ATTR_FLAG_DETACHED
;
}
else
{
return
EINVAL
;
}
return
0
;
}
int
pthread_attr_getdetachstate
(
pthread_attr_t
const
*
attr
,
int
*
state
)
{
*
state
=
(
attr
->
flags
&
PTHREAD_ATTR_FLAG_DETACHED
)
?
PTHREAD_CREATE_DETACHED
:
PTHREAD_CREATE_JOINABLE
;
return
0
;
}
int
pthread_attr_setschedpolicy
(
pthread_attr_t
*
attr
,
int
policy
)
{
attr
->
sched_policy
=
policy
;
return
0
;
}
int
pthread_attr_getschedpolicy
(
pthread_attr_t
const
*
attr
,
int
*
policy
)
{
*
policy
=
attr
->
sched_policy
;
return
0
;
}
int
pthread_attr_setschedparam
(
pthread_attr_t
*
attr
,
struct
sched_param
const
*
param
)
{
attr
->
sched_priority
=
param
->
sched_priority
;
return
0
;
}
int
pthread_attr_getschedparam
(
pthread_attr_t
const
*
attr
,
struct
sched_param
*
param
)
{
param
->
sched_priority
=
attr
->
sched_priority
;
return
0
;
}
int
pthread_attr_setstacksize
(
pthread_attr_t
*
attr
,
size_t
stack_size
)
{
if
((
stack_size
&
(
PAGE_SIZE
-
1
)
||
stack_size
<
PTHREAD_STACK_MIN
))
{
return
EINVAL
;
}
attr
->
stack_size
=
stack_size
;
return
0
;
}
int
pthread_attr_getstacksize
(
pthread_attr_t
const
*
attr
,
size_t
*
stack_size
)
{
*
stack_size
=
attr
->
stack_size
;
return
0
;
}
int
pthread_attr_setstackaddr
(
pthread_attr_t
*
attr
__attribute__
((
unused
)),
void
*
stack_addr
__attribute__
((
unused
)))
{
// This was removed from POSIX.1-2008, and is not implemented on bionic.
// Needed for ABI compatibility with the NDK.
return
ENOSYS
;
}
int
pthread_attr_getstackaddr
(
pthread_attr_t
const
*
attr
,
void
**
stack_addr
)
{
// This was removed from POSIX.1-2008.
// Needed for ABI compatibility with the NDK.
*
stack_addr
=
(
char
*
)
attr
->
stack_base
+
attr
->
stack_size
;
return
0
;
}
int
pthread_attr_setstack
(
pthread_attr_t
*
attr
,
void
*
stack_base
,
size_t
stack_size
)
{
if
((
stack_size
&
(
PAGE_SIZE
-
1
)
||
stack_size
<
PTHREAD_STACK_MIN
))
{
return
EINVAL
;
}
if
((
uint32_t
)
stack_base
&
(
PAGE_SIZE
-
1
))
{
return
EINVAL
;
}
attr
->
stack_base
=
stack_base
;
attr
->
stack_size
=
stack_size
;
return
0
;
}
int
pthread_attr_getstack
(
pthread_attr_t
const
*
attr
,
void
**
stack_base
,
size_t
*
stack_size
)
{
*
stack_base
=
attr
->
stack_base
;
*
stack_size
=
attr
->
stack_size
;
return
0
;
}
int
pthread_attr_setguardsize
(
pthread_attr_t
*
attr
,
size_t
guard_size
)
{
if
(
guard_size
&
(
PAGE_SIZE
-
1
)
||
guard_size
<
PAGE_SIZE
)
{
return
EINVAL
;
}
attr
->
guard_size
=
guard_size
;
return
0
;
}
int
pthread_attr_getguardsize
(
pthread_attr_t
const
*
attr
,
size_t
*
guard_size
)
{
*
guard_size
=
attr
->
guard_size
;
return
0
;
}
int
pthread_getattr_np
(
pthread_t
thid
,
pthread_attr_t
*
attr
)
{
pthread_internal_t
*
thread
=
(
pthread_internal_t
*
)
thid
;
*
attr
=
thread
->
attr
;
return
0
;
}
int
pthread_attr_setscope
(
pthread_attr_t
*
attr
__attribute__
((
unused
)),
int
scope
)
{
if
(
scope
==
PTHREAD_SCOPE_SYSTEM
)
return
0
;
if
(
scope
==
PTHREAD_SCOPE_PROCESS
)
return
ENOTSUP
;
return
EINVAL
;
}
int
pthread_attr_getscope
(
pthread_attr_t
const
*
attr
__attribute__
((
unused
)))
{
return
PTHREAD_SCOPE_SYSTEM
;
}
/* CAVEAT: our implementation of pthread_cleanup_push/pop doesn't support C++ exceptions
* and thread cancelation
*/
...
...
@@ -1709,6 +1881,57 @@ int pthread_once( pthread_once_t* once_control, void (*init_routine)(void) )
return
0
;
}
/* This value is not exported by kernel headers, so hardcode it here */
#define MAX_TASK_COMM_LEN 16
#define TASK_COMM_FMT "/proc/self/task/%u/comm"
int
pthread_setname_np
(
pthread_t
thid
,
const
char
*
thname
)
{
size_t
thname_len
;
int
saved_errno
,
ret
;
if
(
thid
==
0
||
thname
==
NULL
)
return
EINVAL
;
thname_len
=
strlen
(
thname
);
if
(
thname_len
>=
MAX_TASK_COMM_LEN
)
return
ERANGE
;
saved_errno
=
errno
;
if
(
thid
==
pthread_self
())
{
ret
=
prctl
(
PR_SET_NAME
,
(
unsigned
long
)
thname
,
0
,
0
,
0
)
?
errno
:
0
;
}
else
{
/* Have to change another thread's name */
pthread_internal_t
*
thread
=
(
pthread_internal_t
*
)
thid
;
char
comm_name
[
sizeof
(
TASK_COMM_FMT
)
+
8
];
ssize_t
n
;
int
fd
;
snprintf
(
comm_name
,
sizeof
(
comm_name
),
TASK_COMM_FMT
,
(
unsigned
int
)
thread
->
kernel_id
);
fd
=
open
(
comm_name
,
O_RDWR
);
if
(
fd
==
-
1
)
{
ret
=
errno
;
goto
exit
;
}
n
=
TEMP_FAILURE_RETRY
(
write
(
fd
,
thname
,
thname_len
));
close
(
fd
);
if
(
n
<
0
)
ret
=
errno
;
else
if
((
size_t
)
n
!=
thname_len
)
ret
=
EIO
;
else
ret
=
0
;
}
exit:
errno
=
saved_errno
;
return
ret
;
}
/* Return the kernel thread ID for a pthread.
* This is only defined for implementations where pthread <-> kernel is 1:1, which this is.
* Not the same as pthread_getthreadid_np, which is commonly defined to be opaque.
...
...
This diff is collapsed.
Click to expand it.
libc/bionic/pthread_attr.cpp
deleted
100644 → 0
View file @
85f491f9
/*
* 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.
*/
#include <pthread.h>
#include "pthread_internal.h"
#define DEFAULT_STACKSIZE (1024 * 1024)
const
pthread_attr_t
gDefaultPthreadAttr
=
{
.
flags
=
0
,
.
stack_base
=
NULL
,
.
stack_size
=
DEFAULT_STACKSIZE
,
.
guard_size
=
PAGE_SIZE
,
.
sched_policy
=
SCHED_NORMAL
,
.
sched_priority
=
0
};
int
pthread_attr_init
(
pthread_attr_t
*
attr
)
{
*
attr
=
gDefaultPthreadAttr
;
return
0
;
}
int
pthread_attr_destroy
(
pthread_attr_t
*
attr
)
{
memset
(
attr
,
0x42
,
sizeof
(
pthread_attr_t
));
return
0
;
}
int
pthread_attr_setdetachstate
(
pthread_attr_t
*
attr
,
int
state
)
{
if
(
state
==
PTHREAD_CREATE_DETACHED
)
{
attr
->
flags
|=
PTHREAD_ATTR_FLAG_DETACHED
;
}
else
if
(
state
==
PTHREAD_CREATE_JOINABLE
)
{
attr
->
flags
&=
~
PTHREAD_ATTR_FLAG_DETACHED
;
}
else
{
return
EINVAL
;
}
return
0
;
}
int
pthread_attr_getdetachstate
(
pthread_attr_t
const
*
attr
,
int
*
state
)
{
*
state
=
(
attr
->
flags
&
PTHREAD_ATTR_FLAG_DETACHED
)
?
PTHREAD_CREATE_DETACHED
:
PTHREAD_CREATE_JOINABLE
;
return
0
;
}
int
pthread_attr_setschedpolicy
(
pthread_attr_t
*
attr
,
int
policy
)
{
attr
->
sched_policy
=
policy
;
return
0
;
}
int
pthread_attr_getschedpolicy
(
pthread_attr_t
const
*
attr
,
int
*
policy
)
{
*
policy
=
attr
->
sched_policy
;
return
0
;
}
int
pthread_attr_setschedparam
(
pthread_attr_t
*
attr
,
struct
sched_param
const
*
param
)
{
attr
->
sched_priority
=
param
->
sched_priority
;
return
0
;
}
int
pthread_attr_getschedparam
(
pthread_attr_t
const
*
attr
,
struct
sched_param
*
param
)
{
param
->
sched_priority
=
attr
->
sched_priority
;
return
0
;
}
int
pthread_attr_setstacksize
(
pthread_attr_t
*
attr
,
size_t
stack_size
)
{
if
((
stack_size
&
(
PAGE_SIZE
-
1
)
||
stack_size
<
PTHREAD_STACK_MIN
))
{
return
EINVAL
;
}
attr
->
stack_size
=
stack_size
;
return
0
;
}
int
pthread_attr_getstacksize
(
pthread_attr_t
const
*
attr
,
size_t
*
stack_size
)
{
*
stack_size
=
attr
->
stack_size
;
return
0
;
}
int
pthread_attr_setstackaddr
(
pthread_attr_t
*
,
void
*
)
{
// This was removed from POSIX.1-2008, and is not implemented on bionic.
// Needed for ABI compatibility with the NDK.
return
ENOSYS
;
}
int
pthread_attr_getstackaddr
(
pthread_attr_t
const
*
attr
,
void
**
stack_addr
)
{
// This was removed from POSIX.1-2008.
// Needed for ABI compatibility with the NDK.
*
stack_addr
=
(
char
*
)
attr
->
stack_base
+
attr
->
stack_size
;
return
0
;
}
int
pthread_attr_setstack
(
pthread_attr_t
*
attr
,
void
*
stack_base
,
size_t
stack_size
)
{
if
((
stack_size
&
(
PAGE_SIZE
-
1
)
||
stack_size
<
PTHREAD_STACK_MIN
))
{
return
EINVAL
;
}
if
((
uint32_t
)
stack_base
&
(
PAGE_SIZE
-
1
))
{
return
EINVAL
;
}
attr
->
stack_base
=
stack_base
;
attr
->
stack_size
=
stack_size
;
return
0
;
}
int
pthread_attr_getstack
(
pthread_attr_t
const
*
attr
,
void
**
stack_base
,
size_t
*
stack_size
)
{
*
stack_base
=
attr
->
stack_base
;
*
stack_size
=
attr
->
stack_size
;
return
0
;
}
int
pthread_attr_setguardsize
(
pthread_attr_t
*
attr
,
size_t
guard_size
)
{
if
(
guard_size
&
(
PAGE_SIZE
-
1
)
||
guard_size
<
PAGE_SIZE
)
{
return
EINVAL
;
}
attr
->
guard_size
=
guard_size
;
return
0
;
}
int
pthread_attr_getguardsize
(
pthread_attr_t
const
*
attr
,
size_t
*
guard_size
)
{
*
guard_size
=
attr
->
guard_size
;
return
0
;
}
int
pthread_getattr_np
(
pthread_t
thid
,
pthread_attr_t
*
attr
)
{
pthread_internal_t
*
thread
=
(
pthread_internal_t
*
)
thid
;
*
attr
=
thread
->
attr
;
return
0
;
}
int
pthread_attr_setscope
(
pthread_attr_t
*
,
int
scope
)
{
if
(
scope
==
PTHREAD_SCOPE_SYSTEM
)
{
return
0
;
}
if
(
scope
==
PTHREAD_SCOPE_PROCESS
)
{
return
ENOTSUP
;
}
return
EINVAL
;
}
int
pthread_attr_getscope
(
pthread_attr_t
const
*
)
{
return
PTHREAD_SCOPE_SYSTEM
;
}
This diff is collapsed.
Click to expand it.
libc/bionic/pthread_internal.h
View file @
fcaf4e9f
...
...
@@ -62,10 +62,6 @@ 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
;
...
...
This diff is collapsed.
Click to expand it.
libc/bionic/pthread_key.cpp
View file @
fcaf4e9f
...
...
@@ -26,10 +26,33 @@
* SUCH DAMAGE.
*/
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <malloc.h>
#include <memory.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/atomics.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "bionic_atomic_inline.h"
#include "bionic_futex.h"
#include "bionic_pthread.h"
#include "bionic_ssp.h"
#include "bionic_tls.h"
#include "debug_format.h"
#include "pthread_internal.h"
#include "thread_private.h"
/* A technical note regarding our thread-local-storage (TLS) implementation:
*
...
...
This diff is collapsed.
Click to expand it.
libc/bionic/pthread_setname_np.cpp
deleted
100644 → 0
View file @
85f491f9
/*
* 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.
*/
#include <pthread.h>
#include <fcntl.h>
#include <stdio.h> // For snprintf.
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "pthread_internal.h"
#include "private/ErrnoRestorer.h"
// This value is not exported by kernel headers.
#define MAX_TASK_COMM_LEN 16
#define TASK_COMM_FMT "/proc/self/task/%u/comm"
int
pthread_setname_np
(
pthread_t
thread
,
const
char
*
thread_name
)
{
ErrnoRestorer
errno_restorer
;
if
(
thread
==
0
||
thread_name
==
NULL
)
{
return
EINVAL
;
}
size_t
thread_name_len
=
strlen
(
thread_name
);
if
(
thread_name_len
>=
MAX_TASK_COMM_LEN
)
{
return
ERANGE
;
}
// Changing our own name is an easy special case.
if
(
thread
==
pthread_self
())
{
return
prctl
(
PR_SET_NAME
,
(
unsigned
long
)
thread_name
,
0
,
0
,
0
)
?
errno
:
0
;
}
// Have to change another thread's name.
pthread_internal_t
*
t
=
reinterpret_cast
<
pthread_internal_t
*>
(
thread
);
char
comm_name
[
sizeof
(
TASK_COMM_FMT
)
+
8
];
snprintf
(
comm_name
,
sizeof
(
comm_name
),
TASK_COMM_FMT
,
(
unsigned
int
)
t
->
kernel_id
);
int
fd
=
open
(
comm_name
,
O_RDWR
);
if
(
fd
==
-
1
)
{
return
errno
;
}
ssize_t
n
=
TEMP_FAILURE_RETRY
(
write
(
fd
,
thread_name
,
thread_name_len
));
close
(
fd
);
if
(
n
<
0
)
{
return
errno
;
}
else
if
((
size_t
)
n
!=
thread_name_len
)
{
return
EIO
;
}
return
0
;
}
This diff is collapsed.
Click to expand it.
libc/bionic/pthread_sigmask.cpp
View file @
fcaf4e9f
...
...
@@ -30,13 +30,12 @@
#include <pthread.h>
#include <signal.h>
#include "private/ErrnoRestorer.h"
#include "private/kernel_sigset_t.h"
#include <private/kernel_sigset_t.h>
extern
"C"
int
__rt_sigprocmask
(
int
,
const
kernel_sigset_t
*
,
kernel_sigset_t
*
,
size_t
);
int
pthread_sigmask
(
int
how
,
const
sigset_t
*
iset
,
sigset_t
*
oset
)
{
ErrnoRestorer
errno_restorer
;
int
old_errno
=
errno
;
// 'in_set_ptr' is the second parameter to __rt_sigprocmask. It must be NULL
// if 'set' is NULL to ensure correct semantics (which in this case would
...
...
@@ -49,13 +48,15 @@ int pthread_sigmask(int how, const sigset_t* iset, sigset_t* oset) {
}
kernel_sigset_t
out_set
;
if
(
__rt_sigprocmask
(
how
,
in_set_ptr
,
&
out_set
,
sizeof
(
out_set
))
==
-
1
)
{
return
errno
;
int
result
=
__rt_sigprocmask
(
how
,
in_set_ptr
,
&
out_set
,
sizeof
(
out_set
));
if
(
result
<
0
)
{
result
=
errno
;
}
if
(
oset
!=
NULL
)
{
*
oset
=
out_set
.
bionic
;
}
return
0
;
errno
=
old_errno
;
return
result
;
}
This diff is collapsed.
Click to expand it.
libc/bionic/strerror_r.cpp
View file @
fcaf4e9f
...
...
@@ -7,8 +7,6 @@
#include <stdio.h>
#include <string.h>
#include "private/ErrnoRestorer.h"
struct
Pair
{
int
code
;
const
char
*
msg
;
...
...
@@ -44,7 +42,7 @@ extern "C" __LIBC_HIDDEN__ const char* __strsignal_lookup(int signal_number) {
}
int
strerror_r
(
int
error_number
,
char
*
buf
,
size_t
buf_len
)
{
ErrnoRestorer
errno_restorer
;
int
saved_errno
=
errno
;
size_t
length
;
const
char
*
error_name
=
__strerror_lookup
(
error_number
);
...
...
@@ -54,10 +52,11 @@ int strerror_r(int error_number, char* buf, size_t buf_len) {
length
=
snprintf
(
buf
,
buf_len
,
"Unknown error %d"
,
error_number
);
}
if
(
length
>=
buf_len
)
{
errno
_restorer
.
override
(
ERANGE
)
;
errno
=
ERANGE
;
return
-
1
;
}
errno
=
saved_errno
;
return
0
;
}
...
...
This diff is collapsed.
Click to expand it.
libc/bionic/stubs.cpp
View file @
fcaf4e9f
...
...
@@ -31,17 +31,15 @@
#include <grp.h>
#include <mntent.h>
#include <netdb.h>
#include <private/android_filesystem_config.h>
#include <private/debug_format.h>
#include <private/logd.h>
#include <pthread.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "private/android_filesystem_config.h"
#include "private/debug_format.h"
#include "private/ErrnoRestorer.h"
#include "private/logd.h"
// Thread-specific state for the non-reentrant functions.
static
pthread_once_t
stubs_once
=
PTHREAD_ONCE_INIT
;
static
pthread_key_t
stubs_key
;
...
...
@@ -60,7 +58,7 @@ static int do_getpw_r(int by_name, const char* name, uid_t uid,
passwd
**
result
)
{
// getpwnam_r and getpwuid_r don't modify errno, but library calls we
// make might.
ErrnoRestorer
errno_restorer
;
int
old_errno
=
errno
;
*
result
=
NULL
;
// Our implementation of getpwnam(3) and getpwuid(3) use thread-local
...
...
@@ -71,7 +69,9 @@ static int do_getpw_r(int by_name, const char* name, uid_t uid,
// POSIX allows failure to find a match to be considered a non-error.
// Reporting success (0) but with *result NULL is glibc's behavior.
if
(
src
==
NULL
)
{
return
(
errno
==
ENOENT
)
?
0
:
errno
;
int
rc
=
(
errno
==
ENOENT
)
?
0
:
errno
;
errno
=
old_errno
;
return
rc
;
}
// Work out where our strings will go in 'buf', and whether we've got
...
...
@@ -84,11 +84,13 @@ static int do_getpw_r(int by_name, const char* name, uid_t uid,
dst
->
pw_shell
=
buf
+
required_byte_count
;
required_byte_count
+=
strlen
(
src
->
pw_shell
)
+
1
;
if
(
byte_count
<
required_byte_count
)
{
errno
=
old_errno
;
return
ERANGE
;
}
// Copy the strings.
snprintf
(
buf
,
byte_count
,
"%s%c%s%c%s"
,
src
->
pw_name
,
0
,
src
->
pw_dir
,
0
,
src
->
pw_shell
);
snprintf
(
buf
,
byte_count
,
"%s%c%s%c%s"
,
src
->
pw_name
,
0
,
src
->
pw_dir
,
0
,
src
->
pw_shell
);
// pw_passwd is non-POSIX and unused (always NULL) in bionic.
// pw_gecos is non-POSIX and missing in bionic.
...
...
@@ -99,6 +101,7 @@ static int do_getpw_r(int by_name, const char* name, uid_t uid,
dst
->
pw_uid
=
src
->
pw_uid
;
*
result
=
dst
;
errno
=
old_errno
;
return
0
;
}
...
...
This diff is collapsed.
Click to expand it.
libc/bionic/sysconf.cpp
View file @
fcaf4e9f
...
...
@@ -306,7 +306,7 @@ int sysconf(int name) {
return
_POSIX_THREAD_DESTRUCTOR_ITERATIONS
;
case
_SC_THREAD_KEYS_MAX
:
return
(
BIONIC_TLS_SLOTS
-
TLS_SLOT_FIRST_USER_SLOT
-
GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT
);
return
(
BIONIC_TLS_SLOTS
-
TLS_SLOT_FIRST_USER_SLOT
);
case
_SC_THREAD_STACK_MIN
:
return
SYSTEM_THREAD_STACK_MIN
;
case
_SC_THREAD_THREADS_MAX
:
return
SYSTEM_THREAD_THREADS_MAX
;
...
...
This diff is collapsed.
Click to expand it.
libc/bionic/tmpfile.cpp
View file @
fcaf4e9f
...
...
@@ -38,8 +38,6 @@
#include <sys/types.h>
#include <unistd.h>
#include "private/ErrnoRestorer.h"
class
ScopedSignalBlocker
{
public:
ScopedSignalBlocker
()
{
...
...
@@ -79,8 +77,9 @@ static FILE* __tmpfile_dir(const char* tmp_dir) {
struct
stat
sb
;
int
rc
=
fstat
(
fd
,
&
sb
);
if
(
rc
==
-
1
)
{
ErrnoRestorer
errno_restorer
;
int
old_errno
=
errno
;
close
(
fd
);
errno
=
old_errno
;
return
NULL
;
}
}
...
...
@@ -92,8 +91,9 @@ static FILE* __tmpfile_dir(const char* tmp_dir) {
}
// Failure. Clean up. We already unlinked, so we just need to close.
ErrnoRestorer
errno_restorer
;
int
old_errno
=
errno
;
close
(
fd
);
errno
=
old_errno
;
return
NULL
;
}
...
...
This diff is collapsed.
Click to expand it.
libc/private/ErrnoRestorer.h
deleted
100644 → 0
View file @
85f491f9
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ERRNO_RESTORER_H
#define ERRNO_RESTORER_H
#include <errno.h>
class
ErrnoRestorer
{
public:
explicit
ErrnoRestorer
()
:
saved_errno_
(
errno
)
{
}
~
ErrnoRestorer
()
{
errno
=
saved_errno_
;
}
void
override
(
int
new_errno
)
{
saved_errno_
=
new_errno
;
}
private:
int
saved_errno_
;
// Disallow copy and assignment.
ErrnoRestorer
(
const
ErrnoRestorer
&
);
void
operator
=
(
const
ErrnoRestorer
&
);
};
#endif // ERRNO_RESTORER_H
This diff is collapsed.
Click to expand it.
libc/private/ThreadLocalBuffer.h
View file @
fcaf4e9f
...
...
@@ -37,17 +37,18 @@
// TODO: move __cxa_guard_acquire and __cxa_guard_release into libc.
#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \
static pthread_once_t __bionic_tls_ ## name ## _once; \
static pthread_key_t __bionic_tls_ ## name ## _key; \
static void __bionic_tls_ ## name ## _key_destroy(void* buffer) { \
free(buffer); \
} \
/* Run automatically when libc.so is opened by the dynamic linker. */
\
__attribute__((constructor)) static void __bionic_tls_ ## name ## _key_init() { \
static void __bionic_tls_ ## name ## _key_init() { \
pthread_key_create(&__bionic_tls_ ## name ## _key, __bionic_tls_ ## name ## _key_destroy); \
}
// Leaves "name_tls_buffer" and "name_tls_buffer_size" defined and initialized.
#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \
pthread_once(&__bionic_tls_ ## name ## _once, __bionic_tls_ ## name ## _key_init); \
type name ## _tls_buffer = \
reinterpret_cast<type>(pthread_getspecific(__bionic_tls_ ## name ## _key)); \
if (name ## _tls_buffer == NULL) { \
...
...
This diff is collapsed.
Click to expand it.
libc/private/bionic_futex.h
View file @
fcaf4e9f
...
...
@@ -30,8 +30,6 @@
#include <linux/futex.h>
__BEGIN_DECLS
extern
int
__futex_wait
(
volatile
void
*
ftx
,
int
val
,
const
struct
timespec
*
timeout
);
extern
int
__futex_wake
(
volatile
void
*
ftx
,
int
count
);
...
...
@@ -56,6 +54,4 @@ extern int __futex_syscall4(volatile void *ftx, int op, int val, const struct ti
extern
int
__futex_wake_ex
(
volatile
void
*
ftx
,
int
pshared
,
int
val
);
extern
int
__futex_wait_ex
(
volatile
void
*
ftx
,
int
pshared
,
int
val
,
const
struct
timespec
*
timeout
);
__END_DECLS
#endif
/* _BIONIC_FUTEX_H */
This diff is collapsed.
Click to expand it.
libc/private/bionic_tls.h
View file @
fcaf4e9f
...
...
@@ -43,40 +43,28 @@ __BEGIN_DECLS
** pre-allocated slot directly for performance reason).
**/
/* Maximum number of elements in the TLS array. */
#define BIONIC_TLS_SLOTS 64
/* Well-known TLS slots. What data goes in which slot is arbitrary unless otherwise noted. */
enum
{
TLS_SLOT_SELF
=
0
,
/* The kernel requires this specific slot for x86. */
TLS_SLOT_THREAD_ID
,
TLS_SLOT_ERRNO
,
/* These two aren't used by bionic itself, but allow the graphics code to
* access TLS directly rather than using the pthread API. */
TLS_SLOT_OPENGL_API
=
3
,
TLS_SLOT_OPENGL
=
4
,
/* This slot is only used to pass information from the dynamic linker to
* libc.so when the C library is loaded in to memory. The C runtime init
* function will then clear it. Since its use is extremely temporary,
* we reuse an existing location that isn't needed during libc startup. */
TLS_SLOT_BIONIC_PREINIT
=
TLS_SLOT_OPENGL_API
,
TLS_SLOT_STACK_GUARD
=
5
,
/* GCC requires this specific slot for x86. */
TLS_SLOT_DLERROR
,
TLS_SLOT_FIRST_USER_SLOT
/* Must come last! */
};
/*
* Maximum number of elements in the TLS array.
* POSIX says this must be at least 128, but Android has traditionally had only 64, minus those
* ones used internally by bionic itself.
* There are two kinds of slot used internally by bionic --- there are the well-known slots
* enumerated above, and then there are those that are allocated during startup by calls to
* pthread_key_create; grep for GLOBAL_INIT_THREAD_LOCAL_BUFFER to find those. We need to manually
* maintain that second number, but pthread_test will fail if we forget.
/* This slot is only used to pass information from the dynamic linker to
* libc.so when the C library is loaded in to memory. The C runtime init
* function will then clear it. Since its use is extremely temporary,
* we reuse an existing location that isn't needed during libc startup.
*/
#define GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT 4
#define BIONIC_TLS_SLOTS (64 + TLS_SLOT_FIRST_USER_SLOT + GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT)
#define TLS_SLOT_BIONIC_PREINIT TLS_SLOT_OPENGL_API
/* set the Thread Local Storage, must contain at least BIONIC_TLS_SLOTS pointers */
extern
void
__init_tls
(
void
**
tls
,
void
*
thread_info
);
...
...
This diff is collapsed.
Click to expand it.
tests/pthread_test.cpp
View file @
fcaf4e9f
...
...
@@ -28,14 +28,12 @@ TEST(pthread, pthread_key_create) {
ASSERT_EQ
(
EINVAL
,
pthread_key_delete
(
key
));
}
#if !defined(__GLIBC__) // glibc uses keys internally that its sysconf value doesn't account for.
TEST
(
pthread
,
pthread_key_create_lots
)
{
// We can allocate _SC_THREAD_KEYS_MAX keys.
std
::
vector
<
pthread_key_t
>
keys
;
for
(
int
i
=
0
;
i
<
sysconf
(
_SC_THREAD_KEYS_MAX
);
++
i
)
{
pthread_key_t
key
;
// If this fails, it's likely that GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT is wrong.
ASSERT_EQ
(
0
,
pthread_key_create
(
&
key
,
NULL
))
<<
i
<<
" of "
<<
sysconf
(
_SC_THREAD_KEYS_MAX
);
ASSERT_EQ
(
0
,
pthread_key_create
(
&
key
,
NULL
));
keys
.
push_back
(
key
);
}
...
...
@@ -48,7 +46,6 @@ TEST(pthread, pthread_key_create_lots) {
ASSERT_EQ
(
0
,
pthread_key_delete
(
keys
[
i
]));
}
}
#endif
static
void
*
IdFn
(
void
*
arg
)
{
return
arg
;
...
...
@@ -90,15 +87,6 @@ TEST(pthread, pthread_create) {
ASSERT_EQ
(
expected_result
,
result
);
}
TEST
(
pthread
,
pthread_create_EAGAIN
)
{
pthread_attr_t
attributes
;
ASSERT_EQ
(
0
,
pthread_attr_init
(
&
attributes
));
ASSERT_EQ
(
0
,
pthread_attr_setstacksize
(
&
attributes
,
static_cast
<
size_t
>
(
-
1
)
&
~
(
getpagesize
()
-
1
)));
pthread_t
t
;
ASSERT_EQ
(
EAGAIN
,
pthread_create
(
&
t
,
&
attributes
,
IdFn
,
NULL
));
}
TEST
(
pthread
,
pthread_no_join_after_detach
)
{
pthread_t
t1
;
ASSERT_EQ
(
0
,
pthread_create
(
&
t1
,
NULL
,
SleepFn
,
reinterpret_cast
<
void
*>
(
5
)));
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment