Commit graph

8 commits

Author SHA1 Message Date
Elliott Hughes
7484c21c4c Revert "Remove the global thread list."
This reverts commit b0e8c565a6.

Breaks swiftshader (http:/b/34883464).

Change-Id: I7b21193ba8a78f07d7ac65e41d0fe8516940a83b
2017-02-02 02:41:38 +00:00
Elliott Hughes
b0e8c565a6 Remove the global thread list.
Another release, another attempt to fix this bug.

This change affects pthread_detach, pthread_getcpuclockid,
pthread_getschedparam/pthread_setschedparam, pthread_join, and pthread_kill:
instead of returning ESRCH when passed an invalid pthread_t, they'll now SEGV.

Note that this doesn't change behavior as much as you might think: the old
lookup only held the global thread list lock for the duration of the lookup,
so there was still a race between that and the dereference in the caller,
given that callers actually need the tid to pass to some syscall or other,
and sometimes update fields in the pthread_internal_t struct too.

We can't check thread->tid against 0 to see whether a pthread_t is still
valid because a dead thread gets its thread struct unmapped along with its
stack, so the dereference isn't safe.

Taking the affected functions one by one:

* pthread_getcpuclockid and pthread_getschedparam/pthread_setschedparam
  should be fine. Unsafe calls to those seem highly unlikely.

* Unsafe pthread_detach callers probably want to switch to
  pthread_attr_setdetachstate instead, or using pthread_detach(pthread_self())
  from the new thread's start routine rather than doing the detach in the
  parent.

* pthread_join calls should be safe anyway, because a joinable thread won't
  actually exit and unmap until it's joined. If you're joining an
  unjoinable thread, the fix is to stop marking it detached. If you're
  joining an already-joined thread, you need to rethink your design.

* Unsafe pthread_kill calls aren't portably fixable. (And are obviously
  inherently non-portable as-is.) The best alternative on Android is to
  use pthread_gettid_np at some point that you know the thread to be alive,
  and then call kill/tgkill directly. That's still not completely safe
  because if you're too late, the tid may have been reused, but then your
  code is inherently unsafe anyway.

If we find too much code is still broken, we can come back and disable
the global thread list lookups for anything targeting >= O and then have
another go at really removing this in P...

Bug: http://b/19636317
Test: N6P boots, bionic tests pass
Change-Id: Ia92641212f509344b99ee2a9bfab5383147fcba6
2017-01-07 14:16:46 -08:00
Yabin Cui
673b15e4ee Let g_thread_list_lock only protect g_thread_list.
As glibc/netbsd don't protect access to thread struct members by a global
lock, we don't want to do it either. This change reduces the
responsibility of g_thread_list_lock to only protect g_thread_list.

Bug: 19636317
Change-Id: I897890710653dac165d8fa4452c7ecf74abdbf2b
2015-03-23 19:03:49 -07:00
Yabin Cui
58cf31b506 Make pthread join_state not protected by g_thread_list_lock.
1. Move the representation of thread join_state from pthread.attr.flag
   to pthread.join_state. This clarifies thread state change.
2. Use atomic operations for pthread.join_state. So we don't need to
   protect it by g_thread_list_lock. g_thread_list_lock will be reduced
   to only protect g_thread_list or even removed in further changes.

Bug: 19636317
Change-Id: I31fb143a7c69508c7287307dd3b0776993ec0f43
2015-03-12 21:39:49 -07:00
Yabin Cui
8cf1b30567 Use mmap to create the pthread_internal_t
Add name to mmaped regions.
Add pthread benchmark code.
Allocate pthread_internal_t on regular stack.

Bug: 16847284
Change-Id: Id60835163bb0d68092241f1a118015b5a8f85069
2014-12-19 16:05:29 -08:00
Elliott Hughes
877ec6d904 Fix pthread_join.
Let the kernel keep pthread_internal_t::tid updated, including
across forks and for the main thread. This then lets us fix
pthread_join to only return after the thread has really exited.

Also fix the thread attributes of the main thread so we don't
unmap the main thread's stack (which is really owned by the
dynamic linker and contains things like environment variables),
which fixes crashes when joining with an exited main thread
and also fixes problems reported publicly with accessing environment
variables after the main thread exits (for which I've added a new
unit test).

In passing I also fixed a bug where if the clone(2) inside
pthread_create(3) fails, we'd unmap the child's stack and TLS (which
contains the mutex) and then try to unlock the mutex. Boom! It wasn't
until after I'd uploaded the fix for this that I came across a new
public bug reporting this exact failure.

Bug: 8206355
Bug: 11693195
Bug: https://code.google.com/p/android/issues/detail?id=57421
Bug: https://code.google.com/p/android/issues/detail?id=62392
Change-Id: I2af9cf6e8ae510a67256ad93cad891794ed0580b
2013-11-18 19:48:11 -08:00
msg555
0f020d18b1 Handles spurious wake-ups in pthread_join()
Removed 'join_count' from pthread_internal_t and switched to using the flag
PTHREAD_ATTR_FLAG_JOINED to indicate if a thread is being joined. Combined with
a switch to a while loop in pthread_join, this fixes spurious wake-ups but
prevents a thread from being joined multiple times. This is fine for
two reasons:

1) The pthread_join specification allows for undefined behavior when multiple
   threads try to join a single thread.

2) There is no thread safe way to allow multiple threads to join a single
   thread with the pthread interface.  The second thread calling pthread_join
   could be pre-empted until the thread is destroyed and its handle reused for
   a different thread.  Therefore multi-join is always an error.

Bug: https://code.google.com/p/android/issues/detail?id=52255
Change-Id: I8b6784d47620ffdcdbfb14524e7402e21d46c5f7
2013-06-12 17:30:58 -07:00
Elliott Hughes
9d23e04c43 Fix pthreads functions that should return ESRCH.
imgtec pointed out that pthread_kill(3) was broken, but most of the
other functions that ought to return ESRCH for invalid/exited threads
were equally broken.

Change-Id: I96347f6195549aee0c72dc39063e6c5d06d2e01f
2013-02-19 12:21:41 -08:00