• 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 <assert.h>
13 #include <string.h>
14 #include <time.h>
15 #include <stdbool.h>
16 #include <sys/mman.h>
17 #include <chcore/idman.h>
18 #include <chcore-internal/fs_defs.h>
19 #include <chcore/container/hashtable.h>
20 #include <chcore/proc.h>
21 
22 #include "proc_node.h"
23 #include "procmgr_dbg.h"
24 #include "srvmgr.h"
25 #ifdef CHCORE_OH_TEE
26 #include "oh_mem_ops.h"
27 #endif /* CHCORE_OH_TEE */
28 
29 /* For synchronization */
30 static pthread_mutex_t proc_nodes_lock;
31 
32 /* For allocating pid to proc_node */
33 static struct id_manager pid_mgr;
34 static const int PID_MAX = 1024 * 1024;
35 
36 /* Map: client_badge -> proc_node */
37 /*
38  * We use client_badge as the index of procnode.
39  */
40 static struct htable badge2proc;
41 #ifdef CHCORE_OH_TEE
42 static struct htable pid2proc;
43 #endif /* CHCORE_OH_TEE */
44 
45 /* Max number of pcid on x86_64 is different from that (ASID) on aarch64. */
46 static struct id_manager pcid_mgr;
47 #if defined(CHCORE_ARCH_X86_64)
48 static const int PCID_MAX = 1 << 12;
49 #elif defined(CHCORE_ARCH_AARCH64)
50 static const int PCID_MAX = 1 << 16;
51 #elif defined(CHCORE_ARCH_RISCV64)
52 static const int PCID_MAX = 1 << 16;
53 #elif defined(CHCORE_ARCH_SPARC)
54 static const int PCID_MAX = 1 << 16;
55 #else
56 #error "Unsupported architecture"
57 #endif
58 
59 #define HASH_TABLE_SIZE 509
60 /*
61  * PCID in range [0,10) is reserved for boot page table, root process,
62  * fsm, fs, lwip, procmgr and future servers (pcid 0 is not used).
63  * Thus the user apps' pcid starts at 10. (10 is used by init process)
64  */
65 static const int MAX_RESERVED_PCID = 10;
66 
67 /* Only for handle_init */
68 static struct proc_node *proc_init;
69 
generate_server_badge(void)70 static inline badge_t generate_server_badge(void)
71 {
72     static badge_t cur_server_badge = MIN_FREE_SERVER_BADGE;
73     BUG_ON(++cur_server_badge >= MIN_FREE_DRIVER_BADGE);
74     return cur_server_badge;
75 }
76 
generate_driver_badge(void)77 static inline badge_t generate_driver_badge(void)
78 {
79     static badge_t cur_driver_badge = MIN_FREE_DRIVER_BADGE;
80     BUG_ON(++cur_driver_badge >= MIN_FREE_APP_BADGE);
81     return cur_driver_badge;
82 }
83 
generate_app_badge(void)84 static inline badge_t generate_app_badge(void)
85 {
86     static badge_t cur_app_badge = MIN_FREE_APP_BADGE;
87     return cur_app_badge++;
88 }
89 
__new_proc_node(struct proc_node * parent,char * name)90 static struct proc_node *__new_proc_node(struct proc_node *parent, char *name)
91 {
92     struct proc_node *proc = malloc(sizeof(*proc));
93     assert(proc);
94 
95     /* Alloc pid */
96     pthread_mutex_lock(&proc_nodes_lock);
97     proc->pid = alloc_id(&pid_mgr);
98     BUG_ON(proc->pid == -EINVAL);
99     pthread_mutex_unlock(&proc_nodes_lock);
100 
101     proc->name = name;
102     proc->parent = parent;
103     proc->state = PROC_STATE_INIT;
104     pthread_mutex_init(&proc->lock, NULL);
105     if (proc->parent) {
106         /* Add this proc to parent's child list. */
107         pthread_mutex_lock(&parent->lock);
108         list_add(&proc->node, &proc->parent->children);
109         pthread_mutex_unlock(&parent->lock);
110     }
111     init_list_head(&proc->children);
112     init_hlist_node(&proc->hash_node);
113 #ifdef CHCORE_OH_TEE
114     init_hlist_node(&proc->pid_hash_node);
115 #endif /* CHCORE_OH_TEE */
116 
117     return proc;
118 }
119 
init_proc_node_mgr(void)120 void init_proc_node_mgr(void)
121 {
122     init_id_manager(&pid_mgr, PID_MAX, DEFAULT_INIT_ID);
123 
124     pthread_mutex_init(&proc_nodes_lock, NULL);
125     pthread_mutex_init(&recycle_lock, NULL);
126     /* Reserve the pcid for root process and servers. */
127     init_id_manager(&pcid_mgr, PCID_MAX, MAX_RESERVED_PCID);
128 
129     init_htable(&badge2proc, HASH_TABLE_SIZE);
130 #ifdef CHCORE_OH_TEE
131     init_htable(&pid2proc, HASH_TABLE_SIZE);
132 #endif /* CHCORE_OH_TEE */
133 }
134 
135 /*
136  * The name here should be a newly allocated memory that can be directly stored
137  * (and sometime later freed) in the proc_node.
138  */
new_proc_node(struct proc_node * parent,char * name,int proc_type)139 struct proc_node *new_proc_node(struct proc_node *parent, char *name,
140                                 int proc_type)
141 {
142     struct proc_node *proc = __new_proc_node(parent, name);
143 
144     pthread_mutex_lock(&proc_nodes_lock);
145 
146     /* Alloc pcid */
147     if (strcmp(name, "procmgr") == 0 && proc_type == SYSTEM_SERVER) {
148         proc->pcid = PROCMGR_PCID;
149         proc->badge = PROCMGR_BADGE;
150     } else if (strcmp(name, "fsm") == 0 && proc_type == SYSTEM_SERVER) {
151         proc->pcid = FSM_PCID;
152         proc->badge = FSM_BADGE;
153     } else if (strcmp(name, "lwip") == 0 && proc_type == SYSTEM_SERVER) {
154         proc->pcid = LWIP_PCID;
155         proc->badge = LWIP_BADGE;
156     } else if (proc_type == SYSTEM_SERVER) {
157         proc->pcid = alloc_id(&pcid_mgr);
158         proc->badge = generate_server_badge();
159     } else if (proc_type == SYSTEM_DRIVER) {
160         proc->pcid = alloc_id(&pcid_mgr);
161         proc->badge = generate_driver_badge();
162     } else if (proc_type == COMMON_APP) {
163         proc->pcid = alloc_id(&pcid_mgr);
164         proc->badge = generate_app_badge();
165     } else {
166         warn("new proc failed, proc type error %d\n", proc_type);
167         return NULL;
168     }
169     BUG_ON(proc->pcid == -EINVAL);
170 
171     /* Generate badge and add to htable */
172     htable_add(&badge2proc, proc->badge, &proc->hash_node);
173 #ifdef CHCORE_OH_TEE
174     htable_add(&pid2proc, proc->pid, &proc->pid_hash_node);
175 #endif /* CHCORE_OH_TEE */
176 
177     pthread_mutex_init(&proc->wait_lock, NULL);
178     pthread_cond_init(&proc->wait_cv, NULL);
179 
180     pthread_mutex_unlock(&proc_nodes_lock);
181     debug("alloc pcid = %d\n", proc->pcid);
182     return proc;
183 }
184 
free_proc_node_resource(struct proc_node * proc)185 void free_proc_node_resource(struct proc_node *proc)
186 {
187     int pid;
188     int pcid;
189 
190     pthread_mutex_lock(&proc_nodes_lock);
191 
192     pid = proc->pid;
193     pcid = (int)proc->pcid;
194 
195     /* Just delete the node in the hash table. Free proc later. */
196     htable_del(&proc->hash_node);
197 #ifdef CHCORE_OH_TEE
198     htable_del(&proc->pid_hash_node);
199     clean_sharemem(proc->badge);
200 #endif /* CHCORE_OH_TEE */
201 
202     free_id(&pid_mgr, pid);
203     free_id(&pcid_mgr, pcid);
204     debug("free pcid = %d\n", pcid);
205 
206     if (proc->name)
207         free(proc->name);
208     pthread_mutex_unlock(&proc_nodes_lock);
209 }
210 
211 /* Free the resource allocated in new_proc_node in a reverse order */
del_proc_node(struct proc_node * proc)212 void del_proc_node(struct proc_node *proc)
213 {
214     struct proc_node *child;
215     struct proc_node *tmp;
216 
217     BUG_ON(proc->state != PROC_STATE_EXIT);
218 
219     /*
220      * Step 1. Set the child proc node as orphan, delete the child list of
221      * the proc node and free all exited child node.
222      */
223     for_each_in_list_safe (child, tmp, node, &proc->children) {
224         child->parent = NULL;
225         /*
226          * NOTE: If we need keep the relationship between the child of the
227          * proc_node, we need append the child node to a new process(such
228          * as init).
229          */
230         /* Recycle exited child proc node. */
231         if (child->state == PROC_STATE_EXIT) {
232             free_proc_node_resource(child);
233             free(child);
234         }
235     }
236 
237     /*
238      * Step2. If the proc is orphan, free the proc node.
239      */
240     if (!proc->parent) {
241         free_proc_node_resource(proc);
242         free(proc);
243     }
244 }
245 
get_proc_node(badge_t client_badge)246 struct proc_node *get_proc_node(badge_t client_badge)
247 {
248     struct proc_node *proc;
249     struct hlist_head *buckets;
250 
251     pthread_mutex_lock(&proc_nodes_lock);
252     buckets = htable_get_bucket(&badge2proc, client_badge);
253 
254     for_each_in_hlist (proc, hash_node, buckets) {
255         if (client_badge == proc->badge) {
256             goto out;
257         }
258     }
259     /* NOTE: It should be reconstroction. */
260     pthread_mutex_unlock(&proc_nodes_lock);
261     return NULL;
262 out:
263     debug("Find badge = 0x%x, get proc = %p\n", client_badge, proc);
264     pthread_mutex_unlock(&proc_nodes_lock);
265 
266     return proc;
267 }
268 
269 #ifdef CHCORE_OH_TEE
get_proc_node_by_pid(int pid)270 struct proc_node *get_proc_node_by_pid(int pid)
271 {
272     struct proc_node *proc;
273     struct hlist_head *buckets;
274 
275     pthread_mutex_lock(&proc_nodes_lock);
276     buckets = htable_get_bucket(&pid2proc, pid);
277 
278     for_each_in_hlist (proc, pid_hash_node, buckets) {
279         if (pid == proc->pid) {
280             goto out;
281         }
282     }
283     /* NOTE: It should be reconstroction. */
284     pthread_mutex_unlock(&proc_nodes_lock);
285     return NULL;
286 out:
287     debug("Find pid = %d, get proc = %p\n", pid, proc);
288     pthread_mutex_unlock(&proc_nodes_lock);
289 
290     return proc;
291 }
292 #endif /* CHCORE_OH_TEE */
293 
init_root_proc_node(void)294 void init_root_proc_node(void)
295 {
296     /* Init the init node. */
297     proc_init = new_proc_node(NULL, strdup("procmgr"), SYSTEM_SERVER);
298     htable_add(&badge2proc, proc_init->badge, &proc_init->hash_node);
299 #ifdef CHCORE_OH_TEE
300     htable_add(&pid2proc, proc_init->pid, &proc_init->pid_hash_node);
301 #endif /* CHCORE_OH_TEE */
302 
303     __sync_synchronize();
304 }
305