This is the 28th day of my participation in the August Challenge
NSConditionLock analysis
Compiled analysis created by NSConditionLock
NSConditionLock (conditionLock)
Resolution:
NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:2];
In the2
Equivalent to oneMatching conditions
; Set to2
That is to saylockWhenCondition
for2
The first execution of; So print it firstThread 2
;- print
Thread 2
And then, because of[conditionLock unlockWithCondition:1];
Let’s change the match condition to1
, so in execution1
Conditional task, which is printingThread 1
; - Due to the print
Thread 3
The task is not setMatching conditions
, is a normal lock, there is no condition control, so there is no need to match, will be executed first, printThread 3
; - So the final result is printed
Thread 3
.Thread 2
.Thread 1
Print in sequence;
At this time, we found that the execution of NSConditionLock is very similar to that of NSCondition, both of which have conditional control. So we have some questions, right?
NSConditionLock
andNSCondition
What does it matter- Conditions passed in during initialization
2
What is it? lockWhenCondition
How do you do conditional control?unlockWithCondition
What did he do?
Now, let’s break each of these four points of doubt:
As a rule of thumb, if we want to investigate an initWithCondition:2 operation, we can add a symbol breakpoint for initWithCondition:
However, as we continue to execute the code, we find that the initWithCondition symbol breakpoint is not intercepted:
[NSConditionLock initWithCondition:] -[NSConditionLock initWithCondition:] -[NSConditionLock initWithCondition:]
Symbol breakpoint intercepted successfully! Let’s look at what happens in the register:
x0
Is the default parameter, the receiver of the message:NSConditionLock
;x1
Is the default parameter,SEL
:initWithCondition:
;x2
Is the parameter of the method:2
;
Next, we analyze the execution process through assembly code. We can ignore the details. Then, we only need to pay attention to the execution of BL and RETURN instructions, because BL is a jump instruction, and there will be related processing, while return; The instruction returns directly; We put all on the bl instruction of breakpoints, and then continue to execute down, analysis NSConditionLock initWithCondition: method of implementation process:
Now an unknown object calls init and passes in parameter 2; [? init:2]
To continue:
The NSConditionLock object calls the init method and passes argument 2; -[NSConditionLock init:2]
To continue:
The NSConditionLock object calls the zone method; -[NSConditionLock zone]
To continue:
NSCondition calls allocWithZone:; +[NSCondition allocWithZone:]
To continue:
NSCondition calls init; -[NSCondition init]
To continue:
The return method is executed because the return value is placed in the X0 register; NSConditionLock (condition = 2);
-[NSConditionLock initWithCondition:] At this point, the clearing of memory and the handling of member variables are finished; We can look at the memory from the console:
0x01000001ffe44209
forisa
;<NSCondition: 0x28340c000>
And the ones we saw created in the previous assemblyNSCondition
Address consistent;<NSCondition: 0x28340c000>
Become the<NSConditionLock: 0x2808400f0>
A member variable of;
If you do not see 2, you can continue to enlarge the view memory:
We see the address of 2;
-[NSConditionLock initWithCondition:]
- 1.
[? init:2]
- 2,
-[NSConditionLock init:2]
- 3,
-[NSConditionLock zone]
- 4,
+[NSCondition allocWithZone:]
- 5,
-[NSCondition init]
In -[NSConditionLock initWithCondition:], encapsulates an NSCondition
But how the lockWhenCondition and unlockWithCondition methods control is still unknown.
LockWhenCondition and unlockWithCondition analysis
Next, we analyze lockWhenCondition and unlockWithCondition, Add the symbol breakpoint -[NSConditionLock lockWhenCondition:] and -[NSConditionLock unlockWithCondition:]
LockWhenCondition analysis
Next, we still study the execution of BL instructions:
NSDate calls the distantFuture method;
Note that since we are multithreading, we need to pay attention to the Thread on the left. We are currently Thread 7, so we try to analyze in the current Thread and avoid analyzing the logic of other threads.
Continue to instruction B:
Call – [NSConditionLock lockWhenCondition: beforeDate:] method, this method has two parameters, means that we need to have a look at the x3 registers
From the name _NSConstantDateDistantFuture we speculate that the second parameter is extremely likely NSDate calls the distantFuture return values
We at this point, add symbols breakpoint – [NSConditionLock lockWhenCondition: beforeDate:], into this method:
The second argument is 1;
Continue with the next BL instruction:
The -[NSCondition Lock] method is called
Continue down (too many steps, similar analysis, we pick the main analysis) :
The -[NSCondition waitUntilDate] method is called to wait.
Then it will jump to another thread to do the operation, we won’t analyze this part; On coming back again:
The unlock method is called and returns 1, true; I will not wait now.
-[NSConditionLock lockWhenCondition]
- 1.
+[NSDate distantFuture]
- 2,
-[NSConditionLock lockWhenCondition:beforeDate:]
- 2.1,
-[NSCondition lock]
- 2.2,
-[NSCondition waitUntilDate]
- 2.3,
unlock
- 2.1,
Next, unlockWithCondition;
UnlockWithCondition analysis
The -[NSCondition lock] method is called.
To continue:
The -[NSCondition broadcast] method is called.
Call -[NSCondition unlock]
-[NSConditionLock unlockWithCondition]
- 1.
-[NSCondition lock]
- 2,
-[NSCondition broadcast]
- 3,
-[NSCondition unlock]
Source contrast
Because we’re looking at the Swift version, the code is going to be a little different, so I’m going to comment the corresponding code directly in the code;
- NSConditionLock initialization
- lockWhenCondition
- unlockWithCondition
By comparing the source code with the code logic we analyzed through assembly, basically the main process can be analyzed, which is one way we analyze the underlying source code: in the case of no open source, we can still roughly calculate the implementation logic of the underlying code through assembly;