ref: b7d8431036d1fbc8d366ef9ddff5e6ab93e4bc94
parent: a2f0fdbfa016157ee962947f4670ac37f7041508
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Apr 29 17:15:09 EDT 2014
kernel: stop queue bloat before allocating blocks
--- a/sys/src/9/port/qio.c
+++ b/sys/src/9/port/qio.c
@@ -1153,6 +1153,31 @@
}
/*
+ * flow control, wait for queue to get below the limit
+ */
+static void
+qflow(Queue *q)
+{
+ for(;;){
+ if(q->noblock || qnotfull(q))
+ break;
+
+ ilock(q);
+ q->state |= Qflow;
+ iunlock(q);
+
+ eqlock(&q->wlock);
+ if(waserror()){
+ qunlock(&q->wlock);
+ nexterror();
+ }
+ sleep(&q->wr, qnotfull, q);
+ qunlock(&q->wlock);
+ poperror();
+ }
+}
+
+/*
* add a block to a queue obeying flow control
*/
long
@@ -1182,17 +1207,11 @@
}
/* don't queue over the limit */
- if(q->len >= q->limit){
- if(q->noblock){
- iunlock(q);
- freeb(b);
- poperror();
- return n;
- }
- if(q->len >= q->limit*10){
- iunlock(q);
- error(Egreg);
- }
+ if(q->len >= q->limit && q->noblock){
+ iunlock(q);
+ freeb(b);
+ poperror();
+ return n;
}
/* queue the block */
@@ -1228,35 +1247,14 @@
}
/*
- * flow control, wait for queue to get below the limit
- * before allowing the process to continue and queue
- * more. We do this here so that postnote can only
- * interrupt us after the data has been queued. This
- * means that things like 9p flushes and ssl messages
- * will not be disrupted by software interrupts.
- *
- * Note - this is moderately dangerous since a process
- * that keeps getting interrupted and rewriting will
- * queue up to 10 times the queue limit before failing.
+ * flow control, before allowing the process to continue and
+ * queue more. We do this here so that postnote can only
+ * interrupt us after the data has been queued. This means that
+ * things like 9p flushes and ssl messages will not be disrupted
+ * by software interrupts.
*/
- for(;;){
- if(q->noblock || qnotfull(q))
- break;
+ qflow(q);
- ilock(q);
- q->state |= Qflow;
- iunlock(q);
-
- eqlock(&q->wlock);
- if(waserror()){
- qunlock(&q->wlock);
- nexterror();
- }
- sleep(&q->wr, qnotfull, q);
- qunlock(&q->wlock);
- poperror();
- }
-
return n;
}
@@ -1272,6 +1270,16 @@
QDEBUG if(!islo())
print("qwrite hi %#p\n", getcallerpc(&q));
+
+ /* stop queue bloat before allocating blocks */
+ if(q->len/2 >= q->limit && q->noblock == 0 && q->bypass == nil){
+ while(waserror()){
+ if(up->procctl == Proc_exitme || up->procctl == Proc_exitbig)
+ error(Egreg);
+ }
+ qflow(q);
+ poperror();
+ }
sofar = 0;
do {