1 /* 2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU) 3 * Licensed under the Mulan PSL v2. 4 * You can use this software according to the terms and conditions of the Mulan PSL v2. 5 * You may obtain a copy of Mulan PSL v2 at: 6 * http://license.coscl.org.cn/MulanPSL2 7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR 8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR 9 * PURPOSE. 10 * See the Mulan PSL v2 for more details. 11 */ 12 #include <machine.h> 13 #include <sched/sched.h> 14 #include <mm/kmalloc.h> 15 #include <common/util.h> 16 #include <common/kprint.h> 17 #include <object/thread.h> 18 19 /* Extern functions */ 20 void arch_init_thread_fpu(struct thread_ctx *ctx); 21 void arch_free_thread_fpu(struct thread_ctx *ctx); 22 23 /* Each CPU has one lock */ 24 struct lock fpu_owner_locks[PLAT_CPU_NUM]; 25 init_fpu_owner_locks(void)26void init_fpu_owner_locks(void) 27 { 28 int i; 29 30 for (i = 0; i < PLAT_CPU_NUM; ++i) 31 lock_init(&fpu_owner_locks[i]); 32 } 33 34 /* 35 * When CHCORE_KERNEL_RT is defined: 36 * 37 * The kernel stack for a thread looks like: 38 * 39 * High addr 40 * ---------- thread_ctx end: kernel_stack_base + DEFAULT_KERNEL_STACK_SZ 41 * (0x1000) 42 * ... 43 * other fields in the thread_ctx: 44 * e.g., fpu_state, tls_state, sched_ctx 45 * ... 46 * execution context (e.g., registers) 47 * ---------- thread_ctx 48 * ... 49 * ... 50 * stack in use for when the thread enters kernel 51 * ... 52 * ... 53 * ---------- kernel_stack_base 54 * Low addr 55 * 56 */ create_thread_ctx(unsigned int type)57struct thread_ctx *create_thread_ctx(unsigned int type) 58 { 59 struct thread_ctx *ctx; 60 sched_ctx_t *sc; 61 62 63 #ifdef CHCORE_KERNEL_RT 64 void *kernel_stack = NULL; 65 kernel_stack = kzalloc(DEFAULT_KERNEL_STACK_SZ); 66 if (kernel_stack == NULL) { 67 kwarn("create_thread_ctx fails due to lack of memory\n"); 68 return NULL; 69 } 70 ctx = (struct thread_ctx *)(kernel_stack + DEFAULT_KERNEL_STACK_SZ 71 - sizeof(struct thread_ctx)); 72 #else 73 ctx = (struct thread_ctx *)kzalloc(sizeof(struct thread_ctx)); 74 if (ctx == NULL) { 75 kwarn("create_thread_ctx fails due to lack of memory\n"); 76 return NULL; 77 } 78 #endif 79 80 arch_init_thread_fpu(ctx); 81 82 /* Threads whose types are SHADOW or REGISTER don't have scheduling 83 * context. */ 84 if (type == TYPE_SHADOW || type == TYPE_REGISTER) { 85 ctx->sc = NULL; 86 } else { 87 /* Allocate a scheduling context for threads of other types */ 88 sc = kzalloc(sizeof(sched_ctx_t)); 89 if (sc == NULL) { 90 kwarn("create_thread_ctx fails due to lack of memory\n"); 91 #ifdef CHCORE_KERNEL_RT 92 kfree(kernel_stack); 93 #else 94 kfree(ctx); 95 #endif 96 return NULL; 97 } 98 ctx->sc = sc; 99 } 100 101 return ctx; 102 } 103 destroy_thread_ctx(struct thread * thread)104void destroy_thread_ctx(struct thread *thread) 105 { 106 unsigned int cpuid; 107 108 BUG_ON(!thread->thread_ctx); 109 110 if (thread->thread_ctx->is_fpu_owner >= 0) { 111 cpuid = thread->thread_ctx->cpuid; 112 lock(&fpu_owner_locks[cpuid]); 113 BUG_ON(cpu_info[cpuid].fpu_owner != thread); 114 cpu_info[cpuid].fpu_owner = NULL; 115 unlock(&fpu_owner_locks[cpuid]); 116 } 117 arch_free_thread_fpu(thread->thread_ctx); 118 119 /* Register or shadow threads do not have scheduling contexts */ 120 if (thread->thread_ctx->type != TYPE_SHADOW 121 && thread->thread_ctx->type != TYPE_REGISTER) { 122 BUG_ON(!thread->thread_ctx->sc); 123 kfree(thread->thread_ctx->sc); 124 } 125 126 if (thread->thread_ctx->type == TYPE_SHADOW 127 && thread->thread_ctx->state == TS_EXIT 128 && thread->thread_ctx->sc != NULL) { 129 kfree(thread->thread_ctx->sc); 130 } 131 132 #ifdef CHCORE_KERNEL_RT 133 void *kernel_stack; 134 135 kernel_stack = (void *)thread->thread_ctx - DEFAULT_KERNEL_STACK_SZ 136 + sizeof(struct thread_ctx); 137 kfree(kernel_stack); 138 #else 139 kfree(thread->thread_ctx); 140 #endif 141 } 142