Mercurial > projects > ldc
view tango/lib/common/tango/stdc/posix/pthread_darwin.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
line wrap: on
line source
/** * D header file for POSIX. * * Copyright: Public Domain * License: Public Domain * Authors: Sean Kelly * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition */ module tango.stdc.posix.pthread; public import tango.stdc.posix.sys.types; public import tango.stdc.posix.sched; public import tango.stdc.posix.time; private import tango.stdc.stdlib; extern (C): // // Required // version( darwin ) { int pthread_cond_broadcast(pthread_cond_t*); int pthread_cond_destroy(pthread_cond_t*); int pthread_cond_init(pthread_cond_t*, pthread_condattr_t*); //int pthread_cond_signal(pthread_cond_t*); //int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, timespec*); int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*); int pthread_mutex_destroy(pthread_mutex_t*); int pthread_mutex_init(pthread_mutex_t*, pthread_mutexattr_t*); int pthread_mutex_lock(pthread_mutex_t*); int pthread_mutex_trylock(pthread_mutex_t*); int pthread_mutex_unlock(pthread_mutex_t*); //int pthread_rwlock_destroy(pthread_rwlock_t*); //int pthread_rwlock_init(pthread_rwlock_t*, pthread_rwlockattr_t*); //int pthread_rwlock_rdlock(pthread_rwlock_t*); int pthread_rwlock_tryrdlock(pthread_rwlock_t*); int pthread_rwlock_trywrlock(pthread_rwlock_t*); //int pthread_rwlock_unlock(pthread_rwlock_t*); //int pthread_rwlock_wrlock(pthread_rwlock_t*); } // // Barrier (BAR) // /* PTHREAD_BARRIER_SERIAL_THREAD int pthread_barrier_destroy(pthread_barrier_t*); int pthread_barrier_init(pthread_barrier_t*, pthread_barrierattr_t*, uint); int pthread_barrier_wait(pthread_barrier_t*); int pthread_barrierattr_destroy(pthread_barrierattr_t*); int pthread_barrierattr_getpshared(pthread_barrierattr_t*, int*); (BAR|TSH) int pthread_barrierattr_init(pthread_barrierattr_t*); int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); (BAR|TSH) */ version( darwin ) { const PTHREAD_BARRIER_SERIAL_THREAD = -1; // defined in tango.stdc.posix.pthread and redefined here enum { PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED } int pthread_barrier_destroy( pthread_barrier_t* barrier ) { if( barrier is null ) return EINVAL; if( barrier.b_waiters > 0 ) return EBUSY; int mret = pthread_mutex_destroy( &barrier.b_lock ); int cret = pthread_cond_destroy( &barrier.b_cond ); free( barrier ); return mret ? mret : cret; } int pthread_barrier_init( pthread_barrier_t* barrier, pthread_barrierattr_t* attr, uint count ) { if( barrier is null || count <= 0 ) return EINVAL; pthread_barrier_t* newbarrier = cast(pthread_barrier_t*) malloc( pthread_barrier_t.sizeof ); if( newbarrier is null ) return ENOMEM; int ret; if( ( ret = pthread_mutex_init( &newbarrier.b_lock, null ) ) != 0 ) { free( newbarrier ); return ret; } if( ( ret = pthread_cond_init( &newbarrier.b_cond, null ) ) != 0 ) { pthread_mutex_destroy( &newbarrier.b_lock ); free( newbarrier ); return ret; } newbarrier.b_waiters = 0; newbarrier.b_count = count; newbarrier.b_generation = 0; *barrier = *newbarrier; return 0; } int pthread_barrier_wait( pthread_barrier_t* barrier ) { if( barrier is null ) return EINVAL; int ret; if( ( ret = pthread_mutex_lock( &barrier.b_lock ) ) != 0 ) return ret; if( ++barrier.b_waiters == barrier.b_count ) { // current thread is lastest thread barrier.b_generation++; barrier.b_waiters = 0; if( ( ret = pthread_cond_broadcast( &barrier.b_cond ) ) == 0 ) ret = PTHREAD_BARRIER_SERIAL_THREAD; } else { int gen = barrier.b_generation; do { ret = pthread_cond_wait( &barrier.b_cond, &barrier.b_lock ); // test generation to avoid bogus wakeup } while( ret == 0 && gen == barrier.b_generation ); } pthread_mutex_unlock( &barrier.b_lock ); return ret; } int pthread_barrierattr_destroy( pthread_barrierattr_t* attr ) { if( attr is null ) return EINVAL; free( attr ); return 0; } int pthread_barrierattr_getpshared( pthread_barrierattr_t* attr, int* pshared ) { if( attr is null ) return EINVAL; *pshared = attr.pshared; return 0; } int pthread_barrierattr_init( pthread_barrierattr_t* attr ) { if( attr is null ) return EINVAL; if( ( attr = cast(pthread_barrierattr_t*) malloc( pthread_barrierattr_t.sizeof ) ) is null ) return ENOMEM; attr.pshared = PTHREAD_PROCESS_PRIVATE; return 0; } int pthread_barrierattr_setpshared( pthread_barrierattr_t* attr, int pshared ) { if( attr is null ) return EINVAL; // only PTHREAD_PROCESS_PRIVATE is supported if( pshared != PTHREAD_PROCESS_PRIVATE ) return EINVAL; attr.pshared = pshared; return 0; } } // // Timeouts (TMO) // /* int pthread_mutex_timedlock(pthread_mutex_t*, timespec*); int pthread_rwlock_timedrdlock(pthread_rwlock_t*, timespec*); int pthread_rwlock_timedwrlock(pthread_rwlock_t*, timespec*); */ version( darwin ) { private { import tango.stdc.errno; import tango.stdc.posix.unistd; import tango.stdc.posix.sys.time; extern (D) { void timerclear( timeval* tvp ) { tvp.tv_sec = tvp.tv_usec = 0; } bool timerisset( timeval* tvp ) { return tvp.tv_sec || tvp.tv_usec; } bool timer_cmp_leq( timeval* tvp, timeval* uvp ) { return tvp.tv_sec == uvp.tv_sec ? tvp.tv_usec <= uvp.tv_usec : tvp.tv_sec <= uvp.tv_sec; } void timeradd( timeval* tvp, timeval* uvp, timeval* vvp ) { vvp.tv_sec = tvp.tv_sec + uvp.tv_sec; vvp.tv_usec = tvp.tv_usec + uvp.tv_usec; if( vvp.tv_usec >= 1000000 ) { vvp.tv_sec++; vvp.tv_usec -= 1000000; } } void timersub( timeval* tvp, timeval* uvp, timeval* vvp ) { vvp.tv_sec = tvp.tv_sec - uvp.tv_sec; vvp.tv_usec = tvp.tv_usec - uvp.tv_usec; if( vvp.tv_usec < 0 ) { vvp.tv_sec--; vvp.tv_usec += 1000000; } } void TIMEVAL_TO_TIMESPEC( timeval* tv, timespec* ts ) { ts.tv_sec = tv.tv_sec; ts.tv_nsec = tv.tv_usec * 1000; } void TIMESPEC_TO_TIMEVAL( timeval* tv, timespec* ts ) { tv.tv_sec = ts.tv_sec; tv.tv_usec = ts.tv_nsec / 1000; } } } int pthread_mutex_timedlock( pthread_mutex_t* m, timespec* t ) { timeval currtime; timeval maxwait; TIMESPEC_TO_TIMEVAL( &maxwait, t ); timeval waittime; waittime.tv_usec = 100; while( timer_cmp_leq( &currtime, &maxwait ) ) { int ret = pthread_mutex_trylock( m ); switch( ret ) { case 0: // locked successfully return ret; case EBUSY: // waiting timeradd( &currtime, &waittime, &currtime ); break; default: return ret; } usleep( waittime.tv_usec ); } return ETIMEDOUT; } int pthread_rwlock_timedrdlock( pthread_rwlock_t *rwlock, timespec* t ) { timeval currtime; timeval maxwait; TIMESPEC_TO_TIMEVAL( &maxwait, t ); timeval waittime; waittime.tv_usec = 100; while( timer_cmp_leq( &currtime, &maxwait ) ) { int ret = pthread_rwlock_tryrdlock( rwlock ); switch( ret ) { case 0: // locked successfully return ret; case EBUSY: // waiting timeradd( &currtime, &waittime, &currtime ); break; default: return ret; } usleep( waittime.tv_usec ); } return ETIMEDOUT; } int pthread_rwlock_timedwrlock( pthread_rwlock_t* l, timespec* t ) { timeval currtime; timeval maxwait; TIMESPEC_TO_TIMEVAL( &maxwait, t ); timeval waittime; waittime.tv_usec = 100; while( timer_cmp_leq( &currtime, &maxwait ) ) { int ret = pthread_rwlock_trywrlock( l ); switch( ret ) { case 0: // locked successfully return ret; case EBUSY: // waiting timeradd( &currtime, &waittime, &currtime ); break; default: return ret; } usleep( waittime.tv_usec ); } return ETIMEDOUT; } }