bool VM::check_interrupts(CallFrame* call_frame, void* end) { // First, we might be here because someone reset the stack_limit_ so that // we'd fall into here to check interrupts even if the stack is fine, // // So fix up the stack_limit_ if thats the case first. // If this is true, stack_limit_ was just changed to get our attention, reset // it now. if(stack_limit_ == stack_start_) { reset_stack_limit(); } else { if(!check_stack(call_frame, end)) return false; } if(unlikely(check_local_interrupts)) { if(!process_async(call_frame)) return false; } // If the current thread is trying to step, debugger wise, then assist! if(thread_step()) { clear_thread_step(); if(!Helpers::yield_debugger(this, call_frame, Qnil)) return false; } return true; }
bool check_async(CallFrame* call_frame) { if(check_local_interrupts) { return process_async(call_frame); } return true; }
static void *swd_reader(void *arg) { uint32_t data[MAXWORDS]; unsigned query_id; int r; int once = 1; restart: for (;;) { if ((usb = usb_open(0x18d1, 0xdb03, 0))) break; if ((usb = usb_open(0x18d1, 0xdb04, 0))) break; if (once) { xprintf(XSWD, "usb: waiting for debugger device\n"); once = 0; } usleep(250000); } once = 0; xprintf(XSWD, "usb: debugger connected\n"); pthread_mutex_lock(&swd_lock); // send a version query to find out about the firmware // old m3debug fw will just report failure query_id = sequence++; query_id = RSWD_TXN_START(query_id); data[0] = query_id; data[1] = RSWD_MSG(CMD_VERSION, 0, RSWD_VERSION); usb_write(usb, data, 8); for (;;) { pthread_mutex_unlock(&swd_lock); r = usb_read_forever(usb, data, MAXWORDS * 4); pthread_mutex_lock(&swd_lock); if (r < 0) { xprintf(XSWD, "usb: debugger disconnected\n"); swd_online = -1; swd_txn_status = TXN_STATUS_FAIL; pthread_cond_broadcast(&swd_event); break; } if ((r < 4) || (r & 3)) { xprintf(XSWD, "usb: discard packet (%d)\n", r); continue; } if (query_id && (data[0] == query_id)) { query_id = 0; process_query(data + 1, (r / 4) - 1); swd_online = 1; } else if (data[0] == RSWD_TXN_ASYNC) { pthread_mutex_unlock(&swd_lock); process_async(data + 1, (r / 4) - 1); pthread_mutex_lock(&swd_lock); } else if ((swd_txn_status == TXN_STATUS_WAIT) && (data[0] == swd_txn_id)) { swd_txn_status = r; memcpy(swd_txn_data, data, r); pthread_cond_broadcast(&swd_event); } else { xprintf(XSWD, "usb: rx: unexpected txn %08x (%d)\n", data[0], r); } } // wait for a reader to ack the shutdown (and close usb) while (swd_online == -1) { pthread_cond_wait(&swd_event, &swd_lock); } pthread_mutex_unlock(&swd_lock); usleep(250000); goto restart; return NULL; }
int ape_timers_process(ape_global *ape_ctx) { ape_timers *timers = &ape_ctx->timersng; ape_timer_t *cur = timers->head; uint64_t inums = UINT64_MAX, lastsample = 0; process_async(timers); /* TODO: paused timer */ while (cur != NULL) { uint64_t start; if (cur->flags & APE_TIMER_IS_CLEARED) { cur = ape_timer_destroy(timers, cur); continue; } if ((start = mach_absolute_time()) >= cur->schedule - 150000) { uint64_t ret; unsigned int duration; ret = cur->callback(cur->arg); // printf("Timer returned %lld\n", ret); if (ret == -1) { cur->schedule = start + cur->ticks_needs; } else if (ret == 0) { cur = ape_timer_destroy(timers, cur); continue; } else { cur->ticks_needs = ret * 1000000; cur->schedule = start + cur->ticks_needs; } lastsample = mach_absolute_time(); duration = lastsample - start; if (cur->stats.max < duration / 1000000) { cur->stats.max = duration / 1000000; } if (cur->stats.min == 0 || duration / 1000000 < cur->stats.min) { cur->stats.min = duration / 1000000; } cur->stats.nexec++; cur->stats.totaltime += duration / 1000000; } if (cur->schedule < inums) { inums = cur->schedule; } cur = cur->next; } process_async(timers); if (inums == UINT64_MAX) { return APE_TIMER_RESOLUTION; } if (lastsample == 0) { lastsample = mach_absolute_time(); } // printf("Next timer in : %lld or %d\n", inums-lastsample, ape_max(1, // (int)((inums-lastsample+500000)/1000000))); return ape_max((timers->run_in_low_resolution ? 100 : 1), (int)((inums - lastsample + 500000) / 1000000)); }