diff --git a/libtransmission/internal.h b/libtransmission/internal.h index d22b6e995..ac2b119ce 100644 --- a/libtransmission/internal.h +++ b/libtransmission/internal.h @@ -139,7 +139,6 @@ struct tr_torrent run_status_t runStatus; run_status_t runStatusToSave; cp_status_t cpStatus; - struct tr_lock * lock; struct tr_tracker * tracker; struct tr_publisher_tag * trackerSubscription; @@ -188,6 +187,8 @@ struct tr_handle struct tr_peerMgr * peerMgr; struct tr_shared * shared; + struct tr_lock * lock; + tr_handle_status stats[2]; int statCur; @@ -197,4 +198,9 @@ struct tr_handle uint8_t azId[TR_AZ_ID_LEN]; }; +void tr_globalLock ( struct tr_handle * ); +void tr_globalUnlock ( struct tr_handle * ); +int tr_globalIsLocked ( const struct tr_handle * ); + + #endif diff --git a/libtransmission/makemeta.c b/libtransmission/makemeta.c index 43f2b37b2..d1678fd81 100644 --- a/libtransmission/makemeta.c +++ b/libtransmission/makemeta.c @@ -415,10 +415,10 @@ static tr_lock* getQueueLock( tr_handle * h ) { static tr_lock * lock = NULL; - tr_sharedLock( h->shared ); + tr_globalLock( h ); if( !lock ) lock = tr_lockNew( ); - tr_sharedUnlock( h->shared ); + tr_globalUnlock( h ); return lock; } diff --git a/libtransmission/peer-mgr.c b/libtransmission/peer-mgr.c index a129dc66a..a569b794d 100644 --- a/libtransmission/peer-mgr.c +++ b/libtransmission/peer-mgr.c @@ -29,11 +29,10 @@ #include "platform.h" #include "ptrarray.h" #include "ratecontrol.h" +#include "shared.h" #include "trevent.h" #include "utils.h" -#include "pthread.h" - enum { /* how frequently to change which peers are choked */ @@ -106,8 +105,6 @@ struct tr_peerMgr tr_ptrArray * torrents; /* Torrent */ int connectionCount; tr_ptrArray * handshakes; /* in-process */ - tr_lock * lock; - pthread_t lockThread; }; /** @@ -117,16 +114,12 @@ struct tr_peerMgr static void managerLock( struct tr_peerMgr * manager ) { - assert( manager->lockThread != pthread_self() ); - tr_lockLock( manager->lock ); - manager->lockThread = pthread_self(); + tr_globalLock( manager->handle ); } static void managerUnlock( struct tr_peerMgr * manager ) { - assert( manager->lockThread == pthread_self() ); - manager->lockThread = 0; - tr_lockUnlock( manager->lock ); + tr_globalUnlock( manager->handle ); } static void torrentLock( Torrent * torrent ) @@ -141,10 +134,8 @@ torrentUnlock( Torrent * torrent ) static int torrentIsLocked( const Torrent * t ) { - return ( t != NULL ) - && ( t->manager != NULL ) - && ( t->manager->lockThread != 0 ) - && ( t->manager->lockThread == pthread_self( ) ); + return ( t != NULL ) + && ( tr_globalIsLocked( t->manager->handle ) ); } /** @@ -435,7 +426,6 @@ tr_peerMgrNew( tr_handle * handle ) m->handle = handle; m->torrents = tr_ptrArrayNew( ); m->handshakes = tr_ptrArrayNew( ); - m->lock = tr_lockNew( ); return m; } @@ -448,7 +438,6 @@ tr_peerMgrFree( tr_peerMgr * manager ) tr_ptrArrayFree( manager->torrents, (PtrArrayForeachFunc)freeTorrent ); managerUnlock( manager ); - tr_lockFree( manager->lock ); tr_free( manager ); } @@ -482,7 +471,7 @@ struct tr_refill_piece uint32_t piece; uint32_t peerCount; uint32_t fastAllowed; - uint32_t random; + uint8_t random; }; static int @@ -504,7 +493,7 @@ compareRefillPiece (const void * aIn, const void * bIn) return a->fastAllowed < b->fastAllowed ? -1 : 1; /* otherwise go with our random seed */ - return tr_compareUint32( a->random, b->random ); + return tr_compareUint8( a->random, b->random ); } static int @@ -556,7 +545,7 @@ getPreferredPieces( Torrent * t, setme->priority = inf->pieces[piece].priority; setme->peerCount = 0; setme->fastAllowed = 0; - setme->random = tr_rand( UINT32_MAX ); + setme->random = tr_rand( UINT8_MAX ); /* FIXME */ // setme->fastAllowed = tr_bitfieldHas( t->tor->allowedList, i); @@ -819,10 +808,8 @@ msgsCallbackFunc( void * vpeer, void * vevent, void * vt ) tr_peer * peer = vpeer; Torrent * t = (Torrent *) vt; const tr_peermsgs_event * e = (const tr_peermsgs_event *) vevent; - const int needLock = !torrentIsLocked( t ); - if( needLock ) - torrentLock( t ); + torrentLock( t ); switch( e->eventType ) { @@ -861,8 +848,7 @@ msgsCallbackFunc( void * vpeer, void * vevent, void * vt ) assert(0); } - if( needLock ) - torrentUnlock( t ); + torrentUnlock( t ); } static void @@ -964,7 +950,6 @@ initiateHandshake( tr_peerMgr * manager, tr_peerIo * io ) { tr_handshake * handshake; - assert( manager->lockThread!=0 ); assert( io != NULL ); handshake = tr_handshakeNew( io, @@ -1091,14 +1076,12 @@ tr_peerMgrGetPeers( tr_peerMgr * manager, tr_pex ** setme_pex ) { const Torrent * t = getExistingTorrent( (tr_peerMgr*)manager, torrentHash ); - const int isLocked = torrentIsLocked( t ); int i, peerCount; const tr_peer ** peers; tr_pex * pex; tr_pex * walk; - if( !isLocked ) - torrentLock( (Torrent*)t ); + torrentLock( (Torrent*)t ); peers = (const tr_peer **) tr_ptrArrayPeek( t->peers, &peerCount ); pex = walk = tr_new( tr_pex, peerCount ); @@ -1120,8 +1103,7 @@ tr_peerMgrGetPeers( tr_peerMgr * manager, qsort( pex, peerCount, sizeof(tr_pex), tr_pexCompare ); *setme_pex = pex; - if( !isLocked ) - torrentUnlock( (Torrent*)t ); + torrentUnlock( (Torrent*)t ); return peerCount; } diff --git a/libtransmission/platform.c b/libtransmission/platform.c index c532ec98b..616da19c5 100644 --- a/libtransmission/platform.c +++ b/libtransmission/platform.c @@ -56,6 +56,38 @@ **** THREADS ***/ +#ifdef __BEOS__ +typedef thread_id tr_thread_id; +#elif defined(WIN32) +typedef DWORD tr_thread_id; +#else +typedef pthread_t tr_thread_id; +#endif + +static tr_thread_id +tr_getCurrentThread( void ) +{ +#ifdef __BEOS__ + return find_thread( NULL ); +#elif defined(WIN32) + return GetCurrentThreadId(); +#else + return pthread_self( ); +#endif +} + +static int +tr_areThreadsEqual( tr_thread_id a, tr_thread_id b ) +{ +#ifdef __BEOS__ + return a == b; +#elif defined(WIN32) + return a == b; +#else + return pthread_equal( a, b ); +#endif +} + struct tr_thread { void (* func ) ( void * ); @@ -73,6 +105,12 @@ struct tr_thread }; +int +tr_amInThread ( const tr_thread * t ) +{ + return tr_areThreadsEqual( tr_getCurrentThread(), t->thread ); +} + #ifdef WIN32 #define ThreadFuncReturnType unsigned WINAPI #else @@ -122,18 +160,6 @@ tr_threadNew( void (*func)(void *), return t; } - -int -tr_amInThread ( const tr_thread * t ) -{ -#ifdef __BEOS__ - return find_thread(NULL) == t->thread; -#elif defined(WIN32) - return GetCurrentThreadId() == t->thread_id; -#else - return pthread_equal( t->thread, pthread_self( ) ); -#endif -} void tr_threadJoin( tr_thread * t ) @@ -163,12 +189,16 @@ tr_threadJoin( tr_thread * t ) struct tr_lock { + uint32_t depth; #ifdef __BEOS__ sem_id lock; + thread_id lockThread; #elif defined(WIN32) CRITICAL_SECTION lock; + DWORD lockThread; #else pthread_mutex_t lock; + pthread_t lockThread; #endif }; @@ -216,25 +246,48 @@ tr_lockTryLock( tr_lock * l ) /* success on zero! */ void tr_lockLock( tr_lock * l ) { + tr_thread_id currentThread = tr_getCurrentThread( ); + if( l->lockThread == currentThread ) + { + ++l->depth; + } + else + { #ifdef __BEOS__ - acquire_sem( l->lock ); + acquire_sem( l->lock ); #elif defined(WIN32) - EnterCriticalSection( &l->lock ); + EnterCriticalSection( &l->lock ); #else - pthread_mutex_lock( &l->lock ); + pthread_mutex_lock( &l->lock ); #endif + l->lockThread = tr_getCurrentThread( ); + l->depth = 1; + } +} + +int +tr_lockHave( const tr_lock * l ) +{ + return ( l->depth > 0 ) + && ( l->lockThread == tr_getCurrentThread() ); } void tr_lockUnlock( tr_lock * l ) { + assert( tr_lockHave( l ) ); + + if( !--l->depth ) + { + l->lockThread = 0; #ifdef __BEOS__ - release_sem( l->lock ); + release_sem( l->lock ); #elif defined(WIN32) - LeaveCriticalSection( &l->lock ); + LeaveCriticalSection( &l->lock ); #else - pthread_mutex_unlock( &l->lock ); + pthread_mutex_unlock( &l->lock ); #endif + } } /*** diff --git a/libtransmission/platform.h b/libtransmission/platform.h index 93e0b62b7..60bfee2c3 100644 --- a/libtransmission/platform.h +++ b/libtransmission/platform.h @@ -41,6 +41,7 @@ void tr_lockFree ( tr_lock * ); int tr_lockTryLock ( tr_lock * ); void tr_lockLock ( tr_lock * ); void tr_lockUnlock ( tr_lock * ); +int tr_lockHave ( const tr_lock * ); tr_cond * tr_condNew ( void ); void tr_condFree ( tr_cond * ); diff --git a/libtransmission/shared.c b/libtransmission/shared.c index f898bfc52..361a32858 100644 --- a/libtransmission/shared.c +++ b/libtransmission/shared.c @@ -44,7 +44,6 @@ struct tr_shared { tr_handle * h; - tr_lock * lock; tr_timer * pulseTimer; /* Incoming connections */ @@ -75,7 +74,6 @@ tr_shared * tr_sharedInit( tr_handle * h ) tr_shared * s = calloc( 1, sizeof( tr_shared ) ); s->h = h; - s->lock = tr_lockNew( ); s->publicPort = -1; s->bindPort = -1; s->bindSocket = -1; @@ -96,25 +94,11 @@ void tr_sharedClose( tr_shared * s ) tr_timerFree( &s->pulseTimer ); tr_netClose( s->bindSocket ); - tr_lockFree( s->lock ); tr_natpmpClose( s->natpmp ); tr_upnpClose( s->upnp ); free( s ); } -/** -*** -**/ - -void tr_sharedLock( tr_shared * s ) -{ - tr_lockLock( s->lock ); -} -void tr_sharedUnlock( tr_shared * s ) -{ - tr_lockUnlock( s->lock ); -} - /*********************************************************************** * tr_sharedSetPort *********************************************************************** @@ -128,11 +112,11 @@ void tr_sharedSetPort( tr_shared * s, int port ) return; #endif - tr_sharedLock( s ); + tr_globalLock( s->h ); if( port == s->bindPort ) { - tr_sharedUnlock( s ); + tr_globalUnlock( s->h ); return; } s->bindPort = port; @@ -165,7 +149,7 @@ void tr_sharedSetPort( tr_shared * s, int port ) tr_upnpForwardPort( s->upnp, port ); } - tr_sharedUnlock( s ); + tr_globalUnlock( s->h ); } int @@ -237,7 +221,7 @@ SharedLoop( void * vs ) int newPort; tr_shared * s = vs; - tr_sharedLock( s ); + tr_globalLock( s->h ); /* NAT-PMP and UPnP pulses */ newPort = -1; @@ -249,7 +233,7 @@ SharedLoop( void * vs ) /* Handle incoming connections */ AcceptPeers( s ); - tr_sharedUnlock( s ); + tr_globalUnlock( s->h ); return TRUE; } diff --git a/libtransmission/shared.h b/libtransmission/shared.h index dfe2673b8..bd73d8b09 100644 --- a/libtransmission/shared.h +++ b/libtransmission/shared.h @@ -38,15 +38,6 @@ typedef struct tr_shared tr_shared; tr_shared * tr_sharedInit ( tr_handle * ); void tr_sharedClose ( tr_shared * ); -/*********************************************************************** - * tr_sharedLock, tr_sharedUnlock - *********************************************************************** - * Gets / releases exclusive access to ressources used by the shared - * thread - **********************************************************************/ -void tr_sharedLock ( tr_shared * ); -void tr_sharedUnlock ( tr_shared * ); - /*********************************************************************** * tr_sharedSetPort *********************************************************************** diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index 85b13f5de..78dff30f2 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -90,13 +90,13 @@ tr_torrentFindFromObfuscatedHash( tr_handle * handle, void tr_torrentLock( const tr_torrent * tor ) { - tr_lockLock ( (tr_lock*)tor->lock ); + tr_globalLock( tor->handle ); } void tr_torrentUnlock( const tr_torrent * tor ) { - tr_lockUnlock ( (tr_lock*)tor->lock ); + tr_globalUnlock( tor->handle ); } /*** @@ -299,7 +299,7 @@ torrentRealInit( tr_handle * h, tor->info.flags |= flags; - tr_sharedLock( h->shared ); + tr_globalLock( h ); tor->destination = tr_strdup( destination ); @@ -355,8 +355,6 @@ torrentRealInit( tr_handle * h, tr_torrentInitFilePieces( tor ); - tor->lock = tr_lockNew( ); - tor->upload = tr_rcInit(); tor->download = tr_rcInit(); tor->swarmspeed = tr_rcInit(); @@ -364,8 +362,6 @@ torrentRealInit( tr_handle * h, tr_sha1( tor->obfuscatedHash, "req2", 4, info->hash, SHA_DIGEST_LENGTH, NULL ); - - tr_sharedUnlock( h->shared ); tr_peerMgrAddTorrent( h->peerMgr, tor ); @@ -407,11 +403,11 @@ torrentRealInit( tr_handle * h, tor->tracker = tr_trackerNew( tor ); tor->trackerSubscription = tr_trackerSubscribe( tor->tracker, onTrackerResponse, tor ); - tr_sharedLock( h->shared ); tor->next = h->torrentList; h->torrentList = tor; h->torrentCount++; - tr_sharedUnlock( h->shared ); + + tr_globalUnlock( h ); tr_ioRecheckAdd( tor, recheckDoneCB, tor->runStatus ); } @@ -999,11 +995,10 @@ tr_torrentFree( tr_torrent * tor ) assert( tor != NULL ); assert( tor->runStatus == TR_RUN_STOPPED ); - tr_sharedLock( h->shared ); + tr_globalLock( h ); tr_peerMgrRemoveTorrent( h->peerMgr, tor->info.hash ); - tr_lockFree( tor->lock ); tr_cpClose( tor->completion ); tr_rcClose( tor->upload ); @@ -1034,7 +1029,7 @@ tr_torrentFree( tr_torrent * tor ) tr_metainfoFree( inf ); tr_free( tor ); - tr_sharedUnlock( h->shared ); + tr_globalUnlock( h ); } static int diff --git a/libtransmission/transmission.c b/libtransmission/transmission.c index 0685869d8..4689dd2a7 100644 --- a/libtransmission/transmission.c +++ b/libtransmission/transmission.c @@ -121,6 +121,8 @@ tr_handle * tr_init( const char * tag ) if( !h ) return NULL; + h->lock = tr_lockNew( ); + h->encryptionMode = TR_ENCRYPTION_PREFERRED; tr_netInit(); /* must go before tr_eventInit */ @@ -153,6 +155,28 @@ tr_handle * tr_init( const char * tag ) return h; } +/*** +**** +***/ + +void +tr_globalLock( struct tr_handle * handle ) +{ + tr_lockLock( handle->lock ); +} + +void +tr_globalUnlock( struct tr_handle * handle ) +{ + tr_lockUnlock( handle->lock ); +} + +int +tr_globalIsLocked( const struct tr_handle * handle ) +{ + return tr_lockHave( handle->lock ); +} + /*********************************************************************** * tr_setBindPort *********************************************************************** @@ -173,9 +197,9 @@ tr_getPublicPort( const tr_handle * h ) void tr_natTraversalEnable( tr_handle * h, int enable ) { - tr_sharedLock( h->shared ); + tr_globalLock( h ); tr_sharedTraversalEnable( h->shared, enable ); - tr_sharedUnlock( h->shared ); + tr_globalUnlock( h ); } tr_handle_status * tr_handleStatus( tr_handle * h ) @@ -185,12 +209,12 @@ tr_handle_status * tr_handleStatus( tr_handle * h ) h->statCur = ( h->statCur + 1 ) % 2; s = &h->stats[h->statCur]; - tr_sharedLock( h->shared ); + tr_globalLock( h ); s->natTraversalStatus = tr_sharedTraversalStatus( h->shared ); s->publicPort = tr_sharedGetPublicPort( h->shared ); - tr_sharedUnlock( h->shared ); + tr_globalUnlock( h ); return s; } @@ -241,7 +265,7 @@ tr_torrentRates( tr_handle * h, float * dl, float * ul ) *dl = 0.0; *ul = 0.0; - tr_sharedLock( h->shared ); + tr_globalLock( h ); for( tor = h->torrentList; tor; tor = tor->next ) { tr_torrentLock( tor ); @@ -250,7 +274,7 @@ tr_torrentRates( tr_handle * h, float * dl, float * ul ) *ul += tr_rcRate( tor->upload ); tr_torrentUnlock( tor ); } - tr_sharedUnlock( h->shared ); + tr_globalUnlock( h ); } int @@ -300,6 +324,7 @@ tr_close( tr_handle * h ) tr_wait( 200 ); } + tr_lockFree( h->lock ); free( h->tag ); free( h ); fprintf( stderr, "tr_close() completed.\n" );