diff options
Diffstat (limited to 'linuxthreads')
-rw-r--r-- | linuxthreads/ChangeLog | 18 | ||||
-rw-r--r-- | linuxthreads/internals.h | 4 | ||||
-rw-r--r-- | linuxthreads/manager.c | 7 | ||||
-rw-r--r-- | linuxthreads/pthread.c | 8 | ||||
-rw-r--r-- | linuxthreads/sysdeps/i386/i586/Makefile | 3 | ||||
-rw-r--r-- | linuxthreads/sysdeps/i386/i586/Versions | 5 | ||||
-rw-r--r-- | linuxthreads/sysdeps/i386/i586/ptclock_gettime.c | 45 | ||||
-rw-r--r-- | linuxthreads/sysdeps/i386/i586/ptclock_settime.c | 32 | ||||
-rw-r--r-- | linuxthreads/sysdeps/i386/i686/Implies | 1 | ||||
-rw-r--r-- | linuxthreads/sysdeps/i386/useldt.h | 66 |
10 files changed, 170 insertions, 19 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index ca64e526fd..e74f0bfbe8 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,21 @@ +2001-04-21 Ulrich Drepper <drepper@redhat.com> + + * internals.h: Include <cpuclock-init.h>. + (struct _pthread_descr_struct): Add p_cpuclock_offset field if + CPUCLOCK_VARDEF is defined. + * pthread.c (__pthread_initialize_minimal): Initialize + p_cpuclock_offset field for main thread if CPUCLOCK_INIT is defined. + * manager.c (pthread_start_thread): Set p_cpuclock_offset field + for new thread to current CPU clock value. + + * sysdeps/i386/useldt.h: Extend all the macros to handle 8-byte values. + + * sysdeps/i386/i586/Makefile: New file. + * sysdeps/i386/i586/Versions: New file. + * sysdeps/i386/i586/ptclock_gettime.c: New file. + * sysdeps/i386/i586/ptclock_settime.c: New file. + * sysdeps/i386/i686/Implies: New file. + 2001-04-18 Jakub Jelinek <jakub@redhat.com> * sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: Put specs into diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h index 998f7788e8..fbe0ea35d2 100644 --- a/linuxthreads/internals.h +++ b/linuxthreads/internals.h @@ -33,6 +33,7 @@ extern int __compare_and_swap (long int *p, long int oldval, long int newval); #include "pt-machine.h" #include "semaphore.h" #include "../linuxthreads_db/thread_dbP.h" +#include <cpuclock-init.h> #ifndef THREAD_GETMEM # define THREAD_GETMEM(descr, member) descr->member @@ -179,6 +180,9 @@ struct _pthread_descr_struct { struct __res_state *p_resp; /* Pointer to resolver state */ struct __res_state p_res; /* per-thread resolver state */ int p_inheritsched; /* copied from the thread attribute */ +#ifdef CPUCLOCK_VARDEF + CPUCLOCK_VARDEF (p_cpuclock_offset); /* Initial CPU clock for thread. */ +#endif /* New elements must be added at the end. */ } __attribute__ ((aligned(32))); /* We need to align the structure so that doubles are aligned properly. This is 8 diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c index 431e149212..dbe2aa2d19 100644 --- a/linuxthreads/manager.c +++ b/linuxthreads/manager.c @@ -225,10 +225,17 @@ static int pthread_start_thread(void *arg) pthread_descr self = (pthread_descr) arg; struct pthread_request request; void * outcome; +#ifdef CPUCLOCK_VARDEF + CPUCLOCK_VARDEF (tmpclock); +#endif /* Initialize special thread_self processing, if any. */ #ifdef INIT_THREAD_SELF INIT_THREAD_SELF(self, self->p_nr); #endif +#ifdef CPUCLOCK_INIT + CPUCLOCK_INIT (tmpclock); + THREAD_SETMEM (self, p_cpuclock_offset, tmpclock); +#endif /* Make sure our pid field is initialized, just in case we get there before our father has initialized it. */ THREAD_SETMEM(self, p_pid, __getpid()); diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c index ff9c083010..73a7acb9c9 100644 --- a/linuxthreads/pthread.c +++ b/linuxthreads/pthread.c @@ -225,6 +225,11 @@ static void pthread_handle_sigcancel(int sig); static void pthread_handle_sigrestart(int sig); static void pthread_handle_sigdebug(int sig); +/* CPU clock handling. */ +#ifdef CPUCLOCK_VARDECL +CPUCLOCK_VARDECL (_dl_cpuclock_offset); +#endif + /* Signal numbers used for the communication. In these variables we keep track of the used variables. If the platform does not support any real-time signals we will define the @@ -390,6 +395,9 @@ __pthread_initialize_minimal(void) #ifdef INIT_THREAD_SELF INIT_THREAD_SELF(&__pthread_initial_thread, 0); #endif +#ifdef CPUCLOCK_INIT + __pthread_initial_thread.p_cpuclock_offset = _dl_cpuclock_offset; +#endif } diff --git a/linuxthreads/sysdeps/i386/i586/Makefile b/linuxthreads/sysdeps/i386/i586/Makefile new file mode 100644 index 0000000000..96c195f6e5 --- /dev/null +++ b/linuxthreads/sysdeps/i386/i586/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),linuxthreads) +libpthread-sysdep_routines += ptclock_gettime ptclock_settime +endif diff --git a/linuxthreads/sysdeps/i386/i586/Versions b/linuxthreads/sysdeps/i386/i586/Versions new file mode 100644 index 0000000000..f9921aff55 --- /dev/null +++ b/linuxthreads/sysdeps/i386/i586/Versions @@ -0,0 +1,5 @@ +libpthread { + GLIBC_2.2.3 { + __pthread_clock_gettime; __pthread_clock_settime; + } +} diff --git a/linuxthreads/sysdeps/i386/i586/ptclock_gettime.c b/linuxthreads/sysdeps/i386/i586/ptclock_gettime.c new file mode 100644 index 0000000000..818251074e --- /dev/null +++ b/linuxthreads/sysdeps/i386/i586/ptclock_gettime.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2001 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 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 <time.h> +#include <libc-internal.h> + +#include "../../../internals.h" + + +int +__pthread_clock_gettime (unsigned long long int freq, struct timespec *tp) +{ + unsigned long long int tsc; + pthread_descr self = thread_self (); + + /* Get the current counter. */ + asm volatile ("rdtsc" : "=A" (tsc)); + + /* Compute the offset since the start time of the process. */ + tsc -= THREAD_GETMEM (self, p_cpuclock_offset); + + /* Compute the seconds. */ + tp->tv_sec = tsc / freq; + + /* And the nanoseconds. This computation should be stable until + we get machines with about 16GHz frequency. */ + tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq; + + return 0; +} diff --git a/linuxthreads/sysdeps/i386/i586/ptclock_settime.c b/linuxthreads/sysdeps/i386/i586/ptclock_settime.c new file mode 100644 index 0000000000..3026528cc2 --- /dev/null +++ b/linuxthreads/sysdeps/i386/i586/ptclock_settime.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2001 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 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 <time.h> +#include <libc-internal.h> + +#include "../../../internals.h" + + +void +__pthread_clock_settime (unsigned long long int offset) +{ + pthread_descr self = thread_self (); + + /* Compute the offset since the start time of the process. */ + THREAD_SETMEM (self, p_cpuclock_offset, offset); +} diff --git a/linuxthreads/sysdeps/i386/i686/Implies b/linuxthreads/sysdeps/i386/i686/Implies new file mode 100644 index 0000000000..0df509e35f --- /dev/null +++ b/linuxthreads/sysdeps/i386/i686/Implies @@ -0,0 +1 @@ +i386/i586 diff --git a/linuxthreads/sysdeps/i386/useldt.h b/linuxthreads/sysdeps/i386/useldt.h index ebf520cc39..b9566ace1f 100644 --- a/linuxthreads/sysdeps/i386/useldt.h +++ b/linuxthreads/sysdeps/i386/useldt.h @@ -1,6 +1,6 @@ /* Special definitions for ix86 machine using segment register based thread descriptor. - Copyright (C) 1998, 2000 Free Software Foundation, Inc. + Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>. @@ -88,16 +88,24 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); : "0" (0), \ "i" (offsetof (struct _pthread_descr_struct, \ member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ else \ { \ - if (sizeof (__value) != 4) \ - /* There should not be any value with a size other than 1 or 4. */ \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ abort (); \ \ - __asm__ __volatile__ ("movl %%gs:%P1,%0" \ - : "=r" (__value) \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ : "i" (offsetof (struct _pthread_descr_struct, \ - member))); \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ } \ __value; \ }) @@ -112,14 +120,20 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); : "0" (0), \ "r" (offsetof (struct _pthread_descr_struct, \ member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ else \ { \ - if (sizeof (__value) != 4) \ - /* There should not be any value with a size other than 1 or 4. */ \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ abort (); \ \ - __asm__ __volatile__ ("movl %%gs:(%1),%0" \ - : "=r" (__value) \ + __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \ + "movl %%gs:4(%1),%%edx" \ + : "=&A" (__value) \ : "r" (offsetof (struct _pthread_descr_struct, \ member))); \ } \ @@ -135,16 +149,24 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); : "q" (__value), \ "i" (offsetof (struct _pthread_descr_struct, \ member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ else \ { \ - if (sizeof (__value) != 4) \ - /* There should not be any value with a size other than 1 or 4. */ \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ abort (); \ \ - __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ - : "r" (__value), \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (__value), \ "i" (offsetof (struct _pthread_descr_struct, \ - member))); \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ } \ }) @@ -157,14 +179,20 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); : "q" (__value), \ "r" (offsetof (struct _pthread_descr_struct, \ member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ else \ { \ - if (sizeof (__value) != 4) \ - /* There should not be any value with a size other than 1 or 4. */ \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ abort (); \ \ - __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ - : "r" (__value), \ + __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \ + "movl %%edx,%%gs:4(%1)" : \ + : "A" (__value), \ "r" (offsetof (struct _pthread_descr_struct, \ member))); \ } \ |