blob: c7a4320526e94a6e30db8bbc855d416fc7974fbe [file] [log] [blame]
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +01001/* Generic write queue implementation */
2/*
Holger Hans Peter Freytherc7f52c42016-11-12 21:25:21 +01003 * (C) 2010-2016 by Holger Hans Peter Freyther
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +01004 * (C) 2010 by On-Waves
5 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020024#include <errno.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010025#include <osmocom/core/write_queue.h>
Holger Hans Peter Freytherc7f52c42016-11-12 21:25:21 +010026#include <osmocom/core/logging.h>
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010027
Harald Welte2777ecd2011-08-17 14:23:42 +020028/*! \addtogroup write_queue
29 * @{
30 */
31
32/*! \file write_queue.c */
33
34/*! \brief Select loop function for write queue handling
35 * \param[in] fd osmocom file descriptor
36 * \param[in] what bit-mask of events that have happened
Harald Welte2d2e2cc2016-04-25 12:11:20 +020037 * \returns 0 on success; negative on error
Harald Welte2777ecd2011-08-17 14:23:42 +020038 *
39 * This function is provided so that it can be registered with the
40 * select loop abstraction code (\ref osmo_fd::cb).
41 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020042int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what)
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010043{
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020044 struct osmo_wqueue *queue;
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020045 int rc;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010046
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020047 queue = container_of(fd, struct osmo_wqueue, bfd);
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010048
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020049 if (what & BSC_FD_READ) {
50 rc = queue->read_cb(fd);
Holger Hans Peter Freythereb55e6a2014-07-01 19:39:26 +020051 if (rc == -EBADF)
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020052 goto err_badfd;
53 }
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010054
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020055 if (what & BSC_FD_EXCEPT) {
56 rc = queue->except_cb(fd);
Holger Hans Peter Freythereb55e6a2014-07-01 19:39:26 +020057 if (rc == -EBADF)
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020058 goto err_badfd;
59 }
Holger Hans Peter Freyther4052c812010-04-08 10:58:20 +020060
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010061 if (what & BSC_FD_WRITE) {
62 struct msgb *msg;
63
64 fd->when &= ~BSC_FD_WRITE;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010065
Holger Hans Peter Freyther76681ba2011-02-15 00:42:19 +010066 /* the queue might have been emptied */
67 if (!llist_empty(&queue->msg_queue)) {
68 --queue->current_length;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010069
Holger Hans Peter Freyther76681ba2011-02-15 00:42:19 +010070 msg = msgb_dequeue(&queue->msg_queue);
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020071 rc = queue->write_cb(fd, msg);
Holger Hans Peter Freyther76681ba2011-02-15 00:42:19 +010072 msgb_free(msg);
73
Holger Hans Peter Freythereb55e6a2014-07-01 19:39:26 +020074 if (rc == -EBADF)
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020075 goto err_badfd;
76
Holger Hans Peter Freyther76681ba2011-02-15 00:42:19 +010077 if (!llist_empty(&queue->msg_queue))
78 fd->when |= BSC_FD_WRITE;
79 }
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010080 }
81
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020082err_badfd:
83 /* Return value is not checked in osmo_select_main() */
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010084 return 0;
85}
86
Harald Welte2777ecd2011-08-17 14:23:42 +020087/*! \brief Initialize a \ref osmo_wqueue structure
88 * \param[in] queue Write queue to operate on
89 * \param[in] max_length Maximum length of write queue
90 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020091void osmo_wqueue_init(struct osmo_wqueue *queue, int max_length)
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010092{
93 queue->max_length = max_length;
94 queue->current_length = 0;
95 queue->read_cb = NULL;
96 queue->write_cb = NULL;
Holger Hans Peter Freytherc7f52c42016-11-12 21:25:21 +010097 queue->except_cb = NULL;
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020098 queue->bfd.cb = osmo_wqueue_bfd_cb;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010099 INIT_LLIST_HEAD(&queue->msg_queue);
100}
101
Harald Welte2777ecd2011-08-17 14:23:42 +0200102/*! \brief Enqueue a new \ref msgb into a write queue
103 * \param[in] queue Write queue to be used
104 * \param[in] data to-be-enqueued message buffer
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200105 * \returns 0 on success; negative on error
Harald Welte2777ecd2011-08-17 14:23:42 +0200106 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +0200107int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data)
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +0100108{
Holger Hans Peter Freytherc7f52c42016-11-12 21:25:21 +0100109 if (queue->current_length >= queue->max_length) {
110 LOGP(DLGLOBAL, LOGL_ERROR,
111 "wqueue(%p) is full. Rejecting msgb\n", queue);
112 return -ENOSPC;
113 }
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +0100114
115 ++queue->current_length;
116 msgb_enqueue(&queue->msg_queue, data);
117 queue->bfd.when |= BSC_FD_WRITE;
118
119 return 0;
120}
Holger Hans Peter Freyther99a263f2010-03-26 09:20:22 +0100121
Harald Welte2777ecd2011-08-17 14:23:42 +0200122/*! \brief Clear a \ref osmo_wqueue
123 * \param[in] queue Write queue to be cleared
124 *
125 * This function will clear (remove/release) all messages in it.
126 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +0200127void osmo_wqueue_clear(struct osmo_wqueue *queue)
Holger Hans Peter Freyther99a263f2010-03-26 09:20:22 +0100128{
129 while (!llist_empty(&queue->msg_queue)) {
130 struct msgb *msg = msgb_dequeue(&queue->msg_queue);
131 msgb_free(msg);
132 }
133
134 queue->current_length = 0;
135 queue->bfd.when &= ~BSC_FD_WRITE;
136}
Harald Welte2777ecd2011-08-17 14:23:42 +0200137
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200138/*! @} */