This is the 15th day of my participation in the August More text Challenge. For details, see: August More Text Challenge
review
In the last blog has GCD sync sync function, async asynchronous function for the source analysis, so this blog continue to explore the source analysis!
1. Add
The difference between sync and async
- Whether to enable a new thread to execute tasks
- Whether the callback of the task has asynchronous line and synchronization
- Whether a deadlock problem occurs
2. Deadlock source analysis
As analyzed in the previous blog, the process for synchronizing the sync function is _dispatch_sync_f — > _dispatch_sync_F_inline — > _dispatch_barrier_sync_f
Go to the_dispatch_barrier_sync_f
In the process, this is consistent with the analysis in the previous blog, because heredq_width=1
, so it isSerial queues
If it isConcurrent queue
, will go to_dispatch_sync_f_slow
Now, go to_dispatch_barrier_sync_f
Let’s look inside the method
_dispatch_barrier_sync_f
static void
_dispatch_barrier_sync_f(dispatch_queue_t dq, void *ctxt,
dispatch_function_t func, uintptr_t dc_flags)
{
_dispatch_barrier_sync_f_inline(dq, ctxt, func, dc_flags);
}
Copy the code
This method in turn calls the _dispatch_barrier_sync_F_inline method
In this method, the queue is evaluated to see if there is a waiting or pending state
// Decide whether to suspend or wait
if(unlikely(! _dispatch_queue_try_acquire_barrier_sync(dl, tid))) {// Add a task
return _dispatch_sync_f_slow(dl, ctxt, func, DC_FLAG_BARRIER, dl,
DC_FLAG_BARRIER | dc_flags);
}
Copy the code
As mentioned in the previous blog, deadlocks are reported with errors related to _dispatch_sync_f_slow, as follows:
Although the deadlock will go_dispatch_sync_f_slow
Method, but the deadlock error is not_dispatch_sync_f_slow
This error is reported instead as shown in the figure below0
In the error
It’s true that __DISPATCH_WAIT_FOR_QUEUE__ is wrong, so now check
_dispatch_sync_f_slow
在_dispatch_sync_f_slow
Method, we found that the deadlock just reported the error__DISPATCH_WAIT_FOR_QUEUE__
Now take a look inside
__DISPATCH_WAIT_FOR_QUEUE__
Inside __DISPATCH_WAIT_FOR_QUEUE__, we find the same error message as the deadlock message, which means:
Dispatch_sync is called on the queue that the current thread already has. Sorry, I already have her, you’re a little late
if (unlikely(_dq_state_drain_locked_by(dq_state, dsc->dsc_waiter))) {
DISPATCH_CLIENT_CRASH((uintptr_t)dq_state,
"dispatch_sync called on queue "
"already owned by current thread");
}
Copy the code
This dSC_waiter is passed from the _dispatch_sync_f_slow method
_dispatch_tid_self() is the thread ID, defined as follows
_dispatch_thread_port is the channel for the thread, now look at the thread state match
/ / state
uint64_t dq_state = _dispatch_wait_prepare(dq);
if (unlikely(_dq_state_drain_locked_by(dq_state, dsc->dsc_waiter))) {
DISPATCH_CLIENT_CRASH((uintptr_t)dq_state,
"dispatch_sync called on queue "
"already owned by current thread");
}
Copy the code
_dq_state_drain_locked_by
static inline bool
_dq_state_drain_locked_by(uint64_t dq_state, dispatch_tid tid)
{
return _dispatch_lock_is_locked_by((dispatch_lock)dq_state, tid);
}
Copy the code
_dispatch_lock_is_locked_by
static inline bool
_dispatch_lock_is_locked_by(dispatch_lock lock_value, dispatch_tid tid)
{
// equivalent to _dispatch_lock_owner(lock_value) == tid
return ((lock_value ^ tid) & DLOCK_OWNER_MASK) == 0;
}
Copy the code
DLOCK_OWNER_MASK
#define DLOCK_OWNER_MASK ((dispatch_lock)0xfffffffc)
Copy the code
Here is the deadlock judgment: XOR and, which results in a deadlock of 0. Dq_state ^ DSC ->dsc_waiter = 0 and DLOCK_OWNER_MASK = 0
Dq_state ^ DSC -> dSC_waiter = 0 Different or Same is 0, because DLOCK_OWNER_MASK is a very large integer, so dq_state and DSC -> dSC_waiter are both 0.
The id of the thread waiting in the current queue is the same as the one I called. I am already in the waiting state. Now you have new tasks that need to be executed by me. This is why a deadlock occurs when a serial queue performs a synchronization task!
More to come
🌹 just like it 👍🌹
🌹 feel have harvest, can come a wave, collect + concern, comment + forward, lest you can’t find me next 😁🌹
🌹 welcome everyone to leave a message to exchange, criticize and correct, learn from each other 😁, improve self 🌹