4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "bcsignals.h"
31 #if defined(__TERMUX__)
36 Thread::Thread(int synchronous, int realtime, int autodelete)
38 this->synchronous = synchronous != 0;
39 this->realtime = realtime != 0;
40 this->autodelete = autodelete != 0;
44 cancel_enabled = false;
51 void* Thread::entrypoint(void *parameters)
53 Thread *thread = (Thread*)parameters;
55 // allow thread to be cancelled at any point during a region where it is enabled.
56 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
57 // Disable cancellation by default.
58 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
59 thread->cancel_enabled = false;
62 #if defined (__linux__) || defined (__TERMUX__)
63 // Set realtime here since it doesn't work in start
64 if( thread->realtime && getuid() == 0 ) {
65 struct sched_param param = { sched_priority : 1 };
66 if(pthread_setschedparam(thread->tid, SCHED_RR, ¶m) < 0)
67 perror("Thread::entrypoint pthread_attr_setschedpolicy");
71 thread->finished = true;
72 if( !thread->synchronous ) {
73 if( thread->autodelete ) delete thread;
74 else if( !thread->cancelled ) TheList::dbg_del(thread->tid);
75 else thread->tid = ((pthread_t)-1);
83 struct sched_param param;
85 pthread_attr_init(&attr);
87 // previously run, and did not join, join to clean up zombie
88 if( synchronous && exists() )
95 // Inherit realtime from current thread the easy way.
97 realtime = calculate_realtime();
100 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
102 if( realtime && getuid() == 0 ) {
103 if(pthread_attr_setschedpolicy(&attr, SCHED_RR) < 0)
104 perror("Thread::start pthread_attr_setschedpolicy");
105 param.sched_priority = 50;
106 if(pthread_attr_setschedparam(&attr, ¶m) < 0)
107 perror("Thread::start pthread_attr_setschedparam");
110 #if !defined(__TERMUX__)
111 if(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED) < 0)
112 perror("Thread::start pthread_attr_setinheritsched");
116 // autodelete may delete this immediately after create
117 int autodelete = this->autodelete;
119 pthread_create(&tid, &attr, Thread::entrypoint, this);
122 TheList::dbg_add(tid, owner, typeid(*this).name());
127 if( exists() && !cancelled ) {
128 LOCK_LOCKS("Thread::cancel");
131 if( !synchronous ) TheList::dbg_del(tid);
137 int Thread::join() // join this thread
139 if( !exists() ) return 0;
141 // NOTE: this fails if the thread is not synchronous or
142 // or another thread is already waiting to join.
143 int ret = pthread_join(tid, 0);
146 fprintf(stderr, "Thread %p: %s\n", (void*)tid, strerror(ret));
149 CLEAR_LOCKS_TID(tid);
150 TheList::dbg_del(tid);
151 tid = ((pthread_t)-1);
152 // Don't execute anything after this.
153 if( autodelete ) delete this;
157 while( running() && !cancelled ) {
158 int ret = pthread_kill(tid, 0);
162 tid = ((pthread_t)-1);
167 int Thread::enable_cancel()
169 if( !cancel_enabled ) {
170 cancel_enabled = true;
171 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
176 int Thread::disable_cancel()
178 if( cancel_enabled ) {
179 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
180 cancel_enabled = false;
185 int Thread::get_cancel_enabled()
187 return cancel_enabled;
190 void Thread::exit_thread()
197 int Thread::suspend_thread()
200 pthread_kill(tid, SIGSTOP);
204 int Thread::continue_thread()
207 pthread_kill(tid, SIGCONT);
211 int Thread::set_synchronous(int value)
213 this->synchronous = value != 0;
217 int Thread::set_realtime(int value)
219 this->realtime = value != 0;
223 int Thread::set_autodelete(int value)
225 this->autodelete = value != 0;
229 int Thread::get_autodelete()
231 return autodelete ? 1 : 0;
234 int Thread::get_synchronous()
236 return synchronous ? 1 : 0;
239 bool Thread::calculate_realtime()
241 //printf("Thread::calculate_realtime %d %d\n", getpid(), sched_getscheduler(0));
242 return (sched_getscheduler(0) == SCHED_RR ||
243 sched_getscheduler(0) == SCHED_FIFO);
246 int Thread::get_realtime()
248 return realtime ? 1 : 0;
251 unsigned long Thread::get_tid()
253 return (unsigned long)tid;