xref: /OK3568_Linux_fs/external/mpp/osal/driver/mpp_server.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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