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 156136 2006-03-01 06:37:34Z davidxu $
| 26 * $FreeBSD: head/lib/librt/mq.c 156141 2006-03-01 08:06:09Z 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 *);
| 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);
| 45extern int __sys_kmq_open(const char *, int, mode_t, 46 const struct mq_attr *);
|
46extern int __sys_kmq_setattr(int, const struct mq_attr *__restrict, 47 struct mq_attr *__restrict); 48extern ssize_t __sys_kmq_timedreceive(int, char *__restrict, size_t, 49 unsigned *__restrict, const struct timespec *__restrict); 50extern int __sys_kmq_timedsend(int, const char *, size_t, unsigned, 51 const struct timespec *); 52extern int __sys_kmq_unlink(const char *); 53extern int __sys_close(int fd); 54 55struct __mq { 56 int oshandle; 57 struct sigev_node *node; 58}; 59 60__weak_reference(__mq_open, mq_open); 61__weak_reference(__mq_open, _mq_open); 62__weak_reference(__mq_close, mq_close); 63__weak_reference(__mq_close, _mq_close); 64__weak_reference(__mq_notify, mq_notify); 65__weak_reference(__mq_notify, _mq_notify); 66__weak_reference(__mq_getattr, mq_getattr); 67__weak_reference(__mq_getattr, _mq_getattr); 68__weak_reference(__mq_setattr, mq_setattr); 69__weak_reference(__mq_setattr, _mq_setattr); 70__weak_reference(__mq_timedreceive, mq_timedreceive); 71__weak_reference(__mq_timedreceive, _mq_timedreceive); 72__weak_reference(__mq_timedsend, mq_timedsend); 73__weak_reference(__mq_timedsend, _mq_timedsend); 74__weak_reference(__mq_unlink, mq_unlink); 75__weak_reference(__mq_unlink, _mq_unlink); 76__weak_reference(__mq_send, mq_send); 77__weak_reference(__mq_send, _mq_send); 78__weak_reference(__mq_receive, mq_receive); 79__weak_reference(__mq_receive, _mq_receive); 80 81mqd_t
| 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
|
82__mq_open(const char *name, int oflag, mode_t mode)
| 83__mq_open(const char *name, int oflag, mode_t mode, 84 const struct mq_attr *attr)
|
83{ 84 struct __mq *mq; 85 int err; 86 87 mq = malloc(sizeof(struct __mq)); 88 if (mq == NULL) 89 return (NULL); 90
| 85{ 86 struct __mq *mq; 87 int err; 88 89 mq = malloc(sizeof(struct __mq)); 90 if (mq == NULL) 91 return (NULL); 92
|
91 mq->oshandle = __sys_kmq_open(name, oflag, mode);
| 93 mq->oshandle = __sys_kmq_open(name, oflag, mode, attr);
|
92 if (mq->oshandle != -1) { 93 mq->node = NULL; 94 return (mq); 95 } 96 err = errno; 97 free(mq); 98 errno = err; 99 return ((mqd_t)-1L); 100} 101 102int 103__mq_close(mqd_t mqd) 104{ 105 int h; 106 107 if (mqd->node != NULL) { 108 __sigev_list_lock(); 109 __sigev_delete_node(mqd->node); 110 __sigev_list_unlock(); 111 } 112 h = mqd->oshandle; 113 free(mqd); 114 return (__sys_close(h)); 115} 116 117typedef void (*mq_func)(union sigval val); 118 119static void 120mq_dispatch(struct sigev_node *sn, siginfo_t *si) 121{ 122 mq_func f = sn->sn_func; 123 124 /* 125 * Check generation before calling user function, 126 * this should avoid expired notification. 127 */ 128 if (sn->sn_gen == si->si_value.sival_int) 129 f(sn->sn_value); 130} 131 132int 133__mq_notify(mqd_t mqd, const struct sigevent *evp) 134{ 135 struct sigevent ev; 136 struct sigev_node *sn; 137 int ret; 138 139 if (evp == NULL || evp->sigev_notify != SIGEV_THREAD) { 140 if (mqd->node != NULL) { 141 __sigev_list_lock(); 142 __sigev_delete_node(mqd->node); 143 mqd->node = NULL; 144 __sigev_list_unlock(); 145 } 146 return __sys_kmq_notify(mqd->oshandle, evp); 147 } 148 149 if (__sigev_check_init()) { 150 /* 151 * Thread library is not enabled. 152 */ 153 errno = EINVAL; 154 return (-1); 155 } 156 157 sn = __sigev_alloc(SI_MESGQ, evp); 158 if (sn == NULL) { 159 errno = EAGAIN; 160 return (-1); 161 } 162 163 sn->sn_id = mqd->oshandle; 164 sn->sn_dispatch = mq_dispatch; 165 __sigev_get_sigevent(sn, &ev, sn->sn_gen); 166 __sigev_list_lock(); 167 if (mqd->node != NULL) 168 __sigev_delete_node(mqd->node); 169 mqd->node = sn; 170 __sigev_register(sn); 171 ret = __sys_kmq_notify(mqd->oshandle, &ev); 172 __sigev_list_unlock(); 173 return (ret); 174} 175 176int 177__mq_getattr(mqd_t mqd, struct mq_attr *attr) 178{ 179 180 return __sys_kmq_setattr(mqd->oshandle, NULL, attr); 181} 182 183int 184__mq_setattr(mqd_t mqd, const struct mq_attr *newattr, struct mq_attr *oldattr) 185{ 186 187 return __sys_kmq_setattr(mqd->oshandle, newattr, oldattr); 188} 189 190ssize_t 191__mq_timedreceive(mqd_t mqd, char *buf, size_t len, 192 unsigned *prio, const struct timespec *timeout) 193{ 194 195 return __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, timeout); 196} 197 198ssize_t 199__mq_receive(mqd_t mqd, char *buf, size_t len, unsigned *prio) 200{ 201 202 return __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, NULL); 203} 204 205ssize_t 206__mq_timedsend(mqd_t mqd, char *buf, size_t len, 207 unsigned prio, const struct timespec *timeout) 208{ 209 210 return __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, timeout); 211} 212 213ssize_t 214__mq_send(mqd_t mqd, char *buf, size_t len, unsigned prio) 215{ 216 217 return __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, NULL); 218} 219 220int 221__mq_unlink(const char *path) 222{ 223 224 return __sys_kmq_unlink(path); 225} 226 227int 228__mq_oshandle(mqd_t mqd) 229{ 230 return mqd->oshandle; 231}
| 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) 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) 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); 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 return mqd->oshandle; 233}
|