151 lines
2.1 KiB
C
151 lines
2.1 KiB
C
|
|
#include "stdinc.h"
|
||
|
|
#include "dat.h"
|
||
|
|
#include "fns.h"
|
||
|
|
|
||
|
|
typedef struct LumpQueue LumpQueue;
|
||
|
|
typedef struct WLump WLump;
|
||
|
|
|
||
|
|
enum
|
||
|
|
{
|
||
|
|
MaxLumpQ = 1 << 3 /* max. lumps on a single write queue, must be pow 2 */
|
||
|
|
};
|
||
|
|
|
||
|
|
struct WLump
|
||
|
|
{
|
||
|
|
Lump *u;
|
||
|
|
Packet *p;
|
||
|
|
int creator;
|
||
|
|
int gen;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct LumpQueue
|
||
|
|
{
|
||
|
|
QLock lock;
|
||
|
|
Rendez flush;
|
||
|
|
Rendez full;
|
||
|
|
Rendez empty;
|
||
|
|
WLump q[MaxLumpQ];
|
||
|
|
int w;
|
||
|
|
int r;
|
||
|
|
};
|
||
|
|
|
||
|
|
static LumpQueue *lumpqs;
|
||
|
|
static int nqs;
|
||
|
|
|
||
|
|
static QLock glk;
|
||
|
|
static int gen;
|
||
|
|
|
||
|
|
static void queueproc(void *vq);
|
||
|
|
|
||
|
|
int
|
||
|
|
initlumpqueues(int nq)
|
||
|
|
{
|
||
|
|
LumpQueue *q;
|
||
|
|
|
||
|
|
int i;
|
||
|
|
nqs = nq;
|
||
|
|
|
||
|
|
lumpqs = MKNZ(LumpQueue, nq);
|
||
|
|
|
||
|
|
for(i = 0; i < nq; i++){
|
||
|
|
q = &lumpqs[i];
|
||
|
|
q->full.l = &q->lock;
|
||
|
|
q->empty.l = &q->lock;
|
||
|
|
q->flush.l = &q->lock;
|
||
|
|
|
||
|
|
if(vtproc(queueproc, q) < 0){
|
||
|
|
seterr(EOk, "can't start write queue slave: %r");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* queue a lump & it's packet data for writing
|
||
|
|
*/
|
||
|
|
int
|
||
|
|
queuewrite(Lump *u, Packet *p, int creator)
|
||
|
|
{
|
||
|
|
LumpQueue *q;
|
||
|
|
int i;
|
||
|
|
|
||
|
|
i = indexsect(mainindex, u->score);
|
||
|
|
if(i < 0 || i >= nqs){
|
||
|
|
seterr(EBug, "internal error: illegal index section in queuewrite");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
q = &lumpqs[i];
|
||
|
|
|
||
|
|
qlock(&q->lock);
|
||
|
|
while(q->r == ((q->w + 1) & (MaxLumpQ - 1)))
|
||
|
|
rsleep(&q->full);
|
||
|
|
|
||
|
|
q->q[q->w].u = u;
|
||
|
|
q->q[q->w].p = p;
|
||
|
|
q->q[q->w].creator = creator;
|
||
|
|
q->q[q->w].gen = gen;
|
||
|
|
q->w = (q->w + 1) & (MaxLumpQ - 1);
|
||
|
|
|
||
|
|
rwakeup(&q->empty);
|
||
|
|
|
||
|
|
qunlock(&q->lock);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
queueflush(void)
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
LumpQueue *q;
|
||
|
|
|
||
|
|
qlock(&glk);
|
||
|
|
gen++;
|
||
|
|
qunlock(&glk);
|
||
|
|
|
||
|
|
for(i=0; i<mainindex->nsects; i++){
|
||
|
|
q = &lumpqs[i];
|
||
|
|
qlock(&q->lock);
|
||
|
|
while(q->w != q->r && gen - q->q[q->r].gen > 0)
|
||
|
|
rsleep(&q->flush);
|
||
|
|
qunlock(&q->lock);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
queueproc(void *vq)
|
||
|
|
{
|
||
|
|
LumpQueue *q;
|
||
|
|
Lump *u;
|
||
|
|
Packet *p;
|
||
|
|
int creator;
|
||
|
|
|
||
|
|
q = vq;
|
||
|
|
for(;;){
|
||
|
|
qlock(&q->lock);
|
||
|
|
while(q->w == q->r)
|
||
|
|
rsleep(&q->empty);
|
||
|
|
|
||
|
|
u = q->q[q->r].u;
|
||
|
|
p = q->q[q->r].p;
|
||
|
|
creator = q->q[q->r].creator;
|
||
|
|
|
||
|
|
rwakeup(&q->full);
|
||
|
|
|
||
|
|
qunlock(&q->lock);
|
||
|
|
|
||
|
|
if(writeqlump(u, p, creator) < 0)
|
||
|
|
fprint(2, "failed to write lump for %V: %r", u->score);
|
||
|
|
|
||
|
|
qlock(&q->lock);
|
||
|
|
q->r = (q->r + 1) & (MaxLumpQ - 1);
|
||
|
|
rwakeup(&q->flush);
|
||
|
|
qunlock(&q->lock);
|
||
|
|
|
||
|
|
putlump(u);
|
||
|
|
}
|
||
|
|
}
|