root / synthbench / bonnie++ / .svn / text-base / forkit.cpp.svn-base @ 0:839f52ef7657
History | View | Annotate | Download (3.6 kB)
1 |
|
---|---|
2 |
#ifdef OS2 |
3 |
#define INCL_DOSPROCESS |
4 |
#else |
5 |
#include <unistd.h> |
6 |
#include <time.h> |
7 |
#include <stdlib.h> |
8 |
#include <sys/types.h> |
9 |
#include <sys/wait.h> |
10 |
#endif |
11 |
|
12 |
#include "forkit.h" |
13 |
|
14 |
|
15 |
Fork::Fork() |
16 |
: m_read(-1) |
17 |
, m_write(-1) |
18 |
, m_numThreads(0) |
19 |
{ |
20 |
} |
21 |
|
22 |
#ifdef OS2 |
23 |
// for the benefit of this function and the new Fork class it may create |
24 |
// the Fork class must do nothing of note in it's constructor or it's |
25 |
// go() member function. |
26 |
VOID APIENTRY thread_func(ULONG param) |
27 |
{ |
28 |
THREAD_DATA *td = (THREAD_DATA *)param; |
29 |
td->f = new Fork; |
30 |
td->f->startit(td); |
31 |
} |
32 |
#endif |
33 |
|
34 |
void Fork::startit(THREAD_DATA *td) |
35 |
{ |
36 |
m_read = td->child_read; |
37 |
m_write = td->child_write; |
38 |
td->func(this, td->param, td->threadNum); |
39 |
delete td->f; // delete ourself if td->f is not NULL |
40 |
delete td; |
41 |
exit(0); |
42 |
} |
43 |
|
44 |
void Fork::go(FUNCTION func, PVOID param, int num) |
45 |
{ |
46 |
m_numThreads = num; |
47 |
FILE_TYPE control[2]; |
48 |
FILE_TYPE feedback[2]; |
49 |
if (pipe(feedback) || pipe(control)) |
50 |
{ |
51 |
fprintf(stderr, "Can't open pipes.\n"); |
52 |
exit(1); |
53 |
} |
54 |
#ifndef OS2 |
55 |
m_readPoll.events = POLLIN | POLLERR | POLLHUP | POLLNVAL; |
56 |
m_writePoll.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL; |
57 |
#endif |
58 |
|
59 |
THREAD_DATA *td = new THREAD_DATA; |
60 |
td->child_read = control[0]; |
61 |
td->child_write = feedback[1]; |
62 |
td->f = NULL; |
63 |
td->param = param; |
64 |
td->func = func; |
65 |
for(int i = 0; i < num; i++) |
66 |
{ |
67 |
#ifdef OS2 |
68 |
THREAD_DATA *tmp = new THREAD_DATA; |
69 |
memcpy(tmp, td, sizeof(THREAD_DATA)); |
70 |
#endif |
71 |
td->threadNum = i; |
72 |
#ifdef OS2 |
73 |
// yes I know I am casting a pointer to an unsigned long |
74 |
// it's the way you're supposed to do things in OS/2 |
75 |
TID id = 0; |
76 |
if(DosCreateThread(&id, thread_func, ULONG(td), CREATE_READY, 32*1024)) |
77 |
{ |
78 |
fprintf(stderr, "Can't create a thread.\n"); |
79 |
exit(1); |
80 |
} |
81 |
#else |
82 |
int p = fork(); |
83 |
if(p == -1) |
84 |
{ |
85 |
fprintf(stderr, "Can't fork.\n"); |
86 |
exit(1); |
87 |
} |
88 |
if(p == 0) // child |
89 |
{ |
90 |
m_readPoll.fd = td->child_read; |
91 |
m_writePoll.fd = td->child_write; |
92 |
file_close(control[1]); |
93 |
file_close(feedback[0]); |
94 |
srand(getpid() ^ time(NULL)); |
95 |
startit(td); |
96 |
} |
97 |
#endif |
98 |
} |
99 |
// now we're in the parent thread/process |
100 |
m_write = control[1]; |
101 |
m_read = feedback[0]; |
102 |
#ifndef OS2 |
103 |
m_readPoll.fd = m_read; |
104 |
m_writePoll.fd = m_write; |
105 |
file_close(control[0]); |
106 |
file_close(feedback[1]); |
107 |
#endif |
108 |
} |
109 |
|
110 |
int Fork::wait() |
111 |
{ |
112 |
#ifdef OS2 |
113 |
TID status = 0; |
114 |
if(DosWaitThread(&status, DCWW_WAIT)) |
115 |
{ |
116 |
fprintf(stderr, "Can't wait for thread.\n"); |
117 |
return 1; |
118 |
} |
119 |
#else |
120 |
int status = 0; |
121 |
if(::wait(&status) == -1) |
122 |
{ |
123 |
fprintf(stderr, "Can't wait for thread.\n"); |
124 |
return 1; |
125 |
} |
126 |
#endif |
127 |
return 0; |
128 |
} |
129 |
|
130 |
int Fork::Read(PVOID buf, int size, int timeout) |
131 |
{ |
132 |
#ifndef OS2 |
133 |
if(timeout) |
134 |
{ |
135 |
int rc = poll(&m_readPoll, 1, timeout * 1000); |
136 |
if(rc < 0) |
137 |
{ |
138 |
fprintf(stderr, "Can't poll.\n"); |
139 |
return -1; |
140 |
} |
141 |
if(!rc) |
142 |
return 0; |
143 |
} |
144 |
#endif |
145 |
#ifdef OS2 |
146 |
unsigned long actual; |
147 |
int rc = DosRead(m_read, buf, size, &actual); |
148 |
if(rc || actual != size) |
149 |
#else |
150 |
if(size != read(m_read, buf, size) ) |
151 |
#endif |
152 |
{ |
153 |
fprintf(stderr, "Can't read data from IPC pipe.\n"); |
154 |
return -1; |
155 |
} |
156 |
return size; |
157 |
} |
158 |
|
159 |
int Fork::Write(PVOID buf, int size, int timeout) |
160 |
{ |
161 |
#ifndef OS2 |
162 |
if(timeout) |
163 |
{ |
164 |
int rc = poll(&m_writePoll, 1, timeout * 1000); |
165 |
if(rc < 0) |
166 |
{ |
167 |
fprintf(stderr, "Can't poll for write.\n"); |
168 |
return -1; |
169 |
} |
170 |
if(!rc) |
171 |
return 0; |
172 |
} |
173 |
#endif |
174 |
#ifdef OS2 |
175 |
unsigned long actual; |
176 |
int rc = DosWrite(m_write, buf, size, &actual); |
177 |
if(rc || actual != size) |
178 |
#else |
179 |
if(size != write(m_write, buf, size)) |
180 |
#endif |
181 |
{ |
182 |
fprintf(stderr, "Can't write data to IPC pipe.\n"); |
183 |
return -1; |
184 |
} |
185 |
return size; |
186 |
} |
187 |
|