LIST_INIT(&cs->wait_list.list);
LIST_INIT(&cs->send_wait_list);
cs->conn = conn;
+ cs->wait_list.wait_reason = 0;
}
/* Initializes all required fields for a new connection. Note that it does the
struct server;
struct pipe;
+enum sub_event_type {
+ SUB_CAN_SEND = 0x00000001, /* Schedule the tasklet when we can send more */
+ SUB_CAN_RECV = 0x00000002, /* Schedule the tasklet when we can recv more */
+};
+
struct wait_list {
struct tasklet *task;
struct list list;
+ int wait_reason;
};
/* A connection handle is how we differenciate two connections on the lower
CS_SHW_SILENT = 1, /* imminent close, don't notify peer */
};
-enum sub_event_type {
- SUB_CAN_SEND = 0x00000001, /* Schedule the tasklet when we can send more */
-};
/* For each direction, we have a CO_FL_{SOCK,DATA}_<DIR>_ENA flag, which
* indicates if read or write is desired in that direction for the respective
* layers. The current status corresponding to the current layer being used is
struct wait_list *, list);
LIST_DEL(&sw->list);
LIST_INIT(&sw->list);
+ sw->wait_reason &= ~SUB_CAN_SEND;
tasklet_wakeup(sw->task);
}
}
switch (event_type) {
case SUB_CAN_SEND:
sw = param;
- if (LIST_ISEMPTY(&sw->list))
+ if (!(sw->wait_reason & SUB_CAN_SEND)) {
+ sw->wait_reason |= SUB_CAN_SEND;
LIST_ADDQ(&conn->send_wait_list, &sw->list);
+ }
return 0;
default:
break;
goto fail;
h2c->wait_list.task->process = h2_send;
h2c->wait_list.task->context = conn;
+ h2c->wait_list.wait_reason = 0;
h2c->ddht = hpack_dht_alloc(h2_settings_header_table_size);
if (!h2c->ddht)
struct wait_list *, list);
LIST_DEL(&sw->list);
LIST_INIT(&sw->list);
+ sw->wait_reason &= ~SUB_CAN_SEND;
tasklet_wakeup(sw->task);
}
switch (event_type) {
case SUB_CAN_SEND:
sw = param;
- if (LIST_ISEMPTY(&h2s->list) && LIST_ISEMPTY(&sw->list))
+ if (LIST_ISEMPTY(&h2s->list) &&
+ !(sw->wait_reason & SUB_CAN_SEND)) {
LIST_ADDQ(&h2s->h2c->send_wait_list, &sw->list);
+ sw->wait_reason |= SUB_CAN_SEND;
+ }
return 0;
default:
break;
int did_send = 0;
/* We're already waiting to be able to send, give up */
- if (!LIST_ISEMPTY(&cs->wait_list.list))
+ if (cs->wait_list.wait_reason & SUB_CAN_SEND)
return NULL;
if (conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)
if (conn->flags & CO_FL_HANDSHAKE) {
/* a handshake was requested */
/* Schedule ourself to be woken up once the handshake is done */
- LIST_ADDQ(&conn->send_wait_list, &cs->wait_list.list);
+ conn->xprt->subscribe(conn, SUB_CAN_SEND, wl_set_waitcb(&cs->wait_list, si_cs_send, ctx));
return NULL;
}
struct wait_list *, list);
LIST_DEL(&sw->list);
LIST_INIT(&sw->list);
+ sw->wait_reason &= ~SUB_CAN_SEND;
tasklet_wakeup(sw->task);
}
}