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
16 #include "vp9/decoder/vp9_job_queue.h"
17
vp9_jobq_init(JobQueueRowMt * jobq,uint8_t * buf,size_t buf_size)18 void vp9_jobq_init(JobQueueRowMt *jobq, uint8_t *buf, size_t buf_size) {
19 #if CONFIG_MULTITHREAD
20 pthread_mutex_init(&jobq->mutex, NULL);
21 pthread_cond_init(&jobq->cond, NULL);
22 #endif
23 jobq->buf_base = buf;
24 jobq->buf_wr = buf;
25 jobq->buf_rd = buf;
26 jobq->buf_end = buf + buf_size;
27 jobq->terminate = 0;
28 }
29
vp9_jobq_reset(JobQueueRowMt * jobq)30 void vp9_jobq_reset(JobQueueRowMt *jobq) {
31 #if CONFIG_MULTITHREAD
32 pthread_mutex_lock(&jobq->mutex);
33 #endif
34 jobq->buf_wr = jobq->buf_base;
35 jobq->buf_rd = jobq->buf_base;
36 jobq->terminate = 0;
37 #if CONFIG_MULTITHREAD
38 pthread_mutex_unlock(&jobq->mutex);
39 #endif
40 }
41
vp9_jobq_deinit(JobQueueRowMt * jobq)42 void vp9_jobq_deinit(JobQueueRowMt *jobq) {
43 vp9_jobq_reset(jobq);
44 #if CONFIG_MULTITHREAD
45 pthread_mutex_destroy(&jobq->mutex);
46 pthread_cond_destroy(&jobq->cond);
47 #endif
48 }
49
vp9_jobq_terminate(JobQueueRowMt * jobq)50 void vp9_jobq_terminate(JobQueueRowMt *jobq) {
51 #if CONFIG_MULTITHREAD
52 pthread_mutex_lock(&jobq->mutex);
53 #endif
54 jobq->terminate = 1;
55 #if CONFIG_MULTITHREAD
56 pthread_cond_broadcast(&jobq->cond);
57 pthread_mutex_unlock(&jobq->mutex);
58 #endif
59 }
60
vp9_jobq_queue(JobQueueRowMt * jobq,void * job,size_t job_size)61 int vp9_jobq_queue(JobQueueRowMt *jobq, void *job, size_t job_size) {
62 int ret = 0;
63 #if CONFIG_MULTITHREAD
64 pthread_mutex_lock(&jobq->mutex);
65 #endif
66 if (jobq->buf_end >= jobq->buf_wr + job_size) {
67 memcpy(jobq->buf_wr, job, job_size);
68 jobq->buf_wr = jobq->buf_wr + job_size;
69 #if CONFIG_MULTITHREAD
70 pthread_cond_signal(&jobq->cond);
71 #endif
72 ret = 0;
73 } else {
74 /* Wrap around case is not supported */
75 assert(0);
76 ret = 1;
77 }
78 #if CONFIG_MULTITHREAD
79 pthread_mutex_unlock(&jobq->mutex);
80 #endif
81 return ret;
82 }
83
vp9_jobq_dequeue(JobQueueRowMt * jobq,void * job,size_t job_size,int blocking)84 int vp9_jobq_dequeue(JobQueueRowMt *jobq, void *job, size_t job_size,
85 int blocking) {
86 int ret = 0;
87 #if CONFIG_MULTITHREAD
88 pthread_mutex_lock(&jobq->mutex);
89 #endif
90 if (jobq->buf_end >= jobq->buf_rd + job_size) {
91 while (1) {
92 if (jobq->buf_wr >= jobq->buf_rd + job_size) {
93 memcpy(job, jobq->buf_rd, job_size);
94 jobq->buf_rd = jobq->buf_rd + job_size;
95 ret = 0;
96 break;
97 } else {
98 /* If all the entries have been dequeued, then break and return */
99 if (jobq->terminate == 1) {
100 ret = 1;
101 break;
102 }
103 if (blocking == 1) {
104 #if CONFIG_MULTITHREAD
105 pthread_cond_wait(&jobq->cond, &jobq->mutex);
106 #endif
107 } else {
108 /* If there is no job available,
109 * and this is non blocking call then return fail */
110 ret = 1;
111 break;
112 }
113 }
114 }
115 } else {
116 /* Wrap around case is not supported */
117 ret = 1;
118 }
119 #if CONFIG_MULTITHREAD
120 pthread_mutex_unlock(&jobq->mutex);
121 #endif
122
123 return ret;
124 }
125