diff --git a/libports/run/pthread.run b/libports/run/pthread.run index bdc69089c9..047bc619b6 100644 --- a/libports/run/pthread.run +++ b/libports/run/pthread.run @@ -38,3 +38,5 @@ build_boot_image { append qemu_args " -nographic -m 64 " run_genode_until "--- returning from main ---" 10 + +puts "Test succeeded" diff --git a/libports/src/lib/pthread/thread.cc b/libports/src/lib/pthread/thread.cc index f83e70ba3d..d22f922d77 100644 --- a/libports/src/lib/pthread/thread.cc +++ b/libports/src/lib/pthread/thread.cc @@ -25,8 +25,6 @@ using namespace Genode; -static const bool verbose = false; - extern "C" { /* Thread */ @@ -71,25 +69,36 @@ extern "C" { 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(); - /* the main thread does not have a Genode thread object */ - if (!myself) - return &main_thread; - pthread_t pthread = dynamic_cast(myself); + if (pthread) + return pthread; - if (!pthread) { - if (verbose) - PDBG("pthread_self() possibly called from alien thread, returning &main_thread."); - return &main_thread; + /* either it is the main thread, an alien thread or a bug */ + + /* determine name of 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(&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) return EINVAL; - PDBG("not implemented yet"); *attr = 0; return 0; @@ -452,7 +460,7 @@ extern "C" { * logs a warning if the timeout is lower than the minimum. To * 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); } catch (Timeout_exception) { result = ETIMEDOUT; diff --git a/libports/src/lib/pthread/thread.h b/libports/src/lib/pthread/thread.h index cb19830f5e..c5bea08430 100644 --- a/libports/src/lib/pthread/thread.h +++ b/libports/src/lib/pthread/thread.h @@ -50,6 +50,18 @@ extern "C" { _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 *exit_status = _start_routine(_arg); diff --git a/libports/src/test/pthread/main.cc b/libports/src/test/pthread/main.cc index 434c425578..1565d7cbed 100644 --- a/libports/src/test/pthread/main.cc +++ b/libports/src/test/pthread/main.cc @@ -65,7 +65,11 @@ int main(int argc, char **argv) { 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]; diff --git a/tool/autopilot.list b/tool/autopilot.list index 9b3b319587..85d4c8952a 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -42,3 +42,4 @@ blk_cache rump_ext2 virtualbox_auto_disk thread +pthread