blob: 203815bb38928201b2df8967f71f1deab94e5325 [file] [log] [blame]
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +01001/*
Holger Hans Peter Freytherc7f52c42016-11-12 21:25:21 +01002 * (C) 2010-2016 by Holger Hans Peter Freyther
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +01003 * (C) 2010 by On-Waves
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020023#include <errno.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010024#include <osmocom/core/write_queue.h>
Holger Hans Peter Freytherc7f52c42016-11-12 21:25:21 +010025#include <osmocom/core/logging.h>
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010026
Harald Welte2777ecd2011-08-17 14:23:42 +020027/*! \addtogroup write_queue
28 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020029 * Write queue for writing \ref msgb to sockets/fds.
30 *
31 * \file write_queue.c */
Harald Welte2777ecd2011-08-17 14:23:42 +020032
Neels Hofmeyr87e45502017-06-20 00:17:59 +020033/*! Select loop function for write queue handling
Harald Welte2777ecd2011-08-17 14:23:42 +020034 * \param[in] fd osmocom file descriptor
35 * \param[in] what bit-mask of events that have happened
Harald Welte2d2e2cc2016-04-25 12:11:20 +020036 * \returns 0 on success; negative on error
Harald Welte2777ecd2011-08-17 14:23:42 +020037 *
38 * This function is provided so that it can be registered with the
39 * select loop abstraction code (\ref osmo_fd::cb).
40 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020041int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what)
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010042{
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020043 struct osmo_wqueue *queue;
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020044 int rc;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010045
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020046 queue = container_of(fd, struct osmo_wqueue, bfd);
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010047
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020048 if (what & BSC_FD_READ) {
49 rc = queue->read_cb(fd);
Holger Hans Peter Freythereb55e6a2014-07-01 19:39:26 +020050 if (rc == -EBADF)
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020051 goto err_badfd;
52 }
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010053
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020054 if (what & BSC_FD_EXCEPT) {
55 rc = queue->except_cb(fd);
Holger Hans Peter Freythereb55e6a2014-07-01 19:39:26 +020056 if (rc == -EBADF)
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020057 goto err_badfd;
58 }
Holger Hans Peter Freyther4052c812010-04-08 10:58:20 +020059
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010060 if (what & BSC_FD_WRITE) {
61 struct msgb *msg;
62
63 fd->when &= ~BSC_FD_WRITE;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010064
Holger Hans Peter Freyther76681ba2011-02-15 00:42:19 +010065 /* the queue might have been emptied */
66 if (!llist_empty(&queue->msg_queue)) {
67 --queue->current_length;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010068
Holger Hans Peter Freyther76681ba2011-02-15 00:42:19 +010069 msg = msgb_dequeue(&queue->msg_queue);
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020070 rc = queue->write_cb(fd, msg);
Holger Hans Peter Freyther76681ba2011-02-15 00:42:19 +010071 msgb_free(msg);
72
Holger Hans Peter Freythereb55e6a2014-07-01 19:39:26 +020073 if (rc == -EBADF)
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020074 goto err_badfd;
75
Holger Hans Peter Freyther76681ba2011-02-15 00:42:19 +010076 if (!llist_empty(&queue->msg_queue))
77 fd->when |= BSC_FD_WRITE;
78 }
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010079 }
80
Daniel Willmannbd8a89d2014-06-10 10:02:24 +020081err_badfd:
82 /* Return value is not checked in osmo_select_main() */
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010083 return 0;
84}
85
Neels Hofmeyr87e45502017-06-20 00:17:59 +020086/*! Initialize a \ref osmo_wqueue structure
Harald Welte2777ecd2011-08-17 14:23:42 +020087 * \param[in] queue Write queue to operate on
88 * \param[in] max_length Maximum length of write queue
89 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020090void osmo_wqueue_init(struct osmo_wqueue *queue, int max_length)
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010091{
92 queue->max_length = max_length;
93 queue->current_length = 0;
94 queue->read_cb = NULL;
95 queue->write_cb = NULL;
Holger Hans Peter Freytherc7f52c42016-11-12 21:25:21 +010096 queue->except_cb = NULL;
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020097 queue->bfd.cb = osmo_wqueue_bfd_cb;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010098 INIT_LLIST_HEAD(&queue->msg_queue);
99}
100
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200101/*! Enqueue a new \ref msgb into a write queue
Harald Welte2777ecd2011-08-17 14:23:42 +0200102 * \param[in] queue Write queue to be used
103 * \param[in] data to-be-enqueued message buffer
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200104 * \returns 0 on success; negative on error
Harald Welte2777ecd2011-08-17 14:23:42 +0200105 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +0200106int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data)
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +0100107{
Holger Hans Peter Freytherc7f52c42016-11-12 21:25:21 +0100108 if (queue->current_length >= queue->max_length) {
109 LOGP(DLGLOBAL, LOGL_ERROR,
110 "wqueue(%p) is full. Rejecting msgb\n", queue);
111 return -ENOSPC;
112 }
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +0100113
114 ++queue->current_length;
115 msgb_enqueue(&queue->msg_queue, data);
116 queue->bfd.when |= BSC_FD_WRITE;
117
118 return 0;
119}
Holger Hans Peter Freyther99a263f2010-03-26 09:20:22 +0100120
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200121/*! Clear a \ref osmo_wqueue
Harald Welte2777ecd2011-08-17 14:23:42 +0200122 * \param[in] queue Write queue to be cleared
123 *
124 * This function will clear (remove/release) all messages in it.
125 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +0200126void osmo_wqueue_clear(struct osmo_wqueue *queue)
Holger Hans Peter Freyther99a263f2010-03-26 09:20:22 +0100127{
128 while (!llist_empty(&queue->msg_queue)) {
129 struct msgb *msg = msgb_dequeue(&queue->msg_queue);
130 msgb_free(msg);
131 }
132
133 queue->current_length = 0;
134 queue->bfd.when &= ~BSC_FD_WRITE;
135}
Harald Welte2777ecd2011-08-17 14:23:42 +0200136
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200137/*! @} */