Subversion Repositories shark

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 *   xfermem.c
3
 *
4
 *   Oliver Fromme  <oliver.fromme@heim3.tu-clausthal.de>
5
 *   Sun Apr  6 02:26:26 MET DST 1997
6
 *
7
 *   See xfermem.h for documentation/description.
8
 */
9
 
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <string.h>
13
#include <unistd.h>
14
#include <errno.h>
15
#include <sys/types.h>
16
#include <sys/time.h>
17
#include <sys/uio.h>
18
#include <sys/mman.h>
19
#include <sys/socket.h>
20
#include <fcntl.h>
21
 
22
#include "xfermem.h"
23
#include "mpg123.h"
24
 
25
#ifndef USE_MMAP
26
#include <sys/ipc.h>
27
#include <sys/shm.h>
28
#endif
29
 
30
extern int errno;
31
 
32
#if defined (USE_MMAP) && defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
33
#define MAP_ANON MAP_ANONYMOUS
34
#endif
35
 
36
void xfermem_init (txfermem **xf, int bufsize, int msize)
37
{
38
        int regsize = bufsize + msize + sizeof(txfermem);
39
 
40
#ifdef USE_MMAP
41
#  ifdef MAP_ANON
42
        if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE,
43
                        MAP_ANON | MAP_SHARED, -1, 0)) == (txfermem *) -1) {
44
                perror ("mmap()");
45
                exit (1);
46
        }
47
#  else
48
        int devzero;
49
        if ((devzero = open("/dev/zero", O_RDWR, 0)) == -1) {
50
                perror ("open(/dev/zero)");
51
                exit (1);
52
        }
53
        if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE,
54
                        MAP_SHARED, devzero, 0)) == (txfermem *) -1) {
55
                perror ("mmap()");
56
                exit (1);
57
        }
58
        close (devzero);
59
#  endif
60
#else
61
        struct shmid_ds shmemds;
62
        int shmemid;
63
        if ((shmemid = shmget(IPC_PRIVATE, regsize, IPC_CREAT | 0600)) == -1) {
64
                perror ("shmget()");
65
                exit (1);
66
        }
67
        if ((*xf = (txfermem *) shmat(shmemid, 0, 0)) == (txfermem *) -1) {
68
                perror ("shmat()");
69
                shmctl (shmemid, IPC_RMID, &shmemds);
70
                exit (1);
71
        }
72
        if (shmctl(shmemid, IPC_RMID, &shmemds) == -1) {
73
                perror ("shmctl()");
74
                xfermem_done (*xf);
75
                exit (1);
76
        }
77
#endif
78
        if (socketpair(AF_UNIX, SOCK_STREAM, 0, (*xf)->fd) < 0) {
79
                perror ("socketpair()");
80
                xfermem_done (*xf);
81
                exit (1);
82
        }
83
        (*xf)->freeindex = (*xf)->readindex = 0;
84
        (*xf)->wakeme[0] = (*xf)->wakeme[1] = FALSE;
85
        (*xf)->data = ((byte *) *xf) + sizeof(txfermem) + msize;
86
        (*xf)->metadata = ((byte *) *xf) + sizeof(txfermem);
87
        (*xf)->size = bufsize;
88
        (*xf)->metasize = msize;
89
}
90
 
91
void xfermem_done (txfermem *xf)
92
{
93
#ifdef USE_MMAP
94
        munmap ((caddr_t) xf, xf->size + xf->metasize + sizeof(txfermem));
95
#else
96
        if (shmdt((void *) xf) == -1) {
97
                perror ("shmdt()");
98
                exit (1);
99
        }
100
#endif
101
}
102
 
103
void xfermem_init_writer (txfermem *xf)
104
{
105
        close (xf->fd[XF_READER]);
106
}
107
 
108
void xfermem_init_reader (txfermem *xf)
109
{
110
        close (xf->fd[XF_WRITER]);
111
}
112
 
113
int xfermem_get_freespace (txfermem *xf)
114
{
115
        int freeindex, readindex;
116
 
117
        if ((freeindex = xf->freeindex) < 0
118
                        || (readindex = xf->readindex) < 0)
119
                return (0);
120
        if (readindex > freeindex)
121
                return ((readindex - freeindex) - 1);
122
        else
123
                return ((xf->size - (freeindex - readindex)) - 1);
124
}
125
 
126
int xfermem_get_usedspace (txfermem *xf)
127
{
128
        int freeindex, readindex;
129
 
130
        if ((freeindex = xf->freeindex) < 0
131
                        || (readindex = xf->readindex) < 0)
132
                return (0);
133
        if (freeindex >= readindex)
134
                return (freeindex - readindex);
135
        else
136
                return (xf->size - (readindex - freeindex));
137
}
138
 
139
int xfermem_write (txfermem *xf, byte *data, int count)
140
{
141
        int nbytes;
142
 
143
        if ((nbytes = xfermem_get_freespace(xf))> count)
144
                nbytes = count;
145
        if (nbytes) {
146
                if (xf->freeindex + nbytes > xf->size) {
147
                        int first = xf->size - xf->freeindex;
148
                        memcpy (xf->data + xf->freeindex, data, first);
149
                        memcpy (xf->data, data + first, nbytes - first);
150
                }
151
                else
152
                        memcpy (xf->data + xf->freeindex, data, nbytes);
153
                xf->freeindex = (xf->freeindex + nbytes) % xf->size;
154
        }
155
        return (nbytes);
156
}
157
 
158
int xfermem_read (txfermem *xf, byte *data, int count)
159
{
160
        int nbytes;
161
 
162
        if ((nbytes = xfermem_get_usedspace(xf))> count)
163
                nbytes = count;
164
        if (nbytes) {
165
                if (xf->readindex + nbytes > xf->size) {
166
                        int first = xf->size - xf->readindex;
167
                        memcpy (data, xf->data + xf->readindex, first);
168
                        memcpy (data + first, xf->data, nbytes - first);
169
                }
170
                else
171
                        memcpy (data, xf->data + xf->readindex, nbytes);
172
                xf->readindex = (xf->readindex + nbytes) % xf->size;
173
        }
174
        return (nbytes);
175
}
176
 
177
int xfermem_getcmd (int fd, int block)
178
{
179
        fd_set selfds;
180
        struct timeval selto = {0, 0};
181
        byte cmd;
182
 
183
        for (;;) {
184
                FD_ZERO (&selfds);
185
                FD_SET (fd, &selfds);
186
                switch (select(FD_SETSIZE, &selfds, NULL, NULL, block ? NULL : &selto)) {
187
                        case 0:
188
                                if (!block)
189
                                        return (0);
190
                                continue;
191
                        case -1:
192
                                if (errno == EINTR)
193
                                        continue;
194
                                return (-2);
195
                        case 1:
196
                                if (FD_ISSET(fd, &selfds))
197
                                        switch (read(fd, &cmd, 1)) {
198
                                                case 0: /* EOF */
199
                                                        return (-1);
200
                                                case -1:
201
                                                        if (errno == EINTR)
202
                                                                continue;
203
                                                        return (-3);
204
                                                case 1:
205
                                                        return (cmd);
206
                                                default: /* ?!? */
207
                                                        return (-4);
208
                                        }
209
                                else /* ?!? */
210
                                        return (-5);
211
                        default: /* ?!? */
212
                                return (-6);
213
                }
214
        }
215
}
216
 
217
int xfermem_putcmd (int fd, byte cmd)
218
{
219
        for (;;)
220
                switch (write(fd, &cmd, 1)) {
221
                        case 1:
222
                                return (1);
223
                        case -1:
224
                                if (errno != EINTR)
225
                                        return (-1);
226
                }
227
}
228
 
229
int xfermem_block (int readwrite, txfermem *xf)
230
{
231
        int myfd = xf->fd[readwrite];
232
        int result;
233
 
234
        xf->wakeme[readwrite] = TRUE;
235
        if (xf->wakeme[1 - readwrite])
236
                xfermem_putcmd (myfd, XF_CMD_WAKEUP);
237
        result = xfermem_getcmd(myfd, TRUE);
238
        xf->wakeme[readwrite] = FALSE;
239
        return ((result <= 0) ? -1 : result);
240
}
241
 
242
/* EOF */