1 /* 2 * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 11 /*! Threading routines */ 12 13 14 #include <thread.h> 15 16 #include <errno.h> 17 #include <malloc.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <sys/resource.h> 22 23 #include <algorithm> 24 25 #include <OS.h> 26 27 #include <util/AutoLock.h> 28 29 #include <arch/debug.h> 30 #include <boot/kernel_args.h> 31 #include <condition_variable.h> 32 #include <cpu.h> 33 #include <int.h> 34 #include <kimage.h> 35 #include <kscheduler.h> 36 #include <ksignal.h> 37 #include <Notifications.h> 38 #include <real_time_clock.h> 39 #include <slab/Slab.h> 40 #include <smp.h> 41 #include <syscalls.h> 42 #include <syscall_restart.h> 43 #include <team.h> 44 #include <tls.h> 45 #include <user_runtime.h> 46 #include <user_thread.h> 47 #include <vfs.h> 48 #include <vm/vm.h> 49 #include <vm/VMAddressSpace.h> 50 #include <wait_for_objects.h> 51 52 #include "TeamThreadTables.h" 53 54 55 //#define TRACE_THREAD 56 #ifdef TRACE_THREAD 57 # define TRACE(x) dprintf x 58 #else 59 # define TRACE(x) ; 60 #endif 61 62 63 #define THREAD_MAX_MESSAGE_SIZE 65536 64 65 66 // #pragma mark - ThreadHashTable 67 68 69 typedef BKernel::TeamThreadTable<Thread> ThreadHashTable; 70 71 72 // thread list 73 static Thread sIdleThreads[SMP_MAX_CPUS]; 74 static ThreadHashTable sThreadHash; 75 static spinlock sThreadHashLock = B_SPINLOCK_INITIALIZER; 76 static thread_id sNextThreadID = 2; 77 // ID 1 is allocated for the kernel by Team::Team() behind our back 78 79 // some arbitrarily chosen limits -- should probably depend on the available 80 // memory (the limit is not yet enforced) 81 static int32 sMaxThreads = 4096; 82 static int32 sUsedThreads = 0; 83 84 spinlock gThreadCreationLock = B_SPINLOCK_INITIALIZER; 85 86 87 struct UndertakerEntry : DoublyLinkedListLinkImpl<UndertakerEntry> { 88 Thread* thread; 89 team_id teamID; 90 91 UndertakerEntry(Thread* thread, team_id teamID) 92 : 93 thread(thread), 94 teamID(teamID) 95 { 96 } 97 }; 98 99 100 struct ThreadEntryArguments { 101 status_t (*kernelFunction)(void* argument); 102 void* argument; 103 bool enterUserland; 104 }; 105 106 struct UserThreadEntryArguments : ThreadEntryArguments { 107 addr_t userlandEntry; 108 void* userlandArgument1; 109 void* userlandArgument2; 110 pthread_t pthread; 111 arch_fork_arg* forkArgs; 112 uint32 flags; 113 }; 114 115 116 class ThreadNotificationService : public DefaultNotificationService { 117 public: 118 ThreadNotificationService() 119 : DefaultNotificationService("threads") 120 { 121 } 122 123 void Notify(uint32 eventCode, team_id teamID, thread_id threadID, 124 Thread* thread = NULL) 125 { 126 char eventBuffer[180]; 127 KMessage event; 128 event.SetTo(eventBuffer, sizeof(eventBuffer), THREAD_MONITOR); 129 event.AddInt32("event", eventCode); 130 event.AddInt32("team", teamID); 131 event.AddInt32("thread", threadID); 132 if (thread != NULL) 133 event.AddPointer("threadStruct", thread); 134 135 DefaultNotificationService::Notify(event, eventCode); 136 } 137 138 void Notify(uint32 eventCode, Thread* thread) 139 { 140 return Notify(eventCode, thread->id, thread->team->id, thread); 141 } 142 }; 143 144 145 static DoublyLinkedList<UndertakerEntry> sUndertakerEntries; 146 static spinlock sUndertakerLock = B_SPINLOCK_INITIALIZER; 147 static ConditionVariable sUndertakerCondition; 148 static ThreadNotificationService sNotificationService; 149 150 151 // object cache to allocate thread structures from 152 static object_cache* sThreadCache; 153 154 155 // #pragma mark - Thread 156 157 158 /*! Constructs a thread. 159 160 \param name The thread's name. 161 \param threadID The ID to be assigned to the new thread. If 162 \code < 0 \endcode a fresh one is allocated. 163 \param cpu The CPU the thread shall be assigned. 164 */ 165 Thread::Thread(const char* name, thread_id threadID, struct cpu_ent* cpu) 166 : 167 flags(0), 168 serial_number(-1), 169 hash_next(NULL), 170 team_next(NULL), 171 priority(-1), 172 io_priority(-1), 173 cpu(cpu), 174 previous_cpu(NULL), 175 pinned_to_cpu(0), 176 sig_block_mask(0), 177 sigsuspend_original_unblocked_mask(0), 178 user_signal_context(NULL), 179 signal_stack_base(0), 180 signal_stack_size(0), 181 signal_stack_enabled(false), 182 in_kernel(true), 183 has_yielded(false), 184 user_thread(NULL), 185 fault_handler(0), 186 page_faults_allowed(1), 187 team(NULL), 188 select_infos(NULL), 189 kernel_stack_area(-1), 190 kernel_stack_base(0), 191 user_stack_area(-1), 192 user_stack_base(0), 193 user_local_storage(0), 194 kernel_errno(0), 195 user_time(0), 196 kernel_time(0), 197 last_time(0), 198 cpu_clock_offset(0), 199 post_interrupt_callback(NULL), 200 post_interrupt_data(NULL) 201 { 202 id = threadID >= 0 ? threadID : allocate_thread_id(); 203 visible = false; 204 205 // init locks 206 char lockName[32]; 207 snprintf(lockName, sizeof(lockName), "Thread:%" B_PRId32, id); 208 mutex_init_etc(&fLock, lockName, MUTEX_FLAG_CLONE_NAME); 209 210 B_INITIALIZE_SPINLOCK(&time_lock); 211 B_INITIALIZE_SPINLOCK(&scheduler_lock); 212 B_INITIALIZE_RW_SPINLOCK(&team_lock); 213 214 // init name 215 if (name != NULL) 216 strlcpy(this->name, name, B_OS_NAME_LENGTH); 217 else 218 strcpy(this->name, "unnamed thread"); 219 220 exit.status = 0; 221 222 list_init(&exit.waiters); 223 224 exit.sem = -1; 225 msg.write_sem = -1; 226 msg.read_sem = -1; 227 228 // add to thread table -- yet invisible 229 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 230 sThreadHash.Insert(this); 231 } 232 233 234 Thread::~Thread() 235 { 236 // Delete resources that should actually be deleted by the thread itself, 237 // when it exited, but that might still exist, if the thread was never run. 238 239 if (user_stack_area >= 0) 240 delete_area(user_stack_area); 241 242 DeleteUserTimers(false); 243 244 // delete the resources, that may remain in either case 245 246 if (kernel_stack_area >= 0) 247 delete_area(kernel_stack_area); 248 249 fPendingSignals.Clear(); 250 251 if (exit.sem >= 0) 252 delete_sem(exit.sem); 253 if (msg.write_sem >= 0) 254 delete_sem(msg.write_sem); 255 if (msg.read_sem >= 0) 256 delete_sem(msg.read_sem); 257 258 scheduler_on_thread_destroy(this); 259 260 mutex_destroy(&fLock); 261 262 // remove from thread table 263 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 264 sThreadHash.Remove(this); 265 } 266 267 268 /*static*/ status_t 269 Thread::Create(const char* name, Thread*& _thread) 270 { 271 Thread* thread = new Thread(name, -1, NULL); 272 if (thread == NULL) 273 return B_NO_MEMORY; 274 275 status_t error = thread->Init(false); 276 if (error != B_OK) { 277 delete thread; 278 return error; 279 } 280 281 _thread = thread; 282 return B_OK; 283 } 284 285 286 /*static*/ Thread* 287 Thread::Get(thread_id id) 288 { 289 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 290 Thread* thread = sThreadHash.Lookup(id); 291 if (thread != NULL) 292 thread->AcquireReference(); 293 return thread; 294 } 295 296 297 /*static*/ Thread* 298 Thread::GetAndLock(thread_id id) 299 { 300 // look it up and acquire a reference 301 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 302 Thread* thread = sThreadHash.Lookup(id); 303 if (thread == NULL) 304 return NULL; 305 306 thread->AcquireReference(); 307 threadHashLocker.Unlock(); 308 309 // lock and check, if it is still in the hash table 310 thread->Lock(); 311 threadHashLocker.Lock(); 312 313 if (sThreadHash.Lookup(id) == thread) 314 return thread; 315 316 threadHashLocker.Unlock(); 317 318 // nope, the thread is no longer in the hash table 319 thread->UnlockAndReleaseReference(); 320 321 return NULL; 322 } 323 324 325 /*static*/ Thread* 326 Thread::GetDebug(thread_id id) 327 { 328 return sThreadHash.Lookup(id, false); 329 } 330 331 332 /*static*/ bool 333 Thread::IsAlive(thread_id id) 334 { 335 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 336 return sThreadHash.Lookup(id) != NULL; 337 } 338 339 340 void* 341 Thread::operator new(size_t size) 342 { 343 return object_cache_alloc(sThreadCache, 0); 344 } 345 346 347 void* 348 Thread::operator new(size_t, void* pointer) 349 { 350 return pointer; 351 } 352 353 354 void 355 Thread::operator delete(void* pointer, size_t size) 356 { 357 object_cache_free(sThreadCache, pointer, 0); 358 } 359 360 361 status_t 362 Thread::Init(bool idleThread) 363 { 364 status_t error = scheduler_on_thread_create(this, idleThread); 365 if (error != B_OK) 366 return error; 367 368 char temp[64]; 369 snprintf(temp, sizeof(temp), "thread_%" B_PRId32 "_retcode_sem", id); 370 exit.sem = create_sem(0, temp); 371 if (exit.sem < 0) 372 return exit.sem; 373 374 snprintf(temp, sizeof(temp), "%s send", name); 375 msg.write_sem = create_sem(1, temp); 376 if (msg.write_sem < 0) 377 return msg.write_sem; 378 379 snprintf(temp, sizeof(temp), "%s receive", name); 380 msg.read_sem = create_sem(0, temp); 381 if (msg.read_sem < 0) 382 return msg.read_sem; 383 384 error = arch_thread_init_thread_struct(this); 385 if (error != B_OK) 386 return error; 387 388 return B_OK; 389 } 390 391 392 /*! Checks whether the thread is still in the thread hash table. 393 */ 394 bool 395 Thread::IsAlive() const 396 { 397 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 398 399 return sThreadHash.Lookup(id) != NULL; 400 } 401 402 403 void 404 Thread::ResetSignalsOnExec() 405 { 406 // We are supposed keep the pending signals and the signal mask. Only the 407 // signal stack, if set, shall be unset. 408 409 sigsuspend_original_unblocked_mask = 0; 410 user_signal_context = NULL; 411 signal_stack_base = 0; 412 signal_stack_size = 0; 413 signal_stack_enabled = false; 414 } 415 416 417 /*! Adds the given user timer to the thread and, if user-defined, assigns it an 418 ID. 419 420 The caller must hold the thread's lock. 421 422 \param timer The timer to be added. If it doesn't have an ID yet, it is 423 considered user-defined and will be assigned an ID. 424 \return \c B_OK, if the timer was added successfully, another error code 425 otherwise. 426 */ 427 status_t 428 Thread::AddUserTimer(UserTimer* timer) 429 { 430 // If the timer is user-defined, check timer limit and increment 431 // user-defined count. 432 if (timer->ID() < 0 && !team->CheckAddUserDefinedTimer()) 433 return EAGAIN; 434 435 fUserTimers.AddTimer(timer); 436 437 return B_OK; 438 } 439 440 441 /*! Removes the given user timer from the thread. 442 443 The caller must hold the thread's lock. 444 445 \param timer The timer to be removed. 446 447 */ 448 void 449 Thread::RemoveUserTimer(UserTimer* timer) 450 { 451 fUserTimers.RemoveTimer(timer); 452 453 if (timer->ID() >= USER_TIMER_FIRST_USER_DEFINED_ID) 454 team->UserDefinedTimersRemoved(1); 455 } 456 457 458 /*! Deletes all (or all user-defined) user timers of the thread. 459 460 The caller must hold the thread's lock. 461 462 \param userDefinedOnly If \c true, only the user-defined timers are deleted, 463 otherwise all timers are deleted. 464 */ 465 void 466 Thread::DeleteUserTimers(bool userDefinedOnly) 467 { 468 int32 count = fUserTimers.DeleteTimers(userDefinedOnly); 469 if (count > 0) 470 team->UserDefinedTimersRemoved(count); 471 } 472 473 474 void 475 Thread::DeactivateCPUTimeUserTimers() 476 { 477 while (ThreadTimeUserTimer* timer = fCPUTimeUserTimers.Head()) 478 timer->Deactivate(); 479 } 480 481 482 // #pragma mark - ThreadListIterator 483 484 485 ThreadListIterator::ThreadListIterator() 486 { 487 // queue the entry 488 InterruptsSpinLocker locker(sThreadHashLock); 489 sThreadHash.InsertIteratorEntry(&fEntry); 490 } 491 492 493 ThreadListIterator::~ThreadListIterator() 494 { 495 // remove the entry 496 InterruptsSpinLocker locker(sThreadHashLock); 497 sThreadHash.RemoveIteratorEntry(&fEntry); 498 } 499 500 501 Thread* 502 ThreadListIterator::Next() 503 { 504 // get the next team -- if there is one, get reference for it 505 InterruptsSpinLocker locker(sThreadHashLock); 506 Thread* thread = sThreadHash.NextElement(&fEntry); 507 if (thread != NULL) 508 thread->AcquireReference(); 509 510 return thread; 511 } 512 513 514 // #pragma mark - ThreadCreationAttributes 515 516 517 ThreadCreationAttributes::ThreadCreationAttributes(thread_func function, 518 const char* name, int32 priority, void* arg, team_id team, 519 Thread* thread) 520 { 521 this->entry = NULL; 522 this->name = name; 523 this->priority = priority; 524 this->args1 = NULL; 525 this->args2 = NULL; 526 this->stack_address = NULL; 527 this->stack_size = 0; 528 this->guard_size = 0; 529 this->pthread = NULL; 530 this->flags = 0; 531 this->team = team >= 0 ? team : team_get_kernel_team()->id; 532 this->thread = thread; 533 this->signal_mask = 0; 534 this->additional_stack_size = 0; 535 this->kernelEntry = function; 536 this->kernelArgument = arg; 537 this->forkArgs = NULL; 538 } 539 540 541 /*! Initializes the structure from a userland structure. 542 \param userAttributes The userland structure (must be a userland address). 543 \param nameBuffer A character array of at least size B_OS_NAME_LENGTH, 544 which will be used for the \c name field, if the userland structure has 545 a name. The buffer must remain valid as long as this structure is in 546 use afterwards (or until it is reinitialized). 547 \return \c B_OK, if the initialization went fine, another error code 548 otherwise. 549 */ 550 status_t 551 ThreadCreationAttributes::InitFromUserAttributes( 552 const thread_creation_attributes* userAttributes, char* nameBuffer) 553 { 554 if (userAttributes == NULL || !IS_USER_ADDRESS(userAttributes) 555 || user_memcpy((thread_creation_attributes*)this, userAttributes, 556 sizeof(thread_creation_attributes)) != B_OK) { 557 return B_BAD_ADDRESS; 558 } 559 560 if (stack_size != 0 561 && (stack_size < MIN_USER_STACK_SIZE 562 || stack_size > MAX_USER_STACK_SIZE)) { 563 return B_BAD_VALUE; 564 } 565 566 if (entry == NULL || !IS_USER_ADDRESS(entry) 567 || (stack_address != NULL && !IS_USER_ADDRESS(stack_address)) 568 || (name != NULL && (!IS_USER_ADDRESS(name) 569 || user_strlcpy(nameBuffer, name, B_OS_NAME_LENGTH) < 0))) { 570 return B_BAD_ADDRESS; 571 } 572 573 name = name != NULL ? nameBuffer : "user thread"; 574 575 // kernel only attributes (not in thread_creation_attributes): 576 Thread* currentThread = thread_get_current_thread(); 577 team = currentThread->team->id; 578 thread = NULL; 579 signal_mask = currentThread->sig_block_mask; 580 // inherit the current thread's signal mask 581 additional_stack_size = 0; 582 kernelEntry = NULL; 583 kernelArgument = NULL; 584 forkArgs = NULL; 585 586 return B_OK; 587 } 588 589 590 // #pragma mark - private functions 591 592 593 /*! Inserts a thread into a team. 594 The caller must hold the team's lock, the thread's lock, and the scheduler 595 lock. 596 */ 597 static void 598 insert_thread_into_team(Team *team, Thread *thread) 599 { 600 thread->team_next = team->thread_list; 601 team->thread_list = thread; 602 team->num_threads++; 603 604 if (team->num_threads == 1) { 605 // this was the first thread 606 team->main_thread = thread; 607 } 608 thread->team = team; 609 } 610 611 612 /*! Removes a thread from a team. 613 The caller must hold the team's lock, the thread's lock, and the scheduler 614 lock. 615 */ 616 static void 617 remove_thread_from_team(Team *team, Thread *thread) 618 { 619 Thread *temp, *last = NULL; 620 621 for (temp = team->thread_list; temp != NULL; temp = temp->team_next) { 622 if (temp == thread) { 623 if (last == NULL) 624 team->thread_list = temp->team_next; 625 else 626 last->team_next = temp->team_next; 627 628 team->num_threads--; 629 break; 630 } 631 last = temp; 632 } 633 } 634 635 636 static status_t 637 enter_userspace(Thread* thread, UserThreadEntryArguments* args) 638 { 639 status_t error = arch_thread_init_tls(thread); 640 if (error != B_OK) { 641 dprintf("Failed to init TLS for new userland thread \"%s\" (%" B_PRId32 642 ")\n", thread->name, thread->id); 643 free(args->forkArgs); 644 return error; 645 } 646 647 user_debug_update_new_thread_flags(thread); 648 649 // init the thread's user_thread 650 user_thread* userThread = thread->user_thread; 651 userThread->pthread = args->pthread; 652 userThread->flags = 0; 653 userThread->wait_status = B_OK; 654 userThread->defer_signals 655 = (args->flags & THREAD_CREATION_FLAG_DEFER_SIGNALS) != 0 ? 1 : 0; 656 userThread->pending_signals = 0; 657 658 if (args->forkArgs != NULL) { 659 // This is a fork()ed thread. Copy the fork args onto the stack and 660 // free them. 661 arch_fork_arg archArgs = *args->forkArgs; 662 free(args->forkArgs); 663 664 arch_restore_fork_frame(&archArgs); 665 // this one won't return here 666 return B_ERROR; 667 } 668 669 // Jump to the entry point in user space. Only returns, if something fails. 670 return arch_thread_enter_userspace(thread, args->userlandEntry, 671 args->userlandArgument1, args->userlandArgument2); 672 } 673 674 675 status_t 676 thread_enter_userspace_new_team(Thread* thread, addr_t entryFunction, 677 void* argument1, void* argument2) 678 { 679 UserThreadEntryArguments entryArgs; 680 entryArgs.kernelFunction = NULL; 681 entryArgs.argument = NULL; 682 entryArgs.enterUserland = true; 683 entryArgs.userlandEntry = (addr_t)entryFunction; 684 entryArgs.userlandArgument1 = argument1; 685 entryArgs.userlandArgument2 = argument2; 686 entryArgs.pthread = NULL; 687 entryArgs.forkArgs = NULL; 688 entryArgs.flags = 0; 689 690 return enter_userspace(thread, &entryArgs); 691 } 692 693 694 static void 695 common_thread_entry(void* _args) 696 { 697 Thread* thread = thread_get_current_thread(); 698 699 // The thread is new and has been scheduled the first time. 700 701 scheduler_new_thread_entry(thread); 702 703 // unlock the scheduler lock and enable interrupts 704 release_spinlock(&thread->scheduler_lock); 705 enable_interrupts(); 706 707 // call the kernel function, if any 708 ThreadEntryArguments* args = (ThreadEntryArguments*)_args; 709 if (args->kernelFunction != NULL) 710 args->kernelFunction(args->argument); 711 712 // If requested, enter userland, now. 713 if (args->enterUserland) { 714 enter_userspace(thread, (UserThreadEntryArguments*)args); 715 // only returns or error 716 717 // If that's the team's main thread, init the team exit info. 718 if (thread == thread->team->main_thread) 719 team_init_exit_info_on_error(thread->team); 720 } 721 722 // we're done 723 thread_exit(); 724 } 725 726 727 /*! Prepares the given thread's kernel stack for executing its entry function. 728 729 The data pointed to by \a data of size \a dataSize are copied to the 730 thread's kernel stack. A pointer to the copy's data is passed to the entry 731 function. The entry function is common_thread_entry(). 732 733 \param thread The thread. 734 \param data Pointer to data to be copied to the thread's stack and passed 735 to the entry function. 736 \param dataSize The size of \a data. 737 */ 738 static void 739 init_thread_kernel_stack(Thread* thread, const void* data, size_t dataSize) 740 { 741 uint8* stack = (uint8*)thread->kernel_stack_base; 742 uint8* stackTop = (uint8*)thread->kernel_stack_top; 743 744 // clear (or rather invalidate) the kernel stack contents, if compiled with 745 // debugging 746 #if KDEBUG > 0 747 # if defined(DEBUG_KERNEL_STACKS) && defined(STACK_GROWS_DOWNWARDS) 748 memset((void*)(stack + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE), 0xcc, 749 KERNEL_STACK_SIZE); 750 # else 751 memset(stack, 0xcc, KERNEL_STACK_SIZE); 752 # endif 753 #endif 754 755 // copy the data onto the stack, with 16-byte alignment to be on the safe 756 // side 757 void* clonedData; 758 #ifdef STACK_GROWS_DOWNWARDS 759 clonedData = (void*)ROUNDDOWN((addr_t)stackTop - dataSize, 16); 760 stackTop = (uint8*)clonedData; 761 #else 762 clonedData = (void*)ROUNDUP((addr_t)stack, 16); 763 stack = (uint8*)clonedData + ROUNDUP(dataSize, 16); 764 #endif 765 766 memcpy(clonedData, data, dataSize); 767 768 arch_thread_init_kthread_stack(thread, stack, stackTop, 769 &common_thread_entry, clonedData); 770 } 771 772 773 static status_t 774 create_thread_user_stack(Team* team, Thread* thread, void* _stackBase, 775 size_t stackSize, size_t additionalSize, size_t guardSize, 776 char* nameBuffer) 777 { 778 area_id stackArea = -1; 779 uint8* stackBase = (uint8*)_stackBase; 780 781 if (stackBase != NULL) { 782 // A stack has been specified. It must be large enough to hold the 783 // TLS space at least. Guard pages are ignored for existing stacks. 784 STATIC_ASSERT(TLS_SIZE < MIN_USER_STACK_SIZE); 785 if (stackSize < MIN_USER_STACK_SIZE) 786 return B_BAD_VALUE; 787 788 stackSize -= TLS_SIZE; 789 } else { 790 // No user-defined stack -- allocate one. For non-main threads the stack 791 // will be between USER_STACK_REGION and the main thread stack area. For 792 // a main thread the position is fixed. 793 794 guardSize = PAGE_ALIGN(guardSize); 795 796 if (stackSize == 0) { 797 // Use the default size (a different one for a main thread). 798 stackSize = thread->id == team->id 799 ? USER_MAIN_THREAD_STACK_SIZE : USER_STACK_SIZE; 800 } else { 801 // Verify that the given stack size is large enough. 802 if (stackSize < MIN_USER_STACK_SIZE) 803 return B_BAD_VALUE; 804 805 stackSize = PAGE_ALIGN(stackSize); 806 } 807 808 size_t areaSize = PAGE_ALIGN(guardSize + stackSize + TLS_SIZE 809 + additionalSize); 810 811 snprintf(nameBuffer, B_OS_NAME_LENGTH, "%s_%" B_PRId32 "_stack", 812 thread->name, thread->id); 813 814 stackBase = (uint8*)USER_STACK_REGION; 815 816 virtual_address_restrictions virtualRestrictions = {}; 817 virtualRestrictions.address_specification = B_RANDOMIZED_BASE_ADDRESS; 818 virtualRestrictions.address = (void*)stackBase; 819 820 physical_address_restrictions physicalRestrictions = {}; 821 822 stackArea = create_area_etc(team->id, nameBuffer, 823 areaSize, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA | B_STACK_AREA, 824 0, guardSize, &virtualRestrictions, &physicalRestrictions, 825 (void**)&stackBase); 826 if (stackArea < 0) 827 return stackArea; 828 } 829 830 // set the stack 831 ThreadLocker threadLocker(thread); 832 #ifdef STACK_GROWS_DOWNWARDS 833 thread->user_stack_base = (addr_t)stackBase + guardSize; 834 #else 835 thread->user_stack_base = (addr_t)stackBase; 836 #endif 837 thread->user_stack_size = stackSize; 838 thread->user_stack_area = stackArea; 839 840 return B_OK; 841 } 842 843 844 status_t 845 thread_create_user_stack(Team* team, Thread* thread, void* stackBase, 846 size_t stackSize, size_t additionalSize) 847 { 848 char nameBuffer[B_OS_NAME_LENGTH]; 849 return create_thread_user_stack(team, thread, stackBase, stackSize, 850 additionalSize, USER_STACK_GUARD_SIZE, nameBuffer); 851 } 852 853 854 /*! Creates a new thread. 855 856 \param attributes The thread creation attributes, specifying the team in 857 which to create the thread, as well as a whole bunch of other arguments. 858 \param kernel \c true, if a kernel-only thread shall be created, \c false, 859 if the thread shall also be able to run in userland. 860 \return The ID of the newly created thread (>= 0) or an error code on 861 failure. 862 */ 863 thread_id 864 thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel) 865 { 866 status_t status = B_OK; 867 868 TRACE(("thread_create_thread(%s, thread = %p, %s)\n", attributes.name, 869 attributes.thread, kernel ? "kernel" : "user")); 870 871 // get the team 872 Team* team = Team::Get(attributes.team); 873 if (team == NULL) 874 return B_BAD_TEAM_ID; 875 BReference<Team> teamReference(team, true); 876 877 // If a thread object is given, acquire a reference to it, otherwise create 878 // a new thread object with the given attributes. 879 Thread* thread = attributes.thread; 880 if (thread != NULL) { 881 thread->AcquireReference(); 882 } else { 883 status = Thread::Create(attributes.name, thread); 884 if (status != B_OK) 885 return status; 886 } 887 BReference<Thread> threadReference(thread, true); 888 889 thread->team = team; 890 // set already, so, if something goes wrong, the team pointer is 891 // available for deinitialization 892 thread->priority = attributes.priority == -1 893 ? B_NORMAL_PRIORITY : attributes.priority; 894 thread->priority = std::max(thread->priority, 895 (int32)THREAD_MIN_SET_PRIORITY); 896 thread->priority = std::min(thread->priority, 897 (int32)THREAD_MAX_SET_PRIORITY); 898 thread->state = B_THREAD_SUSPENDED; 899 900 thread->sig_block_mask = attributes.signal_mask; 901 902 // init debug structure 903 init_thread_debug_info(&thread->debug_info); 904 905 // create the kernel stack 906 char stackName[B_OS_NAME_LENGTH]; 907 snprintf(stackName, B_OS_NAME_LENGTH, "%s_%" B_PRId32 "_kstack", 908 thread->name, thread->id); 909 virtual_address_restrictions virtualRestrictions = {}; 910 virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; 911 physical_address_restrictions physicalRestrictions = {}; 912 913 thread->kernel_stack_area = create_area_etc(B_SYSTEM_TEAM, stackName, 914 KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 915 B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA 916 | B_KERNEL_STACK_AREA, 0, KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 917 &virtualRestrictions, &physicalRestrictions, 918 (void**)&thread->kernel_stack_base); 919 920 if (thread->kernel_stack_area < 0) { 921 // we're not yet part of a team, so we can just bail out 922 status = thread->kernel_stack_area; 923 924 dprintf("create_thread: error creating kernel stack: %s!\n", 925 strerror(status)); 926 927 return status; 928 } 929 930 thread->kernel_stack_top = thread->kernel_stack_base + KERNEL_STACK_SIZE 931 + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; 932 933 if (kernel) { 934 // Init the thread's kernel stack. It will start executing 935 // common_thread_entry() with the arguments we prepare here. 936 ThreadEntryArguments entryArgs; 937 entryArgs.kernelFunction = attributes.kernelEntry; 938 entryArgs.argument = attributes.kernelArgument; 939 entryArgs.enterUserland = false; 940 941 init_thread_kernel_stack(thread, &entryArgs, sizeof(entryArgs)); 942 } else { 943 // create the userland stack, if the thread doesn't have one yet 944 if (thread->user_stack_base == 0) { 945 status = create_thread_user_stack(team, thread, 946 attributes.stack_address, attributes.stack_size, 947 attributes.additional_stack_size, attributes.guard_size, 948 stackName); 949 if (status != B_OK) 950 return status; 951 } 952 953 // Init the thread's kernel stack. It will start executing 954 // common_thread_entry() with the arguments we prepare here. 955 UserThreadEntryArguments entryArgs; 956 entryArgs.kernelFunction = attributes.kernelEntry; 957 entryArgs.argument = attributes.kernelArgument; 958 entryArgs.enterUserland = true; 959 entryArgs.userlandEntry = (addr_t)attributes.entry; 960 entryArgs.userlandArgument1 = attributes.args1; 961 entryArgs.userlandArgument2 = attributes.args2; 962 entryArgs.pthread = attributes.pthread; 963 entryArgs.forkArgs = attributes.forkArgs; 964 entryArgs.flags = attributes.flags; 965 966 init_thread_kernel_stack(thread, &entryArgs, sizeof(entryArgs)); 967 968 // create the pre-defined thread timers 969 status = user_timer_create_thread_timers(team, thread); 970 if (status != B_OK) 971 return status; 972 } 973 974 // lock the team and see, if it is still alive 975 TeamLocker teamLocker(team); 976 if (team->state >= TEAM_STATE_SHUTDOWN) 977 return B_BAD_TEAM_ID; 978 979 bool debugNewThread = false; 980 if (!kernel) { 981 // allocate the user_thread structure, if not already allocated 982 if (thread->user_thread == NULL) { 983 thread->user_thread = team_allocate_user_thread(team); 984 if (thread->user_thread == NULL) 985 return B_NO_MEMORY; 986 } 987 988 // If the new thread belongs to the same team as the current thread, it 989 // may inherit some of the thread debug flags. 990 Thread* currentThread = thread_get_current_thread(); 991 if (currentThread != NULL && currentThread->team == team) { 992 // inherit all user flags... 993 int32 debugFlags = atomic_get(¤tThread->debug_info.flags) 994 & B_THREAD_DEBUG_USER_FLAG_MASK; 995 996 // ... save the syscall tracing flags, unless explicitely specified 997 if (!(debugFlags & B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS)) { 998 debugFlags &= ~(B_THREAD_DEBUG_PRE_SYSCALL 999 | B_THREAD_DEBUG_POST_SYSCALL); 1000 } 1001 1002 thread->debug_info.flags = debugFlags; 1003 1004 // stop the new thread, if desired 1005 debugNewThread = debugFlags & B_THREAD_DEBUG_STOP_CHILD_THREADS; 1006 } 1007 } 1008 1009 // We're going to make the thread live, now. The thread itself will take 1010 // over a reference to its Thread object. We'll acquire another reference 1011 // for our own use (and threadReference remains armed). 1012 1013 ThreadLocker threadLocker(thread); 1014 1015 InterruptsSpinLocker threadCreationLocker(gThreadCreationLock); 1016 SpinLocker threadHashLocker(sThreadHashLock); 1017 1018 // check the thread limit 1019 if (sUsedThreads >= sMaxThreads) { 1020 // Clean up the user_thread structure. It's a bit unfortunate that the 1021 // Thread destructor cannot do that, so we have to do that explicitly. 1022 threadHashLocker.Unlock(); 1023 threadCreationLocker.Unlock(); 1024 1025 user_thread* userThread = thread->user_thread; 1026 thread->user_thread = NULL; 1027 1028 threadLocker.Unlock(); 1029 1030 if (userThread != NULL) 1031 team_free_user_thread(team, userThread); 1032 1033 return B_NO_MORE_THREADS; 1034 } 1035 1036 // make thread visible in global hash/list 1037 thread->visible = true; 1038 sUsedThreads++; 1039 1040 scheduler_on_thread_init(thread); 1041 1042 thread->AcquireReference(); 1043 1044 // Debug the new thread, if the parent thread required that (see above), 1045 // or the respective global team debug flag is set. But only, if a 1046 // debugger is installed for the team. 1047 if (!kernel) { 1048 int32 teamDebugFlags = atomic_get(&team->debug_info.flags); 1049 debugNewThread |= (teamDebugFlags & B_TEAM_DEBUG_STOP_NEW_THREADS) != 0; 1050 if (debugNewThread 1051 && (teamDebugFlags & B_TEAM_DEBUG_DEBUGGER_INSTALLED) != 0) { 1052 thread->debug_info.flags |= B_THREAD_DEBUG_STOP; 1053 } 1054 } 1055 1056 { 1057 SpinLocker signalLocker(team->signal_lock); 1058 SpinLocker timeLocker(team->time_lock); 1059 1060 // insert thread into team 1061 insert_thread_into_team(team, thread); 1062 } 1063 1064 threadHashLocker.Unlock(); 1065 threadCreationLocker.Unlock(); 1066 threadLocker.Unlock(); 1067 teamLocker.Unlock(); 1068 1069 // notify listeners 1070 sNotificationService.Notify(THREAD_ADDED, thread); 1071 1072 return thread->id; 1073 } 1074 1075 1076 static status_t 1077 undertaker(void* /*args*/) 1078 { 1079 while (true) { 1080 // wait for a thread to bury 1081 InterruptsSpinLocker locker(sUndertakerLock); 1082 1083 while (sUndertakerEntries.IsEmpty()) { 1084 ConditionVariableEntry conditionEntry; 1085 sUndertakerCondition.Add(&conditionEntry); 1086 locker.Unlock(); 1087 1088 conditionEntry.Wait(); 1089 1090 locker.Lock(); 1091 } 1092 1093 UndertakerEntry* _entry = sUndertakerEntries.RemoveHead(); 1094 locker.Unlock(); 1095 1096 UndertakerEntry entry = *_entry; 1097 // we need a copy, since the original entry is on the thread's stack 1098 1099 // we've got an entry 1100 Thread* thread = entry.thread; 1101 1102 // make sure the thread isn't running anymore 1103 InterruptsSpinLocker schedulerLocker(thread->scheduler_lock); 1104 ASSERT(thread->state == THREAD_STATE_FREE_ON_RESCHED); 1105 schedulerLocker.Unlock(); 1106 1107 // remove this thread from from the kernel team -- this makes it 1108 // unaccessible 1109 Team* kernelTeam = team_get_kernel_team(); 1110 TeamLocker kernelTeamLocker(kernelTeam); 1111 thread->Lock(); 1112 1113 InterruptsSpinLocker threadCreationLocker(gThreadCreationLock); 1114 SpinLocker signalLocker(kernelTeam->signal_lock); 1115 SpinLocker timeLocker(kernelTeam->time_lock); 1116 1117 remove_thread_from_team(kernelTeam, thread); 1118 1119 timeLocker.Unlock(); 1120 signalLocker.Unlock(); 1121 threadCreationLocker.Unlock(); 1122 1123 kernelTeamLocker.Unlock(); 1124 1125 // free the thread structure 1126 thread->UnlockAndReleaseReference(); 1127 } 1128 1129 // can never get here 1130 return B_OK; 1131 } 1132 1133 1134 /*! Returns the semaphore the thread is currently waiting on. 1135 1136 The return value is purely informative. 1137 The caller must hold the scheduler lock. 1138 1139 \param thread The thread. 1140 \return The ID of the semaphore the thread is currently waiting on or \c -1, 1141 if it isn't waiting on a semaphore. 1142 */ 1143 static sem_id 1144 get_thread_wait_sem(Thread* thread) 1145 { 1146 if (thread->state == B_THREAD_WAITING 1147 && thread->wait.type == THREAD_BLOCK_TYPE_SEMAPHORE) { 1148 return (sem_id)(addr_t)thread->wait.object; 1149 } 1150 return -1; 1151 } 1152 1153 1154 /*! Fills the thread_info structure with information from the specified thread. 1155 The caller must hold the thread's lock and the scheduler lock. 1156 */ 1157 static void 1158 fill_thread_info(Thread *thread, thread_info *info, size_t size) 1159 { 1160 info->thread = thread->id; 1161 info->team = thread->team->id; 1162 1163 strlcpy(info->name, thread->name, B_OS_NAME_LENGTH); 1164 1165 info->sem = -1; 1166 1167 if (thread->state == B_THREAD_WAITING) { 1168 info->state = B_THREAD_WAITING; 1169 1170 switch (thread->wait.type) { 1171 case THREAD_BLOCK_TYPE_SNOOZE: 1172 info->state = B_THREAD_ASLEEP; 1173 break; 1174 1175 case THREAD_BLOCK_TYPE_SEMAPHORE: 1176 { 1177 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1178 if (sem == thread->msg.read_sem) 1179 info->state = B_THREAD_RECEIVING; 1180 else 1181 info->sem = sem; 1182 break; 1183 } 1184 1185 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1186 default: 1187 break; 1188 } 1189 } else 1190 info->state = (thread_state)thread->state; 1191 1192 info->priority = thread->priority; 1193 info->stack_base = (void *)thread->user_stack_base; 1194 info->stack_end = (void *)(thread->user_stack_base 1195 + thread->user_stack_size); 1196 1197 InterruptsSpinLocker threadTimeLocker(thread->time_lock); 1198 info->user_time = thread->user_time; 1199 info->kernel_time = thread->kernel_time; 1200 } 1201 1202 1203 static status_t 1204 send_data_etc(thread_id id, int32 code, const void *buffer, size_t bufferSize, 1205 int32 flags) 1206 { 1207 // get the thread 1208 Thread *target = Thread::Get(id); 1209 if (target == NULL) 1210 return B_BAD_THREAD_ID; 1211 BReference<Thread> targetReference(target, true); 1212 1213 // get the write semaphore 1214 ThreadLocker targetLocker(target); 1215 sem_id cachedSem = target->msg.write_sem; 1216 targetLocker.Unlock(); 1217 1218 if (bufferSize > THREAD_MAX_MESSAGE_SIZE) 1219 return B_NO_MEMORY; 1220 1221 status_t status = acquire_sem_etc(cachedSem, 1, flags, 0); 1222 if (status == B_INTERRUPTED) { 1223 // we got interrupted by a signal 1224 return status; 1225 } 1226 if (status != B_OK) { 1227 // Any other acquisition problems may be due to thread deletion 1228 return B_BAD_THREAD_ID; 1229 } 1230 1231 void* data; 1232 if (bufferSize > 0) { 1233 data = malloc(bufferSize); 1234 if (data == NULL) 1235 return B_NO_MEMORY; 1236 if (user_memcpy(data, buffer, bufferSize) != B_OK) { 1237 free(data); 1238 return B_BAD_DATA; 1239 } 1240 } else 1241 data = NULL; 1242 1243 targetLocker.Lock(); 1244 1245 // The target thread could have been deleted at this point. 1246 if (!target->IsAlive()) { 1247 targetLocker.Unlock(); 1248 free(data); 1249 return B_BAD_THREAD_ID; 1250 } 1251 1252 // Save message informations 1253 target->msg.sender = thread_get_current_thread()->id; 1254 target->msg.code = code; 1255 target->msg.size = bufferSize; 1256 target->msg.buffer = data; 1257 cachedSem = target->msg.read_sem; 1258 1259 targetLocker.Unlock(); 1260 1261 release_sem(cachedSem); 1262 return B_OK; 1263 } 1264 1265 1266 static int32 1267 receive_data_etc(thread_id *_sender, void *buffer, size_t bufferSize, 1268 int32 flags) 1269 { 1270 Thread *thread = thread_get_current_thread(); 1271 size_t size; 1272 int32 code; 1273 1274 status_t status = acquire_sem_etc(thread->msg.read_sem, 1, flags, 0); 1275 if (status != B_OK) { 1276 // Actually, we're not supposed to return error codes 1277 // but since the only reason this can fail is that we 1278 // were killed, it's probably okay to do so (but also 1279 // meaningless). 1280 return status; 1281 } 1282 1283 if (buffer != NULL && bufferSize != 0 && thread->msg.buffer != NULL) { 1284 size = min_c(bufferSize, thread->msg.size); 1285 status = user_memcpy(buffer, thread->msg.buffer, size); 1286 if (status != B_OK) { 1287 free(thread->msg.buffer); 1288 release_sem(thread->msg.write_sem); 1289 return status; 1290 } 1291 } 1292 1293 *_sender = thread->msg.sender; 1294 code = thread->msg.code; 1295 1296 free(thread->msg.buffer); 1297 release_sem(thread->msg.write_sem); 1298 1299 return code; 1300 } 1301 1302 1303 static status_t 1304 common_getrlimit(int resource, struct rlimit * rlp) 1305 { 1306 if (!rlp) 1307 return B_BAD_ADDRESS; 1308 1309 switch (resource) { 1310 case RLIMIT_NOFILE: 1311 case RLIMIT_NOVMON: 1312 return vfs_getrlimit(resource, rlp); 1313 1314 case RLIMIT_CORE: 1315 rlp->rlim_cur = 0; 1316 rlp->rlim_max = 0; 1317 return B_OK; 1318 1319 case RLIMIT_STACK: 1320 { 1321 rlp->rlim_cur = USER_MAIN_THREAD_STACK_SIZE; 1322 rlp->rlim_max = USER_MAIN_THREAD_STACK_SIZE; 1323 return B_OK; 1324 } 1325 1326 default: 1327 return EINVAL; 1328 } 1329 1330 return B_OK; 1331 } 1332 1333 1334 static status_t 1335 common_setrlimit(int resource, const struct rlimit * rlp) 1336 { 1337 if (!rlp) 1338 return B_BAD_ADDRESS; 1339 1340 switch (resource) { 1341 case RLIMIT_NOFILE: 1342 case RLIMIT_NOVMON: 1343 return vfs_setrlimit(resource, rlp); 1344 1345 case RLIMIT_CORE: 1346 // We don't support core file, so allow settings to 0/0 only. 1347 if (rlp->rlim_cur != 0 || rlp->rlim_max != 0) 1348 return EINVAL; 1349 return B_OK; 1350 1351 default: 1352 return EINVAL; 1353 } 1354 1355 return B_OK; 1356 } 1357 1358 1359 static status_t 1360 common_snooze_etc(bigtime_t timeout, clockid_t clockID, uint32 flags, 1361 bigtime_t* _remainingTime) 1362 { 1363 switch (clockID) { 1364 case CLOCK_REALTIME: 1365 // make sure the B_TIMEOUT_REAL_TIME_BASE flag is set and fall 1366 // through 1367 flags |= B_TIMEOUT_REAL_TIME_BASE; 1368 case CLOCK_MONOTONIC: 1369 { 1370 // Store the start time, for the case that we get interrupted and 1371 // need to return the remaining time. For absolute timeouts we can 1372 // still get he time later, if needed. 1373 bigtime_t startTime 1374 = _remainingTime != NULL && (flags & B_RELATIVE_TIMEOUT) != 0 1375 ? system_time() : 0; 1376 1377 Thread* thread = thread_get_current_thread(); 1378 1379 thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_SNOOZE, 1380 NULL); 1381 status_t status = thread_block_with_timeout(flags, timeout); 1382 1383 if (status == B_TIMED_OUT || status == B_WOULD_BLOCK) 1384 return B_OK; 1385 1386 // If interrupted, compute the remaining time, if requested. 1387 if (status == B_INTERRUPTED && _remainingTime != NULL) { 1388 if ((flags & B_RELATIVE_TIMEOUT) != 0) { 1389 *_remainingTime = std::max( 1390 startTime + timeout - system_time(), (bigtime_t)0); 1391 } else { 1392 bigtime_t now = (flags & B_TIMEOUT_REAL_TIME_BASE) != 0 1393 ? real_time_clock_usecs() : system_time(); 1394 *_remainingTime = std::max(timeout - now, (bigtime_t)0); 1395 } 1396 } 1397 1398 return status; 1399 } 1400 1401 case CLOCK_THREAD_CPUTIME_ID: 1402 // Waiting for ourselves to do something isn't particularly 1403 // productive. 1404 return B_BAD_VALUE; 1405 1406 case CLOCK_PROCESS_CPUTIME_ID: 1407 default: 1408 // We don't have to support those, but we are allowed to. Could be 1409 // done be creating a UserTimer on the fly with a custom UserEvent 1410 // that would just wake us up. 1411 return ENOTSUP; 1412 } 1413 } 1414 1415 1416 // #pragma mark - debugger calls 1417 1418 1419 static int 1420 make_thread_unreal(int argc, char **argv) 1421 { 1422 int32 id = -1; 1423 1424 if (argc > 2) { 1425 print_debugger_command_usage(argv[0]); 1426 return 0; 1427 } 1428 1429 if (argc > 1) 1430 id = strtoul(argv[1], NULL, 0); 1431 1432 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1433 Thread* thread = it.Next();) { 1434 if (id != -1 && thread->id != id) 1435 continue; 1436 1437 if (thread->priority > B_DISPLAY_PRIORITY) { 1438 scheduler_set_thread_priority(thread, B_NORMAL_PRIORITY); 1439 kprintf("thread %" B_PRId32 " made unreal\n", thread->id); 1440 } 1441 } 1442 1443 return 0; 1444 } 1445 1446 1447 static int 1448 set_thread_prio(int argc, char **argv) 1449 { 1450 int32 id; 1451 int32 prio; 1452 1453 if (argc > 3 || argc < 2) { 1454 print_debugger_command_usage(argv[0]); 1455 return 0; 1456 } 1457 1458 prio = strtoul(argv[1], NULL, 0); 1459 if (prio > THREAD_MAX_SET_PRIORITY) 1460 prio = THREAD_MAX_SET_PRIORITY; 1461 if (prio < THREAD_MIN_SET_PRIORITY) 1462 prio = THREAD_MIN_SET_PRIORITY; 1463 1464 if (argc > 2) 1465 id = strtoul(argv[2], NULL, 0); 1466 else 1467 id = thread_get_current_thread()->id; 1468 1469 bool found = false; 1470 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1471 Thread* thread = it.Next();) { 1472 if (thread->id != id) 1473 continue; 1474 scheduler_set_thread_priority(thread, prio); 1475 kprintf("thread %" B_PRId32 " set to priority %" B_PRId32 "\n", id, prio); 1476 found = true; 1477 break; 1478 } 1479 if (!found) 1480 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1481 1482 return 0; 1483 } 1484 1485 1486 static int 1487 make_thread_suspended(int argc, char **argv) 1488 { 1489 int32 id; 1490 1491 if (argc > 2) { 1492 print_debugger_command_usage(argv[0]); 1493 return 0; 1494 } 1495 1496 if (argc == 1) 1497 id = thread_get_current_thread()->id; 1498 else 1499 id = strtoul(argv[1], NULL, 0); 1500 1501 bool found = false; 1502 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1503 Thread* thread = it.Next();) { 1504 if (thread->id != id) 1505 continue; 1506 1507 Signal signal(SIGSTOP, SI_USER, B_OK, team_get_kernel_team()->id); 1508 send_signal_to_thread(thread, signal, B_DO_NOT_RESCHEDULE); 1509 1510 kprintf("thread %" B_PRId32 " suspended\n", id); 1511 found = true; 1512 break; 1513 } 1514 if (!found) 1515 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1516 1517 return 0; 1518 } 1519 1520 1521 static int 1522 make_thread_resumed(int argc, char **argv) 1523 { 1524 int32 id; 1525 1526 if (argc != 2) { 1527 print_debugger_command_usage(argv[0]); 1528 return 0; 1529 } 1530 1531 // force user to enter a thread id, as using 1532 // the current thread is usually not intended 1533 id = strtoul(argv[1], NULL, 0); 1534 1535 bool found = false; 1536 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1537 Thread* thread = it.Next();) { 1538 if (thread->id != id) 1539 continue; 1540 1541 if (thread->state == B_THREAD_SUSPENDED) { 1542 scheduler_enqueue_in_run_queue(thread); 1543 kprintf("thread %" B_PRId32 " resumed\n", thread->id); 1544 } 1545 found = true; 1546 break; 1547 } 1548 if (!found) 1549 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1550 1551 return 0; 1552 } 1553 1554 1555 static int 1556 drop_into_debugger(int argc, char **argv) 1557 { 1558 status_t err; 1559 int32 id; 1560 1561 if (argc > 2) { 1562 print_debugger_command_usage(argv[0]); 1563 return 0; 1564 } 1565 1566 if (argc == 1) 1567 id = thread_get_current_thread()->id; 1568 else 1569 id = strtoul(argv[1], NULL, 0); 1570 1571 err = _user_debug_thread(id); 1572 // TODO: This is a non-trivial syscall doing some locking, so this is 1573 // really nasty and may go seriously wrong. 1574 if (err) 1575 kprintf("drop failed\n"); 1576 else 1577 kprintf("thread %" B_PRId32 " dropped into user debugger\n", id); 1578 1579 return 0; 1580 } 1581 1582 1583 /*! Returns a user-readable string for a thread state. 1584 Only for use in the kernel debugger. 1585 */ 1586 static const char * 1587 state_to_text(Thread *thread, int32 state) 1588 { 1589 switch (state) { 1590 case B_THREAD_READY: 1591 return "ready"; 1592 1593 case B_THREAD_RUNNING: 1594 return "running"; 1595 1596 case B_THREAD_WAITING: 1597 { 1598 if (thread != NULL) { 1599 switch (thread->wait.type) { 1600 case THREAD_BLOCK_TYPE_SNOOZE: 1601 return "zzz"; 1602 1603 case THREAD_BLOCK_TYPE_SEMAPHORE: 1604 { 1605 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1606 if (sem == thread->msg.read_sem) 1607 return "receive"; 1608 break; 1609 } 1610 } 1611 } 1612 1613 return "waiting"; 1614 } 1615 1616 case B_THREAD_SUSPENDED: 1617 return "suspended"; 1618 1619 case THREAD_STATE_FREE_ON_RESCHED: 1620 return "death"; 1621 1622 default: 1623 return "UNKNOWN"; 1624 } 1625 } 1626 1627 1628 static void 1629 print_thread_list_table_head() 1630 { 1631 kprintf("%-*s id state wait for %-*s cpu pri %-*s team " 1632 "name\n", 1633 B_PRINTF_POINTER_WIDTH, "thread", B_PRINTF_POINTER_WIDTH, "object", 1634 B_PRINTF_POINTER_WIDTH, "stack"); 1635 } 1636 1637 1638 static void 1639 _dump_thread_info(Thread *thread, bool shortInfo) 1640 { 1641 if (shortInfo) { 1642 kprintf("%p %6" B_PRId32 " %-10s", thread, thread->id, 1643 state_to_text(thread, thread->state)); 1644 1645 // does it block on a semaphore or a condition variable? 1646 if (thread->state == B_THREAD_WAITING) { 1647 switch (thread->wait.type) { 1648 case THREAD_BLOCK_TYPE_SEMAPHORE: 1649 { 1650 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1651 if (sem == thread->msg.read_sem) 1652 kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); 1653 else { 1654 kprintf("sem %-*" B_PRId32, 1655 B_PRINTF_POINTER_WIDTH + 5, sem); 1656 } 1657 break; 1658 } 1659 1660 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1661 kprintf("cvar %p ", thread->wait.object); 1662 break; 1663 1664 case THREAD_BLOCK_TYPE_SNOOZE: 1665 kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); 1666 break; 1667 1668 case THREAD_BLOCK_TYPE_SIGNAL: 1669 kprintf("signal%*s", B_PRINTF_POINTER_WIDTH + 9, ""); 1670 break; 1671 1672 case THREAD_BLOCK_TYPE_MUTEX: 1673 kprintf("mutex %p ", thread->wait.object); 1674 break; 1675 1676 case THREAD_BLOCK_TYPE_RW_LOCK: 1677 kprintf("rwlock %p ", thread->wait.object); 1678 break; 1679 1680 case THREAD_BLOCK_TYPE_OTHER: 1681 kprintf("other%*s", B_PRINTF_POINTER_WIDTH + 10, ""); 1682 break; 1683 1684 default: 1685 kprintf("??? %p ", thread->wait.object); 1686 break; 1687 } 1688 } else 1689 kprintf("-%*s", B_PRINTF_POINTER_WIDTH + 14, ""); 1690 1691 // on which CPU does it run? 1692 if (thread->cpu) 1693 kprintf("%2d", thread->cpu->cpu_num); 1694 else 1695 kprintf(" -"); 1696 1697 kprintf("%4" B_PRId32 " %p%5" B_PRId32 " %s\n", thread->priority, 1698 (void *)thread->kernel_stack_base, thread->team->id, 1699 thread->name != NULL ? thread->name : "<NULL>"); 1700 1701 return; 1702 } 1703 1704 // print the long info 1705 1706 struct thread_death_entry *death = NULL; 1707 1708 kprintf("THREAD: %p\n", thread); 1709 kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", thread->id, 1710 thread->id); 1711 kprintf("serial_number: %" B_PRId64 "\n", thread->serial_number); 1712 kprintf("name: \"%s\"\n", thread->name); 1713 kprintf("hash_next: %p\nteam_next: %p\n", 1714 thread->hash_next, thread->team_next); 1715 kprintf("priority: %" B_PRId32 " (I/O: %" B_PRId32 ")\n", 1716 thread->priority, thread->io_priority); 1717 kprintf("state: %s\n", state_to_text(thread, thread->state)); 1718 kprintf("cpu: %p ", thread->cpu); 1719 if (thread->cpu) 1720 kprintf("(%d)\n", thread->cpu->cpu_num); 1721 else 1722 kprintf("\n"); 1723 kprintf("sig_pending: %#" B_PRIx64 " (blocked: %#" B_PRIx64 1724 ", before sigsuspend(): %#" B_PRIx64 ")\n", 1725 (int64)thread->ThreadPendingSignals(), 1726 (int64)thread->sig_block_mask, 1727 (int64)thread->sigsuspend_original_unblocked_mask); 1728 kprintf("in_kernel: %d\n", thread->in_kernel); 1729 1730 if (thread->state == B_THREAD_WAITING) { 1731 kprintf("waiting for: "); 1732 1733 switch (thread->wait.type) { 1734 case THREAD_BLOCK_TYPE_SEMAPHORE: 1735 { 1736 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1737 if (sem == thread->msg.read_sem) 1738 kprintf("data\n"); 1739 else 1740 kprintf("semaphore %" B_PRId32 "\n", sem); 1741 break; 1742 } 1743 1744 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1745 kprintf("condition variable %p\n", thread->wait.object); 1746 break; 1747 1748 case THREAD_BLOCK_TYPE_SNOOZE: 1749 kprintf("snooze()\n"); 1750 break; 1751 1752 case THREAD_BLOCK_TYPE_SIGNAL: 1753 kprintf("signal\n"); 1754 break; 1755 1756 case THREAD_BLOCK_TYPE_MUTEX: 1757 kprintf("mutex %p\n", thread->wait.object); 1758 break; 1759 1760 case THREAD_BLOCK_TYPE_RW_LOCK: 1761 kprintf("rwlock %p\n", thread->wait.object); 1762 break; 1763 1764 case THREAD_BLOCK_TYPE_OTHER: 1765 kprintf("other (%s)\n", (char*)thread->wait.object); 1766 break; 1767 1768 default: 1769 kprintf("unknown (%p)\n", thread->wait.object); 1770 break; 1771 } 1772 } 1773 1774 kprintf("fault_handler: %p\n", (void *)thread->fault_handler); 1775 kprintf("team: %p, \"%s\"\n", thread->team, 1776 thread->team->Name()); 1777 kprintf(" exit.sem: %" B_PRId32 "\n", thread->exit.sem); 1778 kprintf(" exit.status: %#" B_PRIx32 " (%s)\n", thread->exit.status, 1779 strerror(thread->exit.status)); 1780 kprintf(" exit.waiters:\n"); 1781 while ((death = (struct thread_death_entry*)list_get_next_item( 1782 &thread->exit.waiters, death)) != NULL) { 1783 kprintf("\t%p (thread %" B_PRId32 ")\n", death, death->thread); 1784 } 1785 1786 kprintf("kernel_stack_area: %" B_PRId32 "\n", thread->kernel_stack_area); 1787 kprintf("kernel_stack_base: %p\n", (void *)thread->kernel_stack_base); 1788 kprintf("user_stack_area: %" B_PRId32 "\n", thread->user_stack_area); 1789 kprintf("user_stack_base: %p\n", (void *)thread->user_stack_base); 1790 kprintf("user_local_storage: %p\n", (void *)thread->user_local_storage); 1791 kprintf("user_thread: %p\n", (void *)thread->user_thread); 1792 kprintf("kernel_errno: %#x (%s)\n", thread->kernel_errno, 1793 strerror(thread->kernel_errno)); 1794 kprintf("kernel_time: %" B_PRId64 "\n", thread->kernel_time); 1795 kprintf("user_time: %" B_PRId64 "\n", thread->user_time); 1796 kprintf("flags: 0x%" B_PRIx32 "\n", thread->flags); 1797 kprintf("architecture dependant section:\n"); 1798 arch_thread_dump_info(&thread->arch_info); 1799 kprintf("scheduler data:\n"); 1800 scheduler_dump_thread_data(thread); 1801 } 1802 1803 1804 static int 1805 dump_thread_info(int argc, char **argv) 1806 { 1807 bool shortInfo = false; 1808 int argi = 1; 1809 if (argi < argc && strcmp(argv[argi], "-s") == 0) { 1810 shortInfo = true; 1811 print_thread_list_table_head(); 1812 argi++; 1813 } 1814 1815 if (argi == argc) { 1816 _dump_thread_info(thread_get_current_thread(), shortInfo); 1817 return 0; 1818 } 1819 1820 for (; argi < argc; argi++) { 1821 const char *name = argv[argi]; 1822 ulong arg = strtoul(name, NULL, 0); 1823 1824 if (IS_KERNEL_ADDRESS(arg)) { 1825 // semi-hack 1826 _dump_thread_info((Thread *)arg, shortInfo); 1827 continue; 1828 } 1829 1830 // walk through the thread list, trying to match name or id 1831 bool found = false; 1832 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1833 Thread* thread = it.Next();) { 1834 if (!strcmp(name, thread->name) || thread->id == (thread_id)arg) { 1835 _dump_thread_info(thread, shortInfo); 1836 found = true; 1837 break; 1838 } 1839 } 1840 1841 if (!found) 1842 kprintf("thread \"%s\" (%" B_PRId32 ") doesn't exist!\n", name, (thread_id)arg); 1843 } 1844 1845 return 0; 1846 } 1847 1848 1849 static int 1850 dump_thread_list(int argc, char **argv) 1851 { 1852 bool realTimeOnly = false; 1853 bool calling = false; 1854 const char *callSymbol = NULL; 1855 addr_t callStart = 0; 1856 addr_t callEnd = 0; 1857 int32 requiredState = 0; 1858 team_id team = -1; 1859 sem_id sem = -1; 1860 1861 if (!strcmp(argv[0], "realtime")) 1862 realTimeOnly = true; 1863 else if (!strcmp(argv[0], "ready")) 1864 requiredState = B_THREAD_READY; 1865 else if (!strcmp(argv[0], "running")) 1866 requiredState = B_THREAD_RUNNING; 1867 else if (!strcmp(argv[0], "waiting")) { 1868 requiredState = B_THREAD_WAITING; 1869 1870 if (argc > 1) { 1871 sem = strtoul(argv[1], NULL, 0); 1872 if (sem == 0) 1873 kprintf("ignoring invalid semaphore argument.\n"); 1874 } 1875 } else if (!strcmp(argv[0], "calling")) { 1876 if (argc < 2) { 1877 kprintf("Need to give a symbol name or start and end arguments.\n"); 1878 return 0; 1879 } else if (argc == 3) { 1880 callStart = parse_expression(argv[1]); 1881 callEnd = parse_expression(argv[2]); 1882 } else 1883 callSymbol = argv[1]; 1884 1885 calling = true; 1886 } else if (argc > 1) { 1887 team = strtoul(argv[1], NULL, 0); 1888 if (team == 0) 1889 kprintf("ignoring invalid team argument.\n"); 1890 } 1891 1892 print_thread_list_table_head(); 1893 1894 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1895 Thread* thread = it.Next();) { 1896 // filter out threads not matching the search criteria 1897 if ((requiredState && thread->state != requiredState) 1898 || (calling && !arch_debug_contains_call(thread, callSymbol, 1899 callStart, callEnd)) 1900 || (sem > 0 && get_thread_wait_sem(thread) != sem) 1901 || (team > 0 && thread->team->id != team) 1902 || (realTimeOnly && thread->priority < B_REAL_TIME_DISPLAY_PRIORITY)) 1903 continue; 1904 1905 _dump_thread_info(thread, true); 1906 } 1907 return 0; 1908 } 1909 1910 1911 // #pragma mark - private kernel API 1912 1913 1914 void 1915 thread_exit(void) 1916 { 1917 cpu_status state; 1918 Thread* thread = thread_get_current_thread(); 1919 Team* team = thread->team; 1920 Team* kernelTeam = team_get_kernel_team(); 1921 status_t status; 1922 struct thread_debug_info debugInfo; 1923 team_id teamID = team->id; 1924 1925 TRACE(("thread %" B_PRId32 " exiting w/return code %#" B_PRIx32 "\n", 1926 thread->id, thread->exit.status)); 1927 1928 if (!are_interrupts_enabled()) 1929 panic("thread_exit() called with interrupts disabled!\n"); 1930 1931 // boost our priority to get this over with 1932 scheduler_set_thread_priority(thread, B_URGENT_DISPLAY_PRIORITY); 1933 1934 if (team != kernelTeam) { 1935 // Delete all user timers associated with the thread. 1936 ThreadLocker threadLocker(thread); 1937 thread->DeleteUserTimers(false); 1938 1939 // detach the thread's user thread 1940 user_thread* userThread = thread->user_thread; 1941 thread->user_thread = NULL; 1942 1943 threadLocker.Unlock(); 1944 1945 // Delete the thread's user thread, if it's not the main thread. If it 1946 // is, we can save the work, since it will be deleted with the team's 1947 // address space. 1948 if (thread != team->main_thread) 1949 team_free_user_thread(team, userThread); 1950 } 1951 1952 // remember the user stack area -- we will delete it below 1953 area_id userStackArea = -1; 1954 if (team->address_space != NULL && thread->user_stack_area >= 0) { 1955 userStackArea = thread->user_stack_area; 1956 thread->user_stack_area = -1; 1957 } 1958 1959 struct job_control_entry *death = NULL; 1960 struct thread_death_entry* threadDeathEntry = NULL; 1961 bool deleteTeam = false; 1962 port_id debuggerPort = -1; 1963 1964 if (team != kernelTeam) { 1965 user_debug_thread_exiting(thread); 1966 1967 if (team->main_thread == thread) { 1968 // The main thread is exiting. Shut down the whole team. 1969 deleteTeam = true; 1970 1971 // kill off all other threads and the user debugger facilities 1972 debuggerPort = team_shutdown_team(team); 1973 1974 // acquire necessary locks, which are: process group lock, kernel 1975 // team lock, parent team lock, and the team lock 1976 team->LockProcessGroup(); 1977 kernelTeam->Lock(); 1978 team->LockTeamAndParent(true); 1979 } else { 1980 threadDeathEntry 1981 = (thread_death_entry*)malloc(sizeof(thread_death_entry)); 1982 1983 // acquire necessary locks, which are: kernel team lock and the team 1984 // lock 1985 kernelTeam->Lock(); 1986 team->Lock(); 1987 } 1988 1989 ThreadLocker threadLocker(thread); 1990 1991 state = disable_interrupts(); 1992 1993 // swap address spaces, to make sure we're running on the kernel's pgdir 1994 vm_swap_address_space(team->address_space, VMAddressSpace::Kernel()); 1995 1996 WriteSpinLocker teamLocker(thread->team_lock); 1997 SpinLocker threadCreationLocker(gThreadCreationLock); 1998 // removing the thread and putting its death entry to the parent 1999 // team needs to be an atomic operation 2000 2001 // remember how long this thread lasted 2002 bigtime_t now = system_time(); 2003 2004 InterruptsSpinLocker signalLocker(kernelTeam->signal_lock); 2005 SpinLocker teamTimeLocker(kernelTeam->time_lock); 2006 SpinLocker threadTimeLocker(thread->time_lock); 2007 2008 thread->kernel_time += now - thread->last_time; 2009 thread->last_time = now; 2010 2011 team->dead_threads_kernel_time += thread->kernel_time; 2012 team->dead_threads_user_time += thread->user_time; 2013 2014 // stop/update thread/team CPU time user timers 2015 if (thread->HasActiveCPUTimeUserTimers() 2016 || team->HasActiveCPUTimeUserTimers()) { 2017 user_timer_stop_cpu_timers(thread, NULL); 2018 } 2019 2020 // deactivate CPU time user timers for the thread 2021 if (thread->HasActiveCPUTimeUserTimers()) 2022 thread->DeactivateCPUTimeUserTimers(); 2023 2024 threadTimeLocker.Unlock(); 2025 2026 // put the thread into the kernel team until it dies 2027 remove_thread_from_team(team, thread); 2028 insert_thread_into_team(kernelTeam, thread); 2029 2030 teamTimeLocker.Unlock(); 2031 signalLocker.Unlock(); 2032 2033 teamLocker.Unlock(); 2034 2035 if (team->death_entry != NULL) { 2036 if (--team->death_entry->remaining_threads == 0) 2037 team->death_entry->condition.NotifyOne(); 2038 } 2039 2040 if (deleteTeam) { 2041 Team* parent = team->parent; 2042 2043 // Set the team job control state to "dead" and detach the job 2044 // control entry from our team struct. 2045 team_set_job_control_state(team, JOB_CONTROL_STATE_DEAD, NULL); 2046 death = team->job_control_entry; 2047 team->job_control_entry = NULL; 2048 2049 if (death != NULL) { 2050 death->InitDeadState(); 2051 2052 // team_set_job_control_state() already moved our entry 2053 // into the parent's list. We just check the soft limit of 2054 // death entries. 2055 if (parent->dead_children.count > MAX_DEAD_CHILDREN) { 2056 death = parent->dead_children.entries.RemoveHead(); 2057 parent->dead_children.count--; 2058 } else 2059 death = NULL; 2060 } 2061 2062 threadCreationLocker.Unlock(); 2063 restore_interrupts(state); 2064 2065 threadLocker.Unlock(); 2066 2067 // Get a temporary reference to the team's process group 2068 // -- team_remove_team() removes the team from the group, which 2069 // might destroy it otherwise and we wouldn't be able to unlock it. 2070 ProcessGroup* group = team->group; 2071 group->AcquireReference(); 2072 2073 pid_t foregroundGroupToSignal; 2074 team_remove_team(team, foregroundGroupToSignal); 2075 2076 // unlock everything but the parent team 2077 team->Unlock(); 2078 if (parent != kernelTeam) 2079 kernelTeam->Unlock(); 2080 group->Unlock(); 2081 group->ReleaseReference(); 2082 2083 // Send SIGCHLD to the parent as long as we still have its lock. 2084 // This makes job control state change + signalling atomic. 2085 Signal childSignal(SIGCHLD, team->exit.reason, B_OK, team->id); 2086 if (team->exit.reason == CLD_EXITED) { 2087 childSignal.SetStatus(team->exit.status); 2088 } else { 2089 childSignal.SetStatus(team->exit.signal); 2090 childSignal.SetSendingUser(team->exit.signaling_user); 2091 } 2092 send_signal_to_team(parent, childSignal, B_DO_NOT_RESCHEDULE); 2093 2094 // also unlock the parent 2095 parent->Unlock(); 2096 2097 // If the team was a session leader with controlling TTY, we have 2098 // to send SIGHUP to the foreground process group. 2099 if (foregroundGroupToSignal >= 0) { 2100 Signal groupSignal(SIGHUP, SI_USER, B_OK, team->id); 2101 send_signal_to_process_group(foregroundGroupToSignal, 2102 groupSignal, B_DO_NOT_RESCHEDULE); 2103 } 2104 } else { 2105 // The thread is not the main thread. We store a thread death entry 2106 // for it, unless someone is already waiting for it. 2107 if (threadDeathEntry != NULL 2108 && list_is_empty(&thread->exit.waiters)) { 2109 threadDeathEntry->thread = thread->id; 2110 threadDeathEntry->status = thread->exit.status; 2111 2112 // add entry -- remove an old one, if we hit the limit 2113 list_add_item(&team->dead_threads, threadDeathEntry); 2114 team->dead_threads_count++; 2115 threadDeathEntry = NULL; 2116 2117 if (team->dead_threads_count > MAX_DEAD_THREADS) { 2118 threadDeathEntry 2119 = (thread_death_entry*)list_remove_head_item( 2120 &team->dead_threads); 2121 team->dead_threads_count--; 2122 } 2123 } 2124 2125 threadCreationLocker.Unlock(); 2126 restore_interrupts(state); 2127 2128 threadLocker.Unlock(); 2129 team->Unlock(); 2130 kernelTeam->Unlock(); 2131 } 2132 2133 TRACE(("thread_exit: thread %" B_PRId32 " now a kernel thread!\n", 2134 thread->id)); 2135 } 2136 2137 free(threadDeathEntry); 2138 2139 // delete the team if we're its main thread 2140 if (deleteTeam) { 2141 team_delete_team(team, debuggerPort); 2142 2143 // we need to delete any death entry that made it to here 2144 delete death; 2145 } 2146 2147 ThreadLocker threadLocker(thread); 2148 2149 state = disable_interrupts(); 2150 SpinLocker threadCreationLocker(gThreadCreationLock); 2151 2152 // mark invisible in global hash/list, so it's no longer accessible 2153 SpinLocker threadHashLocker(sThreadHashLock); 2154 thread->visible = false; 2155 sUsedThreads--; 2156 threadHashLocker.Unlock(); 2157 2158 // Stop debugging for this thread 2159 SpinLocker threadDebugInfoLocker(thread->debug_info.lock); 2160 debugInfo = thread->debug_info; 2161 clear_thread_debug_info(&thread->debug_info, true); 2162 threadDebugInfoLocker.Unlock(); 2163 2164 // Remove the select infos. We notify them a little later. 2165 select_info* selectInfos = thread->select_infos; 2166 thread->select_infos = NULL; 2167 2168 threadCreationLocker.Unlock(); 2169 restore_interrupts(state); 2170 2171 threadLocker.Unlock(); 2172 2173 destroy_thread_debug_info(&debugInfo); 2174 2175 // notify select infos 2176 select_info* info = selectInfos; 2177 while (info != NULL) { 2178 select_sync* sync = info->sync; 2179 2180 notify_select_events(info, B_EVENT_INVALID); 2181 info = info->next; 2182 put_select_sync(sync); 2183 } 2184 2185 // notify listeners 2186 sNotificationService.Notify(THREAD_REMOVED, thread); 2187 2188 // shutdown the thread messaging 2189 2190 status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0); 2191 if (status == B_WOULD_BLOCK) { 2192 // there is data waiting for us, so let us eat it 2193 thread_id sender; 2194 2195 delete_sem(thread->msg.write_sem); 2196 // first, let's remove all possibly waiting writers 2197 receive_data_etc(&sender, NULL, 0, B_RELATIVE_TIMEOUT); 2198 } else { 2199 // we probably own the semaphore here, and we're the last to do so 2200 delete_sem(thread->msg.write_sem); 2201 } 2202 // now we can safely remove the msg.read_sem 2203 delete_sem(thread->msg.read_sem); 2204 2205 // fill all death entries and delete the sem that others will use to wait 2206 // for us 2207 { 2208 sem_id cachedExitSem = thread->exit.sem; 2209 2210 ThreadLocker threadLocker(thread); 2211 2212 // make sure no one will grab this semaphore again 2213 thread->exit.sem = -1; 2214 2215 // fill all death entries 2216 thread_death_entry* entry = NULL; 2217 while ((entry = (thread_death_entry*)list_get_next_item( 2218 &thread->exit.waiters, entry)) != NULL) { 2219 entry->status = thread->exit.status; 2220 } 2221 2222 threadLocker.Unlock(); 2223 2224 delete_sem(cachedExitSem); 2225 } 2226 2227 // delete the user stack, if this was a user thread 2228 if (!deleteTeam && userStackArea >= 0) { 2229 // We postponed deleting the user stack until now, since this way all 2230 // notifications for the thread's death are out already and all other 2231 // threads waiting for this thread's death and some object on its stack 2232 // will wake up before we (try to) delete the stack area. Of most 2233 // relevance is probably the case where this is the main thread and 2234 // other threads use objects on its stack -- so we want them terminated 2235 // first. 2236 // When the team is deleted, all areas are deleted anyway, so we don't 2237 // need to do that explicitly in that case. 2238 vm_delete_area(teamID, userStackArea, true); 2239 } 2240 2241 // notify the debugger 2242 if (teamID != kernelTeam->id) 2243 user_debug_thread_deleted(teamID, thread->id); 2244 2245 // enqueue in the undertaker list and reschedule for the last time 2246 UndertakerEntry undertakerEntry(thread, teamID); 2247 2248 disable_interrupts(); 2249 2250 SpinLocker schedulerLocker(thread->scheduler_lock); 2251 2252 SpinLocker undertakerLocker(sUndertakerLock); 2253 sUndertakerEntries.Add(&undertakerEntry); 2254 sUndertakerCondition.NotifyOne(); 2255 undertakerLocker.Unlock(); 2256 2257 scheduler_reschedule(THREAD_STATE_FREE_ON_RESCHED); 2258 2259 panic("never can get here\n"); 2260 } 2261 2262 2263 /*! Called in the interrupt handler code when a thread enters 2264 the kernel for any reason. 2265 Only tracks time for now. 2266 Interrupts are disabled. 2267 */ 2268 void 2269 thread_at_kernel_entry(bigtime_t now) 2270 { 2271 Thread *thread = thread_get_current_thread(); 2272 2273 TRACE(("thread_at_kernel_entry: entry thread %" B_PRId32 "\n", thread->id)); 2274 2275 // track user time 2276 SpinLocker threadTimeLocker(thread->time_lock); 2277 thread->user_time += now - thread->last_time; 2278 thread->last_time = now; 2279 thread->in_kernel = true; 2280 threadTimeLocker.Unlock(); 2281 } 2282 2283 2284 /*! Called whenever a thread exits kernel space to user space. 2285 Tracks time, handles signals, ... 2286 Interrupts must be enabled. When the function returns, interrupts will be 2287 disabled. 2288 The function may not return. This e.g. happens when the thread has received 2289 a deadly signal. 2290 */ 2291 void 2292 thread_at_kernel_exit(void) 2293 { 2294 Thread *thread = thread_get_current_thread(); 2295 2296 TRACE(("thread_at_kernel_exit: exit thread %" B_PRId32 "\n", thread->id)); 2297 2298 handle_signals(thread); 2299 2300 disable_interrupts(); 2301 2302 // track kernel time 2303 bigtime_t now = system_time(); 2304 SpinLocker threadTimeLocker(thread->time_lock); 2305 thread->in_kernel = false; 2306 thread->kernel_time += now - thread->last_time; 2307 thread->last_time = now; 2308 } 2309 2310 2311 /*! The quick version of thread_kernel_exit(), in case no signals are pending 2312 and no debugging shall be done. 2313 Interrupts must be disabled. 2314 */ 2315 void 2316 thread_at_kernel_exit_no_signals(void) 2317 { 2318 Thread *thread = thread_get_current_thread(); 2319 2320 TRACE(("thread_at_kernel_exit_no_signals: exit thread %" B_PRId32 "\n", 2321 thread->id)); 2322 2323 // track kernel time 2324 bigtime_t now = system_time(); 2325 SpinLocker threadTimeLocker(thread->time_lock); 2326 thread->in_kernel = false; 2327 thread->kernel_time += now - thread->last_time; 2328 thread->last_time = now; 2329 } 2330 2331 2332 void 2333 thread_reset_for_exec(void) 2334 { 2335 Thread* thread = thread_get_current_thread(); 2336 2337 ThreadLocker threadLocker(thread); 2338 2339 // delete user-defined timers 2340 thread->DeleteUserTimers(true); 2341 2342 // cancel pre-defined timer 2343 if (UserTimer* timer = thread->UserTimerFor(USER_TIMER_REAL_TIME_ID)) 2344 timer->Cancel(); 2345 2346 // reset user_thread and user stack 2347 thread->user_thread = NULL; 2348 thread->user_stack_area = -1; 2349 thread->user_stack_base = 0; 2350 thread->user_stack_size = 0; 2351 2352 // reset signals 2353 thread->ResetSignalsOnExec(); 2354 2355 // reset thread CPU time clock 2356 InterruptsSpinLocker timeLocker(thread->time_lock); 2357 thread->cpu_clock_offset = -thread->CPUTime(false); 2358 } 2359 2360 2361 thread_id 2362 allocate_thread_id() 2363 { 2364 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2365 2366 // find the next unused ID 2367 thread_id id; 2368 do { 2369 id = sNextThreadID++; 2370 2371 // deal with integer overflow 2372 if (sNextThreadID < 0) 2373 sNextThreadID = 2; 2374 2375 // check whether the ID is already in use 2376 } while (sThreadHash.Lookup(id, false) != NULL); 2377 2378 return id; 2379 } 2380 2381 2382 thread_id 2383 peek_next_thread_id() 2384 { 2385 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2386 return sNextThreadID; 2387 } 2388 2389 2390 /*! Yield the CPU to other threads. 2391 Thread will continue to run, if there's no other thread in ready 2392 state, and if it has a higher priority than the other ready threads, it 2393 still has a good chance to continue. 2394 */ 2395 void 2396 thread_yield(void) 2397 { 2398 Thread *thread = thread_get_current_thread(); 2399 if (thread == NULL) 2400 return; 2401 2402 InterruptsSpinLocker _(thread->scheduler_lock); 2403 2404 thread->has_yielded = true; 2405 scheduler_reschedule(B_THREAD_READY); 2406 } 2407 2408 2409 void 2410 thread_map(void (*function)(Thread* thread, void* data), void* data) 2411 { 2412 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2413 2414 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 2415 Thread* thread = it.Next();) { 2416 function(thread, data); 2417 } 2418 } 2419 2420 2421 /*! Kernel private thread creation function. 2422 */ 2423 thread_id 2424 spawn_kernel_thread_etc(thread_func function, const char *name, int32 priority, 2425 void *arg, team_id team) 2426 { 2427 return thread_create_thread( 2428 ThreadCreationAttributes(function, name, priority, arg, team), 2429 true); 2430 } 2431 2432 2433 status_t 2434 wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, 2435 status_t *_returnCode) 2436 { 2437 if (id < 0) 2438 return B_BAD_THREAD_ID; 2439 2440 // get the thread, queue our death entry, and fetch the semaphore we have to 2441 // wait on 2442 sem_id exitSem = B_BAD_THREAD_ID; 2443 struct thread_death_entry death; 2444 2445 Thread* thread = Thread::GetAndLock(id); 2446 if (thread != NULL) { 2447 // remember the semaphore we have to wait on and place our death entry 2448 exitSem = thread->exit.sem; 2449 if (exitSem >= 0) 2450 list_add_link_to_head(&thread->exit.waiters, &death); 2451 2452 thread->UnlockAndReleaseReference(); 2453 2454 if (exitSem < 0) 2455 return B_BAD_THREAD_ID; 2456 } else { 2457 // we couldn't find this thread -- maybe it's already gone, and we'll 2458 // find its death entry in our team 2459 Team* team = thread_get_current_thread()->team; 2460 TeamLocker teamLocker(team); 2461 2462 // check the child death entries first (i.e. main threads of child 2463 // teams) 2464 bool deleteEntry; 2465 job_control_entry* freeDeath 2466 = team_get_death_entry(team, id, &deleteEntry); 2467 if (freeDeath != NULL) { 2468 death.status = freeDeath->status; 2469 if (deleteEntry) 2470 delete freeDeath; 2471 } else { 2472 // check the thread death entries of the team (non-main threads) 2473 thread_death_entry* threadDeathEntry = NULL; 2474 while ((threadDeathEntry = (thread_death_entry*)list_get_next_item( 2475 &team->dead_threads, threadDeathEntry)) != NULL) { 2476 if (threadDeathEntry->thread == id) { 2477 list_remove_item(&team->dead_threads, threadDeathEntry); 2478 team->dead_threads_count--; 2479 death.status = threadDeathEntry->status; 2480 free(threadDeathEntry); 2481 break; 2482 } 2483 } 2484 2485 if (threadDeathEntry == NULL) 2486 return B_BAD_THREAD_ID; 2487 } 2488 2489 // we found the thread's death entry in our team 2490 if (_returnCode) 2491 *_returnCode = death.status; 2492 2493 return B_OK; 2494 } 2495 2496 // we need to wait for the death of the thread 2497 2498 resume_thread(id); 2499 // make sure we don't wait forever on a suspended thread 2500 2501 status_t status = acquire_sem_etc(exitSem, 1, flags, timeout); 2502 2503 if (status == B_OK) { 2504 // this should never happen as the thread deletes the semaphore on exit 2505 panic("could acquire exit_sem for thread %" B_PRId32 "\n", id); 2506 } else if (status == B_BAD_SEM_ID) { 2507 // this is the way the thread normally exits 2508 status = B_OK; 2509 } else { 2510 // We were probably interrupted or the timeout occurred; we need to 2511 // remove our death entry now. 2512 thread = Thread::GetAndLock(id); 2513 if (thread != NULL) { 2514 list_remove_link(&death); 2515 thread->UnlockAndReleaseReference(); 2516 } else { 2517 // The thread is already gone, so we need to wait uninterruptibly 2518 // for its exit semaphore to make sure our death entry stays valid. 2519 // It won't take long, since the thread is apparently already in the 2520 // middle of the cleanup. 2521 acquire_sem(exitSem); 2522 status = B_OK; 2523 } 2524 } 2525 2526 if (status == B_OK && _returnCode != NULL) 2527 *_returnCode = death.status; 2528 2529 return status; 2530 } 2531 2532 2533 status_t 2534 select_thread(int32 id, struct select_info* info, bool kernel) 2535 { 2536 // get and lock the thread 2537 Thread* thread = Thread::GetAndLock(id); 2538 if (thread == NULL) 2539 return B_BAD_THREAD_ID; 2540 BReference<Thread> threadReference(thread, true); 2541 ThreadLocker threadLocker(thread, true); 2542 2543 // We support only B_EVENT_INVALID at the moment. 2544 info->selected_events &= B_EVENT_INVALID; 2545 2546 // add info to list 2547 if (info->selected_events != 0) { 2548 info->next = thread->select_infos; 2549 thread->select_infos = info; 2550 2551 // we need a sync reference 2552 atomic_add(&info->sync->ref_count, 1); 2553 } 2554 2555 return B_OK; 2556 } 2557 2558 2559 status_t 2560 deselect_thread(int32 id, struct select_info* info, bool kernel) 2561 { 2562 // get and lock the thread 2563 Thread* thread = Thread::GetAndLock(id); 2564 if (thread == NULL) 2565 return B_BAD_THREAD_ID; 2566 BReference<Thread> threadReference(thread, true); 2567 ThreadLocker threadLocker(thread, true); 2568 2569 // remove info from list 2570 select_info** infoLocation = &thread->select_infos; 2571 while (*infoLocation != NULL && *infoLocation != info) 2572 infoLocation = &(*infoLocation)->next; 2573 2574 if (*infoLocation != info) 2575 return B_OK; 2576 2577 *infoLocation = info->next; 2578 2579 threadLocker.Unlock(); 2580 2581 // surrender sync reference 2582 put_select_sync(info->sync); 2583 2584 return B_OK; 2585 } 2586 2587 2588 int32 2589 thread_max_threads(void) 2590 { 2591 return sMaxThreads; 2592 } 2593 2594 2595 int32 2596 thread_used_threads(void) 2597 { 2598 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2599 return sUsedThreads; 2600 } 2601 2602 2603 /*! Returns a user-readable string for a thread state. 2604 Only for use in the kernel debugger. 2605 */ 2606 const char* 2607 thread_state_to_text(Thread* thread, int32 state) 2608 { 2609 return state_to_text(thread, state); 2610 } 2611 2612 2613 int32 2614 thread_get_io_priority(thread_id id) 2615 { 2616 Thread* thread = Thread::GetAndLock(id); 2617 if (thread == NULL) 2618 return B_BAD_THREAD_ID; 2619 BReference<Thread> threadReference(thread, true); 2620 ThreadLocker threadLocker(thread, true); 2621 2622 int32 priority = thread->io_priority; 2623 if (priority < 0) { 2624 // negative I/O priority means using the (CPU) priority 2625 priority = thread->priority; 2626 } 2627 2628 return priority; 2629 } 2630 2631 2632 void 2633 thread_set_io_priority(int32 priority) 2634 { 2635 Thread* thread = thread_get_current_thread(); 2636 ThreadLocker threadLocker(thread); 2637 2638 thread->io_priority = priority; 2639 } 2640 2641 2642 status_t 2643 thread_init(kernel_args *args) 2644 { 2645 TRACE(("thread_init: entry\n")); 2646 2647 // create the thread hash table 2648 new(&sThreadHash) ThreadHashTable(); 2649 if (sThreadHash.Init(128) != B_OK) 2650 panic("thread_init(): failed to init thread hash table!"); 2651 2652 // create the thread structure object cache 2653 sThreadCache = create_object_cache("threads", sizeof(Thread), 16, NULL, 2654 NULL, NULL); 2655 // Note: The x86 port requires 16 byte alignment of thread structures. 2656 if (sThreadCache == NULL) 2657 panic("thread_init(): failed to allocate thread object cache!"); 2658 2659 if (arch_thread_init(args) < B_OK) 2660 panic("arch_thread_init() failed!\n"); 2661 2662 // skip all thread IDs including B_SYSTEM_TEAM, which is reserved 2663 sNextThreadID = B_SYSTEM_TEAM + 1; 2664 2665 // create an idle thread for each cpu 2666 for (uint32 i = 0; i < args->num_cpus; i++) { 2667 Thread *thread; 2668 area_info info; 2669 char name[64]; 2670 2671 sprintf(name, "idle thread %" B_PRIu32, i + 1); 2672 thread = new(&sIdleThreads[i]) Thread(name, 2673 i == 0 ? team_get_kernel_team_id() : -1, &gCPU[i]); 2674 if (thread == NULL || thread->Init(true) != B_OK) { 2675 panic("error creating idle thread struct\n"); 2676 return B_NO_MEMORY; 2677 } 2678 2679 gCPU[i].running_thread = thread; 2680 2681 thread->team = team_get_kernel_team(); 2682 thread->priority = B_IDLE_PRIORITY; 2683 thread->state = B_THREAD_RUNNING; 2684 sprintf(name, "idle thread %" B_PRIu32 " kstack", i + 1); 2685 thread->kernel_stack_area = find_area(name); 2686 2687 if (get_area_info(thread->kernel_stack_area, &info) != B_OK) 2688 panic("error finding idle kstack area\n"); 2689 2690 thread->kernel_stack_base = (addr_t)info.address; 2691 thread->kernel_stack_top = thread->kernel_stack_base + info.size; 2692 2693 thread->visible = true; 2694 insert_thread_into_team(thread->team, thread); 2695 2696 scheduler_on_thread_init(thread); 2697 } 2698 sUsedThreads = args->num_cpus; 2699 2700 // init the notification service 2701 new(&sNotificationService) ThreadNotificationService(); 2702 2703 sNotificationService.Register(); 2704 2705 // start the undertaker thread 2706 new(&sUndertakerEntries) DoublyLinkedList<UndertakerEntry>(); 2707 sUndertakerCondition.Init(&sUndertakerEntries, "undertaker entries"); 2708 2709 thread_id undertakerThread = spawn_kernel_thread(&undertaker, "undertaker", 2710 B_DISPLAY_PRIORITY, NULL); 2711 if (undertakerThread < 0) 2712 panic("Failed to create undertaker thread!"); 2713 resume_thread(undertakerThread); 2714 2715 // set up some debugger commands 2716 add_debugger_command_etc("threads", &dump_thread_list, "List all threads", 2717 "[ <team> ]\n" 2718 "Prints a list of all existing threads, or, if a team ID is given,\n" 2719 "all threads of the specified team.\n" 2720 " <team> - The ID of the team whose threads shall be listed.\n", 0); 2721 add_debugger_command_etc("ready", &dump_thread_list, 2722 "List all ready threads", 2723 "\n" 2724 "Prints a list of all threads in ready state.\n", 0); 2725 add_debugger_command_etc("running", &dump_thread_list, 2726 "List all running threads", 2727 "\n" 2728 "Prints a list of all threads in running state.\n", 0); 2729 add_debugger_command_etc("waiting", &dump_thread_list, 2730 "List all waiting threads (optionally for a specific semaphore)", 2731 "[ <sem> ]\n" 2732 "Prints a list of all threads in waiting state. If a semaphore is\n" 2733 "specified, only the threads waiting on that semaphore are listed.\n" 2734 " <sem> - ID of the semaphore.\n", 0); 2735 add_debugger_command_etc("realtime", &dump_thread_list, 2736 "List all realtime threads", 2737 "\n" 2738 "Prints a list of all threads with realtime priority.\n", 0); 2739 add_debugger_command_etc("thread", &dump_thread_info, 2740 "Dump info about a particular thread", 2741 "[ -s ] ( <id> | <address> | <name> )*\n" 2742 "Prints information about the specified thread. If no argument is\n" 2743 "given the current thread is selected.\n" 2744 " -s - Print info in compact table form (like \"threads\").\n" 2745 " <id> - The ID of the thread.\n" 2746 " <address> - The address of the thread structure.\n" 2747 " <name> - The thread's name.\n", 0); 2748 add_debugger_command_etc("calling", &dump_thread_list, 2749 "Show all threads that have a specific address in their call chain", 2750 "{ <symbol-pattern> | <start> <end> }\n", 0); 2751 add_debugger_command_etc("unreal", &make_thread_unreal, 2752 "Set realtime priority threads to normal priority", 2753 "[ <id> ]\n" 2754 "Sets the priority of all realtime threads or, if given, the one\n" 2755 "with the specified ID to \"normal\" priority.\n" 2756 " <id> - The ID of the thread.\n", 0); 2757 add_debugger_command_etc("suspend", &make_thread_suspended, 2758 "Suspend a thread", 2759 "[ <id> ]\n" 2760 "Suspends the thread with the given ID. If no ID argument is given\n" 2761 "the current thread is selected.\n" 2762 " <id> - The ID of the thread.\n", 0); 2763 add_debugger_command_etc("resume", &make_thread_resumed, "Resume a thread", 2764 "<id>\n" 2765 "Resumes the specified thread, if it is currently suspended.\n" 2766 " <id> - The ID of the thread.\n", 0); 2767 add_debugger_command_etc("drop", &drop_into_debugger, 2768 "Drop a thread into the userland debugger", 2769 "<id>\n" 2770 "Drops the specified (userland) thread into the userland debugger\n" 2771 "after leaving the kernel debugger.\n" 2772 " <id> - The ID of the thread.\n", 0); 2773 add_debugger_command_etc("priority", &set_thread_prio, 2774 "Set a thread's priority", 2775 "<priority> [ <id> ]\n" 2776 "Sets the priority of the thread with the specified ID to the given\n" 2777 "priority. If no thread ID is given, the current thread is selected.\n" 2778 " <priority> - The thread's new priority (0 - 120)\n" 2779 " <id> - The ID of the thread.\n", 0); 2780 2781 return B_OK; 2782 } 2783 2784 2785 status_t 2786 thread_preboot_init_percpu(struct kernel_args *args, int32 cpuNum) 2787 { 2788 // set up the cpu pointer in the not yet initialized per-cpu idle thread 2789 // so that get_current_cpu and friends will work, which is crucial for 2790 // a lot of low level routines 2791 sIdleThreads[cpuNum].cpu = &gCPU[cpuNum]; 2792 arch_thread_set_current_thread(&sIdleThreads[cpuNum]); 2793 return B_OK; 2794 } 2795 2796 2797 // #pragma mark - thread blocking API 2798 2799 2800 static status_t 2801 thread_block_timeout(timer* timer) 2802 { 2803 Thread* thread = (Thread*)timer->user_data; 2804 thread_unblock(thread, B_TIMED_OUT); 2805 2806 return B_HANDLED_INTERRUPT; 2807 } 2808 2809 2810 /*! Blocks the current thread. 2811 2812 The thread is blocked until someone else unblock it. Must be called after a 2813 call to thread_prepare_to_block(). If the thread has already been unblocked 2814 after the previous call to thread_prepare_to_block(), this function will 2815 return immediately. Cf. the documentation of thread_prepare_to_block() for 2816 more details. 2817 2818 The caller must hold the scheduler lock. 2819 2820 \param thread The current thread. 2821 \return The error code passed to the unblocking function. thread_interrupt() 2822 uses \c B_INTERRUPTED. By convention \c B_OK means that the wait was 2823 successful while another error code indicates a failure (what that means 2824 depends on the client code). 2825 */ 2826 static inline status_t 2827 thread_block_locked(Thread* thread) 2828 { 2829 if (thread->wait.status == 1) { 2830 // check for signals, if interruptible 2831 if (thread_is_interrupted(thread, thread->wait.flags)) { 2832 thread->wait.status = B_INTERRUPTED; 2833 } else 2834 scheduler_reschedule(B_THREAD_WAITING); 2835 } 2836 2837 return thread->wait.status; 2838 } 2839 2840 2841 /*! Blocks the current thread. 2842 2843 The function acquires the scheduler lock and calls thread_block_locked(). 2844 See there for more information. 2845 */ 2846 status_t 2847 thread_block() 2848 { 2849 InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock); 2850 return thread_block_locked(thread_get_current_thread()); 2851 } 2852 2853 2854 /*! Blocks the current thread with a timeout. 2855 2856 The thread is blocked until someone else unblock it or the specified timeout 2857 occurs. Must be called after a call to thread_prepare_to_block(). If the 2858 thread has already been unblocked after the previous call to 2859 thread_prepare_to_block(), this function will return immediately. See 2860 thread_prepare_to_block() for more details. 2861 2862 The caller must not hold the scheduler lock. 2863 2864 \param thread The current thread. 2865 \param timeoutFlags The standard timeout flags: 2866 - \c B_RELATIVE_TIMEOUT: \a timeout specifies the time to wait. 2867 - \c B_ABSOLUTE_TIMEOUT: \a timeout specifies the absolute end time when 2868 the timeout shall occur. 2869 - \c B_TIMEOUT_REAL_TIME_BASE: Only relevant when \c B_ABSOLUTE_TIMEOUT 2870 is specified, too. Specifies that \a timeout is a real time, not a 2871 system time. 2872 If neither \c B_RELATIVE_TIMEOUT nor \c B_ABSOLUTE_TIMEOUT are 2873 specified, an infinite timeout is implied and the function behaves like 2874 thread_block_locked(). 2875 \return The error code passed to the unblocking function. thread_interrupt() 2876 uses \c B_INTERRUPTED. When the timeout occurred, \c B_TIMED_OUT is 2877 returned. By convention \c B_OK means that the wait was successful while 2878 another error code indicates a failure (what that means depends on the 2879 client code). 2880 */ 2881 status_t 2882 thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout) 2883 { 2884 Thread* thread = thread_get_current_thread(); 2885 2886 InterruptsSpinLocker locker(thread->scheduler_lock); 2887 2888 if (thread->wait.status != 1) 2889 return thread->wait.status; 2890 2891 bool useTimer = (timeoutFlags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) 2892 && timeout != B_INFINITE_TIMEOUT; 2893 2894 if (useTimer) { 2895 // Timer flags: absolute/relative. 2896 uint32 timerFlags; 2897 if ((timeoutFlags & B_RELATIVE_TIMEOUT) != 0) { 2898 timerFlags = B_ONE_SHOT_RELATIVE_TIMER; 2899 } else { 2900 timerFlags = B_ONE_SHOT_ABSOLUTE_TIMER; 2901 if ((timeoutFlags & B_TIMEOUT_REAL_TIME_BASE) != 0) 2902 timerFlags |= B_TIMER_REAL_TIME_BASE; 2903 } 2904 2905 // install the timer 2906 thread->wait.unblock_timer.user_data = thread; 2907 add_timer(&thread->wait.unblock_timer, &thread_block_timeout, timeout, 2908 timerFlags); 2909 } 2910 2911 // block 2912 status_t error = thread_block_locked(thread); 2913 2914 locker.Unlock(); 2915 2916 // cancel timer, if it didn't fire 2917 if (error != B_TIMED_OUT && useTimer) 2918 cancel_timer(&thread->wait.unblock_timer); 2919 2920 return error; 2921 } 2922 2923 2924 /*! Unblocks a thread. 2925 2926 Acquires the scheduler lock and calls thread_unblock_locked(). 2927 See there for more information. 2928 */ 2929 void 2930 thread_unblock(Thread* thread, status_t status) 2931 { 2932 InterruptsSpinLocker locker(thread->scheduler_lock); 2933 thread_unblock_locked(thread, status); 2934 } 2935 2936 2937 /*! Unblocks a userland-blocked thread. 2938 The caller must not hold any locks. 2939 */ 2940 static status_t 2941 user_unblock_thread(thread_id threadID, status_t status) 2942 { 2943 // get the thread 2944 Thread* thread = Thread::GetAndLock(threadID); 2945 if (thread == NULL) 2946 return B_BAD_THREAD_ID; 2947 BReference<Thread> threadReference(thread, true); 2948 ThreadLocker threadLocker(thread, true); 2949 2950 if (thread->user_thread == NULL) 2951 return B_NOT_ALLOWED; 2952 2953 InterruptsSpinLocker locker(thread->scheduler_lock); 2954 2955 if (thread->user_thread->wait_status > 0) { 2956 thread->user_thread->wait_status = status; 2957 thread_unblock_locked(thread, status); 2958 } 2959 2960 return B_OK; 2961 } 2962 2963 2964 // #pragma mark - public kernel API 2965 2966 2967 void 2968 exit_thread(status_t returnValue) 2969 { 2970 Thread *thread = thread_get_current_thread(); 2971 Team* team = thread->team; 2972 2973 thread->exit.status = returnValue; 2974 2975 // if called from a kernel thread, we don't deliver the signal, 2976 // we just exit directly to keep the user space behaviour of 2977 // this function 2978 if (team != team_get_kernel_team()) { 2979 // If this is its main thread, set the team's exit status. 2980 if (thread == team->main_thread) { 2981 TeamLocker teamLocker(team); 2982 2983 if (!team->exit.initialized) { 2984 team->exit.reason = CLD_EXITED; 2985 team->exit.signal = 0; 2986 team->exit.signaling_user = 0; 2987 team->exit.status = returnValue; 2988 team->exit.initialized = true; 2989 } 2990 2991 teamLocker.Unlock(); 2992 } 2993 2994 Signal signal(SIGKILLTHR, SI_USER, B_OK, team->id); 2995 send_signal_to_thread(thread, signal, B_DO_NOT_RESCHEDULE); 2996 } else 2997 thread_exit(); 2998 } 2999 3000 3001 status_t 3002 kill_thread(thread_id id) 3003 { 3004 if (id <= 0) 3005 return B_BAD_VALUE; 3006 3007 Thread* currentThread = thread_get_current_thread(); 3008 3009 Signal signal(SIGKILLTHR, SI_USER, B_OK, currentThread->team->id); 3010 return send_signal_to_thread_id(id, signal, 0); 3011 } 3012 3013 3014 status_t 3015 send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize) 3016 { 3017 return send_data_etc(thread, code, buffer, bufferSize, 0); 3018 } 3019 3020 3021 int32 3022 receive_data(thread_id *sender, void *buffer, size_t bufferSize) 3023 { 3024 return receive_data_etc(sender, buffer, bufferSize, 0); 3025 } 3026 3027 3028 bool 3029 has_data(thread_id thread) 3030 { 3031 // TODO: The thread argument is ignored. 3032 int32 count; 3033 3034 if (get_sem_count(thread_get_current_thread()->msg.read_sem, 3035 &count) != B_OK) 3036 return false; 3037 3038 return count == 0 ? false : true; 3039 } 3040 3041 3042 status_t 3043 _get_thread_info(thread_id id, thread_info *info, size_t size) 3044 { 3045 if (info == NULL || size != sizeof(thread_info) || id < B_OK) 3046 return B_BAD_VALUE; 3047 3048 // get the thread 3049 Thread* thread = Thread::GetAndLock(id); 3050 if (thread == NULL) 3051 return B_BAD_THREAD_ID; 3052 BReference<Thread> threadReference(thread, true); 3053 ThreadLocker threadLocker(thread, true); 3054 3055 // fill the info -- also requires the scheduler lock to be held 3056 InterruptsSpinLocker locker(thread->scheduler_lock); 3057 3058 fill_thread_info(thread, info, size); 3059 3060 return B_OK; 3061 } 3062 3063 3064 status_t 3065 _get_next_thread_info(team_id teamID, int32 *_cookie, thread_info *info, 3066 size_t size) 3067 { 3068 if (info == NULL || size != sizeof(thread_info) || teamID < 0) 3069 return B_BAD_VALUE; 3070 3071 int32 lastID = *_cookie; 3072 3073 // get the team 3074 Team* team = Team::GetAndLock(teamID); 3075 if (team == NULL) 3076 return B_BAD_VALUE; 3077 BReference<Team> teamReference(team, true); 3078 TeamLocker teamLocker(team, true); 3079 3080 Thread* thread = NULL; 3081 3082 if (lastID == 0) { 3083 // We start with the main thread 3084 thread = team->main_thread; 3085 } else { 3086 // Find the one thread with an ID greater than ours (as long as the IDs 3087 // don't wrap they are always sorted from highest to lowest). 3088 // TODO: That is broken not only when the IDs wrap, but also for the 3089 // kernel team, to which threads are added when they are dying. 3090 for (Thread* next = team->thread_list; next != NULL; 3091 next = next->team_next) { 3092 if (next->id <= lastID) 3093 break; 3094 3095 thread = next; 3096 } 3097 } 3098 3099 if (thread == NULL) 3100 return B_BAD_VALUE; 3101 3102 lastID = thread->id; 3103 *_cookie = lastID; 3104 3105 ThreadLocker threadLocker(thread); 3106 InterruptsSpinLocker locker(thread->scheduler_lock); 3107 3108 fill_thread_info(thread, info, size); 3109 3110 return B_OK; 3111 } 3112 3113 3114 thread_id 3115 find_thread(const char* name) 3116 { 3117 if (name == NULL) 3118 return thread_get_current_thread_id(); 3119 3120 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 3121 3122 // TODO: Scanning the whole hash with the thread hash lock held isn't 3123 // exactly cheap -- although this function is probably used very rarely. 3124 3125 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 3126 Thread* thread = it.Next();) { 3127 if (!thread->visible) 3128 continue; 3129 3130 if (strcmp(thread->name, name) == 0) 3131 return thread->id; 3132 } 3133 3134 return B_NAME_NOT_FOUND; 3135 } 3136 3137 3138 status_t 3139 rename_thread(thread_id id, const char* name) 3140 { 3141 if (name == NULL) 3142 return B_BAD_VALUE; 3143 3144 // get the thread 3145 Thread* thread = Thread::GetAndLock(id); 3146 if (thread == NULL) 3147 return B_BAD_THREAD_ID; 3148 BReference<Thread> threadReference(thread, true); 3149 ThreadLocker threadLocker(thread, true); 3150 3151 // check whether the operation is allowed 3152 if (thread->team != thread_get_current_thread()->team) 3153 return B_NOT_ALLOWED; 3154 3155 strlcpy(thread->name, name, B_OS_NAME_LENGTH); 3156 3157 team_id teamID = thread->team->id; 3158 3159 threadLocker.Unlock(); 3160 3161 // notify listeners 3162 sNotificationService.Notify(THREAD_NAME_CHANGED, teamID, id); 3163 // don't pass the thread structure, as it's unsafe, if it isn't ours 3164 3165 return B_OK; 3166 } 3167 3168 3169 status_t 3170 set_thread_priority(thread_id id, int32 priority) 3171 { 3172 // make sure the passed in priority is within bounds 3173 if (priority > THREAD_MAX_SET_PRIORITY) 3174 priority = THREAD_MAX_SET_PRIORITY; 3175 if (priority < THREAD_MIN_SET_PRIORITY) 3176 priority = THREAD_MIN_SET_PRIORITY; 3177 3178 // get the thread 3179 Thread* thread = Thread::GetAndLock(id); 3180 if (thread == NULL) 3181 return B_BAD_THREAD_ID; 3182 BReference<Thread> threadReference(thread, true); 3183 ThreadLocker threadLocker(thread, true); 3184 3185 // check whether the change is allowed 3186 if (thread_is_idle_thread(thread)) 3187 return B_NOT_ALLOWED; 3188 3189 return scheduler_set_thread_priority(thread, priority); 3190 } 3191 3192 3193 status_t 3194 snooze_etc(bigtime_t timeout, int timebase, uint32 flags) 3195 { 3196 return common_snooze_etc(timeout, timebase, flags, NULL); 3197 } 3198 3199 3200 /*! snooze() for internal kernel use only; doesn't interrupt on signals. */ 3201 status_t 3202 snooze(bigtime_t timeout) 3203 { 3204 return snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT); 3205 } 3206 3207 3208 /*! snooze_until() for internal kernel use only; doesn't interrupt on 3209 signals. 3210 */ 3211 status_t 3212 snooze_until(bigtime_t timeout, int timebase) 3213 { 3214 return snooze_etc(timeout, timebase, B_ABSOLUTE_TIMEOUT); 3215 } 3216 3217 3218 status_t 3219 wait_for_thread(thread_id thread, status_t *_returnCode) 3220 { 3221 return wait_for_thread_etc(thread, 0, 0, _returnCode); 3222 } 3223 3224 3225 status_t 3226 suspend_thread(thread_id id) 3227 { 3228 if (id <= 0) 3229 return B_BAD_VALUE; 3230 3231 Thread* currentThread = thread_get_current_thread(); 3232 3233 Signal signal(SIGSTOP, SI_USER, B_OK, currentThread->team->id); 3234 return send_signal_to_thread_id(id, signal, 0); 3235 } 3236 3237 3238 status_t 3239 resume_thread(thread_id id) 3240 { 3241 if (id <= 0) 3242 return B_BAD_VALUE; 3243 3244 Thread* currentThread = thread_get_current_thread(); 3245 3246 // Using the kernel internal SIGNAL_CONTINUE_THREAD signal retains 3247 // compatibility to BeOS which documents the combination of suspend_thread() 3248 // and resume_thread() to interrupt threads waiting on semaphores. 3249 Signal signal(SIGNAL_CONTINUE_THREAD, SI_USER, B_OK, 3250 currentThread->team->id); 3251 return send_signal_to_thread_id(id, signal, 0); 3252 } 3253 3254 3255 thread_id 3256 spawn_kernel_thread(thread_func function, const char *name, int32 priority, 3257 void *arg) 3258 { 3259 return thread_create_thread( 3260 ThreadCreationAttributes(function, name, priority, arg), 3261 true); 3262 } 3263 3264 3265 int 3266 getrlimit(int resource, struct rlimit * rlp) 3267 { 3268 status_t error = common_getrlimit(resource, rlp); 3269 if (error != B_OK) { 3270 errno = error; 3271 return -1; 3272 } 3273 3274 return 0; 3275 } 3276 3277 3278 int 3279 setrlimit(int resource, const struct rlimit * rlp) 3280 { 3281 status_t error = common_setrlimit(resource, rlp); 3282 if (error != B_OK) { 3283 errno = error; 3284 return -1; 3285 } 3286 3287 return 0; 3288 } 3289 3290 3291 // #pragma mark - syscalls 3292 3293 3294 void 3295 _user_exit_thread(status_t returnValue) 3296 { 3297 exit_thread(returnValue); 3298 } 3299 3300 3301 status_t 3302 _user_kill_thread(thread_id thread) 3303 { 3304 // TODO: Don't allow kernel threads to be killed! 3305 return kill_thread(thread); 3306 } 3307 3308 3309 status_t 3310 _user_cancel_thread(thread_id threadID, void (*cancelFunction)(int)) 3311 { 3312 // check the cancel function 3313 if (cancelFunction == NULL || !IS_USER_ADDRESS(cancelFunction)) 3314 return B_BAD_VALUE; 3315 3316 // get and lock the thread 3317 Thread* thread = Thread::GetAndLock(threadID); 3318 if (thread == NULL) 3319 return B_BAD_THREAD_ID; 3320 BReference<Thread> threadReference(thread, true); 3321 ThreadLocker threadLocker(thread, true); 3322 3323 // only threads of the same team can be canceled 3324 if (thread->team != thread_get_current_thread()->team) 3325 return B_NOT_ALLOWED; 3326 3327 // set the cancel function 3328 thread->cancel_function = cancelFunction; 3329 3330 // send the cancellation signal to the thread 3331 InterruptsReadSpinLocker teamLocker(thread->team_lock); 3332 SpinLocker locker(thread->team->signal_lock); 3333 return send_signal_to_thread_locked(thread, SIGNAL_CANCEL_THREAD, NULL, 0); 3334 } 3335 3336 3337 status_t 3338 _user_resume_thread(thread_id thread) 3339 { 3340 // TODO: Don't allow kernel threads to be resumed! 3341 return resume_thread(thread); 3342 } 3343 3344 3345 status_t 3346 _user_suspend_thread(thread_id thread) 3347 { 3348 // TODO: Don't allow kernel threads to be suspended! 3349 return suspend_thread(thread); 3350 } 3351 3352 3353 status_t 3354 _user_rename_thread(thread_id thread, const char *userName) 3355 { 3356 char name[B_OS_NAME_LENGTH]; 3357 3358 if (!IS_USER_ADDRESS(userName) 3359 || userName == NULL 3360 || user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK) 3361 return B_BAD_ADDRESS; 3362 3363 // TODO: Don't allow kernel threads to be renamed! 3364 return rename_thread(thread, name); 3365 } 3366 3367 3368 int32 3369 _user_set_thread_priority(thread_id thread, int32 newPriority) 3370 { 3371 // TODO: Don't allow setting priority of kernel threads! 3372 return set_thread_priority(thread, newPriority); 3373 } 3374 3375 3376 thread_id 3377 _user_spawn_thread(thread_creation_attributes* userAttributes) 3378 { 3379 // copy the userland structure to the kernel 3380 char nameBuffer[B_OS_NAME_LENGTH]; 3381 ThreadCreationAttributes attributes; 3382 status_t error = attributes.InitFromUserAttributes(userAttributes, 3383 nameBuffer); 3384 if (error != B_OK) 3385 return error; 3386 3387 // create the thread 3388 thread_id threadID = thread_create_thread(attributes, false); 3389 3390 if (threadID >= 0) 3391 user_debug_thread_created(threadID); 3392 3393 return threadID; 3394 } 3395 3396 3397 status_t 3398 _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags, 3399 bigtime_t* userRemainingTime) 3400 { 3401 // We need to store more syscall restart parameters than usual and need a 3402 // somewhat different handling. Hence we can't use 3403 // syscall_restart_handle_timeout_pre() but do the job ourselves. 3404 struct restart_parameters { 3405 bigtime_t timeout; 3406 clockid_t timebase; 3407 uint32 flags; 3408 }; 3409 3410 Thread* thread = thread_get_current_thread(); 3411 3412 if ((thread->flags & THREAD_FLAGS_SYSCALL_RESTARTED) != 0) { 3413 // The syscall was restarted. Fetch the parameters from the stored 3414 // restart parameters. 3415 restart_parameters* restartParameters 3416 = (restart_parameters*)thread->syscall_restart.parameters; 3417 timeout = restartParameters->timeout; 3418 timebase = restartParameters->timebase; 3419 flags = restartParameters->flags; 3420 } else { 3421 // convert relative timeouts to absolute ones 3422 if ((flags & B_RELATIVE_TIMEOUT) != 0) { 3423 // not restarted yet and the flags indicate a relative timeout 3424 3425 // Make sure we use the system time base, so real-time clock changes 3426 // won't affect our wait. 3427 flags &= ~(uint32)B_TIMEOUT_REAL_TIME_BASE; 3428 if (timebase == CLOCK_REALTIME) 3429 timebase = CLOCK_MONOTONIC; 3430 3431 // get the current time and make the timeout absolute 3432 bigtime_t now; 3433 status_t error = user_timer_get_clock(timebase, now); 3434 if (error != B_OK) 3435 return error; 3436 3437 timeout += now; 3438 3439 // deal with overflow 3440 if (timeout < 0) 3441 timeout = B_INFINITE_TIMEOUT; 3442 3443 flags = (flags & ~B_RELATIVE_TIMEOUT) | B_ABSOLUTE_TIMEOUT; 3444 } else 3445 flags |= B_ABSOLUTE_TIMEOUT; 3446 } 3447 3448 // snooze 3449 bigtime_t remainingTime; 3450 status_t error = common_snooze_etc(timeout, timebase, 3451 flags | B_CAN_INTERRUPT | B_CHECK_PERMISSION, 3452 userRemainingTime != NULL ? &remainingTime : NULL); 3453 3454 // If interrupted, copy the remaining time back to userland and prepare the 3455 // syscall restart. 3456 if (error == B_INTERRUPTED) { 3457 if (userRemainingTime != NULL 3458 && (!IS_USER_ADDRESS(userRemainingTime) 3459 || user_memcpy(userRemainingTime, &remainingTime, 3460 sizeof(remainingTime)) != B_OK)) { 3461 return B_BAD_ADDRESS; 3462 } 3463 3464 // store the normalized values in the restart parameters 3465 restart_parameters* restartParameters 3466 = (restart_parameters*)thread->syscall_restart.parameters; 3467 restartParameters->timeout = timeout; 3468 restartParameters->timebase = timebase; 3469 restartParameters->flags = flags; 3470 3471 // restart the syscall, if possible 3472 atomic_or(&thread->flags, THREAD_FLAGS_RESTART_SYSCALL); 3473 } 3474 3475 return error; 3476 } 3477 3478 3479 void 3480 _user_thread_yield(void) 3481 { 3482 thread_yield(); 3483 } 3484 3485 3486 status_t 3487 _user_get_thread_info(thread_id id, thread_info *userInfo) 3488 { 3489 thread_info info; 3490 status_t status; 3491 3492 if (!IS_USER_ADDRESS(userInfo)) 3493 return B_BAD_ADDRESS; 3494 3495 status = _get_thread_info(id, &info, sizeof(thread_info)); 3496 3497 if (status >= B_OK 3498 && user_memcpy(userInfo, &info, sizeof(thread_info)) < B_OK) 3499 return B_BAD_ADDRESS; 3500 3501 return status; 3502 } 3503 3504 3505 status_t 3506 _user_get_next_thread_info(team_id team, int32 *userCookie, 3507 thread_info *userInfo) 3508 { 3509 status_t status; 3510 thread_info info; 3511 int32 cookie; 3512 3513 if (!IS_USER_ADDRESS(userCookie) || !IS_USER_ADDRESS(userInfo) 3514 || user_memcpy(&cookie, userCookie, sizeof(int32)) < B_OK) 3515 return B_BAD_ADDRESS; 3516 3517 status = _get_next_thread_info(team, &cookie, &info, sizeof(thread_info)); 3518 if (status < B_OK) 3519 return status; 3520 3521 if (user_memcpy(userCookie, &cookie, sizeof(int32)) < B_OK 3522 || user_memcpy(userInfo, &info, sizeof(thread_info)) < B_OK) 3523 return B_BAD_ADDRESS; 3524 3525 return status; 3526 } 3527 3528 3529 thread_id 3530 _user_find_thread(const char *userName) 3531 { 3532 char name[B_OS_NAME_LENGTH]; 3533 3534 if (userName == NULL) 3535 return find_thread(NULL); 3536 3537 if (!IS_USER_ADDRESS(userName) 3538 || user_strlcpy(name, userName, sizeof(name)) < B_OK) 3539 return B_BAD_ADDRESS; 3540 3541 return find_thread(name); 3542 } 3543 3544 3545 status_t 3546 _user_wait_for_thread(thread_id id, status_t *userReturnCode) 3547 { 3548 status_t returnCode; 3549 status_t status; 3550 3551 if (userReturnCode != NULL && !IS_USER_ADDRESS(userReturnCode)) 3552 return B_BAD_ADDRESS; 3553 3554 status = wait_for_thread_etc(id, B_CAN_INTERRUPT, 0, &returnCode); 3555 3556 if (status == B_OK && userReturnCode != NULL 3557 && user_memcpy(userReturnCode, &returnCode, sizeof(status_t)) < B_OK) { 3558 return B_BAD_ADDRESS; 3559 } 3560 3561 return syscall_restart_handle_post(status); 3562 } 3563 3564 3565 bool 3566 _user_has_data(thread_id thread) 3567 { 3568 return has_data(thread); 3569 } 3570 3571 3572 status_t 3573 _user_send_data(thread_id thread, int32 code, const void *buffer, 3574 size_t bufferSize) 3575 { 3576 if (!IS_USER_ADDRESS(buffer)) 3577 return B_BAD_ADDRESS; 3578 3579 return send_data_etc(thread, code, buffer, bufferSize, 3580 B_KILL_CAN_INTERRUPT); 3581 // supports userland buffers 3582 } 3583 3584 3585 status_t 3586 _user_receive_data(thread_id *_userSender, void *buffer, size_t bufferSize) 3587 { 3588 thread_id sender; 3589 status_t code; 3590 3591 if ((!IS_USER_ADDRESS(_userSender) && _userSender != NULL) 3592 || !IS_USER_ADDRESS(buffer)) 3593 return B_BAD_ADDRESS; 3594 3595 code = receive_data_etc(&sender, buffer, bufferSize, B_KILL_CAN_INTERRUPT); 3596 // supports userland buffers 3597 3598 if (_userSender != NULL) 3599 if (user_memcpy(_userSender, &sender, sizeof(thread_id)) < B_OK) 3600 return B_BAD_ADDRESS; 3601 3602 return code; 3603 } 3604 3605 3606 status_t 3607 _user_block_thread(uint32 flags, bigtime_t timeout) 3608 { 3609 syscall_restart_handle_timeout_pre(flags, timeout); 3610 flags |= B_CAN_INTERRUPT; 3611 3612 Thread* thread = thread_get_current_thread(); 3613 ThreadLocker threadLocker(thread); 3614 3615 // check, if already done 3616 if (thread->user_thread->wait_status <= 0) 3617 return thread->user_thread->wait_status; 3618 3619 // nope, so wait 3620 thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_OTHER, "user"); 3621 3622 threadLocker.Unlock(); 3623 3624 status_t status = thread_block_with_timeout(flags, timeout); 3625 3626 threadLocker.Lock(); 3627 3628 // Interruptions or timeouts can race with other threads unblocking us. 3629 // Favor a wake-up by another thread, i.e. if someone changed the wait 3630 // status, use that. 3631 status_t oldStatus = thread->user_thread->wait_status; 3632 if (oldStatus > 0) 3633 thread->user_thread->wait_status = status; 3634 else 3635 status = oldStatus; 3636 3637 threadLocker.Unlock(); 3638 3639 return syscall_restart_handle_timeout_post(status, timeout); 3640 } 3641 3642 3643 status_t 3644 _user_unblock_thread(thread_id threadID, status_t status) 3645 { 3646 status_t error = user_unblock_thread(threadID, status); 3647 3648 if (error == B_OK) 3649 scheduler_reschedule_if_necessary(); 3650 3651 return error; 3652 } 3653 3654 3655 status_t 3656 _user_unblock_threads(thread_id* userThreads, uint32 count, status_t status) 3657 { 3658 enum { 3659 MAX_USER_THREADS_TO_UNBLOCK = 128 3660 }; 3661 3662 if (userThreads == NULL || !IS_USER_ADDRESS(userThreads)) 3663 return B_BAD_ADDRESS; 3664 if (count > MAX_USER_THREADS_TO_UNBLOCK) 3665 return B_BAD_VALUE; 3666 3667 thread_id threads[MAX_USER_THREADS_TO_UNBLOCK]; 3668 if (user_memcpy(threads, userThreads, count * sizeof(thread_id)) != B_OK) 3669 return B_BAD_ADDRESS; 3670 3671 for (uint32 i = 0; i < count; i++) 3672 user_unblock_thread(threads[i], status); 3673 3674 scheduler_reschedule_if_necessary(); 3675 3676 return B_OK; 3677 } 3678 3679 3680 // TODO: the following two functions don't belong here 3681 3682 3683 int 3684 _user_getrlimit(int resource, struct rlimit *urlp) 3685 { 3686 struct rlimit rl; 3687 int ret; 3688 3689 if (urlp == NULL) 3690 return EINVAL; 3691 3692 if (!IS_USER_ADDRESS(urlp)) 3693 return B_BAD_ADDRESS; 3694 3695 ret = common_getrlimit(resource, &rl); 3696 3697 if (ret == 0) { 3698 ret = user_memcpy(urlp, &rl, sizeof(struct rlimit)); 3699 if (ret < 0) 3700 return ret; 3701 3702 return 0; 3703 } 3704 3705 return ret; 3706 } 3707 3708 3709 int 3710 _user_setrlimit(int resource, const struct rlimit *userResourceLimit) 3711 { 3712 struct rlimit resourceLimit; 3713 3714 if (userResourceLimit == NULL) 3715 return EINVAL; 3716 3717 if (!IS_USER_ADDRESS(userResourceLimit) 3718 || user_memcpy(&resourceLimit, userResourceLimit, 3719 sizeof(struct rlimit)) < B_OK) 3720 return B_BAD_ADDRESS; 3721 3722 return common_setrlimit(resource, &resourceLimit); 3723 } 3724