diff --git a/nx/include/switch/kernel/event.h b/nx/include/switch/kernel/event.h
new file mode 100644
index 00000000..2e429a1a
--- /dev/null
+++ b/nx/include/switch/kernel/event.h
@@ -0,0 +1,19 @@
+// Copyright 2018 plutoo
+#pragma once
+#include "../types.h"
+#include "../result.h"
+#include "../kernel/svc.h"
+
+typedef struct {
+    Handle revent;
+    Handle wevent;
+} Event;
+
+Result eventCreate(Event* t);
+void   eventLoadRemote(Event* t, Handle handle);
+void   eventClose(Event* t);
+
+Result eventWait(Event* t, u64 timeout);
+Result eventFire(Event* t);
+Result eventClear(Event* t);
+
diff --git a/nx/source/kernel/event.c b/nx/source/kernel/event.c
new file mode 100644
index 00000000..c038e7bb
--- /dev/null
+++ b/nx/source/kernel/event.c
@@ -0,0 +1,62 @@
+// Copyright 2018 plutoo
+#include "types.h"
+#include "result.h"
+#include "kernel/svc.h"
+#include "kernel/event.h"
+
+Result eventCreate(Event* t)
+{
+    Result rc;
+
+    rc = svcCreateEvent(&t->revent, &t->wevent);
+
+    if (R_FAILED(rc)) {
+        t->revent = INVALID_HANDLE;
+        t->wevent = INVALID_HANDLE;
+    }
+
+    return rc;
+}
+
+void eventLoadRemote(Event* t, Handle handle) {
+    t->revent = handle;
+}
+
+Result eventWait(Event* t, u64 timeout)
+{
+    Result rc;
+
+    rc = svcWaitSynchronizationSingle(t->revent, timeout);
+
+    if (R_SUCCEEDED(rc)) {
+        rc = svcResetSignal(t->revent);
+    }
+
+    return rc;
+}
+
+Result eventFire(Event* t) {
+    return svcSignalEvent(t->wevent);
+}
+
+Result eventClear(Event* t)
+{
+    if (t->wevent != INVALID_HANDLE)
+        return svcClearEvent(t->wevent);
+
+    if (t->revent != INVALID_HANDLE)
+        return svcClearEvent(t->revent);
+
+    return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
+}
+
+void eventClose(Event* t)
+{
+    if (t->revent != INVALID_HANDLE)
+        svcCloseHandle(t->revent);
+    if (t->wevent != INVALID_HANDLE)
+        svcCloseHandle(t->wevent);
+
+    t->revent = INVALID_HANDLE;
+    t->wevent = INVALID_HANDLE;
+}