]> granicus.if.org Git - handbrake/commitdiff
Forgot to svn add some taskset files
authorjstebbins <jstebbins.hb@gmail.com>
Fri, 18 May 2012 06:54:25 +0000 (06:54 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Fri, 18 May 2012 06:54:25 +0000 (06:54 +0000)
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4686 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/bits.h [new file with mode: 0644]
libhb/taskset.c [new file with mode: 0644]
libhb/taskset.h [new file with mode: 0644]

diff --git a/libhb/bits.h b/libhb/bits.h
new file mode 100644 (file)
index 0000000..6338edc
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id$
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://handbrake.fr/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_BITS_H
+#define HB_BITS_H
+
+static inline int
+allbits_set(uint32_t *bitmap, int num_words)
+{
+    unsigned int i;
+    for( i = 0; i < num_words; i++ )
+    {
+        if( bitmap[i] != 0xFFFFFFFF )
+            return (0);
+    }
+    return (1);
+}
+
+static inline int
+bit_is_set( uint32_t *bit_map, int bit_pos )
+{
+    return( ( bit_map[bit_pos >> 5] & (0x1 << (bit_pos & 0x1F) ) ) != 0 );
+}
+
+static inline int
+bit_is_clear( uint32_t *bit_map, int bit_pos )
+{
+    return( ( bit_map[bit_pos >> 5] & ( 0x1 << (bit_pos & 0x1F) )  ) == 0 );
+}
+
+static inline void
+bit_set( uint32_t *bit_map, int bit_pos )
+{
+    bit_map[bit_pos >> 5] |= 0x1 << (bit_pos & 0x1F);
+}
+
+static inline void
+bit_clear(uint32_t *bit_map, int bit_pos)
+{
+    bit_map[bit_pos >> 5] &= ~( 0x1 << ( bit_pos & 0x1F ) );
+}
+
+static inline void
+bit_nclear(uint32_t *bit_map, int start_pos, int stop_pos)
+{
+    int start_word = start_pos >> 5;
+    int stop_word  = stop_pos >> 5;
+
+    if ( start_word == stop_word )
+    {
+
+        bit_map[start_word] &= ( ( 0x7FFFFFFF >> ( 31 - (start_pos & 0x1F ) ) )
+                             |  ( 0xFFFFFFFE << ( stop_pos & 0x1F ) ) );
+    }
+    else
+    {
+        bit_map[start_word] &= ( 0x7FFFFFFF >> ( 31 - ( start_pos & 0x1F ) ) );
+        while (++start_word < stop_word)
+            bit_map[start_word] = 0;
+        bit_map[stop_word]  &= 0xFFFFFFFE << ( stop_pos & 0x1F );
+    }
+}
+
+static inline void
+bit_nset(uint32_t *bit_map, int start_pos, int stop_pos)
+{
+    int start_word = start_pos >> 5;
+    int stop_word  = stop_pos >> 5;
+
+    if ( start_word == stop_word )
+    {
+        bit_map[start_word] |= ( ( 0xFFFFFFFF << ( start_pos & 0x1F ) )
+                             &  ( 0xFFFFFFFF >> ( 31 - ( stop_pos & 0x1F ) ) ) );
+    }
+    else
+    {
+        bit_map[start_word] |= 0xFFFFFFFF << ( start_pos & 0x1F );
+        while (++start_word < stop_word)
+            bit_map[start_word] = 0xFFFFFFFF;
+        bit_map[stop_word]  |= 0xFFFFFFFF >> ( 31 - ( stop_pos & 0x1F ) );
+    }
+}
+
+#endif /* HB_BITS_H */
diff --git a/libhb/taskset.c b/libhb/taskset.c
new file mode 100644 (file)
index 0000000..2721139
--- /dev/null
@@ -0,0 +1,231 @@
+/* $Id$
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://handbrake.fr/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#include "hb.h"
+#include "ports.h"
+#include "taskset.h"
+
+int
+taskset_init( taskset_t *ts, int thread_count, size_t arg_size )
+{
+    int init_step;
+
+    init_step = 0;
+    memset( ts, 0, sizeof( *ts ) );
+    ts->thread_count = thread_count;
+    ts->arg_size = arg_size;
+    ts->bitmap_elements = ( ts->thread_count + 31 ) / 32;
+    ts->task_threads = malloc( sizeof( hb_thread_t* ) * ts->thread_count );
+    if( ts->task_threads == NULL )
+        goto fail;
+    init_step++;
+
+    if( arg_size != 0 )
+    {
+        ts->task_threads_args = malloc( arg_size * ts->thread_count );
+        if( ts->task_threads == NULL )
+            goto fail;
+    }
+    init_step++;
+
+    ts->task_begin_bitmap = malloc( sizeof( uint32_t  ) * ts->bitmap_elements );
+    if( ts->task_begin_bitmap == NULL )
+        goto fail;
+    init_step++;
+
+    ts->task_complete_bitmap = malloc( sizeof( uint32_t ) * ts->bitmap_elements );
+    if( ts->task_complete_bitmap == NULL )
+        goto fail;
+    init_step++;
+
+    ts->task_stop_bitmap = malloc( sizeof( uint32_t ) * ts->bitmap_elements );
+    if( ts->task_stop_bitmap == NULL )
+        goto fail;
+    init_step++;
+
+    ts->task_cond_lock = hb_lock_init();
+    if( ts->task_cond_lock == NULL)
+        goto fail;
+    init_step++;
+
+    ts->task_begin = hb_cond_init();
+    if( ts->task_begin == NULL)
+        goto fail;
+    init_step++;
+
+    ts->task_complete = hb_cond_init();
+    if( ts->task_complete == NULL)
+        goto fail;
+    init_step++;
+
+    /*
+     * Initialize all arg data to 0.
+     */
+    memset(ts->task_threads_args, 0, ts->arg_size * ts->thread_count );
+
+    /*
+     * Inialize bitmaps to all bits set.  This means that any unused bits
+     * in the bitmap are already in the "condition satisfied" state allowing
+     * us to test the bitmap 32bits at a time without having to mask off
+     * the end.
+     */
+    memset(ts->task_begin_bitmap, 0xFF, sizeof( uint32_t ) * ts->bitmap_elements );
+    memset(ts->task_complete_bitmap, 0xFF, sizeof( uint32_t ) * ts->bitmap_elements );
+    memset(ts->task_stop_bitmap, 0, sizeof( uint32_t ) * ts->bitmap_elements );
+    
+    /*
+     * Important to start off with the threads locked waiting
+     * on input, no work completed, and not asked to stop.
+     */
+    bit_nclear( ts->task_begin_bitmap, 0, ts->thread_count - 1 );
+    bit_nclear( ts->task_complete_bitmap, 0, ts->thread_count - 1 );
+    bit_nclear( ts->task_stop_bitmap, 0, ts->thread_count - 1 );
+    return (1);
+
+fail:
+    switch (init_step)
+    {
+        default:
+            hb_cond_close( &ts->task_complete );
+            /* FALL THROUGH */
+        case 7:
+            hb_cond_close( &ts->task_begin );
+            /* FALL THROUGH */
+        case 6:
+            hb_lock_close( &ts->task_cond_lock );
+            /* FALL THROUGH */
+        case 5:
+            free( ts->task_stop_bitmap );
+            /* FALL THROUGH */
+        case 4:
+            free( ts->task_complete_bitmap );
+            /* FALL THROUGH */
+        case 3:
+           free( ts->task_begin_bitmap );
+            /* FALL THROUGH */
+        case 2:
+           if( ts->task_threads_args == NULL )
+                free( ts->task_threads_args );
+            /* FALL THROUGH */
+        case 1:
+           free( ts->task_threads );
+            /* FALL THROUGH */
+        case 0:
+            break;
+    }
+    return (0);
+}
+
+int
+taskset_thread_spawn( taskset_t *ts, int thr_idx, const char *descr,
+                     thread_func_t *func, int priority )
+{
+    ts->task_threads[thr_idx] = hb_thread_init( descr, func,
+                                                taskset_thread_args( ts, thr_idx ),
+                                                priority);
+    return( ts->task_threads[thr_idx] != NULL );
+}
+
+void
+taskset_cycle( taskset_t *ts )
+{
+    hb_lock( ts->task_cond_lock );
+
+    /*
+     * Signal all threads that their work is available.
+     */
+    bit_nset( ts->task_begin_bitmap, 0, ts->thread_count - 1 );
+    hb_cond_broadcast( ts->task_begin );
+
+    /*
+     * Wait until all threads have completed.  Note that we must
+     * loop here as hb_cond_wait() on some platforms (e.g pthead_cond_wait)
+     * may unblock prematurely.
+     */
+    do
+    {
+        hb_cond_wait( ts->task_complete, ts->task_cond_lock );
+    } while ( !allbits_set( ts->task_complete_bitmap, ts->bitmap_elements ) );
+
+    /*
+     * Clear completion indications for next time.
+     */
+    bit_nclear( ts->task_complete_bitmap, 0, ts->thread_count - 1 );
+
+    hb_unlock( ts->task_cond_lock );
+}
+
+/*
+ * Block current thread until work is available for it.
+ */
+void
+taskset_thread_wait4start( taskset_t *ts, int thr_idx )
+{
+    hb_lock( ts->task_cond_lock );
+    while ( bit_is_clear( ts->task_begin_bitmap, thr_idx ) )
+        hb_cond_wait( ts->task_begin, ts->task_cond_lock );
+
+    /*
+     * We've been released for one run.  Insure we block the next
+     * time through the loop.
+     */
+    bit_clear( ts->task_begin_bitmap, thr_idx );
+    hb_unlock( ts->task_cond_lock );
+}
+
+/*
+ * Current thread has completed its work.  Indicate completion,
+ * and if all threads in this task set have completed, wakeup
+ * anyone waiting for this condition.
+ */
+void
+taskset_thread_complete( taskset_t *ts, int thr_idx )
+{
+    hb_lock( ts->task_cond_lock );
+    bit_set( ts->task_complete_bitmap, thr_idx );
+    if( allbits_set( ts->task_complete_bitmap, ts->bitmap_elements ) )
+    {
+        hb_cond_signal( ts->task_complete );
+    }
+    hb_unlock( ts->task_cond_lock );
+}
+
+void
+taskset_fini( taskset_t *ts )
+{
+    int i;
+
+    hb_lock( ts->task_cond_lock );
+    /*
+     * Tell each thread to stop, and then cleanup.
+     */
+    bit_nset( ts->task_stop_bitmap, 0, ts->thread_count - 1 );
+    bit_nset( ts->task_begin_bitmap, 0, ts->thread_count - 1 );
+    hb_cond_broadcast( ts->task_begin );
+
+    /*
+     * Wait for all threads to exit.
+     */
+    hb_cond_wait( ts->task_complete, ts->task_cond_lock );
+    hb_unlock( ts->task_cond_lock );
+
+    /*
+     * Clean up taskset memory.
+     */
+    for( i = 0; i < ts->thread_count; i++)
+    {
+        hb_thread_close( &ts->task_threads[i] );
+    }
+    hb_lock_close( &ts->task_cond_lock );
+    hb_cond_close( &ts->task_begin );
+    hb_cond_close( &ts->task_complete );
+    free( ts->task_threads );
+    if( ts->task_threads_args != NULL )
+        free( ts->task_threads_args );
+    free( ts->task_begin_bitmap );
+    free( ts->task_complete_bitmap );
+    free( ts->task_stop_bitmap );
+}
diff --git a/libhb/taskset.h b/libhb/taskset.h
new file mode 100644 (file)
index 0000000..b482c0b
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id$
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://handbrake.fr/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_TASKSET_H
+#define HB_TASKSET_H
+
+#define TASKSET_POSIX_COMPLIANT 1
+
+#include "bits.h"
+
+typedef struct hb_taskset_s {
+    int                thread_count;
+    int                arg_size;
+    int                bitmap_elements;
+    hb_thread_t     ** task_threads;
+    uint8_t          * task_threads_args;
+    uint32_t         * task_begin_bitmap;    // Threads can begin
+    uint32_t         * task_complete_bitmap; // Threads have completed
+    uint32_t         * task_stop_bitmap;     // Threads should exit
+    hb_lock_t        * task_cond_lock;       // Held during condition tests
+    hb_cond_t        * task_begin;           // Threads can begin work
+    hb_cond_t        * task_complete;        // Threads have finished work.
+} taskset_t;
+
+int taskset_init( taskset_t *, int /*thread_count*/, size_t /*user_arg_size*/ );
+void taskset_cycle( taskset_t * );
+void taskset_fini( taskset_t * );
+
+int  taskset_thread_spawn( taskset_t *, int /*thr_idx*/, const char * /*descr*/,
+                           thread_func_t *, int /*priority*/ );
+void taskset_thread_wait4start( taskset_t *, int );
+void taskset_thread_complete( taskset_t *, int );
+
+static inline void *taskset_thread_args( taskset_t *, int );
+static inline int   taskset_thread_stop( taskset_t *, int );
+
+static inline void *
+taskset_thread_args( taskset_t *ts, int thr_idx )
+{
+    return( ts->task_threads_args + ( ts->arg_size * thr_idx ) );
+}
+
+static inline int
+taskset_thread_stop( taskset_t *ts, int thr_idx )
+{
+    return bit_is_set( ts->task_stop_bitmap, thr_idx );
+}
+
+#endif /* HB_TASKSET_H */