From e96fe50f0dd8d76fabfe139b46f059e3b2373b83 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 20 May 2008 19:31:24 +0000 Subject: Updated to fedora-glibc-20080520T1924 --- ChangeLog | 49 ++++++++++++++++++ elf/soinit.c | 4 -- fedora/branch.mk | 4 +- fedora/glibc.spec.in | 5 +- nptl/ChangeLog | 4 ++ .../sysdeps/unix/sysv/linux/sparc/sparc64/Makefile | 4 ++ nscd/aicache.c | 2 +- nscd/cache.c | 39 +++++++++------ nscd/connections.c | 58 ++++++++++++++++++---- nscd/grpcache.c | 11 ++-- nscd/hstcache.c | 4 +- nscd/initgrcache.c | 4 +- nscd/nscd.h | 3 +- nscd/pwdcache.c | 11 ++-- nscd/servicescache.c | 4 +- resolv/res_query.c | 15 ++++++ resolv/res_send.c | 7 +++ sysdeps/sparc/Makefile | 4 ++ sysdeps/sparc/machine-gmon.h | 33 ++++++++++++ sysdeps/sparc/sparc-mcount.S | 29 +++++++++++ sysdeps/sparc/sparc64/backtrace.c | 58 ++++++++++++++++++++++ .../unix/sysv/linux/sparc/sparc32/sigcontextinfo.h | 3 ++ 22 files changed, 306 insertions(+), 49 deletions(-) create mode 100644 nptl/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile create mode 100644 sysdeps/sparc/machine-gmon.h create mode 100644 sysdeps/sparc/sparc-mcount.S create mode 100644 sysdeps/sparc/sparc64/backtrace.c diff --git a/ChangeLog b/ChangeLog index 671ec52f3f..9ffb261908 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +2008-05-20 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h + (FIRST_FRAME_POINTER): Define. + +2008-05-09 David S. Miller + + * sysdeps/sparc/sparc64/backtrace.c: New file. + +2008-05-14 David S. Miller + + * sysdeps/sparc/machine-gmon.h: New file. + * sysdeps/sparc/sparc-mcount.S: Likewise. + * sysdeps/sparc/Makefile: Add sparc-mcount target to + sysdep_routines in gmon directory. + +2008-05-19 Jakub Jelinek + + * elf/soinit.c (__EH_FRAME_BEGIN__): Remove. + +2008-05-19 Ulrich Drepper + + * resolv/res_query.c (__libc_res_nquery): In case one of two + answer was too short don't try to read that answer's header. + + * resolv/res_send.c (send_dg): In case of timeout and there are + two queries and one has been answered, return value indicating + success. + +2008-05-18 Ulrich Drepper + + * nscd/cache.c (cache_add): Take additional parameter specifying + whether this is in response of a cache refill. Check alignment + of package data. Revamp waking of pruning thread. + (prune_cache): Small optimization. + * nscd/nscd.h: Adjust cache_add prototypes. + * nscd/aicache.c: Adjust cache_add calls. + * nscd/grpcache.c: Likewise. + * nscd/hstcache.c: Likewise. + * nscd/initgrcache.c: Likewise. + * nscd/pwdcache.c: Likewise. + * nscd/servicescache.c: Likewise. + * nscd/connections.c (restart): Really disable cache use before + exec attempt. If it fails, reenable cache. + (nscd_run_prune): Initialize wakeup_time. After wakeup, set wakeup + time to max to be able to notice concurrent cache additions. Unlock + prune_lock while performing gc. Afterwards compute wakeup time with + current wakeup_time value in mind. + 2008-05-17 Ulrich Drepper * nscd/mem.c (gc): Avoid stack overflow when allocating move list. diff --git a/elf/soinit.c b/elf/soinit.c index c0a881ef5d..6fecbb5674 100644 --- a/elf/soinit.c +++ b/elf/soinit.c @@ -20,10 +20,6 @@ run_hooks (void (*const list[]) (void)) (**list) (); } -static const char __EH_FRAME_BEGIN__[] - __attribute__ ((used, section (".eh_frame"))) - = { }; - /* This function will be called from _init in init-first.c. */ void __libc_global_ctors (void) diff --git a/fedora/branch.mk b/fedora/branch.mk index c88650ca1d..a040576330 100644 --- a/fedora/branch.mk +++ b/fedora/branch.mk @@ -3,5 +3,5 @@ glibc-branch := fedora glibc-base := HEAD DIST_BRANCH := devel COLLECTION := dist-f8 -fedora-sync-date := 2008-05-18 10:17 UTC -fedora-sync-tag := fedora-glibc-20080518T1017 +fedora-sync-date := 2008-05-20 19:24 UTC +fedora-sync-tag := fedora-glibc-20080520T1924 diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in index 648e8eba09..3b06768f62 100644 --- a/fedora/glibc.spec.in +++ b/fedora/glibc.spec.in @@ -19,7 +19,7 @@ Summary: The GNU libc libraries Name: glibc Version: @glibcversion@ -Release: 3 +Release: 4 # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries. # Things that are linked directly into dynamically linked programs # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional @@ -976,6 +976,9 @@ rm -f *.filelist* %endif %changelog +* Tue May 20 2008 Jakub Jelinek 2.8.90-4 +- further getaddrinfo and nscd fixes + * Sun May 18 2008 Jakub Jelinek 2.8.90-3 - getaddrinfo and nscd fixes - reenable assertion checking in rawhide diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 56c5baea6c..ac01c3e5bb 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,7 @@ +2008-05-19 Jakub Jelinek + + * elf/soinit.c (__EH_FRAME_BEGIN__): Remove. + 2008-05-10 Ulrich Drepper * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Access diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile new file mode 100644 index 0000000000..774b267efb --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile @@ -0,0 +1,4 @@ +ifeq ($(subdir),nptl) +CFLAGS-pause.c += -fexceptions +CFLAGS-sigsuspend.c += -fexceptions +endif diff --git a/nscd/aicache.c b/nscd/aicache.c index 7ae5a1645c..5ffab76a04 100644 --- a/nscd/aicache.c +++ b/nscd/aicache.c @@ -558,7 +558,7 @@ next_nip: pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, &dataset->head, - true, db, uid); + true, db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); diff --git a/nscd/cache.c b/nscd/cache.c index f4a9de530a..2faaf3403e 100644 --- a/nscd/cache.c +++ b/nscd/cache.c @@ -135,7 +135,7 @@ cache_search (request_type type, void *key, size_t len, int cache_add (int type, const void *key, size_t len, struct datahead *packet, bool first, struct database_dyn *table, - uid_t owner) + uid_t owner, bool prune_wakeup) { if (__builtin_expect (debug_level >= 2, 0)) { @@ -180,6 +180,7 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet, assert (newp->key + newp->len <= table->head->first_free); newp->owner = owner; newp->packet = (char *) packet - table->data; + assert ((newp->packet & BLOCK_ALIGN_M1) == 0); /* Put the new entry in the first position. */ do @@ -211,19 +212,27 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet, (char *) &table->head->array[hash] - (char *) table->head + sizeof (ref_t), MS_ASYNC); - /* Perhaps the prune thread for the data is not running in a long - time. Wake it if necessary. */ - time_t next_wakeup = table->wakeup_time; - while (next_wakeup + CACHE_PRUNE_INTERVAL > packet->timeout) - if (atomic_compare_and_exchange_bool_acq (&table->wakeup_time, - packet->timeout, - next_wakeup) == 0) - { + /* We do not have to worry about the pruning thread if we are + re-adding the data since this is done by the pruning thread. We + also do not have to do anything in case this is not the first + time the data is entered since different data heads all have the + same timeout. */ + if (first && prune_wakeup) + { + /* Perhaps the prune thread for the table is not running in a long + time. Wake it if necessary. */ + pthread_mutex_lock (&table->prune_lock); + time_t next_wakeup = table->wakeup_time; + bool do_wakeup = false; + if (next_wakeup > packet->timeout + CACHE_PRUNE_INTERVAL) + { + table->wakeup_time = packet->timeout; + do_wakeup = true; + } + pthread_mutex_unlock (&table->prune_lock); + if (do_wakeup) pthread_cond_signal (&table->prune_cond); - break; - } - else - next_wakeup = table->wakeup_time; + } /* Mark the in-flight memory as unused. */ for (enum in_flight idx = 0; idx < IDX_last; ++idx) @@ -436,7 +445,8 @@ prune_cache (struct database_dyn *table, time_t now, int fd) ref_t *old = &table->head->array[first]; ref_t run = table->head->array[first]; - while (run != ENDREF) + assert (run != ENDREF); + do { struct hashentry *runp = (struct hashentry *) (data + run); struct datahead *dh @@ -462,6 +472,7 @@ prune_cache (struct database_dyn *table, time_t now, int fd) run = runp->next; } } + while (run != ENDREF); } ++first; diff --git a/nscd/connections.c b/nscd/connections.c index 15148bdf3d..e6a2c946ae 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -1330,11 +1330,14 @@ cannot change to old working directory: %s; disabling paranoia mode"), } /* Synchronize memory. */ + int32_t certainly[lastdb]; for (int cnt = 0; cnt < lastdb; ++cnt) if (dbs[cnt].enabled) { /* Make sure nobody keeps using the database. */ dbs[cnt].head->timestamp = 0; + certainly[cnt] = dbs[cnt].head->nscd_certainly_running; + dbs[cnt].head->nscd_certainly_running = 0; if (dbs[cnt].persistent) // XXX async OK? @@ -1357,6 +1360,15 @@ cannot change to old working directory: %s; disabling paranoia mode"), dbg_log (_("cannot change current working directory to \"/\": %s"), strerror (errno)); paranoia = 0; + + /* Reenable the databases. */ + time_t now = time (NULL); + for (int cnt = 0; cnt < lastdb; ++cnt) + if (dbs[cnt].enabled) + { + dbs[cnt].head->timestamp = now; + dbs[cnt].head->nscd_certainly_running = certainly[cnt]; + } } @@ -1394,42 +1406,68 @@ nscd_run_prune (void *p) int dont_need_update = setup_thread (&dbs[my_number]); + time_t now = time (NULL); + /* We are running. */ - dbs[my_number].head->timestamp = time (NULL); + dbs[my_number].head->timestamp = now; struct timespec prune_ts; - if (clock_gettime (timeout_clock, &prune_ts) == -1) + if (__builtin_expect (clock_gettime (timeout_clock, &prune_ts) == -1, 0)) /* Should never happen. */ abort (); /* Compute the initial timeout time. Prevent all the timers to go off at the same time by adding a db-based value. */ prune_ts.tv_sec += CACHE_PRUNE_INTERVAL + my_number; + dbs[my_number].wakeup_time = now + CACHE_PRUNE_INTERVAL + my_number; + + pthread_mutex_t *prune_lock = &dbs[my_number].prune_lock; + pthread_cond_t *prune_cond = &dbs[my_number].prune_cond; - pthread_mutex_lock (&dbs[my_number].prune_lock); + pthread_mutex_lock (prune_lock); while (1) { /* Wait, but not forever. */ - int e = pthread_cond_timedwait (&dbs[my_number].prune_cond, - &dbs[my_number].prune_lock, - &prune_ts); - assert (e == 0 || e == ETIMEDOUT); + int e = pthread_cond_timedwait (prune_cond, prune_lock, &prune_ts); + assert (__builtin_expect (e == 0 || e == ETIMEDOUT, 1)); time_t next_wait; - time_t now = time (NULL); + now = time (NULL); if (e == ETIMEDOUT || now >= dbs[my_number].wakeup_time) { + /* We will determine the new timout values based on the + cache content. Should there be concurrent additions to + the cache which are not accounted for in the cache + pruning we want to know about it. Therefore set the + timeout to the maximum. It will be descreased when adding + new entries to the cache, if necessary. */ + if (sizeof (time_t) == sizeof (long int)) + dbs[my_number].wakeup_time = LONG_MAX; + else + dbs[my_number].wakeup_time = INT_MAX; + + pthread_mutex_unlock (prune_lock); + next_wait = prune_cache (&dbs[my_number], now, -1); + next_wait = MAX (next_wait, CACHE_PRUNE_INTERVAL); /* If clients cannot determine for sure whether nscd is running we need to wake up occasionally to update the timestamp. Wait 90% of the update period. */ #define UPDATE_MAPPING_TIMEOUT (MAPPING_TIMEOUT * 9 / 10) if (__builtin_expect (! dont_need_update, 0)) - next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait); + { + next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait); + dbs[my_number].head->timestamp = now; + } + + pthread_mutex_lock (prune_lock); /* Make it known when we will wake up again. */ - dbs[my_number].wakeup_time = now + next_wait; + if (now + next_wait < dbs[my_number].wakeup_time) + dbs[my_number].wakeup_time = now + next_wait; + else + next_wait = dbs[my_number].wakeup_time - now; } else /* The cache was just pruned. Do not do it again now. Just diff --git a/nscd/grpcache.c b/nscd/grpcache.c index 9921ae313e..e391dc3984 100644 --- a/nscd/grpcache.c +++ b/nscd/grpcache.c @@ -147,7 +147,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -353,7 +353,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, if (req->type == GETGRBYGID) { if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true, - db, owner) < 0) + db, owner, he == NULL) < 0) goto out; first = false; @@ -362,7 +362,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, else if (strcmp (key_copy, gr_name) != 0) { if (cache_add (GETGRBYNAME, key_copy, key_len + 1, - &dataset->head, true, db, owner) < 0) + &dataset->head, true, db, owner, he == NULL) < 0) goto out; first = false; @@ -372,12 +372,13 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, if ((req->type == GETGRBYNAME || db->propagate) && __builtin_expect (cache_add (GETGRBYNAME, gr_name, gr_name_len, - &dataset->head, first, db, owner) + &dataset->head, first, db, owner, + he == NULL) == 0, 1)) { if (req->type == GETGRBYNAME && db->propagate) (void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head, - false, db, owner); + false, db, owner, false); } out: diff --git a/nscd/hstcache.c b/nscd/hstcache.c index 3ceb6715ce..d4dd51f11a 100644 --- a/nscd/hstcache.c +++ b/nscd/hstcache.c @@ -156,7 +156,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -408,7 +408,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, || req->type == GETHOSTBYADDRv6); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); } diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c index 94e909d4ae..3355df5164 100644 --- a/nscd/initgrcache.c +++ b/nscd/initgrcache.c @@ -231,7 +231,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, uid); + &dataset->head, true, db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -398,7 +398,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (INITGROUPS, cp, req->key_len, &dataset->head, true, - db, uid); + db, uid, he == NULL); pthread_rwlock_unlock (&db->lock); } diff --git a/nscd/nscd.h b/nscd/nscd.h index b024017fd4..b07256de80 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -231,7 +231,8 @@ extern struct datahead *cache_search (request_type, void *key, size_t len, uid_t owner); extern int cache_add (int type, const void *key, size_t len, struct datahead *packet, bool first, - struct database_dyn *table, uid_t owner); + struct database_dyn *table, uid_t owner, + bool prune_wakeup); extern time_t prune_cache (struct database_dyn *table, time_t now, int fd); /* pwdcache.c */ diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c index 2d0a26592c..4a0cabd240 100644 --- a/nscd/pwdcache.c +++ b/nscd/pwdcache.c @@ -154,7 +154,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -348,7 +348,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, if (req->type == GETPWBYUID) { if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true, - db, owner) < 0) + db, owner, he == NULL) < 0) goto out; first = false; @@ -357,7 +357,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, else if (strcmp (key_copy, dataset->strdata) != 0) { if (cache_add (GETPWBYNAME, key_copy, key_len + 1, - &dataset->head, true, db, owner) < 0) + &dataset->head, true, db, owner, he == NULL) < 0) goto out; first = false; @@ -367,11 +367,12 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, if ((req->type == GETPWBYNAME || db->propagate) && __builtin_expect (cache_add (GETPWBYNAME, dataset->strdata, pw_name_len, &dataset->head, - first, db, owner) == 0, 1)) + first, db, owner, he == NULL) + == 0, 1)) { if (req->type == GETPWBYNAME && db->propagate) (void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head, - false, db, owner); + false, db, owner, false); } out: diff --git a/nscd/servicescache.c b/nscd/servicescache.c index c6f0b47e35..c952fa12c8 100644 --- a/nscd/servicescache.c +++ b/nscd/servicescache.c @@ -137,7 +137,7 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, &dataset->strdata, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); @@ -331,7 +331,7 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req, pthread_rwlock_rdlock (&db->lock); (void) cache_add (req->type, key_copy, req->key_len, - &dataset->head, true, db, owner); + &dataset->head, true, db, owner, he == NULL); pthread_rwlock_unlock (&db->lock); } diff --git a/resolv/res_query.c b/resolv/res_query.c index a8e8d7b739..3d2f2fe3a9 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -224,6 +224,21 @@ __libc_res_nquery(res_state statp, tests of HP2. */ HEADER *hp2 = answerp2 ? (HEADER *) *answerp2 : hp; + if (n < sizeof (HEADER) && nanswerp2 != NULL + && *nanswerp2 > sizeof (HEADER)) + { + /* Special case of partial answer. */ + assert (hp != hp2); + hp = hp2; + } + else if (nanswerp2 != NULL + && *nanswerp2 < sizeof (HEADER) && n > sizeof (HEADER)) + { + /* Special case of partial answer. */ + assert (hp != hp2); + hp2 = hp; + } + if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0) && (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) { #ifdef DEBUG diff --git a/resolv/res_send.c b/resolv/res_send.c index b3dbd702a2..e67ef1c676 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -975,6 +975,8 @@ send_dg(res_state statp, int recvresp2 = buf2 == NULL; pfd[0].fd = EXT(statp).nssocks[ns]; pfd[0].events = POLLOUT; + if (resplen2 != NULL) + *resplen2 = 0; wait: if (need_recompute) { recompute_resend: @@ -1001,6 +1003,11 @@ send_dg(res_state statp, if (n == 0) { Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout sending\n")); + if (recvresp1) + return resplen; + if (buf2 != NULL && recvresp2) + return 1; + *gotsomewhere = 1; return (0); } diff --git a/sysdeps/sparc/Makefile b/sysdeps/sparc/Makefile index 40323a0643..9fa5324b41 100644 --- a/sysdeps/sparc/Makefile +++ b/sysdeps/sparc/Makefile @@ -1,6 +1,10 @@ # The Sparc `long double' is a distinct type we support. long-double-fcts = yes +ifeq ($(subdir),gmon) +sysdep_routines += sparc-mcount +endif + ifeq ($(subdir),db2) CPPFLAGS += -DHAVE_SPINLOCKS=1 -DHAVE_ASSEM_SPARC_GCC=1 endif diff --git a/sysdeps/sparc/machine-gmon.h b/sysdeps/sparc/machine-gmon.h new file mode 100644 index 0000000000..296c5ff4d2 --- /dev/null +++ b/sysdeps/sparc/machine-gmon.h @@ -0,0 +1,33 @@ +/* sparc-specific implementation of profiling support. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller , 2008 + + 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 + +/* We must not pollute the global namespace. */ +#define mcount_internal __mcount_internal + +extern void mcount_internal (u_long frompc, u_long selfpc) internal_function; + +#define _MCOUNT_DECL(frompc, selfpc) \ +void internal_function mcount_internal (u_long frompc, u_long selfpc) + +/* Define MCOUNT as empty since we have the implementation in another + file. */ +#define MCOUNT diff --git a/sysdeps/sparc/sparc-mcount.S b/sysdeps/sparc/sparc-mcount.S new file mode 100644 index 0000000000..573b08f51c --- /dev/null +++ b/sysdeps/sparc/sparc-mcount.S @@ -0,0 +1,29 @@ +/* sparc-specific implemetation of profiling support. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller , 2008. + + 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 + +ENTRY(_mcount) + mov %i7, %o0 + ba __mcount_internal + mov %o7, %o1 +END(_mcount) + +weak_alias (_mcount, mcount) diff --git a/sysdeps/sparc/sparc64/backtrace.c b/sysdeps/sparc/sparc64/backtrace.c new file mode 100644 index 0000000000..6d7e429e2e --- /dev/null +++ b/sysdeps/sparc/sparc64/backtrace.c @@ -0,0 +1,58 @@ +/* Return backtrace of current program state. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller + + The GNU C Library is free software; you can redistribute it and/or + 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 + Library General Public License for more details. + + 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. */ + +#include +#include +#include +#include + +struct layout +{ + unsigned long locals[8]; + unsigned long ins[6]; + unsigned long next; + void *__unbounded return_address; +}; + +int +__backtrace (void **array, int size) +{ + struct layout *current; + unsigned long fp; + int count; + + asm volatile ("flushw"); + asm volatile ("mov %%fp, %0" : "=r"(fp)); + current = (struct layout *__unbounded) (fp + STACK_BIAS); + current = BOUNDED_1 (current); + + for (count = 0; count < size; count++) + { + array[count] = current->return_address; + if (!current->next) + break; + current = (struct layout *__unbounded) (current->next + STACK_BIAS); + current = BOUNDED_1 (current); + } + + return count; +} +weak_alias (__backtrace, backtrace) +libc_hidden_def (__backtrace) diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h b/sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h index 2c2770d071..59656978b8 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigcontextinfo.h @@ -20,6 +20,9 @@ #define SIGCONTEXT struct sigcontext * #define SIGCONTEXT_EXTRA_ARGS #define GET_PC(__ctx) ((void *) ((__ctx)->si_regs.pc)) +#define FIRST_FRAME_POINTER \ + ({ void *ret; \ + asm volatile ("ta 3; add %%fp, 56, %0" : "=r" (ret)); ret; }) #define ADVANCE_STACK_FRAME(__next) \ ((void *) (((unsigned *)(__next))+14)) -- cgit v1.2.3