Show
Ignore:
Timestamp:
09/28/10 17:31:36 (3 years ago)
Author:
sampson
Message:

Working on gen_locks

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • branches/windows-client/src/common/gen-locks/gen-win-locks.c

    r8520 r8527  
    2424/* TODO: may need to init and delete in DLL enter/exit functions */ 
    2525LPCRITICAL_SECTION cond_list_lock = NULL; 
     26LPCRITICAL_SECTION cond_test_init_lock = NULL; 
    2627 
    2728pgen_cond_t cond_list_head = NULL; 
     
    137138} 
    138139 
    139 int gen_win_cond_destroy(HANDLE cond) 
    140 { 
    141     if(!cond) 
     140int gen_win_cond_destroy(pgen_cond_t *cond) 
     141{ 
     142    pgen_cond_t cv; 
     143    int result = 0, result1 = 0, result2 = 0; 
     144 
     145    if(!cond || !(*cond)) 
    142146    { 
    143147        return -EINVAL; 
    144148    } 
    145     pthread_cond_destroy(cond); 
    146     return 0; 
    147 } 
    148  
    149 int gen_win_cond_wait(HANDLE cond, HANDLE mut) 
     149     
     150    if (*cond != GEN_COND_INITIALIZER) 
     151    { 
     152        EnterCriticalSection(cond_list_lock); 
     153 
     154        cv = *cond; 
     155 
     156        if (WaitForSingleObject(&(cv->semBlockLock), INFINITE) != WAIT_OBJECT_0) 
     157        {    
     158            return GetLastError(); 
     159        } 
     160 
     161        if ((result = gen_mutex_trylock(&(cv->mtxUnblockLock))) != 0) 
     162        { 
     163            ReleaseSemaphore(&(cv->semBlockLock), 1, NULL); 
     164            return result; 
     165        } 
     166 
     167        if (cv->nWaitersBlocked > cv->nWaitersGone) 
     168        { 
     169            if (!ReleaseSemaphore(&(cv->semBlockLock), 1, NULL)) 
     170            { 
     171                result = GetLastError(); 
     172            } 
     173            result1 = gen_mutex_unlock(&(cv->mtxUnblockLock)); 
     174            result2 = EBUSY; 
     175        } 
     176        else 
     177        { 
     178            /* Now it is safe to destroy */ 
     179            *cond = NULL; 
     180 
     181            if (CloseHandle(&(cv->semBlockLock)) != 0) 
     182            { 
     183                result = GetLastError(); 
     184            } 
     185            if (CloseHandle(&(cv->semBlockQueue)) != 0) 
     186            { 
     187                result1 = GetLastError(); 
     188            } 
     189            if ((result2 = gen_mutex_unlock(&(cv->mtxUnblockLock))) == 0) 
     190            { 
     191                result2 = gen_mutex_destroy(&(cv->mtxUnblockLock)); 
     192            } 
     193 
     194            /* Unlink the CV from the list */ 
     195            if (cond_list_head == cv) 
     196            { 
     197                cond_list_head = cv->next; 
     198            } 
     199            else  
     200            { 
     201                cv->prev->next = cv->next; 
     202            } 
     203 
     204            if (cond_list_tail == cv)  
     205            { 
     206                cond_list_tail = cv->prev; 
     207            } 
     208            else { 
     209                cv->next->prev = cv->prev; 
     210            } 
     211 
     212            free(cv); 
     213        } 
     214 
     215        LeaveCriticalSection(cond_list_lock); 
     216    } 
     217    else 
     218    { 
     219        EnterCriticalSection(cond_test_init_lock); 
     220 
     221        if (*cond == GEN_COND_INITIALIZER)  
     222        { 
     223            *cond = NULL; 
     224        } 
     225        else  
     226        { 
     227            result = EBUSY; 
     228        } 
     229 
     230        LeaveCriticalSection(cond_test_init_lock); 
     231    } 
     232 
     233    return ((result != 0) ? result : ((result1 != 0) ? result1 : result2)); 
     234} 
     235 
     236typedef struct 
     237{ 
     238    gen_mutex_t *mutexPtr; 
     239    pgen_cond_t cv; 
     240    int *resultPtr; 
     241} cond_wait_cleanup_args_t; 
     242 
     243static void __cdecl cond_wait_cleanup(void *args) 
     244{ 
     245    cond_wait_cleanup_args_t *cleanup_args = (cond_wait_cleanup_args_t *) args; 
     246    pgen_cond_t cv = cleanup_args->cv; 
     247    int *resultPtr = cleanup_args->resultPtr; 
     248    int nSignalsWasLeft; 
     249    int result; 
     250 
     251    if ((result = gen_mutex_lock(&(cv->mtxUnblockLock))) != 0)  
     252    { 
     253        *resultPtr = result; 
     254        return; 
     255    } 
     256 
     257    if ((nSignalsWasLeft = cv->nWaitersToUnblock) != 0) 
     258    { 
     259        --(cv->nWaitersToUnblock); 
     260    } 
     261    else if (INT_MAX / 2 == ++(cv->nWaitersGone)) 
     262    { 
     263        if (WaitForSingleObject(&(cv->semBlockLock), INFINITE) != 0) 
     264        { 
     265            *resultPtr = (int) GetLastError(); 
     266            return; 
     267        } 
     268        cv->nWaitersBlocked -= cv->nWaitersGone; 
     269        if (!ReleaseSemaphore(&(cv->semBlockLock), 1, NULL)) 
     270        { 
     271            *resultPtr = (int) GetLastError(); 
     272            return; 
     273        } 
     274        cv->nWaitersGone = 0; 
     275    } 
     276 
     277    if ((result = gen_mutex_unlock(&(cv->mtxUnblockLock))) != 0) 
     278    { 
     279        *resultPtr = result; 
     280        return; 
     281    } 
     282 
     283    if (nSignalsWasLeft == 1)  
     284    { 
     285        if (!ReleaseSemaphore(&(cv->semBlockLock), 1, NULL)) 
     286        { 
     287            *resultPtr = (int) GetLastError(); 
     288            return; 
     289        } 
     290    } 
     291 
     292    if ((result = gen_mutex_lock(cleanup_args->mutexPtr)) != 0) 
     293    { 
     294        *resultPtr = result; 
     295    } 
     296 
     297} 
     298 
     299static __inline int cond_timedwait(pgen_cond_t *cond, 
     300                                   HANDLE *mutex, const struct timespec *abstime) 
     301{ 
     302    int result = 0; 
     303    pgen_cond_t cv; 
     304    cond_wait_cleanup_args_t cleanup_args; 
     305 
     306    if (cond == NULL || *cond == NULL)  
     307    { 
     308        return EINVAL; 
     309    } 
     310 
     311    if (*cond == GEN_COND_INITIALIZER) 
     312    { 
     313        result = cond_check_need_init(cond); 
     314    } 
     315 
     316    if (result != 0 && result != EBUSY)  
     317    { 
     318        return result; 
     319    } 
     320 
     321    cv = *cond; 
     322 
     323    if (WaitForSingleObject(&(cv->semBlockLock), INFINITE) != 0) 
     324    { 
     325        return (int) GetLastError(); 
     326    } 
     327 
     328    ++(cv->nWaitersBlocked); 
     329 
     330    if (!ReleaseSemaphore(&(cv->semBlockLock), 1, NULL)) 
     331    { 
     332        return (int) GetLastError(); 
     333    } 
     334 
     335    cleanup_args.mutexPtr = mutex; 
     336    cleanup_args.cv = cv; 
     337    cleanup_args.resultPtr = &result; 
     338 
     339    // TODO: pthread_cleanup_push(cond_wait_cleanup, (void*) &cleanup_args); 
     340 
     341    /* Now we can release mutex and... */ 
     342    if ((result = gen_mutex_unlock(mutex)) == 0)  
     343    { 
     344 
     345    } 
     346 
     347    return result; 
     348} 
     349 
     350int gen_win_cond_wait(pgen_cond_t *cond, HANDLE *mut) 
    150351{ 
    151352    return pthread_cond_wait(cond, mut); 
    152353} 
    153354 
    154 int gen_win_cond_timedwait(HANDLE cond, HANDLE mut, 
     355int gen_win_cond_timedwait(pgen_cond_t *cond, HANDLE *mut, 
    155356                             const struct timespec *abstime) 
    156357{ 
     
    158359} 
    159360 
    160 int gen_win_cond_signal(HANDLE cond) 
     361int gen_win_cond_signal(pgen_cond_t *cond) 
    161362{ 
    162363    return pthread_cond_signal(cond); 
    163364} 
    164365 
    165 int gen_win_cond_broadcast(HANDLE cond) 
     366int gen_win_cond_broadcast(pgen_cond_t *cond) 
    166367{ 
    167368    return pthread_cond_broadcast(cond);