sysmobts: Read multiple primitives at once but only up to 3

In most cases there are multiple messages ready to be read from
the queue and it is more efficient to read them in one go instead
of going through the select again.
This commit is contained in:
Holger Hans Peter Freyther 2013-05-01 16:13:37 +02:00
parent 44eec601bc
commit 718cc9dcac
1 changed files with 58 additions and 27 deletions

View File

@ -156,49 +156,80 @@ static int wqueue_vector_cb(struct osmo_fd *fd, unsigned int what)
return 0;
}
/* callback when there's something to read from the l1 msg_queue */
static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what)
static int prim_size_for_queue(int queue)
{
//struct msgb *msg = l1p_msgb_alloc();
struct msgb *msg = msgb_alloc_headroom(SYSMOBTS_PRIM_SIZE, 128, "1l_fd");
struct femtol1_hdl *fl1h = ofd->data;
int rc;
msg->l1h = msg->data;
rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg));
if (rc < 0) {
if (rc != -1)
LOGP(DL1C, LOGL_ERROR, "error reading from L1 msg_queue: %s\n",
strerror(errno));
msgb_free(msg);
return rc;
}
msgb_put(msg, rc);
switch (ofd->priv_nr) {
switch (queue) {
case MQ_SYS_WRITE:
return sizeof(SuperFemto_Prim_t);
case MQ_L1_WRITE:
#ifndef HW_SYSMOBTS_V1
case MQ_TCH_WRITE:
case MQ_PDTCH_WRITE:
#endif
return sizeof(GsmL1_Prim_t);
default:
/* The compiler can't know that priv_nr is an enum. Assist. */
LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n",
queue);
assert(false);
break;
}
}
/* callback when there's something to read from the l1 msg_queue */
static int read_dispatch_one(struct femtol1_hdl *fl1h, struct msgb *msg, int queue)
{
switch (queue) {
case MQ_SYS_WRITE:
if (rc != sizeof(SuperFemto_Prim_t))
LOGP(DL1C, LOGL_NOTICE, "%u != "
"sizeof(SuperFemto_Prim_t)\n", rc);
return l1if_handle_sysprim(fl1h, msg);
case MQ_L1_WRITE:
#ifndef HW_SYSMOBTS_V1
case MQ_TCH_WRITE:
case MQ_PDTCH_WRITE:
#endif
if (rc != sizeof(GsmL1_Prim_t))
LOGP(DL1C, LOGL_NOTICE, "%u != "
"sizeof(GsmL1_Prim_t)\n", rc);
return l1if_handle_l1prim(ofd->priv_nr, fl1h, msg);
return l1if_handle_l1prim(queue, fl1h, msg);
default:
/* The compiler can't know that priv_nr is an enum. Assist. */
LOGP(DL1C, LOGL_FATAL, "writing on a wrong queue: %d\n",
ofd->priv_nr);
queue);
assert(false);
break;
}
};
static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what)
{
int i, rc;
const uint32_t prim_size = prim_size_for_queue(ofd->priv_nr);
uint32_t count;
struct iovec iov[3];
struct msgb *msg[ARRAY_SIZE(iov)];
for (i = 0; i < ARRAY_SIZE(iov); ++i) {
msg[i] = msgb_alloc_headroom(prim_size + 128, 128, "1l_fd");
msg[i]->l1h = msg[i]->data;
iov[i].iov_base = msg[i]->l1h;
iov[i].iov_len = msgb_tailroom(msg[i]);
}
rc = readv(ofd->fd, iov, ARRAY_SIZE(iov));
count = rc / prim_size;
for (i = 0; i < count; ++i) {
msgb_put(msg[i], prim_size);
read_dispatch_one(ofd->data, msg[i], ofd->priv_nr);
}
for (i = count; i < ARRAY_SIZE(iov); ++i)
msgb_free(msg[i]);
return 1;
}
/* callback when we can write to one of the l1 msg_queue devices */
static int l1fd_write_cb(struct osmo_fd *ofd, struct msgb *msg)
{