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