|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Communication between threads
5: *
6: * Copyright 1997, 2001 Bernd Schmidt
7: */
8:
9: typedef union {
10: int i;
11: uae_u32 u32;
12: void *pv;
13: } uae_pt;
14:
15: /* These currently require the maximum size to be known at initialization
16: * time, but it wouldn't be hard to use a "normal" pipe as an extension once the
17: * user-level one gets full.
18: * We queue up to chunks pieces of data before signalling the other thread to
19: * avoid overhead. */
20:
21: typedef struct {
22: uae_sem_t lock;
23: uae_sem_t reader_wait;
24: uae_sem_t writer_wait;
25: uae_pt *data;
26: int size, chunks;
27: volatile int rdp, wrp;
28: volatile int writer_waiting;
29: volatile int reader_waiting;
30: } smp_comm_pipe;
31:
32: static __inline__ void init_comm_pipe (smp_comm_pipe *p, int size, int chunks)
33: {
34: p->data = (uae_pt *)malloc (size*sizeof (uae_pt));
35: p->size = size;
36: p->chunks = chunks;
37: p->rdp = p->wrp = 0;
38: p->reader_waiting = 0;
39: p->writer_waiting = 0;
40: uae_sem_init (&p->lock, 0, 1);
41: uae_sem_init (&p->reader_wait, 0, 0);
42: uae_sem_init (&p->writer_wait, 0, 0);
43: }
44:
45: static __inline__ void destroy_comm_pipe (smp_comm_pipe *p)
46: {
47: uae_sem_destroy (&p->lock);
48: uae_sem_destroy (&p->reader_wait);
49: uae_sem_destroy (&p->writer_wait);
50: }
51:
52: static __inline__ void maybe_wake_reader (smp_comm_pipe *p, int no_buffer)
53: {
54: if (p->reader_waiting
55: && (no_buffer || ((p->wrp - p->rdp + p->size) % p->size) >= p->chunks))
56: {
57: p->reader_waiting = 0;
58: uae_sem_post (&p->reader_wait);
59: }
60: }
61:
62: static __inline__ void write_comm_pipe_pt (smp_comm_pipe *p, uae_pt data, int no_buffer)
63: {
64: int nxwrp = (p->wrp + 1) % p->size;
65:
66: if (p->reader_waiting) {
67: /* No need to do all the locking */
68: p->data[p->wrp] = data;
69: p->wrp = nxwrp;
70: maybe_wake_reader (p, no_buffer);
71: return;
72: }
73:
74: uae_sem_wait (&p->lock);
75: if (nxwrp == p->rdp) {
76: /* Pipe full! */
77: p->writer_waiting = 1;
78: uae_sem_post (&p->lock);
79: /* Note that the reader could get in between here and do a
80: * sem_post on writer_wait before we wait on it. That's harmless.
81: * There's a similar case in read_comm_pipe_int_blocking. */
82: uae_sem_wait (&p->writer_wait);
83: uae_sem_wait (&p->lock);
84: }
85: p->data[p->wrp] = data;
86: p->wrp = nxwrp;
87: maybe_wake_reader (p, no_buffer);
88: uae_sem_post (&p->lock);
89: }
90:
91: static __inline__ uae_pt read_comm_pipe_pt_blocking (smp_comm_pipe *p)
92: {
93: uae_pt data;
94:
95: uae_sem_wait (&p->lock);
96: if (p->rdp == p->wrp) {
97: p->reader_waiting = 1;
98: uae_sem_post (&p->lock);
99: uae_sem_wait (&p->reader_wait);
100: uae_sem_wait (&p->lock);
101: }
102: data = p->data[p->rdp];
103: p->rdp = (p->rdp + 1) % p->size;
104:
105: /* We ignore chunks here. If this is a problem, make the size bigger in the init call. */
106: if (p->writer_waiting) {
107: p->writer_waiting = 0;
108: uae_sem_post (&p->writer_wait);
109: }
110: uae_sem_post (&p->lock);
111: return data;
112: }
113:
114: static __inline__ int comm_pipe_has_data (smp_comm_pipe *p)
115: {
116: return p->rdp != p->wrp;
117: }
118:
119: static __inline__ int read_comm_pipe_int_blocking (smp_comm_pipe *p)
120: {
121: uae_pt foo = read_comm_pipe_pt_blocking (p);
122: return foo.i;
123: }
124: static __inline__ uae_u32 read_comm_pipe_u32_blocking (smp_comm_pipe *p)
125: {
126: uae_pt foo = read_comm_pipe_pt_blocking (p);
127: return foo.u32;
128: }
129:
130: static __inline__ void *read_comm_pipe_pvoid_blocking (smp_comm_pipe *p)
131: {
132: uae_pt foo = read_comm_pipe_pt_blocking (p);
133: return foo.pv;
134: }
135:
136: static __inline__ void write_comm_pipe_int (smp_comm_pipe *p, int data, int no_buffer)
137: {
138: uae_pt foo;
139: foo.i = data;
140: write_comm_pipe_pt (p, foo, no_buffer);
141: }
142:
143: static __inline__ void write_comm_pipe_u32 (smp_comm_pipe *p, int data, int no_buffer)
144: {
145: uae_pt foo;
146: foo.u32 = data;
147: write_comm_pipe_pt (p, foo, no_buffer);
148: }
149:
150: static __inline__ void write_comm_pipe_pvoid (smp_comm_pipe *p, void *data, int no_buffer)
151: {
152: uae_pt foo;
153: foo.pv = data;
154: write_comm_pipe_pt (p, foo, no_buffer);
155: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.