iOS_dispatch_semaphore related code

  • dispatch_semaphore_createthe code

Semaphore creation

dispatch_semaphore_t
dispatch_semaphore_create(long value)
{
    
    
	dispatch_semaphore_t dsema;

	// If the internal value is negative, then the absolute of the value is
	// equal to the number of waiting threads. Therefore it is bogus to
	// initialize the semaphore with a negative value.
	if (value < 0) {
    
    
		return DISPATCH_BAD_INPUT;
	}

	dsema = _dispatch_object_alloc(DISPATCH_VTABLE(semaphore),
			sizeof(struct dispatch_semaphore_s));
	dsema->do_next = DISPATCH_OBJECT_LISTLESS;
	dsema->do_targetq = _dispatch_get_default_queue(false);
	dsema->dsema_value = value;
	_dispatch_sema4_init(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);
	dsema->dsema_orig = value;
	return dsema;
}

  • dispatch_semaphore_waitthe code

Semaphore usage -1

long
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)
{
    
    
	// 信号量的值-1
	long value = os_atomic_dec2o(dsema, dsema_value, acquire);
	// 如果-1后的值依旧大于或等于0,则继续执行
	if (likely(value >= 0)) {
    
    
		return 0;
	}
	// 如果-1后小于0,则进行等待
	return _dispatch_semaphore_wait_slow(dsema, timeout);
}

  • _dispatch_semaphore_wait_slowthe code
static long
_dispatch_semaphore_wait_slow(dispatch_semaphore_t dsema,
		dispatch_time_t timeout)
{
    
    
	long orig;

	_dispatch_sema4_create(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);
	switch (timeout) {
    
    
	default:
		if (!_dispatch_sema4_timedwait(&dsema->dsema_sema, timeout)) {
    
    
			break;
		}
		// Fall through and try to undo what the fast path did to
		// dsema->dsema_value
	case DISPATCH_TIME_NOW:
		orig = dsema->dsema_value;
		while (orig < 0) {
    
    
			if (os_atomic_cmpxchgvw2o(dsema, dsema_value, orig, orig + 1,
					&orig, relaxed)) {
    
    
				return _DSEMA4_TIMEOUT();
			}
		}
		// Another thread called semaphore_signal().
		// Fall through and drain the wakeup.
	case DISPATCH_TIME_FOREVER:
		_dispatch_sema4_wait(&dsema->dsema_sema);
		break;
	}
	return 0;
}


  • dispatch_semaphore_signalthe code

Semaphore usage +1

long
dispatch_semaphore_signal(dispatch_semaphore_t dsema)
{
    
    
	// 信号量的值+1
	long value = os_atomic_inc2o(dsema, dsema_value, release);
	// 如果+1后的值大于0,则继续执行
	if (likely(value > 0)) {
    
    
		return 0;
	}
	// 处理边界情况
	if (unlikely(value == LONG_MIN)) {
    
    
		DISPATCH_CLIENT_CRASH(value,
				"Unbalanced call to dispatch_semaphore_signal()");
	}
	return _dispatch_semaphore_signal_slow(dsema);
}

  • dispatch_semaphore_signal_slowthe code
// 此函数返回值只有0或1
long
_dispatch_semaphore_signal_slow(dispatch_semaphore_t dsema)
{
    
    
	_dispatch_sema4_create(&dsema->dsema_sema, _DSEMA4_POLICY_FIFO);
	_dispatch_sema4_signal(&dsema->dsema_sema, 1);
	return 1;
}


  • Some related macro definitions

#define os_atomic_inc2o(p, f, m) \
		os_atomic_add2o(p, f, 1, m)
		
#define os_atomic_add2o(p, f, v, m) \
		os_atomic_add(&(p)->f, (v), m)
		
#define os_atomic_add(p, v, m) \
		_os_atomic_c11_op((p), (v), m, add, +)


#define os_atomic_dec(p, m) \
		os_atomic_sub((p), 1, m)
		
#define os_atomic_sub(p, v, m) \
		_os_atomic_c11_op((p), (v), m, sub, -)
		

#define _os_atomic_c11_op(p, v, m, o, op) \
		({
      
       _os_atomic_basetypeof(p) _v = (v), _r = \
		atomic_fetch_##o##_explicit(_os_atomic_c11_atomic(p), _v, \
		memory_order_##m); (typeof(_r))(_r op _v); })

Guess you like

Origin blog.csdn.net/FlyingKuiKui/article/details/122898011