Fork me on GitHub

root/kernel/syscalls/msgget.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. msg_get_new_mq
  2. msg_release_mq
  3. msg_get_new_md
  4. msg_release_md
  5. msg_init
  6. sys_msgget

   1 /*
   2  * fiwix/kernel/syscalls/msgget.c
   3  *
   4  * Copyright 2022, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/kernel.h>
   9 #include <fiwix/types.h>
  10 #include <fiwix/string.h>
  11 #include <fiwix/errno.h>
  12 #include <fiwix/process.h>
  13 #include <fiwix/ipc.h>
  14 #include <fiwix/msg.h>
  15 
  16 #ifdef __DEBUG__
  17 #include <fiwix/stdio.h>
  18 #endif /*__DEBUG__ */
  19 
  20 #ifdef CONFIG_SYSVIPC
  21 struct msqid_ds *msgque[MSGMNI];
  22 unsigned int num_queues;
  23 unsigned int num_msgs;
  24 unsigned int max_mqid;
  25 unsigned int msg_seq;
  26 
  27 /* FIXME: this should be allocated dynamically */
  28 static struct msqid_ds msgque_pool[MSGMNI];
  29 struct msqid_ds *msg_get_new_mq(void)
  30 {
  31         int n;
  32 
  33         for(n = 0; n < MSGMNI; n++) {
  34                 if(msgque_pool[n].msg_ctime == 0) {
  35                         msgque_pool[n].msg_ctime = 1;
  36                         return &msgque_pool[n];
  37                 }
  38         }
  39         return NULL;
  40 }
  41 
  42 void msg_release_mq(struct msqid_ds *mq)
  43 {
  44         memset_b(mq, 0, sizeof(struct msqid_ds));
  45 }
  46 
  47 struct msg msg_pool[MSGTQL];
  48 struct msg *msg_get_new_md(void)
  49 {
  50         unsigned int n;
  51 
  52         lock_resource(&ipcmsg_resource);
  53 
  54         for(n = 0; n < MSGTQL; n++) {
  55                 if(msg_pool[n].msg_stime == 0) {
  56                         msg_pool[n].msg_stime = 1;
  57                         unlock_resource(&ipcmsg_resource);
  58                         return &msg_pool[n];
  59                 }
  60         }
  61 
  62         unlock_resource(&ipcmsg_resource);
  63         return NULL;
  64 }
  65 
  66 void msg_release_md(struct msg *msg)
  67 {
  68         lock_resource(&ipcmsg_resource);
  69         memset_b(msg, 0, sizeof(struct msg));
  70         unlock_resource(&ipcmsg_resource);
  71 }
  72 
  73 void msg_init(void)
  74 {
  75         int n;
  76 
  77         for(n = 0; n < MSGMNI; n++) {
  78                 msgque[n] = (struct msqid_ds *)IPC_UNUSED;
  79         }
  80         memset_b(msgque_pool, 0, sizeof(msgque_pool));
  81         memset_b(msg_pool, 0, sizeof(msg_pool));
  82         num_queues = num_msgs = max_mqid = msg_seq = 0;
  83 }
  84 
  85 int sys_msgget(key_t key, int msgflg)
  86 {
  87         struct msqid_ds *mq;
  88         struct ipc_perm *perm;
  89         int n;
  90 
  91 #ifdef __DEBUG__
  92         printk("(pid %d) sys_msgget(%d, 0x%x)\n", current->pid, (int)key, msgflg);
  93 #endif /*__DEBUG__ */
  94 
  95         if(key == IPC_PRIVATE) {
  96                 /* create a new message queue */
  97                 if(!(mq = msg_get_new_mq())) {
  98                         return -ENOMEM;
  99                 }
 100                 for(n = 0; n < MSGMNI; n++) {
 101                         if(msgque[n] == (struct msqid_ds *)IPC_UNUSED) {
 102                                 goto init;
 103                         }
 104                 }
 105                 msg_release_mq(mq);
 106                 return -ENOSPC;
 107         }
 108 
 109         mq = NULL;
 110 
 111         for(n = 0; n < MSGMNI; n++) {
 112                 if(msgque[n] == (struct msqid_ds *)IPC_UNUSED) {
 113                         continue;
 114                 }
 115                 if(key == msgque[n]->msg_perm.key) {
 116                         mq = msgque[n];
 117                         break;
 118                 }
 119         }
 120 
 121         if(!mq) {
 122                 if(!(msgflg & IPC_CREAT)) {
 123                         return -ENOENT;
 124                 }
 125 
 126                 /* create a new message queue */
 127                 if(!(mq = msg_get_new_mq())) {
 128                         return -ENOMEM;
 129                 }
 130                 for(n = 0; n < MSGMNI; n++) {
 131                         if(msgque[n] == (struct msqid_ds *)IPC_UNUSED) {
 132                                 goto init;
 133                         }
 134                 }
 135                 msg_release_mq(mq);
 136                 return -ENOSPC;
 137         } else {
 138                 if((msgflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) {
 139                         return -EEXIST;
 140                 }
 141                 if(!ipc_has_perms(&mq->msg_perm, msgflg)) {
 142                         return -EACCES;
 143                 }
 144                 return (mq->msg_perm.seq * MSGMNI) + n;
 145         }
 146 
 147 init:
 148         perm = &mq->msg_perm;
 149         perm->key = key;
 150         perm->uid = perm->cuid = current->euid;
 151         perm->gid = perm->cgid = current->egid;
 152         perm->mode = msgflg & 0777;
 153         perm->seq = msg_seq;
 154         mq->msg_first = mq->msg_last = NULL;
 155         mq->msg_stime = mq->msg_rtime = 0;
 156         mq->msg_ctime = CURRENT_TIME;
 157         mq->unused1 = mq->unused2 = 0;
 158         mq->msg_cbytes = mq->msg_qnum = 0;
 159         mq->msg_qbytes = MSGMNB;
 160         mq->msg_lspid = mq->msg_lrpid = 0;
 161         msgque[n] = mq;
 162         if(n > max_mqid) {
 163                 max_mqid = n;
 164         }
 165         num_queues++;
 166         return (mq->msg_perm.seq * MSGMNI) + n;
 167 }
 168 #endif /* CONFIG_SYSVIPC */

/* [previous][next][first][last][top][bottom][index][help] */