CeDOS - src/kernel/sched/process.c

src/kernel/sched/process.c (view raw)

#include "cedos/sched/process.h"

#define NULL ((void*)0)

PROCESS* list_head = NULL;
PROCESS* list_tail = NULL;
PROCESS_ID next_available = 0;
uint32_t process_count = 0;

/*!
 * Gets a process ID and returns the process struct in the list with the same ID.
 * \param pid Process ID to get the process struct for.
 * \return Process struct for process with ID \p pid. 
 */
PROCESS* get_process(PROCESS_ID pid) {
    if (list_tail->id == pid) { return list_tail; }

    for (PROCESS *p = list_head; p != NULL; p = p->next) {
        if (p->id == pid) { 
            return p; 
        } else if (p->id > pid) {
            return NULL;
        }
    }

    return NULL;
}

/*!
 * Adds a process struct to the list of all processes and assigns it a unique ID.
 * \param process Pointer to the process struct to add to the list.
 * \return Process ID that was assigned to the process struct.
 */
PROCESS_ID add_process(PROCESS *process, PROCESS_ID parent_pid) {
    if (list_head == NULL) {
        list_head = process;
        list_tail = process;
        process->prev = NULL;
    } else {
        list_tail->next = process;
        process->prev = list_tail;
        list_tail = process;
    }

    process->next = NULL;

    PROCESS *parent = (parent_pid == 0) ? NULL : get_process(parent_pid);

    if (parent != NULL) {
        process->next_sibling = parent->child;

        if (parent->child != NULL) {
            parent->child->prev_sibling = process;
        }

        parent->child = process;
    } else {
        process->next_sibling = NULL;
    }

    process->prev_sibling = NULL;
    process->parent = parent;

    process_count++;

    return (process->id = next_available++);
}

/*!
 * Removes the process struct with ID \p pid from the list of all processes.
 * \param pid Process ID whose process struct is to be removed from the list.
 */
void remove_process(PROCESS_ID pid) {
    PROCESS *process = get_process(pid);

    if (process == NULL) { return; }

    if (process == list_head && process == list_tail) {
        list_head = NULL;
        list_tail = NULL;
    } else if (process == list_head && process != list_tail) {
        list_head = process->next;
        list_head->prev = NULL;
    } else if (process != list_head && process == list_tail) {
        list_tail = process->prev;
        list_tail->next = NULL;
    } else {
        PROCESS *prev = process->prev, *next = process->next;
        prev->next = next;
        next->prev = prev;
    }

    PROCESS *prev_sib = process->prev_sibling, *next_sib = process->next_sibling;
    if (prev_sib != NULL) { prev_sib->next_sibling = next_sib; }
    if (next_sib != NULL) { next_sib->prev_sibling = prev_sib; }

    process_count--;
}

/*!
 * Returns the first element of the list.
 * \return First list element.
 */
PROCESS* get_first_process(void) {
    return list_head;
}

/*!
 * Returns the last element of the list.
 * \return Last list element.
 */
PROCESS* get_last_process(void) {
    return list_tail;
}

/*!
 * Returns the number of running processes.
 * \return Number of running processes.
 */
uint32_t get_process_count(void) {
    return process_count;
}