diff --git a/Makefile.dep b/Makefile.dep
index 39bd45a516031f45a7045271b60e32e7041996bc..60614da7582ce1003c7bbe2bd09dd0dc1231ae0e 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -301,6 +301,11 @@ ifneq (,$(filter posix,$(USEMODULE)))
   USEMODULE += vtimer
 endif
 
+ifneq (,$(filter posix_semaphore,$(USEMODULE)))
+  USEMODULE += sem
+  USEMODULE += vtimer
+endif
+
 ifneq (,$(filter sem,$(USEMODULE)))
   USEMODULE += vtimer
 endif
diff --git a/sys/Makefile b/sys/Makefile
index 78f375543289937500880f0dc7e2cb4d09747eae..8baba47737237ea1ede70f76fd767b467d10b92b 100644
--- a/sys/Makefile
+++ b/sys/Makefile
@@ -1,3 +1,6 @@
+ifneq (,$(filter posix_semaphore,$(USEMODULE)))
+    DIRS += posix/semaphore
+endif
 ifneq (,$(filter posix_sockets,$(USEMODULE)))
     DIRS += posix/sockets
 endif
diff --git a/sys/Makefile.include b/sys/Makefile.include
index 1c4d405dee44b8b031c431af1b8dc73be549b5b7..eb3523ce0e3a36dea6d5032334467094749651c0 100644
--- a/sys/Makefile.include
+++ b/sys/Makefile.include
@@ -18,6 +18,9 @@ ifneq (,$(filter posix,$(USEMODULE)))
     USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
     USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
 endif
+ifneq (,$(filter posix_semaphore,$(USEMODULE)))
+    USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
+endif
 ifneq (,$(filter posix_sockets,$(USEMODULE)))
     USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
 endif
diff --git a/sys/posix/include/semaphore.h b/sys/posix/include/semaphore.h
index 0c21e0fb42b20ee4d6b81150c4e3bfeb8b59850d..cbf3fd64f9e4979293a8ff44eec95104d9a6f6fb 100644
--- a/sys/posix/include/semaphore.h
+++ b/sys/posix/include/semaphore.h
@@ -6,117 +6,170 @@
  * directory for more details.
  */
 
-#ifndef _SEMAPHORE_H
-#define _SEMAPHORE_H    1
+/**
+ * @defgroup    posix_semaphore POSIX semaphores
+ * @ingroup     posix
+ * @{
+ * @file
+ * @brief   Semaphores
+ * @see     <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/semaphore.h.html">
+ *              The Open Group Base Specifications Issue 7, <semaphore.h>
+ *          </a>
+ * @author  Christian Mehlis <mehlis@inf.fu-berlin.de>
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ * @author  René Kijewski <kijewski@inf.fu-berlin.de>
+ */
 
+#ifndef POSIX_SEMAPHORE_H_
+#define POSIX_SEMAPHORE_H_
+
+#include <errno.h>
 #include <time.h>
 
-#include "priority_queue.h"
+#include "sem.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/** Value returned if `sem_open' failed.  */
-#define SEM_FAILED      ((sem_t *) 0)
-
 /**
- * @brief Semaphore struct
+ * @brief Value returned if `sem_open' failed.
  */
-typedef struct sem {
-    /** the value of the semaphore */
-    volatile unsigned int value;
-    /** list of threads waiting for the semaphore */
-    priority_queue_t queue;
-} sem_t;
+#define SEM_FAILED      ((sem_t *) 0)
 
 /**
- * @brief Initialize semaphore object SEM to VALUE.
+ * @brief Initialize semaphore.
  *
- * @param sem Semaphore to initialize
- * @param pshared unused
- * @param value Value to set
- */
-int sem_init(sem_t *sem, int pshared, unsigned int value);
-
-/**
- * @brief Free resources associated with semaphore object SEM.
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html">
+ *          The Open Group Base Specifications Issue 7, sem_init()
+ *      </a>
  *
- * @param sem Semaphore to destroy
- */
-int sem_destroy(sem_t *sem);
-
-/*
- * @brief Open a named semaphore NAME with open flags OFLAG.
+ * The sem_init() function shall initialize the unnamed semaphore referred to by @p sem. The value
+ * of the initialized semaphore shall be @p value. Following a successful call to sem_init(),
+ * the semaphore may be used in subsequent calls to sem_wait(), sem_timedwait(),
+ * sem_trywait(), sem_post(), and sem_destroy(). This semaphore shall remain usable until the
+ * semaphore is destroyed.
  *
- * @brief WARNING: named semaphore are currently not supported
+ * @param[out] sem      Semaphore to initialize.
+ * @param[in] pshared   **(unused, since RIOT only has threads)**
+ *                      Semaphore is shared between processes not threads.
+ * @param[in] value     Value to set.
  *
- * @param name Name to set
- * @param oflag Flags to set
+ * @return  0 on success.
+ * @return  -EINVAL, if semaphore is invalid.
  */
-sem_t *sem_open(const char *name, int oflag, ...);
+#define sem_init(sem, pshared, value)   sem_create(sem, value)
 
 /**
- * @brief Close descriptor for named semaphore SEM.
+ * @brief Open a named semaphore @p name with open flags @p oflag.
  *
- * @brief WARNING: named semaphore are currently not supported
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_open.html">
+ *          The Open Group Base Specifications Issue 7, sem_open()
+ *      </a>
  *
- * @param sem Semaphore to close
- */
-int sem_close(sem_t *sem);
-
-/**
- * @brief Remove named semaphore NAME.
+ * @todo  named semaphore are currently not supported
  *
- * @brief WARNING: named semaphore are currently not supported
+ * @param[in] name  Name to set.
+ * @param[in] oflag Flags to set.
  *
- * @param name Name to unlink
+ * @return  Always @ref SEM_FAILED, since it is not implemented currently.
  */
-int sem_unlink(const char *name);
+#define sem_open(name, oflag, ...)      (SEM_FAILED)
 
 /**
- * @brief Wait for SEM being posted.
+ * @brief Close descriptor for named semaphore @p sem.
  *
- * @param sem Semaphore to wait
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_close.html">
+ *          The Open Group Base Specifications Issue 7, sem_close()
+ *      </a>
+ *
+ * @todo  named semaphore are currently not supported
+ *
+ * @param[in] sem   Semaphore to close.
+ *
+ * @return  Always -1, since it is not implemented currently.
  */
-int sem_wait(sem_t *sem);
+#define sem_close(sem)                  (-1)
 
 /**
- * @brief Similar to `sem_wait' but wait only until ABSTIME.
+ * @brief Remove named semaphore @p name.
+ *
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_unlink.html">
+ *          The Open Group Base Specifications Issue 7, sem_unlink()
+ *      </a>
  *
- * @brief WARNING: currently not supported
+ * @todo  named semaphore are currently not supported
  *
- * @param sem Semaphore to wait on
- * @param abstime Max time to wait for a post
+ * @param[in] name  Name to unlink.
  *
+ * @return  Always -1, since it is not implemented currently.
+ */
+#define sem_unlink(name)                (-1)
+
+/**
+ * @brief Similar to `sem_wait' but wait only until @p abstime.
+ *
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html">
+ *          The Open Group Base Specifications Issue 7, sem_timedwait()
+ *      </a>
+ *
+ * The sem_timedwait() function shall lock the semaphore referenced by @p sem as in the sem_wait()
+ * function. However, if the semaphore cannot be locked without waiting for another process or
+ * thread to unlock the semaphore by performing a sem_post() function, this wait shall be
+ * terminated when the specified timeout expires.
+ *
+ * @param[in] sem       Semaphore to wait on.
+ * @param[in] abstime   Absolute time (that is when the clock on which temouts are based equals
+ *                      this value) the timeout for the wait shall expire. If the value specified
+ *                      has already passed the timeout expires immediately.
+ *
+ * @return  0 on success
+ * @return  -EINVAL, if semaphore is invalid.
+ * @return  -ETIMEDOUT, if the semaphore times out.
+ * @return  -ECANCELED, if the semaphore was destroyed.
  */
 int sem_timedwait(sem_t *sem, const struct timespec *abstime);
 
 /**
  * @brief Test whether SEM is posted.
  *
- * @param sem Semaphore to trywait on
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html">
+ *          The Open Group Base Specifications Issue 7, sem_trywait()
+ *      </a>
  *
- */
-int sem_trywait(sem_t *sem);
-
-/**
- * @brief Post SEM.
+ * @param[in] sem   Semaphore to try to wait on
  *
- * @param sem Semaphore to post on
+ * @return  0 on success
+ * @return  -EINVAL, if semaphore is invalid.
+ * @return  -EAGAIN, if the semaphore was already locked.
  */
-int sem_post(sem_t *sem);
+int sem_trywait(sem_t *sem);
 
 /**
  * @brief Get current value of SEM and store it in *SVAL.
  *
- * @param sem Semaphore to get value from
- * @param sval place whre value goes to
+ * @see <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html">
+ *          The Open Group Base Specifications Issue 7, sem_getvalue()
+ *      </a>
+ *
+ * @param[in] sem   Semaphore to get the value from.
+ * @param[out] sval Place where value goes to.
+ *
+ * @return  0 on success
+ * @return  -EINVAL, if semaphore is invalid.
  */
-int sem_getvalue(sem_t *sem, int *sval);
+static inline int sem_getvalue(sem_t *sem, int *sval)
+{
+    if (sem != NULL) {
+        *sval = (int)sem->value;
+        return 0;
+    }
+    return -EINVAL;
+}
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif  /* semaphore.h */
+#endif  /* POSIX_SEMAPHORE_H_ */
+/** @} */
diff --git a/sys/posix/semaphore.c b/sys/posix/semaphore.c
deleted file mode 100644
index 09a4c40c346586ea16a6218bed0b691d0d631e9c..0000000000000000000000000000000000000000
--- a/sys/posix/semaphore.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * Semaphore implemenation
- *
- * Copyright (C) 2013 Freie Universität Berlin
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- *
- * @ingroup posix
- *
- * @{
- *
- * @file
- * @brief   Implementation of semaphores with priority queues
- *
- * @author  Christian Mehlis <mehlis@inf.fu-berlin.de>
- * @author  René Kijewski <kijewski@inf.fu-berlin.de>
- *
- * @}
- */
-
-#include <inttypes.h>
-
-#include "irq.h"
-#include "sched.h"
-#include "tcb.h"
-#include "thread.h"
-
-#define ENABLE_DEBUG (0)
-#include "debug.h"
-
-#include "semaphore.h"
-
-int sem_init(sem_t *sem, int pshared, unsigned int value)
-{
-    (void) pshared;  /* nothing to do */
-
-    sem->value = value;
-
-    /* waiters for the mutex */
-    sem->queue.first = NULL;
-
-    return 0;
-}
-
-int sem_destroy(sem_t *sem)
-{
-    if (sem->queue.first) {
-        DEBUG("sem_destroy: %" PRIkernel_pid ": tried to destroy active semaphore.\n",
-              sched_active_thread->pid);
-        return -1;
-    }
-    return 0;
-}
-
-sem_t *sem_open(const char *name, int oflag, ...)
-{
-    (void) name; /* named semaphore currently not supported */
-    (void) oflag;
-    return SEM_FAILED;
-}
-
-int sem_close(sem_t *sem)
-{
-    (void) sem; /* named semaphore currently not supported */
-    return -1;
-}
-
-int sem_unlink(const char *name)
-{
-    (void) name; /* named semaphore currently not supported */
-    return -1;
-}
-
-int sem_wait(sem_t *sem)
-{
-    while (1) {
-        unsigned old_state = disableIRQ();
-
-        unsigned value = sem->value;
-        if (value != 0) {
-            sem->value = value - 1;
-            restoreIRQ(old_state);
-            return 1;
-        }
-
-        /* I'm going blocked */
-        priority_queue_node_t n;
-        n.priority = (uint32_t) sched_active_thread->priority;
-        n.data = (uintptr_t) sched_active_thread;
-        n.next = NULL;
-        priority_queue_add(&sem->queue, &n);
-
-        DEBUG("sem_wait: %" PRIkernel_pid ": Adding node to mutex queue: prio: %" PRIu32 "\n",
-              sched_active_thread->pid, sched_active_thread->priority);
-
-        /* scheduler should schedule an other thread, that unlocks the
-         * mutex in the future, when this happens I get scheduled again
-         */
-        sched_set_status((tcb_t*) sched_active_thread, STATUS_MUTEX_BLOCKED);
-        restoreIRQ(old_state);
-        thread_yield_higher();
-    }
-}
-
-int sem_timedwait(sem_t *sem, const struct timespec *abstime)
-{
-    (void) sem; /* timedwait currently not supported */
-    (void) abstime;
-    return -1; /* signal problem */
-}
-
-int sem_trywait(sem_t *sem)
-{
-    unsigned old_state = disableIRQ();
-    int result;
-
-    unsigned value = sem->value;
-    if (value == 0) {
-        result = -1;
-    }
-    else {
-        result = 0;
-        sem->value = value - 1;
-    }
-
-    restoreIRQ(old_state);
-    return result;
-}
-
-int sem_post(sem_t *sem)
-{
-    unsigned old_state = disableIRQ();
-    ++sem->value;
-
-    priority_queue_node_t *next = priority_queue_remove_head(&sem->queue);
-    if (next) {
-        tcb_t *next_process = (tcb_t*) next->data;
-        DEBUG("sem_post: %" PRIkernel_pid ": waking up %" PRIkernel_pid "\n",
-              sched_active_thread->pid, next_process->pid);
-        sched_set_status(next_process, STATUS_PENDING);
-
-        uint16_t prio = next_process->priority;
-        restoreIRQ(old_state);
-        sched_switch(prio);
-    }
-    else {
-        restoreIRQ(old_state);
-    }
-
-    return 1;
-}
-
-int sem_getvalue(sem_t *sem, int *sval)
-{
-    *sval = sem->value;
-    return 0;
-}
diff --git a/sys/posix/semaphore/Makefile b/sys/posix/semaphore/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..68d9a081b01f2d1923cfb9a18ebbfc41c8df6a28
--- /dev/null
+++ b/sys/posix/semaphore/Makefile
@@ -0,0 +1,3 @@
+MODULE = posix_semaphore
+
+include $(RIOTBASE)/Makefile.base
diff --git a/sys/posix/semaphore/posix_semaphore.c b/sys/posix/semaphore/posix_semaphore.c
new file mode 100644
index 0000000000000000000000000000000000000000..4f9756296fdc5494ceed9990937e42e9ee5e8726
--- /dev/null
+++ b/sys/posix/semaphore/posix_semaphore.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ *
+ * @author  Christian Mehlis <mehlis@inf.fu-berlin.de>
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ * @author  René Kijewski <kijewski@inf.fu-berlin.de>
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+
+#include "irq.h"
+#include "sched.h"
+#include "sem.h"
+#include "tcb.h"
+#include "timex.h"
+#include "thread.h"
+#include "vtimer.h"
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+#include "semaphore.h"
+
+#define USEC_IN_NS  (1000)
+
+int sem_timedwait(sem_t *sem, const struct timespec *abstime)
+{
+    timex_t now, timeout = { abstime->tv_sec, abstime->tv_nsec / USEC_IN_NS };
+    int res;
+    vtimer_now(&now);
+    if (timex_cmp(now, timeout) > 0) {
+        errno = ETIMEDOUT;
+        return -ETIMEDOUT;
+    }
+    timeout = timex_sub(timeout, now);
+    res = sem_wait_timed(sem, &timeout);
+    if (res < 0) {
+        errno = -res;
+    }
+    return res;
+}
+
+int sem_trywait(sem_t *sem)
+{
+    unsigned int old_state, value;
+    int result;
+    if (sem == NULL) {
+        errno = EINVAL;
+        return -EINVAL;
+    }
+    old_state = disableIRQ();
+    value = sem->value;
+    if (value == 0) {
+        errno = EAGAIN;
+        result = -EAGAIN;
+    }
+    else {
+        result = 0;
+        sem->value = value - 1;
+    }
+
+    restoreIRQ(old_state);
+    return result;
+}
+
+/** @} */
diff --git a/tests/posix_semaphore/Makefile b/tests/posix_semaphore/Makefile
index edb55ba23da3947e13f8155b4f94ad3ea9afd86d..619d444f8ec78fc3f462a83401ee5c9eebfde232 100644
--- a/tests/posix_semaphore/Makefile
+++ b/tests/posix_semaphore/Makefile
@@ -4,7 +4,7 @@ include ../Makefile.tests_common
 BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h mbed_lpc1768 chronos stm32f0discovery \
                           pca10000 pca10005 weio yunjia-nrf51822 nrf6310 spark-core
 
-USEMODULE += posix
+USEMODULE += posix_semaphore
 
 DISABLE_MODULE += auto_init
 
diff --git a/tests/posix_semaphore/main.c b/tests/posix_semaphore/main.c
index c6258511a38585e987063515d8efa9bc93e6324f..55dc06f81b8b15465ba811964bbfde1d34d156e6 100644
--- a/tests/posix_semaphore/main.c
+++ b/tests/posix_semaphore/main.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2013 Christian Mehlis <mehlis@inf.fu-berlin.de>
  * Copyright (C) 2013 René Kijewski <rene.kijewski@fu-berlin.de>
+ * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
  *
  * This file is subject to the terms and conditions of the GNU Lesser
  * General Public License v2.1. See the file LICENSE in the top level