// Executes a binary program int exec(char* bin) { // Looking for free task int index = -1; for (int i = 0; i < tasks_nb; i++) if (!tasks[i].free) { index = i; tasks[i].free = 1; break; } if (index < 0) return 1; // Read program if existing if (file_exists(bin)) { // Copy binary program at the right address if (file_read(bin, (uint32_t*) tasks[index].addr)) return 3; // Commute to task with corresponding TSS as argument call_task(tasks[index].gdt_tss_sel); // Structure array reset tasks[index].task_tss.eip = tasks[index].free = 0; // instruction pointer and freedom tasks[index].task_tss.esp = tasks[index].task_tss.ebp = TASK_LIMIT; // stack pointers // End of routine return 0; } else return 2; }
int32_t scheduler_update(scheduler_t* scheduler) { int32_t i; int32_t realtime_violation = 0; task_set_t* ts = scheduler->task_set; task_function_t call_task; task_argument_t function_argument; task_return_t treturn; // Iterate through registered tasks for (i = ts->current_schedule_slot; i < ts->task_count; i++) { uint32_t current_time = time_keeper_get_micros(); // If the task is active and has waited long enough... if ( (ts->tasks[i].run_mode != RUN_NEVER) && (current_time >= ts->tasks[i].next_run) ) { uint32_t delay = current_time - (ts->tasks[i].next_run); uint32_t task_start_time; task_start_time = time_keeper_get_micros(); // Get function pointer and function argument call_task = ts->tasks[i].call_function; function_argument = ts->tasks[i].function_argument; // Execute task treturn = call_task(function_argument); // Set the next execution time of the task switch (ts->tasks[i].timing_mode) { case PERIODIC_ABSOLUTE: // Do not take delays into account ts->tasks[i].next_run += ts->tasks[i].repeat_period; break; case PERIODIC_RELATIVE: // Take delays into account ts->tasks[i].next_run = time_keeper_get_micros() + ts->tasks[i].repeat_period; break; } // Set the task to inactive if it has to run only once if (ts->tasks[i].run_mode == RUN_ONCE) { ts->tasks[i].run_mode = RUN_NEVER; } // Check real time violations if (ts->tasks[i].next_run < current_time) { realtime_violation = -i; //realtime violation!! ts->tasks[i].rt_violations++; ts->tasks[i].next_run = current_time + ts->tasks[i].repeat_period; } // Compute real-time statistics ts->tasks[i].delay_avg = (7 * ts->tasks[i].delay_avg + delay) / 8; if (delay > ts->tasks[i].delay_max) { ts->tasks[i].delay_max = delay; } ts->tasks[i].delay_var_squared = (15 * ts->tasks[i].delay_var_squared + (delay - ts->tasks[i].delay_avg) * (delay - ts->tasks[i].delay_avg)) / 16; ts->tasks[i].execution_time = (7 * ts->tasks[i].execution_time + (time_keeper_get_micros() - task_start_time)) / 8; // Depending on shceduling strategy, select next task slot switch (scheduler->schedule_strategy) { case FIXED_PRIORITY: // Fixed priority scheme - scheduler will start over with tasks with the highest priority ts->current_schedule_slot = 0; break; case ROUND_ROBIN: // Round robin scheme - scheduler will pick up where it left. if (i >= ts->task_count) { ts->current_schedule_slot = 0; } break; default: break; } return realtime_violation; } } return realtime_violation; }