xref: /haiku/headers/private/kernel/thread.h (revision b289aaf66bbf6e173aa90fa194fc256965f1b34d)
1 /*
2  * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de.
4  * Distributed under the terms of the MIT License.
5  *
6  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 #ifndef _THREAD_H
10 #define _THREAD_H
11 
12 
13 #include <OS.h>
14 #include <thread_types.h>
15 #include <arch/thread.h>
16 
17 // For the thread blocking inline functions only.
18 #include <kscheduler.h>
19 #include <ksignal.h>
20 
21 
22 struct kernel_args;
23 struct select_info;
24 struct thread_creation_attributes;
25 
26 
27 // thread notifications
28 #define THREAD_MONITOR	'_tm_'
29 #define THREAD_ADDED	0x01
30 #define THREAD_REMOVED	0x02
31 
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 void thread_enqueue(struct thread *t, struct thread_queue *q);
38 struct thread *thread_lookat_queue(struct thread_queue *q);
39 struct thread *thread_dequeue(struct thread_queue *q);
40 struct thread *thread_dequeue_id(struct thread_queue *q, thread_id id);
41 
42 void thread_at_kernel_entry(bigtime_t now);
43 	// called when the thread enters the kernel on behalf of the thread
44 void thread_at_kernel_exit(void);
45 void thread_at_kernel_exit_no_signals(void);
46 void thread_reset_for_exec(void);
47 
48 status_t thread_init(struct kernel_args *args);
49 status_t thread_preboot_init_percpu(struct kernel_args *args, int32 cpuNum);
50 void thread_yield(bool force);
51 void thread_exit(void);
52 
53 int32 thread_max_threads(void);
54 int32 thread_used_threads(void);
55 
56 const char* thread_state_to_text(struct thread* thread, int32 state);
57 
58 int32 thread_get_io_priority(thread_id id);
59 void thread_set_io_priority(int32 priority);
60 
61 #define thread_get_current_thread arch_thread_get_current_thread
62 
63 struct thread *thread_get_thread_struct(thread_id id);
64 struct thread *thread_get_thread_struct_locked(thread_id id);
65 
66 static thread_id thread_get_current_thread_id(void);
67 static inline thread_id
68 thread_get_current_thread_id(void)
69 {
70 	struct thread *thread = thread_get_current_thread();
71 	return thread ? thread->id : 0;
72 }
73 
74 static inline bool
75 thread_is_idle_thread(struct thread *thread)
76 {
77 	return thread->entry == NULL;
78 }
79 
80 typedef bool (*thread_iterator_callback)(struct thread* thread, void* cookie);
81 struct thread* thread_iterate_through_threads(thread_iterator_callback callback,
82 	void* cookie);
83 
84 thread_id allocate_thread_id(void);
85 thread_id peek_next_thread_id(void);
86 
87 thread_id spawn_kernel_thread_etc(thread_func, const char *name, int32 priority,
88 	void *args, team_id team, thread_id threadID);
89 status_t wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
90 	status_t *_returnCode);
91 
92 status_t select_thread(int32 object, struct select_info *info, bool kernel);
93 status_t deselect_thread(int32 object, struct select_info *info, bool kernel);
94 
95 #define syscall_64_bit_return_value() arch_syscall_64_bit_return_value()
96 
97 status_t thread_block();
98 status_t thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout);
99 status_t thread_block_with_timeout_locked(uint32 timeoutFlags,
100 			bigtime_t timeout);
101 void thread_unblock(status_t threadID, status_t status);
102 
103 // used in syscalls.c
104 status_t _user_set_thread_priority(thread_id thread, int32 newPriority);
105 status_t _user_rename_thread(thread_id thread, const char *name);
106 status_t _user_suspend_thread(thread_id thread);
107 status_t _user_resume_thread(thread_id thread);
108 status_t _user_rename_thread(thread_id thread, const char *name);
109 thread_id _user_spawn_thread(struct thread_creation_attributes* attributes);
110 status_t _user_wait_for_thread(thread_id id, status_t *_returnCode);
111 status_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags);
112 status_t _user_kill_thread(thread_id thread);
113 void _user_thread_yield(void);
114 void _user_exit_thread(status_t return_value);
115 bool _user_has_data(thread_id thread);
116 status_t _user_send_data(thread_id thread, int32 code, const void *buffer, size_t buffer_size);
117 status_t _user_receive_data(thread_id *_sender, void *buffer, size_t buffer_size);
118 thread_id _user_find_thread(const char *name);
119 status_t _user_get_thread_info(thread_id id, thread_info *info);
120 status_t _user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info);
121 
122 status_t _user_block_thread(uint32 flags, bigtime_t timeout);
123 status_t _user_unblock_thread(thread_id thread, status_t status);
124 status_t _user_unblock_threads(thread_id* threads, uint32 count,
125 	status_t status);
126 
127 // ToDo: these don't belong here
128 struct rlimit;
129 int _user_getrlimit(int resource, struct rlimit * rlp);
130 int _user_setrlimit(int resource, const struct rlimit * rlp);
131 
132 #ifdef __cplusplus
133 }
134 #endif
135 
136 
137 /*!
138 	\a thread must be the current thread.
139 	Thread lock can be, but doesn't need to be held.
140 */
141 static inline bool
142 thread_is_interrupted(struct thread* thread, uint32 flags)
143 {
144 	return ((flags & B_CAN_INTERRUPT)
145 			&& (thread->sig_pending & ~thread->sig_block_mask) != 0)
146 		|| ((flags & B_KILL_CAN_INTERRUPT)
147 			&& (thread->sig_pending & KILL_SIGNALS));
148 }
149 
150 
151 static inline bool
152 thread_is_blocked(struct thread* thread)
153 {
154 	return thread->wait.status == 1;
155 }
156 
157 
158 /*!
159 	\a thread must be the current thread.
160 	Thread lock can be, but doesn't need to be locked.
161 */
162 static inline void
163 thread_prepare_to_block(struct thread* thread, uint32 flags, uint32 type,
164 	const void* object)
165 {
166 	thread->wait.flags = flags;
167 	thread->wait.type = type;
168 	thread->wait.object = object;
169 	atomic_set(&thread->wait.status, 1);
170 		// Set status last to guarantee that the other fields are initialized
171 		// when a thread is waiting.
172 }
173 
174 
175 static inline status_t
176 thread_block_locked(struct thread* thread)
177 {
178 	if (thread->wait.status == 1) {
179 		// check for signals, if interruptable
180 		if (thread_is_interrupted(thread, thread->wait.flags)) {
181 			thread->wait.status = B_INTERRUPTED;
182 		} else {
183 			thread->next_state = B_THREAD_WAITING;
184 			scheduler_reschedule();
185 		}
186 	}
187 
188 	return thread->wait.status;
189 }
190 
191 
192 static inline void
193 thread_unblock_locked(struct thread* thread, status_t status)
194 {
195 	if (atomic_test_and_set(&thread->wait.status, status, 1) != 1)
196 		return;
197 
198 	// wake up the thread, if it is sleeping
199 	if (thread->state == B_THREAD_WAITING)
200 		scheduler_enqueue_in_run_queue(thread);
201 }
202 
203 
204 static inline status_t
205 thread_interrupt(struct thread* thread, bool kill)
206 {
207 	if ((thread->wait.flags & B_CAN_INTERRUPT) != 0
208 		|| (kill && (thread->wait.flags & B_KILL_CAN_INTERRUPT) != 0)) {
209 		thread_unblock_locked(thread, B_INTERRUPTED);
210 		return B_OK;
211 	}
212 
213 	return B_NOT_ALLOWED;
214 }
215 
216 
217 static inline void
218 thread_pin_to_current_cpu(struct thread* thread)
219 {
220 	thread->pinned_to_cpu++;
221 }
222 
223 
224 static inline void
225 thread_unpin_from_current_cpu(struct thread* thread)
226 {
227 	thread->pinned_to_cpu--;
228 }
229 
230 
231 #endif /* _THREAD_H */
232