LTP GCOV extension - code coverage report
Current view: directory - src/utils/ipc - min_ipc_mechanism.c
Test: min.info
Date: 2009-06-18 Instrumented lines: 317
Code covered: 63.1 % Executed lines: 200

       1                 : /*
       2                 :  * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
       3                 :  * and/or its subsidiary(-ies).
       4                 :  * Contact: Konrad Marek Zapalowicz
       5                 :  * Contact e-mail: DG.MIN-Support@nokia.com
       6                 :  * 
       7                 :  * This program is free software: you can redistribute it and/or modify it 
       8                 :  * under the terms of the GNU General Public License as published by the Free 
       9                 :  * Software Foundation, version 2 of the License. 
      10                 :  * 
      11                 :  * This program is distributed in the hope that it will be useful, but WITHOUT 
      12                 :  * ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or 
      13                 :  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General  Public License for
      14                 :  * more details. You should have received a copy of the GNU General Public 
      15                 :  * License along with this program. If not,  see 
      16                 :  * <http://www.gnu.org/licenses/>.
      17                 :  */
      18                 : 
      19                 : 
      20                 : /**
      21                 :  *  @file       min_ipc_mechanism.c
      22                 :  *  @version    0.1
      23                 :  *  @brief      This file contains implementation of the IPC Mechanism of MIN
      24                 :  */
      25                 : 
      26                 : /* ------------------------------------------------------------------------- */
      27                 : /* INCLUDE FILES */
      28                 : #include "min_ipc_mechanism.h"
      29                 : 
      30                 : /* ------------------------------------------------------------------------- */
      31                 : /* EXTERNAL DATA STRUCTURES */
      32                 : /* None */
      33                 : 
      34                 : /* ------------------------------------------------------------------------- */
      35                 : /* EXTERNAL GLOBAL VARIABLES */
      36                 : /* None */
      37                 : 
      38                 : /* ------------------------------------------------------------------------- */
      39                 : /* EXTERNAL FUNCTION PROTOTYPES */
      40                 : /* None */
      41                 : 
      42                 : /* ------------------------------------------------------------------------- */
      43                 : /* GLOBAL VARIABLES */
      44                 : LOCAL int __shm_handler__ = -1;
      45                 : 
      46                 : LOCAL DLList *__shm_handlers__ = INITPTR;
      47                 : /* ------------------------------------------------------------------------- */
      48                 : /* CONSTANTS */
      49                 : /* None */
      50                 : 
      51                 : /* ------------------------------------------------------------------------- */
      52                 : /* MACROS */
      53                 : 
      54                 : /* ------------------------------------------------------------------------- */
      55                 : /* LOCAL GLOBAL VARIABLES */
      56                 : /* ------------------------------------------------------------------------- */
      57                 : /** Buffer for messages that are waiting to be send */
      58                 : LOCAL DLList   *msg_buffer = INITPTR;
      59                 : /* ------------------------------------------------------------------------- */
      60                 : /** PID of process that has called mq_open_queue. 
      61                 :  *  We need to keep a track of process we are in because fork will copy
      62                 :  *  msg_buffer so it will be redundand. Solution is to flush the buffer when 
      63                 :  *  pid will change = situation where there is one buffer per process
      64                 :  */
      65                 : LOCAL pid_t     lastpid = 0;
      66                 : /* ------------------------------------------------------------------------- */
      67                 : /* LOCAL CONSTANTS AND MACROS */
      68                 : /* None */
      69                 : 
      70                 : /* ------------------------------------------------------------------------- */
      71                 : /* MODULE DATA STRUCTURES */
      72                 : /* None */
      73                 : 
      74                 : /* ------------------------------------------------------------------------- */
      75                 : /* LOCAL FUNCTION PROTOTYPES */
      76                 : /* None */
      77                 : /* ------------------------------------------------------------------------- */
      78                 : /** Wrapps around system call msgsnd, it also has error handling included */
      79                 : LOCAL int       mq_wrapper_around_msgsnd (int msqid, MsgBuffer * buf);
      80                 : /* ------------------------------------------------------------------------- */
      81                 : /** Translates MsgBuffer to _MIBuff */
      82                 : LOCAL void      mq_msgbuf_to_internal (struct _MIBuff *ibuf,
      83                 :                                        const MsgBuffer * buf);
      84                 : /* ------------------------------------------------------------------------- */
      85                 : /** Translates _MIBuff to MsgBuffer */
      86                 : LOCAL void      mq_internal_to_msgbuf (MsgBuffer * buf,
      87                 :                                        const struct _MIBuff *ibuf);
      88                 : /* ------------------------------------------------------------------------- */
      89                 : /** Gives the size of internal buffer in bytes */
      90                 : LOCAL unsigned int mq_internal_length (const struct _MIBuff *ibuf);
      91                 : /* ------------------------------------------------------------------------- */
      92                 : LOCAL int _findShmKey(const void *a, const void *b);
      93                 : /* ------------------------------------------------------------------------- */
      94                 : LOCAL int _findShmShmid(const void *a, const void *b);
      95                 : /* ------------------------------------------------------------------------- */
      96                 : /* FORWARD DECLARATIONS */
      97                 : /* None */
      98                 : 
      99                 : /* ------------------------------------------------------------------------- */
     100                 : /* ==================== LOCAL FUNCTIONS ==================================== */
     101                 : /* ------------------------------------------------------------------------- */
     102                 : LOCAL int mq_wrapper_around_msgsnd (int msqid, MsgBuffer * buf)
     103            5859 : {
     104            5859 :         int             retval = ENOERR;
     105            5859 :         int             result = ENOERR;
     106            5859 :         unsigned int    length = sizeof (struct _MIBuff) - sizeof (long);
     107                 :         struct _MIBuff  ibuf;
     108            5859 :         struct _MIBuff *ptr2ibf = INITPTR;
     109            5859 :         DLListIterator  it = DLListNULLIterator;
     110                 : 
     111            5859 :         if (buf == INITPTR) {
     112               0 :                 retval = -1;
     113               0 :                 goto EXIT;
     114                 :         }
     115                 : 
     116                 :         /* lets try to send some buffered first, buffer has to be FIFO */
     117            5859 :         result = 0;
     118            5859 :         it = dl_list_head (msg_buffer);
     119           11718 :         while ((result != -1) && (it != DLListNULLIterator)) {
     120                 : 
     121                 :                 /* try to send message from the buffer */
     122               0 :                 ptr2ibf = (struct _MIBuff *)dl_list_data (it);
     123               0 :                 length = mq_internal_length (ptr2ibf);
     124               0 :                 result = msgsnd (msqid, ptr2ibf, length, IPC_NOWAIT);
     125                 : 
     126                 :                 /* if successfull then remove it from the buffer */
     127               0 :                 if (result != -1) {
     128               0 :                         free (dl_list_data (it));
     129               0 :                         dl_list_remove_it (it);
     130               0 :                         it = dl_list_head (msg_buffer);
     131                 :                 }
     132                 :         }
     133                 : 
     134                 :         /* now lets try to send orginal message */
     135            5859 :         mq_msgbuf_to_internal (&ibuf, buf);
     136            5859 :         length = mq_internal_length (&ibuf);
     137            5859 :         result = msgsnd (msqid, &ibuf, length, IPC_NOWAIT);
     138                 : 
     139                 :         /* Sending has failed, now we have to examine errno */
     140            5859 :         if (result == -1) {
     141               0 :                 switch (errno) {
     142                 :                 case EAGAIN:
     143               0 :                         MIN_NOTICE ("MQ is full - message will be buffered");
     144                 :                         /* Queue is full, we need to buffer the msg */
     145                 :                         /* If buffer is not created then allocate it */
     146               0 :                         if (msg_buffer == INITPTR) {
     147               0 :                                 msg_buffer = dl_list_create ();
     148                 :                         }
     149                 : 
     150                 :                         /* Create new message buffer and copy message */
     151               0 :                         ptr2ibf = NEW (struct _MIBuff);
     152               0 :                         memcpy (ptr2ibf, &ibuf, sizeof (struct _MIBuff));
     153                 : 
     154                 :                         /* Put message into the buffer */
     155               0 :                         dl_list_add (msg_buffer, (void *)ptr2ibf);
     156                 : 
     157               0 :                         break;
     158                 :                 default:
     159                 :                         /* EINVAL, EACCES, EFAULT, EINTR */
     160               0 :                         MIN_ERROR ("MQ Error: %s",strerror (errno));
     161               0 :                         retval = -1;
     162                 :                 }
     163                 :         }
     164            5859 :       EXIT:
     165            5859 :         return retval;
     166                 : }
     167                 : 
     168                 : /* ------------------------------------------------------------------------- */
     169                 : LOCAL void mq_msgbuf_to_internal (struct _MIBuff *ibuf, const MsgBuffer * buf)
     170            5864 : {
     171            5864 :         if (ibuf == INITPTR) {
     172               0 :                 return;
     173                 :         }
     174            5864 :         if (buf == INITPTR) {
     175               0 :                 return;
     176                 :         }
     177                 : 
     178            5864 :         ibuf->receiver_ = buf->receiver_;
     179            5864 :         ibuf->sender_ = buf->sender_;
     180            5864 :         ibuf->type_ = buf->type_;
     181            5864 :         ibuf->param_ = buf->param_;
     182            5864 :         ibuf->special_ = buf->special_;
     183            5864 :         ibuf->extif_msg_type_ = buf->extif_msg_type_;
     184                 : 
     185            5864 :         ibuf->msgbeg_ = strlen (buf->desc_) + 1;
     186            5864 :         STRCPY (ibuf->desc_, buf->desc_, ibuf->msgbeg_);
     187            5864 :         STRCPY (&ibuf->desc_[ibuf->msgbeg_], buf->message_,
     188                 :                 strlen (buf->message_) + 1);
     189                 : }
     190                 : 
     191                 : /* ------------------------------------------------------------------------- */
     192                 : LOCAL void mq_internal_to_msgbuf (MsgBuffer * buf, const struct _MIBuff *ibuf)
     193            4324 : {
     194            4324 :         if (buf == INITPTR) {
     195               0 :                 return;
     196                 :         }
     197            4324 :         if (ibuf == INITPTR) {
     198               0 :                 return;
     199                 :         }
     200                 : 
     201            4324 :         memset (buf, 0x0, sizeof (MsgBuffer));
     202                 : 
     203            4324 :         buf->receiver_ = ibuf->receiver_;
     204            4324 :         buf->sender_ = ibuf->sender_;
     205            4324 :         buf->type_ = ibuf->type_;
     206            4324 :         buf->param_ = ibuf->param_;
     207            4324 :         buf->special_ = ibuf->special_;
     208            4324 :         buf->extif_msg_type_ = ibuf->extif_msg_type_;
     209                 : 
     210            4324 :         STRCPY (buf->desc_, ibuf->desc_, ibuf->msgbeg_);
     211            4324 :         STRCPY (buf->message_, &ibuf->desc_[ibuf->msgbeg_], MaxMsgSize);
     212                 : }
     213                 : 
     214                 : /* ------------------------------------------------------------------------- */
     215                 : LOCAL unsigned int mq_internal_length (const struct _MIBuff *ibuf)
     216            5864 : {
     217                 :         unsigned int    base_length = sizeof (long) * 2 + sizeof (char)
     218                 :             + sizeof (int) * 2 + sizeof (unsigned short)
     219                 :             + sizeof (MINMsgType)
     220            5864 :             + sizeof (TMSCommand);
     221            5864 :         unsigned int    length = 0;
     222                 : 
     223            5864 :         if (ibuf == INITPTR) {
     224               0 :                 goto EXIT;
     225                 :         }
     226            5864 :         length = base_length
     227                 :             + strlen (ibuf->desc_) + 1
     228                 :             + strlen (&ibuf->desc_[ibuf->msgbeg_]) + 1;
     229            5864 :       EXIT:
     230            5864 :         return length;
     231                 : }
     232                 : 
     233                 : /* ------------------------------------------------------------------------- */
     234                 : LOCAL int _findShmKey(const void *a, const void *b)
     235             730 : {
     236             730 :         const key_t *p1 = (const key_t*)b;
     237             730 :         const struct ShmItem *p2 = (const struct ShmItem*)a;
     238                 : 
     239             730 :         if ((*p1)==p2->key_) return 0;
     240               0 :         else return -1;
     241                 : }
     242                 : /* ------------------------------------------------------------------------- */
     243                 : LOCAL int _findShmShmid(const void *a, const void *b)
     244              42 : {
     245              42 :         const int *p1 = (const int*)b;
     246              42 :         const struct ShmItem *p2 = (const struct ShmItem*)a;
     247                 : 
     248              42 :         if ((*p1)==p2->shmid_) return 0;
     249              24 :         else return -1;
     250                 : }
     251                 : /* ------------------------------------------------------------------------- */
     252                 : /* ======================== FUNCTIONS ====================================== */
     253                 : /* ------------------------------------------------------------------------- */
     254                 : /** Checks if queue of a given id already exists.
     255                 :  *  @param queueid queue id, which is 8bit number. Char can be used instead.
     256                 :  *  @return 0 when queue exists, 1 when queue does not exists, -1 in case of
     257                 :  *          failure.
     258                 :  */
     259                 : int mq_queue_exists (int queueid)
     260               0 : {
     261               0 :         int             retval = -1;
     262               0 :         char           *path = "/tmp";
     263               0 :         key_t           key = ftok (path, queueid);
     264               0 :         int             msqid = -1;
     265               0 :         if (key == -1) {
     266               0 :                 MIN_FATAL ("Key for queue not created");
     267               0 :                 errno = EFAULT;
     268                 :         }
     269                 :         else {
     270               0 :                 msqid = msgget (key, IPC_CREAT | IPC_EXCL | 0660);
     271                 :         }
     272               0 :         if (msqid == -1) {
     273               0 :                 if (errno == EEXIST)
     274               0 :                         retval = 1;
     275                 :                 else
     276               0 :                         retval = -1;
     277                 :         } else
     278               0 :                 retval = 0;
     279               0 :         return retval;
     280                 : }
     281                 : 
     282                 : /* ------------------------------------------------------------------------- */
     283                 : void mq_init_buffer ()
     284             737 : {
     285             737 :         DLListIterator  it = DLListNULLIterator;
     286                 : 
     287                 :         /* Prepare the buffer */
     288             737 :         if (msg_buffer == INITPTR) {
     289                 :                 /* If buffer is not created then allocate it */
     290             252 :                 msg_buffer = dl_list_create ();
     291             252 :                 lastpid = getpid ();
     292                 :         } else {
     293                 :                 /* Buffer exists, need to check PID. if PID differs
     294                 :                  * from lastpid then we are a new process and flushing of
     295                 :                  * buffer is needed. Otherwise it is ok.
     296                 :                  */
     297             485 :                 if (lastpid != getpid ()) {
     298                 :                         /* correct the lastpid value */
     299             106 :                         lastpid = getpid ();
     300                 : 
     301                 :                         /* we are a new process, flush the buffer */
     302                 :                         /* but not destroy the buffer */
     303             106 :                         it = dl_list_head (msg_buffer);
     304             212 :                         while (it != DLListNULLIterator) {
     305               0 :                                 free (dl_list_data (it));
     306               0 :                                 dl_list_remove_it (it);
     307               0 :                                 it = dl_list_head (msg_buffer);
     308                 :                         }
     309                 :                 }
     310                 :         }
     311             737 : }
     312                 : 
     313                 : /* ------------------------------------------------------------------------- */
     314                 : /** Creates a new message queue, if queue identified by given key already
     315                 :  *  exists its id is returned.
     316                 :  *  @param queueid queue id, which is 8bit number. Char can be used instead
     317                 :  *  @return queue id number, or -1 in case of failure
     318                 :  *
     319                 :  *  Possible Errors:
     320                 :  *  - ENOSPC Maximum number of allowed message queue has been reached.
     321                 :  *  - EFAULT Error in opening.
     322                 :  */
     323                 : int mq_open_queue (int queueid)
     324             725 : {
     325             725 :         char           *path = "/tmp";
     326             725 :         key_t           key = ftok (path, queueid);
     327             725 :         int             msqid = -1;
     328                 : 
     329                 :         /* create queue */
     330             725 :         if (key == -1) {
     331               0 :                 MIN_FATAL ("Key for queue not created");
     332               0 :                 errno = EFAULT;
     333               0 :                 goto EXIT;
     334                 :         } else {
     335             725 :                 msqid = msgget (key, IPC_CREAT | 0660);
     336             725 :                 if (msqid == -1) {
     337               0 :                         MIN_FATAL ("MQ not created: %s",strerror (errno));
     338                 :                 }
     339                 :         }
     340                 : 
     341             725 :         mq_init_buffer ();
     342             725 :       EXIT:
     343             725 :         return msqid;
     344                 : }
     345                 : 
     346                 : /* ------------------------------------------------------------------------- */
     347                 : /** Closes message queue. The queue is removed from the system.
     348                 :  *  @param msqid message queue identifier.
     349                 :  *  @return 0 on success, -1 on failure
     350                 :  */
     351                 : int mq_close_queue (int msqid)
     352              39 : {
     353                 :         /* flush the buffer */
     354              39 :         mq_flush_msg_buffer ();
     355                 : 
     356                 :         /* close queue */
     357              39 :         if (msgctl (msqid, IPC_RMID, 0) == -1) {
     358               0 :                 MIN_ERROR ("Error when closing MQ");
     359               0 :                 return -1;
     360                 :         }
     361                 :         else
     362              39 :                 return 0;
     363                 : }
     364                 : 
     365                 : /* ------------------------------------------------------------------------- */
     366                 : /** Sends message to the queue.
     367                 :  *  @param msqid message queue identifier
     368                 :  *  @param buf pointer to buffer with data to send
     369                 :  *  @return 0 when succeded, or -1 in case of failure
     370                 :  */
     371                 : int mq_send_message (int msqid, MsgBuffer * buf)
     372            4520 : {
     373            4520 :         return mq_wrapper_around_msgsnd (msqid, buf);
     374                 : }
     375                 : 
     376                 : /* ------------------------------------------------------------------------- */
     377                 : /** Sends message to the queue in a blocking way.
     378                 :  *  @param msqid message queue identifier
     379                 :  *  @param buf pointer to buffer with data to send
     380                 :  *  @return 0 when succeded, or -1 in case of failure
     381                 :  */
     382                 : int mq_send_message_block (int msqid, MsgBuffer * buf)
     383               5 : {
     384               5 :         unsigned int    length = sizeof (struct _MIBuff) - sizeof (long);
     385                 :         struct _MIBuff  ibuf;
     386                 : 
     387               5 :         mq_msgbuf_to_internal (&ibuf, buf);
     388                 : 
     389               5 :         MIN_DEBUG ("%d -> %d [%d]\n", ibuf.sender_, ibuf.receiver_,
     390                 :                      ibuf.type_);
     391               5 :         length = mq_internal_length (&ibuf);
     392               5 :         return msgsnd (msqid, &ibuf, length, 0);
     393                 : }
     394                 : 
     395                 : /* ------------------------------------------------------------------------- */
     396                 : /** Sends message to the queue.
     397                 :  *  @param msqid message queue identifier
     398                 :  *  @param adress pid of the recieving process
     399                 :  *  @param type message type, @see MINMsgType
     400                 :  *  @param param message parameter, its value depends on message type
     401                 :  *  @param msg custom parameter, description of the message, depends on type
     402                 :  *             of the message.
     403                 :  *  @return 0 when succeded, or -1 in case of failure
     404                 :  */
     405                 : int mq_send_message2 (int msqid, long adress, MINMsgType type, int param,
     406                 :                       const char *msg)
     407            1339 : {
     408                 :         MsgBuffer       buf;
     409                 : 
     410                 :         /* construct the message */
     411            1339 :         buf.receiver_ = adress;
     412            1339 :         buf.sender_ = getpid ();
     413            1339 :         buf.type_ = type;
     414            1339 :         buf.param_ = param;
     415            1339 :         STRCPY (buf.desc_, "\0", MaxDescSize);
     416            1339 :         STRCPY (buf.message_, msg, MaxMsgSize);
     417                 : 
     418            1339 :         MIN_DEBUG ("%d -> %d [%d]\n", buf.sender_, buf.receiver_, type);
     419                 : 
     420            1339 :         return mq_wrapper_around_msgsnd (msqid, &buf);
     421                 : }
     422                 : 
     423                 : /* ------------------------------------------------------------------------- */
     424                 : /** Sends message to the queue in a blocking way.
     425                 :  *  @param msqid message queue identifier
     426                 :  *  @param adress pid of the recieving process
     427                 :  *  @param type message type, @see MINMsgType
     428                 :  *  @param param message parameter, its value depends on message type
     429                 :  *  @param msg custom parameter, description of the message, depends on type
     430                 :  *             of the message.
     431                 :  *  @return 0 when succeded, or -1 in case of failure
     432                 :  */
     433                 : int mq_send_message2_block (int msqid, long adress, MINMsgType type,
     434                 :                             int param, const char *msg)
     435               0 : {
     436                 :         struct _MIBuff  ibuf;
     437               0 :         unsigned int    length = sizeof (struct _MIBuff) - sizeof (long);
     438                 : 
     439                 :         /* construct the message */
     440               0 :         ibuf.receiver_ = adress;
     441               0 :         ibuf.sender_ = getpid ();
     442               0 :         ibuf.type_ = type;
     443               0 :         ibuf.param_ = param;
     444               0 :         STRCPY (ibuf.desc_, "\0", MaxDescSize);
     445               0 :         STRCPY (ibuf.desc_, msg, MaxMsgSize);
     446                 : 
     447               0 :         MIN_DEBUG ("%d -> %d [%d]\n", ibuf.sender_, ibuf.receiver_, type);
     448                 : 
     449               0 :         return msgsnd (msqid, &ibuf, length, 0);
     450                 : }
     451                 : 
     452                 : /* ------------------------------------------------------------------------- */
     453                 : /** Reads message from queue.
     454                 :  *  @param msqid message queue identifier
     455                 :  *  @param msg_type the type of message we are going to read
     456                 :  *  @param buf pointer to the buffer for incomming message
     457                 :  *  @return number of bytes recieved, or -1 in case of error
     458                 :  *
     459                 :  *  Possible Errors:
     460                 :  *  - EINVAL invalid value is passed to the function
     461                 :  *  - EINTR function interrupted by the signal
     462                 :  *  - EIDRM queue identifier removed from the system
     463                 :  *  - E2BIG message to big to be recieved
     464                 :  */
     465                 : int mq_read_message (int msqid, long msg_type, MsgBuffer * buf)
     466            4324 : {
     467            4324 :         unsigned int    length = sizeof (struct _MIBuff) - sizeof (long);
     468            4324 :         int             retval = ENOERR;
     469            4324 :         int             result = 0;
     470            4324 :         TSBool          msgread = ESFalse;
     471            4324 :         DLListIterator  it = DLListNULLIterator;
     472            4324 :         struct _MIBuff *ipom = INITPTR;
     473                 :         struct _MIBuff  ibuf;
     474                 : 
     475            4324 :         memset (&ibuf, 0x0, sizeof (struct _MIBuff));
     476                 : 
     477                 :         while (1) {
     478                 : 
     479                 :                 /* peek for message in MQ */
     480            5887 :                 if (mq_peek_message (msqid, msg_type) == 1) {
     481            4324 :                         length = sizeof (struct _MIBuff) - sizeof (long);
     482            4324 :                         retval = msgrcv (msqid, &ibuf, length, msg_type, 0);
     483            4324 :                         if (retval==(ssize_t)-1) {
     484               0 :                                 MIN_FATAL("Message in queue way too big to be recieved, error: %d",errno);
     485                 :                         } else {
     486            4324 :                                 MIN_DEBUG("Read message of size: %d",retval);
     487                 :                         }
     488            4324 :                         mq_internal_to_msgbuf (buf, &ibuf);
     489            4324 :                         msgread = ESTrue;
     490                 :                 }
     491                 : 
     492                 :                 /* try to send buffered */
     493            5887 :                 result = 0;
     494            5887 :                 it = dl_list_head (msg_buffer);
     495           11774 :                 while ((it != DLListNULLIterator) && (result != -1)) {
     496                 : 
     497                 :                         /* try to send message from the buffer */
     498               0 :                         ipom = (struct _MIBuff *)dl_list_data (it);
     499               0 :                         length = mq_internal_length (ipom);
     500               0 :                         result = msgsnd (msqid, ipom, length, IPC_NOWAIT);
     501                 : 
     502                 :                         /* if successfull then remove it from the buffer */
     503               0 :                         if (result != -1) {
     504               0 :                                 free (dl_list_data (it));
     505               0 :                                 dl_list_remove_it (it);
     506               0 :                                 it = dl_list_head (msg_buffer);
     507                 :                         }
     508                 :                 }
     509                 : 
     510                 :                 /* break the loop if msg was read from the queue */
     511            5887 :                 if (msgread == ESTrue) {
     512            4324 :                         break;
     513                 :                 }
     514                 : 
     515                 :                 /* slow down a little bit this fast loop */
     516            1563 :                 usleep (10000);
     517            1563 :         }
     518                 : 
     519            4324 :         return retval;
     520                 : }
     521                 : 
     522                 : /* ------------------------------------------------------------------------- */
     523                 : /** Peeks message queue to see if mesage of given type has arrived. This
     524                 :  *  function is no blocking.
     525                 :  *  @param msqid message queue identifier
     526                 :  *  @param msg_type the type of message we are waiting for. If == 0 then
     527                 :  *         messages of all types will be metched.
     528                 :  *  @return 1 when message arrives, 0 when there is no message.
     529                 :  */
     530                 : int mq_peek_message (int msqid, long msg_type)
     531           26838 : {
     532                 :         int             result =
     533           26838 :             msgrcv (msqid, NULL, 0, msg_type, IPC_NOWAIT);
     534           26838 :         if (result == -1 && errno == E2BIG)
     535            8649 :                 return 1;
     536                 :         else
     537           18189 :                 return 0;
     538                 : }
     539                 : 
     540                 : /* ------------------------------------------------------------------------- */
     541                 : /** Flushes msg_buffer */
     542                 : void mq_flush_msg_buffer ()
     543             220 : {
     544             220 :         DLListIterator  it = DLListNULLIterator;
     545                 : 
     546                 :         /* check size of the buffer */
     547             220 :         MIN_DEBUG ("There are %d messages buffered."
     548                 :                      " Buffer will be flushed", dl_list_size (msg_buffer));
     549                 : 
     550                 :         /* flush the buffer and destroy it */
     551             220 :         it = dl_list_head (msg_buffer);
     552             440 :         while (it != DLListNULLIterator) {
     553               0 :                 free (dl_list_data (it));
     554               0 :                 dl_list_remove_it (it);
     555               0 :                 it = dl_list_head (msg_buffer);
     556                 :         }
     557             220 :         dl_list_free (&msg_buffer);
     558                 : 
     559                 :         /* set lastpid */
     560             220 :         lastpid = 0;
     561             220 : }
     562                 : 
     563                 : /* ------------------------------------------------------------------------- */
     564                 : /** Resends messages from the buffer. */
     565                 : void mq_resend_buffered ()
     566              91 : {
     567                 :         /* obtain id of a queue. It is kind of a hack, queue id should come
     568                 :          * as a parameter, but to avoid extern we are doing it this way. */
     569              91 :         int             msqid = mq_open_queue ('a');
     570              91 :         int             result = 0;
     571              91 :         unsigned int    length = sizeof (struct _MIBuff) - sizeof (long);
     572              91 :         DLListIterator  it = dl_list_head (msg_buffer);
     573              91 :         struct _MIBuff *ptr2ibf = INITPTR;
     574                 : 
     575                 :         /* sending was successfull, lets try to send some buffered */
     576             182 :         while ((it != DLListNULLIterator)) {
     577                 : 
     578                 :                 /* try to send message from the buffer */
     579               0 :                 ptr2ibf = (struct _MIBuff *)dl_list_data (it);
     580               0 :                 length = mq_internal_length (ptr2ibf);
     581               0 :                 result = msgsnd (msqid, ptr2ibf, length, IPC_NOWAIT);
     582                 : 
     583                 :                 /* if successfull then remove it from the buffer */
     584               0 :                 if (result != -1) {
     585               0 :                         free (dl_list_data (it));
     586               0 :                         dl_list_remove_it (it);
     587               0 :                         it = dl_list_head (msg_buffer);
     588                 :                 }
     589                 : 
     590               0 :                 usleep (10000);
     591                 :         }
     592              91 : }
     593                 : 
     594                 : /* ------------------------------------------------------------------------- */
     595                 : int mq_buffer_size ()
     596               0 : {
     597               0 :         return dl_list_size (msg_buffer);
     598                 : }
     599                 : 
     600                 : /* ------------------------------------------------------------------------- */
     601                 : /** Pauses process.
     602                 :  *  @param pid the id of a process to be paused (>0)
     603                 :  *  @return 0 on success and -1 on failure
     604                 :  *
     605                 :  *  Possible Errors:
     606                 :  *  - EINVAL invalid value was passed to the funcion
     607                 :  *  - ESRCH there is no process of a given pid
     608                 :  *  - EPERM calling process has no permission to send a signal
     609                 :  */
     610                 : int sl_pause_process (long pid)
     611               0 : {
     612               0 :         int             retval = -1;
     613               0 :         if (pid != 0)
     614               0 :                 retval = kill (pid, SIGSTOP);
     615                 :         else {
     616               0 :                 MIN_WARN ("Given pid is invalid");
     617               0 :                 errno = EINVAL;
     618                 :         }
     619               0 :         return retval;
     620                 : }
     621                 : 
     622                 : /* ------------------------------------------------------------------------- */
     623                 : /** Pauses process.
     624                 :  *  @param pid the id of a process to be resumed (>0)
     625                 :  *  @return 0 on success and -1 on failure
     626                 :  *
     627                 :  *  Possible Errors:
     628                 :  *  - EINVAL invalid value was passed to the funcion
     629                 :  *  - ESRCH there is no process of a given pid
     630                 :  *  - EPERM calling process has no permission to send a signal
     631                 :  */
     632                 : int sl_resume_process (long pid)
     633               0 : {
     634               0 :         int             retval = -1;
     635               0 :         retval = kill (pid, SIGCONT);
     636               0 :         return retval;
     637                 : }
     638                 : 
     639                 : /* ------------------------------------------------------------------------- */
     640                 : /** Pauses process.
     641                 :  *  @param pid the id of a process to be killed (>0)
     642                 :  *  @return 0 on success and -1 on failure
     643                 :  *
     644                 :  *  Possible Errors:
     645                 :  *  - EINVAL invalid value was passed to the funcion
     646                 :  *  - ESRCH there is no process of a given pid
     647                 :  *  - EPERM calling process has no permission to send a signal
     648                 :  */
     649                 : int sl_kill_process (long pid)
     650               0 : {
     651               0 :         int             retval = -1;
     652               0 :         retval = kill (pid, SIGKILL);
     653               0 :         return retval;
     654                 : }
     655                 : 
     656                 : /* ------------------------------------------------------------------------- */
     657                 : /** Sets signal handler for the given signal.
     658                 :  *  @param signum is the signal id
     659                 :  *  @param sighal pointer to the signal handler function.
     660                 :  *  @return -1 on failure, 0 on success.
     661                 :  */
     662                 : int sl_set_sighandler (int signum, sighandler_t sighal)
     663            1649 : {
     664            1649 :         int             retval = -1;
     665                 :         struct sigaction new_action;
     666            1649 :         new_action.sa_handler = sighal;
     667            1649 :         sigfillset (&new_action.sa_mask);
     668            1649 :         new_action.sa_flags = SA_NOCLDSTOP;
     669            1649 :         retval = sigaction (signum, &new_action, NULL);
     670            1649 :         return retval;
     671                 : }
     672                 : 
     673                 : /* ------------------------------------------------------------------------- */
     674                 : /** Gets shared memory segment
     675                 :  *  @param shmgetid [in] key used when requesting shared memmory segment. 8bit
     676                 :  *  @param size [in] the size of shared memory segment.
     677                 :  *  @return shared memory id or -1 in case of failure.
     678                 :  *
     679                 :  *  Possible Errors:
     680                 :  *  - EFAULT: error in function
     681                 :  */
     682                 : int sm_create (int shmgetid, unsigned int size)
     683             959 : {
     684             959 :         char           *path = "/tmp";
     685                 :         key_t           key;
     686             959 :         struct ShmItem  *tmp = INITPTR;
     687             959 :         DLListIterator it = DLListNULLIterator;
     688                 : 
     689             959 :         key = ftok (path, shmgetid);
     690             959 :         if (key == -1) {
     691               0 :                 MIN_FATAL ("Key for SM not created");
     692               0 :                 errno = EFAULT;
     693               0 :                 return -1;
     694                 :         }
     695                 : 
     696             959 :         if (__shm_handlers__==INITPTR) { __shm_handlers__ = dl_list_create(); }
     697                 :         else {
     698             730 :                 it = dl_list_find(dl_list_head(__shm_handlers__),
     699                 :                                   dl_list_tail(__shm_handlers__),
     700                 :                                   _findShmKey, &key);
     701                 :         }
     702                 : 
     703             959 :         if (it==DLListNULLIterator) {
     704             229 :                 tmp = NEW(struct ShmItem);
     705             229 :                 tmp->key_ = key;
     706             229 :                 tmp->shmid_ = shmget (key, size, IPC_CREAT | 0660);
     707             229 :                 dl_list_add(__shm_handlers__,tmp);
     708             229 :                 return tmp->shmid_;
     709                 :         } else {
     710             730 :                 return ((struct ShmItem*)dl_list_data(it))->shmid_;
     711                 :         }
     712                 : }
     713                 : 
     714                 : /* ------------------------------------------------------------------------- */
     715                 : /** Marks shared memory segment to be destroyed.
     716                 :  *  @param shmid [in] the id of the shared memory segment to be destroyed. 
     717                 :  *  @return 0 in case of success, -1 otherwise.
     718                 :  */
     719                 : int sm_destroy (int shmid)
     720              43 : {
     721              43 :         DLListIterator it = DLListNULLIterator;
     722              43 :         it = dl_list_find(dl_list_head(__shm_handlers__),
     723                 :                           dl_list_tail(__shm_handlers__),
     724                 :                           _findShmShmid, &shmid);
     725                 : 
     726              43 :         if (it==DLListNULLIterator) {
     727              25 :                 MIN_ERROR("Requested to remove not existing SHM %d",
     728                 :                            shmid);
     729              25 :                 return -1;
     730                 :         } else {
     731              18 :                 if (shmctl (shmid, IPC_RMID, 0) == -1)
     732               0 :                         return -1;
     733                 :                 else {
     734              18 :                         free(dl_list_data(it));
     735              18 :                         dl_list_remove_it(it);
     736              18 :                         if (dl_list_size(__shm_handlers__)==0) {
     737              18 :                                 dl_list_free(&__shm_handlers__);
     738                 :                         }
     739              18 :                         return 0;
     740                 :                 }
     741                 :         }
     742                 : }
     743                 : 
     744                 : /* ------------------------------------------------------------------------- */
     745                 : /** Returns pointer to the allocated shared memory segment.
     746                 :  *  @param shmid [in] id of the shared memory segment we want to be attached to
     747                 :  *  @return pointer to the SH segment, or INITPTR in case of failure.
     748                 :  */
     749                 : void           *sm_attach (int shmid)
     750            1015 : {
     751            1015 :         int            *retval = (int *)shmat (shmid, (void *)NULL, 0);
     752            1015 :         if (*retval == -1) {
     753               0 :                 MIN_WARN ("Could not find allocated memory segment");
     754               0 :                 return INITPTR;
     755                 :         }
     756                 :         else
     757            1015 :                 return (void *)retval;
     758                 : }
     759                 : 
     760                 : /* ------------------------------------------------------------------------- */
     761                 : inline void sm_detach (void *shmaddr)
     762            1015 : {
     763            1015 :         if (shmaddr != INITPTR)
     764            1015 :                 shmdt (shmaddr);
     765            1015 : }
     766                 : 
     767                 : /* ------------------------------------------------------------------------- */
     768                 : int sm_read (const void *shmaddr, void *data, unsigned int size)
     769             965 : {
     770             965 :         int             retval = ENOERR;
     771             965 :         if (shmaddr == INITPTR) {
     772               0 :                 errno = EINVAL;
     773               0 :                 retval = -1;
     774               0 :                 goto EXIT;
     775                 :         }
     776             965 :         if (data == INITPTR) {
     777               0 :                 errno = EINVAL;
     778               0 :                 retval = -1;
     779               0 :                 goto EXIT;
     780                 :         }
     781                 : 
     782             965 :         memcpy (data, shmaddr, size);
     783             965 :       EXIT:
     784             965 :         return retval;
     785                 : }
     786                 : 
     787                 : /* ------------------------------------------------------------------------- */
     788                 : int sm_write (void *shmaddr, const void *data, unsigned int size)
     789             208 : {
     790             208 :         int             retval = ENOERR;
     791             208 :         if (shmaddr == INITPTR) {
     792               0 :                 errno = EINVAL;
     793               0 :                 retval = -1;
     794               0 :                 goto EXIT;
     795                 :         }
     796             208 :         if (data == INITPTR) {
     797               0 :                 errno = EINVAL;
     798               0 :                 retval = -1;
     799               0 :                 goto EXIT;
     800                 :         }
     801                 : 
     802             208 :         memcpy (shmaddr, data, size);
     803             208 :       EXIT:
     804             208 :         return retval;
     805                 : }
     806                 : 
     807                 : /* ------------------------------------------------------------------------- */
     808                 : int sm_get_handler()
     809               0 : {
     810               0 :         return __shm_handler__;
     811                 : }
     812                 : /* ------------------------------------------------------------------------- */
     813                 : /** Returns the size of SHM segment
     814                 :  *  @param shmid [in] id of the shared memory segment we want to be attached to
     815                 :  *  @return size of the segment or 0
     816                 :  */
     817                 : size_t sm_get_segsz (int shmid)
     818              54 : {
     819                 :         struct shmid_ds shmid_ds;
     820                 :         
     821              54 :         if (shmctl (shmid, IPC_STAT, &shmid_ds) == -1) {
     822               0 :                 MIN_WARN ("shmget() failed: %s", strerror(errno));
     823               0 :                 return 0;
     824                 :         }
     825                 :  
     826              54 :         return shmid_ds.shm_segsz;
     827                 : }
     828                 : /* ------------------------------------------------------------------------- */
     829                 : 
     830                 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
     831                 : /* None */
     832                 : 
     833                 : /* ------------------------------------------------------------------------- */
     834                 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
     835                 : #ifdef MIN_UNIT_TEST
     836                 : #include "min_ipc_mechanism.tests"
     837                 : #endif                          /* MIN_UNIT_TEST */
     838                 : /* ------------------------------------------------------------------------- */
     839                 : /* End of file */

Generated by: LTP GCOV extension version 1.6