diff options
Diffstat (limited to 'usr/src/lib/librt/common')
21 files changed, 4 insertions, 5275 deletions
diff --git a/usr/src/lib/librt/common/Makefile b/usr/src/lib/librt/common/Makefile deleted file mode 100644 index 052e5a63ad..0000000000 --- a/usr/src/lib/librt/common/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# lib/librt/common/Makefile - -LINTSRC32= lintsrc32 -LINTOUT32= lint32.out -LINTLIB32= $(LIBNAME)32 -$(LINTSRC32):= LINTFLAGS += - -LINTSRC64= lintsrc64 -LINTOUT64= lint64.out -LINTLIB64= $(LIBNAME)64 -$(LINTSRC64):= LINTFLAGS64 += -errchk=longptr64 -fd -Xtransition=yes - -lints : $(LINTSRC32) $(LINTSRC64) - -$(LINTSRC32): $$(SRCS) - $(LINT.c) -o $(LINTLIB32) $(SRCS) > $(LINTOUT32) 2>&1 - -$(LINTSRC64): $$(SRCS) - $(LINT64.c) -o $(LINTLIB64) $(SRCS) > $(LINTOUT64) 2>&1 - -include ../Makefile.com - diff --git a/usr/src/lib/librt/common/aio.c b/usr/src/lib/librt/common/aio.c deleted file mode 100644 index aed292ce56..0000000000 --- a/usr/src/lib/librt/common/aio.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * The POSIX async. I/O functionality is - * implemented in libaio/common/posix_aio.c - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#pragma weak close = __posix_aio_close - -#include "c_synonyms.h" -#include <aio.h> -#include <sys/types.h> -#include <errno.h> -#include <stdlib.h> -#include "pos4.h" -#include "sigev_thread.h" - -extern int _libaio_close(int fd); - -/* - * There is but one spawner for all aio operations. - */ -thread_communication_data_t *sigev_aio_tcd = NULL; - -mutex_t sigev_aio_lock = DEFAULTMUTEX; -cond_t sigev_aio_cv = DEFAULTCV; -int sigev_aio_busy = 0; - -static int -__sigev_thread_init(struct sigevent *sigevp) -{ - thread_communication_data_t *tcdp; - int port; - int rc = 0; - - (void) mutex_lock(&sigev_aio_lock); - while (sigev_aio_busy) - (void) cond_wait(&sigev_aio_cv, &sigev_aio_lock); - if ((tcdp = sigev_aio_tcd) != NULL) - port = tcdp->tcd_port; - else { - sigev_aio_busy = 1; - (void) mutex_unlock(&sigev_aio_lock); - - tcdp = setup_sigev_handler(sigevp, AIO); - if (tcdp == NULL) { - port = -1; - rc = -1; - } else if (launch_spawner(tcdp) != 0) { - free_sigev_handler(tcdp); - tcdp = NULL; - port = -1; - rc = -1; - } else { - port = tcdp->tcd_port; - } - - (void) mutex_lock(&sigev_aio_lock); - sigev_aio_tcd = tcdp; - sigev_aio_busy = 0; - (void) cond_broadcast(&sigev_aio_cv); - } - (void) mutex_unlock(&sigev_aio_lock); - sigevp->sigev_signo = port; - return (rc); -} - -static int -__posix_sigev_thread(aiocb_t *aiocbp) -{ - struct sigevent *sigevp; - - if (aiocbp != NULL) { - sigevp = &aiocbp->aio_sigevent; - if (sigevp->sigev_notify == SIGEV_THREAD && - sigevp->sigev_notify_function != NULL) - return (__sigev_thread_init(sigevp)); - } - return (0); -} - -#if !defined(_LP64) -static int -__posix_sigev_thread64(aiocb64_t *aiocbp) -{ - struct sigevent *sigevp; - - if (aiocbp != NULL) { - sigevp = &aiocbp->aio_sigevent; - if (sigevp->sigev_notify == SIGEV_THREAD && - sigevp->sigev_notify_function != NULL) - return (__sigev_thread_init(sigevp)); - } - return (0); -} -#endif - -int -__posix_aio_close(int fd) -{ - return (_libaio_close(fd)); -} - -int -aio_cancel(int fildes, aiocb_t *aiocbp) -{ - return (__aio_cancel(fildes, aiocbp)); -} - -#if !defined(_LP64) - -int -aio_cancel64(int fildes, aiocb64_t *aiocbp) -{ - return (__aio_cancel64(fildes, aiocbp)); -} - -#endif - -int -aio_error(const aiocb_t *aiocbp) -{ - return (__aio_error(aiocbp)); -} - -#if !defined(_LP64) - -int -aio_error64(const aiocb64_t *aiocbp) -{ - return (__aio_error64(aiocbp)); -} - -#endif - -int -aio_fsync(int op, aiocb_t *aiocbp) -{ - int rc; - - if ((rc = __posix_sigev_thread(aiocbp)) == 0) - rc = __aio_fsync(op, aiocbp); - return (rc); - -} - -#if !defined(_LP64) - -int -aio_fsync64(int op, aiocb64_t *aiocbp) -{ - int rc; - - if ((rc = __posix_sigev_thread64(aiocbp)) == 0) - rc = __aio_fsync64(op, aiocbp); - return (rc); -} - -#endif - -int -aio_read(aiocb_t *aiocbp) -{ - int rc; - - if ((rc = __posix_sigev_thread(aiocbp)) == 0) - rc = __aio_read(aiocbp); - return (rc); -} - -#if !defined(_LP64) - -int -aio_read64(aiocb64_t *aiocbp) -{ - int rc; - - if ((rc = __posix_sigev_thread64(aiocbp)) == 0) - rc = __aio_read64(aiocbp); - return (rc); -} - -#endif - -ssize_t -aio_return(aiocb_t *aiocbp) -{ - return (__aio_return(aiocbp)); -} - -#if !defined(_LP64) - -ssize_t -aio_return64(aiocb64_t *aiocbp) -{ - return (__aio_return64(aiocbp)); -} - -#endif - -int -aio_suspend(const aiocb_t * const list[], int nent, - const timespec_t *timeout) -{ - return (__aio_suspend((void **)list, nent, timeout, 0)); -} - -#if !defined(_LP64) - -int -aio_suspend64(const aiocb64_t * const list[], int nent, - const timespec_t *timeout) -{ - return (__aio_suspend((void **)list, nent, timeout, 1)); -} - -#endif - -int -aio_write(aiocb_t *aiocbp) -{ - int rc; - - if ((rc = __posix_sigev_thread(aiocbp)) == 0) - rc = __aio_write(aiocbp); - return (rc); -} - -#if !defined(_LP64) - -int -aio_write64(aiocb64_t *aiocbp) -{ - int rc; - - if ((rc = __posix_sigev_thread64(aiocbp)) == 0) - rc = __aio_write64(aiocbp); - return (rc); -} - -#endif - -int -lio_listio(int mode, - aiocb_t *_RESTRICT_KYWD const *_RESTRICT_KYWD list, - int nent, struct sigevent *_RESTRICT_KYWD sigevp) -{ - int i; - aiocb_t *aiocbp; - - for (i = 0; i < nent; i++) { - if ((aiocbp = list[i]) != NULL && - aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD && - __posix_sigev_thread(aiocbp) != 0) - return (-1); - } - if (sigevp != NULL && - sigevp->sigev_notify == SIGEV_THREAD && - sigevp->sigev_notify_function != NULL && - __sigev_thread_init(sigevp) != 0) - return (-1); - - return (__lio_listio(mode, list, nent, sigevp)); -} - -#if !defined(_LP64) - -int -lio_listio64(int mode, - aiocb64_t *_RESTRICT_KYWD const *_RESTRICT_KYWD list, - int nent, struct sigevent *_RESTRICT_KYWD sigevp) -{ - int i; - aiocb64_t *aiocbp; - - for (i = 0; i < nent; i++) { - if ((aiocbp = list[i]) != NULL && - aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD && - __posix_sigev_thread64(aiocbp) != 0) - return (-1); - } - if (sigevp != NULL && - sigevp->sigev_notify == SIGEV_THREAD && - sigevp->sigev_notify_function != NULL && - __sigev_thread_init(sigevp) != 0) - return (-1); - - return (__lio_listio64(mode, list, nent, sigevp)); -} - -#endif - - -int -aio_waitn(aiocb_t *list[], uint_t nent, uint_t *nwait, - const timespec_t *timeout) -{ - return (__aio_waitn((void **)list, nent, nwait, timeout)); -} - -#if !defined(_LP64) - -int -aio_waitn64(aiocb64_t *list[], uint_t nent, uint_t *nwait, - const timespec_t *timeout) -{ - return (__aio_waitn((void **)list, nent, nwait, timeout)); -} - -#endif diff --git a/usr/src/lib/librt/common/clock_timer.c b/usr/src/lib/librt/common/clock_timer.c deleted file mode 100644 index 4e9ba1124f..0000000000 --- a/usr/src/lib/librt/common/clock_timer.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#pragma weak clock_getres = _clock_getres -#pragma weak clock_gettime = _clock_gettime -#pragma weak clock_settime = _clock_settime -#pragma weak timer_create = _timer_create -#pragma weak timer_delete = _timer_delete -#pragma weak timer_getoverrun = _timer_getoverrun -#pragma weak timer_gettime = _timer_gettime -#pragma weak timer_settime = _timer_settime - -#pragma weak clock_nanosleep = _clock_nanosleep -#pragma weak nanosleep = _nanosleep - -#include "c_synonyms.h" -#include <time.h> -#include <sys/types.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include "pos4.h" -#include "sigev_thread.h" - -/* - * Array of pointers to tcd's, indexed by timer id. - * No more than 'timer_max' timers can be created by any process. - */ -int timer_max = 0; -thread_communication_data_t **timer_tcd; -static pthread_once_t timer_once = PTHREAD_ONCE_INIT; - -static void -timer_init(void) -{ - timer_max = (int)_sysconf(_SC_TIMER_MAX); - timer_tcd = malloc(timer_max * sizeof (*timer_tcd)); - (void) memset(timer_tcd, 0, timer_max * sizeof (*timer_tcd)); -} - -int -_clock_getres(clockid_t clock_id, timespec_t *res) -{ - return (__clock_getres(clock_id, res)); -} - -int -_clock_gettime(clockid_t clock_id, timespec_t *tp) -{ - return (__clock_gettime(clock_id, tp)); -} - -int -_clock_settime(clockid_t clock_id, const timespec_t *tp) -{ - return (__clock_settime(clock_id, tp)); -} - -int -_timer_create(clockid_t clock_id, struct sigevent *sigevp, timer_t *timerid) -{ - struct sigevent sigevent; - port_notify_t port_notify; - thread_communication_data_t *tcdp; - int sigev_thread = 0; - int rc; - - (void) pthread_once(&timer_once, timer_init); - - if (sigevp != NULL && - sigevp->sigev_notify == SIGEV_THREAD && - sigevp->sigev_notify_function != NULL) { - sigev_thread = 1; - tcdp = setup_sigev_handler(sigevp, TIMER); - if (tcdp == NULL) - return (-1); - /* copy the sigevent structure so we can modify it */ - sigevent = *sigevp; - sigevp = &sigevent; - port_notify.portnfy_port = tcdp->tcd_port; - port_notify.portnfy_user = NULL; - sigevp->sigev_value.sival_ptr = &port_notify; - } - - rc = __timer_create(clock_id, sigevp, timerid); - if (rc == 0 && sigev_thread) { - if ((rc = launch_spawner(tcdp)) != 0) - __timer_delete(*timerid); - else - timer_tcd[*timerid] = tcdp; - } - if (rc != 0 && sigev_thread) - free_sigev_handler(tcdp); - - return (rc); -} - -int -_timer_delete(timer_t timerid) -{ - int rc; - - if ((rc = del_sigev_timer(timerid)) == 0) - return (__timer_delete(timerid)); - else - return (rc); -} - -int -_timer_getoverrun(timer_t timerid) -{ - return (__timer_getoverrun(timerid) + sigev_timer_getoverrun(timerid)); -} - -int -_timer_gettime(timer_t timerid, itimerspec_t *value) -{ - return (__timer_gettime(timerid, value)); -} - -int -_timer_settime(timer_t timerid, int flags, const itimerspec_t *value, - itimerspec_t *ovalue) -{ - return (__timer_settime(timerid, flags, value, ovalue)); -} - -int -_clock_nanosleep(clockid_t clock_id, int flags, - const timespec_t *rqtp, timespec_t *rmtp) -{ - return (__clock_nanosleep(clock_id, flags, rqtp, rmtp)); -} - -int -_nanosleep(const timespec_t *rqtp, timespec_t *rmtp) -{ - return (__nanosleep(rqtp, rmtp)); -} diff --git a/usr/src/lib/librt/common/fallocate.c b/usr/src/lib/librt/common/fallocate.c deleted file mode 100644 index d4b1d0de1f..0000000000 --- a/usr/src/lib/librt/common/fallocate.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "c_synonyms.h" -#include <errno.h> -#include <fcntl.h> -#include <sys/types.h> -#include "pos4.h" - -#include <stdio.h> - -int -posix_fallocate(int fd, off_t offset, off_t len) -{ - struct flock lck; - - lck.l_whence = 0; - lck.l_start = offset; - lck.l_len = len; - lck.l_type = F_WRLCK; - - if (fcntl(fd, F_ALLOCSP, &lck) == -1) { - return (-1); - } - - return (0); -} - -#if defined(_LARGEFILE64_SOURCE) && !defined(_LP64) - -int -posix_fallocate64(int fd, off64_t offset, off64_t len) -{ - struct flock64 lck; - - lck.l_whence = 0; - lck.l_start = offset; - lck.l_len = len; - lck.l_type = F_WRLCK; - - if (fcntl(fd, F_ALLOCSP64, &lck) == -1) { - return (-1); - } - - return (0); -} - -#endif diff --git a/usr/src/lib/librt/common/fdatasync.c b/usr/src/lib/librt/common/fdatasync.c deleted file mode 100644 index c79ddb0ffa..0000000000 --- a/usr/src/lib/librt/common/fdatasync.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "c_synonyms.h" -#include <sys/file.h> - -extern int __fdsync(int fd, int mode); - -int -fdatasync(int fd) -{ - return (__fdsync(fd, FDSYNC)); -} diff --git a/usr/src/lib/librt/common/llib-lrt b/usr/src/lib/librt/common/llib-lrt index 1d0c3a9fcf..0850024175 100644 --- a/usr/src/lib/librt/common/llib-lrt +++ b/usr/src/lib/librt/common/llib-lrt @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,7 +29,6 @@ #pragma ident "%Z%%M% %I% %E% SMI" -#include <sys/types.h> #include <aio.h> #include <mqueue.h> #include <sched.h> diff --git a/usr/src/lib/librt/common/mqlib.h b/usr/src/lib/librt/common/mqlib.h deleted file mode 100644 index 8b51767d0f..0000000000 --- a/usr/src/lib/librt/common/mqlib.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _MQLIB_H -#define _MQLIB_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * mqlib.h - Header file for POSIX.4 message queue - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/types.h> -#include "sigev_thread.h" - -/* - * Default values per message queue - */ -#define MQ_MAXMSG 128 -#define MQ_MAXSIZE 1024 - -#define MQ_MAGIC 0x4d534751 /* "MSGQ" */ - -/* - * Message header which is part of messages in link list - */ -typedef struct { - uint64_t msg_next; /* offset of next message in the link */ - uint64_t msg_len; /* length of the message */ -} msghdr_t; - -/* - * message queue description - */ -struct mq_dn { - size_t mqdn_flags; /* open description flags */ -}; - -/* - * message queue descriptor structure - */ -typedef struct mq_des { - struct mq_des *mqd_next; /* list of all open mq descriptors, */ - struct mq_des *mqd_prev; /* needed for fork-safety */ - int mqd_magic; /* magic # to identify mq_des */ - int mqd_flags; /* operation flag per open */ - struct mq_header *mqd_mq; /* address pointer of message Q */ - struct mq_dn *mqd_mqdn; /* open description */ - thread_communication_data_t *mqd_tcd; /* SIGEV_THREAD notification */ -} mqdes_t; - - -/* - * message queue common header, part of the mmap()ed file. - * Since message queues may be shared between 32- and 64-bit processes, - * care must be taken to make sure that the elements of this structure - * are identical for both _LP64 and _ILP32 cases. - */ -typedef struct mq_header { - /* first field must be mq_totsize, DO NOT insert before this */ - int64_t mq_totsize; /* total size of the Queue */ - int64_t mq_maxsz; /* max size of each message */ - uint32_t mq_maxmsg; /* max messages in the queue */ - uint32_t mq_maxprio; /* maximum mqueue priority */ - uint32_t mq_curmaxprio; /* current maximum MQ priority */ - uint32_t mq_mask; /* priority bitmask */ - uint64_t mq_freep; /* free message's head pointer */ - uint64_t mq_headpp; /* pointer to head pointers */ - uint64_t mq_tailpp; /* pointer to tail pointers */ - signotify_id_t mq_sigid; /* notification id (3 int's) */ - uint32_t mq_ntype; /* notification type (SIGEV_*) */ - uint64_t mq_des; /* pointer to msg Q descriptor */ - mutex_t mq_exclusive; /* acquire for exclusive access */ - sem_t mq_rblocked; /* number of processes rblocked */ - sem_t mq_notfull; /* mq_send()'s block on this */ - sem_t mq_notempty; /* mq_receive()'s block on this */ - sem_t mq_spawner; /* spawner thread blocks on this */ -} mqhdr_t; - -extern mutex_t mq_list_lock; -extern mqdes_t *mq_list; - -/* prototype for signotify system call. unexposed to user */ -int __signotify(int cmd, siginfo_t *sigonfo, signotify_id_t *sn_id); - -#ifdef __cplusplus -} -#endif - -#endif /* _MQLIB_H */ diff --git a/usr/src/lib/librt/common/mqueue.c b/usr/src/lib/librt/common/mqueue.c deleted file mode 100644 index c06b4d1760..0000000000 --- a/usr/src/lib/librt/common/mqueue.c +++ /dev/null @@ -1,1020 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#pragma weak mq_open = _mq_open -#pragma weak mq_close = _mq_close -#pragma weak mq_unlink = _mq_unlink -#pragma weak mq_send = _mq_send -#pragma weak mq_timedsend = _mq_timedsend -#pragma weak mq_reltimedsend_np = _mq_reltimedsend_np -#pragma weak mq_receive = _mq_receive -#pragma weak mq_timedreceive = _mq_timedreceive -#pragma weak mq_reltimedreceive_np = _mq_reltimedreceive_np -#pragma weak mq_notify = _mq_notify -#pragma weak mq_setattr = _mq_setattr -#pragma weak mq_getattr = _mq_getattr - -#include "c_synonyms.h" -#if !defined(__lint) /* need a *_synonyms.h file */ -#define sem_getvalue _sem_getvalue -#define sem_init _sem_init -#define sem_post _sem_post -#define sem_reltimedwait_np _sem_reltimedwait_np -#define sem_timedwait _sem_timedwait -#define sem_trywait _sem_trywait -#define sem_wait _sem_wait -#endif -#define _KMEMUSER -#include <sys/param.h> /* _MQ_OPEN_MAX, _MQ_PRIO_MAX, _SEM_VALUE_MAX */ -#undef _KMEMUSER -#include <mqueue.h> -#include <sys/types.h> -#include <sys/file.h> -#include <sys/mman.h> -#include <errno.h> -#include <stdarg.h> -#include <limits.h> -#include <pthread.h> -#include <assert.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <inttypes.h> - -#include "mqlib.h" -#include "pos4obj.h" -#include "pos4.h" - -/* - * The code assumes that _MQ_OPEN_MAX == -1 or "no fixed implementation limit". - * If this assumption is somehow invalidated, mq_open() needs to be changed - * back to the old version which kept a count and enforced a limit. - * We make sure that this is pointed out to those changing <sys/param.h> - * by checking _MQ_OPEN_MAX at compile time. - */ -#if _MQ_OPEN_MAX != -1 -#error "librt:mq_open() no longer enforces _MQ_OPEN_MAX and needs fixing." -#endif - -#define MQ_ALIGNSIZE 8 /* 64-bit alignment */ - -#ifdef DEBUG -#define MQ_ASSERT(x) \ - assert(x); - -#define MQ_ASSERT_PTR(_m, _p) \ - assert((_p) != NULL && !((uintptr_t)(_p) & (MQ_ALIGNSIZE -1)) && \ - !((uintptr_t)_m + (uintptr_t)(_p) >= (uintptr_t)_m + \ - _m->mq_totsize)); - -#define MQ_ASSERT_SEMVAL_LEQ(sem, val) { \ - int _val; \ - (void) sem_getvalue((sem), &_val); \ - assert((_val) <= val); } -#else -#define MQ_ASSERT(x) -#define MQ_ASSERT_PTR(_m, _p) -#define MQ_ASSERT_SEMVAL_LEQ(sem, val) -#endif - -#define MQ_PTR(m, n) ((msghdr_t *)((uintptr_t)m + (uintptr_t)n)) -#define HEAD_PTR(m, n) ((uint64_t *)((uintptr_t)m + \ - (uintptr_t)m->mq_headpp + n * sizeof (uint64_t))) -#define TAIL_PTR(m, n) ((uint64_t *)((uintptr_t)m + \ - (uintptr_t)m->mq_tailpp + n * sizeof (uint64_t))) - -#define MQ_RESERVED ((mqdes_t *)-1) - -#define ABS_TIME 0 -#define REL_TIME 1 - -mutex_t mq_list_lock = DEFAULTMUTEX; -mqdes_t *mq_list = NULL; - -static int -mq_is_valid(mqdes_t *mqdp) -{ - /* - * Any use of a message queue after it was closed is - * undefined. But the standard strongly favours EBADF - * returns. Before we dereference which could be fatal, - * we first do some pointer sanity checks. - */ - if (mqdp != NULL && mqdp != MQ_RESERVED && - ((uintptr_t)mqdp & 0x7) == 0) { - return (mqdp->mqd_magic == MQ_MAGIC); - } - - return (0); -} - -static void -mq_init(mqhdr_t *mqhp, size_t msgsize, ssize_t maxmsg) -{ - int i; - uint64_t temp; - uint64_t currentp; - uint64_t nextp; - - /* - * We only need to initialize the non-zero fields. The use of - * ftruncate() on the message queue file assures that the - * pages will be zfod. - */ - (void) mutex_init(&mqhp->mq_exclusive, USYNC_PROCESS, NULL); - (void) sem_init(&mqhp->mq_rblocked, 1, 0); - (void) sem_init(&mqhp->mq_notempty, 1, 0); - (void) sem_init(&mqhp->mq_spawner, 1, 0); - (void) sem_init(&mqhp->mq_notfull, 1, (uint_t)maxmsg); - - mqhp->mq_maxsz = msgsize; - mqhp->mq_maxmsg = maxmsg; - - /* - * As of this writing (1997), there are 32 message queue priorities. - * If this is to change, then the size of the mq_mask will - * also have to change. If DEBUG is defined, assert that - * _MQ_PRIO_MAX hasn't changed. - */ - mqhp->mq_maxprio = _MQ_PRIO_MAX; -#if defined(DEBUG) - /* LINTED always true */ - MQ_ASSERT(sizeof (mqhp->mq_mask) * 8 >= _MQ_PRIO_MAX); -#endif - - /* - * Since the message queue can be mapped into different - * virtual address ranges by different processes, we don't - * keep track of pointers, only offsets into the shared region. - */ - mqhp->mq_headpp = sizeof (mqhdr_t); - mqhp->mq_tailpp = mqhp->mq_headpp + - mqhp->mq_maxprio * sizeof (uint64_t); - mqhp->mq_freep = mqhp->mq_tailpp + - mqhp->mq_maxprio * sizeof (uint64_t); - - currentp = mqhp->mq_freep; - MQ_PTR(mqhp, currentp)->msg_next = 0; - - temp = (mqhp->mq_maxsz + MQ_ALIGNSIZE - 1) & ~(MQ_ALIGNSIZE - 1); - for (i = 1; i < mqhp->mq_maxmsg; i++) { - nextp = currentp + sizeof (msghdr_t) + temp; - MQ_PTR(mqhp, currentp)->msg_next = nextp; - MQ_PTR(mqhp, nextp)->msg_next = 0; - currentp = nextp; - } -} - -static size_t -mq_getmsg(mqhdr_t *mqhp, char *msgp, uint_t *msg_prio) -{ - uint64_t currentp; - msghdr_t *curbuf; - uint64_t *headpp; - uint64_t *tailpp; - - MQ_ASSERT(MUTEX_HELD(&mqhp->mq_exclusive)); - - /* - * Get the head and tail pointers for the queue of maximum - * priority. We shouldn't be here unless there is a message for - * us, so it's fair to assert that both the head and tail - * pointers are non-NULL. - */ - headpp = HEAD_PTR(mqhp, mqhp->mq_curmaxprio); - tailpp = TAIL_PTR(mqhp, mqhp->mq_curmaxprio); - - if (msg_prio != NULL) - *msg_prio = mqhp->mq_curmaxprio; - - currentp = *headpp; - MQ_ASSERT_PTR(mqhp, currentp); - curbuf = MQ_PTR(mqhp, currentp); - - if ((*headpp = curbuf->msg_next) == NULL) { - /* - * We just nuked the last message in this priority's queue. - * Twiddle this priority's bit, and then find the next bit - * tipped. - */ - uint_t prio = mqhp->mq_curmaxprio; - - mqhp->mq_mask &= ~(1u << prio); - - for (; prio != 0; prio--) - if (mqhp->mq_mask & (1u << prio)) - break; - mqhp->mq_curmaxprio = prio; - - *tailpp = NULL; - } - - /* - * Copy the message, and put the buffer back on the free list. - */ - (void) memcpy(msgp, (char *)&curbuf[1], curbuf->msg_len); - curbuf->msg_next = mqhp->mq_freep; - mqhp->mq_freep = currentp; - - return (curbuf->msg_len); -} - - -static void -mq_putmsg(mqhdr_t *mqhp, const char *msgp, ssize_t len, uint_t prio) -{ - uint64_t currentp; - msghdr_t *curbuf; - uint64_t *headpp; - uint64_t *tailpp; - - MQ_ASSERT(MUTEX_HELD(&mqhp->mq_exclusive)); - - /* - * Grab a free message block, and link it in. We shouldn't - * be here unless there is room in the queue for us; it's - * fair to assert that the free pointer is non-NULL. - */ - currentp = mqhp->mq_freep; - MQ_ASSERT_PTR(mqhp, currentp); - curbuf = MQ_PTR(mqhp, currentp); - - /* - * Remove a message from the free list, and copy in the new contents. - */ - mqhp->mq_freep = curbuf->msg_next; - curbuf->msg_next = NULL; - (void) memcpy((char *)&curbuf[1], msgp, len); - curbuf->msg_len = len; - - headpp = HEAD_PTR(mqhp, prio); - tailpp = TAIL_PTR(mqhp, prio); - - if (*tailpp == 0) { - /* - * This is the first message on this queue. Set the - * head and tail pointers, and tip the appropriate bit - * in the priority mask. - */ - *headpp = currentp; - *tailpp = currentp; - mqhp->mq_mask |= (1u << prio); - if (prio > mqhp->mq_curmaxprio) - mqhp->mq_curmaxprio = prio; - } else { - MQ_ASSERT_PTR(mqhp, *tailpp); - MQ_PTR(mqhp, *tailpp)->msg_next = currentp; - *tailpp = currentp; - } -} - -mqd_t -_mq_open(const char *path, int oflag, /* mode_t mode, mq_attr *attr */ ...) -{ - va_list ap; - mode_t mode; - struct mq_attr *attr; - int fd; - int err; - int cr_flag = 0; - int locked = 0; - uint64_t total_size; - size_t msgsize; - ssize_t maxmsg; - uint64_t temp; - void *ptr; - mqdes_t *mqdp; - mqhdr_t *mqhp; - struct mq_dn *mqdnp; - - if (__pos4obj_check(path) == -1) - return ((mqd_t)-1); - - /* acquire MSGQ lock to have atomic operation */ - if (__pos4obj_lock(path, MQ_LOCK_TYPE) < 0) - goto out; - locked = 1; - - va_start(ap, oflag); - /* filter oflag to have READ/WRITE/CREATE modes only */ - oflag = oflag & (O_RDONLY|O_WRONLY|O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK); - if ((oflag & O_CREAT) != 0) { - mode = va_arg(ap, mode_t); - attr = va_arg(ap, struct mq_attr *); - } - va_end(ap); - - if ((fd = __pos4obj_open(path, MQ_PERM_TYPE, oflag, - mode, &cr_flag)) < 0) - goto out; - - /* closing permission file */ - (void) __close_nc(fd); - - /* Try to open/create data file */ - if (cr_flag) { - cr_flag = PFILE_CREATE; - if (attr == NULL) { - maxmsg = MQ_MAXMSG; - msgsize = MQ_MAXSIZE; - } else if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0) { - errno = EINVAL; - goto out; - } else if (attr->mq_maxmsg > _SEM_VALUE_MAX) { - errno = ENOSPC; - goto out; - } else { - maxmsg = attr->mq_maxmsg; - msgsize = attr->mq_msgsize; - } - - /* adjust for message size at word boundary */ - temp = (msgsize + MQ_ALIGNSIZE - 1) & ~(MQ_ALIGNSIZE - 1); - - total_size = sizeof (mqhdr_t) + - maxmsg * (temp + sizeof (msghdr_t)) + - 2 * _MQ_PRIO_MAX * sizeof (uint64_t); - - if (total_size > SSIZE_MAX) { - errno = ENOSPC; - goto out; - } - - /* - * data file is opened with read/write to those - * who have read or write permission - */ - mode = mode | (mode & 0444) >> 1 | (mode & 0222) << 1; - if ((fd = __pos4obj_open(path, MQ_DATA_TYPE, - (O_RDWR|O_CREAT|O_EXCL), mode, &err)) < 0) - goto out; - - cr_flag |= DFILE_CREATE | DFILE_OPEN; - - /* force permissions to avoid umask effect */ - if (fchmod(fd, mode) < 0) - goto out; - - if (ftruncate64(fd, (off64_t)total_size) < 0) - goto out; - } else { - if ((fd = __pos4obj_open(path, MQ_DATA_TYPE, - O_RDWR, 0666, &err)) < 0) - goto out; - cr_flag = DFILE_OPEN; - - /* Message queue has not been initialized yet */ - if (read(fd, &total_size, sizeof (total_size)) != - sizeof (total_size) || total_size == 0) { - errno = ENOENT; - goto out; - } - - /* Message queue too big for this process to handle */ - if (total_size > SSIZE_MAX) { - errno = EFBIG; - goto out; - } - } - - if ((mqdp = (mqdes_t *)malloc(sizeof (mqdes_t))) == NULL) { - errno = ENOMEM; - goto out; - } - cr_flag |= ALLOC_MEM; - - if ((ptr = mmap64(NULL, total_size, PROT_READ|PROT_WRITE, - MAP_SHARED, fd, (off64_t)0)) == MAP_FAILED) - goto out; - mqhp = ptr; - cr_flag |= DFILE_MMAP; - - /* closing data file */ - (void) __close_nc(fd); - cr_flag &= ~DFILE_OPEN; - - /* - * create, unlink, size, mmap, and close description file - * all for a flag word in anonymous shared memory - */ - if ((fd = __pos4obj_open(path, MQ_DSCN_TYPE, O_RDWR | O_CREAT, - 0666, &err)) < 0) - goto out; - cr_flag |= DFILE_OPEN; - (void) __pos4obj_unlink(path, MQ_DSCN_TYPE); - if (ftruncate64(fd, (off64_t)sizeof (struct mq_dn)) < 0) - goto out; - - if ((ptr = mmap64(NULL, sizeof (struct mq_dn), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off64_t)0)) == MAP_FAILED) - goto out; - mqdnp = ptr; - cr_flag |= MQDNP_MMAP; - - (void) __close_nc(fd); - cr_flag &= ~DFILE_OPEN; - - /* - * we follow the same strategy as filesystem open() routine, - * where fcntl.h flags are changed to flags defined in file.h. - */ - mqdp->mqd_flags = (oflag - FOPEN) & (FREAD|FWRITE); - mqdnp->mqdn_flags = (oflag - FOPEN) & (FNONBLOCK); - - /* new message queue requires initialization */ - if ((cr_flag & DFILE_CREATE) != 0) { - /* message queue header has to be initialized */ - mq_init(mqhp, msgsize, maxmsg); - mqhp->mq_totsize = total_size; - } - mqdp->mqd_mq = mqhp; - mqdp->mqd_mqdn = mqdnp; - mqdp->mqd_magic = MQ_MAGIC; - mqdp->mqd_tcd = NULL; - if (__pos4obj_unlock(path, MQ_LOCK_TYPE) == 0) { - (void) mutex_lock(&mq_list_lock); - mqdp->mqd_next = mq_list; - mqdp->mqd_prev = NULL; - if (mq_list) - mq_list->mqd_prev = mqdp; - mq_list = mqdp; - (void) mutex_unlock(&mq_list_lock); - return ((mqd_t)mqdp); - } - - locked = 0; /* fall into the error case */ -out: - err = errno; - if ((cr_flag & DFILE_OPEN) != 0) - (void) __close_nc(fd); - if ((cr_flag & DFILE_CREATE) != 0) - (void) __pos4obj_unlink(path, MQ_DATA_TYPE); - if ((cr_flag & PFILE_CREATE) != 0) - (void) __pos4obj_unlink(path, MQ_PERM_TYPE); - if ((cr_flag & ALLOC_MEM) != 0) - free((void *)mqdp); - if ((cr_flag & DFILE_MMAP) != 0) - (void) munmap((caddr_t)mqhp, (size_t)total_size); - if ((cr_flag & MQDNP_MMAP) != 0) - (void) munmap((caddr_t)mqdnp, sizeof (struct mq_dn)); - if (locked) - (void) __pos4obj_unlock(path, MQ_LOCK_TYPE); - errno = err; - return ((mqd_t)-1); -} - -int -_mq_close(mqd_t mqdes) -{ - mqdes_t *mqdp = (mqdes_t *)mqdes; - mqhdr_t *mqhp; - struct mq_dn *mqdnp; - thread_communication_data_t *tcdp; - - if (!mq_is_valid(mqdp)) { - errno = EBADF; - return (-1); - } - - mqhp = mqdp->mqd_mq; - mqdnp = mqdp->mqd_mqdn; - - (void) mutex_lock(&mqhp->mq_exclusive); - if (mqhp->mq_des == (uintptr_t)mqdp && - mqhp->mq_sigid.sn_pid == getpid()) { - /* notification is set for this descriptor, remove it */ - (void) __signotify(SN_CANCEL, NULL, &mqhp->mq_sigid); - mqhp->mq_ntype = 0; - mqhp->mq_des = 0; - } - if ((tcdp = mqdp->mqd_tcd) != NULL) { - mqdp->mqd_tcd = NULL; - del_sigev_mq(tcdp); - } - /* invalidate the descriptor before freeing it */ - mqdp->mqd_magic = 0; - (void) mutex_unlock(&mqhp->mq_exclusive); - - (void) mutex_lock(&mq_list_lock); - if (mqdp->mqd_next) - mqdp->mqd_next->mqd_prev = mqdp->mqd_prev; - if (mqdp->mqd_prev) - mqdp->mqd_prev->mqd_next = mqdp->mqd_next; - if (mq_list == mqdp) - mq_list = mqdp->mqd_next; - (void) mutex_unlock(&mq_list_lock); - - free(mqdp); - (void) munmap((caddr_t)mqdnp, sizeof (struct mq_dn)); - return (munmap((caddr_t)mqhp, (size_t)mqhp->mq_totsize)); -} - -int -_mq_unlink(const char *path) -{ - int err; - - if (__pos4obj_check(path) < 0) - return (-1); - - if (__pos4obj_lock(path, MQ_LOCK_TYPE) < 0) { - return (-1); - } - - err = __pos4obj_unlink(path, MQ_PERM_TYPE); - - if (err == 0 || (err == -1 && errno == EEXIST)) { - errno = 0; - err = __pos4obj_unlink(path, MQ_DATA_TYPE); - } - - if (__pos4obj_unlock(path, MQ_LOCK_TYPE) < 0) - return (-1); - - return (err); - -} - -static int -__mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, - uint_t msg_prio, const timespec_t *timeout, int abs_rel) -{ - mqdes_t *mqdp = (mqdes_t *)mqdes; - mqhdr_t *mqhp; - int err; - int notify = 0; - - /* - * sem_*wait() does cancellation, if called. - * pthread_testcancel() ensures that cancellation takes place if - * there is a cancellation pending when mq_*send() is called. - */ - pthread_testcancel(); - - if (!mq_is_valid(mqdp) || (mqdp->mqd_flags & FWRITE) == 0) { - errno = EBADF; - return (-1); - } - - mqhp = mqdp->mqd_mq; - - if (msg_prio >= mqhp->mq_maxprio) { - errno = EINVAL; - return (-1); - } - if (msg_len > mqhp->mq_maxsz) { - errno = EMSGSIZE; - return (-1); - } - - if (mqdp->mqd_mqdn->mqdn_flags & O_NONBLOCK) - err = sem_trywait(&mqhp->mq_notfull); - else { - /* - * We might get cancelled here... - */ - if (timeout == NULL) - err = sem_wait(&mqhp->mq_notfull); - else if (abs_rel == ABS_TIME) - err = sem_timedwait(&mqhp->mq_notfull, timeout); - else - err = sem_reltimedwait_np(&mqhp->mq_notfull, timeout); - } - if (err == -1) { - /* - * errno has been set to EAGAIN / EINTR / ETIMEDOUT - * by sem_*wait(), so we can just return. - */ - return (-1); - } - - /* - * By the time we're here, we know that we've got the capacity - * to add to the queue...now acquire the exclusive lock. - */ - (void) mutex_lock(&mqhp->mq_exclusive); - - /* - * Now determine if we want to kick the notification. POSIX - * requires that if a process has registered for notification, - * we must kick it when the queue makes an empty to non-empty - * transition, and there are no blocked receivers. Note that - * this mechanism does _not_ guarantee that the kicked process - * will be able to receive a message without blocking; - * another receiver could intervene in the meantime. Thus, - * the notification mechanism is inherently racy; all we can - * do is hope to minimize the window as much as possible. - * In general, we want to avoid kicking the notification when - * there are clearly receivers blocked. We'll determine if - * we want to kick the notification before the mq_putmsg(), - * but the actual signotify() won't be done until the message - * is on the queue. - */ - if (mqhp->mq_sigid.sn_pid != 0) { - int nmessages, nblocked; - - (void) sem_getvalue(&mqhp->mq_notempty, &nmessages); - (void) sem_getvalue(&mqhp->mq_rblocked, &nblocked); - - if (nmessages == 0 && nblocked == 0) - notify = 1; - } - - mq_putmsg(mqhp, msg_ptr, (ssize_t)msg_len, msg_prio); - (void) sem_post(&mqhp->mq_notempty); - - if (notify) { - /* notify and also delete the registration */ - (void) __signotify(SN_SEND, NULL, &mqhp->mq_sigid); - if (mqhp->mq_ntype == SIGEV_THREAD || - mqhp->mq_ntype == SIGEV_PORT) - (void) sem_post(&mqhp->mq_spawner); - mqhp->mq_ntype = 0; - mqhp->mq_des = 0; - } - - MQ_ASSERT_SEMVAL_LEQ(&mqhp->mq_notempty, ((int)mqhp->mq_maxmsg)); - (void) mutex_unlock(&mqhp->mq_exclusive); - - return (0); -} - -int -_mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, uint_t msg_prio) -{ - return (__mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, - NULL, ABS_TIME)); -} - -int -_mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, - uint_t msg_prio, const timespec_t *abs_timeout) -{ - return (__mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, - abs_timeout, ABS_TIME)); -} - -int -_mq_reltimedsend_np(mqd_t mqdes, const char *msg_ptr, size_t msg_len, - uint_t msg_prio, const timespec_t *rel_timeout) -{ - return (__mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, - rel_timeout, REL_TIME)); -} - -static void -decrement_rblocked(mqhdr_t *mqhp) -{ - int canstate; - - (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &canstate); - while (sem_wait(&mqhp->mq_rblocked) == -1) - continue; - (void) pthread_setcancelstate(canstate, NULL); -} - -static ssize_t -__mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, - uint_t *msg_prio, const timespec_t *timeout, int abs_rel) -{ - mqdes_t *mqdp = (mqdes_t *)mqdes; - mqhdr_t *mqhp; - ssize_t msg_size; - int err; - - /* - * sem_*wait() does cancellation, if called. - * pthread_testcancel() ensures that cancellation takes place if - * there is a cancellation pending when mq_*receive() is called. - */ - pthread_testcancel(); - - if (!mq_is_valid(mqdp) || (mqdp->mqd_flags & FREAD) == 0) { - errno = EBADF; - return (ssize_t)(-1); - } - - mqhp = mqdp->mqd_mq; - - if (msg_len < mqhp->mq_maxsz) { - errno = EMSGSIZE; - return (ssize_t)(-1); - } - - /* - * The semaphoring scheme for mq_[timed]receive is a little hairy - * thanks to POSIX.1b's arcane notification mechanism. First, - * we try to take the common case and do a sem_trywait(). - * If that doesn't work, and O_NONBLOCK hasn't been set, - * then note that we're going to sleep by incrementing the rblocked - * semaphore. We decrement that semaphore after waking up. - */ - if (sem_trywait(&mqhp->mq_notempty) == -1) { - if ((mqdp->mqd_mqdn->mqdn_flags & O_NONBLOCK) != 0) { - /* - * errno has been set to EAGAIN or EINTR by - * sem_trywait(), so we can just return. - */ - return (-1); - } - /* - * If we're here, then we're probably going to block... - * increment the rblocked semaphore. If we get - * cancelled, decrement_rblocked() will decrement it. - */ - (void) sem_post(&mqhp->mq_rblocked); - - pthread_cleanup_push(decrement_rblocked, mqhp); - if (timeout == NULL) - err = sem_wait(&mqhp->mq_notempty); - else if (abs_rel == ABS_TIME) - err = sem_timedwait(&mqhp->mq_notempty, timeout); - else - err = sem_reltimedwait_np(&mqhp->mq_notempty, timeout); - pthread_cleanup_pop(1); - - if (err == -1) { - /* - * We took a signal or timeout while waiting - * on mq_notempty... - */ - return (-1); - } - } - - (void) mutex_lock(&mqhp->mq_exclusive); - msg_size = mq_getmsg(mqhp, msg_ptr, msg_prio); - (void) sem_post(&mqhp->mq_notfull); - MQ_ASSERT_SEMVAL_LEQ(&mqhp->mq_notfull, ((int)mqhp->mq_maxmsg)); - (void) mutex_unlock(&mqhp->mq_exclusive); - - return (msg_size); -} - -ssize_t -_mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, uint_t *msg_prio) -{ - return (__mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, - NULL, ABS_TIME)); -} - -ssize_t -_mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, - uint_t *msg_prio, const timespec_t *abs_timeout) -{ - return (__mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, - abs_timeout, ABS_TIME)); -} - -ssize_t -_mq_reltimedreceive_np(mqd_t mqdes, char *msg_ptr, size_t msg_len, - uint_t *msg_prio, const timespec_t *rel_timeout) -{ - return (__mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, - rel_timeout, REL_TIME)); -} - -/* - * Only used below, in _mq_notify(). - * We already have a spawner thread. - * Verify that the attributes match; cancel it if necessary. - */ -static int -cancel_if_necessary(thread_communication_data_t *tcdp, - const struct sigevent *sigevp) -{ - int do_cancel = !_pthread_attr_equal(tcdp->tcd_attrp, - sigevp->sigev_notify_attributes); - - if (do_cancel) { - /* - * Attributes don't match, cancel the spawner thread. - */ - (void) pthread_cancel(tcdp->tcd_server_id); - } else { - /* - * Reuse the existing spawner thread with possibly - * changed notification function and value. - */ - tcdp->tcd_notif.sigev_notify = SIGEV_THREAD; - tcdp->tcd_notif.sigev_signo = 0; - tcdp->tcd_notif.sigev_value = sigevp->sigev_value; - tcdp->tcd_notif.sigev_notify_function = - sigevp->sigev_notify_function; - } - - return (do_cancel); -} - -int -_mq_notify(mqd_t mqdes, const struct sigevent *sigevp) -{ - mqdes_t *mqdp = (mqdes_t *)mqdes; - mqhdr_t *mqhp; - thread_communication_data_t *tcdp; - siginfo_t mq_siginfo; - struct sigevent sigevent; - struct stat64 statb; - port_notify_t *pn; - void *userval; - int ntype; - int port; - - if (!mq_is_valid(mqdp)) { - errno = EBADF; - return (-1); - } - - mqhp = mqdp->mqd_mq; - - (void) mutex_lock(&mqhp->mq_exclusive); - - if (sigevp == NULL) { /* remove notification */ - if (mqhp->mq_des == (uintptr_t)mqdp && - mqhp->mq_sigid.sn_pid == getpid()) { - /* notification is set for this descriptor, remove it */ - (void) __signotify(SN_CANCEL, NULL, &mqhp->mq_sigid); - if ((tcdp = mqdp->mqd_tcd) != NULL) { - (void) mutex_lock(&tcdp->tcd_lock); - if (tcdp->tcd_msg_enabled) { - /* cancel the spawner thread */ - tcdp = mqdp->mqd_tcd; - mqdp->mqd_tcd = NULL; - (void) pthread_cancel( - tcdp->tcd_server_id); - } - (void) mutex_unlock(&tcdp->tcd_lock); - } - mqhp->mq_ntype = 0; - mqhp->mq_des = 0; - } else { - /* notification is not set for this descriptor */ - errno = EBUSY; - goto bad; - } - } else { /* register notification with this process */ - switch (ntype = sigevp->sigev_notify) { - case SIGEV_THREAD: - userval = sigevp->sigev_value.sival_ptr; - port = -1; - break; - case SIGEV_PORT: - pn = sigevp->sigev_value.sival_ptr; - userval = pn->portnfy_user; - port = pn->portnfy_port; - if (fstat64(port, &statb) != 0 || - !S_ISPORT(statb.st_mode)) { - errno = EBADF; - goto bad; - } - (void) memset(&sigevent, 0, sizeof (sigevent)); - sigevent.sigev_notify = SIGEV_PORT; - sigevp = &sigevent; - break; - } - switch (ntype) { - case SIGEV_NONE: - mq_siginfo.si_signo = 0; - mq_siginfo.si_code = SI_MESGQ; - break; - case SIGEV_SIGNAL: - mq_siginfo.si_signo = sigevp->sigev_signo; - mq_siginfo.si_value = sigevp->sigev_value; - mq_siginfo.si_code = SI_MESGQ; - break; - case SIGEV_THREAD: - if ((tcdp = mqdp->mqd_tcd) != NULL && - cancel_if_necessary(tcdp, sigevp)) - mqdp->mqd_tcd = NULL; - /* FALLTHROUGH */ - case SIGEV_PORT: - if ((tcdp = mqdp->mqd_tcd) == NULL) { - /* we must create a spawner thread */ - tcdp = setup_sigev_handler(sigevp, MQ); - if (tcdp == NULL) { - errno = EBADF; - goto bad; - } - tcdp->tcd_msg_enabled = 0; - tcdp->tcd_msg_closing = 0; - tcdp->tcd_msg_avail = &mqhp->mq_spawner; - if (launch_spawner(tcdp) != 0) { - free_sigev_handler(tcdp); - goto bad; - } - mqdp->mqd_tcd = tcdp; - } - mq_siginfo.si_signo = 0; - mq_siginfo.si_code = SI_MESGQ; - break; - default: - errno = EINVAL; - goto bad; - } - - /* register notification */ - if (__signotify(SN_PROC, &mq_siginfo, &mqhp->mq_sigid) < 0) - goto bad; - mqhp->mq_ntype = ntype; - mqhp->mq_des = (uintptr_t)mqdp; - switch (ntype) { - case SIGEV_THREAD: - case SIGEV_PORT: - tcdp->tcd_port = port; - tcdp->tcd_msg_object = mqdp; - tcdp->tcd_msg_userval = userval; - (void) mutex_lock(&tcdp->tcd_lock); - tcdp->tcd_msg_enabled = ntype; - (void) mutex_unlock(&tcdp->tcd_lock); - (void) cond_broadcast(&tcdp->tcd_cv); - break; - } - } - - (void) mutex_unlock(&mqhp->mq_exclusive); - return (0); - -bad: - (void) mutex_unlock(&mqhp->mq_exclusive); - return (-1); -} - -int -_mq_setattr(mqd_t mqdes, const struct mq_attr *mqstat, struct mq_attr *omqstat) -{ - mqdes_t *mqdp = (mqdes_t *)mqdes; - mqhdr_t *mqhp; - uint_t flag = 0; - - if (!mq_is_valid(mqdp)) { - errno = EBADF; - return (-1); - } - - /* store current attributes */ - if (omqstat != NULL) { - int count; - - mqhp = mqdp->mqd_mq; - omqstat->mq_flags = mqdp->mqd_mqdn->mqdn_flags; - omqstat->mq_maxmsg = (long)mqhp->mq_maxmsg; - omqstat->mq_msgsize = (long)mqhp->mq_maxsz; - (void) sem_getvalue(&mqhp->mq_notempty, &count); - omqstat->mq_curmsgs = count; - } - - /* set description attributes */ - if ((mqstat->mq_flags & O_NONBLOCK) != 0) - flag = FNONBLOCK; - mqdp->mqd_mqdn->mqdn_flags = flag; - - return (0); -} - -int -_mq_getattr(mqd_t mqdes, struct mq_attr *mqstat) -{ - mqdes_t *mqdp = (mqdes_t *)mqdes; - mqhdr_t *mqhp; - int count; - - if (!mq_is_valid(mqdp)) { - errno = EBADF; - return (-1); - } - - mqhp = mqdp->mqd_mq; - - mqstat->mq_flags = mqdp->mqd_mqdn->mqdn_flags; - mqstat->mq_maxmsg = (long)mqhp->mq_maxmsg; - mqstat->mq_msgsize = (long)mqhp->mq_maxsz; - (void) sem_getvalue(&mqhp->mq_notempty, &count); - mqstat->mq_curmsgs = count; - return (0); -} diff --git a/usr/src/lib/librt/common/pos4.c b/usr/src/lib/librt/common/pos4.c deleted file mode 100644 index 3bc253960d..0000000000 --- a/usr/src/lib/librt/common/pos4.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "c_synonyms.h" -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include "mqlib.h" -#include "thread_pool.h" - -extern mutex_t semlock; -extern mutex_t md5_lock; - -extern void prefork1_tpool(void); -extern void postfork1_parent_tpool(void); -extern void postfork1_child_tpool(void); - -/* - * A spawner and its workers are gone. - * We are here to clean up the data structures and close the port. - */ -static void -tcd_teardown(thread_communication_data_t *tcdp) -{ - if (tcdp->tcd_poolp != NULL) - tpool_abandon(tcdp->tcd_poolp); - tcdp->tcd_poolp = NULL; - tcdp->tcd_server_id = 0; - free_sigev_handler(tcdp); -} - -static void -_rt_prepare_fork(void) -{ - thread_communication_data_t *tcdp; - mqdes_t *mqdp; - int timer; - - (void) mutex_lock(&sigev_aio_lock); - while (sigev_aio_busy) - (void) cond_wait(&sigev_aio_cv, &sigev_aio_lock); - (void) mutex_lock(&semlock); - (void) mutex_lock(&md5_lock); - if ((tcdp = sigev_aio_tcd) != NULL) - (void) mutex_lock(&tcdp->tcd_lock); - - (void) mutex_lock(&mq_list_lock); - for (mqdp = mq_list; mqdp; mqdp = mqdp->mqd_next) { - if ((tcdp = mqdp->mqd_tcd) != NULL) - (void) mutex_lock(&tcdp->tcd_lock); - } - - for (timer = 0; timer < timer_max; timer++) { - if ((tcdp = timer_tcd[timer]) != NULL) - (void) mutex_lock(&tcdp->tcd_lock); - } - (void) mutex_lock(&free_tcd_lock); - - prefork1_tpool(); -} - -static void -_rt_release_locks(void) -{ - thread_communication_data_t *tcdp; - mqdes_t *mqdp; - int timer; - - (void) mutex_unlock(&free_tcd_lock); - for (timer = 0; timer < timer_max; timer++) { - if ((tcdp = timer_tcd[timer]) != NULL) - (void) mutex_unlock(&tcdp->tcd_lock); - } - - for (mqdp = mq_list; mqdp; mqdp = mqdp->mqd_next) { - if ((tcdp = mqdp->mqd_tcd) != NULL) - (void) mutex_unlock(&tcdp->tcd_lock); - } - (void) mutex_unlock(&mq_list_lock); - - if ((tcdp = sigev_aio_tcd) != NULL) - (void) mutex_unlock(&tcdp->tcd_lock); - (void) mutex_unlock(&md5_lock); - (void) mutex_unlock(&semlock); - (void) mutex_unlock(&sigev_aio_lock); -} - -static void -_rt_parent_fork(void) -{ - postfork1_parent_tpool(); - _rt_release_locks(); -} - -static void -_rt_child_fork(void) -{ - mqdes_t *mqdp; - int timer; - - postfork1_child_tpool(); - _rt_release_locks(); - - /* - * All of the spawners and workers are gone; free their structures. - */ - - if (sigev_aio_tcd != NULL) { /* AIO */ - tcd_teardown(sigev_aio_tcd); - sigev_aio_tcd = NULL; - } - - for (mqdp = mq_list; mqdp; mqdp = mqdp->mqd_next) { /* MQ */ - if (mqdp->mqd_tcd != NULL) { - tcd_teardown(mqdp->mqd_tcd); - mqdp->mqd_tcd = NULL; - } - } - - for (timer = 0; timer < timer_max; timer++) { /* TIMER */ - if (timer_tcd[timer] != NULL) { - tcd_teardown(timer_tcd[timer]); - timer_tcd[timer] = NULL; - } - } -} - -#pragma init(_rt_init) -static void -_rt_init(void) -{ - (void) pthread_atfork(_rt_prepare_fork, - _rt_parent_fork, _rt_child_fork); -} diff --git a/usr/src/lib/librt/common/pos4.h b/usr/src/lib/librt/common/pos4.h deleted file mode 100644 index 8645fd27d9..0000000000 --- a/usr/src/lib/librt/common/pos4.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * These are largely extern definitions for functions that librt - * finds elsewhere (in libaio or libc). - */ - -#ifndef _POS4_H -#define _POS4_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <aio.h> -#include <time.h> -#include <signal.h> -#include <siginfo.h> -#include <unistd.h> -#include <semaphore.h> - -extern int __aio_cancel(int, aiocb_t *); -extern int __aio_cancel64(int, aiocb64_t *); -extern int __aio_error(const aiocb_t *); -extern int __aio_error64(const aiocb64_t *); -extern int __aio_fsync(int, aiocb_t *); -extern int __aio_fsync64(int, aiocb64_t *); -extern int __aio_read(aiocb_t *); -extern int __aio_read64(aiocb64_t *); -extern ssize_t __aio_return(aiocb_t *); -extern ssize_t __aio_return64(aiocb64_t *); -extern int __aio_suspend(void **, int, const timespec_t *, int); -extern int __aio_write(aiocb_t *); -extern int __aio_write64(aiocb64_t *); -extern int __lio_listio(int, - aiocb_t *_RESTRICT_KYWD const *_RESTRICT_KYWD list, - int, struct sigevent *_RESTRICT_KYWD); -extern int __lio_listio64(int, - aiocb64_t *_RESTRICT_KYWD const *_RESTRICT_KYWD list, - int, struct sigevent *_RESTRICT_KYWD); -extern int __aio_waitn(void **list, uint_t, uint_t *, const timespec_t *); - -extern int __clock_getres(clockid_t, timespec_t *); -extern int __clock_gettime(clockid_t, timespec_t *); -extern int __clock_settime(clockid_t, const timespec_t *); -extern int __timer_create(clockid_t, struct sigevent *, timer_t *); -extern int __timer_delete(timer_t); -extern int __timer_getoverrun(timer_t); -extern int __timer_gettime(timer_t, itimerspec_t *); -extern int __timer_settime(timer_t, int, const itimerspec_t *, itimerspec_t *); - -extern int __clock_nanosleep(clockid_t, int, const timespec_t *, timespec_t *); -extern int __nanosleep(const timespec_t *, timespec_t *); - -extern int __sigtimedwait(const sigset_t *, siginfo_t *, - const timespec_t *); -extern int __sigqueue(pid_t pid, int signo, - /* const union sigval */ void *value, int si_code); -extern void _thr_yield(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _POS4_H */ diff --git a/usr/src/lib/librt/common/pos4obj.c b/usr/src/lib/librt/common/pos4obj.c deleted file mode 100644 index 7c344d3a43..0000000000 --- a/usr/src/lib/librt/common/pos4obj.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "c_synonyms.h" -#include <sys/types.h> -#include <errno.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdlib.h> -#include <limits.h> -#include <pthread.h> -#include <thread.h> -#include <string.h> -#include <dirent.h> -#include <stdio.h> -#include <dlfcn.h> -#include <md5.h> -#include "pos4.h" -#include "pos4obj.h" - -#define HASHSTRLEN 32 - -static char *__pos4obj_name(const char *, const char *); -static void __pos4obj_md5toa(unsigned char *, unsigned char *); -static void __pos4obj_clean(char *); - -static char objroot[] = "/tmp/"; -static long int name_max = 0; - -int -__open_nc(const char *path, int oflag, mode_t mode) -{ - int canstate, val; - struct stat64 statbuf; - - /* - * Ensure path is not a symlink to somewhere else. This provides - * a modest amount of protection against easy security attacks. - */ - if (lstat64(path, &statbuf) == 0) { - if (S_ISLNK(statbuf.st_mode)) { - errno = EINVAL; - return (-1); - } - } - - (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &canstate); - val = open64(path, oflag, mode); - (void) pthread_setcancelstate(canstate, &canstate); - - return (val); -} - -int -__close_nc(int fildes) -{ - int canstate, val; - - (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &canstate); - val = close(fildes); - (void) pthread_setcancelstate(canstate, &canstate); - - return (val); -} - -/* - * This is to avoid loading libmd.so.1 unless we absolutely have to. - */ -typedef void (*md5_calc_t)(unsigned char *, unsigned char *, unsigned int); -static void *md5_handle = NULL; -static md5_calc_t real_md5_calc = NULL; -mutex_t md5_lock = DEFAULTMUTEX; - -static void -load_md5_calc(void) -{ - /* - * _sigoff() and _sigon() are consolidation-private interfaces - * in libc that defer and then reenable signals. - */ - extern void _sigoff(void); - extern void _sigon(void); - - _sigoff(); - (void) mutex_lock(&md5_lock); - if (real_md5_calc == NULL) { - md5_handle = dlopen("libmd.so.1", RTLD_LAZY); - if (md5_handle == NULL) - real_md5_calc = (md5_calc_t)(-1); - else { - real_md5_calc = - (md5_calc_t)dlsym(md5_handle, "md5_calc"); - if (real_md5_calc == NULL) { - (void) dlclose(md5_handle); - md5_handle = NULL; - real_md5_calc = (md5_calc_t)(-1); - } - } - } - (void) mutex_unlock(&md5_lock); - _sigon(); -} - -/* - * If librt.so.1 is dlclose()d, take libmd.so.1 down with us. - */ -#pragma fini(unload_md5_calc) -static void -unload_md5_calc(void) -{ - if (md5_handle != NULL) - (void) dlclose(md5_handle); - md5_handle = NULL; - real_md5_calc = NULL; -} - -static char * -__pos4obj_name(const char *path, const char *type) -{ - int shortpath = 1; - int olderrno; - size_t len; - char *dfile; - unsigned char hashbuf[HASHSTRLEN + 1]; - unsigned char md5_digest[MD5_DIGEST_LENGTH]; - - /* - * If the path is path_max - strlen(type) characters or less, - * the name of the file to use will be the path prefixed by - * the type. - * - * In the special case where the path is longer than - * path_max - strlen(type) characters, we create a string based on the - * MD5 hash of the path. We prefix that string with a '.' to - * make it obscure, and create a directory in objroot with - * that name. In that directory, we create a directory named - * after the type of object requested. Inside the type - * directory, the filename will be the path of the object. This - * prevents collisions in all namespaces. - * - * Example: - * Let objroot = "/tmp/", path = "/<longpath>", and type = ".MQD" - * Let the MD5 hash of "<longpath>" = "<hash>" - * - * The desired file is /tmp/.<hash>/.MQD/<longpath> - */ - - /* - * Do not include the leading '/' in the path length. - * Assumes __pos4obj_check(path) has already been called. - */ - if ((strlen(path) - 1) > (name_max - strlen(type))) - shortpath = 0; - - if (shortpath) { - /* - * strlen(path) includes leading slash as space for NUL. - */ - len = strlen(objroot) + strlen(type) + strlen(path); - } else { - /* - * Long path name. Add 3 for extra '/', '.' and '\0' - */ - len = strlen(objroot) + HASHSTRLEN + strlen(type) + - strlen(path) + 3; - } - - if ((dfile = malloc(len)) == NULL) - return (NULL); - - (void) memset(dfile, 0, len); - (void) strcpy(dfile, objroot); - - if (shortpath) { - (void) strcat(dfile, type); - (void) strcat(dfile, path + 1); - return (dfile); - } - - /* - * If we can successfully load it, call md5_calc(). - * Otherwise, (this "can't happen") return NULL. - */ - if (real_md5_calc == NULL) - load_md5_calc(); - if (real_md5_calc == (md5_calc_t)(-1)) { - free(dfile); - return (NULL); - } - - real_md5_calc(md5_digest, (unsigned char *)path + 1, strlen(path + 1)); - __pos4obj_md5toa(hashbuf, md5_digest); - (void) strcat(dfile, "."); - (void) strcat(dfile, (const char *)hashbuf); - - /* - * Errno must be preserved across the following calls to - * mkdir. This needs to be done to prevent incorrect error - * reporting in certain cases. When librt attempts to open a - * non-existent object without the O_CREAT flag, it will - * always create a lock file first. The lock file is created - * and then the open is attempted, but fails with ENOENT. The - * lock file is then destroyed. In the following code path, we - * are finding the absolute path to the lock file after - * already having attempted the open (which set errno to - * ENOENT). The following calls to mkdir will return -1 and - * set errno to EEXIST, since the hash and type directories - * were created when the lock file was created. The correct - * errno is the ENOENT from the attempted open of the desired - * object. - */ - olderrno = errno; - - /* - * Create hash directory. Use 777 permissions so everyone can use it. - */ - if (mkdir(dfile, S_IRWXU|S_IRWXG|S_IRWXO) == 0) { - if (chmod(dfile, S_IRWXU|S_IRWXG|S_IRWXO) == -1) { - free(dfile); - return (NULL); - } - } else { - if (errno != EEXIST) { - free(dfile); - return (NULL); - } - } - - (void) strcat(dfile, "/"); - (void) strcat(dfile, type); - - /* - * Create directory for requested type. Use 777 perms so everyone - * can use it. - */ - if (mkdir(dfile, S_IRWXU|S_IRWXG|S_IRWXO) == 0) { - if (chmod(dfile, S_IRWXU|S_IRWXG|S_IRWXO) == -1) { - free(dfile); - return (NULL); - } - } else { - if (errno != EEXIST) { - free(dfile); - return (NULL); - } - } - - errno = olderrno; - (void) strcat(dfile, path); - return (dfile); -} - -/* - * Takes a 128-bit MD5 digest and transforms to a sequence of 32 ASCII - * characters. Output is the hexadecimal representation of the digest. - * - * The output buffer must be at least HASHSTRLEN + 1 characters - * long. HASHSTRLEN is the size of the MD5 digest (128 bits) - * divided by the number of bits used per char of output (4). The - * extra character at the end is for the NUL terminating character. - */ - -static void -__pos4obj_md5toa(unsigned char *dest, unsigned char *src) -{ - int i; - uint32_t *p; - - /* LINTED pointer cast may result in improper alignment */ - p = (uint32_t *)src; - - for (i = 0; i < (MD5_DIGEST_LENGTH / 4); i++) - (void) snprintf((char *)dest + (i * 8), 9, "%.8x", *p++); - - dest[HASHSTRLEN] = '\0'; -} - -/* - * This open function assume that there is no simultaneous - * open/unlink operation is going on. The caller is supposed - * to ensure that both open in O_CREAT mode happen atomically. - * It returns the crflag as 1 if file is created else 0. - */ -int -__pos4obj_open(const char *name, char *type, int oflag, - mode_t mode, int *crflag) -{ - int fd; - char *dfile; - - errno = 0; - *crflag = 0; - - if ((dfile = __pos4obj_name(name, type)) == NULL) { - return (-1); - } - - if (!(oflag & O_CREAT)) { - if ((fd = __open_nc(dfile, oflag, mode)) == -1) - __pos4obj_clean(dfile); - - free(dfile); - return (fd); - } - - /* - * We need to make sure that crflag is set iff we actually create - * the file. We do this by or'ing in O_EXCL, and attempting an - * open. If that fails with an EEXIST, and O_EXCL wasn't specified - * by the caller, then the file seems to exist; we'll try an - * open with O_CREAT cleared. If that succeeds, then the file - * did indeed exist. If that fails with an ENOENT, however, the - * file was removed between the opens; we need to take another - * lap. - */ - for (;;) { - if ((fd = __open_nc(dfile, (oflag | O_EXCL), mode)) == -1) { - if (errno == EEXIST && !(oflag & O_EXCL)) { - fd = __open_nc(dfile, oflag & ~O_CREAT, mode); - - if (fd == -1 && errno == ENOENT) - continue; - break; - } - } else { - *crflag = 1; - } - break; - } - - free(dfile); - return (fd); -} - - -int -__pos4obj_unlink(const char *name, const char *type) -{ - int err; - char *dfile; - - if ((dfile = __pos4obj_name(name, type)) == NULL) { - return (-1); - } - - err = unlink(dfile); - - __pos4obj_clean(dfile); - - free(dfile); - - return (err); -} - -/* - * This function opens the lock file for each named object - * the presence of this file in the file system is the lock - */ -int -__pos4obj_lock(const char *name, const char *ltype) -{ - char *dfile; - int fd; - int limit = 64; - - if ((dfile = __pos4obj_name(name, ltype)) == NULL) { - return (-1); - } - - while (limit-- > 0) { - if ((fd = __open_nc(dfile, O_RDWR | O_CREAT | O_EXCL, 0666)) - < 0) { - if (errno != EEXIST) - break; - (void) sleep(1); - continue; - } - - (void) __close_nc(fd); - free(dfile); - return (1); - } - - free(dfile); - return (-1); -} - -/* - * Unlocks the file by unlinking it from the filesystem - */ -int -__pos4obj_unlock(const char *path, const char *type) -{ - return (__pos4obj_unlink(path, type)); -} - -/* - * Removes unused hash and type directories that may exist in specified path. - */ -static void -__pos4obj_clean(char *path) -{ - char *p; - int olderrno; - - /* - * path is either - * 1) /<objroot>/<type><path> or - * 2) /<objroot>/.<hash>/<type>/<path> - * - * In case 1, there is nothing to clean. - * - * Detect case 2 by looking for a '/' after /objroot/ and - * remove the two trailing directories, if empty. - */ - if (strchr(path + strlen(objroot), '/') == NULL) - return; - - /* - * Preserve errno across calls to rmdir. See block comment in - * __pos4obj_name() for explanation. - */ - olderrno = errno; - - if ((p = strrchr(path, '/')) == NULL) - return; - *p = '\0'; - - (void) rmdir(path); - - if ((p = strrchr(path, '/')) == NULL) - return; - *p = '\0'; - - (void) rmdir(path); - - errno = olderrno; -} - - -/* - * Check that path starts with a /, does not contain a / within it - * and is not longer than PATH_MAX or NAME_MAX - */ -int -__pos4obj_check(const char *path) -{ - long int i; - - /* - * This assumes that __pos4obj_check() is called before - * any of the other functions in this file - */ - if (name_max == 0 || name_max == -1) { - name_max = pathconf(objroot, _PC_NAME_MAX); - if (name_max == -1) - return (-1); - } - - if (*path++ != '/') { - errno = EINVAL; - return (-1); - } - - for (i = 0; *path != '\0'; i++) { - if (*path++ == '/') { - errno = EINVAL; - return (-1); - } - } - - if (i > PATH_MAX || i > name_max) { - errno = ENAMETOOLONG; - return (-1); - } - - return (0); -} diff --git a/usr/src/lib/librt/common/pos4obj.h b/usr/src/lib/librt/common/pos4obj.h deleted file mode 100644 index 609a43f64c..0000000000 --- a/usr/src/lib/librt/common/pos4obj.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _POS4OBJ_H -#define _POS4OBJ_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * pos4obj.h - Header file for POSIX.4 related object names - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* flags used to indicate current state of open */ -#define DFILE_CREATE 0x01 -#define DFILE_OPEN 0x02 -#define ALLOC_MEM 0x04 -#define DFILE_MMAP 0x08 -#define PFILE_CREATE 0x10 -#define NFILE_CREATE 0x20 -#define MQDNP_MMAP 0x40 - -/* semaphore object types - used in constructing file name */ -#define SEM_DATA_TYPE ".SEMD" -#define SEM_LOCK_TYPE ".SEML" - -/* message queue object types - used in constructing file name */ -#define MQ_DATA_TYPE ".MQD" -#define MQ_PERM_TYPE ".MQP" -#define MQ_DSCN_TYPE ".MQN" -#define MQ_LOCK_TYPE ".MQL" - -/* shared memory object types - used in constructing file name */ -#define SHM_DATA_TYPE ".SHMD" -#define SHM_LOCK_TYPE ".SHML" - -/* functions defined related to object names in POSIX.4 */ -extern int __pos4obj_lock(const char *, const char *); -extern int __pos4obj_unlock(const char *, const char *); -extern int __pos4obj_unlink(const char *, const char *); -extern int __pos4obj_open(const char *, char *, int, mode_t, int *); -extern int __pos4obj_check(const char *); - -/* non-cancelable file operations */ -int __open_nc(const char *, int, mode_t); -int __close_nc(int); - -#ifdef __cplusplus -} -#endif - -#endif /* _POS4OBJ_H */ diff --git a/usr/src/lib/librt/common/sched.c b/usr/src/lib/librt/common/sched.c deleted file mode 100644 index 1ca2f9801e..0000000000 --- a/usr/src/lib/librt/common/sched.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "c_synonyms.h" -#include <sys/types.h> -#include <sched.h> -#include <errno.h> -#include <limits.h> -#include <unistd.h> -#include <sys/priocntl.h> -#include <sys/rtpriocntl.h> -#include <sys/tspriocntl.h> -#include <sys/rt.h> -#include <sys/ts.h> -#include <thread.h> -#include <string.h> -#include <stdlib.h> -#include "pos4.h" - -/* - * The following variables are used for caching information - * for priocntl scheduling classes. - */ -static struct pcclass { - short pcc_state; - pri_t pcc_primin; - pri_t pcc_primax; - pcinfo_t pcc_info; -} rt_class, ts_class, sys_class, ia_class; - -static rtdpent_t *rt_dptbl; /* RT class parameter table */ - -typedef struct { /* type definition for generic class-specific parameters */ - int pc_clparms[PC_CLINFOSZ]; -} pc_clparms_t; - -static int map_gp_to_rtpri(pri_t); - -/* - * cache priocntl information on scheduling classes by policy - */ -static int -get_info_by_policy(int policy) -{ - char *pccname; - struct pcclass *pccp; - - if (policy < 0) { - errno = EINVAL; - return (-1); - } - - switch (policy) { - case SCHED_FIFO: - case SCHED_RR: - pccp = &rt_class; - pccname = "RT"; - break; - case SCHED_OTHER: - pccp = &ts_class; - pccname = "TS"; - break; - case SCHED_SYS: - pccp = &sys_class; - pccname = "sys"; - break; - case SCHED_IA: - pccp = &ia_class; - pccname = "IA"; - break; - default: - return (policy); - } - if (pccp->pcc_state != 0) { - if (pccp->pcc_state < 0) - errno = ENOSYS; - return (pccp->pcc_state); - } - - /* get class's info */ - (void) strcpy(pccp->pcc_info.pc_clname, pccname); - if (policy == SCHED_SYS) - pccp->pcc_info.pc_cid = 0; - else if (priocntl(P_PID, 0, PC_GETCID, (caddr_t)&(pccp->pcc_info)) < 0) - return (-1); - - if (policy == SCHED_FIFO || policy == SCHED_RR) { - pcadmin_t pcadmin; - rtadmin_t rtadmin; - size_t rtdpsize; - - /* get RT class dispatch table in rt_dptbl */ - pcadmin.pc_cid = rt_class.pcc_info.pc_cid; - pcadmin.pc_cladmin = (caddr_t)&rtadmin; - rtadmin.rt_cmd = RT_GETDPSIZE; - if (priocntl(P_PID, 0, PC_ADMIN, (caddr_t)&pcadmin) < 0) - return (-1); - rtdpsize = (size_t)(rtadmin.rt_ndpents * sizeof (rtdpent_t)); - if (rt_dptbl == NULL && - (rt_dptbl = (rtdpent_t *)malloc(rtdpsize)) == NULL) { - errno = EAGAIN; - return (-1); - } - rtadmin.rt_dpents = rt_dptbl; - rtadmin.rt_cmd = RT_GETDPTBL; - if (priocntl(P_PID, 0, PC_ADMIN, (caddr_t)&pcadmin) < 0) - return (-1); - pccp->pcc_primin = 0; - pccp->pcc_primax = ((rtinfo_t *)rt_class.pcc_info.pc_clinfo)-> - rt_maxpri; - } else if (policy == SCHED_OTHER) { - pri_t prio; - - prio = ((tsinfo_t *)ts_class.pcc_info.pc_clinfo)->ts_maxupri/3; - pccp->pcc_primin = -prio; - pccp->pcc_primax = prio; - } else { - /* non-RT scheduling class */ - pcpri_t pcpri; - - /* need RT class info before we can translate priorities */ - if (get_info_by_policy(SCHED_FIFO) < 0) - return (-1); - /* - * get class's global priority's min, max, and - * translate them into RT priority level (index) via rt_dptbl. - */ - pcpri.pc_cid = pccp->pcc_info.pc_cid; - if (priocntl(0, 0, PC_GETPRIRANGE, (caddr_t)&pcpri) < 0) - return (-1); - pccp->pcc_primax = map_gp_to_rtpri(pcpri.pc_clpmax); - pccp->pcc_primin = map_gp_to_rtpri(pcpri.pc_clpmin); - } - - pccp->pcc_state = 1; - return (1); -} - -/* - * Translate global scheduling priority to RT class's user priority. - * Use the gp values in the rt_dptbl to do a reverse mapping - * of a given gpri value relative to the index range of rt_dptbl. - */ -static int -map_gp_to_rtpri(pri_t gpri) -{ - rtdpent_t *rtdp; - pri_t pri; - - if (gpri <= rt_dptbl[rt_class.pcc_primin].rt_globpri) { - pri = gpri - rt_dptbl[rt_class.pcc_primin].rt_globpri + \ - rt_class.pcc_primin; - } else if (gpri >= rt_dptbl[rt_class.pcc_primax].rt_globpri) { - pri = gpri - rt_dptbl[rt_class.pcc_primax].rt_globpri + \ - rt_class.pcc_primax; - } else { - pri = rt_class.pcc_primin + 1; - for (rtdp = rt_dptbl+1; rtdp->rt_globpri < gpri; ++rtdp, ++pri) - ; - if (rtdp->rt_globpri > gpri) - --pri; - } - - return (pri); -} - -static int -get_info_by_class(id_t classid) -{ - pcinfo_t pcinfo; - - /* determine if we already know this classid */ - if (rt_class.pcc_state > 0 && rt_class.pcc_info.pc_cid == classid) - return (1); - if (ts_class.pcc_state > 0 && ts_class.pcc_info.pc_cid == classid) - return (1); - if (sys_class.pcc_state > 0 && sys_class.pcc_info.pc_cid == classid) - return (1); - if (ia_class.pcc_state > 0 && ia_class.pcc_info.pc_cid == classid) - return (1); - - pcinfo.pc_cid = classid; - if (priocntl(0, 0, PC_GETCLINFO, (caddr_t)&pcinfo) < 0) { - if (classid == 0) /* no kernel info for sys class */ - return (get_info_by_policy(SCHED_SYS)); - return (-1); - } - - if (rt_class.pcc_state == 0 && strcmp(pcinfo.pc_clname, "RT") == 0) - return (get_info_by_policy(SCHED_FIFO)); - if (ts_class.pcc_state == 0 && strcmp(pcinfo.pc_clname, "TS") == 0) - return (get_info_by_policy(SCHED_OTHER)); - if (ia_class.pcc_state == 0 && strcmp(pcinfo.pc_clname, "IA") == 0) - return (get_info_by_policy(SCHED_IA)); - - return (1); -} - -int -sched_setparam(pid_t pid, const struct sched_param *param) -{ - pri_t prio = param->sched_priority; - pcparms_t pcparm; - tsparms_t *tsp; - tsinfo_t *tsi; - int scale; - - if (pid < 0) { - errno = ESRCH; - return (-1); - } - if (pid == 0) - pid = P_MYID; - - /* get process's current scheduling policy */ - pcparm.pc_cid = PC_CLNULL; - if (priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcparm) == -1) - return (-1); - if (get_info_by_class(pcparm.pc_cid) < 0) - return (-1); - - if (pcparm.pc_cid == rt_class.pcc_info.pc_cid) { - /* SCHED_FIFO or SCHED_RR policy */ - if (prio < rt_class.pcc_primin || prio > rt_class.pcc_primax) { - errno = EINVAL; - return (-1); - } - ((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs = RT_NOCHANGE; - ((rtparms_t *)pcparm.pc_clparms)->rt_pri = prio; - } else if (pcparm.pc_cid == ts_class.pcc_info.pc_cid) { - /* SCHED_OTHER policy */ - tsi = (tsinfo_t *)ts_class.pcc_info.pc_clinfo; - scale = tsi->ts_maxupri; - tsp = (tsparms_t *)pcparm.pc_clparms; - tsp->ts_uprilim = tsp->ts_upri = -(scale * prio) / 20; - } else { - /* - * policy is not defined by POSIX.4. - * just pass parameter data through to priocntl. - * param should contain an image of class-specific parameters - * (after the sched_priority member). - */ - *((pc_clparms_t *)pcparm.pc_clparms) = - *((pc_clparms_t *)(&(param->sched_priority)+1)); - } - - return ((int)priocntl(P_PID, pid, PC_SETPARMS, (caddr_t)&pcparm)); -} - -int -sched_getparam(pid_t pid, struct sched_param *param) -{ - pcparms_t pcparm; - pri_t prio; - int scale; - tsinfo_t *tsi; - - if (pid < 0) { - errno = ESRCH; - return (-1); - } - if (pid == 0) - pid = P_MYID; - - pcparm.pc_cid = PC_CLNULL; - if (priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcparm) == -1) - return (-1); - if (get_info_by_class(pcparm.pc_cid) < 0) - return (-1); - - if (pcparm.pc_cid == rt_class.pcc_info.pc_cid) { - param->sched_priority = - ((rtparms_t *)pcparm.pc_clparms)->rt_pri; - } else if (pcparm.pc_cid == ts_class.pcc_info.pc_cid) { - param->sched_nicelim = - ((tsparms_t *)pcparm.pc_clparms)->ts_uprilim; - prio = param->sched_nice = - ((tsparms_t *)pcparm.pc_clparms)->ts_upri; - tsi = (tsinfo_t *)ts_class.pcc_info.pc_clinfo; - scale = tsi->ts_maxupri; - if (scale == 0) - param->sched_priority = 0; - else - param->sched_priority = -(prio * 20) / scale; - } else { - /* - * policy is not defined by POSIX.4 - * just return a copy of pcparams_t image in param. - */ - *((pc_clparms_t *)(&(param->sched_priority)+1)) = - *((pc_clparms_t *)pcparm.pc_clparms); - param->sched_priority = - sched_get_priority_min((int)(pcparm.pc_cid + _SCHED_NEXT)); - } - - return (0); -} - -int -sched_setscheduler(pid_t pid, int policy, const struct sched_param *param) -{ - pri_t prio = param->sched_priority; - pcparms_t pcparm; - int oldpolicy; - tsinfo_t *tsi; - tsparms_t *tsp; - int scale; - - if ((oldpolicy = sched_getscheduler(pid)) < 0) - return (-1); - - if (pid == 0) - pid = P_MYID; - - if (get_info_by_policy(policy) < 0) { - errno = EINVAL; - return (-1); - } - - switch (policy) { - case SCHED_FIFO: - case SCHED_RR: - if (prio < rt_class.pcc_primin || prio > rt_class.pcc_primax) { - errno = EINVAL; - return (-1); - } - pcparm.pc_cid = rt_class.pcc_info.pc_cid; - ((rtparms_t *)pcparm.pc_clparms)->rt_pri = prio; - ((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs = - (policy == SCHED_RR ? RT_TQDEF : RT_TQINF); - break; - - case SCHED_OTHER: - pcparm.pc_cid = ts_class.pcc_info.pc_cid; - tsi = (tsinfo_t *)ts_class.pcc_info.pc_clinfo; - scale = tsi->ts_maxupri; - tsp = (tsparms_t *)pcparm.pc_clparms; - tsp->ts_uprilim = tsp->ts_upri = -(scale * prio) / 20; - break; - - default: - switch (policy) { - case SCHED_SYS: - pcparm.pc_cid = sys_class.pcc_info.pc_cid; - break; - case SCHED_IA: - pcparm.pc_cid = ia_class.pcc_info.pc_cid; - break; - default: - pcparm.pc_cid = policy - _SCHED_NEXT; - break; - } - /* - * policy is not defined by POSIX.4. - * just pass parameter data through to priocntl. - * param should contain an image of class-specific parameters - * (after the sched_priority member). - */ - *((pc_clparms_t *)pcparm.pc_clparms) = - *((pc_clparms_t *)&(param->sched_priority)+1); - } - - /* setting scheduling policy & parameters for the process */ - if (priocntl(P_PID, pid, PC_SETPARMS, (caddr_t)&pcparm) == -1) - return (-1); - - return (oldpolicy); -} - -int -sched_getscheduler(pid_t pid) -{ - pcparms_t pcparm; - int policy; - - if (pid < 0) { - errno = ESRCH; - return (-1); - } - if (pid == 0) - pid = P_MYID; - - /* get scheduling policy & parameters for the process */ - pcparm.pc_cid = PC_CLNULL; - if (priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcparm) == -1) - return (-1); - if (get_info_by_class(pcparm.pc_cid) < 0) - return (-1); - - if (pcparm.pc_cid == rt_class.pcc_info.pc_cid) - policy = ((((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs == - RT_TQINF ? SCHED_FIFO : SCHED_RR)); - else if (pcparm.pc_cid == ts_class.pcc_info.pc_cid) - policy = SCHED_OTHER; - else if (pcparm.pc_cid == sys_class.pcc_info.pc_cid) - policy = SCHED_SYS; - else if (pcparm.pc_cid == ia_class.pcc_info.pc_cid) - policy = SCHED_IA; - else { - /* - * policy is not defined by POSIX.4 - * return a unique dot4 policy id. - */ - policy = (int)(_SCHED_NEXT + pcparm.pc_cid); - } - - return (policy); -} - -int -sched_yield(void) -{ - _thr_yield(); - return (0); -} - -int -sched_get_priority_max(int policy) -{ - pcpri_t pcpri; - - if (get_info_by_policy(policy) < 0) - return (-1); - - if (policy == SCHED_FIFO || policy == SCHED_RR) - return (rt_class.pcc_primax); - else if (policy == SCHED_OTHER) - return (ts_class.pcc_primax); - else if (policy == SCHED_SYS) - return (sys_class.pcc_primax); - else if (policy == SCHED_IA) - return (ia_class.pcc_primax); - else { /* policy not in POSIX.4 */ - pcpri.pc_cid = policy - _SCHED_NEXT; - if (priocntl(0, 0, PC_GETPRIRANGE, (caddr_t)&pcpri) == 0) - return (map_gp_to_rtpri(pcpri.pc_clpmax)); - } - - errno = EINVAL; - return (-1); -} - -int -sched_get_priority_min(int policy) -{ - pcpri_t pcpri; - - if (get_info_by_policy(policy) < 0) - return (-1); - - if (policy == SCHED_FIFO || policy == SCHED_RR) - return (rt_class.pcc_primin); - else if (policy == SCHED_OTHER) - return (ts_class.pcc_primin); - else if (policy == SCHED_SYS) - return (sys_class.pcc_primin); - else if (policy == SCHED_IA) - return (ia_class.pcc_primin); - else { /* policy not in POSIX.4 */ - pcpri.pc_cid = policy - _SCHED_NEXT; - if (priocntl(0, 0, PC_GETPRIRANGE, (caddr_t)&pcpri) == 0) - return (map_gp_to_rtpri(pcpri.pc_clpmin)); - } - - errno = EINVAL; - return (-1); -} - -int -sched_rr_get_interval(pid_t pid, timespec_t *interval) -{ - pcparms_t pcparm; - - if (pid < 0) { - errno = ESRCH; - return (-1); - } - if (pid == 0) - pid = P_MYID; - - if (get_info_by_policy(SCHED_RR) < 0) - return (-1); - - pcparm.pc_cid = PC_CLNULL; - if (priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcparm) == -1) - return (-1); - - if (pcparm.pc_cid == rt_class.pcc_info.pc_cid && - (((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs != RT_TQINF)) { - /* SCHED_RR */ - interval->tv_sec = ((rtparms_t *)pcparm.pc_clparms)->rt_tqsecs; - interval->tv_nsec = - ((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs; - return (0); - } - - errno = EINVAL; - return (-1); -} diff --git a/usr/src/lib/librt/common/sem.c b/usr/src/lib/librt/common/sem.c deleted file mode 100644 index 89f2e36991..0000000000 --- a/usr/src/lib/librt/common/sem.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#pragma weak sem_open = _sem_open -#pragma weak sem_close = _sem_close -#pragma weak sem_unlink = _sem_unlink -#pragma weak sem_init = _sem_init -#pragma weak sem_destroy = _sem_destroy -#pragma weak sem_wait = _sem_wait -#pragma weak sem_timedwait = _sem_timedwait -#pragma weak sem_reltimedwait_np = _sem_reltimedwait_np -#pragma weak sem_trywait = _sem_trywait -#pragma weak sem_post = _sem_post -#pragma weak sem_getvalue = _sem_getvalue - -#include "c_synonyms.h" -#include <sys/types.h> -#include <semaphore.h> -#include <synch.h> -#include <errno.h> -#include <stdarg.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <unistd.h> -#include <thread.h> -#include "pos4obj.h" -#include "pos4.h" - -typedef struct semaddr { - struct semaddr *sad_next; /* next in the link */ - char sad_name[PATH_MAX + 1]; /* name of sem object */ - sem_t *sad_addr; /* mmapped address of semaphore */ - ino64_t sad_inode; /* inode # of the mmapped file */ -} semaddr_t; - -static long semvaluemax = 0; -static semaddr_t *semheadp = NULL; -mutex_t semlock = DEFAULTMUTEX; - -sem_t * -_sem_open(const char *path, int oflag, /* mode_t mode, int value */ ...) -{ - va_list ap; - mode_t crmode = 0; - sem_t *sem = NULL; - struct stat64 statbuf; - semaddr_t *next = NULL; - int fd = 0; - int error = 0; - int cr_flag = 0; - uint_t value = 0; - - if (__pos4obj_check(path) == -1) - return (SEM_FAILED); - - /* acquire semaphore lock to have atomic operation */ - if (__pos4obj_lock(path, SEM_LOCK_TYPE) < 0) - return (SEM_FAILED); - - /* modify oflag to have RDWR and filter CREATE mode only */ - oflag = (oflag & (O_CREAT|O_EXCL)) | (O_RDWR); - if (oflag & O_CREAT) { - if (semvaluemax == 0 && - (semvaluemax = _sysconf(_SC_SEM_VALUE_MAX)) <= 0) - semvaluemax = -1; - va_start(ap, oflag); - crmode = va_arg(ap, mode_t); - value = va_arg(ap, uint_t); - va_end(ap); - /* check value < the max for a named semaphore */ - if (semvaluemax < 0 || - (ulong_t)value > (ulong_t)semvaluemax) { - errno = EINVAL; - goto out; - } - } - - errno = 0; - - if ((fd = __pos4obj_open(path, SEM_DATA_TYPE, - oflag, crmode, &cr_flag)) < 0) - goto out; - - if (cr_flag) - cr_flag = DFILE_CREATE | DFILE_OPEN; - else - cr_flag = DFILE_OPEN; - - /* find out inode # for the opened file */ - if (fstat64(fd, &statbuf) < 0) - goto out; - - /* if created, acquire total_size in the file */ - if ((cr_flag & DFILE_CREATE) != 0) { - if (ftruncate64(fd, (off64_t)sizeof (sem_t)) < 0) - goto out; - - } else { - (void) mutex_lock(&semlock); - - /* - * if this semaphore has already been opened, inode - * will indicate then return the same semaphore address - */ - for (next = semheadp; next != NULL; next = next->sad_next) { - if (statbuf.st_ino == next->sad_inode && - strcmp(path, next->sad_name) == 0) { - - (void) __close_nc(fd); - (void) mutex_unlock(&semlock); - (void) __pos4obj_unlock(path, SEM_LOCK_TYPE); - return ((sem_t *)next->sad_addr); - } - } - (void) mutex_unlock(&semlock); - } - - - /* new sem descriptor to be allocated and new address to be mapped */ - if ((next = (semaddr_t *)malloc(sizeof (semaddr_t))) == NULL) { - errno = ENOMEM; - goto out; - } - - cr_flag |= ALLOC_MEM; - - /* LINTED */ - sem = (sem_t *)mmap64(NULL, sizeof (sem_t), PROT_READ|PROT_WRITE, - MAP_SHARED, fd, (off64_t)0); - (void) __close_nc(fd); - cr_flag &= ~DFILE_OPEN; - - if (sem == MAP_FAILED) - goto out; - - cr_flag |= DFILE_MMAP; - - /* add to the list pointed by semheadp */ - next->sad_next = semheadp; - semheadp = next; - next->sad_addr = sem; - next->sad_inode = statbuf.st_ino; - (void) strcpy(next->sad_name, path); - - /* initialize it by jumping through the jump table */ - if (cr_flag & DFILE_CREATE) { - if ((error = sema_init((sema_t *)sem, value, USYNC_PROCESS, 0)) - != 0) { - errno = error; - goto out; - } - } - - if (__pos4obj_unlock(path, SEM_LOCK_TYPE) < 0) - return (SEM_FAILED); - - return (sem); - -out: - error = errno; - if ((cr_flag & DFILE_OPEN) != 0) - (void) __close_nc(fd); - if ((cr_flag & DFILE_CREATE) != 0) - (void) __pos4obj_unlink(path, SEM_DATA_TYPE); - if ((cr_flag & ALLOC_MEM) != 0) - free((caddr_t)next); - if ((cr_flag & DFILE_MMAP) != 0) - (void) munmap((caddr_t)sem, sizeof (sem_t)); - - errno = error; - (void) __pos4obj_unlock(path, SEM_LOCK_TYPE); - return (SEM_FAILED); -} - -int -_sem_close(sem_t *sem) -{ - semaddr_t **next; - semaddr_t *freeit; - - (void) mutex_lock(&semlock); - - for (next = &semheadp; (freeit = *next) != NULL; - next = &(freeit->sad_next)) { - if (freeit->sad_addr == sem) { - *next = freeit->sad_next; - free((caddr_t)freeit); - (void) mutex_unlock(&semlock); - return (munmap((caddr_t)sem, sizeof (sem_t))); - } - } - (void) mutex_unlock(&semlock); - errno = EINVAL; - return (-1); -} - -int -_sem_unlink(const char *path) -{ - int error; - int oerrno; - - if (__pos4obj_check(path) < 0) - return (-1); - - if (__pos4obj_lock(path, SEM_LOCK_TYPE) < 0) - return (-1); - - error = __pos4obj_unlink(path, SEM_DATA_TYPE); - - oerrno = errno; - - (void) __pos4obj_unlock(path, SEM_LOCK_TYPE); - - errno = oerrno; - - return (error); -} - -/* - * SUSV3 requires ("shall fail") an EINVAL failure for operations - * on invalid semaphores, including uninitialized unnamed semaphores. - * The best we can do is check that the magic number is correct. - * This is not perfect, but it allows the test suite to pass. - * (Standards bodies are filled with fools and idiots.) - */ -static int -sem_invalid(sem_t *sem) -{ - if (sem->sem_magic != SEMA_MAGIC) { - errno = EINVAL; - return (-1); - } - return (0); -} - -int -_sem_init(sem_t *sem, int pshared, uint_t value) -{ - int error; - - if ((error = sema_init((sema_t *)sem, value, - pshared ? USYNC_PROCESS : USYNC_THREAD, NULL)) != 0) { - errno = error; - return (-1); - } - return (0); -} - -int -_sem_destroy(sem_t *sem) -{ - int error; - - if (sem_invalid(sem)) - return (-1); - if ((error = sema_destroy((sema_t *)sem)) != 0) { - errno = error; - return (-1); - } - return (0); -} - -int -_sem_post(sem_t *sem) -{ - int error; - - if (sem_invalid(sem)) - return (-1); - if ((error = sema_post((sema_t *)sem)) != 0) { - errno = error; - return (-1); - } - return (0); -} - -int -_sem_wait(sem_t *sem) -{ - int error; - - if (sem_invalid(sem)) - return (-1); - if ((error = sema_wait((sema_t *)sem)) != 0) { - errno = error; - return (-1); - } - return (0); -} - -int -_sem_timedwait(sem_t *sem, const timespec_t *abstime) -{ - int error; - - if (sem_invalid(sem)) - return (-1); - if ((error = sema_timedwait((sema_t *)sem, abstime)) != 0) { - if (error == ETIME) - error = ETIMEDOUT; - errno = error; - return (-1); - } - return (0); -} - -int -_sem_reltimedwait_np(sem_t *sem, const timespec_t *reltime) -{ - int error; - - if (sem_invalid(sem)) - return (-1); - if ((error = sema_reltimedwait((sema_t *)sem, reltime)) != 0) { - if (error == ETIME) - error = ETIMEDOUT; - errno = error; - return (-1); - } - return (0); -} - -int -_sem_trywait(sem_t *sem) -{ - int error; - - if (sem_invalid(sem)) - return (-1); - if ((error = sema_trywait((sema_t *)sem)) != 0) { - if (error == EBUSY) - error = EAGAIN; - errno = error; - return (-1); - } - return (0); -} - -int -_sem_getvalue(sem_t *sem, int *sval) -{ - if (sem_invalid(sem)) - return (-1); - *sval = (int)sem->sem_count; - return (0); -} diff --git a/usr/src/lib/librt/common/shm.c b/usr/src/lib/librt/common/shm.c deleted file mode 100644 index bd27c0ed48..0000000000 --- a/usr/src/lib/librt/common/shm.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "c_synonyms.h" -#include <sys/types.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <limits.h> -#include <errno.h> -#include "pos4obj.h" - -int -shm_open(const char *path, int oflag, mode_t mode) -{ - int flag, fd, flags; - - if (__pos4obj_check(path) == -1) { - return (-1); - } - - /* acquire semaphore lock to have atomic operation */ - if ((__pos4obj_lock(path, SHM_LOCK_TYPE)) < 0) { - return (-1); - } - - fd = __pos4obj_open(path, SHM_DATA_TYPE, oflag, mode, &flag); - - if (fd < 0) { - (void) __pos4obj_unlock(path, SHM_LOCK_TYPE); - return (-1); - } - - - if ((flags = fcntl(fd, F_GETFD)) < 0) { - (void) __pos4obj_unlock(path, SHM_LOCK_TYPE); - return (-1); - } - - if ((fcntl(fd, F_SETFD, flags|FD_CLOEXEC)) < 0) { - (void) __pos4obj_unlock(path, SHM_LOCK_TYPE); - return (-1); - } - - /* relase semaphore lock operation */ - if (__pos4obj_unlock(path, SHM_LOCK_TYPE) < 0) { - return (-1); - } - return (fd); - -} - -int -shm_unlink(const char *path) -{ - int oerrno; - int err; - - if (__pos4obj_check(path) < 0) - return (-1); - - if (__pos4obj_lock(path, SHM_LOCK_TYPE) < 0) - return (-1); - - err = __pos4obj_unlink(path, SHM_DATA_TYPE); - - oerrno = errno; - - (void) __pos4obj_unlock(path, SHM_LOCK_TYPE); - - errno = oerrno; - return (err); - -} diff --git a/usr/src/lib/librt/common/sigev_thread.c b/usr/src/lib/librt/common/sigev_thread.c deleted file mode 100644 index 5388a1dd4c..0000000000 --- a/usr/src/lib/librt/common/sigev_thread.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "c_synonyms.h" -#if !defined(__lint) /* need a *_synonyms.h file */ -#define nanosleep _nanosleep -#define sem_wait _sem_wait -#endif -#include <sys/types.h> -#include <pthread.h> -#include <unistd.h> -#include <stdlib.h> -#include <thread.h> -#include <pthread.h> -#include <synch.h> -#include <port.h> -#include <signal.h> -#include <stdio.h> -#include <errno.h> -#include <stdarg.h> -#include <string.h> -#include <sys/aiocb.h> -#include <time.h> -#include <signal.h> -#include <fcntl.h> -#include "sigev_thread.h" - -mutex_t free_tcd_lock = DEFAULTMUTEX; -static thread_communication_data_t *free_tcd_head = NULL; -static thread_communication_data_t *free_tcd_tail = NULL; -static freelist_t *std_freelist = NULL; - -/* - * Set non-zero via LIBRT_DEBUG to enable debugging printf's. - */ -static int _librt_debug = 0; - -#pragma init(__init_sigev_thread) -static void __init_sigev_thread(void) -{ - char *ldebug; - - if ((ldebug = getenv("_LIBRT_DEBUG")) != NULL) - _librt_debug = atoi(ldebug); -} - -/* - * Routine to print debug messages: - * If _librt_debug is set, printf the debug message to stderr - * with an appropriate prefix. - */ -/*PRINTFLIKE1*/ -static void -dprintf(const char *format, ...) -{ - if (_librt_debug) { - va_list alist; - - va_start(alist, format); - flockfile(stderr); - (void) fputs("librt DEBUG: ", stderr); - (void) vfprintf(stderr, format, alist); - funlockfile(stderr); - va_end(alist); - } -} - -static sigev_thread_data_t * -std_alloc(void) -{ - freelist_t *ptr; - - (void) mutex_lock(&free_tcd_lock); - if ((ptr = std_freelist) == NULL) { - (void) mutex_unlock(&free_tcd_lock); - ptr = malloc(sizeof (sigev_thread_data_t)); - } else { - std_freelist = ptr->fl_next; - (void) mutex_unlock(&free_tcd_lock); - } - return ((sigev_thread_data_t *)ptr); -} - -static void -std_free(sigev_thread_data_t *stdp) -{ - freelist_t *ptr = (freelist_t *)stdp; - - (void) mutex_lock(&free_tcd_lock); - ptr->fl_next = std_freelist; - std_freelist = ptr; - (void) mutex_unlock(&free_tcd_lock); -} - -/* - * The notify_thread() function can be used as the start function of a new - * thread but it is normally called from notifier(), below, in the context - * of a thread pool worker thread. It is used as the start function of a - * new thread only when individual pthread attributes differ from those - * that are common to all workers. This only occurs in the AIO case. - */ -static void * -notify_thread(void *arg) -{ - sigev_thread_data_t *stdp = arg; - void (*function)(union sigval) = stdp->std_func; - union sigval argument = stdp->std_arg; - - std_free(stdp); - function(argument); - return (NULL); -} - -/* - * Thread pool interface to call the user-supplied notification function. - */ -static void -notifier(void *arg) -{ - (void) notify_thread(arg); -} - -/* - * This routine adds a new work request, described by function - * and argument, to the list of outstanding jobs. - * It returns 0 indicating success. A value != 0 indicates an error. - */ -static int -sigev_add_work(thread_communication_data_t *tcdp, - void (*function)(union sigval), union sigval argument) -{ - tpool_t *tpool = tcdp->tcd_poolp; - sigev_thread_data_t *stdp; - - if (tpool == NULL) - return (EINVAL); - if ((stdp = std_alloc()) == NULL) - return (errno); - stdp->std_func = function; - stdp->std_arg = argument; - if (tpool_dispatch(tpool, notifier, stdp) != 0) { - std_free(stdp); - return (errno); - } - return (0); -} - -static void -sigev_destroy_pool(thread_communication_data_t *tcdp) -{ - if (tcdp->tcd_poolp != NULL) - tpool_abandon(tcdp->tcd_poolp); - tcdp->tcd_poolp = NULL; - - if (tcdp->tcd_subsystem == MQ) { - /* - * synchronize with del_sigev_mq() - */ - (void) mutex_lock(&tcdp->tcd_lock); - tcdp->tcd_server_id = 0; - if (tcdp->tcd_msg_closing) { - (void) cond_broadcast(&tcdp->tcd_cv); - (void) mutex_unlock(&tcdp->tcd_lock); - return; /* del_sigev_mq() will free the tcd */ - } - (void) mutex_unlock(&tcdp->tcd_lock); - } - - /* - * now delete everything - */ - free_sigev_handler(tcdp); -} - -/* - * timer_spawner(), mqueue_spawner(), and aio_spawner() are the main - * functions for the daemon threads that get the event(s) for the - * respective SIGEV_THREAD subsystems. There is one timer spawner for - * each timer_create(), one mqueue spawner for every mq_open(), and - * exactly one aio spawner for all aio requests. These spawners add - * work requests to be done by a pool of daemon worker threads. In case - * the event requires creation of a worker thread with different pthread - * attributes than those from the pool of workers, a new daemon thread - * with these attributes is spawned apart from the pool of workers. - * If the spawner fails to add work or fails to create an additional - * thread because of lacking resources, it puts the event back into - * the kernel queue and re-tries some time later. - */ - -void * -timer_spawner(void *arg) -{ - thread_communication_data_t *tcdp = (thread_communication_data_t *)arg; - port_event_t port_event; - - /* destroy the pool if we are cancelled */ - pthread_cleanup_push(sigev_destroy_pool, tcdp); - - for (;;) { - if (port_get(tcdp->tcd_port, &port_event, NULL) != 0) { - dprintf("port_get on port %d failed with %d <%s>\n", - tcdp->tcd_port, errno, strerror(errno)); - break; - } - switch (port_event.portev_source) { - case PORT_SOURCE_TIMER: - break; - case PORT_SOURCE_ALERT: - if (port_event.portev_events != SIGEV_THREAD_TERM) - errno = EPROTO; - goto out; - default: - dprintf("port_get on port %d returned %u " - "(not PORT_SOURCE_TIMER)\n", - tcdp->tcd_port, port_event.portev_source); - errno = EPROTO; - goto out; - } - - tcdp->tcd_overruns = port_event.portev_events - 1; - if (sigev_add_work(tcdp, - tcdp->tcd_notif.sigev_notify_function, - tcdp->tcd_notif.sigev_value) != 0) - break; - /* wait until job is done before looking for another */ - tpool_wait(tcdp->tcd_poolp); - } -out: - pthread_cleanup_pop(1); - return (NULL); -} - -void * -mqueue_spawner(void *arg) -{ - thread_communication_data_t *tcdp = (thread_communication_data_t *)arg; - int ret = 0; - int ntype; - void (*function)(union sigval); - union sigval argument; - - /* destroy the pool if we are cancelled */ - pthread_cleanup_push(sigev_destroy_pool, tcdp); - - while (ret == 0) { - /* - * This kludge is to call _pthread_cond_wait(), not - * _cond_wait(), because _cond_wait() is not a - * cancellation point. *Ugh* - */ - pthread_cond_t *cv = (pthread_cond_t *)&tcdp->tcd_cv; - pthread_mutex_t *mx = (pthread_mutex_t *)&tcdp->tcd_lock; - - (void) mutex_lock(&tcdp->tcd_lock); - pthread_cleanup_push(mutex_unlock, &tcdp->tcd_lock); - while ((ntype = tcdp->tcd_msg_enabled) == 0) - (void) pthread_cond_wait(cv, mx); - pthread_cleanup_pop(1); - - while (sem_wait(tcdp->tcd_msg_avail) == -1) - continue; - - (void) mutex_lock(&tcdp->tcd_lock); - tcdp->tcd_msg_enabled = 0; - (void) mutex_unlock(&tcdp->tcd_lock); - - /* ASSERT(ntype == SIGEV_THREAD || ntype == SIGEV_PORT); */ - if (ntype == SIGEV_THREAD) { - function = tcdp->tcd_notif.sigev_notify_function; - argument.sival_ptr = tcdp->tcd_msg_userval; - ret = sigev_add_work(tcdp, function, argument); - } else { /* ntype == SIGEV_PORT */ - ret = _port_dispatch(tcdp->tcd_port, 0, PORT_SOURCE_MQ, - 0, (uintptr_t)tcdp->tcd_msg_object, - tcdp->tcd_msg_userval); - } - } - (void) mutex_unlock(&tcdp->tcd_lock); - - pthread_cleanup_pop(1); - return (NULL); -} - -void * -aio_spawner(void *arg) -{ - thread_communication_data_t *tcdp = (thread_communication_data_t *)arg; - int error = 0; - void (*function)(union sigval); - union sigval argument; - port_event_t port_event; - struct sigevent *sigevp; - timespec_t delta; - pthread_attr_t *attrp; - - /* destroy the pool if we are cancelled */ - pthread_cleanup_push(sigev_destroy_pool, tcdp); - - while (error == 0) { - if (port_get(tcdp->tcd_port, &port_event, NULL) != 0) { - error = errno; - dprintf("port_get on port %d failed with %d <%s>\n", - tcdp->tcd_port, error, strerror(error)); - break; - } - switch (port_event.portev_source) { - case PORT_SOURCE_AIO: - break; - case PORT_SOURCE_ALERT: - if (port_event.portev_events != SIGEV_THREAD_TERM) - errno = EPROTO; - goto out; - default: - dprintf("port_get on port %d returned %u " - "(not PORT_SOURCE_AIO)\n", - tcdp->tcd_port, port_event.portev_source); - errno = EPROTO; - goto out; - } - argument.sival_ptr = port_event.portev_user; - switch (port_event.portev_events) { - case AIOLIO: -#if !defined(_LP64) - case AIOLIO64: -#endif - sigevp = (struct sigevent *)port_event.portev_object; - function = sigevp->sigev_notify_function; - attrp = sigevp->sigev_notify_attributes; - break; - case AIOAREAD: - case AIOAWRITE: - case AIOFSYNC: - { - aiocb_t *aiocbp = - (aiocb_t *)port_event.portev_object; - function = aiocbp->aio_sigevent.sigev_notify_function; - attrp = aiocbp->aio_sigevent.sigev_notify_attributes; - break; - } -#if !defined(_LP64) - case AIOAREAD64: - case AIOAWRITE64: - case AIOFSYNC64: - { - aiocb64_t *aiocbp = - (aiocb64_t *)port_event.portev_object; - function = aiocbp->aio_sigevent.sigev_notify_function; - attrp = aiocbp->aio_sigevent.sigev_notify_attributes; - break; - } -#endif - default: - function = NULL; - attrp = NULL; - break; - } - - if (function == NULL) - error = EINVAL; - else if (_pthread_attr_equal(attrp, tcdp->tcd_attrp)) - error = sigev_add_work(tcdp, function, argument); - else { - /* - * The attributes don't match. - * Spawn a thread with the non-matching attributes. - */ - pthread_attr_t local_attr; - sigev_thread_data_t *stdp; - - if ((stdp = std_alloc()) == NULL) - error = ENOMEM; - else - error = _pthread_attr_clone(&local_attr, attrp); - - if (error == 0) { - (void) pthread_attr_setdetachstate( - &local_attr, PTHREAD_CREATE_DETACHED); - (void) _pthread_attr_setdaemonstate_np( - &local_attr, PTHREAD_CREATE_DAEMON_NP); - stdp->std_func = function; - stdp->std_arg = argument; - error = pthread_create(NULL, &local_attr, - notify_thread, stdp); - (void) pthread_attr_destroy(&local_attr); - } - if (error && stdp != NULL) - std_free(stdp); - } - - if (error) { - dprintf("Cannot add work, error=%d <%s>.\n", - error, strerror(error)); - if (error == EAGAIN || error == ENOMEM) { - /* (Temporary) no resources are available. */ - if (_port_dispatch(tcdp->tcd_port, 0, - PORT_SOURCE_AIO, port_event.portev_events, - port_event.portev_object, - port_event.portev_user) != 0) - break; - error = 0; - delta.tv_sec = 0; - delta.tv_nsec = NANOSEC / 20; /* 50 msec */ - (void) nanosleep(&delta, NULL); - } - } - } -out: - pthread_cleanup_pop(1); - return (NULL); -} - -/* - * Allocate a thread_communication_data_t block. - */ -static thread_communication_data_t * -alloc_sigev_handler(subsystem_t caller) -{ - thread_communication_data_t *tcdp; - - (void) mutex_lock(&free_tcd_lock); - if ((tcdp = free_tcd_head) == NULL) { - (void) mutex_unlock(&free_tcd_lock); - tcdp = malloc(sizeof (thread_communication_data_t)); - if (tcdp != NULL) { - (void) memset(tcdp, 0, sizeof (*tcdp)); - tcdp->tcd_subsystem = caller; - tcdp->tcd_port = -1; - (void) mutex_init(&tcdp->tcd_lock, - USYNC_THREAD, NULL); - (void) cond_init(&tcdp->tcd_cv, - USYNC_THREAD, NULL); - } - return (tcdp); - } - if ((free_tcd_head = tcdp->tcd_next) == NULL) - free_tcd_tail = NULL; - (void) mutex_unlock(&free_tcd_lock); - tcdp->tcd_next = NULL; - tcdp->tcd_subsystem = caller; - tcdp->tcd_port = -1; - tcdp->tcd_server_id = 0; - tcdp->tcd_poolp = NULL; - return (tcdp); -} - -/* - * Free a thread_communication_data_t block. - */ -void -free_sigev_handler(thread_communication_data_t *tcdp) -{ - if (tcdp->tcd_attrp) { - (void) pthread_attr_destroy(tcdp->tcd_attrp); - tcdp->tcd_attrp = NULL; - } - (void) memset(&tcdp->tcd_notif, 0, sizeof (tcdp->tcd_notif)); - - switch (tcdp->tcd_subsystem) { - case TIMER: - case AIO: - if (tcdp->tcd_port >= 0) - (void) close(tcdp->tcd_port); - break; - case MQ: - tcdp->tcd_msg_avail = NULL; - tcdp->tcd_msg_object = NULL; - tcdp->tcd_msg_userval = NULL; - tcdp->tcd_msg_enabled = 0; - break; - } - tcdp->tcd_port = -1; - - tcdp->tcd_next = NULL; - (void) mutex_lock(&free_tcd_lock); - if (free_tcd_head == NULL) - free_tcd_head = free_tcd_tail = tcdp; - else { - free_tcd_tail->tcd_next = tcdp; - free_tcd_tail = tcdp; - } - (void) mutex_unlock(&free_tcd_lock); -} - -/* - * Initialize data structure and create the port. - */ -thread_communication_data_t * -setup_sigev_handler(const struct sigevent *sigevp, subsystem_t caller) -{ - thread_communication_data_t *tcdp; - int error; - - if (sigevp == NULL) { - errno = EINVAL; - return (NULL); - } - - if ((tcdp = alloc_sigev_handler(caller)) == NULL) { - errno = ENOMEM; - return (NULL); - } - - if (sigevp->sigev_notify_attributes == NULL) - tcdp->tcd_attrp = NULL; /* default attributes */ - else { - /* - * We cannot just copy the sigevp->sigev_notify_attributes - * pointer. We need to initialize a new pthread_attr_t - * structure with the values from the user-supplied - * pthread_attr_t. - */ - tcdp->tcd_attrp = &tcdp->tcd_user_attr; - error = _pthread_attr_clone(tcdp->tcd_attrp, - sigevp->sigev_notify_attributes); - if (error) { - tcdp->tcd_attrp = NULL; - free_sigev_handler(tcdp); - errno = error; - return (NULL); - } - } - tcdp->tcd_notif = *sigevp; - tcdp->tcd_notif.sigev_notify_attributes = tcdp->tcd_attrp; - - if (caller == TIMER || caller == AIO) { - if ((tcdp->tcd_port = port_create()) < 0 || - fcntl(tcdp->tcd_port, FD_CLOEXEC) == -1) { - free_sigev_handler(tcdp); - errno = EBADF; - return (NULL); - } - } - return (tcdp); -} - -/* - * Create a thread pool and launch the spawner. - */ -int -launch_spawner(thread_communication_data_t *tcdp) -{ - int ret; - int maxworkers; - void *(*spawner)(void *); - sigset_t set; - sigset_t oset; - - switch (tcdp->tcd_subsystem) { - case TIMER: - spawner = timer_spawner; - maxworkers = 1; - break; - case MQ: - spawner = mqueue_spawner; - maxworkers = 1; - break; - case AIO: - spawner = aio_spawner; - maxworkers = 100; - break; - default: - return (-1); - } - tcdp->tcd_poolp = tpool_create(1, maxworkers, 20, - tcdp->tcd_notif.sigev_notify_attributes); - if (tcdp->tcd_poolp == NULL) - return (-1); - /* create the spawner with all signals blocked */ - (void) sigfillset(&set); - (void) thr_sigsetmask(SIG_SETMASK, &set, &oset); - ret = thr_create(NULL, 0, spawner, tcdp, - THR_DETACHED | THR_DAEMON, &tcdp->tcd_server_id); - (void) thr_sigsetmask(SIG_SETMASK, &oset, NULL); - if (ret != 0) { - tpool_destroy(tcdp->tcd_poolp); - tcdp->tcd_poolp = NULL; - return (-1); - } - return (0); -} - -/* - * Delete the data associated with the sigev_thread timer, if timer is - * associated with such a notification option. - * Destroy the timer_spawner thread. - */ -int -del_sigev_timer(timer_t timer) -{ - int rc = 0; - thread_communication_data_t *tcdp; - - if ((uint_t)timer < timer_max && (tcdp = timer_tcd[timer]) != NULL) { - (void) mutex_lock(&tcdp->tcd_lock); - if (tcdp->tcd_port >= 0) { - if ((rc = port_alert(tcdp->tcd_port, - PORT_ALERT_SET, SIGEV_THREAD_TERM, NULL)) == 0) { - dprintf("del_sigev_timer(%d) OK.\n", timer); - } - } - timer_tcd[timer] = NULL; - (void) mutex_unlock(&tcdp->tcd_lock); - } - return (rc); -} - -int -sigev_timer_getoverrun(timer_t timer) -{ - thread_communication_data_t *tcdp; - - if ((uint_t)timer < timer_max && (tcdp = timer_tcd[timer]) != NULL) - return (tcdp->tcd_overruns); - return (0); -} - -/* - * Delete the data associated with the sigev_thread message queue, - * if the message queue is associated with such a notification option. - * Destroy the mqueue_spawner thread. - */ -void -del_sigev_mq(thread_communication_data_t *tcdp) -{ - pthread_t server_id; - int rc; - - (void) mutex_lock(&tcdp->tcd_lock); - server_id = tcdp->tcd_server_id; - tcdp->tcd_msg_closing = 1; - if ((rc = pthread_cancel(server_id)) != 0) { - dprintf("Fail to cancel %u with error %d <%s>.\n", - server_id, rc, strerror(rc)); - } else { - /* - * wait for sigev_destroy_pool() to finish - */ - while (tcdp->tcd_server_id == server_id) - (void) cond_wait(&tcdp->tcd_cv, &tcdp->tcd_lock); - } - (void) mutex_unlock(&tcdp->tcd_lock); - if (rc == 0) - free_sigev_handler(tcdp); -} diff --git a/usr/src/lib/librt/common/sigev_thread.h b/usr/src/lib/librt/common/sigev_thread.h deleted file mode 100644 index 0d09bd0525..0000000000 --- a/usr/src/lib/librt/common/sigev_thread.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SIGEV_THREAD_H -#define _SIGEV_THREAD_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <signal.h> -#include <port.h> -#include <mqueue.h> -#include <time.h> -#include <limits.h> -#include <semaphore.h> -#include "thread_pool.h" - -#define SIGEV_THREAD_TERM 1 - -typedef enum {TIMER = 1, MQ, AIO} subsystem_t; /* Calling sub-system */ - -typedef struct { - void (*std_func)(union sigval); /* User-defined notification function */ - union sigval std_arg; /* Parameter of user-defined notification fct */ -} sigev_thread_data_t; - -typedef struct thread_communication_data { - struct thread_communication_data *tcd_next; - struct sigevent tcd_notif; /* encapsulates usr fct and usr vals */ - pthread_attr_t tcd_user_attr; /* copy of caller's attributes */ - pthread_attr_t *tcd_attrp; /* NULL if caller passed NULL */ - int tcd_port; /* port this spawner is controlling */ - thread_t tcd_server_id; /* thread id of server thread */ - subsystem_t tcd_subsystem; /* event generating subsystem */ - tpool_t *tcd_poolp; /* worker thread pool */ - /* for creation/termination synchronization protocol */ - mutex_t tcd_lock; - cond_t tcd_cv; - /* subsystem-specific data */ - union { - struct { - int overruns; /* number of overruns */ - } timer; - struct { - int msg_enabled; /* notification enabled */ - int msg_closing; /* mq_close() is waiting */ - sem_t *msg_avail; /* wait for message available */ - void *msg_object; /* mqd_t */ - void *msg_userval; /* notification user value */ - } mqueue; - } tcd_object; -} thread_communication_data_t; - -#define tcd_overruns tcd_object.timer.overruns - -#define tcd_msg_enabled tcd_object.mqueue.msg_enabled -#define tcd_msg_closing tcd_object.mqueue.msg_closing -#define tcd_msg_avail tcd_object.mqueue.msg_avail -#define tcd_msg_object tcd_object.mqueue.msg_object -#define tcd_msg_userval tcd_object.mqueue.msg_userval - -/* - * Generic freelist data structure. - */ -typedef struct { - void *fl_next; -} freelist_t; - -/* Generic functions common to all entities */ -extern thread_communication_data_t *setup_sigev_handler( - const struct sigevent *, subsystem_t); -extern void free_sigev_handler(thread_communication_data_t *); -extern int launch_spawner(thread_communication_data_t *); - -/* Additional functions for different entities */ -extern void *timer_spawner(void *); -extern int del_sigev_timer(timer_t); -extern int sigev_timer_getoverrun(timer_t); -extern void *mqueue_spawner(void *); -extern void del_sigev_mq(thread_communication_data_t *); -extern void *aio_spawner(void *); - -/* Consolidation-private interfaces from libc */ -#define PTHREAD_CREATE_DAEMON_NP 0x100 /* = THR_DAEMON */ -#define PTHREAD_CREATE_NONDAEMON_NP 0 -extern int _pthread_attr_setdaemonstate_np(pthread_attr_t *, int); -extern int _pthread_attr_getdaemonstate_np(const pthread_attr_t *, int *); -extern int _pthread_attr_clone(pthread_attr_t *, const pthread_attr_t *); -extern int _pthread_attr_equal(const pthread_attr_t *, const pthread_attr_t *); -extern int _port_dispatch(int, int, int, int, uintptr_t, void *); - -extern thread_communication_data_t *sigev_aio_tcd; - -extern mutex_t sigev_aio_lock; -extern cond_t sigev_aio_cv; -extern int sigev_aio_busy; - -extern int timer_max; -extern thread_communication_data_t **timer_tcd; - -extern mutex_t free_tcd_lock; - -#ifdef __cplusplus -} -#endif - -#endif /* _SIGEV_THREAD_H */ diff --git a/usr/src/lib/librt/common/sigrt.c b/usr/src/lib/librt/common/sigrt.c deleted file mode 100644 index 0e1100057c..0000000000 --- a/usr/src/lib/librt/common/sigrt.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#pragma weak sigwaitinfo = _sigwaitinfo -#pragma weak sigtimedwait = _sigtimedwait -#pragma weak sigqueue = _sigqueue - -#include "c_synonyms.h" -#include <sys/types.h> -#include "pos4.h" - -int -_sigwaitinfo(const sigset_t *set, siginfo_t *info) -{ - return (__sigtimedwait(set, info, NULL)); -} - -int -_sigtimedwait(const sigset_t *set, siginfo_t *info, const timespec_t *timeout) -{ - return (__sigtimedwait(set, info, timeout)); -} - -int -_sigqueue(pid_t pid, int signo, const union sigval value) -{ - return (__sigqueue(pid, signo, value.sival_ptr, SI_QUEUE)); -} diff --git a/usr/src/lib/librt/common/thread_pool.c b/usr/src/lib/librt/common/thread_pool.c deleted file mode 100644 index 7ea7aa19ee..0000000000 --- a/usr/src/lib/librt/common/thread_pool.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "c_synonyms.h" -#include <stdlib.h> -#include <signal.h> -#include <errno.h> -#include "thread_pool_impl.h" - -static mutex_t thread_pool_lock = DEFAULTMUTEX; -static tpool_t *thread_pools = NULL; -static tpool_job_t *job_freelist = NULL; - -static pthread_once_t once_control = PTHREAD_ONCE_INIT; -static sigset_t fillset; - -static void -do_fillset(void) -{ - (void) sigfillset(&fillset); -} - -static tpool_job_t * -job_alloc(void) -{ - tpool_job_t *job; - - (void) mutex_lock(&thread_pool_lock); - if ((job = job_freelist) == NULL) { - (void) mutex_unlock(&thread_pool_lock); - job = malloc(sizeof (tpool_job_t)); - } else { - job_freelist = job->tpj_next; - (void) mutex_unlock(&thread_pool_lock); - } - return (job); -} - -static void -job_free(tpool_job_t *job) -{ - (void) mutex_lock(&thread_pool_lock); - job->tpj_next = job_freelist; - job_freelist = job; - (void) mutex_unlock(&thread_pool_lock); -} - -static void -delete_pool(tpool_t *tpool) -{ - tpool_job_t *job; - - /* ASSERT(tpool->tp_current == 0 && tpool->tp_active == NULL); */ - - /* - * Unlink the pool from the global list of all pools. - */ - (void) mutex_lock(&thread_pool_lock); - if (thread_pools == tpool) - thread_pools = tpool->tp_forw; - if (thread_pools == tpool) - thread_pools = NULL; - else { - tpool->tp_back->tp_forw = tpool->tp_forw; - tpool->tp_forw->tp_back = tpool->tp_back; - } - (void) mutex_unlock(&thread_pool_lock); - - /* - * There should be no pending jobs, but just in case... - */ - for (job = tpool->tp_head; job != NULL; job = tpool->tp_head) { - tpool->tp_head = job->tpj_next; - job_free(job); - } - (void) pthread_attr_destroy(&tpool->tp_attr); - free(tpool); -} - -/* - * Worker thread is terminating. - */ -static void -worker_cleanup(tpool_t *tpool) -{ - if (--tpool->tp_current == 0 && - (tpool->tp_flags & (TP_DESTROY | TP_ABANDON))) { - if (tpool->tp_flags & TP_ABANDON) { - (void) mutex_unlock(&tpool->tp_mutex); - delete_pool(tpool); - return; - } - if (tpool->tp_flags & TP_DESTROY) - (void) cond_broadcast(&tpool->tp_busycv); - } - (void) mutex_unlock(&tpool->tp_mutex); -} - -static void -notify_waiters(tpool_t *tpool) -{ - if (tpool->tp_head == NULL && tpool->tp_active == NULL) { - tpool->tp_flags &= ~TP_WAIT; - (void) cond_broadcast(&tpool->tp_waitcv); - } -} - -/* - * Called by a worker thread on return from a tpool_dispatch()d job. - */ -static void -job_cleanup(tpool_t *tpool) -{ - pthread_t self = pthread_self(); - tpool_active_t *activep; - tpool_active_t **activepp; - - (void) mutex_lock(&tpool->tp_mutex); - /* CSTYLED */ - for (activepp = &tpool->tp_active;; activepp = &activep->tpa_next) { - activep = *activepp; - if (activep->tpa_tid == self) { - *activepp = activep->tpa_next; - break; - } - } - if (tpool->tp_flags & TP_WAIT) - notify_waiters(tpool); -} - -static void * -tpool_worker(void *arg) -{ - tpool_t *tpool = (tpool_t *)arg; - int elapsed; - tpool_job_t *job; - void (*func)(void *); - tpool_active_t active; - - (void) mutex_lock(&tpool->tp_mutex); - pthread_cleanup_push(worker_cleanup, tpool); - - /* - * This is the worker's main loop. - * It will only be left if a timeout or an error has occured. - */ - active.tpa_tid = pthread_self(); - for (;;) { - elapsed = 0; - tpool->tp_idle++; - if (tpool->tp_flags & TP_WAIT) - notify_waiters(tpool); - while ((tpool->tp_head == NULL || - (tpool->tp_flags & TP_SUSPEND)) && - !(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))) { - if (tpool->tp_current <= tpool->tp_minimum || - tpool->tp_linger == 0) { - (void) cond_wait(&tpool->tp_workcv, - &tpool->tp_mutex); - } else { - timestruc_t timeout; - - timeout.tv_sec = tpool->tp_linger; - timeout.tv_nsec = 0; - if (cond_reltimedwait(&tpool->tp_workcv, - &tpool->tp_mutex, &timeout) == ETIME) { - elapsed = 1; - break; - } - } - } - tpool->tp_idle--; - if (tpool->tp_flags & TP_DESTROY) - break; - if (tpool->tp_flags & TP_ABANDON) { - /* can't abandon a suspended pool */ - if (tpool->tp_flags & TP_SUSPEND) { - tpool->tp_flags &= ~TP_SUSPEND; - (void) cond_broadcast(&tpool->tp_workcv); - } - if (tpool->tp_head == NULL) - break; - } - if ((job = tpool->tp_head) != NULL && - !(tpool->tp_flags & TP_SUSPEND)) { - elapsed = 0; - func = job->tpj_func; - arg = job->tpj_arg; - tpool->tp_head = job->tpj_next; - if (job == tpool->tp_tail) - tpool->tp_tail = NULL; - tpool->tp_njobs--; - active.tpa_next = tpool->tp_active; - tpool->tp_active = &active; - (void) mutex_unlock(&tpool->tp_mutex); - job_free(job); - pthread_cleanup_push(job_cleanup, tpool); - /* - * Call the specified function. - */ - func(arg); - /* - * We don't know what this thread has been doing, - * so we reset its signal mask and cancellation - * state back to the initial values. - */ - (void) pthread_sigmask(SIG_SETMASK, &fillset, NULL); - (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, - NULL); - (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, - NULL); - pthread_cleanup_pop(1); - } - if (elapsed && tpool->tp_current > tpool->tp_minimum) { - /* - * We timed out and there is no work to be done - * and the number of workers exceeds the minimum. - * Exit now to reduce the size of the pool. - */ - break; - } - } - pthread_cleanup_pop(1); - return (arg); -} - -/* - * Create a worker thread, with all signals blocked. - */ -static int -create_worker(tpool_t *tpool) -{ - sigset_t oset; - int error; - - (void) pthread_once(&once_control, do_fillset); - (void) pthread_sigmask(SIG_SETMASK, &fillset, &oset); - error = pthread_create(NULL, &tpool->tp_attr, tpool_worker, tpool); - (void) pthread_sigmask(SIG_SETMASK, &oset, NULL); - return (error); -} - -tpool_t * -tpool_create(uint_t min_threads, uint_t max_threads, uint_t linger, - pthread_attr_t *attr) -{ - tpool_t *tpool; - void *stackaddr; - size_t stacksize; - size_t minstack; - int error; - - if (min_threads > max_threads || max_threads < 1) { - errno = EINVAL; - return (NULL); - } - if (attr != NULL) { - if (pthread_attr_getstack(attr, &stackaddr, &stacksize) != 0) { - errno = EINVAL; - return (NULL); - } - /* - * Allow only one thread in the pool with a specified stack. - * Require threads to have at least the minimum stack size. - */ - minstack = thr_min_stack(); - if (stackaddr != NULL) { - if (stacksize < minstack || max_threads != 1) { - errno = EINVAL; - return (NULL); - } - } else if (stacksize != 0 && stacksize < minstack) { - errno = EINVAL; - return (NULL); - } - } - - tpool = calloc(1, sizeof (tpool_t)); - if (tpool == NULL) { - errno = ENOMEM; - return (NULL); - } - (void) mutex_init(&tpool->tp_mutex, USYNC_THREAD, NULL); - (void) cond_init(&tpool->tp_busycv, USYNC_THREAD, NULL); - (void) cond_init(&tpool->tp_workcv, USYNC_THREAD, NULL); - (void) cond_init(&tpool->tp_waitcv, USYNC_THREAD, NULL); - tpool->tp_minimum = min_threads; - tpool->tp_maximum = max_threads; - tpool->tp_linger = linger; - - /* - * We cannot just copy the attribute pointer. - * We need to initialize a new pthread_attr_t structure - * with the values from the user-supplied pthread_attr_t. - * If the attribute pointer is NULL, we need to initialize - * the new pthread_attr_t structure with default values. - */ - error = _pthread_attr_clone(&tpool->tp_attr, attr); - if (error) { - free(tpool); - errno = error; - return (NULL); - } - - /* make all pool threads be detached daemon threads */ - (void) pthread_attr_setdetachstate(&tpool->tp_attr, - PTHREAD_CREATE_DETACHED); - (void) _pthread_attr_setdaemonstate_np(&tpool->tp_attr, - PTHREAD_CREATE_DAEMON_NP); - - /* insert into the global list of all thread pools */ - (void) mutex_lock(&thread_pool_lock); - if (thread_pools == NULL) { - tpool->tp_forw = tpool; - tpool->tp_back = tpool; - thread_pools = tpool; - } else { - thread_pools->tp_back->tp_forw = tpool; - tpool->tp_forw = thread_pools; - tpool->tp_back = thread_pools->tp_back; - thread_pools->tp_back = tpool; - } - (void) mutex_unlock(&thread_pool_lock); - - return (tpool); -} - -/* - * Dispatch a work request to the thread pool. - * If there are idle workers, awaken one. - * Else, if the maximum number of workers has - * not been reached, spawn a new worker thread. - * Else just return with the job added to the queue. - */ -int -tpool_dispatch(tpool_t *tpool, void (*func)(void *), void *arg) -{ - tpool_job_t *job; - - if ((job = job_alloc()) == NULL) - return (-1); - job->tpj_next = NULL; - job->tpj_func = func; - job->tpj_arg = arg; - - (void) mutex_lock(&tpool->tp_mutex); - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - - if (tpool->tp_head == NULL) - tpool->tp_head = job; - else - tpool->tp_tail->tpj_next = job; - tpool->tp_tail = job; - tpool->tp_njobs++; - - if (!(tpool->tp_flags & TP_SUSPEND)) { - if (tpool->tp_idle > 0) - (void) cond_signal(&tpool->tp_workcv); - else if (tpool->tp_current < tpool->tp_maximum && - create_worker(tpool) == 0) - tpool->tp_current++; - } - - (void) mutex_unlock(&tpool->tp_mutex); - return (0); -} - -/* - * Assumes: by the time tpool_destroy() is called no one will use this - * thread pool in any way and no one will try to dispatch entries to it. - * Calling tpool_destroy() from a job in the pool will cause deadlock. - */ -void -tpool_destroy(tpool_t *tpool) -{ - tpool_active_t *activep; - - /* ASSERT(!tpool_member(tpool)); */ - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - - (void) mutex_lock(&tpool->tp_mutex); - - /* mark the pool as being destroyed; wakeup idle workers */ - tpool->tp_flags |= TP_DESTROY; - tpool->tp_flags &= ~TP_SUSPEND; - (void) cond_broadcast(&tpool->tp_workcv); - - /* cancel all active workers */ - for (activep = tpool->tp_active; activep; activep = activep->tpa_next) - (void) pthread_cancel(activep->tpa_tid); - - /* wait for all active workers to finish */ - while (tpool->tp_active != NULL) { - tpool->tp_flags |= TP_WAIT; - (void) cond_wait(&tpool->tp_waitcv, &tpool->tp_mutex); - } - - /* the last worker to terminate will wake us up */ - while (tpool->tp_current != 0) - (void) cond_wait(&tpool->tp_busycv, &tpool->tp_mutex); - - (void) mutex_unlock(&tpool->tp_mutex); - delete_pool(tpool); -} - -/* - * Like tpool_destroy(), but don't cancel workers or wait for them to finish. - * The last worker to terminate will delete the pool. - */ -void -tpool_abandon(tpool_t *tpool) -{ - (void) mutex_lock(&tpool->tp_mutex); - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - if (tpool->tp_current == 0) { - /* no workers, just delete the pool */ - (void) mutex_unlock(&tpool->tp_mutex); - delete_pool(tpool); - } else { - /* wake up all workers, last one will delete the pool */ - tpool->tp_flags |= TP_ABANDON; - tpool->tp_flags &= ~TP_SUSPEND; - (void) cond_broadcast(&tpool->tp_workcv); - (void) mutex_unlock(&tpool->tp_mutex); - } -} - -/* - * Wait for all jobs to complete. - * Calling tpool_wait() from a job in the pool will cause deadlock. - */ -void -tpool_wait(tpool_t *tpool) -{ - /* ASSERT(!tpool_member(tpool)); */ - (void) mutex_lock(&tpool->tp_mutex); - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - while (tpool->tp_head != NULL || tpool->tp_active != NULL) { - tpool->tp_flags |= TP_WAIT; - (void) cond_wait(&tpool->tp_waitcv, &tpool->tp_mutex); - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - } - (void) mutex_unlock(&tpool->tp_mutex); -} - -void -tpool_suspend(tpool_t *tpool) -{ - (void) mutex_lock(&tpool->tp_mutex); - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - tpool->tp_flags |= TP_SUSPEND; - (void) mutex_unlock(&tpool->tp_mutex); -} - -int -tpool_suspended(tpool_t *tpool) -{ - int suspended; - - (void) mutex_lock(&tpool->tp_mutex); - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - suspended = (tpool->tp_flags & TP_SUSPEND) != 0; - (void) mutex_unlock(&tpool->tp_mutex); - return (suspended); -} - -void -tpool_resume(tpool_t *tpool) -{ - int excess; - - (void) mutex_lock(&tpool->tp_mutex); - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - if (!(tpool->tp_flags & TP_SUSPEND)) { - (void) mutex_unlock(&tpool->tp_mutex); - return; - } - tpool->tp_flags &= ~TP_SUSPEND; - (void) cond_broadcast(&tpool->tp_workcv); - excess = tpool->tp_njobs - tpool->tp_idle; - while (excess-- > 0 && tpool->tp_current < tpool->tp_maximum) { - if (create_worker(tpool) != 0) - break; /* pthread_create() failed */ - tpool->tp_current++; - } - (void) mutex_unlock(&tpool->tp_mutex); -} - -int -tpool_member(tpool_t *tpool) -{ - pthread_t self = pthread_self(); - tpool_active_t *activep; - - (void) mutex_lock(&tpool->tp_mutex); - /* ASSERT(!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))); */ - for (activep = tpool->tp_active; activep; activep = activep->tpa_next) { - if (activep->tpa_tid == self) { - (void) mutex_unlock(&tpool->tp_mutex); - return (1); - } - } - (void) mutex_unlock(&tpool->tp_mutex); - return (0); -} - -void -prefork1_tpool(void) -{ - tpool_t *tpool; - - (void) mutex_lock(&thread_pool_lock); - if ((tpool = thread_pools) != NULL) { - do { - (void) mutex_lock(&tpool->tp_mutex); - } while ((tpool = tpool->tp_forw) != thread_pools); - } -} - -void -postfork1_parent_tpool(void) -{ - tpool_t *tpool; - - if ((tpool = thread_pools) != NULL) { - do { - (void) mutex_unlock(&tpool->tp_mutex); - } while ((tpool = tpool->tp_forw) != thread_pools); - } - (void) mutex_unlock(&thread_pool_lock); -} - -void -postfork1_child_tpool(void) -{ - pthread_t my_tid = pthread_self(); - tpool_t *tpool; - tpool_job_t *job; - - postfork1_parent_tpool(); /* release locks */ - - /* - * All of the thread pool workers are gone, except possibly - * for the current thread, if it is a thread pool worker thread. - * Retain the thread pools, but make them all empty. Whatever - * jobs were queued or running belong to the parent process. - */ -top: - if ((tpool = thread_pools) == NULL) - return; - - do { - tpool_active_t *activep; - - (void) mutex_init(&tpool->tp_mutex, USYNC_THREAD, NULL); - (void) cond_init(&tpool->tp_busycv, USYNC_THREAD, NULL); - (void) cond_init(&tpool->tp_workcv, USYNC_THREAD, NULL); - (void) cond_init(&tpool->tp_waitcv, USYNC_THREAD, NULL); - for (job = tpool->tp_head; job; job = tpool->tp_head) { - tpool->tp_head = job->tpj_next; - job_free(job); - } - tpool->tp_tail = NULL; - tpool->tp_njobs = 0; - for (activep = tpool->tp_active; activep; - activep = activep->tpa_next) { - if (activep->tpa_tid == my_tid) { - activep->tpa_next = NULL; - break; - } - } - tpool->tp_idle = 0; - tpool->tp_current = 0; - if ((tpool->tp_active = activep) != NULL) - tpool->tp_current = 1; - tpool->tp_flags &= ~TP_WAIT; - if (tpool->tp_flags & (TP_DESTROY | TP_ABANDON)) { - tpool->tp_flags &= ~TP_DESTROY; - tpool->tp_flags |= TP_ABANDON; - if (tpool->tp_current == 0) { - delete_pool(tpool); - goto top; /* start over */ - } - } - } while ((tpool = tpool->tp_forw) != thread_pools); -} diff --git a/usr/src/lib/librt/common/thread_pool.h b/usr/src/lib/librt/common/thread_pool.h deleted file mode 100644 index 200323703c..0000000000 --- a/usr/src/lib/librt/common/thread_pool.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _THREAD_POOL_H_ -#define _THREAD_POOL_H_ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <thread.h> -#include <pthread.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct tpool tpool_t; /* opaque thread pool descriptor */ - -#if defined(__STDC__) - -extern tpool_t *tpool_create(uint_t min_threads, uint_t max_threads, - uint_t linger, pthread_attr_t *attr); -extern int tpool_dispatch(tpool_t *tpool, - void (*func)(void *), void *arg); -extern void tpool_destroy(tpool_t *tpool); -extern void tpool_abandon(tpool_t *tpool); -extern void tpool_wait(tpool_t *tpool); -extern void tpool_suspend(tpool_t *tpool); -extern int tpool_suspended(tpool_t *tpool); -extern void tpool_resume(tpool_t *tpool); -extern int tpool_member(tpool_t *tpool); - -#else /* Non ANSI */ - -extern tpool_t *tpool_create(); -extern int tpool_dispatch(); -extern void tpool_destroy(); -extern void tpool_abandon(); -extern void tpool_wait(); -extern void tpool_suspend(); -extern int tpool_suspended(); -extern void tpool_resume(); -extern int tpool_member(); - -#endif /* __STDC__ */ - -#ifdef __cplusplus -} -#endif - -#endif /* _THREAD_POOL_H_ */ diff --git a/usr/src/lib/librt/common/thread_pool_impl.h b/usr/src/lib/librt/common/thread_pool_impl.h deleted file mode 100644 index 6c25b3c45f..0000000000 --- a/usr/src/lib/librt/common/thread_pool_impl.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _THREAD_POOL_IMPL_H -#define _THREAD_POOL_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "thread_pool.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Thread pool implementation definitions. - * See <thread_pool.h> for interface declarations. - */ - -/* - * FIFO queued job - */ -typedef struct tpool_job tpool_job_t; -struct tpool_job { - tpool_job_t *tpj_next; /* list of jobs */ - void (*tpj_func)(void *); /* function to call */ - void *tpj_arg; /* its argument */ -}; - -/* - * List of active threads, linked through their stacks. - */ -typedef struct tpool_active tpool_active_t; -struct tpool_active { - tpool_active_t *tpa_next; /* list of active threads */ - pthread_t tpa_tid; /* active thread id */ -}; - -/* - * The thread pool. - */ -struct tpool { - tpool_t *tp_forw; /* circular list of all thread pools */ - tpool_t *tp_back; - mutex_t tp_mutex; /* protects the pool data */ - cond_t tp_busycv; /* synchronization in tpool_dispatch */ - cond_t tp_workcv; /* synchronization with workers */ - cond_t tp_waitcv; /* synchronization in tpool_wait() */ - tpool_active_t *tp_active; /* threads performing work */ - tpool_job_t *tp_head; /* FIFO job queue */ - tpool_job_t *tp_tail; - pthread_attr_t tp_attr; /* attributes of the workers */ - int tp_flags; /* see below */ - uint_t tp_linger; /* seconds before idle workers exit */ - int tp_njobs; /* number of jobs in job queue */ - int tp_minimum; /* minimum number of worker threads */ - int tp_maximum; /* maximum number of worker threads */ - int tp_current; /* current number of worker threads */ - int tp_idle; /* number of idle workers */ -}; - -/* tp_flags */ -#define TP_WAIT 0x01 /* waiting in tpool_wait() */ -#define TP_SUSPEND 0x02 /* pool is being suspended */ -#define TP_DESTROY 0x04 /* pool is being destroyed */ -#define TP_ABANDON 0x08 /* pool is abandoned (auto-destroy) */ - -/* Consolidation-private interfaces from libc */ -#define PTHREAD_CREATE_DAEMON_NP 0x100 /* = THR_DAEMON */ -#define PTHREAD_CREATE_NONDAEMON_NP 0 -extern int _pthread_attr_setdaemonstate_np(pthread_attr_t *, int); -extern int _pthread_attr_getdaemonstate_np(const pthread_attr_t *, int *); -extern int _pthread_attr_clone(pthread_attr_t *, const pthread_attr_t *); - -#ifdef __cplusplus -} -#endif - -#endif /* _THREAD_POOL_IMPL_H */ |