DBG("ASIO: New queue %p", q);
ASSERT(q->buffer_size);
q->allocated_requests = 0;
- q->allocated_writebacks = 0;
q->running_requests = 0;
+ q->running_writebacks = 0;
clist_init(&q->idle_list);
clist_init(&q->done_list);
work_queue_init(&asio_wpool, &q->queue);
{
DBG("ASIO: Removing queue %p", q);
ASSERT(!q->running_requests);
+ ASSERT(!q->running_writebacks);
ASSERT(!q->allocated_requests);
- ASSERT(!q->allocated_writebacks);
ASSERT(clist_empty(&q->done_list));
struct asio_request *r;
DBG("ASIO: Got %p", r);
}
r->op = ASIO_FREE;
+ r->fd = -1;
+ r->len = 0;
+ r->status = -1;
+ r->returned_errno = -1;
return r;
}
die("Asynchronous write to fd %d failed: %s", r->fd, strerror(r->returned_errno));
if (r->status != (int)r->len)
die("Asynchronous write to fd %d wrote only %d bytes out of %d", r->fd, r->status, r->len);
- q->allocated_writebacks--;
+ q->running_writebacks--;
asio_put(r);
}
else
return 1;
}
-struct asio_request *
-asio_get_writeback(struct asio_queue *q)
-{
- while (q->allocated_writebacks >= q->max_writebacks)
- {
- DBG("ASIO: Waiting for free writeback request");
- if (!asio_raw_wait(q))
- ASSERT(0);
- }
- q->allocated_writebacks++;
- struct asio_request *r = asio_get(q);
- r->op = ASIO_WRITE_BACK;
- return r;
-}
-
-void
-asio_turn_to_writeback(struct asio_request *r)
-{
- struct asio_queue *q = r->queue;
- ASSERT(r->op != ASIO_WRITE_BACK);
- while (q->allocated_writebacks >= q->max_writebacks)
- {
- DBG("ASIO: Waiting for free writeback request");
- if (!asio_raw_wait(q))
- ASSERT(0);
- }
- q->allocated_writebacks++;
- r->op = ASIO_WRITE_BACK;
-}
-
static void
asio_handler(struct worker_thread *t UNUSED, struct work *w)
{
struct asio_queue *q = r->queue;
DBG("ASIO: Submitting %p on queue %p", r, q);
ASSERT(r->op != ASIO_FREE);
+ if (r->op == ASIO_WRITE_BACK)
+ {
+ while (q->running_writebacks >= q->max_writebacks)
+ {
+ DBG("ASIO: Waiting for free writebacks");
+ if (!asio_raw_wait(q))
+ ASSERT(0);
+ }
+ q->running_writebacks++;
+ }
q->running_requests++;
r->work.go = asio_handler;
r->work.returned = NULL;
asio_put(r);
break;
}
- asio_turn_to_writeback(r);
+ r->op = ASIO_WRITE_BACK;
r->fd = 1;
r->len = r->status;
asio_submit(r);
for (uns i=0; i<10; i++)
{
- r = asio_get_writeback(&q);
+ r = asio_get(&q);
+ r->op = ASIO_WRITE_BACK;
r->fd = 1;
r->len = 1;
r->buffer[0] = 'A' + i;
uns buffer_size; // How large buffers do we use [user-settable]
uns max_writebacks; // Maximum number of writeback requests active [user-settable]
uns allocated_requests;
- uns allocated_writebacks;
- uns running_requests;
+ uns running_requests; // Total number of running requests
+ uns running_writebacks; // How many of them are writebacks
clist idle_list; // Recycled requests waiting for get
clist done_list; // Finished requests
struct work_queue queue;
ASIO_FREE,
ASIO_READ,
ASIO_WRITE,
- ASIO_WRITE_BACK, // Write with no success notification
+ ASIO_WRITE_BACK, // Background write with no success notification
};
struct asio_request {
void asio_init_queue(struct asio_queue *q); // Initialize a new queue
void asio_cleanup_queue(struct asio_queue *q);
-struct asio_request *asio_get(struct asio_queue *q); // Get an empty request (not for writeback)
-struct asio_request *asio_get_writeback(struct asio_queue *q); // Get an empty writeback request
-void asio_turn_to_writeback(struct asio_request *r); // Convert a request allocated as non-writeback to writeback
-void asio_submit(struct asio_request *r); // Submit the request
+struct asio_request *asio_get(struct asio_queue *q); // Get an empty request
+void asio_submit(struct asio_request *r); // Submit the request (can block if too many writebacks)
struct asio_request *asio_wait(struct asio_queue *q); // Wait for the first finished request, NULL if no more
void asio_put(struct asio_request *r); // Return a finished request for recycling
void asio_sync(struct asio_queue *q); // Wait until all requests are finished