glibc/rt/aio_misc.c
Ulrich Drepper cbdee2790d Update.
1997-12-03 23:50  Ulrich Drepper  <drepper@cygnus.com>

	* Makeconfig: Add shared-thread-library variable.

	* math/Makfile (CPPFLAGS): Add -D__LIBC_INTERNAL_MATH_INLINES.
	* sysdeps/i386/Makefile: Don't define ___LIBC_INTERNAL_MATH_INLINES
	here.
	* sysdeps/m68k/fpu/e_acos.c: Likewise.
	* sysdeps/m68k/fpu/e_atan2.c: Likewise.
	* sysdeps/m68k/fpu/e_fmod.c: Likewise.
	* sysdeps/m68k/fpu/e_pow.c: Likewise.
	* sysdeps/m68k/fpu/e_scalb.c: Likewise.
	* sysdeps/m68k/fpu/k_cos.c: Likewise.
	* sysdeps/m68k/fpu/k_sin.c: Likewise.
	* sysdeps/m68k/fpu/k_tan.c: Likewise.
	* sysdeps/m68k/fpu/s_atan.c: Likewise.
	* sysdeps/m68k/fpu/s_ccos.c: Likewise.
	* sysdeps/m68k/fpu/s_ccosh.c: Likewise.
	* sysdeps/m68k/fpu/s_cexp.c: Likewise.
	* sysdeps/m68k/fpu/s_csin.c: Likewise.
	* sysdeps/m68k/fpu/s_csinh.c: Likewise.
	* sysdeps/m68k/fpu/s_frexp.c: Likewise.
	* sysdeps/m68k/fpu/s_ilogb.c: Likewise.
	* sysdeps/m68k/fpu/s_isinf.c: Likewise.
	* sysdeps/m68k/fpu/s_llrint.c: Likewise.
	* sysdeps/m68k/fpu/s_llrintf.c: Likewise.
	* sysdeps/m68k/fpu/s_llrintl.c: Likewise.
	* sysdeps/m68k/fpu/s_lrint.c: Likewise.
	* sysdeps/m68k/fpu/s_modf.c: Likewise.
	* sysdeps/m68k/fpu/s_remquo.c: Likewise.
	* sysdeps/m68k/fpu/s_scalbn.c: Likewise.
	* sysdeps/m68k/fpu/s_sincos.c: Likewise.

	* libc.map: Add __libc_current_sigrtmin, __libc_current_sigrtmax,
	__libc_allocate_rtsig, sigqueue, sigtimedwait, sigwaitinfo.
	* signal/Makefile (headers): Add bits/siginfo.h.
	(routines): Add allocrtsig, sigtimedwait, sigwaitinfo, sigqueue.
	(distribute): Add testrtsig.h.
	* signal/allocrtsig.c: New file.
	* signal/signal.h: Define `union sigval'.  Include <bits/siginfo.h>.
	Declare sigwaitinfo, sigtimedwait, sigqueue, __libc_current_sigrtmin,
	__libc_current_sigrtmax.
	* sysdeps/generic/sigqueue.c: New file.
	* sysdeps/generic/sigtimedwait.c: New file.
	* sysdeps/generic/sigwaitinfo.c: New file.
	* sysdeps/generic/testrtsig.h: New file.
	* sysdeps/generic/bits/siginfo.h: New file.
	* sysdeps/unix/sysv/linux/bits/siginfo.h: New file.
	* sysdeps/unix/sysv/linux/kernel_sigaction.h: Define struct as
	old_kernel_sigaction and rename sa_handler member to k_sa_handler.
	* sysdeps/unix/sysv/linux/rt_sigaction.c: New file.
	* sysdeps/unix/sysv/linux/rt_sigprocmask.c: New file.
	* sysdeps/unix/sysv/linux/rt_sigqueueinfo.c: New file.
	* sysdeps/unix/sysv/linux/rt_sigreturn.c: New file.
	* sysdeps/unix/sysv/linux/rt_sigsuspend.c: New file.
	* sysdeps/unix/sysv/linux/rt_sigtimedwait.c: New file.
	* sysdeps/unix/sysv/linux/sigpending.c: New file.
	* sysdeps/unix/sysv/linux/sigprocmask.c: New file.
	* sysdeps/unix/sysv/linux/sigqueue.c: New file.
	* sysdeps/unix/sysv/linux/sigreturn.c: New file.
	* sysdeps/unix/sysv/linux/sigtimedwait.c: New file.
	* sysdeps/unix/sysv/linux/sigwaitinfo.c: New file.
	* sysdeps/unix/sysv/linux/testrtsig.h: New file.
	* sysdeps/unix/sysv/linux/sigsuspend.c: Update for AIO.
	* sysdeps/unix/sysv/linux/syscalls.list: Update for AIO.
	* sysdeps/unix/sysv/linux/sigaction.c: Update for AIO.
	* sysdeps/unix/sysv/linux/bits/local_lim.h: Define AIO_PRIO_DELTA_MAX.
	* sysdeps/unix/sysv/linux/bits/posix_opt.h: Define _XOPEN_REALTIME
	and _POSIX_REALTIME_SIGNALS.
	* sysdeps/unix/sysv/linux/bits/sigaction.h: Update for AIO.
	* sysdeps/unix/sysv/linux/bits/signum.h: Define SIGRTMIN/MAX and
	update _NSIG.
	* sysdeps/unix/sysv/linux/i386/sigaction.c: Update for AIO.
	* sysdeps/unix/sysv/linux/i386/sys/ucontext.h: Linux/i386 specific
	definitions.

	* Makefile (subdirs): Add rt.
	* shlib-versions: Add entry for librt.
	* rt/Makefile: New file.
	* rt/aio.h: New file.
	* rt/aio_cancel.c: New file.
	* rt/aio_error.c: New file.
	* rt/aio_fsync.c: New file.
	* rt/aio_misc.c: New file.
	* rt/aio_misc.h: New file.
	* rt/aio_read.c: New file.
	* rt/aio_read64.c: New file.
	* rt/aio_return.c: New file.
	* rt/aio_suspend.c: New file.
	* rt/aio_write.c: New file.
	* rt/aio_write64.c: New file.
	* rt/lio_listio.c: New file.
	* rt/lio_listio64.c: New file.
	* sysdeps/generic/aio_sigqueue.c: New file.
	* sysdeps/unix/sysv/linux/aio_sigqueue.c: New file.
	* sysdeps/unix/sysv/linux/Dist: Add new files
	* sysdeps/unix/sysv/linux/Makefile [$(subdir)=signal]
	(sysdep_routines): Add rt_sigsuspend, rt_sigprocmask, rt_sigtimedwait,
	rt_sigqueueinfo, rt_sigaction.

	* posix/Makefile (headers): Add bits/environments.h.
	* posix/confstr.c: Correctly handle _CS_XBS5_ILP32_OFFBIG_CFLAGS
	and _CS_LFS_CFLAGS on 64bit platforms.
	* posix/unistd.h: Define _XOPEN_LEGACY.  Explain _XOPEN_REALTIME
	and _XOPEN_REALTIME_THREADS.  Include bits/environments.h.
	* sysdeps/generic/bits/confname.h: Define _SC_* constants for
	compilation modules.
	* sysdeps/wordsize-32/bits/environments.h: New file.
	* sysdeps/wordsize-64/bits/environments.h: New file.

	* posix/getopt.c: Remove declaration of getpid and __libc_pid.
	* posix/getopt_init.c: Test for value 0xf00baa of uninitialized
	__libc_pid.
	* sysdeps/unix/sysv/linux/init-first.c: Initialize __libc_pid to
	0xf00baa.

	* string/string.h: Add declaration of __strverscmp.
	* string/strverscmp.c: Rename function ot __strverscmp and make old
	name weak alias.

	* sysdeps/generic/dl-sysdep.c: Declare and define __libc_uid.
	* sysdeps/generic/enbl-secure.c: Likewise.
	* sysdeps/mach/hurd/dl-sysdep.c: Likewise.

	* sysdeps/unix/sysv/linux/bits/sigset.h: Pretty print.

	* sysdeps/unix/sysv/linux/sys/pci.h: New file.

1997-12-03  Ulrich Drepper  <drepper@cygnus.com>

	* posix/sys/wait.h: Use __transparent_union__ instead of
	transparent_union.  Reported by Roland McGrath.

1997-12-03  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* resolv/inet_neta.c (inet_neta): Change type of first parameter
	to u_int32_t.  Suggested by John Lavagnino <John_Lavagnino@Brown.edu>
	[PR libc/366].

	* resolv/inet_addr.c (inet_addr): Change return type to u_int32_t.

	* inet/arpa/inet.h: Change types of inet_neta and inet_addr.

1997-12-03 20:40  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>

	* grp/initgroups.c: Increase buffer if it is too small.

1997-12-03  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/unix/sysv/linux/netinet/ip.h: Don't use u_int8_t for bit
	fields, this is no ISO C.  Reported by Andreas Jaeger.

1997-12-03  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* sysdeps/i386/sys/ucontext.h (enum): Add missing commata.

1997-12-03 08:58  Philip Blundell  <pb@nexus.co.uk>

	* sysdeps/generic/bits/utsname.h: <sys/utsname.h> defines
	_SYS_UTSNAME_H not _UTSNAME_H.

1997-11-28  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* elf/dl-profile.c (_dl_start_profile): Avoid overflow when
	computing s_scale.

1997-11-29  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/libm-ieee754/s_csqrt.c: Use different formula for now.
	* sysdeps/libm-ieee754/s_csqrtf.c: Likewise.
	* sysdeps/libm-ieee754/s_csqrtl.c: Likewise.

	* math/libm-test.c (csqrt_test): Add testcase.

1997-12-03 15:44  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/unix/sysv/linux/sys/ultrasound.h: New file.
	* sysdeps/unix/sysv/linux/sys/Dist: Add it.
	* sysdeps/unix/sysv/linux/sys/Makefile [$(subdir)=misc]: Likewise.

1997-11-30  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>

	* sysdeps/unix/sysv/linux/sys/timex.h: Fix declaration.

1997-12-01  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* math/libm-test.c (acos_test): Add more tests.
	(asin_test): Likewise.
	(atan_test): Likewise.
	(exp_test): Likewise.
	(sin_test): Likewise.
	(sqrt_test): Likewise.
	(cpow_test): Likewise.
	(csqrt_test): Likewise.
	(cexp_test): Correct typo in gcc version test.

1997-12-02 17:14  Philip Blundell  <pb@nexus.co.uk>

	* sysdeps/arm/__longjmp.S: Define _SETJMP_H before including
	<bits/setjmp.h>.
	* sysdeps/arm/setjmp.S: Likewise.

	* sysdeps/unix/sysv/linux/arm/bits/mman.h: New file.

1997-12-02 18:07  Philip Blundell  <pb@nexus.co.uk>

	* stdio/stdio.h: Add prototype for tmpfile64().

1997-12-02 17:47  Philip Blundell  <pb@nexus.co.uk>

	* stdio/stdio.h (__stdio_gen_tempname): Add extra argument to
	prototype to keep in step with libio version.

	* stdio-common/tmpfile64.c: Include <errno.h> for ENOSYS.

1997-12-02 17:41  Philip Blundell  <pb@nexus.co.uk>

	* sysdeps/generic/Makefile: Don't try to use make_siglist if
	cross-compiling.

1997-12-02 01:18  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/unix/sysv/linux/i386/clone.S: When cloned process returns
	load GOT ptr before jumping to _exit.
	Reported by Xavier Leroy.
1997-12-04 00:12:34 +00:00

307 lines
9.3 KiB
C

/* Handle general operations.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
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 <aio.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include "aio_misc.h"
/* We need a list of pending operations. This is sorted according to
the priority given in the aio_reqprio member. */
aiocb_union *__aio_requests;
/* Since the list is global we need a semaphore protecting it. */
sem_t __aio_requests_sema;
/* The initialization function. It gets automatically called if any
aio_* function is used in the program. */
static void
__attribute__ ((unused))
aio_initialize (void)
{
/* Initialize the semaphore. We allow exactly one user at a time. */
sem_init (&__aio_requests_sema, 0, 1);
}
text_set_element (__libc_subinit, aio_initialize);
/* The thread handler. */
static void *handle_fildes_io (void *arg);
/* The main function of the async I/O handling. It enqueues requests
and if necessary starts and handles threads. */
int
__aio_enqueue_request (aiocb_union *aiocbp, int operation, int require_lock)
{
int result;
int policy, prio;
struct sched_param param;
aiocb_union *runp;
if (aiocbp->aiocb.aio_reqprio < 0
|| aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX)
{
/* Invalid priority value. */
__set_errno (EINVAL);
aiocbp->aiocb.__error_code = EINVAL;
aiocbp->aiocb.__return_value = -1;
return -1;
}
if (pthread_getschedparam (pthread_self (), &policy, &param) < 0)
{
/* Something went wrong. */
aiocbp->aiocb.__error_code = errno;
aiocbp->aiocb.__return_value = -1;
return -1;
}
/* Compute priority for this request. */
prio = param.sched_priority - aiocbp->aiocb.aio_reqprio;
/* Get the semaphore. */
if (require_lock)
sem_wait (&__aio_requests_sema);
runp = __aio_requests;
/* First look whether the current file descriptor is currently
worked with. */
while (runp != NULL && runp->aiocb.aio_fildes < aiocbp->aiocb.aio_fildes)
runp = (aiocb_union *) runp->aiocb.__next_fd;
if (runp != NULL)
{
/* The current file descriptor is worked on. It makes no sense
to start another thread since this new thread would have to
wait for the previous one to terminate. Simply enqueue it
after the running one according to the priority. */
while (runp->aiocb.__next_prio != NULL
&& runp->aiocb.__next_prio->__abs_prio >= prio)
runp = (aiocb_union *) runp->aiocb.__next_prio;
aiocbp->aiocb.__next_prio = runp->aiocb.__next_prio;
aiocbp->aiocb.__abs_prio = prio;
aiocbp->aiocb.__policy = policy;
aiocbp->aiocb.aio_lio_opcode = operation;
aiocbp->aiocb.__error_code = EINPROGRESS;
aiocbp->aiocb.__return_value = 0;
runp->aiocb.__next_prio = (struct aiocb *) aiocbp;
result = 0;
}
else
{
/* We create a new thread for this file descriptor. The
function which gets called will handle all available requests
for this descriptor and when all are processed it will
terminate. */
pthread_t thid;
pthread_attr_t attr;
/* First enqueue the request (the list is empty). */
aiocbp->aiocb.__next_fd = NULL;
aiocbp->aiocb.__last_fd = NULL;
aiocbp->aiocb.__next_prio = NULL;
aiocbp->aiocb.__abs_prio = prio;
aiocbp->aiocb.__policy = policy;
aiocbp->aiocb.aio_lio_opcode = operation;
aiocbp->aiocb.__error_code = EINPROGRESS;
aiocbp->aiocb.__return_value = 0;
/* Make sure the thread is created detached. */
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
/* Now try to start a thread. */
if (pthread_create (&thid, &attr, handle_fildes_io, aiocbp) < 0)
{
result = -1;
aiocbp->aiocb.__error_code = errno;
aiocbp->aiocb.__return_value = -1;
}
else
/* We managed to enqueue the request. All errors which can
happen now can be recognized by calls to `aio_return' and
`aio_error'. */
result = 0;
}
/* Release the semaphore. */
if (require_lock)
sem_post (&__aio_requests_sema);
return result;
}
static void *
handle_fildes_io (void *arg)
{
pthread_t self = pthread_self ();
struct sched_param param;
aiocb_union *runp = (aiocb_union *) arg;
int policy;
int fildes = runp->aiocb.aio_fildes; /* This is always the same. */
pthread_getschedparam (self, &policy, &param);
do
{
/* Change the priority to the requested value (if necessary). */
if (runp->aiocb.__abs_prio != param.sched_priority
|| runp->aiocb.__policy != policy)
{
param.sched_priority = runp->aiocb.__abs_prio;
policy = runp->aiocb.__policy;
pthread_setschedparam (self, policy, &param);
}
/* Process request pointed to by RUNP. We must not be disturbed
by signals. */
if ((runp->aiocb.aio_lio_opcode & 127) == LIO_READ)
{
if (runp->aiocb.aio_lio_opcode & 128)
runp->aiocb.__return_value =
TEMP_FAILURE_RETRY (__pread64 (fildes,
(void *) runp->aiocb64.aio_buf,
runp->aiocb64.aio_nbytes,
runp->aiocb64.aio_offset));
else
runp->aiocb.__return_value =
TEMP_FAILURE_RETRY (__pread (fildes,
(void *) runp->aiocb.aio_buf,
runp->aiocb.aio_nbytes,
runp->aiocb.aio_offset));
}
else if ((runp->aiocb.aio_lio_opcode & 127) == LIO_WRITE)
{
if (runp->aiocb.aio_lio_opcode & 128)
runp->aiocb.__return_value =
TEMP_FAILURE_RETRY (__pwrite64 (fildes,
(const void *) runp->aiocb64.aio_buf,
runp->aiocb64.aio_nbytes,
runp->aiocb64.aio_offset));
else
runp->aiocb.__return_value =
TEMP_FAILURE_RETRY (__pwrite (fildes,
(const void *) runp->aiocb.aio_buf,
runp->aiocb.aio_nbytes,
runp->aiocb.aio_offset));
}
else if (runp->aiocb.aio_lio_opcode == __LIO_DSYNC)
runp->aiocb.__return_value = TEMP_FAILURE_RETRY (fdatasync (fildes));
else if (runp->aiocb.aio_lio_opcode == __LIO_SYNC)
runp->aiocb.__return_value = TEMP_FAILURE_RETRY (fsync (fildes));
else
{
/* This is an invalid opcode. */
runp->aiocb.__return_value = -1;
__set_errno (EINVAL);
}
if (runp->aiocb.__return_value == -1)
runp->aiocb.__error_code = errno;
else
runp->aiocb.__error_code = 0;
/* Send the signal to notify about finished processing of the
request. */
if (runp->aiocb.aio_sigevent.sigev_notify == SIGEV_THREAD)
{
/* We have to start a thread. */
pthread_t tid;
pthread_attr_t attr, *pattr;
pattr = (pthread_attr_t *)
runp->aiocb.aio_sigevent.sigev_notify_attributes;
if (pattr == NULL)
{
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pattr = &attr;
}
if (pthread_create (&tid,
(pthread_attr_t *)
runp->aiocb.aio_sigevent.sigev_notify_attributes,
(void *(*) (void *))
runp->aiocb.aio_sigevent.sigev_notify_function,
runp->aiocb.aio_sigevent.sigev_value.sival_ptr)
< 0)
{
/* XXX What shall we do if already an error is set by
read/write/fsync? */
runp->aiocb.__error_code = errno;
runp->aiocb.__return_value = -1;
}
}
else if (runp->aiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL)
/* We have to send a signal. */
if (__aio_sigqueue (runp->aiocb.aio_sigevent.sigev_signo,
runp->aiocb.aio_sigevent.sigev_value) < 0)
{
/* XXX What shall we do if already an error is set by
read/write/fsync? */
runp->aiocb.__error_code = errno;
runp->aiocb.__return_value = -1;
}
/* Get the semaphore. */
sem_wait (&__aio_requests_sema);
/* Now dequeue the current request. */
if (runp->aiocb.__next_prio == NULL)
{
if (runp->aiocb.__next_fd != NULL)
runp->aiocb.__next_fd->__last_fd = runp->aiocb.__last_fd;
if (runp->aiocb.__last_fd != NULL)
runp->aiocb.__last_fd->__next_fd = runp->aiocb.__next_fd;
runp = NULL;
}
else
{
runp->aiocb.__next_prio->__last_fd = runp->aiocb.__last_fd;
runp->aiocb.__next_prio->__next_fd = runp->aiocb.__next_fd;
if (runp->aiocb.__next_fd != NULL)
runp->aiocb.__next_fd->__last_fd = runp->aiocb.__next_prio;
if (runp->aiocb.__last_fd != NULL)
runp->aiocb.__last_fd->__next_fd = runp->aiocb.__next_prio;
runp = (aiocb_union *) runp->aiocb.__next_prio;
}
/* Release the semaphore. */
sem_post (&__aio_requests_sema);
}
while (runp != NULL);
pthread_exit (NULL);
}