Changeset b3c8d478e9091fe55a2513eb8e416162da3bb5e4
- 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
| r82921f3 |
rb3c8d47 |
|
| 188 | 188 | |
|---|
| 189 | 189 | /* Objects management */ |
|---|
| | 190 | vlc_spinlock_t ref_spin; |
|---|
| 190 | 191 | unsigned i_refcount; |
|---|
| 191 | 192 | vlc_destructor_t pf_destructor; |
|---|
| r5421e9c |
rb3c8d47 |
|
| 90 | 90 | |
|---|
| 91 | 91 | static void vlc_object_destroy( vlc_object_t *p_this ); |
|---|
| 92 | | static void vlc_object_yield_locked( vlc_object_t *p_this ); |
|---|
| 93 | 92 | |
|---|
| 94 | 93 | /***************************************************************************** |
|---|
| … | … | |
| 170 | 169 | } |
|---|
| 171 | 170 | |
|---|
| | 171 | vlc_spin_init( &p_priv->ref_spin ); |
|---|
| 172 | 172 | p_priv->i_refcount = 1; |
|---|
| 173 | 173 | p_priv->pf_destructor = kVLCDestructor; |
|---|
| … | … | |
| 188 | 188 | vlc_mutex_lock( &structure_lock ); |
|---|
| 189 | 189 | p_new->i_object_id = p_libvlc_global->i_counter++; |
|---|
| 190 | | |
|---|
| 191 | 190 | /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's |
|---|
| 192 | 191 | * useless to try and recover anything if pp_objects gets smashed. */ |
|---|
| … | … | |
| 425 | 424 | #endif |
|---|
| 426 | 425 | |
|---|
| | 426 | vlc_spin_destroy( &p_priv->ref_spin ); |
|---|
| 427 | 427 | vlc_mutex_destroy( &p_this->object_lock ); |
|---|
| 428 | 428 | vlc_cond_destroy( &p_this->object_wait ); |
|---|
| … | … | |
| 714 | 714 | if( pp_objects[i_middle+1]->i_object_id == i_id ) |
|---|
| 715 | 715 | { |
|---|
| 716 | | vlc_object_yield_locked( pp_objects[i_middle+1] ); |
|---|
| | 716 | vlc_object_yield( pp_objects[i_middle+1] ); |
|---|
| 717 | 717 | obj = pp_objects[i_middle+1]; |
|---|
| 718 | 718 | } |
|---|
| … | … | |
| 722 | 722 | else |
|---|
| 723 | 723 | { |
|---|
| 724 | | vlc_object_yield_locked( pp_objects[i_middle] ); |
|---|
| | 724 | vlc_object_yield( pp_objects[i_middle] ); |
|---|
| 725 | 725 | vlc_mutex_unlock( &structure_lock ); |
|---|
| 726 | 726 | return pp_objects[i_middle]; |
|---|
| … | … | |
| 750 | 750 | if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type ) |
|---|
| 751 | 751 | { |
|---|
| 752 | | vlc_object_yield_locked( p_this ); |
|---|
| | 752 | vlc_object_yield( p_this ); |
|---|
| 753 | 753 | vlc_mutex_unlock( &structure_lock ); |
|---|
| 754 | 754 | return p_this; |
|---|
| … | … | |
| 798 | 798 | vlc_mutex_lock( &structure_lock ); |
|---|
| 799 | 799 | |
|---|
| 800 | | /* Avoid obvious freed object uses */ |
|---|
| 801 | | assert( vlc_internals( p_this )->i_refcount > 0 ); |
|---|
| 802 | | |
|---|
| 803 | 800 | /* If have the requested name ourselves, don't look further */ |
|---|
| 804 | 801 | if( !(i_mode & FIND_STRICT) |
|---|
| … | … | |
| 806 | 803 | && !strcmp( p_this->psz_object_name, psz_name ) ) |
|---|
| 807 | 804 | { |
|---|
| 808 | | vlc_object_yield_locked( p_this ); |
|---|
| | 805 | vlc_object_yield( p_this ); |
|---|
| 809 | 806 | vlc_mutex_unlock( &structure_lock ); |
|---|
| 810 | 807 | return p_this; |
|---|
| … | … | |
| 842 | 839 | |
|---|
| 843 | 840 | /** |
|---|
| 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 | */ |
|---|
| | 843 | void __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 ); |
|---|
| 853 | 848 | /* Avoid obvious freed object uses */ |
|---|
| 854 | | assert( vlc_internals( p_this )->i_refcount > 0 ); |
|---|
| 855 | | |
|---|
| | 849 | assert( internals->i_refcount > 0 ); |
|---|
| 856 | 850 | /* 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 | } |
|---|
| 868 | 854 | |
|---|
| 869 | 855 | /***************************************************************************** |
|---|
| … | … | |
| 873 | 859 | void __vlc_object_release( vlc_object_t *p_this ) |
|---|
| 874 | 860 | { |
|---|
| | 861 | vlc_object_internals_t *internals = vlc_internals( p_this ); |
|---|
| 875 | 862 | bool b_should_destroy; |
|---|
| 876 | 863 | |
|---|
| | 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 */ |
|---|
| 877 | 879 | 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 ); |
|---|
| 882 | 885 | |
|---|
| 883 | 886 | if( b_should_destroy ) |
|---|
| 884 | 887 | { |
|---|
| 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. */ |
|---|
| 887 | 890 | libvlc_global_data_t *p_libvlc_global = vlc_global(); |
|---|
| 888 | 891 | int i_index; |
|---|
| 889 | 892 | |
|---|
| 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. */ |
|---|
| 892 | 893 | i_index = FindIndex( p_this, p_libvlc_global->pp_objects, |
|---|
| 893 | 894 | p_libvlc_global->i_objects ); |
|---|
| … | … | |
| 914 | 915 | |
|---|
| 915 | 916 | vlc_mutex_lock( &structure_lock ); |
|---|
| 916 | | |
|---|
| 917 | | /* Avoid obvious freed object uses */ |
|---|
| 918 | | assert( vlc_internals( p_this )->i_refcount > 0 ); |
|---|
| 919 | 917 | |
|---|
| 920 | 918 | /* Attach the parent to its child */ |
|---|
| … | … | |
| 1300 | 1298 | if( p_tmp->i_object_type == i_type ) |
|---|
| 1301 | 1299 | { |
|---|
| 1302 | | vlc_object_yield_locked( p_tmp ); |
|---|
| | 1300 | vlc_object_yield( p_tmp ); |
|---|
| 1303 | 1301 | return p_tmp; |
|---|
| 1304 | 1302 | } |
|---|
| … | … | |
| 1316 | 1314 | if( p_tmp->i_object_type == i_type ) |
|---|
| 1317 | 1315 | { |
|---|
| 1318 | | vlc_object_yield_locked( p_tmp ); |
|---|
| | 1316 | vlc_object_yield( p_tmp ); |
|---|
| 1319 | 1317 | return p_tmp; |
|---|
| 1320 | 1318 | } |
|---|
| … | … | |
| 1354 | 1352 | && !strcmp( p_tmp->psz_object_name, psz_name ) ) |
|---|
| 1355 | 1353 | { |
|---|
| 1356 | | vlc_object_yield_locked( p_tmp ); |
|---|
| | 1354 | vlc_object_yield( p_tmp ); |
|---|
| 1357 | 1355 | return p_tmp; |
|---|
| 1358 | 1356 | } |
|---|
| … | … | |
| 1371 | 1369 | && !strcmp( p_tmp->psz_object_name, psz_name ) ) |
|---|
| 1372 | 1370 | { |
|---|
| 1373 | | vlc_object_yield_locked( p_tmp ); |
|---|
| | 1371 | vlc_object_yield( p_tmp ); |
|---|
| 1374 | 1372 | return p_tmp; |
|---|
| 1375 | 1373 | } |
|---|
| … | … | |
| 1572 | 1570 | } |
|---|
| 1573 | 1571 | |
|---|
| 1574 | | vlc_object_yield_locked( p_object ); |
|---|
| | 1572 | vlc_object_yield( p_object ); |
|---|
| 1575 | 1573 | |
|---|
| 1576 | 1574 | p_list->p_values[i_index].p_object = p_object; |
|---|
| … | … | |
| 1594 | 1592 | } |
|---|
| 1595 | 1593 | |
|---|
| 1596 | | vlc_object_yield_locked( p_object ); |
|---|
| | 1594 | vlc_object_yield( p_object ); |
|---|
| 1597 | 1595 | |
|---|
| 1598 | 1596 | p_list->p_values[p_list->i_count].p_object = p_object; |
|---|