bool init_pagetable(uintptr_t rounded_kernel_memory_end) { kernel_page_directory_num = rounded_kernel_memory_end / 0x200000; kernel_pml4 = create_pml4(); __asm__ volatile( "movq %0, %%cr3" ::"r"((uintptr_t)kernel_pml4 - START_KERNEL_MAP) : "memory"); return true; }
int create_process_base(uint8_t* image_data, int argc, char** argv, char** envp, proc_t** cpt, uint8_t asked_priority, registers_t* r) { proc_spinlock_lock(&__thread_modifier); uint8_t cpp = get_current_cput()->ct->parent_process->priority; proc_spinlock_unlock(&__thread_modifier); if (cpp > asked_priority) { return EINVAL; } int envc = 0; char** envt = envp; while (*envt != NULL) { ++envc; ++envt; } int err; if ((err = cpy_array(argc, &argv)) != 0) return err; if ((err = cpy_array(envc, &envp)) != 0) { free_array(argc, argv); return err; } // envp and argv are now kernel structures proc_t* process = malloc(sizeof(proc_t)); if (process == NULL) { return ENOMEM_INTERNAL; } memset(process, 0, sizeof(proc_t)); process->__ob_lock = 0; process->process_list.data = process; process->pprocess = true; process->fds = create_array(); if (process->fds == NULL) { free(process); return ENOMEM_INTERNAL; } process->threads = create_array(); if (process->fds == NULL) { destroy_array(process->fds); free(process); return ENOMEM_INTERNAL; } process->mem_maps = NULL; process->proc_random = rg_create_random_generator(get_unix_time()); process->parent = NULL; process->priority = asked_priority; process->pml4 = create_pml4(); if (process->pml4 == 0) { destroy_array(process->fds); free(process); return ENOMEM_INTERNAL; } process->futexes = create_uint64_table(); if (process->futexes == NULL) { destroy_array(process->threads); destroy_array(process->fds); free(process); return ENOMEM_INTERNAL; } process->input_buffer = create_queue_static(__message_getter); if (process->input_buffer == NULL) { destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); return ENOMEM_INTERNAL; } process->pq_input_buffer = create_queue_static(__message_getter); if (process->input_buffer == NULL) { free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); return ENOMEM_INTERNAL; } process->blocked_wait_messages = create_list_static(__message_getter); if (process->blocked_wait_messages == NULL) { free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); return ENOMEM_INTERNAL; } process->temp_processes = create_list_static(__process_get_function); if (process->blocked_wait_messages == NULL) { free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); return ENOMEM_INTERNAL; } thread_t* main_thread = malloc(sizeof(thread_t)); if (main_thread == NULL) { free_list(process->temp_processes); free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); // TODO: free process address page return ENOMEM_INTERNAL; } memset(main_thread, 0, sizeof(thread_t)); main_thread->parent_process = process; main_thread->priority = asked_priority; main_thread->blocked = false; main_thread->continuation = malloc(sizeof(continuation_t)); if (main_thread->continuation == NULL) { free(main_thread); free_list(process->temp_processes); free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); // TODO: free process address page return ENOMEM_INTERNAL; } main_thread->continuation->present = false; main_thread->futex_block = create_list_static(__blocked_getter); if (main_thread->futex_block == NULL) { free(main_thread->continuation); free(main_thread); free_list(process->temp_processes); free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); // TODO: free process address page return ENOMEM_INTERNAL; } array_push_data(process->threads, main_thread); err = load_elf_exec((uintptr_t)image_data, process); if (err == ELF_ERROR_ENOMEM) { err = ENOMEM_INTERNAL; } else if (err != 0) { err = EINVAL; } if (err != 0) { free_list(main_thread->futex_block); free(main_thread->continuation); free(main_thread); free_list(process->temp_processes); free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); // TODO: free process address page return err; } char** argvu = argv; char** envpu = envp; if ((err = cpy_array_user(argc, &argvu, process)) != 0) { free_list(main_thread->futex_block); free(main_thread->continuation); free(main_thread); free_list(process->temp_processes); free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); // TODO: free process address page return err; } if ((err = cpy_array_user(envc, &envpu, process)) != 0) { free_list(main_thread->futex_block); free(main_thread->continuation); free(main_thread); free_list(process->temp_processes); free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); // TODO: free process address page return err; } main_thread->local_info = proc_alloc_direct(process, sizeof(tli_t)); if (main_thread->local_info == NULL) { free_list(main_thread->futex_block); free(main_thread->continuation); free(main_thread); free_list(process->temp_processes); free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); // TODO: free process address page return ENOMEM_INTERNAL; } tli_t* li = different_page_mem(process->pml4, main_thread->local_info); li->self = main_thread->local_info; for (int i=0; i<MESSAGE_BUFFER_CNT; i++) { _message_t* m = &process->output_buffer[i]; m->owner = process; m->used = false; m->message = proc_alloc_direct(process, 0x200000); if (m->message == NULL) { free_list(main_thread->futex_block); free(main_thread->continuation); free(main_thread); free_list(process->temp_processes); free_list(process->blocked_wait_messages); free_queue(process->pq_input_buffer); free_queue(process->input_buffer); destroy_table(process->futexes); destroy_array(process->threads); destroy_array(process->fds); free(process); // TODO: free process address page return ENOMEM_INTERNAL; } } process->argc = argc; process->argv = argvu; process->environ = envpu; main_thread->last_r12 = 0; main_thread->last_r11 = 0; main_thread->last_r10 = 0; main_thread->last_r9 = 0; main_thread->last_r8 = 0; main_thread->last_rax = 0; main_thread->last_rbx = 0; main_thread->last_rcx = 0; main_thread->last_rdx = 0; main_thread->last_rdi = 0; main_thread->last_rsi = 0; main_thread->last_rbp = 0; main_thread->last_rflags = 0x200; // enable interrupts proc_spinlock_lock(&__proclist_lock); main_thread->tId = __atomic_add_fetch(&thread_id_num, 1, __ATOMIC_SEQ_CST); process->proc_id = ++process_id_num; list_push_right(processes, process); proc_spinlock_unlock(&__proclist_lock); li->t = main_thread->tId; main_thread->last_rdi = (ruint_t)(uintptr_t)process->argc; main_thread->last_rsi = (ruint_t)(uintptr_t)process->argv; main_thread->last_rdx = (ruint_t)(uintptr_t)process->environ; main_thread->blocked_list.data = main_thread; main_thread->schedule_list.data = main_thread; free_array(argc, argv); free_array(envc, envp); // TODO: add split option? main_thread->last_rax = process->proc_id; enschedule_best(main_thread); *cpt = process; return 0; }