152a38012Sejakowatz/*
2b1673075SPawel Dziepak * Copyright 2014, Pawe�� Dziepak, pdziepak@quarnos.org.
34535495dSIngo Weinhold * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
40b70ea59SAxel Dörfler * Copyright 2002-2007, Axel D��rfler, axeld@pinc-software.de.
5545ecbe8SAxel Dörfler * Distributed under the terms of the MIT License.
6545ecbe8SAxel Dörfler *
7545ecbe8SAxel Dörfler * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
8545ecbe8SAxel Dörfler * Distributed under the terms of the NewOS License.
9545ecbe8SAxel Dörfler */
1052a38012Sejakowatz#ifndef _THREAD_H
1152a38012Sejakowatz#define _THREAD_H
1252a38012Sejakowatz
1352a38012Sejakowatz
14a9731b41SAxel Dörfler#include <OS.h>
1552a38012Sejakowatz
168cf8e537SPawel Dziepak#include <arch/atomic.h>
178cf8e537SPawel Dziepak#include <arch/thread.h>
18b95f6d47SIngo Weinhold// For the thread blocking inline functions only.
19b95f6d47SIngo Weinhold#include <kscheduler.h>
20b95f6d47SIngo Weinhold#include <ksignal.h>
218cf8e537SPawel Dziepak#include <thread_types.h>
22b95f6d47SIngo Weinhold
23b95f6d47SIngo Weinhold
2424df6592SIngo Weinholdstruct arch_fork_arg;
25f3cadd05SAxel Dörflerstruct kernel_args;
26636bfc08SIngo Weinholdstruct select_info;
274c49f205SIngo Weinholdstruct thread_creation_attributes;
284c49f205SIngo Weinhold
29f510e6ceSlillo
30efd536ffSIngo Weinhold// thread notifications
314ebc8f61SIngo Weinhold#define THREAD_MONITOR		'_tm_'
324ebc8f61SIngo Weinhold#define THREAD_ADDED		0x01
334ebc8f61SIngo Weinhold#define THREAD_REMOVED		0x02
344ebc8f61SIngo Weinhold#define THREAD_NAME_CHANGED	0x04
35efd536ffSIngo Weinhold
36efd536ffSIngo Weinhold
3724df6592SIngo Weinholdnamespace BKernel {
3824df6592SIngo Weinhold
3924df6592SIngo Weinhold
4024df6592SIngo Weinholdstruct ThreadCreationAttributes : thread_creation_attributes {
4124df6592SIngo Weinhold	// when calling from kernel only
4224df6592SIngo Weinhold	team_id			team;
4324df6592SIngo Weinhold	Thread*			thread;
4424df6592SIngo Weinhold	sigset_t		signal_mask;
4524df6592SIngo Weinhold	size_t			additional_stack_size;	// additional space in the stack
4624df6592SIngo Weinhold											// area after the TLS region, not
4724df6592SIngo Weinhold											// used as thread stack
4824df6592SIngo Weinhold	thread_func		kernelEntry;
4924df6592SIngo Weinhold	void*			kernelArgument;
5024df6592SIngo Weinhold	arch_fork_arg*	forkArgs;				// If non-NULL, the userland thread
5124df6592SIngo Weinhold											// will be started with this
5224df6592SIngo Weinhold											// register context.
5324df6592SIngo Weinhold
5424df6592SIngo Weinholdpublic:
5524df6592SIngo Weinhold								ThreadCreationAttributes() {}
5624df6592SIngo Weinhold									// no-init constructor
5724df6592SIngo Weinhold								ThreadCreationAttributes(
5824df6592SIngo Weinhold									thread_func function, const char* name,
5924df6592SIngo Weinhold									int32 priority, void* arg,
6024df6592SIngo Weinhold									team_id team = -1, Thread* thread = NULL);
6124df6592SIngo Weinhold
6224df6592SIngo Weinhold			status_t			InitFromUserAttributes(
6324df6592SIngo Weinhold									const thread_creation_attributes*
6424df6592SIngo Weinhold										userAttributes,
6524df6592SIngo Weinhold									char* nameBuffer);
6624df6592SIngo Weinhold};
6724df6592SIngo Weinhold
6824df6592SIngo Weinhold
6924df6592SIngo Weinhold}	// namespace BKernel
7024df6592SIngo Weinhold
7124df6592SIngo Weinholdusing BKernel::ThreadCreationAttributes;
7224df6592SIngo Weinhold
7324df6592SIngo Weinhold
7403fb2d88SPawel Dziepakextern spinlock gThreadCreationLock;
7503fb2d88SPawel Dziepak
7603fb2d88SPawel Dziepak
7714f5ad8cSAxel Dörfler#ifdef __cplusplus
7814f5ad8cSAxel Dörflerextern "C" {
7914f5ad8cSAxel Dörfler#endif
8014f5ad8cSAxel Dörfler
8134b3b26bSIngo Weinholdvoid thread_at_kernel_entry(bigtime_t now);
82ee02a939SAxel Dörfler	// called when the thread enters the kernel on behalf of the thread
8390bce836SAxel Dörflervoid thread_at_kernel_exit(void);
8434b3b26bSIngo Weinholdvoid thread_at_kernel_exit_no_signals(void);
850b70ea59SAxel Dörflervoid thread_reset_for_exec(void);
8652a38012Sejakowatz
87f3cadd05SAxel Dörflerstatus_t thread_init(struct kernel_args *args);
88badc7b67STravis Geiselbrechtstatus_t thread_preboot_init_percpu(struct kernel_args *args, int32 cpuNum);
8929e65827SPawel Dziepakvoid thread_yield(void);
908fe70e82Slillovoid thread_exit(void);
9152a38012Sejakowatz
9203f7d3d1SPawel Dziepakvoid thread_map(void (*function)(Thread* thread, void* data), void* data);
9303f7d3d1SPawel Dziepak
94545ecbe8SAxel Dörflerint32 thread_max_threads(void);
95545ecbe8SAxel Dörflerint32 thread_used_threads(void);
96545ecbe8SAxel Dörfler
974535495dSIngo Weinholdconst char* thread_state_to_text(Thread* thread, int32 state);
9807569b03SIngo Weinhold
993b3e3805SIngo Weinholdint32 thread_get_io_priority(thread_id id);
1003b3e3805SIngo Weinholdvoid thread_set_io_priority(int32 priority);
1013b3e3805SIngo Weinhold
10252a38012Sejakowatz#define thread_get_current_thread arch_thread_get_current_thread
10352a38012Sejakowatz
104e96a8449SAxel Dörflerstatic thread_id thread_get_current_thread_id(void);
105e96a8449SAxel Dörflerstatic inline thread_id
106e96a8449SAxel Dörflerthread_get_current_thread_id(void)
107e96a8449SAxel Dörfler{
1084535495dSIngo Weinhold	Thread *thread = thread_get_current_thread();
109d14aab0dSAxel Dörfler	return thread ? thread->id : 0;
110d14aab0dSAxel Dörfler}
111d14aab0dSAxel Dörfler
112d14aab0dSAxel Dörflerstatic inline bool
1134535495dSIngo Weinholdthread_is_idle_thread(Thread *thread)
114d14aab0dSAxel Dörfler{
11524df6592SIngo Weinhold	return thread->priority == B_IDLE_PRIORITY;
11652a38012Sejakowatz}
117e96a8449SAxel Dörfler
11824df6592SIngo Weinholdthread_id allocate_thread_id();
11924df6592SIngo Weinholdthread_id peek_next_thread_id();
120efd536ffSIngo Weinhold
12124df6592SIngo Weinholdstatus_t thread_enter_userspace_new_team(Thread* thread, addr_t entryFunction,
12224df6592SIngo Weinhold	void* argument1, void* argument2);
12324df6592SIngo Weinholdstatus_t thread_create_user_stack(Team* team, Thread* thread, void* stackBase,
12424df6592SIngo Weinhold	size_t stackSize, size_t additionalSize);
12524df6592SIngo Weinholdthread_id thread_create_thread(const ThreadCreationAttributes& attributes,
12624df6592SIngo Weinhold	bool kernel);
1275939c4d7SIngo Weinhold
1285939c4d7SIngo Weinholdthread_id spawn_kernel_thread_etc(thread_func, const char *name, int32 priority,
12924df6592SIngo Weinhold	void *args, team_id team);
13033a9adb3SAxel Dörflerstatus_t wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
13133a9adb3SAxel Dörfler	status_t *_returnCode);
13252a38012Sejakowatz
133636bfc08SIngo Weinholdstatus_t select_thread(int32 object, struct select_info *info, bool kernel);
134636bfc08SIngo Weinholdstatus_t deselect_thread(int32 object, struct select_info *info, bool kernel);
135636bfc08SIngo Weinhold
13634b3b26bSIngo Weinhold#define syscall_64_bit_return_value() arch_syscall_64_bit_return_value()
13734b3b26bSIngo Weinhold
138b95f6d47SIngo Weinholdstatus_t thread_block();
139b95f6d47SIngo Weinholdstatus_t thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout);
140c8dd9f77SPawel Dziepakvoid thread_unblock(Thread* thread, status_t status);
141b95f6d47SIngo Weinhold
14252a38012Sejakowatz// used in syscalls.c
1439e5bff5fSAxel Dörflerstatus_t _user_set_thread_priority(thread_id thread, int32 newPriority);
14454327b01SAxel Dörflerstatus_t _user_rename_thread(thread_id thread, const char *name);
1459e5bff5fSAxel Dörflerstatus_t _user_suspend_thread(thread_id thread);
1469e5bff5fSAxel Dörflerstatus_t _user_resume_thread(thread_id thread);
1470865e4b2SAxel Dörflerstatus_t _user_rename_thread(thread_id thread, const char *name);
1484c49f205SIngo Weinholdthread_id _user_spawn_thread(struct thread_creation_attributes* attributes);
1499e5bff5fSAxel Dörflerstatus_t _user_wait_for_thread(thread_id id, status_t *_returnCode);
15024df6592SIngo Weinholdstatus_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags,
15124df6592SIngo Weinhold	bigtime_t* _remainingTime);
1529e5bff5fSAxel Dörflerstatus_t _user_kill_thread(thread_id thread);
15324df6592SIngo Weinholdstatus_t _user_cancel_thread(thread_id threadID, void (*cancelFunction)(int));
154204131dcSAxel Dörflervoid _user_thread_yield(void);
1559e5bff5fSAxel Dörflervoid _user_exit_thread(status_t return_value);
1569e5bff5fSAxel Dörflerbool _user_has_data(thread_id thread);
1579e5bff5fSAxel Dörflerstatus_t _user_send_data(thread_id thread, int32 code, const void *buffer, size_t buffer_size);
1589e5bff5fSAxel Dörflerstatus_t _user_receive_data(thread_id *_sender, void *buffer, size_t buffer_size);
1599e5bff5fSAxel Dörflerthread_id _user_find_thread(const char *name);
1609e5bff5fSAxel Dörflerstatus_t _user_get_thread_info(thread_id id, thread_info *info);
1619e5bff5fSAxel Dörflerstatus_t _user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info);
1629e5bff5fSAxel Dörfler
163b5e3c0a1SIngo Weinholdstatus_t _user_block_thread(uint32 flags, bigtime_t timeout);
164b5e3c0a1SIngo Weinholdstatus_t _user_unblock_thread(thread_id thread, status_t status);
165b5e3c0a1SIngo Weinholdstatus_t _user_unblock_threads(thread_id* threads, uint32 count,
166b5e3c0a1SIngo Weinhold	status_t status);
167b5e3c0a1SIngo Weinhold
1689e5bff5fSAxel Dörfler// ToDo: these don't belong here
16997dda329SAxel Dörflerstruct rlimit;
1709e5bff5fSAxel Dörflerint _user_getrlimit(int resource, struct rlimit * rlp);
1719e5bff5fSAxel Dörflerint _user_setrlimit(int resource, const struct rlimit * rlp);
17252a38012Sejakowatz
17352a38012Sejakowatz#ifdef __cplusplus
17452a38012Sejakowatz}
17552a38012Sejakowatz#endif
17652a38012Sejakowatz
177b95f6d47SIngo Weinhold
17824df6592SIngo Weinhold/*!	Checks whether the current thread would immediately be interrupted when
17924df6592SIngo Weinhold	blocking it with the given wait/interrupt flags.
18024df6592SIngo Weinhold
18124df6592SIngo Weinhold	The caller must hold the scheduler lock.
18224df6592SIngo Weinhold
18324df6592SIngo Weinhold	\param thread The current thread.
18424df6592SIngo Weinhold	\param flags Wait/interrupt flags to be considered. Relevant are:
18524df6592SIngo Weinhold		- \c B_CAN_INTERRUPT: The thread can be interrupted by any non-blocked
18624df6592SIngo Weinhold			signal. Implies \c B_KILL_CAN_INTERRUPT (specified or not).
18724df6592SIngo Weinhold		- \c B_KILL_CAN_INTERRUPT: The thread can be interrupted by a kill
18824df6592SIngo Weinhold			signal.
18924df6592SIngo Weinhold	\return \c true, if the thread would be interrupted, \c false otherwise.
190b95f6d47SIngo Weinhold*/
191b95f6d47SIngo Weinholdstatic inline bool
1924535495dSIngo Weinholdthread_is_interrupted(Thread* thread, uint32 flags)
193b95f6d47SIngo Weinhold{
19424df6592SIngo Weinhold	sigset_t pendingSignals = thread->AllPendingSignals();
19524df6592SIngo Weinhold	return ((flags & B_CAN_INTERRUPT) != 0
19624df6592SIngo Weinhold			&& (pendingSignals & ~thread->sig_block_mask) != 0)
19724df6592SIngo Weinhold		|| ((flags & B_KILL_CAN_INTERRUPT) != 0
19824df6592SIngo Weinhold			&& (pendingSignals & KILL_SIGNALS) != 0);
199b95f6d47SIngo Weinhold}
200b95f6d47SIngo Weinhold
201b95f6d47SIngo Weinhold
2020e35d5d2SJohn Scipione/*!	Checks whether the given thread is currently blocked (i.e. still waiting
2030e35d5d2SJohn Scipione	for something).
20424df6592SIngo Weinhold
20524df6592SIngo Weinhold	If a stable answer is required, the caller must hold the scheduler lock.
20624df6592SIngo Weinhold	Alternatively, if waiting is not interruptible and cannot time out, holding
20724df6592SIngo Weinhold	the client lock held when calling thread_prepare_to_block() and the
20824df6592SIngo Weinhold	unblocking functions works as well.
20924df6592SIngo Weinhold
21024df6592SIngo Weinhold	\param thread The thread in question.
21124df6592SIngo Weinhold	\return \c true, if the thread is blocked, \c false otherwise.
21224df6592SIngo Weinhold*/
213b95f6d47SIngo Weinholdstatic inline bool
2144535495dSIngo Weinholdthread_is_blocked(Thread* thread)
215b95f6d47SIngo Weinhold{
2162b7ea4cdSPawel Dziepak	return atomic_get(&thread->wait.status) == 1;
217b95f6d47SIngo Weinhold}
218b95f6d47SIngo Weinhold
219b95f6d47SIngo Weinhold
22024df6592SIngo Weinhold/*!	Prepares the current thread for waiting.
22124df6592SIngo Weinhold
22224df6592SIngo Weinhold	This is the first of two steps necessary to block the current thread
22324df6592SIngo Weinhold	(IOW, to let it wait for someone else to unblock it or optionally time out
22424df6592SIngo Weinhold	after a specified delay). The process consists of two steps to avoid race
22524df6592SIngo Weinhold	conditions in case a lock other than the scheduler lock is involved.
22624df6592SIngo Weinhold
22724df6592SIngo Weinhold	Usually the thread waits for some condition to change and this condition is
22824df6592SIngo Weinhold	something reflected in the caller's data structures which should be
22924df6592SIngo Weinhold	protected by a client lock the caller knows about. E.g. in the semaphore
23024df6592SIngo Weinhold	code that lock is a per-semaphore spinlock that protects the semaphore data,
23124df6592SIngo Weinhold	including the semaphore count and the queue of waiting threads. For certain
23224df6592SIngo Weinhold	low-level locking primitives (e.g. mutexes) that client lock is the
23324df6592SIngo Weinhold	scheduler lock itself, which simplifies things a bit.
23424df6592SIngo Weinhold
23524df6592SIngo Weinhold	If a client lock other than the scheduler lock is used, this function must
23624df6592SIngo Weinhold	be called with that lock being held. Afterwards that lock should be dropped
23724df6592SIngo Weinhold	and the function that actually blocks the thread shall be invoked
23811cacd0cSPawel Dziepak	(thread_block[_locked]() or thread_block_with_timeout()). In between these
23911cacd0cSPawel Dziepak	two steps no functionality that uses the thread blocking API for this thread
24011cacd0cSPawel Dziepak	shall be used.
24124df6592SIngo Weinhold
24224df6592SIngo Weinhold	When the caller determines that the condition for unblocking the thread
24324df6592SIngo Weinhold	occurred, it calls thread_unblock_locked() to unblock the thread. At that
24424df6592SIngo Weinhold	time one of locks that are held when calling thread_prepare_to_block() must
24524df6592SIngo Weinhold	be held. Usually that would be the client lock. In two cases it generally
24624df6592SIngo Weinhold	isn't, however, since the unblocking code doesn't know about the client
24711cacd0cSPawel Dziepak	lock: 1. When thread_block_with_timeout() had been used and the timeout
24811cacd0cSPawel Dziepak	occurs. 2. When thread_prepare_to_block() had been called with one or both
24911cacd0cSPawel Dziepak	of the \c B_CAN_INTERRUPT or \c B_KILL_CAN_INTERRUPT flags specified and
25011cacd0cSPawel Dziepak	someone calls thread_interrupt() that is supposed to wake up the thread.
25124df6592SIngo Weinhold	In either of these two cases only the scheduler lock is held by the
25224df6592SIngo Weinhold	unblocking code. A timeout can only happen after
25311cacd0cSPawel Dziepak	thread_block_with_timeout() has been called, but an interruption is
25424df6592SIngo Weinhold	possible at any time. The client code must deal with those situations.
25524df6592SIngo Weinhold
25624df6592SIngo Weinhold	Generally blocking and unblocking threads proceed in the following manner:
25724df6592SIngo Weinhold
25824df6592SIngo Weinhold	Blocking thread:
25924df6592SIngo Weinhold	- Acquire client lock.
26024df6592SIngo Weinhold	- Check client condition and decide whether blocking is necessary.
26124df6592SIngo Weinhold	- Modify some client data structure to indicate that this thread is now
26224df6592SIngo Weinhold		waiting.
26324df6592SIngo Weinhold	- Release client lock (unless client lock is the scheduler lock).
26424df6592SIngo Weinhold	- Block.
26524df6592SIngo Weinhold	- Acquire client lock (unless client lock is the scheduler lock).
26624df6592SIngo Weinhold	- Check client condition and compare with block result. E.g. if the wait was
26724df6592SIngo Weinhold		interrupted or timed out, but the client condition indicates success, it
26824df6592SIngo Weinhold		may be considered a success after all, since usually that happens when
26924df6592SIngo Weinhold		another thread concurrently changed the client condition and also tried
27024df6592SIngo Weinhold		to unblock the waiting thread. It is even necessary when that other
27124df6592SIngo Weinhold		thread changed the client data structures in a way that associate some
27224df6592SIngo Weinhold		resource with the unblocked thread, or otherwise the unblocked thread
27324df6592SIngo Weinhold		would have to reverse that here.
27424df6592SIngo Weinhold	- If still necessary -- i.e. not already taken care of by an unblocking
27524df6592SIngo Weinhold		thread -- modify some client structure to indicate that the thread is no
27624df6592SIngo Weinhold		longer waiting, so it isn't erroneously unblocked later.
27724df6592SIngo Weinhold
27824df6592SIngo Weinhold	Unblocking thread:
27924df6592SIngo Weinhold	- Acquire client lock.
28024df6592SIngo Weinhold	- Check client condition and decide whether a blocked thread can be woken
28124df6592SIngo Weinhold		up.
28224df6592SIngo Weinhold	- Check the client data structure that indicates whether one or more threads
28324df6592SIngo Weinhold		are waiting and which thread(s) need(s) to be woken up.
28424df6592SIngo Weinhold	- Unblock respective thread(s).
28524df6592SIngo Weinhold	- Possibly change some client structure, so that an unblocked thread can
28624df6592SIngo Weinhold		decide whether a concurrent timeout/interruption can be ignored, or
28724df6592SIngo Weinhold		simply so that it doesn't have to do any more cleanup.
28824df6592SIngo Weinhold
28924df6592SIngo Weinhold	Note that in the blocking thread the steps after blocking are strictly
29024df6592SIngo Weinhold	required only if timeouts or interruptions are possible. If they are not,
29124df6592SIngo Weinhold	the blocking thread can only be woken up explicitly by an unblocking thread,
29224df6592SIngo Weinhold	which could already take care of all the necessary client data structure
29324df6592SIngo Weinhold	modifications, so that the blocking thread wouldn't have to do that.
29424df6592SIngo Weinhold
29524df6592SIngo Weinhold	Note that the client lock can but does not have to be a spinlock.
29624df6592SIngo Weinhold	A mutex, a semaphore, or anything that doesn't try to use the thread
29724df6592SIngo Weinhold	blocking API for the calling thread when releasing the lock is fine.
29824df6592SIngo Weinhold	In particular that means in principle thread_prepare_to_block() can be
29924df6592SIngo Weinhold	called with interrupts enabled.
30024df6592SIngo Weinhold
30124df6592SIngo Weinhold	Care must be taken when the wait can be interrupted or can time out,
30224df6592SIngo Weinhold	especially with a client lock that uses the thread blocking API. After a
30324df6592SIngo Weinhold	blocked thread has been interrupted or the the time out occurred it cannot
30424df6592SIngo Weinhold	acquire the client lock (or any other lock using the thread blocking API)
3055d4501aaSMichael Lotz	without first making sure that the thread doesn't still appear to be
30624df6592SIngo Weinhold	waiting to other client code. Otherwise another thread could try to unblock
30724df6592SIngo Weinhold	it which could erroneously unblock the thread while already waiting on the
30824df6592SIngo Weinhold	client lock. So usually when interruptions or timeouts are possible a
30924df6592SIngo Weinhold	spinlock needs to be involved.
31024df6592SIngo Weinhold
31124df6592SIngo Weinhold	\param thread The current thread.
31224df6592SIngo Weinhold	\param flags The blocking flags. Relevant are:
31324df6592SIngo Weinhold		- \c B_CAN_INTERRUPT: The thread can be interrupted by any non-blocked
31424df6592SIngo Weinhold			signal. Implies \c B_KILL_CAN_INTERRUPT (specified or not).
31524df6592SIngo Weinhold		- \c B_KILL_CAN_INTERRUPT: The thread can be interrupted by a kill
31624df6592SIngo Weinhold			signal.
31724df6592SIngo Weinhold	\param type The type of object the thread will be blocked at. Informative/
31824df6592SIngo Weinhold		for debugging purposes. Must be one of the \c THREAD_BLOCK_TYPE_*
31924df6592SIngo Weinhold		constants. \c THREAD_BLOCK_TYPE_OTHER implies that \a object is a
32024df6592SIngo Weinhold		string.
32124df6592SIngo Weinhold	\param object The object the thread will be blocked at.  Informative/for
32224df6592SIngo Weinhold		debugging purposes.
323b95f6d47SIngo Weinhold*/
324b95f6d47SIngo Weinholdstatic inline void
3254535495dSIngo Weinholdthread_prepare_to_block(Thread* thread, uint32 flags, uint32 type,
326f842b6faSIngo Weinhold	const void* object)
327b95f6d47SIngo Weinhold{
328b95f6d47SIngo Weinhold	thread->wait.flags = flags;
329b95f6d47SIngo Weinhold	thread->wait.type = type;
330b95f6d47SIngo Weinhold	thread->wait.object = object;
331b95f6d47SIngo Weinhold	atomic_set(&thread->wait.status, 1);
332b95f6d47SIngo Weinhold		// Set status last to guarantee that the other fields are initialized
333b95f6d47SIngo Weinhold		// when a thread is waiting.
334b95f6d47SIngo Weinhold}
335b95f6d47SIngo Weinhold
336b95f6d47SIngo Weinhold
33724df6592SIngo Weinhold/*!	Unblocks the specified blocked thread.
33824df6592SIngo Weinhold
33924df6592SIngo Weinhold	If the thread is no longer waiting (e.g. because thread_unblock_locked() has
34024df6592SIngo Weinhold	already been called in the meantime), this function does not have any
34124df6592SIngo Weinhold	effect.
34224df6592SIngo Weinhold
34324df6592SIngo Weinhold	The caller must hold the scheduler lock and the client lock (might be the
34424df6592SIngo Weinhold	same).
34524df6592SIngo Weinhold
34624df6592SIngo Weinhold	\param thread The thread to be unblocked.
34724df6592SIngo Weinhold	\param status The unblocking status. That's what the unblocked thread's
34824df6592SIngo Weinhold		call to thread_block_locked() will return.
34924df6592SIngo Weinhold*/
3500338371fSIngo Weinholdstatic inline void
3514535495dSIngo Weinholdthread_unblock_locked(Thread* thread, status_t status)
352b95f6d47SIngo Weinhold{
353b95f6d47SIngo Weinhold	if (atomic_test_and_set(&thread->wait.status, status, 1) != 1)
3540338371fSIngo Weinhold		return;
355b95f6d47SIngo Weinhold
356b95f6d47SIngo Weinhold	// wake up the thread, if it is sleeping
357b95f6d47SIngo Weinhold	if (thread->state == B_THREAD_WAITING)
3580338371fSIngo Weinhold		scheduler_enqueue_in_run_queue(thread);
359b95f6d47SIngo Weinhold}
360b95f6d47SIngo Weinhold
361b95f6d47SIngo Weinhold
36224df6592SIngo Weinhold/*!	Interrupts the specified blocked thread, if possible.
36324df6592SIngo Weinhold
36424df6592SIngo Weinhold	The function checks whether the thread can be interrupted and, if so, calls
36524df6592SIngo Weinhold	\code thread_unblock_locked(thread, B_INTERRUPTED) \endcode. Otherwise the
36624df6592SIngo Weinhold	function is a no-op.
36724df6592SIngo Weinhold
36824df6592SIngo Weinhold	The caller must hold the scheduler lock. Normally thread_unblock_locked()
36924df6592SIngo Weinhold	also requires the client lock to be held, but in this case the caller
37024df6592SIngo Weinhold	usually doesn't know it. This implies that the client code needs to take
37124df6592SIngo Weinhold	special care, if waits are interruptible. See thread_prepare_to_block() for
37224df6592SIngo Weinhold	more information.
37324df6592SIngo Weinhold
37424df6592SIngo Weinhold	\param thread The thread to be interrupted.
37524df6592SIngo Weinhold	\param kill If \c false, the blocked thread is only interrupted, when the
37624df6592SIngo Weinhold		flag \c B_CAN_INTERRUPT was specified for the blocked thread. If
37724df6592SIngo Weinhold		\c true, it is only interrupted, when at least one of the flags
37824df6592SIngo Weinhold		\c B_CAN_INTERRUPT or \c B_KILL_CAN_INTERRUPT was specified for the
37924df6592SIngo Weinhold		blocked thread.
38024df6592SIngo Weinhold	\return \c B_OK, if the thread is interruptible and thread_unblock_locked()
38124df6592SIngo Weinhold		was called, \c B_NOT_ALLOWED otherwise. \c B_OK doesn't imply that the
38224df6592SIngo Weinhold		thread actually has been interrupted -- it could have been unblocked
38324df6592SIngo Weinhold		before already.
38424df6592SIngo Weinhold*/
385b95f6d47SIngo Weinholdstatic inline status_t
3864535495dSIngo Weinholdthread_interrupt(Thread* thread, bool kill)
387b95f6d47SIngo Weinhold{
388135bb9c9SPawel Dziepak	if (thread_is_blocked(thread)) {
389135bb9c9SPawel Dziepak		if ((thread->wait.flags & B_CAN_INTERRUPT) != 0
390135bb9c9SPawel Dziepak			|| (kill && (thread->wait.flags & B_KILL_CAN_INTERRUPT) != 0)) {
391135bb9c9SPawel Dziepak			thread_unblock_locked(thread, B_INTERRUPTED);
392135bb9c9SPawel Dziepak			return B_OK;
393135bb9c9SPawel Dziepak		}
394b95f6d47SIngo Weinhold	}
395b95f6d47SIngo Weinhold
396b95f6d47SIngo Weinhold	return B_NOT_ALLOWED;
397b95f6d47SIngo Weinhold}
398b95f6d47SIngo Weinhold
399b95f6d47SIngo Weinhold
4006503e5d9SIngo Weinholdstatic inline void
4014535495dSIngo Weinholdthread_pin_to_current_cpu(Thread* thread)
4026503e5d9SIngo Weinhold{
4036503e5d9SIngo Weinhold	thread->pinned_to_cpu++;
4046503e5d9SIngo Weinhold}
4056503e5d9SIngo Weinhold
4066503e5d9SIngo Weinhold
4076503e5d9SIngo Weinholdstatic inline void
4084535495dSIngo Weinholdthread_unpin_from_current_cpu(Thread* thread)
4096503e5d9SIngo Weinhold{
4106503e5d9SIngo Weinhold	thread->pinned_to_cpu--;
4116503e5d9SIngo Weinhold}
4126503e5d9SIngo Weinhold
4136503e5d9SIngo Weinhold
414