#include <pid.h> #include <proc_syscalls.h> #include <syscall.h> #include <lib.h> #include <limits.h> #include <types.h> #include <kern/errno.h> #include <machine/trapframe.h> #include <thread.h> #include <synch.h> #include <addrspace.h> #include <proc.h> #include <current.h> #include <spl.h> // will need a lock static struct pid_node *pid_head; void pid_bootstrap(void) { pid_list_lock = lock_create("pid_list_lock"); if(pid_list_lock == NULL) { panic("could not create pid list lock!"); } } static struct child_node * child_node_create(pid_t pid) { struct child_node* new_node = kmalloc(sizeof(struct child_node)); if (new_node == NULL) { return NULL; } new_node->pid = pid; new_node->next = NULL; return new_node; } static struct pid_node * pid_node_create(pid_t pid) { struct pid_node * new_node = kmalloc(sizeof(struct pid_node)); if (new_node == NULL) { return NULL; } new_node->pid_cv = cv_create("pid_cv"); if (new_node->pid_cv == NULL) { kfree(new_node->pid_cv); return NULL; } new_node->pid = pid; new_node->next = NULL; new_node->parent_pid = INVALID_PID; new_node->finished = false; new_node->child_list = NULL; return new_node; } // This will require checks to see if it is safe to remove int pid_remove(pid_t pid) { lock_acquire(pid_list_lock); struct pid_node *last = NULL; struct pid_node *current = pid_head; while(current != NULL) { if(current->pid == pid) { if(last != NULL) { last->next = current->next; } while(current->child_list != NULL) { struct child_node *child = current->child_list; current->child_list = current->child_list->next; kfree(child); } if(current->parent_pid != INVALID_PID) { pid_remove_child(current->pid, current->parent_pid); } cv_destroy(current->pid_cv); kfree(current); lock_release(pid_list_lock); return 0; } last = current; current = current->next; } // node with pid not found lock_release(pid_list_lock); return -1; } int pid_insert_kern(pid_t * pid) { KASSERT(pid_head == NULL); struct pid_node *kern_node = pid_node_create(PID_KERN); if (kern_node == NULL) { return ENOMEM; } pid_head = kern_node; *pid = kern_node->pid; return 0; } int pid_insert(pid_t * pid) { // while(!pid_list_lock->lk_free); lock_acquire(pid_list_lock); struct pid_node *search_node = pid_head; struct pid_node *new_node; struct pid_node *search_node_last = search_node; uint16_t linked_list_entries = 1; while(search_node != NULL) { if(linked_list_entries >= PID_MAX) { lock_release(pid_list_lock); return ENPROC; } // insert at tail if reached end of list if(search_node->next == NULL) { new_node = pid_node_create(search_node->pid + 1); if (new_node == NULL) { lock_release(pid_list_lock); return ENOMEM; } search_node->next = new_node; *pid = new_node->pid; lock_release(pid_list_lock); return 0; } // Insert between nodes if space else if (search_node->pid - search_node_last->pid > 1) { new_node = pid_node_create(search_node_last->pid + 1); if (new_node == NULL) { lock_release(pid_list_lock); return ENOMEM; } new_node->next = search_node; search_node_last->next = new_node; *pid = new_node->pid; lock_release(pid_list_lock); return 0; } search_node_last = search_node; search_node = search_node->next; linked_list_entries++; } lock_release(pid_list_lock); return ENOMEM; } struct pid_node* pid_get_node(pid_t pid) { KASSERT(lock_do_i_hold(pid_list_lock)); struct pid_node *search_node = pid_head; while(search_node != NULL) { if(search_node->pid == pid) { return search_node; } search_node = search_node->next; } return NULL; } int pid_assign_parent(pid_t child_pid, pid_t parent_pid) { KASSERT(lock_do_i_hold(pid_list_lock)); struct pid_node *current = pid_head; while(current != NULL) { if(current->pid == child_pid) { current->parent_pid = parent_pid; return 0; } current = current->next; } return -1; } int pid_assign_child(pid_t child_pid, pid_t parent_pid) { KASSERT(lock_do_i_hold(pid_list_lock)); struct pid_node *parent = pid_get_node(parent_pid); if(parent == NULL) { return -1; } // Insert at head if empty if(parent->child_list == NULL) { parent->child_list = child_node_create(child_pid); if (parent->child_list == NULL) { return ENOMEM; } return 0; } struct child_node *search_node = parent->child_list; while(search_node != NULL) { // insert at tail if(search_node->next == NULL) { search_node->next = child_node_create(child_pid); if (search_node->next == NULL) { return ENOMEM; } return 0; } search_node = search_node->next; } return -1; } int pid_remove_child(pid_t child_pid, pid_t parent_pid) { KASSERT(lock_do_i_hold(pid_list_lock)); struct pid_node *parent = pid_get_node(parent_pid); if(parent == NULL) { return -1; } if(parent->child_list == NULL) { return -1; } struct child_node *search_node = parent->child_list; struct child_node *last_node = NULL; struct pid_node *child; while(search_node != NULL) { if(search_node->pid == child_pid) { if(last_node != NULL) { last_node->next = search_node->next; } else { parent->child_list = search_node->next; } child = pid_get_node(search_node->pid); if(child!= NULL) { child->parent_pid = INVALID_PID; } kfree(search_node); return 0; } last_node = search_node; search_node = search_node->next; } return -1; } bool pid_is_child(pid_t child_pid, pid_t parent_pid) { struct pid_node *parent = pid_head; while(parent != NULL) { if(parent->pid == parent_pid) { break; } parent = parent->next; } if(parent->pid != parent_pid) { return false; } struct child_node *search_node = parent->child_list; while(search_node != NULL) { // insert at tail if(search_node->pid == child_pid) { return true; } search_node = search_node->next; } return false; }