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) { 1555 scheduler_enqueue_in_run_queue(thread); 1556 kprintf("thread %" B_PRId32 " resumed\n", thread->id); 1557 } 1558 found = true; 1559 break; 1560 } 1561 if (!found) 1562 kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); 1563 1564 return 0; 1565 } 1566 1567 1568 static int 1569 drop_into_debugger(int argc, char **argv) 1570 { 1571 status_t err; 1572 int32 id; 1573 1574 if (argc > 2) { 1575 print_debugger_command_usage(argv[0]); 1576 return 0; 1577 } 1578 1579 if (argc == 1) 1580 id = thread_get_current_thread()->id; 1581 else 1582 id = strtoul(argv[1], NULL, 0); 1583 1584 err = _user_debug_thread(id); 1585 // TODO: This is a non-trivial syscall doing some locking, so this is 1586 // really nasty and may go seriously wrong. 1587 if (err) 1588 kprintf("drop failed\n"); 1589 else 1590 kprintf("thread %" B_PRId32 " dropped into user debugger\n", id); 1591 1592 return 0; 1593 } 1594 1595 1596 /*! Returns a user-readable string for a thread state. 1597 Only for use in the kernel debugger. 1598 */ 1599 static const char * 1600 state_to_text(Thread *thread, int32 state) 1601 { 1602 switch (state) { 1603 case B_THREAD_READY: 1604 return "ready"; 1605 1606 case B_THREAD_RUNNING: 1607 return "running"; 1608 1609 case B_THREAD_WAITING: 1610 { 1611 if (thread != NULL) { 1612 switch (thread->wait.type) { 1613 case THREAD_BLOCK_TYPE_SNOOZE: 1614 return "zzz"; 1615 1616 case THREAD_BLOCK_TYPE_SEMAPHORE: 1617 { 1618 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1619 if (sem == thread->msg.read_sem) 1620 return "receive"; 1621 break; 1622 } 1623 } 1624 } 1625 1626 return "waiting"; 1627 } 1628 1629 case B_THREAD_SUSPENDED: 1630 return "suspended"; 1631 1632 case THREAD_STATE_FREE_ON_RESCHED: 1633 return "death"; 1634 1635 default: 1636 return "UNKNOWN"; 1637 } 1638 } 1639 1640 1641 static void 1642 print_thread_list_table_head() 1643 { 1644 kprintf("%-*s id state wait for %-*s cpu pri %-*s team " 1645 "name\n", 1646 B_PRINTF_POINTER_WIDTH, "thread", B_PRINTF_POINTER_WIDTH, "object", 1647 B_PRINTF_POINTER_WIDTH, "stack"); 1648 } 1649 1650 1651 static void 1652 _dump_thread_info(Thread *thread, bool shortInfo) 1653 { 1654 if (shortInfo) { 1655 kprintf("%p %6" B_PRId32 " %-10s", thread, thread->id, 1656 state_to_text(thread, thread->state)); 1657 1658 // does it block on a semaphore or a condition variable? 1659 if (thread->state == B_THREAD_WAITING) { 1660 switch (thread->wait.type) { 1661 case THREAD_BLOCK_TYPE_SEMAPHORE: 1662 { 1663 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1664 if (sem == thread->msg.read_sem) 1665 kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); 1666 else { 1667 kprintf("sem %-*" B_PRId32, 1668 B_PRINTF_POINTER_WIDTH + 5, sem); 1669 } 1670 break; 1671 } 1672 1673 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1674 kprintf("cvar %p ", thread->wait.object); 1675 break; 1676 1677 case THREAD_BLOCK_TYPE_SNOOZE: 1678 kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); 1679 break; 1680 1681 case THREAD_BLOCK_TYPE_SIGNAL: 1682 kprintf("signal%*s", B_PRINTF_POINTER_WIDTH + 9, ""); 1683 break; 1684 1685 case THREAD_BLOCK_TYPE_MUTEX: 1686 kprintf("mutex %p ", thread->wait.object); 1687 break; 1688 1689 case THREAD_BLOCK_TYPE_RW_LOCK: 1690 kprintf("rwlock %p ", thread->wait.object); 1691 break; 1692 1693 case THREAD_BLOCK_TYPE_OTHER: 1694 kprintf("other%*s", B_PRINTF_POINTER_WIDTH + 10, ""); 1695 break; 1696 1697 default: 1698 kprintf("??? %p ", thread->wait.object); 1699 break; 1700 } 1701 } else 1702 kprintf("-%*s", B_PRINTF_POINTER_WIDTH + 14, ""); 1703 1704 // on which CPU does it run? 1705 if (thread->cpu) 1706 kprintf("%2d", thread->cpu->cpu_num); 1707 else 1708 kprintf(" -"); 1709 1710 kprintf("%4" B_PRId32 " %p%5" B_PRId32 " %s\n", thread->priority, 1711 (void *)thread->kernel_stack_base, thread->team->id, 1712 thread->name != NULL ? thread->name : "<NULL>"); 1713 1714 return; 1715 } 1716 1717 // print the long info 1718 1719 struct thread_death_entry *death = NULL; 1720 1721 kprintf("THREAD: %p\n", thread); 1722 kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", thread->id, 1723 thread->id); 1724 kprintf("serial_number: %" B_PRId64 "\n", thread->serial_number); 1725 kprintf("name: \"%s\"\n", thread->name); 1726 kprintf("hash_next: %p\nteam_next: %p\n", 1727 thread->hash_next, thread->team_next); 1728 kprintf("priority: %" B_PRId32 " (I/O: %" B_PRId32 ")\n", 1729 thread->priority, thread->io_priority); 1730 kprintf("state: %s\n", state_to_text(thread, thread->state)); 1731 kprintf("cpu: %p ", thread->cpu); 1732 if (thread->cpu) 1733 kprintf("(%d)\n", thread->cpu->cpu_num); 1734 else 1735 kprintf("\n"); 1736 kprintf("sig_pending: %#" B_PRIx64 " (blocked: %#" B_PRIx64 1737 ", before sigsuspend(): %#" B_PRIx64 ")\n", 1738 (int64)thread->ThreadPendingSignals(), 1739 (int64)thread->sig_block_mask, 1740 (int64)thread->sigsuspend_original_unblocked_mask); 1741 kprintf("in_kernel: %d\n", thread->in_kernel); 1742 1743 if (thread->state == B_THREAD_WAITING) { 1744 kprintf("waiting for: "); 1745 1746 switch (thread->wait.type) { 1747 case THREAD_BLOCK_TYPE_SEMAPHORE: 1748 { 1749 sem_id sem = (sem_id)(addr_t)thread->wait.object; 1750 if (sem == thread->msg.read_sem) 1751 kprintf("data\n"); 1752 else 1753 kprintf("semaphore %" B_PRId32 "\n", sem); 1754 break; 1755 } 1756 1757 case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: 1758 kprintf("condition variable %p\n", thread->wait.object); 1759 break; 1760 1761 case THREAD_BLOCK_TYPE_SNOOZE: 1762 kprintf("snooze()\n"); 1763 break; 1764 1765 case THREAD_BLOCK_TYPE_SIGNAL: 1766 kprintf("signal\n"); 1767 break; 1768 1769 case THREAD_BLOCK_TYPE_MUTEX: 1770 kprintf("mutex %p\n", thread->wait.object); 1771 break; 1772 1773 case THREAD_BLOCK_TYPE_RW_LOCK: 1774 kprintf("rwlock %p\n", thread->wait.object); 1775 break; 1776 1777 case THREAD_BLOCK_TYPE_OTHER: 1778 kprintf("other (%s)\n", (char*)thread->wait.object); 1779 break; 1780 1781 default: 1782 kprintf("unknown (%p)\n", thread->wait.object); 1783 break; 1784 } 1785 } 1786 1787 kprintf("fault_handler: %p\n", (void *)thread->fault_handler); 1788 kprintf("team: %p, \"%s\"\n", thread->team, 1789 thread->team->Name()); 1790 kprintf(" exit.sem: %" B_PRId32 "\n", thread->exit.sem); 1791 kprintf(" exit.status: %#" B_PRIx32 " (%s)\n", thread->exit.status, 1792 strerror(thread->exit.status)); 1793 kprintf(" exit.waiters:\n"); 1794 while ((death = (struct thread_death_entry*)list_get_next_item( 1795 &thread->exit.waiters, death)) != NULL) { 1796 kprintf("\t%p (thread %" B_PRId32 ")\n", death, death->thread); 1797 } 1798 1799 kprintf("kernel_stack_area: %" B_PRId32 "\n", thread->kernel_stack_area); 1800 kprintf("kernel_stack_base: %p\n", (void *)thread->kernel_stack_base); 1801 kprintf("user_stack_area: %" B_PRId32 "\n", thread->user_stack_area); 1802 kprintf("user_stack_base: %p\n", (void *)thread->user_stack_base); 1803 kprintf("user_local_storage: %p\n", (void *)thread->user_local_storage); 1804 kprintf("user_thread: %p\n", (void *)thread->user_thread); 1805 kprintf("kernel_errno: %#x (%s)\n", thread->kernel_errno, 1806 strerror(thread->kernel_errno)); 1807 kprintf("kernel_time: %" B_PRId64 "\n", thread->kernel_time); 1808 kprintf("user_time: %" B_PRId64 "\n", thread->user_time); 1809 kprintf("flags: 0x%" B_PRIx32 "\n", thread->flags); 1810 kprintf("architecture dependant section:\n"); 1811 arch_thread_dump_info(&thread->arch_info); 1812 kprintf("scheduler data:\n"); 1813 scheduler_dump_thread_data(thread); 1814 } 1815 1816 1817 static int 1818 dump_thread_info(int argc, char **argv) 1819 { 1820 bool shortInfo = false; 1821 int argi = 1; 1822 if (argi < argc && strcmp(argv[argi], "-s") == 0) { 1823 shortInfo = true; 1824 print_thread_list_table_head(); 1825 argi++; 1826 } 1827 1828 if (argi == argc) { 1829 _dump_thread_info(thread_get_current_thread(), shortInfo); 1830 return 0; 1831 } 1832 1833 for (; argi < argc; argi++) { 1834 const char *name = argv[argi]; 1835 ulong arg = strtoul(name, NULL, 0); 1836 1837 if (IS_KERNEL_ADDRESS(arg)) { 1838 // semi-hack 1839 _dump_thread_info((Thread *)arg, shortInfo); 1840 continue; 1841 } 1842 1843 // walk through the thread list, trying to match name or id 1844 bool found = false; 1845 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1846 Thread* thread = it.Next();) { 1847 if (!strcmp(name, thread->name) || thread->id == (thread_id)arg) { 1848 _dump_thread_info(thread, shortInfo); 1849 found = true; 1850 break; 1851 } 1852 } 1853 1854 if (!found) 1855 kprintf("thread \"%s\" (%" B_PRId32 ") doesn't exist!\n", name, (thread_id)arg); 1856 } 1857 1858 return 0; 1859 } 1860 1861 1862 static int 1863 dump_thread_list(int argc, char **argv) 1864 { 1865 bool realTimeOnly = false; 1866 bool calling = false; 1867 const char *callSymbol = NULL; 1868 addr_t callStart = 0; 1869 addr_t callEnd = 0; 1870 int32 requiredState = 0; 1871 team_id team = -1; 1872 sem_id sem = -1; 1873 1874 if (!strcmp(argv[0], "realtime")) 1875 realTimeOnly = true; 1876 else if (!strcmp(argv[0], "ready")) 1877 requiredState = B_THREAD_READY; 1878 else if (!strcmp(argv[0], "running")) 1879 requiredState = B_THREAD_RUNNING; 1880 else if (!strcmp(argv[0], "waiting")) { 1881 requiredState = B_THREAD_WAITING; 1882 1883 if (argc > 1) { 1884 sem = strtoul(argv[1], NULL, 0); 1885 if (sem == 0) 1886 kprintf("ignoring invalid semaphore argument.\n"); 1887 } 1888 } else if (!strcmp(argv[0], "calling")) { 1889 if (argc < 2) { 1890 kprintf("Need to give a symbol name or start and end arguments.\n"); 1891 return 0; 1892 } else if (argc == 3) { 1893 callStart = parse_expression(argv[1]); 1894 callEnd = parse_expression(argv[2]); 1895 } else 1896 callSymbol = argv[1]; 1897 1898 calling = true; 1899 } else if (argc > 1) { 1900 team = strtoul(argv[1], NULL, 0); 1901 if (team == 0) 1902 kprintf("ignoring invalid team argument.\n"); 1903 } 1904 1905 print_thread_list_table_head(); 1906 1907 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 1908 Thread* thread = it.Next();) { 1909 // filter out threads not matching the search criteria 1910 if ((requiredState && thread->state != requiredState) 1911 || (calling && !arch_debug_contains_call(thread, callSymbol, 1912 callStart, callEnd)) 1913 || (sem > 0 && get_thread_wait_sem(thread) != sem) 1914 || (team > 0 && thread->team->id != team) 1915 || (realTimeOnly && thread->priority < B_REAL_TIME_DISPLAY_PRIORITY)) 1916 continue; 1917 1918 _dump_thread_info(thread, true); 1919 } 1920 return 0; 1921 } 1922 1923 1924 // #pragma mark - private kernel API 1925 1926 1927 void 1928 thread_exit(void) 1929 { 1930 cpu_status state; 1931 Thread* thread = thread_get_current_thread(); 1932 Team* team = thread->team; 1933 Team* kernelTeam = team_get_kernel_team(); 1934 status_t status; 1935 struct thread_debug_info debugInfo; 1936 team_id teamID = team->id; 1937 1938 TRACE(("thread %" B_PRId32 " exiting w/return code %#" B_PRIx32 "\n", 1939 thread->id, thread->exit.status)); 1940 1941 if (!are_interrupts_enabled()) 1942 panic("thread_exit() called with interrupts disabled!\n"); 1943 1944 // boost our priority to get this over with 1945 scheduler_set_thread_priority(thread, B_URGENT_DISPLAY_PRIORITY); 1946 1947 if (team != kernelTeam) { 1948 // Delete all user timers associated with the thread. 1949 ThreadLocker threadLocker(thread); 1950 thread->DeleteUserTimers(false); 1951 1952 // detach the thread's user thread 1953 user_thread* userThread = thread->user_thread; 1954 thread->user_thread = NULL; 1955 1956 threadLocker.Unlock(); 1957 1958 // Delete the thread's user thread, if it's not the main thread. If it 1959 // is, we can save the work, since it will be deleted with the team's 1960 // address space. 1961 if (thread != team->main_thread) 1962 team_free_user_thread(team, userThread); 1963 } 1964 1965 // remember the user stack area -- we will delete it below 1966 area_id userStackArea = -1; 1967 if (team->address_space != NULL && thread->user_stack_area >= 0) { 1968 userStackArea = thread->user_stack_area; 1969 thread->user_stack_area = -1; 1970 } 1971 1972 struct job_control_entry *death = NULL; 1973 struct thread_death_entry* threadDeathEntry = NULL; 1974 bool deleteTeam = false; 1975 port_id debuggerPort = -1; 1976 1977 if (team != kernelTeam) { 1978 user_debug_thread_exiting(thread); 1979 1980 if (team->main_thread == thread) { 1981 // The main thread is exiting. Shut down the whole team. 1982 deleteTeam = true; 1983 1984 // kill off all other threads and the user debugger facilities 1985 debuggerPort = team_shutdown_team(team); 1986 1987 // acquire necessary locks, which are: process group lock, kernel 1988 // team lock, parent team lock, and the team lock 1989 team->LockProcessGroup(); 1990 kernelTeam->Lock(); 1991 team->LockTeamAndParent(true); 1992 } else { 1993 threadDeathEntry 1994 = (thread_death_entry*)malloc(sizeof(thread_death_entry)); 1995 1996 // acquire necessary locks, which are: kernel team lock and the team 1997 // lock 1998 kernelTeam->Lock(); 1999 team->Lock(); 2000 } 2001 2002 ThreadLocker threadLocker(thread); 2003 2004 state = disable_interrupts(); 2005 2006 // swap address spaces, to make sure we're running on the kernel's pgdir 2007 vm_swap_address_space(team->address_space, VMAddressSpace::Kernel()); 2008 2009 WriteSpinLocker teamLocker(thread->team_lock); 2010 SpinLocker threadCreationLocker(gThreadCreationLock); 2011 // removing the thread and putting its death entry to the parent 2012 // team needs to be an atomic operation 2013 2014 // remember how long this thread lasted 2015 bigtime_t now = system_time(); 2016 2017 InterruptsSpinLocker signalLocker(kernelTeam->signal_lock); 2018 SpinLocker teamTimeLocker(kernelTeam->time_lock); 2019 SpinLocker threadTimeLocker(thread->time_lock); 2020 2021 thread->kernel_time += now - thread->last_time; 2022 thread->last_time = now; 2023 2024 team->dead_threads_kernel_time += thread->kernel_time; 2025 team->dead_threads_user_time += thread->user_time; 2026 2027 // stop/update thread/team CPU time user timers 2028 if (thread->HasActiveCPUTimeUserTimers() 2029 || team->HasActiveCPUTimeUserTimers()) { 2030 user_timer_stop_cpu_timers(thread, NULL); 2031 } 2032 2033 // deactivate CPU time user timers for the thread 2034 if (thread->HasActiveCPUTimeUserTimers()) 2035 thread->DeactivateCPUTimeUserTimers(); 2036 2037 threadTimeLocker.Unlock(); 2038 2039 // put the thread into the kernel team until it dies 2040 remove_thread_from_team(team, thread); 2041 insert_thread_into_team(kernelTeam, thread); 2042 2043 teamTimeLocker.Unlock(); 2044 signalLocker.Unlock(); 2045 2046 teamLocker.Unlock(); 2047 2048 if (team->death_entry != NULL) { 2049 if (--team->death_entry->remaining_threads == 0) 2050 team->death_entry->condition.NotifyOne(); 2051 } 2052 2053 if (deleteTeam) { 2054 Team* parent = team->parent; 2055 2056 // Set the team job control state to "dead" and detach the job 2057 // control entry from our team struct. 2058 team_set_job_control_state(team, JOB_CONTROL_STATE_DEAD, NULL); 2059 death = team->job_control_entry; 2060 team->job_control_entry = NULL; 2061 2062 if (death != NULL) { 2063 death->InitDeadState(); 2064 2065 // team_set_job_control_state() already moved our entry 2066 // into the parent's list. We just check the soft limit of 2067 // death entries. 2068 if (parent->dead_children.count > MAX_DEAD_CHILDREN) { 2069 death = parent->dead_children.entries.RemoveHead(); 2070 parent->dead_children.count--; 2071 } else 2072 death = NULL; 2073 } 2074 2075 threadCreationLocker.Unlock(); 2076 restore_interrupts(state); 2077 2078 threadLocker.Unlock(); 2079 2080 // Get a temporary reference to the team's process group 2081 // -- team_remove_team() removes the team from the group, which 2082 // might destroy it otherwise and we wouldn't be able to unlock it. 2083 ProcessGroup* group = team->group; 2084 group->AcquireReference(); 2085 2086 pid_t foregroundGroupToSignal; 2087 team_remove_team(team, foregroundGroupToSignal); 2088 2089 // unlock everything but the parent team 2090 team->Unlock(); 2091 if (parent != kernelTeam) 2092 kernelTeam->Unlock(); 2093 group->Unlock(); 2094 group->ReleaseReference(); 2095 2096 // Send SIGCHLD to the parent as long as we still have its lock. 2097 // This makes job control state change + signalling atomic. 2098 Signal childSignal(SIGCHLD, team->exit.reason, B_OK, team->id); 2099 if (team->exit.reason == CLD_EXITED) { 2100 childSignal.SetStatus(team->exit.status); 2101 } else { 2102 childSignal.SetStatus(team->exit.signal); 2103 childSignal.SetSendingUser(team->exit.signaling_user); 2104 } 2105 send_signal_to_team(parent, childSignal, B_DO_NOT_RESCHEDULE); 2106 2107 // also unlock the parent 2108 parent->Unlock(); 2109 2110 // If the team was a session leader with controlling TTY, we have 2111 // to send SIGHUP to the foreground process group. 2112 if (foregroundGroupToSignal >= 0) { 2113 Signal groupSignal(SIGHUP, SI_USER, B_OK, team->id); 2114 send_signal_to_process_group(foregroundGroupToSignal, 2115 groupSignal, B_DO_NOT_RESCHEDULE); 2116 } 2117 } else { 2118 // The thread is not the main thread. We store a thread death entry 2119 // for it, unless someone is already waiting for it. 2120 if (threadDeathEntry != NULL 2121 && list_is_empty(&thread->exit.waiters)) { 2122 threadDeathEntry->thread = thread->id; 2123 threadDeathEntry->status = thread->exit.status; 2124 2125 // add entry -- remove an old one, if we hit the limit 2126 list_add_item(&team->dead_threads, threadDeathEntry); 2127 team->dead_threads_count++; 2128 threadDeathEntry = NULL; 2129 2130 if (team->dead_threads_count > MAX_DEAD_THREADS) { 2131 threadDeathEntry 2132 = (thread_death_entry*)list_remove_head_item( 2133 &team->dead_threads); 2134 team->dead_threads_count--; 2135 } 2136 } 2137 2138 threadCreationLocker.Unlock(); 2139 restore_interrupts(state); 2140 2141 threadLocker.Unlock(); 2142 team->Unlock(); 2143 kernelTeam->Unlock(); 2144 } 2145 2146 TRACE(("thread_exit: thread %" B_PRId32 " now a kernel thread!\n", 2147 thread->id)); 2148 } 2149 2150 free(threadDeathEntry); 2151 2152 // delete the team if we're its main thread 2153 if (deleteTeam) { 2154 team_delete_team(team, debuggerPort); 2155 2156 // we need to delete any death entry that made it to here 2157 delete death; 2158 } 2159 2160 ThreadLocker threadLocker(thread); 2161 2162 state = disable_interrupts(); 2163 SpinLocker threadCreationLocker(gThreadCreationLock); 2164 2165 // mark invisible in global hash/list, so it's no longer accessible 2166 SpinLocker threadHashLocker(sThreadHashLock); 2167 thread->visible = false; 2168 sUsedThreads--; 2169 threadHashLocker.Unlock(); 2170 2171 // Stop debugging for this thread 2172 SpinLocker threadDebugInfoLocker(thread->debug_info.lock); 2173 debugInfo = thread->debug_info; 2174 clear_thread_debug_info(&thread->debug_info, true); 2175 threadDebugInfoLocker.Unlock(); 2176 2177 // Remove the select infos. We notify them a little later. 2178 select_info* selectInfos = thread->select_infos; 2179 thread->select_infos = NULL; 2180 2181 threadCreationLocker.Unlock(); 2182 restore_interrupts(state); 2183 2184 threadLocker.Unlock(); 2185 2186 destroy_thread_debug_info(&debugInfo); 2187 2188 // notify select infos 2189 select_info* info = selectInfos; 2190 while (info != NULL) { 2191 select_sync* sync = info->sync; 2192 2193 notify_select_events(info, B_EVENT_INVALID); 2194 info = info->next; 2195 put_select_sync(sync); 2196 } 2197 2198 // notify listeners 2199 sNotificationService.Notify(THREAD_REMOVED, thread); 2200 2201 // shutdown the thread messaging 2202 2203 status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0); 2204 if (status == B_WOULD_BLOCK) { 2205 // there is data waiting for us, so let us eat it 2206 thread_id sender; 2207 2208 delete_sem(thread->msg.write_sem); 2209 // first, let's remove all possibly waiting writers 2210 receive_data_etc(&sender, NULL, 0, B_RELATIVE_TIMEOUT); 2211 } else { 2212 // we probably own the semaphore here, and we're the last to do so 2213 delete_sem(thread->msg.write_sem); 2214 } 2215 // now we can safely remove the msg.read_sem 2216 delete_sem(thread->msg.read_sem); 2217 2218 // fill all death entries and delete the sem that others will use to wait 2219 // for us 2220 { 2221 sem_id cachedExitSem = thread->exit.sem; 2222 2223 ThreadLocker threadLocker(thread); 2224 2225 // make sure no one will grab this semaphore again 2226 thread->exit.sem = -1; 2227 2228 // fill all death entries 2229 thread_death_entry* entry = NULL; 2230 while ((entry = (thread_death_entry*)list_get_next_item( 2231 &thread->exit.waiters, entry)) != NULL) { 2232 entry->status = thread->exit.status; 2233 } 2234 2235 threadLocker.Unlock(); 2236 2237 delete_sem(cachedExitSem); 2238 } 2239 2240 // delete the user stack, if this was a user thread 2241 if (!deleteTeam && userStackArea >= 0) { 2242 // We postponed deleting the user stack until now, since this way all 2243 // notifications for the thread's death are out already and all other 2244 // threads waiting for this thread's death and some object on its stack 2245 // will wake up before we (try to) delete the stack area. Of most 2246 // relevance is probably the case where this is the main thread and 2247 // other threads use objects on its stack -- so we want them terminated 2248 // first. 2249 // When the team is deleted, all areas are deleted anyway, so we don't 2250 // need to do that explicitly in that case. 2251 vm_delete_area(teamID, userStackArea, true); 2252 } 2253 2254 // notify the debugger 2255 if (teamID != kernelTeam->id) 2256 user_debug_thread_deleted(teamID, thread->id); 2257 2258 // enqueue in the undertaker list and reschedule for the last time 2259 UndertakerEntry undertakerEntry(thread, teamID); 2260 2261 disable_interrupts(); 2262 2263 SpinLocker schedulerLocker(thread->scheduler_lock); 2264 2265 SpinLocker undertakerLocker(sUndertakerLock); 2266 sUndertakerEntries.Add(&undertakerEntry); 2267 sUndertakerCondition.NotifyOne(); 2268 undertakerLocker.Unlock(); 2269 2270 scheduler_reschedule(THREAD_STATE_FREE_ON_RESCHED); 2271 2272 panic("never can get here\n"); 2273 } 2274 2275 2276 /*! Called in the interrupt handler code when a thread enters 2277 the kernel for any reason. 2278 Only tracks time for now. 2279 Interrupts are disabled. 2280 */ 2281 void 2282 thread_at_kernel_entry(bigtime_t now) 2283 { 2284 Thread *thread = thread_get_current_thread(); 2285 2286 TRACE(("thread_at_kernel_entry: entry thread %" B_PRId32 "\n", thread->id)); 2287 2288 // track user time 2289 SpinLocker threadTimeLocker(thread->time_lock); 2290 thread->user_time += now - thread->last_time; 2291 thread->last_time = now; 2292 thread->in_kernel = true; 2293 threadTimeLocker.Unlock(); 2294 } 2295 2296 2297 /*! Called whenever a thread exits kernel space to user space. 2298 Tracks time, handles signals, ... 2299 Interrupts must be enabled. When the function returns, interrupts will be 2300 disabled. 2301 The function may not return. This e.g. happens when the thread has received 2302 a deadly signal. 2303 */ 2304 void 2305 thread_at_kernel_exit(void) 2306 { 2307 Thread *thread = thread_get_current_thread(); 2308 2309 TRACE(("thread_at_kernel_exit: exit thread %" B_PRId32 "\n", thread->id)); 2310 2311 handle_signals(thread); 2312 2313 disable_interrupts(); 2314 2315 // track kernel time 2316 bigtime_t now = system_time(); 2317 SpinLocker threadTimeLocker(thread->time_lock); 2318 thread->in_kernel = false; 2319 thread->kernel_time += now - thread->last_time; 2320 thread->last_time = now; 2321 } 2322 2323 2324 /*! The quick version of thread_kernel_exit(), in case no signals are pending 2325 and no debugging shall be done. 2326 Interrupts must be disabled. 2327 */ 2328 void 2329 thread_at_kernel_exit_no_signals(void) 2330 { 2331 Thread *thread = thread_get_current_thread(); 2332 2333 TRACE(("thread_at_kernel_exit_no_signals: exit thread %" B_PRId32 "\n", 2334 thread->id)); 2335 2336 // track kernel time 2337 bigtime_t now = system_time(); 2338 SpinLocker threadTimeLocker(thread->time_lock); 2339 thread->in_kernel = false; 2340 thread->kernel_time += now - thread->last_time; 2341 thread->last_time = now; 2342 } 2343 2344 2345 void 2346 thread_reset_for_exec(void) 2347 { 2348 Thread* thread = thread_get_current_thread(); 2349 2350 ThreadLocker threadLocker(thread); 2351 2352 // delete user-defined timers 2353 thread->DeleteUserTimers(true); 2354 2355 // cancel pre-defined timer 2356 if (UserTimer* timer = thread->UserTimerFor(USER_TIMER_REAL_TIME_ID)) 2357 timer->Cancel(); 2358 2359 // reset user_thread and user stack 2360 thread->user_thread = NULL; 2361 thread->user_stack_area = -1; 2362 thread->user_stack_base = 0; 2363 thread->user_stack_size = 0; 2364 2365 // reset signals 2366 thread->ResetSignalsOnExec(); 2367 2368 // reset thread CPU time clock 2369 InterruptsSpinLocker timeLocker(thread->time_lock); 2370 thread->cpu_clock_offset = -thread->CPUTime(false); 2371 } 2372 2373 2374 thread_id 2375 allocate_thread_id() 2376 { 2377 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2378 2379 // find the next unused ID 2380 thread_id id; 2381 do { 2382 id = sNextThreadID++; 2383 2384 // deal with integer overflow 2385 if (sNextThreadID < 0) 2386 sNextThreadID = 2; 2387 2388 // check whether the ID is already in use 2389 } while (sThreadHash.Lookup(id, false) != NULL); 2390 2391 return id; 2392 } 2393 2394 2395 thread_id 2396 peek_next_thread_id() 2397 { 2398 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2399 return sNextThreadID; 2400 } 2401 2402 2403 /*! Yield the CPU to other threads. 2404 Thread will continue to run, if there's no other thread in ready 2405 state, and if it has a higher priority than the other ready threads, it 2406 still has a good chance to continue. 2407 */ 2408 void 2409 thread_yield(void) 2410 { 2411 Thread *thread = thread_get_current_thread(); 2412 if (thread == NULL) 2413 return; 2414 2415 InterruptsSpinLocker _(thread->scheduler_lock); 2416 2417 thread->has_yielded = true; 2418 scheduler_reschedule(B_THREAD_READY); 2419 } 2420 2421 2422 void 2423 thread_map(void (*function)(Thread* thread, void* data), void* data) 2424 { 2425 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2426 2427 for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); 2428 Thread* thread = it.Next();) { 2429 function(thread, data); 2430 } 2431 } 2432 2433 2434 /*! Kernel private thread creation function. 2435 */ 2436 thread_id 2437 spawn_kernel_thread_etc(thread_func function, const char *name, int32 priority, 2438 void *arg, team_id team) 2439 { 2440 return thread_create_thread( 2441 ThreadCreationAttributes(function, name, priority, arg, team), 2442 true); 2443 } 2444 2445 2446 status_t 2447 wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, 2448 status_t *_returnCode) 2449 { 2450 if (id < 0) 2451 return B_BAD_THREAD_ID; 2452 2453 // get the thread, queue our death entry, and fetch the semaphore we have to 2454 // wait on 2455 sem_id exitSem = B_BAD_THREAD_ID; 2456 struct thread_death_entry death; 2457 2458 Thread* thread = Thread::GetAndLock(id); 2459 if (thread != NULL) { 2460 // remember the semaphore we have to wait on and place our death entry 2461 exitSem = thread->exit.sem; 2462 if (exitSem >= 0) 2463 list_add_link_to_head(&thread->exit.waiters, &death); 2464 2465 thread->UnlockAndReleaseReference(); 2466 2467 if (exitSem < 0) 2468 return B_BAD_THREAD_ID; 2469 } else { 2470 // we couldn't find this thread -- maybe it's already gone, and we'll 2471 // find its death entry in our team 2472 Team* team = thread_get_current_thread()->team; 2473 TeamLocker teamLocker(team); 2474 2475 // check the child death entries first (i.e. main threads of child 2476 // teams) 2477 bool deleteEntry; 2478 job_control_entry* freeDeath 2479 = team_get_death_entry(team, id, &deleteEntry); 2480 if (freeDeath != NULL) { 2481 death.status = freeDeath->status; 2482 if (deleteEntry) 2483 delete freeDeath; 2484 } else { 2485 // check the thread death entries of the team (non-main threads) 2486 thread_death_entry* threadDeathEntry = NULL; 2487 while ((threadDeathEntry = (thread_death_entry*)list_get_next_item( 2488 &team->dead_threads, threadDeathEntry)) != NULL) { 2489 if (threadDeathEntry->thread == id) { 2490 list_remove_item(&team->dead_threads, threadDeathEntry); 2491 team->dead_threads_count--; 2492 death.status = threadDeathEntry->status; 2493 free(threadDeathEntry); 2494 break; 2495 } 2496 } 2497 2498 if (threadDeathEntry == NULL) 2499 return B_BAD_THREAD_ID; 2500 } 2501 2502 // we found the thread's death entry in our team 2503 if (_returnCode) 2504 *_returnCode = death.status; 2505 2506 return B_OK; 2507 } 2508 2509 // we need to wait for the death of the thread 2510 2511 resume_thread(id); 2512 // make sure we don't wait forever on a suspended thread 2513 2514 status_t status = acquire_sem_etc(exitSem, 1, flags, timeout); 2515 2516 if (status == B_OK) { 2517 // this should never happen as the thread deletes the semaphore on exit 2518 panic("could acquire exit_sem for thread %" B_PRId32 "\n", id); 2519 } else if (status == B_BAD_SEM_ID) { 2520 // this is the way the thread normally exits 2521 status = B_OK; 2522 } else { 2523 // We were probably interrupted or the timeout occurred; we need to 2524 // remove our death entry now. 2525 thread = Thread::GetAndLock(id); 2526 if (thread != NULL) { 2527 list_remove_link(&death); 2528 thread->UnlockAndReleaseReference(); 2529 } else { 2530 // The thread is already gone, so we need to wait uninterruptibly 2531 // for its exit semaphore to make sure our death entry stays valid. 2532 // It won't take long, since the thread is apparently already in the 2533 // middle of the cleanup. 2534 acquire_sem(exitSem); 2535 status = B_OK; 2536 } 2537 } 2538 2539 if (status == B_OK && _returnCode != NULL) 2540 *_returnCode = death.status; 2541 2542 return status; 2543 } 2544 2545 2546 status_t 2547 select_thread(int32 id, struct select_info* info, bool kernel) 2548 { 2549 // get and lock the thread 2550 Thread* thread = Thread::GetAndLock(id); 2551 if (thread == NULL) 2552 return B_BAD_THREAD_ID; 2553 BReference<Thread> threadReference(thread, true); 2554 ThreadLocker threadLocker(thread, true); 2555 2556 // We support only B_EVENT_INVALID at the moment. 2557 info->selected_events &= B_EVENT_INVALID; 2558 2559 // add info to list 2560 if (info->selected_events != 0) { 2561 info->next = thread->select_infos; 2562 thread->select_infos = info; 2563 2564 // we need a sync reference 2565 atomic_add(&info->sync->ref_count, 1); 2566 } 2567 2568 return B_OK; 2569 } 2570 2571 2572 status_t 2573 deselect_thread(int32 id, struct select_info* info, bool kernel) 2574 { 2575 // get and lock the thread 2576 Thread* thread = Thread::GetAndLock(id); 2577 if (thread == NULL) 2578 return B_BAD_THREAD_ID; 2579 BReference<Thread> threadReference(thread, true); 2580 ThreadLocker threadLocker(thread, true); 2581 2582 // remove info from list 2583 select_info** infoLocation = &thread->select_infos; 2584 while (*infoLocation != NULL && *infoLocation != info) 2585 infoLocation = &(*infoLocation)->next; 2586 2587 if (*infoLocation != info) 2588 return B_OK; 2589 2590 *infoLocation = info->next; 2591 2592 threadLocker.Unlock(); 2593 2594 // surrender sync reference 2595 put_select_sync(info->sync); 2596 2597 return B_OK; 2598 } 2599 2600 2601 int32 2602 thread_max_threads(void) 2603 { 2604 return sMaxThreads; 2605 } 2606 2607 2608 int32 2609 thread_used_threads(void) 2610 { 2611 InterruptsSpinLocker threadHashLocker(sThreadHashLock); 2612 return sUsedThreads; 2613 } 2614 2615 2616 /*! Returns a user-readable string for a thread state. 2617 Only for use in the kernel debugger. 2618 */ 2619 const char* 2620 thread_state_to_text(Thread* thread, int32 state) 2621 { 2622 return state_to_text(thread, state); 2623 } 2624 2625 2626 int32 2627 thread_get_io_priority(thread_id id) 2628 { 2629 Thread* thread = Thread::GetAndLock(id); 2630 if (thread == NULL) 2631 return B_BAD_THREAD_ID; 2632 BReference<Thread> threadReference(thread, true); 2633 ThreadLocker threadLocker(thread, true); 2634 2635 int32 priority = thread->io_priority; 2636 if (priority < 0) { 2637 // negative I/O priority means using the (CPU) priority 2638 priority = thread->priority; 2639 } 2640 2641 return priority; 2642 } 2643 2644 2645 void 2646 thread_set_io_priority(int32 priority) 2647 { 2648 Thread* thread = thread_get_current_thread(); 2649 ThreadLocker threadLocker(thread); 2650 2651 thread->io_priority = priority; 2652 } 2653 2654 2655 status_t 2656 thread_init(kernel_args *args) 2657 { 2658 TRACE(("thread_init: entry\n")); 2659 2660 // create the thread hash table 2661 new(&sThreadHash) ThreadHashTable(); 2662 if (sThreadHash.Init(128) != B_OK) 2663 panic("thread_init(): failed to init thread hash table!"); 2664 2665 // create the thread structure object cache 2666 sThreadCache = create_object_cache("threads", sizeof(Thread), 16, NULL, 2667 NULL, NULL); 2668 // Note: The x86 port requires 16 byte alignment of thread structures. 2669 if (sThreadCache == NULL) 2670 panic("thread_init(): failed to allocate thread object cache!"); 2671 2672 if (arch_thread_init(args) < B_OK) 2673 panic("arch_thread_init() failed!\n"); 2674 2675 // skip all thread IDs including B_SYSTEM_TEAM, which is reserved 2676 sNextThreadID = B_SYSTEM_TEAM + 1; 2677 2678 // create an idle thread for each cpu 2679 for (uint32 i = 0; i < args->num_cpus; i++) { 2680 Thread *thread; 2681 area_info info; 2682 char name[64]; 2683 2684 sprintf(name, "idle thread %" B_PRIu32, i + 1); 2685 thread = new(&sIdleThreads[i]) Thread(name, 2686 i == 0 ? team_get_kernel_team_id() : -1, &gCPU[i]); 2687 if (thread == NULL || thread->Init(true) != B_OK) { 2688 panic("error creating idle thread struct\n"); 2689 return B_NO_MEMORY; 2690 } 2691 2692 gCPU[i].running_thread = thread; 2693 2694 thread->team = team_get_kernel_team(); 2695 thread->priority = B_IDLE_PRIORITY; 2696 thread->state = B_THREAD_RUNNING; 2697 sprintf(name, "idle thread %" B_PRIu32 " kstack", i + 1); 2698 thread->kernel_stack_area = find_area(name); 2699 2700 if (get_area_info(thread->kernel_stack_area, &info) != B_OK) 2701 panic("error finding idle kstack area\n"); 2702 2703 thread->kernel_stack_base = (addr_t)info.address; 2704 thread->kernel_stack_top = thread->kernel_stack_base + info.size; 2705 2706 thread->visible = true; 2707 insert_thread_into_team(thread->team, thread); 2708 2709 scheduler_on_thread_init(thread); 2710 } 2711 sUsedThreads = args->num_cpus; 2712 2713 // init the notification service 2714 new(&sNotificationService) ThreadNotificationService(); 2715 2716 sNotificationService.Register(); 2717 2718 // start the undertaker thread 2719 new(&sUndertakerEntries) DoublyLinkedList<UndertakerEntry>(); 2720 sUndertakerCondition.Init(&sUndertakerEntries, "undertaker entries"); 2721 2722 thread_id undertakerThread = spawn_kernel_thread(&undertaker, "undertaker", 2723 B_DISPLAY_PRIORITY, NULL); 2724 if (undertakerThread < 0) 2725 panic("Failed to create undertaker thread!"); 2726 resume_thread(undertakerThread); 2727 2728 // set up some debugger commands 2729 add_debugger_command_etc("threads", &dump_thread_list, "List all threads", 2730 "[ <team> ]\n" 2731 "Prints a list of all existing threads, or, if a team ID is given,\n" 2732 "all threads of the specified team.\n" 2733 " <team> - The ID of the team whose threads shall be listed.\n", 0); 2734 add_debugger_command_etc("ready", &dump_thread_list, 2735 "List all ready threads", 2736 "\n" 2737 "Prints a list of all threads in ready state.\n", 0); 2738 add_debugger_command_etc("running", &dump_thread_list, 2739 "List all running threads", 2740 "\n" 2741 "Prints a list of all threads in running state.\n", 0); 2742 add_debugger_command_etc("waiting", &dump_thread_list, 2743 "List all waiting threads (optionally for a specific semaphore)", 2744 "[ <sem> ]\n" 2745 "Prints a list of all threads in waiting state. If a semaphore is\n" 2746 "specified, only the threads waiting on that semaphore are listed.\n" 2747 " <sem> - ID of the semaphore.\n", 0); 2748 add_debugger_command_etc("realtime", &dump_thread_list, 2749 "List all realtime threads", 2750 "\n" 2751 "Prints a list of all threads with realtime priority.\n", 0); 2752 add_debugger_command_etc("thread", &dump_thread_info, 2753 "Dump info about a particular thread", 2754 "[ -s ] ( <id> | <address> | <name> )*\n" 2755 "Prints information about the specified thread. If no argument is\n" 2756 "given the current thread is selected.\n" 2757 " -s - Print info in compact table form (like \"threads\").\n" 2758 " <id> - The ID of the thread.\n" 2759 " <address> - The address of the thread structure.\n" 2760 " <name> - The thread's name.\n", 0); 2761 add_debugger_command_etc("calling", &dump_thread_list, 2762 "Show all threads that have a specific address in their call chain", 2763 "{ <symbol-pattern> | <start> <end> }\n", 0); 2764 add_debugger_command_etc("unreal", &make_thread_unreal, 2765 "Set realtime priority threads to normal priority", 2766 "[ <id> ]\n" 2767 "Sets the priority of all realtime threads or, if given, the one\n" 2768 "with the specified ID to \"normal\" priority.\n" 2769 " <id> - The ID of the thread.\n", 0); 2770 add_debugger_command_etc("suspend", &make_thread_suspended, 2771 "Suspend a thread", 2772 "[ <id> ]\n" 2773 "Suspends the thread with the given ID. If no ID argument is given\n" 2774 "the current thread is selected.\n" 2775 " <id> - The ID of the thread.\n", 0); 2776 add_debugger_command_etc("resume", &make_thread_resumed, "Resume a thread", 2777 "<id>\n" 2778 "Resumes the specified thread, if it is currently suspended.\n" 2779 " <id> - The ID of the thread.\n", 0); 2780 add_debugger_command_etc("drop", &drop_into_debugger, 2781 "Drop a thread into the userland debugger", 2782 "<id>\n" 2783 "Drops the specified (userland) thread into the userland debugger\n" 2784 "after leaving the kernel debugger.\n" 2785 " <id> - The ID of the thread.\n", 0); 2786 add_debugger_command_etc("priority", &set_thread_prio, 2787 "Set a thread's priority", 2788 "<priority> [ <id> ]\n" 2789 "Sets the priority of the thread with the specified ID to the given\n" 2790 "priority. If no thread ID is given, the current thread is selected.\n" 2791 " <priority> - The thread's new priority (0 - 120)\n" 2792 " <id> - The ID of the thread.\n", 0); 2793 2794 return B_OK; 2795 } 2796 2797 2798 status_t 2799 thread_preboot_init_percpu(struct kernel_args *args, int32 cpuNum) 2800 { 2801 // set up the cpu pointer in the not yet initialized per-cpu idle thread 2802 // so that get_current_cpu and friends will work, which is crucial for 2803 // a lot of low level routines 2804 sIdleThreads[cpuNum].cpu = &gCPU[cpuNum]; 2805 arch_thread_set_current_thread(&sIdleThreads[cpuNum]); 2806 return B_OK; 2807 } 2808 2809 2810 // #pragma mark - thread blocking API 2811 2812 2813 static status_t 2814 thread_block_timeout(timer* timer) 2815 { 2816 Thread* thread = (Thread*)timer->user_data; 2817 thread_unblock(thread, B_TIMED_OUT); 2818 2819 return B_HANDLED_INTERRUPT; 2820 } 2821 2822 2823 /*! Blocks the current thread. 2824 2825 The thread is blocked until someone else unblock it. Must be called after a 2826 call to thread_prepare_to_block(). If the thread has already been unblocked 2827 after the previous call to thread_prepare_to_block(), this function will 2828 return immediately. Cf. the documentation of thread_prepare_to_block() for 2829 more details. 2830 2831 The caller must hold the scheduler lock. 2832 2833 \param thread The current thread. 2834 \return The error code passed to the unblocking function. thread_interrupt() 2835 uses \c B_INTERRUPTED. By convention \c B_OK means that the wait was 2836 successful while another error code indicates a failure (what that means 2837 depends on the client code). 2838 */ 2839 static inline status_t 2840 thread_block_locked(Thread* thread) 2841 { 2842 if (thread->wait.status == 1) { 2843 // check for signals, if interruptible 2844 if (thread_is_interrupted(thread, thread->wait.flags)) { 2845 thread->wait.status = B_INTERRUPTED; 2846 } else 2847 scheduler_reschedule(B_THREAD_WAITING); 2848 } 2849 2850 return thread->wait.status; 2851 } 2852 2853 2854 /*! Blocks the current thread. 2855 2856 The function acquires the scheduler lock and calls thread_block_locked(). 2857 See there for more information. 2858 */ 2859 status_t 2860 thread_block() 2861 { 2862 InterruptsSpinLocker _(thread_get_current_thread()->scheduler_lock); 2863 return thread_block_locked(thread_get_current_thread()); 2864 } 2865 2866 2867 /*! Blocks the current thread with a timeout. 2868 2869 The thread is blocked until someone else unblock it or the specified timeout 2870 occurs. Must be called after a call to thread_prepare_to_block(). If the 2871 thread has already been unblocked after the previous call to 2872 thread_prepare_to_block(), this function will return immediately. See 2873 thread_prepare_to_block() for more details. 2874 2875 The caller must not hold the scheduler lock. 2876 2877 \param thread The current thread. 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