Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2012 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21.  * IN THE SOFTWARE.
  22.  */
  23.  
  24. #include "swapchain9.h"
  25. #include "surface9.h"
  26. #include "device9.h"
  27.  
  28. #include "nine_helpers.h"
  29. #include "nine_pipe.h"
  30. #include "nine_dump.h"
  31.  
  32. #include "util/u_inlines.h"
  33. #include "util/u_surface.h"
  34. #include "hud/hud_context.h"
  35. #include "state_tracker/drm_driver.h"
  36.  
  37. #include "os/os_thread.h"
  38. #include "threadpool.h"
  39.  
  40. static void *
  41. threadpool_worker(void *data)
  42. {
  43.     struct threadpool *pool = data;
  44.  
  45.     pthread_mutex_lock(&pool->m);
  46.  
  47.     while (!pool->shutdown) {
  48.         struct threadpool_task *task;
  49.  
  50.         /* Block (dropping the lock) until new work arrives for us. */
  51.         while (!pool->workqueue && !pool->shutdown)
  52.             pthread_cond_wait(&pool->new_work, &pool->m);
  53.  
  54.         if (pool->shutdown) {
  55.             pthread_mutex_unlock(&pool->m);
  56.             return NULL;
  57.         }
  58.  
  59.         /* Pull the first task from the list.  We don't free it -- it now lacks
  60.          * a reference other than the worker creator's, whose responsibility it
  61.          * is to call threadpool_wait_for_work() to free it.
  62.          */
  63.         task = pool->workqueue;
  64.         pool->workqueue = task->next;
  65.  
  66.         /* Call the task's work func. */
  67.         pthread_mutex_unlock(&pool->m);
  68.         task->work(task->data);
  69.         pthread_mutex_lock(&pool->m);
  70.         task->finished = TRUE;
  71.         pthread_cond_broadcast(&task->finish);
  72.     }
  73.  
  74.     pthread_mutex_unlock(&pool->m);
  75.  
  76.     return NULL;
  77. }
  78.  
  79. struct threadpool *
  80. _mesa_threadpool_create(void)
  81. {
  82.     struct threadpool *pool = calloc(1, sizeof(*pool));
  83.  
  84.     if (!pool)
  85.         return NULL;
  86.  
  87.     pthread_mutex_init(&pool->m, NULL);
  88.     pthread_cond_init(&pool->new_work, NULL);
  89.  
  90.     pthread_create(&pool->thread, NULL, threadpool_worker, pool);
  91.  
  92.     return pool;
  93. }
  94.  
  95. void
  96. _mesa_threadpool_destroy(struct threadpool *pool)
  97. {
  98.     if (!pool)
  99.         return;
  100.  
  101.     pthread_mutex_lock(&pool->m);
  102.     pool->shutdown = TRUE;
  103.     pthread_cond_broadcast(&pool->new_work);
  104.     pthread_mutex_unlock(&pool->m);
  105.  
  106.     pthread_join(pool->thread, NULL);
  107.  
  108.     pthread_cond_destroy(&pool->new_work);
  109.     pthread_mutex_destroy(&pool->m);
  110.     free(pool);
  111. }
  112.  
  113. /**
  114.  * Queues a request for the work function to be asynchronously executed by the
  115.  * thread pool.
  116.  *
  117.  * The work func will get the "data" argument as its parameter -- any
  118.  * communication between the caller and the work function will occur through
  119.  * that.
  120.  *
  121.  * If there is an error, the work function is called immediately and NULL is
  122.  * returned.
  123.  */
  124. struct threadpool_task *
  125. _mesa_threadpool_queue_task(struct threadpool *pool,
  126.                             threadpool_task_func work, void *data)
  127. {
  128.     struct threadpool_task *task, *previous;
  129.  
  130.     if (!pool) {
  131.         work(data);
  132.         return NULL;
  133.     }
  134.  
  135.     task = calloc(1, sizeof(*task));
  136.     if (!task) {
  137.         work(data);
  138.         return NULL;
  139.     }
  140.  
  141.     task->work = work;
  142.     task->data = data;
  143.     task->next = NULL;
  144.     pthread_cond_init(&task->finish, NULL);
  145.  
  146.     pthread_mutex_lock(&pool->m);
  147.  
  148.     if (!pool->workqueue) {
  149.         pool->workqueue = task;
  150.     } else {
  151.         previous = pool->workqueue;
  152.         while (previous && previous->next)
  153.             previous = previous->next;
  154.  
  155.         previous->next = task;
  156.     }
  157.     pthread_cond_signal(&pool->new_work);
  158.     pthread_mutex_unlock(&pool->m);
  159.  
  160.     return task;
  161. }
  162.  
  163. /**
  164.  * Blocks on the completion of the given task and frees the task.
  165.  */
  166. void
  167. _mesa_threadpool_wait_for_task(struct threadpool *pool,
  168.                                struct threadpool_task **task_handle)
  169. {
  170.     struct threadpool_task *task = *task_handle;
  171.  
  172.     if (!pool || !task)
  173.         return;
  174.  
  175.     pthread_mutex_lock(&pool->m);
  176.     while (!task->finished)
  177.         pthread_cond_wait(&task->finish, &pool->m);
  178.     pthread_mutex_unlock(&pool->m);
  179.  
  180.     pthread_cond_destroy(&task->finish);
  181.     free(task);
  182.     *task_handle = NULL;
  183. }
  184.