Example #1
0
int TSReleaseReader(TSReaderWriterLock *rwlock)
{
	SInt32 flags;
	int ret = 0;

	// Try to decrement the reader count until we are successful
	do
	{
		flags = rwlock->_flags;

	} while (!OSAtomicCompareAndSwap32Barrier(flags, ((flags & FLAGS_MASK) | ((flags & READER_COUNT_MASK) - 1)), &rwlock->_flags));

	// If there is a writer waiting, wake it up
	if (flags & WRITER_WAITING)
	{
		ret = TSLockMutex(&rwlock->_condLock, NULL);
		if (0 == ret)
		{
			if ((rwlock->_flags & (WRITER_WAITING | READER_COUNT_MASK)) == WRITER_WAITING)
			{
				ret = TSSignalCondition(&rwlock->_cond);
			}
			TSUnlockMutex(&rwlock->_condLock);
		}
	}

	return ret;
}
Example #2
0
int32_t __sync_lock_test_and_set_4(int32_t *ptr, int32_t value, ...)
{
    int32_t old;

    do {
		old = *ptr;
	} while (!OSAtomicCompareAndSwap32Barrier(old, value, ptr));

    return old;
}
Example #3
0
int TSWriterToReader(TSReaderWriterLock *rwlock)
{
	// Increment the reader count while at the same time clearing the writer flag
	SInt32 flags;
	do
	{
		flags = rwlock->_flags;
	} while (!OSAtomicCompareAndSwap32Barrier(flags, ((flags & WRITER_WAITING) | ((flags & READER_COUNT_MASK) + 1)), &rwlock->_flags));

	// Release the writer mutex
	TSUnlockMutex(&rwlock->_writerLock);
	return 0;
}
Example #4
0
//------------------------------------------------------------------------
bool FAtomicCompareAndSwap (volatile int32& var, int32 oldVar, int32 newVar)
{
#if WINDOWS
	return InterlockedCompareExchange (&var, newVar, oldVar) == oldVar;
#elif MAC
	return OSAtomicCompareAndSwap32Barrier (oldVar, newVar, NATIVE_ATOMIC_TYPE &var);
#else
	if (var == oldVar)
	{
		var = newVar;
		return true;
	}
	return false;
#endif
}
Example #5
0
int TSAcquireReader(TSReaderWriterLock *rwlock)
{
	while (1)
	{
		SInt32 flags = rwlock->_flags;

		// While there is a writer, wait for the writer to release
		while (flags & WRITER_HAS_LOCK)
		{
			int ret = TSLockMutex(&rwlock->_writerLock, NULL);
			if (0 != ret) return ret;
			TSUnlockMutex(&rwlock->_writerLock);
			flags = rwlock->_flags;
		}

		// Try to increment the reader count, if somebody else gets there first, try again
		if (OSAtomicCompareAndSwap32Barrier(flags, ((flags & FLAGS_MASK) | ((flags & READER_COUNT_MASK) + 1)), &rwlock->_flags)) return 0;
	}
}
Example #6
0
static void
_asl_global_init()
{
	if (_asl_global.server_port == MACH_PORT_NULL)
	{
		mach_port_t newport = MACH_PORT_NULL;
		char *str = getenv("ASL_DISABLE");
		if ((str == NULL) || strcmp(str, "1"))
		{
			bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &newport);
			if (newport != MACH_PORT_NULL)
			{
				if (!OSAtomicCompareAndSwap32Barrier(MACH_PORT_NULL, newport, (int32_t *)&_asl_global.server_port))
				{
					mach_port_deallocate(mach_task_self(), newport);
				}
			}
		}
	}
}
static int
_pthread_cond_signal(pthread_cond_t *ocond, bool broadcast, mach_port_t thread)
{
	int res;
	_pthread_cond *cond = (_pthread_cond *)ocond;

	uint32_t updateval;
	uint32_t diffgen;
	uint32_t ulval;

	uint64_t oldval64, newval64;
	uint32_t lcntval, ucntval, scntval;
	volatile uint32_t *c_lseqcnt, *c_useqcnt, *c_sseqcnt;

	int retry_count = 0, uretry_count = 0;
	int ucountreset = 0;

	bool inited = false;
	res = _pthread_cond_check_init(cond, &inited);
	if (res != 0 || inited == true) {
		return res;
	}

	COND_GETSEQ_ADDR(cond, &c_lseqcnt, &c_useqcnt, &c_sseqcnt);

	bool retry;
	do {
		retry = false;

		lcntval = *c_lseqcnt;
		ucntval = *c_useqcnt;
		scntval = *c_sseqcnt;

		if (((lcntval & PTHRW_COUNT_MASK) == (scntval & PTHRW_COUNT_MASK)) ||
		    (thread == MACH_PORT_NULL && ((lcntval & PTHRW_COUNT_MASK) == (ucntval & PTHRW_COUNT_MASK)))) {
			/* validate it is spurious and return */
			oldval64 = (((uint64_t)scntval) << 32);
			oldval64 |= lcntval;
			newval64 = oldval64;
			
			if (OSAtomicCompareAndSwap64Barrier(oldval64, newval64, (volatile int64_t *)c_lseqcnt) != TRUE) {
				retry = true;
				continue;
			} else {
				return 0;
			}
		}

		if (thread) {
			break;
		}

		/* validate to eliminate spurious values, race snapshots */
		if (is_seqhigher((scntval & PTHRW_COUNT_MASK), (lcntval & PTHRW_COUNT_MASK))) {
			/* since ucntval may be newer, just redo */
			retry_count++;
			if (retry_count > 8192) {
				return EAGAIN;
			} else {
				sched_yield();
				retry = true;
				continue;
			}
		} else if (is_seqhigher((ucntval & PTHRW_COUNT_MASK), (lcntval & PTHRW_COUNT_MASK))) {
			/* since ucntval may be newer, just redo */
			uretry_count++;
			if (uretry_count > 8192) {
				/*
				 * U value if not used for a while can go out of sync
				 * set this to S value and try one more time.
				 */
				if (ucountreset != 0) {
					return EAGAIN;
				} else if (OSAtomicCompareAndSwap32Barrier(ucntval, (scntval & PTHRW_COUNT_MASK), (volatile int32_t *)c_useqcnt) == TRUE) {
					/* now the U is reset to S value */
					ucountreset = 1;
					uretry_count = 0;
				}
			}
			sched_yield();
			retry = true;
			continue;
		}

		if (is_seqlower(ucntval & PTHRW_COUNT_MASK, scntval & PTHRW_COUNT_MASK) != 0) {
			/* If U < S, set U = S+diff due to intr's TO, etc */
			ulval = (scntval & PTHRW_COUNT_MASK);
		} else {
			/* If U >= S, set U = U+diff due to intr's TO, etc */
			ulval = (ucntval & PTHRW_COUNT_MASK);
		}

		if (broadcast) {
			diffgen = diff_genseq(lcntval, ulval);
			// Set U = L
			ulval = (lcntval & PTHRW_COUNT_MASK);
		} else {
			ulval += PTHRW_INC;
		}

	} while (retry || OSAtomicCompareAndSwap32Barrier(ucntval, ulval, (volatile int32_t *)c_useqcnt) != TRUE);
	
	uint32_t flags = 0;
	if (cond->pshared == PTHREAD_PROCESS_SHARED) {
		flags |= _PTHREAD_MTX_OPT_PSHARED;
	}

	uint64_t cvlsgen = ((uint64_t)scntval << 32) | lcntval;

	if (broadcast) {
		// pass old U val so kernel will know the diffgen
		uint64_t cvudgen = ((uint64_t)ucntval << 32) | diffgen;
		updateval = __psynch_cvbroad(ocond, cvlsgen, cvudgen, flags, NULL, 0, 0);
	} else {
		updateval = __psynch_cvsignal(ocond, cvlsgen, ucntval, thread, NULL, 0, 0, flags);
	}

	if (updateval != (uint32_t)-1 && updateval != 0) {
		_pthread_cond_updateval(cond, 0, updateval);
	}

	return 0;
}
Example #8
0
int32_t __sync_val_compare_and_swap_4(int32_t *ptr, int32_t oldval, int32_t newval, ...)
{
    int32_t old = *ptr;
    OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr);
    return old;
}
Example #9
0
bool __sync_bool_compare_and_swap_4(int32_t *ptr, int32_t oldval, int32_t newval, ...)
{
    return OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr);
}