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 spinlock sThreadHashLock = B_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 InterruptsSpinLocker 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 InterruptsSpinLocker 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 InterruptsSpinLocker 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 InterruptsSpinLocker 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 InterruptsSpinLocker 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 InterruptsSpinLocker 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 InterruptsSpinLocker locker(sThreadHashLock); 490 sThreadHash.InsertIteratorEntry(&fEntry); 491 } 492 493 494 ThreadListIterator::~ThreadListIterator() 495 { 496 // remove the entry 497 InterruptsSpinLocker 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 InterruptsSpinLocker 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 SpinLocker 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 switch (clockID) { 1377 case CLOCK_REALTIME: 1378 // make sure the B_TIMEOUT_REAL_TIME_BASE flag is set and fall 1379 // through 1380 flags |= B_TIMEOUT_REAL_TIME_BASE; 1381 case CLOCK_MONOTONIC: 1382 { 1383 // Store the start time, for the case that we get interrupted and 1384 // need to return the remaining time. For absolute timeouts we can 1385 // still get he time later, if needed. 1386 bigtime_t startTime 1387 = _remainingTime != NULL && (flags & B_RELATIVE_TIMEOUT) != 0 1388 ? system_time() : 0; 1389 1390 Thread* thread = thread_get_current_thread(); 1391 1392 thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_SNOOZE, 1393 NULL); 1394 status_t status = thread_block_with_timeout(flags, timeout); 1395 1396 if (status == B_TIMED_OUT || status == B_WOULD_BLOCK) 1397 return B_OK; 1398 1399 // If interrupted, compute the remaining time, if requested. 1400 if (status == B_INTERRUPTED && _remainingTime != NULL) { 1401 if ((flags & B_RELATIVE_TIMEOUT) != 0) { 1402 *_remainingTime = std::max( 1403 startTime + timeout - system_time(), (bigtime_t)0); 1404 } else { 1405 bigtime_t now = (flags & B_TIMEOUT_REAL_TIME_BASE) != 0 1406 ? real_time_clock_usecs() : system_time(); 1407 *_remainingTime = std::max(timeout - now, (bigtime_t)0); 1408 } 1409 } 1410 1411 return status; 1412 } 1413 1414 case CLOCK_THREAD_CPUTIME_ID: 1415 // Waiting for ourselves to do something isn't particularly 1416 // productive. 1417 return B_BAD_VALUE; 1418 1419 case CLOCK_PROCESS_CPUTIME_ID: 1420 default: 1421 // We don't have to support those, but we are allowed to. Could be 1422 // done be creating a UserTimer on the fly with a custom UserEvent 1423 // that would just wake us up. 1424 return ENOTSUP; 1425 } 1426 } 1427 1428 1429 // #pragma mark - debugger calls 1430 1431 1432 static int 1433 make_thread_unreal(int argc, char **argv) 1434 { 1435 int32 id = -1; 1436 1437 if (argc > 2) { 1438 print_debugger_command_usage(argv[0]); 1439 return 0; 1440 } 1441 1442 if (argc > 1) 1443 id = strtoul(argv[1], NULL, 0); 1444 1445 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1446 Thread* thread = it.Next();) { 1447 if (id != -1 && thread->id != id) 1448 continue; 1449 1450 if (thread->priority > B_DISPLAY_PRIORITY) { 1451 scheduler_set_thread_priority(thread, B_NORMAL_PRIORITY); 1452 kprintf("thread %" B_PRId32 " made unreal\n", thread->id); 1453 } 1454 } 1455 1456 return 0; 1457 } 1458 1459 1460 static int 1461 set_thread_prio(int argc, char **argv) 1462 { 1463 int32 id; 1464 int32 prio; 1465 1466 if (argc > 3 || argc < 2) { 1467 print_debugger_command_usage(argv[0]); 1468 return 0; 1469 } 1470 1471 prio = strtoul(argv[1], NULL, 0); 1472 if (prio > THREAD_MAX_SET_PRIORITY) 1473 prio = THREAD_MAX_SET_PRIORITY; 1474 if (prio < THREAD_MIN_SET_PRIORITY) 1475 prio = THREAD_MIN_SET_PRIORITY; 1476 1477 if (argc > 2) 1478 id = strtoul(argv[2], NULL, 0); 1479 else 1480 id = thread_get_current_thread()->id; 1481 1482 bool found = false; 1483 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1484 Thread* thread = it.Next();) { 1485 if (thread->id != id) 1486 continue; 1487 scheduler_set_thread_priority(thread, prio); 1488 kprintf("thread %" B_PRId32 " set to priority %" B_PRId32 "\n", id, prio); 1489 found = true; 1490 break; 1491 } 1492 if (!found) 1493 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1494 1495 return 0; 1496 } 1497 1498 1499 static int 1500 make_thread_suspended(int argc, char **argv) 1501 { 1502 int32 id; 1503 1504 if (argc > 2) { 1505 print_debugger_command_usage(argv[0]); 1506 return 0; 1507 } 1508 1509 if (argc == 1) 1510 id = thread_get_current_thread()->id; 1511 else 1512 id = strtoul(argv[1], NULL, 0); 1513 1514 bool found = false; 1515 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1516 Thread* thread = it.Next();) { 1517 if (thread->id != id) 1518 continue; 1519 1520 Signal signal(SIGSTOP, SI_USER, B_OK, team_get_kernel_team()->id); 1521 send_signal_to_thread(thread, signal, B_DO_NOT_RESCHEDULE); 1522 1523 kprintf("thread %" B_PRId32 " suspended\n", id); 1524 found = true; 1525 break; 1526 } 1527 if (!found) 1528 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1529 1530 return 0; 1531 } 1532 1533 1534 static int 1535 make_thread_resumed(int argc, char **argv) 1536 { 1537 int32 id; 1538 1539 if (argc != 2) { 1540 print_debugger_command_usage(argv[0]); 1541 return 0; 1542 } 1543 1544 // force user to enter a thread id, as using 1545 // the current thread is usually not intended 1546 id = strtoul(argv[1], NULL, 0); 1547 1548 bool found = false; 1549 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1550 Thread* thread = it.Next();) { 1551 if (thread->id != id) 1552 continue; 1553 1554 if (thread->state == B_THREAD_SUSPENDED || thread->state == B_THREAD_ASLEEP 1555 || thread->state == B_THREAD_WAITING) { 1556 scheduler_enqueue_in_run_queue(thread); 1557 kprintf("thread %" B_PRId32 " resumed\n", thread->id); 1558 } else 1559 kprintf("thread %" B_PRId32 " is already running\n", thread->id); 1560 found = true; 1561 break; 1562 } 1563 if (!found) 1564 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1565 1566 return 0; 1567 } 1568 1569 1570 static int 1571 drop_into_debugger(int argc, char **argv) 1572 { 1573 status_t err; 1574 int32 id; 1575 1576 if (argc > 2) { 1577 print_debugger_command_usage(argv[0]); 1578 return 0; 1579 } 1580 1581 if (argc == 1) 1582 id = thread_get_current_thread()->id; 1583 else 1584 id = strtoul(argv[1], NULL, 0); 1585 1586 err = _user_debug_thread(id); 1587 // TODO: This is a non-trivial syscall doing some locking, so this is 1588 // really nasty and may go seriously wrong. 1589 if (err) 1590 kprintf("drop failed\n"); 1591 else 1592 kprintf("thread %" B_PRId32 " dropped into user debugger\n", id); 1593 1594 return 0; 1595 } 1596 1597 1598 /*! Returns a user-readable string for a thread state. 1599 Only for use in the kernel debugger. 1600 */ 1601 static const char * 1602 state_to_text(Thread *thread, int32 state) 1603 { 1604 switch (state) { 1605 case B_THREAD_READY: 1606 return "ready"; 1607 1608 case B_THREAD_RUNNING: 1609 return "running"; 1610 1611 case B_THREAD_WAITING: 1612 { 1613 if (thread != NULL) { 1614 switch (thread->wait.type) { 1615 case THREAD_BLOCK_TYPE_SNOOZE: 1616 return "zzz"; 1617 1618 case THREAD_BLOCK_TYPE_SEMAPHORE: 1619 { 1620 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1621 if (sem == thread->msg.read_sem) 1622 return "receive"; 1623 break; 1624 } 1625 } 1626 } 1627 1628 return "waiting"; 1629 } 1630 1631 case B_THREAD_SUSPENDED: 1632 return "suspended"; 1633 1634 case THREAD_STATE_FREE_ON_RESCHED: 1635 return "death"; 1636 1637 default: 1638 return "UNKNOWN"; 1639 } 1640 } 1641 1642 1643 static void 1644 print_thread_list_table_head() 1645 { 1646 kprintf("%-*s id state wait for %-*s cpu pri %-*s team " 1647 "name\n", 1648 B_PRINTF_POINTER_WIDTH, "thread", B_PRINTF_POINTER_WIDTH, "object", 1649 B_PRINTF_POINTER_WIDTH, "stack"); 1650 } 1651 1652 1653 static void 1654 _dump_thread_info(Thread *thread, bool shortInfo) 1655 { 1656 if (shortInfo) { 1657 kprintf("%p %6" B_PRId32 " %-10s", thread, thread->id, 1658 state_to_text(thread, thread->state)); 1659 1660 // does it block on a semaphore or a condition variable? 1661 if (thread->state == B_THREAD_WAITING) { 1662 switch (thread->wait.type) { 1663 case THREAD_BLOCK_TYPE_SEMAPHORE: 1664 { 1665 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1666 if (sem == thread->msg.read_sem) 1667 kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); 1668 else { 1669 kprintf("sem %-*" B_PRId32, 1670 B_PRINTF_POINTER_WIDTH + 5, sem); 1671 } 1672 break; 1673 } 1674 1675 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1676 kprintf("cvar %p ", thread->wait.object); 1677 break; 1678 1679 case THREAD_BLOCK_TYPE_SNOOZE: 1680 kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); 1681 break; 1682 1683 case THREAD_BLOCK_TYPE_SIGNAL: 1684 kprintf("signal%*s", B_PRINTF_POINTER_WIDTH + 9, ""); 1685 break; 1686 1687 case THREAD_BLOCK_TYPE_MUTEX: 1688 kprintf("mutex %p ", thread->wait.object); 1689 break; 1690 1691 case THREAD_BLOCK_TYPE_RW_LOCK: 1692 kprintf("rwlock %p ", thread->wait.object); 1693 break; 1694 1695 case THREAD_BLOCK_TYPE_OTHER: 1696 kprintf("other%*s", B_PRINTF_POINTER_WIDTH + 10, ""); 1697 break; 1698 1699 default: 1700 kprintf("??? %p ", thread->wait.object); 1701 break; 1702 } 1703 } else 1704 kprintf("-%*s", B_PRINTF_POINTER_WIDTH + 14, ""); 1705 1706 // on which CPU does it run? 1707 if (thread->cpu) 1708 kprintf("%2d", thread->cpu->cpu_num); 1709 else 1710 kprintf(" -"); 1711 1712 kprintf("%4" B_PRId32 " %p%5" B_PRId32 " %s\n", thread->priority, 1713 (void *)thread->kernel_stack_base, thread->team->id, thread->name); 1714 1715 return; 1716 } 1717 1718 // print the long info 1719 1720 struct thread_death_entry *death = NULL; 1721 1722 kprintf("THREAD: %p\n", thread); 1723 kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", thread->id, 1724 thread->id); 1725 kprintf("serial_number: %" B_PRId64 "\n", thread->serial_number); 1726 kprintf("name: \"%s\"\n", thread->name); 1727 kprintf("hash_next: %p\nteam_next: %p\n", 1728 thread->hash_next, thread->team_next); 1729 kprintf("priority: %" B_PRId32 " (I/O: %" B_PRId32 ")\n", 1730 thread->priority, thread->io_priority); 1731 kprintf("state: %s\n", state_to_text(thread, thread->state)); 1732 kprintf("cpu: %p ", thread->cpu); 1733 if (thread->cpu) 1734 kprintf("(%d)\n", thread->cpu->cpu_num); 1735 else 1736 kprintf("\n"); 1737 kprintf("sig_pending: %#" B_PRIx64 " (blocked: %#" B_PRIx64 1738 ", before sigsuspend(): %#" B_PRIx64 ")\n", 1739 (int64)thread->ThreadPendingSignals(), 1740 (int64)thread->sig_block_mask, 1741 (int64)thread->sigsuspend_original_unblocked_mask); 1742 kprintf("in_kernel: %d\n", thread->in_kernel); 1743 1744 if (thread->state == B_THREAD_WAITING) { 1745 kprintf("waiting for: "); 1746 1747 switch (thread->wait.type) { 1748 case THREAD_BLOCK_TYPE_SEMAPHORE: 1749 { 1750 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1751 if (sem == thread->msg.read_sem) 1752 kprintf("data\n"); 1753 else 1754 kprintf("semaphore %" B_PRId32 "\n", sem); 1755 break; 1756 } 1757 1758 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1759 kprintf("condition variable %p\n", thread->wait.object); 1760 break; 1761 1762 case THREAD_BLOCK_TYPE_SNOOZE: 1763 kprintf("snooze()\n"); 1764 break; 1765 1766 case THREAD_BLOCK_TYPE_SIGNAL: 1767 kprintf("signal\n"); 1768 break; 1769 1770 case THREAD_BLOCK_TYPE_MUTEX: 1771 kprintf("mutex %p\n", thread->wait.object); 1772 break; 1773 1774 case THREAD_BLOCK_TYPE_RW_LOCK: 1775 kprintf("rwlock %p\n", thread->wait.object); 1776 break; 1777 1778 case THREAD_BLOCK_TYPE_OTHER: 1779 kprintf("other (%s)\n", (char*)thread->wait.object); 1780 break; 1781 1782 default: 1783 kprintf("unknown (%p)\n", thread->wait.object); 1784 break; 1785 } 1786 } 1787 1788 kprintf("fault_handler: %p\n", (void *)thread->fault_handler); 1789 kprintf("team: %p, \"%s\"\n", thread->team, 1790 thread->team->Name()); 1791 kprintf(" exit.sem: %" B_PRId32 "\n", thread->exit.sem); 1792 kprintf(" exit.status: %#" B_PRIx32 " (%s)\n", thread->exit.status, 1793 strerror(thread->exit.status)); 1794 kprintf(" exit.waiters:\n"); 1795 while ((death = (struct thread_death_entry*)list_get_next_item( 1796 &thread->exit.waiters, death)) != NULL) { 1797 kprintf("\t%p (thread %" B_PRId32 ")\n", death, death->thread); 1798 } 1799 1800 kprintf("kernel_stack_area: %" B_PRId32 "\n", thread->kernel_stack_area); 1801 kprintf("kernel_stack_base: %p\n", (void *)thread->kernel_stack_base); 1802 kprintf("user_stack_area: %" B_PRId32 "\n", thread->user_stack_area); 1803 kprintf("user_stack_base: %p\n", (void *)thread->user_stack_base); 1804 kprintf("user_local_storage: %p\n", (void *)thread->user_local_storage); 1805 kprintf("user_thread: %p\n", (void *)thread->user_thread); 1806 kprintf("kernel_errno: %#x (%s)\n", thread->kernel_errno, 1807 strerror(thread->kernel_errno)); 1808 kprintf("kernel_time: %" B_PRId64 "\n", thread->kernel_time); 1809 kprintf("user_time: %" B_PRId64 "\n", thread->user_time); 1810 kprintf("flags: 0x%" B_PRIx32 "\n", thread->flags); 1811 kprintf("architecture dependant section:\n"); 1812 arch_thread_dump_info(&thread->arch_info); 1813 kprintf("scheduler data:\n"); 1814 scheduler_dump_thread_data(thread); 1815 } 1816 1817 1818 static int 1819 dump_thread_info(int argc, char **argv) 1820 { 1821 bool shortInfo = false; 1822 int argi = 1; 1823 if (argi < argc && strcmp(argv[argi], "-s") == 0) { 1824 shortInfo = true; 1825 print_thread_list_table_head(); 1826 argi++; 1827 } 1828 1829 if (argi == argc) { 1830 _dump_thread_info(thread_get_current_thread(), shortInfo); 1831 return 0; 1832 } 1833 1834 for (; argi < argc; argi++) { 1835 const char *name = argv[argi]; 1836 ulong arg = strtoul(name, NULL, 0); 1837 1838 if (IS_KERNEL_ADDRESS(arg)) { 1839 // semi-hack 1840 _dump_thread_info((Thread *)arg, shortInfo); 1841 continue; 1842 } 1843 1844 // walk through the thread list, trying to match name or id 1845 bool found = false; 1846 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1847 Thread* thread = it.Next();) { 1848 if (!strcmp(name, thread->name) || thread->id == (thread_id)arg) { 1849 _dump_thread_info(thread, shortInfo); 1850 found = true; 1851 break; 1852 } 1853 } 1854 1855 if (!found) 1856 kprintf("thread \"%s\" (%" B_PRId32 ") doesn't exist!\n", name, (thread_id)arg); 1857 } 1858 1859 return 0; 1860 } 1861 1862 1863 static int 1864 dump_thread_list(int argc, char **argv) 1865 { 1866 bool realTimeOnly = false; 1867 bool calling = false; 1868 const char *callSymbol = NULL; 1869 addr_t callStart = 0; 1870 addr_t callEnd = 0; 1871 int32 requiredState = 0; 1872 team_id team = -1; 1873 sem_id sem = -1; 1874 1875 if (!strcmp(argv[0], "realtime")) 1876 realTimeOnly = true; 1877 else if (!strcmp(argv[0], "ready")) 1878 requiredState = B_THREAD_READY; 1879 else if (!strcmp(argv[0], "running")) 1880 requiredState = B_THREAD_RUNNING; 1881 else if (!strcmp(argv[0], "waiting")) { 1882 requiredState = B_THREAD_WAITING; 1883 1884 if (argc > 1) { 1885 sem = strtoul(argv[1], NULL, 0); 1886 if (sem == 0) 1887 kprintf("ignoring invalid semaphore argument.\n"); 1888 } 1889 } else if (!strcmp(argv[0], "calling")) { 1890 if (argc < 2) { 1891 kprintf("Need to give a symbol name or start and end arguments.\n"); 1892 return 0; 1893 } else if (argc == 3) { 1894 callStart = parse_expression(argv[1]); 1895 callEnd = parse_expression(argv[2]); 1896 } else 1897 callSymbol = argv[1]; 1898 1899 calling = true; 1900 } else if (argc > 1) { 1901 team = strtoul(argv[1], NULL, 0); 1902 if (team == 0) 1903 kprintf("ignoring invalid team argument.\n"); 1904 } 1905 1906 print_thread_list_table_head(); 1907 1908 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1909 Thread* thread = it.Next();) { 1910 // filter out threads not matching the search criteria 1911 if ((requiredState && thread->state != requiredState) 1912 || (calling && !arch_debug_contains_call(thread, callSymbol, 1913 callStart, callEnd)) 1914 || (sem > 0 && get_thread_wait_sem(thread) != sem) 1915 || (team > 0 && thread->team->id != team) 1916 || (realTimeOnly && thread->priority < B_REAL_TIME_DISPLAY_PRIORITY)) 1917 continue; 1918 1919 _dump_thread_info(thread, true); 1920 } 1921 return 0; 1922 } 1923 1924 1925 // #pragma mark - private kernel API 1926 1927 1928 void 1929 thread_exit(void) 1930 { 1931 cpu_status state; 1932 Thread* thread = thread_get_current_thread(); 1933 Team* team = thread->team; 1934 Team* kernelTeam = team_get_kernel_team(); 1935 status_t status; 1936 struct thread_debug_info debugInfo; 1937 team_id teamID = team->id; 1938 1939 TRACE(("thread %" B_PRId32 " exiting w/return code %#" B_PRIx32 "\n", 1940 thread->id, thread->exit.status)); 1941 1942 if (!are_interrupts_enabled()) 1943 panic("thread_exit() called with interrupts disabled!\n"); 1944 1945 // boost our priority to get this over with 1946 scheduler_set_thread_priority(thread, B_URGENT_DISPLAY_PRIORITY); 1947 1948 if (team != kernelTeam) { 1949 // Delete all user timers associated with the thread. 1950 ThreadLocker threadLocker(thread); 1951 thread->DeleteUserTimers(false); 1952 1953 // detach the thread's user thread 1954 user_thread* userThread = thread->user_thread; 1955 thread->user_thread = NULL; 1956 1957 threadLocker.Unlock(); 1958 1959 // Delete the thread's user thread, if it's not the main thread. If it 1960 // is, we can save the work, since it will be deleted with the team's 1961 // address space. 1962 if (thread != team->main_thread) 1963 team_free_user_thread(team, userThread); 1964 } 1965 1966 // remember the user stack area -- we will delete it below 1967 area_id userStackArea = -1; 1968 if (team->address_space != NULL && thread->user_stack_area >= 0) { 1969 userStackArea = thread->user_stack_area; 1970 thread->user_stack_area = -1; 1971 } 1972 1973 struct job_control_entry *death = NULL; 1974 struct thread_death_entry* threadDeathEntry = NULL; 1975 bool deleteTeam = false; 1976 port_id debuggerPort = -1; 1977 1978 if (team != kernelTeam) { 1979 user_debug_thread_exiting(thread); 1980 1981 if (team->main_thread == thread) { 1982 // The main thread is exiting. Shut down the whole team. 1983 deleteTeam = true; 1984 1985 // kill off all other threads and the user debugger facilities 1986 debuggerPort = team_shutdown_team(team); 1987 1988 // acquire necessary locks, which are: process group lock, kernel 1989 // team lock, parent team lock, and the team lock 1990 team->LockProcessGroup(); 1991 kernelTeam->Lock(); 1992 team->LockTeamAndParent(true); 1993 } else { 1994 threadDeathEntry 1995 = (thread_death_entry*)malloc(sizeof(thread_death_entry)); 1996 1997 // acquire necessary locks, which are: kernel team lock and the team 1998 // lock 1999 kernelTeam->Lock(); 2000 team->Lock(); 2001 } 2002 2003 ThreadLocker threadLocker(thread); 2004 2005 state = disable_interrupts(); 2006 2007 // swap address spaces, to make sure we're running on the kernel's pgdir 2008 vm_swap_address_space(team->address_space, VMAddressSpace::Kernel()); 2009 2010 WriteSpinLocker teamLocker(thread->team_lock); 2011 SpinLocker threadCreationLocker(gThreadCreationLock); 2012 // removing the thread and putting its death entry to the parent 2013 // team needs to be an atomic operation 2014 2015 // remember how long this thread lasted 2016 bigtime_t now = system_time(); 2017 2018 InterruptsSpinLocker signalLocker(kernelTeam->signal_lock); 2019 SpinLocker teamTimeLocker(kernelTeam->time_lock); 2020 SpinLocker threadTimeLocker(thread->time_lock); 2021 2022 thread->kernel_time += now - thread->last_time; 2023 thread->last_time = now; 2024 2025 team->dead_threads_kernel_time += thread->kernel_time; 2026 team->dead_threads_user_time += thread->user_time; 2027 2028 // stop/update thread/team CPU time user timers 2029 if (thread->HasActiveCPUTimeUserTimers() 2030 || team->HasActiveCPUTimeUserTimers()) { 2031 user_timer_stop_cpu_timers(thread, NULL); 2032 } 2033 2034 // deactivate CPU time user timers for the thread 2035 if (thread->HasActiveCPUTimeUserTimers()) 2036 thread->DeactivateCPUTimeUserTimers(); 2037 2038 threadTimeLocker.Unlock(); 2039 2040 // put the thread into the kernel team until it dies 2041 remove_thread_from_team(team, thread); 2042 insert_thread_into_team(kernelTeam, thread); 2043 2044 teamTimeLocker.Unlock(); 2045 signalLocker.Unlock(); 2046 2047 teamLocker.Unlock(); 2048 2049 if (team->death_entry != NULL) { 2050 if (--team->death_entry->remaining_threads == 0) 2051 team->death_entry->condition.NotifyOne(); 2052 } 2053 2054 if (deleteTeam) { 2055 Team* parent = team->parent; 2056 2057 // Set the team job control state to "dead" and detach the job 2058 // control entry from our team struct. 2059 team_set_job_control_state(team, JOB_CONTROL_STATE_DEAD, NULL); 2060 death = team->job_control_entry; 2061 team->job_control_entry = NULL; 2062 2063 if (death != NULL) { 2064 death->InitDeadState(); 2065 2066 // team_set_job_control_state() already moved our entry 2067 // into the parent's list. We just check the soft limit of 2068 // death entries. 2069 if (parent->dead_children.count > MAX_DEAD_CHILDREN) { 2070 death = parent->dead_children.entries.RemoveHead(); 2071 parent->dead_children.count--; 2072 } else 2073 death = NULL; 2074 } 2075 2076 threadCreationLocker.Unlock(); 2077 restore_interrupts(state); 2078 2079 threadLocker.Unlock(); 2080 2081 // Get a temporary reference to the team's process group 2082 // -- team_remove_team() removes the team from the group, which 2083 // might destroy it otherwise and we wouldn't be able to unlock it. 2084 ProcessGroup* group = team->group; 2085 group->AcquireReference(); 2086 2087 pid_t foregroundGroupToSignal; 2088 team_remove_team(team, foregroundGroupToSignal); 2089 2090 // unlock everything but the parent team 2091 team->Unlock(); 2092 if (parent != kernelTeam) 2093 kernelTeam->Unlock(); 2094 group->Unlock(); 2095 group->ReleaseReference(); 2096 2097 // Send SIGCHLD to the parent as long as we still have its lock. 2098 // This makes job control state change + signalling atomic. 2099 Signal childSignal(SIGCHLD, team->exit.reason, B_OK, team->id); 2100 if (team->exit.reason == CLD_EXITED) { 2101 childSignal.SetStatus(team->exit.status); 2102 } else { 2103 childSignal.SetStatus(team->exit.signal); 2104 childSignal.SetSendingUser(team->exit.signaling_user); 2105 } 2106 send_signal_to_team(parent, childSignal, B_DO_NOT_RESCHEDULE); 2107 2108 // also unlock the parent 2109 parent->Unlock(); 2110 2111 // If the team was a session leader with controlling TTY, we have 2112 // to send SIGHUP to the foreground process group. 2113 if (foregroundGroupToSignal >= 0) { 2114 Signal groupSignal(SIGHUP, SI_USER, B_OK, team->id); 2115 send_signal_to_process_group(foregroundGroupToSignal, 2116 groupSignal, B_DO_NOT_RESCHEDULE); 2117 } 2118 } else { 2119 // The thread is not the main thread. We store a thread death entry 2120 // for it, unless someone is already waiting for it. 2121 if (threadDeathEntry != NULL 2122 && list_is_empty(&thread->exit.waiters)) { 2123 threadDeathEntry->thread = thread->id; 2124 threadDeathEntry->status = thread->exit.status; 2125 2126 // add entry -- remove an old one, if we hit the limit 2127 list_add_item(&team->dead_threads, threadDeathEntry); 2128 team->dead_threads_count++; 2129 threadDeathEntry = NULL; 2130 2131 if (team->dead_threads_count > MAX_DEAD_THREADS) { 2132 threadDeathEntry 2133 = (thread_death_entry*)list_remove_head_item( 2134 &team->dead_threads); 2135 team->dead_threads_count--; 2136 } 2137 } 2138 2139 threadCreationLocker.Unlock(); 2140 restore_interrupts(state); 2141 2142 threadLocker.Unlock(); 2143 team->Unlock(); 2144 kernelTeam->Unlock(); 2145 } 2146 2147 TRACE(("thread_exit: thread %" B_PRId32 " now a kernel thread!\n", 2148 thread->id)); 2149 } 2150 2151 free(threadDeathEntry); 2152 2153 // delete the team if we're its main thread 2154 if (deleteTeam) { 2155 team_delete_team(team, debuggerPort); 2156 2157 // we need to delete any death entry that made it to here 2158 delete death; 2159 } 2160 2161 ThreadLocker threadLocker(thread); 2162 2163 state = disable_interrupts(); 2164 SpinLocker threadCreationLocker(gThreadCreationLock); 2165 2166 // mark invisible in global hash/list, so it's no longer accessible 2167 SpinLocker threadHashLocker(sThreadHashLock); 2168 thread->visible = false; 2169 sUsedThreads--; 2170 threadHashLocker.Unlock(); 2171 2172 // Stop debugging for this thread 2173 SpinLocker threadDebugInfoLocker(thread->debug_info.lock); 2174 debugInfo = thread->debug_info; 2175 clear_thread_debug_info(&thread->debug_info, true); 2176 threadDebugInfoLocker.Unlock(); 2177 2178 // Remove the select infos. We notify them a little later. 2179 select_info* selectInfos = thread->select_infos; 2180 thread->select_infos = NULL; 2181 2182 threadCreationLocker.Unlock(); 2183 restore_interrupts(state); 2184 2185 threadLocker.Unlock(); 2186 2187 destroy_thread_debug_info(&debugInfo); 2188 2189 // notify select infos 2190 select_info* info = selectInfos; 2191 while (info != NULL) { 2192 select_sync* sync = info->sync; 2193 2194 notify_select_events(info, B_EVENT_INVALID); 2195 info = info->next; 2196 put_select_sync(sync); 2197 } 2198 2199 // notify listeners 2200 sNotificationService.Notify(THREAD_REMOVED, thread); 2201 2202 // shutdown the thread messaging 2203 2204 status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0); 2205 if (status == B_WOULD_BLOCK) { 2206 // there is data waiting for us, so let us eat it 2207 thread_id sender; 2208 2209 delete_sem(thread->msg.write_sem); 2210 // first, let's remove all possibly waiting writers 2211 receive_data_etc(&sender, NULL, 0, B_RELATIVE_TIMEOUT); 2212 } else { 2213 // we probably own the semaphore here, and we're the last to do so 2214 delete_sem(thread->msg.write_sem); 2215 } 2216 // now we can safely remove the msg.read_sem 2217 delete_sem(thread->msg.read_sem); 2218 2219 // fill all death entries and delete the sem that others will use to wait 2220 // for us 2221 { 2222 sem_id cachedExitSem = thread->exit.sem; 2223 2224 ThreadLocker threadLocker(thread); 2225 2226 // make sure no one will grab this semaphore again 2227 thread->exit.sem = -1; 2228 2229 // fill all death entries 2230 thread_death_entry* entry = NULL; 2231 while ((entry = (thread_death_entry*)list_get_next_item( 2232 &thread->exit.waiters, entry)) != NULL) { 2233 entry->status = thread->exit.status; 2234 } 2235 2236 threadLocker.Unlock(); 2237 2238 delete_sem(cachedExitSem); 2239 } 2240 2241 // delete the user stack, if this was a user thread 2242 if (!deleteTeam && userStackArea >= 0) { 2243 // We postponed deleting the user stack until now, since this way all 2244 // notifications for the thread's death are out already and all other 2245 // threads waiting for this thread's death and some object on its stack 2246 // will wake up before we (try to) delete the stack area. Of most 2247 // relevance is probably the case where this is the main thread and 2248 // other threads use objects on its stack -- so we want them terminated 2249 // first. 2250 // When the team is deleted, all areas are deleted anyway, so we don't 2251 // need to do that explicitly in that case. 2252 vm_delete_area(teamID, userStackArea, true); 2253 } 2254 2255 // notify the debugger 2256 if (teamID != kernelTeam->id) 2257 user_debug_thread_deleted(teamID, thread->id); 2258 2259 // enqueue in the undertaker list and reschedule for the last time 2260 UndertakerEntry undertakerEntry(thread, teamID); 2261 2262 disable_interrupts(); 2263 2264 SpinLocker schedulerLocker(thread->scheduler_lock); 2265 2266 SpinLocker undertakerLocker(sUndertakerLock); 2267 sUndertakerEntries.Add(&undertakerEntry); 2268 sUndertakerCondition.NotifyOne(); 2269 undertakerLocker.Unlock(); 2270 2271 scheduler_reschedule(THREAD_STATE_FREE_ON_RESCHED); 2272 2273 panic("never can get here\n"); 2274 } 2275 2276 2277 /*! Called in the interrupt handler code when a thread enters 2278 the kernel for any reason. 2279 Only tracks time for now. 2280 Interrupts are disabled. 2281 */ 2282 void 2283 thread_at_kernel_entry(bigtime_t now) 2284 { 2285 Thread *thread = thread_get_current_thread(); 2286 2287 TRACE(("thread_at_kernel_entry: entry thread %" B_PRId32 "\n", thread->id)); 2288 2289 // track user time 2290 SpinLocker threadTimeLocker(thread->time_lock); 2291 thread->user_time += now - thread->last_time; 2292 thread->last_time = now; 2293 thread->in_kernel = true; 2294 threadTimeLocker.Unlock(); 2295 } 2296 2297 2298 /*! Called whenever a thread exits kernel space to user space. 2299 Tracks time, handles signals, ... 2300 Interrupts must be enabled. When the function returns, interrupts will be 2301 disabled. 2302 The function may not return. This e.g. happens when the thread has received 2303 a deadly signal. 2304 */ 2305 void 2306 thread_at_kernel_exit(void) 2307 { 2308 Thread *thread = thread_get_current_thread(); 2309 2310 TRACE(("thread_at_kernel_exit: exit thread %" B_PRId32 "\n", thread->id)); 2311 2312 handle_signals(thread); 2313 2314 disable_interrupts(); 2315 2316 // track kernel time 2317 bigtime_t now = system_time(); 2318 SpinLocker threadTimeLocker(thread->time_lock); 2319 thread->in_kernel = false; 2320 thread->kernel_time += now - thread->last_time; 2321 thread->last_time = now; 2322 } 2323 2324 2325 /*! The quick version of thread_kernel_exit(), in case no signals are pending 2326 and no debugging shall be done. 2327 Interrupts must be disabled. 2328 */ 2329 void 2330 thread_at_kernel_exit_no_signals(void) 2331 { 2332 Thread *thread = thread_get_current_thread(); 2333 2334 TRACE(("thread_at_kernel_exit_no_signals: exit thread %" B_PRId32 "\n", 2335 thread->id)); 2336 2337 // track kernel time 2338 bigtime_t now = system_time(); 2339 SpinLocker threadTimeLocker(thread->time_lock); 2340 thread->in_kernel = false; 2341 thread->kernel_time += now - thread->last_time; 2342 thread->last_time = now; 2343 } 2344 2345 2346 void 2347 thread_reset_for_exec(void) 2348 { 2349 Thread* thread = thread_get_current_thread(); 2350 2351 ThreadLocker threadLocker(thread); 2352 2353 // delete user-defined timers 2354 thread->DeleteUserTimers(true); 2355 2356 // cancel pre-defined timer 2357 if (UserTimer* timer = thread->UserTimerFor(USER_TIMER_REAL_TIME_ID)) 2358 timer->Cancel(); 2359 2360 // reset user_thread and user stack 2361 thread->user_thread = NULL; 2362 thread->user_stack_area = -1; 2363 thread->user_stack_base = 0; 2364 thread->user_stack_size = 0; 2365 2366 // reset signals 2367 thread->ResetSignalsOnExec(); 2368 2369 // reset thread CPU time clock 2370 InterruptsSpinLocker timeLocker(thread->time_lock); 2371 thread->cpu_clock_offset = -thread->CPUTime(false); 2372 } 2373 2374 2375 thread_id 2376 allocate_thread_id() 2377 { 2378 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2379 2380 // find the next unused ID 2381 thread_id id; 2382 do { 2383 id = sNextThreadID++; 2384 2385 // deal with integer overflow 2386 if (sNextThreadID < 0) 2387 sNextThreadID = 2; 2388 2389 // check whether the ID is already in use 2390 } while (sThreadHash.Lookup(id, false) != NULL); 2391 2392 return id; 2393 } 2394 2395 2396 thread_id 2397 peek_next_thread_id() 2398 { 2399 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2400 return sNextThreadID; 2401 } 2402 2403 2404 /*! Yield the CPU to other threads. 2405 Thread will continue to run, if there's no other thread in ready 2406 state, and if it has a higher priority than the other ready threads, it 2407 still has a good chance to continue. 2408 */ 2409 void 2410 thread_yield(void) 2411 { 2412 Thread *thread = thread_get_current_thread(); 2413 if (thread == NULL) 2414 return; 2415 2416 InterruptsSpinLocker _(thread->scheduler_lock); 2417 2418 thread->has_yielded = true; 2419 scheduler_reschedule(B_THREAD_READY); 2420 } 2421 2422 2423 void 2424 thread_map(void (*function)(Thread* thread, void* data), void* data) 2425 { 2426 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2427 2428 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 2429 Thread* thread = it.Next();) { 2430 function(thread, data); 2431 } 2432 } 2433 2434 2435 /*! Kernel private thread creation function. 2436 */ 2437 thread_id 2438 spawn_kernel_thread_etc(thread_func function, const char *name, int32 priority, 2439 void *arg, team_id team) 2440 { 2441 return thread_create_thread( 2442 ThreadCreationAttributes(function, name, priority, arg, team), 2443 true); 2444 } 2445 2446 2447 status_t 2448 wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, 2449 status_t *_returnCode) 2450 { 2451 if (id < 0) 2452 return B_BAD_THREAD_ID; 2453 2454 // get the thread, queue our death entry, and fetch the semaphore we have to 2455 // wait on 2456 sem_id exitSem = B_BAD_THREAD_ID; 2457 struct thread_death_entry death; 2458 2459 Thread* thread = Thread::GetAndLock(id); 2460 if (thread != NULL) { 2461 // remember the semaphore we have to wait on and place our death entry 2462 exitSem = thread->exit.sem; 2463 if (exitSem >= 0) 2464 list_add_link_to_head(&thread->exit.waiters, &death); 2465 2466 thread->UnlockAndReleaseReference(); 2467 2468 if (exitSem < 0) 2469 return B_BAD_THREAD_ID; 2470 } else { 2471 // we couldn't find this thread -- maybe it's already gone, and we'll 2472 // find its death entry in our team 2473 Team* team = thread_get_current_thread()->team; 2474 TeamLocker teamLocker(team); 2475 2476 // check the child death entries first (i.e. main threads of child 2477 // teams) 2478 bool deleteEntry; 2479 job_control_entry* freeDeath 2480 = team_get_death_entry(team, id, &deleteEntry); 2481 if (freeDeath != NULL) { 2482 death.status = freeDeath->status; 2483 if (deleteEntry) 2484 delete freeDeath; 2485 } else { 2486 // check the thread death entries of the team (non-main threads) 2487 thread_death_entry* threadDeathEntry = NULL; 2488 while ((threadDeathEntry = (thread_death_entry*)list_get_next_item( 2489 &team->dead_threads, threadDeathEntry)) != NULL) { 2490 if (threadDeathEntry->thread == id) { 2491 list_remove_item(&team->dead_threads, threadDeathEntry); 2492 team->dead_threads_count--; 2493 death.status = threadDeathEntry->status; 2494 free(threadDeathEntry); 2495 break; 2496 } 2497 } 2498 2499 if (threadDeathEntry == NULL) 2500 return B_BAD_THREAD_ID; 2501 } 2502 2503 // we found the thread's death entry in our team 2504 if (_returnCode) 2505 *_returnCode = death.status; 2506 2507 return B_OK; 2508 } 2509 2510 // we need to wait for the death of the thread 2511 2512 resume_thread(id); 2513 // make sure we don't wait forever on a suspended thread 2514 2515 status_t status = acquire_sem_etc(exitSem, 1, flags, timeout); 2516 2517 if (status == B_OK) { 2518 // this should never happen as the thread deletes the semaphore on exit 2519 panic("could acquire exit_sem for thread %" B_PRId32 "\n", id); 2520 } else if (status == B_BAD_SEM_ID) { 2521 // this is the way the thread normally exits 2522 status = B_OK; 2523 } else { 2524 // We were probably interrupted or the timeout occurred; we need to 2525 // remove our death entry now. 2526 thread = Thread::GetAndLock(id); 2527 if (thread != NULL) { 2528 list_remove_link(&death); 2529 thread->UnlockAndReleaseReference(); 2530 } else { 2531 // The thread is already gone, so we need to wait uninterruptibly 2532 // for its exit semaphore to make sure our death entry stays valid. 2533 // It won't take long, since the thread is apparently already in the 2534 // middle of the cleanup. 2535 acquire_sem(exitSem); 2536 status = B_OK; 2537 } 2538 } 2539 2540 if (status == B_OK && _returnCode != NULL) 2541 *_returnCode = death.status; 2542 2543 return status; 2544 } 2545 2546 2547 status_t 2548 select_thread(int32 id, struct select_info* info, bool kernel) 2549 { 2550 // get and lock the thread 2551 Thread* thread = Thread::GetAndLock(id); 2552 if (thread == NULL) 2553 return B_BAD_THREAD_ID; 2554 BReference<Thread> threadReference(thread, true); 2555 ThreadLocker threadLocker(thread, true); 2556 2557 // We support only B_EVENT_INVALID at the moment. 2558 info->selected_events &= B_EVENT_INVALID; 2559 2560 // add info to list 2561 if (info->selected_events != 0) { 2562 info->next = thread->select_infos; 2563 thread->select_infos = info; 2564 2565 // we need a sync reference 2566 atomic_add(&info->sync->ref_count, 1); 2567 } 2568 2569 return B_OK; 2570 } 2571 2572 2573 status_t 2574 deselect_thread(int32 id, struct select_info* info, bool kernel) 2575 { 2576 // get and lock the thread 2577 Thread* thread = Thread::GetAndLock(id); 2578 if (thread == NULL) 2579 return B_BAD_THREAD_ID; 2580 BReference<Thread> threadReference(thread, true); 2581 ThreadLocker threadLocker(thread, true); 2582 2583 // remove info from list 2584 select_info** infoLocation = &thread->select_infos; 2585 while (*infoLocation != NULL && *infoLocation != info) 2586 infoLocation = &(*infoLocation)->next; 2587 2588 if (*infoLocation != info) 2589 return B_OK; 2590 2591 *infoLocation = info->next; 2592 2593 threadLocker.Unlock(); 2594 2595 // surrender sync reference 2596 put_select_sync(info->sync); 2597 2598 return B_OK; 2599 } 2600 2601 2602 int32 2603 thread_max_threads(void) 2604 { 2605 return sMaxThreads; 2606 } 2607 2608 2609 int32 2610 thread_used_threads(void) 2611 { 2612 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2613 return sUsedThreads; 2614 } 2615 2616 2617 /*! Returns a user-readable string for a thread state. 2618 Only for use in the kernel debugger. 2619 */ 2620 const char* 2621 thread_state_to_text(Thread* thread, int32 state) 2622 { 2623 return state_to_text(thread, state); 2624 } 2625 2626 2627 int32 2628 thread_get_io_priority(thread_id id) 2629 { 2630 Thread* thread = Thread::GetAndLock(id); 2631 if (thread == NULL) 2632 return B_BAD_THREAD_ID; 2633 BReference<Thread> threadReference(thread, true); 2634 ThreadLocker threadLocker(thread, true); 2635 2636 int32 priority = thread->io_priority; 2637 if (priority < 0) { 2638 // negative I/O priority means using the (CPU) priority 2639 priority = thread->priority; 2640 } 2641 2642 return priority; 2643 } 2644 2645 2646 void 2647 thread_set_io_priority(int32 priority) 2648 { 2649 Thread* thread = thread_get_current_thread(); 2650 ThreadLocker threadLocker(thread); 2651 2652 thread->io_priority = priority; 2653 } 2654 2655 2656 status_t 2657 thread_init(kernel_args *args) 2658 { 2659 TRACE(("thread_init: entry\n")); 2660 2661 // create the thread hash table 2662 new(&sThreadHash) ThreadHashTable(); 2663 if (sThreadHash.Init(128) != B_OK) 2664 panic("thread_init(): failed to init thread hash table!"); 2665 2666 // create the thread structure object cache 2667 sThreadCache = create_object_cache("threads", sizeof(Thread), 16, NULL, 2668 NULL, NULL); 2669 // Note: The x86 port requires 16 byte alignment of thread structures. 2670 if (sThreadCache == NULL) 2671 panic("thread_init(): failed to allocate thread object cache!"); 2672 2673 if (arch_thread_init(args) < B_OK) 2674 panic("arch_thread_init() failed!\n"); 2675 2676 // skip all thread IDs including B_SYSTEM_TEAM, which is reserved 2677 sNextThreadID = B_SYSTEM_TEAM + 1; 2678 2679 // create an idle thread for each cpu 2680 for (uint32 i = 0; i < args->num_cpus; i++) { 2681 Thread *thread; 2682 area_info info; 2683 char name[64]; 2684 2685 sprintf(name, "idle thread %" B_PRIu32, i + 1); 2686 thread = new(&sIdleThreads[i]) Thread(name, 2687 i == 0 ? team_get_kernel_team_id() : -1, &gCPU[i]); 2688 if (thread == NULL || thread->Init(true) != B_OK) { 2689 panic("error creating idle thread struct\n"); 2690 return B_NO_MEMORY; 2691 } 2692 2693 gCPU[i].running_thread = thread; 2694 2695 thread->team = team_get_kernel_team(); 2696 thread->priority = B_IDLE_PRIORITY; 2697 thread->state = B_THREAD_RUNNING; 2698 sprintf(name, "idle thread %" B_PRIu32 " kstack", i + 1); 2699 thread->kernel_stack_area = find_area(name); 2700 2701 if (get_area_info(thread->kernel_stack_area, &info) != B_OK) 2702 panic("error finding idle kstack area\n"); 2703 2704 thread->kernel_stack_base = (addr_t)info.address; 2705 thread->kernel_stack_top = thread->kernel_stack_base + info.size; 2706 2707 thread->visible = true; 2708 insert_thread_into_team(thread->team, thread); 2709 2710 scheduler_on_thread_init(thread); 2711 } 2712 sUsedThreads = args->num_cpus; 2713 2714 // init the notification service 2715 new(&sNotificationService) ThreadNotificationService(); 2716 2717 sNotificationService.Register(); 2718 2719 // start the undertaker thread 2720 new(&sUndertakerEntries) DoublyLinkedList<UndertakerEntry>(); 2721 sUndertakerCondition.Init(&sUndertakerEntries, "undertaker entries"); 2722 2723 thread_id undertakerThread = spawn_kernel_thread(&undertaker, "undertaker", 2724 B_DISPLAY_PRIORITY, NULL); 2725 if (undertakerThread < 0) 2726 panic("Failed to create undertaker thread!"); 2727 resume_thread(undertakerThread); 2728 2729 // set up some debugger commands 2730 add_debugger_command_etc("threads", &dump_thread_list, "List all threads", 2731 "[ <team> ]\n" 2732 "Prints a list of all existing threads, or, if a team ID is given,\n" 2733 "all threads of the specified team.\n" 2734 " <team> - The ID of the team whose threads shall be listed.\n", 0); 2735 add_debugger_command_etc("ready", &dump_thread_list, 2736 "List all ready threads", 2737 "\n" 2738 "Prints a list of all threads in ready state.\n", 0); 2739 add_debugger_command_etc("running", &dump_thread_list, 2740 "List all running threads", 2741 "\n" 2742 "Prints a list of all threads in running state.\n", 0); 2743 add_debugger_command_etc("waiting", &dump_thread_list, 2744 "List all waiting threads (optionally for a specific semaphore)", 2745 "[ <sem> ]\n" 2746 "Prints a list of all threads in waiting state. If a semaphore is\n" 2747 "specified, only the threads waiting on that semaphore are listed.\n" 2748 " <sem> - ID of the semaphore.\n", 0); 2749 add_debugger_command_etc("realtime", &dump_thread_list, 2750 "List all realtime threads", 2751 "\n" 2752 "Prints a list of all threads with realtime priority.\n", 0); 2753 add_debugger_command_etc("thread", &dump_thread_info, 2754 "Dump info about a particular thread", 2755 "[ -s ] ( <id> | <address> | <name> )*\n" 2756 "Prints information about the specified thread. If no argument is\n" 2757 "given the current thread is selected.\n" 2758 " -s - Print info in compact table form (like \"threads\").\n" 2759 " <id> - The ID of the thread.\n" 2760 " <address> - The address of the thread structure.\n" 2761 " <name> - The thread's name.\n", 0); 2762 add_debugger_command_etc("calling", &dump_thread_list, 2763 "Show all threads that have a specific address in their call chain", 2764 "{ <symbol-pattern> | <start> <end> }\n", 0); 2765 add_debugger_command_etc("unreal", &make_thread_unreal, 2766 "Set realtime priority threads to normal priority", 2767 "[ <id> ]\n" 2768 "Sets the priority of all realtime threads or, if given, the one\n" 2769 "with the specified ID to \"normal\" priority.\n" 2770 " <id> - The ID of the thread.\n", 0); 2771 add_debugger_command_etc("suspend", &make_thread_suspended, 2772 "Suspend a thread", 2773 "[ <id> ]\n" 2774 "Suspends the thread with the given ID. If no ID argument is given\n" 2775 "the current thread is selected.\n" 2776 " <id> - The ID of the thread.\n", 0); 2777 add_debugger_command_etc("resume", &make_thread_resumed, "Resume a thread", 2778 "<id>\n" 2779 "Resumes the specified thread, if it is currently suspended.\n" 2780 " <id> - The ID of the thread.\n", 0); 2781 add_debugger_command_etc("drop", &drop_into_debugger, 2782 "Drop a thread into the userland debugger", 2783 "<id>\n" 2784 "Drops the specified (userland) thread into the userland debugger\n" 2785 "after leaving the kernel debugger.\n" 2786 " <id> - The ID of the thread.\n", 0); 2787 add_debugger_command_etc("priority", &set_thread_prio, 2788 "Set a thread's priority", 2789 "<priority> [ <id> ]\n" 2790 "Sets the priority of the thread with the specified ID to the given\n" 2791 "priority. If no thread ID is given, the current thread is selected.\n" 2792 " <priority> - The thread's new priority (0 - 120)\n" 2793 " <id> - The ID of the thread.\n", 0); 2794 2795 return B_OK; 2796 } 2797 2798 2799 status_t 2800 thread_preboot_init_percpu(struct kernel_args *args, int32 cpuNum) 2801 { 2802 // set up the cpu pointer in the not yet initialized per-cpu idle thread 2803 // so that get_current_cpu and friends will work, which is crucial for 2804 // a lot of low level routines 2805 sIdleThreads[cpuNum].cpu = &gCPU[cpuNum]; 2806 arch_thread_set_current_thread(&sIdleThreads[cpuNum]); 2807 return B_OK; 2808 } 2809 2810 2811 // #pragma mark - thread blocking API 2812 2813 2814 static status_t 2815 thread_block_timeout(timer* timer) 2816 { 2817 Thread* thread = (Thread*)timer->user_data; 2818 thread_unblock(thread, B_TIMED_OUT); 2819 2820 return B_HANDLED_INTERRUPT; 2821 } 2822 2823 2824 /*! Blocks the current thread. 2825 2826 The thread is blocked until someone else unblock it. Must be called after a 2827 call to thread_prepare_to_block(). If the thread has already been unblocked 2828 after the previous call to thread_prepare_to_block(), this function will 2829 return immediately. Cf. the documentation of thread_prepare_to_block() for 2830 more details. 2831 2832 The caller must hold the scheduler lock. 2833 2834 \param thread The current thread. 2835 \return The error code passed to the unblocking function. thread_interrupt() 2836 uses \c B_INTERRUPTED. By convention \c B_OK means that the wait was 2837 successful while another error code indicates a failure (what that means 2838 depends on the client code). 2839 */ 2840 static inline status_t 2841 thread_block_locked(Thread* thread) 2842 { 2843 if (thread->wait.status == 1) { 2844 // check for signals, if interruptible 2845 if (thread_is_interrupted(thread, thread->wait.flags)) { 2846 thread->wait.status = B_INTERRUPTED; 2847 } else 2848 scheduler_reschedule(B_THREAD_WAITING); 2849 } 2850 2851 return thread->wait.status; 2852 } 2853 2854 2855 /*! Blocks the current thread. 2856 2857 The function acquires the scheduler lock and calls thread_block_locked(). 2858 See there for more information. 2859 */ 2860 status_t 2861 thread_block() 2862 { 2863 InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock); 2864 return thread_block_locked(thread_get_current_thread()); 2865 } 2866 2867 2868 /*! Blocks the current thread with a timeout. 2869 2870 The current thread is blocked until someone else unblock it or the specified 2871 timeout occurs. Must be called after a call to thread_prepare_to_block(). If 2872 the thread has already been unblocked after the previous call to 2873 thread_prepare_to_block(), this function will return immediately. See 2874 thread_prepare_to_block() for more details. 2875 2876 The caller must not hold the scheduler lock. 2877 2878 \param timeoutFlags The standard timeout flags: 2879 - \c B_RELATIVE_TIMEOUT: \a timeout specifies the time to wait. 2880 - \c B_ABSOLUTE_TIMEOUT: \a timeout specifies the absolute end time when 2881 the timeout shall occur. 2882 - \c B_TIMEOUT_REAL_TIME_BASE: Only relevant when \c B_ABSOLUTE_TIMEOUT 2883 is specified, too. Specifies that \a timeout is a real time, not a 2884 system time. 2885 If neither \c B_RELATIVE_TIMEOUT nor \c B_ABSOLUTE_TIMEOUT are 2886 specified, an infinite timeout is implied and the function behaves like 2887 thread_block_locked(). 2888 \return The error code passed to the unblocking function. thread_interrupt() 2889 uses \c B_INTERRUPTED. When the timeout occurred, \c B_TIMED_OUT is 2890 returned. By convention \c B_OK means that the wait was successful while 2891 another error code indicates a failure (what that means depends on the 2892 client code). 2893 */ 2894 status_t 2895 thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout) 2896 { 2897 Thread* thread = thread_get_current_thread(); 2898 2899 InterruptsSpinLocker locker(thread->scheduler_lock); 2900 2901 if (thread->wait.status != 1) 2902 return thread->wait.status; 2903 2904 bool useTimer = (timeoutFlags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) 2905 && timeout != B_INFINITE_TIMEOUT; 2906 2907 if (useTimer) { 2908 // Timer flags: absolute/relative. 2909 uint32 timerFlags; 2910 if ((timeoutFlags & B_RELATIVE_TIMEOUT) != 0) { 2911 timerFlags = B_ONE_SHOT_RELATIVE_TIMER; 2912 } else { 2913 timerFlags = B_ONE_SHOT_ABSOLUTE_TIMER; 2914 if ((timeoutFlags & B_TIMEOUT_REAL_TIME_BASE) != 0) 2915 timerFlags |= B_TIMER_REAL_TIME_BASE; 2916 } 2917 2918 // install the timer 2919 thread->wait.unblock_timer.user_data = thread; 2920 add_timer(&thread->wait.unblock_timer, &thread_block_timeout, timeout, 2921 timerFlags); 2922 } 2923 2924 // block 2925 status_t error = thread_block_locked(thread); 2926 2927 locker.Unlock(); 2928 2929 // cancel timer, if it didn't fire 2930 if (error != B_TIMED_OUT && useTimer) 2931 cancel_timer(&thread->wait.unblock_timer); 2932 2933 return error; 2934 } 2935 2936 2937 /*! Unblocks a thread. 2938 2939 Acquires the scheduler lock and calls thread_unblock_locked(). 2940 See there for more information. 2941 */ 2942 void 2943 thread_unblock(Thread* thread, status_t status) 2944 { 2945 InterruptsSpinLocker locker(thread->scheduler_lock); 2946 thread_unblock_locked(thread, status); 2947 } 2948 2949 2950 /*! Unblocks a userland-blocked thread. 2951 The caller must not hold any locks. 2952 */ 2953 static status_t 2954 user_unblock_thread(thread_id threadID, status_t status) 2955 { 2956 // get the thread 2957 Thread* thread = Thread::GetAndLock(threadID); 2958 if (thread == NULL) 2959 return B_BAD_THREAD_ID; 2960 BReference<Thread> threadReference(thread, true); 2961 ThreadLocker threadLocker(thread, true); 2962 2963 if (thread->user_thread == NULL) 2964 return B_NOT_ALLOWED; 2965 2966 InterruptsSpinLocker locker(thread->scheduler_lock); 2967 2968 set_ac(); 2969 if (thread->user_thread->wait_status > 0) { 2970 thread->user_thread->wait_status = status; 2971 clear_ac(); 2972 thread_unblock_locked(thread, status); 2973 } else 2974 clear_ac(); 2975 2976 return B_OK; 2977 } 2978 2979 2980 // #pragma mark - public kernel API 2981 2982 2983 void 2984 exit_thread(status_t returnValue) 2985 { 2986 Thread *thread = thread_get_current_thread(); 2987 Team* team = thread->team; 2988 2989 thread->exit.status = returnValue; 2990 2991 // if called from a kernel thread, we don't deliver the signal, 2992 // we just exit directly to keep the user space behaviour of 2993 // this function 2994 if (team != team_get_kernel_team()) { 2995 // If this is its main thread, set the team's exit status. 2996 if (thread == team->main_thread) { 2997 TeamLocker teamLocker(team); 2998 2999 if (!team->exit.initialized) { 3000 team->exit.reason = CLD_EXITED; 3001 team->exit.signal = 0; 3002 team->exit.signaling_user = 0; 3003 team->exit.status = returnValue; 3004 team->exit.initialized = true; 3005 } 3006 3007 teamLocker.Unlock(); 3008 } 3009 3010 Signal signal(SIGKILLTHR, SI_USER, B_OK, team->id); 3011 send_signal_to_thread(thread, signal, B_DO_NOT_RESCHEDULE); 3012 } else 3013 thread_exit(); 3014 } 3015 3016 3017 status_t 3018 kill_thread(thread_id id) 3019 { 3020 if (id <= 0) 3021 return B_BAD_VALUE; 3022 3023 Thread* currentThread = thread_get_current_thread(); 3024 3025 Signal signal(SIGKILLTHR, SI_USER, B_OK, currentThread->team->id); 3026 return send_signal_to_thread_id(id, signal, 0); 3027 } 3028 3029 3030 status_t 3031 send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize) 3032 { 3033 return send_data_etc(thread, code, buffer, bufferSize, 0); 3034 } 3035 3036 3037 int32 3038 receive_data(thread_id *sender, void *buffer, size_t bufferSize) 3039 { 3040 return receive_data_etc(sender, buffer, bufferSize, 0); 3041 } 3042 3043 3044 bool 3045 has_data(thread_id thread) 3046 { 3047 // TODO: The thread argument is ignored. 3048 int32 count; 3049 3050 if (get_sem_count(thread_get_current_thread()->msg.read_sem, 3051 &count) != B_OK) 3052 return false; 3053 3054 return count == 0 ? false : true; 3055 } 3056 3057 3058 status_t 3059 _get_thread_info(thread_id id, thread_info *info, size_t size) 3060 { 3061 if (info == NULL || size != sizeof(thread_info) || id < B_OK) 3062 return B_BAD_VALUE; 3063 3064 // get the thread 3065 Thread* thread = Thread::GetAndLock(id); 3066 if (thread == NULL) 3067 return B_BAD_THREAD_ID; 3068 BReference<Thread> threadReference(thread, true); 3069 ThreadLocker threadLocker(thread, true); 3070 3071 // fill the info -- also requires the scheduler lock to be held 3072 InterruptsSpinLocker locker(thread->scheduler_lock); 3073 3074 fill_thread_info(thread, info, size); 3075 3076 return B_OK; 3077 } 3078 3079 3080 status_t 3081 _get_next_thread_info(team_id teamID, int32 *_cookie, thread_info *info, 3082 size_t size) 3083 { 3084 if (info == NULL || size != sizeof(thread_info) || teamID < 0) 3085 return B_BAD_VALUE; 3086 3087 int32 lastID = *_cookie; 3088 3089 // get the team 3090 Team* team = Team::GetAndLock(teamID); 3091 if (team == NULL) 3092 return B_BAD_VALUE; 3093 BReference<Team> teamReference(team, true); 3094 TeamLocker teamLocker(team, true); 3095 3096 Thread* thread = NULL; 3097 3098 if (lastID == 0) { 3099 // We start with the main thread 3100 thread = team->main_thread; 3101 } else { 3102 // Find the one thread with an ID greater than ours (as long as the IDs 3103 // don't wrap they are always sorted from highest to lowest). 3104 // TODO: That is broken not only when the IDs wrap, but also for the 3105 // kernel team, to which threads are added when they are dying. 3106 for (Thread* next = team->thread_list; next != NULL; 3107 next = next->team_next) { 3108 if (next->id <= lastID) 3109 break; 3110 3111 thread = next; 3112 } 3113 } 3114 3115 if (thread == NULL) 3116 return B_BAD_VALUE; 3117 3118 lastID = thread->id; 3119 *_cookie = lastID; 3120 3121 ThreadLocker threadLocker(thread); 3122 InterruptsSpinLocker locker(thread->scheduler_lock); 3123 3124 fill_thread_info(thread, info, size); 3125 3126 return B_OK; 3127 } 3128 3129 3130 thread_id 3131 find_thread(const char* name) 3132 { 3133 if (name == NULL) 3134 return thread_get_current_thread_id(); 3135 3136 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 3137 3138 // TODO: Scanning the whole hash with the thread hash lock held isn't 3139 // exactly cheap -- although this function is probably used very rarely. 3140 3141 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 3142 Thread* thread = it.Next();) { 3143 if (!thread->visible) 3144 continue; 3145 3146 if (strcmp(thread->name, name) == 0) 3147 return thread->id; 3148 } 3149 3150 return B_NAME_NOT_FOUND; 3151 } 3152 3153 3154 status_t 3155 rename_thread(thread_id id, const char* name) 3156 { 3157 if (name == NULL) 3158 return B_BAD_VALUE; 3159 3160 // get the thread 3161 Thread* thread = Thread::GetAndLock(id); 3162 if (thread == NULL) 3163 return B_BAD_THREAD_ID; 3164 BReference<Thread> threadReference(thread, true); 3165 ThreadLocker threadLocker(thread, true); 3166 3167 // check whether the operation is allowed 3168 if (thread->team != thread_get_current_thread()->team) 3169 return B_NOT_ALLOWED; 3170 3171 strlcpy(thread->name, name, B_OS_NAME_LENGTH); 3172 3173 team_id teamID = thread->team->id; 3174 3175 threadLocker.Unlock(); 3176 3177 // notify listeners 3178 sNotificationService.Notify(THREAD_NAME_CHANGED, teamID, id); 3179 // don't pass the thread structure, as it's unsafe, if it isn't ours 3180 3181 return B_OK; 3182 } 3183 3184 3185 status_t 3186 set_thread_priority(thread_id id, int32 priority) 3187 { 3188 // make sure the passed in priority is within bounds 3189 if (priority > THREAD_MAX_SET_PRIORITY) 3190 priority = THREAD_MAX_SET_PRIORITY; 3191 if (priority < THREAD_MIN_SET_PRIORITY) 3192 priority = THREAD_MIN_SET_PRIORITY; 3193 3194 // get the thread 3195 Thread* thread = Thread::GetAndLock(id); 3196 if (thread == NULL) 3197 return B_BAD_THREAD_ID; 3198 BReference<Thread> threadReference(thread, true); 3199 ThreadLocker threadLocker(thread, true); 3200 3201 // check whether the change is allowed 3202 if (thread_is_idle_thread(thread)) 3203 return B_NOT_ALLOWED; 3204 3205 return scheduler_set_thread_priority(thread, priority); 3206 } 3207 3208 3209 status_t 3210 snooze_etc(bigtime_t timeout, int timebase, uint32 flags) 3211 { 3212 return common_snooze_etc(timeout, timebase, flags, NULL); 3213 } 3214 3215 3216 /*! snooze() for internal kernel use only; doesn't interrupt on signals. */ 3217 status_t 3218 snooze(bigtime_t timeout) 3219 { 3220 return snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT); 3221 } 3222 3223 3224 /*! snooze_until() for internal kernel use only; doesn't interrupt on 3225 signals. 3226 */ 3227 status_t 3228 snooze_until(bigtime_t timeout, int timebase) 3229 { 3230 return snooze_etc(timeout, timebase, B_ABSOLUTE_TIMEOUT); 3231 } 3232 3233 3234 status_t 3235 wait_for_thread(thread_id thread, status_t *_returnCode) 3236 { 3237 return wait_for_thread_etc(thread, 0, 0, _returnCode); 3238 } 3239 3240 3241 status_t 3242 suspend_thread(thread_id id) 3243 { 3244 if (id <= 0) 3245 return B_BAD_VALUE; 3246 3247 Thread* currentThread = thread_get_current_thread(); 3248 3249 Signal signal(SIGSTOP, SI_USER, B_OK, currentThread->team->id); 3250 return send_signal_to_thread_id(id, signal, 0); 3251 } 3252 3253 3254 status_t 3255 resume_thread(thread_id id) 3256 { 3257 if (id <= 0) 3258 return B_BAD_VALUE; 3259 3260 Thread* currentThread = thread_get_current_thread(); 3261 3262 // Using the kernel internal SIGNAL_CONTINUE_THREAD signal retains 3263 // compatibility to BeOS which documents the combination of suspend_thread() 3264 // and resume_thread() to interrupt threads waiting on semaphores. 3265 Signal signal(SIGNAL_CONTINUE_THREAD, SI_USER, B_OK, 3266 currentThread->team->id); 3267 return send_signal_to_thread_id(id, signal, 0); 3268 } 3269 3270 3271 thread_id 3272 spawn_kernel_thread(thread_func function, const char *name, int32 priority, 3273 void *arg) 3274 { 3275 return thread_create_thread( 3276 ThreadCreationAttributes(function, name, priority, arg), 3277 true); 3278 } 3279 3280 3281 int 3282 getrlimit(int resource, struct rlimit * rlp) 3283 { 3284 status_t error = common_getrlimit(resource, rlp); 3285 if (error != B_OK) { 3286 errno = error; 3287 return -1; 3288 } 3289 3290 return 0; 3291 } 3292 3293 3294 int 3295 setrlimit(int resource, const struct rlimit * rlp) 3296 { 3297 status_t error = common_setrlimit(resource, rlp); 3298 if (error != B_OK) { 3299 errno = error; 3300 return -1; 3301 } 3302 3303 return 0; 3304 } 3305 3306 3307 // #pragma mark - syscalls 3308 3309 3310 void 3311 _user_exit_thread(status_t returnValue) 3312 { 3313 exit_thread(returnValue); 3314 } 3315 3316 3317 status_t 3318 _user_kill_thread(thread_id thread) 3319 { 3320 // TODO: Don't allow kernel threads to be killed! 3321 return kill_thread(thread); 3322 } 3323 3324 3325 status_t 3326 _user_cancel_thread(thread_id threadID, void (*cancelFunction)(int)) 3327 { 3328 // check the cancel function 3329 if (cancelFunction == NULL || !IS_USER_ADDRESS(cancelFunction)) 3330 return B_BAD_VALUE; 3331 3332 // get and lock the thread 3333 Thread* thread = Thread::GetAndLock(threadID); 3334 if (thread == NULL) 3335 return B_BAD_THREAD_ID; 3336 BReference<Thread> threadReference(thread, true); 3337 ThreadLocker threadLocker(thread, true); 3338 3339 // only threads of the same team can be canceled 3340 if (thread->team != thread_get_current_thread()->team) 3341 return B_NOT_ALLOWED; 3342 3343 // set the cancel function 3344 thread->cancel_function = cancelFunction; 3345 3346 // send the cancellation signal to the thread 3347 InterruptsReadSpinLocker teamLocker(thread->team_lock); 3348 SpinLocker locker(thread->team->signal_lock); 3349 return send_signal_to_thread_locked(thread, SIGNAL_CANCEL_THREAD, NULL, 0); 3350 } 3351 3352 3353 status_t 3354 _user_resume_thread(thread_id thread) 3355 { 3356 // TODO: Don't allow kernel threads to be resumed! 3357 return resume_thread(thread); 3358 } 3359 3360 3361 status_t 3362 _user_suspend_thread(thread_id thread) 3363 { 3364 // TODO: Don't allow kernel threads to be suspended! 3365 return suspend_thread(thread); 3366 } 3367 3368 3369 status_t 3370 _user_rename_thread(thread_id thread, const char *userName) 3371 { 3372 char name[B_OS_NAME_LENGTH]; 3373 3374 if (!IS_USER_ADDRESS(userName) 3375 || userName == NULL 3376 || user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK) 3377 return B_BAD_ADDRESS; 3378 3379 // TODO: Don't allow kernel threads to be renamed! 3380 return rename_thread(thread, name); 3381 } 3382 3383 3384 int32 3385 _user_set_thread_priority(thread_id thread, int32 newPriority) 3386 { 3387 // TODO: Don't allow setting priority of kernel threads! 3388 return set_thread_priority(thread, newPriority); 3389 } 3390 3391 3392 thread_id 3393 _user_spawn_thread(thread_creation_attributes* userAttributes) 3394 { 3395 // copy the userland structure to the kernel 3396 char nameBuffer[B_OS_NAME_LENGTH]; 3397 ThreadCreationAttributes attributes; 3398 status_t error = attributes.InitFromUserAttributes(userAttributes, 3399 nameBuffer); 3400 if (error != B_OK) 3401 return error; 3402 3403 // create the thread 3404 thread_id threadID = thread_create_thread(attributes, false); 3405 3406 if (threadID >= 0) 3407 user_debug_thread_created(threadID); 3408 3409 return threadID; 3410 } 3411 3412 3413 status_t 3414 _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags, 3415 bigtime_t* userRemainingTime) 3416 { 3417 // We need to store more syscall restart parameters than usual and need a 3418 // somewhat different handling. Hence we can't use 3419 // syscall_restart_handle_timeout_pre() but do the job ourselves. 3420 struct restart_parameters { 3421 bigtime_t timeout; 3422 clockid_t timebase; 3423 uint32 flags; 3424 }; 3425 3426 Thread* thread = thread_get_current_thread(); 3427 3428 if ((thread->flags & THREAD_FLAGS_SYSCALL_RESTARTED) != 0) { 3429 // The syscall was restarted. Fetch the parameters from the stored 3430 // restart parameters. 3431 restart_parameters* restartParameters 3432 = (restart_parameters*)thread->syscall_restart.parameters; 3433 timeout = restartParameters->timeout; 3434 timebase = restartParameters->timebase; 3435 flags = restartParameters->flags; 3436 } else { 3437 // convert relative timeouts to absolute ones 3438 if ((flags & B_RELATIVE_TIMEOUT) != 0) { 3439 // not restarted yet and the flags indicate a relative timeout 3440 3441 // Make sure we use the system time base, so real-time clock changes 3442 // won't affect our wait. 3443 flags &= ~(uint32)B_TIMEOUT_REAL_TIME_BASE; 3444 if (timebase == CLOCK_REALTIME) 3445 timebase = CLOCK_MONOTONIC; 3446 3447 // get the current time and make the timeout absolute 3448 bigtime_t now; 3449 status_t error = user_timer_get_clock(timebase, now); 3450 if (error != B_OK) 3451 return error; 3452 3453 timeout += now; 3454 3455 // deal with overflow 3456 if (timeout < 0) 3457 timeout = B_INFINITE_TIMEOUT; 3458 3459 flags = (flags & ~B_RELATIVE_TIMEOUT) | B_ABSOLUTE_TIMEOUT; 3460 } else 3461 flags |= B_ABSOLUTE_TIMEOUT; 3462 } 3463 3464 // snooze 3465 bigtime_t remainingTime; 3466 status_t error = common_snooze_etc(timeout, timebase, 3467 flags | B_CAN_INTERRUPT | B_CHECK_PERMISSION, 3468 userRemainingTime != NULL ? &remainingTime : NULL); 3469 3470 // If interrupted, copy the remaining time back to userland and prepare the 3471 // syscall restart. 3472 if (error == B_INTERRUPTED) { 3473 if (userRemainingTime != NULL 3474 && (!IS_USER_ADDRESS(userRemainingTime) 3475 || user_memcpy(userRemainingTime, &remainingTime, 3476 sizeof(remainingTime)) != B_OK)) { 3477 return B_BAD_ADDRESS; 3478 } 3479 3480 // store the normalized values in the restart parameters 3481 restart_parameters* restartParameters 3482 = (restart_parameters*)thread->syscall_restart.parameters; 3483 restartParameters->timeout = timeout; 3484 restartParameters->timebase = timebase; 3485 restartParameters->flags = flags; 3486 3487 // restart the syscall, if possible 3488 atomic_or(&thread->flags, THREAD_FLAGS_RESTART_SYSCALL); 3489 } 3490 3491 return error; 3492 } 3493 3494 3495 void 3496 _user_thread_yield(void) 3497 { 3498 thread_yield(); 3499 } 3500 3501 3502 status_t 3503 _user_get_thread_info(thread_id id, thread_info *userInfo) 3504 { 3505 thread_info info; 3506 status_t status; 3507 3508 if (!IS_USER_ADDRESS(userInfo)) 3509 return B_BAD_ADDRESS; 3510 3511 status = _get_thread_info(id, &info, sizeof(thread_info)); 3512 3513 if (status >= B_OK 3514 && user_memcpy(userInfo, &info, sizeof(thread_info)) < B_OK) 3515 return B_BAD_ADDRESS; 3516 3517 return status; 3518 } 3519 3520 3521 status_t 3522 _user_get_next_thread_info(team_id team, int32 *userCookie, 3523 thread_info *userInfo) 3524 { 3525 status_t status; 3526 thread_info info; 3527 int32 cookie; 3528 3529 if (!IS_USER_ADDRESS(userCookie) || !IS_USER_ADDRESS(userInfo) 3530 || user_memcpy(&cookie, userCookie, sizeof(int32)) < B_OK) 3531 return B_BAD_ADDRESS; 3532 3533 status = _get_next_thread_info(team, &cookie, &info, sizeof(thread_info)); 3534 if (status < B_OK) 3535 return status; 3536 3537 if (user_memcpy(userCookie, &cookie, sizeof(int32)) < B_OK 3538 || user_memcpy(userInfo, &info, sizeof(thread_info)) < B_OK) 3539 return B_BAD_ADDRESS; 3540 3541 return status; 3542 } 3543 3544 3545 thread_id 3546 _user_find_thread(const char *userName) 3547 { 3548 char name[B_OS_NAME_LENGTH]; 3549 3550 if (userName == NULL) 3551 return find_thread(NULL); 3552 3553 if (!IS_USER_ADDRESS(userName) 3554 || user_strlcpy(name, userName, sizeof(name)) < B_OK) 3555 return B_BAD_ADDRESS; 3556 3557 return find_thread(name); 3558 } 3559 3560 3561 status_t 3562 _user_wait_for_thread(thread_id id, status_t *userReturnCode) 3563 { 3564 status_t returnCode; 3565 status_t status; 3566 3567 if (userReturnCode != NULL && !IS_USER_ADDRESS(userReturnCode)) 3568 return B_BAD_ADDRESS; 3569 3570 status = wait_for_thread_etc(id, B_CAN_INTERRUPT, 0, &returnCode); 3571 3572 if (status == B_OK && userReturnCode != NULL 3573 && user_memcpy(userReturnCode, &returnCode, sizeof(status_t)) < B_OK) { 3574 return B_BAD_ADDRESS; 3575 } 3576 3577 return syscall_restart_handle_post(status); 3578 } 3579 3580 3581 bool 3582 _user_has_data(thread_id thread) 3583 { 3584 return has_data(thread); 3585 } 3586 3587 3588 status_t 3589 _user_send_data(thread_id thread, int32 code, const void *buffer, 3590 size_t bufferSize) 3591 { 3592 if (!IS_USER_ADDRESS(buffer)) 3593 return B_BAD_ADDRESS; 3594 3595 return send_data_etc(thread, code, buffer, bufferSize, 3596 B_KILL_CAN_INTERRUPT); 3597 // supports userland buffers 3598 } 3599 3600 3601 status_t 3602 _user_receive_data(thread_id *_userSender, void *buffer, size_t bufferSize) 3603 { 3604 thread_id sender; 3605 status_t code; 3606 3607 if ((!IS_USER_ADDRESS(_userSender) && _userSender != NULL) 3608 || !IS_USER_ADDRESS(buffer)) 3609 return B_BAD_ADDRESS; 3610 3611 code = receive_data_etc(&sender, buffer, bufferSize, B_KILL_CAN_INTERRUPT); 3612 // supports userland buffers 3613 3614 if (_userSender != NULL) 3615 if (user_memcpy(_userSender, &sender, sizeof(thread_id)) < B_OK) 3616 return B_BAD_ADDRESS; 3617 3618 return code; 3619 } 3620 3621 3622 status_t 3623 _user_block_thread(uint32 flags, bigtime_t timeout) 3624 { 3625 syscall_restart_handle_timeout_pre(flags, timeout); 3626 flags |= B_CAN_INTERRUPT; 3627 3628 Thread* thread = thread_get_current_thread(); 3629 ThreadLocker threadLocker(thread); 3630 3631 // check, if already done 3632 set_ac(); 3633 if (thread->user_thread->wait_status <= 0) { 3634 status_t status = thread->user_thread->wait_status; 3635 clear_ac(); 3636 return status; 3637 } 3638 clear_ac(); 3639 3640 // nope, so wait 3641 thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_OTHER, "user"); 3642 3643 threadLocker.Unlock(); 3644 3645 status_t status = thread_block_with_timeout(flags, timeout); 3646 3647 threadLocker.Lock(); 3648 3649 // Interruptions or timeouts can race with other threads unblocking us. 3650 // Favor a wake-up by another thread, i.e. if someone changed the wait 3651 // status, use that. 3652 set_ac(); 3653 status_t oldStatus = thread->user_thread->wait_status; 3654 if (oldStatus > 0) { 3655 thread->user_thread->wait_status = status; 3656 clear_ac(); 3657 } else { 3658 clear_ac(); 3659 status = oldStatus; 3660 } 3661 3662 threadLocker.Unlock(); 3663 3664 return syscall_restart_handle_timeout_post(status, timeout); 3665 } 3666 3667 3668 status_t 3669 _user_unblock_thread(thread_id threadID, status_t status) 3670 { 3671 status_t error = user_unblock_thread(threadID, status); 3672 3673 if (error == B_OK) 3674 scheduler_reschedule_if_necessary(); 3675 3676 return error; 3677 } 3678 3679 3680 status_t 3681 _user_unblock_threads(thread_id* userThreads, uint32 count, status_t status) 3682 { 3683 enum { 3684 MAX_USER_THREADS_TO_UNBLOCK = 128 3685 }; 3686 3687 if (userThreads == NULL || !IS_USER_ADDRESS(userThreads)) 3688 return B_BAD_ADDRESS; 3689 if (count > MAX_USER_THREADS_TO_UNBLOCK) 3690 return B_BAD_VALUE; 3691 3692 thread_id threads[MAX_USER_THREADS_TO_UNBLOCK]; 3693 if (user_memcpy(threads, userThreads, count * sizeof(thread_id)) != B_OK) 3694 return B_BAD_ADDRESS; 3695 3696 for (uint32 i = 0; i < count; i++) 3697 user_unblock_thread(threads[i], status); 3698 3699 scheduler_reschedule_if_necessary(); 3700 3701 return B_OK; 3702 } 3703 3704 3705 // TODO: the following two functions don't belong here 3706 3707 3708 int 3709 _user_getrlimit(int resource, struct rlimit *urlp) 3710 { 3711 struct rlimit rl; 3712 int ret; 3713 3714 if (urlp == NULL) 3715 return EINVAL; 3716 3717 if (!IS_USER_ADDRESS(urlp)) 3718 return B_BAD_ADDRESS; 3719 3720 ret = common_getrlimit(resource, &rl); 3721 3722 if (ret == 0) { 3723 ret = user_memcpy(urlp, &rl, sizeof(struct rlimit)); 3724 if (ret < 0) 3725 return ret; 3726 3727 return 0; 3728 } 3729 3730 return ret; 3731 } 3732 3733 3734 int 3735 _user_setrlimit(int resource, const struct rlimit *userResourceLimit) 3736 { 3737 struct rlimit resourceLimit; 3738 3739 if (userResourceLimit == NULL) 3740 return EINVAL; 3741 3742 if (!IS_USER_ADDRESS(userResourceLimit) 3743 || user_memcpy(&resourceLimit, userResourceLimit, 3744 sizeof(struct rlimit)) < B_OK) 3745 return B_BAD_ADDRESS; 3746 3747 return common_setrlimit(resource, &resourceLimit); 3748 } 3749