1 /*
2 * xcam_thread.cpp - Thread
3 *
4 * Copyright (c) 2014 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Wind Yuan <feng.yuan@intel.com>
19 */
20
21 #include "xcam_thread.h"
22 #include "xcam_mutex.h"
23 #include <errno.h>
24 #include <signal.h>
25
26 namespace XCam {
27
Thread(const char * name)28 Thread::Thread (const char *name)
29 : _name (NULL)
30 , _thread_id (0)
31 , _started (false)
32 , _stopped (true)
33 , _policy (-1)
34 , _priority (-1)
35 {
36 if (name)
37 _name = strndup (name, XCAM_MAX_STR_SIZE);
38
39 XCAM_LOG_DEBUG ("Thread(%s) construction", XCAM_STR(_name));
40 }
41
~Thread()42 Thread::~Thread ()
43 {
44 XCAM_LOG_DEBUG ("Thread(%s) destruction", XCAM_STR(_name));
45
46 if (_name)
47 xcam_free (_name);
48 }
49
50 void *
thread_func(void * user_data)51 Thread::thread_func (void *user_data)
52 {
53 Thread *thread = (Thread *)user_data;
54 bool ret = true;
55
56 {
57 // Make sure running after start
58 SmartLock locker(thread->_mutex);
59 pthread_detach (pthread_self());
60 }
61 ret = thread->started ();
62
63 sigset_t set;
64
65 /* Block SIGQUIT and SIGTERM */
66
67 sigemptyset(&set);
68 sigaddset(&set, SIGQUIT);
69 sigaddset(&set, SIGINT);
70 sigaddset(&set, SIGTERM);
71 pthread_sigmask(SIG_BLOCK, &set, NULL);
72 while (true) {
73 {
74 SmartLock locker(thread->_mutex);
75 if (!thread->_started || ret == false) {
76 thread->_started = false;
77 thread->_thread_id = 0;
78 ret = false;
79 break;
80 }
81 }
82
83 ret = thread->loop ();
84 }
85
86 thread->stopped ();
87
88 {
89 SmartLock locker(thread->_mutex);
90 thread->_stopped = true;
91 }
92 thread->_exit_cond.broadcast ();
93
94 return NULL;
95 }
96
97 bool
started()98 Thread::started ()
99 {
100 XCAM_LOG_DEBUG ("Thread(%s) started", XCAM_STR(_name));
101 return true;
102 }
103
104 void
stopped()105 Thread::stopped ()
106 {
107 XCAM_LOG_DEBUG ("Thread(%s) stopped", XCAM_STR(_name));
108 }
109
start()110 bool Thread::start ()
111 {
112 SmartLock locker(_mutex);
113 if (_started)
114 return true;
115
116 pthread_attr_t attr;
117 size_t stacksize = 0;
118
119 if (pthread_attr_init(&attr)) {
120 XCAM_ASSERT(0);
121 }
122 if (!pthread_attr_getstacksize(&attr, &stacksize)) {
123 if (stacksize < 2048 * 1024) {
124 stacksize = 2048 * 1024;
125 }
126 pthread_attr_setstacksize(&attr, stacksize);
127 }
128
129 if (_policy != -1 || _priority != -1) {
130 int ret = -1;
131
132 if (_policy != -1) {
133 ret = pthread_attr_setschedpolicy(&attr, _policy);
134 if (ret) {
135 XCAM_LOG_WARNING ("Thread(%s) set sched policy failed.(%d, %s)",
136 XCAM_STR(_name), ret, strerror(ret));
137 }
138 }
139
140 if (_policy != -1 && _policy != SCHED_OTHER && _priority != -1) {
141 struct sched_param param;
142 param.sched_priority = _priority;
143 ret = pthread_attr_setschedparam(&attr, ¶m);
144 if (ret) {
145 XCAM_LOG_WARNING ("Thread(%s) set sched priority failed.(%d, %s)",
146 XCAM_STR(_name), ret, strerror(ret));
147 }
148 }
149
150 ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
151 if (ret) {
152 XCAM_LOG_WARNING ("Thread(%s) set sched inherit failed.(%d, %s)",
153 XCAM_STR(_name), ret, strerror(ret));
154 }
155 }
156
157 if (pthread_create(&_thread_id, &attr, (void* (*)(void*))thread_func, this) != 0) {
158 pthread_attr_destroy(&attr);
159 return false;
160 }
161
162 pthread_attr_destroy(&attr);
163 _started = true;
164 _stopped = false;
165
166 #ifdef __USE_GNU
167 char thread_name[16];
168 xcam_mem_clear (thread_name);
169 snprintf (thread_name, sizeof (thread_name), "xc:%s", XCAM_STR(_name));
170 int ret = pthread_setname_np (_thread_id, thread_name);
171 if (ret != 0) {
172 XCAM_LOG_WARNING ("Thread(%s) set name to thread_id failed.(%d, %s)", XCAM_STR(_name), ret, strerror(ret));
173 }
174 #endif
175
176 return true;
177 }
178
179 bool
emit_stop()180 Thread::emit_stop ()
181 {
182 SmartLock locker(_mutex);
183 _started = false;
184 return true;
185 }
186
stop()187 bool Thread::stop ()
188 {
189 XCAM_LOG_DEBUG ("stop thread(%s) _started: %d _stopped: %d",
190 XCAM_STR(_name), _started, _stopped);
191
192 emit_stop();
193
194 SmartLock locker(_mutex);
195 while (!_stopped) {
196 _exit_cond.wait(_mutex);
197 }
198
199 _policy = -1;
200 _priority = -1;
201
202 return true;
203 }
204
is_running()205 bool Thread::is_running ()
206 {
207 SmartLock locker(_mutex);
208 return _started;
209 }
210
211 }
212