2 #include "os/os_thread.h"
3 #include "pipe/p_defines.h"
4 #include "util/u_ringbuffer.h"
5 #include "util/u_math.h"
6 #include "util/u_memory.h"
10 struct util_ringbuffer
12 struct util_packet
*buf
;
15 /* Can this be done with atomic variables??
24 struct util_ringbuffer
*util_ringbuffer_create( unsigned dwords
)
26 struct util_ringbuffer
*ring
= CALLOC_STRUCT(util_ringbuffer
);
30 assert(util_is_power_of_two(dwords
));
32 ring
->buf
= MALLOC( dwords
* sizeof(unsigned) );
33 if (ring
->buf
== NULL
)
36 ring
->mask
= dwords
- 1;
38 pipe_condvar_init(ring
->change
);
39 pipe_mutex_init(ring
->mutex
);
48 void util_ringbuffer_destroy( struct util_ringbuffer
*ring
)
50 pipe_condvar_destroy(ring
->change
);
51 pipe_mutex_destroy(ring
->mutex
);
57 * Return number of free entries in the ring
59 static INLINE
unsigned util_ringbuffer_space( const struct util_ringbuffer
*ring
)
61 return (ring
->tail
- (ring
->head
+ 1)) & ring
->mask
;
65 * Is the ring buffer empty?
67 static INLINE boolean
util_ringbuffer_empty( const struct util_ringbuffer
*ring
)
69 return util_ringbuffer_space(ring
) == ring
->mask
;
72 void util_ringbuffer_enqueue( struct util_ringbuffer
*ring
,
73 const struct util_packet
*packet
)
77 /* XXX: over-reliance on mutexes, etc:
79 pipe_mutex_lock(ring
->mutex
);
81 /* make sure we don't request an impossible amount of space
83 assert(packet
->dwords
<= ring
->mask
);
85 /* Wait for free space:
87 while (util_ringbuffer_space(ring
) < packet
->dwords
)
88 pipe_condvar_wait(ring
->change
, ring
->mutex
);
92 for (i
= 0; i
< packet
->dwords
; i
++) {
94 /* Copy all dwords of the packet. Note we're abusing the
95 * typesystem a little - we're being passed a pointer to
96 * something, but probably not an array of packet structs:
98 ring
->buf
[ring
->head
] = packet
[i
];
100 ring
->head
&= ring
->mask
;
105 pipe_condvar_signal(ring
->change
);
106 pipe_mutex_unlock(ring
->mutex
);
109 enum pipe_error
util_ringbuffer_dequeue( struct util_ringbuffer
*ring
,
110 struct util_packet
*packet
,
114 const struct util_packet
*ring_packet
;
118 /* XXX: over-reliance on mutexes, etc:
120 pipe_mutex_lock(ring
->mutex
);
122 /* Get next ring entry:
125 while (util_ringbuffer_empty(ring
))
126 pipe_condvar_wait(ring
->change
, ring
->mutex
);
129 if (util_ringbuffer_empty(ring
)) {
130 ret
= PIPE_ERROR_OUT_OF_MEMORY
;
135 ring_packet
= &ring
->buf
[ring
->tail
];
137 /* Both of these are considered bugs. Raise an assert on debug builds.
139 if (ring_packet
->dwords
> ring
->mask
+ 1 - util_ringbuffer_space(ring
) ||
140 ring_packet
->dwords
> max_dwords
) {
142 ret
= PIPE_ERROR_BAD_INPUT
;
146 /* Copy data from ring:
148 for (i
= 0; i
< ring_packet
->dwords
; i
++) {
149 packet
[i
] = ring
->buf
[ring
->tail
];
151 ring
->tail
&= ring
->mask
;
157 pipe_condvar_signal(ring
->change
);
158 pipe_mutex_unlock(ring
->mutex
);