Give DATA a slot between slow cumulative BLE ACKs

This commit is contained in:
evgeny committed 2026-10-29 22:29:46 +01:00
1 parent b7e0b1f12c
commit c52afe4f41
1 file changed
+14 -2
+14 -2
View File
@@ -38,7 +38,7 @@ struct ble_connection {
uint16_t tx_next, tx_acked, rx_last, flight_head, flight_count, flight_bytes, flight_sizes[FLOW_SLOTS];
uint64_t flight_deadline, ack_due, ack_sent;
void* ack_timer;
int rx_flow_seen, ack_dirty, pending_ack;
int rx_flow_seen, ack_dirty, pending_ack, ack_yield;
enum ble_channel pending_channel, next_channel;
int outgoing, opened, ready, pending, control_pending;
uint8_t control[17];
@@ -176,7 +176,18 @@ static void pump(struct ble_transport* t, struct ble_connection* c) {
uint8_t value[BLE_VALUE_MAX];
size_t len;
c->pending_bytes = 0;
/* После ACK дать один слот payload: медленный ATT completion не должен вытеснять DATA при непрерывном RX. */
int payload_ready = c->control_pending && BLE_TX_WINDOW_BYTES - c->flight_bytes >= 17 + FLOW_HEADER && c->flight_count < FLOW_SLOTS;
if (c->ready && !c->control_pending) for (int i = 0; i < BLE_CHANNEL_COUNT; i++) {
struct ble_channel_state* ch = &c->channels[i];
if (i == BLE_CHANNEL_DATA && (BLE_TX_WINDOW_BYTES - c->flight_bytes < FLOW_MIN_VALUE || c->flight_count == FLOW_SLOTS)) continue;
if (ch->current || queue_entry_count(ch->tx)) payload_ready = 1;
}
c->pending_ack = c->ack_dirty && get_time_us() >= c->ack_due;
if (c->pending_ack && c->ack_yield && payload_ready) {
DEBUG_TRACE(DEBUG_CATEGORY_DEBUG, "BLE ACK yields payload slot link=%llu flight_bytes=%u", (unsigned long long)c->id, c->flight_bytes);
c->pending_ack = 0;
}
c->pending_channel = BLE_CHANNEL_DATA;
if (c->pending_ack) { write16(value, c->rx_last); len = 2; }
else if (c->control_pending) {
@@ -216,6 +227,7 @@ static void pump(struct ble_transport* t, struct ble_connection* c) {
int result = ble_backend_send(t->backend, c->id, wire, value, len);
if (result == BLE_OK) {
c->pending = 1; c->submitted = get_time_us(); c->deadline = c->submitted + DEADLINE_US;
if (wire != BLE_WIRE_ACK) c->ack_yield = 0;
if (wire == BLE_WIRE_ACK) {
if (c->ack_timer) { uasync_cancel_timeout(t->ua, c->ack_timer); c->ack_timer = NULL; }
c->ack_dirty = 0; c->ack_sent = c->submitted; c->stats.ack_tx++;
@@ -526,7 +538,7 @@ void ble_backend_sent(struct ble_transport* t, ble_link_id id, int success) {
c->stats.fragments++; c->stats.wait_us += waited;
if (waited > c->stats.max_wait_us) c->stats.max_wait_us = waited;
c->pending = 0;
if (c->pending_ack) { c->pending_ack = 0; pump(t, c); return; }
if (c->pending_ack) { c->pending_ack = 0; c->ack_yield = 1; pump(t, c); return; }
struct ble_channel_state* ch = &c->channels[channel];
if (!c->pending_bytes) c->control_pending = 0;
else if (ch->current) {