• 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 <chcore/syscall.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <chcore-internal/chanmgr_defs.h>
18 #include <chcore-internal/procmgr_defs.h>
19 #include <chcore/ipc.h>
20 #include <chcore/container/hashtable.h>
21 #include <pthread.h>
22 
23 #include <ipclib.h>
24 
25 #define ipc_info(fmt, ...) \
26     printf("%s %d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
27 
28 struct __ipc_tls_st {
29     ipc_struct_t *chanmgr_ipc_struct;
30     int channel[2];
31     int msg_hdl;
32 };
33 static struct __ipc_tls_st __ipc_tls__[1024];
34 
35 #define __ipc_tls (__ipc_tls__[gettid()])
36 
37 /* attain chanmgr ipc_struct */
__conn_server(void)38 static ipc_struct_t *__conn_server(void)
39 {
40     cap_t server_cap;
41     ipc_msg_t *ipc_msg;
42     struct proc_request *req;
43     ipc_struct_t *cis = NULL;
44     int ret;
45 
46     ipc_msg = ipc_create_msg(procmgr_ipc_struct, sizeof(struct proc_request));
47     req = (struct proc_request *)ipc_get_msg_data(ipc_msg);
48     req->req = PROC_REQ_GET_SERVER_CAP;
49     req->get_server_cap.server_id = SERVER_CHANMGR;
50     ret = ipc_call(procmgr_ipc_struct, ipc_msg);
51     if (ret != 0) {
52         goto out;
53     }
54 
55     server_cap = ipc_get_msg_cap(ipc_msg, 0);
56     if (server_cap < 0) {
57         ret = -1;
58         goto out;
59     }
60 
61     do {
62         cis = ipc_register_client(server_cap);
63         usys_yield();
64     } while (cis == NULL);
65 
66 out:
67     ipc_destroy_msg(ipc_msg);
68     return cis;
69 }
70 
71 /* per-thread chanmgr ipc_struct */
__chanmgr_ipc_struct(void)72 static ipc_struct_t *__chanmgr_ipc_struct(void)
73 {
74     if (__ipc_tls.chanmgr_ipc_struct == NULL) {
75         __ipc_tls.chanmgr_ipc_struct = __conn_server();
76     }
77 
78     return __ipc_tls.chanmgr_ipc_struct;
79 }
80 
81 #define chanmgr_ipc_struct (__chanmgr_ipc_struct())
82 
__ipc_util_create_channel(const char * name,int ch_num,int channel,struct reg_items_st reg_items)83 static int __ipc_util_create_channel(const char *name, int ch_num, int channel,
84                                      struct reg_items_st reg_items)
85 {
86     ipc_msg_t *ipc_msg;
87     struct chan_request *req;
88     int ret;
89 
90     ipc_msg = ipc_create_msg_with_cap(
91         chanmgr_ipc_struct, sizeof(struct chan_request), 1);
92     req = (struct chan_request *)ipc_get_msg_data(ipc_msg);
93     req->req = CHAN_REQ_CREATE_CHANNEL;
94     ret = ipc_set_msg_cap(ipc_msg, 0, channel);
95     if (ret < 0) {
96         ret = -EINVAL;
97         goto out_fail;
98     }
99 
100     memset(req->create_channel.name, 0, sizeof(req->create_channel.name));
101     if (name != NULL && (reg_items.reg_name || reg_items.reg_tamgr)) {
102         if (strlen(name) >= CHAN_REQ_NAME_LEN) {
103             ret = -ENAMETOOLONG;
104             goto out_fail;
105         }
106         memcpy(req->create_channel.name, name, strlen(name));
107     }
108     if (reg_items.reg_pid) {
109         req->create_channel.ch_num = ch_num;
110     }
111     memcpy(&req->create_channel.reg_items,
112            &reg_items,
113            sizeof(struct reg_items_st));
114 
115     ret = ipc_call(chanmgr_ipc_struct, ipc_msg);
116 
117 out_fail:
118     ipc_destroy_msg(ipc_msg);
119 
120     return ret;
121 }
122 
__ipc_util_remove_channel(const char * name,int ch_num,uint32_t taskid)123 static int __ipc_util_remove_channel(const char *name, int ch_num,
124                                      uint32_t taskid)
125 {
126     ipc_msg_t *ipc_msg;
127     struct chan_request *req;
128     int ret;
129 
130     if (taskid == 0) {
131         taskid = get_self_taskid();
132     }
133 
134     ipc_msg = ipc_create_msg(chanmgr_ipc_struct, sizeof(struct chan_request));
135     req = (struct chan_request *)ipc_get_msg_data(ipc_msg);
136     req->req = CHAN_REQ_REMOVE_CHANNEL;
137 
138     memset(req->remove_channel.name, 0, sizeof(req->remove_channel.name));
139     if (name) {
140         if (strlen(name) >= CHAN_REQ_NAME_LEN) {
141             ret = -ENAMETOOLONG;
142             goto out_fail;
143         }
144         memcpy(req->remove_channel.name, name, strlen(name));
145     }
146     if (ch_num == 0 || ch_num == 1) {
147         req->remove_channel.taskid = taskid;
148         req->remove_channel.ch_num = ch_num;
149     }
150 
151     ret = ipc_call(chanmgr_ipc_struct, ipc_msg);
152 
153 out_fail:
154     ipc_destroy_msg(ipc_msg);
155 
156     return ret;
157 }
158 
__ipc_util_hunt_by_name(const char * name,uint32_t * taskid)159 static int __ipc_util_hunt_by_name(const char *name, uint32_t *taskid)
160 {
161     ipc_msg_t *ipc_msg;
162     struct chan_request *req;
163     int ret;
164 
165     ipc_msg = ipc_create_msg(chanmgr_ipc_struct, sizeof(struct chan_request));
166     req = (struct chan_request *)ipc_get_msg_data(ipc_msg);
167     req->req = CHAN_REQ_HUNT_BY_NAME;
168 
169     if (name == NULL) {
170         ret = -EINVAL;
171         goto out_fail;
172     }
173     if (strlen(name) >= CHAN_REQ_NAME_LEN) {
174         ret = -ENAMETOOLONG;
175         goto out_fail;
176     }
177 
178     memset(req->hunt_by_name.name, 0, sizeof(req->hunt_by_name.name));
179     memcpy(req->hunt_by_name.name, name, strlen(name));
180     ret = ipc_call(chanmgr_ipc_struct, ipc_msg);
181     if (ret == 0) {
182         *taskid = req->hunt_by_name.taskid;
183     }
184 
185 out_fail:
186     ipc_destroy_msg(ipc_msg);
187 
188     return ret;
189 }
190 
__ipc_util_get_ch_from_path(const char * name,int * cap)191 static int __ipc_util_get_ch_from_path(const char *name, int *cap)
192 {
193     ipc_msg_t *ipc_msg;
194     struct chan_request *req;
195     int ret;
196 
197     ipc_msg = ipc_create_msg(chanmgr_ipc_struct, sizeof(struct chan_request));
198     req = (struct chan_request *)ipc_get_msg_data(ipc_msg);
199     req->req = CHAN_REQ_GET_CH_FROM_PATH;
200 
201     if (name == NULL) {
202         ret = -EINVAL;
203         goto out_fail;
204     }
205     if (strlen(name) >= CHAN_REQ_NAME_LEN) {
206         ret = -ENAMETOOLONG;
207         goto out_fail;
208     }
209 
210     memset(req->get_ch_from_path.name, 0, sizeof(req->get_ch_from_path.name));
211     memcpy(req->get_ch_from_path.name, name, strlen(name));
212     ret = ipc_call(chanmgr_ipc_struct, ipc_msg);
213     if (ret == 0) {
214         ret = ipc_get_msg_cap(ipc_msg, 0);
215         if (ret < 0) {
216             ret = -EINVAL;
217         } else {
218             *cap = ret;
219             ret = 0;
220         }
221     }
222 
223 out_fail:
224     ipc_destroy_msg(ipc_msg);
225 
226     return ret;
227 }
228 
__ipc_util_get_ch_from_taskid(uint32_t taskid,int ch_num,int * cap)229 static int __ipc_util_get_ch_from_taskid(uint32_t taskid, int ch_num, int *cap)
230 {
231     ipc_msg_t *ipc_msg;
232     struct chan_request *req;
233     int ret;
234 
235     ipc_msg = ipc_create_msg(chanmgr_ipc_struct, sizeof(struct chan_request));
236     req = (struct chan_request *)ipc_get_msg_data(ipc_msg);
237     req->req = CHAN_REQ_GET_CH_FROM_TASKID;
238 
239     req->get_ch_from_taskid.taskid = taskid;
240     req->get_ch_from_taskid.ch_num = ch_num;
241     ret = ipc_call(chanmgr_ipc_struct, ipc_msg);
242     if (ret == 0) {
243         ret = ipc_get_msg_cap(ipc_msg, 0);
244         if (ret < 0) {
245             ret = -EINVAL;
246         } else {
247             *cap = ret;
248             ret = 0;
249         }
250     }
251 
252     ipc_destroy_msg(ipc_msg);
253 
254     return ret;
255 }
256 
__ipc_util_register_tamgr(const char * name)257 static int __ipc_util_register_tamgr(const char *name)
258 {
259     ipc_msg_t *ipc_msg;
260     struct chan_request *req;
261     int ret;
262 
263     ipc_msg = ipc_create_msg(chanmgr_ipc_struct, sizeof(struct chan_request));
264     req = (struct chan_request *)ipc_get_msg_data(ipc_msg);
265     req->req = CHAN_REQ_REGISTER_TAMGR;
266 
267     if (strlen(name) >= CHAN_REQ_NAME_LEN) {
268         ret = -ENAMETOOLONG;
269         goto out;
270     }
271     memcpy(req->register_tamgr.name, name, strlen(name) + 1);
272 
273     ret = ipc_call(chanmgr_ipc_struct, ipc_msg);
274     ipc_destroy_msg(ipc_msg);
275 
276 out:
277     return ret;
278 }
279 
280 #define HTABLE_SIZE 1024
281 
282 struct task2capmgr {
283     pthread_mutex_t lock;
284     struct htable table;
285     volatile int initialized;
286 };
287 
__task2cap(void)288 static struct task2capmgr *__task2cap(void)
289 {
290     static struct task2capmgr task2cap_table = {.initialized = 0};
291     int old;
292 
293     old = __sync_val_compare_and_swap(&task2cap_table.initialized, 0, 1);
294     if (old == 0) {
295         init_htable(&task2cap_table.table, HTABLE_SIZE);
296         pthread_mutex_init(&task2cap_table.lock, NULL);
297     }
298     return &task2cap_table;
299 }
300 
301 #define task2cap (__task2cap())
302 
303 struct task2cap_ent {
304     struct hlist_node task2cap_node;
305     cap_t cap;
306     taskid_t taskid;
307     int ch_num;
308 };
309 
__get_entry(taskid_t taskid,int ch_num)310 static struct task2cap_ent *__get_entry(taskid_t taskid, int ch_num)
311 {
312     struct task2cap_ent *entry;
313     struct hlist_head *bucket;
314 
315     bucket = htable_get_bucket(&task2cap->table, taskid);
316     for_each_in_hlist (entry, task2cap_node, bucket) {
317         if (entry->taskid == taskid && entry->ch_num == ch_num) {
318             return entry;
319         }
320     }
321 
322     return NULL;
323 }
324 
325 /*
326  * Create channel(s) and register mapping info among name, taskid and channel
327  * @name: channel's name
328  * @ch_cnt: the number(1 or 2) of channel(s) to be created
329  * @pp_ch: output the cap(s) of corresponding channel(s)
330  * @reg_items: guidance on specific registration behaviors
331  *
332  * Create ch_cnt channel(s).
333  * if reg_items.reg_name is true and name is not NULL:
334  *      register (name, channel[0]) mapping info into chanmgr
335  * if reg_items.reg_tamgr is true and name is not NULL:
336  *      register (name, taskid) mapping info into chanmgr
337  * if reg_items.reg_pid is true:
338  *      register ((taskid, ch_num), channel) mapping info into chanmgr
339  *      save channel cap(s) into pthread struct
340  * Return:
341  *      0: success
342  *      errno: fail
343  */
ipc_create_channel(const char * name,int32_t ch_cnt,cref_t * pp_ch[],struct reg_items_st reg_items)344 int32_t ipc_create_channel(const char *name, int32_t ch_cnt, cref_t *pp_ch[],
345                            struct reg_items_st reg_items)
346 {
347     int ret, i;
348     cap_t chan[2];
349 
350     if (name && reg_items.reg_tamgr) {
351         ret = __ipc_util_register_tamgr(name);
352         if (ret < 0)
353             goto out_fail;
354         reg_items.reg_tamgr = false;
355     }
356 
357     if (!reg_items.reg_tamgr && !reg_items.reg_pid && !reg_items.reg_name) {
358         ret = 0;
359         goto out_fail;
360     }
361 
362     if (!(ch_cnt > 0 && ch_cnt <= CH_CNT_MAX)) {
363         ret = -EINVAL;
364         goto out_fail;
365     }
366 
367     for (i = 0; i < ch_cnt; i++) {
368         ret = usys_tee_msg_create_channel();
369         if (ret < 0) {
370             goto out_free_channel;
371         }
372         chan[i] = ret;
373     }
374 
375     /* remove old local channels if reg_pid */
376     if (reg_items.reg_pid && __ipc_tls.channel[0] != 0) {
377         ipc_remove_channel(0, NULL, 0, 0);
378     }
379     ret = __ipc_util_create_channel(name, 0, chan[0], reg_items);
380     if (ret < 0) {
381         goto out_free_channel;
382     }
383     if (ch_cnt == CH_CNT_MAX) {
384         if (reg_items.reg_pid && __ipc_tls.channel[1] != 0) {
385             ipc_remove_channel(0, NULL, 1, 0);
386         }
387         ret = __ipc_util_create_channel(NULL, 1, chan[1], reg_items);
388         if (ret < 0) {
389             goto out_remove_first_channel;
390         }
391     }
392 
393     for (i = 0; i < ch_cnt; i++) {
394         if (reg_items.reg_pid) {
395             __ipc_tls.channel[i] = chan[i];
396         }
397         if (pp_ch) {
398             *pp_ch[i] = chan[i];
399         }
400     }
401 
402     return 0;
403 
404 out_remove_first_channel:
405     __ipc_util_remove_channel(name, 0, 0);
406 
407 out_free_channel:
408     for (i = i - 1; i >= 0; i--) {
409         usys_revoke_cap(chan[i], false);
410     }
411 
412 out_fail:
413     return ret;
414 }
415 
416 /*
417  * Remove channel(s) and deregister mapping info among name, taskid and channel
418  * @task_id: taskid in ((taskid, ch_num), channel) mapping info
419  * @name: name in (name, channel) & (name, taskid) mapping info
420  * @ch_num: ch_num in ((taskid, ch_num), channel) mapping info & which channel
421  * in pthread struct to be removed
422  * @ch: channel cap
423  *
424  * if name is not NULL:
425  *      deregister (name, channel) and (name, taskid) mapping info in chanmgr if
426  * exist deregister ((taskid, ch_num), channel) mapping info in chanmgr if exist
427  * if ch is 0, remove the ch_numth channel in pthread struct
428  * else, remove ch
429  * Return:
430  *      0: success
431  *      errno: fail
432  */
ipc_remove_channel(uint32_t task_id,const char * name,int32_t ch_num,cref_t ch)433 int32_t ipc_remove_channel(uint32_t task_id, const char *name, int32_t ch_num,
434                            cref_t ch)
435 {
436     int ret;
437 
438     if (task_id == 0) {
439         task_id = get_self_taskid();
440     }
441 
442     if (ch == 0) {
443         if (ch_num == 0 || ch_num == 1) {
444             ch = __ipc_tls.channel[ch_num];
445         } else {
446             return -EINVAL;
447         }
448     }
449 
450     ret = __ipc_util_remove_channel(name, ch_num, task_id);
451     if (ret != 0) {
452         goto out;
453     }
454 
455     ret = usys_tee_msg_stop_channel(ch);
456     if (ret != 0) {
457         goto out;
458     }
459 
460     if ((ch_num == 0 || ch_num == 1) && task_id == get_self_taskid()) {
461         __ipc_tls.channel[ch_num] = 0;
462     }
463 
464     ret = usys_revoke_cap(ch, false);
465 
466 out:
467     return ret;
468 }
469 
470 /*
471  * Release channel reference cap from path.
472  * @path: not used in ChCore
473  * @rref: channel cap
474  *
475  * Revoke the channel cap directly.
476  * Return:
477  *      0: success
478  *      errno: fail
479  */
ipc_release_from_path(const char * path,cref_t rref)480 uint32_t ipc_release_from_path(const char *path, cref_t rref)
481 {
482     int ret;
483 
484     ret = usys_revoke_cap(rref, false);
485 
486     return ret;
487 }
488 
489 /*
490  * Release channel reference cap from task_id.
491  *
492  * Revoke the corresponding channel cap.
493  * Return:
494  *      0: success
495  *      errno: fail
496  */
ipc_release_from_taskid(uint32_t task_id,int32_t ch_num)497 uint32_t ipc_release_from_taskid(uint32_t task_id, int32_t ch_num)
498 {
499     int ret = 0;
500     struct task2cap_ent *entry;
501 
502     pthread_mutex_lock(&task2cap->lock);
503 
504     entry = __get_entry(task_id, ch_num);
505     if (entry == NULL) {
506         ret = -ENOENT;
507         goto out;
508     }
509 
510     usys_revoke_cap(entry->cap, false);
511     htable_del(&entry->task2cap_node);
512     free(entry);
513 
514 out:
515     pthread_mutex_unlock(&task2cap->lock);
516     return ret;
517 }
518 
ipc_release_by_name(const char * name)519 uint32_t ipc_release_by_name(const char *name)
520 {
521     return 0;
522 }
523 
524 /*
525  * Get channel cap from chanmgr, which can be indexed through channel name.
526  * @name: name of the channel
527  * @p_ch: output the cap of the channel
528  *
529  * Send ChCore IPC request to chanmgr to get channel cap.
530  * Return:
531  *      0: success
532  *      errno: fail
533  */
ipc_get_ch_from_path(const char * name,cref_t * p_ch)534 int32_t ipc_get_ch_from_path(const char *name, cref_t *p_ch)
535 {
536     int ret;
537 
538     ret = __ipc_util_get_ch_from_path(name, p_ch);
539 
540     return ret;
541 }
542 
543 /*
544  * Get channel cap from chanmgr, which can be indexed through (taskid, ch_num).
545  * @taskid: taskid in ((taskid, ch_num), channel) mapping info
546  * @ch_num: ch_num in ((taskid, ch_num), channel) mapping info
547  * @p_ch: output the cap of the channel
548  *
549  * Send ChCore IPC request to chanmgr to get channel cap.
550  * Return:
551  *      0: success
552  *      errno: fail
553  */
ipc_get_ch_from_taskid(uint32_t taskid,int32_t ch_num,cref_t * p_ch)554 int32_t ipc_get_ch_from_taskid(uint32_t taskid, int32_t ch_num, cref_t *p_ch)
555 {
556     int ret;
557     struct task2cap_ent *entry;
558 
559     pthread_mutex_lock(&task2cap->lock);
560 
561     entry = __get_entry(taskid, ch_num);
562     if (entry != NULL) {
563         *p_ch = entry->cap;
564         ret = 0;
565         goto out;
566     }
567 
568     entry = malloc(sizeof(*entry));
569     if (entry == NULL) {
570         ret = -ENOMEM;
571         goto out;
572     }
573 
574     ret = __ipc_util_get_ch_from_taskid(taskid, ch_num, p_ch);
575     if (ret != 0) {
576         goto out_free_entry;
577     }
578 
579     entry->taskid = taskid;
580     entry->ch_num = ch_num;
581     entry->cap = *p_ch;
582     init_hlist_node(&entry->task2cap_node);
583     htable_add(&task2cap->table, taskid, &entry->task2cap_node);
584 
585     pthread_mutex_unlock(&task2cap->lock);
586     return 0;
587 
588 out_free_entry:
589     free(entry);
590 out:
591     pthread_mutex_unlock(&task2cap->lock);
592     return ret;
593 }
594 
595 /*
596  * Get server's taskid from chanmgr, which can be indexed through name.
597  * @name: name of the channel
598  * @task_id: output the taskid of the server who created the channel named @name
599  *
600  * Send ChCore IPC request to chanmgr to get taskid.
601  * Return:
602  *      0: success
603  *      errno: fail
604  */
ipc_hunt_by_name(const char * name,uint32_t * task_id)605 uint32_t ipc_hunt_by_name(const char *name, uint32_t *task_id)
606 {
607     int ret;
608 
609     ret = __ipc_util_hunt_by_name(name, task_id);
610 
611     return ret;
612 }
613 
614 /*
615  * Get the ch_numth channel cap stored in pthread struct.
616  * @ch_num: the ch_numth channel in pthread struct
617  * @p_ch: output the ch_numth channel cap in pthread struct
618  *
619  * Get the ch_numth channel cap from pthread struct.
620  * Return:
621  *      0: success
622  *      errno: fail
623  */
ipc_get_my_channel(int32_t ch_num,cref_t * p_ch)624 int32_t ipc_get_my_channel(int32_t ch_num, cref_t *p_ch)
625 {
626     if (ch_num != 0 && ch_num != 1) {
627         return -EINVAL;
628     }
629     if (__ipc_tls.channel[ch_num] <= 0) {
630         return -ENOENT;
631     }
632     *p_ch = __ipc_tls.channel[ch_num];
633     return 0;
634 }
635 
636 /*
637  * ipc_msg_call to the given channel, waiting for server's ipc_reply.
638  * @channel: cap of the channel
639  * @send_buf: send message buffer to be transfered to the server
640  * @send_len: length of the send buffer
641  * @reply_buf: reply buffer to be filled in when ipc_msg_reply from the server
642  * @reply_len: length of reply buffer
643  * @timeout: timeout
644  *
645  * ipc_msg_call will block current thread temporarily and transfer msg @send_buf
646  * to server. Current thread will be resumed after the server calls
647  * ipc_msg_reply.
648  * Return:
649  *      0: success
650  *      errno: fail
651  */
ipc_msg_call(cref_t channel,void * send_buf,size_t send_len,void * reply_buf,size_t reply_len,int32_t timeout)652 int32_t ipc_msg_call(cref_t channel, void *send_buf, size_t send_len,
653                      void *reply_buf, size_t reply_len, int32_t timeout)
654 {
655     int ret;
656 
657     ret = usys_tee_msg_call(
658         channel, send_buf, send_len, reply_buf, reply_len, NULL);
659 
660     return ret;
661 }
662 
663 /*
664  * ipc_msg_reply to the given msg_hdl.
665  * @msg_hdl: cap of the msg_hdl
666  * @reply_buf: message buffer to be transfered back to client
667  * @len: length of reply buffer
668  * @timeout: timeout
669  *
670  * The client to be replied, which is recored in msg_hdl, will be resumed after
671  * ipc_msg_reply.
672  * Return:
673  *      0: success
674  *      errno: fail
675  */
ipc_msg_reply(cref_t msg_hdl,void * reply_buf,size_t len)676 int32_t ipc_msg_reply(cref_t msg_hdl, void *reply_buf, size_t len)
677 {
678     int ret;
679 
680     ret = usys_tee_msg_reply(msg_hdl, reply_buf, len);
681 
682     return ret;
683 }
684 
685 /*
686  * ipc_msg_notification to the given channel.
687  * @ch: cap of the channel
688  * @send_buf: message buffer to be transfered to the server
689  * @send_len: length of the send buffer
690  *
691  * ipc_msg_notification sends message asynchronously to the given channel, which
692  * will not block current thread at all.
693  * Return:
694  *      0: success
695  *      errno: fail
696  */
ipc_msg_notification(cref_t ch,void * send_buf,size_t send_len)697 int32_t ipc_msg_notification(cref_t ch, void *send_buf, size_t send_len)
698 {
699     int ret;
700 
701     ret = usys_tee_msg_notify(ch, send_buf, send_len);
702 
703     return ret;
704 }
705 
706 /*
707  * ipc_msg_receive at the given channel.
708  * @channel: cap of the channel
709  * @recv_buf: the buffer to be filled in with client's message
710  * @recv_len: length of the recv buffer
711  * @msg_hdl: cap of the msg_hdl
712  * @info: the info(client's taskid, message type(sync or async)) of the ipc
713  * @timeout: timeout
714  *
715  * Current server thread will wait for message.
716  * Return:
717  *      0: success
718  *      errno: fail
719  */
ipc_msg_receive(cref_t channel,void * recv_buf,size_t recv_len,cref_t msg_hdl,struct src_msginfo * info,int32_t timeout)720 int32_t ipc_msg_receive(cref_t channel, void *recv_buf, size_t recv_len,
721                         cref_t msg_hdl, struct src_msginfo *info,
722                         int32_t timeout)
723 {
724     int ret;
725 
726     ret = usys_tee_msg_receive(
727         channel, recv_buf, recv_len, msg_hdl, info, timeout);
728 
729     return ret;
730 }
731 
732 /*
733  * Create msg_hdl.
734  *
735  * Create msg_hdl and return cap of the msg_hdl.
736  * Return:
737  *      >= 0: cap of the msg_hdl
738  *      errno: fail
739  */
ipc_msg_create_hdl(void)740 cref_t ipc_msg_create_hdl(void)
741 {
742     int ret;
743 
744     ret = usys_tee_msg_create_msg_hdl();
745 
746     return ret;
747 }
748 
749 /*
750  * Delete msg_hdl.
751  * @msg_hdl: cap of the msg_hdl
752  *
753  * Revoke msg_hdl cap directly.
754  * Return:
755  *      0: success
756  *      errno: fail
757  */
ipc_msg_delete_hdl(cref_t msg_hdl)758 int32_t ipc_msg_delete_hdl(cref_t msg_hdl)
759 {
760     int ret;
761 
762     ret = usys_revoke_cap(msg_hdl, false);
763 
764     return ret;
765 }
766 
767 /*
768  * Save msg_hdl locally.
769  * @msg_hdl: cap of the msg_hdl
770  *
771  * Save msg_hdl cap into pthread struct.
772  */
ipc_save_my_msghdl(cref_t msg_hdl)773 int32_t ipc_save_my_msghdl(cref_t msg_hdl)
774 {
775     __ipc_tls.msg_hdl = msg_hdl;
776     return 0;
777 }
778 
779 /*
780  * Get msg_hdl locally.
781  *
782  * Return msg_hdl cap stored in pthread struct.
783  * Return:
784  *      >= 0: cap of the msg_hdl
785  *      errno: fail
786  */
ipc_get_my_msghdl(void)787 cref_t ipc_get_my_msghdl(void)
788 {
789     if (__ipc_tls.msg_hdl == 0) {
790         __ipc_tls.msg_hdl = ipc_msg_create_hdl();
791     }
792     return __ipc_tls.msg_hdl;
793 }
794 
795 /*
796  * Get taskid of current thread.
797  *
798  * Return taskid of current thread.
799  * Return: taskid
800  */
get_self_taskid(void)801 uint32_t get_self_taskid(void)
802 {
803     return pid_to_taskid(gettid(), getpid());
804 }
805 
check_ref_valid(cref_t cref)806 bool check_ref_valid(cref_t cref)
807 {
808     return cref >= 0;
809 }
810 
tamgr_register(const char * name)811 int tamgr_register(const char *name)
812 {
813     return __ipc_util_register_tamgr(name);
814 }
815