1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include "amp_platform.h"
6 #include "amp_defines.h"
7 #include "amp_config.h"
8 #include "aos_system.h"
9 #include "amp_task.h"
10 #include "amp_list.h"
11
12 #define MOD_STR "AMP_TASK"
13 #define AMP_MSGQ_WAITIME (2000)
14 #define AMP_MSGQ_MAX_NUM 64
15
16 typedef struct {
17 dlist_t node;
18 void (*callback)(void);
19 } amp_source_node_t;
20
21 static dlist_t g_sources_list = AMP_DLIST_HEAD_INIT(g_sources_list);
22
23 static aos_queue_t amp_task_mq = NULL; /* JSEngine message queue */
24 static aos_mutex_t amp_task_mutex = NULL; /* JSEngine mutex */
25
26 static void (*g_task_msg_notify)(int (*msg_handler)(void));
27
amp_module_free(void)28 void amp_module_free(void)
29 {
30 amp_source_node_t *source_node;
31 dlist_t *temp;
32
33 dlist_for_each_entry_safe(&g_sources_list, temp, source_node, amp_source_node_t, node) {
34 source_node->callback();
35 dlist_del(&source_node->node);
36 amp_free(source_node);
37 }
38 }
39
amp_module_free_register(void (* callback)(void))40 int32_t amp_module_free_register(void (*callback)(void))
41 {
42 amp_source_node_t *source_node;
43
44 if (!callback) {
45 return -1;
46 }
47
48 source_node = amp_malloc(sizeof(amp_source_node_t));
49 if (!source_node) {
50 return -1;
51 }
52 source_node->callback = callback;
53 dlist_add_tail(&source_node->node, &g_sources_list);
54 return 0;
55 }
56
amp_task_yield(uint32_t timeout)57 int32_t amp_task_yield(uint32_t timeout)
58 {
59 int32_t ret = 0;
60 size_t revsize;
61
62 amp_task_msg_t amp_msg;
63
64 memset(&_msg, 0, sizeof(amp_msg));
65 amp_msg.type = AMP_TASK_MSG_TYPE_MAX;
66
67 if ((ret = aos_queue_recv(&_task_mq, timeout, &_msg, &revsize)) != 0) {
68 return -1;
69 }
70
71 if (amp_msg.type == AMP_TASK_MSG_CALLBACK) {
72 amp_msg.callback(amp_msg.param);
73 }
74
75 else if (amp_msg.type == AMP_TASK_MSG_EXIT) {
76 return 1;
77 }
78
79 return 0;
80 }
81
amp_task_yield_nowait(void)82 static int amp_task_yield_nowait(void)
83 {
84 return amp_task_yield(0);
85 }
86
amp_task_timer_cb_handler(void * timer,void * arg)87 static void amp_task_timer_cb_handler(void *timer, void *arg)
88 {
89 amp_task_msg_t *p_amp_msg = (amp_task_msg_t *)arg;
90
91 if (amp_task_mq == NULL) {
92 return;
93 }
94
95 aos_queue_send(&_task_mq, p_amp_msg, sizeof(amp_task_msg_t));
96 }
97
amp_task_timer_action(uint32_t ms,amp_engine_call_t action,void * arg,amp_timer_type_t type,void ** timer_msg)98 aos_timer_t *amp_task_timer_action(uint32_t ms, amp_engine_call_t action, void *arg, amp_timer_type_t type,
99 void **timer_msg)
100 {
101 int ret = -1;
102
103 aos_timer_t *timer_id = (aos_timer_t *)amp_malloc(sizeof(aos_timer_t));
104 if (timer_id == NULL) {
105 return NULL;
106 }
107
108 amp_task_msg_t *p_param = (amp_task_msg_t *)amp_calloc(1, sizeof(amp_task_msg_t));
109
110 if (!p_param)
111 return NULL;
112
113 *timer_msg = p_param;
114
115 if (amp_task_mq == NULL) {
116 goto fail;
117 }
118
119 p_param->callback = action;
120 p_param->param = arg;
121 p_param->type = AMP_TASK_MSG_CALLBACK;
122
123 if (type == AMP_TIMER_REPEAT) {
124 ret = aos_timer_create(timer_id, amp_task_timer_cb_handler, p_param, ms, AOS_TIMER_REPEAT);
125 } else if (type == AMP_TIMER_ONCE) {
126 ret = aos_timer_create(timer_id, amp_task_timer_cb_handler, p_param, ms, 0);
127 } else {
128 goto fail;
129 }
130
131 if (ret != 0)
132 goto fail;
133
134 ret = aos_timer_start(timer_id);
135 if (ret) {
136 aos_timer_free(timer_id);
137 goto fail;
138 }
139
140 return timer_id;
141
142 fail:
143 amp_free(p_param);
144 amp_free(timer_id);
145 return NULL;
146 }
147
amp_task_schedule_call(amp_engine_call_t call,void * arg)148 int32_t amp_task_schedule_call(amp_engine_call_t call, void *arg)
149 {
150 amp_task_msg_t msg_buf;
151 amp_task_msg_t *p_param = &msg_buf;
152
153 if (amp_task_mq == NULL) {
154 return -1;
155 }
156
157 p_param->callback = call;
158 p_param->param = arg;
159 p_param->type = AMP_TASK_MSG_CALLBACK;
160 if (amp_task_mq == NULL) {
161 amp_warn(MOD_STR, "amp_task_mq has not been initlized");
162 return -1;
163 }
164 aos_queue_send(&_task_mq, p_param, sizeof(amp_task_msg_t));
165 #ifdef HAASUI_AMP_BUILD
166 if (g_task_msg_notify)
167 g_task_msg_notify(amp_task_yield_nowait);
168 #endif
169 return 0;
170 }
171
amp_task_msg_register(void (* msg_notify)(int (* msg_handler)(void)))172 void amp_task_msg_register(void (*msg_notify)(int (*msg_handler)(void)))
173 {
174 g_task_msg_notify = msg_notify;
175 }
176
amp_task_exit_call(amp_engine_call_t call,void * arg)177 int32_t amp_task_exit_call(amp_engine_call_t call, void *arg)
178 {
179 amp_task_msg_t msg_buf;
180 amp_task_msg_t *p_param = &msg_buf;
181
182 memset(p_param, 0, sizeof(amp_task_msg_t));
183 p_param->callback = call;
184 p_param->param = arg;
185 p_param->type = AMP_TASK_MSG_EXIT;
186 if (amp_task_mq == NULL) {
187 amp_warn(MOD_STR, "amp_task_mq has not been initlized");
188 return -1;
189 }
190 aos_mutex_lock(&_task_mutex, AOS_WAIT_FOREVER);
191 aos_queue_send(&_task_mq, p_param, sizeof(amp_task_msg_t));
192 aos_mutex_unlock(&_task_mutex);
193 return 0;
194 }
195
amp_task_init()196 int32_t amp_task_init()
197 {
198 if (amp_task_mq != NULL) {
199 return 0;
200 }
201
202 if (aos_queue_new(&_task_mq, NULL, AMP_MSGQ_MAX_NUM * sizeof(amp_task_msg_t), sizeof(amp_task_msg_t)) != 0) {
203 amp_error(MOD_STR, "create messageQ error");
204 return -1;
205 }
206 if (aos_mutex_new(&_task_mutex) != 0) {
207 amp_error(MOD_STR, "create mutex error");
208 return -1;
209 }
210
211 amp_debug(MOD_STR, "jsengine task init");
212 return 0;
213 }
214
amp_task_deinit()215 int32_t amp_task_deinit()
216 {
217 if (amp_task_mq != NULL) {
218 aos_queue_free(&_task_mq);
219 amp_task_mq = NULL;
220 }
221
222 if (amp_task_mutex != NULL) {
223 aos_mutex_free(&_task_mutex);
224 amp_task_mutex = NULL;
225 }
226
227 /* free all jsengine heap */
228 jsengine_exit();
229
230 amp_debug(MOD_STR, "jsengine task free");
231 return 0;
232 }
233