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