1/*
2 * Event queue utility.
3 *
4 * Copyright (C) 2015, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
11 *
12 * $Id:$
13 */
14
15#include <stdlib.h>
16#include <string.h>
17#include <mqueue.h>
18#include <sys/stat.h>
19#include <errno.h>
20#include "trace.h"
21#include "eventQ.h"
22
23#define MAX_NAME_LENGTH		32
24
25struct eventQ
26{
27	char name[MAX_NAME_LENGTH + 1];
28	int queueDepth;
29	size_t eventSize;
30	mqd_t mq;
31};
32
33/* flush event queue */
34static void flush(eventQT *eventq)
35{
36	char *data;
37
38	data = malloc(eventq->eventSize);
39	if (data == 0)
40		return;
41
42	while (eventQReceive(eventq, data) != -1)
43	{}
44
45	free(data);
46}
47
48/* create event queue */
49static eventQT *create(char *name, int queueDepth, size_t eventSize)
50{
51	eventQT *eventq;
52	struct mq_attr attr;
53
54	eventq = malloc(sizeof(*eventq));
55	if (eventq == 0)
56		return 0;
57	memset(eventq, 0, sizeof(*eventq));
58	strncpy(eventq->name, name, MAX_NAME_LENGTH);
59	eventq->queueDepth = queueDepth;
60	eventq->eventSize = eventSize;
61
62	/* event queue attributes */
63	memset(&attr, 0, sizeof(attr));
64	attr.mq_maxmsg = eventq->queueDepth;
65	attr.mq_msgsize = eventq->eventSize;
66
67	/* create event queue */
68	eventq->mq = mq_open(eventq->name,
69		O_RDWR | O_NONBLOCK | O_CREAT,
70		S_IRWXU | S_IRWXG, &attr);
71	if (eventq->mq == (mqd_t)-1) {
72		TRACE(TRACE_ERROR, "failed to create event queue\n");
73		perror("eventQCreate");
74		free(eventq);
75		return 0;
76	}
77
78	/* queue may not be empty if not a clean shutdown */
79	flush(eventq);
80
81	return eventq;
82}
83
84/* create event queue */
85eventQT *eventQCreate(char *name, int queueDepth, size_t eventSize)
86{
87	eventQT *eventq;
88
89	/* previous queue may be lingering around if not a clean shutdown */
90	/* delete it first */
91	eventq = create(name, queueDepth, eventSize);
92	eventQDelete(eventq);
93
94	return create(name, queueDepth, eventSize);
95}
96
97/* delete event queue */
98void eventQDelete(eventQT *eventq)
99{
100	mq_close(eventq->mq);
101	mq_unlink(eventq->name);
102	free(eventq);
103}
104
105/* post to event queue */
106int eventQSend(eventQT *eventq, char *event)
107{
108	return mq_send(eventq->mq, event, eventq->eventSize, 0);
109}
110
111/* retrieve from event queue */
112int eventQReceive(eventQT *eventq, char *event)
113{
114	return mq_receive(eventq->mq, event, eventq->eventSize, 0);
115}
116