libc: don't take alien thread for main pthread

It covers bugs which we should detect and fix, especially depending on
the result of pthread_myself locking implementation (ours and vbox) takes
decision to take a lock or just to assume it is a reentrant locking attempt.

Fixes #1128
This commit is contained in:
Alexander Boettcher 2014-04-09 15:47:26 +02:00 committed by Norman Feske
parent b9cf2eade8
commit 8824ce8962
5 changed files with 45 additions and 18 deletions

View File

@ -38,3 +38,5 @@ build_boot_image {
append qemu_args " -nographic -m 64 " append qemu_args " -nographic -m 64 "
run_genode_until "--- returning from main ---" 10 run_genode_until "--- returning from main ---" 10
puts "Test succeeded"

View File

@ -25,8 +25,6 @@
using namespace Genode; using namespace Genode;
static const bool verbose = false;
extern "C" { extern "C" {
/* Thread */ /* Thread */
@ -71,25 +69,36 @@ extern "C" {
pthread_t pthread_self(void) pthread_t pthread_self(void)
{ {
static struct pthread_attr main_thread_attr;
static struct pthread main_thread(&main_thread_attr, 0, 0, 64*1024,
"main", nullptr);
Thread_base *myself = Thread_base::myself(); Thread_base *myself = Thread_base::myself();
/* the main thread does not have a Genode thread object */
if (!myself)
return &main_thread;
pthread_t pthread = dynamic_cast<pthread_t>(myself); pthread_t pthread = dynamic_cast<pthread_t>(myself);
if (pthread)
return pthread;
if (!pthread) { /* either it is the main thread, an alien thread or a bug */
if (verbose)
PDBG("pthread_self() possibly called from alien thread, returning &main_thread."); /* determine name of thread */
return &main_thread; char name[Thread_base::Context::NAME_LEN];
myself->name(name, sizeof(name));
/* determine if stack is in first context area slot */
addr_t stack = reinterpret_cast<addr_t>(&myself);
bool is_main = Native_config::context_area_virtual_base() <= stack &&
stack < Native_config::context_area_virtual_base() +
Native_config::context_virtual_size();
/* check that stack and name is of main thread */
if (is_main && !strcmp(name, "main")) {
/* create a pthread object containing copy of main Thread_base */
static struct pthread_attr main_thread_attr;
static struct pthread main(*myself, &main_thread_attr);
return &main;
} }
return pthread; PERR("pthread_self() called from alien thread named '%s'", name);
return nullptr;
} }
@ -359,7 +368,6 @@ extern "C" {
if (!attr) if (!attr)
return EINVAL; return EINVAL;
PDBG("not implemented yet");
*attr = 0; *attr = 0;
return 0; return 0;
@ -452,7 +460,7 @@ extern "C" {
* logs a warning if the timeout is lower than the minimum. To * logs a warning if the timeout is lower than the minimum. To
* prevent the warning, limit timeouts to >= 10 ms here. * prevent the warning, limit timeouts to >= 10 ms here.
*/ */
if (timeout != 0) timeout = max(timeout, 10); if (timeout != 0) timeout = max(timeout, 10U);
c->signal_sem.down(timeout); c->signal_sem.down(timeout);
} catch (Timeout_exception) { } catch (Timeout_exception) {
result = ETIMEDOUT; result = ETIMEDOUT;

View File

@ -50,6 +50,18 @@ extern "C" {
_attr->pthread = this; _attr->pthread = this;
} }
/**
* Constructor to create pthread object out of existing thread,
* e.g. main Genode thread
*/
pthread(Thread_base &myself, pthread_attr_t attr)
: Thread_base(myself),
_attr(attr), _start_routine(nullptr), _arg(nullptr)
{
if (_attr)
_attr->pthread = this;
}
void entry() void entry()
{ {
void *exit_status = _start_routine(_arg); void *exit_status = _start_routine(_arg);

View File

@ -65,7 +65,11 @@ int main(int argc, char **argv)
{ {
printf("--- pthread test ---\n"); printf("--- pthread test ---\n");
printf("main thread: running, my thread ID is %p\n", pthread_self()); pthread_t pthread_main = pthread_self();
printf("main thread: running, my thread ID is %p\n", pthread_main);
if (!pthread_main)
return -1;
Thread thread[NUM_THREADS]; Thread thread[NUM_THREADS];

View File

@ -42,3 +42,4 @@ blk_cache
rump_ext2 rump_ext2
virtualbox_auto_disk virtualbox_auto_disk
thread thread
pthread