2004-07-07  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/pthread/getcpuclockid.c (pthread_getcpuclockid): Allow
	using other thread's clock.
	* ptclock_gettime.c (__pthread_clock_gettime): Likewise.
	* ptclock_settime.c (__pthread_clock_settime): Likewise.
	* internals.h (__pthread_clock_gettime, __pthread_clock_settime):
	Remove prototypes.
	Reported by Bernd Schmidt <bernds@redhat.com>.
	* Makefile (librt-tests): Add tst-clock1.
	* tst-clock1.c: New test.

	* sysdeps/x86_64/Versions: New file.
	* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: New file.
	* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: New file.
This commit is contained in:
Ulrich Drepper 2004-07-08 23:55:54 +00:00
parent ece385dbb8
commit 1b8cbd0847
10 changed files with 573 additions and 19 deletions

View File

@ -1,3 +1,19 @@
2004-07-07 Jakub Jelinek <jakub@redhat.com>
* sysdeps/pthread/getcpuclockid.c (pthread_getcpuclockid): Allow
using other thread's clock.
* ptclock_gettime.c (__pthread_clock_gettime): Likewise.
* ptclock_settime.c (__pthread_clock_settime): Likewise.
* internals.h (__pthread_clock_gettime, __pthread_clock_settime):
Remove prototypes.
Reported by Bernd Schmidt <bernds@redhat.com>.
* Makefile (librt-tests): Add tst-clock1.
* tst-clock1.c: New test.
* sysdeps/x86_64/Versions: New file.
* sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: New file.
* sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: New file.
2004-04-16 Andreas Schwab <schwab@suse.de>
* sysdeps/ia64/tls.h (INIT_SYSINFO): Cast dl_sysinfo to void*.

View File

@ -105,7 +105,7 @@ omit-deps += crti crtn
CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions $(fno-unit-at-a-time)
endif
librt-tests = ex10 ex11
librt-tests = ex10 ex11 tst-clock1
tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 $(librt-tests) ex12 ex13 joinrace \
tststack $(tests-nodelete-$(have-z-nodelete)) ecmutex ex14 ex15 ex16 \
ex17 ex18 tst-cancel tst-context bug-sleep \

View File

@ -405,9 +405,6 @@ extern int __pthread_spin_unlock (pthread_spinlock_t *__lock);
extern int __pthread_spin_init (pthread_spinlock_t *__lock, int __pshared);
extern int __pthread_spin_destroy (pthread_spinlock_t *__lock);
extern int __pthread_clock_gettime (hp_timing_t freq, struct timespec *tp);
extern void __pthread_clock_settime (hp_timing_t offset);
/* Global pointers to old or new suspend functions */
extern void (*__pthread_restart)(pthread_descr);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2001 Free Software Foundation, Inc.
/* Copyright (C) 2001, 2004 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
@ -16,23 +16,46 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <time.h>
#include <libc-internal.h>
#include "internals.h"
#include "spinlock.h"
#if HP_TIMING_AVAIL
int
__pthread_clock_gettime (hp_timing_t freq, struct timespec *tp)
__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
struct timespec *tp)
{
hp_timing_t tsc;
hp_timing_t tsc, cpuclock_offset;
pthread_descr self = thread_self ();
pthread_t thread = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE;
const unsigned int mask = ~0U >> CLOCK_IDFIELD_SIZE;
if (thread == 0 || (THREAD_GETMEM (self, p_tid) & mask) == thread)
cpuclock_offset = THREAD_GETMEM (self, p_cpuclock_offset);
else
{
pthread_descr th;
pthread_handle handle = thread_handle (thread);
__pthread_lock (&handle->h_lock, NULL);
th = handle->h_descr;
if (th == NULL || (th->p_tid & mask) != thread || th->p_terminated)
{
__pthread_unlock (&handle->h_lock);
__set_errno (EINVAL);
return -1;
}
cpuclock_offset = th->p_cpuclock_offset;
__pthread_unlock (&handle->h_lock);
}
/* Get the current counter. */
HP_TIMING_NOW (tsc);
/* Compute the offset since the start time of the process. */
tsc -= THREAD_GETMEM (self, p_cpuclock_offset);
tsc -= cpuclock_offset;
/* Compute the seconds. */
tp->tv_sec = tsc / freq;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2001 Free Software Foundation, Inc.
/* Copyright (C) 2001, 2004 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
@ -16,18 +16,40 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <time.h>
#include <libc-internal.h>
#include "internals.h"
#include "spinlock.h"
#if HP_TIMING_AVAIL
void
__pthread_clock_settime (hp_timing_t offset)
int
__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset)
{
pthread_descr self = thread_self ();
pthread_t thread = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE;
const unsigned int mask = ~0U >> CLOCK_IDFIELD_SIZE;
/* Compute the offset since the start time of the process. */
THREAD_SETMEM (self, p_cpuclock_offset, offset);
if (thread == 0 || (THREAD_GETMEM (self, p_tid) & mask) == thread)
/* Our own clock. */
THREAD_SETMEM (self, p_cpuclock_offset, offset);
else
{
pthread_descr th;
pthread_handle handle = thread_handle (thread);
__pthread_lock (&handle->h_lock, NULL);
th = handle->h_descr;
if (th == NULL || (th->p_tid & mask) != thread || th->p_terminated)
{
__pthread_unlock (&handle->h_lock);
__set_errno (EINVAL);
return -1;
}
th->p_cpuclock_offset = offset;
__pthread_unlock (&handle->h_lock);
}
return 0;
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
/* Copyright (C) 2000, 2001, 2004 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,18 +19,27 @@
#include <errno.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#include <internals.h>
int
pthread_getcpuclockid (pthread_t thread_id, clockid_t *clock_id)
{
/* We don't allow any process ID but our own. */
if (thread_handle (thread_id)->h_descr != thread_self ())
return EPERM;
#ifdef CLOCK_THREAD_CPUTIME_ID
/* We need to store the thread ID in the CLOCKID variable together
with a number identifying the clock. We reserve the low 3 bits
for the clock ID and the rest for the thread ID. This is
problematic if the thread ID is too large. But 29 bits should be
fine.
If some day more clock IDs are needed the ID part can be
enlarged. The IDs are entirely internal. */
if (2 * PTHREAD_THREADS_MAX
>= 1 << (8 * sizeof (*clock_id) - CLOCK_IDFIELD_SIZE))
return ERANGE;
/* Store the number. */
*clock_id = CLOCK_THREAD_CPUTIME_ID;
*clock_id = CLOCK_THREAD_CPUTIME_ID | (thread_id << CLOCK_IDFIELD_SIZE);
return 0;
#else

View File

@ -0,0 +1,144 @@
/* Define POSIX options for Linux/ia64.
Copyright (C) 1996-2001, 2002, 2003, 2004 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; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _POSIX_OPT_H
#define _POSIX_OPT_H 1
/* Job control is supported. */
#define _POSIX_JOB_CONTROL 1
/* Processes have a saved set-user-ID and a saved set-group-ID. */
#define _POSIX_SAVED_IDS 1
/* Priority scheduling is supported. */
#define _POSIX_PRIORITY_SCHEDULING 200112L
/* Synchronizing file data is supported. */
#define _POSIX_SYNCHRONIZED_IO 200112L
/* The fsync function is present. */
#define _POSIX_FSYNC 200112L
/* Mapping of files to memory is supported. */
#define _POSIX_MAPPED_FILES 200112L
/* Locking of all memory is supported. */
#define _POSIX_MEMLOCK 200112L
/* Locking of ranges of memory is supported. */
#define _POSIX_MEMLOCK_RANGE 200112L
/* Setting of memory protections is supported. */
#define _POSIX_MEMORY_PROTECTION 200112L
/* Only root can change owner of file. */
#define _POSIX_CHOWN_RESTRICTED 1
/* `c_cc' member of 'struct termios' structure can be disabled by
using the value _POSIX_VDISABLE. */
#define _POSIX_VDISABLE '\0'
/* Filenames are not silently truncated. */
#define _POSIX_NO_TRUNC 1
/* X/Open realtime support is available. */
#define _XOPEN_REALTIME 1
/* X/Open realtime thread support is available. */
#define _XOPEN_REALTIME_THREADS 1
/* XPG4.2 shared memory is supported. */
#define _XOPEN_SHM 1
/* Tell we have POSIX threads. */
#define _POSIX_THREADS 200112L
/* We have the reentrant functions described in POSIX. */
#define _POSIX_REENTRANT_FUNCTIONS 1
#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L
/* We provide priority scheduling for threads. */
#define _POSIX_THREAD_PRIORITY_SCHEDULING 200112L
/* We support user-defined stack sizes. */
#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
/* We support user-defined stacks. */
#define _POSIX_THREAD_ATTR_STACKADDR 200112L
/* We support POSIX.1b semaphores, but only the non-shared form for now. */
#define _POSIX_SEMAPHORES 200112L
/* Real-time signals are supported. */
#define _POSIX_REALTIME_SIGNALS 200112L
/* We support asynchronous I/O. */
#define _POSIX_ASYNCHRONOUS_IO 200112L
#define _POSIX_ASYNC_IO 1
/* Alternative name for Unix98. */
#define _LFS_ASYNCHRONOUS_IO 1
/* The LFS support in asynchronous I/O is also available. */
#define _LFS64_ASYNCHRONOUS_IO 1
/* The rest of the LFS is also available. */
#define _LFS_LARGEFILE 1
#define _LFS64_LARGEFILE 1
#define _LFS64_STDIO 1
/* POSIX shared memory objects are implemented. */
#define _POSIX_SHARED_MEMORY_OBJECTS 200112L
/* CPU-time clocks supported. */
#define _POSIX_CPUTIME 200112L
/* We support the clock also in threads. */
#define _POSIX_THREAD_CPUTIME 200112L
/* GNU libc provides regular expression handling. */
#define _POSIX_REGEXP 1
/* Reader/Writer locks are available. */
#define _POSIX_READER_WRITER_LOCKS 200112L
/* We have a POSIX shell. */
#define _POSIX_SHELL 1
/* We support the Timeouts option. */
#define _POSIX_TIMEOUTS 200112L
/* We support spinlocks. */
#define _POSIX_SPIN_LOCKS 200112L
/* The `spawn' function family is supported. */
#define _POSIX_SPAWN 200112L
/* We have POSIX timers. */
#define _POSIX_TIMERS 200112L
/* The barrier functions are available. */
#define _POSIX_BARRIERS 200112L
/* POSIX message queues are available. */
#define _POSIX_MESSAGE_PASSING 200112L
/* The monotonic clock might be available. */
#define _POSIX_MONOTONIC_CLOCK 0
#endif /* posix_opt.h */

View File

@ -0,0 +1,144 @@
/* Define POSIX options for Linux/x86_64.
Copyright (C) 1996-2001, 2002, 2003, 2004 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; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _POSIX_OPT_H
#define _POSIX_OPT_H 1
/* Job control is supported. */
#define _POSIX_JOB_CONTROL 1
/* Processes have a saved set-user-ID and a saved set-group-ID. */
#define _POSIX_SAVED_IDS 1
/* Priority scheduling is supported. */
#define _POSIX_PRIORITY_SCHEDULING 200112L
/* Synchronizing file data is supported. */
#define _POSIX_SYNCHRONIZED_IO 200112L
/* The fsync function is present. */
#define _POSIX_FSYNC 200112L
/* Mapping of files to memory is supported. */
#define _POSIX_MAPPED_FILES 200112L
/* Locking of all memory is supported. */
#define _POSIX_MEMLOCK 200112L
/* Locking of ranges of memory is supported. */
#define _POSIX_MEMLOCK_RANGE 200112L
/* Setting of memory protections is supported. */
#define _POSIX_MEMORY_PROTECTION 200112L
/* Only root can change owner of file. */
#define _POSIX_CHOWN_RESTRICTED 1
/* `c_cc' member of 'struct termios' structure can be disabled by
using the value _POSIX_VDISABLE. */
#define _POSIX_VDISABLE '\0'
/* Filenames are not silently truncated. */
#define _POSIX_NO_TRUNC 1
/* X/Open realtime support is available. */
#define _XOPEN_REALTIME 1
/* X/Open realtime thread support is available. */
#define _XOPEN_REALTIME_THREADS 1
/* XPG4.2 shared memory is supported. */
#define _XOPEN_SHM 1
/* Tell we have POSIX threads. */
#define _POSIX_THREADS 200112L
/* We have the reentrant functions described in POSIX. */
#define _POSIX_REENTRANT_FUNCTIONS 1
#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L
/* We provide priority scheduling for threads. */
#define _POSIX_THREAD_PRIORITY_SCHEDULING 200112L
/* We support user-defined stack sizes. */
#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
/* We support user-defined stacks. */
#define _POSIX_THREAD_ATTR_STACKADDR 200112L
/* We support POSIX.1b semaphores, but only the non-shared form for now. */
#define _POSIX_SEMAPHORES 200112L
/* Real-time signals are supported. */
#define _POSIX_REALTIME_SIGNALS 200112L
/* We support asynchronous I/O. */
#define _POSIX_ASYNCHRONOUS_IO 200112L
#define _POSIX_ASYNC_IO 1
/* Alternative name for Unix98. */
#define _LFS_ASYNCHRONOUS_IO 1
/* The LFS support in asynchronous I/O is also available. */
#define _LFS64_ASYNCHRONOUS_IO 1
/* The rest of the LFS is also available. */
#define _LFS_LARGEFILE 1
#define _LFS64_LARGEFILE 1
#define _LFS64_STDIO 1
/* POSIX shared memory objects are implemented. */
#define _POSIX_SHARED_MEMORY_OBJECTS 200112L
/* CPU-time clocks supported. */
#define _POSIX_CPUTIME 200112L
/* We support the clock also in threads. */
#define _POSIX_THREAD_CPUTIME 200112L
/* GNU libc provides regular expression handling. */
#define _POSIX_REGEXP 1
/* Reader/Writer locks are available. */
#define _POSIX_READER_WRITER_LOCKS 200112L
/* We have a POSIX shell. */
#define _POSIX_SHELL 1
/* We support the Timeouts option. */
#define _POSIX_TIMEOUTS 200112L
/* We support spinlocks. */
#define _POSIX_SPIN_LOCKS 200112L
/* The `spawn' function family is supported. */
#define _POSIX_SPAWN 200112L
/* We have POSIX timers. */
#define _POSIX_TIMERS 200112L
/* The barrier functions are available. */
#define _POSIX_BARRIERS 200112L
/* POSIX message queues are available. */
#define _POSIX_MESSAGE_PASSING 200112L
/* The monotonic clock might be available. */
#define _POSIX_MONOTONIC_CLOCK 0
#endif /* posix_opt.h */

View File

@ -0,0 +1,5 @@
libpthread {
GLIBC_PRIVATE {
__pthread_clock_gettime; __pthread_clock_settime;
}
}

194
linuxthreads/tst-clock1.c Normal file
View File

@ -0,0 +1,194 @@
/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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 <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#if _POSIX_THREAD_CPUTIME
static pthread_barrier_t b2;
static pthread_barrier_t bN;
static void *
tf (void *arg)
{
int e = pthread_barrier_wait (&b2);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
e = pthread_barrier_wait (&bN);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
return NULL;
}
#endif
int
do_test (void)
{
#if _POSIX_THREAD_CPUTIME
# define N 10
if (pthread_barrier_init (&b2, NULL, 2) != 0
|| pthread_barrier_init (&bN, NULL, N + 1) != 0)
{
puts ("barrier_init failed");
return 1;
}
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
pthread_t th[N + 1];
clockid_t cl[N + 1];
# ifndef CLOCK_THREAD_CPUTIME_ID
if (pthread_getcpuclockid (pthread_self (), &cl[0]) != 0)
{
puts ("own pthread_getcpuclockid failed");
return 1;
}
# else
cl[0] = CLOCK_THREAD_CPUTIME_ID;
# endif
pthread_attr_t at;
if (pthread_attr_init (&at) != 0)
{
puts ("attr_init failed");
return 1;
}
if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
{
puts ("attr_setstacksize failed");
return 1;
}
int i;
int e;
for (i = 0; i < N; ++i)
{
if (pthread_create (&th[i], &at, tf, NULL) != 0)
{
puts ("create failed");
return 1;
}
e = pthread_barrier_wait (&b2);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
return 1;
}
ts.tv_sec = 0;
ts.tv_nsec = 100000000;
TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
if (pthread_getcpuclockid (th[i], &cl[i + 1]) != 0)
{
puts ("pthread_getcpuclockid failed");
return 1;
}
}
if (pthread_attr_destroy (&at) != 0)
{
puts ("attr_destroy failed");
return 1;
}
struct timespec t[N + 1];
for (i = 0; i < N + 1; ++i)
if (clock_gettime (cl[i], &t[i]) != 0)
{
printf ("clock_gettime round %d failed\n", i);
return 1;
}
for (i = 0; i < N; ++i)
{
struct timespec diff;
diff.tv_sec = t[i].tv_sec - t[i + 1].tv_sec;
diff.tv_nsec = t[i].tv_nsec - t[i + 1].tv_nsec;
if (diff.tv_nsec < 0)
{
diff.tv_nsec += 1000000000;
--diff.tv_sec;
}
if (diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_nsec < 100000000))
{
printf ("\
difference between thread %d and %d too small (%ld.%09ld)\n",
i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
return 1;
}
printf ("diff %d->%d: %ld.%09ld\n",
i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
}
ts.tv_sec = 0;
ts.tv_nsec = 0;
for (i = 0; i < N + 1; ++i)
if (clock_settime (cl[i], &ts) != 0)
{
printf ("clock_settime(%d) round %d failed\n", cl[i], i);
return 1;
}
for (i = 0; i < N + 1; ++i)
{
if (clock_gettime (cl[i], &ts) != 0)
{
puts ("clock_gettime failed");
return 1;
}
if (ts.tv_sec > t[i].tv_sec
|| (ts.tv_sec == t[i].tv_sec && ts.tv_nsec > t[i].tv_nsec))
{
puts ("clock_settime didn't reset clock");
return 1;
}
}
#endif
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"