2 * Copyright © 2012 Intel Corporation
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:
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
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
24 #include "swapchain9.h"
28 #include "nine_helpers.h"
29 #include "nine_pipe.h"
30 #include "nine_dump.h"
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"
37 #include "os/os_thread.h"
38 #include "threadpool.h"
41 threadpool_worker(void *data
)
43 struct threadpool
*pool
= data
;
45 pthread_mutex_lock(&pool
->m
);
47 while (!pool
->shutdown
) {
48 struct threadpool_task
*task
;
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
);
55 pthread_mutex_unlock(&pool
->m
);
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.
63 task
= pool
->workqueue
;
64 pool
->workqueue
= task
->next
;
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
);
74 pthread_mutex_unlock(&pool
->m
);
80 _mesa_threadpool_create(struct NineSwapChain9
*swapchain
)
82 struct threadpool
*pool
= calloc(1, sizeof(*pool
));
87 pthread_mutex_init(&pool
->m
, NULL
);
88 pthread_cond_init(&pool
->new_work
, NULL
);
90 pool
->wthread
= NineSwapChain9_CreateThread(swapchain
, threadpool_worker
, pool
);
92 /* using pthread as fallback */
93 pthread_create(&pool
->pthread
, NULL
, threadpool_worker
, pool
);
99 _mesa_threadpool_destroy(struct NineSwapChain9
*swapchain
, struct threadpool
*pool
)
104 pthread_mutex_lock(&pool
->m
);
105 pool
->shutdown
= TRUE
;
106 pthread_cond_broadcast(&pool
->new_work
);
107 pthread_mutex_unlock(&pool
->m
);
110 NineSwapChain9_WaitForThread(swapchain
, pool
->wthread
);
112 pthread_join(pool
->pthread
, NULL
);
115 pthread_cond_destroy(&pool
->new_work
);
116 pthread_mutex_destroy(&pool
->m
);
121 * Queues a request for the work function to be asynchronously executed by the
124 * The work func will get the "data" argument as its parameter -- any
125 * communication between the caller and the work function will occur through
128 * If there is an error, the work function is called immediately and NULL is
131 struct threadpool_task
*
132 _mesa_threadpool_queue_task(struct threadpool
*pool
,
133 threadpool_task_func work
, void *data
)
135 struct threadpool_task
*task
, *previous
;
142 task
= calloc(1, sizeof(*task
));
151 pthread_cond_init(&task
->finish
, NULL
);
153 pthread_mutex_lock(&pool
->m
);
155 if (!pool
->workqueue
) {
156 pool
->workqueue
= task
;
158 previous
= pool
->workqueue
;
159 while (previous
&& previous
->next
)
160 previous
= previous
->next
;
162 previous
->next
= task
;
164 pthread_cond_signal(&pool
->new_work
);
165 pthread_mutex_unlock(&pool
->m
);
171 * Blocks on the completion of the given task and frees the task.
174 _mesa_threadpool_wait_for_task(struct threadpool
*pool
,
175 struct threadpool_task
**task_handle
)
177 struct threadpool_task
*task
= *task_handle
;
182 pthread_mutex_lock(&pool
->m
);
183 while (!task
->finished
)
184 pthread_cond_wait(&task
->finish
, &pool
->m
);
185 pthread_mutex_unlock(&pool
->m
);
187 pthread_cond_destroy(&task
->finish
);