|
@@ -0,0 +1,3515 @@
|
|
|
+diff -Nur uClibc-git/include/elf.h uClibc-xtensa/include/elf.h
|
|
|
+--- uClibc-git/include/elf.h 2014-06-02 17:40:33.826710944 +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-git/include/link.h 2014-06-02 17:40:33.846711055 +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-git/ldso/include/dl-hash.h 2014-06-02 17:40:33.902711365 +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-git/ldso/include/inline-hashtab.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/ldso/include/ldsodefs.h 2014-06-02 17:40:33.922711475 +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-git/ldso/include/tlsdeschtab.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/ldso/ldso/dl-tls.c 2014-06-02 17:40:33.946711608 +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-git/ldso/ldso/fdpic/dl-inlines.h 2014-06-02 17:40:33.950711630 +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-git/ldso/ldso/xtensa/dl-debug.h 2014-06-02 17:40:33.958711675 +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-git/ldso/ldso/xtensa/dl-startup.h 2014-06-02 17:40:33.958711675 +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-git/ldso/ldso/xtensa/dl-sysdep.h 2014-06-02 17:40:33.958711675 +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-git/ldso/ldso/xtensa/dl-tlsdesc.S 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/ldso/ldso/xtensa/elfinterp.c 2014-06-02 17:40:33.958711675 +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-git/ldso/ldso/xtensa/resolve.S 2014-06-02 17:40:33.958711675 +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-git/libc/sysdeps/linux/xtensa/clone.S 2014-06-02 17:40:34.722715903 +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-git/libc/sysdeps/linux/xtensa/fork.c 2014-06-02 17:40:34.726715926 +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-git/libc/sysdeps/linux/xtensa/jmpbuf-unwind.h 2014-06-02 17:40:34.726715926 +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-git/libc/sysdeps/linux/xtensa/Makefile.arch 2014-06-02 17:40:34.686715704 +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-git/libc/sysdeps/linux/xtensa/sys/ptrace.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libc/sysdeps/linux/xtensa/sysdep.h 2014-06-02 17:40:34.726715926 +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-git/libc/sysdeps/linux/xtensa/vfork.S 2014-06-02 17:40:34.726715926 +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-git/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c 2014-06-02 17:40:35.102718006 +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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/pthreadtypes.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/bits/semaphore.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/clone.S 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/createthread.c 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/fork.c 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.c 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/lowlevellock.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/Makefile.arch 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pthread_once.c 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-initfini.c 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/pt-vfork.S 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/sysdep-cancel.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/unix/sysv/linux/xtensa/vfork.S 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/dl-tls.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/jmpbuf-unwind.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/libc-tls.c 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/Makefile.arch 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/pthreaddef.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/tcb-offsets.sym 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/tlsdesc.sym 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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-git/libpthread/nptl/sysdeps/xtensa/tls.h 1970-01-01 01:00:00.000000000 +0100
|
|
|
|
|
|
+@@ -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 */
|