2 * Copyright © 2016 Advanced Micro Devices, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
29 static PIPE_THREAD_ROUTINE(util_queue_thread_func
, param
)
31 struct util_queue
*queue
= (struct util_queue
*)param
;
35 struct util_queue_job job
;
37 pipe_semaphore_wait(&queue
->queued
);
38 if (queue
->kill_thread
)
41 pipe_mutex_lock(queue
->lock
);
43 for (i
= 1; i
< queue
->num_jobs
; i
++)
44 queue
->jobs
[i
- 1] = queue
->jobs
[i
];
45 queue
->jobs
[--queue
->num_jobs
].job
= NULL
;
46 pipe_mutex_unlock(queue
->lock
);
48 pipe_semaphore_signal(&queue
->has_space
);
51 queue
->execute_job(job
.job
);
52 pipe_semaphore_signal(&job
.fence
->done
);
56 /* signal remaining jobs before terminating */
57 pipe_mutex_lock(queue
->lock
);
58 for (i
= 0; i
< queue
->num_jobs
; i
++) {
59 pipe_semaphore_signal(&queue
->jobs
[i
].fence
->done
);
60 queue
->jobs
[i
].job
= NULL
;
63 pipe_mutex_unlock(queue
->lock
);
68 util_queue_init(struct util_queue
*queue
,
69 void (*execute_job
)(void *))
71 memset(queue
, 0, sizeof(*queue
));
72 queue
->execute_job
= execute_job
;
73 pipe_mutex_init(queue
->lock
);
74 pipe_semaphore_init(&queue
->has_space
, ARRAY_SIZE(queue
->jobs
));
75 pipe_semaphore_init(&queue
->queued
, 0);
76 queue
->thread
= pipe_thread_create(util_queue_thread_func
, queue
);
80 util_queue_destroy(struct util_queue
*queue
)
82 queue
->kill_thread
= 1;
83 pipe_semaphore_signal(&queue
->queued
);
84 pipe_thread_wait(queue
->thread
);
85 pipe_semaphore_destroy(&queue
->has_space
);
86 pipe_semaphore_destroy(&queue
->queued
);
87 pipe_mutex_destroy(queue
->lock
);
91 util_queue_fence_init(struct util_queue_fence
*fence
)
93 pipe_semaphore_init(&fence
->done
, 1);
97 util_queue_fence_destroy(struct util_queue_fence
*fence
)
99 pipe_semaphore_destroy(&fence
->done
);
103 util_queue_add_job(struct util_queue
*queue
,
105 struct util_queue_fence
*fence
)
107 /* Set the semaphore to "busy". */
108 pipe_semaphore_wait(&fence
->done
);
110 /* if the queue is full, wait until there is space */
111 pipe_semaphore_wait(&queue
->has_space
);
113 pipe_mutex_lock(queue
->lock
);
114 assert(queue
->num_jobs
< ARRAY_SIZE(queue
->jobs
));
115 queue
->jobs
[queue
->num_jobs
].job
= job
;
116 queue
->jobs
[queue
->num_jobs
].fence
= fence
;
118 pipe_mutex_unlock(queue
->lock
);
119 pipe_semaphore_signal(&queue
->queued
);
123 util_queue_job_wait(struct util_queue_fence
*fence
)
125 /* wait and set the semaphore to "busy" */
126 pipe_semaphore_wait(&fence
->done
);
127 /* set the semaphore to "idle" */
128 pipe_semaphore_signal(&fence
->done
);