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. */
16 #include <kernel/OS.h>
19 #if defined(SYS_DARWIN) || defined(SYS_FREEBSD)
20 #include <sys/types.h>
21 #include <sys/sysctl.h>
25 #include <sys/param.h>
26 #include <sys/sysctl.h>
27 #include <machine/cpu.h>
40 #include <sys/processor.h>
51 #include <sys/types.h>
52 #include <sys/socket.h>
54 #include <netinet/in.h>
59 /************************************************************************
61 ************************************************************************
62 * Returns the current date in milliseconds.
63 * On Win32, we implement a gettimeofday emulation here because
64 * libdvdread and libmp4v2 use it without checking.
65 ************************************************************************/
72 int gettimeofday( struct timeval * tv, struct timezone * tz )
75 tick = GetTickCount();
76 tv->tv_sec = tick / 1000;
77 tv->tv_usec = ( tick % 1000 ) * 1000;
83 uint64_t hb_get_date()
86 gettimeofday( &tv, NULL );
87 return( (uint64_t) tv.tv_sec * 1000 + (uint64_t) tv.tv_usec / 1000 );
90 /************************************************************************
92 ************************************************************************
93 * Waits <delay> milliseconds.
94 ************************************************************************/
95 void hb_snooze( int delay )
101 #if defined( SYS_BEOS )
102 snooze( 1000 * delay );
103 #elif defined( SYS_DARWIN ) || defined( SYS_LINUX ) || defined( SYS_FREEBSD) || defined( SYS_SunOS )
104 usleep( 1000 * delay );
105 #elif defined( SYS_CYGWIN ) || defined( SYS_MINGW )
110 /************************************************************************
112 ************************************************************************
113 * Whenever possible, returns the number of CPUs on the current
114 * computer. Returns 1 otherwise.
115 * The detection is actually only performed on the first call.
116 ************************************************************************/
117 int hb_get_cpu_count()
119 static int cpu_count = 0;
127 #if defined(SYS_CYGWIN) || defined(SYS_MINGW)
129 GetSystemInfo( &cpuinfo );
130 cpu_count = cpuinfo.dwNumberOfProcessors;
132 #elif defined(SYS_LINUX)
135 memset( &p_aff, 0, sizeof(p_aff) );
136 sched_getaffinity( 0, sizeof(p_aff), &p_aff );
137 for( cpu_count = 0, bit = 0; bit < sizeof(p_aff); bit++ )
138 cpu_count += (((uint8_t *)&p_aff)[bit / 8] >> (bit % 8)) & 1;
140 #elif defined(SYS_BEOS)
142 get_system_info( &info );
143 cpu_count = info.cpu_count;
145 #elif defined(SYS_DARWIN) || defined(SYS_FREEBSD) || defined(SYS_OPENBSD)
146 size_t length = sizeof( cpu_count );
148 int mib[2] = { CTL_HW, HW_NCPU };
149 if( sysctl(mib, 2, &cpu_count, &length, NULL, 0) )
151 if( sysctlbyname("hw.ncpu", &cpu_count, &length, NULL, 0) )
157 #elif defined( SYS_SunOS )
159 processorid_t cpumax;
162 cpumax = sysconf(_SC_CPUID_MAX);
164 for(i = 0; i <= cpumax; i++ )
166 if(p_online(i, P_STATUS) != -1)
175 cpu_count = MAX( 1, cpu_count );
176 cpu_count = MIN( cpu_count, 8 );
181 /************************************************************************
182 * Get a tempory directory for HB
183 ***********************************************************************/
184 void hb_get_tempory_directory( hb_handle_t * h, char path[512] )
188 /* Create the base */
189 #if defined( SYS_CYGWIN ) || defined( SYS_MINGW )
191 int i_size = GetTempPath( 512, base );
192 if( i_size <= 0 || i_size >= 512 )
194 if( getcwd( base, 512 ) == NULL )
195 strcpy( base, "c:" ); /* Bad fallback but ... */
198 /* c:/path/ works like a charm under cygwin(win32?) so use it */
199 while( ( p = strchr( base, '\\' ) ) )
202 strcpy( base, "/tmp" );
204 /* I prefer to remove evntual last '/' (for cygwin) */
205 if( base[strlen(base)-1] == '/' )
206 base[strlen(base)-1] = '\0';
208 snprintf( path, 512, "%s/hb.%d", base, hb_get_pid( h ) );
211 /************************************************************************
212 * Get a tempory filename for HB
213 ***********************************************************************/
214 void hb_get_tempory_filename( hb_handle_t * h, char name[1024],
219 hb_get_tempory_directory( h, name );
222 va_start( args, fmt );
223 vsnprintf( &name[strlen(name)], 1024 - strlen(name), fmt, args );
227 /************************************************************************
229 ************************************************************************
230 * Wrapper to the real mkdir, needed only because it doesn't take a
231 * second argument on Win32. Grrr.
232 ***********************************************************************/
233 void hb_mkdir( char * name )
242 /************************************************************************
243 * Portable thread implementation
244 ***********************************************************************/
249 void (* function) ( void * );
255 #if defined( SYS_BEOS )
259 //#elif defined( SYS_CYGWIN )
264 /************************************************************************
266 ************************************************************************
267 * We use it as the root routine for any thread, for two reasons:
268 * + To set the thread priority on OS X (pthread_setschedparam() could
269 * be called from hb_thread_init(), but it's nicer to do it as we
270 * are sure it is done before the real routine starts)
271 * + Get informed when the thread exits, so we know whether
272 * hb_thread_close() will block or not.
273 ***********************************************************************/
274 static void hb_thread_func( void * _t )
276 hb_thread_t * t = (hb_thread_t *) _t;
278 #if defined( SYS_DARWIN )
279 /* Set the thread priority */
280 struct sched_param param;
281 memset( ¶m, 0, sizeof( struct sched_param ) );
282 param.sched_priority = t->priority;
283 pthread_setschedparam( pthread_self(), SCHED_OTHER, ¶m );
286 #if defined( SYS_BEOS )
287 signal( SIGINT, SIG_IGN );
290 /* Start the actual routine */
291 t->function( t->arg );
293 /* Inform that the thread can be joined now */
294 hb_deep_log( 2, "thread %x exited (\"%s\")", t->thread, t->name );
297 hb_unlock( t->lock );
300 /************************************************************************
302 ************************************************************************
303 * name: user-friendly name
304 * function: the thread routine
305 * arg: argument of the routine
306 * priority: HB_LOW_PRIORITY or HB_NORMAL_PRIORITY
307 ***********************************************************************/
308 hb_thread_t * hb_thread_init( char * name, void (* function)(void *),
309 void * arg, int priority )
311 hb_thread_t * t = calloc( sizeof( hb_thread_t ), 1 );
313 t->name = strdup( name );
314 t->function = function;
316 t->priority = priority;
318 t->lock = hb_lock_init();
320 /* Create and start the thread */
321 #if defined( SYS_BEOS )
322 t->thread = spawn_thread( (thread_func) hb_thread_func,
324 resume_thread( t->thread );
327 pthread_create( &t->thread, NULL,
328 (void * (*)( void * )) hb_thread_func, t );
330 //#elif defined( SYS_CYGWIN )
331 // t->thread = CreateThread( NULL, 0,
332 // (LPTHREAD_START_ROUTINE) hb_thread_func, t, 0, NULL );
334 // /* Maybe use THREAD_PRIORITY_LOWEST instead */
335 // if( priority == HB_LOW_PRIORITY )
336 // SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
339 hb_deep_log( 2, "thread %x started (\"%s\")", t->thread, t->name );
343 /************************************************************************
345 ************************************************************************
346 * Joins the thread and frees memory.
347 ***********************************************************************/
348 void hb_thread_close( hb_thread_t ** _t )
350 hb_thread_t * t = *_t;
352 /* Join the thread */
353 #if defined( SYS_BEOS )
355 wait_for_thread( t->thread, &exit_value );
358 pthread_join( t->thread, NULL );
360 //#elif defined( SYS_CYGWIN )
361 // WaitForSingleObject( t->thread, INFINITE );
364 hb_deep_log( 2, "thread %x joined (\"%s\")",
365 t->thread, t->name );
367 hb_lock_close( &t->lock );
373 /************************************************************************
374 * hb_thread_has_exited()
375 ************************************************************************
376 * Returns 1 if the thread can be joined right away, 0 otherwise.
377 ***********************************************************************/
378 int hb_thread_has_exited( hb_thread_t * t )
384 hb_unlock( t->lock );
389 /************************************************************************
390 * Portable mutex implementation
391 ***********************************************************************/
394 #if defined( SYS_BEOS )
397 pthread_mutex_t mutex;
398 //#elif defined( SYS_CYGWIN )
403 /************************************************************************
408 ************************************************************************
409 * Basic wrappers to OS-specific semaphore or mutex functions.
410 ***********************************************************************/
411 hb_lock_t * hb_lock_init()
413 hb_lock_t * l = calloc( sizeof( hb_lock_t ), 1 );
415 #if defined( SYS_BEOS )
416 l->sem = create_sem( 1, "sem" );
418 pthread_mutexattr_t mta;
420 pthread_mutexattr_init(&mta);
422 #if defined( SYS_CYGWIN )
423 pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_NORMAL);
426 pthread_mutex_init( &l->mutex, &mta );
427 //#elif defined( SYS_CYGWIN )
428 // l->mutex = CreateMutex( 0, FALSE, 0 );
434 void hb_lock_close( hb_lock_t ** _l )
438 #if defined( SYS_BEOS )
439 delete_sem( l->sem );
441 pthread_mutex_destroy( &l->mutex );
442 //#elif defined( SYS_CYGWIN )
443 // CloseHandle( l->mutex );
450 void hb_lock( hb_lock_t * l )
452 #if defined( SYS_BEOS )
453 acquire_sem( l->sem );
455 pthread_mutex_lock( &l->mutex );
456 //#elif defined( SYS_CYGWIN )
457 // WaitForSingleObject( l->mutex, INFINITE );
461 void hb_unlock( hb_lock_t * l )
463 #if defined( SYS_BEOS )
464 release_sem( l->sem );
466 pthread_mutex_unlock( &l->mutex );
467 //#elif defined( SYS_CYGWIN )
468 // ReleaseMutex( l->mutex );
472 /************************************************************************
473 * Portable condition variable implementation
474 ***********************************************************************/
477 #if defined( SYS_BEOS )
481 //#elif defined( SYS_CYGWIN )
486 /************************************************************************
491 ************************************************************************
492 * Win9x is not supported by this implementation (SignalObjectAndWait()
493 * only available on Windows 2000/XP).
494 ***********************************************************************/
495 hb_cond_t * hb_cond_init()
497 hb_cond_t * c = calloc( sizeof( hb_cond_t ), 1 );
499 #if defined( SYS_BEOS )
502 pthread_cond_init( &c->cond, NULL );
503 //#elif defined( SYS_CYGWIN )
504 // c->event = CreateEvent( NULL, FALSE, FALSE, NULL );
510 void hb_cond_close( hb_cond_t ** _c )
514 #if defined( SYS_BEOS )
516 pthread_cond_destroy( &c->cond );
517 //#elif defined( SYS_CYGWIN )
518 // CloseHandle( c->event );
525 void hb_cond_wait( hb_cond_t * c, hb_lock_t * lock )
527 #if defined( SYS_BEOS )
528 c->thread = find_thread( NULL );
529 release_sem( lock->sem );
530 suspend_thread( c->thread );
531 acquire_sem( lock->sem );
534 pthread_cond_wait( &c->cond, &lock->mutex );
535 //#elif defined( SYS_CYGWIN )
536 // SignalObjectAndWait( lock->mutex, c->event, INFINITE, FALSE );
537 // WaitForSingleObject( lock->mutex, INFINITE );
541 void hb_cond_signal( hb_cond_t * c )
543 #if defined( SYS_BEOS )
544 while( c->thread != -1 )
547 get_thread_info( c->thread, &info );
548 if( info.state == B_THREAD_SUSPENDED )
550 resume_thread( c->thread );
553 /* Looks like we have been called between hb_cond_wait's
554 release_sem() and suspend_thread() lines. Wait until the
555 thread is actually suspended before we resume it */
559 pthread_cond_signal( &c->cond );
560 //#elif defined( SYS_CYGWIN )
561 // PulseEvent( c->event );
565 /************************************************************************
567 ***********************************************************************/
574 hb_net_t * hb_net_open( char * address, int port )
576 hb_net_t * n = calloc( sizeof( hb_net_t ), 1 );
578 struct sockaddr_in sock;
579 struct hostent * host;
581 /* TODO: find out why this doesn't work on Win32 */
582 if( !( host = gethostbyname( address ) ) )
584 hb_log( "gethostbyname failed (%s)", address );
589 memset( &sock, 0, sizeof( struct sockaddr_in ) );
590 sock.sin_family = host->h_addrtype;
591 sock.sin_port = htons( port );
592 memcpy( &sock.sin_addr, host->h_addr, host->h_length );
594 if( ( n->socket = socket( host->h_addrtype, SOCK_STREAM, 0 ) ) < 0 )
596 hb_log( "socket failed" );
601 if( connect( n->socket, (struct sockaddr *) &sock,
602 sizeof( struct sockaddr_in ) ) < 0 )
604 hb_log( "connect failed" );
612 int hb_net_send( hb_net_t * n, char * buffer )
614 return send( n->socket, buffer, strlen( buffer ), 0 );
617 int hb_net_recv( hb_net_t * n, char * buffer, int size )
619 return recv( n->socket, buffer, size - 1, 0 );
622 void hb_net_close( hb_net_t ** _n )
624 hb_net_t * n = (hb_net_t *) *_n;