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