blob: 3e488aea4bdab622bf9d37d2fadc52a952036119 [file] [log] [blame]
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +01001/* Generic write queue implementation */
2/*
3 * (C) 2010 by Holger Hans Peter Freyther
4 * (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 Freyther8df932a2010-02-26 20:30:32 +010026
Harald Welte2777ecd2011-08-17 14:23:42 +020027/*! \addtogroup write_queue
28 * @{
29 */
30
31/*! \file write_queue.c */
32
33/*! \brief Select loop function for write queue handling
34 * \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
Harald Welte2777ecd2011-08-17 14:23:42 +020086/*! \brief Initialize a \ref osmo_wqueue structure
87 * \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;
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +020096 queue->bfd.cb = osmo_wqueue_bfd_cb;
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +010097 INIT_LLIST_HEAD(&queue->msg_queue);
98}
99
Harald Welte2777ecd2011-08-17 14:23:42 +0200100/*! \brief Enqueue a new \ref msgb into a write queue
101 * \param[in] queue Write queue to be used
102 * \param[in] data to-be-enqueued message buffer
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200103 * \returns 0 on success; negative on error
Harald Welte2777ecd2011-08-17 14:23:42 +0200104 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +0200105int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data)
Holger Hans Peter Freyther8df932a2010-02-26 20:30:32 +0100106{
107// if (queue->current_length + 1 >= queue->max_length)
108// LOGP(DMSC, LOGL_ERROR, "The queue is full. Dropping not yet implemented.\n");
109
110 ++queue->current_length;
111 msgb_enqueue(&queue->msg_queue, data);
112 queue->bfd.when |= BSC_FD_WRITE;
113
114 return 0;
115}
Holger Hans Peter Freyther99a263f2010-03-26 09:20:22 +0100116
Harald Welte2777ecd2011-08-17 14:23:42 +0200117/*! \brief Clear a \ref osmo_wqueue
118 * \param[in] queue Write queue to be cleared
119 *
120 * This function will clear (remove/release) all messages in it.
121 */
Pablo Neira Ayuso9111d932011-05-07 12:42:51 +0200122void osmo_wqueue_clear(struct osmo_wqueue *queue)
Holger Hans Peter Freyther99a263f2010-03-26 09:20:22 +0100123{
124 while (!llist_empty(&queue->msg_queue)) {
125 struct msgb *msg = msgb_dequeue(&queue->msg_queue);
126 msgb_free(msg);
127 }
128
129 queue->current_length = 0;
130 queue->bfd.when &= ~BSC_FD_WRITE;
131}
Harald Welte2777ecd2011-08-17 14:23:42 +0200132
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200133/*! @} */