summaryrefslogtreecommitdiff
path: root/libelf/elf32_getehdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'libelf/elf32_getehdr.c')
-rw-r--r--libelf/elf32_getehdr.c46
1 files changed, 34 insertions, 12 deletions
diff --git a/libelf/elf32_getehdr.c b/libelf/elf32_getehdr.c
index bdb2cc41..8009133b 100644
--- a/libelf/elf32_getehdr.c
+++ b/libelf/elf32_getehdr.c
@@ -62,12 +62,11 @@
#endif
-ElfW2(LIBELFBITS,Ehdr) *
-elfw2(LIBELFBITS,getehdr) (elf)
+static ElfW2(LIBELFBITS,Ehdr) *
+getehdr_impl (elf, wrlock)
Elf *elf;
+ int wrlock;
{
- ElfW2(LIBELFBITS,Ehdr) *result;
-
if (elf == NULL)
return NULL;
@@ -77,22 +76,45 @@ elfw2(LIBELFBITS,getehdr) (elf)
return NULL;
}
- rwlock_rdlock (elf->lock);
-
+ again:
if (elf->class == 0)
- elf->class = ELFW(ELFCLASS,LIBELFBITS);
+ {
+ if (!wrlock)
+ {
+ rwlock_unlock (elf->lock);
+ rwlock_wrlock (elf->lock);
+ wrlock = 1;
+ goto again;
+ }
+ elf->class = ELFW(ELFCLASS,LIBELFBITS);
+ }
else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
{
__libelf_seterrno (ELF_E_INVALID_CLASS);
- result = NULL;
- goto out;
+ return NULL;
}
- result = elf->state.ELFW(elf,LIBELFBITS).ehdr;
+ return elf->state.ELFW(elf,LIBELFBITS).ehdr;
+}
+
+ElfW2(LIBELFBITS,Ehdr) *
+__elfw2(LIBELFBITS,getehdr_wrlock) (elf)
+ Elf *elf;
+{
+ return getehdr_impl (elf, 1);
+}
+
+ElfW2(LIBELFBITS,Ehdr) *
+elfw2(LIBELFBITS,getehdr) (elf)
+ Elf *elf;
+{
+ ElfW2(LIBELFBITS,Ehdr) *result;
+ if (elf == NULL)
+ return NULL;
- out:
+ rwlock_rdlock (elf->lock);
+ result = getehdr_impl (elf, 0);
rwlock_unlock (elf->lock);
return result;
}
-INTDEF(elfw2(LIBELFBITS,getehdr))