/**
 *
 * 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();
}
Beispiel #5
0
/**
 *
 * 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();

}
Beispiel #6
0
/**
 *
 * 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;
}
Beispiel #9
0
/**
 *
 * 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();
}