• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)26 void 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)57 struct 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)104 void 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