/** * * Puts a process on the blocked list and stops its execution (if it's executed) * * @param[in] pid Process ID * @param[in] eventID The Id of the event which can put the process (PID) back on the ready list * @param[in] condition the condition under which the process is released */ void Sys_Block_Process(uint pid, uint eventID, pConditionFunction condition){ if(sys_ready_processes == 0){ return; } if(sys_ready_processes->next == 0){ return; //no proccess to block } Sys_Start_AtomicSection(); sys_pcb_list_element *element = Sys_Remove_Process_from_List(pid, &sys_ready_processes); Sys_Insert_Process_to_List(element, &sys_blocked_processes); //Event must be registered and process must be subscribed to it Sys_Register_Event(eventID);//if already registered -> just returns; Sys_Subscribe_to_Event(eventID, pid, &Sys_Continue_Pocess, condition); //if already registered -> returns if(sys_running_process->pcb.process_ID == pid){//if this is the running process // CALL Scheduler Sys_End_AtomicSection(); Sys_Force_TimerInterrupt(); } Sys_End_AtomicSection(); }
/** * * This function blocks the current process while waiting for an event that sends data which meet the condition. * * @param[in] eventID Identifier of the event that need to occur * @param[in] function Pointer to the function that represents the condition function (return true if condition is met and continues the process). If function = 0 .. condition is always met. * @return sys_event_data * Pointer to the event data struct that contains the values carried by the event */ sys_event_data *Sys_Wait_For_Condition(uint eventID, pConditionFunction function){ Sys_Block_Process(sys_running_process->pcb.process_ID, eventID, function); //This is only executed if process continued //now get return value (tansmited event data) Sys_Start_AtomicSection(); sys_process_event_handler *event = sys_running_process->pcb.event_register; sys_process_event_handler *prev_event = event; while(event != 0){ if(event->eventID == eventID && event->condition == function){ void *data = event->buffered_data; if(prev_event == event){ sys_running_process->pcb.event_register = event->next; }else{ prev_event->next = event->next; } event->next = 0; Sys_Free(event);//deletes event handler but leaves the data (return value) Sys_End_AtomicSection(); return data; } prev_event = event; event = event->next; } Sys_End_AtomicSection(); return 0; }
/** * * Puts a process with the process ID (PID) back on the ready list. Consequently the process can be executed again. * * @param[in] pid Process ID * @param[in] eventID Event ID * @param[in] data pointer to the data of the event */ bool Sys_Continue_Pocess(uint pid, uint eventID, sys_event_data *data){ if(sys_blocked_processes == 0) return true; //no proccess is blocked .. process must be running Sys_Start_AtomicSection(); sys_pcb_list_element *element = Sys_Remove_Process_from_List(pid, &sys_blocked_processes); Sys_Insert_Process_to_List(element, &sys_ready_processes); Sys_Remove_Event_from_EventRegister(eventID, Sys_Continue_Pocess, &(element->pcb.event_register)); bool exists_another = false;//exists another subscribed event handler of the eventID sys_process_event_handler * event = element->pcb.event_register; while(event != 0){ if(event->eventID == eventID){ exists_another = true; } event = event->next; } if(exists_another == false){ Sys_Unsubscribe_from_Event(eventID, pid); } Sys_End_AtomicSection(); return true; }
/** * * This function deletes the syss_process_control_block element and stops a process * * @param[in] pid This argument is the process identifier */ void Sys_Kill_Process(uint pid){ // Check if the process is in the ready list sys_pcb_list_element *element;//first is the system if(pid == 0){ return; //DO NOT KILL THE SYSTEM } Sys_Start_AtomicSection(); if(pid == sys_running_process->pcb.process_ID){//Do not kill the running program Sys_End_AtomicSection(); Sys_Set_Running_Process_to_Zombie();//kill asynchronously return; } element = Sys_Remove_Process_from_List(pid, &sys_ready_processes); if(element != 0){ element->pcb.sheduler_info.state = SYS_PROCESS_STATE_ZOMBIE; Sys_Delete_Process(element); Sys_End_AtomicSection(); return; } element = Sys_Remove_Process_from_List(pid, &sys_blocked_processes); if(element != 0){ element->pcb.sheduler_info.state = SYS_PROCESS_STATE_ZOMBIE; Sys_Delete_Process(element); Sys_End_AtomicSection(); return; } Sys_End_AtomicSection(); }
/** * * This Function frees dynamic allocated memory. This freeing is performed as atomic action. * * @param data pointer to memory that should be freed. */ void Sys_Free(void *data){ Sys_Start_AtomicSection(); free(data); Sys_End_AtomicSection(); }
/** * * This Function allocates memory of the size \b length. This allocation is performed as atomic action. * * @param length value how many bytes should be allocated * @return pointer to the allocated memory */ void *Sys_Malloc(uint length){ void *out = 0; Sys_Start_AtomicSection(); out = malloc(length); Sys_End_AtomicSection(); return out; }
/** * * This function removes all subscriptions of any process to event (eventID) * * * @param[in] eventID Identifier of the event that has to be removed */ void Sys_Remove_All_Event_Subscriptions(uint eventID){ sys_pcb_list_element *process; Sys_Start_AtomicSection(); process = sys_ready_processes; while(process != 0){//go through all processes Sys_Remove_Event_from_EventRegister(eventID, ALL_FUNCTIONS, &(process->pcb.event_register) ); process = process->next; } Sys_End_AtomicSection(); }
/** * * This function counts the number of blocked process * * @return uint returns the number of blocked processes */ uint Sys_Get_Number_BlockedProcesses(){ uint n = 0; sys_process_control_block_list_element *element; Sys_Start_AtomicSection(); element = sys_blocked_processes; while(element != 0){ n++; element = element->next; } Sys_End_AtomicSection(); return n; }
/** * * Function to copies memory of the size \b length from \b source_i to \b destination_o. This copying is performed as atomic action. * * @param[in] source_i pointer to the source * @param[out] destination_o pointer to the destination * @param[in] length size of the memory that has to be copied */ void Sys_Memcpy(void *source_i, void *destination_o, uint length){ uint8 *source = source_i; uint8 *destination = destination_o; Sys_Start_AtomicSection(); uint i = 0; for(i = 0; i < length; i++){ destination[i] = source[i]; } Sys_End_AtomicSection(); }
/** * * This function executes all event handlers and processes stored event data. First it checks the list of occurred events and then it executes all event handlers of these events * */ inline void Sys_Execute_All_EventHandler(){ sys_occurred_event *o_event; Sys_Start_AtomicSection(); o_event = sys_occurred_events; sys_occurred_events = 0; while(o_event != 0){//assuming there are less processes then events Sys_Execute_Events_in_ProcessList(o_event->eventID, sys_ready_processes); Sys_Execute_Events_in_ProcessList(o_event->eventID, sys_blocked_processes); sys_occurred_event *occured_event = o_event; o_event = o_event->next; occured_event->next = 0; Sys_Free(occured_event); } Sys_End_AtomicSection(); }
/** * * This function puts the running process in the zombie list and switches content to the next ready process * */ void Sys_Set_Running_Process_to_Zombie(){ Sys_Start_AtomicSection(); if(sys_running_process->pcb.process_ID == 0){//system is never a zombie Sys_End_AtomicSection(); return; } sys_pcb_list_element *process = 0; sys_pcb_list_element *previous_process = 0; sys_running_process->pcb.sheduler_info.state = SYS_PROCESS_STATE_ZOMBIE; Sys_Unsubscribe_Process(sys_running_process->pcb.process_ID);//unsubscribe this process from all events and clear the event-list //remove the element from the list if(sys_running_process->previous == 0){ previous_process = sys_running_process->next; if(previous_process == 0){//no nnext and no previous element goto goZombieMode; } while(previous_process->next != 0){//take the last element previous_process = previous_process->next; } }else{ previous_process = sys_running_process->previous; } sys_running_process = previous_process; goZombieMode: process = Sys_Remove_Process_from_List(sys_running_process->pcb.process_ID, &sys_ready_processes); Sys_Insert_Process_to_List(process, &sys_zombies); Sys_End_AtomicSection(); Sys_Force_TimerInterrupt();//this schedules the next after the prvious process }
/** * * This function adds the event-data to the local list of the process (pid). * * @param[in] pid process identifier * @param[in] eventID event identifier * @param[in] data memory that contains the value of the occurred event * @param[in] length length of the data (bytes) */ void Sys_Add_Event_to_Process(uint pid, uint eventID, void *data, uint length){ sys_pcb_list_element *element; Sys_Start_AtomicSection(); element = Sys_Find_Process(pid); if(element == 0){//no process with pid Sys_End_AtomicSection(); return; } bool add_event = true; sys_occurred_event **o_event = &sys_occurred_events; while(*o_event != 0){//check if the event (eventID) already occurred if((*o_event)->eventID == eventID){//it already occurred add_event = false; break; } o_event = &((*o_event)->next); } if(add_event){//if it hasn't occurred //add eventID to the list of occurred events (*o_event) = Sys_Malloc(sizeof(sys_occurred_event)); if((*o_event) == 0){ Sys_End_AtomicSection(); return; //no memory left } (*o_event)->eventID = eventID; (*o_event)->next = 0; } //NOW add the data sys_process_event_handler *event = element->pcb.event_register; while( (event = Sys_Next_EventHandler(event, eventID)) != 0 ){ //check if the condition was met to add the event data bool is_condition_met = false; if(event->condition != 0){ is_condition_met = event->condition(data); }else{//no condition is always met is_condition_met = true; } if( is_condition_met ){ sys_event_data *e_data = (sys_event_data*) Sys_Malloc(sizeof(sys_event_data)); if(e_data == 0){//if malloc fails .. exit Sys_End_AtomicSection(); return; } //create the struct that holds the data if(length != 0){//if there is data e_data->value = Sys_Malloc(length); if(e_data->value == 0){//if malloc fails .. exit Sys_Free(e_data); Sys_End_AtomicSection(); return; } Sys_Memcpy(data, e_data->value, length); }else{ e_data->value = 0; } e_data->size = length; e_data->next = 0; //add the struct to the end of the buffered_data if(event->buffered_data == 0){ event->buffered_data = e_data; }else{ sys_event_data *set_data = event->buffered_data; while(set_data->next != 0){ set_data = set_data->next; } set_data->next = e_data; } event = event->next; } } Sys_End_AtomicSection(); }