sp_iom.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. #include "precompile.h"
  2. #include "sp_iom.h"
  3. #include "sp_def.h"
  4. #include "spinlock.h"
  5. #include "timerqueue.h"
  6. #include "array.h"
  7. #include "memutil.h"
  8. #include "sp_logwithlinkforc.h"
  9. #include <time.h>
  10. #include "dbgutil.h"
  11. #define TAG SPBASE_TAG("sp_iom")
  12. #ifndef _WIN32
  13. #include <unistd.h>
  14. #include <sys/syscall.h>
  15. static int GetParentProcessID()
  16. {
  17. #if 0
  18. return getppid();
  19. #else
  20. return (int)syscall(SYS_getppid);
  21. #endif
  22. }
  23. #endif //NOT _WIN32
  24. #define POLL_INTERVAL 10
  25. #define IOM_T_EXIT 0
  26. #define IOM_T_GET_STATE 1
  27. #define IOM_T_SEND_INFO 2
  28. static int translate_error(int bus_error)
  29. {
  30. int error;
  31. switch (bus_error) {
  32. case BUS_E_OK:
  33. error = Error_Succeed;
  34. break;
  35. case BUS_E_FAIL:
  36. error = Error_Unexpect;
  37. break;
  38. case BUS_E_NETBROKEN:
  39. error = Error_NetBroken;
  40. break;
  41. case BUS_E_NOTFOUND:
  42. error = Error_NotExist;
  43. break;
  44. default:
  45. error = Error_Unexpect;
  46. break;
  47. }
  48. return error;
  49. }
  50. typedef struct pkt_handler_t {
  51. int key;
  52. sp_iom_on_pkt on_pkt;
  53. void *user_data;
  54. }pkt_handler_t;
  55. typedef struct sys_handler_t {
  56. int key;
  57. sp_iom_on_sys on_sys;
  58. void *user_data;
  59. }sys_handler_t;
  60. struct sp_iom_t
  61. {
  62. bus_endpt_t *endpt;
  63. timer_queue_t *tm_queue;
  64. spinlock_t tm_lock;
  65. spinlock_t pkt_handler_lock;
  66. spinlock_t sys_handler_lock;
  67. array_header_t *arr_pkt_handler;
  68. array_header_t *arr_sys_handler;
  69. int stop;
  70. int poll_thread_id;
  71. };
  72. static __inline void iom_pkt_handler_lock(sp_iom_t *iom)
  73. {
  74. spinlock_enter(&iom->pkt_handler_lock, -1);
  75. }
  76. static __inline void iom_pkt_handler_unlock(sp_iom_t *iom)
  77. {
  78. spinlock_leave(&iom->pkt_handler_lock);
  79. }
  80. static __inline void iom_sys_handler_lock(sp_iom_t *iom)
  81. {
  82. spinlock_enter(&iom->sys_handler_lock, -1);
  83. }
  84. static __inline void iom_sys_handler_unlock(sp_iom_t *iom)
  85. {
  86. spinlock_leave(&iom->sys_handler_lock);
  87. }
  88. static __inline void iom_tm_lock(sp_iom_t *iom)
  89. {
  90. spinlock_enter(&iom->tm_lock, -1);
  91. }
  92. static __inline void iom_tm_unlock(sp_iom_t *iom)
  93. {
  94. spinlock_leave(&iom->tm_lock);
  95. }
  96. static pkt_handler_t* find_pkt_handler(sp_iom_t *iom, int key, int *idx)
  97. {
  98. int i;
  99. for (i = 0; i < iom->arr_pkt_handler->nelts; ++i) {
  100. pkt_handler_t *t = ARRAY_IDX(iom->arr_pkt_handler, i, pkt_handler_t*);
  101. if (t->key == key) {
  102. if (idx)
  103. *idx = i;
  104. return t;
  105. }
  106. }
  107. return NULL;
  108. }
  109. static sys_handler_t* find_sys_handler(sp_iom_t *iom, int key, int *idx)
  110. {
  111. int i;
  112. for (i = 0; i < iom->arr_sys_handler->nelts; ++i) {
  113. sys_handler_t *t = ARRAY_IDX(iom->arr_sys_handler, i, sys_handler_t*);
  114. if (t->key == key) {
  115. if (idx)
  116. *idx = i;
  117. return t;
  118. }
  119. }
  120. return NULL;
  121. }
  122. static void on_pkt(bus_endpt_t *endpt, int epid, int type, iobuffer_t **p_pkt, void *user_data)
  123. {
  124. sp_iom_t *iom = (sp_iom_t *)user_data;
  125. int i;
  126. iom_pkt_handler_lock(iom);
  127. for (i = 0; i < iom->arr_pkt_handler->nelts; ++i) {
  128. pkt_handler_t *pkt_handler = ARRAY_IDX(iom->arr_pkt_handler, i, pkt_handler_t*);
  129. if (pkt_handler->on_pkt) {
  130. int read_state = iobuffer_get_read_state(*p_pkt);
  131. int write_state = iobuffer_get_write_state(*p_pkt);
  132. int svc_id;
  133. int from_svc_id;
  134. int pkt_id;
  135. int count;
  136. //WLog_DBG(TAG, "to get svc info");
  137. iobuffer_format_read(*p_pkt, "444", &from_svc_id, &svc_id, &pkt_id);
  138. //mod和svc会注册处理句柄,如果返回非0,则认为当前处理器无法处理,需要交由下一个处理器处理
  139. count = pkt_handler->on_pkt(iom, svc_id, epid, from_svc_id, type, pkt_id, p_pkt, pkt_handler->user_data);
  140. if (count && p_pkt && *p_pkt) {
  141. iobuffer_restore_read_state(*p_pkt, read_state);
  142. iobuffer_restore_write_state(*p_pkt, write_state);
  143. } else {
  144. break;
  145. }
  146. }
  147. }
  148. iom_pkt_handler_unlock(iom);
  149. }
  150. static void on_msg(bus_endpt_t *endpt, int msg, int nparam, param_size_t params[], int *result, void *user_data)
  151. {
  152. sp_iom_t *iom = (sp_iom_t *)user_data;
  153. WLog_DBG(TAG, "==> on msg %d, %d, result? %d", msg, nparam, result != NULL ? 1: 0);
  154. if (msg == IOM_T_SEND_INFO) {
  155. int pkt_type = params[0];
  156. int this_svc_id = params[1];
  157. int epid = params[2];
  158. int svc_id = params[3];
  159. int pkt_id = params[4];
  160. iobuffer_t *pkt = (iobuffer_t*)params[5];
  161. int read_state, write_state;
  162. int ret;
  163. read_state = iobuffer_get_read_state(pkt);
  164. write_state = iobuffer_get_write_state(pkt);
  165. iobuffer_write_head(pkt, IOBUF_T_I4, &pkt_id, 0);
  166. iobuffer_write_head(pkt, IOBUF_T_I4, &svc_id, 0);
  167. iobuffer_write_head(pkt, IOBUF_T_I4, &this_svc_id, 0);
  168. if (result) {
  169. int state = 0;
  170. //WLog_DBG(TAG, "get state first");
  171. ret = bus_endpt_get_state(endpt, epid, &state);
  172. if (ret == 0) {
  173. ret = (state == BUS_STATE_ON) ? 0 : -1;
  174. #ifndef _WIN32
  175. if (ret != 0)
  176. sp_dbg_warn("bus endpt state is invalid, would not send any IOM_T_SEND_INFO type msg: %d", state);
  177. #endif //NOT _WIN32
  178. }
  179. if (ret == 0)
  180. ret = bus_endpt_send_info(endpt, epid, pkt_type, pkt);
  181. *result = ret;
  182. if (ret != 0) {
  183. iobuffer_restore_read_state(pkt, read_state);
  184. iobuffer_restore_write_state(pkt, write_state);
  185. } else {
  186. iobuffer_dec_ref(pkt);
  187. }
  188. } else {
  189. bus_endpt_send_info(endpt, epid, pkt_type, pkt);
  190. iobuffer_dec_ref(pkt);
  191. }
  192. WLog_DBG(TAG, "<== on_msg send_info end, pkt type: 0x%08X, this_svc_id:%d, epid:%d, svc_id:%d, pkt_id:%d", pkt_type, this_svc_id, epid, svc_id, pkt_id);
  193. } else if (msg == IOM_T_GET_STATE) {
  194. int epid = params[0];
  195. int *state = (int*)params[1];
  196. int *rc = (int*)params[2];
  197. *rc = bus_endpt_get_state(endpt, epid, state);
  198. } else if (msg == IOM_T_EXIT) {
  199. sp_iom_stop(iom);
  200. } else {
  201. TOOLKIT_ASSERT(0);
  202. }
  203. }
  204. static void on_sys(bus_endpt_t *endpt, int epid, int state, void *user_data)
  205. {
  206. sp_iom_t *iom = (sp_iom_t *)user_data;
  207. int i;
  208. iom_sys_handler_lock(iom);
  209. for (i = 0; i < iom->arr_sys_handler->nelts; ++i) {
  210. sys_handler_t *sys_handler = ARRAY_IDX(iom->arr_sys_handler, i, sys_handler_t*);
  211. if (sys_handler->on_sys) {
  212. sys_handler->on_sys(iom, epid, state, sys_handler->user_data);
  213. }
  214. }
  215. iom_sys_handler_unlock(iom);
  216. }
  217. int sp_iom_create(const char *url, int epid, sp_iom_t **p_iom)
  218. {
  219. sp_iom_t *iom;
  220. bus_endpt_callback callback;
  221. int rc;
  222. iom = ZALLOC_T(sp_iom_t);
  223. callback.on_evt = NULL;
  224. callback.on_sys = &on_sys;
  225. callback.on_pkt = &on_pkt;
  226. callback.on_inf = &on_pkt;
  227. callback.on_msg = &on_msg;
  228. callback.user_data = iom;
  229. rc = bus_endpt_create(url, epid, &callback, &iom->endpt);
  230. if (rc != 0) {
  231. WLog_ERR(TAG, "bus endpoint create failed!");
  232. goto on_error;
  233. }
  234. timer_heap_create(&iom->tm_queue);
  235. spinlock_init(&iom->pkt_handler_lock);
  236. spinlock_init(&iom->sys_handler_lock);
  237. spinlock_init(&iom->tm_lock);
  238. iom->arr_pkt_handler = array_make(3, sizeof(pkt_handler_t*));
  239. iom->arr_sys_handler = array_make(3, sizeof(sys_handler_t*));
  240. iom->poll_thread_id = 0;
  241. *p_iom = iom;
  242. return 0;
  243. on_error:
  244. free(iom);
  245. return Error_Unexpect;
  246. }
  247. void sp_iom_destroy(sp_iom_t *iom)
  248. {
  249. timer_queue_destroy(iom->tm_queue);
  250. bus_endpt_destroy(iom->endpt);
  251. /**replaced with toolkit_array_free2 [5/23/2020 Gifur] */
  252. //array_free(iom->arr_pkt_handler);
  253. //array_free(iom->arr_sys_handler);
  254. array_free2(iom->arr_pkt_handler);
  255. array_free2(iom->arr_sys_handler);
  256. free(iom);
  257. }
  258. int sp_iom_add_pkt_handler(sp_iom_t *iom, int key, sp_iom_on_pkt on_pkt, void *user_data)
  259. {
  260. int rc = 0;
  261. pkt_handler_t *pkt_handler;
  262. iom_pkt_handler_lock(iom);
  263. pkt_handler = find_pkt_handler(iom, key, NULL);
  264. if (!pkt_handler) {
  265. pkt_handler = MALLOC_T(pkt_handler_t);
  266. pkt_handler->key = key;
  267. pkt_handler->on_pkt = on_pkt;
  268. pkt_handler->user_data = user_data;
  269. ARRAY_PUSH(iom->arr_pkt_handler, pkt_handler_t*) = pkt_handler;
  270. } else {
  271. rc = Error_Duplication;
  272. }
  273. iom_pkt_handler_unlock(iom);
  274. return rc;
  275. }
  276. int sp_iom_remove_pkt_handler(sp_iom_t *iom, int key)
  277. {
  278. int rc = 0;
  279. pkt_handler_t *pkt_handler;
  280. int i;
  281. iom_pkt_handler_lock(iom);
  282. pkt_handler = find_pkt_handler(iom, key, &i);
  283. if (pkt_handler) {
  284. if (i < iom->arr_pkt_handler->nelts-1)
  285. ARRAY_IDX(iom->arr_pkt_handler, i, pkt_handler_t*) = ARRAY_IDX(iom->arr_pkt_handler, iom->arr_pkt_handler->nelts-1, pkt_handler_t*);
  286. array_pop(iom->arr_pkt_handler);
  287. free(pkt_handler);
  288. } else {
  289. rc = Error_NotExist;
  290. }
  291. iom_pkt_handler_unlock(iom);
  292. return rc;
  293. }
  294. int sp_iom_add_sys_handler(sp_iom_t *iom, int key, sp_iom_on_sys on_sys, void *user_data)
  295. {
  296. int rc = 0;
  297. sys_handler_t *sys_handler;
  298. iom_sys_handler_lock(iom);
  299. sys_handler = find_sys_handler(iom, key, NULL);
  300. if (!sys_handler) {
  301. sys_handler = MALLOC_T(sys_handler_t);
  302. sys_handler->key = key;
  303. sys_handler->on_sys = on_sys;
  304. sys_handler->user_data = user_data;
  305. ARRAY_PUSH(iom->arr_sys_handler, sys_handler_t*) = sys_handler;
  306. } else {
  307. rc = Error_Duplication;
  308. }
  309. iom_sys_handler_unlock(iom);
  310. return rc;
  311. }
  312. int sp_iom_remove_sys_handler(sp_iom_t *iom, int key)
  313. {
  314. int rc = 0;
  315. sys_handler_t *sys_handler;
  316. int i;
  317. iom_sys_handler_lock(iom);
  318. sys_handler = find_sys_handler(iom, key, &i);
  319. if (sys_handler) {
  320. ARRAY_DEL(iom->arr_sys_handler, i, sys_handler_t*);
  321. free(sys_handler);
  322. } else {
  323. rc = Error_NotExist;
  324. }
  325. iom_sys_handler_unlock(iom);
  326. return rc;
  327. }
  328. static int sp_iom_poll(sp_iom_t *iom, int *timeout)
  329. {
  330. int rc;
  331. if (iom->poll_thread_id == 0) {
  332. iom->poll_thread_id = (int)GetCurrentThreadId();
  333. }
  334. rc = bus_endpt_poll(iom->endpt, *timeout);
  335. for (;;) {
  336. int cnt;
  337. long timerBeginTime, timerPlayTime;
  338. iom_tm_lock(iom);
  339. timerBeginTime = clock();
  340. cnt = timer_queue_poll_one(iom->tm_queue, NULL, timeout); // timeout返回下一个定时器超时间隔
  341. timerPlayTime = clock() - timerBeginTime;
  342. /*
  343. if (timerPlayTime > 500) //timer play time over than 500ms, it may make the main thread run slow
  344. DbgWithLinkForC(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM, "timer queue poll one consumed %d ms, trigger timer count: %d", timerPlayTime, cnt);
  345. */
  346. iom_tm_unlock(iom);
  347. if (!cnt) {
  348. //sp_dbg_debug("no timer execute current times.");
  349. break;
  350. }
  351. }
  352. return rc;
  353. }
  354. int sp_iom_run(sp_iom_t *iom)
  355. {
  356. int timeout = POLL_INTERVAL;
  357. #ifdef RVC_OS_WIN
  358. while (InterlockedExchangeAdd((LONG*)&iom->stop, 0) == 0 || timer_queue_get_count(iom->tm_queue) > 0) {
  359. int rc = sp_iom_poll(iom, &timeout);
  360. if (rc >= 0) {
  361. if (timeout > POLL_INTERVAL || timeout < 0)
  362. timeout = POLL_INTERVAL;
  363. } else {
  364. DbgWithLinkForC(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM, "iom poll failed!");
  365. ExitProcess(-1);
  366. return rc;
  367. }
  368. }
  369. #else
  370. int parent_id = GetParentProcessID();
  371. /*the adapte func 'InterlockedExchangeAdd' implemented under winpr went wrong, maybe 64bit has responsibility*/
  372. while (iom->stop == 0 || timer_queue_get_count(iom->tm_queue) > 0) {
  373. int rc = sp_iom_poll(iom, &timeout);
  374. if (rc >= 0) {
  375. if (timeout > POLL_INTERVAL || timeout < 0)
  376. timeout = POLL_INTERVAL;
  377. } else {
  378. DbgWithLinkForC(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM, "iom poll failed! %d", rc);
  379. return rc;
  380. }
  381. if (rc == 0) {
  382. const int cur_ppid = GetParentProcessID();
  383. if (cur_ppid != parent_id) {
  384. if (cur_ppid == 1 /*init's pid*/) {
  385. DbgWithLinkForC(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM, "for moudle, spshell gone while for spshell, guardian gone. last parent pid: %d", parent_id);
  386. }
  387. parent_id = cur_ppid; /*just test, or would print lots of log here.*/
  388. }
  389. }
  390. }
  391. #endif //RVC_OS_WIN
  392. DbgWithLinkForC(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM, "iom run exit ok!");
  393. return 0;
  394. }
  395. int sp_iom_stop(sp_iom_t *iom)
  396. {
  397. DbgWithLinkForC(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM, "set iom stop flag!");
  398. InterlockedExchange((LONG*)&iom->stop, 1);
  399. return 0;
  400. }
  401. int sp_iom_send(sp_iom_t *iom, int this_svc_id, int epid, int svc_id, int pkt_type, int pkt_id, iobuffer_t **p_pkt)
  402. {
  403. iobuffer_t *pkt = p_pkt ? *p_pkt : NULL;
  404. int rc;
  405. WLog_DBG(TAG, "== > sp_iom_send: pkt type: 0x%08X, this_svc id: %d, epid:%d, svc id:%d, pkt_id: %d",
  406. pkt_type, this_svc_id, epid, svc_id, pkt_id);
  407. if (!pkt) {
  408. pkt = iobuffer_create(-1, -1);
  409. }
  410. {
  411. param_size_t params[] = {
  412. pkt_type,
  413. this_svc_id,
  414. epid,
  415. svc_id,
  416. pkt_id,
  417. (param_size_t)pkt,
  418. };
  419. rc = bus_endpt_send_msg(iom->endpt, IOM_T_SEND_INFO, array_size(params), params);
  420. }
  421. if (!p_pkt || !*p_pkt) {
  422. if (rc != 0) {
  423. iobuffer_dec_ref(pkt);
  424. }
  425. } else {
  426. if (rc == 0)
  427. *p_pkt = NULL;
  428. }
  429. if (rc != 0)
  430. rc = Error_IO;
  431. WLog_DBG(TAG, "<== sp_iom_send: pkt type: 0x%08X, this_svc id: %d, epid:%d, svc id:%d, pkt_id: %d, rc=%d!",
  432. pkt_type, this_svc_id, epid, svc_id, pkt_id, rc);
  433. return rc;
  434. }
  435. int sp_iom_post(sp_iom_t *iom, int this_svc_id, int epid, int svc_id, int pkt_type, int pkt_id, iobuffer_t **p_pkt)
  436. {
  437. iobuffer_t *pkt = p_pkt ? *p_pkt : NULL;
  438. int rc;
  439. if (!pkt) {
  440. pkt = iobuffer_create(-1, -1);
  441. }
  442. {
  443. param_size_t params[] = {
  444. pkt_type,
  445. this_svc_id,
  446. epid,
  447. svc_id,
  448. pkt_id,
  449. (param_size_t)pkt,
  450. };
  451. rc = bus_endpt_post_msg(iom->endpt, IOM_T_SEND_INFO, array_size(params), params);
  452. }
  453. if (!p_pkt || !*p_pkt) {
  454. if (rc != 0)
  455. iobuffer_dec_ref(pkt);
  456. } else {
  457. if (rc == 0)
  458. *p_pkt = NULL;
  459. }
  460. if (rc != 0)
  461. {
  462. DbgWithLinkForC(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM, "iom post unexpected, epid:%d, rc:%d", epid, rc);
  463. rc = Error_Unexpect;
  464. }
  465. return rc;
  466. }
  467. int sp_iom_get_state(sp_iom_t *iom, int epid, int *state)
  468. {
  469. int rc = 0;
  470. int rc1;
  471. param_size_t params[] = {epid, (param_size_t)state, (param_size_t)&rc};
  472. // use -1 for get state
  473. rc1 = bus_endpt_send_msg(iom->endpt, IOM_T_GET_STATE, array_size(params), params);
  474. if (rc != 0) {
  475. DbgWithLinkForC(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM, "get epid(%d) state: %d, rc1:%d, rc:%d", epid, *state, rc1, rc);
  476. rc = Error_Unexpect;
  477. }
  478. return rc1 == 0 ? rc : Error_Unexpect;
  479. }
  480. int sp_iom_schedule_timer(sp_iom_t *iom, timer_entry *entry, unsigned int delay)
  481. {
  482. int rc;
  483. iom_tm_lock(iom);
  484. rc = timer_queue_schedule(iom->tm_queue, entry, delay);
  485. iom_tm_unlock(iom);
  486. return rc ? Error_Unexpect : 0;
  487. }
  488. int sp_iom_cancel_timer(sp_iom_t *iom, timer_entry *entry, int cancel)
  489. {
  490. int rc;
  491. iom_tm_lock(iom);
  492. rc = timer_queue_cancel(iom->tm_queue, entry, cancel);
  493. iom_tm_unlock(iom);
  494. return rc ? Error_Unexpect : 0;
  495. }
  496. int sp_iom_get_epid(sp_iom_t *iom)
  497. {
  498. return bus_endpt_get_epid(iom->endpt);
  499. }
  500. const char *sp_iom_get_comm_url(sp_iom_t *iom)
  501. {
  502. return bus_endpt_get_url(iom->endpt);
  503. }
  504. int sp_iom_post_quit(sp_iom_t *iom)
  505. {
  506. int rc = bus_endpt_post_msg(iom->endpt, IOM_T_EXIT, 0, 0);
  507. if (rc != 0)
  508. rc = Error_Unexpect;
  509. return rc;
  510. }
  511. int sp_iom_get_poll_thread_id(sp_iom_t *iom)
  512. {
  513. return iom->poll_thread_id;
  514. }