_MD_CreateThread( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PRIntn is; int rv; PRThread *me = _PR_MD_CURRENT_THREAD(); pthread_attr_t attr; if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); if (pthread_mutex_init(&thread->md.pthread_mutex, NULL) != 0) { if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } if (pthread_cond_init(&thread->md.pthread_cond, NULL) != 0) { pthread_mutex_destroy(&thread->md.pthread_mutex); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } thread->flags |= _PR_GLOBAL_SCOPE; pthread_attr_init(&attr); /* initialize attr with default attributes */ if (pthread_attr_setstacksize(&attr, (size_t) stackSize) != 0) { pthread_mutex_destroy(&thread->md.pthread_mutex); pthread_cond_destroy(&thread->md.pthread_cond); pthread_attr_destroy(&attr); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } thread->md.wait = 0; rv = pthread_create(&thread->md.pthread, &attr, start, (void *)thread); if (0 == rv) { _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_created); _MD_ATOMIC_INCREMENT(&_pr_md_pthreads); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_SUCCESS; } else { pthread_mutex_destroy(&thread->md.pthread_mutex); pthread_cond_destroy(&thread->md.pthread_cond); pthread_attr_destroy(&attr); _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_failed); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, rv); return PR_FAILURE; } }
PR_WaitCondVar (PRCondVar *cvar, PRIntervalTime timeout) { status_t err; if( timeout == PR_INTERVAL_NO_WAIT ) { PR_Unlock( cvar->lock ); PR_Lock( cvar->lock ); return PR_SUCCESS; } if( _MD_ATOMIC_INCREMENT( &cvar->signalBenCount ) > 1 ) { if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) { _MD_ATOMIC_DECREMENT( &cvar->signalBenCount ); return PR_FAILURE; } } cvar->nw += 1; if( _MD_ATOMIC_DECREMENT( &cvar->signalBenCount ) > 0 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } PR_Unlock( cvar->lock ); if( timeout==PR_INTERVAL_NO_TIMEOUT ) { err = acquire_sem(cvar->sem); } else { err = acquire_sem_etc(cvar->sem, 1, B_RELATIVE_TIMEOUT, PR_IntervalToMicroseconds(timeout) ); } if( _MD_ATOMIC_INCREMENT( &cvar->signalBenCount ) > 1 ) { while (acquire_sem(cvar->signalSem) == B_INTERRUPTED); } if (cvar->ns > 0) { release_sem_etc(cvar->handshakeSem, 1, B_DO_NOT_RESCHEDULE); cvar->ns -= 1; } cvar->nw -= 1; if( _MD_ATOMIC_DECREMENT( &cvar->signalBenCount ) > 0 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } PR_Lock( cvar->lock ); if(err==B_NO_ERROR || (err == B_TIMED_OUT && timeout!=PR_INTERVAL_NO_TIMEOUT)) { return PR_SUCCESS; } return PR_FAILURE; }
PR_NotifyCondVar (PRCondVar *cvar) { status_t err ; if( _MD_ATOMIC_INCREMENT( &cvar->signalBenCount) > 1 ) { if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) { _MD_ATOMIC_DECREMENT( &cvar->signalBenCount ); return PR_FAILURE; } } if (cvar->nw > cvar->ns) { cvar->ns += 1; release_sem_etc(cvar->sem, 1, B_DO_NOT_RESCHEDULE); if( _MD_ATOMIC_DECREMENT( &cvar->signalBenCount) > 0 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } while (acquire_sem(cvar->handshakeSem) == B_INTERRUPTED) { err = B_INTERRUPTED; } } else { if( _MD_ATOMIC_DECREMENT( &cvar->signalBenCount ) > 0 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } } return PR_SUCCESS; }