Changeset 6727 in vbox
- Timestamp:
- Feb 1, 2008 5:06:53 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/linux/sems-linux.cpp
r5999 r6727 85 85 86 86 87 #ifndef VBOX_REWRITTEN_MUTEX 87 88 /** 88 89 * Posix internal representation of a Mutex semaphore. … … 97 98 volatile uint32_t cNesting; 98 99 }; 100 #else /* VBOX_REWRITTEN_MUTEX */ 101 /** 102 * Linux internal representation of a Mutex semaphore. 103 */ 104 struct RTSEMMUTEXINTERNAL 105 { 106 /** Magic value. */ 107 intptr_t volatile iMagic; 108 /** The futex state variable. 109 * 0 means unlocked. 110 * 1 means locked, no waiters. 111 * 2 means locked, one or more waiters. 112 */ 113 int32_t volatile iState; 114 /** The owner of the mutex. */ 115 volatile pthread_t Owner; 116 /** Nesting count. */ 117 volatile uint32_t cNesting; 118 }; 119 #endif /* VBOX_REWRITTEN_MUTEX */ 99 120 100 121 … … 281 302 return VERR_SEM_DESTROYED; 282 303 283 /* Did somebody wake us up usfrom RTSemEventSignal()? */304 /* Did somebody wake us up from RTSemEventSignal()? */ 284 305 if (rc == 0) 285 306 return VINF_SUCCESS; … … 535 556 return false; 536 557 558 #ifdef VBOX_REWRITTEN_MUTEX 559 if (pIntMutexSem->iMagic != RTSEMMUTEX_MAGIC) 560 return false; 561 562 #endif /* VBOX_REWRITTEN_MUTEX */ 537 563 if (pIntMutexSem->cNesting == (uint32_t)~0) 538 564 return false; … … 542 568 543 569 570 #ifndef VBOX_REWRITTEN_MUTEX 544 571 RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem) 545 572 { … … 745 772 return VINF_SUCCESS; 746 773 } 747 774 #else /* VBOX_REWRITTEN_MUTEX */ 775 RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX pMutexSem) 776 { 777 /* 778 * Allocate semaphore handle. 779 */ 780 struct RTSEMMUTEXINTERNAL *pIntMutexSem = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL)); 781 if (pIntMutexSem) 782 { 783 pIntMutexSem->iMagic = RTSEMMUTEX_MAGIC; 784 pIntMutexSem->iState = 0; 785 pIntMutexSem->Owner = (pthread_t)~0; 786 pIntMutexSem->cNesting = 0; 787 788 *pMutexSem = pIntMutexSem; 789 return VINF_SUCCESS; 790 } 791 792 return VERR_NO_MEMORY; 793 } 794 795 796 RTDECL(int) RTSemMutexDestroy(RTSEMMUTEX MutexSem) 797 { 798 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem; 799 /* 800 * Validate input. 801 */ 802 if (!rtsemMutexValid(pIntMutexSem)) 803 { 804 AssertMsgFailed(("Invalid handle %p!\n", MutexSem)); 805 return VERR_INVALID_HANDLE; 806 } 807 808 /* 809 * Invalidate the semaphore and wake up anyone waiting on it. 810 */ 811 ASMAtomicXchgSize(&pIntMutexSem->iMagic, RTSEMMUTEX_MAGIC + 1); 812 if (ASMAtomicXchgS32(&pIntMutexSem->iState, 0) > 0) 813 { 814 sys_futex(&pIntMutexSem->iState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0); 815 usleep(1000); 816 } 817 pIntMutexSem->Owner = (pthread_t)~0; 818 pIntMutexSem->cNesting = ~0; 819 820 /* 821 * Free the semaphore memory and be gone. 822 */ 823 RTMemFree(pIntMutexSem); 824 return VINF_SUCCESS; 825 } 826 827 828 static int rtsemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies, bool fAutoResume) 829 { 830 /* 831 * Validate input. 832 */ 833 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem; 834 if (!rtsemMutexValid(pIntMutexSem)) 835 { 836 AssertMsgFailed(("Invalid handle %p!\n", MutexSem)); 837 return VERR_INVALID_HANDLE; 838 } 839 840 /* 841 * Check if nested request. 842 */ 843 pthread_t Self = pthread_self(); 844 if ( pIntMutexSem->Owner == Self 845 && pIntMutexSem->cNesting > 0) 846 { 847 pIntMutexSem->cNesting++; 848 return VINF_SUCCESS; 849 } 850 851 /* 852 * Convert timeout value. 853 */ 854 struct timespec ts; 855 struct timespec *pTimeout = NULL; 856 if (cMillies != RT_INDEFINITE_WAIT) 857 { 858 ts.tv_sec = cMillies / 1000; 859 ts.tv_nsec = (cMillies % 1000) * 1000000; 860 pTimeout = &ts; 861 } 862 863 /* 864 * Lock the mutex. 865 */ 866 int32_t iOld; 867 ASMAtomicCmpXchgExS32(&pIntMutexSem->iState, 1, 0, &iOld); 868 if (iOld != 0) 869 { 870 iOld = ASMAtomicXchgS32(&pIntMutexSem->iState, 2); 871 while (iOld != 0) 872 { 873 /* 874 * Go to sleep. 875 */ 876 long rc = sys_futex(&pIntMutexSem->iState, FUTEX_WAIT, 2, pTimeout, NULL, 0); 877 if (RT_UNLIKELY(pIntMutexSem->iMagic != RTSEMMUTEX_MAGIC)) 878 return VERR_SEM_DESTROYED; 879 880 /* 881 * Act on the wakup code. 882 */ 883 if (rc == -ETIMEDOUT) 884 { 885 Assert(pTimeout); 886 iOld = ASMAtomicXchgS32(&pIntMutexSem->iState, 2); 887 return VERR_TIMEOUT; 888 } 889 if (rc == 0) 890 /* we'll leave the loop now unless another thread is faster */; 891 else if (rc == -EWOULDBLOCK) 892 /* retry with new value. */; 893 else if (rc == -EINTR) 894 { 895 if (!fAutoResume) 896 return VERR_INTERRUPTED; 897 } 898 else 899 { 900 /* this shouldn't happen! */ 901 AssertMsgFailed(("rc=%ld errno=%d\n", rc, errno)); 902 return RTErrConvertFromErrno(rc); 903 } 904 905 iOld = ASMAtomicXchgS32(&pIntMutexSem->iState, 2); 906 } 907 } 908 909 /* 910 * Set the owner and nesting. 911 */ 912 pIntMutexSem->Owner = Self; 913 ASMAtomicXchgU32(&pIntMutexSem->cNesting, 1); 914 return VINF_SUCCESS; 915 } 916 917 918 RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies) 919 { 920 int rc = rtsemMutexRequest(MutexSem, cMillies, true); 921 Assert(rc != VERR_INTERRUPTED); 922 return rc; 923 } 924 925 926 RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies) 927 { 928 return rtsemMutexRequest(MutexSem, cMillies, false); 929 } 930 931 932 RTDECL(int) RTSemMutexRelease(RTSEMMUTEX MutexSem) 933 { 934 /* 935 * Validate input. 936 */ 937 struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem; 938 if (!rtsemMutexValid(pIntMutexSem)) 939 { 940 AssertMsgFailed(("Invalid handle %p!\n", MutexSem)); 941 return VERR_INVALID_HANDLE; 942 } 943 944 /* 945 * Check if nested. 946 */ 947 pthread_t Self = pthread_self(); 948 if ( pIntMutexSem->Owner != Self 949 || pIntMutexSem->cNesting == (uint32_t)~0) 950 { 951 AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n", 952 pIntMutexSem, Self, pIntMutexSem->Owner, pIntMutexSem->cNesting)); 953 return VERR_NOT_OWNER; 954 } 955 956 /* 957 * If nested we'll just pop a nesting. 958 */ 959 if (pIntMutexSem->cNesting > 1) 960 { 961 pIntMutexSem->cNesting--; 962 return VINF_SUCCESS; 963 } 964 965 /* 966 * Clear the state. (cNesting == 1) 967 */ 968 pIntMutexSem->Owner = (pthread_t)~0; 969 ASMAtomicXchgU32(&pIntMutexSem->cNesting, 0); 970 971 /* 972 * Release the mutex. 973 */ 974 int32_t iNew = ASMAtomicDecS32(&pIntMutexSem->iState); 975 if (iNew != 0) 976 { 977 /* somebody is waiting, try wake up one of them. */ 978 pIntMutexSem->iState = 0; 979 (void)sys_futex(&pIntMutexSem->iState, FUTEX_WAKE, 1, NULL, NULL, 0); 980 } 981 return VINF_SUCCESS; 982 } 983 #endif /* VBOX_REWRITTEN_MUTEX */ 748 984 749 985
Note:
See TracChangeset
for help on using the changeset viewer.