3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
11 #include "openclwrapper.h"
17 #define FIFO_TIMEOUT 200
18 //#define HB_FIFO_DEBUG 1
19 //#define HB_BUFFER_DEBUG 1
25 hb_cond_t
* cond_full
;
27 hb_cond_t
* cond_empty
;
29 hb_cond_t
* cond_alert_full
;
37 #if defined(HB_FIFO_DEBUG)
38 // Fifo list for debugging
43 #if defined(HB_FIFO_DEBUG)
44 static hb_fifo_t fifo_list
=
50 /* we round the requested buffer size up to the next power of 2 so there can
51 * be at most 32 possible pools when the size is a 32 bit int. To avoid a lot
52 * of slow & error-prone run-time checking we allow for all 32. */
53 #define MAX_BUFFER_POOLS 32
54 #define BUFFER_POOL_FIRST 10
55 #define BUFFER_POOL_LAST 25
56 /* the buffer pool only exists to avoid the two malloc and two free calls that
57 * it would otherwise take to allocate & free a buffer. but we don't want to
58 * tie up a lot of memory in the pool because this allocator isn't as general
59 * as malloc so memory tied up here puts more pressure on the malloc pool.
60 * A pool of 16 elements will avoid 94% of the malloc/free calls without wasting
62 #define BUFFER_POOL_MAX_ELEMENTS 32
64 struct hb_buffer_pools_s
68 hb_fifo_t
*pool
[MAX_BUFFER_POOLS
];
69 #if defined(HB_BUFFER_DEBUG)
70 hb_list_t
*alloc_list
;
75 void hb_buffer_pool_init( void )
77 buffers
.lock
= hb_lock_init();
78 buffers
.allocated
= 0;
80 #if defined(HB_BUFFER_DEBUG)
81 buffers
.alloc_list
= hb_list_init();
84 /* we allocate pools for sizes 2^10 through 2^25. requests larger than
85 * 2^25 will get passed through to malloc. */
88 // Create larger queue for 2^10 bucket since all allocations smaller than
89 // 2^10 come from here.
90 buffers
.pool
[BUFFER_POOL_FIRST
] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS
*10, 1);
91 buffers
.pool
[BUFFER_POOL_FIRST
]->buffer_size
= 1 << 10;
93 /* requests smaller than 2^10 are satisfied from the 2^10 pool. */
94 for ( i
= 1; i
< BUFFER_POOL_FIRST
; ++i
)
96 buffers
.pool
[i
] = buffers
.pool
[BUFFER_POOL_FIRST
];
98 for ( i
= BUFFER_POOL_FIRST
+ 1; i
<= BUFFER_POOL_LAST
; ++i
)
100 buffers
.pool
[i
] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS
, 1);
101 buffers
.pool
[i
]->buffer_size
= 1 << i
;
105 #if defined(HB_FIFO_DEBUG)
107 static void dump_fifo(hb_fifo_t
* f
)
109 hb_buffer_t
* b
= f
->first
;
115 fprintf(stderr
, "%p:%d:%d\n", b
, b
->size
, b
->alloc
);
118 fprintf(stderr
, "\n");
122 static void fifo_list_add( hb_fifo_t
* f
)
124 hb_fifo_t
*next
= fifo_list
.next
;
130 static void fifo_list_rem( hb_fifo_t
* f
)
132 hb_fifo_t
*next
, *prev
;
135 next
= fifo_list
.next
;
137 while ( next
&& next
!= f
)
144 prev
->next
= f
->next
;
148 // These routines are useful for finding and debugging problems
149 // with the fifos and buffer pools
150 static void buffer_pool_validate( hb_fifo_t
* f
)
158 if (b
->alloc
!= f
->buffer_size
)
160 fprintf(stderr
, "Invalid buffer pool size! buf %p size %d pool size %d\n", b
, b
->alloc
, f
->buffer_size
);
167 hb_unlock( f
->lock
);
170 static void buffer_pools_validate( void )
173 for ( ii
= BUFFER_POOL_FIRST
; ii
<= BUFFER_POOL_LAST
; ++ii
)
175 buffer_pool_validate( buffers
.pool
[ii
] );
179 void fifo_list_validate( void )
181 hb_fifo_t
*next
= fifo_list
.next
;
186 buffer_pools_validate();
190 hb_lock( next
->lock
);
193 // Count the number of entries in this fifo
197 // check that the current buffer is not duplicated in this fifo
202 fprintf(stderr
, "Duplicate buffer in fifo!\n");
209 // check that the current buffer is not duplicated in another fifo
219 fprintf(stderr
, "Duplicate buffer in another fifo!\n");
225 hb_unlock( m
->lock
);
233 if ( count
!= next
->size
)
235 fprintf(stderr
, "Invalid fifo size! count %d size %d\n", count
, next
->size
);
239 hb_unlock( next
->lock
);
246 void hb_buffer_pool_free( void )
253 hb_lock(buffers
.lock
);
255 #if defined(HB_BUFFER_DEBUG)
256 hb_deep_log(2, "leaked %d buffers", hb_list_count(buffers
.alloc_list
));
257 for (i
= 0; i
< hb_list_count(buffers
.alloc_list
); i
++)
259 hb_buffer_t
*b
= hb_list_item(buffers
.alloc_list
, i
);
260 hb_deep_log(2, "leaked buffer %p type %d size %d alloc %d",
261 b
, b
->s
.type
, b
->size
, b
->alloc
);
265 for( i
= BUFFER_POOL_FIRST
; i
<= BUFFER_POOL_LAST
; ++i
)
268 while( ( b
= hb_fifo_get(buffers
.pool
[i
]) ) )
274 if (b
->cl
.buffer
!= NULL
)
277 if (hb_cl_free_mapped_buffer(b
->cl
.buffer
, b
->data
) == 0)
279 hb_log("hb_buffer_pool_free: bad free: %p -> buffer %p map %p",
280 b
, b
->cl
.buffer
, b
->data
);
293 hb_deep_log( 2, "Freed %d buffers of size %d", count
,
294 buffers
.pool
[i
]->buffer_size
);
298 hb_deep_log( 2, "Allocated %"PRId64
" bytes of buffers on this pass and Freed %"PRId64
" bytes, "
299 "%"PRId64
" bytes leaked", buffers
.allocated
, freed
, buffers
.allocated
- freed
);
300 buffers
.allocated
= 0;
301 hb_unlock(buffers
.lock
);
304 static hb_fifo_t
*size_to_pool( int size
)
307 for ( i
= BUFFER_POOL_FIRST
; i
<= BUFFER_POOL_LAST
; ++i
)
309 if ( size
<= (1 << i
) )
311 return buffers
.pool
[i
];
317 hb_buffer_t
* hb_buffer_init_internal( int size
, int needsMapped
)
320 // Certain libraries (hrm ffmpeg) expect buffers passed to them to
321 // end on certain alignments (ffmpeg is 8). So allocate some extra bytes.
322 // Note that we can't simply align the end of our buffer because
323 // sometimes we feed data to these libraries starting from arbitrary
324 // points within the buffer.
325 int alloc
= size
+ 16;
326 hb_fifo_t
*buffer_pool
= size_to_pool( alloc
);
330 b
= hb_fifo_get( buffer_pool
);
333 if (b
!= NULL
&& needsMapped
&& b
->cl
.buffer
== NULL
)
335 // We need a mapped OpenCL buffer and that is not
336 // what we got out of the pool.
337 // Ditch it; it will get replaced with what we need.
349 * Zero the contents of the buffer, would be nice if we
350 * didn't have to do this.
352 uint8_t *data
= b
->data
;
355 cl_mem buffer
= b
->cl
.buffer
;
356 cl_event last_event
= b
->cl
.last_event
;
357 int loc
= b
->cl
.buffer_location
;
359 memset( b
, 0, sizeof(hb_buffer_t
) );
360 b
->alloc
= buffer_pool
->buffer_size
;
363 b
->s
.start
= AV_NOPTS_VALUE
;
364 b
->s
.stop
= AV_NOPTS_VALUE
;
365 b
->s
.renderOffset
= AV_NOPTS_VALUE
;
368 b
->cl
.buffer
= buffer
;
369 b
->cl
.last_event
= last_event
;
370 b
->cl
.buffer_location
= loc
;
372 #if defined(HB_BUFFER_DEBUG)
373 hb_lock(buffers
.lock
);
374 hb_list_add(buffers
.alloc_list
, b
);
375 hb_unlock(buffers
.lock
);
382 * No existing buffers, create a new one
384 if( !( b
= calloc( sizeof( hb_buffer_t
), 1 ) ) )
386 hb_log( "out of memory" );
391 b
->alloc
= buffer_pool
? buffer_pool
->buffer_size
: alloc
;
396 b
->cl
.last_event
= NULL
;
397 b
->cl
.buffer_location
= HOST
;
402 int status
= hb_cl_create_mapped_buffer(&b
->cl
.buffer
, &b
->data
, b
->alloc
);
405 hb_error("Failed to map CL buffer");
414 #if defined( SYS_DARWIN ) || defined( SYS_FREEBSD ) || defined( SYS_MINGW )
415 b
->data
= malloc( b
->alloc
);
416 #elif defined( SYS_CYGWIN )
418 b
->data
= malloc( b
->alloc
+ 17 );
420 b
->data
= memalign( 16, b
->alloc
);
426 hb_log( "out of memory" );
430 hb_lock(buffers
.lock
);
431 buffers
.allocated
+= b
->alloc
;
432 hb_unlock(buffers
.lock
);
434 b
->s
.start
= AV_NOPTS_VALUE
;
435 b
->s
.stop
= AV_NOPTS_VALUE
;
436 b
->s
.renderOffset
= AV_NOPTS_VALUE
;
437 #if defined(HB_BUFFER_DEBUG)
438 hb_lock(buffers
.lock
);
439 hb_list_add(buffers
.alloc_list
, b
);
440 hb_unlock(buffers
.lock
);
445 hb_buffer_t
* hb_buffer_init( int size
)
447 return hb_buffer_init_internal(size
, 0);
450 hb_buffer_t
* hb_buffer_eof_init(void)
452 hb_buffer_t
* buf
= hb_buffer_init(0);
453 buf
->s
.flags
= HB_BUF_FLAG_EOF
;
457 void hb_buffer_realloc( hb_buffer_t
* b
, int size
)
459 if ( size
> b
->alloc
|| b
->data
== NULL
)
461 uint32_t orig
= b
->data
!= NULL
? b
->alloc
: 0;
462 size
= size_to_pool( size
)->buffer_size
;
463 b
->data
= realloc( b
->data
, size
);
466 hb_lock(buffers
.lock
);
467 buffers
.allocated
+= size
- orig
;
468 hb_unlock(buffers
.lock
);
472 void hb_buffer_reduce( hb_buffer_t
* b
, int size
)
475 if ( size
< b
->alloc
/ 8 || b
->data
== NULL
)
477 hb_buffer_t
* tmp
= hb_buffer_init( size
);
479 hb_buffer_swap_copy( b
, tmp
);
480 memcpy( b
->data
, tmp
->data
, size
);
482 hb_buffer_close( &tmp
);
486 hb_buffer_t
* hb_buffer_dup( const hb_buffer_t
* src
)
494 buf
= hb_buffer_init( src
->size
);
497 memcpy( buf
->data
, src
->data
, src
->size
);
500 if ( buf
->s
.type
== FRAME_BUF
)
501 hb_buffer_init_planes( buf
);
505 memcpy(&buf
->qsv_details
, &src
->qsv_details
, sizeof(src
->qsv_details
));
511 int hb_buffer_copy(hb_buffer_t
* dst
, const hb_buffer_t
* src
)
513 if (src
== NULL
|| dst
== NULL
)
516 if ( dst
->size
< src
->size
)
519 memcpy( dst
->data
, src
->data
, src
->size
);
522 if (dst
->s
.type
== FRAME_BUF
)
523 hb_buffer_init_planes(dst
);
528 static void hb_buffer_init_planes_internal( hb_buffer_t
* b
, uint8_t * has_plane
)
530 uint8_t * plane
= b
->data
;
533 for( p
= 0; p
< 4; p
++ )
537 b
->plane
[p
].data
= plane
;
538 b
->plane
[p
].stride
= hb_image_stride( b
->f
.fmt
, b
->f
.width
, p
);
539 b
->plane
[p
].height_stride
= hb_image_height_stride( b
->f
.fmt
, b
->f
.height
, p
);
540 b
->plane
[p
].width
= hb_image_width( b
->f
.fmt
, b
->f
.width
, p
);
541 b
->plane
[p
].height
= hb_image_height( b
->f
.fmt
, b
->f
.height
, p
);
542 b
->plane
[p
].size
= b
->plane
[p
].stride
* b
->plane
[p
].height_stride
;
543 plane
+= b
->plane
[p
].size
;
548 void hb_buffer_init_planes( hb_buffer_t
* b
)
550 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(b
->f
.fmt
);
558 uint8_t has_plane
[4] = {0,};
560 for( p
= 0; p
< 4; p
++ )
562 has_plane
[desc
->comp
[p
].plane
] = 1;
564 hb_buffer_init_planes_internal( b
, has_plane
);
567 // this routine gets a buffer for an uncompressed picture
568 // with pixel format pix_fmt and dimensions width x height.
569 hb_buffer_t
* hb_frame_buffer_init( int pix_fmt
, int width
, int height
)
571 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
574 uint8_t has_plane
[4] = {0,};
580 for( p
= 0; p
< 4; p
++ )
582 has_plane
[desc
->comp
[p
].plane
] = 1;
586 for( p
= 0; p
< 4; p
++ )
590 size
+= hb_image_stride( pix_fmt
, width
, p
) *
591 hb_image_height_stride( pix_fmt
, height
, p
);
596 buf
= hb_buffer_init_internal(size
, hb_use_buffers());
601 buf
->s
.type
= FRAME_BUF
;
602 buf
->f
.width
= width
;
603 buf
->f
.height
= height
;
604 buf
->f
.fmt
= pix_fmt
;
606 hb_buffer_init_planes_internal( buf
, has_plane
);
610 // this routine reallocs a buffer for an uncompressed YUV420 video frame
611 // with dimensions width x height.
612 void hb_video_buffer_realloc( hb_buffer_t
* buf
, int width
, int height
)
614 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(buf
->f
.fmt
);
616 uint8_t has_plane
[4] = {0,};
622 for( p
= 0; p
< 4; p
++ )
624 has_plane
[desc
->comp
[p
].plane
] = 1;
628 for( p
= 0; p
< 4; p
++ )
632 size
+= hb_image_stride( buf
->f
.fmt
, width
, p
) *
633 hb_image_height_stride( buf
->f
.fmt
, height
, p
);
637 hb_buffer_realloc(buf
, size
);
639 buf
->f
.width
= width
;
640 buf
->f
.height
= height
;
643 hb_buffer_init_planes_internal( buf
, has_plane
);
646 // this routine 'moves' data from src to dst by interchanging 'data',
647 // 'size' & 'alloc' between them and copying the rest of the fields
649 void hb_buffer_swap_copy( hb_buffer_t
*src
, hb_buffer_t
*dst
)
651 uint8_t *data
= dst
->data
;
652 int size
= dst
->size
;
653 int alloc
= dst
->alloc
;
656 cl_mem buffer
= dst
->cl
.buffer
;
657 cl_event last_event
= dst
->cl
.last_event
;
658 int loc
= dst
->cl
.buffer_location
;
667 src
->cl
.buffer
= buffer
;
668 src
->cl
.last_event
= last_event
;
669 src
->cl
.buffer_location
= loc
;
672 // Frees the specified buffer list.
673 void hb_buffer_close( hb_buffer_t
** _b
)
675 hb_buffer_t
* b
= *_b
;
679 hb_buffer_t
* next
= b
->next
;
680 hb_fifo_t
*buffer_pool
= size_to_pool( b
->alloc
);
684 #if defined(HB_BUFFER_DEBUG)
685 hb_lock(buffers
.lock
);
686 hb_list_rem(buffers
.alloc_list
, b
);
687 hb_unlock(buffers
.lock
);
689 // Close any attached subtitle buffers
690 hb_buffer_close( &b
->sub
);
692 if( buffer_pool
&& b
->data
&& !hb_fifo_is_full( buffer_pool
) )
694 hb_fifo_push_head( buffer_pool
, b
);
698 // either the pool is full or this size doesn't use a pool
702 if (b
->cl
.buffer
!= NULL
)
705 if (hb_cl_free_mapped_buffer(b
->cl
.buffer
, b
->data
) == 0)
707 hb_log("hb_buffer_pool_free: bad free %p -> buffer %p map %p",
708 b
, b
->cl
.buffer
, b
->data
);
715 hb_lock(buffers
.lock
);
716 buffers
.allocated
-= b
->alloc
;
717 hb_unlock(buffers
.lock
);
726 void hb_buffer_move_subs( hb_buffer_t
* dst
, hb_buffer_t
* src
)
728 // Note that dst takes ownership of the subtitles
733 memcpy(&dst
->qsv_details
, &src
->qsv_details
, sizeof(src
->qsv_details
));
738 hb_image_t
* hb_image_init(int pix_fmt
, int width
, int height
)
740 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(pix_fmt
);
742 uint8_t has_plane
[4] = {0,};
748 for (p
= 0; p
< 4; p
++)
750 has_plane
[desc
->comp
[p
].plane
] = 1;
754 for (p
= 0; p
< 4; p
++)
758 size
+= hb_image_stride( pix_fmt
, width
, p
) *
759 hb_image_height_stride( pix_fmt
, height
, p
);
763 hb_image_t
*image
= calloc(1, sizeof(hb_image_t
));
768 #if defined( SYS_DARWIN ) || defined( SYS_FREEBSD ) || defined( SYS_MINGW )
769 image
->data
= malloc(size
);
770 #elif defined( SYS_CYGWIN )
772 image
->data
= malloc(size
+ 17);
774 image
->data
= memalign(16, size
);
776 if (image
->data
== NULL
)
781 image
->format
= pix_fmt
;
782 image
->width
= width
;
783 image
->height
= height
;
784 memset(image
->data
, 0, size
);
786 uint8_t * plane
= image
->data
;
787 for (p
= 0; p
< 4; p
++)
791 image
->plane
[p
].data
= plane
;
792 image
->plane
[p
].stride
= hb_image_stride(pix_fmt
, width
, p
);
793 image
->plane
[p
].height_stride
=
794 hb_image_height_stride(pix_fmt
, height
, p
);
795 image
->plane
[p
].width
= hb_image_width(pix_fmt
, width
, p
);
796 image
->plane
[p
].height
= hb_image_height(pix_fmt
, height
, p
);
797 image
->plane
[p
].size
=
798 image
->plane
[p
].stride
* image
->plane
[p
].height_stride
;
799 plane
+= image
->plane
[p
].size
;
805 hb_image_t
* hb_buffer_to_image(hb_buffer_t
*buf
)
807 hb_image_t
*image
= calloc(1, sizeof(hb_image_t
));
809 #if defined( SYS_DARWIN ) || defined( SYS_FREEBSD ) || defined( SYS_MINGW )
810 image
->data
= malloc( buf
->size
);
811 #elif defined( SYS_CYGWIN )
813 image
->data
= malloc( buf
->size
+ 17 );
815 image
->data
= memalign( 16, buf
->size
);
817 if (image
->data
== NULL
)
823 image
->format
= buf
->f
.fmt
;
824 image
->width
= buf
->f
.width
;
825 image
->height
= buf
->f
.height
;
826 memcpy(image
->data
, buf
->data
, buf
->size
);
829 uint8_t *data
= image
->data
;
830 for (p
= 0; p
< 4; p
++)
832 image
->plane
[p
].data
= data
;
833 image
->plane
[p
].width
= buf
->plane
[p
].width
;
834 image
->plane
[p
].height
= buf
->plane
[p
].height
;
835 image
->plane
[p
].stride
= buf
->plane
[p
].stride
;
836 image
->plane
[p
].height_stride
= buf
->plane
[p
].height_stride
;
837 image
->plane
[p
].size
= buf
->plane
[p
].size
;
838 data
+= image
->plane
[p
].size
;
843 void hb_image_close(hb_image_t
**_image
)
848 hb_image_t
* image
= *_image
;
857 hb_fifo_t
* hb_fifo_init( int capacity
, int thresh
)
860 f
= calloc( sizeof( hb_fifo_t
), 1 );
861 f
->lock
= hb_lock_init();
862 f
->cond_full
= hb_cond_init();
863 f
->cond_empty
= hb_cond_init();
864 f
->capacity
= capacity
;
868 #if defined(HB_FIFO_DEBUG)
869 // Add the fifo to the global fifo list
875 void hb_fifo_register_full_cond( hb_fifo_t
* f
, hb_cond_t
* c
)
877 f
->cond_alert_full
= c
;
880 int hb_fifo_size_bytes( hb_fifo_t
* f
)
892 hb_unlock( f
->lock
);
897 int hb_fifo_size( hb_fifo_t
* f
)
903 hb_unlock( f
->lock
);
908 int hb_fifo_is_full( hb_fifo_t
* f
)
913 ret
= ( f
->size
>= f
->capacity
);
914 hb_unlock( f
->lock
);
919 float hb_fifo_percent_full( hb_fifo_t
* f
)
924 ret
= f
->size
/ f
->capacity
;
925 hb_unlock( f
->lock
);
930 // Pulls the first packet out of this FIFO, blocking until such a packet is available.
931 // Returns NULL if this FIFO has been closed or flushed.
932 hb_buffer_t
* hb_fifo_get_wait( hb_fifo_t
* f
)
940 hb_cond_timedwait( f
->cond_empty
, f
->lock
, FIFO_TIMEOUT
);
943 hb_unlock( f
->lock
);
951 if( f
->wait_full
&& f
->size
== f
->capacity
- f
->thresh
)
954 hb_cond_signal( f
->cond_full
);
956 hb_unlock( f
->lock
);
961 // Pulls a packet out of this FIFO, or returns NULL if no packet is available.
962 hb_buffer_t
* hb_fifo_get( hb_fifo_t
* f
)
969 hb_unlock( f
->lock
);
976 if( f
->wait_full
&& f
->size
== f
->capacity
- f
->thresh
)
979 hb_cond_signal( f
->cond_full
);
981 hb_unlock( f
->lock
);
986 hb_buffer_t
* hb_fifo_see_wait( hb_fifo_t
* f
)
994 hb_cond_timedwait( f
->cond_empty
, f
->lock
, FIFO_TIMEOUT
);
997 hb_unlock( f
->lock
);
1002 hb_unlock( f
->lock
);
1007 // Returns the first packet in the specified FIFO.
1008 // If the FIFO is empty, returns NULL.
1009 hb_buffer_t
* hb_fifo_see( hb_fifo_t
* f
)
1016 hb_unlock( f
->lock
);
1020 hb_unlock( f
->lock
);
1025 hb_buffer_t
* hb_fifo_see2( hb_fifo_t
* f
)
1032 hb_unlock( f
->lock
);
1036 hb_unlock( f
->lock
);
1041 // Waits until the specified FIFO is no longer full or until FIFO_TIMEOUT milliseconds have elapsed.
1042 // Returns whether the FIFO is non-full upon return.
1043 int hb_fifo_full_wait( hb_fifo_t
* f
)
1048 if( f
->size
>= f
->capacity
)
1051 hb_cond_timedwait( f
->cond_full
, f
->lock
, FIFO_TIMEOUT
);
1053 result
= ( f
->size
< f
->capacity
);
1054 hb_unlock( f
->lock
);
1058 // Pushes the specified buffer onto the specified FIFO,
1059 // blocking until the FIFO has space available.
1060 void hb_fifo_push_wait( hb_fifo_t
* f
, hb_buffer_t
* b
)
1068 if( f
->size
>= f
->capacity
)
1071 if (f
->cond_alert_full
!= NULL
)
1072 hb_cond_broadcast( f
->cond_alert_full
);
1073 hb_cond_timedwait( f
->cond_full
, f
->lock
, FIFO_TIMEOUT
);
1085 while( f
->last
->next
)
1088 f
->last
= f
->last
->next
;
1090 if( f
->wait_empty
&& f
->size
>= 1 )
1093 hb_cond_signal( f
->cond_empty
);
1095 hb_unlock( f
->lock
);
1098 // Appends the specified packet list to the end of the specified FIFO.
1099 void hb_fifo_push( hb_fifo_t
* f
, hb_buffer_t
* b
)
1107 if (f
->size
>= f
->capacity
&&
1108 f
->cond_alert_full
!= NULL
)
1110 hb_cond_broadcast( f
->cond_alert_full
);
1122 while( f
->last
->next
)
1125 f
->last
= f
->last
->next
;
1127 if( f
->wait_empty
&& f
->size
>= 1 )
1130 hb_cond_signal( f
->cond_empty
);
1132 hb_unlock( f
->lock
);
1135 // Prepends the specified packet list to the start of the specified FIFO.
1136 void hb_fifo_push_head( hb_fifo_t
* f
, hb_buffer_t
* b
)
1147 if (f
->size
>= f
->capacity
&&
1148 f
->cond_alert_full
!= NULL
)
1150 hb_cond_broadcast( f
->cond_alert_full
);
1154 * If there are a chain of buffers prepend the lot
1165 tmp
->next
= f
->first
;
1173 f
->size
+= ( size
+ 1 );
1175 hb_unlock( f
->lock
);
1178 // Pushes a list of packets onto the specified FIFO as a single element.
1179 void hb_fifo_push_list_element( hb_fifo_t
*fifo
, hb_buffer_t
*buffer_list
)
1181 hb_buffer_t
*container
= hb_buffer_init( 0 );
1182 // XXX: Using an arbitrary hb_buffer_t pointer (other than 'next')
1183 // to carry the list inside a single "container" buffer
1184 container
->sub
= buffer_list
;
1186 hb_fifo_push( fifo
, container
);
1189 // Removes a list of packets from the specified FIFO that were stored as a single element.
1190 hb_buffer_t
*hb_fifo_get_list_element( hb_fifo_t
*fifo
)
1192 hb_buffer_t
*container
= hb_fifo_get( fifo
);
1193 // XXX: Using an arbitrary hb_buffer_t pointer (other than 'next')
1194 // to carry the list inside a single "container" buffer
1195 hb_buffer_t
*buffer_list
= container
->sub
;
1196 hb_buffer_close( &container
);
1201 void hb_fifo_close( hb_fifo_t
** _f
)
1203 hb_fifo_t
* f
= *_f
;
1209 hb_deep_log( 2, "fifo_close: trashing %d buffer(s)", hb_fifo_size( f
) );
1210 while( ( b
= hb_fifo_get( f
) ) )
1212 hb_buffer_close( &b
);
1215 hb_lock_close( &f
->lock
);
1216 hb_cond_close( &f
->cond_empty
);
1217 hb_cond_close( &f
->cond_full
);
1219 #if defined(HB_FIFO_DEBUG)
1220 // Remove the fifo from the global fifo list
1229 void hb_fifo_flush( hb_fifo_t
* f
)
1233 while( ( b
= hb_fifo_get( f
) ) )
1235 hb_buffer_close( &b
);
1238 hb_cond_signal( f
->cond_empty
);
1239 hb_cond_signal( f
->cond_full
);
1240 hb_unlock( f
->lock
);