static void vm_suspend_resume(struct vmctx *ctx) { /* * If we get warm reboot request, we don't want to exit the * vcpu_loop/vm_loop/mevent_loop. So we do: * 1. pause VM * 2. flush and clear ioreqs * 3. stop vm watchdog * 4. wait for resume signal * 5. reset vm watchdog * 6. hypercall restart vm */ vm_pause(ctx); vm_clear_ioreq(ctx); vm_stop_watchdog(ctx); wait_for_resume(ctx); pm_backto_wakeup(ctx); vm_reset_watchdog(ctx); vm_reset(ctx); /* set the BSP init state */ vm_set_vcpu_regs(ctx, &ctx->bsp_regs); vm_run(ctx); }
/** * Pour requested_amount grams from bottle.. * Return 0 on success, other values are return values of * delay_until (including scale error codes). */ errv_t Bottle::pour(int requested_amount, int& measured_amount) { // orig_weight is weight including ingredients poured until now int orig_weight, ret; while (1) { // get weight while turning bottle, because ads1231_stable_millis() // blocks bottle in pause position too long int below_pause = (pos_down + get_pause_pos()) / 2; ret = turn_to(below_pause, TURN_DOWN_DELAY, true, &orig_weight); // Note that checking weight here is a critical issue, allows hacking // the robot. If a heavy weight is placed while measuring and then // removed while pouring (results in more alcohol). Stable weight // should resolve most problems. if (ret == WEIGHT_NOT_STABLE) { ret = ads1231_get_stable_grams(orig_weight); } if (ret != 0 && ret != WHERE_THE_FUCK_IS_THE_CUP) { return ret; } if (ret == WHERE_THE_FUCK_IS_THE_CUP || orig_weight < WEIGHT_EPSILON) { // no cup... RETURN_IFN_0(wait_for_cup()); } else { // everything fine break; } } // loop until successfully poured or aborted or other fatal error while(1) { // petres wants POURING message also after resume... // https://github.com/rfjakob/barwin-arduino/issues/10 MSG(String("POURING ") + String(number) + String(" ") + String(orig_weight)); DEBUG_MSG_LN("Turn down"); ret = turn_down(TURN_DOWN_DELAY, true); // enable check_weight // wait for requested weight // FIXME here we do not want WEIGHT_EPSILON and sharp > if (ret == 0) { DEBUG_MSG_LN("Waiting"); ret = delay_until(POURING_TIMEOUT, orig_weight + requested_amount - UPGRIGHT_OFFSET, true); } if (ret == 0) break; // All good DEBUG_MSG_LN(String("pour: got err ") + String(ret)); // Bottle empty // Note that this does not work if requested_amount is less than // UPGRIGHT_OFFSET! if(ret == BOTTLE_EMPTY) { ERROR(strerror(BOTTLE_EMPTY) + String(" ") + String(number) ); // TODO other speed here? it is empty already! RETURN_IFN_0(turn_to(pos_up + BOTTLE_EMPTY_POS_OFFSET, TURN_UP_DELAY)); RETURN_IFN_0(wait_for_resume()); // might return ABORTED } // Cup was removed early else if(ret == WHERE_THE_FUCK_IS_THE_CUP) { ERROR(strerror(WHERE_THE_FUCK_IS_THE_CUP)); RETURN_IFN_0(turn_to_pause_pos(FAST_TURN_UP_DELAY)); RETURN_IFN_0(wait_for_cup()); } // other error - turn bottle up and return error code // includes: scale error, user abort, ... else { return ret; } } // We turn to pause pos and not completely up so we can crossfade RETURN_IFN_0(turn_to_pause_pos(TURN_UP_DELAY)); RETURN_IFN_0(ads1231_get_grams(measured_amount)); measured_amount -= orig_weight; DEBUG_START(); DEBUG_MSG("Stats: "); DEBUG_VAL(requested_amount); DEBUG_VAL(measured_amount); DEBUG_END(); return 0; }