Changeset b3c8d478e9091fe55a2513eb8e416162da3bb5e4

Show
Ignore:
Timestamp:
05/07/08 22:13:01 (2 months ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1210191181 +0300
git-parent:

[5421e9cd54ac4384583f13daf9323304e532c257]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1210191172 +0300
Message:

Use a per-object spin around the reference count.

So we don't contend for the global structure lock all the time.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/libvlc.h

    r82921f3 rb3c8d47  
    188188 
    189189    /* Objects management */ 
     190    vlc_spinlock_t   ref_spin; 
    190191    unsigned         i_refcount; 
    191192    vlc_destructor_t pf_destructor; 
  • src/misc/objects.c

    r5421e9c rb3c8d47  
    9090 
    9191static void vlc_object_destroy( vlc_object_t *p_this ); 
    92 static void vlc_object_yield_locked( vlc_object_t *p_this ); 
    9392 
    9493/***************************************************************************** 
     
    170169    } 
    171170 
     171    vlc_spin_init( &p_priv->ref_spin ); 
    172172    p_priv->i_refcount = 1; 
    173173    p_priv->pf_destructor = kVLCDestructor; 
     
    188188    vlc_mutex_lock( &structure_lock ); 
    189189    p_new->i_object_id = p_libvlc_global->i_counter++; 
    190  
    191190    /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's 
    192191     * useless to try and recover anything if pp_objects gets smashed. */ 
     
    425424#endif 
    426425 
     426    vlc_spin_destroy( &p_priv->ref_spin ); 
    427427    vlc_mutex_destroy( &p_this->object_lock ); 
    428428    vlc_cond_destroy( &p_this->object_wait ); 
     
    714714                if( pp_objects[i_middle+1]->i_object_id == i_id ) 
    715715                { 
    716                     vlc_object_yield_locked( pp_objects[i_middle+1] ); 
     716                    vlc_object_yield( pp_objects[i_middle+1] ); 
    717717                    obj = pp_objects[i_middle+1]; 
    718718                } 
     
    722722        else 
    723723        { 
    724             vlc_object_yield_locked( pp_objects[i_middle] ); 
     724            vlc_object_yield( pp_objects[i_middle] ); 
    725725            vlc_mutex_unlock( &structure_lock ); 
    726726            return pp_objects[i_middle]; 
     
    750750    if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type ) 
    751751    { 
    752         vlc_object_yield_locked( p_this ); 
     752        vlc_object_yield( p_this ); 
    753753        vlc_mutex_unlock( &structure_lock ); 
    754754        return p_this; 
     
    798798    vlc_mutex_lock( &structure_lock ); 
    799799 
    800     /* Avoid obvious freed object uses */ 
    801     assert( vlc_internals( p_this )->i_refcount > 0 ); 
    802  
    803800    /* If have the requested name ourselves, don't look further */ 
    804801    if( !(i_mode & FIND_STRICT) 
     
    806803        && !strcmp( p_this->psz_object_name, psz_name ) ) 
    807804    { 
    808         vlc_object_yield_locked( p_this ); 
     805        vlc_object_yield( p_this ); 
    809806        vlc_mutex_unlock( &structure_lock ); 
    810807        return p_this; 
     
    842839 
    843840/** 
    844  **************************************************************************** 
    845  * increment an object refcount 
    846  *****************************************************************************/ 
    847  
    848 /* When the structure_lock is locked */ 
    849 static void vlc_object_yield_locked( vlc_object_t *p_this ) 
    850 
    851     vlc_assert_locked (&structure_lock); 
    852  
     841 * Increment an object reference counter. 
     842 */ 
     843void __vlc_object_yield( vlc_object_t *p_this ) 
     844
     845    vlc_object_internals_t *internals = vlc_internals( p_this ); 
     846 
     847    vlc_spin_lock( &internals->ref_spin ); 
    853848    /* Avoid obvious freed object uses */ 
    854     assert( vlc_internals( p_this )->i_refcount > 0 ); 
    855  
     849    assert( internals->i_refcount > 0 ); 
    856850    /* Increment the counter */ 
    857     vlc_internals( p_this )->i_refcount++; 
    858 
    859  
    860 /* Public function */ 
    861 void __vlc_object_yield( vlc_object_t *p_this ) 
    862 
    863     vlc_mutex_lock( &structure_lock ); 
    864     vlc_object_yield_locked( p_this ); 
    865     vlc_mutex_unlock( &structure_lock ); 
    866 
    867  
     851    internals->i_refcount++; 
     852    vlc_spin_unlock( &internals->ref_spin ); 
     853
    868854 
    869855/***************************************************************************** 
     
    873859void __vlc_object_release( vlc_object_t *p_this ) 
    874860{ 
     861    vlc_object_internals_t *internals = vlc_internals( p_this ); 
    875862    bool b_should_destroy; 
    876863 
     864    vlc_spin_lock( &internals->ref_spin ); 
     865    assert( internals->i_refcount > 0 ); 
     866 
     867    if( internals->i_refcount > 1 ) 
     868    { 
     869        /* Fast path */ 
     870        /* There are still other references to the object */ 
     871        internals->i_refcount--; 
     872        vlc_spin_unlock( &internals->ref_spin ); 
     873        return; 
     874    } 
     875    vlc_spin_unlock( &internals->ref_spin ); 
     876 
     877    /* Slow path */ 
     878    /* Remember that we cannot hold the spin while waiting on the mutex */ 
    877879    vlc_mutex_lock( &structure_lock ); 
    878  
    879     assert( vlc_internals( p_this )->i_refcount > 0 ); 
    880     vlc_internals( p_this )->i_refcount--; 
    881     b_should_destroy = (vlc_internals( p_this )->i_refcount == 0); 
     880    /* Take the spin again. Note that another thread may have yielded the 
     881     * object in the (very short) mean time. */ 
     882    vlc_spin_lock( &internals->ref_spin ); 
     883    b_should_destroy = --internals->i_refcount == 0; 
     884    vlc_spin_unlock( &internals->ref_spin ); 
    882885 
    883886    if( b_should_destroy ) 
    884887    { 
    885         /* Make sure this object can't be obtained via vlc_find_object now that 
    886          * it is freed */ 
     888        /* Remove the object from the table so that it cannot be returned from 
     889         * vlc_object_find() and friends. */ 
    887890        libvlc_global_data_t *p_libvlc_global = vlc_global(); 
    888891        int i_index; 
    889892 
    890         /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's 
    891          * useless to try and recover anything if pp_objects gets smashed. */ 
    892893        i_index = FindIndex( p_this, p_libvlc_global->pp_objects, 
    893894                             p_libvlc_global->i_objects ); 
     
    914915 
    915916    vlc_mutex_lock( &structure_lock ); 
    916  
    917     /* Avoid obvious freed object uses */ 
    918     assert( vlc_internals( p_this )->i_refcount > 0 ); 
    919917 
    920918    /* Attach the parent to its child */ 
     
    13001298            if( p_tmp->i_object_type == i_type ) 
    13011299            { 
    1302                 vlc_object_yield_locked( p_tmp ); 
     1300                vlc_object_yield( p_tmp ); 
    13031301                return p_tmp; 
    13041302            } 
     
    13161314            if( p_tmp->i_object_type == i_type ) 
    13171315            { 
    1318                 vlc_object_yield_locked( p_tmp ); 
     1316                vlc_object_yield( p_tmp ); 
    13191317                return p_tmp; 
    13201318            } 
     
    13541352                && !strcmp( p_tmp->psz_object_name, psz_name ) ) 
    13551353            { 
    1356                 vlc_object_yield_locked( p_tmp ); 
     1354                vlc_object_yield( p_tmp ); 
    13571355                return p_tmp; 
    13581356            } 
     
    13711369                && !strcmp( p_tmp->psz_object_name, psz_name ) ) 
    13721370            { 
    1373                 vlc_object_yield_locked( p_tmp ); 
     1371                vlc_object_yield( p_tmp ); 
    13741372                return p_tmp; 
    13751373            } 
     
    15721570    } 
    15731571 
    1574     vlc_object_yield_locked( p_object ); 
     1572    vlc_object_yield( p_object ); 
    15751573 
    15761574    p_list->p_values[i_index].p_object = p_object; 
     
    15941592    } 
    15951593 
    1596     vlc_object_yield_locked( p_object ); 
     1594    vlc_object_yield( p_object ); 
    15971595 
    15981596    p_list->p_values[p_list->i_count].p_object = p_object;