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