LCOV - code coverage report
Current view: top level - third_party/aom/aom_util - aom_thread.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 86 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
       3             :  *
       4             :  * This source code is subject to the terms of the BSD 2 Clause License and
       5             :  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
       6             :  * was not distributed with this source code in the LICENSE file, you can
       7             :  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
       8             :  * Media Patent License 1.0 was not distributed with this source code in the
       9             :  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
      10             :  */
      11             : //
      12             : // Multi-threaded worker
      13             : //
      14             : // Original source:
      15             : //  https://chromium.googlesource.com/webm/libwebp
      16             : 
      17             : #include <assert.h>
      18             : #include <string.h>  // for memset()
      19             : #include "./aom_thread.h"
      20             : #include "aom_mem/aom_mem.h"
      21             : 
      22             : #if CONFIG_MULTITHREAD
      23             : 
      24             : struct AVxWorkerImpl {
      25             :   pthread_mutex_t mutex_;
      26             :   pthread_cond_t condition_;
      27             :   pthread_t thread_;
      28             : };
      29             : 
      30             : //------------------------------------------------------------------------------
      31             : 
      32             : static void execute(AVxWorker *const worker);  // Forward declaration.
      33             : 
      34           0 : static THREADFN thread_loop(void *ptr) {
      35           0 :   AVxWorker *const worker = (AVxWorker *)ptr;
      36           0 :   int done = 0;
      37           0 :   while (!done) {
      38           0 :     pthread_mutex_lock(&worker->impl_->mutex_);
      39           0 :     while (worker->status_ == OK) {  // wait in idling mode
      40           0 :       pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
      41             :     }
      42           0 :     if (worker->status_ == WORK) {
      43           0 :       execute(worker);
      44           0 :       worker->status_ = OK;
      45           0 :     } else if (worker->status_ == NOT_OK) {  // finish the worker
      46           0 :       done = 1;
      47             :     }
      48             :     // signal to the main thread that we're done (for sync())
      49           0 :     pthread_cond_signal(&worker->impl_->condition_);
      50           0 :     pthread_mutex_unlock(&worker->impl_->mutex_);
      51             :   }
      52           0 :   return THREAD_RETURN(NULL);  // Thread is finished
      53             : }
      54             : 
      55             : // main thread state control
      56           0 : static void change_state(AVxWorker *const worker, AVxWorkerStatus new_status) {
      57             :   // No-op when attempting to change state on a thread that didn't come up.
      58             :   // Checking status_ without acquiring the lock first would result in a data
      59             :   // race.
      60           0 :   if (worker->impl_ == NULL) return;
      61             : 
      62           0 :   pthread_mutex_lock(&worker->impl_->mutex_);
      63           0 :   if (worker->status_ >= OK) {
      64             :     // wait for the worker to finish
      65           0 :     while (worker->status_ != OK) {
      66           0 :       pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_);
      67             :     }
      68             :     // assign new status and release the working thread if needed
      69           0 :     if (new_status != OK) {
      70           0 :       worker->status_ = new_status;
      71           0 :       pthread_cond_signal(&worker->impl_->condition_);
      72             :     }
      73             :   }
      74           0 :   pthread_mutex_unlock(&worker->impl_->mutex_);
      75             : }
      76             : 
      77             : #endif  // CONFIG_MULTITHREAD
      78             : 
      79             : //------------------------------------------------------------------------------
      80             : 
      81           0 : static void init(AVxWorker *const worker) {
      82           0 :   memset(worker, 0, sizeof(*worker));
      83           0 :   worker->status_ = NOT_OK;
      84           0 : }
      85             : 
      86           0 : static int sync(AVxWorker *const worker) {
      87             : #if CONFIG_MULTITHREAD
      88           0 :   change_state(worker, OK);
      89             : #endif
      90           0 :   assert(worker->status_ <= OK);
      91           0 :   return !worker->had_error;
      92             : }
      93             : 
      94           0 : static int reset(AVxWorker *const worker) {
      95           0 :   int ok = 1;
      96           0 :   worker->had_error = 0;
      97           0 :   if (worker->status_ < OK) {
      98             : #if CONFIG_MULTITHREAD
      99           0 :     worker->impl_ = (AVxWorkerImpl *)aom_calloc(1, sizeof(*worker->impl_));
     100           0 :     if (worker->impl_ == NULL) {
     101           0 :       return 0;
     102             :     }
     103           0 :     if (pthread_mutex_init(&worker->impl_->mutex_, NULL)) {
     104           0 :       goto Error;
     105             :     }
     106           0 :     if (pthread_cond_init(&worker->impl_->condition_, NULL)) {
     107           0 :       pthread_mutex_destroy(&worker->impl_->mutex_);
     108           0 :       goto Error;
     109             :     }
     110           0 :     pthread_mutex_lock(&worker->impl_->mutex_);
     111           0 :     ok = !pthread_create(&worker->impl_->thread_, NULL, thread_loop, worker);
     112           0 :     if (ok) worker->status_ = OK;
     113           0 :     pthread_mutex_unlock(&worker->impl_->mutex_);
     114           0 :     if (!ok) {
     115           0 :       pthread_mutex_destroy(&worker->impl_->mutex_);
     116           0 :       pthread_cond_destroy(&worker->impl_->condition_);
     117             :     Error:
     118           0 :       aom_free(worker->impl_);
     119           0 :       worker->impl_ = NULL;
     120           0 :       return 0;
     121             :     }
     122             : #else
     123             :     worker->status_ = OK;
     124             : #endif
     125           0 :   } else if (worker->status_ > OK) {
     126           0 :     ok = sync(worker);
     127             :   }
     128           0 :   assert(!ok || (worker->status_ == OK));
     129           0 :   return ok;
     130             : }
     131             : 
     132           0 : static void execute(AVxWorker *const worker) {
     133           0 :   if (worker->hook != NULL) {
     134           0 :     worker->had_error |= !worker->hook(worker->data1, worker->data2);
     135             :   }
     136           0 : }
     137             : 
     138           0 : static void launch(AVxWorker *const worker) {
     139             : #if CONFIG_MULTITHREAD
     140           0 :   change_state(worker, WORK);
     141             : #else
     142             :   execute(worker);
     143             : #endif
     144           0 : }
     145             : 
     146           0 : static void end(AVxWorker *const worker) {
     147             : #if CONFIG_MULTITHREAD
     148           0 :   if (worker->impl_ != NULL) {
     149           0 :     change_state(worker, NOT_OK);
     150           0 :     pthread_join(worker->impl_->thread_, NULL);
     151           0 :     pthread_mutex_destroy(&worker->impl_->mutex_);
     152           0 :     pthread_cond_destroy(&worker->impl_->condition_);
     153           0 :     aom_free(worker->impl_);
     154           0 :     worker->impl_ = NULL;
     155             :   }
     156             : #else
     157             :   worker->status_ = NOT_OK;
     158             :   assert(worker->impl_ == NULL);
     159             : #endif
     160           0 :   assert(worker->status_ == NOT_OK);
     161           0 : }
     162             : 
     163             : //------------------------------------------------------------------------------
     164             : 
     165             : static AVxWorkerInterface g_worker_interface = { init,   reset,   sync,
     166             :                                                  launch, execute, end };
     167             : 
     168           0 : int aom_set_worker_interface(const AVxWorkerInterface *const winterface) {
     169           0 :   if (winterface == NULL || winterface->init == NULL ||
     170           0 :       winterface->reset == NULL || winterface->sync == NULL ||
     171           0 :       winterface->launch == NULL || winterface->execute == NULL ||
     172           0 :       winterface->end == NULL) {
     173           0 :     return 0;
     174             :   }
     175           0 :   g_worker_interface = *winterface;
     176           0 :   return 1;
     177             : }
     178             : 
     179           0 : const AVxWorkerInterface *aom_get_worker_interface(void) {
     180           0 :   return &g_worker_interface;
     181             : }
     182             : 
     183             : //------------------------------------------------------------------------------

Generated by: LCOV version 1.13