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
15 taskset_init( taskset_t
*ts
, int thread_count
, size_t arg_size
)
20 memset( ts
, 0, sizeof( *ts
) );
21 ts
->thread_count
= thread_count
;
22 ts
->arg_size
= arg_size
;
23 ts
->bitmap_elements
= ( ts
->thread_count
+ 31 ) / 32;
24 ts
->task_threads
= malloc( sizeof( hb_thread_t
* ) * ts
->thread_count
);
25 if( ts
->task_threads
== NULL
)
31 ts
->task_threads_args
= malloc( arg_size
* ts
->thread_count
);
32 if( ts
->task_threads
== NULL
)
37 ts
->task_begin_bitmap
= malloc( sizeof( uint32_t ) * ts
->bitmap_elements
);
38 if( ts
->task_begin_bitmap
== NULL
)
42 ts
->task_complete_bitmap
= malloc( sizeof( uint32_t ) * ts
->bitmap_elements
);
43 if( ts
->task_complete_bitmap
== NULL
)
47 ts
->task_stop_bitmap
= malloc( sizeof( uint32_t ) * ts
->bitmap_elements
);
48 if( ts
->task_stop_bitmap
== NULL
)
52 ts
->task_cond_lock
= hb_lock_init();
53 if( ts
->task_cond_lock
== NULL
)
57 ts
->task_begin
= hb_cond_init();
58 if( ts
->task_begin
== NULL
)
62 ts
->task_complete
= hb_cond_init();
63 if( ts
->task_complete
== NULL
)
68 * Initialize all arg data to 0.
70 memset(ts
->task_threads_args
, 0, ts
->arg_size
* ts
->thread_count
);
73 * Inialize bitmaps to all bits set. This means that any unused bits
74 * in the bitmap are already in the "condition satisfied" state allowing
75 * us to test the bitmap 32bits at a time without having to mask off
78 memset(ts
->task_begin_bitmap
, 0xFF, sizeof( uint32_t ) * ts
->bitmap_elements
);
79 memset(ts
->task_complete_bitmap
, 0xFF, sizeof( uint32_t ) * ts
->bitmap_elements
);
80 memset(ts
->task_stop_bitmap
, 0, sizeof( uint32_t ) * ts
->bitmap_elements
);
83 * Important to start off with the threads locked waiting
84 * on input, no work completed, and not asked to stop.
86 bit_nclear( ts
->task_begin_bitmap
, 0, ts
->thread_count
- 1 );
87 bit_nclear( ts
->task_complete_bitmap
, 0, ts
->thread_count
- 1 );
88 bit_nclear( ts
->task_stop_bitmap
, 0, ts
->thread_count
- 1 );
95 hb_cond_close( &ts
->task_complete
);
98 hb_cond_close( &ts
->task_begin
);
101 hb_lock_close( &ts
->task_cond_lock
);
104 free( ts
->task_stop_bitmap
);
107 free( ts
->task_complete_bitmap
);
110 free( ts
->task_begin_bitmap
);
113 if( ts
->task_threads_args
== NULL
)
114 free( ts
->task_threads_args
);
117 free( ts
->task_threads
);
126 taskset_thread_spawn( taskset_t
*ts
, int thr_idx
, const char *descr
,
127 thread_func_t
*func
, int priority
)
129 ts
->task_threads
[thr_idx
] = hb_thread_init( descr
, func
,
130 taskset_thread_args( ts
, thr_idx
),
132 return( ts
->task_threads
[thr_idx
] != NULL
);
136 taskset_cycle( taskset_t
*ts
)
138 hb_lock( ts
->task_cond_lock
);
141 * Signal all threads that their work is available.
143 bit_nset( ts
->task_begin_bitmap
, 0, ts
->thread_count
- 1 );
144 hb_cond_broadcast( ts
->task_begin
);
147 * Wait until all threads have completed. Note that we must
148 * loop here as hb_cond_wait() on some platforms (e.g pthead_cond_wait)
149 * may unblock prematurely.
153 hb_cond_wait( ts
->task_complete
, ts
->task_cond_lock
);
154 } while ( !allbits_set( ts
->task_complete_bitmap
, ts
->bitmap_elements
) );
157 * Clear completion indications for next time.
159 bit_nclear( ts
->task_complete_bitmap
, 0, ts
->thread_count
- 1 );
161 hb_unlock( ts
->task_cond_lock
);
165 * Block current thread until work is available for it.
168 taskset_thread_wait4start( taskset_t
*ts
, int thr_idx
)
170 hb_lock( ts
->task_cond_lock
);
171 while ( bit_is_clear( ts
->task_begin_bitmap
, thr_idx
) )
172 hb_cond_wait( ts
->task_begin
, ts
->task_cond_lock
);
175 * We've been released for one run. Insure we block the next
176 * time through the loop.
178 bit_clear( ts
->task_begin_bitmap
, thr_idx
);
179 hb_unlock( ts
->task_cond_lock
);
183 * Current thread has completed its work. Indicate completion,
184 * and if all threads in this task set have completed, wakeup
185 * anyone waiting for this condition.
188 taskset_thread_complete( taskset_t
*ts
, int thr_idx
)
190 hb_lock( ts
->task_cond_lock
);
191 bit_set( ts
->task_complete_bitmap
, thr_idx
);
192 if( allbits_set( ts
->task_complete_bitmap
, ts
->bitmap_elements
) )
194 hb_cond_signal( ts
->task_complete
);
196 hb_unlock( ts
->task_cond_lock
);
200 taskset_fini( taskset_t
*ts
)
204 hb_lock( ts
->task_cond_lock
);
206 * Tell each thread to stop, and then cleanup.
208 bit_nset( ts
->task_stop_bitmap
, 0, ts
->thread_count
- 1 );
209 bit_nset( ts
->task_begin_bitmap
, 0, ts
->thread_count
- 1 );
210 hb_cond_broadcast( ts
->task_begin
);
213 * Wait for all threads to exit.
215 hb_cond_wait( ts
->task_complete
, ts
->task_cond_lock
);
216 hb_unlock( ts
->task_cond_lock
);
219 * Clean up taskset memory.
221 for( i
= 0; i
< ts
->thread_count
; i
++)
223 hb_thread_close( &ts
->task_threads
[i
] );
225 hb_lock_close( &ts
->task_cond_lock
);
226 hb_cond_close( &ts
->task_begin
);
227 hb_cond_close( &ts
->task_complete
);
228 free( ts
->task_threads
);
229 if( ts
->task_threads_args
!= NULL
)
230 free( ts
->task_threads_args
);
231 free( ts
->task_begin_bitmap
);
232 free( ts
->task_complete_bitmap
);
233 free( ts
->task_stop_bitmap
);