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; } } }
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); }
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); }
// 为删除录像而停止录像服务 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(); }
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; } }
void ServerJoin(Server* server) { if (server != NULL) { if (server->thread != NULL) { ThreadJoin(server->thread); } aio4c_free(server); } }
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; }
int main(){ int i; ThreadId tid = ThreadFork(test, 2); ThreadJoin(tid); for(i = 0; i < 10; i++){ PrintStr("loop in main() \n"); } }
/********************************************************** * 停止录像模块的所有线程 ***********************************************************/ 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 ); } }
void ThreadPool::Stop() { { MutexLock l(&m_); stop_ = true; } has_tasks_.SignalAll(); for(int i = 0; i<nthreads_; i++) ThreadJoin(tids_[i]); }
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 ); } }
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 ); } }
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; } }
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); }
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; }
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); }
///===================================================== /// ///===================================================== void Thread::Join(){ if (m_handle != nullptr) { ThreadJoin(m_handle); m_handle = nullptr; } }
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 }
void ClTimer::WaitTimerThreadQuit() { m_TimerQuit = 1; ThreadJoin( m_TimerThreadID, NULL ); }
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; }
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; }
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; }