~kris/9p

9hist

ref: fbcfb82ea6cd5e69275bbca8cfb9fe1e33904487 9hist/port/stream.c -rw-r--r-- 1.4 KiB
fbcfb82e — David du Colombier Plan 9 from Bell Labs 1993-05-11 33 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

static Queue *freed;

/*
 *  Interrupt handlers use freeb() to release blocks.  They are
 *  garbage collected by the kproc running bgc().
 */
static void
bgc(void *arg)
{
	Block *b, *nb;

	USED(arg);
	for(;;){
		tsleep(&freed->r, return0, 0, 500);
		if(freed->first == 0)
			continue;

		x = slphi();
		lock(&freed);
		b = freed->first;
		freed->first = freed->last = 0;;
		unlock(&freed);
		spllo();

		for(; b; b = nb){
			nb = b->next;
			free(b);
		}
	}
}

void
freeb(Block *b)
{
	lock(&freed);
	b->next = freed->first;
	freed->first = b;
	unlock(&freed);
}

void
blockinit(void)
{
	/* start garbage collector */
	kproc("buffer", bgc, 0);
}

/*
 *  allocate queues and blocks
 */
Queue*
allocq(int limit)
{
	Queue *q;

	q = smalloc(sizeof(Queue));
	q->limit = limit;
}

Block*
allocb(int size)
{
	Block *b;

	b = alloc(sizeof(Block) + size);
	if(b == 0)
		exhausted("blocks");

	b->base = (uchar*)(b+1);
	b->rp = b->wp = b->base;
	b->lim = b->base + size;

	return b;
}

/*
 *  copy out of a queue, returns # bytes copied
 */
int
consume(Queue *q, uchar *p, int len, int drop)
{
	Block *b;
	int n;

	lock(q);
	b = q->first;
	if(b == 0){
		q->state |= Qcsleep;
		unlock(q);
		return -1;
	}
	n = BLEN(b);
	if(n < len){
		memmove(p, b->rp, n);
	} else {
		memmove(p, b->rp, len);
}