Changeset 4045


Ignore:
Timestamp:
Dec 3, 2007, 4:26:02 PM (14 years ago)
Author:
charles
Message:

backport the [4040...4044] mutex fix to 0.9x

Location:
branches/0.9x/libtransmission
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/0.9x/libtransmission/fdlimit.c

    r3917 r4045  
    110110    int                  normalMax;
    111111    tr_lock            * lock;
    112     tr_cond            * cond;
    113112    struct tr_openfile   open[TR_MAX_OPEN_FILES];
    114113};
     
    181180    o->fd = -1;
    182181    o->isCheckedOut = 0;
    183     tr_condSignal( gFd->cond );
    184182}
    185183
     
    193191tr_fdFileCheckout( const char * filename, int write )
    194192{
    195     int i, winner;
     193    int i, winner = -1;
    196194    struct tr_openfile * o;
    197195
     
    216214        if( fileIsCheckedOut( o ) ) {
    217215            dbgmsg( "found it!  it's open, but checked out.  waiting..." );
    218             tr_condWait( gFd->cond, gFd->lock );
     216            tr_lockUnlock( gFd->lock );
     217            tr_wait( 200 );
     218            tr_lockLock( gFd->lock );
    219219            i = -1; /* reloop */
    220220            continue;
     
    229229        dbgmsg( "found it!  it's ready for use!" );
    230230        winner = i;
    231         goto done;
    232     }
    233 
     231        break;
     232    }
    234233
    235234    dbgmsg( "it's not already open.  looking for an open slot or an old file." );
    236     for( ;; )
     235    while( winner < 0 )
    237236    {
    238237        uint64_t date = tr_date( ) + 1;
    239         winner = -1;
    240 
     238
     239        /* look for the file that's been open longest */
    241240        for( i=0; i<TR_MAX_OPEN_FILES; ++i )
    242241        {
     
    246245                winner = i;
    247246                dbgmsg( "found an empty slot in %d", winner );
    248                 goto done;
     247                break;
    249248            }
    250249
     
    258257            dbgmsg( "closing file '%s', slot #%d", gFd->open[winner].filename, winner );
    259258            TrCloseFile( winner );
    260             goto done;
    261         }
    262 
    263         /* All used! Wait a bit and try again */
    264         dbgmsg( "everything's full!  waiting for someone else to finish something" );
    265         tr_condWait( gFd->cond, gFd->lock );
    266     }
    267 
    268 done:
    269 
     259        } else {
     260            dbgmsg( "everything's full!  waiting for someone else to finish something" );
     261            tr_lockUnlock( gFd->lock );
     262            tr_wait( 200 );
     263            tr_lockLock( gFd->lock );
     264        }
     265    }
     266
     267    assert( winner >= 0 );
    270268    o = &gFd->open[winner];
    271269    if( !fileIsOpen( o ) )
     
    310308    }
    311309   
    312     tr_condSignal( gFd->cond );
    313310    tr_lockUnlock( gFd->lock );
    314311}
     
    336333    }
    337334   
    338     tr_condSignal( gFd->cond );
    339335    tr_lockUnlock( gFd->lock );
    340336}
     
    463459    gFd = tr_new0( struct tr_fd_s, 1 );
    464460    gFd->lock = tr_lockNew( );
    465     gFd->cond = tr_condNew( );
    466461
    467462    /* count the max number of sockets we can use */
     
    491486
    492487    tr_lockFree( gFd->lock );
    493     tr_condFree( gFd->cond );
    494488
    495489    tr_list_free( &reservedSockets, NULL );
  • branches/0.9x/libtransmission/platform.c

    r3897 r4045  
    3939  #include <shlobj.h> /* for CSIDL_APPDATA, CSIDL_PROFILE */
    4040#else
     41  #define _XOPEN_SOURCE 500 /* needed for recursive locks. */
     42  #ifndef __USE_UNIX98
     43  #define __USE_UNIX98 /* some older Linuxes need it spelt out for them */
     44  #endif
    4145  #include <pthread.h>
    4246#endif
     
    190194struct tr_lock
    191195{
    192     uint32_t depth;
     196    int depth;
    193197#ifdef __BEOS__
    194198    sem_id lock;
     
    211215    l->lock = create_sem( 1, "" );
    212216#elif defined(WIN32)
    213     InitializeCriticalSection( &l->lock );
    214 #else
    215     pthread_mutex_init( &l->lock, NULL );
     217    InitializeCriticalSection( &l->lock ); /* critical sections support recursion */
     218#else
     219    pthread_mutexattr_t attr;
     220    pthread_mutexattr_init( &attr );
     221    pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
     222    pthread_mutex_init( &l->lock, &attr );
    216223#endif
    217224
     
    235242tr_lockLock( tr_lock * l )
    236243{
    237     const tr_thread_id currentThread = tr_getCurrentThread( );
    238 
    239     if( l->lockThread == currentThread )
    240     {
    241         ++l->depth;
    242     }
    243     else
    244     {
    245 #ifdef __BEOS__
    246         acquire_sem( l->lock );
    247 #elif defined(WIN32)
    248         EnterCriticalSection( &l->lock );
    249 #else
    250         pthread_mutex_lock( &l->lock );
    251 #endif
    252         l->lockThread = currentThread;
    253         l->depth = 1;
    254     }
     244#ifdef __BEOS__
     245    acquire_sem( l->lock );
     246#elif defined(WIN32)
     247    EnterCriticalSection( &l->lock );
     248#else
     249    pthread_mutex_lock( &l->lock );
     250#endif
     251    assert( l->depth >= 0 );
     252    if( l->depth )
     253        assert( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread() ) );
     254    l->lockThread = tr_getCurrentThread( );
     255    ++l->depth;
    255256}
    256257
     
    259260{
    260261    return ( l->depth > 0 )
    261         && ( l->lockThread == tr_getCurrentThread() );
     262        && ( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread() ) );
    262263}
    263264
     
    265266tr_lockUnlock( tr_lock * l )
    266267{
    267     assert( tr_lockHave( l ) );
    268 
    269     if( !--l->depth )
    270     {
    271         l->lockThread = 0;
    272 #ifdef __BEOS__
    273         release_sem( l->lock );
    274 #elif defined(WIN32)
    275         LeaveCriticalSection( &l->lock );
    276 #else
    277         pthread_mutex_unlock( &l->lock );
    278 #endif
    279     }
    280 }
    281 
    282 /***
    283 ****  COND
    284 ***/
    285 
    286 struct tr_cond
    287 {
    288 #ifdef __BEOS__
    289     sem_id sem;
    290     thread_id threads[BEOS_MAX_THREADS];
    291     int start, end;
    292 #elif defined(WIN32)
    293     tr_list * events;
    294     tr_lock * lock;
    295 #else
    296     pthread_cond_t cond;
    297 #endif
    298 };
    299 
    300 #ifdef WIN32
    301 static DWORD getContEventTLS( void )
    302 {
    303     static int inited = FALSE;
    304     static DWORD event_tls;
    305     if( !inited ) {
    306         inited = TRUE;
    307         event_tls = TlsAlloc();
    308     }
    309     return event_tls;
    310 }
    311 #endif
    312 
    313 tr_cond*
    314 tr_condNew( void )
    315 {
    316     tr_cond * c = tr_new0( tr_cond, 1 );
    317 #ifdef __BEOS__
    318     c->sem = create_sem( 1, "" );
    319     c->start = 0;
    320     c->end = 0;
    321 #elif defined(WIN32)
    322     c->events = NULL;
    323     c->lock = tr_lockNew( );
    324 #else
    325     pthread_cond_init( &c->cond, NULL );
    326 #endif
    327     return c;
    328 }
    329 
    330 void
    331 tr_condWait( tr_cond * c, tr_lock * l )
    332 {
    333 #ifdef __BEOS__
    334 
    335     /* Keep track of that thread */
    336     acquire_sem( c->sem );
    337     c->threads[c->end] = find_thread( NULL );
    338     c->end = ( c->end + 1 ) % BEOS_MAX_THREADS;
    339     assert( c->end != c->start ); /* We hit BEOS_MAX_THREADS, arggh */
    340     release_sem( c->sem );
    341 
     268    assert( l->depth > 0 );
     269    assert( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread() ));
     270
     271    --l->depth;
     272    assert( l->depth >= 0 );
     273#ifdef __BEOS__
    342274    release_sem( l->lock );
    343     suspend_thread( find_thread( NULL ) ); /* Wait for signal */
    344     acquire_sem( l->lock );
    345 
    346 #elif defined(WIN32)
    347 
    348     /* get this thread's cond event */
    349     DWORD key = getContEventTLS ( );
    350     HANDLE hEvent = TlsGetValue( key );
    351     if( !hEvent ) {
    352         hEvent = CreateEvent( 0, FALSE, FALSE, 0 );
    353         TlsSetValue( key, hEvent );
    354     }
    355 
    356     /* add it to the list of events waiting to be signaled */
    357     tr_lockLock( c->lock );
    358     tr_list_append( &c->events, hEvent );
    359     tr_lockUnlock( c->lock );
    360 
    361     /* now wait for it to be signaled */
    362     tr_lockUnlock( l );
    363     WaitForSingleObject( hEvent, INFINITE );
    364     tr_lockLock( l );
    365 
    366     /* remove it from the list of events waiting to be signaled */
    367     tr_lockLock( c->lock );
    368     tr_list_remove_data( &c->events, hEvent );
    369     tr_lockUnlock( c->lock );
    370 
    371 #else
    372 
    373     pthread_cond_wait( &c->cond, &l->lock );
    374 
    375 #endif
    376 }
    377 
    378 #ifdef __BEOS__
    379 static int condTrySignal( tr_cond * c )
    380 {
    381     if( c->start == c->end )
    382         return 1;
    383 
    384     for( ;; )
    385     {
    386         thread_info info;
    387         get_thread_info( c->threads[c->start], &info );
    388         if( info.state == B_THREAD_SUSPENDED )
    389         {
    390             resume_thread( c->threads[c->start] );
    391             c->start = ( c->start + 1 ) % BEOS_MAX_THREADS;
    392             break;
    393         }
    394         /* The thread is not suspended yet, which can happen since
    395          * tr_condWait does not atomically suspends after releasing
    396          * the semaphore. Wait a bit and try again. */
    397         snooze( 5000 );
    398     }
    399     return 0;
    400 }
    401 #endif
    402 void
    403 tr_condSignal( tr_cond * c )
    404 {
    405 #ifdef __BEOS__
    406 
    407     acquire_sem( c->sem );
    408     condTrySignal( c );
    409     release_sem( c->sem );
    410 
    411 #elif defined(WIN32)
    412 
    413     tr_lockLock( c->lock );
    414     if( c->events != NULL )
    415         SetEvent( (HANDLE)c->events->data );
    416     tr_lockUnlock( c->lock );
    417 
    418 #else
    419 
    420     pthread_cond_signal( &c->cond );
    421 
    422 #endif
    423 }
    424 
    425 void
    426 tr_condBroadcast( tr_cond * c )
    427 {
    428 #ifdef __BEOS__
    429 
    430     acquire_sem( c->sem );
    431     while( !condTrySignal( c ) );
    432     release_sem( c->sem );
    433 
    434 #elif defined(WIN32)
    435 
    436     tr_list * l;
    437     tr_lockLock( c->lock );
    438     for( l=c->events; l!=NULL; l=l->next )
    439         SetEvent( (HANDLE)l->data );
    440     tr_lockUnlock( c->lock );
    441 
    442 #else
    443 
    444     pthread_cond_broadcast( &c->cond );
    445 
    446 #endif
    447 }
    448 
    449 void
    450 tr_condFree( tr_cond * c )
    451 {
    452 #ifdef __BEOS__
    453     delete_sem( c->sem );
    454 #elif defined(WIN32)
    455     tr_list_free( &c->events, NULL );
    456     tr_lockFree( c->lock );
    457 #else
    458     pthread_cond_destroy( &c->cond );
    459 #endif
    460     tr_free( c );
    461 }
    462 
     275#elif defined(WIN32)
     276    LeaveCriticalSection( &l->lock );
     277#else
     278    pthread_mutex_unlock( &l->lock );
     279#endif
     280}
    463281
    464282/***
     
    852670    }
    853671
    854     bzero( &snl, sizeof( snl ) );
     672    memset( &snl, 0, sizeof(snl) );
    855673    snl.nl_family = AF_NETLINK;
    856674
    857     bzero( &req, sizeof( req ) );
     675    memset( &req, 0, sizeof(req) );
    858676    req.nlh.nlmsg_len = NLMSG_LENGTH( sizeof( req.rtg ) );
    859677    req.nlh.nlmsg_type = RTM_GETROUTE;
     
    893711    for( ;; )
    894712    {
    895         bzero( &snl, sizeof( snl ) );
    896713        slen = sizeof( snl );
     714        memset( &snl, 0, slen );
    897715        res = recvfrom( fd, buf, len, 0, (struct sockaddr *) &snl, &slen );
    898716        if( 0 > res )
  • branches/0.9x/libtransmission/platform.h

    r3897 r4045  
    2626
    2727typedef struct tr_lock   tr_lock;
    28 typedef struct tr_cond   tr_cond;
    2928typedef struct tr_thread tr_thread;
    3029
     
    4342int          tr_lockHave       ( const tr_lock * );
    4443
    45 tr_cond *    tr_condNew       ( void );
    46 void         tr_condFree      ( tr_cond * );
    47 void         tr_condSignal    ( tr_cond * );
    48 void         tr_condBroadcast ( tr_cond * );
    49 void         tr_condWait      ( tr_cond *, tr_lock * );
    50 
    5144struct in_addr; /* forward declaration to calm gcc down */
    5245int
Note: See TracChangeset for help on using the changeset viewer.