Implement installing MISR (a mid-level interrupt service routine)

This is the middle-level interrupt handler that's triggered from the
LISR. It's just a dedicated thread for now.

Change-Id: I1a27facd695d97d33d6d4b6cf2010b772ad29e64
diff --git a/services/server/env/fuchsia/osfunc.cc b/services/server/env/fuchsia/osfunc.cc
index 10cccd5..5fa771c 100644
--- a/services/server/env/fuchsia/osfunc.cc
+++ b/services/server/env/fuchsia/osfunc.cc
@@ -100,6 +100,14 @@
 	}
 };
 
+struct MisrHandle
+{
+	std::thread thread;
+	// ZX_EVENT_SIGNALED is used to wake up, and ZX_USER_SIGNAL_0 is used to
+	// force the handler to quit.
+	zx::event event;
+};
+
 
 } // namespace msd_img
 
@@ -451,34 +459,67 @@
 	return 0;
 }
 
-/*
-	OSInstallMISR
-*/
 PVRSRV_ERROR
 OSInstallMISR(IMG_HANDLE *hMISRData, PFN_MISR pfnMISR, void *hData)
 {
-	NOT_IMPLEMENTED();
-	return PVRSRV_ERROR_NOT_SUPPORTED;
+	auto misr_handle = std::make_unique<msd_img::MisrHandle>();
+	zx_status_t status = zx::event::create(0, &misr_handle->event);
+	if (status != ZX_OK)
+	{
+		return ZxStatusToError(status);
+	}
+	misr_handle->thread = std::thread(
+		[](PFN_MISR pfnMISR, void *hData, msd_img::MisrHandle *misr_handle) {
+			while (true)
+			{
+				zx_signals_t observed;
+				zx_status_t status = misr_handle->event.wait_one(ZX_EVENT_SIGNALED | ZX_USER_SIGNAL_0,
+										 zx::time::infinite(), &observed);
+				if (status != ZX_OK)
+				{
+					DLOG("Failed to wait on MISR handle");
+					return;
+				}
+				// Clear before running the callback to ensure a signal during the
+				// callback won't be ignored.
+				status = misr_handle->event.signal(ZX_EVENT_SIGNALED, 0);
+				if (status != ZX_OK)
+				{
+					DLOG("Failed clear MISR handle");
+					return;
+				}
+				if (observed & ZX_USER_SIGNAL_0)
+					break;
+				pfnMISR(hData);
+			}
+		},
+		pfnMISR, hData, misr_handle.get());
+	*hMISRData = misr_handle.release();
+	return PVRSRV_OK;
 }
 
-/*
-	OSUninstallMISR
-*/
 PVRSRV_ERROR
 OSUninstallMISR(IMG_HANDLE hMISRData)
 {
-	NOT_IMPLEMENTED();
-	return PVRSRV_ERROR_NOT_SUPPORTED;
+	auto misr_handle = reinterpret_cast<msd_img::MisrHandle *>(hMISRData);
+	if (misr_handle->event.signal(0, ZX_USER_SIGNAL_0) != ZX_OK)
+	{
+		DLOG("Failed to signal MISR on shutdown");
+		misr_handle->thread.detach();
+	}
+	else
+	{
+		misr_handle->thread.join();
+	}
+	delete misr_handle;
+	return PVRSRV_OK;
 }
 
-/*
-	OSScheduleMISR
-*/
 PVRSRV_ERROR
 OSScheduleMISR(IMG_HANDLE hMISRData)
 {
-	NOT_IMPLEMENTED();
-	return PVRSRV_ERROR_NOT_SUPPORTED;
+	auto misr_handle = reinterpret_cast<msd_img::MisrHandle *>(hMISRData);
+	return ZxStatusToError(misr_handle->event.signal(0, ZX_EVENT_SIGNALED));
 }
 
 PVRSRV_ERROR