• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
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 
13 #include "tee_task.h"
14 #include "spawn_ext.h"
15 #include <sys/wait.h>
16 #include <signal.h>
17 #include <inttypes.h>
18 
19 #include <stdio.h>
20 #include <elf.h>
21 #include <fileio.h>
22 #include <priorities.h>
23 #include <drv.h>
24 #include <spawn_init.h>
25 #include <get_elf_info.h>
26 #include <target_type.h>
27 
28 #include "ta_framework.h"
29 #include "tee_log.h"
30 #include "tee_config.h"
31 #include "gtask_config_hal.h"
32 
33 #include <string.h>
34 #include "ipclib.h"
35 #include "securec.h"
36 #include "uuid2path.h"
37 #include "timer.h"
38 
39 #include "gtask_core.h" /* for session_struct */
40 #include "session_manager.h"
41 
42 #include "task_adaptor_pub.h"
43 #include "init.h"
44 #include "dynload.h"
45 #include <ipclib_hal.h>
46 
47 #define MAX_PATH_NAME_LEN 64
48 #define PAGES_FOR_STACK   2
49 
50 #define CREATE_THREAD_FAIL  0xFFFFFFFFU
51 #if defined(CONFIG_OFF_DRV_TIMER) && defined(CONFIG_ARCH_AARCH64)
52 #define TASK_TIMEOUT 2000
53 #else
54 #define TASK_TIMEOUT 0xFFFFFFFFU
55 #endif
ta_name_to_path(const struct service_struct * service,char * path_name,size_t len,int * p_priority)56 static TEE_Result ta_name_to_path(const struct service_struct *service,
57                                   char *path_name, size_t len, int *p_priority)
58 {
59     uint32_t i;
60     uint32_t builtin_task_num = get_builtin_task_nums();
61 
62     if (service == NULL || len > MAX_PATH_NAME_LEN)
63         return TEE_ERROR_BAD_PARAMETERS;
64 
65     /* search builtin tasks first */
66     for (i = 0; i < builtin_task_num; i++) {
67         const struct task_info_st *builtin_task_info = get_builtin_task_info_by_index(i);
68         if (builtin_task_info == NULL)
69             break;
70 
71         if (strncmp(service->name, builtin_task_info->name, strlen(builtin_task_info->name) + 1) == 0) {
72             if (strncpy_s(path_name, len, builtin_task_info->path, strlen(builtin_task_info->path)) == EOK) {
73                 /* set priority for buitlin task */
74                 *p_priority = builtin_task_info->priority;
75                 return TEE_SUCCESS;
76             }
77             return TEE_ERROR_GENERIC;
78         }
79     }
80 
81     /* set default priority for normal dynload task */
82     *p_priority = PRIO_TEE_TA;
83 
84     /* for dynload task, use uuid as path */
85     if (uuid_to_fname(&service->property.uuid, path_name, (int)len) == 0)
86         return TEE_SUCCESS;
87 
88     tloge("%s uuid_to_fname error!\n", service->name);
89 
90     return TEE_ERROR_ITEM_NOT_FOUND;
91 }
92 
93 #define WAIT_MAX 5
gt_wait_process(uint32_t task_id)94 void gt_wait_process(uint32_t task_id)
95 {
96     int i;
97     int wstatus;
98 
99     (void)ipc_release_from_taskid(task_id, 0);
100     for (i = 0; i < WAIT_MAX; i++) {
101         if (wait(&wstatus) == (pid_t)taskid_to_pid(task_id)) {
102             tlogd("wait %" PRIu32 " exit succeeded\n", task_id);
103             break;
104         }
105     }
106     if (i == WAIT_MAX)
107         tloge("wait %" PRIu32 " exit failed\n", task_id);
108 }
109 
start_timeout(void)110 static timer_event *start_timeout(void)
111 {
112 #if (!defined CONFIG_OFF_TIMER) && (!defined CONFIG_OFF_DRV_TIMER)
113     struct timer_private_data_kernel dummy = { 0 };
114     timeval_t val;
115 
116     dummy.dev_id = 1;
117     dummy.type   = TIMER_CALLBACK_TIMEOUT;
118 
119     timer_event *event = tee_time_event_create(NULL, TIMER_GENERIC, (void *)(&dummy));
120     if (event == NULL) {
121         tloge("create timer failed\n");
122         return NULL;
123     }
124 
125     /* wait for 2 seconds */
126     val.tval.sec  = 2;
127     val.tval.nsec = 0;
128     if (tee_time_event_start(event, &val) != 0)
129         tloge("start timer failed\n");
130     return event;
131 #else
132     return NULL;
133 #endif
134 }
135 
stop_timeout(timer_event * event)136 static void stop_timeout(timer_event *event)
137 {
138     if (event == NULL)
139         return;
140 
141 #if (!defined CONFIG_OFF_TIMER) && (!defined CONFIG_OFF_DRV_TIMER)
142     if (tee_time_event_stop(event) != 0)
143         tloge("stop timer failed\n");
144 
145     if (tee_time_event_destroy(event) != 0)
146         tloge("destroy timer failed\n");
147 #endif
148 }
149 
gt_create_thread(pid_t * pid)150 static int gt_create_thread(pid_t *pid)
151 {
152     struct global_to_service_thread_msg entry_msg = { { { 0 } } };
153     uint32_t msg_id;
154     taskid_t sender_pid;
155     uint32_t rc;
156     uint64_t stack_size;
157 
158     if (get_cur_service() == NULL || get_cur_service()->service_thread == 0)
159         return NORMAL_FAIL_RET;
160 
161     stack_size = get_cur_service()->property.stack_size;
162     if (stack_size > MAX_STACK_SIZE) {
163         tloge("Stack is too large 0x%" PRIx32 "\n", stack_size);
164         return NORMAL_FAIL_RET;
165     }
166 
167     entry_msg.create_msg.stack_size = stack_size + PAGE_SIZE;
168     if (entry_msg.create_msg.stack_size <= stack_size) {
169         tloge("stack size overflow\n");
170         return NORMAL_FAIL_RET;
171     }
172 
173     rc = ipc_msg_snd(CALL_TA_CREATE_THREAD, get_cur_service()->service_thread, &entry_msg, sizeof(entry_msg));
174     if (rc != 0) {
175         tloge("CALL_TA_CRTEATE_THREAD msg send failed:0x%" PRIx32 "\n", rc);
176         return NORMAL_FAIL_RET;
177     }
178     /*
179      * wait at Q#1 for ACK message from "worker_thread" created by service thread,
180      * drop messages from other sources.
181      */
182     timer_event *event = start_timeout();
183     do {
184         if (ipc_msg_q_recv(&msg_id, &sender_pid, 1, TASK_TIMEOUT) != 0) {
185             stop_timeout(event);
186             tloge("CALL_TA_CRTEATE_THREAD msg QRecv failed\n");
187             return NORMAL_FAIL_RET;
188         }
189         if (taskid_to_pid(sender_pid) == get_timer_pid() && msg_id == TIMER_CALLBACK_TIMEOUT) {
190             stop_timeout(event);
191             tloge("CALL_TA_CREATE_THREAD timeout\n");
192             return TIMEOUT_FAIL_RET;
193         }
194     } while (taskid_to_pid(sender_pid) != taskid_to_pid(get_cur_service()->service_thread));
195     stop_timeout(event);
196     tlogd("gtask get tid 0x%" PRIx32 " from pid 0x%" PRIx32 "\n", msg_id, sender_pid);
197 
198     if (msg_id == CREATE_THREAD_FAIL) {
199         tloge("gtask create TA create failed\n");
200         return NORMAL_FAIL_RET;
201     }
202 
203     *pid = (int)sender_pid;
204 
205     return SUCC_RET;
206 }
207 
gt_recycle_thread(uint32_t task_id,uint32_t session_id)208 static int gt_recycle_thread(uint32_t task_id, uint32_t session_id)
209 {
210     struct global_to_service_thread_msg entry_msg = { { { 0 } } };
211     uint32_t msg_id;
212     taskid_t pid = 0;
213     uint32_t rc;
214 
215     if (get_cur_service() == NULL || get_cur_service()->service_thread == 0)
216         return NORMAL_FAIL_RET;
217 
218     msg_id = CALL_TA_REMOVE_THREAD;
219     tlogd("Recycle thread %s task_id %" PRIx32 " msgid = 0x%" PRIx32 "\n", get_cur_service()->name, task_id, msg_id);
220 
221     entry_msg.remove_msg.tid = taskid_to_tid(task_id);
222     entry_msg.remove_msg.session_id = session_id;
223     rc = ipc_msg_snd(msg_id, get_cur_service()->service_thread, &entry_msg, sizeof(entry_msg));
224     if (rc != 0) {
225         tloge("recycle msg 0x%" PRIx32 " send failed:0x%" PRIx32 "\n", msg_id, rc);
226         return NORMAL_FAIL_RET;
227     }
228 
229     /*
230      * wait at Q#1 for ACK message from get_cur_service()->service_thread,
231      * drop messages from other sources.
232      */
233     timer_event *event = start_timeout();
234     do {
235         if (ipc_msg_q_recv(&msg_id, &pid, 1, TASK_TIMEOUT) != 0) {
236             stop_timeout(event);
237             tloge("recycle msg QRecv failed\n");
238             return NORMAL_FAIL_RET;
239         }
240         if (taskid_to_pid(pid) == get_timer_pid() && msg_id == TIMER_CALLBACK_TIMEOUT) {
241             stop_timeout(event);
242             tloge("CALL_TA_REMOVE_THREAD timeout\n");
243             return TIMEOUT_FAIL_RET;
244         }
245     } while (pid != get_cur_service()->service_thread);
246     stop_timeout(event);
247 
248     /* "invalid tid" is the the only case for this */
249     if (msg_id != 0) {
250         tloge("recycle failed, ret=%" PRIu32 "\n", msg_id);
251         return NORMAL_FAIL_RET;
252     }
253 
254     return SUCC_RET;
255 }
256 
decide_executer(const char * ehdr,uint32_t ehdr_size,int32_t fd)257 static int32_t decide_executer(const char *ehdr, uint32_t ehdr_size, int32_t fd)
258 {
259     (void)fd;
260     int32_t elf_class = get_elf_class(ehdr, ehdr_size);
261     int32_t elf_type  = get_elf_type(ehdr, ehdr_size, elf_class);
262 
263     tlogd("elf_class: %d, elf type: %d\n", elf_class, elf_type);
264 
265     if (elf_type == ET_REL)
266         return ELF_NOT_SUPPORT;
267 
268     if (elf_type == ET_DYN)
269         return ELF_TARUNNER;
270 
271     tloge("unsupported elf type\n");
272     return ELF_NOT_SUPPORT;
273 }
274 
275 #define EH_SIZE sizeof(Elf64_Ehdr)
276 
check_binary_type(const char * name)277 static int check_binary_type(const char *name)
278 {
279     int ldr = ELF_NOT_SUPPORT;
280     char ehdr[EH_SIZE];
281 
282     int fd = open(name, O_RDONLY);
283     if (fd < 0) {
284         tloge("cannot open file %d\n", fd);
285         return ldr;
286     }
287 
288     if (read(fd, ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
289         tloge("read file failed, name=%s\n", name);
290         goto close_fd;
291     }
292 
293     ldr = decide_executer(ehdr, sizeof(ehdr), fd);
294 
295 close_fd:
296     close(fd);
297     return ldr;
298 }
299 
set_stack_size(posix_spawnattr_t * spawnattr)300 static int32_t set_stack_size(posix_spawnattr_t *spawnattr)
301 {
302     uint64_t total_size;
303     uint64_t stack_size = (get_cur_service()->property).stack_size;
304 
305     if (stack_size > MAX_STACK_SIZE) {
306         tloge("Stack is too large 0x%" PRIx32 "\n", get_cur_service()->property.stack_size);
307         return -1;
308     }
309 
310     /* rdr log buffer and msg_recv buffer need more stack */
311     total_size = stack_size + PAGE_SIZE;
312     if (total_size <= stack_size) {
313         tloge("stack size overflow!\n");
314         return -1;
315     }
316 
317     if (total_size < PAGE_SIZE * PAGES_FOR_STACK)
318         total_size = PAGE_SIZE * PAGES_FOR_STACK;
319 
320     return spawnattr_setstack(spawnattr, total_size);
321 }
322 
get_mem_total_size(uint64_t * size)323 static int32_t get_mem_total_size(uint64_t *size)
324 {
325     uint64_t heap_size;
326     uint64_t stack_size;
327     uint64_t total_size;
328     uint64_t tmp_size;
329 
330     heap_size = (get_cur_service()->property).heap_size;
331     stack_size = get_cur_service()->property.stack_size;
332 
333     if ((get_cur_service()->property).multi_session == true) {
334         tmp_size = stack_size * TA_STACK_MAX;
335         if (tmp_size <= stack_size) {
336             tloge("size overflow!\n");
337             return -1;
338         }
339         total_size = heap_size + tmp_size;
340     } else {
341         tmp_size = stack_size;
342         total_size = heap_size + tmp_size;
343     }
344 
345     if (total_size <= heap_size || total_size <= tmp_size) {
346         tloge("size overflow!\n");
347         return -1;
348     }
349     *size = total_size;
350     return 0;
351 }
352 
tee_spawn_with_attr(int * ptask_id,const char * elf_path,char * argv[],char * env[],const spawn_uuid_t * uuid)353 static int tee_spawn_with_attr(int *ptask_id, const char *elf_path, char *argv[], char *env[],
354                               const spawn_uuid_t *uuid)
355 {
356     pid_t pid;
357     tid_t tid;
358     posix_spawnattr_t spawnattr;
359     uint64_t heap_size;
360 
361     if (spawnattr_init(&spawnattr) != 0)
362         return -1;
363 
364     if (get_cur_service() == NULL)
365         return -1;
366 
367     if (set_stack_size(&spawnattr) != 0) {
368         tloge("set stack size failed\n");
369         return -1;
370     }
371 
372     spawnattr_setuuid(&spawnattr, uuid);
373 
374     if (get_mem_total_size(&heap_size) != 0)
375         return -1;
376 
377     if (spawnattr_setheap(&spawnattr, heap_size) != 0)
378         return -1;
379 
380     if (posix_spawn_ex(&pid, elf_path, NULL, &spawnattr, argv, env, &tid) != 0)
381         return -1;
382 
383     /* build task_id by pid and tid */
384     if (ptask_id != NULL)
385         *ptask_id = pid_to_taskid((uint32_t)tid, (uint32_t)pid);
386 
387     return 0;
388 }
389 
get_elf_path(int32_t bin_type,char * loader_path,uint32_t loader_path_size)390 static int32_t get_elf_path(int32_t bin_type, char *loader_path, uint32_t loader_path_size)
391 {
392     if (get_cur_service()->ta_64bit == true) {
393         if (memcpy_s(loader_path, loader_path_size, "/tarunner.elf", sizeof("/tarunner.elf")) != EOK) {
394             tloge("set loader tarunner fail\n");
395             return -1;
396         }
397     } else if (bin_type == ELF_TARUNNER) {
398         if (memcpy_s(loader_path, loader_path_size, "/tarunner_a32.elf", sizeof("/tarunner_a32.elf")) != EOK) {
399             tloge("set loader tarunner a32 fail\n");
400             return -1;
401         }
402     } else {
403         tloge("unsupported elf type\n");
404         return -1;
405     }
406 
407     return 0;
408 }
409 
wait_srvc_thread_message(struct msg_recv_param * msg_recv_p,uint32_t * task_id,taskid_t service_thread)410 static void wait_srvc_thread_message(struct msg_recv_param *msg_recv_p, uint32_t *task_id, taskid_t service_thread)
411 {
412     /*
413      * wait at Q#1 for ACK message from "worker_thread" created by
414      * service thread, drop messages from other sources.
415      */
416     timer_event *event = start_timeout();
417     do {
418         if (ipc_msg_q_recv(&(msg_recv_p->msg_id), task_id, 1, TASK_TIMEOUT) != 0)
419             tloge("gtask get tid failed\n");
420         if (taskid_to_pid(*task_id) == get_timer_pid() && msg_recv_p->msg_id == TIMER_CALLBACK_TIMEOUT) {
421             tloge("spawn multi-session TA timeout\n");
422             msg_recv_p->msg_id = CREATE_THREAD_FAIL;
423             break;
424         }
425     } while (taskid_to_pid(*task_id) != taskid_to_pid(service_thread));
426     stop_timeout(event);
427     tlogd("gtask get tid 0x%" PRIx32 " from pid 0x%" PRIx32 "\n", msg_recv_p->msg_id, task_id);
428 }
429 
create_service_thread(const char * elf_path,char ** argv,char ** env,const spawn_uuid_t * uuid,uint32_t * puw_pid)430 static int32_t create_service_thread(const char *elf_path, char **argv, char **env,
431                                      const spawn_uuid_t *uuid, uint32_t *puw_pid)
432 {
433     taskid_t service_thread = 0;
434     uint32_t task_id         = 0;
435     struct msg_recv_param msg_recv_p;
436     int32_t ret;
437 
438     ret = tee_spawn_with_attr((int *)&service_thread, elf_path, argv, env, uuid);
439     if (ret != 0)
440         return -1;
441 
442     wait_srvc_thread_message(&msg_recv_p, &task_id, service_thread);
443     /* create thread fail, kill service thread and return error */
444     if (msg_recv_p.msg_id == CREATE_THREAD_FAIL) {
445         if (kill((int)taskid_to_pid(service_thread), 0) == 0)
446             gt_wait_process(service_thread);
447         else
448             tloge("kill BAD service thread failed\n");
449         return -1;
450     }
451     // record service_thread to current service
452     get_cur_service()->service_thread = service_thread;
453     *puw_pid                          = task_id;
454     /* send msg to internal service */
455     task_adapt_ta_create(taskid_to_pid(service_thread), &((get_cur_service()->property).uuid));
456     return 0;
457 }
458 
set_argv_for_tsk(struct argv_base_buffer * argv,char * loader_path,uint32_t loader_path_size,const char * path_name,uint32_t path_name_size)459 static int set_argv_for_tsk(struct argv_base_buffer *argv, char *loader_path, uint32_t loader_path_size,
460     const char *path_name, uint32_t path_name_size)
461 {
462     int bin_type = check_binary_type(path_name);
463     if (bin_type < ELF_NATIVE)
464         return -EINVAL;
465 
466     if (ta_no_uncommit(&((get_cur_service()->property).uuid))) {
467         argv->uncommit[0] = 'n';
468         argv->uncommit[1] = 'o';
469         argv->uncommit[2] = '_';
470         argv->uncommit[3] = 'u';
471         argv->uncommit[4] = 'c';
472     }
473 
474     if (bin_type != ELF_NATIVE) {
475         if (get_elf_path(bin_type, loader_path, loader_path_size) != 0)
476             return -EINVAL;
477 
478         if (memcpy_s(argv->elf_path, sizeof(argv->elf_path), loader_path, loader_path_size) != EOK)
479             return -EINVAL;
480 
481         /* tasks load by  taloader and tarunner */
482         if (strncpy_s(argv->task_name, sizeof(argv->task_name), get_cur_service()->name,
483                       sizeof(get_cur_service()->name) - 1) != EOK)
484             return -EINVAL;
485         if (strncpy_s(argv->task_path, sizeof(argv->task_path), path_name, path_name_size - 1) != EOK)
486             return -EINVAL;
487 
488         /*
489          * During parameter transfer, '/0' is used to determine the parameter length.
490          * Multiple strings are transferred here, so replace '/0' with '#'
491          */
492         (void)memset_s(argv->client_name, sizeof(argv->client_name), '#', sizeof(argv->client_name));
493         argv->client_name[sizeof(argv->client_name) - 1] = '\0';
494         if (get_dyn_client_name(get_cur_service()->ta_64bit, argv->client_name,
495             sizeof(argv->client_name)) != 0)
496             tlogd("no dyn client exists\n");
497     } else {
498         if (memcpy_s(loader_path, loader_path_size, path_name, path_name_size) != EOK) {
499             tloge("native set loader path fail\n");
500             return -EINVAL;
501         }
502 
503         if (strncpy_s(argv->task_name, sizeof(argv->task_name), path_name, path_name_size) != EOK)
504             return -EINVAL;
505     }
506     return 0;
507 }
508 
init_spawn_buffer(struct spawn_buffer * sbuf,char ** argv,uint32_t argv_size,char ** env,uint32_t env_size)509 static int32_t init_spawn_buffer(struct spawn_buffer *sbuf, char **argv, uint32_t argv_size,
510     char **env, uint32_t env_size)
511 {
512     if (argv_size < ARGV_MAX || env_size < ENV_MAX) {
513         tloge("argv size:%u env size:%u invalid\n", argv_size, env_size);
514         return -1;
515     }
516 
517     env[ENV_PRIORITY_INDEX] = sbuf->env.priority;
518     env[ENV_UID_INDEX] = sbuf->env.uid;
519     env[ENV_TARGET_TYPE_INDEX] = sbuf->env.target_type;
520 
521     argv[ARGV_ELF_PATH_INDEX] = sbuf->argv.elf_path;
522     argv[ARGV_TASK_NAME_INDEX] = sbuf->argv.task_name;
523     argv[ARGV_TASK_PATH_INDEX] = sbuf->argv.task_path;
524     argv[ARGV_UNCOMMIT_INDEX] = sbuf->argv.uncommit;
525     argv[ARGV_CLIENT_NAME_INDEX] = sbuf->argv.client_name;
526 
527     return 0;
528 }
529 
init_spawn_argv_env(const struct tsk_init_param * init_param,struct spawn_buffer * sbuffer,char * loader_path,uint32_t loader_path_size)530 static int32_t init_spawn_argv_env(const struct tsk_init_param *init_param, struct spawn_buffer *sbuffer,
531     char *loader_path, uint32_t loader_path_size)
532 {
533     char path_name[MAX_PATH_NAME_LEN] = { 0 };
534 
535     struct env_param eparam = { 0 };
536     eparam.target_type = TA_TARGET_TYPE;
537 
538     /* get elf path for current service */
539     if (ta_name_to_path(get_cur_service(), path_name, sizeof(path_name), &(eparam.priority)) != TEE_SUCCESS)
540         return -EINVAL;
541 
542     if (set_env_for_task(&eparam, &(init_param->uuid), &(sbuffer->env)) != 0)
543         return -EINVAL;
544 
545     if (set_argv_for_tsk(&(sbuffer->argv), loader_path, loader_path_size,  path_name, sizeof(path_name)) != 0)
546         return -EINVAL;
547 
548     return 0;
549 }
550 
gt_create_proc(const struct tsk_init_param * init_param,uint32_t * task_id)551 static int gt_create_proc(const struct tsk_init_param *init_param, uint32_t *task_id)
552 {
553     char loader_path[MAX_PATH_NAME_LEN] = { 0 };
554     int ret;
555     char *argv[ARGV_MAX] = { NULL };
556     char *env[ENV_MAX] = { NULL }; /* need NULL-terminated */
557     spawn_uuid_t uuid = {0};
558 
559     /* make spawn_buffer in one page */
560     char buffer[2 * sizeof(struct spawn_buffer)] = { 0 };
561     struct spawn_buffer *sbuffer = (struct spawn_buffer *)&buffer;
562     if (((uintptr_t)buffer & (PAGE_SIZE - 1)) + sizeof(struct spawn_buffer) > PAGE_SIZE)
563         sbuffer = (struct spawn_buffer *)(buffer + sizeof(struct spawn_buffer));
564 
565     if (init_spawn_buffer(sbuffer, argv, ARGV_MAX, env, ENV_MAX) != 0)
566         return -1;
567 
568     if (init_spawn_argv_env(init_param, sbuffer, loader_path, sizeof(loader_path)) != 0)
569         return -1;
570 
571     if (memmove_s(&uuid.uuid, sizeof(uuid.uuid), &(init_param->uuid), sizeof(init_param->uuid)) != EOK) {
572         tloge("memmove uuid failed\n");
573         return -EINVAL;
574     }
575 
576     if (strncmp(loader_path, TAFS_MOUNTPOINT, strlen(TAFS_MOUNTPOINT)) == 0)
577         uuid.uuid_valid = 1;
578 
579     ret = create_service_thread(loader_path, argv, env, &uuid, task_id);
580     return ret;
581 }
582 
sre_task_create(const struct tsk_init_param * init_param,uint32_t * task_id)583 int sre_task_create(const struct tsk_init_param *init_param, uint32_t *task_id)
584 {
585     int ret;
586 
587     if (init_param == NULL || task_id == NULL || get_cur_service() == NULL) {
588         tloge("invalid param!\n");
589         return -EINVAL;
590     }
591 
592     if (get_cur_service()->service_thread == 0) {
593         ret = gt_create_proc(init_param, task_id);
594     } else {
595         /* create working thread */
596         ret = gt_create_thread((pid_t *)task_id);
597     }
598     return ret;
599 }
600 
sre_task_delete_ex(uint32_t uw_task_pid,bool is_service_dead,uint32_t session_id)601 int32_t sre_task_delete_ex(uint32_t uw_task_pid, bool is_service_dead, uint32_t session_id)
602 {
603     int ret;
604 
605     /* Multi-thread task */
606     (void)ipc_release_from_taskid(uw_task_pid, 0);
607 
608     /* service has exception, cannot send msg to it anymore */
609     if (is_service_dead)
610         return SUCC_RET;
611 
612     ret = gt_recycle_thread((uint32_t)uw_task_pid, session_id);
613     return ret;
614 }
615