Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/winsys/svga/drm/pb_buffer_simple_fenced.c
4573 views
1
/**************************************************************************
2
*
3
* Copyright 2007-2015 VMware, Inc.
4
* All Rights Reserved.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the
8
* "Software"), to deal in the Software without restriction, including
9
* without limitation the rights to use, copy, modify, merge, publish,
10
* distribute, sub license, and/or sell copies of the Software, and to
11
* permit persons to whom the Software is furnished to do so, subject to
12
* the following conditions:
13
*
14
* The above copyright notice and this permission notice (including the
15
* next paragraph) shall be included in all copies or substantial portions
16
* of the Software.
17
*
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
*
26
**************************************************************************/
27
28
/**
29
* \file
30
* Implementation of fenced buffers.
31
*
32
* \author Jose Fonseca <jfonseca-at-vmware-dot-com>
33
* \author Thomas Hellström <thellstrom-at-vmware-dot-com>
34
*/
35
36
37
#include "pipe/p_config.h"
38
39
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
40
#include <unistd.h>
41
#include <sched.h>
42
#endif
43
#include <inttypes.h>
44
45
#include "pipe/p_compiler.h"
46
#include "pipe/p_defines.h"
47
#include "util/u_debug.h"
48
#include "os/os_thread.h"
49
#include "util/u_memory.h"
50
#include "util/list.h"
51
52
#include "pipebuffer/pb_buffer.h"
53
#include "pipebuffer/pb_bufmgr.h"
54
#include "pipebuffer/pb_buffer_fenced.h"
55
#include "vmw_screen.h"
56
57
58
/**
59
* Convenience macro (type safe).
60
*/
61
#define SUPER(__derived) (&(__derived)->base)
62
63
64
struct fenced_manager
65
{
66
struct pb_manager base;
67
struct pb_manager *provider;
68
struct pb_fence_ops *ops;
69
70
/**
71
* Following members are mutable and protected by this mutex.
72
*/
73
mtx_t mutex;
74
75
/**
76
* Fenced buffer list.
77
*
78
* All fenced buffers are placed in this listed, ordered from the oldest
79
* fence to the newest fence.
80
*/
81
struct list_head fenced;
82
pb_size num_fenced;
83
84
struct list_head unfenced;
85
pb_size num_unfenced;
86
87
};
88
89
90
/**
91
* Fenced buffer.
92
*
93
* Wrapper around a pipe buffer which adds fencing and reference counting.
94
*/
95
struct fenced_buffer
96
{
97
/*
98
* Immutable members.
99
*/
100
101
struct pb_buffer base;
102
struct fenced_manager *mgr;
103
104
/*
105
* Following members are mutable and protected by fenced_manager::mutex.
106
*/
107
108
struct list_head head;
109
110
/**
111
* Buffer with storage.
112
*/
113
struct pb_buffer *buffer;
114
pb_size size;
115
116
/**
117
* A bitmask of PB_USAGE_CPU/GPU_READ/WRITE describing the current
118
* buffer usage.
119
*/
120
unsigned flags;
121
122
unsigned mapcount;
123
124
struct pb_validate *vl;
125
unsigned validation_flags;
126
127
struct pipe_fence_handle *fence;
128
};
129
130
131
static inline struct fenced_manager *
132
fenced_manager(struct pb_manager *mgr)
133
{
134
assert(mgr);
135
return (struct fenced_manager *)mgr;
136
}
137
138
139
static inline struct fenced_buffer *
140
fenced_buffer(struct pb_buffer *buf)
141
{
142
assert(buf);
143
return (struct fenced_buffer *)buf;
144
}
145
146
147
static void
148
fenced_buffer_destroy_gpu_storage_locked(struct fenced_buffer *fenced_buf);
149
150
static enum pipe_error
151
fenced_buffer_create_gpu_storage_locked(struct fenced_manager *fenced_mgr,
152
struct fenced_buffer *fenced_buf,
153
const struct pb_desc *desc,
154
boolean wait);
155
/**
156
* Dump the fenced buffer list.
157
*
158
* Useful to understand failures to allocate buffers.
159
*/
160
static void
161
fenced_manager_dump_locked(struct fenced_manager *fenced_mgr)
162
{
163
#ifdef DEBUG
164
struct pb_fence_ops *ops = fenced_mgr->ops;
165
struct list_head *curr, *next;
166
struct fenced_buffer *fenced_buf;
167
168
debug_printf("%10s %7s %8s %7s %10s %s\n",
169
"buffer", "size", "refcount", "storage", "fence", "signalled");
170
171
curr = fenced_mgr->unfenced.next;
172
next = curr->next;
173
while(curr != &fenced_mgr->unfenced) {
174
fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
175
assert(!fenced_buf->fence);
176
debug_printf("%10p %"PRIu64" %8u %7s\n",
177
(void *) fenced_buf,
178
fenced_buf->base.size,
179
p_atomic_read(&fenced_buf->base.reference.count),
180
fenced_buf->buffer ? "gpu" : "none");
181
curr = next;
182
next = curr->next;
183
}
184
185
curr = fenced_mgr->fenced.next;
186
next = curr->next;
187
while(curr != &fenced_mgr->fenced) {
188
int signaled;
189
fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
190
assert(fenced_buf->buffer);
191
signaled = ops->fence_signalled(ops, fenced_buf->fence, 0);
192
debug_printf("%10p %"PRIu64" %8u %7s %10p %s\n",
193
(void *) fenced_buf,
194
fenced_buf->base.size,
195
p_atomic_read(&fenced_buf->base.reference.count),
196
"gpu",
197
(void *) fenced_buf->fence,
198
signaled == 0 ? "y" : "n");
199
curr = next;
200
next = curr->next;
201
}
202
#else
203
(void)fenced_mgr;
204
#endif
205
}
206
207
208
static inline void
209
fenced_buffer_destroy_locked(struct fenced_manager *fenced_mgr,
210
struct fenced_buffer *fenced_buf)
211
{
212
assert(!pipe_is_referenced(&fenced_buf->base.reference));
213
214
assert(!fenced_buf->fence);
215
assert(fenced_buf->head.prev);
216
assert(fenced_buf->head.next);
217
list_del(&fenced_buf->head);
218
assert(fenced_mgr->num_unfenced);
219
--fenced_mgr->num_unfenced;
220
221
fenced_buffer_destroy_gpu_storage_locked(fenced_buf);
222
223
FREE(fenced_buf);
224
}
225
226
227
/**
228
* Add the buffer to the fenced list.
229
*
230
* Reference count should be incremented before calling this function.
231
*/
232
static inline void
233
fenced_buffer_add_locked(struct fenced_manager *fenced_mgr,
234
struct fenced_buffer *fenced_buf)
235
{
236
assert(pipe_is_referenced(&fenced_buf->base.reference));
237
assert(fenced_buf->flags & PB_USAGE_GPU_READ_WRITE);
238
assert(fenced_buf->fence);
239
240
p_atomic_inc(&fenced_buf->base.reference.count);
241
242
list_del(&fenced_buf->head);
243
assert(fenced_mgr->num_unfenced);
244
--fenced_mgr->num_unfenced;
245
list_addtail(&fenced_buf->head, &fenced_mgr->fenced);
246
++fenced_mgr->num_fenced;
247
}
248
249
250
/**
251
* Remove the buffer from the fenced list, and potentially destroy the buffer
252
* if the reference count reaches zero.
253
*
254
* Returns TRUE if the buffer was detroyed.
255
*/
256
static inline boolean
257
fenced_buffer_remove_locked(struct fenced_manager *fenced_mgr,
258
struct fenced_buffer *fenced_buf)
259
{
260
struct pb_fence_ops *ops = fenced_mgr->ops;
261
262
assert(fenced_buf->fence);
263
assert(fenced_buf->mgr == fenced_mgr);
264
265
ops->fence_reference(ops, &fenced_buf->fence, NULL);
266
fenced_buf->flags &= ~PB_USAGE_GPU_READ_WRITE;
267
268
assert(fenced_buf->head.prev);
269
assert(fenced_buf->head.next);
270
271
list_del(&fenced_buf->head);
272
assert(fenced_mgr->num_fenced);
273
--fenced_mgr->num_fenced;
274
275
list_addtail(&fenced_buf->head, &fenced_mgr->unfenced);
276
++fenced_mgr->num_unfenced;
277
278
if (p_atomic_dec_zero(&fenced_buf->base.reference.count)) {
279
fenced_buffer_destroy_locked(fenced_mgr, fenced_buf);
280
return TRUE;
281
}
282
283
return FALSE;
284
}
285
286
287
/**
288
* Wait for the fence to expire, and remove it from the fenced list.
289
*
290
* This function will release and re-acquire the mutex, so any copy of mutable
291
* state must be discarded after calling it.
292
*/
293
static inline enum pipe_error
294
fenced_buffer_finish_locked(struct fenced_manager *fenced_mgr,
295
struct fenced_buffer *fenced_buf)
296
{
297
struct pb_fence_ops *ops = fenced_mgr->ops;
298
enum pipe_error ret = PIPE_ERROR;
299
300
#if 0
301
debug_warning("waiting for GPU");
302
#endif
303
304
assert(pipe_is_referenced(&fenced_buf->base.reference));
305
assert(fenced_buf->fence);
306
307
if(fenced_buf->fence) {
308
struct pipe_fence_handle *fence = NULL;
309
int finished;
310
boolean proceed;
311
312
ops->fence_reference(ops, &fence, fenced_buf->fence);
313
314
mtx_unlock(&fenced_mgr->mutex);
315
316
finished = ops->fence_finish(ops, fenced_buf->fence, 0);
317
318
mtx_lock(&fenced_mgr->mutex);
319
320
assert(pipe_is_referenced(&fenced_buf->base.reference));
321
322
/*
323
* Only proceed if the fence object didn't change in the meanwhile.
324
* Otherwise assume the work has been already carried out by another
325
* thread that re-acquired the lock before us.
326
*/
327
proceed = fence == fenced_buf->fence ? TRUE : FALSE;
328
329
ops->fence_reference(ops, &fence, NULL);
330
331
if(proceed && finished == 0) {
332
/*
333
* Remove from the fenced list
334
*/
335
336
boolean destroyed;
337
338
destroyed = fenced_buffer_remove_locked(fenced_mgr, fenced_buf);
339
340
/* TODO: remove consequents buffers with the same fence? */
341
342
assert(!destroyed);
343
(void) destroyed;
344
345
fenced_buf->flags &= ~PB_USAGE_GPU_READ_WRITE;
346
347
ret = PIPE_OK;
348
}
349
}
350
351
return ret;
352
}
353
354
355
/**
356
* Remove as many fenced buffers from the fenced list as possible.
357
*
358
* Returns TRUE if at least one buffer was removed.
359
*/
360
static boolean
361
fenced_manager_check_signalled_locked(struct fenced_manager *fenced_mgr,
362
boolean wait)
363
{
364
struct pb_fence_ops *ops = fenced_mgr->ops;
365
struct list_head *curr, *next;
366
struct fenced_buffer *fenced_buf;
367
struct pipe_fence_handle *prev_fence = NULL;
368
boolean ret = FALSE;
369
370
curr = fenced_mgr->fenced.next;
371
next = curr->next;
372
while(curr != &fenced_mgr->fenced) {
373
fenced_buf = LIST_ENTRY(struct fenced_buffer, curr, head);
374
375
if(fenced_buf->fence != prev_fence) {
376
int signaled;
377
378
if (wait) {
379
signaled = ops->fence_finish(ops, fenced_buf->fence, 0);
380
381
/*
382
* Don't return just now. Instead preemptively check if the
383
* following buffers' fences already expired,
384
* without further waits.
385
*/
386
wait = FALSE;
387
}
388
else {
389
signaled = ops->fence_signalled(ops, fenced_buf->fence, 0);
390
}
391
392
if (signaled != 0) {
393
return ret;
394
}
395
396
prev_fence = fenced_buf->fence;
397
}
398
else {
399
/* This buffer's fence object is identical to the previous buffer's
400
* fence object, so no need to check the fence again.
401
*/
402
assert(ops->fence_signalled(ops, fenced_buf->fence, 0) == 0);
403
}
404
405
fenced_buffer_remove_locked(fenced_mgr, fenced_buf);
406
407
ret = TRUE;
408
409
curr = next;
410
next = curr->next;
411
}
412
413
return ret;
414
}
415
416
417
/**
418
* Destroy the GPU storage.
419
*/
420
static void
421
fenced_buffer_destroy_gpu_storage_locked(struct fenced_buffer *fenced_buf)
422
{
423
if(fenced_buf->buffer) {
424
pb_reference(&fenced_buf->buffer, NULL);
425
}
426
}
427
428
429
/**
430
* Try to create GPU storage for this buffer.
431
*
432
* This function is a shorthand around pb_manager::create_buffer for
433
* fenced_buffer_create_gpu_storage_locked()'s benefit.
434
*/
435
static inline boolean
436
fenced_buffer_try_create_gpu_storage_locked(struct fenced_manager *fenced_mgr,
437
struct fenced_buffer *fenced_buf,
438
const struct pb_desc *desc)
439
{
440
struct pb_manager *provider = fenced_mgr->provider;
441
442
assert(!fenced_buf->buffer);
443
444
fenced_buf->buffer = provider->create_buffer(fenced_mgr->provider,
445
fenced_buf->size, desc);
446
return fenced_buf->buffer ? TRUE : FALSE;
447
}
448
449
450
/**
451
* Create GPU storage for this buffer.
452
*/
453
static enum pipe_error
454
fenced_buffer_create_gpu_storage_locked(struct fenced_manager *fenced_mgr,
455
struct fenced_buffer *fenced_buf,
456
const struct pb_desc *desc,
457
boolean wait)
458
{
459
assert(!fenced_buf->buffer);
460
461
/*
462
* Check for signaled buffers before trying to allocate.
463
*/
464
fenced_manager_check_signalled_locked(fenced_mgr, FALSE);
465
466
fenced_buffer_try_create_gpu_storage_locked(fenced_mgr, fenced_buf, desc);
467
468
/*
469
* Keep trying while there is some sort of progress:
470
* - fences are expiring,
471
* - or buffers are being being swapped out from GPU memory into CPU memory.
472
*/
473
while(!fenced_buf->buffer &&
474
(fenced_manager_check_signalled_locked(fenced_mgr, FALSE))) {
475
fenced_buffer_try_create_gpu_storage_locked(fenced_mgr, fenced_buf,
476
desc);
477
}
478
479
if(!fenced_buf->buffer && wait) {
480
/*
481
* Same as before, but this time around, wait to free buffers if
482
* necessary.
483
*/
484
while(!fenced_buf->buffer &&
485
(fenced_manager_check_signalled_locked(fenced_mgr, TRUE))) {
486
fenced_buffer_try_create_gpu_storage_locked(fenced_mgr, fenced_buf,
487
desc);
488
}
489
}
490
491
if(!fenced_buf->buffer) {
492
if(0)
493
fenced_manager_dump_locked(fenced_mgr);
494
495
/* give up */
496
return PIPE_ERROR_OUT_OF_MEMORY;
497
}
498
499
return PIPE_OK;
500
}
501
502
503
static void
504
fenced_buffer_destroy(void *winsys, struct pb_buffer *buf)
505
{
506
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
507
struct fenced_manager *fenced_mgr = fenced_buf->mgr;
508
509
assert(!pipe_is_referenced(&fenced_buf->base.reference));
510
511
mtx_lock(&fenced_mgr->mutex);
512
513
fenced_buffer_destroy_locked(fenced_mgr, fenced_buf);
514
515
mtx_unlock(&fenced_mgr->mutex);
516
}
517
518
519
static void *
520
fenced_buffer_map(struct pb_buffer *buf,
521
unsigned flags, void *flush_ctx)
522
{
523
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
524
struct fenced_manager *fenced_mgr = fenced_buf->mgr;
525
struct pb_fence_ops *ops = fenced_mgr->ops;
526
void *map = NULL;
527
528
mtx_lock(&fenced_mgr->mutex);
529
530
assert(!(flags & PB_USAGE_GPU_READ_WRITE));
531
532
/*
533
* Serialize writes.
534
*/
535
while((fenced_buf->flags & PB_USAGE_GPU_WRITE) ||
536
((fenced_buf->flags & PB_USAGE_GPU_READ) &&
537
(flags & PB_USAGE_CPU_WRITE))) {
538
539
/*
540
* Don't wait for the GPU to finish accessing it,
541
* if blocking is forbidden.
542
*/
543
if((flags & PB_USAGE_DONTBLOCK) &&
544
ops->fence_signalled(ops, fenced_buf->fence, 0) != 0) {
545
goto done;
546
}
547
548
if (flags & PB_USAGE_UNSYNCHRONIZED) {
549
break;
550
}
551
552
/*
553
* Wait for the GPU to finish accessing. This will release and re-acquire
554
* the mutex, so all copies of mutable state must be discarded.
555
*/
556
fenced_buffer_finish_locked(fenced_mgr, fenced_buf);
557
}
558
559
map = pb_map(fenced_buf->buffer, flags, flush_ctx);
560
561
if(map) {
562
++fenced_buf->mapcount;
563
fenced_buf->flags |= flags & PB_USAGE_CPU_READ_WRITE;
564
}
565
566
done:
567
mtx_unlock(&fenced_mgr->mutex);
568
569
return map;
570
}
571
572
573
static void
574
fenced_buffer_unmap(struct pb_buffer *buf)
575
{
576
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
577
struct fenced_manager *fenced_mgr = fenced_buf->mgr;
578
579
mtx_lock(&fenced_mgr->mutex);
580
581
assert(fenced_buf->mapcount);
582
if(fenced_buf->mapcount) {
583
if (fenced_buf->buffer)
584
pb_unmap(fenced_buf->buffer);
585
--fenced_buf->mapcount;
586
if(!fenced_buf->mapcount)
587
fenced_buf->flags &= ~PB_USAGE_CPU_READ_WRITE;
588
}
589
590
mtx_unlock(&fenced_mgr->mutex);
591
}
592
593
594
static enum pipe_error
595
fenced_buffer_validate(struct pb_buffer *buf,
596
struct pb_validate *vl,
597
unsigned flags)
598
{
599
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
600
struct fenced_manager *fenced_mgr = fenced_buf->mgr;
601
enum pipe_error ret;
602
603
mtx_lock(&fenced_mgr->mutex);
604
605
if(!vl) {
606
/* invalidate */
607
fenced_buf->vl = NULL;
608
fenced_buf->validation_flags = 0;
609
ret = PIPE_OK;
610
goto done;
611
}
612
613
assert(flags & PB_USAGE_GPU_READ_WRITE);
614
assert(!(flags & ~PB_USAGE_GPU_READ_WRITE));
615
flags &= PB_USAGE_GPU_READ_WRITE;
616
617
/* Buffer cannot be validated in two different lists */
618
if(fenced_buf->vl && fenced_buf->vl != vl) {
619
ret = PIPE_ERROR_RETRY;
620
goto done;
621
}
622
623
if(fenced_buf->vl == vl &&
624
(fenced_buf->validation_flags & flags) == flags) {
625
/* Nothing to do -- buffer already validated */
626
ret = PIPE_OK;
627
goto done;
628
}
629
630
ret = pb_validate(fenced_buf->buffer, vl, flags);
631
if (ret != PIPE_OK)
632
goto done;
633
634
fenced_buf->vl = vl;
635
fenced_buf->validation_flags |= flags;
636
637
done:
638
mtx_unlock(&fenced_mgr->mutex);
639
640
return ret;
641
}
642
643
644
static void
645
fenced_buffer_fence(struct pb_buffer *buf,
646
struct pipe_fence_handle *fence)
647
{
648
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
649
struct fenced_manager *fenced_mgr = fenced_buf->mgr;
650
struct pb_fence_ops *ops = fenced_mgr->ops;
651
652
mtx_lock(&fenced_mgr->mutex);
653
654
assert(pipe_is_referenced(&fenced_buf->base.reference));
655
assert(fenced_buf->buffer);
656
657
if(fence != fenced_buf->fence) {
658
assert(fenced_buf->vl);
659
assert(fenced_buf->validation_flags);
660
661
if (fenced_buf->fence) {
662
boolean destroyed;
663
destroyed = fenced_buffer_remove_locked(fenced_mgr, fenced_buf);
664
assert(!destroyed);
665
(void) destroyed;
666
}
667
if (fence) {
668
ops->fence_reference(ops, &fenced_buf->fence, fence);
669
fenced_buf->flags |= fenced_buf->validation_flags;
670
fenced_buffer_add_locked(fenced_mgr, fenced_buf);
671
}
672
673
pb_fence(fenced_buf->buffer, fence);
674
675
fenced_buf->vl = NULL;
676
fenced_buf->validation_flags = 0;
677
}
678
679
mtx_unlock(&fenced_mgr->mutex);
680
}
681
682
683
static void
684
fenced_buffer_get_base_buffer(struct pb_buffer *buf,
685
struct pb_buffer **base_buf,
686
pb_size *offset)
687
{
688
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
689
struct fenced_manager *fenced_mgr = fenced_buf->mgr;
690
691
mtx_lock(&fenced_mgr->mutex);
692
693
assert(fenced_buf->buffer);
694
695
if(fenced_buf->buffer)
696
pb_get_base_buffer(fenced_buf->buffer, base_buf, offset);
697
else {
698
*base_buf = buf;
699
*offset = 0;
700
}
701
702
mtx_unlock(&fenced_mgr->mutex);
703
}
704
705
706
static const struct pb_vtbl
707
fenced_buffer_vtbl = {
708
fenced_buffer_destroy,
709
fenced_buffer_map,
710
fenced_buffer_unmap,
711
fenced_buffer_validate,
712
fenced_buffer_fence,
713
fenced_buffer_get_base_buffer
714
};
715
716
717
/**
718
* Wrap a buffer in a fenced buffer.
719
*/
720
static struct pb_buffer *
721
fenced_bufmgr_create_buffer(struct pb_manager *mgr,
722
pb_size size,
723
const struct pb_desc *desc)
724
{
725
struct fenced_manager *fenced_mgr = fenced_manager(mgr);
726
struct fenced_buffer *fenced_buf;
727
enum pipe_error ret;
728
729
fenced_buf = CALLOC_STRUCT(fenced_buffer);
730
if(!fenced_buf)
731
goto no_buffer;
732
733
pipe_reference_init(&fenced_buf->base.reference, 1);
734
fenced_buf->base.alignment_log2 = util_logbase2(desc->alignment);
735
fenced_buf->base.usage = desc->usage;
736
fenced_buf->base.size = size;
737
fenced_buf->size = size;
738
739
fenced_buf->base.vtbl = &fenced_buffer_vtbl;
740
fenced_buf->mgr = fenced_mgr;
741
742
mtx_lock(&fenced_mgr->mutex);
743
744
/*
745
* Try to create GPU storage without stalling,
746
*/
747
ret = fenced_buffer_create_gpu_storage_locked(fenced_mgr, fenced_buf,
748
desc, TRUE);
749
750
/*
751
* Give up.
752
*/
753
if(ret != PIPE_OK) {
754
goto no_storage;
755
}
756
757
assert(fenced_buf->buffer);
758
759
list_addtail(&fenced_buf->head, &fenced_mgr->unfenced);
760
++fenced_mgr->num_unfenced;
761
mtx_unlock(&fenced_mgr->mutex);
762
763
return &fenced_buf->base;
764
765
no_storage:
766
mtx_unlock(&fenced_mgr->mutex);
767
FREE(fenced_buf);
768
no_buffer:
769
return NULL;
770
}
771
772
773
static void
774
fenced_bufmgr_flush(struct pb_manager *mgr)
775
{
776
struct fenced_manager *fenced_mgr = fenced_manager(mgr);
777
778
mtx_lock(&fenced_mgr->mutex);
779
while(fenced_manager_check_signalled_locked(fenced_mgr, TRUE))
780
;
781
mtx_unlock(&fenced_mgr->mutex);
782
783
assert(fenced_mgr->provider->flush);
784
if(fenced_mgr->provider->flush)
785
fenced_mgr->provider->flush(fenced_mgr->provider);
786
}
787
788
789
static void
790
fenced_bufmgr_destroy(struct pb_manager *mgr)
791
{
792
struct fenced_manager *fenced_mgr = fenced_manager(mgr);
793
794
mtx_lock(&fenced_mgr->mutex);
795
796
/* Wait on outstanding fences */
797
while (fenced_mgr->num_fenced) {
798
mtx_unlock(&fenced_mgr->mutex);
799
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
800
sched_yield();
801
#endif
802
mtx_lock(&fenced_mgr->mutex);
803
while(fenced_manager_check_signalled_locked(fenced_mgr, TRUE))
804
;
805
}
806
807
#ifdef DEBUG
808
/*assert(!fenced_mgr->num_unfenced);*/
809
#endif
810
811
mtx_unlock(&fenced_mgr->mutex);
812
mtx_destroy(&fenced_mgr->mutex);
813
814
FREE(fenced_mgr);
815
}
816
817
818
struct pb_manager *
819
simple_fenced_bufmgr_create(struct pb_manager *provider,
820
struct pb_fence_ops *ops)
821
{
822
struct fenced_manager *fenced_mgr;
823
824
if(!provider)
825
return NULL;
826
827
fenced_mgr = CALLOC_STRUCT(fenced_manager);
828
if (!fenced_mgr)
829
return NULL;
830
831
fenced_mgr->base.destroy = fenced_bufmgr_destroy;
832
fenced_mgr->base.create_buffer = fenced_bufmgr_create_buffer;
833
fenced_mgr->base.flush = fenced_bufmgr_flush;
834
835
fenced_mgr->provider = provider;
836
fenced_mgr->ops = ops;
837
838
list_inithead(&fenced_mgr->fenced);
839
fenced_mgr->num_fenced = 0;
840
841
list_inithead(&fenced_mgr->unfenced);
842
fenced_mgr->num_unfenced = 0;
843
844
(void) mtx_init(&fenced_mgr->mutex, mtx_plain);
845
846
return &fenced_mgr->base;
847
}
848
849