2002-07-09 16:24:59 +04:00
|
|
|
/*
|
2014-03-17 05:11:22 +04:00
|
|
|
* Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org.
|
2011-01-11 00:54:38 +03:00
|
|
|
* Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
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
|
|
|
|
2014-01-06 09:49:34 +04:00
|
|
|
#include <arch/atomic.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>
|
2014-01-06 09:49:34 +04:00
|
|
|
#include <thread_types.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
|
|
|
|
|
|
|
|
2011-06-12 04:00:23 +04:00
|
|
|
struct arch_fork_arg;
|
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
|
2010-12-16 04:44:15 +03:00
|
|
|
#define THREAD_MONITOR '_tm_'
|
|
|
|
#define THREAD_ADDED 0x01
|
|
|
|
#define THREAD_REMOVED 0x02
|
|
|
|
#define THREAD_NAME_CHANGED 0x04
|
2009-04-12 01:45:25 +04:00
|
|
|
|
|
|
|
|
2011-06-12 04:00:23 +04:00
|
|
|
namespace BKernel {
|
|
|
|
|
|
|
|
|
|
|
|
struct ThreadCreationAttributes : thread_creation_attributes {
|
|
|
|
// when calling from kernel only
|
|
|
|
team_id team;
|
|
|
|
Thread* thread;
|
|
|
|
sigset_t signal_mask;
|
|
|
|
size_t additional_stack_size; // additional space in the stack
|
|
|
|
// area after the TLS region, not
|
|
|
|
// used as thread stack
|
|
|
|
thread_func kernelEntry;
|
|
|
|
void* kernelArgument;
|
|
|
|
arch_fork_arg* forkArgs; // If non-NULL, the userland thread
|
|
|
|
// will be started with this
|
|
|
|
// register context.
|
|
|
|
|
|
|
|
public:
|
|
|
|
ThreadCreationAttributes() {}
|
|
|
|
// no-init constructor
|
|
|
|
ThreadCreationAttributes(
|
|
|
|
thread_func function, const char* name,
|
|
|
|
int32 priority, void* arg,
|
|
|
|
team_id team = -1, Thread* thread = NULL);
|
|
|
|
|
|
|
|
status_t InitFromUserAttributes(
|
|
|
|
const thread_creation_attributes*
|
|
|
|
userAttributes,
|
|
|
|
char* nameBuffer);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace BKernel
|
|
|
|
|
|
|
|
using BKernel::ThreadCreationAttributes;
|
|
|
|
|
|
|
|
|
2013-11-08 05:41:26 +04:00
|
|
|
extern spinlock gThreadCreationLock;
|
|
|
|
|
|
|
|
|
2004-03-16 05:40:03 +03:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
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);
|
2013-10-09 22:42:34 +04:00
|
|
|
void thread_yield(void);
|
2002-10-26 05:11:15 +04:00
|
|
|
void thread_exit(void);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2013-11-25 01:51:07 +04:00
|
|
|
void thread_map(void (*function)(Thread* thread, void* data), void* data);
|
|
|
|
|
2004-12-01 00:06:11 +03:00
|
|
|
int32 thread_max_threads(void);
|
|
|
|
int32 thread_used_threads(void);
|
|
|
|
|
2011-01-11 00:54:38 +03:00
|
|
|
const char* thread_state_to_text(Thread* thread, int32 state);
|
2008-08-23 03:51:22 +04:00
|
|
|
|
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
|
|
|
|
|
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)
|
|
|
|
{
|
2011-01-11 00:54:38 +03:00
|
|
|
Thread *thread = thread_get_current_thread();
|
2006-02-01 23:03:55 +03:00
|
|
|
return thread ? thread->id : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
2011-01-11 00:54:38 +03:00
|
|
|
thread_is_idle_thread(Thread *thread)
|
2006-02-01 23:03:55 +03:00
|
|
|
{
|
2011-06-12 04:00:23 +04:00
|
|
|
return thread->priority == B_IDLE_PRIORITY;
|
2002-07-09 16:24:59 +04:00
|
|
|
}
|
2002-10-05 05:17:28 +04:00
|
|
|
|
2011-06-12 04:00:23 +04:00
|
|
|
thread_id allocate_thread_id();
|
|
|
|
thread_id peek_next_thread_id();
|
2009-04-12 01:45:25 +04:00
|
|
|
|
2011-06-12 04:00:23 +04:00
|
|
|
status_t thread_enter_userspace_new_team(Thread* thread, addr_t entryFunction,
|
|
|
|
void* argument1, void* argument2);
|
|
|
|
status_t thread_create_user_stack(Team* team, Thread* thread, void* stackBase,
|
|
|
|
size_t stackSize, size_t additionalSize);
|
|
|
|
thread_id thread_create_thread(const ThreadCreationAttributes& attributes,
|
|
|
|
bool kernel);
|
2005-03-08 21:16:16 +03:00
|
|
|
|
|
|
|
thread_id spawn_kernel_thread_etc(thread_func, const char *name, int32 priority,
|
2011-06-12 04:00:23 +04:00
|
|
|
void *args, team_id team);
|
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);
|
2013-10-30 06:58:36 +04:00
|
|
|
void thread_unblock(Thread* thread, status_t status);
|
* 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
|
|
|
|
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);
|
2011-06-12 04:00:23 +04:00
|
|
|
status_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags,
|
|
|
|
bigtime_t* _remainingTime);
|
2004-03-03 03:52:47 +03:00
|
|
|
status_t _user_kill_thread(thread_id thread);
|
2011-06-12 04:00:23 +04:00
|
|
|
status_t _user_cancel_thread(thread_id threadID, void (*cancelFunction)(int));
|
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
|
|
|
|
2011-06-12 04:00:23 +04:00
|
|
|
/*! Checks whether the current thread would immediately be interrupted when
|
|
|
|
blocking it with the given wait/interrupt flags.
|
|
|
|
|
|
|
|
The caller must hold the scheduler lock.
|
|
|
|
|
|
|
|
\param thread The current thread.
|
|
|
|
\param flags Wait/interrupt flags to be considered. Relevant are:
|
|
|
|
- \c B_CAN_INTERRUPT: The thread can be interrupted by any non-blocked
|
|
|
|
signal. Implies \c B_KILL_CAN_INTERRUPT (specified or not).
|
|
|
|
- \c B_KILL_CAN_INTERRUPT: The thread can be interrupted by a kill
|
|
|
|
signal.
|
|
|
|
\return \c true, if the thread would be interrupted, \c false otherwise.
|
* 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 bool
|
2011-01-11 00:54:38 +03:00
|
|
|
thread_is_interrupted(Thread* thread, uint32 flags)
|
* 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
|
|
|
{
|
2011-06-12 04:00:23 +04:00
|
|
|
sigset_t pendingSignals = thread->AllPendingSignals();
|
|
|
|
return ((flags & B_CAN_INTERRUPT) != 0
|
|
|
|
&& (pendingSignals & ~thread->sig_block_mask) != 0)
|
|
|
|
|| ((flags & B_KILL_CAN_INTERRUPT) != 0
|
|
|
|
&& (pendingSignals & KILL_SIGNALS) != 0);
|
* 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-12 23:40:37 +04:00
|
|
|
/*! Checks whether the given thread is currently blocked (i.e. still waiting
|
|
|
|
for something).
|
2011-06-12 04:00:23 +04:00
|
|
|
|
|
|
|
If a stable answer is required, the caller must hold the scheduler lock.
|
|
|
|
Alternatively, if waiting is not interruptible and cannot time out, holding
|
|
|
|
the client lock held when calling thread_prepare_to_block() and the
|
|
|
|
unblocking functions works as well.
|
|
|
|
|
|
|
|
\param thread The thread in question.
|
|
|
|
\return \c true, if the thread is blocked, \c false otherwise.
|
|
|
|
*/
|
* 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 bool
|
2011-01-11 00:54:38 +03:00
|
|
|
thread_is_blocked(Thread* thread)
|
* 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
|
|
|
{
|
2013-11-29 22:31:10 +04:00
|
|
|
return atomic_get(&thread->wait.status) == 1;
|
* 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-12 04:00:23 +04:00
|
|
|
/*! Prepares the current thread for waiting.
|
|
|
|
|
|
|
|
This is the first of two steps necessary to block the current thread
|
|
|
|
(IOW, to let it wait for someone else to unblock it or optionally time out
|
|
|
|
after a specified delay). The process consists of two steps to avoid race
|
|
|
|
conditions in case a lock other than the scheduler lock is involved.
|
|
|
|
|
|
|
|
Usually the thread waits for some condition to change and this condition is
|
|
|
|
something reflected in the caller's data structures which should be
|
|
|
|
protected by a client lock the caller knows about. E.g. in the semaphore
|
|
|
|
code that lock is a per-semaphore spinlock that protects the semaphore data,
|
|
|
|
including the semaphore count and the queue of waiting threads. For certain
|
|
|
|
low-level locking primitives (e.g. mutexes) that client lock is the
|
|
|
|
scheduler lock itself, which simplifies things a bit.
|
|
|
|
|
|
|
|
If a client lock other than the scheduler lock is used, this function must
|
|
|
|
be called with that lock being held. Afterwards that lock should be dropped
|
|
|
|
and the function that actually blocks the thread shall be invoked
|
2013-11-05 02:45:14 +04:00
|
|
|
(thread_block[_locked]() or thread_block_with_timeout()). In between these
|
|
|
|
two steps no functionality that uses the thread blocking API for this thread
|
|
|
|
shall be used.
|
2011-06-12 04:00:23 +04:00
|
|
|
|
|
|
|
When the caller determines that the condition for unblocking the thread
|
|
|
|
occurred, it calls thread_unblock_locked() to unblock the thread. At that
|
|
|
|
time one of locks that are held when calling thread_prepare_to_block() must
|
|
|
|
be held. Usually that would be the client lock. In two cases it generally
|
|
|
|
isn't, however, since the unblocking code doesn't know about the client
|
2013-11-05 02:45:14 +04:00
|
|
|
lock: 1. When thread_block_with_timeout() had been used and the timeout
|
|
|
|
occurs. 2. When thread_prepare_to_block() had been called with one or both
|
|
|
|
of the \c B_CAN_INTERRUPT or \c B_KILL_CAN_INTERRUPT flags specified and
|
|
|
|
someone calls thread_interrupt() that is supposed to wake up the thread.
|
2011-06-12 04:00:23 +04:00
|
|
|
In either of these two cases only the scheduler lock is held by the
|
|
|
|
unblocking code. A timeout can only happen after
|
2013-11-05 02:45:14 +04:00
|
|
|
thread_block_with_timeout() has been called, but an interruption is
|
2011-06-12 04:00:23 +04:00
|
|
|
possible at any time. The client code must deal with those situations.
|
|
|
|
|
|
|
|
Generally blocking and unblocking threads proceed in the following manner:
|
|
|
|
|
|
|
|
Blocking thread:
|
|
|
|
- Acquire client lock.
|
|
|
|
- Check client condition and decide whether blocking is necessary.
|
|
|
|
- Modify some client data structure to indicate that this thread is now
|
|
|
|
waiting.
|
|
|
|
- Release client lock (unless client lock is the scheduler lock).
|
|
|
|
- Block.
|
|
|
|
- Acquire client lock (unless client lock is the scheduler lock).
|
|
|
|
- Check client condition and compare with block result. E.g. if the wait was
|
|
|
|
interrupted or timed out, but the client condition indicates success, it
|
|
|
|
may be considered a success after all, since usually that happens when
|
|
|
|
another thread concurrently changed the client condition and also tried
|
|
|
|
to unblock the waiting thread. It is even necessary when that other
|
|
|
|
thread changed the client data structures in a way that associate some
|
|
|
|
resource with the unblocked thread, or otherwise the unblocked thread
|
|
|
|
would have to reverse that here.
|
|
|
|
- If still necessary -- i.e. not already taken care of by an unblocking
|
|
|
|
thread -- modify some client structure to indicate that the thread is no
|
|
|
|
longer waiting, so it isn't erroneously unblocked later.
|
|
|
|
|
|
|
|
Unblocking thread:
|
|
|
|
- Acquire client lock.
|
|
|
|
- Check client condition and decide whether a blocked thread can be woken
|
|
|
|
up.
|
|
|
|
- Check the client data structure that indicates whether one or more threads
|
|
|
|
are waiting and which thread(s) need(s) to be woken up.
|
|
|
|
- Unblock respective thread(s).
|
|
|
|
- Possibly change some client structure, so that an unblocked thread can
|
|
|
|
decide whether a concurrent timeout/interruption can be ignored, or
|
|
|
|
simply so that it doesn't have to do any more cleanup.
|
|
|
|
|
|
|
|
Note that in the blocking thread the steps after blocking are strictly
|
|
|
|
required only if timeouts or interruptions are possible. If they are not,
|
|
|
|
the blocking thread can only be woken up explicitly by an unblocking thread,
|
|
|
|
which could already take care of all the necessary client data structure
|
|
|
|
modifications, so that the blocking thread wouldn't have to do that.
|
|
|
|
|
|
|
|
Note that the client lock can but does not have to be a spinlock.
|
|
|
|
A mutex, a semaphore, or anything that doesn't try to use the thread
|
|
|
|
blocking API for the calling thread when releasing the lock is fine.
|
|
|
|
In particular that means in principle thread_prepare_to_block() can be
|
|
|
|
called with interrupts enabled.
|
|
|
|
|
|
|
|
Care must be taken when the wait can be interrupted or can time out,
|
|
|
|
especially with a client lock that uses the thread blocking API. After a
|
|
|
|
blocked thread has been interrupted or the the time out occurred it cannot
|
|
|
|
acquire the client lock (or any other lock using the thread blocking API)
|
|
|
|
without first making sure that the thread doesn't still appears to be
|
|
|
|
waiting to other client code. Otherwise another thread could try to unblock
|
|
|
|
it which could erroneously unblock the thread while already waiting on the
|
|
|
|
client lock. So usually when interruptions or timeouts are possible a
|
|
|
|
spinlock needs to be involved.
|
|
|
|
|
|
|
|
\param thread The current thread.
|
|
|
|
\param flags The blocking flags. Relevant are:
|
|
|
|
- \c B_CAN_INTERRUPT: The thread can be interrupted by any non-blocked
|
|
|
|
signal. Implies \c B_KILL_CAN_INTERRUPT (specified or not).
|
|
|
|
- \c B_KILL_CAN_INTERRUPT: The thread can be interrupted by a kill
|
|
|
|
signal.
|
|
|
|
\param type The type of object the thread will be blocked at. Informative/
|
|
|
|
for debugging purposes. Must be one of the \c THREAD_BLOCK_TYPE_*
|
|
|
|
constants. \c THREAD_BLOCK_TYPE_OTHER implies that \a object is a
|
|
|
|
string.
|
|
|
|
\param object The object the thread will be blocked at. Informative/for
|
|
|
|
debugging purposes.
|
* 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 void
|
2011-01-11 00:54:38 +03:00
|
|
|
thread_prepare_to_block(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.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-12 04:00:23 +04:00
|
|
|
/*! Unblocks the specified blocked thread.
|
|
|
|
|
|
|
|
If the thread is no longer waiting (e.g. because thread_unblock_locked() has
|
|
|
|
already been called in the meantime), this function does not have any
|
|
|
|
effect.
|
|
|
|
|
|
|
|
The caller must hold the scheduler lock and the client lock (might be the
|
|
|
|
same).
|
|
|
|
|
|
|
|
\param thread The thread to be unblocked.
|
|
|
|
\param status The unblocking status. That's what the unblocked thread's
|
|
|
|
call to thread_block_locked() will return.
|
|
|
|
*/
|
2009-12-14 00:18:27 +03:00
|
|
|
static inline void
|
2011-01-11 00:54:38 +03:00
|
|
|
thread_unblock_locked(Thread* thread, status_t status)
|
* 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
|
|
|
{
|
|
|
|
if (atomic_test_and_set(&thread->wait.status, status, 1) != 1)
|
2009-12-14 00:18:27 +03:00
|
|
|
return;
|
* 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
|
|
|
|
|
|
|
// wake up the thread, if it is sleeping
|
|
|
|
if (thread->state == B_THREAD_WAITING)
|
2009-12-14 00:18:27 +03:00
|
|
|
scheduler_enqueue_in_run_queue(thread);
|
* 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
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-12 04:00:23 +04:00
|
|
|
/*! Interrupts the specified blocked thread, if possible.
|
|
|
|
|
|
|
|
The function checks whether the thread can be interrupted and, if so, calls
|
|
|
|
\code thread_unblock_locked(thread, B_INTERRUPTED) \endcode. Otherwise the
|
|
|
|
function is a no-op.
|
|
|
|
|
|
|
|
The caller must hold the scheduler lock. Normally thread_unblock_locked()
|
|
|
|
also requires the client lock to be held, but in this case the caller
|
|
|
|
usually doesn't know it. This implies that the client code needs to take
|
|
|
|
special care, if waits are interruptible. See thread_prepare_to_block() for
|
|
|
|
more information.
|
|
|
|
|
|
|
|
\param thread The thread to be interrupted.
|
|
|
|
\param kill If \c false, the blocked thread is only interrupted, when the
|
|
|
|
flag \c B_CAN_INTERRUPT was specified for the blocked thread. If
|
|
|
|
\c true, it is only interrupted, when at least one of the flags
|
|
|
|
\c B_CAN_INTERRUPT or \c B_KILL_CAN_INTERRUPT was specified for the
|
|
|
|
blocked thread.
|
|
|
|
\return \c B_OK, if the thread is interruptible and thread_unblock_locked()
|
|
|
|
was called, \c B_NOT_ALLOWED otherwise. \c B_OK doesn't imply that the
|
|
|
|
thread actually has been interrupted -- it could have been unblocked
|
|
|
|
before already.
|
|
|
|
*/
|
* 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
|
2011-01-11 00:54:38 +03:00
|
|
|
thread_interrupt(Thread* thread, bool kill)
|
* 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
|
|
|
{
|
2013-12-31 06:50:01 +04:00
|
|
|
if (thread_is_blocked(thread)) {
|
|
|
|
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;
|
|
|
|
}
|
* 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
|
|
|
}
|
|
|
|
|
|
|
|
return B_NOT_ALLOWED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-11 22:11:12 +04:00
|
|
|
static inline void
|
2011-01-11 00:54:38 +03:00
|
|
|
thread_pin_to_current_cpu(Thread* thread)
|
2008-10-11 22:11:12 +04:00
|
|
|
{
|
|
|
|
thread->pinned_to_cpu++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
2011-01-11 00:54:38 +03:00
|
|
|
thread_unpin_from_current_cpu(Thread* thread)
|
2008-10-11 22:11:12 +04:00
|
|
|
{
|
|
|
|
thread->pinned_to_cpu--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-17 05:11:22 +04:00
|
|
|
static inline void
|
|
|
|
thread_prepare_suspend()
|
|
|
|
{
|
|
|
|
Thread* thread = thread_get_current_thread();
|
|
|
|
thread->going_to_suspend = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
thread_suspend(bool alreadyPrepared = false)
|
|
|
|
{
|
|
|
|
Thread* thread = thread_get_current_thread();
|
|
|
|
if (!alreadyPrepared)
|
|
|
|
thread_prepare_suspend();
|
|
|
|
|
|
|
|
cpu_status state = disable_interrupts();
|
|
|
|
acquire_spinlock(&thread->scheduler_lock);
|
|
|
|
|
|
|
|
if (thread->going_to_suspend)
|
|
|
|
scheduler_reschedule(B_THREAD_SUSPENDED);
|
|
|
|
|
|
|
|
release_spinlock(&thread->scheduler_lock);
|
|
|
|
restore_interrupts(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
thread_continue(Thread* thread)
|
|
|
|
{
|
|
|
|
thread->going_to_suspend = false;
|
|
|
|
|
|
|
|
cpu_status state = disable_interrupts();
|
|
|
|
acquire_spinlock(&thread->scheduler_lock);
|
|
|
|
|
|
|
|
if (thread->state == B_THREAD_SUSPENDED)
|
|
|
|
scheduler_enqueue_in_run_queue(thread);
|
|
|
|
|
|
|
|
release_spinlock(&thread->scheduler_lock);
|
|
|
|
restore_interrupts(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
#endif /* _THREAD_H */
|