|
@@ -1,3515 +0,0 @@
|
|
|
-diff -Nur uClibc-git/include/elf.h uClibc-xtensa/include/elf.h
|
|
|
|
|
|
-+++ uClibc-xtensa/include/elf.h 2014-06-03 16:03:19.065886532 +0200
|
|
|
-@@ -3072,8 +3071,11 @@
|
|
|
- #define R_XTENSA_SLOT12_ALT 47
|
|
|
- #define R_XTENSA_SLOT13_ALT 48
|
|
|
- #define R_XTENSA_SLOT14_ALT 49
|
|
|
-+#define R_XTENSA_TLSDESC_FN 50
|
|
|
-+#define R_XTENSA_TLSDESC_ARG 51
|
|
|
-+#define R_XTENSA_TLS_TPOFF 53
|
|
|
- /* Keep this the last entry. */
|
|
|
--#define R_XTENSA_NUM 50
|
|
|
-+#define R_XTENSA_NUM 54
|
|
|
-
|
|
|
- /* C6X specific relocs */
|
|
|
- #define R_C6000_NONE 0
|
|
|
-diff -Nur uClibc-git/include/link.h uClibc-xtensa/include/link.h
|
|
|
|
|
|
-+++ uClibc-xtensa/include/link.h 2014-06-03 15:28:27.185347373 +0200
|
|
|
-@@ -132,6 +132,8 @@
|
|
|
- size_t l_tls_modid;
|
|
|
- /* Nonzero if _dl_init_static_tls should be called for this module */
|
|
|
- unsigned int l_need_tls_init:1;
|
|
|
-+ /* Address of TLS descriptor hash table. */
|
|
|
-+ void *l_tlsdesc_table;
|
|
|
- #endif
|
|
|
- #endif
|
|
|
- };
|
|
|
-diff -Nur uClibc-git/ldso/include/dl-hash.h uClibc-xtensa/ldso/include/dl-hash.h
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/include/dl-hash.h 2014-06-03 15:29:09.505536959 +0200
|
|
|
-@@ -70,6 +70,8 @@
|
|
|
- size_t l_tls_modid;
|
|
|
- /* Nonzero if _dl_init_static_tls should be called for this module */
|
|
|
- unsigned int l_need_tls_init:1;
|
|
|
-+ /* Address of TLS descriptor hash table. */
|
|
|
-+ void *l_tlsdesc_table;
|
|
|
- #endif
|
|
|
-
|
|
|
- ElfW(Addr) mapaddr;
|
|
|
-diff -Nur uClibc-git/ldso/include/inline-hashtab.h uClibc-xtensa/ldso/include/inline-hashtab.h
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/include/inline-hashtab.h 2014-06-03 11:57:42.031052092 +0200
|
|
|
-@@ -0,0 +1,265 @@
|
|
|
-+/*
|
|
|
-+ * The hashcode handling code below is heavily inspired in libiberty's
|
|
|
-+ * hashtab code, but with most adaptation points and support for
|
|
|
-+ * deleting elements removed.
|
|
|
-+ *
|
|
|
-+ * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
|
|
-+ * Contributed by Vladimir Makarov (vmakarov@cygnus.com).
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#ifndef INLINE_HASHTAB_H
|
|
|
-+# define INLINE_HASHTAB_H 1
|
|
|
-+
|
|
|
-+static __always_inline unsigned long
|
|
|
-+higher_prime_number(unsigned long n)
|
|
|
-+{
|
|
|
-+ /* These are primes that are near, but slightly smaller than, a power of two. */
|
|
|
-+ static const unsigned long primes[] = {
|
|
|
-+ 7,
|
|
|
-+ 13,
|
|
|
-+ 31,
|
|
|
-+ 61,
|
|
|
-+ 127,
|
|
|
-+ 251,
|
|
|
-+ 509,
|
|
|
-+ 1021,
|
|
|
-+ 2039,
|
|
|
-+ 4093,
|
|
|
-+ 8191,
|
|
|
-+ 16381,
|
|
|
-+ 32749,
|
|
|
-+ 65521,
|
|
|
-+ 131071,
|
|
|
-+ 262139,
|
|
|
-+ 524287,
|
|
|
-+ 1048573,
|
|
|
-+ 2097143,
|
|
|
-+ 4194301,
|
|
|
-+ 8388593,
|
|
|
-+ 16777213,
|
|
|
-+ 33554393,
|
|
|
-+ 67108859,
|
|
|
-+ 134217689,
|
|
|
-+ 268435399,
|
|
|
-+ 536870909,
|
|
|
-+ 1073741789,
|
|
|
-+ /* 4294967291 */
|
|
|
-+ ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
|
|
|
-+ };
|
|
|
-+ const unsigned long *low = &primes[0];
|
|
|
-+ const unsigned long *high = &primes[ARRAY_SIZE(primes)];
|
|
|
-+
|
|
|
-+ while (low != high) {
|
|
|
-+ const unsigned long *mid = low + (high - low) / 2;
|
|
|
-+ if (n > *mid)
|
|
|
-+ low = mid + 1;
|
|
|
-+ else
|
|
|
-+ high = mid;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+#if 0
|
|
|
-+ /* If we've run out of primes, abort. */
|
|
|
-+ if (n > *low) {
|
|
|
-+ fprintf(stderr, "Cannot find prime bigger than %lu\n", n);
|
|
|
-+ abort();
|
|
|
-+ }
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+ return *low;
|
|
|
-+}
|
|
|
-+
|
|
|
-+struct funcdesc_ht
|
|
|
-+{
|
|
|
-+ /* Table itself */
|
|
|
-+ void **entries;
|
|
|
-+
|
|
|
-+ /* Current size (in entries) of the hash table */
|
|
|
-+ size_t size;
|
|
|
-+
|
|
|
-+ /* Current number of elements */
|
|
|
-+ size_t n_elements;
|
|
|
-+};
|
|
|
-+
|
|
|
-+static __always_inline struct funcdesc_ht *
|
|
|
-+htab_create(void)
|
|
|
-+{
|
|
|
-+ struct funcdesc_ht *ht = _dl_malloc(sizeof(*ht));
|
|
|
-+ size_t ent_size;
|
|
|
-+
|
|
|
-+ if (!ht)
|
|
|
-+ return NULL;
|
|
|
-+ ht->size = 3;
|
|
|
-+ ent_size = sizeof(void *) * ht->size;
|
|
|
-+ ht->entries = _dl_malloc(ent_size);
|
|
|
-+ if (!ht->entries)
|
|
|
-+ return NULL;
|
|
|
-+
|
|
|
-+ ht->n_elements = 0;
|
|
|
-+ _dl_memset(ht->entries, 0, ent_size);
|
|
|
-+
|
|
|
-+ return ht;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * This is only called from _dl_loadaddr_unmap, so it's safe to call
|
|
|
-+ * _dl_free(). See the discussion below.
|
|
|
-+ */
|
|
|
-+static __always_inline void
|
|
|
-+htab_delete(struct funcdesc_ht *htab)
|
|
|
-+{
|
|
|
-+ size_t i;
|
|
|
-+
|
|
|
-+ for (i = htab->size - 1; i >= 0; i--)
|
|
|
-+ if (htab->entries[i])
|
|
|
-+ _dl_free(htab->entries[i]);
|
|
|
-+
|
|
|
-+ _dl_free(htab->entries);
|
|
|
-+ _dl_free(htab);
|
|
|
-+}
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * Similar to htab_find_slot, but without several unwanted side effects:
|
|
|
-+ * - Does not call htab->eq_f when it finds an existing entry.
|
|
|
-+ * - Does not change the count of elements/searches/collisions in the
|
|
|
-+ * hash table.
|
|
|
-+ * This function also assumes there are no deleted entries in the table.
|
|
|
-+ * HASH is the hash value for the element to be inserted.
|
|
|
-+ */
|
|
|
-+static __always_inline void **
|
|
|
-+find_empty_slot_for_expand(struct funcdesc_ht *htab, int hash)
|
|
|
-+{
|
|
|
-+ size_t size = htab->size;
|
|
|
-+ unsigned int index = hash % size;
|
|
|
-+ void **slot = htab->entries + index;
|
|
|
-+ int hash2;
|
|
|
-+
|
|
|
-+ if (!*slot)
|
|
|
-+ return slot;
|
|
|
-+
|
|
|
-+ hash2 = 1 + hash % (size - 2);
|
|
|
-+ for (;;) {
|
|
|
-+ index += hash2;
|
|
|
-+ if (index >= size)
|
|
|
-+ index -= size;
|
|
|
-+
|
|
|
-+ slot = htab->entries + index;
|
|
|
-+ if (!*slot)
|
|
|
-+ return slot;
|
|
|
-+ }
|
|
|
-+}
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * The following function changes size of memory allocated for the
|
|
|
-+ * entries and repeatedly inserts the table elements. The occupancy
|
|
|
-+ * of the table after the call will be about 50%. Naturally the hash
|
|
|
-+ * table must already exist. Remember also that the place of the
|
|
|
-+ * table entries is changed. If memory allocation failures are allowed,
|
|
|
-+ * this function will return zero, indicating that the table could not be
|
|
|
-+ * expanded. If all goes well, it will return a non-zero value.
|
|
|
-+ */
|
|
|
-+static __always_inline int
|
|
|
-+htab_expand(struct funcdesc_ht *htab, int (*hash_fn) (void *))
|
|
|
-+{
|
|
|
-+ void **oentries;
|
|
|
-+ void **olimit;
|
|
|
-+ void **p;
|
|
|
-+ void **nentries;
|
|
|
-+ size_t nsize;
|
|
|
-+
|
|
|
-+ oentries = htab->entries;
|
|
|
-+ olimit = oentries + htab->size;
|
|
|
-+
|
|
|
-+ /*
|
|
|
-+ * Resize only when table after removal of unused elements is either
|
|
|
-+ * too full or too empty.
|
|
|
-+ */
|
|
|
-+ if (htab->n_elements * 2 > htab->size)
|
|
|
-+ nsize = higher_prime_number(htab->n_elements * 2);
|
|
|
-+ else
|
|
|
-+ nsize = htab->size;
|
|
|
-+
|
|
|
-+ nentries = _dl_malloc(sizeof(*nentries) * nsize);
|
|
|
-+ _dl_memset(nentries, 0, sizeof(*nentries) * nsize);
|
|
|
-+ if (nentries == NULL)
|
|
|
-+ return 0;
|
|
|
-+ htab->entries = nentries;
|
|
|
-+ htab->size = nsize;
|
|
|
-+
|
|
|
-+ p = oentries;
|
|
|
-+ do {
|
|
|
-+ if (*p)
|
|
|
-+ *find_empty_slot_for_expand(htab, hash_fn(*p)) = *p;
|
|
|
-+ p++;
|
|
|
-+ } while (p < olimit);
|
|
|
-+
|
|
|
-+#if 0
|
|
|
-+ /*
|
|
|
-+ * We can't tell whether this was allocated by the _dl_malloc()
|
|
|
-+ * built into ld.so or malloc() in the main executable or libc,
|
|
|
-+ * and calling free() for something that wasn't malloc()ed could
|
|
|
-+ * do Very Bad Things (TM). Take the conservative approach
|
|
|
-+ * here, potentially wasting as much memory as actually used by
|
|
|
-+ * the hash table, even if multiple growths occur. That's not
|
|
|
-+ * so bad as to require some overengineered solution that would
|
|
|
-+ * enable us to keep track of how it was allocated.
|
|
|
-+ */
|
|
|
-+ _dl_free(oentries);
|
|
|
-+#endif
|
|
|
-+ return 1;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * This function searches for a hash table slot containing an entry
|
|
|
-+ * equal to the given element. To delete an entry, call this with
|
|
|
-+ * INSERT = 0, then call htab_clear_slot on the slot returned (possibly
|
|
|
-+ * after doing some checks). To insert an entry, call this with
|
|
|
-+ * INSERT = 1, then write the value you want into the returned slot.
|
|
|
-+ * When inserting an entry, NULL may be returned if memory allocation
|
|
|
-+ * fails.
|
|
|
-+ */
|
|
|
-+static __always_inline void **
|
|
|
-+htab_find_slot(struct funcdesc_ht *htab, void *ptr, int insert,
|
|
|
-+ int (*hash_fn)(void *), int (*eq_fn)(void *, void *))
|
|
|
-+{
|
|
|
-+ unsigned int index;
|
|
|
-+ int hash, hash2;
|
|
|
-+ size_t size;
|
|
|
-+ void **entry;
|
|
|
-+
|
|
|
-+ if (htab->size * 3 <= htab->n_elements * 4 &&
|
|
|
-+ htab_expand(htab, hash_fn) == 0)
|
|
|
-+ return NULL;
|
|
|
-+
|
|
|
-+ hash = hash_fn(ptr);
|
|
|
-+
|
|
|
-+ size = htab->size;
|
|
|
-+ index = hash % size;
|
|
|
-+
|
|
|
-+ entry = &htab->entries[index];
|
|
|
-+ if (!*entry)
|
|
|
-+ goto empty_entry;
|
|
|
-+ else if (eq_fn(*entry, ptr))
|
|
|
-+ return entry;
|
|
|
-+
|
|
|
-+ hash2 = 1 + hash % (size - 2);
|
|
|
-+ for (;;) {
|
|
|
-+ index += hash2;
|
|
|
-+ if (index >= size)
|
|
|
-+ index -= size;
|
|
|
-+
|
|
|
-+ entry = &htab->entries[index];
|
|
|
-+ if (!*entry)
|
|
|
-+ goto empty_entry;
|
|
|
-+ else if (eq_fn(*entry, ptr))
|
|
|
-+ return entry;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ empty_entry:
|
|
|
-+ if (!insert)
|
|
|
-+ return NULL;
|
|
|
-+
|
|
|
-+ htab->n_elements++;
|
|
|
-+ return entry;
|
|
|
-+}
|
|
|
-+
|
|
|
-+#endif
|
|
|
-diff -Nur uClibc-git/ldso/include/ldsodefs.h uClibc-xtensa/ldso/include/ldsodefs.h
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/include/ldsodefs.h 2014-06-03 16:10:51.175659505 +0200
|
|
|
-@@ -62,13 +62,18 @@
|
|
|
-
|
|
|
- extern void _dl_allocate_static_tls (struct link_map *map)
|
|
|
- internal_function attribute_hidden;
|
|
|
-+extern int _dl_try_allocate_static_tls (struct link_map* map)
|
|
|
-+ internal_function attribute_hidden;
|
|
|
-
|
|
|
- /* Taken from glibc/elf/dl-reloc.c */
|
|
|
- #define CHECK_STATIC_TLS(sym_map) \
|
|
|
- do { \
|
|
|
-- if (unlikely((sym_map)->l_tls_offset == NO_TLS_OFFSET)) \
|
|
|
-+ if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET, 0)) \
|
|
|
- _dl_allocate_static_tls (sym_map); \
|
|
|
- } while (0)
|
|
|
-+#define TRY_STATIC_TLS(sym_map) \
|
|
|
-+ (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \
|
|
|
-+ || _dl_try_allocate_static_tls (sym_map) == 0)
|
|
|
-
|
|
|
- /* These are internal entry points to the two halves of _dl_allocate_tls,
|
|
|
- only used within rtld.c itself at startup time. */
|
|
|
-diff -Nur uClibc-git/ldso/include/tlsdeschtab.h uClibc-xtensa/ldso/include/tlsdeschtab.h
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/include/tlsdeschtab.h 2014-06-03 14:58:29.681335708 +0200
|
|
|
-@@ -0,0 +1,119 @@
|
|
|
-+/* Hash table for TLS descriptors.
|
|
|
-+ Copyright (C) 2005-2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+ Contributed by Alexandre Oliva <aoliva@redhat.com>
|
|
|
-+
|
|
|
-+ uClibc port by Baruch Siach <baruch@tkos.co.il>
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#ifndef TLSDESCHTAB_H
|
|
|
-+# define TLSDESCHTAB_H 1
|
|
|
-+
|
|
|
-+# ifdef SHARED
|
|
|
-+
|
|
|
-+# include <inline-hashtab.h>
|
|
|
-+
|
|
|
-+inline static int
|
|
|
-+hash_tlsdesc (void *p)
|
|
|
-+{
|
|
|
-+ struct tlsdesc_dynamic_arg *td = p;
|
|
|
-+
|
|
|
-+ /* We know all entries are for the same module, so ti_offset is the
|
|
|
-+ only distinguishing entry. */
|
|
|
-+ return td->tlsinfo.ti_offset;
|
|
|
-+}
|
|
|
-+
|
|
|
-+inline static int
|
|
|
-+eq_tlsdesc (void *p, void *q)
|
|
|
-+{
|
|
|
-+ struct tlsdesc_dynamic_arg *tdp = p, *tdq = q;
|
|
|
-+
|
|
|
-+ return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset;
|
|
|
-+}
|
|
|
-+
|
|
|
-+inline static int
|
|
|
-+map_generation (struct link_map *map)
|
|
|
-+{
|
|
|
-+ size_t idx = map->l_tls_modid;
|
|
|
-+ struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
|
|
|
-+
|
|
|
-+ /* Find the place in the dtv slotinfo list. */
|
|
|
-+ do
|
|
|
-+ {
|
|
|
-+ /* Does it fit in the array of this list element? */
|
|
|
-+ if (idx < listp->len)
|
|
|
-+ {
|
|
|
-+ /* We should never get here for a module in static TLS, so
|
|
|
-+ we can assume that, if the generation count is zero, we
|
|
|
-+ still haven't determined the generation count for this
|
|
|
-+ module. */
|
|
|
-+ if (listp->slotinfo[idx].gen)
|
|
|
-+ return listp->slotinfo[idx].gen;
|
|
|
-+ else
|
|
|
-+ break;
|
|
|
-+ }
|
|
|
-+ idx -= listp->len;
|
|
|
-+ listp = listp->next;
|
|
|
-+ }
|
|
|
-+ while (listp != NULL);
|
|
|
-+
|
|
|
-+ /* If we get to this point, the module still hasn't been assigned an
|
|
|
-+ entry in the dtv slotinfo data structures, and it will when we're
|
|
|
-+ done with relocations. At that point, the module will get a
|
|
|
-+ generation number that is one past the current generation, so
|
|
|
-+ return exactly that. */
|
|
|
-+ return GL(dl_tls_generation) + 1;
|
|
|
-+}
|
|
|
-+
|
|
|
-+void *
|
|
|
-+internal_function
|
|
|
-+_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
|
|
|
-+{
|
|
|
-+ struct funcdesc_ht *ht;
|
|
|
-+ void **entry;
|
|
|
-+ struct tlsdesc_dynamic_arg *td, test;
|
|
|
-+
|
|
|
-+ ht = map->l_tlsdesc_table;
|
|
|
-+ if (! ht)
|
|
|
-+ {
|
|
|
-+ ht = htab_create ();
|
|
|
-+ if (! ht)
|
|
|
-+ return 0;
|
|
|
-+ map->l_tlsdesc_table = ht;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ test.tlsinfo.ti_module = map->l_tls_modid;
|
|
|
-+ test.tlsinfo.ti_offset = ti_offset;
|
|
|
-+ entry = htab_find_slot (ht, &test, 1, hash_tlsdesc, eq_tlsdesc);
|
|
|
-+ if (*entry)
|
|
|
-+ {
|
|
|
-+ td = *entry;
|
|
|
-+ return td;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ *entry = td = _dl_malloc (sizeof (struct tlsdesc_dynamic_arg));
|
|
|
-+ /* This may be higher than the map's generation, but it doesn't
|
|
|
-+ matter much. Worst case, we'll have one extra DTV update per
|
|
|
-+ thread. */
|
|
|
-+ td->gen_count = map_generation (map);
|
|
|
-+ td->tlsinfo = test.tlsinfo;
|
|
|
-+
|
|
|
-+ return td;
|
|
|
-+}
|
|
|
-+
|
|
|
-+# endif /* SHARED */
|
|
|
-+
|
|
|
-+#endif
|
|
|
-diff -Nur uClibc-git/ldso/ldso/dl-tls.c uClibc-xtensa/ldso/ldso/dl-tls.c
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/ldso/dl-tls.c 2014-06-03 16:10:28.547570023 +0200
|
|
|
-@@ -100,20 +100,16 @@
|
|
|
- * the static TLS area already allocated for each running thread. If this
|
|
|
- * object's TLS segment is too big to fit, we fail. If it fits,
|
|
|
- * we set MAP->l_tls_offset and return.
|
|
|
-- * This function intentionally does not return any value but signals error
|
|
|
-- * directly, as static TLS should be rare and code handling it should
|
|
|
-- * not be inlined as much as possible.
|
|
|
- */
|
|
|
--void
|
|
|
--internal_function __attribute_noinline__
|
|
|
--_dl_allocate_static_tls (struct link_map *map)
|
|
|
-+int
|
|
|
-+internal_function
|
|
|
-+_dl_try_allocate_static_tls (struct link_map* map)
|
|
|
- {
|
|
|
- /* If the alignment requirements are too high fail. */
|
|
|
- if (map->l_tls_align > _dl_tls_static_align)
|
|
|
- {
|
|
|
- fail:
|
|
|
-- _dl_dprintf(2, "cannot allocate memory in static TLS block");
|
|
|
-- _dl_exit(30);
|
|
|
-+ return -1;
|
|
|
- }
|
|
|
-
|
|
|
- # ifdef TLS_TCB_AT_TP
|
|
|
-@@ -169,6 +165,23 @@
|
|
|
- }
|
|
|
- else
|
|
|
- map->l_need_tls_init = 1;
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ * This function intentionally does not return any value but signals error
|
|
|
-+ * directly, as static TLS should be rare and code handling it should
|
|
|
-+ * not be inlined as much as possible.
|
|
|
-+ */
|
|
|
-+void
|
|
|
-+internal_function __attribute_noinline__
|
|
|
-+_dl_allocate_static_tls (struct link_map *map)
|
|
|
-+{
|
|
|
-+ if (_dl_try_allocate_static_tls (map)) {
|
|
|
-+ _dl_dprintf(2, "cannot allocate memory in static TLS block");
|
|
|
-+ _dl_exit(30);
|
|
|
-+ }
|
|
|
- }
|
|
|
-
|
|
|
- #ifdef SHARED
|
|
|
-diff -Nur uClibc-git/ldso/ldso/fdpic/dl-inlines.h uClibc-xtensa/ldso/ldso/fdpic/dl-inlines.h
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/ldso/fdpic/dl-inlines.h 2014-06-03 11:57:43.263058897 +0200
|
|
|
-@@ -5,6 +5,8 @@
|
|
|
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
|
|
|
- */
|
|
|
-
|
|
|
-+#include <inline-hashtab.h>
|
|
|
-+
|
|
|
- /* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete load map. */
|
|
|
- static __always_inline void
|
|
|
- __dl_init_loadaddr_map(struct elf32_fdpic_loadaddr *loadaddr, Elf32_Addr dl_boot_got_pointer,
|
|
|
-@@ -143,269 +145,18 @@
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
--/*
|
|
|
-- * The hashcode handling code below is heavily inspired in libiberty's
|
|
|
-- * hashtab code, but with most adaptation points and support for
|
|
|
-- * deleting elements removed.
|
|
|
-- *
|
|
|
-- * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
|
|
-- * Contributed by Vladimir Makarov (vmakarov@cygnus.com).
|
|
|
-- */
|
|
|
--static __always_inline unsigned long
|
|
|
--higher_prime_number(unsigned long n)
|
|
|
--{
|
|
|
-- /* These are primes that are near, but slightly smaller than, a power of two. */
|
|
|
-- static const unsigned long primes[] = {
|
|
|
-- 7,
|
|
|
-- 13,
|
|
|
-- 31,
|
|
|
-- 61,
|
|
|
-- 127,
|
|
|
-- 251,
|
|
|
-- 509,
|
|
|
-- 1021,
|
|
|
-- 2039,
|
|
|
-- 4093,
|
|
|
-- 8191,
|
|
|
-- 16381,
|
|
|
-- 32749,
|
|
|
-- 65521,
|
|
|
-- 131071,
|
|
|
-- 262139,
|
|
|
-- 524287,
|
|
|
-- 1048573,
|
|
|
-- 2097143,
|
|
|
-- 4194301,
|
|
|
-- 8388593,
|
|
|
-- 16777213,
|
|
|
-- 33554393,
|
|
|
-- 67108859,
|
|
|
-- 134217689,
|
|
|
-- 268435399,
|
|
|
-- 536870909,
|
|
|
-- 1073741789,
|
|
|
-- /* 4294967291 */
|
|
|
-- ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
|
|
|
-- };
|
|
|
-- const unsigned long *low = &primes[0];
|
|
|
-- const unsigned long *high = &primes[ARRAY_SIZE(primes)];
|
|
|
--
|
|
|
-- while (low != high) {
|
|
|
-- const unsigned long *mid = low + (high - low) / 2;
|
|
|
-- if (n > *mid)
|
|
|
-- low = mid + 1;
|
|
|
-- else
|
|
|
-- high = mid;
|
|
|
-- }
|
|
|
--
|
|
|
--#if 0
|
|
|
-- /* If we've run out of primes, abort. */
|
|
|
-- if (n > *low) {
|
|
|
-- fprintf(stderr, "Cannot find prime bigger than %lu\n", n);
|
|
|
-- abort();
|
|
|
-- }
|
|
|
--#endif
|
|
|
--
|
|
|
-- return *low;
|
|
|
--}
|
|
|
--
|
|
|
--struct funcdesc_ht
|
|
|
--{
|
|
|
-- /* Table itself */
|
|
|
-- struct funcdesc_value **entries;
|
|
|
--
|
|
|
-- /* Current size (in entries) of the hash table */
|
|
|
-- size_t size;
|
|
|
--
|
|
|
-- /* Current number of elements */
|
|
|
-- size_t n_elements;
|
|
|
--};
|
|
|
--
|
|
|
--static __always_inline int
|
|
|
--hash_pointer(const void *p)
|
|
|
-+static int
|
|
|
-+hash_pointer(void *p)
|
|
|
- {
|
|
|
- return (int) ((long)p >> 3);
|
|
|
- }
|
|
|
-
|
|
|
--static __always_inline struct funcdesc_ht *
|
|
|
--htab_create(void)
|
|
|
--{
|
|
|
-- struct funcdesc_ht *ht = _dl_malloc(sizeof(*ht));
|
|
|
-- size_t ent_size;
|
|
|
--
|
|
|
-- if (!ht)
|
|
|
-- return NULL;
|
|
|
-- ht->size = 3;
|
|
|
-- ent_size = sizeof(struct funcdesc_ht_value *) * ht->size;
|
|
|
-- ht->entries = _dl_malloc(ent_size);
|
|
|
-- if (!ht->entries)
|
|
|
-- return NULL;
|
|
|
--
|
|
|
-- ht->n_elements = 0;
|
|
|
-- _dl_memset(ht->entries, 0, ent_size);
|
|
|
--
|
|
|
-- return ht;
|
|
|
--}
|
|
|
--
|
|
|
--/*
|
|
|
-- * This is only called from _dl_loadaddr_unmap, so it's safe to call
|
|
|
-- * _dl_free(). See the discussion below.
|
|
|
-- */
|
|
|
--static __always_inline void
|
|
|
--htab_delete(struct funcdesc_ht *htab)
|
|
|
--{
|
|
|
-- size_t i;
|
|
|
--
|
|
|
-- for (i = htab->size - 1; i >= 0; i--)
|
|
|
-- if (htab->entries[i])
|
|
|
-- _dl_free(htab->entries[i]);
|
|
|
--
|
|
|
-- _dl_free(htab->entries);
|
|
|
-- _dl_free(htab);
|
|
|
--}
|
|
|
--
|
|
|
--/*
|
|
|
-- * Similar to htab_find_slot, but without several unwanted side effects:
|
|
|
-- * - Does not call htab->eq_f when it finds an existing entry.
|
|
|
-- * - Does not change the count of elements/searches/collisions in the
|
|
|
-- * hash table.
|
|
|
-- * This function also assumes there are no deleted entries in the table.
|
|
|
-- * HASH is the hash value for the element to be inserted.
|
|
|
-- */
|
|
|
--static __always_inline struct funcdesc_value **
|
|
|
--find_empty_slot_for_expand(struct funcdesc_ht *htab, int hash)
|
|
|
-+static int
|
|
|
-+eq_pointer(void *p, void *q)
|
|
|
- {
|
|
|
-- size_t size = htab->size;
|
|
|
-- unsigned int index = hash % size;
|
|
|
-- struct funcdesc_value **slot = htab->entries + index;
|
|
|
-- int hash2;
|
|
|
--
|
|
|
-- if (!*slot)
|
|
|
-- return slot;
|
|
|
--
|
|
|
-- hash2 = 1 + hash % (size - 2);
|
|
|
-- for (;;) {
|
|
|
-- index += hash2;
|
|
|
-- if (index >= size)
|
|
|
-- index -= size;
|
|
|
--
|
|
|
-- slot = htab->entries + index;
|
|
|
-- if (!*slot)
|
|
|
-- return slot;
|
|
|
-- }
|
|
|
--}
|
|
|
--
|
|
|
--/*
|
|
|
-- * The following function changes size of memory allocated for the
|
|
|
-- * entries and repeatedly inserts the table elements. The occupancy
|
|
|
-- * of the table after the call will be about 50%. Naturally the hash
|
|
|
-- * table must already exist. Remember also that the place of the
|
|
|
-- * table entries is changed. If memory allocation failures are allowed,
|
|
|
-- * this function will return zero, indicating that the table could not be
|
|
|
-- * expanded. If all goes well, it will return a non-zero value.
|
|
|
-- */
|
|
|
--static __always_inline int
|
|
|
--htab_expand(struct funcdesc_ht *htab)
|
|
|
--{
|
|
|
-- struct funcdesc_value **oentries;
|
|
|
-- struct funcdesc_value **olimit;
|
|
|
-- struct funcdesc_value **p;
|
|
|
-- struct funcdesc_value **nentries;
|
|
|
-- size_t nsize;
|
|
|
--
|
|
|
-- oentries = htab->entries;
|
|
|
-- olimit = oentries + htab->size;
|
|
|
--
|
|
|
-- /*
|
|
|
-- * Resize only when table after removal of unused elements is either
|
|
|
-- * too full or too empty.
|
|
|
-- */
|
|
|
-- if (htab->n_elements * 2 > htab->size)
|
|
|
-- nsize = higher_prime_number(htab->n_elements * 2);
|
|
|
-- else
|
|
|
-- nsize = htab->size;
|
|
|
--
|
|
|
-- nentries = _dl_malloc(sizeof(*nentries) * nsize);
|
|
|
-- _dl_memset(nentries, 0, sizeof(*nentries) * nsize);
|
|
|
-- if (nentries == NULL)
|
|
|
-- return 0;
|
|
|
-- htab->entries = nentries;
|
|
|
-- htab->size = nsize;
|
|
|
--
|
|
|
-- p = oentries;
|
|
|
-- do {
|
|
|
-- if (*p)
|
|
|
-- *find_empty_slot_for_expand(htab, hash_pointer((*p)->entry_point)) = *p;
|
|
|
-- p++;
|
|
|
-- } while (p < olimit);
|
|
|
--
|
|
|
--#if 0
|
|
|
-- /*
|
|
|
-- * We can't tell whether this was allocated by the _dl_malloc()
|
|
|
-- * built into ld.so or malloc() in the main executable or libc,
|
|
|
-- * and calling free() for something that wasn't malloc()ed could
|
|
|
-- * do Very Bad Things (TM). Take the conservative approach
|
|
|
-- * here, potentially wasting as much memory as actually used by
|
|
|
-- * the hash table, even if multiple growths occur. That's not
|
|
|
-- * so bad as to require some overengineered solution that would
|
|
|
-- * enable us to keep track of how it was allocated.
|
|
|
-- */
|
|
|
-- _dl_free(oentries);
|
|
|
--#endif
|
|
|
-- return 1;
|
|
|
--}
|
|
|
--
|
|
|
--/*
|
|
|
-- * This function searches for a hash table slot containing an entry
|
|
|
-- * equal to the given element. To delete an entry, call this with
|
|
|
-- * INSERT = 0, then call htab_clear_slot on the slot returned (possibly
|
|
|
-- * after doing some checks). To insert an entry, call this with
|
|
|
-- * INSERT = 1, then write the value you want into the returned slot.
|
|
|
-- * When inserting an entry, NULL may be returned if memory allocation
|
|
|
-- * fails.
|
|
|
-- */
|
|
|
--static __always_inline struct funcdesc_value **
|
|
|
--htab_find_slot(struct funcdesc_ht *htab, void *ptr, int insert)
|
|
|
--{
|
|
|
-- unsigned int index;
|
|
|
-- int hash, hash2;
|
|
|
-- size_t size;
|
|
|
-- struct funcdesc_value **entry;
|
|
|
--
|
|
|
-- if (htab->size * 3 <= htab->n_elements * 4 &&
|
|
|
-- htab_expand(htab) == 0)
|
|
|
-- return NULL;
|
|
|
--
|
|
|
-- hash = hash_pointer(ptr);
|
|
|
--
|
|
|
-- size = htab->size;
|
|
|
-- index = hash % size;
|
|
|
--
|
|
|
-- entry = &htab->entries[index];
|
|
|
-- if (!*entry)
|
|
|
-- goto empty_entry;
|
|
|
-- else if ((*entry)->entry_point == ptr)
|
|
|
-- return entry;
|
|
|
--
|
|
|
-- hash2 = 1 + hash % (size - 2);
|
|
|
-- for (;;) {
|
|
|
-- index += hash2;
|
|
|
-- if (index >= size)
|
|
|
-- index -= size;
|
|
|
--
|
|
|
-- entry = &htab->entries[index];
|
|
|
-- if (!*entry)
|
|
|
-- goto empty_entry;
|
|
|
-- else if ((*entry)->entry_point == ptr)
|
|
|
-- return entry;
|
|
|
-- }
|
|
|
--
|
|
|
-- empty_entry:
|
|
|
-- if (!insert)
|
|
|
-- return NULL;
|
|
|
-+ struct funcdesc_value *entry = p;
|
|
|
-
|
|
|
-- htab->n_elements++;
|
|
|
-- return entry;
|
|
|
-+ return entry->entry_point == q;
|
|
|
- }
|
|
|
-
|
|
|
- void *
|
|
|
-@@ -424,7 +175,7 @@
|
|
|
- tpnt->funcdesc_ht = ht;
|
|
|
- }
|
|
|
-
|
|
|
-- entry = htab_find_slot(ht, entry_point, 1);
|
|
|
-+ entry = htab_find_slot(ht, entry_point, 1, hash_pointer, eq_pointer);
|
|
|
- if (*entry) {
|
|
|
- _dl_assert((*entry)->entry_point == entry_point);
|
|
|
- return _dl_stabilize_funcdesc(*entry);
|
|
|
-@@ -459,7 +210,8 @@
|
|
|
- if (fd->got_value != rpnt->loadaddr.got_value)
|
|
|
- continue;
|
|
|
-
|
|
|
-- address = htab_find_slot(rpnt->funcdesc_ht, (void *)fd->entry_point, 0);
|
|
|
-+ address = htab_find_slot(rpnt->funcdesc_ht, (void *)fd->entry_point, 0,
|
|
|
-+ hash_pointer, eq_pointer);
|
|
|
-
|
|
|
- if (address && *(struct funcdesc_value *const*)address == fd) {
|
|
|
- address = (*(struct funcdesc_value *const*)address)->entry_point;
|
|
|
-diff -Nur uClibc-git/ldso/ldso/xtensa/dl-debug.h uClibc-xtensa/ldso/ldso/xtensa/dl-debug.h
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/ldso/xtensa/dl-debug.h 2014-06-03 12:22:20.032058866 +0200
|
|
|
-@@ -8,54 +8,31 @@
|
|
|
-
|
|
|
- static const char * const _dl_reltypes_tab[] =
|
|
|
- {
|
|
|
-- "R_XTENSA_NONE",
|
|
|
-- "R_XTENSA_32",
|
|
|
-- "R_XTENSA_RTLD",
|
|
|
-- "R_XTENSA_GLOB_DAT",
|
|
|
-- "R_XTENSA_JMP_SLOT",
|
|
|
-- "R_XTENSA_RELATIVE",
|
|
|
-- "R_XTENSA_PLT",
|
|
|
-- "R_XTENSA_UNUSED7",
|
|
|
-- "R_XTENSA_OP0",
|
|
|
-- "R_XTENSA_OP1",
|
|
|
-- "R_XTENSA_OP2",
|
|
|
-- "R_XTENSA_ASM_EXPAND",
|
|
|
-- "R_XTENSA_ASM_SIMPLIFY",
|
|
|
-- "R_XTENSA_UNUSED13",
|
|
|
-- "R_XTENSA_UNUSED14",
|
|
|
-- "R_XTENSA_GNU_VTINHERIT",
|
|
|
-- "R_XTENSA_GNU_VTENTRY",
|
|
|
-- "R_XTENSA_DIFF8",
|
|
|
-- "R_XTENSA_DIFF16",
|
|
|
-- "R_XTENSA_DIFF32",
|
|
|
-- "R_XTENSA_SLOT0_OP",
|
|
|
-- "R_XTENSA_SLOT1_OP",
|
|
|
-- "R_XTENSA_SLOT2_OP",
|
|
|
-- "R_XTENSA_SLOT3_OP",
|
|
|
-- "R_XTENSA_SLOT4_OP",
|
|
|
-- "R_XTENSA_SLOT5_OP",
|
|
|
-- "R_XTENSA_SLOT6_OP",
|
|
|
-- "R_XTENSA_SLOT7_OP",
|
|
|
-- "R_XTENSA_SLOT8_OP",
|
|
|
-- "R_XTENSA_SLOT9_OP",
|
|
|
-- "R_XTENSA_SLOT10_OP",
|
|
|
-- "R_XTENSA_SLOT11_OP",
|
|
|
-- "R_XTENSA_SLOT12_OP",
|
|
|
-- "R_XTENSA_SLOT13_OP",
|
|
|
-- "R_XTENSA_SLOT14_OP",
|
|
|
-- "R_XTENSA_SLOT0_ALT",
|
|
|
-- "R_XTENSA_SLOT1_ALT",
|
|
|
-- "R_XTENSA_SLOT2_ALT",
|
|
|
-- "R_XTENSA_SLOT3_ALT",
|
|
|
-- "R_XTENSA_SLOT4_ALT",
|
|
|
-- "R_XTENSA_SLOT5_ALT",
|
|
|
-- "R_XTENSA_SLOT6_ALT",
|
|
|
-- "R_XTENSA_SLOT7_ALT",
|
|
|
-- "R_XTENSA_SLOT8_ALT",
|
|
|
-- "R_XTENSA_SLOT9_ALT",
|
|
|
-- "R_XTENSA_SLOT10_ALT",
|
|
|
-- "R_XTENSA_SLOT11_ALT",
|
|
|
-- "R_XTENSA_SLOT12_ALT",
|
|
|
-- "R_XTENSA_SLOT13_ALT",
|
|
|
-- "R_XTENSA_SLOT14_ALT"
|
|
|
-+ [0] "R_XTENSA_NONE", "R_XTENSA_32",
|
|
|
-+ [2] "R_XTENSA_RTLD", "R_XTENSA_GLOB_DAT",
|
|
|
-+ [4] "R_XTENSA_JMP_SLOT", "R_XTENSA_RELATIVE",
|
|
|
-+ [6] "R_XTENSA_PLT", "R_XTENSA_UNUSED7",
|
|
|
-+ [8] "R_XTENSA_OP0", "R_XTENSA_OP1",
|
|
|
-+ [10] "R_XTENSA_OP2", "R_XTENSA_ASM_EXPAND",
|
|
|
-+ [12] "R_XTENSA_ASM_SIMPLIFY", "R_XTENSA_UNUSED13",
|
|
|
-+ [14] "R_XTENSA_UNUSED14", "R_XTENSA_GNU_VTINHERIT",
|
|
|
-+ [16] "R_XTENSA_GNU_VTENTRY", "R_XTENSA_DIFF8",
|
|
|
-+ [18] "R_XTENSA_DIFF16", "R_XTENSA_DIFF32",
|
|
|
-+ [20] "R_XTENSA_SLOT0_OP", "R_XTENSA_SLOT1_OP",
|
|
|
-+ [22] "R_XTENSA_SLOT2_OP", "R_XTENSA_SLOT3_OP",
|
|
|
-+ [24] "R_XTENSA_SLOT4_OP", "R_XTENSA_SLOT5_OP",
|
|
|
-+ [26] "R_XTENSA_SLOT6_OP", "R_XTENSA_SLOT7_OP",
|
|
|
-+ [28] "R_XTENSA_SLOT8_OP", "R_XTENSA_SLOT9_OP",
|
|
|
-+ [30] "R_XTENSA_SLOT10_OP", "R_XTENSA_SLOT11_OP",
|
|
|
-+ [32] "R_XTENSA_SLOT12_OP", "R_XTENSA_SLOT13_OP",
|
|
|
-+ [34] "R_XTENSA_SLOT14_OP", "R_XTENSA_SLOT0_ALT",
|
|
|
-+ [36] "R_XTENSA_SLOT1_ALT", "R_XTENSA_SLOT2_ALT",
|
|
|
-+ [38] "R_XTENSA_SLOT3_ALT", "R_XTENSA_SLOT4_ALT",
|
|
|
-+ [40] "R_XTENSA_SLOT5_ALT", "R_XTENSA_SLOT6_ALT",
|
|
|
-+ [42] "R_XTENSA_SLOT7_ALT", "R_XTENSA_SLOT8_ALT",
|
|
|
-+ [44] "R_XTENSA_SLOT9_ALT", "R_XTENSA_SLOT10_ALT",
|
|
|
-+ [46] "R_XTENSA_SLOT11_ALT", "R_XTENSA_SLOT12_ALT",
|
|
|
-+ [48] "R_XTENSA_SLOT13_ALT", "R_XTENSA_SLOT14_ALT",
|
|
|
-+ [50] "R_XTENSA_TLSDESC_FN", "R_XTENSA_TLSDESC_ARG",
|
|
|
-+ [52] "R_XTENSA_TLS_TPOFF"
|
|
|
- };
|
|
|
-diff -Nur uClibc-git/ldso/ldso/xtensa/dl-startup.h uClibc-xtensa/ldso/ldso/xtensa/dl-startup.h
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/ldso/xtensa/dl-startup.h 2014-06-03 12:22:20.112059404 +0200
|
|
|
-@@ -11,7 +11,6 @@
|
|
|
- __asm__ (
|
|
|
- " .text\n"
|
|
|
- " .align 4\n"
|
|
|
-- " .literal_position\n"
|
|
|
- " .global _start\n"
|
|
|
- " .type _start, @function\n"
|
|
|
- " .hidden _start\n"
|
|
|
-diff -Nur uClibc-git/ldso/ldso/xtensa/dl-sysdep.h uClibc-xtensa/ldso/ldso/xtensa/dl-sysdep.h
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/ldso/xtensa/dl-sysdep.h 2014-06-03 12:22:20.340060933 +0200
|
|
|
-@@ -78,10 +78,13 @@
|
|
|
- struct elf_resolve;
|
|
|
- extern unsigned long _dl_linux_resolver (struct elf_resolve *, int);
|
|
|
-
|
|
|
--/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
|
|
|
-- undefined references should not be allowed to define the value. */
|
|
|
-+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
|
|
|
-+ TLS variable, so undefined references should not be allowed to define
|
|
|
-+ the value. */
|
|
|
- #define elf_machine_type_class(type) \
|
|
|
-- (((type) == R_XTENSA_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
|
|
|
-+ (((type) == R_XTENSA_JMP_SLOT || (type) == R_XTENSA_TLS_TPOFF \
|
|
|
-+ || (type) == R_XTENSA_TLSDESC_FN || (type) == R_XTENSA_TLSDESC_ARG) \
|
|
|
-+ * ELF_RTYPE_CLASS_PLT)
|
|
|
-
|
|
|
- /* Return the link-time address of _DYNAMIC. */
|
|
|
- static __always_inline Elf32_Addr
|
|
|
-diff -Nur uClibc-git/ldso/ldso/xtensa/dl-tlsdesc.S uClibc-xtensa/ldso/ldso/xtensa/dl-tlsdesc.S
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/ldso/xtensa/dl-tlsdesc.S 2014-06-03 12:22:20.340060933 +0200
|
|
|
-@@ -0,0 +1,96 @@
|
|
|
-+/* Thread-local storage handling in the ELF dynamic linker. Xtensa version.
|
|
|
-+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library. If not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#include <sysdep.h>
|
|
|
-+#include <tls.h>
|
|
|
-+#include "tlsdesc.h"
|
|
|
-+
|
|
|
-+
|
|
|
-+ .text
|
|
|
-+ .align 4
|
|
|
-+ .hidden _dl_tlsdesc_return
|
|
|
-+ .global _dl_tlsdesc_return
|
|
|
-+ .type _dl_tlsdesc_return, @function
|
|
|
-+_dl_tlsdesc_return:
|
|
|
-+ entry a1, 16
|
|
|
-+ rur.threadptr a3
|
|
|
-+ add a2, a2, a3
|
|
|
-+ retw
|
|
|
-+ .size _dl_tlsdesc_return, .-_dl_tlsdesc_return
|
|
|
-+
|
|
|
-+#ifdef SHARED
|
|
|
-+
|
|
|
-+
|
|
|
-+ /* This function is used for symbols that need dynamic TLS.
|
|
|
-+
|
|
|
-+ The argument passed to this function points to the TLS descriptor.
|
|
|
-+
|
|
|
-+ The assembly code that follows is a rendition of the following
|
|
|
-+ C code, hand-optimized a little bit.
|
|
|
-+
|
|
|
-+ ptrdiff_t
|
|
|
-+ _dl_tlsdesc_dynamic(struct tlsdesc_dynamic_arg *td)
|
|
|
-+ {
|
|
|
-+ dtv_t *dtv = (dtv_t *)THREAD_DTV();
|
|
|
-+ if (td->gen_count <= dtv[0].counter
|
|
|
-+ && dtv[td->tlsinfo.ti_module].pointer.val
|
|
|
-+ != TLS_DTV_UNALLOCATED)
|
|
|
-+ return dtv[td->tlsinfo.ti_module].pointer.val
|
|
|
-+ + td->tlsinfo.ti_offset - __builtin_thread_pointer();
|
|
|
-+ return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer();
|
|
|
-+ }
|
|
|
-+ */
|
|
|
-+
|
|
|
-+ .align 4
|
|
|
-+ .hidden _dl_tlsdesc_dynamic
|
|
|
-+ .global _dl_tlsdesc_dynamic
|
|
|
-+ .type _dl_tlsdesc_dynamic, @function
|
|
|
-+_dl_tlsdesc_dynamic:
|
|
|
-+ entry a1, 32
|
|
|
-+
|
|
|
-+ /* dtv_t *dtv = (dtv_t *)THREAD_DTV(); */
|
|
|
-+ rur.threadptr a3
|
|
|
-+ l32i a4, a3, 0
|
|
|
-+
|
|
|
-+ /* if (td->gen_count <= dtv[0].counter */
|
|
|
-+ l32i a6, a2, TLSDESC_GEN_COUNT
|
|
|
-+ l32i a7, a4, 0
|
|
|
-+ blt a7, a6, .Lslow
|
|
|
-+
|
|
|
-+ /* && dtv[td->tlsinfo.ti_module].pointer.val != TLS_DTV_UNALLOCATED) */
|
|
|
-+ l32i a6, a2, TLSDESC_MODID
|
|
|
-+ addx8 a6, a3, a6
|
|
|
-+ l32i a6, a6, 0
|
|
|
-+ beqi a6, -1, .Lslow
|
|
|
-+
|
|
|
-+ /* return dtv[td->tlsinfo.ti_module].pointer.val
|
|
|
-+ + td->tlsinfo.ti_offset - __builtin_thread_pointer(); */
|
|
|
-+ l32i a6, a2, TLSDESC_MODOFF
|
|
|
-+ sub a2, a6, a3
|
|
|
-+ retw
|
|
|
-+
|
|
|
-+ /* return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer(); */
|
|
|
-+.Lslow:
|
|
|
-+ mov a10, a2
|
|
|
-+ movi a8, __tls_get_addr
|
|
|
-+ callx8 a8
|
|
|
-+ sub a2, a10, a3
|
|
|
-+ retw
|
|
|
-+ .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
|
|
|
-+
|
|
|
-+#endif /* SHARED */
|
|
|
-diff -Nur uClibc-git/ldso/ldso/xtensa/elfinterp.c uClibc-xtensa/ldso/ldso/xtensa/elfinterp.c
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/ldso/xtensa/elfinterp.c 2014-06-03 12:22:20.340060933 +0200
|
|
|
-@@ -31,6 +31,8 @@
|
|
|
- */
|
|
|
-
|
|
|
- #include "ldso.h"
|
|
|
-+#include "dl-tls.h"
|
|
|
-+#include "tlsdeschtab.h"
|
|
|
-
|
|
|
- unsigned long
|
|
|
- _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
|
|
|
-@@ -146,6 +148,9 @@
|
|
|
- int reloc_type;
|
|
|
- int symtab_index;
|
|
|
- char *symname;
|
|
|
-+#if defined USE_TLS && USE_TLS
|
|
|
-+ struct elf_resolve *tls_tpnt = NULL;
|
|
|
-+#endif
|
|
|
- struct symbol_ref sym_ref;
|
|
|
- ElfW(Addr) *reloc_addr;
|
|
|
- ElfW(Addr) symbol_addr;
|
|
|
-@@ -172,15 +177,22 @@
|
|
|
- * here, so all bases should be covered.
|
|
|
- */
|
|
|
- if (unlikely (!symbol_addr &&
|
|
|
-+ ELF_ST_TYPE (sym_ref.sym->st_info) != STT_TLS &&
|
|
|
- ELF_ST_BIND (sym_ref.sym->st_info) != STB_WEAK)) {
|
|
|
-- _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
|
|
|
-- _dl_progname, symname);
|
|
|
-- _dl_exit (1);
|
|
|
-+ return 1;
|
|
|
- }
|
|
|
- if (_dl_trace_prelink) {
|
|
|
- _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
|
|
|
- &sym_ref, elf_machine_type_class(reloc_type));
|
|
|
- }
|
|
|
-+#if defined USE_TLS && USE_TLS
|
|
|
-+ tls_tpnt = sym_ref.tpnt;
|
|
|
-+#endif
|
|
|
-+ } else {
|
|
|
-+ symbol_addr =symtab[symtab_index].st_value;
|
|
|
-+#if defined USE_TLS && USE_TLS
|
|
|
-+ tls_tpnt = tpnt;
|
|
|
-+#endif
|
|
|
- }
|
|
|
-
|
|
|
- #if defined (__SUPPORT_LD_DEBUG__)
|
|
|
-@@ -198,8 +210,8 @@
|
|
|
-
|
|
|
- case R_XTENSA_RTLD:
|
|
|
- if (rpnt->r_addend == 1) {
|
|
|
-- /* Grab the function pointer stashed at the beginning of the
|
|
|
-- GOT by the GOT_INIT function. */
|
|
|
-+ /* Grab the function pointer stashed at the beginning
|
|
|
-+ of the GOT by the GOT_INIT function. */
|
|
|
- *reloc_addr = *(ElfW(Addr) *) tpnt->dynamic_info[DT_PLTGOT];
|
|
|
- } else if (rpnt->r_addend == 2) {
|
|
|
- /* Store the link map for the object. */
|
|
|
-@@ -213,6 +225,35 @@
|
|
|
- *reloc_addr += tpnt->loadaddr + rpnt->r_addend;
|
|
|
- break;
|
|
|
-
|
|
|
-+#if defined USE_TLS && USE_TLS
|
|
|
-+ case R_XTENSA_TLS_TPOFF:
|
|
|
-+ CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
|
|
|
-+ *reloc_addr = symbol_addr + tls_tpnt->l_tls_offset + rpnt->r_addend;
|
|
|
-+ break;
|
|
|
-+ case R_XTENSA_TLSDESC_FN:
|
|
|
-+#ifndef SHARED
|
|
|
-+ CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
|
|
|
-+#else
|
|
|
-+ if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
|
|
|
-+ *reloc_addr = (ElfW(Addr)) _dl_tlsdesc_dynamic;
|
|
|
-+ else
|
|
|
-+#endif
|
|
|
-+ *reloc_addr = (ElfW(Addr)) _dl_tlsdesc_return;
|
|
|
-+ break;
|
|
|
-+ case R_XTENSA_TLSDESC_ARG:
|
|
|
-+#ifndef SHARED
|
|
|
-+ CHECK_STATIC_TLS((struct link_map *) tls_tpnt);
|
|
|
-+#else
|
|
|
-+ if (!TRY_STATIC_TLS ((struct link_map *) tls_tpnt))
|
|
|
-+ *reloc_addr = (ElfW(Addr))
|
|
|
-+ _dl_make_tlsdesc_dynamic((struct link_map *) tls_tpnt,
|
|
|
-+ symbol_addr + *reloc_addr);
|
|
|
-+ else
|
|
|
-+#endif
|
|
|
-+ *reloc_addr += symbol_addr + tls_tpnt->l_tls_offset;
|
|
|
-+ break;
|
|
|
-+#endif
|
|
|
-+
|
|
|
- default:
|
|
|
- return -1; /* Calls _dl_exit(1). */
|
|
|
- }
|
|
|
-diff -Nur uClibc-git/ldso/ldso/xtensa/resolve.S uClibc-xtensa/ldso/ldso/xtensa/resolve.S
|
|
|
|
|
|
-+++ uClibc-xtensa/ldso/ldso/xtensa/resolve.S 2014-06-03 12:22:20.344060961 +0200
|
|
|
-@@ -27,7 +27,6 @@
|
|
|
-
|
|
|
- .text
|
|
|
- .align 4
|
|
|
-- .literal_position
|
|
|
- .global _dl_linux_resolve
|
|
|
- .type _dl_linux_resolve, @function
|
|
|
- _dl_linux_resolve:
|
|
|
-diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/clone.S uClibc-xtensa/libc/sysdeps/linux/xtensa/clone.S
|
|
|
|
|
|
-+++ uClibc-xtensa/libc/sysdeps/linux/xtensa/clone.S 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -1,34 +1,38 @@
|
|
|
--/* Copyright (C) 2001, 2005, 2007 Free Software Foundation, Inc.
|
|
|
-+/* Copyright (C) 2001, 2005 Free Software Foundation, Inc.
|
|
|
-
|
|
|
- The GNU C Library is free software; you can redistribute it and/or
|
|
|
-- modify it under the terms of the GNU Lesser General Public
|
|
|
-- License as published by the Free Software Foundation; either
|
|
|
-- version 2.1 of the License, or (at your option) any later version.
|
|
|
-+ modify it under the terms of the GNU Library General Public License as
|
|
|
-+ published by the Free Software Foundation; either version 2 of the
|
|
|
-+ License, or (at your option) any later version.
|
|
|
-
|
|
|
- The GNU C Library is distributed in the hope that it will be useful,
|
|
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-- Lesser General Public License for more details.
|
|
|
-+ Library General Public License for more details.
|
|
|
-
|
|
|
-- You should have received a copy of the GNU Lesser General Public
|
|
|
-- License along with the GNU C Library; if not, see
|
|
|
-- <http://www.gnu.org/licenses/>. */
|
|
|
-+ You should have received a copy of the GNU Library General Public
|
|
|
-+ License along with the GNU C Library; see the file COPYING.LIB. If not,
|
|
|
-+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
-+ Boston, MA 02111-1307, USA. */
|
|
|
-
|
|
|
- /* clone is even more special than fork as it mucks with stacks
|
|
|
-- and invokes a function in the right context after it's all over. */
|
|
|
-+ and invokes a function in the right context after its all over. */
|
|
|
-
|
|
|
--#include "sysdep.h"
|
|
|
--#include <sys/syscall.h>
|
|
|
-+#include <features.h>
|
|
|
-+#include <sysdep.h>
|
|
|
- #define _ERRNO_H 1
|
|
|
- #include <bits/errno.h>
|
|
|
--
|
|
|
--/* int clone (a2 = int (*fn)(void *arg),
|
|
|
-- a3 = void *child_stack,
|
|
|
-- a4 = int flags,
|
|
|
-- a5 = void *arg,
|
|
|
-- a6 = pid_t *ptid,
|
|
|
-- a7 = struct user_desc *tls,
|
|
|
-- 16(sp) = pid_t *ctid) */
|
|
|
-+#ifdef RESET_PID
|
|
|
-+#include <tls.h>
|
|
|
-+#endif
|
|
|
-+#define __ASSEMBLY__
|
|
|
-+#include <linux/sched.h>
|
|
|
-+
|
|
|
-+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
|
|
-+ a2 a3 a4 a5
|
|
|
-+ pid_t *ptid, struct user_desc *tls, pid_t *ctid)
|
|
|
-+ a6 a7 16(sp)
|
|
|
-+*/
|
|
|
-
|
|
|
- .text
|
|
|
- ENTRY (__clone)
|
|
|
-@@ -39,7 +43,7 @@
|
|
|
-
|
|
|
- /* a2 and a3 are candidates for destruction by system-call return
|
|
|
- parameters. We don't need the stack pointer after the system
|
|
|
-- call. We trust that the kernel will preserve a7, a9, and a6. */
|
|
|
-+ call. We trust that the kernel will preserve a6, a7 and a9. */
|
|
|
-
|
|
|
- mov a9, a5 /* save function argument */
|
|
|
- mov a5, a7
|
|
|
-@@ -48,19 +52,18 @@
|
|
|
- mov a6, a4
|
|
|
- mov a4, a8
|
|
|
- l32i a8, a1, 16 /* child_tid */
|
|
|
-- movi a2, SYS_ify (clone)
|
|
|
-+ movi a2, SYS_ify(clone)
|
|
|
-+
|
|
|
-+ /* syscall(NR_clone,clone_flags, usp, parent_tid, child_tls, child_tid)
|
|
|
-+ a2 a6 a3 a4 a5 a8
|
|
|
-+ */
|
|
|
-
|
|
|
-- /* syscall (a2 = NR_clone,
|
|
|
-- a6 = clone_flags,
|
|
|
-- a3 = usp,
|
|
|
-- a4 = parent_tid,
|
|
|
-- a5 = child_tls,
|
|
|
-- a8 = child_tid) */
|
|
|
- syscall
|
|
|
- bltz a2, SYSCALL_ERROR_LABEL
|
|
|
- beqz a2, .Lthread_start
|
|
|
-
|
|
|
-- /* Fall through for parent. */
|
|
|
-+ /* fall through for parent */
|
|
|
-+
|
|
|
- .Lpseudo_end:
|
|
|
- retw
|
|
|
-
|
|
|
-@@ -69,32 +72,38 @@
|
|
|
- j SYSCALL_ERROR_LABEL
|
|
|
-
|
|
|
- .Lthread_start:
|
|
|
-- /* Start child thread. */
|
|
|
-- movi a0, 0 /* terminate the stack frame */
|
|
|
-+
|
|
|
-+#if CLONE_THREAD != 0x00010000 || CLONE_VM != 0x00000100
|
|
|
-+# error invalid values for CLONE_THREAD or CLONE_VM
|
|
|
-+#endif
|
|
|
-
|
|
|
- #ifdef RESET_PID
|
|
|
-- /* Check and see if we need to reset the PID. */
|
|
|
-- bbsi.l a6, 16, 1f /* CLONE_THREAD = 0x00010000 */
|
|
|
-+ bbsi.l a6, 16, .Lskip_restore_pid /* CLONE_THREAD = 0x00010000 */
|
|
|
- movi a2, -1
|
|
|
-- bbsi.l a6, 8, 2f /* CLONE_VM = 0x00000100 */
|
|
|
-- movi a2, SYS_ify (getpid)
|
|
|
-+ bbsi a6, 8, .Lgotpid /* CLONE_VM = 0x00000100 */
|
|
|
-+ movi a2, SYS_ify(getpid)
|
|
|
- syscall
|
|
|
--2: rur a3, THREADPTR
|
|
|
-- movi a4, PID_OFFSET
|
|
|
-- add a4, a4, a3
|
|
|
-- s32i a2, a4, 0
|
|
|
-- movi a4, TID_OFFSET
|
|
|
-- add a4, a4, a3
|
|
|
-- s32i a2, a3, 0
|
|
|
--1:
|
|
|
--#endif /* RESET_PID */
|
|
|
-+.Lgotpid:
|
|
|
-+ rur a3, threadptr
|
|
|
-+ movi a0, TLS_PRE_TCB_SIZE
|
|
|
-+ sub a3, a3, a0
|
|
|
-+ s32i a2, a3, PID
|
|
|
-+ s32i a2, a3, TID
|
|
|
-+.Lskip_restore_pid:
|
|
|
-+#endif
|
|
|
-
|
|
|
-+ /* start child thread */
|
|
|
-+ movi a0, 0 /* terminate the stack frame */
|
|
|
- mov a6, a9 /* load up the 'arg' parameter */
|
|
|
- callx4 a7 /* call the user's function */
|
|
|
-
|
|
|
- /* Call _exit. Note that any return parameter from the user's
|
|
|
-- function in a6 is seen as inputs to _exit. */
|
|
|
-- movi a2, JUMPTARGET(_exit)
|
|
|
-+ function in a6 is seen as inputs to _exit. */
|
|
|
-+#ifdef PIC
|
|
|
-+ movi a2, _exit@PLT
|
|
|
-+#else
|
|
|
-+ movi a2, _exit
|
|
|
-+#endif
|
|
|
- callx4 a2
|
|
|
-
|
|
|
- PSEUDO_END (__clone)
|
|
|
-diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/fork.c uClibc-xtensa/libc/sysdeps/linux/xtensa/fork.c
|
|
|
|
|
|
-+++ uClibc-xtensa/libc/sysdeps/linux/xtensa/fork.c 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -20,6 +20,10 @@
|
|
|
- {
|
|
|
- return (pid_t) INLINE_SYSCALL(clone, 2, SIGCHLD, 0);
|
|
|
- }
|
|
|
--lt_strong_alias(fork)
|
|
|
--lt_libc_hidden(fork)
|
|
|
-+# ifdef __UCLIBC_HAS_THREADS__
|
|
|
-+strong_alias(fork,__libc_fork)
|
|
|
-+libc_hidden_weak(fork)
|
|
|
-+# else
|
|
|
-+libc_hidden_def(fork)
|
|
|
-+# endif
|
|
|
- #endif
|
|
|
-diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h uClibc-xtensa/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -1,25 +1,23 @@
|
|
|
--/* Copyright (C) 1997, 1998, 2007 Free Software Foundation, Inc.
|
|
|
-- This file is part of the GNU C Library.
|
|
|
--
|
|
|
-- The GNU C Library is free software; you can redistribute it and/or
|
|
|
-- modify it under the terms of the GNU Lesser General Public
|
|
|
-- License as published by the Free Software Foundation; either
|
|
|
-- version 2.1 of the License, or (at your option) any later version.
|
|
|
--
|
|
|
-- The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-- Lesser General Public License for more details.
|
|
|
--
|
|
|
-- You should have received a copy of the GNU Lesser General Public
|
|
|
-- License along with the GNU C Library; if not, see
|
|
|
-- <http://www.gnu.org/licenses/>. */
|
|
|
--
|
|
|
--/* Test if longjmp to JMPBUF would unwind the frame containing a local
|
|
|
-- variable at ADDRESS. */
|
|
|
--
|
|
|
-+/*
|
|
|
-+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
|
|
|
-+ *
|
|
|
-+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
|
|
|
-+ */
|
|
|
- #include <setjmp.h>
|
|
|
- #include <jmpbuf-offsets.h>
|
|
|
-
|
|
|
-+/* Test if longjmp to JMPBUF would unwind the frame
|
|
|
-+ containing a local variable at ADDRESS. */
|
|
|
- #define _JMPBUF_UNWINDS(jmpbuf, address) \
|
|
|
- ((void *) (address) < (void *) (jmpbuf)[JB_SP])
|
|
|
-+
|
|
|
-+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
|
|
|
-+#include <stdint.h>
|
|
|
-+#include <unwind.h>
|
|
|
-+
|
|
|
-+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
|
|
|
-+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
|
|
|
-+
|
|
|
-+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
|
|
|
-+ ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))
|
|
|
-+#endif
|
|
|
-diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/Makefile.arch uClibc-xtensa/libc/sysdeps/linux/xtensa/Makefile.arch
|
|
|
|
|
|
-+++ uClibc-xtensa/libc/sysdeps/linux/xtensa/Makefile.arch 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -5,7 +5,10 @@
|
|
|
- # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
|
|
|
- #
|
|
|
-
|
|
|
--CSRC-y := brk.c fork.c sigaction.c __syscall_error.c
|
|
|
-+CSRC-y := brk.c sigaction.c __syscall_error.c
|
|
|
-
|
|
|
- SSRC-y := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \
|
|
|
- sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S
|
|
|
-+
|
|
|
-+CSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += fork.c
|
|
|
-+SSRC-$(if $(UCLIBC_HAS_THREADS_NATIVE),,y) += clone.S
|
|
|
-diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/sys/ptrace.h uClibc-xtensa/libc/sysdeps/linux/xtensa/sys/ptrace.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libc/sysdeps/linux/xtensa/sys/ptrace.h 2014-06-03 11:58:41.563379928 +0200
|
|
|
-@@ -0,0 +1,155 @@
|
|
|
-+/* `ptrace' debugger support interface. Linux version.
|
|
|
-+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007
|
|
|
-+ Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#ifndef _SYS_PTRACE_H
|
|
|
-+#define _SYS_PTRACE_H 1
|
|
|
-+
|
|
|
-+#include <features.h>
|
|
|
-+
|
|
|
-+/* Kludge away careless namespace pollution from the kernel. */
|
|
|
-+
|
|
|
-+#undef PTRACE_GETREGS
|
|
|
-+#undef PTRACE_SETREGS
|
|
|
-+#undef PTRACE_GETFPREGS
|
|
|
-+#undef PTRACE_SETFPREGS
|
|
|
-+#undef PTRACE_GETFPREGSIZE
|
|
|
-+
|
|
|
-+
|
|
|
-+__BEGIN_DECLS
|
|
|
-+
|
|
|
-+/* Type of the REQUEST argument to `ptrace.' */
|
|
|
-+enum __ptrace_request
|
|
|
-+{
|
|
|
-+ /* Indicate that the process making this request should be traced.
|
|
|
-+ All signals received by this process can be intercepted by its
|
|
|
-+ parent, and its parent can use the other `ptrace' requests. */
|
|
|
-+ PTRACE_TRACEME = 0,
|
|
|
-+#define PT_TRACE_ME PTRACE_TRACEME
|
|
|
-+
|
|
|
-+ /* Return the word in the process's text space at address ADDR. */
|
|
|
-+ PTRACE_PEEKTEXT = 1,
|
|
|
-+#define PT_READ_I PTRACE_PEEKTEXT
|
|
|
-+
|
|
|
-+ /* Return the word in the process's data space at address ADDR. */
|
|
|
-+ PTRACE_PEEKDATA = 2,
|
|
|
-+#define PT_READ_D PTRACE_PEEKDATA
|
|
|
-+
|
|
|
-+ /* Return the word in the process's user area at offset ADDR. */
|
|
|
-+ PTRACE_PEEKUSER = 3,
|
|
|
-+#define PT_READ_U PTRACE_PEEKUSER
|
|
|
-+
|
|
|
-+ /* Write the word DATA into the process's text space at address ADDR. */
|
|
|
-+ PTRACE_POKETEXT = 4,
|
|
|
-+#define PT_WRITE_I PTRACE_POKETEXT
|
|
|
-+
|
|
|
-+ /* Write the word DATA into the process's data space at address ADDR. */
|
|
|
-+ PTRACE_POKEDATA = 5,
|
|
|
-+#define PT_WRITE_D PTRACE_POKEDATA
|
|
|
-+
|
|
|
-+ /* Write the word DATA into the process's user area at offset ADDR. */
|
|
|
-+ PTRACE_POKEUSER = 6,
|
|
|
-+#define PT_WRITE_U PTRACE_POKEUSER
|
|
|
-+
|
|
|
-+ /* Continue the process. */
|
|
|
-+ PTRACE_CONT = 7,
|
|
|
-+#define PT_CONTINUE PTRACE_CONT
|
|
|
-+
|
|
|
-+ /* Kill the process. */
|
|
|
-+ PTRACE_KILL = 8,
|
|
|
-+#define PT_KILL PTRACE_KILL
|
|
|
-+
|
|
|
-+ /* Single step the process.
|
|
|
-+ This is not supported on all machines. */
|
|
|
-+ PTRACE_SINGLESTEP = 9,
|
|
|
-+#define PT_STEP PTRACE_SINGLESTEP
|
|
|
-+
|
|
|
-+ /* Get all general purpose registers used by a processes.
|
|
|
-+ This is not supported on all machines. */
|
|
|
-+ PTRACE_GETREGS = 12,
|
|
|
-+#define PT_GETREGS PTRACE_GETREGS
|
|
|
-+
|
|
|
-+ /* Set all general purpose registers used by a processes.
|
|
|
-+ This is not supported on all machines. */
|
|
|
-+ PTRACE_SETREGS = 13,
|
|
|
-+#define PT_SETREGS PTRACE_SETREGS
|
|
|
-+
|
|
|
-+ /* Get all floating point registers used by a processes.
|
|
|
-+ This is not supported on all machines. */
|
|
|
-+ PTRACE_GETFPREGS = 14,
|
|
|
-+#define PT_GETFPREGS PTRACE_GETFPREGS
|
|
|
-+
|
|
|
-+ /* Set all floating point registers used by a processes.
|
|
|
-+ This is not supported on all machines. */
|
|
|
-+ PTRACE_SETFPREGS = 15,
|
|
|
-+#define PT_SETFPREGS PTRACE_SETFPREGS
|
|
|
-+
|
|
|
-+ /* Attach to a process that is already running. */
|
|
|
-+ PTRACE_ATTACH = 16,
|
|
|
-+#define PT_ATTACH PTRACE_ATTACH
|
|
|
-+
|
|
|
-+ /* Detach from a process attached to with PTRACE_ATTACH. */
|
|
|
-+ PTRACE_DETACH = 17,
|
|
|
-+#define PT_DETACH PTRACE_DETACH
|
|
|
-+
|
|
|
-+ /* Get size required for the buffer holding the floating point registers.
|
|
|
-+ This is not supported on all machines. */
|
|
|
-+ PTRACE_GETFPREGSIZE = 18,
|
|
|
-+#define PT_GETFPREGSIZE PTRACE_GETFPREGSIZE
|
|
|
-+
|
|
|
-+ /* Continue and stop at the next (return from) syscall. */
|
|
|
-+ PTRACE_SYSCALL = 24
|
|
|
-+#define PT_SYSCALL PTRACE_SYSCALL
|
|
|
-+};
|
|
|
-+
|
|
|
-+/* Options set using PTRACE_SETOPTIONS. */
|
|
|
-+enum __ptrace_setoptions {
|
|
|
-+ PTRACE_O_TRACESYSGOOD = 0x00000001,
|
|
|
-+ PTRACE_O_TRACEFORK = 0x00000002,
|
|
|
-+ PTRACE_O_TRACEVFORK = 0x00000004,
|
|
|
-+ PTRACE_O_TRACECLONE = 0x00000008,
|
|
|
-+ PTRACE_O_TRACEEXEC = 0x00000010,
|
|
|
-+ PTRACE_O_TRACEVFORKDONE = 0x00000020,
|
|
|
-+ PTRACE_O_TRACEEXIT = 0x00000040,
|
|
|
-+ PTRACE_O_MASK = 0x0000007f
|
|
|
-+};
|
|
|
-+
|
|
|
-+/* Wait extended result codes for the above trace options. */
|
|
|
-+enum __ptrace_eventcodes {
|
|
|
-+ PTRACE_EVENT_FORK = 1,
|
|
|
-+ PTRACE_EVENT_VFORK = 2,
|
|
|
-+ PTRACE_EVENT_CLONE = 3,
|
|
|
-+ PTRACE_EVENT_EXEC = 4,
|
|
|
-+ PTRACE_EVENT_VFORK_DONE = 5,
|
|
|
-+ PTRACE_EVENT_EXIT = 6
|
|
|
-+};
|
|
|
-+
|
|
|
-+/* Perform process tracing functions. REQUEST is one of the values
|
|
|
-+ above, and determines the action to be taken.
|
|
|
-+ For all requests except PTRACE_TRACEME, PID specifies the process to be
|
|
|
-+ traced.
|
|
|
-+
|
|
|
-+ PID and the other arguments described above for the various requests should
|
|
|
-+ appear (those that are used for the particular request) as:
|
|
|
-+ pid_t PID, void *ADDR, int DATA, void *ADDR2
|
|
|
-+ after REQUEST. */
|
|
|
-+extern long int ptrace (enum __ptrace_request __request, ...) __THROW;
|
|
|
-+
|
|
|
-+__END_DECLS
|
|
|
-+
|
|
|
-+#endif /* _SYS_PTRACE_H */
|
|
|
-diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/sysdep.h uClibc-xtensa/libc/sysdeps/linux/xtensa/sysdep.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libc/sysdeps/linux/xtensa/sysdep.h 2014-06-03 15:24:57.308410770 +0200
|
|
|
-@@ -16,6 +16,10 @@
|
|
|
- License along with the GNU C Library; if not, see
|
|
|
- <http://www.gnu.org/licenses/>. */
|
|
|
-
|
|
|
-+#ifndef _LINUX_XTENSA_SYSDEP_H
|
|
|
-+#define _LINUX_XTENSA_SYSDEP_H 1
|
|
|
-+
|
|
|
-+#include <common/sysdep.h>
|
|
|
- #include <sys/syscall.h>
|
|
|
-
|
|
|
- #ifdef __ASSEMBLER__
|
|
|
-@@ -24,12 +28,6 @@
|
|
|
- #define ASM_TYPE_DIRECTIVE(name, typearg) .type name, typearg
|
|
|
- #define ASM_SIZE_DIRECTIVE(name) .size name, . - name
|
|
|
-
|
|
|
--#ifdef __STDC__
|
|
|
--#define C_LABEL(name) name :
|
|
|
--#else
|
|
|
--#define C_LABEL(name) name/**/:
|
|
|
--#endif
|
|
|
--
|
|
|
- #define ENTRY(name) \
|
|
|
- ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
|
|
|
- ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \
|
|
|
-@@ -52,6 +50,15 @@
|
|
|
- #undef END
|
|
|
- #define END(name) ASM_SIZE_DIRECTIVE(name)
|
|
|
-
|
|
|
-+/* Local label name for asm code. */
|
|
|
-+#ifndef L
|
|
|
-+# ifdef HAVE_ELF
|
|
|
-+# define L(name) .L##name
|
|
|
-+# else
|
|
|
-+# define L(name) name
|
|
|
-+# endif
|
|
|
-+#endif
|
|
|
-+
|
|
|
- /* Define a macro for this directive so it can be removed in a few places. */
|
|
|
- #define LITERAL_POSITION .literal_position
|
|
|
-
|
|
|
-@@ -123,19 +130,7 @@
|
|
|
- #define PSEUDO_END_ERRVAL(name) \
|
|
|
- END (name)
|
|
|
-
|
|
|
--#undef ret_ERRVAL
|
|
|
--#define ret_ERRVAL retw
|
|
|
--
|
|
|
--#if defined RTLD_PRIVATE_ERRNO
|
|
|
--# define SYSCALL_ERROR_HANDLER \
|
|
|
--0: movi a4, rtld_errno; \
|
|
|
-- neg a2, a2; \
|
|
|
-- s32i a2, a4, 0; \
|
|
|
-- movi a2, -1; \
|
|
|
-- j .Lpseudo_end;
|
|
|
--
|
|
|
--#elif defined _LIBC_REENTRANT
|
|
|
--
|
|
|
-+#if defined _LIBC_REENTRANT
|
|
|
- # if defined USE___THREAD
|
|
|
- # ifndef NOT_IN_libc
|
|
|
- # define SYSCALL_ERROR_ERRNO __libc_errno
|
|
|
-@@ -170,3 +165,9 @@
|
|
|
- #endif /* _LIBC_REENTRANT */
|
|
|
-
|
|
|
- #endif /* __ASSEMBLER__ */
|
|
|
-+
|
|
|
-+/* Pointer mangling is not yet supported for Xtensa. */
|
|
|
-+#define PTR_MANGLE(var) (void) (var)
|
|
|
-+#define PTR_DEMANGLE(var) (void) (var)
|
|
|
-+
|
|
|
-+#endif /* _LINUX_XTENSA_SYSDEP_H */
|
|
|
-diff -Nur uClibc-git/libc/sysdeps/linux/xtensa/vfork.S uClibc-xtensa/libc/sysdeps/linux/xtensa/vfork.S
|
|
|
|
|
|
-+++ uClibc-xtensa/libc/sysdeps/linux/xtensa/vfork.S 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -1,4 +1,4 @@
|
|
|
--/* Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
|
|
-+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
|
|
|
- This file is part of the GNU C Library.
|
|
|
-
|
|
|
- The GNU C Library is free software; you can redistribute it and/or
|
|
|
-@@ -19,72 +19,67 @@
|
|
|
- #include <sys/syscall.h>
|
|
|
- #define _SIGNAL_H
|
|
|
- #include <bits/signum.h>
|
|
|
-+#define __ASSEMBLY__
|
|
|
-+#include <linux/sched.h>
|
|
|
-
|
|
|
-
|
|
|
--/* Clone the calling process, but without copying the whole address space.
|
|
|
-+/*
|
|
|
-+ Clone the calling process, but without copying the whole address space.
|
|
|
- The calling process is suspended until the new process exits or is
|
|
|
- replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
|
|
|
- and the process ID of the new process to the old process.
|
|
|
-
|
|
|
- Note that it is important that we don't create a new stack frame for the
|
|
|
-- caller. */
|
|
|
-+ caller.
|
|
|
-
|
|
|
--
|
|
|
--/* The following are defined in linux/sched.h, which unfortunately
|
|
|
-- is not safe for inclusion in an assembly file. */
|
|
|
--#define CLONE_VM 0x00000100 /* set if VM shared between processes */
|
|
|
--#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to
|
|
|
-- wake it up on mm_release */
|
|
|
-+*/
|
|
|
-
|
|
|
- #ifndef SAVE_PID
|
|
|
--#define SAVE_PID
|
|
|
-+#define SAVE_PID(a,b,c,d)
|
|
|
- #endif
|
|
|
--
|
|
|
- #ifndef RESTORE_PID
|
|
|
--#define RESTORE_PID
|
|
|
-+#define RESTORE_PID(a,b,c)
|
|
|
-+#endif
|
|
|
-+#ifndef RESTORE_PID12
|
|
|
-+#define RESTORE_PID12(a,b,c)
|
|
|
- #endif
|
|
|
-
|
|
|
-+/*
|
|
|
-+ pid_t vfork(void);
|
|
|
-+ Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)
|
|
|
-+ */
|
|
|
-
|
|
|
--/* pid_t vfork(void);
|
|
|
-- Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */
|
|
|
-
|
|
|
- HIDDEN_ENTRY (__vfork)
|
|
|
-+ .literal .Ljumptable, 0, .L4, .L8, .L12
|
|
|
-
|
|
|
-- movi a6, .Ljumptable
|
|
|
-- extui a2, a0, 30, 2 /* call-size: call4/8/12 = 1/2/3 */
|
|
|
-- addx4 a4, a2, a6 /* find return address in jumptable */
|
|
|
-- l32i a4, a4, 0
|
|
|
-- add a4, a4, a6
|
|
|
--
|
|
|
-+ mov a3, a0 # move return address out of the way
|
|
|
-+ movi a0, .Ljumptable
|
|
|
-+ extui a2, a3, 30, 2 # call-size: call4/8/12 = 1/2/3
|
|
|
-+ addx4 a0, a2, a0 # find return address in jumptable
|
|
|
- slli a2, a2, 30
|
|
|
-- xor a3, a0, a2 /* remove call-size from return addr */
|
|
|
-- extui a5, a4, 30, 2 /* get high bits of jump target */
|
|
|
-- slli a5, a5, 30
|
|
|
-- or a3, a3, a5 /* stuff them into the return address */
|
|
|
-- xor a4, a4, a5 /* clear high bits of jump target */
|
|
|
-- or a0, a4, a2 /* create temporary return address */
|
|
|
-- retw /* "return" to .L4, .L8, or .L12 */
|
|
|
--
|
|
|
-- .align 4
|
|
|
--.Ljumptable:
|
|
|
-- .word 0
|
|
|
-- .word .L4 - .Ljumptable
|
|
|
-- .word .L8 - .Ljumptable
|
|
|
-- .word .L12 - .Ljumptable
|
|
|
-+ l32i a0, a0, 0
|
|
|
-+
|
|
|
-+ xor a3, a3, a2 # remove call-size from return address
|
|
|
-+ or a0, a0, a2 # create temporary return address
|
|
|
-+ retw
|
|
|
-
|
|
|
- /* a7: return address */
|
|
|
-+
|
|
|
- .L4: mov a12, a2
|
|
|
- mov a13, a3
|
|
|
-
|
|
|
-- SAVE_PID
|
|
|
-+ SAVE_PID(a5,a15,a2,a3)
|
|
|
-
|
|
|
-- /* Use syscall 'clone'. Set new stack pointer to the same address. */
|
|
|
-- movi a2, SYS_ify (clone)
|
|
|
-+ /* use syscall 'clone' and set new stack pointer to the same address */
|
|
|
-+
|
|
|
-+ movi a2, SYS_ify(clone)
|
|
|
- movi a3, 0
|
|
|
- movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
|
|
|
-+
|
|
|
- syscall
|
|
|
-
|
|
|
-- RESTORE_PID
|
|
|
-+ RESTORE_PID(a5,a15,a2)
|
|
|
-
|
|
|
- movi a5, -4096
|
|
|
-
|
|
|
-@@ -94,22 +89,24 @@
|
|
|
-
|
|
|
- bgeu a6, a5, 1f
|
|
|
- jx a7
|
|
|
--1: call4 .Lerr /* returns to original caller */
|
|
|
-
|
|
|
-+1: call4 .Lerr
|
|
|
-
|
|
|
- /* a11: return address */
|
|
|
-+
|
|
|
- .L8: mov a12, a2
|
|
|
- mov a13, a3
|
|
|
- mov a14, a6
|
|
|
-
|
|
|
-- SAVE_PID
|
|
|
-+ SAVE_PID(a9,a15,a2,a3)
|
|
|
-
|
|
|
-- movi a2, SYS_ify (clone)
|
|
|
-+ movi a2, SYS_ify(clone)
|
|
|
- movi a3, 0
|
|
|
- movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
|
|
|
-+
|
|
|
- syscall
|
|
|
-
|
|
|
-- RESTORE_PID
|
|
|
-+ RESTORE_PID(a9,a15,a2)
|
|
|
-
|
|
|
- movi a9, -4096
|
|
|
-
|
|
|
-@@ -120,22 +117,25 @@
|
|
|
-
|
|
|
- bgeu a10, a9, 1f
|
|
|
- jx a11
|
|
|
--1: call8 .Lerr /* returns to original caller */
|
|
|
-+
|
|
|
-+1: call8 .Lerr
|
|
|
-
|
|
|
-
|
|
|
- /* a15: return address */
|
|
|
-+
|
|
|
- .L12: mov a12, a2
|
|
|
- mov a13, a3
|
|
|
- mov a14, a6
|
|
|
-
|
|
|
-- SAVE_PID
|
|
|
-+ SAVE_PID (a2,a3,a2,a6)
|
|
|
-
|
|
|
-- movi a2, SYS_ify (clone)
|
|
|
-+ movi a2, SYS_ify(clone)
|
|
|
- movi a3, 0
|
|
|
- movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD
|
|
|
-+
|
|
|
- syscall
|
|
|
-
|
|
|
-- RESTORE_PID
|
|
|
-+ RESTORE_PID12(a3,a6,a15)
|
|
|
-
|
|
|
- mov a3, a13
|
|
|
- movi a13, -4096
|
|
|
-@@ -147,18 +147,18 @@
|
|
|
-
|
|
|
- bgeu a14, a13, 1f
|
|
|
- jx a15
|
|
|
--1: call12 .Lerr /* returns to original caller */
|
|
|
-
|
|
|
-+1: call12 .Lerr
|
|
|
-
|
|
|
- .align 4
|
|
|
-+
|
|
|
- .Lerr: entry a1, 16
|
|
|
-
|
|
|
-- /* Restore the return address. */
|
|
|
-- extui a4, a0, 30, 2 /* get the call-size bits */
|
|
|
-+ /* Restore return address */
|
|
|
-+
|
|
|
-+ extui a4, a0, 30, 2
|
|
|
- slli a4, a4, 30
|
|
|
-- slli a3, a3, 2 /* clear high bits of target address */
|
|
|
-- srli a3, a3, 2
|
|
|
-- or a0, a3, a4 /* combine them */
|
|
|
-+ or a0, a3, a4
|
|
|
-
|
|
|
- PSEUDO_END (__vfork)
|
|
|
- .Lpseudo_end:
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c 2014-06-03 12:35:45.097932730 +0200
|
|
|
-@@ -22,8 +22,6 @@
|
|
|
- #include <lowlevellock.h>
|
|
|
- #include <sys/time.h>
|
|
|
- #include <tls.h>
|
|
|
--#include <tcb-offsets.h>
|
|
|
--
|
|
|
-
|
|
|
- void
|
|
|
- __lll_lock_wait_private (int *futex)
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/pthreadtypes.h uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/pthreadtypes.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/pthreadtypes.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,184 @@
|
|
|
-+/* Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library. If not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#ifndef _BITS_PTHREADTYPES_H
|
|
|
-+#define _BITS_PTHREADTYPES_H 1
|
|
|
-+
|
|
|
-+#include <endian.h>
|
|
|
-+
|
|
|
-+#define __SIZEOF_PTHREAD_ATTR_T 36
|
|
|
-+#define __SIZEOF_PTHREAD_MUTEX_T 24
|
|
|
-+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
|
|
|
-+#define __SIZEOF_PTHREAD_COND_T 48
|
|
|
-+#define __SIZEOF_PTHREAD_COND_COMPAT_T 12
|
|
|
-+#define __SIZEOF_PTHREAD_CONDATTR_T 4
|
|
|
-+#define __SIZEOF_PTHREAD_RWLOCK_T 32
|
|
|
-+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
|
|
|
-+#define __SIZEOF_PTHREAD_BARRIER_T 20
|
|
|
-+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Thread identifiers. The structure of the attribute type is not
|
|
|
-+ exposed on purpose. */
|
|
|
-+typedef unsigned long int pthread_t;
|
|
|
-+
|
|
|
-+
|
|
|
-+union pthread_attr_t
|
|
|
-+{
|
|
|
-+ char __size[__SIZEOF_PTHREAD_ATTR_T];
|
|
|
-+ long int __align;
|
|
|
-+};
|
|
|
-+#ifndef __have_pthread_attr_t
|
|
|
-+typedef union pthread_attr_t pthread_attr_t;
|
|
|
-+# define __have_pthread_attr_t 1
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+
|
|
|
-+typedef struct __pthread_internal_slist
|
|
|
-+{
|
|
|
-+ struct __pthread_internal_slist *__next;
|
|
|
-+} __pthread_slist_t;
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Data structures for mutex handling. The structure of the attribute
|
|
|
-+ type is not exposed on purpose. */
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ struct __pthread_mutex_s
|
|
|
-+ {
|
|
|
-+ int __lock;
|
|
|
-+ unsigned int __count;
|
|
|
-+ int __owner;
|
|
|
-+ /* KIND must stay at this position in the structure to maintain
|
|
|
-+ binary compatibility. */
|
|
|
-+ int __kind;
|
|
|
-+ unsigned int __nusers;
|
|
|
-+ __extension__ union
|
|
|
-+ {
|
|
|
-+ int __spins;
|
|
|
-+ __pthread_slist_t __list;
|
|
|
-+ };
|
|
|
-+ } __data;
|
|
|
-+ char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
|
|
-+ long int __align;
|
|
|
-+} pthread_mutex_t;
|
|
|
-+
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
|
|
|
-+ long int __align;
|
|
|
-+} pthread_mutexattr_t;
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Data structure for conditional variable handling. The structure of
|
|
|
-+ the attribute type is not exposed on purpose. */
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ struct
|
|
|
-+ {
|
|
|
-+ int __lock;
|
|
|
-+ unsigned int __futex;
|
|
|
-+ __extension__ unsigned long long int __total_seq;
|
|
|
-+ __extension__ unsigned long long int __wakeup_seq;
|
|
|
-+ __extension__ unsigned long long int __woken_seq;
|
|
|
-+ void *__mutex;
|
|
|
-+ unsigned int __nwaiters;
|
|
|
-+ unsigned int __broadcast_seq;
|
|
|
-+ } __data;
|
|
|
-+ char __size[__SIZEOF_PTHREAD_COND_T];
|
|
|
-+ __extension__ long long int __align;
|
|
|
-+} pthread_cond_t;
|
|
|
-+
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ char __size[__SIZEOF_PTHREAD_CONDATTR_T];
|
|
|
-+ long int __align;
|
|
|
-+} pthread_condattr_t;
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Keys for thread-specific data */
|
|
|
-+typedef unsigned int pthread_key_t;
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Once-only execution */
|
|
|
-+typedef int pthread_once_t;
|
|
|
-+
|
|
|
-+
|
|
|
-+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
|
|
|
-+/* Data structure for read-write lock variable handling. The
|
|
|
-+ structure of the attribute type is not exposed on purpose. */
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ struct
|
|
|
-+ {
|
|
|
-+ int __lock;
|
|
|
-+ unsigned int __nr_readers;
|
|
|
-+ unsigned int __readers_wakeup;
|
|
|
-+ unsigned int __writer_wakeup;
|
|
|
-+ unsigned int __nr_readers_queued;
|
|
|
-+ unsigned int __nr_writers_queued;
|
|
|
-+#if __BYTE_ORDER == __BIG_ENDIAN
|
|
|
-+ unsigned char __pad1;
|
|
|
-+ unsigned char __pad2;
|
|
|
-+ unsigned char __shared;
|
|
|
-+ /* FLAGS must stay at this position in the structure to maintain
|
|
|
-+ binary compatibility. */
|
|
|
-+ unsigned char __flags;
|
|
|
-+#else
|
|
|
-+ /* FLAGS must stay at this position in the structure to maintain
|
|
|
-+ binary compatibility. */
|
|
|
-+ unsigned char __flags;
|
|
|
-+ unsigned char __shared;
|
|
|
-+ unsigned char __pad1;
|
|
|
-+ unsigned char __pad2;
|
|
|
-+#endif
|
|
|
-+ int __writer;
|
|
|
-+ } __data;
|
|
|
-+ char __size[__SIZEOF_PTHREAD_RWLOCK_T];
|
|
|
-+ long int __align;
|
|
|
-+} pthread_rwlock_t;
|
|
|
-+
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
|
|
|
-+ long int __align;
|
|
|
-+} pthread_rwlockattr_t;
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+
|
|
|
-+#ifdef __USE_XOPEN2K
|
|
|
-+/* POSIX spinlock data type. */
|
|
|
-+typedef volatile int pthread_spinlock_t;
|
|
|
-+
|
|
|
-+
|
|
|
-+/* POSIX barriers data type. The structure of the type is
|
|
|
-+ deliberately not exposed. */
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ char __size[__SIZEOF_PTHREAD_BARRIER_T];
|
|
|
-+ long int __align;
|
|
|
-+} pthread_barrier_t;
|
|
|
-+
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
|
|
|
-+ int __align;
|
|
|
-+} pthread_barrierattr_t;
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+
|
|
|
-+#endif /* bits/pthreadtypes.h */
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/semaphore.h uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/semaphore.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/semaphore.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,35 @@
|
|
|
-+/* Copyright (C) 2012 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, write to the Free
|
|
|
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+ 02111-1307 USA. */
|
|
|
-+
|
|
|
-+#ifndef _SEMAPHORE_H
|
|
|
-+# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+
|
|
|
-+#define __SIZEOF_SEM_T 16
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Value returned if `sem_open' failed. */
|
|
|
-+#define SEM_FAILED ((sem_t *) 0)
|
|
|
-+
|
|
|
-+
|
|
|
-+typedef union
|
|
|
-+{
|
|
|
-+ char __size[__SIZEOF_SEM_T];
|
|
|
-+ long int __align;
|
|
|
-+} sem_t;
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/clone.S uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/clone.S
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/clone.S 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,3 @@
|
|
|
-+#define RESET_PID
|
|
|
-+#include <tcb-offsets.h>
|
|
|
-+#include <libc/sysdeps/linux/xtensa/clone.S>
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/createthread.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/createthread.c
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/createthread.c 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,24 @@
|
|
|
-+/* Copyright (C) 2012 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, write to the Free
|
|
|
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+ 02111-1307 USA. */
|
|
|
-+
|
|
|
-+/* Value passed to 'clone' for initialization of the thread register. */
|
|
|
-+#define TLS_VALUE (pd + 1)
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Get the real implementation. */
|
|
|
-+#include <sysdeps/pthread/createthread.c>
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/fork.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/fork.c
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/fork.c 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,29 @@
|
|
|
-+/* Copyright (C) 2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#include <sched.h>
|
|
|
-+#include <signal.h>
|
|
|
-+#include <sysdep.h>
|
|
|
-+#include <tls.h>
|
|
|
-+
|
|
|
-+
|
|
|
-+#define ARCH_FORK() \
|
|
|
-+ INLINE_SYSCALL (clone, 5, \
|
|
|
-+ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \
|
|
|
-+ NULL, NULL, &THREAD_SELF->tid)
|
|
|
-+
|
|
|
-+#include "../fork.c"
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.c
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.c 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,132 @@
|
|
|
-+/* low level locking for pthread library. Generic futex-using version.
|
|
|
-+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library. If not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#include <errno.h>
|
|
|
-+#include <sysdep.h>
|
|
|
-+#include <lowlevellock.h>
|
|
|
-+#include <sys/time.h>
|
|
|
-+
|
|
|
-+void
|
|
|
-+__lll_lock_wait_private (int *futex)
|
|
|
-+{
|
|
|
-+ do
|
|
|
-+ {
|
|
|
-+ int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
|
|
|
-+ if (oldval != 0)
|
|
|
-+ lll_futex_wait (futex, 2, LLL_PRIVATE);
|
|
|
-+ }
|
|
|
-+ while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
|
|
|
-+}
|
|
|
-+
|
|
|
-+
|
|
|
-+/* These functions don't get included in libc.so */
|
|
|
-+#ifdef IS_IN_libpthread
|
|
|
-+void
|
|
|
-+__lll_lock_wait (int *futex, int private)
|
|
|
-+{
|
|
|
-+ do
|
|
|
-+ {
|
|
|
-+ int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
|
|
|
-+ if (oldval != 0)
|
|
|
-+ lll_futex_wait (futex, 2, private);
|
|
|
-+ }
|
|
|
-+ while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
|
|
|
-+}
|
|
|
-+
|
|
|
-+
|
|
|
-+int
|
|
|
-+__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
|
|
|
-+{
|
|
|
-+ struct timespec rt;
|
|
|
-+
|
|
|
-+ /* Reject invalid timeouts. */
|
|
|
-+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
|
|
|
-+ return EINVAL;
|
|
|
-+
|
|
|
-+ /* Upgrade the lock. */
|
|
|
-+ if (atomic_exchange_acq (futex, 2) == 0)
|
|
|
-+ return 0;
|
|
|
-+
|
|
|
-+ do
|
|
|
-+ {
|
|
|
-+ struct timeval tv;
|
|
|
-+
|
|
|
-+ /* Get the current time. */
|
|
|
-+ (void) __gettimeofday (&tv, NULL);
|
|
|
-+
|
|
|
-+ /* Compute relative timeout. */
|
|
|
-+ rt.tv_sec = abstime->tv_sec - tv.tv_sec;
|
|
|
-+ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
|
|
-+ if (rt.tv_nsec < 0)
|
|
|
-+ {
|
|
|
-+ rt.tv_nsec += 1000000000;
|
|
|
-+ --rt.tv_sec;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* Already timed out? */
|
|
|
-+ if (rt.tv_sec < 0)
|
|
|
-+ return ETIMEDOUT;
|
|
|
-+
|
|
|
-+ // XYZ: Lost the lock to check whether it was private.
|
|
|
-+ lll_futex_timed_wait (futex, 2, &rt, private);
|
|
|
-+ }
|
|
|
-+ while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+
|
|
|
-+int
|
|
|
-+__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
|
|
|
-+{
|
|
|
-+ int tid;
|
|
|
-+
|
|
|
-+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
|
|
|
-+ return EINVAL;
|
|
|
-+
|
|
|
-+ /* Repeat until thread terminated. */
|
|
|
-+ while ((tid = *tidp) != 0)
|
|
|
-+ {
|
|
|
-+ struct timeval tv;
|
|
|
-+ struct timespec rt;
|
|
|
-+
|
|
|
-+ /* Get the current time. */
|
|
|
-+ (void) __gettimeofday (&tv, NULL);
|
|
|
-+
|
|
|
-+ /* Compute relative timeout. */
|
|
|
-+ rt.tv_sec = abstime->tv_sec - tv.tv_sec;
|
|
|
-+ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
|
|
|
-+ if (rt.tv_nsec < 0)
|
|
|
-+ {
|
|
|
-+ rt.tv_nsec += 1000000000;
|
|
|
-+ --rt.tv_sec;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* Already timed out? */
|
|
|
-+ if (rt.tv_sec < 0)
|
|
|
-+ return ETIMEDOUT;
|
|
|
-+
|
|
|
-+ /* Wait until thread terminates. */
|
|
|
-+ // XYZ: Lost the lock to check whether it was private.
|
|
|
-+ if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
|
|
|
-+ return ETIMEDOUT;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+#endif
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.h uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,293 @@
|
|
|
-+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library. If not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#ifndef _LOWLEVELLOCK_H
|
|
|
-+#define _LOWLEVELLOCK_H 1
|
|
|
-+
|
|
|
-+#include <time.h>
|
|
|
-+#include <sys/param.h>
|
|
|
-+#include <bits/pthreadtypes.h>
|
|
|
-+#include <atomic.h>
|
|
|
-+#include <sysdep.h>
|
|
|
-+#include <bits/kernel-features.h>
|
|
|
-+
|
|
|
-+#define FUTEX_WAIT 0
|
|
|
-+#define FUTEX_WAKE 1
|
|
|
-+#define FUTEX_REQUEUE 3
|
|
|
-+#define FUTEX_CMP_REQUEUE 4
|
|
|
-+#define FUTEX_WAKE_OP 5
|
|
|
-+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
|
|
|
-+#define FUTEX_LOCK_PI 6
|
|
|
-+#define FUTEX_UNLOCK_PI 7
|
|
|
-+#define FUTEX_TRYLOCK_PI 8
|
|
|
-+#define FUTEX_WAIT_BITSET 9
|
|
|
-+#define FUTEX_WAKE_BITSET 10
|
|
|
-+#define FUTEX_PRIVATE_FLAG 128
|
|
|
-+#define FUTEX_CLOCK_REALTIME 256
|
|
|
-+
|
|
|
-+#define FUTEX_BITSET_MATCH_ANY 0xffffffff
|
|
|
-+
|
|
|
-+/* Values for 'private' parameter of locking macros. Yes, the
|
|
|
-+ definition seems to be backwards. But it is not. The bit will be
|
|
|
-+ reversed before passing to the system call. */
|
|
|
-+#define LLL_PRIVATE 0
|
|
|
-+#define LLL_SHARED FUTEX_PRIVATE_FLAG
|
|
|
-+
|
|
|
-+
|
|
|
-+#if !defined NOT_IN_libc || defined IS_IN_rtld
|
|
|
-+/* In libc.so or ld.so all futexes are private. */
|
|
|
-+# ifdef __ASSUME_PRIVATE_FUTEX
|
|
|
-+# define __lll_private_flag(fl, private) \
|
|
|
-+ ((fl) | FUTEX_PRIVATE_FLAG)
|
|
|
-+# else
|
|
|
-+# define __lll_private_flag(fl, private) \
|
|
|
-+ ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
|
|
|
-+# endif
|
|
|
-+#else
|
|
|
-+# ifdef __ASSUME_PRIVATE_FUTEX
|
|
|
-+# define __lll_private_flag(fl, private) \
|
|
|
-+ (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
|
|
|
-+# else
|
|
|
-+# define __lll_private_flag(fl, private) \
|
|
|
-+ (__builtin_constant_p (private) \
|
|
|
-+ ? ((private) == 0 \
|
|
|
-+ ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \
|
|
|
-+ : (fl)) \
|
|
|
-+ : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \
|
|
|
-+ & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
|
|
|
-+# endif
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+
|
|
|
-+#define lll_futex_wait(futexp, val, private) \
|
|
|
-+ lll_futex_timed_wait(futexp, val, NULL, private)
|
|
|
-+
|
|
|
-+#define lll_futex_timed_wait(futexp, val, timespec, private) \
|
|
|
-+ ({ \
|
|
|
-+ INTERNAL_SYSCALL_DECL (__err); \
|
|
|
-+ long int __ret; \
|
|
|
-+ __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
|
|
|
-+ __lll_private_flag (FUTEX_WAIT, private), \
|
|
|
-+ (val), (timespec)); \
|
|
|
-+ __ret; \
|
|
|
-+ })
|
|
|
-+
|
|
|
-+#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
|
|
|
-+ ({ \
|
|
|
-+ INTERNAL_SYSCALL_DECL (__err); \
|
|
|
-+ long int __ret; \
|
|
|
-+ int __op = FUTEX_WAIT_BITSET | clockbit; \
|
|
|
-+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
|
|
|
-+ __lll_private_flag (__op, private), \
|
|
|
-+ (val), (timespec), NULL /* Unused. */, \
|
|
|
-+ FUTEX_BITSET_MATCH_ANY); \
|
|
|
-+ __ret; \
|
|
|
-+ })
|
|
|
-+
|
|
|
-+#define lll_futex_wake(futexp, nr, private) \
|
|
|
-+ ({ \
|
|
|
-+ INTERNAL_SYSCALL_DECL (__err); \
|
|
|
-+ long int __ret; \
|
|
|
-+ __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
|
|
|
-+ __lll_private_flag (FUTEX_WAKE, private), \
|
|
|
-+ (nr), 0); \
|
|
|
-+ __ret; \
|
|
|
-+ })
|
|
|
-+
|
|
|
-+#define lll_robust_dead(futexv, private) \
|
|
|
-+ do \
|
|
|
-+ { \
|
|
|
-+ int *__futexp = &(futexv); \
|
|
|
-+ atomic_or (__futexp, FUTEX_OWNER_DIED); \
|
|
|
-+ lll_futex_wake (__futexp, 1, private); \
|
|
|
-+ } \
|
|
|
-+ while (0)
|
|
|
-+
|
|
|
-+/* Returns non-zero if error happened, zero if success. */
|
|
|
-+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
|
|
|
-+ ({ \
|
|
|
-+ INTERNAL_SYSCALL_DECL (__err); \
|
|
|
-+ long int __ret; \
|
|
|
-+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
|
|
|
-+ __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
|
|
|
-+ (nr_wake), (nr_move), (mutex), (val)); \
|
|
|
-+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
|
|
|
-+ })
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Returns non-zero if error happened, zero if success. */
|
|
|
-+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
|
|
|
-+ ({ \
|
|
|
-+ INTERNAL_SYSCALL_DECL (__err); \
|
|
|
-+ long int __ret; \
|
|
|
-+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
|
|
|
-+ __lll_private_flag (FUTEX_WAKE_OP, private), \
|
|
|
-+ (nr_wake), (nr_wake2), (futexp2), \
|
|
|
-+ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
|
|
|
-+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
|
|
|
-+ })
|
|
|
-+
|
|
|
-+
|
|
|
-+#define lll_trylock(lock) \
|
|
|
-+ atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
|
|
|
-+
|
|
|
-+#define lll_cond_trylock(lock) \
|
|
|
-+ atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
|
|
|
-+
|
|
|
-+#define __lll_robust_trylock(futex, id) \
|
|
|
-+ (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
|
|
|
-+#define lll_robust_trylock(lock, id) \
|
|
|
-+ __lll_robust_trylock (&(lock), id)
|
|
|
-+
|
|
|
-+extern void __lll_lock_wait_private (int *futex) attribute_hidden;
|
|
|
-+extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
|
|
|
-+extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
|
|
|
-+
|
|
|
-+#define __lll_lock(futex, private) \
|
|
|
-+ ((void) ({ \
|
|
|
-+ int *__futex = (futex); \
|
|
|
-+ if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, \
|
|
|
-+ 1, 0), 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)
|
|
|
-+
|
|
|
-+
|
|
|
-+#define __lll_robust_lock(futex, id, private) \
|
|
|
-+ ({ \
|
|
|
-+ int *__futex = (futex); \
|
|
|
-+ int __val = 0; \
|
|
|
-+ \
|
|
|
-+ if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
|
|
|
-+ 0), 0)) \
|
|
|
-+ __val = __lll_robust_lock_wait (__futex, private); \
|
|
|
-+ __val; \
|
|
|
-+ })
|
|
|
-+#define lll_robust_lock(futex, id, private) \
|
|
|
-+ __lll_robust_lock (&(futex), id, private)
|
|
|
-+
|
|
|
-+
|
|
|
-+#define __lll_cond_lock(futex, private) \
|
|
|
-+ ((void) ({ \
|
|
|
-+ int *__futex = (futex); \
|
|
|
-+ if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0)) \
|
|
|
-+ __lll_lock_wait (__futex, private); \
|
|
|
-+ }))
|
|
|
-+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
|
|
|
-+
|
|
|
-+
|
|
|
-+#define lll_robust_cond_lock(futex, id, private) \
|
|
|
-+ __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
|
|
|
-+
|
|
|
-+
|
|
|
-+extern int __lll_timedlock_wait (int *futex, const struct timespec *,
|
|
|
-+ int private) attribute_hidden;
|
|
|
-+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
|
|
|
-+ int private) attribute_hidden;
|
|
|
-+
|
|
|
-+#define __lll_timedlock(futex, abstime, private) \
|
|
|
-+ ({ \
|
|
|
-+ int *__futex = (futex); \
|
|
|
-+ int __val = 0; \
|
|
|
-+ \
|
|
|
-+ if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0)) \
|
|
|
-+ __val = __lll_timedlock_wait (__futex, abstime, private); \
|
|
|
-+ __val; \
|
|
|
-+ })
|
|
|
-+#define lll_timedlock(futex, abstime, private) \
|
|
|
-+ __lll_timedlock (&(futex), abstime, private)
|
|
|
-+
|
|
|
-+
|
|
|
-+#define __lll_robust_timedlock(futex, abstime, id, private) \
|
|
|
-+ ({ \
|
|
|
-+ int *__futex = (futex); \
|
|
|
-+ int __val = 0; \
|
|
|
-+ \
|
|
|
-+ if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
|
|
|
-+ 0), 0)) \
|
|
|
-+ __val = __lll_robust_timedlock_wait (__futex, abstime, private); \
|
|
|
-+ __val; \
|
|
|
-+ })
|
|
|
-+#define lll_robust_timedlock(futex, abstime, id, private) \
|
|
|
-+ __lll_robust_timedlock (&(futex), abstime, id, private)
|
|
|
-+
|
|
|
-+
|
|
|
-+#define __lll_unlock(futex, private) \
|
|
|
-+ (void) \
|
|
|
-+ ({ int *__futex = (futex); \
|
|
|
-+ int __oldval = atomic_exchange_rel (__futex, 0); \
|
|
|
-+ if (__builtin_expect (__oldval > 1, 0)) \
|
|
|
-+ lll_futex_wake (__futex, 1, private); \
|
|
|
-+ })
|
|
|
-+#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
|
|
|
-+
|
|
|
-+
|
|
|
-+#define __lll_robust_unlock(futex, private) \
|
|
|
-+ (void) \
|
|
|
-+ ({ int *__futex = (futex); \
|
|
|
-+ int __oldval = atomic_exchange_rel (__futex, 0); \
|
|
|
-+ if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \
|
|
|
-+ lll_futex_wake (__futex, 1, private); \
|
|
|
-+ })
|
|
|
-+#define lll_robust_unlock(futex, private) \
|
|
|
-+ __lll_robust_unlock(&(futex), private)
|
|
|
-+
|
|
|
-+
|
|
|
-+#define lll_islocked(futex) \
|
|
|
-+ (futex != 0)
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Our internal lock implementation is identical to the binary-compatible
|
|
|
-+ mutex implementation. */
|
|
|
-+
|
|
|
-+/* Initializers for lock. */
|
|
|
-+#define LLL_LOCK_INITIALIZER (0)
|
|
|
-+#define LLL_LOCK_INITIALIZER_LOCKED (1)
|
|
|
-+
|
|
|
-+/* The states of a lock are:
|
|
|
-+ 0 - untaken
|
|
|
-+ 1 - taken by one user
|
|
|
-+ >1 - taken by more users */
|
|
|
-+
|
|
|
-+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
|
|
|
-+ wakeup when the clone terminates. The memory location contains the
|
|
|
-+ thread ID while the clone is running and is reset to zero
|
|
|
-+ afterwards. */
|
|
|
-+#define lll_wait_tid(tid) \
|
|
|
-+ do { \
|
|
|
-+ __typeof (tid) __tid; \
|
|
|
-+ while ((__tid = (tid)) != 0) \
|
|
|
-+ lll_futex_wait (&(tid), __tid, LLL_SHARED);\
|
|
|
-+ } while (0)
|
|
|
-+
|
|
|
-+extern int __lll_timedwait_tid (int *, const struct timespec *)
|
|
|
-+ attribute_hidden;
|
|
|
-+
|
|
|
-+#define lll_timedwait_tid(tid, abstime) \
|
|
|
-+ ({ \
|
|
|
-+ int __res = 0; \
|
|
|
-+ if ((tid) != 0) \
|
|
|
-+ __res = __lll_timedwait_tid (&(tid), (abstime)); \
|
|
|
-+ __res; \
|
|
|
-+ })
|
|
|
-+
|
|
|
-+#endif /* lowlevellock.h */
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/Makefile.arch uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/Makefile.arch
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/Makefile.arch 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,17 @@
|
|
|
-+# Makefile for uClibc NPTL
|
|
|
-+#
|
|
|
-+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
|
|
|
-+#
|
|
|
-+
|
|
|
-+libc_linux_arch_CSRC = fork.c
|
|
|
-+libc_linux_arch_SSRC = clone.S vfork.S
|
|
|
-+libpthread_linux_arch_CSRC = pthread_once.c
|
|
|
-+libpthread_linux_arch_SSRC = pt-vfork.S
|
|
|
-+
|
|
|
-+CFLAGS-OMIT-fork.c = -DNOT_IN_libc -DIS_IN_libpthread
|
|
|
-+ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT
|
|
|
-+
|
|
|
-+ASFLAGS-clone.S = -D_LIBC_REENTRANT
|
|
|
-+ASFLAGS-vfork.S = -D_LIBC_REENTRANT
|
|
|
-+ASFLAGS-syscall.S = -D_LIBC_REENTRANT
|
|
|
-+ASFLAGS-mmap.S = -D_LIBC_REENTRANT
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pthread_once.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pthread_once.c
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pthread_once.c 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,89 @@
|
|
|
-+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library. If not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#include "pthreadP.h"
|
|
|
-+#include <lowlevellock.h>
|
|
|
-+
|
|
|
-+unsigned long int __fork_generation attribute_hidden;
|
|
|
-+
|
|
|
-+static void
|
|
|
-+clear_once_control (void *arg)
|
|
|
-+{
|
|
|
-+ pthread_once_t *once_control = (pthread_once_t *) arg;
|
|
|
-+
|
|
|
-+ *once_control = 0;
|
|
|
-+ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
|
|
|
-+}
|
|
|
-+
|
|
|
-+int
|
|
|
-+__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
|
|
|
-+{
|
|
|
-+ for (;;)
|
|
|
-+ {
|
|
|
-+ int oldval;
|
|
|
-+ int newval;
|
|
|
-+
|
|
|
-+ /* Pseudo code:
|
|
|
-+ newval = __fork_generation | 1;
|
|
|
-+ oldval = *once_control;
|
|
|
-+ if ((oldval & 2) == 0)
|
|
|
-+ *once_control = newval;
|
|
|
-+ Do this atomically.
|
|
|
-+ */
|
|
|
-+ do
|
|
|
-+ {
|
|
|
-+ newval = __fork_generation | 1;
|
|
|
-+ oldval = *once_control;
|
|
|
-+ if (oldval & 2)
|
|
|
-+ break;
|
|
|
-+ } while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval);
|
|
|
-+
|
|
|
-+ /* Check if the initializer has already been done. */
|
|
|
-+ if ((oldval & 2) != 0)
|
|
|
-+ return 0;
|
|
|
-+
|
|
|
-+ /* Check if another thread already runs the initializer. */
|
|
|
-+ if ((oldval & 1) == 0)
|
|
|
-+ break;
|
|
|
-+
|
|
|
-+ /* Check whether the initializer execution was interrupted by a fork. */
|
|
|
-+ if (oldval != newval)
|
|
|
-+ break;
|
|
|
-+
|
|
|
-+ /* Same generation, some other thread was faster. Wait. */
|
|
|
-+ lll_futex_wait (once_control, oldval, LLL_PRIVATE);
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ /* This thread is the first here. Do the initialization.
|
|
|
-+ Register a cleanup handler so that in case the thread gets
|
|
|
-+ interrupted the initialization can be restarted. */
|
|
|
-+ pthread_cleanup_push (clear_once_control, once_control);
|
|
|
-+
|
|
|
-+ init_routine ();
|
|
|
-+
|
|
|
-+ pthread_cleanup_pop (0);
|
|
|
-+
|
|
|
-+ /* Say that the initialisation is done. */
|
|
|
-+ *once_control = __fork_generation | 2;
|
|
|
-+
|
|
|
-+ /* Wake up all other threads. */
|
|
|
-+ lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+weak_alias (__pthread_once, pthread_once)
|
|
|
-+strong_alias (__pthread_once, __pthread_once_internal)
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-initfini.c uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-initfini.c
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-initfini.c 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,134 @@
|
|
|
-+/* Special .init and .fini section support. Linuxthread version.
|
|
|
-+ Copyright (C) 1995,1996,1997,2000,2001,2002 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it
|
|
|
-+ and/or modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ In addition to the permissions in the GNU Lesser General Public
|
|
|
-+ License, the Free Software Foundation gives you unlimited
|
|
|
-+ permission to link the compiled version of this file with other
|
|
|
-+ programs, and to distribute those programs without any restriction
|
|
|
-+ coming from the use of this file. (The Library General Public
|
|
|
-+ License restrictions do apply in other respects; for example, they
|
|
|
-+ cover modification of the file, and distribution when not linked
|
|
|
-+ into another program.)
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be
|
|
|
-+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
|
-+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
-+ GNU Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; see the file COPYING.LIB. If not,
|
|
|
-+ see <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+/* This file is compiled into assembly code which is then munged by a sed
|
|
|
-+ script into two files: crti.s and crtn.s.
|
|
|
-+
|
|
|
-+ * crti.s puts a function prologue at the beginning of the
|
|
|
-+ .init and .fini sections and defines global symbols for
|
|
|
-+ those addresses, so they can be called as functions.
|
|
|
-+
|
|
|
-+ * crtn.s puts the corresponding function epilogues
|
|
|
-+ in the .init and .fini sections. */
|
|
|
-+
|
|
|
-+#include <stdlib.h>
|
|
|
-+
|
|
|
-+/* We use embedded asm for .section unconditionally, as this makes it
|
|
|
-+ easier to insert the necessary directives into crtn.S. */
|
|
|
-+#define SECTION(x) __asm__ (".section " x )
|
|
|
-+
|
|
|
-+/* Embed an #include to pull in the alignment and .end directives. */
|
|
|
-+__asm__ ("\n#include \"defs.h\"");
|
|
|
-+__asm__ ("\n#if defined __i686 && defined __ASSEMBLER__");
|
|
|
-+__asm__ ("\n#undef __i686");
|
|
|
-+__asm__ ("\n#define __i686 __i686");
|
|
|
-+__asm__ ("\n#endif");
|
|
|
-+
|
|
|
-+/* The initial common code ends here. */
|
|
|
-+__asm__ ("\n/*@HEADER_ENDS*/");
|
|
|
-+
|
|
|
-+/* To determine whether we need .end and .align: */
|
|
|
-+__asm__ ("\n/*@TESTS_BEGIN*/");
|
|
|
-+extern void dummy (void (*foo) (void));
|
|
|
-+void
|
|
|
-+dummy (void (*foo) (void))
|
|
|
-+{
|
|
|
-+ if (foo)
|
|
|
-+ (*foo) ();
|
|
|
-+}
|
|
|
-+__asm__ ("\n/*@TESTS_END*/");
|
|
|
-+
|
|
|
-+/* The beginning of _init: */
|
|
|
-+__asm__ ("\n/*@_init_PROLOG_BEGINS*/");
|
|
|
-+
|
|
|
-+static void
|
|
|
-+call_initialize_minimal (void)
|
|
|
-+{
|
|
|
-+ extern void __pthread_initialize_minimal_internal (void)
|
|
|
-+ __attribute ((visibility ("hidden")));
|
|
|
-+
|
|
|
-+ __pthread_initialize_minimal_internal ();
|
|
|
-+}
|
|
|
-+
|
|
|
-+SECTION (".init");
|
|
|
-+extern void __attribute__ ((section (".init"))) _init (void);
|
|
|
-+void
|
|
|
-+_init (void)
|
|
|
-+{
|
|
|
-+ /* The very first thing we must do is to set up the registers. */
|
|
|
-+ call_initialize_minimal ();
|
|
|
-+
|
|
|
-+ __asm__ ("ALIGN");
|
|
|
-+ __asm__("END_INIT");
|
|
|
-+ /* Now the epilog. */
|
|
|
-+ __asm__ ("\n/*@_init_PROLOG_ENDS*/");
|
|
|
-+ __asm__ ("\n/*@_init_EPILOG_BEGINS*/");
|
|
|
-+ SECTION(".init");
|
|
|
-+}
|
|
|
-+__asm__ ("END_INIT");
|
|
|
-+
|
|
|
-+/* End of the _init epilog, beginning of the _fini prolog. */
|
|
|
-+__asm__ ("\n/*@_init_EPILOG_ENDS*/");
|
|
|
-+__asm__ ("\n/*@_fini_PROLOG_BEGINS*/");
|
|
|
-+
|
|
|
-+SECTION (".fini");
|
|
|
-+extern void __attribute__ ((section (".fini"))) _fini (void);
|
|
|
-+void
|
|
|
-+_fini (void)
|
|
|
-+{
|
|
|
-+
|
|
|
-+ /* End of the _fini prolog. */
|
|
|
-+ __asm__ ("ALIGN");
|
|
|
-+ __asm__ ("END_FINI");
|
|
|
-+ __asm__ ("\n/*@_fini_PROLOG_ENDS*/");
|
|
|
-+
|
|
|
-+ /* Xtensa: It doesn't really matter whether GCC thinks this is a leaf
|
|
|
-+ function or not, and the scripts that are supposed to remove the
|
|
|
-+ call don't catch the literal, resulting in an undefined symbol
|
|
|
-+ reference. */
|
|
|
-+#if 0
|
|
|
-+ {
|
|
|
-+ /* Let GCC know that _fini is not a leaf function by having a dummy
|
|
|
-+ function call here. We arrange for this call to be omitted from
|
|
|
-+ either crt file. */
|
|
|
-+ extern void i_am_not_a_leaf (void);
|
|
|
-+ i_am_not_a_leaf ();
|
|
|
-+ }
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+ /* Beginning of the _fini epilog. */
|
|
|
-+ __asm__ ("\n/*@_fini_EPILOG_BEGINS*/");
|
|
|
-+ SECTION (".fini");
|
|
|
-+}
|
|
|
-+__asm__ ("END_FINI");
|
|
|
-+
|
|
|
-+/* End of the _fini epilog. Any further generated assembly (e.g. .ident)
|
|
|
-+ is shared between both crt files. */
|
|
|
-+__asm__ ("\n/*@_fini_EPILOG_ENDS*/");
|
|
|
-+__asm__ ("\n/*@TRAILER_BEGINS*/");
|
|
|
-+
|
|
|
-+/* End of file. */
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-vfork.S uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-vfork.S
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-vfork.S 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,48 @@
|
|
|
-+/* Copyright (C) 2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library. If not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#include <tls.h>
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ Save the PID value (save the negated value)
|
|
|
-+ Registers ar, as are available; pid, tp are preserved across
|
|
|
-+ */
|
|
|
-+#define SAVE_PID(pid, tp, ar, as) \
|
|
|
-+ rur tp, threadptr; \
|
|
|
-+ movi ar, TLS_PRE_TCB_SIZE; \
|
|
|
-+ sub tp, tp, ar; \
|
|
|
-+ l32i pid, tp, PID; \
|
|
|
-+ neg ar, pid; \
|
|
|
-+ s32i pid, tp, PID; \
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ Restore the PID value if we are back in the parent.
|
|
|
-+ */
|
|
|
-+#define RESTORE_PID(pid, tp, res) \
|
|
|
-+ beqz res, 1f; \
|
|
|
-+ s32i pid, tp, PID; \
|
|
|
-+1:
|
|
|
-+
|
|
|
-+#define RESTORE_PID12(ar, as, at) \
|
|
|
-+ rur as, threadptr; \
|
|
|
-+ movi ar, TLS_PRE_TCB_SIZE; \
|
|
|
-+ sub as, as, ar; \
|
|
|
-+ l32i ar, as, PID; \
|
|
|
-+ neg ar, ar; \
|
|
|
-+ s32i ar, as, PID;
|
|
|
-+
|
|
|
-+#include <libc/sysdeps/linux/xtensa/vfork.S>
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,108 @@
|
|
|
-+/* Copyright (C) 2003 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, write to the Free
|
|
|
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+ 02111-1307 USA. */
|
|
|
-+
|
|
|
-+#include <sysdep.h>
|
|
|
-+#include <tls.h>
|
|
|
-+/* #include <pt-machine.h> */
|
|
|
-+#ifndef __ASSEMBLER__
|
|
|
-+# include <pthreadP.h>
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
|
|
|
-+// FIXME: ENTRY includes an entry instruction, here we'd want entry sp, 48!
|
|
|
-+# undef PSEUDO
|
|
|
-+# define PSEUDO(name, syscall_name, args) \
|
|
|
-+ .text; \
|
|
|
-+ ENTRY (name) \
|
|
|
-+ SINGLE_THREAD_P(a15); \
|
|
|
-+ bnez a15, .Lpseudo_cancel; \
|
|
|
-+ DO_CALL (syscall_name, args); \
|
|
|
-+ bgez a2, .Lpseudo_done; \
|
|
|
-+ movi a4, -4095; \
|
|
|
-+ blt a2, a4, .Lpseudo_done; \
|
|
|
-+ j SYSCALL_ERROR_LABEL; \
|
|
|
-+ .Lpseudo_done: \
|
|
|
-+ retw; \
|
|
|
-+ .Lpseudo_cancel: \
|
|
|
-+ /* The syscall args are in a2...a7; no need to save */ \
|
|
|
-+ CENABLE; \
|
|
|
-+ /* The return value is in a10 and preserved across the syscall */ \
|
|
|
-+ DO_CALL (syscall_name, args); \
|
|
|
-+ CDISABLE; \
|
|
|
-+ bgez a2, .Lpseudo_end; \
|
|
|
-+ movi a4, -4095; \
|
|
|
-+ blt a2, a4, .Lpseudo_end; \
|
|
|
-+ j SYSCALL_ERROR_LABEL; \
|
|
|
-+ .Lpseudo_end:
|
|
|
-+
|
|
|
-+
|
|
|
-+# ifdef IS_IN_libpthread
|
|
|
-+# define CENABLE_FUNC __pthread_enable_asynccancel
|
|
|
-+# define CDISABLE_FUNC __pthread_disable_asynccancel
|
|
|
-+# define __local_multiple_threads __pthread_multiple_threads
|
|
|
-+# elif !defined NOT_IN_libc
|
|
|
-+# define CENABLE_FUNC __libc_enable_asynccancel
|
|
|
-+# define CDISABLE_FUNC __libc_disable_asynccancel
|
|
|
-+# define __local_multiple_threads __libc_multiple_threads
|
|
|
-+# elif defined IS_IN_librt
|
|
|
-+# define CENABLE_FUNC __librt_enable_asynccancel
|
|
|
-+# define CDISABLE_FUNC __librt_disable_asynccancel
|
|
|
-+# else
|
|
|
-+# error Unsupported library
|
|
|
-+# endif
|
|
|
-+
|
|
|
-+# define CENABLE movi a8, CENABLE_FUNC; \
|
|
|
-+ callx8 a8
|
|
|
-+# define CDISABLE movi a8, CDISABLE_FUNC; \
|
|
|
-+ callx8 a8
|
|
|
-+
|
|
|
-+# if defined IS_IN_libpthread || !defined NOT_IN_libc
|
|
|
-+# ifndef __ASSEMBLER__
|
|
|
-+extern int __local_multiple_threads attribute_hidden;
|
|
|
-+# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1)
|
|
|
-+# else
|
|
|
-+# define SINGLE_THREAD_P(reg) movi reg, __local_multiple_threads; \
|
|
|
-+ l32i reg, reg, 0;
|
|
|
-+# endif
|
|
|
-+
|
|
|
-+# else
|
|
|
-+# ifndef __ASSEMBLER__
|
|
|
-+# define SINGLE_THREAD_P \
|
|
|
-+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
|
|
|
-+ header.multiple_threads) == 0, 1)
|
|
|
-+# else
|
|
|
-+# define SINGLE_THREAD_P(reg) \
|
|
|
-+ rur reg, threadptr; \
|
|
|
-+ l32i reg, reg, MULTIPLE_THREADS_OFFSET;
|
|
|
-+# endif
|
|
|
-+# endif
|
|
|
-+
|
|
|
-+#else
|
|
|
-+
|
|
|
-+/* This code should never be used but we define it anyhow. */
|
|
|
-+# define SINGLE_THREAD_P (1)
|
|
|
-+# define NO_CANCELLATION 1
|
|
|
-+
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+
|
|
|
-+#ifndef __ASSEMBLER__
|
|
|
-+# define RTLD_SINGLE_THREAD_P \
|
|
|
-+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
|
|
|
-+ header.multiple_threads) == 0, 1)
|
|
|
-+#endif
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/vfork.S uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/vfork.S
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/vfork.S 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,59 @@
|
|
|
-+/* Copyright (C) 2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library. If not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#include <tls.h>
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ Save the PID value, save 0x80000000 if PID was 0.
|
|
|
-+ Registers a2 and a3 are available; ar should return the PID and as threadptr
|
|
|
-+ */
|
|
|
-+
|
|
|
-+#define SAVE_PID(pid,tp,ar,as) \
|
|
|
-+ rur tp, threadptr; \
|
|
|
-+ movi ar, TLS_PRE_TCB_SIZE; \
|
|
|
-+ sub tp, tp, ar; \
|
|
|
-+ l32i pid, tp, PID; \
|
|
|
-+ neg ar, pid; \
|
|
|
-+ movi as, 0x80000000; \
|
|
|
-+ moveqz ar, as, ar; \
|
|
|
-+ s32i ar, tp, PID; \
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ Restore the PID value, restore to 0 if saved value was 0x80000000
|
|
|
-+ Return value from the syscall is in a2.
|
|
|
-+ */
|
|
|
-+#define RESTORE_PID(pid,tp,res) \
|
|
|
-+ beqz res, 1f; \
|
|
|
-+ s32i pid, tp, PID; \
|
|
|
-+1:
|
|
|
-+
|
|
|
-+/*
|
|
|
-+ Special version for call12, where we don't have enough registers
|
|
|
-+ available to preserve the original PID.
|
|
|
-+ */
|
|
|
-+#define RESTORE_PID12(ar, as, at) \
|
|
|
-+ rur as, threadptr; \
|
|
|
-+ movi ar, TLS_PRE_TCB_SIZE; \
|
|
|
-+ sub as, as, ar; \
|
|
|
-+ l32i ar, as, PID; \
|
|
|
-+ movi at, 0x80000000; \
|
|
|
-+ sub at, at, ar; \
|
|
|
-+ neg ar, ar; \
|
|
|
-+ moveqz ar, at, at; \
|
|
|
-+ s32i ar, as, PID;
|
|
|
-+
|
|
|
-+#include <libc/sysdeps/linux/xtensa/vfork.S>
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/dl-tls.h uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/dl-tls.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/dl-tls.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,58 @@
|
|
|
-+/* Thread-local storage handling in the ELF dynamic linker. Xtensa version.
|
|
|
-+ Copyright (C) 2013 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, write to the Free
|
|
|
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+ 02111-1307 USA. */
|
|
|
-+
|
|
|
-+#ifndef _XTENSA_DL_TLS_H
|
|
|
-+#define _XTENSA_DL_TLS_H 1
|
|
|
-+
|
|
|
-+/* Type used for the representation of TLS information in the GOT. */
|
|
|
-+typedef struct
|
|
|
-+{
|
|
|
-+ unsigned long int ti_module;
|
|
|
-+ unsigned long int ti_offset;
|
|
|
-+} tls_index;
|
|
|
-+
|
|
|
-+extern void *__tls_get_addr (tls_index *ti);
|
|
|
-+
|
|
|
-+/* Type used to represent a TLS descriptor. */
|
|
|
-+struct tlsdesc
|
|
|
-+{
|
|
|
-+ union
|
|
|
-+ {
|
|
|
-+ void *pointer;
|
|
|
-+ long value;
|
|
|
-+ } argument;
|
|
|
-+ ptrdiff_t (*entry)(struct tlsdesc *);
|
|
|
-+};
|
|
|
-+
|
|
|
-+/* Type used as the argument in a TLS descriptor for a symbol that
|
|
|
-+ needs dynamic TLS offsets. */
|
|
|
-+struct tlsdesc_dynamic_arg
|
|
|
-+{
|
|
|
-+ tls_index tlsinfo;
|
|
|
-+ size_t gen_count;
|
|
|
-+};
|
|
|
-+
|
|
|
-+extern ptrdiff_t attribute_hidden
|
|
|
-+ _dl_tlsdesc_return(struct tlsdesc_dynamic_arg *);
|
|
|
-+
|
|
|
-+extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset);
|
|
|
-+extern ptrdiff_t attribute_hidden
|
|
|
-+ _dl_tlsdesc_dynamic(struct tlsdesc_dynamic_arg *);
|
|
|
-+
|
|
|
-+#endif
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/jmpbuf-unwind.h uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/jmpbuf-unwind.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/jmpbuf-unwind.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,32 @@
|
|
|
-+/* Copyright (C) 2005,2006 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#include <setjmp.h>
|
|
|
-+#include <stdint.h>
|
|
|
-+#include <unwind.h>
|
|
|
-+
|
|
|
-+/* Test if longjmp to JMPBUF would unwind the frame
|
|
|
-+ containing a local variable at ADDRESS. */
|
|
|
-+#undef _JMPBUF_UNWINDS
|
|
|
-+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
|
|
|
-+ ((void *) (address) < (void *) demangle (jmpbuf[JB_SP]))
|
|
|
-+
|
|
|
-+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
|
|
|
-+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
|
|
|
-+
|
|
|
-+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
|
|
|
-+ ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/libc-tls.c uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/libc-tls.c
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/libc-tls.c 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,36 @@
|
|
|
-+/* Thread-local storage handling in the ELF dynamic linker. Xtensa version.
|
|
|
-+ Copyright (C) 2005 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, see
|
|
|
-+ <http://www.gnu.org/licenses/>. */
|
|
|
-+
|
|
|
-+#include <sysdeps/generic/libc-tls.c>
|
|
|
-+#include <dl-tls.h>
|
|
|
-+
|
|
|
-+#if defined(USE_TLS) && USE_TLS
|
|
|
-+
|
|
|
-+/* On Xtensa, linker optimizations are not required, so __tls_get_addr
|
|
|
-+ can be called even in statically linked binaries. In this case module
|
|
|
-+ must be always 1 and PT_TLS segment exist in the binary, otherwise it
|
|
|
-+ would not link. */
|
|
|
-+
|
|
|
-+void *
|
|
|
-+__tls_get_addr (tls_index *ti)
|
|
|
-+{
|
|
|
-+ dtv_t *dtv = THREAD_DTV ();
|
|
|
-+ return (char *) dtv[1].pointer.val + ti->ti_offset;
|
|
|
-+}
|
|
|
-+
|
|
|
-+#endif
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/Makefile.arch uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/Makefile.arch
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/Makefile.arch 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,40 @@
|
|
|
-+# Copyright (C) 2012 Free Software Foundation, Inc.
|
|
|
-+# This file is part of the GNU C Library.
|
|
|
-+#
|
|
|
-+# The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+# modify it under the terms of the GNU Lesser General Public
|
|
|
-+# License as published by the Free Software Foundation; either
|
|
|
-+# version 2.1 of the License, or (at your option) any later version.
|
|
|
-+#
|
|
|
-+# The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+# Lesser General Public License for more details.
|
|
|
-+#
|
|
|
-+# You should have received a copy of the GNU Lesser General Public
|
|
|
-+# License along with the GNU C Library; if not, write to the Free
|
|
|
-+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+# 02111-1307 USA.
|
|
|
-+
|
|
|
-+CFLAGS-pt-raise.c = -DNOT_IN_libc -DIS_IN_libpthread
|
|
|
-+
|
|
|
-+ASFLAGS-dl-tlsdesc.S = -DNOT_IN_libc=1
|
|
|
-+ASFLAGS-pthread_spin_lock.S = -DNOT_IN_libc -DIS_IN_libpthread
|
|
|
-+ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc -DIS_IN_libpthread
|
|
|
-+ASFLAGS-nptl-sysdep.S = -DNOT_IN_libc -DIS_IN_libpthread \
|
|
|
-+ -D_LIBC_REENTRANT \
|
|
|
-+ -I$(top_srcdir)libc/sysdeps/linux/xtensa
|
|
|
-+
|
|
|
-+libc_arch_a_CSRC = libc-tls.c
|
|
|
-+librt_arch_a_SSRC = dl-tlsdesc.S
|
|
|
-+
|
|
|
-+CFLAGS-gen_tlsdesc.c = -S
|
|
|
-+$(libpthread_arch_OUT)/gen_tlsdesc.c: $(libpthread_arch_DIR)/tlsdesc.sym | $(libpthread_arch_OUT)
|
|
|
-+ $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@
|
|
|
-+$(libpthread_arch_OUT)/gen_tlsdesc.s: $(libpthread_arch_OUT)/gen_tlsdesc.c | headers
|
|
|
-+ $(compile.c)
|
|
|
-+libpthread-generated-y += $(libpthread_arch_OUT)/gen_tlsdesc.s
|
|
|
-+$(libpthread_arch_OUT)/tlsdesc.h: $(libpthread_arch_OUT)/gen_tlsdesc.s
|
|
|
-+ $(do_sed) $(PTHREAD_GENERATE_MANGLE) $< > $@
|
|
|
-+ @if test ! -s $@ ; then rm -f $@ ; false ; fi
|
|
|
-+pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(libpthread_arch_OUT)/tlsdesc.h
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/pthreaddef.h uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthreaddef.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthreaddef.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,39 @@
|
|
|
-+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, write to the Free
|
|
|
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+ 02111-1307 USA. */
|
|
|
-+
|
|
|
-+/* Default stack size. */
|
|
|
-+#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
|
|
|
-+
|
|
|
-+/* Required stack pointer alignment at beginning. */
|
|
|
-+#define STACK_ALIGN 16
|
|
|
-+
|
|
|
-+/* Minimal stack size after allocating thread descriptor and guard size. */
|
|
|
-+#define MINIMAL_REST_STACK 2048
|
|
|
-+
|
|
|
-+/* Alignment requirement for TCB. */
|
|
|
-+#define TCB_ALIGNMENT 16
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Location of current stack frame. */
|
|
|
-+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
|
|
|
-+
|
|
|
-+
|
|
|
-+/* XXX Until we have a better place keep the definitions here. */
|
|
|
-+
|
|
|
-+#define __exit_thread_inline(val) \
|
|
|
-+ INLINE_SYSCALL (exit, 1, (val))
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,37 @@
|
|
|
-+/* Copyright (C) 2012 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, write to the Free
|
|
|
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+ 02111-1307 USA. */
|
|
|
-+
|
|
|
-+ .text
|
|
|
-+ .align 4
|
|
|
-+
|
|
|
-+ .globl pthread_spin_lock
|
|
|
-+pthread_spin_lock:
|
|
|
-+
|
|
|
-+ entry a1, 16
|
|
|
-+
|
|
|
-+ movi a3, 0
|
|
|
-+ wsr a3, scompare1
|
|
|
-+ movi a3, 1
|
|
|
-+1: s32c1i a3, a2, 0
|
|
|
-+ bnez a3, 1b
|
|
|
-+ movi a2, 0
|
|
|
-+
|
|
|
-+ retw
|
|
|
-+
|
|
|
-+ .type pthread_spin_lock, @function
|
|
|
-+ .size pthread_spin_lock, .-pthread_spin_lock
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,40 @@
|
|
|
-+/* Copyright (C) 2005 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, write to the Free
|
|
|
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+ 02111-1307 USA. */
|
|
|
-+
|
|
|
-+#define _ERRNO_H 1
|
|
|
-+#include <bits/errno.h>
|
|
|
-+
|
|
|
-+ .text
|
|
|
-+ .align 4
|
|
|
-+
|
|
|
-+ .globl pthread_spin_trylock
|
|
|
-+pthread_spin_trylock:
|
|
|
-+
|
|
|
-+ entry a1, 16
|
|
|
-+
|
|
|
-+ movi a3, 0
|
|
|
-+ wsr a3, scompare1
|
|
|
-+ movi a3, 1
|
|
|
-+ s32c1i a3, a2, 0
|
|
|
-+ movi a2, EBUSY
|
|
|
-+ moveqz a2, a3, a3
|
|
|
-+
|
|
|
-+ retw
|
|
|
-+
|
|
|
-+ .type pthread_spin_trylock, @function
|
|
|
-+ .size pthread_spin_trylock, .-pthread_spin_trylock
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/tcb-offsets.sym uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tcb-offsets.sym
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tcb-offsets.sym 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,7 @@
|
|
|
-+#include <sysdep.h>
|
|
|
-+#include <tls.h>
|
|
|
-+
|
|
|
-+TLS_PRE_TCB_SIZE sizeof (struct pthread)
|
|
|
-+MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
|
|
|
-+PID offsetof (struct pthread, pid)
|
|
|
-+TID offsetof (struct pthread, tid)
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/tlsdesc.sym uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tlsdesc.sym
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tlsdesc.sym 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,10 @@
|
|
|
-+#include <stddef.h>
|
|
|
-+#include <sysdep.h>
|
|
|
-+#include <tls.h>
|
|
|
-+#include <link.h>
|
|
|
-+#include <dl-tls.h>
|
|
|
-+
|
|
|
-+TLSDESC_ARG offsetof(struct tlsdesc, argument)
|
|
|
-+TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count)
|
|
|
-+TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
|
|
|
-+TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
|
|
|
-diff -Nur uClibc-git/libpthread/nptl/sysdeps/xtensa/tls.h uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tls.h
|
|
|
|
|
|
-+++ uClibc-xtensa/libpthread/nptl/sysdeps/xtensa/tls.h 2014-06-03 12:04:16.669187814 +0200
|
|
|
-@@ -0,0 +1,159 @@
|
|
|
-+/* Definition for thread-local data handling. NPTL/Xtensa version.
|
|
|
-+ Copyright (C) 2012 Free Software Foundation, Inc.
|
|
|
-+ This file is part of the GNU C Library.
|
|
|
-+
|
|
|
-+ The GNU C Library is free software; you can redistribute it and/or
|
|
|
-+ modify it under the terms of the GNU Lesser General Public
|
|
|
-+ License as published by the Free Software Foundation; either
|
|
|
-+ version 2.1 of the License, or (at your option) any later version.
|
|
|
-+
|
|
|
-+ The GNU C Library is distributed in the hope that it will be useful,
|
|
|
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
-+ Lesser General Public License for more details.
|
|
|
-+
|
|
|
-+ You should have received a copy of the GNU Lesser General Public
|
|
|
-+ License along with the GNU C Library; if not, write to the Free
|
|
|
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
-+ 02111-1307 USA. */
|
|
|
-+
|
|
|
-+#ifndef _TLS_H
|
|
|
-+#define _TLS_H
|
|
|
-+
|
|
|
-+#ifndef __ASSEMBLER__
|
|
|
-+
|
|
|
-+# include <stdbool.h>
|
|
|
-+# include <stddef.h>
|
|
|
-+# include <stdint.h>
|
|
|
-+
|
|
|
-+/* Type for the dtv. */
|
|
|
-+typedef union dtv
|
|
|
-+{
|
|
|
-+ size_t counter;
|
|
|
-+ struct
|
|
|
-+ {
|
|
|
-+ void *val;
|
|
|
-+ bool is_static;
|
|
|
-+ } pointer;
|
|
|
-+} dtv_t;
|
|
|
-+
|
|
|
-+
|
|
|
-+#else /* __ASSEMBLER__ */
|
|
|
-+# include <tcb-offsets.h>
|
|
|
-+#endif /* __ASSEMBLER__ */
|
|
|
-+
|
|
|
-+/* We require TLS support in the tools. */
|
|
|
-+#define HAVE_TLS_SUPPORT 1
|
|
|
-+#define HAVE_TLS_MODEL_ATTRIBUTE 1
|
|
|
-+#define HAVE___THREAD 1
|
|
|
-+
|
|
|
-+/* Signal that TLS support is available. */
|
|
|
-+#define USE_TLS 1
|
|
|
-+
|
|
|
-+#ifndef __ASSEMBLER__
|
|
|
-+
|
|
|
-+/* Get system call information. */
|
|
|
-+# include <sysdep.h>
|
|
|
-+
|
|
|
-+/* The TLS blocks start right after the TCB. */
|
|
|
-+# define TLS_DTV_AT_TP 1
|
|
|
-+
|
|
|
-+/* Get the thread descriptor definition. */
|
|
|
-+# include <../../descr.h>
|
|
|
-+
|
|
|
-+typedef struct
|
|
|
-+{
|
|
|
-+ dtv_t *dtv;
|
|
|
-+ void *private;
|
|
|
-+} tcbhead_t;
|
|
|
-+
|
|
|
-+/* This is the size of the initial TCB. */
|
|
|
-+# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
|
|
|
-+
|
|
|
-+/* Alignment requirements for the initial TCB. */
|
|
|
-+# define TLS_INIT_TCB_ALIGN 16
|
|
|
-+
|
|
|
-+/* This is the size of the TCB. */
|
|
|
-+# define TLS_TCB_SIZE sizeof (tcbhead_t)
|
|
|
-+
|
|
|
-+/* This is the size we need before TCB. */
|
|
|
-+# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
|
|
|
-+
|
|
|
-+/* Alignment requirements for the TCB. */
|
|
|
-+# define TLS_TCB_ALIGN 16
|
|
|
-+
|
|
|
-+
|
|
|
-+/* Install the dtv pointer. The pointer passed is to the element with
|
|
|
-+ index -1 which contain the length. */
|
|
|
-+# define INSTALL_DTV(tcbp, dtvp) \
|
|
|
-+ (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
|
|
|
-+
|
|
|
-+/* Install new dtv for current thread. */
|
|
|
-+# define INSTALL_NEW_DTV(dtv) \
|
|
|
-+ ({ tcbhead_t *__tcbp; \
|
|
|
-+ __asm__ __volatile__ ("rur %0, threadptr" : "=r" (__tcbp)); \
|
|
|
-+ __tcbp->dtv = (dtv); }) \
|
|
|
-+
|
|
|
-+/* Return dtv of given thread descriptor. */
|
|
|
-+# define GET_DTV(tcbp) \
|
|
|
-+ (((tcbhead_t *) (tcbp))->dtv)
|
|
|
-+
|
|
|
-+/* Code to initially initialize the thread pointer. This might need
|
|
|
-+ special attention since 'errno' is not yet available and if the
|
|
|
-+ operation can cause a failure 'errno' must not be touched. */
|
|
|
-+# define TLS_INIT_TP(tcbp, secondcall) \
|
|
|
-+ ({ __asm__ __volatile__ ("wur %0, threadptr" : : "r" (tcbp)); 0; })
|
|
|
-+
|
|
|
-+/* Return the address of the dtv for the current thread. */
|
|
|
-+# define THREAD_DTV() \
|
|
|
-+ ({ tcbhead_t *__tcbp; \
|
|
|
-+ __asm__ __volatile__ ("rur %0, threadptr" : "=r" (__tcbp)); \
|
|
|
-+ __tcbp->dtv; })
|
|
|
-+
|
|
|
-+/* Return the thread descriptor for the current thread. */
|
|
|
-+# define THREAD_SELF \
|
|
|
-+ ({ struct pthread *__self; \
|
|
|
-+ __asm__ ("rur %0, threadptr" : "=r" (__self)); \
|
|
|
-+ __self - 1; })
|
|
|
-+
|
|
|
-+/* Magic for libthread_db to know how to do THREAD_SELF. */
|
|
|
-+# define DB_THREAD_SELF \
|
|
|
-+ CONST_THREAD_AREA (32, sizeof (struct pthread))
|
|
|
-+
|
|
|
-+/* Access to data in the thread descriptor is easy. */
|
|
|
-+#define THREAD_GETMEM(descr, member) \
|
|
|
-+ descr->member
|
|
|
-+#define THREAD_GETMEM_NC(descr, member, idx) \
|
|
|
-+ descr->member[idx]
|
|
|
-+#define THREAD_SETMEM(descr, member, value) \
|
|
|
-+ descr->member = (value)
|
|
|
-+#define THREAD_SETMEM_NC(descr, member, idx, value) \
|
|
|
-+ descr->member[idx] = (value)
|
|
|
-+
|
|
|
-+/* Get and set the global scope generation counter in struct pthread. */
|
|
|
-+#define THREAD_GSCOPE_FLAG_UNUSED 0
|
|
|
-+#define THREAD_GSCOPE_FLAG_USED 1
|
|
|
-+#define THREAD_GSCOPE_FLAG_WAIT 2
|
|
|
-+#define THREAD_GSCOPE_RESET_FLAG() \
|
|
|
-+ do \
|
|
|
-+ { int __res \
|
|
|
-+ = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \
|
|
|
-+ THREAD_GSCOPE_FLAG_UNUSED); \
|
|
|
-+ if (__res == THREAD_GSCOPE_FLAG_WAIT) \
|
|
|
-+ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \
|
|
|
-+ } \
|
|
|
-+ while (0)
|
|
|
-+#define THREAD_GSCOPE_SET_FLAG() \
|
|
|
-+ do \
|
|
|
-+ { \
|
|
|
-+ THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \
|
|
|
-+ atomic_write_barrier (); \
|
|
|
-+ } \
|
|
|
-+ while (0)
|
|
|
-+
|
|
|
-+#define THREAD_GSCOPE_WAIT() \
|
|
|
-+ GL(dl_wait_lookup_done) ()
|
|
|
-+
|
|
|
-+#endif /* __ASSEMBLER__ */
|
|
|
-+
|
|
|
-+#endif /* tls.h */
|