2002-07-09 16:24:59 +04:00
|
|
|
/*
|
2007-08-16 22:01:47 +04:00
|
|
|
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de.
|
2004-12-01 00:06:11 +03:00
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
|
|
|
* Distributed under the terms of the NewOS License.
|
|
|
|
*/
|
2002-07-09 16:24:59 +04:00
|
|
|
#ifndef _THREAD_H
|
|
|
|
#define _THREAD_H
|
|
|
|
|
|
|
|
|
2003-01-27 05:54:21 +03:00
|
|
|
#include <OS.h>
|
2002-07-09 16:24:59 +04:00
|
|
|
#include <thread_types.h>
|
|
|
|
#include <arch/thread.h>
|
|
|
|
|
* Introduced a set of functions (thread_prepare_to_block(),
thread_block(), thread_unblock(),...) that allow a thread to wait for
something without needing a semaphore or condition variable. It can
simply block and another thread can unblock it. Supports timeouts and
interrupting. Both semaphores and condition variables use this
common mechanism, now.
* Semaphores:
- Some simplifications due to the thread blocking mechanism.
- Changed locking order to sem -> thread. It was the other way around
before and when introducing the wait_for_objects() support I had
also introduced a situation where the locking was reverse, which
could potentially cause a dead lock on SMP systems.
- Instead of queueing thread structures, a semaphore queues
queued_thread entries now, which are created on the stack. The
thread::sem structure could thus be removed.
- Added sem_entry::net_count, which is sem_entry::count plus the
acquisition count of all waiting threads. This number is needed in
remove_thread_from_sem() and instead of computing it there we
maintain it.
- Fixed remove_thread_from_sem(). It would not unblock threads, if
the sem count was <= 0.
- Made sem::last_acquirer unconditional. It is actually needed for
sem_info::latest_holder. Fixed fill_sem_info() accordingly.
- Added some optional tracing output, though only via ktrace_printf().
* Condition variables:
- Could be simplified significantly through the use of the thread
blocking mechanism. Removed a good deal of unnecessary code.
- Moved the ConditionVariableEntry "flags" parameter from Wait() to
Add(), and adjusted all places where condition variables are used
accordingly.
* snooze() uses thread_block_with_timeout() instead of a semaphore.
* Simplified thread interrupting in the signal and user debugger code.
Instead of separate functions for threads waiting on a semaphore or
condititon variable, we only have a single thread_interrupt(), now.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25099 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-04-22 20:22:42 +04:00
|
|
|
// For the thread blocking inline functions only.
|
|
|
|
#include <kscheduler.h>
|
|
|
|
#include <ksignal.h>
|
|
|
|
|
|
|
|
|
2005-01-25 17:24:01 +03:00
|
|
|
struct kernel_args;
|
2007-10-02 23:47:31 +04:00
|
|
|
struct select_info;
|
2008-05-09 05:32:36 +04:00
|
|
|
struct thread_creation_attributes;
|
|
|
|
|
2002-10-23 21:31:10 +04:00
|
|
|
|
2009-04-12 01:45:25 +04:00
|
|
|
// thread notifications
|
|
|
|
#define THREAD_MONITOR '_tm_'
|
|
|
|
#define THREAD_ADDED 0x01
|
|
|
|
#define THREAD_REMOVED 0x02
|
|
|
|
|
|
|
|
|
2004-03-16 05:40:03 +03:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
void thread_enqueue(struct thread *t, struct thread_queue *q);
|
|
|
|
struct thread *thread_lookat_queue(struct thread_queue *q);
|
|
|
|
struct thread *thread_dequeue(struct thread_queue *q);
|
2007-08-16 22:01:47 +04:00
|
|
|
struct thread *thread_dequeue_id(struct thread_queue *q, thread_id id);
|
2003-01-27 05:54:21 +03:00
|
|
|
|
2008-01-11 03:36:44 +03:00
|
|
|
void thread_at_kernel_entry(bigtime_t now);
|
2002-10-05 23:44:27 +04:00
|
|
|
// called when the thread enters the kernel on behalf of the thread
|
2005-02-11 06:10:21 +03:00
|
|
|
void thread_at_kernel_exit(void);
|
2008-01-11 03:36:44 +03:00
|
|
|
void thread_at_kernel_exit_no_signals(void);
|
2007-08-16 22:01:47 +04:00
|
|
|
void thread_reset_for_exec(void);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2005-01-25 17:24:01 +03:00
|
|
|
status_t thread_init(struct kernel_args *args);
|
2007-02-19 03:11:24 +03:00
|
|
|
status_t thread_preboot_init_percpu(struct kernel_args *args, int32 cpuNum);
|
2008-02-07 14:40:31 +03:00
|
|
|
void thread_yield(bool force);
|
2002-10-26 05:11:15 +04:00
|
|
|
void thread_exit(void);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2004-12-01 00:06:11 +03:00
|
|
|
int32 thread_max_threads(void);
|
|
|
|
int32 thread_used_threads(void);
|
|
|
|
|
2008-08-23 03:51:22 +04:00
|
|
|
const char* thread_state_to_text(struct thread* thread, int32 state);
|
|
|
|
|
2008-08-31 04:37:02 +04:00
|
|
|
int32 thread_get_io_priority(thread_id id);
|
|
|
|
void thread_set_io_priority(int32 priority);
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
#define thread_get_current_thread arch_thread_get_current_thread
|
|
|
|
|
|
|
|
struct thread *thread_get_thread_struct(thread_id id);
|
2002-08-16 17:14:29 +04:00
|
|
|
struct thread *thread_get_thread_struct_locked(thread_id id);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-10-05 05:17:28 +04:00
|
|
|
static thread_id thread_get_current_thread_id(void);
|
|
|
|
static inline thread_id
|
|
|
|
thread_get_current_thread_id(void)
|
|
|
|
{
|
2006-02-01 23:03:55 +03:00
|
|
|
struct thread *thread = thread_get_current_thread();
|
|
|
|
return thread ? thread->id : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
thread_is_idle_thread(struct thread *thread)
|
|
|
|
{
|
|
|
|
return thread->entry == NULL;
|
2002-07-09 16:24:59 +04:00
|
|
|
}
|
2002-10-05 05:17:28 +04:00
|
|
|
|
2009-04-12 01:45:25 +04:00
|
|
|
typedef bool (*thread_iterator_callback)(struct thread* thread, void* cookie);
|
|
|
|
struct thread* thread_iterate_through_threads(thread_iterator_callback callback,
|
|
|
|
void* cookie);
|
|
|
|
|
2005-03-09 04:42:37 +03:00
|
|
|
thread_id allocate_thread_id(void);
|
|
|
|
thread_id peek_next_thread_id(void);
|
2005-03-08 21:16:16 +03:00
|
|
|
|
|
|
|
thread_id spawn_kernel_thread_etc(thread_func, const char *name, int32 priority,
|
|
|
|
void *args, team_id team, thread_id threadID);
|
2006-03-08 19:41:03 +03:00
|
|
|
status_t wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
|
|
|
|
status_t *_returnCode);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2007-10-02 23:47:31 +04:00
|
|
|
status_t select_thread(int32 object, struct select_info *info, bool kernel);
|
|
|
|
status_t deselect_thread(int32 object, struct select_info *info, bool kernel);
|
|
|
|
|
2008-01-11 03:36:44 +03:00
|
|
|
#define syscall_64_bit_return_value() arch_syscall_64_bit_return_value()
|
|
|
|
|
* Introduced a set of functions (thread_prepare_to_block(),
thread_block(), thread_unblock(),...) that allow a thread to wait for
something without needing a semaphore or condition variable. It can
simply block and another thread can unblock it. Supports timeouts and
interrupting. Both semaphores and condition variables use this
common mechanism, now.
* Semaphores:
- Some simplifications due to the thread blocking mechanism.
- Changed locking order to sem -> thread. It was the other way around
before and when introducing the wait_for_objects() support I had
also introduced a situation where the locking was reverse, which
could potentially cause a dead lock on SMP systems.
- Instead of queueing thread structures, a semaphore queues
queued_thread entries now, which are created on the stack. The
thread::sem structure could thus be removed.
- Added sem_entry::net_count, which is sem_entry::count plus the
acquisition count of all waiting threads. This number is needed in
remove_thread_from_sem() and instead of computing it there we
maintain it.
- Fixed remove_thread_from_sem(). It would not unblock threads, if
the sem count was <= 0.
- Made sem::last_acquirer unconditional. It is actually needed for
sem_info::latest_holder. Fixed fill_sem_info() accordingly.
- Added some optional tracing output, though only via ktrace_printf().
* Condition variables:
- Could be simplified significantly through the use of the thread
blocking mechanism. Removed a good deal of unnecessary code.
- Moved the ConditionVariableEntry "flags" parameter from Wait() to
Add(), and adjusted all places where condition variables are used
accordingly.
* snooze() uses thread_block_with_timeout() instead of a semaphore.
* Simplified thread interrupting in the signal and user debugger code.
Instead of separate functions for threads waiting on a semaphore or
condititon variable, we only have a single thread_interrupt(), now.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25099 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-04-22 20:22:42 +04:00
|
|
|
status_t thread_block();
|
|
|
|
status_t thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout);
|
|
|
|
status_t thread_block_with_timeout_locked(uint32 timeoutFlags,
|
|
|
|
bigtime_t timeout);
|
|
|
|
bool thread_unblock(status_t threadID, status_t status);
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
// used in syscalls.c
|
2004-03-03 03:52:47 +03:00
|
|
|
status_t _user_set_thread_priority(thread_id thread, int32 newPriority);
|
2004-04-07 01:30:06 +04:00
|
|
|
status_t _user_rename_thread(thread_id thread, const char *name);
|
2004-03-03 03:52:47 +03:00
|
|
|
status_t _user_suspend_thread(thread_id thread);
|
|
|
|
status_t _user_resume_thread(thread_id thread);
|
2004-05-24 16:12:58 +04:00
|
|
|
status_t _user_rename_thread(thread_id thread, const char *name);
|
2008-05-09 05:32:36 +04:00
|
|
|
thread_id _user_spawn_thread(struct thread_creation_attributes* attributes);
|
2004-03-03 03:52:47 +03:00
|
|
|
status_t _user_wait_for_thread(thread_id id, status_t *_returnCode);
|
|
|
|
status_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags);
|
|
|
|
status_t _user_kill_thread(thread_id thread);
|
2006-01-31 05:29:02 +03:00
|
|
|
void _user_thread_yield(void);
|
2004-03-03 03:52:47 +03:00
|
|
|
void _user_exit_thread(status_t return_value);
|
|
|
|
bool _user_has_data(thread_id thread);
|
|
|
|
status_t _user_send_data(thread_id thread, int32 code, const void *buffer, size_t buffer_size);
|
|
|
|
status_t _user_receive_data(thread_id *_sender, void *buffer, size_t buffer_size);
|
|
|
|
thread_id _user_find_thread(const char *name);
|
|
|
|
status_t _user_get_thread_info(thread_id id, thread_info *info);
|
|
|
|
status_t _user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info);
|
|
|
|
|
2008-05-12 17:53:56 +04:00
|
|
|
status_t _user_block_thread(uint32 flags, bigtime_t timeout);
|
|
|
|
status_t _user_unblock_thread(thread_id thread, status_t status);
|
|
|
|
status_t _user_unblock_threads(thread_id* threads, uint32 count,
|
|
|
|
status_t status);
|
|
|
|
|
2004-03-03 03:52:47 +03:00
|
|
|
// ToDo: these don't belong here
|
2004-12-14 01:22:45 +03:00
|
|
|
struct rlimit;
|
2004-03-03 03:52:47 +03:00
|
|
|
int _user_getrlimit(int resource, struct rlimit * rlp);
|
|
|
|
int _user_setrlimit(int resource, const struct rlimit * rlp);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
* Introduced a set of functions (thread_prepare_to_block(),
thread_block(), thread_unblock(),...) that allow a thread to wait for
something without needing a semaphore or condition variable. It can
simply block and another thread can unblock it. Supports timeouts and
interrupting. Both semaphores and condition variables use this
common mechanism, now.
* Semaphores:
- Some simplifications due to the thread blocking mechanism.
- Changed locking order to sem -> thread. It was the other way around
before and when introducing the wait_for_objects() support I had
also introduced a situation where the locking was reverse, which
could potentially cause a dead lock on SMP systems.
- Instead of queueing thread structures, a semaphore queues
queued_thread entries now, which are created on the stack. The
thread::sem structure could thus be removed.
- Added sem_entry::net_count, which is sem_entry::count plus the
acquisition count of all waiting threads. This number is needed in
remove_thread_from_sem() and instead of computing it there we
maintain it.
- Fixed remove_thread_from_sem(). It would not unblock threads, if
the sem count was <= 0.
- Made sem::last_acquirer unconditional. It is actually needed for
sem_info::latest_holder. Fixed fill_sem_info() accordingly.
- Added some optional tracing output, though only via ktrace_printf().
* Condition variables:
- Could be simplified significantly through the use of the thread
blocking mechanism. Removed a good deal of unnecessary code.
- Moved the ConditionVariableEntry "flags" parameter from Wait() to
Add(), and adjusted all places where condition variables are used
accordingly.
* snooze() uses thread_block_with_timeout() instead of a semaphore.
* Simplified thread interrupting in the signal and user debugger code.
Instead of separate functions for threads waiting on a semaphore or
condititon variable, we only have a single thread_interrupt(), now.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25099 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-04-22 20:22:42 +04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
\a thread must be the current thread.
|
|
|
|
Thread lock can be, but doesn't need to be held.
|
|
|
|
*/
|
|
|
|
static inline bool
|
|
|
|
thread_is_interrupted(struct thread* thread, uint32 flags)
|
|
|
|
{
|
|
|
|
return ((flags & B_CAN_INTERRUPT)
|
|
|
|
&& (thread->sig_pending & ~thread->sig_block_mask) != 0)
|
|
|
|
|| ((flags & B_KILL_CAN_INTERRUPT)
|
|
|
|
&& (thread->sig_pending & KILL_SIGNALS));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
thread_is_blocked(struct thread* thread)
|
|
|
|
{
|
|
|
|
return thread->wait.status == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\a thread must be the current thread.
|
|
|
|
Thread lock can be, but doesn't need to be locked.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
thread_prepare_to_block(struct thread* thread, uint32 flags, uint32 type,
|
2008-04-23 01:43:54 +04:00
|
|
|
const void* object)
|
* Introduced a set of functions (thread_prepare_to_block(),
thread_block(), thread_unblock(),...) that allow a thread to wait for
something without needing a semaphore or condition variable. It can
simply block and another thread can unblock it. Supports timeouts and
interrupting. Both semaphores and condition variables use this
common mechanism, now.
* Semaphores:
- Some simplifications due to the thread blocking mechanism.
- Changed locking order to sem -> thread. It was the other way around
before and when introducing the wait_for_objects() support I had
also introduced a situation where the locking was reverse, which
could potentially cause a dead lock on SMP systems.
- Instead of queueing thread structures, a semaphore queues
queued_thread entries now, which are created on the stack. The
thread::sem structure could thus be removed.
- Added sem_entry::net_count, which is sem_entry::count plus the
acquisition count of all waiting threads. This number is needed in
remove_thread_from_sem() and instead of computing it there we
maintain it.
- Fixed remove_thread_from_sem(). It would not unblock threads, if
the sem count was <= 0.
- Made sem::last_acquirer unconditional. It is actually needed for
sem_info::latest_holder. Fixed fill_sem_info() accordingly.
- Added some optional tracing output, though only via ktrace_printf().
* Condition variables:
- Could be simplified significantly through the use of the thread
blocking mechanism. Removed a good deal of unnecessary code.
- Moved the ConditionVariableEntry "flags" parameter from Wait() to
Add(), and adjusted all places where condition variables are used
accordingly.
* snooze() uses thread_block_with_timeout() instead of a semaphore.
* Simplified thread interrupting in the signal and user debugger code.
Instead of separate functions for threads waiting on a semaphore or
condititon variable, we only have a single thread_interrupt(), now.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25099 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-04-22 20:22:42 +04:00
|
|
|
{
|
|
|
|
thread->wait.flags = flags;
|
|
|
|
thread->wait.type = type;
|
|
|
|
thread->wait.object = object;
|
|
|
|
atomic_set(&thread->wait.status, 1);
|
|
|
|
// Set status last to guarantee that the other fields are initialized
|
|
|
|
// when a thread is waiting.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline status_t
|
|
|
|
thread_block_locked(struct thread* thread)
|
|
|
|
{
|
|
|
|
if (thread->wait.status == 1) {
|
|
|
|
// check for signals, if interruptable
|
|
|
|
if (thread_is_interrupted(thread, thread->wait.flags)) {
|
|
|
|
thread->wait.status = B_INTERRUPTED;
|
|
|
|
} else {
|
|
|
|
thread->next_state = B_THREAD_WAITING;
|
|
|
|
scheduler_reschedule();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return thread->wait.status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
thread_unblock_locked(struct thread* thread, status_t status)
|
|
|
|
{
|
|
|
|
if (atomic_test_and_set(&thread->wait.status, status, 1) != 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// wake up the thread, if it is sleeping
|
|
|
|
if (thread->state == B_THREAD_WAITING)
|
2009-08-21 08:11:40 +04:00
|
|
|
return scheduler_enqueue_in_run_queue(thread);
|
|
|
|
|
|
|
|
return false;
|
* Introduced a set of functions (thread_prepare_to_block(),
thread_block(), thread_unblock(),...) that allow a thread to wait for
something without needing a semaphore or condition variable. It can
simply block and another thread can unblock it. Supports timeouts and
interrupting. Both semaphores and condition variables use this
common mechanism, now.
* Semaphores:
- Some simplifications due to the thread blocking mechanism.
- Changed locking order to sem -> thread. It was the other way around
before and when introducing the wait_for_objects() support I had
also introduced a situation where the locking was reverse, which
could potentially cause a dead lock on SMP systems.
- Instead of queueing thread structures, a semaphore queues
queued_thread entries now, which are created on the stack. The
thread::sem structure could thus be removed.
- Added sem_entry::net_count, which is sem_entry::count plus the
acquisition count of all waiting threads. This number is needed in
remove_thread_from_sem() and instead of computing it there we
maintain it.
- Fixed remove_thread_from_sem(). It would not unblock threads, if
the sem count was <= 0.
- Made sem::last_acquirer unconditional. It is actually needed for
sem_info::latest_holder. Fixed fill_sem_info() accordingly.
- Added some optional tracing output, though only via ktrace_printf().
* Condition variables:
- Could be simplified significantly through the use of the thread
blocking mechanism. Removed a good deal of unnecessary code.
- Moved the ConditionVariableEntry "flags" parameter from Wait() to
Add(), and adjusted all places where condition variables are used
accordingly.
* snooze() uses thread_block_with_timeout() instead of a semaphore.
* Simplified thread interrupting in the signal and user debugger code.
Instead of separate functions for threads waiting on a semaphore or
condititon variable, we only have a single thread_interrupt(), now.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25099 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-04-22 20:22:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline status_t
|
|
|
|
thread_interrupt(struct thread* thread, bool kill)
|
|
|
|
{
|
|
|
|
if ((thread->wait.flags & B_CAN_INTERRUPT) != 0
|
|
|
|
|| (kill && (thread->wait.flags & B_KILL_CAN_INTERRUPT) != 0)) {
|
|
|
|
thread_unblock_locked(thread, B_INTERRUPTED);
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return B_NOT_ALLOWED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-11 22:11:12 +04:00
|
|
|
static inline void
|
|
|
|
thread_pin_to_current_cpu(struct thread* thread)
|
|
|
|
{
|
|
|
|
thread->pinned_to_cpu++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
thread_unpin_from_current_cpu(struct thread* thread)
|
|
|
|
{
|
|
|
|
thread->pinned_to_cpu--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
thread_disable_scheduling(struct thread* thread)
|
|
|
|
{
|
|
|
|
thread->keep_scheduled++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
thread_enable_scheduling(struct thread* thread)
|
|
|
|
{
|
|
|
|
thread->keep_scheduled--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
#endif /* _THREAD_H */
|