/*
 * @File: mqh.h
 *
 * @Contents: POSIX Message Passing helper definitions and macros
 *
 * Copyright (C) 2002 Sergio Saez <ssaez@disca.upv.es>
 * Project OCERA (Open Components for Realtime Embedded Applications)
 *
 */

#ifndef MQH_H
#define MQH_H

/*
 * Required include files
 */

#include <pthread.h>
#include <semaphore.h>

#include <mqueue.h>
#include <mq_prio.h>

/*
 * Definitions
 */ 

#define INIT_LIST(list, pool, max)              \
do {                                            \
    int i;                                      \
    (list)= &(pool)[0];                         \
    for (i= 0; i < (max) - 1; i++) {            \
        (pool)[i].next= &(pool)[i+1];           \
    }                                           \
    (pool)[(max)-1].next= NULL;                 \
} while (0)


/* mq_attr default values */
#ifdef CONFIG_MQ_ATTR_DFT_MAXMSG
#define _RTL_MQ_ATTR_DFT_MAXMSG      CONFIG_MQ_ATTR_DFT_MAXMSG     
#else
#define _RTL_MQ_ATTR_DFT_MAXMSG      16 /* 16 messages */
#endif

#ifdef CONFIG_MQ_ATTR_DFT_MSGSIZE
#define _RTL_MQ_ATTR_DFT_MSGSIZE     CONFIG_MQ_ATTR_DFT_MSGSIZE
#else
#define _RTL_MQ_ATTR_DFT_MSGSIZE     128 /* 128 bytes */
#endif

/* message queue attribute mq_flags masks */
#define MQ_ATTR_F_UNLINKED      (1<<0)

/*
 * Data types and access macros
 */

/*** Message ***/

/* Message data */
struct mq_msg {
    struct mq_msg *     next;   /* Next message in the queue */
    long                length; /* Length of the message */
    char *              data;   /* Data of the message */
};

#define MQ_MSG_DATA_PTR(msg_p)  ((msg_p)->data)
                                /* Future versions of 'mq_msg' could have message data
                                 * inline, and no as a pointer. */

/*** Message queue ***/

/* State of a message queue. */
struct mq_message_queue {
    struct mq_attr      attr;   /* Message queue attributes */
    long                count;  /* Number of open descriptors that refers to this queue */
    char *              data;   /* Memory space for this message queue */
    struct mq_msg *	msgs;	/* Memory space for message structures */
    struct mq_msg *	slots;	/* Free message structures */

    /* Asynchronous notification */

    pthread_t           notification_thread;
    int                 notification_signo; /* Only non-real-time signals are allowed at
                                             * this time */
    mqd_t               notification_mqdes; /* Message queue descriptor used for
                                             * attaching a notification */
    
    /* Message queues by priority */
    struct mq_msg *	first[_RTL_MQ_PRIO_MAX];
    struct mq_msg *	last[_RTL_MQ_PRIO_MAX];

    /* Priority queue */
    mq_pq_t		pq;

    /* Synchronization variables */
    sem_t               queue_sem, queue_send, queue_receive;

};

#define IS_VALID_MESSAGE_QUEUE(mq) ((mq)->data != NULL)

/*** Message queue name space ***/

struct mq_message_queue_entry {
    struct mq_message_queue_entry *     next;
    char                                name[PATH_MAX];
    struct mq_message_queue             queue;
};

#define IS_VALID_MESSAGE_QUEUE_ENTRY(mqe) ((mqe)->name != '\0')

/*** Message queue descriptors ***/

/* Content of a message queue descriptor */
struct mq_description {
    long                        flags;
    struct mq_message_queue *   queue; /* Message queue described */
    
};

#define IS_VALID_DESCRIPTION(d) ((d)->queue != NULL)

/*
 * Prototypes 
 */ 

void mq_ns_init (void);
int mq_ns_lookup 
	(
	 const char * name,
	 struct mq_message_queue ** mq
	);
int mq_ns_bind 
	(
	 const char * name,
	 struct mq_message_queue ** mq,
	 long oflags
	);
int mq_ns_unlink 
	(
	 const char * name
	);
int mq_ns_unbind 
	(
	 const struct mq_message_queue * mq
	);
int mq_queue_init 
	(
	 struct mq_message_queue * mq,
	 struct mq_attr * attr
	);
inline int mq_queue_destroy 
	(
	 struct mq_message_queue * mq
	);
int mq_queue_open 
	(
	 struct mq_message_queue * mq
	);
int mq_queue_close 
	(
	 struct mq_message_queue * mq
	);
int mq_queue_unlink 
	(
	 struct mq_message_queue * mq
	);
struct mq_msg * mq_queue_get_slot 
	(
	 struct mq_message_queue * mq
	);
void mq_queue_release_slot 
	(
	 struct mq_message_queue * mq,
	 struct mq_msg * msg
	);

#endif /* end mqh.h */
