void kscrashsentry_uninstallMachHandler(void) { KSLOG_DEBUG("Uninstalling mach exception handler."); if(!g_installed) { KSLOG_DEBUG("Mach exception handler was already uninstalled."); return; } // NOTE: Do not deallocate the exception port. If a secondary crash occurs // it will hang the process. ksmachexc_i_restoreExceptionPorts(); thread_t thread_self = ksmach_thread_self(); if(g_primaryPThread != 0 && g_primaryMachThread != thread_self) { KSLOG_DEBUG("Cancelling primary exception thread."); if(g_context->handlingCrash) { thread_terminate(g_primaryMachThread); } else { pthread_cancel(g_primaryPThread); } g_primaryMachThread = 0; g_primaryPThread = 0; } if(g_secondaryPThread != 0 && g_secondaryMachThread != thread_self) { KSLOG_DEBUG("Cancelling secondary exception thread."); if(g_context->handlingCrash) { thread_terminate(g_secondaryMachThread); } else { pthread_cancel(g_secondaryPThread); } g_secondaryMachThread = 0; g_secondaryPThread = 0; } KSLOG_DEBUG("Mach exception handlers uninstalled."); g_installed = 0; }
/* virtual */ void IOWorkLoop::threadMain() { restartThread: do { if ( !runEventSources() ) goto exitThread; IOInterruptState is = IOSimpleLockLockDisableInterrupt(workToDoLock); if ( !ISSETP(&fFlags, kLoopTerminate) && !workToDo) { assert_wait((void *) &workToDo, false); IOSimpleLockUnlockEnableInterrupt(workToDoLock, is); thread_continue_t cptr = NULL; if (!reserved || !(kPreciousStack & reserved->options)) cptr = OSMemberFunctionCast( thread_continue_t, this, &IOWorkLoop::threadMain); thread_block_parameter(cptr, this); goto restartThread; /* NOTREACHED */ } // At this point we either have work to do or we need // to commit suicide. But no matter // Clear the simple lock and retore the interrupt state IOSimpleLockUnlockEnableInterrupt(workToDoLock, is); } while(workToDo); exitThread: thread_t thread = workThread; workThread = 0; // Say we don't have a loop and free ourselves free(); thread_deallocate(thread); (void) thread_terminate(thread); }
error_t setup_thread_target (void) { error_t err; static task_t task; static thread_t thread; if (MACH_PORT_VALID (thread)) { thread_terminate (thread); mach_port_deallocate (mach_task_self (), thread); } if (MACH_PORT_VALID (task)) { task_terminate (task); mach_port_deallocate (mach_task_self (), task); } err = task_create (mach_task_self (), 0, &task); if (err) return err; err = thread_create (task, &thread); if (err) return err; return setup (thread, MACH_MSG_TYPE_COPY_SEND); }
void profile_enable( bool enable ) { bool was_enabled = ( _profile_enable > 0 ); bool is_enabled = enable; if( is_enabled && !was_enabled ) { _profile_enable = 1; //Start output thread _profile_io_thread = thread_create( _profile_io, "profile_io", THREAD_PRIORITY_BELOWNORMAL, 0 ); thread_start( _profile_io_thread, 0 ); while( !thread_is_running( _profile_io_thread ) ) thread_yield(); } else if( !is_enabled && was_enabled ) { //Stop output thread thread_terminate( _profile_io_thread ); thread_destroy( _profile_io_thread ); while( thread_is_running( _profile_io_thread ) ) thread_yield(); _profile_enable = 0; } }
/* ----------------------------------------------------------------------------- L2TP Timer, at 500 ms. Replaces l2tp_slowtimo, which is deprecated. ----------------------------------------------------------------------------- */ static uint8_t l2tp_timer_thread_is_dying = 0; /* > 0 if dying */ static uint8_t l2tp_timer_thread_is_dead = 0; /* > 0 if dead */ static void l2tp_timer() { struct timespec ts = {0}; /* timeout of 500 ms */ ts.tv_nsec = 500 * 1000 * 1000; ts.tv_sec = 0; lck_mtx_lock(ppp_domain_mutex); while (TRUE) { if (l2tp_timer_thread_is_dying > 0) { break; } l2tp_rfc_slowtimer(); msleep(&l2tp_timer_thread_is_dying, ppp_domain_mutex, PSOCK, "l2tp_timer_sleep", &ts); } l2tp_timer_thread_is_dead++; wakeup(&l2tp_timer_thread_is_dead); lck_mtx_unlock(ppp_domain_mutex); thread_terminate(current_thread()); }
/* * Thread 1 - Priority = 100 */ static void thread_1(void) { int error; printf("thread_1: starting\n"); /* * 2) Lock mutex B */ printf("thread_1: 2) lock B\n"); error = mutex_lock(&mtx_B); if (error) printf("error=%d\n", error); /* * 3) Lock mutex A * * Switch to thread 1. */ printf("thread_1: 3) lock A\n"); error = mutex_lock(&mtx_A); if (error) printf("error=%d\n", error); printf("thread_1: exit\n"); thread_terminate(th_1); }
/* * Thread 2 - Priority = 101 */ static void thread_2(void) { int error; printf("thread_2: starting\n"); /* * 1) Lock mutex A */ printf("thread_2: 1) lock A\n"); error = mutex_lock(&mtx_A); if (error) printf("error=%d\n", error); /* * Switch to thread 1 */ thread_resume(th_1); printf("thread_2: running\n"); /* * 4) Lock mutex B * * Deadlock occurs here! */ printf("thread_2: 4) lock B\n"); error = mutex_lock(&mtx_B); if (error) printf("error=%d\n", error); if (error == EDEADLK) printf("**** DEADLOCK!! ****\n"); printf("thread_2: exit\n"); thread_terminate(th_2); }
/* * The main routine create 10 copy of this thread. But, since the * initial semaphore value is 3, only 3 threads can run at same time. */ static void new_thread(void) { thread_t t; t = thread_self(); printf("Start thread=%x\n", (u_int)t); thread_yield(); /* * Acquire semaphore */ sem_wait(&sem, 0); /* * Sleep 2000 ms */ printf("Running thread=%x\n", (u_int)t); timer_sleep(2000, 0); /* * Release semaphore */ sem_post(&sem); printf("End thread=%x\n", (u_int)t); thread_terminate(t); }
int thread_cleanup(thread_t thread, unsigned int seconds) { int rc; rc = thread_join(thread, seconds); switch( rc ) { case WAIT_OBJECT_0: // Everything OK! Thread exited #ifdef WIN32 CloseHandle( thread ); #endif return 0; break; case WAIT_TIMEOUT: // Damn! Should be closed by now... Force it! #ifndef WIN32 pthread_detach( thread ); #endif rc = thread_terminate( thread ); #ifdef WIN32 if( rc == 0 ) CloseHandle( thread ); #endif return rc; break; default: // WTF??? Something went really wrong. fatal("Something went REALLY wrong while waiting for a thread to complete!\n"); } return rc; }
static void read_thread(void) { int rc; memset(read_buf, 0, BUF_SIZE); syslog(LOG_INFO, "read_thread:\n read1..."); if ((rc = read(rd_fd, read_buf, RD1_SIZE)) < 0) err(1, "read1 %d", RD1_SIZE); else if (rc != RD1_SIZE) errx(1, "read1 %d, expected %d", rc, RD1_SIZE); syslog(LOG_INFO, "read1 ok\n read2..."); if ((rc = read(rd_fd, read_buf + RD1_SIZE, RD2_SIZE)) < 0) err(1, "read2 %d", RD2_SIZE); else if (rc != RD2_SIZE) errx(1, "read2 %d, expected %d", rc, RD2_SIZE); syslog(LOG_INFO, "read2 ok\n close..."); if (close(rd_fd) < 0) err(1, "close(%d)", rd_fd); syslog(LOG_INFO, "read close ok\n read thread_terminate\n"); thread_terminate(thread_self()); }
extern "C" void Start(Baton *baton) { struct _pthread self; $bzero(&self, sizeof(self)); const mach_header_xx *pthread(Library(baton, "/usr/lib/system/libsystem_pthread.dylib")); if (pthread == NULL) pthread = Library(baton, "/usr/lib/system/libsystem_c.dylib"); void (*$__pthread_set_self)(pthread_t); cyset($__pthread_set_self, "___pthread_set_self", pthread); self.tsd[0] = &self; $__pthread_set_self(&self); int (*$pthread_create)(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); cyset($pthread_create, "_pthread_create", pthread); pthread_t thread; $pthread_create(&thread, NULL, &Routine, baton); const mach_header_xx *kernel(Library(baton, "/usr/lib/system/libsystem_kernel.dylib")); mach_port_t (*$mach_thread_self)(); cyset($mach_thread_self, "_mach_thread_self", kernel); kern_return_t (*$thread_terminate)(thread_act_t); cyset($thread_terminate, "_thread_terminate", kernel); $thread_terminate($mach_thread_self()); }
void gdb_pthread_kill(pthread_t pthread) { mach_port_t mthread; kern_return_t kret; int ret; mthread = pthread_mach_thread_np(pthread); kret = thread_suspend(mthread); MACH_CHECK_ERROR(kret); ret = pthread_cancel(pthread); if (ret != 0) { /* in case a macro has re-defined this function: */ #undef strerror warning("Unable to cancel thread: %s (%d)", strerror(errno), errno); thread_terminate(mthread); } kret = thread_abort (mthread); MACH_CHECK_ERROR (kret); kret = thread_resume (mthread); MACH_CHECK_ERROR (kret); ret = pthread_join (pthread, NULL); if (ret != 0) { warning ("Unable to join to canceled thread: %s (%d)", strerror (errno), errno); } }
DECLARE_TEST( mutex, sync ) { mutex_t* mutex; object_t thread[32]; int ith; mutex = mutex_allocate( "test" ); mutex_lock( mutex ); for( ith = 0; ith < 32; ++ith ) { thread[ith] = thread_create( mutex_thread, "mutex_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread[ith], mutex ); } test_wait_for_threads_startup( thread, 32 ); for( ith = 0; ith < 32; ++ith ) { thread_terminate( thread[ith] ); thread_destroy( thread[ith] ); } mutex_unlock( mutex ); test_wait_for_threads_exit( thread, 32 ); mutex_deallocate( mutex ); EXPECT_EQ( thread_counter, 32 * 128 ); return 0; }
void attack(void) { object_t *objp = (object_t *)random(); object_t obj = (object_t)random(); char *name = (char *)random(); void *msg = (void *)random(); size_t size = (size_t)random(); task_t self = task_self(); void *addr = (void *)random(); int attr = random() & 7; thread_t t = (thread_t)random(); thread_t *tp = (thread_t *)random(); object_create(NULL, NULL); object_create(NULL, objp); object_create(name, NULL); object_create(name, objp); object_destroy(0); object_destroy(obj); object_lookup(NULL, objp); object_lookup(name, NULL); object_lookup(name, objp); msg_send(0, msg, size); msg_send(obj, NULL, size); msg_send(obj, msg, 0); msg_send(0, msg, 0); msg_send(0, NULL, size); msg_send(obj, msg, size); msg_receive(0, msg, size); msg_receive(obj, NULL, size); msg_receive(obj, msg, 0); msg_receive(0, msg, 0); msg_receive(0, NULL, size); msg_receive(obj, msg, size); msg_reply(0, msg, size); msg_reply(obj, NULL, size); msg_reply(obj, msg, 0); msg_reply(0, msg, 0); msg_reply(0, NULL, size); msg_reply(obj, msg, size); vm_allocate(self, addr, size, 1); vm_allocate(self, &addr, size, 1); vm_free(self, addr); vm_attribute(self, addr, attr); vm_map(self, addr, size, &addr); thread_create(self, tp); thread_suspend(t); thread_terminate(t); }
static void test_run( void ) { unsigned int ig, gsize, ic, csize; void* result = 0; #if !BUILD_MONOLITHIC object_t thread_event = 0; #endif log_infof( HASH_TEST, "Running test suite: %s", test_suite.application().short_name ); _test_failed = false; #if !BUILD_MONOLITHIC thread_event = thread_create( test_event_thread, "event_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread_event, 0 ); while( !thread_is_running( thread_event ) ) thread_yield(); #endif for( ig = 0, gsize = array_size( _test_groups ); ig < gsize; ++ig ) { log_infof( HASH_TEST, "Running tests from group %s", _test_groups[ig]->name ); for( ic = 0, csize = array_size( _test_groups[ig]->cases ); ic < csize; ++ic ) { log_infof( HASH_TEST, " Running %s tests", _test_groups[ig]->cases[ic]->name ); result = _test_groups[ig]->cases[ic]->fn(); if( result != 0 ) { log_warn( HASH_TEST, WARNING_SUSPICIOUS, " FAILED" ); _test_failed = true; } else { log_info( HASH_TEST, " PASSED" ); } #if BUILD_MONOLITHIC if( _test_should_terminate ) { _test_failed = true; goto exit; } #endif } } #if !BUILD_MONOLITHIC thread_terminate( thread_event ); thread_destroy( thread_event ); while( thread_is_running( thread_event ) || thread_is_thread( thread_event ) ) thread_yield(); #else exit: #endif log_infof( HASH_TEST, "Finished test suite: %s", test_suite.application().short_name ); }
inline void myExitThread(THREAD_T *thread) { THREAD_T thread_ptr = *thread; *thread = NULL; thread_deallocate(thread_ptr); thread_terminate(thread_ptr); }
int main(int argc, char *argv[]) { struct timerinfo info; task_t task; char stack[16]; u_long start, end; int i, pri, error; printf("Benchmark to create/terminate %d threads\n", NR_THREADS); sys_info(INFO_TIMER, &info); if (info.hz == 0) panic("can not get timer tick rate"); thread_getpri(thread_self(), &pri); thread_setpri(thread_self(), pri - 1); task = task_self(); error = vm_allocate(task, (void **)&thread, sizeof(thread_t) * NR_THREADS, 1); if (error) panic("vm_allocate is failed"); sys_time(&start); /* * Create threads */ for (i = 0; i < NR_THREADS; i++) { if (thread_create(task, &thread[i]) != 0) panic("thread_create is failed"); if (thread_load(thread[i], null_thread, &stack) != 0) panic("thread_load is failed"); if (thread_resume(thread[i]) != 0) panic("thread_resume is failed"); } /* * Teminate threads */ for (i = 0; i < NR_THREADS; i++) thread_terminate(thread[i]); sys_time(&end); vm_free(task, thread); printf("Complete. The score is %d msec (%d ticks).\n", (int)((end - start) * 1000 / info.hz), (int)(end - start)); return 0; }
void printer_free(NumPrinter* p){ mutex_lock(printer_num); if(p->thread != NULL){ thread_terminate(p->thread); thread_free(p->thread); } mutex_unlock(printer_num); free(p); }
/** * Native kernel thread wrapper function. * * This will forward to rtThreadMain and do termination upon return. * * @param pvArg Pointer to the argument package. * @param Ignored Wait result, which we ignore. */ static void rtThreadNativeMain(void *pvArg, wait_result_t Ignored) { const thread_t Self = current_thread(); PRTTHREADINT pThread = (PRTTHREADINT)pvArg; rtThreadMain(pThread, (RTNATIVETHREAD)Self, &pThread->szName[0]); kern_return_t kr = thread_terminate(Self); AssertFatalMsgFailed(("kr=%d\n", kr)); }
DECLARE_TEST( profile, thread ) { object_t thread[32]; int ith; int frame; error_t err = error(); _test_profile_offset = 0; atomic_store32( &_test_profile_output_counter, 0 ); profile_initialize( "test_profile", _test_profile_buffer, 30000/*_test_profile_buffer_size*/ ); profile_enable( true ); profile_set_output_wait( 1 ); log_info( HASH_TEST, "This test will intentionally run out of memory in profiling system" ); for( ith = 0; ith < 32; ++ith ) { thread[ith] = thread_create( _profile_fail_thread, "profile_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread[ith], 0 ); } test_wait_for_threads_startup( thread, 32 ); for( frame = 0; frame < 1000; ++frame ) { thread_sleep( 16 ); profile_end_frame( frame ); } for( ith = 0; ith < 32; ++ith ) { thread_terminate( thread[ith] ); thread_destroy( thread[ith] ); thread_yield(); } test_wait_for_threads_exit( thread, 32 ); thread_sleep( 1000 ); profile_enable( false ); profile_shutdown(); err = error(); #if BUILD_ENABLE_PROFILE EXPECT_GT( atomic_load32( &_test_profile_output_counter ), 0 ); //TODO: Implement parsing output results #else EXPECT_EQ( atomic_load32( &_test_profile_output_counter ), 0 ); #endif EXPECT_EQ( err, ERROR_NONE ); return 0; }
int main () { // Define vars kern_return_t res; mach_port_t parent, child; thread_state_t state_child; struct i386_thread_state state_child_i386; mach_msg_type_number_t state_cnt = THREAD_STATE_MAX; parent = mach_task_self(); // Create thread res = thread_create(parent, &child); if (res != KERN_SUCCESS) { printf("Error creating the thread: 0x%x, %s\n", res, mach_error_string(res)); exit(1); } // Get thread state res = thread_get_state(child, i386_THREAD_STATE, (thread_state_t)&state_child_i386, &state_cnt); if (res != KERN_SUCCESS) { printf("Error getting the state of the child: 0x%x, %s\n", res, mach_error_string(res)); exit (1); } state_child_i386.uesp = (unsigned int) stack - 80; state_child_i386.eip = (unsigned int) thread_core; // Set thread state res = thread_set_state(child, i386_THREAD_STATE, (thread_state_t)&state_child_i386, state_cnt); if (res != KERN_SUCCESS) { printf("Error setting the state of the child: 0x%x, %s\n", res, mach_error_string(res)); exit(1); } // Resume thread res = thread_resume(child); if (res != KERN_SUCCESS) { printf("Error resuming the child thread: 0x%x, %s\n", res, mach_error_string(res)); exit(1); } sleep(20); // Terminate thread res = thread_terminate(child); if (res != KERN_SUCCESS) { printf("Error terminating the child thread: 0x%x, %s\n", res, mach_error_string(res)); exit (1); } }
static void osxfuse_thread_macfuse_mode(__unused void * parameter, __unused wait_result_t wait_result) { if (fuse_macfuse_mode) { fuse_sysctl_macfuse_start(); } else { fuse_sysctl_macfuse_stop(); } lck_mtx_unlock(osxfuse_sysctl_lock); thread_terminate(current_thread()); }
DECLARE_TEST( semaphore, threaded ) { object_t thread[32]; int ith; int failed_waits; semaphore_test_t test; semaphore_initialize( &test.read, 0 ); semaphore_initialize( &test.write, 0 ); test.loopcount = 128; test.counter = 0; for( ith = 0; ith < 32; ++ith ) { thread[ith] = thread_create( semaphore_waiter, "semaphore_waiter", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread[ith], &test ); } test_wait_for_threads_startup( thread, 32 ); failed_waits = 0; for( ith = 0; ith < test.loopcount * 32; ++ith ) { semaphore_post( &test.read ); thread_yield(); if( !semaphore_try_wait( &test.write, 200 ) ) { failed_waits++; EXPECT_TRUE( semaphore_wait( &test.write ) ); } } for( ith = 0; ith < 32; ++ith ) { thread_terminate( thread[ith] ); thread_destroy( thread[ith] ); thread_yield(); } test_wait_for_threads_exit( thread, 32 ); EXPECT_EQ( test.counter, test.loopcount * 32 ); EXPECT_EQ( failed_waits, 0 ); semaphore_destroy( &test.read ); semaphore_destroy( &test.write ); return 0; }
void BrcmPatchRAM::uploadFirmwareThread(void *arg, wait_result_t wait) { DebugLog("sendFirmwareThread enter\n"); BrcmPatchRAM* me = static_cast<BrcmPatchRAM*>(arg); me->resetDevice(); IOSleep(20); me->uploadFirmware(); me->publishPersonality(); me->scheduleWork(kWorkFinished); DebugLog("sendFirmwareThread termination\n"); thread_terminate(current_thread()); DebugLog("!!! sendFirmwareThread post-terminate !!! should not be here\n"); }
static void cmd_kill(int argc, char **argv) { thread_t t; char *ep; if (argc < 2) { puts("Usage: kill thread"); return; } t = (thread_t)strtoul(argv[1], &ep, 16); printf("Kill thread id:%x\n", (u_int)t); if (thread_terminate(t)) printf("Thread %x does not exist\n", (u_int)t); }
/* * processor_start_thread: * * First thread to execute on a started processor. * * Called at splsched. */ void processor_start_thread(void *machine_param) { processor_t processor = current_processor(); thread_t self = current_thread(); slave_machine_init(machine_param); /* * If running the idle processor thread, * reenter the idle loop, else terminate. */ if (self == processor->idle_thread) thread_block((thread_continue_t)idle_thread); thread_terminate(self); /*NOTREACHED*/ }
static kern_return_t thread_create_running_internal2( register task_t task, int flavor, thread_state_t new_state, mach_msg_type_number_t new_state_count, thread_t *new_thread, boolean_t from_user) { register kern_return_t result; thread_t thread; if (task == TASK_NULL || task == kernel_task) return (KERN_INVALID_ARGUMENT); result = thread_create_internal(task, -1, (thread_continue_t)thread_bootstrap_return, TH_OPTION_NONE, &thread); if (result != KERN_SUCCESS) return (result); result = machine_thread_set_state( thread, flavor, new_state, new_state_count); if (result != KERN_SUCCESS) { task_unlock(task); lck_mtx_unlock(&tasks_threads_lock); thread_terminate(thread); thread_deallocate(thread); return (result); } thread_mtx_lock(thread); thread_start_internal(thread); thread_mtx_unlock(thread); if (from_user) extmod_statistics_incr_thread_create(task); task_unlock(task); lck_mtx_unlock(&tasks_threads_lock); *new_thread = thread; return (result); }
int main () { kern_return_t res; mach_port_t parent, child; thread_state_t state_child; struct i386_thread_state state_child_i386; mach_msg_type_number_t state_Cnt = THREAD_STATE_MAX; parent = mach_task_self(); res = thread_create(parent, &child); if (res != KERN_SUCCESS) { fprintf(stderr, "Error creating the thread: 0x%x, %s\n", res, mach_error_string(res)); exit(1); } res = thread_get_state (child, i386_THREAD_STATE, (thread_state_t)&state_child_i386, &state_Cnt); if (res != KERN_SUCCESS) { fprintf (stderr, "Error getting the state of the child: 0x%x, %s\n", res, mach_error_string(res)); exit (1); } state_child_i386.uesp = (unsigned int) stack - 80; state_child_i386.eip = (unsigned int) thread_asshole; res = thread_set_state (child, i386_THREAD_STATE,(thread_state_t)&state_child_i386, state_Cnt); if (res != KERN_SUCCESS) { fprintf (stderr, "Error setting the state of the child: 0x%x, %s\n", res, mach_error_string(res)); exit(1); } res = thread_resume (child); if (res != KERN_SUCCESS) { fprintf (stderr, "Error resuming the child thread: 0x%x, %s\n", res, mach_error_string(res)); exit(1); } sleep(30); res = thread_terminate (child); if (res != KERN_SUCCESS) { fprintf (stderr, "Error terminating the child thread: 0x%x, %s\n", res, mach_error_string(res)); exit (1); } }
DECLARE_TEST( uuid, threaded ) { object_t thread[32]; int ith, i, jth, j; int num_threads = math_clamp( system_hardware_threads() + 1, 3, 32 ); for( ith = 0; ith < num_threads; ++ith ) { thread[ith] = thread_create( uuid_thread_time, "uuid_thread", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread[ith], (void*)(uintptr_t)ith ); } test_wait_for_threads_startup( thread, num_threads ); for( ith = 0; ith < num_threads; ++ith ) { thread_terminate( thread[ith] ); thread_destroy( thread[ith] ); } test_wait_for_threads_exit( thread, num_threads ); for( ith = 0; ith < num_threads; ++ith ) { for( i = 0; i < 8192; ++i ) { for( jth = ith + 1; jth < num_threads; ++jth ) { for( j = 0; j < 8192; ++j ) { EXPECT_FALSE( uuid_equal( uuid_thread_store[ith][i], uuid_thread_store[jth][j] ) ); } } for( j = i + 1; j < 8192; ++j ) { EXPECT_FALSE( uuid_equal( uuid_thread_store[ith][i], uuid_thread_store[ith][j] ) ); } } } return 0; }
void iTCOWatchdog::free_common() { if (is_active) { tcoWdDisableTimer(); is_active = false; } thread_terminate(thread.Thread); IODelete(thread.Data, struct thread_data, 1); if (WorkaroundBug) { fPCIDevice->ioWrite32(ITCO_SMIEN, fPCIDevice->ioRead32(ITCO_SMIEN) | (ITCO_SMIEN_ENABLE+1)); clearStatus(); WorkaroundBug = false; } else if (SMIWereEnabled) { fPCIDevice->ioWrite32(ITCO_SMIEN, fPCIDevice->ioRead32(ITCO_SMIEN) | ITCO_SMIEN_ENABLE); clearStatus(); SMIWereEnabled = false; } }