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"
40 /* POSIX thread function */
42 threadpool_worker(void *data
)
44 struct threadpool
*pool
= data
;
46 pthread_mutex_lock(&pool
->m
);
48 while (!pool
->shutdown
) {
49 struct threadpool_task
*task
;
51 /* Block (dropping the lock) until new work arrives for us. */
52 while (!pool
->workqueue
&& !pool
->shutdown
)
53 pthread_cond_wait(&pool
->new_work
, &pool
->m
);
58 /* Pull the first task from the list. We don't free it -- it now lacks
59 * a reference other than the worker creator's, whose responsibility it
60 * is to call threadpool_wait_for_work() to free it.
62 task
= pool
->workqueue
;
63 pool
->workqueue
= task
->next
;
65 /* Call the task's work func. */
66 pthread_mutex_unlock(&pool
->m
);
67 task
->work(task
->data
);
68 pthread_mutex_lock(&pool
->m
);
69 task
->finished
= TRUE
;
70 pthread_cond_broadcast(&task
->finish
);
73 pthread_mutex_unlock(&pool
->m
);
78 /* Windows thread function */
79 static DWORD NINE_WINAPI
80 wthreadpool_worker(void *data
)
82 threadpool_worker(data
);
88 _mesa_threadpool_create(struct NineSwapChain9
*swapchain
)
90 struct threadpool
*pool
= calloc(1, sizeof(*pool
));
95 pthread_mutex_init(&pool
->m
, NULL
);
96 pthread_cond_init(&pool
->new_work
, NULL
);
98 /* This uses WINE's CreateThread, so the thread function needs to use
100 pool
->wthread
= NineSwapChain9_CreateThread(swapchain
, wthreadpool_worker
, pool
);
101 if (!pool
->wthread
) {
102 /* using pthread as fallback */
103 pthread_create(&pool
->pthread
, NULL
, threadpool_worker
, pool
);
109 _mesa_threadpool_destroy(struct NineSwapChain9
*swapchain
, struct threadpool
*pool
)
114 pthread_mutex_lock(&pool
->m
);
115 pool
->shutdown
= TRUE
;
116 pthread_cond_broadcast(&pool
->new_work
);
117 pthread_mutex_unlock(&pool
->m
);
120 NineSwapChain9_WaitForThread(swapchain
, pool
->wthread
);
122 pthread_join(pool
->pthread
, NULL
);
125 pthread_cond_destroy(&pool
->new_work
);
126 pthread_mutex_destroy(&pool
->m
);
131 * Queues a request for the work function to be asynchronously executed by the
134 * The work func will get the "data" argument as its parameter -- any
135 * communication between the caller and the work function will occur through
138 * If there is an error, the work function is called immediately and NULL is
141 struct threadpool_task
*
142 _mesa_threadpool_queue_task(struct threadpool
*pool
,
143 threadpool_task_func work
, void *data
)
145 struct threadpool_task
*task
, *previous
;
152 task
= calloc(1, sizeof(*task
));
161 pthread_cond_init(&task
->finish
, NULL
);
163 pthread_mutex_lock(&pool
->m
);
165 if (!pool
->workqueue
) {
166 pool
->workqueue
= task
;
168 previous
= pool
->workqueue
;
169 while (previous
&& previous
->next
)
170 previous
= previous
->next
;
172 previous
->next
= task
;
174 pthread_cond_signal(&pool
->new_work
);
175 pthread_mutex_unlock(&pool
->m
);
181 * Blocks on the completion of the given task and frees the task.
184 _mesa_threadpool_wait_for_task(struct threadpool
*pool
,
185 struct threadpool_task
**task_handle
)
187 struct threadpool_task
*task
= *task_handle
;
192 pthread_mutex_lock(&pool
->m
);
193 while (!task
->finished
)
194 pthread_cond_wait(&task
->finish
, &pool
->m
);
195 pthread_mutex_unlock(&pool
->m
);
197 pthread_cond_destroy(&task
->finish
);