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