diff --git a/libports/lib/mk/pthread.mk b/libports/lib/mk/pthread.mk
new file mode 100644
index 0000000000..543c1821a3
--- /dev/null
+++ b/libports/lib/mk/pthread.mk
@@ -0,0 +1,8 @@
+SRC_CC = semaphore.cc \
+ thread.cc
+
+LIBS += libc
+
+vpath % $(REP_DIR)/src/lib/pthread
+
+SHARED_LIB = yes
diff --git a/libports/run/pthread.run b/libports/run/pthread.run
new file mode 100644
index 0000000000..61caff38c1
--- /dev/null
+++ b/libports/run/pthread.run
@@ -0,0 +1,35 @@
+build "core init test/pthread"
+
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+build_boot_image {
+ core init test-pthread
+ ld.lib.so libc.lib.so libc_log.lib.so pthread.lib.so
+}
+
+append qemu_args " -nographic -m 64 "
+
+run_genode_until "--- returning from main ---" 10
diff --git a/libports/src/lib/pthread/semaphore.cc b/libports/src/lib/pthread/semaphore.cc
new file mode 100644
index 0000000000..d95af43d24
--- /dev/null
+++ b/libports/src/lib/pthread/semaphore.cc
@@ -0,0 +1,103 @@
+/*
+ * \brief POSIX semaphore implementation
+ * \author Christian Prochaska
+ * \date 2012-03-12
+ *
+ */
+
+/*
+ * Copyright (C) 2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#include
+#include
+
+#include
+
+using namespace Genode;
+
+extern "C" {
+
+ /*
+ * This class is named 'struct sem' because the 'sem_t' type is
+ * defined as 'struct sem*' in 'semaphore.h'
+ */
+ struct sem : Timed_semaphore
+ {
+ sem(int value) : Timed_semaphore(value) { }
+ };
+
+
+ int sem_close(sem_t *)
+ {
+ PDBG("not implemented");
+ return -1;
+ }
+
+
+ int sem_destroy(sem_t *sem)
+ {
+ destroy(env()->heap(), *sem);
+ return 0;
+ }
+
+
+ int sem_getvalue(sem_t * __restrict sem, int * __restrict sval)
+ {
+ *sval = (*sem)->cnt();
+ return 0;
+ }
+
+
+ int sem_init(sem_t *sem, int pshared, unsigned int value)
+ {
+ *sem = new (env()->heap()) struct sem(value);
+ return 0;
+ }
+
+
+ sem_t *sem_open(const char *, int, ...)
+ {
+ PDBG("not implemented");
+ return 0;
+ }
+
+
+ int sem_post(sem_t *sem)
+ {
+ (*sem)->up();
+ return 0;
+ }
+
+
+ int sem_timedwait(sem_t * __restrict, const struct timespec * __restrict)
+ {
+ PDBG("not implemented");
+ return -1;
+ }
+
+
+ int sem_trywait(sem_t *)
+ {
+ PDBG("not implemented");
+ return -1;
+ }
+
+
+ int sem_unlink(const char *)
+ {
+ PDBG("not implemented");
+ return -1;
+ }
+
+
+ int sem_wait(sem_t *sem)
+ {
+ (*sem)->down();
+ return 0;
+ }
+
+}
diff --git a/libports/src/lib/pthread/thread.cc b/libports/src/lib/pthread/thread.cc
new file mode 100644
index 0000000000..1b628905b1
--- /dev/null
+++ b/libports/src/lib/pthread/thread.cc
@@ -0,0 +1,93 @@
+/*
+ * \brief POSIX thread implementation
+ * \author Christian Prochaska
+ * \date 2012-03-12
+ *
+ */
+
+/*
+ * Copyright (C) 2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+using namespace Genode;
+
+extern "C" {
+
+ enum { STACK_SIZE=64*1024 };
+
+ /*
+ * This class is named 'struct pthread' because the 'pthread_t' type is
+ * defined as 'struct pthread*' in '_pthreadtypes.h'
+ */
+ struct pthread : Thread
+ {
+ void *(*_start_routine) (void *);
+ void *_arg;
+
+ pthread(void *(*start_routine) (void *), void *arg)
+ : Thread("pthread"),
+ _start_routine(start_routine),
+ _arg(arg) { }
+
+ void entry()
+ {
+ void *exit_status = _start_routine(_arg);
+ pthread_exit(exit_status);
+ }
+ };
+
+
+ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
+ void *(*start_routine) (void *), void *arg)
+ {
+ pthread_t thread_obj = new (env()->heap()) pthread(start_routine, arg);
+
+ if (!thread_obj) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ *thread = thread_obj;
+
+ thread_obj->start();
+
+ return 0;
+ }
+
+
+ int pthread_cancel(pthread_t thread)
+ {
+ destroy(env()->heap(), thread);
+ return 0;
+ }
+
+
+ void pthread_exit(void *value_ptr)
+ {
+ pthread_cancel(pthread_self());
+ sleep_forever();
+ }
+
+
+ pthread_t pthread_self(void)
+ {
+ static struct pthread main_thread(0, 0);
+
+ pthread_t thread = static_cast(Thread_base::myself());
+
+ /* the main thread does not have a Genode thread object */
+ return thread ? thread : &main_thread;
+ }
+
+}
diff --git a/libports/src/test/pthread/main.cc b/libports/src/test/pthread/main.cc
new file mode 100644
index 0000000000..45696793b5
--- /dev/null
+++ b/libports/src/test/pthread/main.cc
@@ -0,0 +1,132 @@
+/*
+ * \brief POSIX thread and semaphore test
+ * \author Christian Prochaska
+ * \date 2012-04-04
+ */
+
+/*
+ * Copyright (C) 2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#include
+#include
+#include
+#include
+
+
+enum { NUM_THREADS = 2 };
+
+
+struct Thread_args {
+ int thread_num;
+ sem_t thread_finished_sem;
+ pthread_t thread_id_self; /* thread ID returned by 'pthread_self()' */
+};
+
+
+struct Thread {
+ Thread_args thread_args;
+ pthread_t thread_id_create; /* thread ID returned by 'pthread_create()' */
+};
+
+
+void *thread_func(void *arg)
+{
+ Thread_args *thread_args = (Thread_args*)arg;
+
+ printf("thread %d: running, my thread ID is %p\n",
+ thread_args->thread_num, pthread_self());
+
+ thread_args->thread_id_self = pthread_self();
+
+ sem_post(&thread_args->thread_finished_sem);
+
+ /* sleep forever */
+ sem_t sleep_sem;
+ sem_init(&sleep_sem, 0, 0);
+ sem_wait(&sleep_sem);
+
+ return 0;
+}
+
+static inline void compare_semaphore_values(int reported_value, int expected_value)
+{
+ if (reported_value != expected_value) {
+ printf("error: sem_getvalue() did not return the expected value\n");
+ exit(-1);
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ printf("--- pthread test ---\n");
+
+ printf("main thread: running, my thread ID is %p\n", pthread_self());
+
+ Thread thread[NUM_THREADS];
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ thread[i].thread_args.thread_num = i + 1;
+
+ printf("main thread: creating semaphore for thread %d\n",
+ thread[i].thread_args.thread_num);
+
+ if (sem_init(&thread[i].thread_args.thread_finished_sem, 0, 1) != 0) {
+ printf("sem_init() failed\n");
+ return -1;
+ }
+
+ /* check result of 'sem_getvalue()' before and after calling 'sem_wait()' */
+
+ int sem_value = -1;
+
+ sem_getvalue(&thread[i].thread_args.thread_finished_sem, &sem_value);
+ compare_semaphore_values(sem_value, 1);
+
+ sem_wait(&thread[i].thread_args.thread_finished_sem);
+
+ sem_getvalue(&thread[i].thread_args.thread_finished_sem, &sem_value);
+ compare_semaphore_values(sem_value, 0);
+
+ thread[i].thread_args.thread_id_self = 0;
+
+ printf("main thread: creating thread %d\n", thread[i].thread_args.thread_num);
+
+ if (pthread_create(&thread[i].thread_id_create, 0, thread_func,
+ &thread[i].thread_args) != 0) {
+ printf("error: pthread_create() failed\n");
+ return -1;
+ }
+ printf("main thread: thread %d has thread ID %p\n",
+ thread[i].thread_args.thread_num, thread[i].thread_id_create);
+ }
+
+ printf("main thread: waiting for the threads to finish\n");
+
+ for (int i = 0; i < NUM_THREADS; i++)
+ sem_wait(&thread[i].thread_args.thread_finished_sem);
+
+ printf("main thread: comparing the thread IDs\n");
+
+ for (int i = 0; i < NUM_THREADS; i++)
+ if (thread[i].thread_args.thread_id_self != thread[i].thread_id_create) {
+ printf("error: thread IDs don't match\n");
+ }
+
+ printf("main thread: destroying the threads\n");
+
+ for (int i = 0; i < NUM_THREADS; i++)
+ pthread_cancel(thread[i].thread_id_create);
+
+ printf("main thread: destroying the semaphores\n");
+
+ for (int i = 0; i < NUM_THREADS; i++)
+ sem_destroy(&thread[i].thread_args.thread_finished_sem);
+
+ printf("--- returning from main ---\n");
+ return 0;
+}
diff --git a/libports/src/test/pthread/target.mk b/libports/src/test/pthread/target.mk
new file mode 100644
index 0000000000..40c7c2c136
--- /dev/null
+++ b/libports/src/test/pthread/target.mk
@@ -0,0 +1,3 @@
+TARGET = test-pthread
+SRC_CC = main.cc
+LIBS = libc libc_log pthread