1 /*
2 * Copyright 2021 Rockchip Electronics Co. LTD
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define MODULE_TAG "mpp_server"
18
19 #include <sys/ioctl.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 #include <string.h>
23
24 #include "mpp_env.h"
25 #include "mpp_list.h"
26 #include "mpp_time.h"
27 #include "osal_2str.h"
28 #include "mpp_common.h"
29 #include "mpp_mem_pool.h"
30
31 #include "mpp_device_debug.h"
32 #include "mpp_service_impl.h"
33 #include "mpp_server.h"
34
35 #define MAX_BATCH_TASK 8
36 #define MAX_SESSION_TASK 4
37 #define MAX_REQ_SEND_CNT MAX_REQ_NUM
38 #define MAX_REQ_WAIT_CNT 2
39
40 #define MPP_SERVER_DBG_FLOW (0x00000001)
41
42 #define mpp_serv_dbg(flag, fmt, ...) _mpp_dbg(mpp_server_debug, flag, fmt, ## __VA_ARGS__)
43 #define mpp_serv_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_server_debug, flag, fmt, ## __VA_ARGS__)
44
45 #define mpp_serv_dbg_flow(fmt, ...) mpp_serv_dbg(MPP_SERVER_DBG_FLOW, fmt, ## __VA_ARGS__)
46
47 #define FIFO_WRITE(size, count, wr, rd) \
48 do { \
49 wr++; \
50 if (wr >= size) wr = 0; \
51 count++; \
52 mpp_assert(count <= size); \
53 } while (0)
54
55 #define FIFO_READ(size, count, wr, rd) \
56 do { \
57 rd++; \
58 if (rd >= size) rd = 0; \
59 count--; \
60 mpp_assert(count >= 0); \
61 } while (0)
62
63 typedef struct MppDevTask_t MppDevTask;
64 typedef struct MppDevBatTask_t MppDevBatTask;
65 typedef struct MppDevSession_t MppDevSession;
66 typedef struct MppDevBatServ_t MppDevBatServ;
67
68 struct MppDevTask_t {
69 /* link to server */
70 struct list_head link_server;
71 /* link to session tasks */
72 struct list_head link_session;
73 /* link to batch tasks */
74 struct list_head link_batch;
75
76 MppDevSession *session;
77 MppDevBatTask *batch;
78
79 RK_S32 slot_idx;
80
81 /* lock by server */
82 RK_S32 task_id;
83 /* lock by batch */
84 RK_S32 batch_slot_id;
85
86 MppReqV1 *req;
87 RK_S32 req_cnt;
88 };
89
90 struct MppDevBatTask_t {
91 MppMutexCond *cond;
92
93 /* link to server */
94 struct list_head link_server;
95 /* link to session tasks */
96 struct list_head link_tasks;
97
98 RK_U32 batch_id;
99
100 MppDevBatCmd *bat_cmd;
101 MppReqV1 *send_reqs;
102 MppReqV1 *wait_reqs;
103
104 /* lock and clean by server */
105 RK_S32 send_req_cnt;
106 RK_S32 wait_req_cnt;
107
108 /* lock by server */
109 RK_S32 fill_cnt;
110 RK_S32 fill_full;
111 RK_S32 fill_timeout;
112 RK_S32 poll_cnt;
113 };
114
115 struct MppDevSession_t {
116 MppMutexCond *cond;
117
118 /* hash table to server */
119 struct list_head list_server;
120 /* link to session waiting tasks */
121 struct list_head list_wait;
122 /* link to session free tasks */
123 struct list_head list_done;
124
125 MppDevMppService *ctx;
126 MppDevBatServ *server;
127
128 RK_S32 client;
129
130 RK_S32 task_wait;
131 RK_S32 task_done;
132
133 MppDevTask tasks[MAX_SESSION_TASK];
134 };
135
136 struct MppDevBatServ_t {
137 Mutex *lock;
138
139 RK_S32 server_fd;
140 RK_U32 batch_id;
141 RK_U32 task_id;
142
143 /* timer for serializing process */
144 MppTimer timer;
145
146 /* session register */
147 struct list_head session_list;
148 RK_S32 session_count;
149
150 /* batch task queue */
151 struct list_head list_batch;
152 struct list_head list_batch_free;
153 MppMemPool batch_pool;
154 RK_S32 batch_max_count;
155 RK_S32 batch_task_size;
156 RK_S32 batch_run;
157 RK_S32 batch_free;
158 RK_S32 max_task_in_batch;
159
160 /* link to all pending tasks */
161 struct list_head pending_task;
162 RK_S32 pending_count;
163 };
164
165 RK_U32 mpp_server_debug = 0;
166
batch_reset(MppDevBatTask * batch)167 static void batch_reset(MppDevBatTask *batch)
168 {
169 mpp_assert(list_empty(&batch->link_tasks));
170
171 batch->fill_cnt = 0;
172 batch->fill_full = 0;
173 batch->fill_timeout = 0;
174 batch->poll_cnt = 0;
175 batch->send_req_cnt = 0;
176 batch->wait_req_cnt = 0;
177 }
178
batch_add(MppDevBatServ * server)179 MppDevBatTask *batch_add(MppDevBatServ *server)
180 {
181 MppDevBatTask *batch = (MppDevBatTask *)mpp_mem_pool_get(server->batch_pool);
182
183 mpp_assert(batch);
184 if (NULL == batch)
185 return batch;
186
187 INIT_LIST_HEAD(&batch->link_server);
188 INIT_LIST_HEAD(&batch->link_tasks);
189
190 batch->send_reqs = (MppReqV1 *)(batch + 1);
191 batch->wait_reqs = batch->send_reqs +
192 (server->max_task_in_batch * MAX_REQ_SEND_CNT);
193 batch->bat_cmd = (MppDevBatCmd *)(batch->wait_reqs +
194 (server->max_task_in_batch * MAX_REQ_WAIT_CNT));
195
196 batch_reset(batch);
197 list_add_tail(&batch->link_server, &server->list_batch_free);
198 server->batch_free++;
199
200 mpp_serv_dbg_flow("batch add free count %d:%d\n", server->batch_run, server->batch_free);
201 return batch;
202 }
203
batch_del(MppDevBatServ * server,MppDevBatTask * batch)204 void batch_del(MppDevBatServ *server, MppDevBatTask *batch)
205 {
206 mpp_assert(batch);
207 mpp_assert(batch->fill_cnt == 0);
208 mpp_assert(list_empty(&batch->link_tasks));
209
210 list_del_init(&batch->link_server);
211
212 mpp_mem_pool_put(server->batch_pool, batch);
213 server->batch_free--;
214 mpp_serv_dbg_flow("batch del free count %d:%d\n", server->batch_run, server->batch_free);
215 }
216
batch_send(MppDevBatServ * server,MppDevBatTask * batch)217 void batch_send(MppDevBatServ *server, MppDevBatTask *batch)
218 {
219 RK_S32 ret = 0;
220
221 mpp_assert(batch->send_req_cnt);
222
223 ret = mpp_service_ioctl_request(server->server_fd, batch->send_reqs);
224 if (ret) {
225 mpp_err_f("ioctl batch cmd failed ret %d errno %d %s\n",
226 ret, errno, strerror(errno));
227 ret = errno;
228 mpp_serv_dbg_flow("batch %d -> send failed\n", batch->batch_id);
229 }
230
231 list_del_init(&batch->link_server);
232 list_add_tail(&batch->link_server, &server->list_batch);
233 server->batch_free--;
234 server->batch_run++;
235 mpp_serv_dbg_flow("batch %d -> send %d for %s\n", batch->batch_id,
236 batch->fill_cnt, batch->fill_timeout ? "timeout" : "ready");
237 }
238
process_task(void * p)239 void process_task(void *p)
240 {
241 MppDevBatServ *server = (MppDevBatServ *)p;
242 Mutex *lock = server->lock;
243 RK_S32 ret = MPP_OK;
244 MppDevTask *task;
245 MppDevBatTask *batch;
246 MppDevSession *session = NULL;
247 MppDevBatCmd *bat_cmd;
248 MppReqV1 *req = NULL;
249 RK_S32 pending = 0;
250
251 mpp_serv_dbg_flow("process task start\n");
252
253 /* 1. try poll and get finished task */
254 do {
255 batch = list_first_entry_or_null(&server->list_batch, MppDevBatTask, link_server);
256 if (NULL == batch)
257 break;
258
259 mpp_assert(batch->wait_req_cnt);
260 ret = mpp_service_ioctl_request(server->server_fd, batch->wait_reqs);
261 if (!ret) {
262 MppDevTask *n;
263
264 list_for_each_entry_safe(task, n, &batch->link_tasks, MppDevTask, link_batch) {
265 RK_S32 batch_slot_id = task->batch_slot_id;
266 MppDevBatCmd *cmd = batch->bat_cmd + batch_slot_id;
267
268 mpp_assert(batch_slot_id < server->max_task_in_batch);
269 session = task->session;
270
271 ret = cmd->ret;
272 if (ret == EAGAIN)
273 continue;
274
275 if (ret == -EIO) {
276 mpp_err_f("batch %d:%d task %d poll error found\n",
277 batch->batch_id, task->batch_slot_id, task->task_id);
278 cmd->flag |= 1;
279 continue;
280 }
281 if (ret == 0) {
282 list_del_init(&task->link_batch);
283 task->batch = NULL;
284
285 mpp_serv_dbg_flow("batch %d:%d session %d ready and remove\n",
286 batch->batch_id, task->batch_slot_id, session->client);
287 session->cond->lock();
288 session->task_done++;
289 session->cond->signal();
290 session->cond->unlock();
291 if (session->ctx && session->ctx->dev_cb)
292 mpp_callback(session->ctx->dev_cb, NULL);
293
294 batch->poll_cnt++;
295 cmd->flag |= 1;
296 }
297 }
298
299 mpp_serv_dbg_flow("batch %d fill %d poll %d\n", batch->batch_id,
300 batch->fill_cnt, batch->poll_cnt);
301
302 if (batch->poll_cnt == batch->fill_cnt) {
303 mpp_serv_dbg_flow("batch %d poll done\n", batch->batch_id);
304 list_del_init(&batch->link_server);
305 list_add_tail(&batch->link_server, &server->list_batch_free);
306 server->batch_run--;
307 server->batch_free++;
308
309 batch_reset(batch);
310 batch = NULL;
311 continue;
312 }
313 } else {
314 mpp_log_f("batch %d poll ret %d errno %d %s", batch->batch_id,
315 ret, errno, strerror(errno));
316 mpp_log_f("stop timer\n");
317 mpp_timer_set_enable(server->timer, 0);
318 }
319 break;
320 } while (1);
321
322 /* 2. get prending task to fill */
323 lock->lock();
324 pending = server->pending_count;
325 if (!pending && !server->batch_run && !server->session_count) {
326 mpp_timer_set_enable(server->timer, 0);
327 mpp_serv_dbg_flow("stop timer\n");
328 }
329 lock->unlock();
330
331 mpp_serv_dbg_flow("pending %d running %d free %d max %d process start\n",
332 pending, server->batch_run, server->batch_free, server->batch_max_count);
333
334 try_proc_pending_task:
335 /* 3. try get batch task*/
336 if (!server->batch_free) {
337 /* if not enough and max count does not reached create new batch */
338 if (server->batch_free + server->batch_run >= server->batch_max_count) {
339 mpp_serv_dbg_flow("finish for not batch slot\n");
340 return ;
341 }
342
343 batch_add(server);
344 }
345 mpp_assert(server->batch_free);
346
347 /* 4. if no pending task to send check timeout batch and send it */
348 if (!pending) {
349 if (!server->batch_free) {
350 /* no pending and no free batch just done */
351 return;
352 }
353
354 batch = list_first_entry_or_null(&server->list_batch_free, MppDevBatTask, link_server);
355 mpp_assert(batch);
356 if (NULL == batch) {
357 mpp_log_f("batch run %d free %d\n", server->batch_run, server->batch_free);
358 return;
359 }
360
361 /* send one timeout task */
362 if (batch->fill_cnt)
363 batch_send(server, batch);
364
365 mpp_serv_dbg_flow("finish for no pending task\n");
366 return;
367 }
368
369 mpp_serv_dbg_flow("pending task %d left to process\n", pending);
370
371 /* 5. add task to add batch and try send batch */
372 if (!server->batch_free) {
373 /* no pending and no free batch just done */
374 return;
375 }
376
377 batch = list_first_entry_or_null(&server->list_batch_free, MppDevBatTask, link_server);
378 mpp_assert(batch);
379 mpp_assert(pending);
380
381 task = NULL;
382 lock->lock();
383 task = list_first_entry_or_null(&server->pending_task, MppDevTask, link_server);
384 list_del_init(&task->link_server);
385 server->pending_count--;
386 lock->unlock();
387 pending--;
388
389 /* first task and setup new batch id */
390 if (!batch->fill_cnt)
391 batch->batch_id = server->batch_id++;
392
393 task->batch = batch;
394 task->batch_slot_id = batch->fill_cnt++;
395 mpp_assert(task->batch_slot_id < server->max_task_in_batch);
396 list_add_tail(&task->link_batch, &batch->link_tasks);
397 if (batch->fill_cnt >= server->max_task_in_batch)
398 batch->fill_full = 1;
399
400 session = task->session;
401 mpp_assert(session);
402 mpp_assert(session->ctx);
403
404 bat_cmd = batch->bat_cmd + task->batch_slot_id;
405 bat_cmd->flag = 0;
406 bat_cmd->client = session->client;
407 bat_cmd->ret = 0;
408
409 /* fill task to batch */
410 /* add session info before each session task and then copy session request */
411 req = &batch->send_reqs[batch->send_req_cnt++];
412 req->cmd = MPP_CMD_SET_SESSION_FD;
413 req->flag = MPP_FLAGS_MULTI_MSG;
414 req->offset = 0;
415 req->size = sizeof(*bat_cmd);
416 req->data_ptr = REQ_DATA_PTR(bat_cmd);
417
418 {
419 RK_S32 i;
420
421 for (i = 0; i < task->req_cnt; i++)
422 batch->send_reqs[batch->send_req_cnt++] = task->req[i];
423 }
424
425 mpp_assert(batch->send_req_cnt <= server->max_task_in_batch * MAX_REQ_NUM);
426
427 /* setup poll request */
428 req = &batch->wait_reqs[batch->wait_req_cnt++];
429 req->cmd = MPP_CMD_SET_SESSION_FD;
430 req->flag = MPP_FLAGS_MULTI_MSG;
431 req->offset = 0;
432 req->size = sizeof(*bat_cmd);
433 req->data_ptr = REQ_DATA_PTR(bat_cmd);
434
435 req = &batch->wait_reqs[batch->wait_req_cnt++];
436 req->cmd = MPP_CMD_POLL_HW_FINISH;
437 req->flag = MPP_FLAGS_POLL_NON_BLOCK | MPP_FLAGS_MULTI_MSG | MPP_FLAGS_LAST_MSG;
438 req->offset = 0;
439 req->size = 0;
440 req->data_ptr = 0;
441
442 mpp_serv_dbg_flow("batch %d:%d add task %d:%d:%d\n",
443 batch->batch_id, task->batch_slot_id, session->client,
444 task->slot_idx, task->task_id);
445
446 if (batch->fill_full) {
447 list_del_init(&batch->link_server);
448 list_add_tail(&batch->link_server, &server->list_batch);
449 mpp_serv_dbg_flow("batch %d -> fill_nb %d fill ready\n",
450 batch->batch_id, batch->fill_cnt);
451 batch_send(server, batch);
452 batch = NULL;
453 }
454 goto try_proc_pending_task;
455 }
456
mpp_server_thread(void * ctx)457 static void *mpp_server_thread(void *ctx)
458 {
459 process_task((MppDevBatServ *)ctx);
460 return NULL;
461 }
462
send_task(MppDevMppService * ctx)463 MPP_RET send_task(MppDevMppService *ctx)
464 {
465 MppDevTask *task = NULL;
466 MppDevSession *session = (MppDevSession *)ctx->serv_ctx;
467
468 if (NULL == session || NULL == session->server) {
469 mpp_err_f("invalid ctx %p session %p send task\n", ctx, session);
470 return MPP_NOK;
471 }
472
473 MppDevBatServ *server = session->server;
474
475 /* get free task from session and add to run list */
476 session->cond->lock();
477 /* get a free task and setup */
478 task = list_first_entry_or_null(&session->list_done, MppDevTask, link_session);
479 mpp_assert(task);
480
481 task->req = ctx->reqs;
482 task->req_cnt = ctx->req_cnt;
483
484 list_del_init(&task->link_session);
485 list_add_tail(&task->link_session, &session->list_wait);
486
487 session->task_wait++;
488 session->cond->unlock();
489
490 server->lock->lock();
491 task->task_id = server->task_id++;
492 list_del_init(&task->link_server);
493 list_add_tail(&task->link_server, &server->pending_task);
494 server->pending_count++;
495 mpp_serv_dbg_flow("session %d:%d add pending %d\n",
496 session->client, task->slot_idx, server->pending_count);
497
498 mpp_timer_set_enable(server->timer, 1);
499 server->lock->unlock();
500
501 return MPP_OK;
502 }
503
wait_task(MppDevMppService * ctx,RK_S64 timeout)504 MPP_RET wait_task(MppDevMppService *ctx, RK_S64 timeout)
505 {
506 RK_S32 ret = MPP_OK;
507 MppDevTask *task = NULL;
508 MppDevSession *session = (MppDevSession *)ctx->serv_ctx;
509 (void) timeout;
510
511 if (NULL == session) {
512 mpp_err_f("invalid ctx %p send task\n", ctx);
513 return MPP_NOK;
514 }
515
516 task = list_first_entry_or_null(&session->list_wait, MppDevTask, link_session);
517 mpp_assert(task);
518
519 session->cond->lock();
520 if (session->task_wait != session->task_done) {
521 mpp_serv_dbg_flow("session %d wait %d start %d:%d\n", session->client,
522 task->task_id, session->task_wait, session->task_done);
523 session->cond->wait();
524 }
525 mpp_serv_dbg_flow("session %d wait %d done %d:%d\n", session->client,
526 task->task_id, session->task_wait, session->task_done);
527 session->cond->unlock();
528
529 list_del_init(&task->link_session);
530 list_add_tail(&task->link_session, &session->list_done);
531
532 mpp_assert(session->task_wait == session->task_done);
533
534 return (MPP_RET)ret;
535 }
536
537 class MppDevServer : Mutex
538 {
539 private:
540 // avoid any unwanted function
541 MppDevServer();
542 ~MppDevServer();
543 MppDevServer(const MppDevServer &);
544 MppDevServer &operator=(const MppDevServer &);
545
546 void clear();
547
548 const char *mServerError;
549 const char *mServerName;
550 RK_S32 mInited;
551 RK_U32 mEnable;
552
553 MppDevBatServ *mBatServer[VPU_CLIENT_BUTT];
554
555 MppMemPool mSessionPool;
556 MppMemPool mBatchPool;
557
558 RK_S32 mMaxTaskInBatch;
559
560 const MppServiceCmdCap *mCmdCap;
561
562 public:
get_inst()563 static MppDevServer *get_inst() {
564 static MppDevServer inst;
565 return &inst;
566 }
567
568 MppDevBatServ *bat_server_get(MppClientType client_type);
569 MPP_RET bat_server_put(MppClientType client_type);
570
571 MPP_RET attach(MppDevMppService *ctx);
572 MPP_RET detach(MppDevMppService *ctx);
573
574 MPP_RET check_status(void);
575 };
576
MppDevServer()577 MppDevServer::MppDevServer() :
578 mServerError(NULL),
579 mServerName(NULL),
580 mInited(0),
581 mEnable(1),
582 mSessionPool(NULL),
583 mBatchPool(NULL),
584 mMaxTaskInBatch(0),
585 mCmdCap(NULL)
586 {
587 RK_S32 batch_task_size = 0;
588
589 mpp_env_get_u32("mpp_server_debug", &mpp_server_debug, 0);
590 mpp_env_get_u32("mpp_server_enable", &mEnable, 1);
591 mpp_env_get_u32("mpp_server_batch_task", (RK_U32 *)&mMaxTaskInBatch,
592 MAX_BATCH_TASK);
593
594 mpp_assert(mMaxTaskInBatch >= 1 && mMaxTaskInBatch <= 32);
595 batch_task_size = sizeof(MppDevBatTask) + mMaxTaskInBatch *
596 (sizeof(MppReqV1) * (MAX_REQ_SEND_CNT + MAX_REQ_WAIT_CNT) +
597 sizeof(MppDevBatCmd));
598
599 mCmdCap = mpp_get_mpp_service_cmd_cap();
600 if (MPP_OK != mpp_service_check_cmd_valid(MPP_CMD_SET_SESSION_FD, mCmdCap)) {
601 mServerError = "mpp_service cmd not support";
602 return;
603 }
604
605 do {
606 mServerName = mpp_get_mpp_service_name();
607 if (NULL == mServerName) {
608 mServerError = "get service device failed";
609 break;
610 }
611
612 mSessionPool = mpp_mem_pool_init(sizeof(MppDevSession));
613 if (NULL == mSessionPool) {
614 mServerError = "create session pool failed";
615 break;
616 }
617
618 mBatchPool = mpp_mem_pool_init(batch_task_size);
619 if (NULL == mBatchPool) {
620 mServerError = "create batch tack pool failed";
621 break;
622 }
623
624 mInited = 1;
625 } while (0);
626
627 if (!mInited) {
628 clear();
629 return;
630 }
631
632 memset(mBatServer, 0, sizeof(mBatServer));
633 }
634
~MppDevServer()635 MppDevServer::~MppDevServer()
636 {
637 RK_S32 i;
638
639 for (i = 0; i < VPU_CLIENT_BUTT; i++)
640 bat_server_put((MppClientType)i);
641
642 clear();
643 }
644
clear()645 void MppDevServer::clear()
646 {
647 if (mSessionPool) {
648 mpp_mem_pool_deinit(mSessionPool);
649 mSessionPool = NULL;
650 }
651
652 if (mBatchPool) {
653 mpp_mem_pool_deinit(mBatchPool);
654 mBatchPool = NULL;
655 }
656 mInited = 0;
657 mEnable = 0;
658 }
659
bat_server_get(MppClientType client_type)660 MppDevBatServ *MppDevServer::bat_server_get(MppClientType client_type)
661 {
662 MppDevBatServ *server = NULL;
663
664 AutoMutex auto_lock(this);
665
666 server = mBatServer[client_type];
667 if (server)
668 return server;
669
670 server = mpp_calloc(MppDevBatServ, 1);
671 if (NULL == server) {
672 mpp_err("mpp server failed to get bat server\n");
673 return NULL;
674 }
675
676 server->server_fd = open(mServerName, O_RDWR | O_CLOEXEC);
677 if (server->server_fd < 0) {
678 mpp_err("mpp server get bat server failed to open device\n");
679 goto failed;
680 }
681
682 char timer_name[32];
683
684 snprintf(timer_name, sizeof(timer_name) - 1, "%s_bat",
685 strof_client_type(client_type));
686
687 server->timer = mpp_timer_get(timer_name);
688 if (NULL == server->timer) {
689 mpp_err("mpp server get bat server failed to create timer\n");
690 goto failed;
691 }
692
693 server->lock = new Mutex();
694 if (NULL == server->lock) {
695 mpp_err("mpp server get bat server failed to create mutex\n");
696 goto failed;
697 }
698
699 mpp_timer_set_callback(server->timer, mpp_server_thread, server);
700 /* 10ms */
701 mpp_timer_set_timing(server->timer, 10, 10);
702
703 INIT_LIST_HEAD(&server->session_list);
704 INIT_LIST_HEAD(&server->list_batch);
705 INIT_LIST_HEAD(&server->list_batch_free);
706 INIT_LIST_HEAD(&server->pending_task);
707
708 server->batch_pool = mBatchPool;
709 server->max_task_in_batch = mMaxTaskInBatch;
710
711 mBatServer[client_type] = server;
712 return server;
713
714 failed:
715 if (server) {
716 if (server->timer) {
717 mpp_timer_put(server->timer);
718 server->timer = NULL;
719 }
720
721 if (server->server_fd >= 0) {
722 close(server->server_fd);
723 server->server_fd = -1;
724 }
725 if (server->lock) {
726 delete server->lock;
727 server->lock = NULL;
728 }
729 }
730 MPP_FREE(server);
731 return server;
732 }
733
bat_server_put(MppClientType client_type)734 MPP_RET MppDevServer::bat_server_put(MppClientType client_type)
735 {
736 MppDevBatTask *batch, *n;
737 MppDevBatServ *server = NULL;
738 AutoMutex auto_lock(this);
739
740 if (NULL == mBatServer[client_type])
741 return MPP_OK;
742
743 server = mBatServer[client_type];
744 mBatServer[client_type] = NULL;
745
746 mpp_assert(server->batch_run == 0);
747 mpp_assert(list_empty(&server->list_batch));
748 mpp_assert(server->pending_count == 0);
749
750 /* stop thread first */
751 if (server->timer) {
752 mpp_timer_put(server->timer);
753 server->timer = NULL;
754 }
755
756 if (server->batch_free) {
757 list_for_each_entry_safe(batch, n, &server->list_batch_free, MppDevBatTask, link_server) {
758 batch_del(server, batch);
759 }
760 } else {
761 mpp_assert(list_empty(&server->list_batch_free));
762 }
763
764 if (server->server_fd >= 0) {
765 close(server->server_fd);
766 server->server_fd = -1;
767 }
768 if (server->lock) {
769 delete server->lock;
770 server->lock = NULL;
771 }
772 MPP_FREE(server);
773 return MPP_OK;
774 }
775
attach(MppDevMppService * ctx)776 MPP_RET MppDevServer::attach(MppDevMppService *ctx)
777 {
778 RK_U32 i;
779
780 if (!mInited) {
781 mpp_err("mpp server failed for %s\n", mServerError);
782 return MPP_NOK;
783 }
784
785 MppClientType client_type = (MppClientType)ctx->client_type;
786
787 if (client_type < 0 || client_type >= VPU_CLIENT_BUTT) {
788 mpp_err("mpp server attach failed with invalid client type %d\n", client_type);
789 return MPP_NOK;
790 }
791
792 /* if client type server is not created create it first */
793 MppDevBatServ *server = bat_server_get(client_type);
794 if (NULL == server) {
795 mpp_err("mpp server get bat server with client type %d failed\n", client_type);
796 return MPP_NOK;
797 }
798
799 AutoMutex auto_lock(server->lock);
800 if (ctx->serv_ctx)
801 return MPP_OK;
802
803 MppDevSession *session = (MppDevSession *)mpp_mem_pool_get(mSessionPool);
804 INIT_LIST_HEAD(&session->list_server);
805 INIT_LIST_HEAD(&session->list_wait);
806 INIT_LIST_HEAD(&session->list_done);
807
808 session->ctx = ctx;
809 session->server = server;
810 session->client = ctx->client;
811 session->cond = new MppMutexCond();
812 session->task_wait = 0;
813 session->task_done = 0;
814
815 for (i = 0; i < MPP_ARRAY_ELEMS(session->tasks); i++) {
816 MppDevTask *task = &session->tasks[i];
817
818 INIT_LIST_HEAD(&task->link_server);
819 INIT_LIST_HEAD(&task->link_session);
820 INIT_LIST_HEAD(&task->link_batch);
821 task->session = session;
822 task->batch = NULL;
823 task->task_id = -1;
824 task->slot_idx = i;
825
826 list_add_tail(&task->link_session, &session->list_done);
827 }
828
829 list_add_tail(&session->list_server, &server->session_list);
830 ctx->serv_ctx = session;
831
832 if (mEnable) {
833 ctx->batch_io = 1;
834 ctx->server = server->server_fd;
835 } else {
836 ctx->batch_io = 0;
837 ctx->server = ctx->client;
838 }
839
840 server->batch_max_count++;
841 server->session_count++;
842
843 return MPP_OK;
844 }
845
detach(MppDevMppService * ctx)846 MPP_RET MppDevServer::detach(MppDevMppService *ctx)
847 {
848 if (!mInited) {
849 mpp_err("mpp server failed for %s\n", mServerError);
850 return MPP_NOK;
851 }
852
853 MppClientType client_type = (MppClientType)ctx->client_type;
854
855 MppDevBatServ *server = bat_server_get(client_type);
856 MppDevSession *session = (MppDevSession *)ctx->serv_ctx;
857
858 mpp_assert(server);
859
860 AutoMutex auto_lock(server->lock);
861 if (NULL == ctx->serv_ctx)
862 return MPP_OK;
863
864 ctx->server = ctx->client;
865 ctx->serv_ctx = NULL;
866 ctx->batch_io = 0;
867
868 mpp_assert(server);
869 mpp_assert(session);
870 mpp_assert(session->client == ctx->client);
871 mpp_assert(session->task_wait == session->task_done);
872 mpp_assert(list_empty(&session->list_wait));
873
874 list_del_init(&session->list_server);
875
876 if (session->cond) {
877 delete session->cond;
878 session->cond = NULL;
879 }
880
881 mpp_mem_pool_put(mSessionPool, session);
882 server->batch_max_count++;
883 server->session_count++;
884
885 return MPP_OK;
886 }
887
check_status(void)888 MPP_RET MppDevServer::check_status(void)
889 {
890 if (!mInited) {
891 mpp_err("mpp server failed for %s\n", mServerError);
892 return MPP_NOK;
893 }
894
895 return MPP_OK;
896 }
897
mpp_server_attach(MppDev ctx)898 MPP_RET mpp_server_attach(MppDev ctx)
899 {
900 MppDevMppService *dev = (MppDevMppService *)ctx;
901
902 return MppDevServer::get_inst()->attach(dev);
903 }
904
mpp_server_detach(MppDev ctx)905 MPP_RET mpp_server_detach(MppDev ctx)
906 {
907 MppDevMppService *dev = (MppDevMppService *)ctx;
908
909 return MppDevServer::get_inst()->detach(dev);
910 }
911
mpp_server_send_task(MppDev ctx)912 MPP_RET mpp_server_send_task(MppDev ctx)
913 {
914 MPP_RET ret = MppDevServer::get_inst()->check_status();
915 if (!ret)
916 ret = send_task((MppDevMppService *)ctx);
917
918 return ret;
919 }
920
mpp_server_wait_task(MppDev ctx,RK_S64 timeout)921 MPP_RET mpp_server_wait_task(MppDev ctx, RK_S64 timeout)
922 {
923 MPP_RET ret = MppDevServer::get_inst()->check_status();
924 if (!ret)
925 ret = wait_task((MppDevMppService *)ctx, timeout);
926
927 return ret;
928 }
929