struct queue *service_dispatch(struct monitor *monitor, struct queue *q) { if (!q) { q = worker_queue_pop(); if (!q) return 0; } uint32_t handle = queue_handle(q); struct service *s = service_grab(handle); if (!s) { queue_release(q, queue_message_dtor, (void *)(uintptr_t)handle); return worker_queue_pop(); } struct message m; if (!queue_pop(q, &m)) { service_release(handle); return worker_queue_pop(); } int overload = queue_overload(q); if (overload) service_log(handle, "service may overload, message queue length = %d\n", overload); monitor_trigger(monitor, m.source, handle); if (s->logfile) log_output(s->logfile, &m); s->module.dispatch(s->handle, s->ud, &m); service_alloc(m.data, 0); monitor_trigger(monitor, 0, 0); struct queue *next = worker_queue_pop(); if (next) { worker_queue_push(q); q = next; } service_release(handle); return q; }
void scheduler_rr(uint32_t sp) { int i; int vm_count; int prev_vm_id; int next_vm_id; bool vm_valid; bool not_in_wfi; vm_count = sizeof(vm) / sizeof(guest); prev_vm_id = vm_id; next_vm_id = vm_id; //switch to other guests first if possible for(i = 0; i < vm_count; i++) { next_vm_id++; if(next_vm_id == vm_count) { next_vm_id = 0; } vm_valid = vm[next_vm_id].valid; not_in_wfi = vm[next_vm_id].sched.wfi_state != WFI_In; if(vm_valid && not_in_wfi) { //printm(d_scheduler, "vm switch, vm %d to vm %d", prev_vm_id, next_vm_id); //leaving from wfi if(vm[next_vm_id].sched.wfi_state == WFI_PendingIRQ) { printd(d_scheduler, "leave wfi"); vm[next_vm_id].sched.wfi_state = WFI_Out; //scheduler_wait_gic_vcpu_if(); } guest_suspend(&vm[prev_vm_id], sp); guest_restore(&vm[next_vm_id], sp); monitor_trigger(&sys_monitor, VM_SWITCH); scheduler_reset_timer(); scheduler_leave_idle(); return; } } //nothing to switch guest_suspend(&vm[prev_vm_id], sp); scheduler_reset_timer(); scheduler_enter_idle(); //never return idle_thread(); }