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