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