1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 // -*- c++ -*-
19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
20
21 // OSCL_T H R E A D (T H R E A D I M P L E M E N T A T I O N)
22
23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
24
25 /*! \file oscl_thread.cpp .This file provides THREAD implementation that can be ported
26 to three OS LINUX, SYMBIAN, WIN32
27 */
28
29
30
31 // Implementation file for OSCL threads
32 #include "oscl_thread.h"
33
34
35
36 /*
37 * Class contructor
38 */
OsclThread()39 OSCL_EXPORT_REF OsclThread::OsclThread()
40 {
41 bCreated = false;
42 iJoined = false;
43 }
44
45
46
47 /*
48 * Class destructor
49 */
~OsclThread()50 OSCL_EXPORT_REF OsclThread::~OsclThread()
51 {
52
53 ;
54
55 }
56
57
58 /**
59 * OSCL Proc layer function
60 * Input Argument:
61 * function_name = Name of the thread Function
62 * stack_size = Size of the thread stack
63 * argument = Argument to be passed to thread function
64 * Thread_State = Enumeration which specifies the state of the thread on creation
65 * with values Running and Suspend
66 * Return value : eOsclProcError
67 */
Create(TOsclThreadFuncPtr function_name,int32 stack_size,TOsclThreadFuncArg argument,OsclThread_State state,bool oIsJoinable)68 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::Create(TOsclThreadFuncPtr function_name,
69 int32 stack_size,
70 TOsclThreadFuncArg argument,
71 OsclThread_State state,
72 bool oIsJoinable)
73 {
74 if (stack_size < 0)
75 return OsclProcStatus::INVALID_PARAM_ERROR;
76
77 if (function_name == NULL)
78 return OsclProcStatus::INVALID_PARAM_ERROR;
79
80 //Reset thread creation state, since the thread may
81 //have exited.
82 if (bCreated)
83 bCreated = false;
84
85
86 switch (state)
87 {
88 case Start_on_creation:
89 break;
90 case Suspend_on_creation:
91 //can't create suspended pthread.
92 return OsclProcStatus::INVALID_PARAM_ERROR;
93 }
94 pthread_attr_t attr;
95 pthread_attr_init(&attr);
96 if (stack_size != 0)
97 pthread_attr_setstacksize(&attr, stack_size);
98
99 // Default detachstate attribute to PTHREAD_CREATE_DETACHED state
100 int detach_ret;
101 if (oIsJoinable)
102 {
103 detach_ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
104 iJoined = true;
105 }
106 else
107 {
108 detach_ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
109 }
110 switch (detach_ret)
111 {
112 case 0: // successful, continue thread creation
113 break;
114 case EINVAL:
115 default:
116 return OsclProcStatus::PSHARED_ATTRIBUTE_SETTING_ERROR;
117 }
118
119 int result = pthread_create(
120 (pthread_t*) & ObjThread,
121 &attr,
122 function_name,
123 (void*)argument);
124
125 switch (result)
126 {
127 case 0:
128 bCreated = true;
129 return OsclProcStatus::SUCCESS_ERROR;
130 case EAGAIN:
131 return OsclProcStatus::NOT_ENOUGH_RESOURCES_ERROR;
132 default:
133 return OsclProcStatus::OTHER_ERROR;
134 }
135
136 }
137
138
139 /**
140 * OSCL Proc layer function
141 * ExitThread is a static function which is used to end the current thread. When called it
142 * just ends the execution of the current thread.
143 * Input Argument:
144 * exitcode = Exitcode of the thread. This can be used by other threads to know the
145 * exit status of this thread.
146 * Return value : None
147 */
Exit(OsclAny * exitcode)148 OSCL_EXPORT_REF void OsclThread::Exit(OsclAny* exitcode)
149 {
150 //intentionally not implemented.
151 OSCL_UNUSED_ARG(exitcode);
152
153 }
154
EnableKill()155 OSCL_EXPORT_REF void OsclThread::EnableKill()
156 {
157 ; //nothing needed
158
159 }
160
161 /**
162 * OSCL Proc layer function
163 * Suspend current thread execution for specified time.
164 * @param msec, t2: sleep time in milliseconds.
165 */
SleepMillisec(const int32 msec)166 OSCL_EXPORT_REF void OsclThread::SleepMillisec(const int32 msec)
167 {
168 struct timespec reqt, remt;
169 reqt.tv_sec = msec / 1000;
170 reqt.tv_nsec = 1000000 * (msec % 1000);
171 nanosleep(&reqt, &remt) ;
172
173 }
174
175
176 /**
177
178 * OSCL Proc layer function
179
180 * This is used to terminate a thread other than the current thread.
181
182 * Input Argument:
183
184 * exitcode = Exitcode of the thread. This can be used by other threads to know the
185
186 * exit status of this thread.
187
188 * Return value : Error code
189
190 */
191
Terminate(OsclAny * oscl_ExitCode)192 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::Terminate(OsclAny* oscl_ExitCode)
193 {
194
195
196 if (!bCreated)
197 return OsclProcStatus::INVALID_OPERATION_ERROR;
198
199 {
200 OSCL_UNUSED_ARG(oscl_ExitCode);
201
202 bCreated = false;
203 if (iJoined)
204 {
205 if (pthread_join(ObjThread, NULL) == 0)
206 {
207 return OsclProcStatus::SUCCESS_ERROR;
208 }
209 else
210 {
211 return OsclProcStatus::OTHER_ERROR;
212 }
213 }
214 return OsclProcStatus::NOT_IMPLEMENTED;
215 }
216 }
217
218
219
220
221
222
223
224 /**
225
226 * OSCL Proc layer function
227
228 * This API suspends the thread being referred. The thread can later be brought into execution
229
230 * by calling OSCL_ResumeThread() on it.
231
232 * Input Argument: None
233
234 * Return value : Error code
235
236 */
237
Suspend()238 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::Suspend()
239
240 {
241
242 if (!bCreated)
243 return OsclProcStatus::INVALID_OPERATION_ERROR;
244
245
246
247
248 {
249 //pthread doesn't support suspend/resume
250 return OsclProcStatus::NOT_IMPLEMENTED;
251
252 }
253
254
255 }
256
257
258
259
260
261
262
263 /**
264
265 * OSCL Proc layer function
266
267 * ResumeThread resumes the suspended thread and brings it into execution.
268
269 * Input Argument: None
270
271 * Return value : Error code
272
273 */
274
Resume()275 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::Resume()
276
277 {
278
279 if (!bCreated)
280 return OsclProcStatus::INVALID_OPERATION_ERROR;
281
282
283
284
285 {
286
287 //pthread doesn't support suspend/resume
288 return OsclProcStatus::NOT_IMPLEMENTED;
289
290 }
291
292
293 }
294
295
296
297
298
299 /**
300
301 * OSCL Proc layer function
302
303 * GetThreadPriority gets the priority of the thread. It takes reference of the input argument
304
305 * and assigns priority to it from one of the already defined priorities.
306
307 * Input Argument:
308
309 * int16& refThreadPriority : Output Priority value
310
311 * Return value : Error code
312
313 */
314
GetPriority(OsclThreadPriority & refThreadPriority)315 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::GetPriority(OsclThreadPriority& refThreadPriority)
316
317 {
318 if (!bCreated)
319 return OsclProcStatus::INVALID_OPERATION_ERROR;
320
321 struct sched_param schedparam;
322 int sched_policy = 0;
323 int pri;
324 int result;
325 result = pthread_getschedparam(ObjThread, &sched_policy, &schedparam);
326 if (result != 0)
327 {
328 switch (result)
329 {
330 case ESRCH:
331 return OsclProcStatus::INVALID_THREAD_ERROR;
332 case EFAULT:
333 return OsclProcStatus::INVALID_PARAM_ERROR;
334 default:
335 return OsclProcStatus::OTHER_ERROR;
336 }
337 }
338
339 pri = schedparam.sched_priority;
340 switch (sched_policy)
341 {
342 case SCHED_RR:
343 case SCHED_FIFO:
344 {
345 //static priority is 1..99
346 if (pri < 1)
347 return OsclProcStatus::OTHER_ERROR;
348 else if (pri == 1)
349 refThreadPriority = ThreadPriorityLowest;
350 else if (pri <= 20)
351 refThreadPriority = ThreadPriorityLow;
352 else if (pri <= 40)
353 refThreadPriority = ThreadPriorityBelowNormal;
354 else if (pri <= 55)
355 refThreadPriority = ThreadPriorityNormal;
356 else if (pri <= 75)
357 refThreadPriority = ThreadPriorityAboveNormal;
358 else if (pri <= 98)
359 refThreadPriority = ThreadPriorityHighest;
360 else if (pri == 99)
361 refThreadPriority = ThreadPriorityTimeCritical;
362 else if (pri > 99)
363 return OsclProcStatus::OTHER_ERROR;
364 return OsclProcStatus::SUCCESS_ERROR;
365 }
366 break;
367
368 case SCHED_OTHER:
369 {
370 //static priority is always zero.
371 if (pri != 0)
372 return OsclProcStatus::OTHER_ERROR;
373 refThreadPriority = ThreadPriorityNormal;
374 return OsclProcStatus::SUCCESS_ERROR;
375 }
376 break;
377
378 default:
379 return OsclProcStatus::OTHER_ERROR;
380 }
381 }
382
383
384
385 /**
386 * OSCL Proc layer function
387 * SetThreadPriority sets the priority of the thread. It takes priority as the input argument
388 * and assigns it to the thread referred.
389 * Input Argument:
390 * ePriorityLevel : Input Priority value
391 * Return value : Error code
392 */
SetPriority(OsclThreadPriority ePriority)393 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::SetPriority(OsclThreadPriority ePriority)
394 {
395 if (!bCreated)
396 return OsclProcStatus::INVALID_OPERATION_ERROR;
397
398 //not supported.
399 OSCL_UNUSED_ARG(ePriority);
400 return OsclProcStatus::NOT_IMPLEMENTED;
401
402 }
403
404
405
406 /**
407
408 * OSCL Proc layer function
409
410 * This is used to compare whether the thread ID's are equal.
411
412 * @param Thread ID passed by the application
413
414 * @return Error code
415
416 */
417
GetId(TOsclThreadId & refThreadId)418 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::GetId(TOsclThreadId& refThreadId)
419
420 {
421
422
423
424
425 refThreadId = pthread_self();
426
427 return OsclProcStatus::SUCCESS_ERROR;
428
429
430 }
431
432
CompareId(TOsclThreadId & t1,TOsclThreadId & t2)433 OSCL_EXPORT_REF bool OsclThread::CompareId(TOsclThreadId &t1, TOsclThreadId &t2)
434 //static routine
435 {
436 return (pthread_equal(t1, t2) != 0);
437 }
438
439
440
441
442
443
444 /**
445
446 * Helper Function
447
448 * Map the Operating system errors to OSCL defined erros
449
450 * Input Argument:
451
452 * error : Input error as one of the OS errors
453
454 * Return value : Error code ( User defined )
455
456 */
457
458
459
460
461
462
463