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); } }
gboolean mono_threads_core_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { kern_return_t ret; gboolean res; g_assert (info); ret = thread_suspend (info->native_handle); THREADS_SUSPEND_DEBUG ("SUSPEND %p -> %d\n", (void*)info->native_handle, ret); if (ret != KERN_SUCCESS) return FALSE; /* We're in the middle of a self-suspend, resume and register */ if (!mono_threads_transition_finish_async_suspend (info)) { mono_threads_add_to_pending_operation_set (info); g_assert (thread_resume (info->native_handle) == KERN_SUCCESS); THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/1 %p -> %d\n", (void*)info->native_handle, 0); //XXX interrupt_kernel doesn't make sense in this case as the target is not in a syscall return TRUE; } res = mono_threads_get_runtime_callbacks ()-> thread_state_init_from_handle (&info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX], info); THREADS_SUSPEND_DEBUG ("thread state %p -> %d\n", (void*)info->native_handle, res); if (res) { if (interrupt_kernel) thread_abort (info->native_handle); } else { mono_threads_transition_async_suspend_compensation (info); g_assert (thread_resume (info->native_handle) == KERN_SUCCESS); THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/2 %p -> %d\n", (void*)info->native_handle, 0); } return res; }
void mono_threads_core_abort_syscall (MonoThreadInfo *info) { kern_return_t ret; do { ret = thread_suspend (info->native_handle); } while (ret == KERN_ABORTED); if (ret != KERN_SUCCESS) return; do { ret = thread_abort_safely (info->native_handle); } while (ret == KERN_ABORTED); /* * We are doing thread_abort when thread_abort_safely returns KERN_SUCCESS because * for some reason accept is not interrupted by thread_abort_safely. * The risk of aborting non-atomic operations while calling thread_abort should not * exist because by the time thread_abort_safely returns KERN_SUCCESS the target * thread should have return from the kernel and should be waiting for thread_resume * to resume the user code. */ if (ret == KERN_SUCCESS) ret = thread_abort (info->native_handle); do { ret = thread_resume (info->native_handle); } while (ret == KERN_ABORTED); g_assert (ret == KERN_SUCCESS); }
void tgdb_get_registers(mach_port_t thread, struct i386_thread_state *ss, struct i386_float_state *fs) { kern_return_t kr; mach_msg_type_number_t count; kr = thread_abort(thread); if (kr == KERN_NO_THREAD) { /* No thread attach to this activation */ bzero(ss, i386_THREAD_STATE_COUNT); bzero(fs, i386_FLOAT_STATE_COUNT); return; } if (kr != KERN_SUCCESS && kr != KERN_NO_THREAD) { printf("tgdb: can't abort thread\n"); return; } count = i386_THREAD_STATE_COUNT; kr = thread_get_state(thread, i386_THREAD_STATE, (thread_state_t) ss, &count); if (kr != KERN_SUCCESS) { printf("tgdb: can't get thread state\n"); return; } if (0 && tgdb_debug_flags & 256) { printf("\ntgdb_get_registers:\n"); print_thread_state(ss); } if (fs) { count = i386_FLOAT_STATE_COUNT; kr = thread_get_state(thread, i386_FLOAT_STATE, (thread_state_t)fs, &count); if (kr != KERN_SUCCESS) { printf("tgdb: can't get float thread state\n"); return; } } }
gboolean mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { kern_return_t ret; g_assert (info); do { ret = thread_suspend (info->native_handle); } while (ret == KERN_ABORTED); THREADS_SUSPEND_DEBUG ("SUSPEND %p -> %d\n", (gpointer)(gsize)info->native_handle, ret); if (ret != KERN_SUCCESS) return FALSE; if (!mono_threads_transition_finish_async_suspend (info)) { /* We raced with self-suspend and lost. Resume the native * thread. It is still self-suspended, waiting to be resumed. * So suspend can continue. */ do { ret = thread_resume (info->native_handle); } while (ret == KERN_ABORTED); g_assert (ret == KERN_SUCCESS); info->suspend_can_continue = TRUE; THREADS_SUSPEND_DEBUG ("\tlost race with self suspend %p\n", (gpointer)(gsize)info->native_handle); g_assert (mono_threads_is_hybrid_suspension_enabled ()); //XXX interrupt_kernel doesn't make sense in this case as the target is not in a syscall return TRUE; } info->suspend_can_continue = mono_threads_get_runtime_callbacks ()-> thread_state_init_from_handle (&info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX], info, NULL); THREADS_SUSPEND_DEBUG ("thread state %p -> %d\n", (gpointer)(gsize)info->native_handle, ret); if (info->suspend_can_continue) { if (interrupt_kernel) thread_abort (info->native_handle); } else { THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/2 %p -> %d\n", (gpointer)(gsize)info->native_handle, 0); } return TRUE; }
void tgdb_set_registers(mach_port_t thread, struct i386_thread_state *ss, struct i386_float_state *fs) { kern_return_t kr; kr = thread_abort(thread); if (kr == KERN_NO_THREAD) { return; } if (0 && tgdb_debug_flags & 256) { printf("\ntgdb_set_registers:\n"); print_thread_state(ss); } kr = thread_set_state(thread, i386_THREAD_STATE, (thread_state_t)ss, i386_THREAD_STATE_COUNT); if (kr != KERN_SUCCESS) { printf("tgdb: can't set thread state\n"); return; } if (fs) { kr = thread_set_state(thread, i386_FLOAT_STATE, (thread_state_t)fs, i386_FLOAT_STATE_COUNT); if (kr != KERN_SUCCESS) { printf("tgdb: can't set float state\n"); return; } } return; }
void up_abort(void) { #if 0 thread_abort(); #endif }
void TimerInterrupt(void) { // D(bug("TimerIRQ\n")); // Look for active TMTasks that have expired tm_time_t now; timer_current_time(now); TMDesc *desc = tmDescList; while (desc) { TMDesc *next = desc->next; uint32 tm = desc->task; if ((ReadMacInt16(tm + qType) & 0x8000) && timer_cmp_time(desc->wakeup, now) <= 0) { // Found one, mark as inactive and remove it from the Time Manager queue WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff); dequeue_tm(tm); // Call timer function uint32 addr = ReadMacInt32(tm + tmAddr); if (addr) { D(bug("Calling TimeTask %08lx, addr %08lx\n", tm, addr)); M68kRegisters r; r.a[0] = addr; r.a[1] = tm; Execute68k(r.a[0], &r); D(bug(" returned from TimeTask\n")); } } desc = next; } #if PRECISE_TIMING // Look for next task to be called and set wakeup_time #if PRECISE_TIMING_BEOS while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; suspend_thread(timer_thread); #endif #if PRECISE_TIMING_MACH semaphore_wait(wakeup_time_sem); thread_suspend(timer_thread); #endif #if PRECISE_TIMING_POSIX timer_thread_suspend(); pthread_mutex_lock(&wakeup_time_lock); #endif wakeup_time = wakeup_time_max; for (TMDesc *d = tmDescList; d; d = d->next) if ((ReadMacInt16(d->task + qType) & 0x8000)) if (timer_cmp_time(d->wakeup, wakeup_time) < 0) wakeup_time = d->wakeup; #if PRECISE_TIMING_BEOS release_sem(wakeup_time_sem); thread_info info; do { resume_thread(timer_thread); // This will unblock the thread get_thread_info(timer_thread, &info); } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) #endif #if PRECISE_TIMING_MACH semaphore_signal(wakeup_time_sem); thread_abort(timer_thread); thread_resume(timer_thread); #endif #if PRECISE_TIMING_POSIX pthread_mutex_unlock(&wakeup_time_lock); timer_thread_resume(); assert(suspend_count == 0); #endif #endif }
int16 PrimeTime(uint32 tm, int32 time) { D(bug("PrimeTime %08lx, time %ld\n", tm, time)); // Find descriptor TMDesc *desc = find_desc(tm); if (!desc) { printf("FATAL: PrimeTime(%08lx): Descriptor not found\n", (long unsigned int)tm); return 0; } // Convert delay time tm_time_t delay; timer_mac2host_time(delay, time); // Extended task? if (ReadMacInt16(tm + qType) & 0x4000) { // Yes, tmWakeUp set? if (ReadMacInt32(tm + tmWakeUp)) { // PrimeTime(0) can either mean (a) "the task runs as soon as interrupts are enabled" // or (b) "continue previous delay" if an expired task was stopped via RmvTime() and // then re-installed using InsXTime(). Since tmWakeUp was set, this is case (b). // The remaining time was saved in tmCount by RmvTime(). if (time == 0) { timer_mac2host_time(delay, ReadMacInt16(tm + tmCount)); } // Yes, calculate wakeup time relative to last scheduled time tm_time_t wakeup; timer_add_time(wakeup, desc->wakeup, delay); desc->wakeup = wakeup; } else { // No, calculate wakeup time relative to current time tm_time_t now; timer_current_time(now); timer_add_time(desc->wakeup, now, delay); } // Set tmWakeUp to indicate that task was scheduled WriteMacInt32(tm + tmWakeUp, 0x12345678); } else { // Not extended task, calculate wakeup time relative to current time tm_time_t now; timer_current_time(now); timer_add_time(desc->wakeup, now, delay); } // Make task active and enqueue it in the Time Manager queue #if PRECISE_TIMING_BEOS while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; suspend_thread(timer_thread); #endif #ifdef PRECISE_TIMING_MACH semaphore_wait(wakeup_time_sem); thread_suspend(timer_thread); #endif #if PRECISE_TIMING_POSIX timer_thread_suspend(); pthread_mutex_lock(&wakeup_time_lock); #endif WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) | 0x8000); enqueue_tm(tm); #if PRECISE_TIMING // Look for next task to be called and set wakeup_time wakeup_time = wakeup_time_max; for (TMDesc *d = tmDescList; d; d = d->next) if ((ReadMacInt16(d->task + qType) & 0x8000)) if (timer_cmp_time(d->wakeup, wakeup_time) < 0) wakeup_time = d->wakeup; #ifdef PRECISE_TIMING_BEOS release_sem(wakeup_time_sem); thread_info info; do { resume_thread(timer_thread); // This will unblock the thread get_thread_info(timer_thread, &info); } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) #endif #ifdef PRECISE_TIMING_MACH semaphore_signal(wakeup_time_sem); thread_abort(timer_thread); thread_resume(timer_thread); #endif #ifdef PRECISE_TIMING_POSIX pthread_mutex_unlock(&wakeup_time_lock); timer_thread_resume(); assert(suspend_count == 0); #endif #endif return 0; }
int16 RmvTime(uint32 tm) { D(bug("RmvTime %08lx\n", tm)); // Find descriptor TMDesc *desc = find_desc(tm); if (!desc) { printf("WARNING: RmvTime(%08lx): Descriptor not found\n", (long unsigned int)tm); return 0; } // Task active? #if PRECISE_TIMING_BEOS while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ; suspend_thread(timer_thread); #endif #ifdef PRECISE_TIMING_MACH semaphore_wait(wakeup_time_sem); thread_suspend(timer_thread); #endif #if PRECISE_TIMING_POSIX timer_thread_suspend(); pthread_mutex_lock(&wakeup_time_lock); #endif if (ReadMacInt16(tm + qType) & 0x8000) { // Yes, make task inactive and remove it from the Time Manager queue WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff); dequeue_tm(tm); #if PRECISE_TIMING // Look for next task to be called and set wakeup_time wakeup_time = wakeup_time_max; for (TMDesc *d = tmDescList; d; d = d->next) if ((ReadMacInt16(d->task + qType) & 0x8000)) if (timer_cmp_time(d->wakeup, wakeup_time) < 0) wakeup_time = d->wakeup; #endif // Compute remaining time tm_time_t remaining, current; timer_current_time(current); timer_sub_time(remaining, desc->wakeup, current); WriteMacInt32(tm + tmCount, timer_host2mac_time(remaining)); } else WriteMacInt32(tm + tmCount, 0); D(bug(" tmCount %ld\n", ReadMacInt32(tm + tmCount))); #if PRECISE_TIMING_BEOS release_sem(wakeup_time_sem); thread_info info; do { resume_thread(timer_thread); // This will unblock the thread get_thread_info(timer_thread, &info); } while (info.state == B_THREAD_SUSPENDED); // Sometimes, resume_thread() doesn't work (BeOS bug?) #endif #ifdef PRECISE_TIMING_MACH semaphore_signal(wakeup_time_sem); thread_abort(timer_thread); thread_resume(timer_thread); #endif #if PRECISE_TIMING_POSIX pthread_mutex_unlock(&wakeup_time_lock); timer_thread_resume(); assert(suspend_count == 0); #endif // Free descriptor free_desc(desc); return 0; }
kern_return_t rthread_abort(rthread_t th) { return(thread_abort(th->wired)); }
void mono_threads_core_interrupt (MonoThreadInfo *info) { thread_abort (info->native_handle); }