In analyzing iofclose.c file, I found some strange part of that.
// glibc-2.23.90/libio/iofclose.c:53
if (fp->_IO_file_flags & _IO_IS_FILEBUF)
_IO_un_link ((struct _IO_FILE_plus *) fp);
_IO_acquire_lock (fp); // !!!!! This part !!!!!
...
As You see this source, fclose() calls _IO_acquire_lock
internally.
And _IO_acquire_lock
calls _IO_lock_lock
below this.
//glibc-2.23.90/sysdeps/nptl/stdio-lock.h:39
#define _IO_lock_lock(_name) \
do { \
void *__self = THREAD_SELF; \
if ((_name).owner != __self) \
{ \
lll_lock ((_name).lock, LLL_PRIVATE); \
...
In _IO_lock_lock
, void *__self = THREAD_SELF;
and if ((_name).owner != __self)
logic is appeared like this.
0x7f9a21eca393 <_IO_new_fclose+291>: mov r8,QWORD PTR fs:0x10
0x7f9a21eca39c <_IO_new_fclose+300>: cmp r8,QWORD PTR [rdx+0x8]
0x7f9a21eca3a0 <_IO_new_fclose+304>: je 0x7f9a21eca3e2 <_IO_new_fclose+370>
0x7f9a21eca3a2 <_IO_new_fclose+306>: mov esi,0x1
...
Then, if lll_lock((_name).lock, LLL_PRIVATE);
is called after branch command, lll_lock()
is proceeded like this.
0x7f9a21eca3a2 <_IO_new_fclose+306>: mov esi,0x1
0x7f9a21eca3a7 <_IO_new_fclose+311>: xor eax,eax
0x7f9a21eca3a9 <_IO_new_fclose+313>:
cmp DWORD PTR [rip+0x35c390],0x0 # 0x7f9a22226740 <__libc_multiple_threads>
0x7f9a21eca3b0 <_IO_new_fclose+320>: je 0x7f9a21eca3ba <_IO_new_fclose+330>
...
In this assembly, logic of comparing __libc_multiple_threads
is being.
But, when I saw lll_lock()
code, I can't find that logic...
//glibc-2.23.90/sysdeps/unix/sysv/linux/sparc/lowlevellock.h:51
static inline void
__attribute__ ((always_inline))
__lll_lock (int *futex, int private)
{
int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
if (__glibc_unlikely (val != 0))
{
if (__builtin_constant_p (private) && private == LLL_PRIVATE)
__lll_lock_wait_private (futex);
else
__lll_lock_wait (futex, private);
}
}
#define lll_lock(futex, private) __lll_lock (&(futex), private)
How happened this situation?
Where can i find these assembly logic in this c source code?
You're reading the source code for the SPARC locking implementation, but the assembly you've shown is x86. I think the code you want is in sysdeps/unix/sysv/linux/x86/lowlevellock.h. There you'll see it tests if (is_single_thread)
. This expands to SINGLE_THREAD_P
, which is defined in sysdeps/unix/sysv/linux/single-thread.h to expand to __glibc_likely (__libc_multiple_threads == 0)
.