diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index 629889a6ff17..b38603b59a88 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -1,447 +1,372 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1998 John Birrell . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Private definitions for libc, libc_r and libpthread. * */ #ifndef _LIBC_PRIVATE_H_ #define _LIBC_PRIVATE_H_ #include #include +#include + extern char **environ; /* * The kernel doesn't expose PID_MAX to the user space. Save it here * to allow to run a newer world on a pre-1400079 kernel. */ #define _PID_MAX 99999 /* * This global flag is non-zero when a process has created one * or more threads. It is used to avoid calling locking functions * when they are not required. */ #ifndef __LIBC_ISTHREADED_DECLARED #define __LIBC_ISTHREADED_DECLARED extern int __isthreaded; #endif /* * Elf_Auxinfo *__elf_aux_vector, the pointer to the ELF aux vector * provided by kernel. Either set for us by rtld, or found at runtime * on stack for static binaries. * * Type is void to avoid polluting whole libc with ELF types. */ extern void *__elf_aux_vector; /* * libc should use libc_dlopen internally, which respects a global * flag where loading of new shared objects can be restricted. */ void *libc_dlopen(const char *, int); /* * For dynamic linker. */ void _rtld_error(const char *fmt, ...); /* * File lock contention is difficult to diagnose without knowing * where locks were set. Allow a debug library to be built which * records the source file and line number of each lock call. */ #ifdef _FLOCK_DEBUG #define _FLOCKFILE(x) _flockfile_debug(x, __FILE__, __LINE__) #else #define _FLOCKFILE(x) _flockfile(x) #endif /* * Macros for locking and unlocking FILEs. These test if the * process is threaded to avoid locking when not required. */ #define FLOCKFILE(fp) if (__isthreaded) _FLOCKFILE(fp) #define FUNLOCKFILE(fp) if (__isthreaded) _funlockfile(fp) struct _spinlock; extern struct _spinlock __stdio_thread_lock __hidden; #define STDIO_THREAD_LOCK() \ do { \ if (__isthreaded) \ _SPINLOCK(&__stdio_thread_lock); \ } while (0) #define STDIO_THREAD_UNLOCK() \ do { \ if (__isthreaded) \ _SPINUNLOCK(&__stdio_thread_lock); \ } while (0) void __libc_spinlock_stub(struct _spinlock *); void __libc_spinunlock_stub(struct _spinlock *); /* * Indexes into the pthread jump table. * * Warning! If you change this type, you must also change the threads * libraries that reference it (libc_r, libpthread). */ typedef enum { PJT_ATFORK, PJT_ATTR_DESTROY, PJT_ATTR_GETDETACHSTATE, PJT_ATTR_GETGUARDSIZE, PJT_ATTR_GETINHERITSCHED, PJT_ATTR_GETSCHEDPARAM, PJT_ATTR_GETSCHEDPOLICY, PJT_ATTR_GETSCOPE, PJT_ATTR_GETSTACKADDR, PJT_ATTR_GETSTACKSIZE, PJT_ATTR_INIT, PJT_ATTR_SETDETACHSTATE, PJT_ATTR_SETGUARDSIZE, PJT_ATTR_SETINHERITSCHED, PJT_ATTR_SETSCHEDPARAM, PJT_ATTR_SETSCHEDPOLICY, PJT_ATTR_SETSCOPE, PJT_ATTR_SETSTACKADDR, PJT_ATTR_SETSTACKSIZE, PJT_CANCEL, PJT_CLEANUP_POP, PJT_CLEANUP_PUSH, PJT_COND_BROADCAST, PJT_COND_DESTROY, PJT_COND_INIT, PJT_COND_SIGNAL, PJT_COND_TIMEDWAIT, PJT_COND_WAIT, PJT_DETACH, PJT_EQUAL, PJT_EXIT, PJT_GETSPECIFIC, PJT_JOIN, PJT_KEY_CREATE, PJT_KEY_DELETE, PJT_KILL, PJT_MAIN_NP, PJT_MUTEXATTR_DESTROY, PJT_MUTEXATTR_INIT, PJT_MUTEXATTR_SETTYPE, PJT_MUTEX_DESTROY, PJT_MUTEX_INIT, PJT_MUTEX_LOCK, PJT_MUTEX_TRYLOCK, PJT_MUTEX_UNLOCK, PJT_ONCE, PJT_RWLOCK_DESTROY, PJT_RWLOCK_INIT, PJT_RWLOCK_RDLOCK, PJT_RWLOCK_TRYRDLOCK, PJT_RWLOCK_TRYWRLOCK, PJT_RWLOCK_UNLOCK, PJT_RWLOCK_WRLOCK, PJT_SELF, PJT_SETCANCELSTATE, PJT_SETCANCELTYPE, PJT_SETSPECIFIC, PJT_SIGMASK, PJT_TESTCANCEL, PJT_CLEANUP_POP_IMP, PJT_CLEANUP_PUSH_IMP, PJT_CANCEL_ENTER, PJT_CANCEL_LEAVE, PJT_MUTEX_CONSISTENT, PJT_MUTEXATTR_GETROBUST, PJT_MUTEXATTR_SETROBUST, PJT_GETTHREADID_NP, PJT_ATTR_GET_NP, PJT_GETNAME_NP, PJT_MAX } pjt_index_t; typedef int (*pthread_func_t)(void); typedef pthread_func_t pthread_func_entry_t[2]; extern pthread_func_entry_t __thr_jtable[]; void __set_error_selector(int *(*arg)(void)); int _pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex, void *(calloc_cb)(__size_t, __size_t)); typedef int (*interpos_func_t)(void); interpos_func_t *__libc_interposing_slot(int interposno); extern interpos_func_t __libc_interposing[] __hidden; interpos_func_t *__libsys_interposing_slot(int interposno); enum { INTERPOS_accept, INTERPOS_accept4, INTERPOS_aio_suspend, INTERPOS_close, INTERPOS_connect, INTERPOS_fcntl, INTERPOS_fsync, INTERPOS_fork, INTERPOS_msync, INTERPOS_nanosleep, INTERPOS_openat, INTERPOS_poll, INTERPOS_pselect, INTERPOS_recvfrom, INTERPOS_recvmsg, INTERPOS_select, INTERPOS_sendmsg, INTERPOS_sendto, INTERPOS_setcontext, INTERPOS_sigaction, INTERPOS_sigprocmask, INTERPOS_sigsuspend, INTERPOS_sigwait, INTERPOS_sigtimedwait, INTERPOS_sigwaitinfo, INTERPOS_swapcontext, INTERPOS_system, INTERPOS_tcdrain, INTERPOS_read, INTERPOS_readv, INTERPOS_wait4, INTERPOS_write, INTERPOS_writev, INTERPOS__pthread_mutex_init_calloc_cb, INTERPOS_spinlock, INTERPOS_spinunlock, INTERPOS_kevent, INTERPOS_wait6, INTERPOS_ppoll, INTERPOS_map_stacks_exec, INTERPOS_fdatasync, INTERPOS_clock_nanosleep, INTERPOS_distribute_static_tls, INTERPOS_pdfork, INTERPOS_MAX }; /* * yplib internal interfaces */ #ifdef YP int _yp_check(char **); #endif void __libc_start1(int, char *[], char *[], void (*)(void), int (*)(int, char *[], char *[])) __dead2; void __libc_start1_gcrt(int, char *[], char *[], void (*)(void), int (*)(int, char *[], char *[]), int *, int *) __dead2; /* * Initialise TLS for static programs */ void _init_tls(void); /* * Provides pthread_once()-like functionality for both single-threaded * and multi-threaded applications. */ int _once(pthread_once_t *, void (*)(void)); /* * This is a pointer in the C run-time startup code. It is used * by getprogname() and setprogname(). */ extern const char *__progname; /* * This function is used by the threading libraries to notify malloc that a * thread is exiting. */ void _malloc_thread_cleanup(void); /* * This function is used by the threading libraries to notify libc that a * thread is exiting, so its thread-local dtors should be called. */ void __cxa_thread_call_dtors(void); int __cxa_thread_atexit_hidden(void (*dtor_func)(void *), void *obj, void *dso_symbol) __hidden; /* * These functions are used by the threading libraries in order to protect * malloc across fork(). */ void _malloc_prefork(void); void _malloc_postfork(void); void _malloc_first_thread(void); /* * Function to clean up streams, called from abort() and exit(). */ extern void (*__cleanup)(void) __hidden; /* * Get kern.osreldate to detect ABI revisions. Explicitly * ignores value of $OSVERSION and caches result. */ int __getosreldate(void); #include #include struct aiocb; struct fd_set; struct iovec; struct kevent; struct msghdr; struct pollfd; struct rusage; struct sigaction; struct sockaddr; struct stat; struct statfs; struct timespec; struct timeval; struct timezone; struct __siginfo; struct __ucontext; struct __wrusage; enum idtype; -int __sys_aio_suspend(const struct aiocb * const[], int, - const struct timespec *); -int __sys_accept(int, struct sockaddr *, __socklen_t *); -int __sys_accept4(int, struct sockaddr *, __socklen_t *, int); -int __sys_clock_gettime(__clockid_t, struct timespec *ts); -int __sys_clock_nanosleep(__clockid_t, int, - const struct timespec *, struct timespec *); -int __sys_close(int); -int __sys_close_range(unsigned, unsigned, int); -int __sys_connect(int, const struct sockaddr *, __socklen_t); -int __sys_fcntl(int, int, __intptr_t); -int __sys_fdatasync(int); -int __sys_fstat(int fd, struct stat *); -int __sys_fstatfs(int fd, struct statfs *); -int __sys_fstatat(int, const char *, struct stat *, int); -int __sys_fsync(int); -__pid_t __sys_fork(void); -int __sys_ftruncate(int, __off_t); -__ssize_t __sys_getdirentries(int, char *, __size_t, __off_t *); -int __sys_getfsstat(struct statfs *, long, int); -int __sys_gettimeofday(struct timeval *, struct timezone *); -int __sys_kevent(int, const struct kevent *, int, struct kevent *, - int, const struct timespec *); -__off_t __sys_lseek(int, __off_t, int); -void *__sys_mmap(void *, __size_t, int, int, int, __off_t); -int __sys_msync(void *, __size_t, int); -int __sys_nanosleep(const struct timespec *, struct timespec *); -int __sys_open(const char *, int, ...); -int __sys_openat(int, const char *, int, ...); -int __sys_pdfork(int *, int); -int __sys_pselect(int, struct fd_set *, struct fd_set *, - struct fd_set *, const struct timespec *, - const __sigset_t *); -int __sys_ptrace(int, __pid_t, char *, int); -int __sys_poll(struct pollfd *, unsigned, int); -int __sys_ppoll(struct pollfd *, unsigned, const struct timespec *, - const __sigset_t *); -__ssize_t __sys_pread(int, void *, __size_t, __off_t); -__ssize_t __sys_pwrite(int, const void *, __size_t, __off_t); -__ssize_t __sys_read(int, void *, __size_t); -__ssize_t __sys_readv(int, const struct iovec *, int); -__ssize_t __sys_recv(int, void *, __size_t, int); -__ssize_t __sys_recvfrom(int, void *, __size_t, int, struct sockaddr *, - __socklen_t *); -__ssize_t __sys_recvmsg(int, struct msghdr *, int); -int __sys_sched_getcpu(void); -int __sys_select(int, struct fd_set *, struct fd_set *, - struct fd_set *, struct timeval *); -__ssize_t __sys_sendmsg(int, const struct msghdr *, int); -__ssize_t __sys_sendto(int, const void *, __size_t, int, - const struct sockaddr *, __socklen_t); -int __sys_setcontext(const struct __ucontext *); -int __sys_sigaction(int, const struct sigaction *, - struct sigaction *); -int __sys_sigprocmask(int, const __sigset_t *, __sigset_t *); -int __sys_sigsuspend(const __sigset_t *); -int __sys_sigtimedwait(const __sigset_t *, struct __siginfo *, - const struct timespec *); -int __sys_sigwait(const __sigset_t *, int *); -int __sys_sigwaitinfo(const __sigset_t *, struct __siginfo *); -int __sys___specialfd(int, const void *, __size_t); -int __sys_statfs(const char *, struct statfs *); -int __sys_swapcontext(struct __ucontext *, - const struct __ucontext *); -int __sys_thr_kill(long, int); -int __sys_thr_self(long *); -int __sys_truncate(const char *, __off_t); -__pid_t __sys_wait4(__pid_t, int *, int, struct rusage *); -__pid_t __sys_wait6(enum idtype, __id_t, int *, int, - struct __wrusage *, struct __siginfo *); -__ssize_t __sys_write(int, const void *, __size_t); -__ssize_t __sys_writev(int, const struct iovec *, int); -int __sys_shm_open2(const char *, int, __mode_t, int, const char *); int __libc_sigaction(int, const struct sigaction *, struct sigaction *) __hidden; int __libc_sigprocmask(int, const __sigset_t *, __sigset_t *) __hidden; int __libc_sigsuspend(const __sigset_t *) __hidden; int __libsys_sigwait(const __sigset_t *, int *) __hidden; int __libc_system(const char *); int __libc_tcdrain(int); -int __sys_futimens(int fd, const struct timespec *times) __hidden; -int __sys_utimensat(int fd, const char *path, - const struct timespec *times, int flag) __hidden; - int _elf_aux_info(int aux, void *buf, int buflen); struct dl_phdr_info; int __elf_phdr_match_addr(struct dl_phdr_info *, void *); void __init_elf_aux_vector(void); void __libc_map_stacks_exec(void); void __libc_distribute_static_tls(__size_t, void *, __size_t, __size_t); __uintptr_t __libc_static_tls_base(__size_t); void _pthread_cancel_enter(int); void _pthread_cancel_leave(int); struct _pthread_cleanup_info; void ___pthread_cleanup_push_imp(void (*)(void *), void *, struct _pthread_cleanup_info *); void ___pthread_cleanup_pop_imp(int); void __throw_constraint_handler_s(const char * restrict msg, int error); struct __nl_cat_d; struct _xlocale; struct __nl_cat_d *__catopen_l(const char *name, int type, struct _xlocale *locale); #endif /* _LIBC_PRIVATE_H_ */ diff --git a/lib/librt/mq.c b/lib/librt/mq.c index 89387b136792..eba52f76c928 100644 --- a/lib/librt/mq.c +++ b/lib/librt/mq.c @@ -1,280 +1,268 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2006 David Xu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include "namespace.h" #include #include #include #include #include #include "sigev_thread.h" #include "un-namespace.h" #include "libc_private.h" -extern int __sys_kmq_notify(int, const struct sigevent *); -extern int __sys_kmq_open(const char *, int, mode_t, - const struct mq_attr *); -extern int __sys_kmq_setattr(int, const struct mq_attr *__restrict, - struct mq_attr *__restrict); -extern ssize_t __sys_kmq_timedreceive(int, char *__restrict, size_t, - unsigned *__restrict, const struct timespec *__restrict); -extern int __sys_kmq_timedsend(int, const char *, size_t, unsigned, - const struct timespec *); -extern int __sys_kmq_unlink(const char *); -extern int __sys_close(int fd); - struct __mq { int oshandle; struct sigev_node *node; }; __weak_reference(__mq_open, mq_open); __weak_reference(__mq_open, _mq_open); __weak_reference(__mq_close, mq_close); __weak_reference(__mq_close, _mq_close); __weak_reference(__mq_notify, mq_notify); __weak_reference(__mq_notify, _mq_notify); __weak_reference(__mq_getattr, mq_getattr); __weak_reference(__mq_getattr, _mq_getattr); __weak_reference(__mq_setattr, mq_setattr); __weak_reference(__mq_setattr, _mq_setattr); __weak_reference(__mq_timedreceive_cancel, mq_timedreceive); __weak_reference(__mq_timedreceive, _mq_timedreceive); __weak_reference(__mq_timedsend_cancel, mq_timedsend); __weak_reference(__mq_timedsend, _mq_timedsend); __weak_reference(__mq_unlink, mq_unlink); __weak_reference(__mq_unlink, _mq_unlink); __weak_reference(__mq_send_cancel, mq_send); __weak_reference(__mq_send, _mq_send); __weak_reference(__mq_receive_cancel, mq_receive); __weak_reference(__mq_receive, _mq_receive); mqd_t __mq_open(const char *name, int oflag, mode_t mode, const struct mq_attr *attr) { struct __mq *mq; int err; mq = malloc(sizeof(struct __mq)); if (mq == NULL) return (NULL); mq->oshandle = __sys_kmq_open(name, oflag, mode, attr); if (mq->oshandle != -1) { mq->node = NULL; return (mq); } err = errno; free(mq); errno = err; return ((mqd_t)-1L); } int __mq_close(mqd_t mqd) { int h; if (mqd->node != NULL) { __sigev_list_lock(); __sigev_delete_node(mqd->node); __sigev_list_unlock(); } h = mqd->oshandle; free(mqd); return (__sys_close(h)); } typedef void (*mq_func)(union sigval val); static void mq_dispatch(struct sigev_node *sn) { mq_func f = sn->sn_func; /* * Check generation before calling user function, * this should avoid expired notification. */ if (sn->sn_gen == sn->sn_info.si_value.sival_int) f(sn->sn_value); } int __mq_notify(mqd_t mqd, const struct sigevent *evp) { struct sigevent ev; struct sigev_node *sn; int ret; if (evp == NULL || evp->sigev_notify != SIGEV_THREAD) { if (mqd->node != NULL) { __sigev_list_lock(); __sigev_delete_node(mqd->node); mqd->node = NULL; __sigev_list_unlock(); } return __sys_kmq_notify(mqd->oshandle, evp); } if (__sigev_check_init()) { /* * Thread library is not enabled. */ errno = EINVAL; return (-1); } sn = __sigev_alloc(SI_MESGQ, evp, mqd->node, 1); if (sn == NULL) { errno = EAGAIN; return (-1); } sn->sn_id = mqd->oshandle; sn->sn_dispatch = mq_dispatch; __sigev_get_sigevent(sn, &ev, sn->sn_gen); __sigev_list_lock(); if (mqd->node != NULL) __sigev_delete_node(mqd->node); mqd->node = sn; __sigev_register(sn); ret = __sys_kmq_notify(mqd->oshandle, &ev); __sigev_list_unlock(); return (ret); } int __mq_getattr(mqd_t mqd, struct mq_attr *attr) { return __sys_kmq_setattr(mqd->oshandle, NULL, attr); } int __mq_setattr(mqd_t mqd, const struct mq_attr *newattr, struct mq_attr *oldattr) { return __sys_kmq_setattr(mqd->oshandle, newattr, oldattr); } ssize_t __mq_timedreceive(mqd_t mqd, char *buf, size_t len, unsigned *prio, const struct timespec *timeout) { return __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, timeout); } ssize_t __mq_timedreceive_cancel(mqd_t mqd, char *buf, size_t len, unsigned *prio, const struct timespec *timeout) { int ret; _pthread_cancel_enter(1); ret = __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, timeout); _pthread_cancel_leave(ret == -1); return (ret); } ssize_t __mq_receive(mqd_t mqd, char *buf, size_t len, unsigned *prio) { return __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, NULL); } ssize_t __mq_receive_cancel(mqd_t mqd, char *buf, size_t len, unsigned *prio) { int ret; _pthread_cancel_enter(1); ret = __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, NULL); _pthread_cancel_leave(ret == -1); return (ret); } ssize_t __mq_timedsend(mqd_t mqd, char *buf, size_t len, unsigned prio, const struct timespec *timeout) { return __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, timeout); } ssize_t __mq_timedsend_cancel(mqd_t mqd, char *buf, size_t len, unsigned prio, const struct timespec *timeout) { int ret; _pthread_cancel_enter(1); ret = __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, timeout); _pthread_cancel_leave(ret == -1); return (ret); } ssize_t __mq_send(mqd_t mqd, char *buf, size_t len, unsigned prio) { return __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, NULL); } ssize_t __mq_send_cancel(mqd_t mqd, char *buf, size_t len, unsigned prio) { int ret; _pthread_cancel_enter(1); ret = __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, NULL); _pthread_cancel_leave(ret == -1); return (ret); } int __mq_unlink(const char *path) { return __sys_kmq_unlink(path); } #pragma weak mq_getfd_np int mq_getfd_np(mqd_t mqd) { return (mqd->oshandle); }