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 */ 39 OSCL_EXPORT_REF OsclThread::OsclThread() 40 { 41 bCreated = false; 42 iJoined = false; 43 } 44 45 46 47 /* 48 * Class destructor 49 */ 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 */ 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 */ 148 OSCL_EXPORT_REF void OsclThread::Exit(OsclAny* exitcode) 149 { 150 //intentionally not implemented. 151 OSCL_UNUSED_ARG(exitcode); 152 153 } 154 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 */ 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 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 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 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 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 */ 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 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 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