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
15Fork::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.
26VOID 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
34void 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
44void 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
110int 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
130int 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
159int 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
188