1 #include <stdlib.h>
2 #include "thread.h"
3 #include <stdio.h>
4 #include <errno.h>
5
6 #include <unistd.h>
7 #include <time.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10 #include <pthread.h>
11
Thread()12 Thread::Thread()
13 : m_read(-1)
14 , m_write(-1)
15 , m_threadNum(-1)
16
17 , m_parentRead(-1)
18 , m_parentWrite(-1)
19 , m_childRead(-1)
20 , m_childWrite(-1)
21 , m_numThreads(0)
22 , m_retVal(NULL)
23 , m_thread_info(NULL)
24 {
25 }
26
Thread(int threadNum,const Thread * parent)27 Thread::Thread(int threadNum, const Thread *parent)
28 : m_read(parent->m_childRead)
29 , m_write(parent->m_childWrite)
30 , m_threadNum(threadNum)
31
32 , m_parentRead(-1)
33 , m_parentWrite(-1)
34 , m_childRead(-1)
35 , m_childWrite(-1)
36 , m_numThreads(parent->m_numThreads)
37 , m_retVal(&parent->m_retVal[threadNum])
38 , m_thread_info(NULL)
39 {
40 }
41
~Thread()42 Thread::~Thread()
43 {
44 if(m_threadNum == -1)
45 {
46 for(int i = 0; i < m_numThreads; i++)
47 {
48 pthread_join(m_thread_info[i], NULL);
49 }
50 close(m_parentRead);
51 close(m_parentWrite);
52 close(m_childRead);
53 close(m_childWrite);
54 delete m_thread_info;
55 delete m_retVal;
56 }
57 }
58
59 // for the benefit of this function and the new Thread class it may create
60 // the Thread class must do nothing of note in it's constructor or it's
61 // go() member function.
thread_func(PVOID param)62 PVOID thread_func(PVOID param)
63 {
64 THREAD_DATA *td = (THREAD_DATA *)param;
65 Thread *thread = td->f->newThread(td->threadNum);
66 thread->setRetVal(thread->action(td->param));
67 delete thread;
68 delete td;
69 return NULL;
70 }
71
go(PVOID param,int num)72 void Thread::go(PVOID param, int num)
73 {
74 m_numThreads += num;
75 int control[2];
76 int feedback[2];
77 if (pipe(feedback) || pipe(control))
78 {
79 fprintf(stderr, "Can't open pipes.\n");
80 exit(1);
81 }
82 m_parentRead = feedback[0];
83 m_parentWrite = control[1];
84 m_childRead = control[0];
85 m_childWrite = feedback[1];
86 m_read = m_parentRead;
87 m_write = m_parentWrite;
88 m_readPoll.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
89 m_writePoll.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
90 m_readPoll.fd = m_parentRead;
91 m_writePoll.fd = m_parentWrite;
92 pthread_attr_t attr;
93 if(pthread_attr_init(&attr)
94 || pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)
95 || pthread_attr_setstacksize(&attr, 32*1024))
96 fprintf(stderr, "Can't set thread attributes.\n");
97
98 m_retVal = new int[num + 1];
99 m_thread_info = new pthread_t[num];
100 for(int i = 1; i <= num; i++)
101 {
102 m_retVal[i] = -1;
103 THREAD_DATA *td = new THREAD_DATA;
104 td->f = this;
105 td->param = param;
106 td->threadNum = i;
107 int p = pthread_create(&m_thread_info[i - 1], &attr, thread_func, PVOID(td));
108 if(p)
109 {
110 fprintf(stderr, "Can't create a thread.\n");
111 exit(1);
112 }
113 }
114 if(pthread_attr_destroy(&attr))
115 fprintf(stderr, "Can't destroy thread attributes.\n");
116 m_readPoll.fd = m_read;
117 m_writePoll.fd = m_write;
118 }
119
setRetVal(int rc)120 void Thread::setRetVal(int rc)
121 {
122 *m_retVal = rc;
123 }
124
Read(PVOID buf,int size,int timeout)125 int Thread::Read(PVOID buf, int size, int timeout)
126 {
127 if(timeout)
128 {
129 int rc = poll(&m_readPoll, 1, timeout * 1000);
130 if(rc < 0)
131 {
132 fprintf(stderr, "Can't poll read ITC.\n");
133 return -1;
134 }
135 if(!rc)
136 return 0;
137 }
138 if(size != read(m_read, buf, size) )
139 {
140 fprintf(stderr, "Can't read data from ITC pipe.\n");
141 return -1;
142 }
143 return size;
144 }
145
Write(PVOID buf,int size,int timeout)146 int Thread::Write(PVOID buf, int size, int timeout)
147 {
148 if(timeout)
149 {
150 int rc;
151 do
152 {
153 rc = poll(&m_writePoll, 1, timeout * 1000);
154 if(rc < 0 && errno != EINTR)
155 {
156 fprintf(stderr, "Can't poll write ITC.\n");
157 return -1;
158 }
159 } while(rc == -1);
160 if(!rc)
161 return 0;
162 }
163 if(size != write(m_write, buf, size))
164 {
165 fprintf(stderr, "Can't write data to ITC pipe.\n");
166 return -1;
167 }
168 return size;
169 }
170
171