Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: source/libvpx/vp9/decoder/vp9_thread.c

Issue 375983002: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « source/libvpx/vp9/decoder/vp9_thread.h ('k') | source/libvpx/vp9/encoder/vp9_aq_complexity.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 Google Inc. All Rights Reserved. 1 // Copyright 2013 Google Inc. All Rights Reserved.
2 // 2 //
3 // Use of this source code is governed by a BSD-style license 3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source 4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may 6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree. 7 // be found in the AUTHORS file in the root of the source tree.
8 // ----------------------------------------------------------------------------- 8 // -----------------------------------------------------------------------------
9 // 9 //
10 // Multi-threaded worker 10 // Multi-threaded worker
11 // 11 //
12 // Original source: 12 // Original source:
13 // http://git.chromium.org/webm/libwebp.git 13 // http://git.chromium.org/webm/libwebp.git
14 // 100644 blob eff8f2a8c20095aade3c292b0e9292dac6cb3587 src/utils/thread.c 14 // 100644 blob 08ad4e1fecba302bf1247645e84a7d2779956bc3 src/utils/thread.c
15
16 15
17 #include <assert.h> 16 #include <assert.h>
18 #include <string.h> // for memset() 17 #include <string.h> // for memset()
19 #include "./vp9_thread.h" 18 #include "./vp9_thread.h"
20 19 #include "vpx_mem/vpx_mem.h"
21 #if defined(__cplusplus) || defined(c_plusplus)
22 extern "C" {
23 #endif
24 20
25 #if CONFIG_MULTITHREAD 21 #if CONFIG_MULTITHREAD
26 22
23 struct VP9WorkerImpl {
24 pthread_mutex_t mutex_;
25 pthread_cond_t condition_;
26 pthread_t thread_;
27 };
28
27 //------------------------------------------------------------------------------ 29 //------------------------------------------------------------------------------
28 30
29 static THREADFN thread_loop(void *ptr) { // thread loop 31 static void execute(VP9Worker *const worker); // Forward declaration.
30 VP9Worker* const worker = (VP9Worker*)ptr; 32
33 static THREADFN thread_loop(void *ptr) {
34 VP9Worker *const worker = (VP9Worker*)ptr;
31 int done = 0; 35 int done = 0;
32 while (!done) { 36 while (!done) {
33 pthread_mutex_lock(&worker->mutex_); 37 pthread_mutex_lock(&worker->impl_->mutex_);
34 while (worker->status_ == OK) { // wait in idling mode 38 while (worker->status_ == OK) { // wait in idling mode
35 pthread_cond_wait(&worker->condition_, &worker->mutex_); 39 pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
36 } 40 }
37 if (worker->status_ == WORK) { 41 if (worker->status_ == WORK) {
38 vp9_worker_execute(worker); 42 execute(worker);
39 worker->status_ = OK; 43 worker->status_ = OK;
40 } else if (worker->status_ == NOT_OK) { // finish the worker 44 } else if (worker->status_ == NOT_OK) { // finish the worker
41 done = 1; 45 done = 1;
42 } 46 }
43 // signal to the main thread that we're done (for Sync()) 47 // signal to the main thread that we're done (for sync())
44 pthread_cond_signal(&worker->condition_); 48 pthread_cond_signal(&worker->impl_->condition_);
45 pthread_mutex_unlock(&worker->mutex_); 49 pthread_mutex_unlock(&worker->impl_->mutex_);
46 } 50 }
47 return THREAD_RETURN(NULL); // Thread is finished 51 return THREAD_RETURN(NULL); // Thread is finished
48 } 52 }
49 53
50 // main thread state control 54 // main thread state control
51 static void change_state(VP9Worker* const worker, 55 static void change_state(VP9Worker *const worker,
52 VP9WorkerStatus new_status) { 56 VP9WorkerStatus new_status) {
53 // no-op when attempting to change state on a thread that didn't come up 57 // No-op when attempting to change state on a thread that didn't come up.
54 if (worker->status_ < OK) return; 58 // Checking status_ without acquiring the lock first would result in a data
59 // race.
60 if (worker->impl_ == NULL) return;
55 61
56 pthread_mutex_lock(&worker->mutex_); 62 pthread_mutex_lock(&worker->impl_->mutex_);
57 // wait for the worker to finish 63 if (worker->status_ >= OK) {
58 while (worker->status_ != OK) { 64 // wait for the worker to finish
59 pthread_cond_wait(&worker->condition_, &worker->mutex_); 65 while (worker->status_ != OK) {
66 pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
67 }
68 // assign new status and release the working thread if needed
69 if (new_status != OK) {
70 worker->status_ = new_status;
71 pthread_cond_signal(&worker->impl_->condition_);
72 }
60 } 73 }
61 // assign new status and release the working thread if needed 74 pthread_mutex_unlock(&worker->impl_->mutex_);
62 if (new_status != OK) {
63 worker->status_ = new_status;
64 pthread_cond_signal(&worker->condition_);
65 }
66 pthread_mutex_unlock(&worker->mutex_);
67 } 75 }
68 76
69 #endif // CONFIG_MULTITHREAD 77 #endif // CONFIG_MULTITHREAD
70 78
71 //------------------------------------------------------------------------------ 79 //------------------------------------------------------------------------------
72 80
73 void vp9_worker_init(VP9Worker* const worker) { 81 static void init(VP9Worker *const worker) {
74 memset(worker, 0, sizeof(*worker)); 82 memset(worker, 0, sizeof(*worker));
75 worker->status_ = NOT_OK; 83 worker->status_ = NOT_OK;
76 } 84 }
77 85
78 int vp9_worker_sync(VP9Worker* const worker) { 86 static int sync(VP9Worker *const worker) {
79 #if CONFIG_MULTITHREAD 87 #if CONFIG_MULTITHREAD
80 change_state(worker, OK); 88 change_state(worker, OK);
81 #endif 89 #endif
82 assert(worker->status_ <= OK); 90 assert(worker->status_ <= OK);
83 return !worker->had_error; 91 return !worker->had_error;
84 } 92 }
85 93
86 int vp9_worker_reset(VP9Worker* const worker) { 94 static int reset(VP9Worker *const worker) {
87 int ok = 1; 95 int ok = 1;
88 worker->had_error = 0; 96 worker->had_error = 0;
89 if (worker->status_ < OK) { 97 if (worker->status_ < OK) {
90 #if CONFIG_MULTITHREAD 98 #if CONFIG_MULTITHREAD
91 if (pthread_mutex_init(&worker->mutex_, NULL) || 99 worker->impl_ = (VP9WorkerImpl*)vpx_calloc(1, sizeof(*worker->impl_));
92 pthread_cond_init(&worker->condition_, NULL)) { 100 if (worker->impl_ == NULL) {
93 return 0; 101 return 0;
94 } 102 }
95 pthread_mutex_lock(&worker->mutex_); 103 if (pthread_mutex_init(&worker->impl_->mutex_, NULL)) {
96 ok = !pthread_create(&worker->thread_, NULL, thread_loop, worker); 104 goto Error;
105 }
106 if (pthread_cond_init(&worker->impl_->condition_, NULL)) {
107 pthread_mutex_destroy(&worker->impl_->mutex_);
108 goto Error;
109 }
110 pthread_mutex_lock(&worker->impl_->mutex_);
111 ok = !pthread_create(&worker->impl_->thread_, NULL, thread_loop, worker);
97 if (ok) worker->status_ = OK; 112 if (ok) worker->status_ = OK;
98 pthread_mutex_unlock(&worker->mutex_); 113 pthread_mutex_unlock(&worker->impl_->mutex_);
114 if (!ok) {
115 pthread_mutex_destroy(&worker->impl_->mutex_);
116 pthread_cond_destroy(&worker->impl_->condition_);
117 Error:
118 vpx_free(worker->impl_);
119 worker->impl_ = NULL;
120 return 0;
121 }
99 #else 122 #else
100 worker->status_ = OK; 123 worker->status_ = OK;
101 #endif 124 #endif
102 } else if (worker->status_ > OK) { 125 } else if (worker->status_ > OK) {
103 ok = vp9_worker_sync(worker); 126 ok = sync(worker);
104 } 127 }
105 assert(!ok || (worker->status_ == OK)); 128 assert(!ok || (worker->status_ == OK));
106 return ok; 129 return ok;
107 } 130 }
108 131
109 void vp9_worker_execute(VP9Worker* const worker) { 132 static void execute(VP9Worker *const worker) {
110 if (worker->hook != NULL) { 133 if (worker->hook != NULL) {
111 worker->had_error |= !worker->hook(worker->data1, worker->data2); 134 worker->had_error |= !worker->hook(worker->data1, worker->data2);
112 } 135 }
113 } 136 }
114 137
115 void vp9_worker_launch(VP9Worker* const worker) { 138 static void launch(VP9Worker *const worker) {
116 #if CONFIG_MULTITHREAD 139 #if CONFIG_MULTITHREAD
117 change_state(worker, WORK); 140 change_state(worker, WORK);
118 #else 141 #else
119 vp9_worker_execute(worker); 142 execute(worker);
120 #endif 143 #endif
121 } 144 }
122 145
123 void vp9_worker_end(VP9Worker* const worker) { 146 static void end(VP9Worker *const worker) {
124 if (worker->status_ >= OK) { 147 if (worker->status_ >= OK) {
125 #if CONFIG_MULTITHREAD 148 #if CONFIG_MULTITHREAD
126 change_state(worker, NOT_OK); 149 change_state(worker, NOT_OK);
127 pthread_join(worker->thread_, NULL); 150 pthread_join(worker->impl_->thread_, NULL);
128 pthread_mutex_destroy(&worker->mutex_); 151 pthread_mutex_destroy(&worker->impl_->mutex_);
129 pthread_cond_destroy(&worker->condition_); 152 pthread_cond_destroy(&worker->impl_->condition_);
130 #else 153 #else
131 worker->status_ = NOT_OK; 154 worker->status_ = NOT_OK;
132 #endif 155 #endif
133 } 156 }
157 vpx_free(worker->impl_);
158 worker->impl_ = NULL;
134 assert(worker->status_ == NOT_OK); 159 assert(worker->status_ == NOT_OK);
135 } 160 }
136 161
137 //------------------------------------------------------------------------------ 162 //------------------------------------------------------------------------------
138 163
139 #if defined(__cplusplus) || defined(c_plusplus) 164 static VP9WorkerInterface g_worker_interface = {
140 } // extern "C" 165 init, reset, sync, launch, execute, end
141 #endif 166 };
167
168 int vp9_set_worker_interface(const VP9WorkerInterface* const winterface) {
169 if (winterface == NULL ||
170 winterface->init == NULL || winterface->reset == NULL ||
171 winterface->sync == NULL || winterface->launch == NULL ||
172 winterface->execute == NULL || winterface->end == NULL) {
173 return 0;
174 }
175 g_worker_interface = *winterface;
176 return 1;
177 }
178
179 const VP9WorkerInterface *vp9_get_worker_interface(void) {
180 return &g_worker_interface;
181 }
182
183 //------------------------------------------------------------------------------
OLDNEW
« no previous file with comments | « source/libvpx/vp9/decoder/vp9_thread.h ('k') | source/libvpx/vp9/encoder/vp9_aq_complexity.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698