static void ReclaimDSandMarkReset(th_context *th, VariantSF to, int leader) { CPtr csf = openreg ; for(;;) { if( !is_completed(compl_subgoal_ptr(csf))) /* Handle early completion */ { subg_grabbed(compl_subgoal_ptr(csf)) = TRUE ; subg_tid(compl_subgoal_ptr(csf)) = leader ; subg_asf_list_ptr(compl_subgoal_ptr(csf)) = NULL; subg_compl_susp_ptr(compl_subgoal_ptr(csf)) = NULL; } if( compl_subgoal_ptr(csf) == to ) break; csf = prev_compl_frame(csf) ; } }
static void handle_unsupported_answer_subst(NODEptr as_leaf) { ASI unsup_asi = Delay(as_leaf); VariantSF unsup_subgoal = asi_subgoal(unsup_asi); #ifdef DEBUG_DELAYVAR fprintf(stddbg, ">>>> start handle_unsupported_answer_subst()\n"); #endif delete_branch(as_leaf, &subg_ans_root_ptr(unsup_subgoal)); simplify_pos_unsupported(as_leaf); if (is_completed(unsup_subgoal)) { if (subgoal_fails(unsup_subgoal)) { simplify_neg_fails(unsup_subgoal); } } free(unsup_asi); }
static void * build_worker(void *arg_) { thread_start_arg *arg = (thread_start_arg *) arg_; td_job_queue * const queue = arg->queue; const int job_id = arg->job_id; pthread_mutex_lock(&queue->mutex); ++queue->thread_count; while (!queue->siginfo.flag) { td_node *node; int slot; int count = queue->tail - queue->head; if (0 == count) { pthread_cond_wait(&queue->work_avail, &queue->mutex); continue; } slot = (queue->head++) % queue->array_size; node = queue->array[slot]; queue->array[slot] = NULL; node->job.flags &= ~TD_JOBF_QUEUED; advance_job(queue, node, job_id); if (is_completed(node) && is_root(node)) queue->siginfo.flag = 1; } --queue->thread_count; pthread_mutex_unlock(&queue->mutex); pthread_cond_broadcast(&queue->work_avail); return NULL; }
static void handle_empty_dl_creation(DL dl) { NODEptr as_leaf = dl_asl(dl); ASI asi = Delay(as_leaf); VariantSF subgoal; #ifdef DEBUG_DELAYVAR fprintf(stddbg, ">>>> start handle_empty_dl_creation()\n"); #endif /* * Only when `as_leaf' is still a conditional answer can we do * remove_dl_from_dl_list(), simplify_pos_unconditional(), and * simplify_neg_succeeds() here. * * If `as_leaf' is already marked UNCONDITIONAL (by * unmark_conditional_answer(as_leaf) in simplify_pos_unconditional()), * that means this is the second time when `as_leaf' becomes * unconditional. So we don't need do anything. All the DLs have been * released in the first time. */ if (is_conditional_answer(as_leaf)) { /* if it is still conditional */ remove_dl_from_dl_list(dl, asi); subgoal = asi_subgoal(Delay(as_leaf)); #ifdef DEBUG_DELAYVAR xsb_dbgmsg((LOG_DEBUG, ">>>> the subgoal is:")); dbg_print_subgoal(LOG_DEBUG,stddbg, subgoal); xsb_dbgmsg((LOG_DEBUG, "\n")); #endif /* * simplify_pos_unconditional(as_leaf) will release all other DLs for * as_leaf, and mark as_leaf as UNCONDITIONAL. */ simplify_pos_unconditional(as_leaf); /*-- perform early completion if necessary; please preserve invariants --*/ if (!is_completed(subgoal) && most_general_answer(as_leaf)) { perform_early_completion(subgoal, subg_cp_ptr(subgoal)); subg_compl_susp_ptr(subgoal) = NULL; } simplify_neg_succeeds(subgoal); } }
static struct task_struct* psnedf_schedule(struct task_struct * prev) { psnedf_domain_t* pedf = local_pedf; rt_domain_t* edf = &pedf->domain; struct task_struct* next; int out_of_time, sleep, preempt, np, exists, blocks, resched; raw_readyq_lock(&pedf->slock); /* sanity checking * differently from gedf, when a task exits (dead) * pedf->schedule may be null and prev _is_ realtime */ BUG_ON(pedf->scheduled && pedf->scheduled != prev); BUG_ON(pedf->scheduled && !is_realtime(prev)); /* (0) Determine state */ exists = pedf->scheduled != NULL; blocks = exists && !is_running(pedf->scheduled); out_of_time = exists && budget_enforced(pedf->scheduled) && bt_flag_is_set(pedf->scheduled, BTF_BUDGET_EXHAUSTED); np = exists && is_np(pedf->scheduled); sleep = exists && is_completed(pedf->scheduled); preempt = edf_preemption_needed(edf, prev); /* If we need to preempt do so. * The following checks set resched to 1 in case of special * circumstances. */ resched = preempt; /* Do budget stuff */ if (blocks) budget_state_machine(prev,on_blocked); else if (sleep) budget_state_machine(prev,on_sleep); else if (preempt) budget_state_machine(prev,on_preempt); /* If a task blocks we have no choice but to reschedule. */ if (blocks) resched = 1; /* Request a sys_exit_np() call if we would like to preempt but cannot. * Multiple calls to request_exit_np() don't hurt. */ if (np && (out_of_time || preempt || sleep)) request_exit_np(pedf->scheduled); /* Any task that is preemptable and either exhausts its execution * budget or wants to sleep completes. We may have to reschedule after * this. */ if (!np && (out_of_time || sleep) && !blocks) { job_completion(pedf->scheduled, !sleep); resched = 1; } /* The final scheduling decision. Do we need to switch for some reason? * Switch if we are in RT mode and have no task or if we need to * resched. */ next = NULL; if ((!np || blocks) && (resched || !exists)) { /* When preempting a task that does not block, then * re-insert it into either the ready queue or the * release queue (if it completed). requeue() picks * the appropriate queue. */ if (pedf->scheduled && !blocks) requeue(pedf->scheduled, edf); next = __take_ready(edf); } else /* Only override Linux scheduler if we have a real-time task * scheduled that needs to continue. */ if (exists) next = prev; if (next) { TRACE_TASK(next, "scheduled at %llu\n", litmus_clock()); } else { TRACE("becoming idle at %llu\n", litmus_clock()); } pedf->scheduled = next; sched_state_task_picked(); raw_readyq_unlock(&pedf->slock); return next; }
static void advance_job(td_job_queue *queue, td_node *node, int job_id) { td_jobstate state; while ((state = node->job.state) < TD_JOB_COMPLETED) { switch (state) { case TD_JOB_INITIAL: if (node->job.block_count > 0) { /* enqueue any blocking jobs and transition to the blocked state */ int i, count, bc = 0; td_node **deps = node->deps; for (i = 0, count = node->dep_count; i < count; ++i) { td_node *dep = deps[i]; if (!is_completed(dep)) { ++bc; if (!is_queued(dep) && dep->job.state < TD_JOB_BLOCKED) enqueue(queue, dep); } } assert(bc == node->job.block_count); transition_job(queue, node, TD_JOB_BLOCKED); pthread_cond_broadcast(&queue->work_avail); return; } else { /* nothing is blocking this job, so scan implicit deps immediately */ transition_job(queue, node, TD_JOB_SCANNING); } break; case TD_JOB_BLOCKED: assert(0 == node->job.block_count); if (0 == node->job.failed_deps) transition_job(queue, node, TD_JOB_SCANNING); else transition_job(queue, node, TD_JOB_FAILED); break; case TD_JOB_SCANNING: if (0 == scan_implicit_deps(queue, node)) { update_input_signature(queue, node); if (is_up_to_date(queue, node)) transition_job(queue, node, TD_JOB_UPTODATE); else transition_job(queue, node, TD_JOB_RUNNING); } else { /* implicit dependency scanning failed */ transition_job(queue, node, TD_JOB_FAILED); } break; case TD_JOB_RUNNING: if (0 != run_job(queue, node, job_id)) transition_job(queue, node, TD_JOB_FAILED); else transition_job(queue, node, TD_JOB_COMPLETED); break; default: assert(0); td_croak("can't get here"); break; } } if (is_completed(node)) { int qcount = 0; td_job_chain *chain = node->job.pending_jobs; if (td_debug_check(queue->engine, TD_DEBUG_QUEUE)) printf("%s completed - enqueing blocked jobs\n", node->annotation); /* unblock all jobs that are waiting for this job and enqueue them */ while (chain) { td_node *n = chain->node; if (is_failed(node)) n->job.failed_deps++; /* nodes blocked on this node can't be completed yet */ assert(!is_completed(n)); if (0 == --n->job.block_count) { if (!is_queued(n)) enqueue(queue, n); ++qcount; } chain = chain->next; } if (1 < qcount) pthread_cond_broadcast(&queue->work_avail); else if (1 == qcount) pthread_cond_signal(&queue->work_avail); } }
static struct task_struct* demo_schedule(struct task_struct * prev) { struct demo_cpu_state *local_state = local_cpu_state(); /* next == NULL means "schedule background work". */ struct task_struct *next = NULL; /* prev's task state */ int exists, out_of_time, job_completed, self_suspends, preempt, resched; raw_spin_lock(&local_state->local_queues.ready_lock); BUG_ON(local_state->scheduled && local_state->scheduled != prev); BUG_ON(local_state->scheduled && !is_realtime(prev)); exists = local_state->scheduled != NULL; self_suspends = exists && !is_current_running(); out_of_time = exists && budget_enforced(prev) && budget_exhausted(prev); job_completed = exists && is_completed(prev); /* preempt is true if task `prev` has lower priority than something on * the ready queue. */ preempt = edf_preemption_needed(&local_state->local_queues, prev); /* check all conditions that make us reschedule */ resched = preempt; /* if `prev` suspends, it CANNOT be scheduled anymore => reschedule */ if (self_suspends) { resched = 1; } /* also check for (in-)voluntary job completions */ if (out_of_time || job_completed) { demo_job_completion(prev, out_of_time); resched = 1; } if (resched) { /* First check if the previous task goes back onto the ready * queue, which it does if it did not self_suspend. */ if (exists && !self_suspends) { demo_requeue(prev, local_state); } next = __take_ready(&local_state->local_queues); } else { /* No preemption is required. */ next = local_state->scheduled; } local_state->scheduled = next; if (exists && prev != next) { TRACE_TASK(prev, "descheduled.\n"); } if (next) { TRACE_TASK(next, "scheduled.\n"); } /* This mandatory. It triggers a transition in the LITMUS^RT remote * preemption state machine. Call this AFTER the plugin has made a local * scheduling decision. */ sched_state_task_picked(); raw_spin_unlock(&local_state->local_queues.ready_lock); return next; }
/* ==================================== */ static gint item_event(GooCanvasItem *item, GooCanvasItem *target, GdkEvent *event, PieceItem *data) { double item_x, item_y; if(!gcomprisBoard) return FALSE; if(board_paused) return FALSE; if(data && !data->on_top) return FALSE; switch (event->type) { case GDK_ENTER_NOTIFY: g_object_set(item, "stroke-color", "white", "line-width", (double)3, NULL); break; case GDK_LEAVE_NOTIFY: g_object_set(item, "stroke-color", "black", "line-width", (double)1, NULL); break; case GDK_BUTTON_PRESS: switch(event->button.button) { case 1: gc_sound_play_ogg ("sounds/bleep.wav", NULL); gc_drag_offset_save(event); goo_canvas_item_raise(data->group, NULL); break; } break; case GDK_MOTION_NOTIFY: gc_drag_item_move(event, data->group); break; case GDK_BUTTON_RELEASE: { gint i; gint tmpi, tmpj; double tmpx, tmpy; PieceItem *piece_src; PieceItem *piece_dst; gint col = 0, line; item_x = event->button.x; item_y = event->button.y; goo_canvas_convert_from_item_space(goo_canvas_item_get_canvas(item), item, &item_x, &item_y); /* Search the column (x) where this item is ungrabbed */ for(i=0; i<=number_of_item_x; i++) if(position[i][0]->x < item_x && position[i+1][0]->x > item_x) col = i; /* Bad drop / Outside of column area */ /* Bad drop / On the same column */ if(col<0 || col > number_of_item_x || col == data->i) { gc_sound_play_ogg ("sounds/eraser2.wav", NULL); /* Return to the original position */ gc_item_absolute_move (data->group, data->x , data->y); return FALSE; } /* Now search the free line (y) */ line = number_of_item_y; for(i=number_of_item_y-1; i>=0; i--) if(position[col][i]->color == -1) line = i; /* Bad drop / Too many pieces here */ if(line >= number_of_item_y) { gc_sound_play_ogg ("sounds/eraser2.wav", NULL); /* Return to the original position */ gc_item_absolute_move (data->group, data->x , data->y); return FALSE; } /* Update ontop values for the piece under the grabbed one */ if(data->j>0) position[data->i][data->j-1]->on_top = TRUE; /* Update ontop values for the piece under the ungrabbed one */ if(line>0) position[col][line-1]->on_top = FALSE; /* Move the piece */ piece_dst = position[col][line]; piece_src = data; gc_item_absolute_move (data->group, piece_dst->x , piece_dst->y); gc_sound_play_ogg ("sounds/scroll.wav", NULL); /* Swap values in the pieces */ tmpx = data->x; tmpy = data->y; piece_src->x = piece_dst->x; piece_src->y = piece_dst->y; piece_dst->x = tmpx; piece_dst->y = tmpy; tmpi = data->i; tmpj = data->j; position[tmpi][tmpj]->i = piece_dst->i; position[tmpi][tmpj]->j = piece_dst->j; piece_dst->i = tmpi; piece_dst->j = tmpj; position[piece_src->i][piece_src->j] = piece_src; position[piece_dst->i][piece_dst->j] = piece_dst; // dump_solution(); if(is_completed()) { gamewon = TRUE; hanoi_destroy_all_items(); gc_bonus_display(gamewon, GC_BONUS_SMILEY); } } break; default: break; } return FALSE; }