1 /* $Id: ports.c,v 1.15 2005/10/15 18:05:03 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.fr/>.
5 It may be used under the terms of the GNU General Public License. */
10 #if defined( SYS_BEOS )
13 #elif defined( SYS_CYGWIN )
15 #elif defined( SYS_SunOS )
16 #include <sys/processor.h>
24 //#include <winsock2.h>
25 //#include <ws2tcpip.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <netinet/in.h>
35 /************************************************************************
37 ************************************************************************
38 * Returns the current date in milliseconds.
39 * On Win32, we implement a gettimeofday emulation here because
40 * libdvdread and libmp4v2 use it without checking.
41 ************************************************************************/
48 int gettimeofday( struct timeval * tv, struct timezone * tz )
51 tick = GetTickCount();
52 tv->tv_sec = tick / 1000;
53 tv->tv_usec = ( tick % 1000 ) * 1000;
59 uint64_t hb_get_date()
62 gettimeofday( &tv, NULL );
63 return( (uint64_t) tv.tv_sec * 1000 + (uint64_t) tv.tv_usec / 1000 );
66 /************************************************************************
68 ************************************************************************
69 * Waits <delay> milliseconds.
70 ************************************************************************/
71 void hb_snooze( int delay )
77 #if defined( SYS_BEOS )
78 snooze( 1000 * delay );
79 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD) || defined( SYS_SunOS )
80 usleep( 1000 * delay );
81 #elif defined( SYS_CYGWIN )
86 /************************************************************************
88 ************************************************************************
89 * Whenever possible, returns the number of CPUs on the current
90 * computer. Returns 1 otherwise.
91 * The detection is actually only performed on the first call.
92 ************************************************************************/
93 int hb_get_cpu_count()
95 static int cpu_count = 0;
103 #if defined( SYS_BEOS )
106 get_system_info( &info );
107 cpu_count = info.cpu_count;
110 #elif defined( SYS_DARWIN ) || defined( SYS_FREEBSD )
114 if( ( info = popen( "/usr/sbin/sysctl hw.ncpu", "r" ) ) )
116 memset( buffer, 0, 16 );
117 if( fgets( buffer, 15, info ) )
119 if( sscanf( buffer, "hw.ncpu: %d", &cpu_count ) != 1 )
127 #elif defined( SYS_LINUX )
132 if( ( info = popen( "grep -c '^processor' /proc/cpuinfo",
135 memset( buffer, 0, 8 );
136 if( fgets( buffer, 7, info ) )
138 if( sscanf( buffer, "%d", &cpu_count ) != 1 )
147 #elif defined( SYS_CYGWIN )
149 GetSystemInfo( &cpuinfo );
150 cpu_count = cpuinfo.dwNumberOfProcessors;
151 #elif defined( SYS_SunOS )
153 processorid_t cpumax;
156 cpumax = sysconf(_SC_CPUID_MAX);
158 for(i = 0; i <= cpumax; i++ )
160 if(p_online(i, P_STATUS) != -1)
169 cpu_count = MAX( 1, cpu_count );
170 cpu_count = MIN( cpu_count, 8 );
175 /************************************************************************
176 * Get a tempory directory for HB
177 ***********************************************************************/
178 void hb_get_tempory_directory( hb_handle_t * h, char path[512] )
182 /* Create the base */
185 int i_size = GetTempPath( 512, base );
186 if( i_size <= 0 || i_size >= 512 )
188 if( getcwd( base, 512 ) == NULL )
189 strcpy( base, "c:" ); /* Bad fallback but ... */
192 /* c:/path/ works like a charm under cygwin(win32?) so use it */
193 while( ( p = strchr( base, '\\' ) ) )
196 strcpy( base, "/tmp" );
198 /* I prefer to remove evntual last '/' (for cygwin) */
199 if( base[strlen(base)-1] == '/' )
200 base[strlen(base)-1] = '\0';
202 snprintf( path, 512, "%s/hb.%d", base, hb_get_pid( h ) );
205 /************************************************************************
206 * Get a tempory filename for HB
207 ***********************************************************************/
208 void hb_get_tempory_filename( hb_handle_t * h, char name[1024],
213 hb_get_tempory_directory( h, name );
216 va_start( args, fmt );
217 vsnprintf( &name[strlen(name)], 1024 - strlen(name), fmt, args );
221 /************************************************************************
223 ************************************************************************
224 * Wrapper to the real mkdir, needed only because it doesn't take a
225 * second argument on Win32. Grrr.
226 ***********************************************************************/
227 void hb_mkdir( char * name )
236 /************************************************************************
237 * Portable thread implementation
238 ***********************************************************************/
243 void (* function) ( void * );
249 #if defined( SYS_BEOS )
253 //#elif defined( SYS_CYGWIN )
258 /************************************************************************
260 ************************************************************************
261 * We use it as the root routine for any thread, for two reasons:
262 * + To set the thread priority on OS X (pthread_setschedparam() could
263 * be called from hb_thread_init(), but it's nicer to do it as we
264 * are sure it is done before the real routine starts)
265 * + Get informed when the thread exits, so we know whether
266 * hb_thread_close() will block or not.
267 ***********************************************************************/
268 static void hb_thread_func( void * _t )
270 hb_thread_t * t = (hb_thread_t *) _t;
272 #if defined( SYS_DARWIN )
273 /* Set the thread priority */
274 struct sched_param param;
275 memset( ¶m, 0, sizeof( struct sched_param ) );
276 param.sched_priority = t->priority;
277 pthread_setschedparam( pthread_self(), SCHED_OTHER, ¶m );
280 #if defined( SYS_BEOS )
281 signal( SIGINT, SIG_IGN );
284 /* Start the actual routine */
285 t->function( t->arg );
287 /* Inform that the thread can be joined now */
288 hb_log( "thread %x exited (\"%s\")", t->thread, t->name );
291 hb_unlock( t->lock );
294 /************************************************************************
296 ************************************************************************
297 * name: user-friendly name
298 * function: the thread routine
299 * arg: argument of the routine
300 * priority: HB_LOW_PRIORITY or HB_NORMAL_PRIORITY
301 ***********************************************************************/
302 hb_thread_t * hb_thread_init( char * name, void (* function)(void *),
303 void * arg, int priority )
305 hb_thread_t * t = calloc( sizeof( hb_thread_t ), 1 );
307 t->name = strdup( name );
308 t->function = function;
310 t->priority = priority;
312 t->lock = hb_lock_init();
314 /* Create and start the thread */
315 #if defined( SYS_BEOS )
316 t->thread = spawn_thread( (thread_func) hb_thread_func,
318 resume_thread( t->thread );
321 pthread_create( &t->thread, NULL,
322 (void * (*)( void * )) hb_thread_func, t );
324 //#elif defined( SYS_CYGWIN )
325 // t->thread = CreateThread( NULL, 0,
326 // (LPTHREAD_START_ROUTINE) hb_thread_func, t, 0, NULL );
328 // /* Maybe use THREAD_PRIORITY_LOWEST instead */
329 // if( priority == HB_LOW_PRIORITY )
330 // SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
333 hb_log( "thread %x started (\"%s\")", t->thread, t->name );
337 /************************************************************************
339 ************************************************************************
340 * Joins the thread and frees memory.
341 ***********************************************************************/
342 void hb_thread_close( hb_thread_t ** _t )
344 hb_thread_t * t = *_t;
346 /* Join the thread */
347 #if defined( SYS_BEOS )
349 wait_for_thread( t->thread, &exit_value );
352 pthread_join( t->thread, NULL );
354 //#elif defined( SYS_CYGWIN )
355 // WaitForSingleObject( t->thread, INFINITE );
358 hb_log( "thread %x joined (\"%s\")",
359 t->thread, t->name );
361 hb_lock_close( &t->lock );
367 /************************************************************************
368 * hb_thread_has_exited()
369 ************************************************************************
370 * Returns 1 if the thread can be joined right away, 0 otherwise.
371 ***********************************************************************/
372 int hb_thread_has_exited( hb_thread_t * t )
378 hb_unlock( t->lock );
383 /************************************************************************
384 * Portable mutex implementation
385 ***********************************************************************/
388 #if defined( SYS_BEOS )
391 pthread_mutex_t mutex;
392 //#elif defined( SYS_CYGWIN )
397 /************************************************************************
402 ************************************************************************
403 * Basic wrappers to OS-specific semaphore or mutex functions.
404 ***********************************************************************/
405 hb_lock_t * hb_lock_init()
407 hb_lock_t * l = calloc( sizeof( hb_lock_t ), 1 );
409 #if defined( SYS_BEOS )
410 l->sem = create_sem( 1, "sem" );
412 pthread_mutexattr_t mta;
414 pthread_mutexattr_init(&mta);
415 pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_NORMAL);
417 pthread_mutex_init( &l->mutex, &mta );
418 //#elif defined( SYS_CYGWIN )
419 // l->mutex = CreateMutex( 0, FALSE, 0 );
425 void hb_lock_close( hb_lock_t ** _l )
429 #if defined( SYS_BEOS )
430 delete_sem( l->sem );
432 pthread_mutex_destroy( &l->mutex );
433 //#elif defined( SYS_CYGWIN )
434 // CloseHandle( l->mutex );
441 void hb_lock( hb_lock_t * l )
443 #if defined( SYS_BEOS )
444 acquire_sem( l->sem );
446 pthread_mutex_lock( &l->mutex );
447 //#elif defined( SYS_CYGWIN )
448 // WaitForSingleObject( l->mutex, INFINITE );
452 void hb_unlock( hb_lock_t * l )
454 #if defined( SYS_BEOS )
455 release_sem( l->sem );
457 pthread_mutex_unlock( &l->mutex );
458 //#elif defined( SYS_CYGWIN )
459 // ReleaseMutex( l->mutex );
463 /************************************************************************
464 * Portable condition variable implementation
465 ***********************************************************************/
468 #if defined( SYS_BEOS )
472 //#elif defined( SYS_CYGWIN )
477 /************************************************************************
482 ************************************************************************
483 * Win9x is not supported by this implementation (SignalObjectAndWait()
484 * only available on Windows 2000/XP).
485 ***********************************************************************/
486 hb_cond_t * hb_cond_init()
488 hb_cond_t * c = calloc( sizeof( hb_cond_t ), 1 );
490 #if defined( SYS_BEOS )
493 pthread_cond_init( &c->cond, NULL );
494 //#elif defined( SYS_CYGWIN )
495 // c->event = CreateEvent( NULL, FALSE, FALSE, NULL );
501 void hb_cond_close( hb_cond_t ** _c )
505 #if defined( SYS_BEOS )
507 pthread_cond_destroy( &c->cond );
508 //#elif defined( SYS_CYGWIN )
509 // CloseHandle( c->event );
516 void hb_cond_wait( hb_cond_t * c, hb_lock_t * lock )
518 #if defined( SYS_BEOS )
519 c->thread = find_thread( NULL );
520 release_sem( lock->sem );
521 suspend_thread( c->thread );
522 acquire_sem( lock->sem );
525 pthread_cond_wait( &c->cond, &lock->mutex );
526 //#elif defined( SYS_CYGWIN )
527 // SignalObjectAndWait( lock->mutex, c->event, INFINITE, FALSE );
528 // WaitForSingleObject( lock->mutex, INFINITE );
532 void hb_cond_signal( hb_cond_t * c )
534 #if defined( SYS_BEOS )
535 while( c->thread != -1 )
538 get_thread_info( c->thread, &info );
539 if( info.state == B_THREAD_SUSPENDED )
541 resume_thread( c->thread );
544 /* Looks like we have been called between hb_cond_wait's
545 release_sem() and suspend_thread() lines. Wait until the
546 thread is actually suspended before we resume it */
550 pthread_cond_signal( &c->cond );
551 //#elif defined( SYS_CYGWIN )
552 // PulseEvent( c->event );
556 /************************************************************************
558 ***********************************************************************/
565 hb_net_t * hb_net_open( char * address, int port )
567 hb_net_t * n = calloc( sizeof( hb_net_t ), 1 );
569 struct sockaddr_in sock;
570 struct hostent * host;
572 /* TODO: find out why this doesn't work on Win32 */
573 if( !( host = gethostbyname( address ) ) )
575 hb_log( "gethostbyname failed (%s)", address );
580 memset( &sock, 0, sizeof( struct sockaddr_in ) );
581 sock.sin_family = host->h_addrtype;
582 sock.sin_port = htons( port );
583 memcpy( &sock.sin_addr, host->h_addr, host->h_length );
585 if( ( n->socket = socket( host->h_addrtype, SOCK_STREAM, 0 ) ) < 0 )
587 hb_log( "socket failed" );
592 if( connect( n->socket, (struct sockaddr *) &sock,
593 sizeof( struct sockaddr_in ) ) < 0 )
595 hb_log( "connect failed" );
603 int hb_net_send( hb_net_t * n, char * buffer )
605 return send( n->socket, buffer, strlen( buffer ), 0 );
608 int hb_net_recv( hb_net_t * n, char * buffer, int size )
610 return recv( n->socket, buffer, size - 1, 0 );
613 void hb_net_close( hb_net_t ** _n )
615 hb_net_t * n = (hb_net_t *) *_n;