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