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