1/* 2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 3 * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this list of 9 * conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 * of conditions and the following disclaimer in the documentation and/or other materials 13 * provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used 16 * to endorse or promote products derived from this software without specific prior written 17 * permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include "pprivate.h" 33#include "pthread.h" 34#include "sched.h" 35 36#include "stdio.h" 37#include "map_error.h" 38#include "los_process_pri.h" 39#include "los_sched_pri.h" 40 41 42/* 43 * Array of pthread control structures. A pthread_t object is 44 * "just" an index into this array. 45 */ 46STATIC _pthread_data g_pthreadData[LOSCFG_BASE_CORE_TSK_LIMIT + 1]; 47 48/* Count of number of threads that have exited and not been reaped. */ 49STATIC INT32 g_pthreadsExited = 0; 50 51/* this is to protect the pthread data */ 52STATIC pthread_mutex_t g_pthreadsDataMutex = PTHREAD_MUTEX_INITIALIZER; 53 54/* pointed to by PTHREAD_CANCELED */ 55UINTPTR g_pthreadCanceledDummyVar; 56 57/* 58 * Private version of pthread_self() that returns a pointer to our internal 59 * control structure. 60 */ 61_pthread_data *pthread_get_self_data(void) 62{ 63 UINT32 runningTaskPID = ((LosTaskCB *)(OsCurrTaskGet()))->taskID; 64 _pthread_data *data = &g_pthreadData[runningTaskPID]; 65 66 return data; 67} 68 69_pthread_data *pthread_get_data(pthread_t id) 70{ 71 _pthread_data *data = NULL; 72 73 if (OS_TID_CHECK_INVALID(id)) { 74 return NULL; 75 } 76 77 data = &g_pthreadData[id]; 78 /* Check that this is a valid entry */ 79 if ((data->state == PTHREAD_STATE_FREE) || (data->state == PTHREAD_STATE_EXITED)) { 80 return NULL; 81 } 82 83 /* Check that the entry matches the id */ 84 if (data->id != id) { 85 return NULL; 86 } 87 88 /* Return the pointer */ 89 return data; 90} 91 92/* 93 * Check whether there is a cancel pending and if so, whether 94 * cancellations are enabled. We do it in this order to reduce the 95 * number of tests in the common case - when no cancellations are 96 * pending. We make this inline so it can be called directly below for speed 97 */ 98STATIC INT32 CheckForCancel(VOID) 99{ 100 _pthread_data *self = pthread_get_self_data(); 101 if (self->canceled && (self->cancelstate == PTHREAD_CANCEL_ENABLE)) { 102 return 1; 103 } 104 return 0; 105} 106 107STATIC VOID ProcessUnusedStatusTask(_pthread_data *data) 108{ 109 data->state = PTHREAD_STATE_FREE; 110 (VOID)memset_s(data, sizeof(_pthread_data), 0, sizeof(_pthread_data)); 111} 112 113/* 114 * This function is called to tidy up and dispose of any threads that have 115 * exited. This work must be done from a thread other than the one exiting. 116 * Note: this function must be called with pthread_mutex locked. 117 */ 118STATIC VOID PthreadReap(VOID) 119{ 120 UINT32 i; 121 _pthread_data *data = NULL; 122 /* 123 * Loop over the thread table looking for exited threads. The 124 * g_pthreadsExited counter springs us out of this once we have 125 * found them all (and keeps us out if there are none to do). 126 */ 127 for (i = 0; g_pthreadsExited && (i < g_taskMaxNum); i++) { 128 data = &g_pthreadData[i]; 129 if (data->state == PTHREAD_STATE_EXITED) { 130 /* the Huawei LiteOS not delete the dead TCB,so need to delete the TCB */ 131 (VOID)LOS_TaskDelete(data->task->taskID); 132 if (data->task->taskStatus & OS_TASK_STATUS_UNUSED) { 133 ProcessUnusedStatusTask(data); 134 g_pthreadsExited--; 135 } 136 } 137 } 138} 139 140STATIC VOID SetPthreadAttr(const _pthread_data *self, const pthread_attr_t *attr, pthread_attr_t *outAttr) 141{ 142 /* 143 * Set use_attr to the set of attributes we are going to 144 * actually use. Either those passed in, or the default set. 145 */ 146 if (attr == NULL) { 147 (VOID)pthread_attr_init(outAttr); 148 } else { 149 (VOID)memcpy_s(outAttr, sizeof(pthread_attr_t), attr, sizeof(pthread_attr_t)); 150 } 151 152 /* 153 * If the stack size is not valid, we can assume that it is at 154 * least PTHREAD_STACK_MIN bytes. 155 */ 156 if (!outAttr->stacksize_set) { 157 outAttr->stacksize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; 158 } 159 if (outAttr->inheritsched == PTHREAD_INHERIT_SCHED) { 160 if (self->task == NULL) { 161 outAttr->schedparam.sched_priority = LOS_TaskPriGet(OsCurrTaskGet()->taskID); 162 } else { 163 outAttr->schedpolicy = self->attr.schedpolicy; 164 outAttr->schedparam = self->attr.schedparam; 165 outAttr->scope = self->attr.scope; 166 } 167 } 168} 169 170STATIC VOID SetPthreadDataAttr(const pthread_attr_t *userAttr, const pthread_t threadID, 171 LosTaskCB *taskCB, _pthread_data *created) 172{ 173 created->attr = *userAttr; 174 created->id = threadID; 175 created->task = taskCB; 176 created->state = (userAttr->detachstate == PTHREAD_CREATE_JOINABLE) ? 177 PTHREAD_STATE_RUNNING : PTHREAD_STATE_DETACHED; 178 /* need to confirmation */ 179 created->cancelstate = PTHREAD_CANCEL_ENABLE; 180 created->canceltype = PTHREAD_CANCEL_DEFERRED; 181 created->cancelbuffer = NULL; 182 created->canceled = 0; 183 created->freestack = 0; /* no use default : 0 */ 184 created->stackmem = taskCB->topOfStack; 185 created->thread_data = NULL; 186} 187 188STATIC UINT32 InitPthreadData(pthread_t threadID, pthread_attr_t *userAttr, 189 const CHAR name[], size_t len) 190{ 191 errno_t err; 192 UINT32 ret = LOS_OK; 193 LosTaskCB *taskCB = OS_TCB_FROM_TID(threadID); 194 _pthread_data *created = &g_pthreadData[threadID]; 195 196 err = strncpy_s(created->name, sizeof(created->name), name, len); 197 if (err != EOK) { 198 PRINT_ERR("%s: %d, err: %d\n", __FUNCTION__, __LINE__, err); 199 return LOS_NOK; 200 } 201 userAttr->stacksize = taskCB->stackSize; 202 err = OsSetTaskName(taskCB, created->name, FALSE); 203 if (err != LOS_OK) { 204 PRINT_ERR("%s: %d, err: %d\n", __FUNCTION__, __LINE__, err); 205 return LOS_NOK; 206 } 207#ifdef LOSCFG_KERNEL_SMP 208 if (userAttr->cpuset.__bits[0] > 0) { 209 taskCB->cpuAffiMask = (UINT16)userAttr->cpuset.__bits[0]; 210 } 211#endif 212 213 SetPthreadDataAttr(userAttr, threadID, taskCB, created); 214 return ret; 215} 216 217int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 218 void *(*startRoutine)(void *), void *arg) 219{ 220 pthread_attr_t userAttr; 221 UINT32 ret; 222 CHAR name[PTHREAD_DATA_NAME_MAX] = {0}; 223 STATIC UINT16 pthreadNumber = 1; 224 TSK_INIT_PARAM_S taskInitParam = {0}; 225 UINT32 taskHandle; 226 _pthread_data *self = pthread_get_self_data(); 227 228 if ((thread == NULL) || (startRoutine == NULL)) { 229 return EINVAL; 230 } 231 232 SetPthreadAttr(self, attr, &userAttr); 233 234 (VOID)snprintf_s(name, sizeof(name), sizeof(name) - 1, "pth%02d", pthreadNumber); 235 pthreadNumber++; 236 237 taskInitParam.pcName = name; 238 taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)startRoutine; 239 taskInitParam.auwArgs[0] = (UINTPTR)arg; 240 taskInitParam.usTaskPrio = (UINT16)userAttr.schedparam.sched_priority; 241 taskInitParam.uwStackSize = userAttr.stacksize; 242 if (OsProcessIsUserMode(OsCurrProcessGet())) { 243 taskInitParam.processID = (UINTPTR)OsGetKernelInitProcess(); 244 } else { 245 taskInitParam.processID = (UINTPTR)OsCurrProcessGet(); 246 } 247 if (userAttr.detachstate == PTHREAD_CREATE_DETACHED) { 248 taskInitParam.uwResved = LOS_TASK_STATUS_DETACHED; 249 } else { 250 /* Set the pthread default joinable */ 251 taskInitParam.uwResved = LOS_TASK_ATTR_JOINABLE; 252 } 253 254 PthreadReap(); 255 ret = LOS_TaskCreateOnly(&taskHandle, &taskInitParam); 256 if (ret == LOS_OK) { 257 *thread = (pthread_t)taskHandle; 258 ret = InitPthreadData(*thread, &userAttr, name, PTHREAD_DATA_NAME_MAX); 259 if (ret != LOS_OK) { 260 goto ERROR_OUT_WITH_TASK; 261 } 262 (VOID)LOS_SetTaskScheduler(taskHandle, SCHED_RR, taskInitParam.usTaskPrio); 263 } 264 265 if (ret == LOS_OK) { 266 return ENOERR; 267 } else { 268 goto ERROR_OUT; 269 } 270 271ERROR_OUT_WITH_TASK: 272 (VOID)LOS_TaskDelete(taskHandle); 273ERROR_OUT: 274 *thread = (pthread_t)-1; 275 276 return map_errno(ret); 277} 278 279void pthread_exit(void *retVal) 280{ 281 _pthread_data *self = pthread_get_self_data(); 282 UINT32 intSave; 283 284 if (pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, (int *)0) != ENOERR) { 285 PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 286 } 287 288 if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) { 289 PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 290 } 291 292 self->task->joinRetval = retVal; 293 /* 294 * If we are already detached, go to EXITED state, otherwise 295 * go into JOIN state. 296 */ 297 if (self->state == PTHREAD_STATE_DETACHED) { 298 self->state = PTHREAD_STATE_EXITED; 299 g_pthreadsExited++; 300 } else { 301 self->state = PTHREAD_STATE_JOIN; 302 } 303 304 if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) { 305 PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 306 } 307 SCHEDULER_LOCK(intSave); 308 /* If the thread is the highest thread,it can't schedule in LOS_SemPost. */ 309 OsTaskJoinPostUnsafe(self->task); 310 if (self->task->taskStatus & OS_TASK_STATUS_RUNNING) { 311 OsSchedResched(); 312 } 313 SCHEDULER_UNLOCK(intSave); 314} 315 316STATIC INT32 ProcessByJoinState(_pthread_data *joined) 317{ 318 UINT32 intSave; 319 INT32 err = 0; 320 UINT32 ret; 321 switch (joined->state) { 322 case PTHREAD_STATE_RUNNING: 323 /* The thread is still running, we must wait for it. */ 324 SCHEDULER_LOCK(intSave); 325 ret = OsTaskJoinPendUnsafe(joined->task); 326 SCHEDULER_UNLOCK(intSave); 327 if (ret != LOS_OK) { 328 err = (INT32)ret; 329 break; 330 } 331 332 joined->state = PTHREAD_STATE_ALRDY_JOIN; 333 break; 334 /* 335 * The thread has become unjoinable while we waited, so we 336 * fall through to complain. 337 */ 338 case PTHREAD_STATE_FREE: 339 case PTHREAD_STATE_DETACHED: 340 case PTHREAD_STATE_EXITED: 341 /* None of these may be joined. */ 342 err = EINVAL; 343 break; 344 case PTHREAD_STATE_ALRDY_JOIN: 345 err = EINVAL; 346 break; 347 case PTHREAD_STATE_JOIN: 348 break; 349 default: 350 PRINT_ERR("state: %u is not supported\n", (UINT32)joined->state); 351 break; 352 } 353 return err; 354} 355 356int pthread_join(pthread_t thread, void **retVal) 357{ 358 INT32 err; 359 UINT8 status; 360 _pthread_data *self = NULL; 361 _pthread_data *joined = NULL; 362 363 /* Check for cancellation first. */ 364 pthread_testcancel(); 365 366 /* Dispose of any dead threads */ 367 (VOID)pthread_mutex_lock(&g_pthreadsDataMutex); 368 PthreadReap(); 369 (VOID)pthread_mutex_unlock(&g_pthreadsDataMutex); 370 371 self = pthread_get_self_data(); 372 joined = pthread_get_data(thread); 373 if (joined == NULL) { 374 return ESRCH; 375 } 376 status = joined->state; 377 378 if (joined == self) { 379 return EDEADLK; 380 } 381 382 err = ProcessByJoinState(joined); 383 (VOID)pthread_mutex_lock(&g_pthreadsDataMutex); 384 385 if (!err) { 386 /* 387 * Here, we know that joinee is a thread that has exited and is 388 * ready to be joined. 389 */ 390 if (retVal != NULL) { 391 /* Get the retVal */ 392 *retVal = joined->task->joinRetval; 393 } 394 395 /* Set state to exited. */ 396 joined->state = PTHREAD_STATE_EXITED; 397 g_pthreadsExited++; 398 399 /* Dispose of any dead threads */ 400 PthreadReap(); 401 } else { 402 joined->state = status; 403 } 404 405 (VOID)pthread_mutex_unlock(&g_pthreadsDataMutex); 406 /* Check for cancellation before returning */ 407 pthread_testcancel(); 408 409 return err; 410} 411 412/* 413 * Set the detachstate of the thread to "detached". The thread then does not 414 * need to be joined and its resources will be freed when it exits. 415 */ 416int pthread_detach(pthread_t thread) 417{ 418 int ret = 0; 419 UINT32 intSave; 420 421 _pthread_data *detached = NULL; 422 423 if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) { 424 ret = ESRCH; 425 } 426 detached = pthread_get_data(thread); 427 if (detached == NULL) { 428 ret = ESRCH; /* No such thread */ 429 } else if (detached->state == PTHREAD_STATE_DETACHED) { 430 ret = EINVAL; /* Already detached! */ 431 } else if (detached->state == PTHREAD_STATE_JOIN) { 432 detached->state = PTHREAD_STATE_EXITED; 433 g_pthreadsExited++; 434 } else { 435 /* Set state to detached and kick any joinees to make them return. */ 436 SCHEDULER_LOCK(intSave); 437 if (!(detached->task->taskStatus & OS_TASK_STATUS_EXIT)) { 438 ret = OsTaskSetDetachUnsafe(detached->task); 439 if (ret == ESRCH) { 440 ret = LOS_OK; 441 } else if (ret == LOS_OK) { 442 detached->state = PTHREAD_STATE_DETACHED; 443 } 444 } else { 445 detached->state = PTHREAD_STATE_EXITED; 446 g_pthreadsExited++; 447 } 448 SCHEDULER_UNLOCK(intSave); 449 } 450 451 /* Dispose of any dead threads */ 452 PthreadReap(); 453 if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) { 454 ret = ESRCH; 455 } 456 457 return ret; 458} 459 460int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param) 461{ 462 _pthread_data *data = NULL; 463 int ret; 464 465 if ((param == NULL) || (param->sched_priority > OS_TASK_PRIORITY_LOWEST)) { 466 return EINVAL; 467 } 468 469 if (policy != SCHED_RR) { 470 return EINVAL; 471 } 472 473 /* The parameters seem OK, change the thread. */ 474 ret = pthread_mutex_lock(&g_pthreadsDataMutex); 475 if (ret != ENOERR) { 476 return ret; 477 } 478 479 data = pthread_get_data(thread); 480 if (data == NULL) { 481 ret = pthread_mutex_unlock(&g_pthreadsDataMutex); 482 if (ret != ENOERR) { 483 return ret; 484 } 485 return ESRCH; 486 } 487 488 /* Only support one policy now */ 489 data->attr.schedpolicy = SCHED_RR; 490 data->attr.schedparam = *param; 491 492 ret = pthread_mutex_unlock(&g_pthreadsDataMutex); 493 if (ret != ENOERR) { 494 return ret; 495 } 496 (VOID)LOS_TaskPriSet((UINT32)thread, (UINT16)param->sched_priority); 497 498 return ENOERR; 499} 500 501int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) 502{ 503 _pthread_data *data = NULL; 504 int ret; 505 506 if ((policy == NULL) || (param == NULL)) { 507 return EINVAL; 508 } 509 510 ret = pthread_mutex_lock(&g_pthreadsDataMutex); 511 if (ret != ENOERR) { 512 return ret; 513 } 514 515 data = pthread_get_data(thread); 516 if (data == NULL) { 517 goto ERR_OUT; 518 } 519 520 *policy = data->attr.schedpolicy; 521 *param = data->attr.schedparam; 522 523 ret = pthread_mutex_unlock(&g_pthreadsDataMutex); 524 return ret; 525ERR_OUT: 526 ret = pthread_mutex_unlock(&g_pthreadsDataMutex); 527 if (ret != ENOERR) { 528 return ret; 529 } 530 return ESRCH; 531} 532 533/* Call initRoutine just the once per control variable. */ 534int pthread_once(pthread_once_t *onceControl, void (*initRoutine)(void)) 535{ 536 pthread_once_t old; 537 int ret; 538 539 if ((onceControl == NULL) || (initRoutine == NULL)) { 540 return EINVAL; 541 } 542 543 /* Do a test and set on the onceControl object. */ 544 ret = pthread_mutex_lock(&g_pthreadsDataMutex); 545 if (ret != ENOERR) { 546 return ret; 547 } 548 549 old = *onceControl; 550 *onceControl = 1; 551 552 ret = pthread_mutex_unlock(&g_pthreadsDataMutex); 553 if (ret != ENOERR) { 554 return ret; 555 } 556 /* If the onceControl was zero, call the initRoutine(). */ 557 if (!old) { 558 initRoutine(); 559 } 560 561 return ENOERR; 562} 563 564/* Thread specific data */ 565int pthread_key_create(pthread_key_t *key, void (*destructor)(void *)) 566{ 567 (VOID)key; 568 (VOID)destructor; 569 PRINT_ERR("[%s] is not support.\n", __FUNCTION__); 570 return 0; 571} 572 573/* Store the pointer value in the thread-specific data slot addressed by the key. */ 574int pthread_setspecific(pthread_key_t key, const void *pointer) 575{ 576 (VOID)key; 577 (VOID)pointer; 578 PRINT_ERR("[%s] is not support.\n", __FUNCTION__); 579 return 0; 580} 581 582/* Retrieve the pointer value in the thread-specific data slot addressed by the key. */ 583void *pthread_getspecific(pthread_key_t key) 584{ 585 (VOID)key; 586 PRINT_ERR("[%s] is not support.\n", __FUNCTION__); 587 return NULL; 588} 589 590/* 591 * Set cancel state of current thread to ENABLE or DISABLE. 592 * Returns old state in *oldState. 593 */ 594int pthread_setcancelstate(int state, int *oldState) 595{ 596 _pthread_data *self = NULL; 597 int ret; 598 599 if ((state != PTHREAD_CANCEL_ENABLE) && (state != PTHREAD_CANCEL_DISABLE)) { 600 return EINVAL; 601 } 602 603 ret = pthread_mutex_lock(&g_pthreadsDataMutex); 604 if (ret != ENOERR) { 605 return ret; 606 } 607 608 self = pthread_get_self_data(); 609 610 if (oldState != NULL) { 611 *oldState = self->cancelstate; 612 } 613 614 self->cancelstate = (UINT8)state; 615 616 ret = pthread_mutex_unlock(&g_pthreadsDataMutex); 617 if (ret != ENOERR) { 618 return ret; 619 } 620 621 return ENOERR; 622} 623 624/* 625 * Set cancel type of current thread to ASYNCHRONOUS or DEFERRED. 626 * Returns old type in *oldType. 627 */ 628int pthread_setcanceltype(int type, int *oldType) 629{ 630 _pthread_data *self = NULL; 631 int ret; 632 633 if ((type != PTHREAD_CANCEL_ASYNCHRONOUS) && (type != PTHREAD_CANCEL_DEFERRED)) { 634 return EINVAL; 635 } 636 637 ret = pthread_mutex_lock(&g_pthreadsDataMutex); 638 if (ret != ENOERR) { 639 return ret; 640 } 641 642 self = pthread_get_self_data(); 643 if (oldType != NULL) { 644 *oldType = self->canceltype; 645 } 646 647 self->canceltype = (UINT8)type; 648 649 ret = pthread_mutex_unlock(&g_pthreadsDataMutex); 650 if (ret != ENOERR) { 651 return ret; 652 } 653 654 return ENOERR; 655} 656 657STATIC UINT32 DoPthreadCancel(_pthread_data *data) 658{ 659 UINT32 ret = LOS_OK; 660 UINT32 intSave; 661 LOS_TaskLock(); 662 data->canceled = 0; 663 if ((data->task->taskStatus & OS_TASK_STATUS_EXIT) || (LOS_TaskSuspend(data->task->taskID) != ENOERR)) { 664 ret = LOS_NOK; 665 goto OUT; 666 } 667 668 if (data->task->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) { 669 SCHEDULER_LOCK(intSave); 670 OsTaskJoinPostUnsafe(data->task); 671 SCHEDULER_UNLOCK(intSave); 672 g_pthreadCanceledDummyVar = (UINTPTR)PTHREAD_CANCELED; 673 data->task->joinRetval = (VOID *)g_pthreadCanceledDummyVar; 674 } else if (data->state && !(data->task->taskStatus & OS_TASK_STATUS_UNUSED)) { 675 data->state = PTHREAD_STATE_EXITED; 676 g_pthreadsExited++; 677 PthreadReap(); 678 } else { 679 ret = LOS_NOK; 680 } 681OUT: 682 LOS_TaskUnlock(); 683 return ret; 684} 685 686int pthread_cancel(pthread_t thread) 687{ 688 _pthread_data *data = NULL; 689 690 if (pthread_mutex_lock(&g_pthreadsDataMutex) != ENOERR) { 691 PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 692 } 693 694 data = pthread_get_data(thread); 695 if (data == NULL) { 696 if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) { 697 PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 698 } 699 return ESRCH; 700 } 701 702 data->canceled = 1; 703 704 if ((data->cancelstate == PTHREAD_CANCEL_ENABLE) && 705 (data->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)) { 706 /* 707 * If the thread has cancellation enabled, and it is in 708 * asynchronous mode, suspend it and set corresponding thread's status. 709 * We also release the thread out of any current wait to make it wake up. 710 */ 711 if (DoPthreadCancel(data) == LOS_NOK) { 712 goto ERROR_OUT; 713 } 714 } 715 716 /* 717 * Otherwise the thread has cancellation disabled, in which case 718 * it is up to the thread to enable cancellation 719 */ 720 if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) { 721 PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 722 } 723 724 return ENOERR; 725ERROR_OUT: 726 if (pthread_mutex_unlock(&g_pthreadsDataMutex) != ENOERR) { 727 PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); 728 } 729 return ESRCH; 730} 731 732/* 733 * Test for a pending cancellation for the current thread and terminate 734 * the thread if there is one. 735 */ 736void pthread_testcancel(void) 737{ 738 if (CheckForCancel()) { 739 /* 740 * If we have cancellation enabled, and there is a cancellation 741 * pending, then go ahead and do the deed. 742 * Exit now with special retVal. pthread_exit() calls the 743 * cancellation handlers implicitly. 744 */ 745 pthread_exit((void *)PTHREAD_CANCELED); 746 } 747} 748 749/* Get current thread id. */ 750pthread_t pthread_self(void) 751{ 752 _pthread_data *data = pthread_get_self_data(); 753 754 return data->id; 755} 756 757/* Compare two thread identifiers. */ 758int pthread_equal(pthread_t thread1, pthread_t thread2) 759{ 760 return thread1 == thread2; 761} 762 763void pthread_cleanup_push_inner(struct pthread_cleanup_buffer *buffer, 764 void (*routine)(void *), void *arg) 765{ 766 (VOID)buffer; 767 (VOID)routine; 768 (VOID)arg; 769 PRINT_ERR("[%s] is not support.\n", __FUNCTION__); 770 return; 771} 772 773void pthread_cleanup_pop_inner(struct pthread_cleanup_buffer *buffer, int execute) 774{ 775 (VOID)buffer; 776 (VOID)execute; 777 PRINT_ERR("[%s] is not support.\n", __FUNCTION__); 778 return; 779} 780 781/* 782 * Set the cpu affinity mask for the thread 783 */ 784int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t* cpuset) 785{ 786 INT32 ret = sched_setaffinity(thread, cpusetsize, cpuset); 787 if (ret == -1) { 788 return errno; 789 } else { 790 return ENOERR; 791 } 792} 793 794/* 795 * Get the cpu affinity mask from the thread 796 */ 797int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t* cpuset) 798{ 799 INT32 ret = sched_getaffinity(thread, cpusetsize, cpuset); 800 if (ret == -1) { 801 return errno; 802 } else { 803 return ENOERR; 804 } 805} 806 807