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