1/*- 2 * Copyright (c) 2006 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
| 1/*- 2 * Copyright (c) 2006 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
|
26 * $FreeBSD: head/lib/librt/mq.c 156193 2006-03-01 23:40:00Z davidxu $
| 26 * $FreeBSD: head/lib/librt/mq.c 156267 2006-03-04 00:18:19Z davidxu $
|
27 */ 28 29#include <sys/cdefs.h> 30#include <sys/types.h> 31#include <sys/syscall.h> 32#include <sys/mqueue.h> 33 34#include "namespace.h" 35#include <errno.h> 36#include <pthread.h> 37#include <stddef.h> 38#include <stdlib.h> 39#include <signal.h> 40#include <unistd.h> 41#include "sigev_thread.h" 42#include "un-namespace.h" 43 44extern int __sys_kmq_notify(int, const struct sigevent *); 45extern int __sys_kmq_open(const char *, int, mode_t, 46 const struct mq_attr *); 47extern int __sys_kmq_setattr(int, const struct mq_attr *__restrict, 48 struct mq_attr *__restrict); 49extern ssize_t __sys_kmq_timedreceive(int, char *__restrict, size_t, 50 unsigned *__restrict, const struct timespec *__restrict); 51extern int __sys_kmq_timedsend(int, const char *, size_t, unsigned, 52 const struct timespec *); 53extern int __sys_kmq_unlink(const char *); 54extern int __sys_close(int fd); 55 56struct __mq { 57 int oshandle; 58 struct sigev_node *node; 59}; 60 61__weak_reference(__mq_open, mq_open); 62__weak_reference(__mq_open, _mq_open); 63__weak_reference(__mq_close, mq_close); 64__weak_reference(__mq_close, _mq_close); 65__weak_reference(__mq_notify, mq_notify); 66__weak_reference(__mq_notify, _mq_notify); 67__weak_reference(__mq_getattr, mq_getattr); 68__weak_reference(__mq_getattr, _mq_getattr); 69__weak_reference(__mq_setattr, mq_setattr); 70__weak_reference(__mq_setattr, _mq_setattr); 71__weak_reference(__mq_timedreceive, mq_timedreceive); 72__weak_reference(__mq_timedreceive, _mq_timedreceive); 73__weak_reference(__mq_timedsend, mq_timedsend); 74__weak_reference(__mq_timedsend, _mq_timedsend); 75__weak_reference(__mq_unlink, mq_unlink); 76__weak_reference(__mq_unlink, _mq_unlink); 77__weak_reference(__mq_send, mq_send); 78__weak_reference(__mq_send, _mq_send); 79__weak_reference(__mq_receive, mq_receive); 80__weak_reference(__mq_receive, _mq_receive); 81 82mqd_t 83__mq_open(const char *name, int oflag, mode_t mode, 84 const struct mq_attr *attr) 85{ 86 struct __mq *mq; 87 int err; 88 89 mq = malloc(sizeof(struct __mq)); 90 if (mq == NULL) 91 return (NULL); 92 93 mq->oshandle = __sys_kmq_open(name, oflag, mode, attr); 94 if (mq->oshandle != -1) { 95 mq->node = NULL; 96 return (mq); 97 } 98 err = errno; 99 free(mq); 100 errno = err; 101 return ((mqd_t)-1L); 102} 103 104int 105__mq_close(mqd_t mqd) 106{ 107 int h; 108 109 if (mqd->node != NULL) { 110 __sigev_list_lock(); 111 __sigev_delete_node(mqd->node); 112 __sigev_list_unlock(); 113 } 114 h = mqd->oshandle; 115 free(mqd); 116 return (__sys_close(h)); 117} 118 119typedef void (*mq_func)(union sigval val); 120 121static void
| 27 */ 28 29#include <sys/cdefs.h> 30#include <sys/types.h> 31#include <sys/syscall.h> 32#include <sys/mqueue.h> 33 34#include "namespace.h" 35#include <errno.h> 36#include <pthread.h> 37#include <stddef.h> 38#include <stdlib.h> 39#include <signal.h> 40#include <unistd.h> 41#include "sigev_thread.h" 42#include "un-namespace.h" 43 44extern int __sys_kmq_notify(int, const struct sigevent *); 45extern int __sys_kmq_open(const char *, int, mode_t, 46 const struct mq_attr *); 47extern int __sys_kmq_setattr(int, const struct mq_attr *__restrict, 48 struct mq_attr *__restrict); 49extern ssize_t __sys_kmq_timedreceive(int, char *__restrict, size_t, 50 unsigned *__restrict, const struct timespec *__restrict); 51extern int __sys_kmq_timedsend(int, const char *, size_t, unsigned, 52 const struct timespec *); 53extern int __sys_kmq_unlink(const char *); 54extern int __sys_close(int fd); 55 56struct __mq { 57 int oshandle; 58 struct sigev_node *node; 59}; 60 61__weak_reference(__mq_open, mq_open); 62__weak_reference(__mq_open, _mq_open); 63__weak_reference(__mq_close, mq_close); 64__weak_reference(__mq_close, _mq_close); 65__weak_reference(__mq_notify, mq_notify); 66__weak_reference(__mq_notify, _mq_notify); 67__weak_reference(__mq_getattr, mq_getattr); 68__weak_reference(__mq_getattr, _mq_getattr); 69__weak_reference(__mq_setattr, mq_setattr); 70__weak_reference(__mq_setattr, _mq_setattr); 71__weak_reference(__mq_timedreceive, mq_timedreceive); 72__weak_reference(__mq_timedreceive, _mq_timedreceive); 73__weak_reference(__mq_timedsend, mq_timedsend); 74__weak_reference(__mq_timedsend, _mq_timedsend); 75__weak_reference(__mq_unlink, mq_unlink); 76__weak_reference(__mq_unlink, _mq_unlink); 77__weak_reference(__mq_send, mq_send); 78__weak_reference(__mq_send, _mq_send); 79__weak_reference(__mq_receive, mq_receive); 80__weak_reference(__mq_receive, _mq_receive); 81 82mqd_t 83__mq_open(const char *name, int oflag, mode_t mode, 84 const struct mq_attr *attr) 85{ 86 struct __mq *mq; 87 int err; 88 89 mq = malloc(sizeof(struct __mq)); 90 if (mq == NULL) 91 return (NULL); 92 93 mq->oshandle = __sys_kmq_open(name, oflag, mode, attr); 94 if (mq->oshandle != -1) { 95 mq->node = NULL; 96 return (mq); 97 } 98 err = errno; 99 free(mq); 100 errno = err; 101 return ((mqd_t)-1L); 102} 103 104int 105__mq_close(mqd_t mqd) 106{ 107 int h; 108 109 if (mqd->node != NULL) { 110 __sigev_list_lock(); 111 __sigev_delete_node(mqd->node); 112 __sigev_list_unlock(); 113 } 114 h = mqd->oshandle; 115 free(mqd); 116 return (__sys_close(h)); 117} 118 119typedef void (*mq_func)(union sigval val); 120 121static void
|
122mq_dispatch(struct sigev_node *sn, siginfo_t *si)
| 122mq_dispatch(struct sigev_node *sn)
|
123{ 124 mq_func f = sn->sn_func; 125 126 /* 127 * Check generation before calling user function, 128 * this should avoid expired notification. 129 */
| 123{ 124 mq_func f = sn->sn_func; 125 126 /* 127 * Check generation before calling user function, 128 * this should avoid expired notification. 129 */
|
130 if (sn->sn_gen == si->si_value.sival_int)
| 130 if (sn->sn_gen == sn->sn_info.si_value.sival_int)
|
131 f(sn->sn_value); 132} 133 134int 135__mq_notify(mqd_t mqd, const struct sigevent *evp) 136{ 137 struct sigevent ev; 138 struct sigev_node *sn; 139 int ret; 140 141 if (evp == NULL || evp->sigev_notify != SIGEV_THREAD) { 142 if (mqd->node != NULL) { 143 __sigev_list_lock(); 144 __sigev_delete_node(mqd->node); 145 mqd->node = NULL; 146 __sigev_list_unlock(); 147 } 148 return __sys_kmq_notify(mqd->oshandle, evp); 149 } 150 151 if (__sigev_check_init()) { 152 /* 153 * Thread library is not enabled. 154 */ 155 errno = EINVAL; 156 return (-1); 157 } 158
| 131 f(sn->sn_value); 132} 133 134int 135__mq_notify(mqd_t mqd, const struct sigevent *evp) 136{ 137 struct sigevent ev; 138 struct sigev_node *sn; 139 int ret; 140 141 if (evp == NULL || evp->sigev_notify != SIGEV_THREAD) { 142 if (mqd->node != NULL) { 143 __sigev_list_lock(); 144 __sigev_delete_node(mqd->node); 145 mqd->node = NULL; 146 __sigev_list_unlock(); 147 } 148 return __sys_kmq_notify(mqd->oshandle, evp); 149 } 150 151 if (__sigev_check_init()) { 152 /* 153 * Thread library is not enabled. 154 */ 155 errno = EINVAL; 156 return (-1); 157 } 158
|
159 sn = __sigev_alloc(SI_MESGQ, evp);
| 159 sn = __sigev_alloc(SI_MESGQ, evp, mqd->node, 1);
|
160 if (sn == NULL) { 161 errno = EAGAIN; 162 return (-1); 163 } 164 165 sn->sn_id = mqd->oshandle; 166 sn->sn_dispatch = mq_dispatch; 167 __sigev_get_sigevent(sn, &ev, sn->sn_gen); 168 __sigev_list_lock(); 169 if (mqd->node != NULL) 170 __sigev_delete_node(mqd->node); 171 mqd->node = sn; 172 __sigev_register(sn); 173 ret = __sys_kmq_notify(mqd->oshandle, &ev); 174 __sigev_list_unlock(); 175 return (ret); 176} 177 178int 179__mq_getattr(mqd_t mqd, struct mq_attr *attr) 180{ 181 182 return __sys_kmq_setattr(mqd->oshandle, NULL, attr); 183} 184 185int 186__mq_setattr(mqd_t mqd, const struct mq_attr *newattr, struct mq_attr *oldattr) 187{ 188 189 return __sys_kmq_setattr(mqd->oshandle, newattr, oldattr); 190} 191 192ssize_t 193__mq_timedreceive(mqd_t mqd, char *buf, size_t len, 194 unsigned *prio, const struct timespec *timeout) 195{ 196 197 return __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, timeout); 198} 199 200ssize_t 201__mq_receive(mqd_t mqd, char *buf, size_t len, unsigned *prio) 202{ 203 204 return __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, NULL); 205} 206 207ssize_t 208__mq_timedsend(mqd_t mqd, char *buf, size_t len, 209 unsigned prio, const struct timespec *timeout) 210{ 211 212 return __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, timeout); 213} 214 215ssize_t 216__mq_send(mqd_t mqd, char *buf, size_t len, unsigned prio) 217{ 218 219 return __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, NULL); 220} 221 222int 223__mq_unlink(const char *path) 224{ 225 226 return __sys_kmq_unlink(path); 227} 228 229int 230__mq_oshandle(mqd_t mqd) 231{ 232 233 return (mqd->oshandle); 234}
| 160 if (sn == NULL) { 161 errno = EAGAIN; 162 return (-1); 163 } 164 165 sn->sn_id = mqd->oshandle; 166 sn->sn_dispatch = mq_dispatch; 167 __sigev_get_sigevent(sn, &ev, sn->sn_gen); 168 __sigev_list_lock(); 169 if (mqd->node != NULL) 170 __sigev_delete_node(mqd->node); 171 mqd->node = sn; 172 __sigev_register(sn); 173 ret = __sys_kmq_notify(mqd->oshandle, &ev); 174 __sigev_list_unlock(); 175 return (ret); 176} 177 178int 179__mq_getattr(mqd_t mqd, struct mq_attr *attr) 180{ 181 182 return __sys_kmq_setattr(mqd->oshandle, NULL, attr); 183} 184 185int 186__mq_setattr(mqd_t mqd, const struct mq_attr *newattr, struct mq_attr *oldattr) 187{ 188 189 return __sys_kmq_setattr(mqd->oshandle, newattr, oldattr); 190} 191 192ssize_t 193__mq_timedreceive(mqd_t mqd, char *buf, size_t len, 194 unsigned *prio, const struct timespec *timeout) 195{ 196 197 return __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, timeout); 198} 199 200ssize_t 201__mq_receive(mqd_t mqd, char *buf, size_t len, unsigned *prio) 202{ 203 204 return __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, NULL); 205} 206 207ssize_t 208__mq_timedsend(mqd_t mqd, char *buf, size_t len, 209 unsigned prio, const struct timespec *timeout) 210{ 211 212 return __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, timeout); 213} 214 215ssize_t 216__mq_send(mqd_t mqd, char *buf, size_t len, unsigned prio) 217{ 218 219 return __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, NULL); 220} 221 222int 223__mq_unlink(const char *path) 224{ 225 226 return __sys_kmq_unlink(path); 227} 228 229int 230__mq_oshandle(mqd_t mqd) 231{ 232 233 return (mqd->oshandle); 234}
|