Example #1
0
VOID
PdoDestroy(
    IN  PXENFILT_PDO    Pdo
    )
{
    PDEVICE_OBJECT      LowerDeviceObject = Pdo->LowerDeviceObject;
    PXENFILT_DX         Dx = Pdo->Dx;
    PDEVICE_OBJECT      FilterDeviceObject = Dx->DeviceObject;

    ASSERT3U(__PdoGetDevicePnpState(Pdo), ==, Deleted);

    ASSERT(__PdoIsMissing(Pdo));
    Pdo->Missing = FALSE;

    __PdoUnlink(Pdo);

    Info("%p (%s) (%s)\n",
         FilterDeviceObject,
         __PdoGetName(Pdo),
         Pdo->Reason);
    Pdo->Reason = NULL;

    Dx->Pdo = NULL;

    EmulatedRemoveObject(__PdoGetEmulatedInterface(Pdo),
                         Pdo->EmulatedObject);
    Pdo->EmulatedObject = NULL;
    Pdo->EmulatedInterface = NULL;

    ThreadAlert(Pdo->DevicePowerThread);
    ThreadJoin(Pdo->DevicePowerThread);
    Pdo->DevicePowerThread = NULL;

    ThreadAlert(Pdo->SystemPowerThread);
    ThreadJoin(Pdo->SystemPowerThread);
    Pdo->SystemPowerThread = NULL;

    Pdo->PhysicalDeviceObject = NULL;
    Pdo->LowerDeviceObject = NULL;
    Pdo->Dx = NULL;

    IoDetachDevice(LowerDeviceObject);

    ASSERT(IsZeroMemory(Pdo, sizeof (XENFILT_PDO)));
    __PdoFree(Pdo);

    IoDeleteDevice(FilterDeviceObject);
}
void WdtServiceStop()
{
	int ret;
    
	g_WdtTm.runFlag = 0;
    
	ret = ThreadJoin( g_WdtTm.id, NULL );
	if( 0 != ret )
    {
    	ERRORPRINT( "error:ThreadJoin:%s\r\n", STRERROR_ERRNO );
    }

    if(g_wdt_fd > 0)
    {
        ret = close(g_wdt_fd);
        if(ret < 0)
        {
            ERRORPRINT("watch dog driver close failed!\n");
        }
        else
        {
            g_wdt_fd = -1;
        }
    }
}
Example #3
0
void ReaderEnd(Reader* reader) {
    if (reader->thread != NULL) {
        if (reader->queue != NULL) {
            EnqueueExitItem(reader->queue);
        }

        if (reader->selector != NULL) {
            SelectorWakeUp(reader->selector);
        }

        ThreadJoin(reader->thread);
    }

    FreeSelector(&reader->selector);

    if (reader->name != NULL) {
        aio4c_free(reader->name);
    }

    if (reader->pipe != NULL) {
        aio4c_free(reader->pipe);
    }

    aio4c_free(reader);
}
Example #4
0
  void BuildQueueDestroy(BuildQueue* queue)
  {
    Log(kDebug, "destroying build queue");
    const BuildQueueConfig* config = &queue->m_Config;

    MutexLock(&queue->m_Lock);
    queue->m_QuitSignalled = true;
    MutexUnlock(&queue->m_Lock);

    CondBroadcast(&queue->m_WorkAvailable);

    for (int i = 0, thread_count = config->m_ThreadCount; i < thread_count; ++i)
    {
      if (i > 0)
      {
        Log(kDebug, "joining with build thread %d", i);
        ThreadJoin(queue->m_Threads[i]);
      }

      ThreadStateDestroy(&queue->m_ThreadState[i]);
    }

    // Deallocate storage.
    MemAllocHeap* heap = queue->m_Config.m_Heap;
    HeapFree(heap, queue->m_ExpensiveWaitList);
    HeapFree(heap, queue->m_Queue);

    CondDestroy(&queue->m_WorkAvailable);
    MutexDestroy(&queue->m_Lock);

    // Unblock all signals on the main thread.
    SignalHandlerSetCondition(nullptr);
    SignalBlockThread(false);
  }
Example #5
0
// 为删除录像而停止录像服务
void RecordStopServiceForDel()
{
	int chNum = REAL_CHANNEL_NUM;
	int i;
	rec_manage.recordManageRunFlag = 0;    
	if(0 != ThreadJoin(rec_manage.recordManageId,NULL))
    {
    	SVPrint("error:ThreadJoin(rec_manage.recordManageId,NULL)\r\n");
    }

	for(i=0;i<chNum;i++)
    {
    	if(REC_SLEEP != GetRecordCtlFlag(i))
        {
        	SetRecordCtlFlag( i, REC_STOP );
        	RecordPoolSignal( i );
        }
    }
    
	for(i=0;i<chNum;i++)
    {
    	while(REC_SLEEP != GetRecordCtlFlag(i))
        {
        	Usleep(50);
        }
    }
    
	sync();    
}
Example #6
0
		void TManager::ThreadDelete( troutine tr ) {
			ThreadJoin(tr);

			Thread *thr = threads[tr];
			delete thr;
			threads.erase(tr);
		}
//---------------------------------------------------------------------------
void TSnapThread::Join() 
{
    if (Started && !Closed)
    {
        ThreadJoin();
        Closed = true;
    }
}
Example #8
0
void ServerJoin(Server* server) {
    if (server != NULL) {
        if (server->thread != NULL) {
            ThreadJoin(server->thread);
        }
        aio4c_free(server);
    }
}
Example #9
0
bool CThread::Join(unsigned timeout)
{
#ifdef _WIN32
	if ( m_hThread )
#elif _LINUX
	if ( m_threadId )
#endif
	{
		AssertMsg(GetCurrentCThread() != this, _T("Thread cannot be joined with self"));

#ifdef _WIN32
		return ThreadJoin( (ThreadHandle_t)m_hThread );
#elif _LINUX
		return ThreadJoin( (ThreadHandle_t)m_threadId );
#endif
	}
	return true;
}
Example #10
0
int main(){
  int i;
  ThreadId tid = ThreadFork(test, 2);
  ThreadJoin(tid);

  for(i = 0; i < 10; i++){
    PrintStr("loop in main() \n");
  }
}
Example #11
0
/**********************************************************
* 停止录像模块的所有线程
***********************************************************/
void FiRecStopRecordService(void)
{
	int chNum = REAL_CHANNEL_NUM;
	int i;    
    
	rec_manage.recordManageRunFlag = 0;    
	if(0 != ThreadJoin(rec_manage.recordManageId,NULL))
    {
    	SVPrint("error:ThreadJoin(rec_manage.recordManageId,NULL)\r\n");
    }

	for(i=0;i<chNum;i++)
    {
    	if(REC_SLEEP != GetRecordCtlFlag(i))
        {
        	SetRecordCtlFlag(i,REC_STOP);            
        	RecordPoolSignal( i );
        }
    }
	for( i=0; i<chNum; i++ )
    {
    	while(REC_SLEEP != GetRecordCtlFlag(i))
        {
        	Usleep(50);
        }
    }
    
	for( i=0; i<chNum; i++ )
    {
    	rec_thread[i].recordThreadRunFlag = 0;            
    }
    
	for( i=0; i<chNum; i++ )
    {
    	if( 0 != ThreadJoin( rec_thread[i].recordThreadId, NULL) )
        {
        	SVPrint("ThreadJoin(rec_thread[%d].recordThreadId,NULL)\r\n",i);
        }
    }
    
	StopRecordGetH264Thread();
	FiRecDelRecordInit();
	return;
}
void StopRecordGetH264Thread()
{
	int ret;
	g_recordGetH264Tm.runFlag = 0;
	ret = ThreadJoin( g_recordGetH264Tm.id, NULL );
	if( 0 != ret )
    {
    	SVPrint( "error:ThreadJoin:%s\r\n", STRERROR_ERRNO );
    }
}
Example #13
0
void ThreadPool::Stop()
{
	{
		MutexLock l(&m_);
		stop_ = true;
	}
	has_tasks_.SignalAll();
	for(int i = 0; i<nthreads_; i++)
		ThreadJoin(tids_[i]);
}
Example #14
0
void StopSnapJpgThread()
{
	int ret;
	g_snapJpgTm.runFlag = 0;
	ret = ThreadJoin( g_snapJpgTm.id, NULL );
	if( 0 != ret )
    {
    	SVPrint( "error:ThreadJoin:%s\r\n", STRERROR_ERRNO );
    }
}
Example #15
0
void StopDtuAppThread()
{
	int ret;
	g_dtuAppTm.runFlag = 0;
	g_dtuWorkCondition.Signal();
	ret = ThreadJoin( g_dtuAppTm.id, NULL );
	if( 0 != ret )
    {
    	SVPrint( "error:ThreadJoin:%s\r\n", STRERROR_ERRNO );
    }
}
Example #16
0
File: Os.c Project: astaykov/ohNet
static void DestroyInterfaceChangedObserver_Linux()
{
    if (gInterfaceChangedObserver != NULL) {
        if (gInterfaceChangedObserver->iThread != NULL) {
            OsNetworkInterrupt(gInterfaceChangedObserver->netHnd, 1);
            ThreadJoin(gInterfaceChangedObserver->iThread);
            OsThreadDestroy(gInterfaceChangedObserver->iThread);
        }
                   
        OsNetworkClose(gInterfaceChangedObserver->netHnd);

        free(gInterfaceChangedObserver);
        gInterfaceChangedObserver = NULL;
    }
}
Example #17
0
void WorkerEnd(Worker* worker) {
    if (worker->thread != NULL) {
        if (worker->queue != NULL) {
            EnqueueExitItem(worker->queue);
        }

        ThreadJoin(worker->thread);
    }

    if (worker->name != NULL) {
        aio4c_free(worker->name);
    }

    aio4c_free(worker);
}
Example #18
0
static void DestroyInterfaceChangedObserver_Linux(OsContext* aContext)
{
    if (aContext->iInterfaceChangedObserver != NULL) {
        if (aContext->iInterfaceChangedObserver->iThread != NULL) {
            OsNetworkInterrupt(aContext->iInterfaceChangedObserver->netHnd, 1);
            ThreadJoin(aContext->iInterfaceChangedObserver->iThread);
            OsThreadDestroy(aContext->iInterfaceChangedObserver->iThread);
        }
                   
        OsNetworkClose(aContext->iInterfaceChangedObserver->netHnd);

        free(aContext->iInterfaceChangedObserver);
        aContext->iInterfaceChangedObserver = NULL;
    }
}
Matrix thrd_centerthenproject(Subspace *s, Matrix images) {
  int t;
  int chunk;
  int remainder;
  int start;
  int end;
#if (NUM_THREADS>1)
  pthread_attr_t attr;
  int rc;

  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

  thrd_barrier = thread_barrier_init(NUM_THREADS);
#endif

  subspims = makeMatrix(s->basis->col_dim, images->col_dim);

  for(t=0; t < NUM_THREADS; t++) {
    
    thrd_data_array[t].id = t;
    
    thrd_data_array[t].images = images;
    thrd_data_array[t].s = s;
    thrd_data_array[t].subspims = subspims;
    
#if (NUM_THREADS>1)
    /* create threads */
    if (t!=NUM_THREADS-1) {
      rc = pthread_create(&thread[t], &attr, main_thrd_work, 
			  (void*) &thrd_data_array[t]); 
      if (rc) {
	printf("ERROR; return code from pthread_create() is %d\n", rc);
	exit(-1);
      }
    }
#endif
  }

#if (NUM_THREADS>1)
  /* Free attribute and wait for the other threads */
  pthread_attr_destroy(&attr);
#endif

  main_thrd_work(&thrd_data_array[NUM_THREADS-1]);
  ThreadJoin();
  return subspims;
}
Example #20
0
	void WorkerThread::Unmake()
	{
		//BOOST_LOG( gn_log::get() ) << "(Concurrent) \tWorker[ " << Index_ << " ] joining...\n";
		LogInfo("WorkerThread[%i] joining...", Index_);
		
		if(Index_ != 0)
		{
			//Thread_.join();
			ThreadJoin(Thread_.get());
		}
		else
			LocalWorkerThread_ = nullptr;
			//ThisThread_.release();
		

		Tasks_.swap( std::vector<TaskBase *>() );	// force deallocation of the task vector
		TaskMutex_.reset();
		Pool_ = nullptr;
		Index_ = static_cast<uint32>(-1);
	}
Example #21
0
///=====================================================
/// 
///=====================================================
void Thread::Join(){
	if (m_handle != nullptr) {
		ThreadJoin(m_handle);
		m_handle = nullptr;
	}
}
Example #22
0
FloatBitMap_t *FloatBitMap_t::ComputeSelfShadowedBumpmapFromHeightInAlphaChannel(
	float bump_scale, int nrays_to_trace_per_pixel, 
	uint32 nOptionFlags ) const
{

	// first, add all the triangles from the height map to the "world".
	// we will make multiple copies to handle wrapping
	int tcnt = 1;

	Vector * verts;
	Vector * normals;
	ComputeVertexPositionsAndNormals( bump_scale, & verts, & normals );

	RayTracingEnvironment rtEnv;
	rtEnv.Flags |= RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS;	// save some ram

	if ( nrays_to_trace_per_pixel )
	{
		rtEnv.MakeRoomForTriangles( ( 1 + 2 * NREPS_TILE ) * ( 1 + 2 * NREPS_TILE ) * 2 * Height * Width );

		// now, add a whole mess of triangles to trace against
		for( int tilex =- NREPS_TILE; tilex <= NREPS_TILE; tilex++ )
			for( int tiley =- NREPS_TILE; tiley <= NREPS_TILE; tiley++ )
			{
				int min_x = 0;
				int max_x = Width - 1;
				int min_y = 0;
				int max_y = Height - 1;
				if ( tilex < 0 )
					min_x = Width / 2;
				if ( tilex > 0 )
					max_x = Width / 2;
				if ( tiley < 0 )
					min_y = Height / 2;
				if ( tiley > 0 )
					max_y = Height / 2;
				for( int y = min_y; y <= max_y; y++ )
					for( int x = min_x; x <= max_x; x++ )
					{
						Vector ofs( tilex * Width, tiley * Height, 0 );
						int x1 = ( x + 1 ) % Width;
						int y1 = ( y + 1 ) % Height;
						Vector v0 = verts[x + y * Width];
						Vector v1 = verts[x1 + y * Width];
						Vector v2 = verts[x1 + y1 * Width];
						Vector v3 = verts[x + y1 * Width];
						v0.x = x; v0.y = y;
						v1.x = x + 1; v1.y = y;
						v2.x = x + 1; v2.y = y + 1;
						v3.x = x; v3.y = y + 1;
						v0 += ofs; v1 += ofs; v2 += ofs; v3 += ofs;
						rtEnv.AddTriangle( tcnt++, v0, v1, v2, Vector( 1, 1, 1 ) );
						rtEnv.AddTriangle( tcnt++, v0, v3, v2, Vector( 1, 1, 1 ) );
					}
			}
		//printf("added %d triangles\n",tcnt-1);
		ReportProgress("Creating kd-tree",0,0);
		rtEnv.SetupAccelerationStructure();
		// ok, now we have built a structure for ray intersection. we will take advantage
		// of the SSE ray tracing code by intersecting rays as a batch.
	}

	// We need to calculate for each vertex (i.e. pixel) of the heightmap, how "much" of the world
	// it can see in each basis direction. we will do this by sampling a sphere of rays around the
	// vertex, and using dot-product weighting to measure the lighting contribution in each basis
	// direction.  note that the surface normal is not used here. The surface normal will end up
	// being reflected in the result because of rays being blocked when they try to pass through
	// the planes of the triangles touching the vertex.

	// note that there is no reason inter-bounced lighting could not be folded into this
	// calculation.

	FloatBitMap_t * ret = new FloatBitMap_t( Width, Height );


	Vector *trace_directions=new Vector[nrays_to_trace_per_pixel];
	DirectionalSampler_t my_sphere_sampler;
	for( int r=0; r < nrays_to_trace_per_pixel; r++)
	{
		Vector trace_dir=my_sphere_sampler.NextValue();
//		trace_dir=Vector(1,0,0);
		trace_dir.z=fabs(trace_dir.z);						// upwards facing only
		trace_directions[ r ]= trace_dir;
	}

	volatile SSBumpCalculationContext ctxs[32];
	ctxs[0].m_pRtEnv =& rtEnv;
	ctxs[0].ret_bm = ret;
	ctxs[0].src_bm = this;
	ctxs[0].nrays_to_trace_per_pixel = nrays_to_trace_per_pixel;
	ctxs[0].bump_scale = bump_scale;
	ctxs[0].trace_directions = trace_directions;
	ctxs[0].normals = normals;
	ctxs[0].min_y = 0;
	ctxs[0].max_y = Height - 1;
	ctxs[0].m_nOptionFlags = nOptionFlags;
	int nthreads = min( 32, GetCPUInformation().m_nPhysicalProcessors );

	ThreadHandle_t waithandles[32];
	int starty = 0;
	int ystep = Height / nthreads;
	for( int t = 0;t < nthreads; t++ )
	{
		if ( t )
			memcpy( (void * ) ( & ctxs[t] ), ( void * ) & ctxs[0], sizeof( ctxs[0] ));
		ctxs[t].thread_number = t;
		ctxs[t].min_y = starty;
		if ( t != nthreads - 1 )
			ctxs[t].max_y = min( Height - 1, starty + ystep - 1 );
		else
			ctxs[t].max_y = Height - 1;
		waithandles[t]= CreateSimpleThread( SSBumpCalculationThreadFN, ( SSBumpCalculationContext * ) & ctxs[t] );
		starty += ystep;
	}
	for(int t=0;t<nthreads;t++)
	{
		ThreadJoin( waithandles[t] );
	}
	if ( nOptionFlags & SSBUMP_MOD2X_DETAIL_TEXTURE )
	{
		const float flOutputScale = 0.5 * ( 1.0 / .57735026 ); // normalize so that a flat normal yields 0.5
		// scale output weights by color channel
		for( int nY = 0; nY < Height; nY++ )
			for( int nX = 0; nX < Width; nX++ )
			{
				float flScale = flOutputScale * (2.0/3.0) * ( Pixel( nX, nY, 0 ) + Pixel( nX, nY, 1 ) + Pixel( nX, nY, 2 ) );
				ret->Pixel( nX, nY, 0 ) *= flScale;
				ret->Pixel( nX, nY, 1 ) *= flScale;
				ret->Pixel( nX, nY, 2 ) *= flScale;
			}
	}
	
	delete[] verts;
	delete[] trace_directions;
	delete[] normals;
	return ret;												// destructor will clean up rtenv
}
Example #23
0
void ClTimer::WaitTimerThreadQuit()
{
	m_TimerQuit	= 1;
	ThreadJoin( m_TimerThreadID, NULL );
}
Example #24
0
int main(int argc, char *argv[])
{
    GUITHREAD thdFb = -1;
    GUITHREAD thdKeypad = -1;
    GUITHREAD thdTouch = -1;

    GUIWINDOW *pWnd = NULL;

    int iExit = 0;

    //初始化设备驱动
    //InitializeDevice();

    //装载输入法数据库
    //OpenInputDb("/home/ubuntu/workspace/guilib/run/input/china.db");

    //初始化GUI环境,运行调度线程及事件封装线程
    InitializeGUI();

    //运行设备抽象层的线程
    ThreadCreate(&thdFb, NULL,
                 DefaultFbThread, GetCurrFbmap());
    //ThreadCreate(&thdKeypad, NULL,
    //             DefaultKeypadThread, GetCurrKeypad());
    ThreadCreate(&thdTouch, NULL,
                 DefaultTouchThread, GetCurrTouch());
	
    //第一个窗体线程运行
    pWnd = CreateWindow(0, 0, 800, 480,
                        FrmWiFiInit, FrmWiFiExit,
                        FrmWiFiPaint, FrmWiFiLoop,
                        FrmWiFiPause, FrmWiFiResume,
                        NULL);   //pWnd由调度线程释放
    SendSysMsg_ThreadCreate(pWnd);

    //等待结束标志设立
    while (!iExit)
    {
        iExit = GetExitFlag();
        if (iExit)
        {
            ThreadCancel(thdTouch);     //取消可能阻塞的触摸屏线程
            ThreadCancel(thdKeypad);    //取消可能阻塞的键盘线程
            ThreadCancel(thdFb);        //取消可能阻塞的帧缓冲线程
            break;
        }

        MsecSleep(100);
    }

    //回收设备抽象层的线程
    ThreadJoin(thdTouch, NULL);
    ThreadJoin(thdKeypad, NULL);
    ThreadJoin(thdFb, NULL);

    //释放GUI环境,回收事件封装线程及调度线程
    ReleaseGUI();

    //释放输入法数据库
    CloseInputDb();

    //释放设备驱动
    //ReleaseDevice();

    return 0;
}
Example #25
0
int main(int argc, char** argv)
{
	if (argc < 2)
		return usage(argc, argv);

	parent = pthread_self();
	sigset_t original, masking;
	sigemptyset(&original);
	sigemptyset(&masking);
	sigaddset(&masking, SIGUSR1);
	pthread_sigmask(SIG_SETMASK, &masking, &original);

	int wakeupThreads = 0;
	try
	{
		wakeupThreads = lexicalCast<int>(argv[argc-1]);
		if (wakeupThreads < 1)
			return usage(argc, argv);

		std::cout << "wakeup threads of " << wakeupThreads << std::endl;
	}
	catch (std::exception& e)
	{
		std::cerr << e.what() << std::endl;
		return usage(argc, argv);
	}

	void* handle = WWWInit();
	std::vector<Item> items = loadItems();
	resetItems(items);
	void* filterManagerContext = FilterManagerCreate(NULL);

	std::map<void*, void*> contextMap;
	

	// create threads.
	for (int count = 0; count != wakeupThreads; ++count)
	{
		std::vector<Item>::iterator itor = find_uncheck_item(items);
		if (itor == items.end())
			break;

		itor->check_flg = true;
		void* thread = ThreadCreate();
		void* httpContext = HTTPCreateContext(itor->url_check.c_str(),
											  NULL, NULL, 20);
		contextMap[thread] = httpContext;
		std::cout << "thread: " << thread <<
			"   context: " << httpContext << std::endl;
		ThreadStart(thread, httpContext, handler);
	}

	try
	{
		std::vector<Item>::iterator itor;
		while ((itor = find_uncheck_item(items)) != items.end())
		{
			itor->check_flg = true;
			
			int signalNum = 0;
			sigwait(&masking, &signalNum);
			if (signalNum == SIGUSR1)
			{
				// signal一回で複数の待ちハンドラを処理した方が良さそう
				ScopedLock<Mutex> lock(syncObject);
				assert (idleThreads.size() > 0);
				void* thread = idleThreads.back();
				idleThreads.pop_back();
				ThreadJoin(thread);

				void* httpContext = contextMap[thread];
				assert(httpContext != NULL);
				contextMap[thread] = NULL;

				{
					char url[2048];
					url[HTTPGetURL(httpContext, url, sizeof(url))] = 0;
					std::vector<Item>::iterator item_itor =
						find_item_from_url(items, url);

					if (item_itor == items.end())
						throw std::runtime_error((std::string("unfind URL: ") +
												  url).c_str());

					char date[256];
					date[HTTPGetLastModified(httpContext,
											 date, sizeof(date))] = 0;
					item_itor->last_updated = date;

					item_itor->crc32 = HTTPGetFilteredCRC32(httpContext,
													   filterManagerContext);
				
					item_itor->content_length =
						HTTPGetContentsLength(httpContext);

					HTTPClose(httpContext);
				}
				HTTPCreateContext(itor->url_check.c_str(),
								  NULL, NULL, 20);
				contextMap[thread] = httpContext;
				std::cout << "thread: " << thread <<
					"   context: " << httpContext << std::endl;
				ThreadStart(thread, httpContext, handler);
			}
		}

		// 稼働中のスレッドがwakeupThreads個存在する
		for (int count = 0; count != wakeupThreads; ++count)
		{
			int signalNum = 0;
			// signal一回で複数の待ちハンドラを処理した方が良さそう
			sigwait(&masking, &signalNum);
			ScopedLock<Mutex> lock(syncObject);
			ThreadClose(idleThreads.back());
			idleThreads.pop_back();
		}
	}
	catch (std::exception& e)
	{
		std::cerr << "raise exception: " << e.what() << std::endl;
	}
	catch (...)
	{
		std::cerr << "unknown exception raised." << std::endl;
	}

	saveItems(items);
	FilterManagerTerminate(filterManagerContext);
	WWWTerminate(handle);
	pthread_sigmask(SIG_SETMASK, &original, NULL);

	return 0;
}
Example #26
0
NTSTATUS
PdoCreate(
    PXENFILT_FDO                    Fdo,
    PDEVICE_OBJECT                  PhysicalDeviceObject,
    XENFILT_EMULATED_OBJECT_TYPE    Type
    )
{
    PDEVICE_OBJECT                  LowerDeviceObject;
    ULONG                           DeviceType;
    PDEVICE_OBJECT                  FilterDeviceObject;
    PXENFILT_DX                     Dx;
    PXENFILT_PDO                    Pdo;
    NTSTATUS                        status;

    LowerDeviceObject = IoGetAttachedDeviceReference(PhysicalDeviceObject);
    DeviceType = LowerDeviceObject->DeviceType;
    ObDereferenceObject(LowerDeviceObject);

#pragma prefast(suppress:28197) // Possibly leaking memory 'PhysicalDeviceObject'
    status = IoCreateDevice(DriverGetDriverObject(),
                            sizeof(XENFILT_DX),
                            NULL,
                            DeviceType,
                            FILE_DEVICE_SECURE_OPEN,
                            FALSE,
                            &FilterDeviceObject);
    if (!NT_SUCCESS(status))
        goto fail1;

    Dx = (PXENFILT_DX)FilterDeviceObject->DeviceExtension;
    RtlZeroMemory(Dx, sizeof (XENFILT_DX));

    Dx->Type = PHYSICAL_DEVICE_OBJECT;
    Dx->DeviceObject = FilterDeviceObject;
    Dx->DevicePnpState = Present;
    Dx->SystemPowerState = PowerSystemShutdown;
    Dx->DevicePowerState = PowerDeviceD3;

    IoInitializeRemoveLock(&Dx->RemoveLock, PDO_TAG, 0, 0);

    Pdo = __PdoAllocate(sizeof (XENFILT_PDO));

    status = STATUS_NO_MEMORY;
    if (Pdo == NULL)
        goto fail2;

    LowerDeviceObject = IoAttachDeviceToDeviceStack(FilterDeviceObject,
                                                    PhysicalDeviceObject);

    status = STATUS_UNSUCCESSFUL;
    if (LowerDeviceObject == NULL)
        goto fail3;

    Pdo->Dx = Dx;
    Pdo->PhysicalDeviceObject = PhysicalDeviceObject;
    Pdo->LowerDeviceObject = LowerDeviceObject;

    status = ThreadCreate(PdoSystemPower, Pdo, &Pdo->SystemPowerThread);
    if (!NT_SUCCESS(status))
        goto fail4;

    status = ThreadCreate(PdoDevicePower, Pdo, &Pdo->DevicePowerThread);
    if (!NT_SUCCESS(status))
        goto fail5;

    Pdo->EmulatedInterface = FdoGetEmulatedInterface(Fdo);

    status = EmulatedAddObject(__PdoGetEmulatedInterface(Pdo),
                               Type,
                               FdoGetPrefix(Fdo),
                               Pdo->LowerDeviceObject,
                               &Pdo->EmulatedObject);
    if (!NT_SUCCESS(status))
        goto fail6;

    __PdoSetName(Pdo);

    Info("%p (%s)\n",
          FilterDeviceObject,
          __PdoGetName(Pdo));

    Dx->Pdo = Pdo;

#pragma prefast(suppress:28182) // Dereferencing NULL pointer
    FilterDeviceObject->DeviceType = LowerDeviceObject->DeviceType;
    FilterDeviceObject->Characteristics = LowerDeviceObject->Characteristics;

    FilterDeviceObject->Flags |= LowerDeviceObject->Flags;
    FilterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    __PdoLink(Pdo, Fdo);

    return STATUS_SUCCESS;

fail6:
    Error("fail6\n");

    ThreadAlert(Pdo->DevicePowerThread);
    ThreadJoin(Pdo->DevicePowerThread);
    Pdo->DevicePowerThread = NULL;

fail5:
    Error("fail5\n");

    ThreadAlert(Pdo->SystemPowerThread);
    ThreadJoin(Pdo->SystemPowerThread);
    Pdo->SystemPowerThread = NULL;

fail4:
    Error("fail4\n");

    Pdo->PhysicalDeviceObject = NULL;
    Pdo->LowerDeviceObject = NULL;
    Pdo->Dx = NULL;

    IoDetachDevice(LowerDeviceObject);

fail3:
    Error("fail3\n");

    ASSERT(IsZeroMemory(Pdo, sizeof (XENFILT_PDO)));
    __PdoFree(Pdo);

fail2:
    Error("fail2\n");

    IoDeleteDevice(FilterDeviceObject);

fail1:
    Error("fail1 (%08x)\n", status);

    return status;
}