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