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