1/* $FreeBSD: head/sys/kern/sysv_msg.c 80670 2001-07-30 19:28:02Z asmodai $ */
| 1/* $FreeBSD: head/sys/kern/sysv_msg.c 82607 2001-08-31 00:02:18Z dillon $ */
|
2 3/* 4 * Implementation of SVID messages 5 * 6 * Author: Daniel Boulet 7 * 8 * Copyright 1993 Daniel Boulet and RTMX Inc. 9 * 10 * This system call was implemented by Daniel Boulet under contract from RTMX. 11 * 12 * Redistribution and use in source forms, with and without modification, 13 * are permitted provided that this entire comment appears intact. 14 * 15 * Redistribution in binary form may occur without any restrictions. 16 * Obviously, it would be nice if you gave credit where credit is due 17 * but requiring it would be too onerous. 18 * 19 * This software is provided ``AS IS'' without any warranties of any kind. 20 */ 21 22#include "opt_sysvipc.h" 23 24#include <sys/param.h> 25#include <sys/systm.h> 26#include <sys/sysproto.h> 27#include <sys/kernel.h> 28#include <sys/proc.h>
| 2 3/* 4 * Implementation of SVID messages 5 * 6 * Author: Daniel Boulet 7 * 8 * Copyright 1993 Daniel Boulet and RTMX Inc. 9 * 10 * This system call was implemented by Daniel Boulet under contract from RTMX. 11 * 12 * Redistribution and use in source forms, with and without modification, 13 * are permitted provided that this entire comment appears intact. 14 * 15 * Redistribution in binary form may occur without any restrictions. 16 * Obviously, it would be nice if you gave credit where credit is due 17 * but requiring it would be too onerous. 18 * 19 * This software is provided ``AS IS'' without any warranties of any kind. 20 */ 21 22#include "opt_sysvipc.h" 23 24#include <sys/param.h> 25#include <sys/systm.h> 26#include <sys/sysproto.h> 27#include <sys/kernel.h> 28#include <sys/proc.h>
|
| 29#include <sys/lock.h> 30#include <sys/mutex.h>
|
29#include <sys/msg.h> 30#include <sys/syscall.h> 31#include <sys/sysent.h> 32#include <sys/sysctl.h> 33#include <sys/malloc.h> 34#include <sys/jail.h> 35 36static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues"); 37 38static void msginit __P((void)); 39static int msgunload __P((void)); 40static int sysvmsg_modload __P((struct module *, int, void *)); 41 42#define MSG_DEBUG 43#undef MSG_DEBUG_OK 44 45static void msg_freehdr __P((struct msg *msghdr)); 46 47/* XXX casting to (sy_call_t *) is bogus, as usual. */ 48static sy_call_t *msgcalls[] = { 49 (sy_call_t *)msgctl, (sy_call_t *)msgget, 50 (sy_call_t *)msgsnd, (sy_call_t *)msgrcv 51}; 52 53struct msg { 54 struct msg *msg_next; /* next msg in the chain */ 55 long msg_type; /* type of this message */ 56 /* >0 -> type of this message */ 57 /* 0 -> free header */ 58 u_short msg_ts; /* size of this message */ 59 short msg_spot; /* location of start of msg in buffer */ 60}; 61 62 63#ifndef MSGSSZ 64#define MSGSSZ 8 /* Each segment must be 2^N long */ 65#endif 66#ifndef MSGSEG 67#define MSGSEG 2048 /* must be less than 32767 */ 68#endif 69#define MSGMAX (MSGSSZ*MSGSEG) 70#ifndef MSGMNB 71#define MSGMNB 2048 /* max # of bytes in a queue */ 72#endif 73#ifndef MSGMNI 74#define MSGMNI 40 75#endif 76#ifndef MSGTQL 77#define MSGTQL 40 78#endif 79 80/* 81 * Based on the configuration parameters described in an SVR2 (yes, two) 82 * config(1m) man page. 83 * 84 * Each message is broken up and stored in segments that are msgssz bytes 85 * long. For efficiency reasons, this should be a power of two. Also, 86 * it doesn't make sense if it is less than 8 or greater than about 256. 87 * Consequently, msginit in kern/sysv_msg.c checks that msgssz is a power of 88 * two between 8 and 1024 inclusive (and panic's if it isn't). 89 */ 90struct msginfo msginfo = { 91 MSGMAX, /* max chars in a message */ 92 MSGMNI, /* # of message queue identifiers */ 93 MSGMNB, /* max chars in a queue */ 94 MSGTQL, /* max messages in system */ 95 MSGSSZ, /* size of a message segment */ 96 /* (must be small power of 2 greater than 4) */ 97 MSGSEG /* number of message segments */ 98}; 99 100/* 101 * macros to convert between msqid_ds's and msqid's. 102 * (specific to this implementation) 103 */ 104#define MSQID(ix,ds) ((ix) & 0xffff | (((ds).msg_perm.seq << 16) & 0xffff0000)) 105#define MSQID_IX(id) ((id) & 0xffff) 106#define MSQID_SEQ(id) (((id) >> 16) & 0xffff) 107 108/* 109 * The rest of this file is specific to this particular implementation. 110 */ 111 112struct msgmap { 113 short next; /* next segment in buffer */ 114 /* -1 -> available */ 115 /* 0..(MSGSEG-1) -> index of next segment */ 116}; 117 118#define MSG_LOCKED 01000 /* Is this msqid_ds locked? */ 119 120static int nfree_msgmaps; /* # of free map entries */ 121static short free_msgmaps; /* head of linked list of free map entries */ 122static struct msg *free_msghdrs;/* list of free msg headers */ 123static char *msgpool; /* MSGMAX byte long msg buffer pool */ 124static struct msgmap *msgmaps; /* MSGSEG msgmap structures */ 125static struct msg *msghdrs; /* MSGTQL msg headers */ 126static struct msqid_ds *msqids; /* MSGMNI msqid_ds struct's */ 127 128static void 129msginit() 130{ 131 register int i; 132 133 msgpool = malloc(msginfo.msgmax, M_MSG, M_WAITOK); 134 if (msgpool == NULL) 135 panic("msgpool is NULL"); 136 msgmaps = malloc(sizeof(struct msgmap) * msginfo.msgseg, M_MSG, M_WAITOK); 137 if (msgmaps == NULL) 138 panic("msgmaps is NULL"); 139 msghdrs = malloc(sizeof(struct msg) * msginfo.msgtql, M_MSG, M_WAITOK); 140 if (msghdrs == NULL) 141 panic("msghdrs is NULL"); 142 msqids = malloc(sizeof(struct msqid_ds) * msginfo.msgmni, M_MSG, M_WAITOK); 143 if (msqids == NULL) 144 panic("msqids is NULL"); 145 146 /* 147 * msginfo.msgssz should be a power of two for efficiency reasons. 148 * It is also pretty silly if msginfo.msgssz is less than 8 149 * or greater than about 256 so ... 150 */ 151 152 i = 8; 153 while (i < 1024 && i != msginfo.msgssz) 154 i <<= 1; 155 if (i != msginfo.msgssz) { 156 printf("msginfo.msgssz=%d (0x%x)\n", msginfo.msgssz, 157 msginfo.msgssz); 158 panic("msginfo.msgssz not a small power of 2"); 159 } 160 161 if (msginfo.msgseg > 32767) { 162 printf("msginfo.msgseg=%d\n", msginfo.msgseg); 163 panic("msginfo.msgseg > 32767"); 164 } 165 166 if (msgmaps == NULL) 167 panic("msgmaps is NULL"); 168 169 for (i = 0; i < msginfo.msgseg; i++) { 170 if (i > 0) 171 msgmaps[i-1].next = i; 172 msgmaps[i].next = -1; /* implies entry is available */ 173 } 174 free_msgmaps = 0; 175 nfree_msgmaps = msginfo.msgseg; 176 177 if (msghdrs == NULL) 178 panic("msghdrs is NULL"); 179 180 for (i = 0; i < msginfo.msgtql; i++) { 181 msghdrs[i].msg_type = 0; 182 if (i > 0) 183 msghdrs[i-1].msg_next = &msghdrs[i]; 184 msghdrs[i].msg_next = NULL; 185 } 186 free_msghdrs = &msghdrs[0]; 187 188 if (msqids == NULL) 189 panic("msqids is NULL"); 190 191 for (i = 0; i < msginfo.msgmni; i++) { 192 msqids[i].msg_qbytes = 0; /* implies entry is available */ 193 msqids[i].msg_perm.seq = 0; /* reset to a known value */ 194 msqids[i].msg_perm.mode = 0; 195 } 196} 197 198static int 199msgunload() 200{ 201 struct msqid_ds *msqptr; 202 int msqid; 203 204 for (msqid = 0; msqid < msginfo.msgmni; msqid++) { 205 /* 206 * Look for an unallocated and unlocked msqid_ds. 207 * msqid_ds's can be locked by msgsnd or msgrcv while 208 * they are copying the message in/out. We can't 209 * re-use the entry until they release it. 210 */ 211 msqptr = &msqids[msqid]; 212 if (msqptr->msg_qbytes != 0 || 213 (msqptr->msg_perm.mode & MSG_LOCKED) != 0) 214 break; 215 } 216 if (msqid != msginfo.msgmni) 217 return (EBUSY); 218 219 free(msgpool, M_MSG); 220 free(msgmaps, M_MSG); 221 free(msghdrs, M_MSG); 222 free(msqids, M_MSG); 223 return (0); 224} 225 226 227static int 228sysvmsg_modload(struct module *module, int cmd, void *arg) 229{ 230 int error = 0; 231 232 switch (cmd) { 233 case MOD_LOAD: 234 msginit(); 235 break; 236 case MOD_UNLOAD: 237 error = msgunload(); 238 break; 239 case MOD_SHUTDOWN: 240 break; 241 default: 242 error = EINVAL; 243 break; 244 } 245 return (error); 246} 247 248static moduledata_t sysvmsg_mod = { 249 "sysvmsg", 250 &sysvmsg_modload, 251 NULL 252}; 253 254SYSCALL_MODULE_HELPER(msgsys, 6); 255SYSCALL_MODULE_HELPER(msgctl, 3); 256SYSCALL_MODULE_HELPER(msgget, 2); 257SYSCALL_MODULE_HELPER(msgsnd, 4); 258SYSCALL_MODULE_HELPER(msgrcv, 5); 259 260DECLARE_MODULE(sysvmsg, sysvmsg_mod, 261 SI_SUB_SYSV_MSG, SI_ORDER_FIRST); 262MODULE_VERSION(sysvmsg, 1); 263 264/* 265 * Entry point for all MSG calls
| 31#include <sys/msg.h> 32#include <sys/syscall.h> 33#include <sys/sysent.h> 34#include <sys/sysctl.h> 35#include <sys/malloc.h> 36#include <sys/jail.h> 37 38static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues"); 39 40static void msginit __P((void)); 41static int msgunload __P((void)); 42static int sysvmsg_modload __P((struct module *, int, void *)); 43 44#define MSG_DEBUG 45#undef MSG_DEBUG_OK 46 47static void msg_freehdr __P((struct msg *msghdr)); 48 49/* XXX casting to (sy_call_t *) is bogus, as usual. */ 50static sy_call_t *msgcalls[] = { 51 (sy_call_t *)msgctl, (sy_call_t *)msgget, 52 (sy_call_t *)msgsnd, (sy_call_t *)msgrcv 53}; 54 55struct msg { 56 struct msg *msg_next; /* next msg in the chain */ 57 long msg_type; /* type of this message */ 58 /* >0 -> type of this message */ 59 /* 0 -> free header */ 60 u_short msg_ts; /* size of this message */ 61 short msg_spot; /* location of start of msg in buffer */ 62}; 63 64 65#ifndef MSGSSZ 66#define MSGSSZ 8 /* Each segment must be 2^N long */ 67#endif 68#ifndef MSGSEG 69#define MSGSEG 2048 /* must be less than 32767 */ 70#endif 71#define MSGMAX (MSGSSZ*MSGSEG) 72#ifndef MSGMNB 73#define MSGMNB 2048 /* max # of bytes in a queue */ 74#endif 75#ifndef MSGMNI 76#define MSGMNI 40 77#endif 78#ifndef MSGTQL 79#define MSGTQL 40 80#endif 81 82/* 83 * Based on the configuration parameters described in an SVR2 (yes, two) 84 * config(1m) man page. 85 * 86 * Each message is broken up and stored in segments that are msgssz bytes 87 * long. For efficiency reasons, this should be a power of two. Also, 88 * it doesn't make sense if it is less than 8 or greater than about 256. 89 * Consequently, msginit in kern/sysv_msg.c checks that msgssz is a power of 90 * two between 8 and 1024 inclusive (and panic's if it isn't). 91 */ 92struct msginfo msginfo = { 93 MSGMAX, /* max chars in a message */ 94 MSGMNI, /* # of message queue identifiers */ 95 MSGMNB, /* max chars in a queue */ 96 MSGTQL, /* max messages in system */ 97 MSGSSZ, /* size of a message segment */ 98 /* (must be small power of 2 greater than 4) */ 99 MSGSEG /* number of message segments */ 100}; 101 102/* 103 * macros to convert between msqid_ds's and msqid's. 104 * (specific to this implementation) 105 */ 106#define MSQID(ix,ds) ((ix) & 0xffff | (((ds).msg_perm.seq << 16) & 0xffff0000)) 107#define MSQID_IX(id) ((id) & 0xffff) 108#define MSQID_SEQ(id) (((id) >> 16) & 0xffff) 109 110/* 111 * The rest of this file is specific to this particular implementation. 112 */ 113 114struct msgmap { 115 short next; /* next segment in buffer */ 116 /* -1 -> available */ 117 /* 0..(MSGSEG-1) -> index of next segment */ 118}; 119 120#define MSG_LOCKED 01000 /* Is this msqid_ds locked? */ 121 122static int nfree_msgmaps; /* # of free map entries */ 123static short free_msgmaps; /* head of linked list of free map entries */ 124static struct msg *free_msghdrs;/* list of free msg headers */ 125static char *msgpool; /* MSGMAX byte long msg buffer pool */ 126static struct msgmap *msgmaps; /* MSGSEG msgmap structures */ 127static struct msg *msghdrs; /* MSGTQL msg headers */ 128static struct msqid_ds *msqids; /* MSGMNI msqid_ds struct's */ 129 130static void 131msginit() 132{ 133 register int i; 134 135 msgpool = malloc(msginfo.msgmax, M_MSG, M_WAITOK); 136 if (msgpool == NULL) 137 panic("msgpool is NULL"); 138 msgmaps = malloc(sizeof(struct msgmap) * msginfo.msgseg, M_MSG, M_WAITOK); 139 if (msgmaps == NULL) 140 panic("msgmaps is NULL"); 141 msghdrs = malloc(sizeof(struct msg) * msginfo.msgtql, M_MSG, M_WAITOK); 142 if (msghdrs == NULL) 143 panic("msghdrs is NULL"); 144 msqids = malloc(sizeof(struct msqid_ds) * msginfo.msgmni, M_MSG, M_WAITOK); 145 if (msqids == NULL) 146 panic("msqids is NULL"); 147 148 /* 149 * msginfo.msgssz should be a power of two for efficiency reasons. 150 * It is also pretty silly if msginfo.msgssz is less than 8 151 * or greater than about 256 so ... 152 */ 153 154 i = 8; 155 while (i < 1024 && i != msginfo.msgssz) 156 i <<= 1; 157 if (i != msginfo.msgssz) { 158 printf("msginfo.msgssz=%d (0x%x)\n", msginfo.msgssz, 159 msginfo.msgssz); 160 panic("msginfo.msgssz not a small power of 2"); 161 } 162 163 if (msginfo.msgseg > 32767) { 164 printf("msginfo.msgseg=%d\n", msginfo.msgseg); 165 panic("msginfo.msgseg > 32767"); 166 } 167 168 if (msgmaps == NULL) 169 panic("msgmaps is NULL"); 170 171 for (i = 0; i < msginfo.msgseg; i++) { 172 if (i > 0) 173 msgmaps[i-1].next = i; 174 msgmaps[i].next = -1; /* implies entry is available */ 175 } 176 free_msgmaps = 0; 177 nfree_msgmaps = msginfo.msgseg; 178 179 if (msghdrs == NULL) 180 panic("msghdrs is NULL"); 181 182 for (i = 0; i < msginfo.msgtql; i++) { 183 msghdrs[i].msg_type = 0; 184 if (i > 0) 185 msghdrs[i-1].msg_next = &msghdrs[i]; 186 msghdrs[i].msg_next = NULL; 187 } 188 free_msghdrs = &msghdrs[0]; 189 190 if (msqids == NULL) 191 panic("msqids is NULL"); 192 193 for (i = 0; i < msginfo.msgmni; i++) { 194 msqids[i].msg_qbytes = 0; /* implies entry is available */ 195 msqids[i].msg_perm.seq = 0; /* reset to a known value */ 196 msqids[i].msg_perm.mode = 0; 197 } 198} 199 200static int 201msgunload() 202{ 203 struct msqid_ds *msqptr; 204 int msqid; 205 206 for (msqid = 0; msqid < msginfo.msgmni; msqid++) { 207 /* 208 * Look for an unallocated and unlocked msqid_ds. 209 * msqid_ds's can be locked by msgsnd or msgrcv while 210 * they are copying the message in/out. We can't 211 * re-use the entry until they release it. 212 */ 213 msqptr = &msqids[msqid]; 214 if (msqptr->msg_qbytes != 0 || 215 (msqptr->msg_perm.mode & MSG_LOCKED) != 0) 216 break; 217 } 218 if (msqid != msginfo.msgmni) 219 return (EBUSY); 220 221 free(msgpool, M_MSG); 222 free(msgmaps, M_MSG); 223 free(msghdrs, M_MSG); 224 free(msqids, M_MSG); 225 return (0); 226} 227 228 229static int 230sysvmsg_modload(struct module *module, int cmd, void *arg) 231{ 232 int error = 0; 233 234 switch (cmd) { 235 case MOD_LOAD: 236 msginit(); 237 break; 238 case MOD_UNLOAD: 239 error = msgunload(); 240 break; 241 case MOD_SHUTDOWN: 242 break; 243 default: 244 error = EINVAL; 245 break; 246 } 247 return (error); 248} 249 250static moduledata_t sysvmsg_mod = { 251 "sysvmsg", 252 &sysvmsg_modload, 253 NULL 254}; 255 256SYSCALL_MODULE_HELPER(msgsys, 6); 257SYSCALL_MODULE_HELPER(msgctl, 3); 258SYSCALL_MODULE_HELPER(msgget, 2); 259SYSCALL_MODULE_HELPER(msgsnd, 4); 260SYSCALL_MODULE_HELPER(msgrcv, 5); 261 262DECLARE_MODULE(sysvmsg, sysvmsg_mod, 263 SI_SUB_SYSV_MSG, SI_ORDER_FIRST); 264MODULE_VERSION(sysvmsg, 1); 265 266/* 267 * Entry point for all MSG calls
|
| 268 * 269 * MPSAFE
|
266 */ 267int 268msgsys(p, uap) 269 struct proc *p; 270 /* XXX actually varargs. */ 271 struct msgsys_args /* { 272 u_int which; 273 int a2; 274 int a3; 275 int a4; 276 int a5; 277 int a6; 278 } */ *uap; 279{
| 270 */ 271int 272msgsys(p, uap) 273 struct proc *p; 274 /* XXX actually varargs. */ 275 struct msgsys_args /* { 276 u_int which; 277 int a2; 278 int a3; 279 int a4; 280 int a5; 281 int a6; 282 } */ *uap; 283{
|
| 284 int error;
|
280
| 285
|
281 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) 282 return (ENOSYS);
| 286 mtx_lock(&Giant);
|
283
| 287
|
284 if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0])) 285 return (EINVAL); 286 return ((*msgcalls[uap->which])(p, &uap->a2));
| 288 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 289 error = ENOSYS; 290 goto done2; 291 } 292 if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0])) { 293 error = EINVAL; 294 goto done2; 295 } 296 error = (*msgcalls[uap->which])(p, &uap->a2); 297done2: 298 mtx_unlock(&Giant); 299 return (error);
|
287} 288 289static void 290msg_freehdr(msghdr) 291 struct msg *msghdr; 292{ 293 while (msghdr->msg_ts > 0) { 294 short next; 295 if (msghdr->msg_spot < 0 || msghdr->msg_spot >= msginfo.msgseg) 296 panic("msghdr->msg_spot out of range"); 297 next = msgmaps[msghdr->msg_spot].next; 298 msgmaps[msghdr->msg_spot].next = free_msgmaps; 299 free_msgmaps = msghdr->msg_spot; 300 nfree_msgmaps++; 301 msghdr->msg_spot = next; 302 if (msghdr->msg_ts >= msginfo.msgssz) 303 msghdr->msg_ts -= msginfo.msgssz; 304 else 305 msghdr->msg_ts = 0; 306 } 307 if (msghdr->msg_spot != -1) 308 panic("msghdr->msg_spot != -1"); 309 msghdr->msg_next = free_msghdrs; 310 free_msghdrs = msghdr; 311} 312 313#ifndef _SYS_SYSPROTO_H_ 314struct msgctl_args { 315 int msqid; 316 int cmd; 317 struct msqid_ds *buf; 318}; 319#endif 320
| 300} 301 302static void 303msg_freehdr(msghdr) 304 struct msg *msghdr; 305{ 306 while (msghdr->msg_ts > 0) { 307 short next; 308 if (msghdr->msg_spot < 0 || msghdr->msg_spot >= msginfo.msgseg) 309 panic("msghdr->msg_spot out of range"); 310 next = msgmaps[msghdr->msg_spot].next; 311 msgmaps[msghdr->msg_spot].next = free_msgmaps; 312 free_msgmaps = msghdr->msg_spot; 313 nfree_msgmaps++; 314 msghdr->msg_spot = next; 315 if (msghdr->msg_ts >= msginfo.msgssz) 316 msghdr->msg_ts -= msginfo.msgssz; 317 else 318 msghdr->msg_ts = 0; 319 } 320 if (msghdr->msg_spot != -1) 321 panic("msghdr->msg_spot != -1"); 322 msghdr->msg_next = free_msghdrs; 323 free_msghdrs = msghdr; 324} 325 326#ifndef _SYS_SYSPROTO_H_ 327struct msgctl_args { 328 int msqid; 329 int cmd; 330 struct msqid_ds *buf; 331}; 332#endif 333
|
| 334/* 335 * MPSAFE 336 */
|
321int 322msgctl(p, uap) 323 struct proc *p; 324 register struct msgctl_args *uap; 325{ 326 int msqid = uap->msqid; 327 int cmd = uap->cmd; 328 struct msqid_ds *user_msqptr = uap->buf;
| 337int 338msgctl(p, uap) 339 struct proc *p; 340 register struct msgctl_args *uap; 341{ 342 int msqid = uap->msqid; 343 int cmd = uap->cmd; 344 struct msqid_ds *user_msqptr = uap->buf;
|
329 int rval, eval;
| 345 int rval, error;
|
330 struct msqid_ds msqbuf; 331 register struct msqid_ds *msqptr; 332 333#ifdef MSG_DEBUG_OK 334 printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr); 335#endif
| 346 struct msqid_ds msqbuf; 347 register struct msqid_ds *msqptr; 348 349#ifdef MSG_DEBUG_OK 350 printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr); 351#endif
|
| 352 mtx_lock(&Giant);
|
336
| 353
|
337 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) 338 return (ENOSYS);
| 354 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 355 error = ENOSYS; 356 goto done2; 357 }
|
339 340 msqid = IPCID_TO_IX(msqid); 341 342 if (msqid < 0 || msqid >= msginfo.msgmni) { 343#ifdef MSG_DEBUG_OK 344 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, 345 msginfo.msgmni); 346#endif
| 358 359 msqid = IPCID_TO_IX(msqid); 360 361 if (msqid < 0 || msqid >= msginfo.msgmni) { 362#ifdef MSG_DEBUG_OK 363 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, 364 msginfo.msgmni); 365#endif
|
347 return(EINVAL);
| 366 error = EINVAL; 367 goto done2;
|
348 } 349 350 msqptr = &msqids[msqid]; 351 352 if (msqptr->msg_qbytes == 0) { 353#ifdef MSG_DEBUG_OK 354 printf("no such msqid\n"); 355#endif
| 368 } 369 370 msqptr = &msqids[msqid]; 371 372 if (msqptr->msg_qbytes == 0) { 373#ifdef MSG_DEBUG_OK 374 printf("no such msqid\n"); 375#endif
|
356 return(EINVAL);
| 376 error = EINVAL; 377 goto done2;
|
357 } 358 if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { 359#ifdef MSG_DEBUG_OK 360 printf("wrong sequence number\n"); 361#endif
| 378 } 379 if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { 380#ifdef MSG_DEBUG_OK 381 printf("wrong sequence number\n"); 382#endif
|
362 return(EINVAL);
| 383 error = EINVAL; 384 goto done2;
|
363 } 364
| 385 } 386
|
365 eval = 0;
| 387 error = 0;
|
366 rval = 0; 367 368 switch (cmd) { 369 370 case IPC_RMID: 371 { 372 struct msg *msghdr;
| 388 rval = 0; 389 390 switch (cmd) { 391 392 case IPC_RMID: 393 { 394 struct msg *msghdr;
|
373 if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_M))) 374 return(eval);
| 395 if ((error = ipcperm(p, &msqptr->msg_perm, IPC_M))) 396 goto done2;
|
375 /* Free the message headers */ 376 msghdr = msqptr->msg_first; 377 while (msghdr != NULL) { 378 struct msg *msghdr_tmp; 379 380 /* Free the segments of each message */ 381 msqptr->msg_cbytes -= msghdr->msg_ts; 382 msqptr->msg_qnum--; 383 msghdr_tmp = msghdr; 384 msghdr = msghdr->msg_next; 385 msg_freehdr(msghdr_tmp); 386 } 387 388 if (msqptr->msg_cbytes != 0) 389 panic("msg_cbytes is screwed up"); 390 if (msqptr->msg_qnum != 0) 391 panic("msg_qnum is screwed up"); 392 393 msqptr->msg_qbytes = 0; /* Mark it as free */ 394 395 wakeup((caddr_t)msqptr); 396 } 397 398 break; 399 400 case IPC_SET:
| 397 /* Free the message headers */ 398 msghdr = msqptr->msg_first; 399 while (msghdr != NULL) { 400 struct msg *msghdr_tmp; 401 402 /* Free the segments of each message */ 403 msqptr->msg_cbytes -= msghdr->msg_ts; 404 msqptr->msg_qnum--; 405 msghdr_tmp = msghdr; 406 msghdr = msghdr->msg_next; 407 msg_freehdr(msghdr_tmp); 408 } 409 410 if (msqptr->msg_cbytes != 0) 411 panic("msg_cbytes is screwed up"); 412 if (msqptr->msg_qnum != 0) 413 panic("msg_qnum is screwed up"); 414 415 msqptr->msg_qbytes = 0; /* Mark it as free */ 416 417 wakeup((caddr_t)msqptr); 418 } 419 420 break; 421 422 case IPC_SET:
|
401 if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_M))) 402 return(eval); 403 if ((eval = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0) 404 return(eval);
| 423 if ((error = ipcperm(p, &msqptr->msg_perm, IPC_M))) 424 goto done2; 425 if ((error = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0) 426 goto done2;
|
405 if (msqbuf.msg_qbytes > msqptr->msg_qbytes) {
| 427 if (msqbuf.msg_qbytes > msqptr->msg_qbytes) {
|
406 eval = suser(p); 407 if (eval) 408 return(eval);
| 428 error = suser(p); 429 if (error) 430 goto done2;
|
409 } 410 if (msqbuf.msg_qbytes > msginfo.msgmnb) { 411#ifdef MSG_DEBUG_OK 412 printf("can't increase msg_qbytes beyond %d (truncating)\n", 413 msginfo.msgmnb); 414#endif 415 msqbuf.msg_qbytes = msginfo.msgmnb; /* silently restrict qbytes to system limit */ 416 } 417 if (msqbuf.msg_qbytes == 0) { 418#ifdef MSG_DEBUG_OK 419 printf("can't reduce msg_qbytes to 0\n"); 420#endif
| 431 } 432 if (msqbuf.msg_qbytes > msginfo.msgmnb) { 433#ifdef MSG_DEBUG_OK 434 printf("can't increase msg_qbytes beyond %d (truncating)\n", 435 msginfo.msgmnb); 436#endif 437 msqbuf.msg_qbytes = msginfo.msgmnb; /* silently restrict qbytes to system limit */ 438 } 439 if (msqbuf.msg_qbytes == 0) { 440#ifdef MSG_DEBUG_OK 441 printf("can't reduce msg_qbytes to 0\n"); 442#endif
|
421 return(EINVAL); /* non-standard errno! */
| 443 error = EINVAL; /* non-standard errno! */ 444 goto done2;
|
422 } 423 msqptr->msg_perm.uid = msqbuf.msg_perm.uid; /* change the owner */ 424 msqptr->msg_perm.gid = msqbuf.msg_perm.gid; /* change the owner */ 425 msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777) | 426 (msqbuf.msg_perm.mode & 0777); 427 msqptr->msg_qbytes = msqbuf.msg_qbytes; 428 msqptr->msg_ctime = time_second; 429 break; 430 431 case IPC_STAT:
| 445 } 446 msqptr->msg_perm.uid = msqbuf.msg_perm.uid; /* change the owner */ 447 msqptr->msg_perm.gid = msqbuf.msg_perm.gid; /* change the owner */ 448 msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777) | 449 (msqbuf.msg_perm.mode & 0777); 450 msqptr->msg_qbytes = msqbuf.msg_qbytes; 451 msqptr->msg_ctime = time_second; 452 break; 453 454 case IPC_STAT:
|
432 if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_R))) {
| 455 if ((error = ipcperm(p, &msqptr->msg_perm, IPC_R))) {
|
433#ifdef MSG_DEBUG_OK 434 printf("requester doesn't have read access\n"); 435#endif
| 456#ifdef MSG_DEBUG_OK 457 printf("requester doesn't have read access\n"); 458#endif
|
436 return(eval);
| 459 goto done2;
|
437 }
| 460 }
|
438 eval = copyout((caddr_t)msqptr, user_msqptr,
| 461 error = copyout((caddr_t)msqptr, user_msqptr,
|
439 sizeof(struct msqid_ds)); 440 break; 441 442 default: 443#ifdef MSG_DEBUG_OK 444 printf("invalid command %d\n", cmd); 445#endif
| 462 sizeof(struct msqid_ds)); 463 break; 464 465 default: 466#ifdef MSG_DEBUG_OK 467 printf("invalid command %d\n", cmd); 468#endif
|
446 return(EINVAL);
| 469 error = EINVAL; 470 goto done2;
|
447 } 448
| 471 } 472
|
449 if (eval == 0)
| 473 if (error == 0)
|
450 p->p_retval[0] = rval;
| 474 p->p_retval[0] = rval;
|
451 return(eval);
| 475done2: 476 mtx_unlock(&Giant); 477 return(error);
|
452} 453 454#ifndef _SYS_SYSPROTO_H_ 455struct msgget_args { 456 key_t key; 457 int msgflg; 458}; 459#endif 460
| 478} 479 480#ifndef _SYS_SYSPROTO_H_ 481struct msgget_args { 482 key_t key; 483 int msgflg; 484}; 485#endif 486
|
| 487/* 488 * MPSAFE 489 */
|
461int 462msgget(p, uap) 463 struct proc *p; 464 register struct msgget_args *uap; 465{
| 490int 491msgget(p, uap) 492 struct proc *p; 493 register struct msgget_args *uap; 494{
|
466 int msqid, eval;
| 495 int msqid, error = 0;
|
467 int key = uap->key; 468 int msgflg = uap->msgflg; 469 struct ucred *cred = p->p_ucred; 470 register struct msqid_ds *msqptr = NULL; 471 472#ifdef MSG_DEBUG_OK 473 printf("msgget(0x%x, 0%o)\n", key, msgflg); 474#endif 475
| 496 int key = uap->key; 497 int msgflg = uap->msgflg; 498 struct ucred *cred = p->p_ucred; 499 register struct msqid_ds *msqptr = NULL; 500 501#ifdef MSG_DEBUG_OK 502 printf("msgget(0x%x, 0%o)\n", key, msgflg); 503#endif 504
|
476 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) 477 return (ENOSYS);
| 505 mtx_lock(&Giant);
|
478
| 506
|
| 507 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 508 error = ENOSYS; 509 goto done2; 510 } 511
|
479 if (key != IPC_PRIVATE) { 480 for (msqid = 0; msqid < msginfo.msgmni; msqid++) { 481 msqptr = &msqids[msqid]; 482 if (msqptr->msg_qbytes != 0 && 483 msqptr->msg_perm.key == key) 484 break; 485 } 486 if (msqid < msginfo.msgmni) { 487#ifdef MSG_DEBUG_OK 488 printf("found public key\n"); 489#endif 490 if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) { 491#ifdef MSG_DEBUG_OK 492 printf("not exclusive\n"); 493#endif
| 512 if (key != IPC_PRIVATE) { 513 for (msqid = 0; msqid < msginfo.msgmni; msqid++) { 514 msqptr = &msqids[msqid]; 515 if (msqptr->msg_qbytes != 0 && 516 msqptr->msg_perm.key == key) 517 break; 518 } 519 if (msqid < msginfo.msgmni) { 520#ifdef MSG_DEBUG_OK 521 printf("found public key\n"); 522#endif 523 if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) { 524#ifdef MSG_DEBUG_OK 525 printf("not exclusive\n"); 526#endif
|
494 return(EEXIST);
| 527 error = EEXIST; 528 goto done2;
|
495 }
| 529 }
|
496 if ((eval = ipcperm(p, &msqptr->msg_perm, msgflg & 0700 ))) {
| 530 if ((error = ipcperm(p, &msqptr->msg_perm, msgflg & 0700 ))) {
|
497#ifdef MSG_DEBUG_OK 498 printf("requester doesn't have 0%o access\n", 499 msgflg & 0700); 500#endif
| 531#ifdef MSG_DEBUG_OK 532 printf("requester doesn't have 0%o access\n", 533 msgflg & 0700); 534#endif
|
501 return(eval);
| 535 goto done2;
|
502 } 503 goto found; 504 } 505 } 506 507#ifdef MSG_DEBUG_OK 508 printf("need to allocate the msqid_ds\n"); 509#endif 510 if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) { 511 for (msqid = 0; msqid < msginfo.msgmni; msqid++) { 512 /* 513 * Look for an unallocated and unlocked msqid_ds. 514 * msqid_ds's can be locked by msgsnd or msgrcv while 515 * they are copying the message in/out. We can't 516 * re-use the entry until they release it. 517 */ 518 msqptr = &msqids[msqid]; 519 if (msqptr->msg_qbytes == 0 && 520 (msqptr->msg_perm.mode & MSG_LOCKED) == 0) 521 break; 522 } 523 if (msqid == msginfo.msgmni) { 524#ifdef MSG_DEBUG_OK 525 printf("no more msqid_ds's available\n"); 526#endif
| 536 } 537 goto found; 538 } 539 } 540 541#ifdef MSG_DEBUG_OK 542 printf("need to allocate the msqid_ds\n"); 543#endif 544 if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) { 545 for (msqid = 0; msqid < msginfo.msgmni; msqid++) { 546 /* 547 * Look for an unallocated and unlocked msqid_ds. 548 * msqid_ds's can be locked by msgsnd or msgrcv while 549 * they are copying the message in/out. We can't 550 * re-use the entry until they release it. 551 */ 552 msqptr = &msqids[msqid]; 553 if (msqptr->msg_qbytes == 0 && 554 (msqptr->msg_perm.mode & MSG_LOCKED) == 0) 555 break; 556 } 557 if (msqid == msginfo.msgmni) { 558#ifdef MSG_DEBUG_OK 559 printf("no more msqid_ds's available\n"); 560#endif
|
527 return(ENOSPC);
| 561 error = ENOSPC; 562 goto done2;
|
528 } 529#ifdef MSG_DEBUG_OK 530 printf("msqid %d is available\n", msqid); 531#endif 532 msqptr->msg_perm.key = key; 533 msqptr->msg_perm.cuid = cred->cr_uid; 534 msqptr->msg_perm.uid = cred->cr_uid; 535 msqptr->msg_perm.cgid = cred->cr_gid; 536 msqptr->msg_perm.gid = cred->cr_gid; 537 msqptr->msg_perm.mode = (msgflg & 0777); 538 /* Make sure that the returned msqid is unique */ 539 msqptr->msg_perm.seq++; 540 msqptr->msg_first = NULL; 541 msqptr->msg_last = NULL; 542 msqptr->msg_cbytes = 0; 543 msqptr->msg_qnum = 0; 544 msqptr->msg_qbytes = msginfo.msgmnb; 545 msqptr->msg_lspid = 0; 546 msqptr->msg_lrpid = 0; 547 msqptr->msg_stime = 0; 548 msqptr->msg_rtime = 0; 549 msqptr->msg_ctime = time_second; 550 } else { 551#ifdef MSG_DEBUG_OK 552 printf("didn't find it and wasn't asked to create it\n"); 553#endif
| 563 } 564#ifdef MSG_DEBUG_OK 565 printf("msqid %d is available\n", msqid); 566#endif 567 msqptr->msg_perm.key = key; 568 msqptr->msg_perm.cuid = cred->cr_uid; 569 msqptr->msg_perm.uid = cred->cr_uid; 570 msqptr->msg_perm.cgid = cred->cr_gid; 571 msqptr->msg_perm.gid = cred->cr_gid; 572 msqptr->msg_perm.mode = (msgflg & 0777); 573 /* Make sure that the returned msqid is unique */ 574 msqptr->msg_perm.seq++; 575 msqptr->msg_first = NULL; 576 msqptr->msg_last = NULL; 577 msqptr->msg_cbytes = 0; 578 msqptr->msg_qnum = 0; 579 msqptr->msg_qbytes = msginfo.msgmnb; 580 msqptr->msg_lspid = 0; 581 msqptr->msg_lrpid = 0; 582 msqptr->msg_stime = 0; 583 msqptr->msg_rtime = 0; 584 msqptr->msg_ctime = time_second; 585 } else { 586#ifdef MSG_DEBUG_OK 587 printf("didn't find it and wasn't asked to create it\n"); 588#endif
|
554 return(ENOENT);
| 589 error = ENOENT; 590 goto done2;
|
555 } 556 557found: 558 /* Construct the unique msqid */ 559 p->p_retval[0] = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm);
| 591 } 592 593found: 594 /* Construct the unique msqid */ 595 p->p_retval[0] = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm);
|
560 return(0);
| 596done2: 597 mtx_unlock(&Giant); 598 return (error);
|
561} 562 563#ifndef _SYS_SYSPROTO_H_ 564struct msgsnd_args { 565 int msqid; 566 void *msgp; 567 size_t msgsz; 568 int msgflg; 569}; 570#endif 571
| 599} 600 601#ifndef _SYS_SYSPROTO_H_ 602struct msgsnd_args { 603 int msqid; 604 void *msgp; 605 size_t msgsz; 606 int msgflg; 607}; 608#endif 609
|
| 610/* 611 * MPSAFE 612 */
|
572int 573msgsnd(p, uap) 574 struct proc *p; 575 register struct msgsnd_args *uap; 576{ 577 int msqid = uap->msqid; 578 void *user_msgp = uap->msgp; 579 size_t msgsz = uap->msgsz; 580 int msgflg = uap->msgflg;
| 613int 614msgsnd(p, uap) 615 struct proc *p; 616 register struct msgsnd_args *uap; 617{ 618 int msqid = uap->msqid; 619 void *user_msgp = uap->msgp; 620 size_t msgsz = uap->msgsz; 621 int msgflg = uap->msgflg;
|
581 int segs_needed, eval;
| 622 int segs_needed, error = 0;
|
582 register struct msqid_ds *msqptr; 583 register struct msg *msghdr; 584 short next; 585 586#ifdef MSG_DEBUG_OK 587 printf("call to msgsnd(%d, 0x%x, %d, %d)\n", msqid, user_msgp, msgsz, 588 msgflg); 589#endif
| 623 register struct msqid_ds *msqptr; 624 register struct msg *msghdr; 625 short next; 626 627#ifdef MSG_DEBUG_OK 628 printf("call to msgsnd(%d, 0x%x, %d, %d)\n", msqid, user_msgp, msgsz, 629 msgflg); 630#endif
|
| 631 mtx_lock(&Giant);
|
590
| 632
|
591 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) 592 return (ENOSYS);
| 633 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 634 error = ENOSYS; 635 goto done2; 636 }
|
593 594 msqid = IPCID_TO_IX(msqid); 595 596 if (msqid < 0 || msqid >= msginfo.msgmni) { 597#ifdef MSG_DEBUG_OK 598 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, 599 msginfo.msgmni); 600#endif
| 637 638 msqid = IPCID_TO_IX(msqid); 639 640 if (msqid < 0 || msqid >= msginfo.msgmni) { 641#ifdef MSG_DEBUG_OK 642 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, 643 msginfo.msgmni); 644#endif
|
601 return(EINVAL);
| 645 error = EINVAL; 646 goto done2;
|
602 } 603 604 msqptr = &msqids[msqid]; 605 if (msqptr->msg_qbytes == 0) { 606#ifdef MSG_DEBUG_OK 607 printf("no such message queue id\n"); 608#endif
| 647 } 648 649 msqptr = &msqids[msqid]; 650 if (msqptr->msg_qbytes == 0) { 651#ifdef MSG_DEBUG_OK 652 printf("no such message queue id\n"); 653#endif
|
609 return(EINVAL);
| 654 error = EINVAL; 655 goto done2;
|
610 } 611 if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { 612#ifdef MSG_DEBUG_OK 613 printf("wrong sequence number\n"); 614#endif
| 656 } 657 if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { 658#ifdef MSG_DEBUG_OK 659 printf("wrong sequence number\n"); 660#endif
|
615 return(EINVAL);
| 661 error = EINVAL; 662 goto done2;
|
616 } 617
| 663 } 664
|
618 if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_W))) {
| 665 if ((error = ipcperm(p, &msqptr->msg_perm, IPC_W))) {
|
619#ifdef MSG_DEBUG_OK 620 printf("requester doesn't have write access\n"); 621#endif
| 666#ifdef MSG_DEBUG_OK 667 printf("requester doesn't have write access\n"); 668#endif
|
622 return(eval);
| 669 goto done2;
|
623 } 624 625 segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz; 626#ifdef MSG_DEBUG_OK 627 printf("msgsz=%d, msgssz=%d, segs_needed=%d\n", msgsz, msginfo.msgssz, 628 segs_needed); 629#endif 630 for (;;) { 631 int need_more_resources = 0; 632 633 /* 634 * check msgsz 635 * (inside this loop in case msg_qbytes changes while we sleep) 636 */ 637 638 if (msgsz > msqptr->msg_qbytes) { 639#ifdef MSG_DEBUG_OK 640 printf("msgsz > msqptr->msg_qbytes\n"); 641#endif
| 670 } 671 672 segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz; 673#ifdef MSG_DEBUG_OK 674 printf("msgsz=%d, msgssz=%d, segs_needed=%d\n", msgsz, msginfo.msgssz, 675 segs_needed); 676#endif 677 for (;;) { 678 int need_more_resources = 0; 679 680 /* 681 * check msgsz 682 * (inside this loop in case msg_qbytes changes while we sleep) 683 */ 684 685 if (msgsz > msqptr->msg_qbytes) { 686#ifdef MSG_DEBUG_OK 687 printf("msgsz > msqptr->msg_qbytes\n"); 688#endif
|
642 return(EINVAL);
| 689 error = EINVAL; 690 goto done2;
|
643 } 644 645 if (msqptr->msg_perm.mode & MSG_LOCKED) { 646#ifdef MSG_DEBUG_OK 647 printf("msqid is locked\n"); 648#endif 649 need_more_resources = 1; 650 } 651 if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes) { 652#ifdef MSG_DEBUG_OK 653 printf("msgsz + msg_cbytes > msg_qbytes\n"); 654#endif 655 need_more_resources = 1; 656 } 657 if (segs_needed > nfree_msgmaps) { 658#ifdef MSG_DEBUG_OK 659 printf("segs_needed > nfree_msgmaps\n"); 660#endif 661 need_more_resources = 1; 662 } 663 if (free_msghdrs == NULL) { 664#ifdef MSG_DEBUG_OK 665 printf("no more msghdrs\n"); 666#endif 667 need_more_resources = 1; 668 } 669 670 if (need_more_resources) { 671 int we_own_it; 672 673 if ((msgflg & IPC_NOWAIT) != 0) { 674#ifdef MSG_DEBUG_OK 675 printf("need more resources but caller doesn't want to wait\n"); 676#endif
| 691 } 692 693 if (msqptr->msg_perm.mode & MSG_LOCKED) { 694#ifdef MSG_DEBUG_OK 695 printf("msqid is locked\n"); 696#endif 697 need_more_resources = 1; 698 } 699 if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes) { 700#ifdef MSG_DEBUG_OK 701 printf("msgsz + msg_cbytes > msg_qbytes\n"); 702#endif 703 need_more_resources = 1; 704 } 705 if (segs_needed > nfree_msgmaps) { 706#ifdef MSG_DEBUG_OK 707 printf("segs_needed > nfree_msgmaps\n"); 708#endif 709 need_more_resources = 1; 710 } 711 if (free_msghdrs == NULL) { 712#ifdef MSG_DEBUG_OK 713 printf("no more msghdrs\n"); 714#endif 715 need_more_resources = 1; 716 } 717 718 if (need_more_resources) { 719 int we_own_it; 720 721 if ((msgflg & IPC_NOWAIT) != 0) { 722#ifdef MSG_DEBUG_OK 723 printf("need more resources but caller doesn't want to wait\n"); 724#endif
|
677 return(EAGAIN);
| 725 error = EAGAIN; 726 goto done2;
|
678 } 679 680 if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) { 681#ifdef MSG_DEBUG_OK 682 printf("we don't own the msqid_ds\n"); 683#endif 684 we_own_it = 0; 685 } else { 686 /* Force later arrivals to wait for our 687 request */ 688#ifdef MSG_DEBUG_OK 689 printf("we own the msqid_ds\n"); 690#endif 691 msqptr->msg_perm.mode |= MSG_LOCKED; 692 we_own_it = 1; 693 } 694#ifdef MSG_DEBUG_OK 695 printf("goodnight\n"); 696#endif
| 727 } 728 729 if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) { 730#ifdef MSG_DEBUG_OK 731 printf("we don't own the msqid_ds\n"); 732#endif 733 we_own_it = 0; 734 } else { 735 /* Force later arrivals to wait for our 736 request */ 737#ifdef MSG_DEBUG_OK 738 printf("we own the msqid_ds\n"); 739#endif 740 msqptr->msg_perm.mode |= MSG_LOCKED; 741 we_own_it = 1; 742 } 743#ifdef MSG_DEBUG_OK 744 printf("goodnight\n"); 745#endif
|
697 eval = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH,
| 746 error = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH,
|
698 "msgwait", 0); 699#ifdef MSG_DEBUG_OK
| 747 "msgwait", 0); 748#ifdef MSG_DEBUG_OK
|
700 printf("good morning, eval=%d\n", eval);
| 749 printf("good morning, error=%d\n", error);
|
701#endif 702 if (we_own_it) 703 msqptr->msg_perm.mode &= ~MSG_LOCKED;
| 750#endif 751 if (we_own_it) 752 msqptr->msg_perm.mode &= ~MSG_LOCKED;
|
704 if (eval != 0) {
| 753 if (error != 0) {
|
705#ifdef MSG_DEBUG_OK 706 printf("msgsnd: interrupted system call\n"); 707#endif
| 754#ifdef MSG_DEBUG_OK 755 printf("msgsnd: interrupted system call\n"); 756#endif
|
708 return(EINTR);
| 757 error = EINTR; 758 goto done2;
|
709 } 710 711 /* 712 * Make sure that the msq queue still exists 713 */ 714 715 if (msqptr->msg_qbytes == 0) { 716#ifdef MSG_DEBUG_OK 717 printf("msqid deleted\n"); 718#endif
| 759 } 760 761 /* 762 * Make sure that the msq queue still exists 763 */ 764 765 if (msqptr->msg_qbytes == 0) { 766#ifdef MSG_DEBUG_OK 767 printf("msqid deleted\n"); 768#endif
|
719 return(EIDRM);
| 769 error = EIDRM; 770 goto done2;
|
720 } 721 722 } else { 723#ifdef MSG_DEBUG_OK 724 printf("got all the resources that we need\n"); 725#endif 726 break; 727 } 728 } 729 730 /* 731 * We have the resources that we need. 732 * Make sure! 733 */ 734 735 if (msqptr->msg_perm.mode & MSG_LOCKED) 736 panic("msg_perm.mode & MSG_LOCKED"); 737 if (segs_needed > nfree_msgmaps) 738 panic("segs_needed > nfree_msgmaps"); 739 if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes) 740 panic("msgsz + msg_cbytes > msg_qbytes"); 741 if (free_msghdrs == NULL) 742 panic("no more msghdrs"); 743 744 /* 745 * Re-lock the msqid_ds in case we page-fault when copying in the 746 * message 747 */ 748 749 if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) 750 panic("msqid_ds is already locked"); 751 msqptr->msg_perm.mode |= MSG_LOCKED; 752 753 /* 754 * Allocate a message header 755 */ 756 757 msghdr = free_msghdrs; 758 free_msghdrs = msghdr->msg_next; 759 msghdr->msg_spot = -1; 760 msghdr->msg_ts = msgsz; 761 762 /* 763 * Allocate space for the message 764 */ 765 766 while (segs_needed > 0) { 767 if (nfree_msgmaps <= 0) 768 panic("not enough msgmaps"); 769 if (free_msgmaps == -1) 770 panic("nil free_msgmaps"); 771 next = free_msgmaps; 772 if (next <= -1) 773 panic("next too low #1"); 774 if (next >= msginfo.msgseg) 775 panic("next out of range #1"); 776#ifdef MSG_DEBUG_OK 777 printf("allocating segment %d to message\n", next); 778#endif 779 free_msgmaps = msgmaps[next].next; 780 nfree_msgmaps--; 781 msgmaps[next].next = msghdr->msg_spot; 782 msghdr->msg_spot = next; 783 segs_needed--; 784 } 785 786 /* 787 * Copy in the message type 788 */ 789
| 771 } 772 773 } else { 774#ifdef MSG_DEBUG_OK 775 printf("got all the resources that we need\n"); 776#endif 777 break; 778 } 779 } 780 781 /* 782 * We have the resources that we need. 783 * Make sure! 784 */ 785 786 if (msqptr->msg_perm.mode & MSG_LOCKED) 787 panic("msg_perm.mode & MSG_LOCKED"); 788 if (segs_needed > nfree_msgmaps) 789 panic("segs_needed > nfree_msgmaps"); 790 if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes) 791 panic("msgsz + msg_cbytes > msg_qbytes"); 792 if (free_msghdrs == NULL) 793 panic("no more msghdrs"); 794 795 /* 796 * Re-lock the msqid_ds in case we page-fault when copying in the 797 * message 798 */ 799 800 if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) 801 panic("msqid_ds is already locked"); 802 msqptr->msg_perm.mode |= MSG_LOCKED; 803 804 /* 805 * Allocate a message header 806 */ 807 808 msghdr = free_msghdrs; 809 free_msghdrs = msghdr->msg_next; 810 msghdr->msg_spot = -1; 811 msghdr->msg_ts = msgsz; 812 813 /* 814 * Allocate space for the message 815 */ 816 817 while (segs_needed > 0) { 818 if (nfree_msgmaps <= 0) 819 panic("not enough msgmaps"); 820 if (free_msgmaps == -1) 821 panic("nil free_msgmaps"); 822 next = free_msgmaps; 823 if (next <= -1) 824 panic("next too low #1"); 825 if (next >= msginfo.msgseg) 826 panic("next out of range #1"); 827#ifdef MSG_DEBUG_OK 828 printf("allocating segment %d to message\n", next); 829#endif 830 free_msgmaps = msgmaps[next].next; 831 nfree_msgmaps--; 832 msgmaps[next].next = msghdr->msg_spot; 833 msghdr->msg_spot = next; 834 segs_needed--; 835 } 836 837 /* 838 * Copy in the message type 839 */ 840
|
790 if ((eval = copyin(user_msgp, &msghdr->msg_type,
| 841 if ((error = copyin(user_msgp, &msghdr->msg_type,
|
791 sizeof(msghdr->msg_type))) != 0) { 792#ifdef MSG_DEBUG_OK
| 842 sizeof(msghdr->msg_type))) != 0) { 843#ifdef MSG_DEBUG_OK
|
793 printf("error %d copying the message type\n", eval);
| 844 printf("error %d copying the message type\n", error);
|
794#endif 795 msg_freehdr(msghdr); 796 msqptr->msg_perm.mode &= ~MSG_LOCKED; 797 wakeup((caddr_t)msqptr);
| 845#endif 846 msg_freehdr(msghdr); 847 msqptr->msg_perm.mode &= ~MSG_LOCKED; 848 wakeup((caddr_t)msqptr);
|
798 return(eval);
| 849 goto done2;
|
799 } 800 user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); 801 802 /* 803 * Validate the message type 804 */ 805 806 if (msghdr->msg_type < 1) { 807 msg_freehdr(msghdr); 808 msqptr->msg_perm.mode &= ~MSG_LOCKED; 809 wakeup((caddr_t)msqptr); 810#ifdef MSG_DEBUG_OK 811 printf("mtype (%d) < 1\n", msghdr->msg_type); 812#endif
| 850 } 851 user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); 852 853 /* 854 * Validate the message type 855 */ 856 857 if (msghdr->msg_type < 1) { 858 msg_freehdr(msghdr); 859 msqptr->msg_perm.mode &= ~MSG_LOCKED; 860 wakeup((caddr_t)msqptr); 861#ifdef MSG_DEBUG_OK 862 printf("mtype (%d) < 1\n", msghdr->msg_type); 863#endif
|
813 return(EINVAL);
| 864 error = EINVAL; 865 goto done2;
|
814 } 815 816 /* 817 * Copy in the message body 818 */ 819 820 next = msghdr->msg_spot; 821 while (msgsz > 0) { 822 size_t tlen; 823 if (msgsz > msginfo.msgssz) 824 tlen = msginfo.msgssz; 825 else 826 tlen = msgsz; 827 if (next <= -1) 828 panic("next too low #2"); 829 if (next >= msginfo.msgseg) 830 panic("next out of range #2");
| 866 } 867 868 /* 869 * Copy in the message body 870 */ 871 872 next = msghdr->msg_spot; 873 while (msgsz > 0) { 874 size_t tlen; 875 if (msgsz > msginfo.msgssz) 876 tlen = msginfo.msgssz; 877 else 878 tlen = msgsz; 879 if (next <= -1) 880 panic("next too low #2"); 881 if (next >= msginfo.msgseg) 882 panic("next out of range #2");
|
831 if ((eval = copyin(user_msgp, &msgpool[next * msginfo.msgssz],
| 883 if ((error = copyin(user_msgp, &msgpool[next * msginfo.msgssz],
|
832 tlen)) != 0) { 833#ifdef MSG_DEBUG_OK
| 884 tlen)) != 0) { 885#ifdef MSG_DEBUG_OK
|
834 printf("error %d copying in message segment\n", eval);
| 886 printf("error %d copying in message segment\n", error);
|
835#endif 836 msg_freehdr(msghdr); 837 msqptr->msg_perm.mode &= ~MSG_LOCKED; 838 wakeup((caddr_t)msqptr);
| 887#endif 888 msg_freehdr(msghdr); 889 msqptr->msg_perm.mode &= ~MSG_LOCKED; 890 wakeup((caddr_t)msqptr);
|
839 return(eval);
| 891 goto done2;
|
840 } 841 msgsz -= tlen; 842 user_msgp = (char *)user_msgp + tlen; 843 next = msgmaps[next].next; 844 } 845 if (next != -1) 846 panic("didn't use all the msg segments"); 847 848 /* 849 * We've got the message. Unlock the msqid_ds. 850 */ 851 852 msqptr->msg_perm.mode &= ~MSG_LOCKED; 853 854 /* 855 * Make sure that the msqid_ds is still allocated. 856 */ 857 858 if (msqptr->msg_qbytes == 0) { 859 msg_freehdr(msghdr); 860 wakeup((caddr_t)msqptr);
| 892 } 893 msgsz -= tlen; 894 user_msgp = (char *)user_msgp + tlen; 895 next = msgmaps[next].next; 896 } 897 if (next != -1) 898 panic("didn't use all the msg segments"); 899 900 /* 901 * We've got the message. Unlock the msqid_ds. 902 */ 903 904 msqptr->msg_perm.mode &= ~MSG_LOCKED; 905 906 /* 907 * Make sure that the msqid_ds is still allocated. 908 */ 909 910 if (msqptr->msg_qbytes == 0) { 911 msg_freehdr(msghdr); 912 wakeup((caddr_t)msqptr);
|
861 return(EIDRM);
| 913 error = EIDRM; 914 goto done2;
|
862 } 863 864 /* 865 * Put the message into the queue 866 */ 867 868 if (msqptr->msg_first == NULL) { 869 msqptr->msg_first = msghdr; 870 msqptr->msg_last = msghdr; 871 } else { 872 msqptr->msg_last->msg_next = msghdr; 873 msqptr->msg_last = msghdr; 874 } 875 msqptr->msg_last->msg_next = NULL; 876 877 msqptr->msg_cbytes += msghdr->msg_ts; 878 msqptr->msg_qnum++; 879 msqptr->msg_lspid = p->p_pid; 880 msqptr->msg_stime = time_second; 881 882 wakeup((caddr_t)msqptr); 883 p->p_retval[0] = 0;
| 915 } 916 917 /* 918 * Put the message into the queue 919 */ 920 921 if (msqptr->msg_first == NULL) { 922 msqptr->msg_first = msghdr; 923 msqptr->msg_last = msghdr; 924 } else { 925 msqptr->msg_last->msg_next = msghdr; 926 msqptr->msg_last = msghdr; 927 } 928 msqptr->msg_last->msg_next = NULL; 929 930 msqptr->msg_cbytes += msghdr->msg_ts; 931 msqptr->msg_qnum++; 932 msqptr->msg_lspid = p->p_pid; 933 msqptr->msg_stime = time_second; 934 935 wakeup((caddr_t)msqptr); 936 p->p_retval[0] = 0;
|
884 return(0);
| 937done2: 938 mtx_unlock(&Giant); 939 return (error);
|
885} 886 887#ifndef _SYS_SYSPROTO_H_ 888struct msgrcv_args { 889 int msqid; 890 void *msgp; 891 size_t msgsz; 892 long msgtyp; 893 int msgflg; 894}; 895#endif 896
| 940} 941 942#ifndef _SYS_SYSPROTO_H_ 943struct msgrcv_args { 944 int msqid; 945 void *msgp; 946 size_t msgsz; 947 long msgtyp; 948 int msgflg; 949}; 950#endif 951
|
| 952/* 953 * MPSAFE 954 */
|
897int 898msgrcv(p, uap) 899 struct proc *p; 900 register struct msgrcv_args *uap; 901{ 902 int msqid = uap->msqid; 903 void *user_msgp = uap->msgp; 904 size_t msgsz = uap->msgsz; 905 long msgtyp = uap->msgtyp; 906 int msgflg = uap->msgflg; 907 size_t len; 908 register struct msqid_ds *msqptr; 909 register struct msg *msghdr;
| 955int 956msgrcv(p, uap) 957 struct proc *p; 958 register struct msgrcv_args *uap; 959{ 960 int msqid = uap->msqid; 961 void *user_msgp = uap->msgp; 962 size_t msgsz = uap->msgsz; 963 long msgtyp = uap->msgtyp; 964 int msgflg = uap->msgflg; 965 size_t len; 966 register struct msqid_ds *msqptr; 967 register struct msg *msghdr;
|
910 int eval;
| 968 int error = 0;
|
911 short next; 912 913#ifdef MSG_DEBUG_OK 914 printf("call to msgrcv(%d, 0x%x, %d, %ld, %d)\n", msqid, user_msgp, 915 msgsz, msgtyp, msgflg); 916#endif 917
| 969 short next; 970 971#ifdef MSG_DEBUG_OK 972 printf("call to msgrcv(%d, 0x%x, %d, %ld, %d)\n", msqid, user_msgp, 973 msgsz, msgtyp, msgflg); 974#endif 975
|
918 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) 919 return (ENOSYS);
| 976 mtx_lock(&Giant);
|
920
| 977
|
| 978 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 979 error = ENOSYS; 980 goto done2; 981 } 982
|
921 msqid = IPCID_TO_IX(msqid); 922 923 if (msqid < 0 || msqid >= msginfo.msgmni) { 924#ifdef MSG_DEBUG_OK 925 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, 926 msginfo.msgmni); 927#endif
| 983 msqid = IPCID_TO_IX(msqid); 984 985 if (msqid < 0 || msqid >= msginfo.msgmni) { 986#ifdef MSG_DEBUG_OK 987 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, 988 msginfo.msgmni); 989#endif
|
928 return(EINVAL);
| 990 error = EINVAL; 991 goto done2;
|
929 } 930 931 msqptr = &msqids[msqid]; 932 if (msqptr->msg_qbytes == 0) { 933#ifdef MSG_DEBUG_OK 934 printf("no such message queue id\n"); 935#endif
| 992 } 993 994 msqptr = &msqids[msqid]; 995 if (msqptr->msg_qbytes == 0) { 996#ifdef MSG_DEBUG_OK 997 printf("no such message queue id\n"); 998#endif
|
936 return(EINVAL);
| 999 error = EINVAL; 1000 goto done2;
|
937 } 938 if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { 939#ifdef MSG_DEBUG_OK 940 printf("wrong sequence number\n"); 941#endif
| 1001 } 1002 if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { 1003#ifdef MSG_DEBUG_OK 1004 printf("wrong sequence number\n"); 1005#endif
|
942 return(EINVAL);
| 1006 error = EINVAL; 1007 goto done2;
|
943 } 944
| 1008 } 1009
|
945 if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_R))) {
| 1010 if ((error = ipcperm(p, &msqptr->msg_perm, IPC_R))) {
|
946#ifdef MSG_DEBUG_OK 947 printf("requester doesn't have read access\n"); 948#endif
| 1011#ifdef MSG_DEBUG_OK 1012 printf("requester doesn't have read access\n"); 1013#endif
|
949 return(eval);
| 1014 goto done2;
|
950 } 951 952 msghdr = NULL; 953 while (msghdr == NULL) { 954 if (msgtyp == 0) { 955 msghdr = msqptr->msg_first; 956 if (msghdr != NULL) { 957 if (msgsz < msghdr->msg_ts && 958 (msgflg & MSG_NOERROR) == 0) { 959#ifdef MSG_DEBUG_OK 960 printf("first message on the queue is too big (want %d, got %d)\n", 961 msgsz, msghdr->msg_ts); 962#endif
| 1015 } 1016 1017 msghdr = NULL; 1018 while (msghdr == NULL) { 1019 if (msgtyp == 0) { 1020 msghdr = msqptr->msg_first; 1021 if (msghdr != NULL) { 1022 if (msgsz < msghdr->msg_ts && 1023 (msgflg & MSG_NOERROR) == 0) { 1024#ifdef MSG_DEBUG_OK 1025 printf("first message on the queue is too big (want %d, got %d)\n", 1026 msgsz, msghdr->msg_ts); 1027#endif
|
963 return(E2BIG);
| 1028 error = E2BIG; 1029 goto done2;
|
964 } 965 if (msqptr->msg_first == msqptr->msg_last) { 966 msqptr->msg_first = NULL; 967 msqptr->msg_last = NULL; 968 } else { 969 msqptr->msg_first = msghdr->msg_next; 970 if (msqptr->msg_first == NULL) 971 panic("msg_first/last screwed up #1"); 972 } 973 } 974 } else { 975 struct msg *previous; 976 struct msg **prev; 977 978 previous = NULL; 979 prev = &(msqptr->msg_first); 980 while ((msghdr = *prev) != NULL) { 981 /* 982 * Is this message's type an exact match or is 983 * this message's type less than or equal to 984 * the absolute value of a negative msgtyp? 985 * Note that the second half of this test can 986 * NEVER be true if msgtyp is positive since 987 * msg_type is always positive! 988 */ 989 990 if (msgtyp == msghdr->msg_type || 991 msghdr->msg_type <= -msgtyp) { 992#ifdef MSG_DEBUG_OK 993 printf("found message type %d, requested %d\n", 994 msghdr->msg_type, msgtyp); 995#endif 996 if (msgsz < msghdr->msg_ts && 997 (msgflg & MSG_NOERROR) == 0) { 998#ifdef MSG_DEBUG_OK 999 printf("requested message on the queue is too big (want %d, got %d)\n", 1000 msgsz, msghdr->msg_ts); 1001#endif
| 1030 } 1031 if (msqptr->msg_first == msqptr->msg_last) { 1032 msqptr->msg_first = NULL; 1033 msqptr->msg_last = NULL; 1034 } else { 1035 msqptr->msg_first = msghdr->msg_next; 1036 if (msqptr->msg_first == NULL) 1037 panic("msg_first/last screwed up #1"); 1038 } 1039 } 1040 } else { 1041 struct msg *previous; 1042 struct msg **prev; 1043 1044 previous = NULL; 1045 prev = &(msqptr->msg_first); 1046 while ((msghdr = *prev) != NULL) { 1047 /* 1048 * Is this message's type an exact match or is 1049 * this message's type less than or equal to 1050 * the absolute value of a negative msgtyp? 1051 * Note that the second half of this test can 1052 * NEVER be true if msgtyp is positive since 1053 * msg_type is always positive! 1054 */ 1055 1056 if (msgtyp == msghdr->msg_type || 1057 msghdr->msg_type <= -msgtyp) { 1058#ifdef MSG_DEBUG_OK 1059 printf("found message type %d, requested %d\n", 1060 msghdr->msg_type, msgtyp); 1061#endif 1062 if (msgsz < msghdr->msg_ts && 1063 (msgflg & MSG_NOERROR) == 0) { 1064#ifdef MSG_DEBUG_OK 1065 printf("requested message on the queue is too big (want %d, got %d)\n", 1066 msgsz, msghdr->msg_ts); 1067#endif
|
1002 return(E2BIG);
| 1068 error = E2BIG; 1069 goto done2;
|
1003 } 1004 *prev = msghdr->msg_next; 1005 if (msghdr == msqptr->msg_last) { 1006 if (previous == NULL) { 1007 if (prev != 1008 &msqptr->msg_first) 1009 panic("msg_first/last screwed up #2"); 1010 msqptr->msg_first = 1011 NULL; 1012 msqptr->msg_last = 1013 NULL; 1014 } else { 1015 if (prev == 1016 &msqptr->msg_first) 1017 panic("msg_first/last screwed up #3"); 1018 msqptr->msg_last = 1019 previous; 1020 } 1021 } 1022 break; 1023 } 1024 previous = msghdr; 1025 prev = &(msghdr->msg_next); 1026 } 1027 } 1028 1029 /* 1030 * We've either extracted the msghdr for the appropriate 1031 * message or there isn't one. 1032 * If there is one then bail out of this loop. 1033 */ 1034 1035 if (msghdr != NULL) 1036 break; 1037 1038 /* 1039 * Hmph! No message found. Does the user want to wait? 1040 */ 1041 1042 if ((msgflg & IPC_NOWAIT) != 0) { 1043#ifdef MSG_DEBUG_OK 1044 printf("no appropriate message found (msgtyp=%d)\n", 1045 msgtyp); 1046#endif 1047 /* The SVID says to return ENOMSG. */
| 1070 } 1071 *prev = msghdr->msg_next; 1072 if (msghdr == msqptr->msg_last) { 1073 if (previous == NULL) { 1074 if (prev != 1075 &msqptr->msg_first) 1076 panic("msg_first/last screwed up #2"); 1077 msqptr->msg_first = 1078 NULL; 1079 msqptr->msg_last = 1080 NULL; 1081 } else { 1082 if (prev == 1083 &msqptr->msg_first) 1084 panic("msg_first/last screwed up #3"); 1085 msqptr->msg_last = 1086 previous; 1087 } 1088 } 1089 break; 1090 } 1091 previous = msghdr; 1092 prev = &(msghdr->msg_next); 1093 } 1094 } 1095 1096 /* 1097 * We've either extracted the msghdr for the appropriate 1098 * message or there isn't one. 1099 * If there is one then bail out of this loop. 1100 */ 1101 1102 if (msghdr != NULL) 1103 break; 1104 1105 /* 1106 * Hmph! No message found. Does the user want to wait? 1107 */ 1108 1109 if ((msgflg & IPC_NOWAIT) != 0) { 1110#ifdef MSG_DEBUG_OK 1111 printf("no appropriate message found (msgtyp=%d)\n", 1112 msgtyp); 1113#endif 1114 /* The SVID says to return ENOMSG. */
|
1048 return(ENOMSG);
| 1115 error = ENOMSG; 1116 goto done2;
|
1049 } 1050 1051 /* 1052 * Wait for something to happen 1053 */ 1054 1055#ifdef MSG_DEBUG_OK 1056 printf("msgrcv: goodnight\n"); 1057#endif
| 1117 } 1118 1119 /* 1120 * Wait for something to happen 1121 */ 1122 1123#ifdef MSG_DEBUG_OK 1124 printf("msgrcv: goodnight\n"); 1125#endif
|
1058 eval = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, "msgwait",
| 1126 error = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, "msgwait",
|
1059 0); 1060#ifdef MSG_DEBUG_OK
| 1127 0); 1128#ifdef MSG_DEBUG_OK
|
1061 printf("msgrcv: good morning (eval=%d)\n", eval);
| 1129 printf("msgrcv: good morning (error=%d)\n", error);
|
1062#endif 1063
| 1130#endif 1131
|
1064 if (eval != 0) {
| 1132 if (error != 0) {
|
1065#ifdef MSG_DEBUG_OK 1066 printf("msgsnd: interrupted system call\n"); 1067#endif
| 1133#ifdef MSG_DEBUG_OK 1134 printf("msgsnd: interrupted system call\n"); 1135#endif
|
1068 return(EINTR);
| 1136 error = EINTR; 1137 goto done2;
|
1069 } 1070 1071 /* 1072 * Make sure that the msq queue still exists 1073 */ 1074 1075 if (msqptr->msg_qbytes == 0 || 1076 msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { 1077#ifdef MSG_DEBUG_OK 1078 printf("msqid deleted\n"); 1079#endif
| 1138 } 1139 1140 /* 1141 * Make sure that the msq queue still exists 1142 */ 1143 1144 if (msqptr->msg_qbytes == 0 || 1145 msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { 1146#ifdef MSG_DEBUG_OK 1147 printf("msqid deleted\n"); 1148#endif
|
1080 return(EIDRM);
| 1149 error = EIDRM; 1150 goto done2;
|
1081 } 1082 } 1083 1084 /* 1085 * Return the message to the user. 1086 * 1087 * First, do the bookkeeping (before we risk being interrupted). 1088 */ 1089 1090 msqptr->msg_cbytes -= msghdr->msg_ts; 1091 msqptr->msg_qnum--; 1092 msqptr->msg_lrpid = p->p_pid; 1093 msqptr->msg_rtime = time_second; 1094 1095 /* 1096 * Make msgsz the actual amount that we'll be returning. 1097 * Note that this effectively truncates the message if it is too long 1098 * (since msgsz is never increased). 1099 */ 1100 1101#ifdef MSG_DEBUG_OK 1102 printf("found a message, msgsz=%d, msg_ts=%d\n", msgsz, 1103 msghdr->msg_ts); 1104#endif 1105 if (msgsz > msghdr->msg_ts) 1106 msgsz = msghdr->msg_ts; 1107 1108 /* 1109 * Return the type to the user. 1110 */ 1111
| 1151 } 1152 } 1153 1154 /* 1155 * Return the message to the user. 1156 * 1157 * First, do the bookkeeping (before we risk being interrupted). 1158 */ 1159 1160 msqptr->msg_cbytes -= msghdr->msg_ts; 1161 msqptr->msg_qnum--; 1162 msqptr->msg_lrpid = p->p_pid; 1163 msqptr->msg_rtime = time_second; 1164 1165 /* 1166 * Make msgsz the actual amount that we'll be returning. 1167 * Note that this effectively truncates the message if it is too long 1168 * (since msgsz is never increased). 1169 */ 1170 1171#ifdef MSG_DEBUG_OK 1172 printf("found a message, msgsz=%d, msg_ts=%d\n", msgsz, 1173 msghdr->msg_ts); 1174#endif 1175 if (msgsz > msghdr->msg_ts) 1176 msgsz = msghdr->msg_ts; 1177 1178 /* 1179 * Return the type to the user. 1180 */ 1181
|
1112 eval = copyout((caddr_t)&(msghdr->msg_type), user_msgp,
| 1182 error = copyout((caddr_t)&(msghdr->msg_type), user_msgp,
|
1113 sizeof(msghdr->msg_type));
| 1183 sizeof(msghdr->msg_type));
|
1114 if (eval != 0) {
| 1184 if (error != 0) {
|
1115#ifdef MSG_DEBUG_OK
| 1185#ifdef MSG_DEBUG_OK
|
1116 printf("error (%d) copying out message type\n", eval);
| 1186 printf("error (%d) copying out message type\n", error);
|
1117#endif 1118 msg_freehdr(msghdr); 1119 wakeup((caddr_t)msqptr);
| 1187#endif 1188 msg_freehdr(msghdr); 1189 wakeup((caddr_t)msqptr);
|
1120 return(eval);
| 1190 goto done2;
|
1121 } 1122 user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); 1123 1124 /* 1125 * Return the segments to the user 1126 */ 1127 1128 next = msghdr->msg_spot; 1129 for (len = 0; len < msgsz; len += msginfo.msgssz) { 1130 size_t tlen; 1131 1132 if (msgsz - len > msginfo.msgssz) 1133 tlen = msginfo.msgssz; 1134 else 1135 tlen = msgsz - len; 1136 if (next <= -1) 1137 panic("next too low #3"); 1138 if (next >= msginfo.msgseg) 1139 panic("next out of range #3");
| 1191 } 1192 user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); 1193 1194 /* 1195 * Return the segments to the user 1196 */ 1197 1198 next = msghdr->msg_spot; 1199 for (len = 0; len < msgsz; len += msginfo.msgssz) { 1200 size_t tlen; 1201 1202 if (msgsz - len > msginfo.msgssz) 1203 tlen = msginfo.msgssz; 1204 else 1205 tlen = msgsz - len; 1206 if (next <= -1) 1207 panic("next too low #3"); 1208 if (next >= msginfo.msgseg) 1209 panic("next out of range #3");
|
1140 eval = copyout((caddr_t)&msgpool[next * msginfo.msgssz],
| 1210 error = copyout((caddr_t)&msgpool[next * msginfo.msgssz],
|
1141 user_msgp, tlen);
| 1211 user_msgp, tlen);
|
1142 if (eval != 0) {
| 1212 if (error != 0) {
|
1143#ifdef MSG_DEBUG_OK 1144 printf("error (%d) copying out message segment\n",
| 1213#ifdef MSG_DEBUG_OK 1214 printf("error (%d) copying out message segment\n",
|
1145 eval);
| 1215 error);
|
1146#endif 1147 msg_freehdr(msghdr); 1148 wakeup((caddr_t)msqptr);
| 1216#endif 1217 msg_freehdr(msghdr); 1218 wakeup((caddr_t)msqptr);
|
1149 return(eval);
| 1219 goto done2;
|
1150 } 1151 user_msgp = (char *)user_msgp + tlen; 1152 next = msgmaps[next].next; 1153 } 1154 1155 /* 1156 * Done, return the actual number of bytes copied out. 1157 */ 1158 1159 msg_freehdr(msghdr); 1160 wakeup((caddr_t)msqptr); 1161 p->p_retval[0] = msgsz;
| 1220 } 1221 user_msgp = (char *)user_msgp + tlen; 1222 next = msgmaps[next].next; 1223 } 1224 1225 /* 1226 * Done, return the actual number of bytes copied out. 1227 */ 1228 1229 msg_freehdr(msghdr); 1230 wakeup((caddr_t)msqptr); 1231 p->p_retval[0] = msgsz;
|
1162 return(0);
| 1232done2: 1233 mtx_unlock(&Giant); 1234 return (error);
|
1163} 1164 1165static int 1166sysctl_msqids(SYSCTL_HANDLER_ARGS) 1167{ 1168 1169 return (SYSCTL_OUT(req, msqids, 1170 sizeof(struct msqid_ds) * msginfo.msgmni)); 1171} 1172 1173SYSCTL_DECL(_kern_ipc); 1174SYSCTL_INT(_kern_ipc, OID_AUTO, msgmax, CTLFLAG_RD, &msginfo.msgmax, 0, ""); 1175SYSCTL_INT(_kern_ipc, OID_AUTO, msgmni, CTLFLAG_RD, &msginfo.msgmni, 0, ""); 1176SYSCTL_INT(_kern_ipc, OID_AUTO, msgmnb, CTLFLAG_RD, &msginfo.msgmnb, 0, ""); 1177SYSCTL_INT(_kern_ipc, OID_AUTO, msgtql, CTLFLAG_RD, &msginfo.msgtql, 0, ""); 1178SYSCTL_INT(_kern_ipc, OID_AUTO, msgssz, CTLFLAG_RD, &msginfo.msgssz, 0, ""); 1179SYSCTL_INT(_kern_ipc, OID_AUTO, msgseg, CTLFLAG_RD, &msginfo.msgseg, 0, "") 1180SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLFLAG_RD, 1181 NULL, 0, sysctl_msqids, "", "Message queue IDs");
| 1235} 1236 1237static int 1238sysctl_msqids(SYSCTL_HANDLER_ARGS) 1239{ 1240 1241 return (SYSCTL_OUT(req, msqids, 1242 sizeof(struct msqid_ds) * msginfo.msgmni)); 1243} 1244 1245SYSCTL_DECL(_kern_ipc); 1246SYSCTL_INT(_kern_ipc, OID_AUTO, msgmax, CTLFLAG_RD, &msginfo.msgmax, 0, ""); 1247SYSCTL_INT(_kern_ipc, OID_AUTO, msgmni, CTLFLAG_RD, &msginfo.msgmni, 0, ""); 1248SYSCTL_INT(_kern_ipc, OID_AUTO, msgmnb, CTLFLAG_RD, &msginfo.msgmnb, 0, ""); 1249SYSCTL_INT(_kern_ipc, OID_AUTO, msgtql, CTLFLAG_RD, &msginfo.msgtql, 0, ""); 1250SYSCTL_INT(_kern_ipc, OID_AUTO, msgssz, CTLFLAG_RD, &msginfo.msgssz, 0, ""); 1251SYSCTL_INT(_kern_ipc, OID_AUTO, msgseg, CTLFLAG_RD, &msginfo.msgseg, 0, "") 1252SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLFLAG_RD, 1253 NULL, 0, sysctl_msqids, "", "Message queue IDs");
|