/** * @brief check urb advance * @param host struct uhci_host * @param urb struct usb_request_block * @param usbsts u16 */ static u8 check_urb_advance(struct uhci_host *host, struct usb_request_block *urb, u16 usbsts) { struct uhci_td_meta *tdm; phys32_t qh_element; int elapse, len; elapse = (uhci_current_frame_number(host) + UHCI_NUM_FRAMES - URB_UHCI(urb)->frnum_issued) & (UHCI_NUM_FRAMES - 1); if (!elapse) return urb->status; spinlock_lock(&host->lock_hfl); recheck: urb->actlen = 0; qh_element = URB_UHCI(urb)->qh->element; /* atomic */ /* count up actual length of input/output data */ for (tdm = URB_UHCI(urb)->tdm_head; tdm; tdm = tdm->next) { if (!is_active_td(tdm->td)) { len = UHCI_TD_STAT_ACTLEN(tdm->td); if (!is_setup_td(tdm->td)) urb->actlen += len; } if ((phys32_t)tdm->td_phys == qh_element) { urb->status = UHCI_TD_STAT_STATUS(tdm->td); break; } } if (is_terminate(qh_element)) { urb->status = URB_STATUS_ADVANCED; } else { /* double check */ if (qh_element != URB_UHCI(urb)->qh->element) goto recheck; if (!(urb->status & URB_STATUS_RUN) && !(urb->status & URB_STATUS_ERRORS) && (uhci_td_actlen(tdm->td) == uhci_td_maxlen(tdm->td)) && tdm->next && is_active(tdm->next->status_copy)) urb->status = URB_STATUS_RUN; } URB_UHCI(urb)->qh_element_copy = qh_element; spinlock_unlock(&host->lock_hfl); return urb->status; }
int gotcha_diag(diagnostic_problem problem, const_tv_term alpha) { priority_queue opened; gotcha_node initial; dnf_tree consistent_input; tv_term_list_list systems; unsigned int old_diagnoses; int terminate = 0; int result = 1; diagnostic_problem_reset(problem); sort_int_list(alpha->neg); sort_int_list(alpha->pos); start_stopwatch("observation filtering time"); consistent_input = dnf_tree_filter(dnf_tree_copy(problem->u.tv_tdnf_sd.model), alpha); stop_stopwatch("observation filtering time"); systems = new_tv_term_list_list(); get_systems(consistent_input, systems); /* Start the timer. */ start_stopwatch("search time"); opened = priority_queue_new(cmp_nodes, (priority_queue_element_destroy_func_t)gotcha_node_free, (void *)systems->sz); initial = gotcha_node_new(systems->sz); priority_queue_push(opened, initial); increase_int_counter("pushed"); maximize_int_counter("max", 1); while (!terminate && !priority_queue_empty(opened)) { gotcha_node current = priority_queue_pop(opened); candidate_found(current->cardinality); if (is_terminate()) { gotcha_node_free(current); break; } if (current->depth != 0) { /* The root node has no siblings. */ if (!enqueue_sibling(problem, opened, current, systems)) { result = 0; gotcha_node_free(current); break; } } if (is_diagnosis(current, systems)) { tv_term diagnosis = build_term(current, systems); if (NULL == diagnosis) { result = 0; gotcha_node_free(current); break; } old_diagnoses = problem->diagnoses->sz; if (!add_diagnosis_from_tv_term(problem, diagnosis, &terminate, 1)) { result = 0; rfre_tv_term(diagnosis); gotcha_node_free(current); break; } if (cones != NULL && problem->diagnoses->sz - 1 == old_diagnoses) { assert(problem->diagnoses->sz > 0); /* @todo: Fix the termination here. */ expand_cone_exhaustive(cones, alpha, problem->diagnoses->arr[problem->diagnoses->sz - 1]); } rfre_tv_term(diagnosis); gotcha_node_free(current); } else { if (!enqueue_next_best_state(problem, opened, current, systems)) { result = 0; gotcha_node_free(current); break; } } } priority_queue_free(opened); fre_tv_term_list_list(systems); /* Stop the timer. */ stop_stopwatch("search time"); dnf_tree_free(consistent_input); return result; }