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_AS: 1311 rlp->rlim_cur = __HAIKU_ADDR_MAX; 1312 rlp->rlim_max = __HAIKU_ADDR_MAX; 1313 return B_OK; 1314 1315 case RLIMIT_CORE: 1316 rlp->rlim_cur = 0; 1317 rlp->rlim_max = 0; 1318 return B_OK; 1319 1320 case RLIMIT_DATA: 1321 rlp->rlim_cur = RLIM_INFINITY; 1322 rlp->rlim_max = RLIM_INFINITY; 1323 return B_OK; 1324 1325 case RLIMIT_NOFILE: 1326 case RLIMIT_NOVMON: 1327 return vfs_getrlimit(resource, rlp); 1328 1329 case RLIMIT_STACK: 1330 { 1331 rlp->rlim_cur = USER_MAIN_THREAD_STACK_SIZE; 1332 rlp->rlim_max = USER_MAIN_THREAD_STACK_SIZE; 1333 return B_OK; 1334 } 1335 1336 default: 1337 return EINVAL; 1338 } 1339 1340 return B_OK; 1341 } 1342 1343 1344 static status_t 1345 common_setrlimit(int resource, const struct rlimit * rlp) 1346 { 1347 if (!rlp) 1348 return B_BAD_ADDRESS; 1349 1350 switch (resource) { 1351 case RLIMIT_CORE: 1352 // We don't support core file, so allow settings to 0/0 only. 1353 if (rlp->rlim_cur != 0 || rlp->rlim_max != 0) 1354 return EINVAL; 1355 return B_OK; 1356 1357 case RLIMIT_NOFILE: 1358 case RLIMIT_NOVMON: 1359 return vfs_setrlimit(resource, rlp); 1360 1361 default: 1362 return EINVAL; 1363 } 1364 1365 return B_OK; 1366 } 1367 1368 1369 static status_t 1370 common_snooze_etc(bigtime_t timeout, clockid_t clockID, uint32 flags, 1371 bigtime_t* _remainingTime) 1372 { 1373 switch (clockID) { 1374 case CLOCK_REALTIME: 1375 // make sure the B_TIMEOUT_REAL_TIME_BASE flag is set and fall 1376 // through 1377 flags |= B_TIMEOUT_REAL_TIME_BASE; 1378 case CLOCK_MONOTONIC: 1379 { 1380 // Store the start time, for the case that we get interrupted and 1381 // need to return the remaining time. For absolute timeouts we can 1382 // still get he time later, if needed. 1383 bigtime_t startTime 1384 = _remainingTime != NULL && (flags & B_RELATIVE_TIMEOUT) != 0 1385 ? system_time() : 0; 1386 1387 Thread* thread = thread_get_current_thread(); 1388 1389 thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_SNOOZE, 1390 NULL); 1391 status_t status = thread_block_with_timeout(flags, timeout); 1392 1393 if (status == B_TIMED_OUT || status == B_WOULD_BLOCK) 1394 return B_OK; 1395 1396 // If interrupted, compute the remaining time, if requested. 1397 if (status == B_INTERRUPTED && _remainingTime != NULL) { 1398 if ((flags & B_RELATIVE_TIMEOUT) != 0) { 1399 *_remainingTime = std::max( 1400 startTime + timeout - system_time(), (bigtime_t)0); 1401 } else { 1402 bigtime_t now = (flags & B_TIMEOUT_REAL_TIME_BASE) != 0 1403 ? real_time_clock_usecs() : system_time(); 1404 *_remainingTime = std::max(timeout - now, (bigtime_t)0); 1405 } 1406 } 1407 1408 return status; 1409 } 1410 1411 case CLOCK_THREAD_CPUTIME_ID: 1412 // Waiting for ourselves to do something isn't particularly 1413 // productive. 1414 return B_BAD_VALUE; 1415 1416 case CLOCK_PROCESS_CPUTIME_ID: 1417 default: 1418 // We don't have to support those, but we are allowed to. Could be 1419 // done be creating a UserTimer on the fly with a custom UserEvent 1420 // that would just wake us up. 1421 return ENOTSUP; 1422 } 1423 } 1424 1425 1426 // #pragma mark - debugger calls 1427 1428 1429 static int 1430 make_thread_unreal(int argc, char **argv) 1431 { 1432 int32 id = -1; 1433 1434 if (argc > 2) { 1435 print_debugger_command_usage(argv[0]); 1436 return 0; 1437 } 1438 1439 if (argc > 1) 1440 id = strtoul(argv[1], NULL, 0); 1441 1442 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1443 Thread* thread = it.Next();) { 1444 if (id != -1 && thread->id != id) 1445 continue; 1446 1447 if (thread->priority > B_DISPLAY_PRIORITY) { 1448 scheduler_set_thread_priority(thread, B_NORMAL_PRIORITY); 1449 kprintf("thread %" B_PRId32 " made unreal\n", thread->id); 1450 } 1451 } 1452 1453 return 0; 1454 } 1455 1456 1457 static int 1458 set_thread_prio(int argc, char **argv) 1459 { 1460 int32 id; 1461 int32 prio; 1462 1463 if (argc > 3 || argc < 2) { 1464 print_debugger_command_usage(argv[0]); 1465 return 0; 1466 } 1467 1468 prio = strtoul(argv[1], NULL, 0); 1469 if (prio > THREAD_MAX_SET_PRIORITY) 1470 prio = THREAD_MAX_SET_PRIORITY; 1471 if (prio < THREAD_MIN_SET_PRIORITY) 1472 prio = THREAD_MIN_SET_PRIORITY; 1473 1474 if (argc > 2) 1475 id = strtoul(argv[2], NULL, 0); 1476 else 1477 id = thread_get_current_thread()->id; 1478 1479 bool found = false; 1480 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1481 Thread* thread = it.Next();) { 1482 if (thread->id != id) 1483 continue; 1484 scheduler_set_thread_priority(thread, prio); 1485 kprintf("thread %" B_PRId32 " set to priority %" B_PRId32 "\n", id, prio); 1486 found = true; 1487 break; 1488 } 1489 if (!found) 1490 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1491 1492 return 0; 1493 } 1494 1495 1496 static int 1497 make_thread_suspended(int argc, char **argv) 1498 { 1499 int32 id; 1500 1501 if (argc > 2) { 1502 print_debugger_command_usage(argv[0]); 1503 return 0; 1504 } 1505 1506 if (argc == 1) 1507 id = thread_get_current_thread()->id; 1508 else 1509 id = strtoul(argv[1], NULL, 0); 1510 1511 bool found = false; 1512 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1513 Thread* thread = it.Next();) { 1514 if (thread->id != id) 1515 continue; 1516 1517 Signal signal(SIGSTOP, SI_USER, B_OK, team_get_kernel_team()->id); 1518 send_signal_to_thread(thread, signal, B_DO_NOT_RESCHEDULE); 1519 1520 kprintf("thread %" B_PRId32 " suspended\n", id); 1521 found = true; 1522 break; 1523 } 1524 if (!found) 1525 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1526 1527 return 0; 1528 } 1529 1530 1531 static int 1532 make_thread_resumed(int argc, char **argv) 1533 { 1534 int32 id; 1535 1536 if (argc != 2) { 1537 print_debugger_command_usage(argv[0]); 1538 return 0; 1539 } 1540 1541 // force user to enter a thread id, as using 1542 // the current thread is usually not intended 1543 id = strtoul(argv[1], NULL, 0); 1544 1545 bool found = false; 1546 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1547 Thread* thread = it.Next();) { 1548 if (thread->id != id) 1549 continue; 1550 1551 if (thread->state == B_THREAD_SUSPENDED) { 1552 scheduler_enqueue_in_run_queue(thread); 1553 kprintf("thread %" B_PRId32 " resumed\n", thread->id); 1554 } 1555 found = true; 1556 break; 1557 } 1558 if (!found) 1559 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1560 1561 return 0; 1562 } 1563 1564 1565 static int 1566 drop_into_debugger(int argc, char **argv) 1567 { 1568 status_t err; 1569 int32 id; 1570 1571 if (argc > 2) { 1572 print_debugger_command_usage(argv[0]); 1573 return 0; 1574 } 1575 1576 if (argc == 1) 1577 id = thread_get_current_thread()->id; 1578 else 1579 id = strtoul(argv[1], NULL, 0); 1580 1581 err = _user_debug_thread(id); 1582 // TODO: This is a non-trivial syscall doing some locking, so this is 1583 // really nasty and may go seriously wrong. 1584 if (err) 1585 kprintf("drop failed\n"); 1586 else 1587 kprintf("thread %" B_PRId32 " dropped into user debugger\n", id); 1588 1589 return 0; 1590 } 1591 1592 1593 /*! Returns a user-readable string for a thread state. 1594 Only for use in the kernel debugger. 1595 */ 1596 static const char * 1597 state_to_text(Thread *thread, int32 state) 1598 { 1599 switch (state) { 1600 case B_THREAD_READY: 1601 return "ready"; 1602 1603 case B_THREAD_RUNNING: 1604 return "running"; 1605 1606 case B_THREAD_WAITING: 1607 { 1608 if (thread != NULL) { 1609 switch (thread->wait.type) { 1610 case THREAD_BLOCK_TYPE_SNOOZE: 1611 return "zzz"; 1612 1613 case THREAD_BLOCK_TYPE_SEMAPHORE: 1614 { 1615 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1616 if (sem == thread->msg.read_sem) 1617 return "receive"; 1618 break; 1619 } 1620 } 1621 } 1622 1623 return "waiting"; 1624 } 1625 1626 case B_THREAD_SUSPENDED: 1627 return "suspended"; 1628 1629 case THREAD_STATE_FREE_ON_RESCHED: 1630 return "death"; 1631 1632 default: 1633 return "UNKNOWN"; 1634 } 1635 } 1636 1637 1638 static void 1639 print_thread_list_table_head() 1640 { 1641 kprintf("%-*s id state wait for %-*s cpu pri %-*s team " 1642 "name\n", 1643 B_PRINTF_POINTER_WIDTH, "thread", B_PRINTF_POINTER_WIDTH, "object", 1644 B_PRINTF_POINTER_WIDTH, "stack"); 1645 } 1646 1647 1648 static void 1649 _dump_thread_info(Thread *thread, bool shortInfo) 1650 { 1651 if (shortInfo) { 1652 kprintf("%p %6" B_PRId32 " %-10s", thread, thread->id, 1653 state_to_text(thread, thread->state)); 1654 1655 // does it block on a semaphore or a condition variable? 1656 if (thread->state == B_THREAD_WAITING) { 1657 switch (thread->wait.type) { 1658 case THREAD_BLOCK_TYPE_SEMAPHORE: 1659 { 1660 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1661 if (sem == thread->msg.read_sem) 1662 kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); 1663 else { 1664 kprintf("sem %-*" B_PRId32, 1665 B_PRINTF_POINTER_WIDTH + 5, sem); 1666 } 1667 break; 1668 } 1669 1670 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1671 kprintf("cvar %p ", thread->wait.object); 1672 break; 1673 1674 case THREAD_BLOCK_TYPE_SNOOZE: 1675 kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); 1676 break; 1677 1678 case THREAD_BLOCK_TYPE_SIGNAL: 1679 kprintf("signal%*s", B_PRINTF_POINTER_WIDTH + 9, ""); 1680 break; 1681 1682 case THREAD_BLOCK_TYPE_MUTEX: 1683 kprintf("mutex %p ", thread->wait.object); 1684 break; 1685 1686 case THREAD_BLOCK_TYPE_RW_LOCK: 1687 kprintf("rwlock %p ", thread->wait.object); 1688 break; 1689 1690 case THREAD_BLOCK_TYPE_OTHER: 1691 kprintf("other%*s", B_PRINTF_POINTER_WIDTH + 10, ""); 1692 break; 1693 1694 default: 1695 kprintf("??? %p ", thread->wait.object); 1696 break; 1697 } 1698 } else 1699 kprintf("-%*s", B_PRINTF_POINTER_WIDTH + 14, ""); 1700 1701 // on which CPU does it run? 1702 if (thread->cpu) 1703 kprintf("%2d", thread->cpu->cpu_num); 1704 else 1705 kprintf(" -"); 1706 1707 kprintf("%4" B_PRId32 " %p%5" B_PRId32 " %s\n", thread->priority, 1708 (void *)thread->kernel_stack_base, thread->team->id, 1709 thread->name != NULL ? thread->name : "<NULL>"); 1710 1711 return; 1712 } 1713 1714 // print the long info 1715 1716 struct thread_death_entry *death = NULL; 1717 1718 kprintf("THREAD: %p\n", thread); 1719 kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", thread->id, 1720 thread->id); 1721 kprintf("serial_number: %" B_PRId64 "\n", thread->serial_number); 1722 kprintf("name: \"%s\"\n", thread->name); 1723 kprintf("hash_next: %p\nteam_next: %p\n", 1724 thread->hash_next, thread->team_next); 1725 kprintf("priority: %" B_PRId32 " (I/O: %" B_PRId32 ")\n", 1726 thread->priority, thread->io_priority); 1727 kprintf("state: %s\n", state_to_text(thread, thread->state)); 1728 kprintf("cpu: %p ", thread->cpu); 1729 if (thread->cpu) 1730 kprintf("(%d)\n", thread->cpu->cpu_num); 1731 else 1732 kprintf("\n"); 1733 kprintf("sig_pending: %#" B_PRIx64 " (blocked: %#" B_PRIx64 1734 ", before sigsuspend(): %#" B_PRIx64 ")\n", 1735 (int64)thread->ThreadPendingSignals(), 1736 (int64)thread->sig_block_mask, 1737 (int64)thread->sigsuspend_original_unblocked_mask); 1738 kprintf("in_kernel: %d\n", thread->in_kernel); 1739 1740 if (thread->state == B_THREAD_WAITING) { 1741 kprintf("waiting for: "); 1742 1743 switch (thread->wait.type) { 1744 case THREAD_BLOCK_TYPE_SEMAPHORE: 1745 { 1746 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1747 if (sem == thread->msg.read_sem) 1748 kprintf("data\n"); 1749 else 1750 kprintf("semaphore %" B_PRId32 "\n", sem); 1751 break; 1752 } 1753 1754 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1755 kprintf("condition variable %p\n", thread->wait.object); 1756 break; 1757 1758 case THREAD_BLOCK_TYPE_SNOOZE: 1759 kprintf("snooze()\n"); 1760 break; 1761 1762 case THREAD_BLOCK_TYPE_SIGNAL: 1763 kprintf("signal\n"); 1764 break; 1765 1766 case THREAD_BLOCK_TYPE_MUTEX: 1767 kprintf("mutex %p\n", thread->wait.object); 1768 break; 1769 1770 case THREAD_BLOCK_TYPE_RW_LOCK: 1771 kprintf("rwlock %p\n", thread->wait.object); 1772 break; 1773 1774 case THREAD_BLOCK_TYPE_OTHER: 1775 kprintf("other (%s)\n", (char*)thread->wait.object); 1776 break; 1777 1778 default: 1779 kprintf("unknown (%p)\n", thread->wait.object); 1780 break; 1781 } 1782 } 1783 1784 kprintf("fault_handler: %p\n", (void *)thread->fault_handler); 1785 kprintf("team: %p, \"%s\"\n", thread->team, 1786 thread->team->Name()); 1787 kprintf(" exit.sem: %" B_PRId32 "\n", thread->exit.sem); 1788 kprintf(" exit.status: %#" B_PRIx32 " (%s)\n", thread->exit.status, 1789 strerror(thread->exit.status)); 1790 kprintf(" exit.waiters:\n"); 1791 while ((death = (struct thread_death_entry*)list_get_next_item( 1792 &thread->exit.waiters, death)) != NULL) { 1793 kprintf("\t%p (thread %" B_PRId32 ")\n", death, death->thread); 1794 } 1795 1796 kprintf("kernel_stack_area: %" B_PRId32 "\n", thread->kernel_stack_area); 1797 kprintf("kernel_stack_base: %p\n", (void *)thread->kernel_stack_base); 1798 kprintf("user_stack_area: %" B_PRId32 "\n", thread->user_stack_area); 1799 kprintf("user_stack_base: %p\n", (void *)thread->user_stack_base); 1800 kprintf("user_local_storage: %p\n", (void *)thread->user_local_storage); 1801 kprintf("user_thread: %p\n", (void *)thread->user_thread); 1802 kprintf("kernel_errno: %#x (%s)\n", thread->kernel_errno, 1803 strerror(thread->kernel_errno)); 1804 kprintf("kernel_time: %" B_PRId64 "\n", thread->kernel_time); 1805 kprintf("user_time: %" B_PRId64 "\n", thread->user_time); 1806 kprintf("flags: 0x%" B_PRIx32 "\n", thread->flags); 1807 kprintf("architecture dependant section:\n"); 1808 arch_thread_dump_info(&thread->arch_info); 1809 kprintf("scheduler data:\n"); 1810 scheduler_dump_thread_data(thread); 1811 } 1812 1813 1814 static int 1815 dump_thread_info(int argc, char **argv) 1816 { 1817 bool shortInfo = false; 1818 int argi = 1; 1819 if (argi < argc && strcmp(argv[argi], "-s") == 0) { 1820 shortInfo = true; 1821 print_thread_list_table_head(); 1822 argi++; 1823 } 1824 1825 if (argi == argc) { 1826 _dump_thread_info(thread_get_current_thread(), shortInfo); 1827 return 0; 1828 } 1829 1830 for (; argi < argc; argi++) { 1831 const char *name = argv[argi]; 1832 ulong arg = strtoul(name, NULL, 0); 1833 1834 if (IS_KERNEL_ADDRESS(arg)) { 1835 // semi-hack 1836 _dump_thread_info((Thread *)arg, shortInfo); 1837 continue; 1838 } 1839 1840 // walk through the thread list, trying to match name or id 1841 bool found = false; 1842 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1843 Thread* thread = it.Next();) { 1844 if (!strcmp(name, thread->name) || thread->id == (thread_id)arg) { 1845 _dump_thread_info(thread, shortInfo); 1846 found = true; 1847 break; 1848 } 1849 } 1850 1851 if (!found) 1852 kprintf("thread \"%s\" (%" B_PRId32 ") doesn't exist!\n", name, (thread_id)arg); 1853 } 1854 1855 return 0; 1856 } 1857 1858 1859 static int 1860 dump_thread_list(int argc, char **argv) 1861 { 1862 bool realTimeOnly = false; 1863 bool calling = false; 1864 const char *callSymbol = NULL; 1865 addr_t callStart = 0; 1866 addr_t callEnd = 0; 1867 int32 requiredState = 0; 1868 team_id team = -1; 1869 sem_id sem = -1; 1870 1871 if (!strcmp(argv[0], "realtime")) 1872 realTimeOnly = true; 1873 else if (!strcmp(argv[0], "ready")) 1874 requiredState = B_THREAD_READY; 1875 else if (!strcmp(argv[0], "running")) 1876 requiredState = B_THREAD_RUNNING; 1877 else if (!strcmp(argv[0], "waiting")) { 1878 requiredState = B_THREAD_WAITING; 1879 1880 if (argc > 1) { 1881 sem = strtoul(argv[1], NULL, 0); 1882 if (sem == 0) 1883 kprintf("ignoring invalid semaphore argument.\n"); 1884 } 1885 } else if (!strcmp(argv[0], "calling")) { 1886 if (argc < 2) { 1887 kprintf("Need to give a symbol name or start and end arguments.\n"); 1888 return 0; 1889 } else if (argc == 3) { 1890 callStart = parse_expression(argv[1]); 1891 callEnd = parse_expression(argv[2]); 1892 } else 1893 callSymbol = argv[1]; 1894 1895 calling = true; 1896 } else if (argc > 1) { 1897 team = strtoul(argv[1], NULL, 0); 1898 if (team == 0) 1899 kprintf("ignoring invalid team argument.\n"); 1900 } 1901 1902 print_thread_list_table_head(); 1903 1904 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1905 Thread* thread = it.Next();) { 1906 // filter out threads not matching the search criteria 1907 if ((requiredState && thread->state != requiredState) 1908 || (calling && !arch_debug_contains_call(thread, callSymbol, 1909 callStart, callEnd)) 1910 || (sem > 0 && get_thread_wait_sem(thread) != sem) 1911 || (team > 0 && thread->team->id != team) 1912 || (realTimeOnly && thread->priority < B_REAL_TIME_DISPLAY_PRIORITY)) 1913 continue; 1914 1915 _dump_thread_info(thread, true); 1916 } 1917 return 0; 1918 } 1919 1920 1921 // #pragma mark - private kernel API 1922 1923 1924 void 1925 thread_exit(void) 1926 { 1927 cpu_status state; 1928 Thread* thread = thread_get_current_thread(); 1929 Team* team = thread->team; 1930 Team* kernelTeam = team_get_kernel_team(); 1931 status_t status; 1932 struct thread_debug_info debugInfo; 1933 team_id teamID = team->id; 1934 1935 TRACE(("thread %" B_PRId32 " exiting w/return code %#" B_PRIx32 "\n", 1936 thread->id, thread->exit.status)); 1937 1938 if (!are_interrupts_enabled()) 1939 panic("thread_exit() called with interrupts disabled!\n"); 1940 1941 // boost our priority to get this over with 1942 scheduler_set_thread_priority(thread, B_URGENT_DISPLAY_PRIORITY); 1943 1944 if (team != kernelTeam) { 1945 // Delete all user timers associated with the thread. 1946 ThreadLocker threadLocker(thread); 1947 thread->DeleteUserTimers(false); 1948 1949 // detach the thread's user thread 1950 user_thread* userThread = thread->user_thread; 1951 thread->user_thread = NULL; 1952 1953 threadLocker.Unlock(); 1954 1955 // Delete the thread's user thread, if it's not the main thread. If it 1956 // is, we can save the work, since it will be deleted with the team's 1957 // address space. 1958 if (thread != team->main_thread) 1959 team_free_user_thread(team, userThread); 1960 } 1961 1962 // remember the user stack area -- we will delete it below 1963 area_id userStackArea = -1; 1964 if (team->address_space != NULL && thread->user_stack_area >= 0) { 1965 userStackArea = thread->user_stack_area; 1966 thread->user_stack_area = -1; 1967 } 1968 1969 struct job_control_entry *death = NULL; 1970 struct thread_death_entry* threadDeathEntry = NULL; 1971 bool deleteTeam = false; 1972 port_id debuggerPort = -1; 1973 1974 if (team != kernelTeam) { 1975 user_debug_thread_exiting(thread); 1976 1977 if (team->main_thread == thread) { 1978 // The main thread is exiting. Shut down the whole team. 1979 deleteTeam = true; 1980 1981 // kill off all other threads and the user debugger facilities 1982 debuggerPort = team_shutdown_team(team); 1983 1984 // acquire necessary locks, which are: process group lock, kernel 1985 // team lock, parent team lock, and the team lock 1986 team->LockProcessGroup(); 1987 kernelTeam->Lock(); 1988 team->LockTeamAndParent(true); 1989 } else { 1990 threadDeathEntry 1991 = (thread_death_entry*)malloc(sizeof(thread_death_entry)); 1992 1993 // acquire necessary locks, which are: kernel team lock and the team 1994 // lock 1995 kernelTeam->Lock(); 1996 team->Lock(); 1997 } 1998 1999 ThreadLocker threadLocker(thread); 2000 2001 state = disable_interrupts(); 2002 2003 // swap address spaces, to make sure we're running on the kernel's pgdir 2004 vm_swap_address_space(team->address_space, VMAddressSpace::Kernel()); 2005 2006 WriteSpinLocker teamLocker(thread->team_lock); 2007 SpinLocker threadCreationLocker(gThreadCreationLock); 2008 // removing the thread and putting its death entry to the parent 2009 // team needs to be an atomic operation 2010 2011 // remember how long this thread lasted 2012 bigtime_t now = system_time(); 2013 2014 InterruptsSpinLocker signalLocker(kernelTeam->signal_lock); 2015 SpinLocker teamTimeLocker(kernelTeam->time_lock); 2016 SpinLocker threadTimeLocker(thread->time_lock); 2017 2018 thread->kernel_time += now - thread->last_time; 2019 thread->last_time = now; 2020 2021 team->dead_threads_kernel_time += thread->kernel_time; 2022 team->dead_threads_user_time += thread->user_time; 2023 2024 // stop/update thread/team CPU time user timers 2025 if (thread->HasActiveCPUTimeUserTimers() 2026 || team->HasActiveCPUTimeUserTimers()) { 2027 user_timer_stop_cpu_timers(thread, NULL); 2028 } 2029 2030 // deactivate CPU time user timers for the thread 2031 if (thread->HasActiveCPUTimeUserTimers()) 2032 thread->DeactivateCPUTimeUserTimers(); 2033 2034 threadTimeLocker.Unlock(); 2035 2036 // put the thread into the kernel team until it dies 2037 remove_thread_from_team(team, thread); 2038 insert_thread_into_team(kernelTeam, thread); 2039 2040 teamTimeLocker.Unlock(); 2041 signalLocker.Unlock(); 2042 2043 teamLocker.Unlock(); 2044 2045 if (team->death_entry != NULL) { 2046 if (--team->death_entry->remaining_threads == 0) 2047 team->death_entry->condition.NotifyOne(); 2048 } 2049 2050 if (deleteTeam) { 2051 Team* parent = team->parent; 2052 2053 // Set the team job control state to "dead" and detach the job 2054 // control entry from our team struct. 2055 team_set_job_control_state(team, JOB_CONTROL_STATE_DEAD, NULL); 2056 death = team->job_control_entry; 2057 team->job_control_entry = NULL; 2058 2059 if (death != NULL) { 2060 death->InitDeadState(); 2061 2062 // team_set_job_control_state() already moved our entry 2063 // into the parent's list. We just check the soft limit of 2064 // death entries. 2065 if (parent->dead_children.count > MAX_DEAD_CHILDREN) { 2066 death = parent->dead_children.entries.RemoveHead(); 2067 parent->dead_children.count--; 2068 } else 2069 death = NULL; 2070 } 2071 2072 threadCreationLocker.Unlock(); 2073 restore_interrupts(state); 2074 2075 threadLocker.Unlock(); 2076 2077 // Get a temporary reference to the team's process group 2078 // -- team_remove_team() removes the team from the group, which 2079 // might destroy it otherwise and we wouldn't be able to unlock it. 2080 ProcessGroup* group = team->group; 2081 group->AcquireReference(); 2082 2083 pid_t foregroundGroupToSignal; 2084 team_remove_team(team, foregroundGroupToSignal); 2085 2086 // unlock everything but the parent team 2087 team->Unlock(); 2088 if (parent != kernelTeam) 2089 kernelTeam->Unlock(); 2090 group->Unlock(); 2091 group->ReleaseReference(); 2092 2093 // Send SIGCHLD to the parent as long as we still have its lock. 2094 // This makes job control state change + signalling atomic. 2095 Signal childSignal(SIGCHLD, team->exit.reason, B_OK, team->id); 2096 if (team->exit.reason == CLD_EXITED) { 2097 childSignal.SetStatus(team->exit.status); 2098 } else { 2099 childSignal.SetStatus(team->exit.signal); 2100 childSignal.SetSendingUser(team->exit.signaling_user); 2101 } 2102 send_signal_to_team(parent, childSignal, B_DO_NOT_RESCHEDULE); 2103 2104 // also unlock the parent 2105 parent->Unlock(); 2106 2107 // If the team was a session leader with controlling TTY, we have 2108 // to send SIGHUP to the foreground process group. 2109 if (foregroundGroupToSignal >= 0) { 2110 Signal groupSignal(SIGHUP, SI_USER, B_OK, team->id); 2111 send_signal_to_process_group(foregroundGroupToSignal, 2112 groupSignal, B_DO_NOT_RESCHEDULE); 2113 } 2114 } else { 2115 // The thread is not the main thread. We store a thread death entry 2116 // for it, unless someone is already waiting for it. 2117 if (threadDeathEntry != NULL 2118 && list_is_empty(&thread->exit.waiters)) { 2119 threadDeathEntry->thread = thread->id; 2120 threadDeathEntry->status = thread->exit.status; 2121 2122 // add entry -- remove an old one, if we hit the limit 2123 list_add_item(&team->dead_threads, threadDeathEntry); 2124 team->dead_threads_count++; 2125 threadDeathEntry = NULL; 2126 2127 if (team->dead_threads_count > MAX_DEAD_THREADS) { 2128 threadDeathEntry 2129 = (thread_death_entry*)list_remove_head_item( 2130 &team->dead_threads); 2131 team->dead_threads_count--; 2132 } 2133 } 2134 2135 threadCreationLocker.Unlock(); 2136 restore_interrupts(state); 2137 2138 threadLocker.Unlock(); 2139 team->Unlock(); 2140 kernelTeam->Unlock(); 2141 } 2142 2143 TRACE(("thread_exit: thread %" B_PRId32 " now a kernel thread!\n", 2144 thread->id)); 2145 } 2146 2147 free(threadDeathEntry); 2148 2149 // delete the team if we're its main thread 2150 if (deleteTeam) { 2151 team_delete_team(team, debuggerPort); 2152 2153 // we need to delete any death entry that made it to here 2154 delete death; 2155 } 2156 2157 ThreadLocker threadLocker(thread); 2158 2159 state = disable_interrupts(); 2160 SpinLocker threadCreationLocker(gThreadCreationLock); 2161 2162 // mark invisible in global hash/list, so it's no longer accessible 2163 SpinLocker threadHashLocker(sThreadHashLock); 2164 thread->visible = false; 2165 sUsedThreads--; 2166 threadHashLocker.Unlock(); 2167 2168 // Stop debugging for this thread 2169 SpinLocker threadDebugInfoLocker(thread->debug_info.lock); 2170 debugInfo = thread->debug_info; 2171 clear_thread_debug_info(&thread->debug_info, true); 2172 threadDebugInfoLocker.Unlock(); 2173 2174 // Remove the select infos. We notify them a little later. 2175 select_info* selectInfos = thread->select_infos; 2176 thread->select_infos = NULL; 2177 2178 threadCreationLocker.Unlock(); 2179 restore_interrupts(state); 2180 2181 threadLocker.Unlock(); 2182 2183 destroy_thread_debug_info(&debugInfo); 2184 2185 // notify select infos 2186 select_info* info = selectInfos; 2187 while (info != NULL) { 2188 select_sync* sync = info->sync; 2189 2190 notify_select_events(info, B_EVENT_INVALID); 2191 info = info->next; 2192 put_select_sync(sync); 2193 } 2194 2195 // notify listeners 2196 sNotificationService.Notify(THREAD_REMOVED, thread); 2197 2198 // shutdown the thread messaging 2199 2200 status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0); 2201 if (status == B_WOULD_BLOCK) { 2202 // there is data waiting for us, so let us eat it 2203 thread_id sender; 2204 2205 delete_sem(thread->msg.write_sem); 2206 // first, let's remove all possibly waiting writers 2207 receive_data_etc(&sender, NULL, 0, B_RELATIVE_TIMEOUT); 2208 } else { 2209 // we probably own the semaphore here, and we're the last to do so 2210 delete_sem(thread->msg.write_sem); 2211 } 2212 // now we can safely remove the msg.read_sem 2213 delete_sem(thread->msg.read_sem); 2214 2215 // fill all death entries and delete the sem that others will use to wait 2216 // for us 2217 { 2218 sem_id cachedExitSem = thread->exit.sem; 2219 2220 ThreadLocker threadLocker(thread); 2221 2222 // make sure no one will grab this semaphore again 2223 thread->exit.sem = -1; 2224 2225 // fill all death entries 2226 thread_death_entry* entry = NULL; 2227 while ((entry = (thread_death_entry*)list_get_next_item( 2228 &thread->exit.waiters, entry)) != NULL) { 2229 entry->status = thread->exit.status; 2230 } 2231 2232 threadLocker.Unlock(); 2233 2234 delete_sem(cachedExitSem); 2235 } 2236 2237 // delete the user stack, if this was a user thread 2238 if (!deleteTeam && userStackArea >= 0) { 2239 // We postponed deleting the user stack until now, since this way all 2240 // notifications for the thread's death are out already and all other 2241 // threads waiting for this thread's death and some object on its stack 2242 // will wake up before we (try to) delete the stack area. Of most 2243 // relevance is probably the case where this is the main thread and 2244 // other threads use objects on its stack -- so we want them terminated 2245 // first. 2246 // When the team is deleted, all areas are deleted anyway, so we don't 2247 // need to do that explicitly in that case. 2248 vm_delete_area(teamID, userStackArea, true); 2249 } 2250 2251 // notify the debugger 2252 if (teamID != kernelTeam->id) 2253 user_debug_thread_deleted(teamID, thread->id); 2254 2255 // enqueue in the undertaker list and reschedule for the last time 2256 UndertakerEntry undertakerEntry(thread, teamID); 2257 2258 disable_interrupts(); 2259 2260 SpinLocker schedulerLocker(thread->scheduler_lock); 2261 2262 SpinLocker undertakerLocker(sUndertakerLock); 2263 sUndertakerEntries.Add(&undertakerEntry); 2264 sUndertakerCondition.NotifyOne(); 2265 undertakerLocker.Unlock(); 2266 2267 scheduler_reschedule(THREAD_STATE_FREE_ON_RESCHED); 2268 2269 panic("never can get here\n"); 2270 } 2271 2272 2273 /*! Called in the interrupt handler code when a thread enters 2274 the kernel for any reason. 2275 Only tracks time for now. 2276 Interrupts are disabled. 2277 */ 2278 void 2279 thread_at_kernel_entry(bigtime_t now) 2280 { 2281 Thread *thread = thread_get_current_thread(); 2282 2283 TRACE(("thread_at_kernel_entry: entry thread %" B_PRId32 "\n", thread->id)); 2284 2285 // track user time 2286 SpinLocker threadTimeLocker(thread->time_lock); 2287 thread->user_time += now - thread->last_time; 2288 thread->last_time = now; 2289 thread->in_kernel = true; 2290 threadTimeLocker.Unlock(); 2291 } 2292 2293 2294 /*! Called whenever a thread exits kernel space to user space. 2295 Tracks time, handles signals, ... 2296 Interrupts must be enabled. When the function returns, interrupts will be 2297 disabled. 2298 The function may not return. This e.g. happens when the thread has received 2299 a deadly signal. 2300 */ 2301 void 2302 thread_at_kernel_exit(void) 2303 { 2304 Thread *thread = thread_get_current_thread(); 2305 2306 TRACE(("thread_at_kernel_exit: exit thread %" B_PRId32 "\n", thread->id)); 2307 2308 handle_signals(thread); 2309 2310 disable_interrupts(); 2311 2312 // track kernel time 2313 bigtime_t now = system_time(); 2314 SpinLocker threadTimeLocker(thread->time_lock); 2315 thread->in_kernel = false; 2316 thread->kernel_time += now - thread->last_time; 2317 thread->last_time = now; 2318 } 2319 2320 2321 /*! The quick version of thread_kernel_exit(), in case no signals are pending 2322 and no debugging shall be done. 2323 Interrupts must be disabled. 2324 */ 2325 void 2326 thread_at_kernel_exit_no_signals(void) 2327 { 2328 Thread *thread = thread_get_current_thread(); 2329 2330 TRACE(("thread_at_kernel_exit_no_signals: exit thread %" B_PRId32 "\n", 2331 thread->id)); 2332 2333 // track kernel time 2334 bigtime_t now = system_time(); 2335 SpinLocker threadTimeLocker(thread->time_lock); 2336 thread->in_kernel = false; 2337 thread->kernel_time += now - thread->last_time; 2338 thread->last_time = now; 2339 } 2340 2341 2342 void 2343 thread_reset_for_exec(void) 2344 { 2345 Thread* thread = thread_get_current_thread(); 2346 2347 ThreadLocker threadLocker(thread); 2348 2349 // delete user-defined timers 2350 thread->DeleteUserTimers(true); 2351 2352 // cancel pre-defined timer 2353 if (UserTimer* timer = thread->UserTimerFor(USER_TIMER_REAL_TIME_ID)) 2354 timer->Cancel(); 2355 2356 // reset user_thread and user stack 2357 thread->user_thread = NULL; 2358 thread->user_stack_area = -1; 2359 thread->user_stack_base = 0; 2360 thread->user_stack_size = 0; 2361 2362 // reset signals 2363 thread->ResetSignalsOnExec(); 2364 2365 // reset thread CPU time clock 2366 InterruptsSpinLocker timeLocker(thread->time_lock); 2367 thread->cpu_clock_offset = -thread->CPUTime(false); 2368 } 2369 2370 2371 thread_id 2372 allocate_thread_id() 2373 { 2374 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2375 2376 // find the next unused ID 2377 thread_id id; 2378 do { 2379 id = sNextThreadID++; 2380 2381 // deal with integer overflow 2382 if (sNextThreadID < 0) 2383 sNextThreadID = 2; 2384 2385 // check whether the ID is already in use 2386 } while (sThreadHash.Lookup(id, false) != NULL); 2387 2388 return id; 2389 } 2390 2391 2392 thread_id 2393 peek_next_thread_id() 2394 { 2395 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2396 return sNextThreadID; 2397 } 2398 2399 2400 /*! Yield the CPU to other threads. 2401 Thread will continue to run, if there's no other thread in ready 2402 state, and if it has a higher priority than the other ready threads, it 2403 still has a good chance to continue. 2404 */ 2405 void 2406 thread_yield(void) 2407 { 2408 Thread *thread = thread_get_current_thread(); 2409 if (thread == NULL) 2410 return; 2411 2412 InterruptsSpinLocker _(thread->scheduler_lock); 2413 2414 thread->has_yielded = true; 2415 scheduler_reschedule(B_THREAD_READY); 2416 } 2417 2418 2419 void 2420 thread_map(void (*function)(Thread* thread, void* data), void* data) 2421 { 2422 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2423 2424 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 2425 Thread* thread = it.Next();) { 2426 function(thread, data); 2427 } 2428 } 2429 2430 2431 /*! Kernel private thread creation function. 2432 */ 2433 thread_id 2434 spawn_kernel_thread_etc(thread_func function, const char *name, int32 priority, 2435 void *arg, team_id team) 2436 { 2437 return thread_create_thread( 2438 ThreadCreationAttributes(function, name, priority, arg, team), 2439 true); 2440 } 2441 2442 2443 status_t 2444 wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, 2445 status_t *_returnCode) 2446 { 2447 if (id < 0) 2448 return B_BAD_THREAD_ID; 2449 2450 // get the thread, queue our death entry, and fetch the semaphore we have to 2451 // wait on 2452 sem_id exitSem = B_BAD_THREAD_ID; 2453 struct thread_death_entry death; 2454 2455 Thread* thread = Thread::GetAndLock(id); 2456 if (thread != NULL) { 2457 // remember the semaphore we have to wait on and place our death entry 2458 exitSem = thread->exit.sem; 2459 if (exitSem >= 0) 2460 list_add_link_to_head(&thread->exit.waiters, &death); 2461 2462 thread->UnlockAndReleaseReference(); 2463 2464 if (exitSem < 0) 2465 return B_BAD_THREAD_ID; 2466 } else { 2467 // we couldn't find this thread -- maybe it's already gone, and we'll 2468 // find its death entry in our team 2469 Team* team = thread_get_current_thread()->team; 2470 TeamLocker teamLocker(team); 2471 2472 // check the child death entries first (i.e. main threads of child 2473 // teams) 2474 bool deleteEntry; 2475 job_control_entry* freeDeath 2476 = team_get_death_entry(team, id, &deleteEntry); 2477 if (freeDeath != NULL) { 2478 death.status = freeDeath->status; 2479 if (deleteEntry) 2480 delete freeDeath; 2481 } else { 2482 // check the thread death entries of the team (non-main threads) 2483 thread_death_entry* threadDeathEntry = NULL; 2484 while ((threadDeathEntry = (thread_death_entry*)list_get_next_item( 2485 &team->dead_threads, threadDeathEntry)) != NULL) { 2486 if (threadDeathEntry->thread == id) { 2487 list_remove_item(&team->dead_threads, threadDeathEntry); 2488 team->dead_threads_count--; 2489 death.status = threadDeathEntry->status; 2490 free(threadDeathEntry); 2491 break; 2492 } 2493 } 2494 2495 if (threadDeathEntry == NULL) 2496 return B_BAD_THREAD_ID; 2497 } 2498 2499 // we found the thread's death entry in our team 2500 if (_returnCode) 2501 *_returnCode = death.status; 2502 2503 return B_OK; 2504 } 2505 2506 // we need to wait for the death of the thread 2507 2508 resume_thread(id); 2509 // make sure we don't wait forever on a suspended thread 2510 2511 status_t status = acquire_sem_etc(exitSem, 1, flags, timeout); 2512 2513 if (status == B_OK) { 2514 // this should never happen as the thread deletes the semaphore on exit 2515 panic("could acquire exit_sem for thread %" B_PRId32 "\n", id); 2516 } else if (status == B_BAD_SEM_ID) { 2517 // this is the way the thread normally exits 2518 status = B_OK; 2519 } else { 2520 // We were probably interrupted or the timeout occurred; we need to 2521 // remove our death entry now. 2522 thread = Thread::GetAndLock(id); 2523 if (thread != NULL) { 2524 list_remove_link(&death); 2525 thread->UnlockAndReleaseReference(); 2526 } else { 2527 // The thread is already gone, so we need to wait uninterruptibly 2528 // for its exit semaphore to make sure our death entry stays valid. 2529 // It won't take long, since the thread is apparently already in the 2530 // middle of the cleanup. 2531 acquire_sem(exitSem); 2532 status = B_OK; 2533 } 2534 } 2535 2536 if (status == B_OK && _returnCode != NULL) 2537 *_returnCode = death.status; 2538 2539 return status; 2540 } 2541 2542 2543 status_t 2544 select_thread(int32 id, struct select_info* info, bool kernel) 2545 { 2546 // get and lock the thread 2547 Thread* thread = Thread::GetAndLock(id); 2548 if (thread == NULL) 2549 return B_BAD_THREAD_ID; 2550 BReference<Thread> threadReference(thread, true); 2551 ThreadLocker threadLocker(thread, true); 2552 2553 // We support only B_EVENT_INVALID at the moment. 2554 info->selected_events &= B_EVENT_INVALID; 2555 2556 // add info to list 2557 if (info->selected_events != 0) { 2558 info->next = thread->select_infos; 2559 thread->select_infos = info; 2560 2561 // we need a sync reference 2562 atomic_add(&info->sync->ref_count, 1); 2563 } 2564 2565 return B_OK; 2566 } 2567 2568 2569 status_t 2570 deselect_thread(int32 id, struct select_info* info, bool kernel) 2571 { 2572 // get and lock the thread 2573 Thread* thread = Thread::GetAndLock(id); 2574 if (thread == NULL) 2575 return B_BAD_THREAD_ID; 2576 BReference<Thread> threadReference(thread, true); 2577 ThreadLocker threadLocker(thread, true); 2578 2579 // remove info from list 2580 select_info** infoLocation = &thread->select_infos; 2581 while (*infoLocation != NULL && *infoLocation != info) 2582 infoLocation = &(*infoLocation)->next; 2583 2584 if (*infoLocation != info) 2585 return B_OK; 2586 2587 *infoLocation = info->next; 2588 2589 threadLocker.Unlock(); 2590 2591 // surrender sync reference 2592 put_select_sync(info->sync); 2593 2594 return B_OK; 2595 } 2596 2597 2598 int32 2599 thread_max_threads(void) 2600 { 2601 return sMaxThreads; 2602 } 2603 2604 2605 int32 2606 thread_used_threads(void) 2607 { 2608 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2609 return sUsedThreads; 2610 } 2611 2612 2613 /*! Returns a user-readable string for a thread state. 2614 Only for use in the kernel debugger. 2615 */ 2616 const char* 2617 thread_state_to_text(Thread* thread, int32 state) 2618 { 2619 return state_to_text(thread, state); 2620 } 2621 2622 2623 int32 2624 thread_get_io_priority(thread_id id) 2625 { 2626 Thread* thread = Thread::GetAndLock(id); 2627 if (thread == NULL) 2628 return B_BAD_THREAD_ID; 2629 BReference<Thread> threadReference(thread, true); 2630 ThreadLocker threadLocker(thread, true); 2631 2632 int32 priority = thread->io_priority; 2633 if (priority < 0) { 2634 // negative I/O priority means using the (CPU) priority 2635 priority = thread->priority; 2636 } 2637 2638 return priority; 2639 } 2640 2641 2642 void 2643 thread_set_io_priority(int32 priority) 2644 { 2645 Thread* thread = thread_get_current_thread(); 2646 ThreadLocker threadLocker(thread); 2647 2648 thread->io_priority = priority; 2649 } 2650 2651 2652 status_t 2653 thread_init(kernel_args *args) 2654 { 2655 TRACE(("thread_init: entry\n")); 2656 2657 // create the thread hash table 2658 new(&sThreadHash) ThreadHashTable(); 2659 if (sThreadHash.Init(128) != B_OK) 2660 panic("thread_init(): failed to init thread hash table!"); 2661 2662 // create the thread structure object cache 2663 sThreadCache = create_object_cache("threads", sizeof(Thread), 16, NULL, 2664 NULL, NULL); 2665 // Note: The x86 port requires 16 byte alignment of thread structures. 2666 if (sThreadCache == NULL) 2667 panic("thread_init(): failed to allocate thread object cache!"); 2668 2669 if (arch_thread_init(args) < B_OK) 2670 panic("arch_thread_init() failed!\n"); 2671 2672 // skip all thread IDs including B_SYSTEM_TEAM, which is reserved 2673 sNextThreadID = B_SYSTEM_TEAM + 1; 2674 2675 // create an idle thread for each cpu 2676 for (uint32 i = 0; i < args->num_cpus; i++) { 2677 Thread *thread; 2678 area_info info; 2679 char name[64]; 2680 2681 sprintf(name, "idle thread %" B_PRIu32, i + 1); 2682 thread = new(&sIdleThreads[i]) Thread(name, 2683 i == 0 ? team_get_kernel_team_id() : -1, &gCPU[i]); 2684 if (thread == NULL || thread->Init(true) != B_OK) { 2685 panic("error creating idle thread struct\n"); 2686 return B_NO_MEMORY; 2687 } 2688 2689 gCPU[i].running_thread = thread; 2690 2691 thread->team = team_get_kernel_team(); 2692 thread->priority = B_IDLE_PRIORITY; 2693 thread->state = B_THREAD_RUNNING; 2694 sprintf(name, "idle thread %" B_PRIu32 " kstack", i + 1); 2695 thread->kernel_stack_area = find_area(name); 2696 2697 if (get_area_info(thread->kernel_stack_area, &info) != B_OK) 2698 panic("error finding idle kstack area\n"); 2699 2700 thread->kernel_stack_base = (addr_t)info.address; 2701 thread->kernel_stack_top = thread->kernel_stack_base + info.size; 2702 2703 thread->visible = true; 2704 insert_thread_into_team(thread->team, thread); 2705 2706 scheduler_on_thread_init(thread); 2707 } 2708 sUsedThreads = args->num_cpus; 2709 2710 // init the notification service 2711 new(&sNotificationService) ThreadNotificationService(); 2712 2713 sNotificationService.Register(); 2714 2715 // start the undertaker thread 2716 new(&sUndertakerEntries) DoublyLinkedList<UndertakerEntry>(); 2717 sUndertakerCondition.Init(&sUndertakerEntries, "undertaker entries"); 2718 2719 thread_id undertakerThread = spawn_kernel_thread(&undertaker, "undertaker", 2720 B_DISPLAY_PRIORITY, NULL); 2721 if (undertakerThread < 0) 2722 panic("Failed to create undertaker thread!"); 2723 resume_thread(undertakerThread); 2724 2725 // set up some debugger commands 2726 add_debugger_command_etc("threads", &dump_thread_list, "List all threads", 2727 "[ <team> ]\n" 2728 "Prints a list of all existing threads, or, if a team ID is given,\n" 2729 "all threads of the specified team.\n" 2730 " <team> - The ID of the team whose threads shall be listed.\n", 0); 2731 add_debugger_command_etc("ready", &dump_thread_list, 2732 "List all ready threads", 2733 "\n" 2734 "Prints a list of all threads in ready state.\n", 0); 2735 add_debugger_command_etc("running", &dump_thread_list, 2736 "List all running threads", 2737 "\n" 2738 "Prints a list of all threads in running state.\n", 0); 2739 add_debugger_command_etc("waiting", &dump_thread_list, 2740 "List all waiting threads (optionally for a specific semaphore)", 2741 "[ <sem> ]\n" 2742 "Prints a list of all threads in waiting state. If a semaphore is\n" 2743 "specified, only the threads waiting on that semaphore are listed.\n" 2744 " <sem> - ID of the semaphore.\n", 0); 2745 add_debugger_command_etc("realtime", &dump_thread_list, 2746 "List all realtime threads", 2747 "\n" 2748 "Prints a list of all threads with realtime priority.\n", 0); 2749 add_debugger_command_etc("thread", &dump_thread_info, 2750 "Dump info about a particular thread", 2751 "[ -s ] ( <id> | <address> | <name> )*\n" 2752 "Prints information about the specified thread. If no argument is\n" 2753 "given the current thread is selected.\n" 2754 " -s - Print info in compact table form (like \"threads\").\n" 2755 " <id> - The ID of the thread.\n" 2756 " <address> - The address of the thread structure.\n" 2757 " <name> - The thread's name.\n", 0); 2758 add_debugger_command_etc("calling", &dump_thread_list, 2759 "Show all threads that have a specific address in their call chain", 2760 "{ <symbol-pattern> | <start> <end> }\n", 0); 2761 add_debugger_command_etc("unreal", &make_thread_unreal, 2762 "Set realtime priority threads to normal priority", 2763 "[ <id> ]\n" 2764 "Sets the priority of all realtime threads or, if given, the one\n" 2765 "with the specified ID to \"normal\" priority.\n" 2766 " <id> - The ID of the thread.\n", 0); 2767 add_debugger_command_etc("suspend", &make_thread_suspended, 2768 "Suspend a thread", 2769 "[ <id> ]\n" 2770 "Suspends the thread with the given ID. If no ID argument is given\n" 2771 "the current thread is selected.\n" 2772 " <id> - The ID of the thread.\n", 0); 2773 add_debugger_command_etc("resume", &make_thread_resumed, "Resume a thread", 2774 "<id>\n" 2775 "Resumes the specified thread, if it is currently suspended.\n" 2776 " <id> - The ID of the thread.\n", 0); 2777 add_debugger_command_etc("drop", &drop_into_debugger, 2778 "Drop a thread into the userland debugger", 2779 "<id>\n" 2780 "Drops the specified (userland) thread into the userland debugger\n" 2781 "after leaving the kernel debugger.\n" 2782 " <id> - The ID of the thread.\n", 0); 2783 add_debugger_command_etc("priority", &set_thread_prio, 2784 "Set a thread's priority", 2785 "<priority> [ <id> ]\n" 2786 "Sets the priority of the thread with the specified ID to the given\n" 2787 "priority. If no thread ID is given, the current thread is selected.\n" 2788 " <priority> - The thread's new priority (0 - 120)\n" 2789 " <id> - The ID of the thread.\n", 0); 2790 2791 return B_OK; 2792 } 2793 2794 2795 status_t 2796 thread_preboot_init_percpu(struct kernel_args *args, int32 cpuNum) 2797 { 2798 // set up the cpu pointer in the not yet initialized per-cpu idle thread 2799 // so that get_current_cpu and friends will work, which is crucial for 2800 // a lot of low level routines 2801 sIdleThreads[cpuNum].cpu = &gCPU[cpuNum]; 2802 arch_thread_set_current_thread(&sIdleThreads[cpuNum]); 2803 return B_OK; 2804 } 2805 2806 2807 // #pragma mark - thread blocking API 2808 2809 2810 static status_t 2811 thread_block_timeout(timer* timer) 2812 { 2813 Thread* thread = (Thread*)timer->user_data; 2814 thread_unblock(thread, B_TIMED_OUT); 2815 2816 return B_HANDLED_INTERRUPT; 2817 } 2818 2819 2820 /*! Blocks the current thread. 2821 2822 The thread is blocked until someone else unblock it. Must be called after a 2823 call to thread_prepare_to_block(). If the thread has already been unblocked 2824 after the previous call to thread_prepare_to_block(), this function will 2825 return immediately. Cf. the documentation of thread_prepare_to_block() for 2826 more details. 2827 2828 The caller must hold the scheduler lock. 2829 2830 \param thread The current thread. 2831 \return The error code passed to the unblocking function. thread_interrupt() 2832 uses \c B_INTERRUPTED. By convention \c B_OK means that the wait was 2833 successful while another error code indicates a failure (what that means 2834 depends on the client code). 2835 */ 2836 static inline status_t 2837 thread_block_locked(Thread* thread) 2838 { 2839 if (thread->wait.status == 1) { 2840 // check for signals, if interruptible 2841 if (thread_is_interrupted(thread, thread->wait.flags)) { 2842 thread->wait.status = B_INTERRUPTED; 2843 } else 2844 scheduler_reschedule(B_THREAD_WAITING); 2845 } 2846 2847 return thread->wait.status; 2848 } 2849 2850 2851 /*! Blocks the current thread. 2852 2853 The function acquires the scheduler lock and calls thread_block_locked(). 2854 See there for more information. 2855 */ 2856 status_t 2857 thread_block() 2858 { 2859 InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock); 2860 return thread_block_locked(thread_get_current_thread()); 2861 } 2862 2863 2864 /*! Blocks the current thread with a timeout. 2865 2866 The thread is blocked until someone else unblock it or the specified timeout 2867 occurs. Must be called after a call to thread_prepare_to_block(). If the 2868 thread has already been unblocked after the previous call to 2869 thread_prepare_to_block(), this function will return immediately. See 2870 thread_prepare_to_block() for more details. 2871 2872 The caller must not hold the scheduler lock. 2873 2874 \param thread The current thread. 2875 \param timeoutFlags The standard timeout flags: 2876 - \c B_RELATIVE_TIMEOUT: \a timeout specifies the time to wait. 2877 - \c B_ABSOLUTE_TIMEOUT: \a timeout specifies the absolute end time when 2878 the timeout shall occur. 2879 - \c B_TIMEOUT_REAL_TIME_BASE: Only relevant when \c B_ABSOLUTE_TIMEOUT 2880 is specified, too. Specifies that \a timeout is a real time, not a 2881 system time. 2882 If neither \c B_RELATIVE_TIMEOUT nor \c B_ABSOLUTE_TIMEOUT are 2883 specified, an infinite timeout is implied and the function behaves like 2884 thread_block_locked(). 2885 \return The error code passed to the unblocking function. thread_interrupt() 2886 uses \c B_INTERRUPTED. When the timeout occurred, \c B_TIMED_OUT is 2887 returned. By convention \c B_OK means that the wait was successful while 2888 another error code indicates a failure (what that means depends on the 2889 client code). 2890 */ 2891 status_t 2892 thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout) 2893 { 2894 Thread* thread = thread_get_current_thread(); 2895 2896 InterruptsSpinLocker locker(thread->scheduler_lock); 2897 2898 if (thread->wait.status != 1) 2899 return thread->wait.status; 2900 2901 bool useTimer = (timeoutFlags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) 2902 && timeout != B_INFINITE_TIMEOUT; 2903 2904 if (useTimer) { 2905 // Timer flags: absolute/relative. 2906 uint32 timerFlags; 2907 if ((timeoutFlags & B_RELATIVE_TIMEOUT) != 0) { 2908 timerFlags = B_ONE_SHOT_RELATIVE_TIMER; 2909 } else { 2910 timerFlags = B_ONE_SHOT_ABSOLUTE_TIMER; 2911 if ((timeoutFlags & B_TIMEOUT_REAL_TIME_BASE) != 0) 2912 timerFlags |= B_TIMER_REAL_TIME_BASE; 2913 } 2914 2915 // install the timer 2916 thread->wait.unblock_timer.user_data = thread; 2917 add_timer(&thread->wait.unblock_timer, &thread_block_timeout, timeout, 2918 timerFlags); 2919 } 2920 2921 // block 2922 status_t error = thread_block_locked(thread); 2923 2924 locker.Unlock(); 2925 2926 // cancel timer, if it didn't fire 2927 if (error != B_TIMED_OUT && useTimer) 2928 cancel_timer(&thread->wait.unblock_timer); 2929 2930 return error; 2931 } 2932 2933 2934 /*! Unblocks a thread. 2935 2936 Acquires the scheduler lock and calls thread_unblock_locked(). 2937 See there for more information. 2938 */ 2939 void 2940 thread_unblock(Thread* thread, status_t status) 2941 { 2942 InterruptsSpinLocker locker(thread->scheduler_lock); 2943 thread_unblock_locked(thread, status); 2944 } 2945 2946 2947 /*! Unblocks a userland-blocked thread. 2948 The caller must not hold any locks. 2949 */ 2950 static status_t 2951 user_unblock_thread(thread_id threadID, status_t status) 2952 { 2953 // get the thread 2954 Thread* thread = Thread::GetAndLock(threadID); 2955 if (thread == NULL) 2956 return B_BAD_THREAD_ID; 2957 BReference<Thread> threadReference(thread, true); 2958 ThreadLocker threadLocker(thread, true); 2959 2960 if (thread->user_thread == NULL) 2961 return B_NOT_ALLOWED; 2962 2963 InterruptsSpinLocker locker(thread->scheduler_lock); 2964 2965 if (thread->user_thread->wait_status > 0) { 2966 thread->user_thread->wait_status = status; 2967 thread_unblock_locked(thread, status); 2968 } 2969 2970 return B_OK; 2971 } 2972 2973 2974 // #pragma mark - public kernel API 2975 2976 2977 void 2978 exit_thread(status_t returnValue) 2979 { 2980 Thread *thread = thread_get_current_thread(); 2981 Team* team = thread->team; 2982 2983 thread->exit.status = returnValue; 2984 2985 // if called from a kernel thread, we don't deliver the signal, 2986 // we just exit directly to keep the user space behaviour of 2987 // this function 2988 if (team != team_get_kernel_team()) { 2989 // If this is its main thread, set the team's exit status. 2990 if (thread == team->main_thread) { 2991 TeamLocker teamLocker(team); 2992 2993 if (!team->exit.initialized) { 2994 team->exit.reason = CLD_EXITED; 2995 team->exit.signal = 0; 2996 team->exit.signaling_user = 0; 2997 team->exit.status = returnValue; 2998 team->exit.initialized = true; 2999 } 3000 3001 teamLocker.Unlock(); 3002 } 3003 3004 Signal signal(SIGKILLTHR, SI_USER, B_OK, team->id); 3005 send_signal_to_thread(thread, signal, B_DO_NOT_RESCHEDULE); 3006 } else 3007 thread_exit(); 3008 } 3009 3010 3011 status_t 3012 kill_thread(thread_id id) 3013 { 3014 if (id <= 0) 3015 return B_BAD_VALUE; 3016 3017 Thread* currentThread = thread_get_current_thread(); 3018 3019 Signal signal(SIGKILLTHR, SI_USER, B_OK, currentThread->team->id); 3020 return send_signal_to_thread_id(id, signal, 0); 3021 } 3022 3023 3024 status_t 3025 send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize) 3026 { 3027 return send_data_etc(thread, code, buffer, bufferSize, 0); 3028 } 3029 3030 3031 int32 3032 receive_data(thread_id *sender, void *buffer, size_t bufferSize) 3033 { 3034 return receive_data_etc(sender, buffer, bufferSize, 0); 3035 } 3036 3037 3038 bool 3039 has_data(thread_id thread) 3040 { 3041 // TODO: The thread argument is ignored. 3042 int32 count; 3043 3044 if (get_sem_count(thread_get_current_thread()->msg.read_sem, 3045 &count) != B_OK) 3046 return false; 3047 3048 return count == 0 ? false : true; 3049 } 3050 3051 3052 status_t 3053 _get_thread_info(thread_id id, thread_info *info, size_t size) 3054 { 3055 if (info == NULL || size != sizeof(thread_info) || id < B_OK) 3056 return B_BAD_VALUE; 3057 3058 // get the thread 3059 Thread* thread = Thread::GetAndLock(id); 3060 if (thread == NULL) 3061 return B_BAD_THREAD_ID; 3062 BReference<Thread> threadReference(thread, true); 3063 ThreadLocker threadLocker(thread, true); 3064 3065 // fill the info -- also requires the scheduler lock to be held 3066 InterruptsSpinLocker locker(thread->scheduler_lock); 3067 3068 fill_thread_info(thread, info, size); 3069 3070 return B_OK; 3071 } 3072 3073 3074 status_t 3075 _get_next_thread_info(team_id teamID, int32 *_cookie, thread_info *info, 3076 size_t size) 3077 { 3078 if (info == NULL || size != sizeof(thread_info) || teamID < 0) 3079 return B_BAD_VALUE; 3080 3081 int32 lastID = *_cookie; 3082 3083 // get the team 3084 Team* team = Team::GetAndLock(teamID); 3085 if (team == NULL) 3086 return B_BAD_VALUE; 3087 BReference<Team> teamReference(team, true); 3088 TeamLocker teamLocker(team, true); 3089 3090 Thread* thread = NULL; 3091 3092 if (lastID == 0) { 3093 // We start with the main thread 3094 thread = team->main_thread; 3095 } else { 3096 // Find the one thread with an ID greater than ours (as long as the IDs 3097 // don't wrap they are always sorted from highest to lowest). 3098 // TODO: That is broken not only when the IDs wrap, but also for the 3099 // kernel team, to which threads are added when they are dying. 3100 for (Thread* next = team->thread_list; next != NULL; 3101 next = next->team_next) { 3102 if (next->id <= lastID) 3103 break; 3104 3105 thread = next; 3106 } 3107 } 3108 3109 if (thread == NULL) 3110 return B_BAD_VALUE; 3111 3112 lastID = thread->id; 3113 *_cookie = lastID; 3114 3115 ThreadLocker threadLocker(thread); 3116 InterruptsSpinLocker locker(thread->scheduler_lock); 3117 3118 fill_thread_info(thread, info, size); 3119 3120 return B_OK; 3121 } 3122 3123 3124 thread_id 3125 find_thread(const char* name) 3126 { 3127 if (name == NULL) 3128 return thread_get_current_thread_id(); 3129 3130 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 3131 3132 // TODO: Scanning the whole hash with the thread hash lock held isn't 3133 // exactly cheap -- although this function is probably used very rarely. 3134 3135 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 3136 Thread* thread = it.Next();) { 3137 if (!thread->visible) 3138 continue; 3139 3140 if (strcmp(thread->name, name) == 0) 3141 return thread->id; 3142 } 3143 3144 return B_NAME_NOT_FOUND; 3145 } 3146 3147 3148 status_t 3149 rename_thread(thread_id id, const char* name) 3150 { 3151 if (name == NULL) 3152 return B_BAD_VALUE; 3153 3154 // get the thread 3155 Thread* thread = Thread::GetAndLock(id); 3156 if (thread == NULL) 3157 return B_BAD_THREAD_ID; 3158 BReference<Thread> threadReference(thread, true); 3159 ThreadLocker threadLocker(thread, true); 3160 3161 // check whether the operation is allowed 3162 if (thread->team != thread_get_current_thread()->team) 3163 return B_NOT_ALLOWED; 3164 3165 strlcpy(thread->name, name, B_OS_NAME_LENGTH); 3166 3167 team_id teamID = thread->team->id; 3168 3169 threadLocker.Unlock(); 3170 3171 // notify listeners 3172 sNotificationService.Notify(THREAD_NAME_CHANGED, teamID, id); 3173 // don't pass the thread structure, as it's unsafe, if it isn't ours 3174 3175 return B_OK; 3176 } 3177 3178 3179 status_t 3180 set_thread_priority(thread_id id, int32 priority) 3181 { 3182 // make sure the passed in priority is within bounds 3183 if (priority > THREAD_MAX_SET_PRIORITY) 3184 priority = THREAD_MAX_SET_PRIORITY; 3185 if (priority < THREAD_MIN_SET_PRIORITY) 3186 priority = THREAD_MIN_SET_PRIORITY; 3187 3188 // get the thread 3189 Thread* thread = Thread::GetAndLock(id); 3190 if (thread == NULL) 3191 return B_BAD_THREAD_ID; 3192 BReference<Thread> threadReference(thread, true); 3193 ThreadLocker threadLocker(thread, true); 3194 3195 // check whether the change is allowed 3196 if (thread_is_idle_thread(thread)) 3197 return B_NOT_ALLOWED; 3198 3199 return scheduler_set_thread_priority(thread, priority); 3200 } 3201 3202 3203 status_t 3204 snooze_etc(bigtime_t timeout, int timebase, uint32 flags) 3205 { 3206 return common_snooze_etc(timeout, timebase, flags, NULL); 3207 } 3208 3209 3210 /*! snooze() for internal kernel use only; doesn't interrupt on signals. */ 3211 status_t 3212 snooze(bigtime_t timeout) 3213 { 3214 return snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT); 3215 } 3216 3217 3218 /*! snooze_until() for internal kernel use only; doesn't interrupt on 3219 signals. 3220 */ 3221 status_t 3222 snooze_until(bigtime_t timeout, int timebase) 3223 { 3224 return snooze_etc(timeout, timebase, B_ABSOLUTE_TIMEOUT); 3225 } 3226 3227 3228 status_t 3229 wait_for_thread(thread_id thread, status_t *_returnCode) 3230 { 3231 return wait_for_thread_etc(thread, 0, 0, _returnCode); 3232 } 3233 3234 3235 status_t 3236 suspend_thread(thread_id id) 3237 { 3238 if (id <= 0) 3239 return B_BAD_VALUE; 3240 3241 Thread* currentThread = thread_get_current_thread(); 3242 3243 Signal signal(SIGSTOP, SI_USER, B_OK, currentThread->team->id); 3244 return send_signal_to_thread_id(id, signal, 0); 3245 } 3246 3247 3248 status_t 3249 resume_thread(thread_id id) 3250 { 3251 if (id <= 0) 3252 return B_BAD_VALUE; 3253 3254 Thread* currentThread = thread_get_current_thread(); 3255 3256 // Using the kernel internal SIGNAL_CONTINUE_THREAD signal retains 3257 // compatibility to BeOS which documents the combination of suspend_thread() 3258 // and resume_thread() to interrupt threads waiting on semaphores. 3259 Signal signal(SIGNAL_CONTINUE_THREAD, SI_USER, B_OK, 3260 currentThread->team->id); 3261 return send_signal_to_thread_id(id, signal, 0); 3262 } 3263 3264 3265 thread_id 3266 spawn_kernel_thread(thread_func function, const char *name, int32 priority, 3267 void *arg) 3268 { 3269 return thread_create_thread( 3270 ThreadCreationAttributes(function, name, priority, arg), 3271 true); 3272 } 3273 3274 3275 int 3276 getrlimit(int resource, struct rlimit * rlp) 3277 { 3278 status_t error = common_getrlimit(resource, rlp); 3279 if (error != B_OK) { 3280 errno = error; 3281 return -1; 3282 } 3283 3284 return 0; 3285 } 3286 3287 3288 int 3289 setrlimit(int resource, const struct rlimit * rlp) 3290 { 3291 status_t error = common_setrlimit(resource, rlp); 3292 if (error != B_OK) { 3293 errno = error; 3294 return -1; 3295 } 3296 3297 return 0; 3298 } 3299 3300 3301 // #pragma mark - syscalls 3302 3303 3304 void 3305 _user_exit_thread(status_t returnValue) 3306 { 3307 exit_thread(returnValue); 3308 } 3309 3310 3311 status_t 3312 _user_kill_thread(thread_id thread) 3313 { 3314 // TODO: Don't allow kernel threads to be killed! 3315 return kill_thread(thread); 3316 } 3317 3318 3319 status_t 3320 _user_cancel_thread(thread_id threadID, void (*cancelFunction)(int)) 3321 { 3322 // check the cancel function 3323 if (cancelFunction == NULL || !IS_USER_ADDRESS(cancelFunction)) 3324 return B_BAD_VALUE; 3325 3326 // get and lock the thread 3327 Thread* thread = Thread::GetAndLock(threadID); 3328 if (thread == NULL) 3329 return B_BAD_THREAD_ID; 3330 BReference<Thread> threadReference(thread, true); 3331 ThreadLocker threadLocker(thread, true); 3332 3333 // only threads of the same team can be canceled 3334 if (thread->team != thread_get_current_thread()->team) 3335 return B_NOT_ALLOWED; 3336 3337 // set the cancel function 3338 thread->cancel_function = cancelFunction; 3339 3340 // send the cancellation signal to the thread 3341 InterruptsReadSpinLocker teamLocker(thread->team_lock); 3342 SpinLocker locker(thread->team->signal_lock); 3343 return send_signal_to_thread_locked(thread, SIGNAL_CANCEL_THREAD, NULL, 0); 3344 } 3345 3346 3347 status_t 3348 _user_resume_thread(thread_id thread) 3349 { 3350 // TODO: Don't allow kernel threads to be resumed! 3351 return resume_thread(thread); 3352 } 3353 3354 3355 status_t 3356 _user_suspend_thread(thread_id thread) 3357 { 3358 // TODO: Don't allow kernel threads to be suspended! 3359 return suspend_thread(thread); 3360 } 3361 3362 3363 status_t 3364 _user_rename_thread(thread_id thread, const char *userName) 3365 { 3366 char name[B_OS_NAME_LENGTH]; 3367 3368 if (!IS_USER_ADDRESS(userName) 3369 || userName == NULL 3370 || user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK) 3371 return B_BAD_ADDRESS; 3372 3373 // TODO: Don't allow kernel threads to be renamed! 3374 return rename_thread(thread, name); 3375 } 3376 3377 3378 int32 3379 _user_set_thread_priority(thread_id thread, int32 newPriority) 3380 { 3381 // TODO: Don't allow setting priority of kernel threads! 3382 return set_thread_priority(thread, newPriority); 3383 } 3384 3385 3386 thread_id 3387 _user_spawn_thread(thread_creation_attributes* userAttributes) 3388 { 3389 // copy the userland structure to the kernel 3390 char nameBuffer[B_OS_NAME_LENGTH]; 3391 ThreadCreationAttributes attributes; 3392 status_t error = attributes.InitFromUserAttributes(userAttributes, 3393 nameBuffer); 3394 if (error != B_OK) 3395 return error; 3396 3397 // create the thread 3398 thread_id threadID = thread_create_thread(attributes, false); 3399 3400 if (threadID >= 0) 3401 user_debug_thread_created(threadID); 3402 3403 return threadID; 3404 } 3405 3406 3407 status_t 3408 _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags, 3409 bigtime_t* userRemainingTime) 3410 { 3411 // We need to store more syscall restart parameters than usual and need a 3412 // somewhat different handling. Hence we can't use 3413 // syscall_restart_handle_timeout_pre() but do the job ourselves. 3414 struct restart_parameters { 3415 bigtime_t timeout; 3416 clockid_t timebase; 3417 uint32 flags; 3418 }; 3419 3420 Thread* thread = thread_get_current_thread(); 3421 3422 if ((thread->flags & THREAD_FLAGS_SYSCALL_RESTARTED) != 0) { 3423 // The syscall was restarted. Fetch the parameters from the stored 3424 // restart parameters. 3425 restart_parameters* restartParameters 3426 = (restart_parameters*)thread->syscall_restart.parameters; 3427 timeout = restartParameters->timeout; 3428 timebase = restartParameters->timebase; 3429 flags = restartParameters->flags; 3430 } else { 3431 // convert relative timeouts to absolute ones 3432 if ((flags & B_RELATIVE_TIMEOUT) != 0) { 3433 // not restarted yet and the flags indicate a relative timeout 3434 3435 // Make sure we use the system time base, so real-time clock changes 3436 // won't affect our wait. 3437 flags &= ~(uint32)B_TIMEOUT_REAL_TIME_BASE; 3438 if (timebase == CLOCK_REALTIME) 3439 timebase = CLOCK_MONOTONIC; 3440 3441 // get the current time and make the timeout absolute 3442 bigtime_t now; 3443 status_t error = user_timer_get_clock(timebase, now); 3444 if (error != B_OK) 3445 return error; 3446 3447 timeout += now; 3448 3449 // deal with overflow 3450 if (timeout < 0) 3451 timeout = B_INFINITE_TIMEOUT; 3452 3453 flags = (flags & ~B_RELATIVE_TIMEOUT) | B_ABSOLUTE_TIMEOUT; 3454 } else 3455 flags |= B_ABSOLUTE_TIMEOUT; 3456 } 3457 3458 // snooze 3459 bigtime_t remainingTime; 3460 status_t error = common_snooze_etc(timeout, timebase, 3461 flags | B_CAN_INTERRUPT | B_CHECK_PERMISSION, 3462 userRemainingTime != NULL ? &remainingTime : NULL); 3463 3464 // If interrupted, copy the remaining time back to userland and prepare the 3465 // syscall restart. 3466 if (error == B_INTERRUPTED) { 3467 if (userRemainingTime != NULL 3468 && (!IS_USER_ADDRESS(userRemainingTime) 3469 || user_memcpy(userRemainingTime, &remainingTime, 3470 sizeof(remainingTime)) != B_OK)) { 3471 return B_BAD_ADDRESS; 3472 } 3473 3474 // store the normalized values in the restart parameters 3475 restart_parameters* restartParameters 3476 = (restart_parameters*)thread->syscall_restart.parameters; 3477 restartParameters->timeout = timeout; 3478 restartParameters->timebase = timebase; 3479 restartParameters->flags = flags; 3480 3481 // restart the syscall, if possible 3482 atomic_or(&thread->flags, THREAD_FLAGS_RESTART_SYSCALL); 3483 } 3484 3485 return error; 3486 } 3487 3488 3489 void 3490 _user_thread_yield(void) 3491 { 3492 thread_yield(); 3493 } 3494 3495 3496 status_t 3497 _user_get_thread_info(thread_id id, thread_info *userInfo) 3498 { 3499 thread_info info; 3500 status_t status; 3501 3502 if (!IS_USER_ADDRESS(userInfo)) 3503 return B_BAD_ADDRESS; 3504 3505 status = _get_thread_info(id, &info, sizeof(thread_info)); 3506 3507 if (status >= B_OK 3508 && user_memcpy(userInfo, &info, sizeof(thread_info)) < B_OK) 3509 return B_BAD_ADDRESS; 3510 3511 return status; 3512 } 3513 3514 3515 status_t 3516 _user_get_next_thread_info(team_id team, int32 *userCookie, 3517 thread_info *userInfo) 3518 { 3519 status_t status; 3520 thread_info info; 3521 int32 cookie; 3522 3523 if (!IS_USER_ADDRESS(userCookie) || !IS_USER_ADDRESS(userInfo) 3524 || user_memcpy(&cookie, userCookie, sizeof(int32)) < B_OK) 3525 return B_BAD_ADDRESS; 3526 3527 status = _get_next_thread_info(team, &cookie, &info, sizeof(thread_info)); 3528 if (status < B_OK) 3529 return status; 3530 3531 if (user_memcpy(userCookie, &cookie, sizeof(int32)) < B_OK 3532 || user_memcpy(userInfo, &info, sizeof(thread_info)) < B_OK) 3533 return B_BAD_ADDRESS; 3534 3535 return status; 3536 } 3537 3538 3539 thread_id 3540 _user_find_thread(const char *userName) 3541 { 3542 char name[B_OS_NAME_LENGTH]; 3543 3544 if (userName == NULL) 3545 return find_thread(NULL); 3546 3547 if (!IS_USER_ADDRESS(userName) 3548 || user_strlcpy(name, userName, sizeof(name)) < B_OK) 3549 return B_BAD_ADDRESS; 3550 3551 return find_thread(name); 3552 } 3553 3554 3555 status_t 3556 _user_wait_for_thread(thread_id id, status_t *userReturnCode) 3557 { 3558 status_t returnCode; 3559 status_t status; 3560 3561 if (userReturnCode != NULL && !IS_USER_ADDRESS(userReturnCode)) 3562 return B_BAD_ADDRESS; 3563 3564 status = wait_for_thread_etc(id, B_CAN_INTERRUPT, 0, &returnCode); 3565 3566 if (status == B_OK && userReturnCode != NULL 3567 && user_memcpy(userReturnCode, &returnCode, sizeof(status_t)) < B_OK) { 3568 return B_BAD_ADDRESS; 3569 } 3570 3571 return syscall_restart_handle_post(status); 3572 } 3573 3574 3575 bool 3576 _user_has_data(thread_id thread) 3577 { 3578 return has_data(thread); 3579 } 3580 3581 3582 status_t 3583 _user_send_data(thread_id thread, int32 code, const void *buffer, 3584 size_t bufferSize) 3585 { 3586 if (!IS_USER_ADDRESS(buffer)) 3587 return B_BAD_ADDRESS; 3588 3589 return send_data_etc(thread, code, buffer, bufferSize, 3590 B_KILL_CAN_INTERRUPT); 3591 // supports userland buffers 3592 } 3593 3594 3595 status_t 3596 _user_receive_data(thread_id *_userSender, void *buffer, size_t bufferSize) 3597 { 3598 thread_id sender; 3599 status_t code; 3600 3601 if ((!IS_USER_ADDRESS(_userSender) && _userSender != NULL) 3602 || !IS_USER_ADDRESS(buffer)) 3603 return B_BAD_ADDRESS; 3604 3605 code = receive_data_etc(&sender, buffer, bufferSize, B_KILL_CAN_INTERRUPT); 3606 // supports userland buffers 3607 3608 if (_userSender != NULL) 3609 if (user_memcpy(_userSender, &sender, sizeof(thread_id)) < B_OK) 3610 return B_BAD_ADDRESS; 3611 3612 return code; 3613 } 3614 3615 3616 status_t 3617 _user_block_thread(uint32 flags, bigtime_t timeout) 3618 { 3619 syscall_restart_handle_timeout_pre(flags, timeout); 3620 flags |= B_CAN_INTERRUPT; 3621 3622 Thread* thread = thread_get_current_thread(); 3623 ThreadLocker threadLocker(thread); 3624 3625 // check, if already done 3626 if (thread->user_thread->wait_status <= 0) 3627 return thread->user_thread->wait_status; 3628 3629 // nope, so wait 3630 thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_OTHER, "user"); 3631 3632 threadLocker.Unlock(); 3633 3634 status_t status = thread_block_with_timeout(flags, timeout); 3635 3636 threadLocker.Lock(); 3637 3638 // Interruptions or timeouts can race with other threads unblocking us. 3639 // Favor a wake-up by another thread, i.e. if someone changed the wait 3640 // status, use that. 3641 status_t oldStatus = thread->user_thread->wait_status; 3642 if (oldStatus > 0) 3643 thread->user_thread->wait_status = status; 3644 else 3645 status = oldStatus; 3646 3647 threadLocker.Unlock(); 3648 3649 return syscall_restart_handle_timeout_post(status, timeout); 3650 } 3651 3652 3653 status_t 3654 _user_unblock_thread(thread_id threadID, status_t status) 3655 { 3656 status_t error = user_unblock_thread(threadID, status); 3657 3658 if (error == B_OK) 3659 scheduler_reschedule_if_necessary(); 3660 3661 return error; 3662 } 3663 3664 3665 status_t 3666 _user_unblock_threads(thread_id* userThreads, uint32 count, status_t status) 3667 { 3668 enum { 3669 MAX_USER_THREADS_TO_UNBLOCK = 128 3670 }; 3671 3672 if (userThreads == NULL || !IS_USER_ADDRESS(userThreads)) 3673 return B_BAD_ADDRESS; 3674 if (count > MAX_USER_THREADS_TO_UNBLOCK) 3675 return B_BAD_VALUE; 3676 3677 thread_id threads[MAX_USER_THREADS_TO_UNBLOCK]; 3678 if (user_memcpy(threads, userThreads, count * sizeof(thread_id)) != B_OK) 3679 return B_BAD_ADDRESS; 3680 3681 for (uint32 i = 0; i < count; i++) 3682 user_unblock_thread(threads[i], status); 3683 3684 scheduler_reschedule_if_necessary(); 3685 3686 return B_OK; 3687 } 3688 3689 3690 // TODO: the following two functions don't belong here 3691 3692 3693 int 3694 _user_getrlimit(int resource, struct rlimit *urlp) 3695 { 3696 struct rlimit rl; 3697 int ret; 3698 3699 if (urlp == NULL) 3700 return EINVAL; 3701 3702 if (!IS_USER_ADDRESS(urlp)) 3703 return B_BAD_ADDRESS; 3704 3705 ret = common_getrlimit(resource, &rl); 3706 3707 if (ret == 0) { 3708 ret = user_memcpy(urlp, &rl, sizeof(struct rlimit)); 3709 if (ret < 0) 3710 return ret; 3711 3712 return 0; 3713 } 3714 3715 return ret; 3716 } 3717 3718 3719 int 3720 _user_setrlimit(int resource, const struct rlimit *userResourceLimit) 3721 { 3722 struct rlimit resourceLimit; 3723 3724 if (userResourceLimit == NULL) 3725 return EINVAL; 3726 3727 if (!IS_USER_ADDRESS(userResourceLimit) 3728 || user_memcpy(&resourceLimit, userResourceLimit, 3729 sizeof(struct rlimit)) < B_OK) 3730 return B_BAD_ADDRESS; 3731 3732 return common_setrlimit(resource, &resourceLimit); 3733 } 3734