1 /*
2 * Copyright (c) 2018 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <assert.h>
12 #include <string.h>
13
14 #include "vpx/vpx_integer.h"
15 #include "vpx_util/vpx_pthread.h"
16
17 #include "vp9/decoder/vp9_job_queue.h"
18
vp9_jobq_init(JobQueueRowMt * jobq,uint8_t * buf,size_t buf_size)19 void vp9_jobq_init(JobQueueRowMt *jobq, uint8_t *buf, size_t buf_size) {
20 #if CONFIG_MULTITHREAD
21 pthread_mutex_init(&jobq->mutex, NULL);
22 pthread_cond_init(&jobq->cond, NULL);
23 #endif
24 jobq->buf_base = buf;
25 jobq->buf_wr = buf;
26 jobq->buf_rd = buf;
27 jobq->buf_end = buf + buf_size;
28 jobq->terminate = 0;
29 }
30
vp9_jobq_reset(JobQueueRowMt * jobq)31 void vp9_jobq_reset(JobQueueRowMt *jobq) {
32 #if CONFIG_MULTITHREAD
33 pthread_mutex_lock(&jobq->mutex);
34 #endif
35 jobq->buf_wr = jobq->buf_base;
36 jobq->buf_rd = jobq->buf_base;
37 jobq->terminate = 0;
38 #if CONFIG_MULTITHREAD
39 pthread_mutex_unlock(&jobq->mutex);
40 #endif
41 }
42
vp9_jobq_deinit(JobQueueRowMt * jobq)43 void vp9_jobq_deinit(JobQueueRowMt *jobq) {
44 vp9_jobq_reset(jobq);
45 #if CONFIG_MULTITHREAD
46 pthread_mutex_destroy(&jobq->mutex);
47 pthread_cond_destroy(&jobq->cond);
48 #endif
49 }
50
vp9_jobq_terminate(JobQueueRowMt * jobq)51 void vp9_jobq_terminate(JobQueueRowMt *jobq) {
52 #if CONFIG_MULTITHREAD
53 pthread_mutex_lock(&jobq->mutex);
54 #endif
55 jobq->terminate = 1;
56 #if CONFIG_MULTITHREAD
57 pthread_cond_broadcast(&jobq->cond);
58 pthread_mutex_unlock(&jobq->mutex);
59 #endif
60 }
61
vp9_jobq_queue(JobQueueRowMt * jobq,void * job,size_t job_size)62 int vp9_jobq_queue(JobQueueRowMt *jobq, void *job, size_t job_size) {
63 int ret = 0;
64 #if CONFIG_MULTITHREAD
65 pthread_mutex_lock(&jobq->mutex);
66 #endif
67 if (jobq->buf_end >= jobq->buf_wr + job_size) {
68 memcpy(jobq->buf_wr, job, job_size);
69 jobq->buf_wr = jobq->buf_wr + job_size;
70 #if CONFIG_MULTITHREAD
71 pthread_cond_signal(&jobq->cond);
72 #endif
73 ret = 0;
74 } else {
75 /* Wrap around case is not supported */
76 assert(0);
77 ret = 1;
78 }
79 #if CONFIG_MULTITHREAD
80 pthread_mutex_unlock(&jobq->mutex);
81 #endif
82 return ret;
83 }
84
vp9_jobq_dequeue(JobQueueRowMt * jobq,void * job,size_t job_size,int blocking)85 int vp9_jobq_dequeue(JobQueueRowMt *jobq, void *job, size_t job_size,
86 int blocking) {
87 int ret = 0;
88 #if CONFIG_MULTITHREAD
89 pthread_mutex_lock(&jobq->mutex);
90 #endif
91 if (jobq->buf_end >= jobq->buf_rd + job_size) {
92 while (1) {
93 if (jobq->buf_wr >= jobq->buf_rd + job_size) {
94 memcpy(job, jobq->buf_rd, job_size);
95 jobq->buf_rd = jobq->buf_rd + job_size;
96 ret = 0;
97 break;
98 } else {
99 /* If all the entries have been dequeued, then break and return */
100 if (jobq->terminate == 1) {
101 ret = 1;
102 break;
103 }
104 if (blocking == 1) {
105 #if CONFIG_MULTITHREAD
106 pthread_cond_wait(&jobq->cond, &jobq->mutex);
107 #endif
108 } else {
109 /* If there is no job available,
110 * and this is non blocking call then return fail */
111 ret = 1;
112 break;
113 }
114 }
115 }
116 } else {
117 /* Wrap around case is not supported */
118 ret = 1;
119 }
120 #if CONFIG_MULTITHREAD
121 pthread_mutex_unlock(&jobq->mutex);
122 #endif
123
124 return ret;
125 }
126