… | |
… | |
6 | #include <unistd.h> |
6 | #include <unistd.h> |
7 | #include <sched.h> |
7 | #include <sched.h> |
8 | |
8 | |
9 | #define STACKSIZE 128 /* yeah */ |
9 | #define STACKSIZE 128 /* yeah */ |
10 | |
10 | |
11 | #define REQ_EXIT 0 |
11 | #define REQ_QUIT 0 |
12 | #define REQ_READ 1 |
12 | #define REQ_READ 1 |
13 | #define REQ_WRITE 2 |
13 | #define REQ_WRITE 2 |
14 | |
14 | |
15 | typedef struct { |
15 | typedef struct { |
16 | char stack[STACKSIZE]; |
16 | char stack[STACKSIZE]; |
… | |
… | |
22 | |
22 | |
23 | /* read/write */ |
23 | /* read/write */ |
24 | int fd; |
24 | int fd; |
25 | off_t offset; |
25 | off_t offset; |
26 | size_t length; |
26 | size_t length; |
27 | ssize_t done; |
27 | ssize_t result; |
28 | int errorno; |
28 | int errorno; |
29 | |
29 | |
30 | SV *data; |
30 | SV *data; |
31 | void *dataptr; |
31 | void *dataptr; |
32 | STRLEN offset; |
32 | STRLEN dataoffset; |
33 | } aio_cb; |
33 | } aio_cb; |
34 | |
34 | |
35 | typedef aio_cb *aio_req; |
35 | typedef aio_cb *aio_req; |
36 | |
36 | |
37 | static int started; |
37 | static int started; |
38 | static int reqpipe[2], respipe[2]; |
38 | static int reqpipe[2], respipe[2]; |
39 | |
39 | |
|
|
40 | static int aio_proc(void *arg); |
|
|
41 | |
40 | static void |
42 | static void |
41 | start_thread(void) |
43 | start_thread(void) |
42 | { |
44 | { |
43 | aio_thread *thr = NEW ( |
45 | aio_thread *thr; |
|
|
46 | |
|
|
47 | New (0, thr, 1, aio_thread); |
|
|
48 | |
44 | __clone (aio_proc, |
49 | if (clone (aio_proc, |
|
|
50 | &(thr->stack[STACKSIZE]), |
|
|
51 | CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND, |
|
|
52 | thr) >= 0) |
|
|
53 | started++; |
|
|
54 | else |
|
|
55 | Safefree (thr); |
45 | } |
56 | } |
46 | |
57 | |
47 | static void |
58 | static void |
48 | end_thread(void) |
59 | end_thread(void) |
49 | { |
60 | { |
50 | aio_req req = 0; |
61 | aio_req req = 0; |
51 | write (reqpipe[1], &req, sizeof (aio_req)); |
62 | write (reqpipe[1], &req, sizeof (aio_req)); |
52 | nthreads--; |
63 | started--; |
|
|
64 | } |
|
|
65 | |
|
|
66 | static void |
|
|
67 | set_errno(int errorno) |
|
|
68 | { |
|
|
69 | errno = errorno; |
|
|
70 | } |
|
|
71 | |
|
|
72 | #undef errno |
|
|
73 | #include <asm/unistd.h> |
|
|
74 | |
|
|
75 | static int |
|
|
76 | aio_proc(void *thr_arg) |
|
|
77 | { |
|
|
78 | aio_thread *thr = thr_arg; |
|
|
79 | int sig; |
|
|
80 | int errno; |
|
|
81 | aio_req req; |
|
|
82 | |
|
|
83 | /* we rely on gcc's ability to create closures. */ |
|
|
84 | _syscall3(int,lseek,int,fd,off_t,offset,int,whence); |
|
|
85 | _syscall3(int,read,int,fd,char *,buf,off_t,count); |
|
|
86 | _syscall3(int,write,int,fd,char *,buf,off_t,count); |
|
|
87 | |
|
|
88 | /* first get rid of any signals */ |
|
|
89 | for (sig = 1; sig < _NSIG; sig++) |
|
|
90 | if (sig != SIGTERM) |
|
|
91 | signal (sig, SIG_IGN); |
|
|
92 | |
|
|
93 | /* then loop */ |
|
|
94 | while (read (reqpipe[0], (void *)&req, sizeof (req)) == sizeof (req)) |
|
|
95 | { |
|
|
96 | req->thread = thr; |
|
|
97 | |
|
|
98 | if (req->type == REQ_READ || req->type == REQ_WRITE) |
|
|
99 | { |
|
|
100 | errno = 0; |
|
|
101 | |
|
|
102 | if (lseek (req->fd, req->offset, SEEK_SET) == req->offset) |
|
|
103 | { |
|
|
104 | if (req->type == REQ_READ) |
|
|
105 | req->result = read (req->fd, req->dataptr, req->length); |
|
|
106 | else |
|
|
107 | req->result = write(req->fd, req->dataptr, req->length); |
|
|
108 | } |
|
|
109 | |
|
|
110 | req->errorno = errno; |
|
|
111 | } |
|
|
112 | else |
|
|
113 | { |
|
|
114 | write (respipe[1], (void *)&req, sizeof (req)); |
|
|
115 | break; |
|
|
116 | } |
|
|
117 | |
|
|
118 | write (respipe[1], (void *)&req, sizeof (req)); |
|
|
119 | } |
|
|
120 | |
|
|
121 | return 0; |
53 | } |
122 | } |
54 | |
123 | |
55 | MODULE = Linux::AIO PACKAGE = Linux::AIO |
124 | MODULE = Linux::AIO PACKAGE = Linux::AIO |
56 | |
125 | |
57 | BOOT: |
126 | BOOT: |