* Fixed a bug reported by Ryan: the stack_end pointer of a thread was reported
one too low in comparison with BeOS (ie. the end pointer was inclusive, now
it's exclusive).
* Moved static functions fill_thread_info(), and {send|receive}_data_etc() to
the private function section.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22945 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+146
-149
@@ -63,9 +63,6 @@ struct thread_key {
|
|||||||
thread_id id;
|
thread_id id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static status_t receive_data_etc(thread_id *_sender, void *buffer,
|
|
||||||
size_t bufferSize, int32 flags);
|
|
||||||
|
|
||||||
// global
|
// global
|
||||||
spinlock thread_spinlock = 0;
|
spinlock thread_spinlock = 0;
|
||||||
|
|
||||||
@@ -655,6 +652,152 @@ thread_exit2(void *_args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Fills the thread_info structure with information from the specified
|
||||||
|
thread.
|
||||||
|
The thread lock must be held when called.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
fill_thread_info(struct thread *thread, thread_info *info, size_t size)
|
||||||
|
{
|
||||||
|
info->thread = thread->id;
|
||||||
|
info->team = thread->team->id;
|
||||||
|
|
||||||
|
strlcpy(info->name, thread->name, B_OS_NAME_LENGTH);
|
||||||
|
|
||||||
|
if (thread->state == B_THREAD_WAITING) {
|
||||||
|
if (thread->sem.blocking == sSnoozeSem)
|
||||||
|
info->state = B_THREAD_ASLEEP;
|
||||||
|
else if (thread->sem.blocking == thread->msg.read_sem)
|
||||||
|
info->state = B_THREAD_RECEIVING;
|
||||||
|
else
|
||||||
|
info->state = B_THREAD_WAITING;
|
||||||
|
} else
|
||||||
|
info->state = (thread_state)thread->state;
|
||||||
|
|
||||||
|
info->priority = thread->priority;
|
||||||
|
info->sem = thread->sem.blocking;
|
||||||
|
info->user_time = thread->user_time;
|
||||||
|
info->kernel_time = thread->kernel_time;
|
||||||
|
info->stack_base = (void *)thread->user_stack_base;
|
||||||
|
info->stack_end = (void *)(thread->user_stack_base
|
||||||
|
+ thread->user_stack_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
send_data_etc(thread_id id, int32 code, const void *buffer,
|
||||||
|
size_t bufferSize, int32 flags)
|
||||||
|
{
|
||||||
|
struct thread *target;
|
||||||
|
sem_id cachedSem;
|
||||||
|
cpu_status state;
|
||||||
|
status_t status;
|
||||||
|
cbuf *data;
|
||||||
|
|
||||||
|
state = disable_interrupts();
|
||||||
|
GRAB_THREAD_LOCK();
|
||||||
|
target = thread_get_thread_struct_locked(id);
|
||||||
|
if (!target) {
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
restore_interrupts(state);
|
||||||
|
return B_BAD_THREAD_ID;
|
||||||
|
}
|
||||||
|
cachedSem = target->msg.write_sem;
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
if (bufferSize > THREAD_MAX_MESSAGE_SIZE)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status = acquire_sem_etc(cachedSem, 1, flags, 0);
|
||||||
|
if (status == B_INTERRUPTED) {
|
||||||
|
// We got interrupted by a signal
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if (status != B_OK) {
|
||||||
|
// Any other acquisition problems may be due to thread deletion
|
||||||
|
return B_BAD_THREAD_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferSize > 0) {
|
||||||
|
data = cbuf_get_chain(bufferSize);
|
||||||
|
if (data == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
status = cbuf_user_memcpy_to_chain(data, 0, buffer, bufferSize);
|
||||||
|
if (status < B_OK) {
|
||||||
|
cbuf_free_chain(data);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
data = NULL;
|
||||||
|
|
||||||
|
state = disable_interrupts();
|
||||||
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
|
// The target thread could have been deleted at this point
|
||||||
|
target = thread_get_thread_struct_locked(id);
|
||||||
|
if (target == NULL) {
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
restore_interrupts(state);
|
||||||
|
cbuf_free_chain(data);
|
||||||
|
return B_BAD_THREAD_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save message informations
|
||||||
|
target->msg.sender = thread_get_current_thread()->id;
|
||||||
|
target->msg.code = code;
|
||||||
|
target->msg.size = bufferSize;
|
||||||
|
target->msg.buffer = data;
|
||||||
|
cachedSem = target->msg.read_sem;
|
||||||
|
|
||||||
|
RELEASE_THREAD_LOCK();
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
release_sem(cachedSem);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32
|
||||||
|
receive_data_etc(thread_id *_sender, void *buffer, size_t bufferSize,
|
||||||
|
int32 flags)
|
||||||
|
{
|
||||||
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
status_t status;
|
||||||
|
size_t size;
|
||||||
|
int32 code;
|
||||||
|
|
||||||
|
status = acquire_sem_etc(thread->msg.read_sem, 1, flags, 0);
|
||||||
|
if (status < B_OK) {
|
||||||
|
// Actually, we're not supposed to return error codes
|
||||||
|
// but since the only reason this can fail is that we
|
||||||
|
// were killed, it's probably okay to do so (but also
|
||||||
|
// meaningless).
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer != NULL && bufferSize != 0) {
|
||||||
|
size = min_c(bufferSize, thread->msg.size);
|
||||||
|
status = cbuf_user_memcpy_from_chain(buffer, thread->msg.buffer,
|
||||||
|
0, size);
|
||||||
|
if (status < B_OK) {
|
||||||
|
cbuf_free_chain(thread->msg.buffer);
|
||||||
|
release_sem(thread->msg.write_sem);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*_sender = thread->msg.sender;
|
||||||
|
code = thread->msg.code;
|
||||||
|
|
||||||
|
cbuf_free_chain(thread->msg.buffer);
|
||||||
|
release_sem(thread->msg.write_sem);
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - debugger calls
|
// #pragma mark - debugger calls
|
||||||
|
|
||||||
|
|
||||||
@@ -1789,80 +1932,6 @@ kill_thread(thread_id id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
send_data_etc(thread_id id, int32 code, const void *buffer,
|
|
||||||
size_t bufferSize, int32 flags)
|
|
||||||
{
|
|
||||||
struct thread *target;
|
|
||||||
sem_id cachedSem;
|
|
||||||
cpu_status state;
|
|
||||||
status_t status;
|
|
||||||
cbuf *data;
|
|
||||||
|
|
||||||
state = disable_interrupts();
|
|
||||||
GRAB_THREAD_LOCK();
|
|
||||||
target = thread_get_thread_struct_locked(id);
|
|
||||||
if (!target) {
|
|
||||||
RELEASE_THREAD_LOCK();
|
|
||||||
restore_interrupts(state);
|
|
||||||
return B_BAD_THREAD_ID;
|
|
||||||
}
|
|
||||||
cachedSem = target->msg.write_sem;
|
|
||||||
RELEASE_THREAD_LOCK();
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
if (bufferSize > THREAD_MAX_MESSAGE_SIZE)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
status = acquire_sem_etc(cachedSem, 1, flags, 0);
|
|
||||||
if (status == B_INTERRUPTED) {
|
|
||||||
// We got interrupted by a signal
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
if (status != B_OK) {
|
|
||||||
// Any other acquisition problems may be due to thread deletion
|
|
||||||
return B_BAD_THREAD_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bufferSize > 0) {
|
|
||||||
data = cbuf_get_chain(bufferSize);
|
|
||||||
if (data == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
status = cbuf_user_memcpy_to_chain(data, 0, buffer, bufferSize);
|
|
||||||
if (status < B_OK) {
|
|
||||||
cbuf_free_chain(data);
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
data = NULL;
|
|
||||||
|
|
||||||
state = disable_interrupts();
|
|
||||||
GRAB_THREAD_LOCK();
|
|
||||||
|
|
||||||
// The target thread could have been deleted at this point
|
|
||||||
target = thread_get_thread_struct_locked(id);
|
|
||||||
if (target == NULL) {
|
|
||||||
RELEASE_THREAD_LOCK();
|
|
||||||
restore_interrupts(state);
|
|
||||||
cbuf_free_chain(data);
|
|
||||||
return B_BAD_THREAD_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save message informations
|
|
||||||
target->msg.sender = thread_get_current_thread()->id;
|
|
||||||
target->msg.code = code;
|
|
||||||
target->msg.size = bufferSize;
|
|
||||||
target->msg.buffer = data;
|
|
||||||
cachedSem = target->msg.read_sem;
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
release_sem(cachedSem);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
|
send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
@@ -1870,45 +1939,6 @@ send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32
|
|
||||||
receive_data_etc(thread_id *_sender, void *buffer, size_t bufferSize,
|
|
||||||
int32 flags)
|
|
||||||
{
|
|
||||||
struct thread *thread = thread_get_current_thread();
|
|
||||||
status_t status;
|
|
||||||
size_t size;
|
|
||||||
int32 code;
|
|
||||||
|
|
||||||
status = acquire_sem_etc(thread->msg.read_sem, 1, flags, 0);
|
|
||||||
if (status < B_OK) {
|
|
||||||
// Actually, we're not supposed to return error codes
|
|
||||||
// but since the only reason this can fail is that we
|
|
||||||
// were killed, it's probably okay to do so (but also
|
|
||||||
// meaningless).
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer != NULL && bufferSize != 0) {
|
|
||||||
size = min_c(bufferSize, thread->msg.size);
|
|
||||||
status = cbuf_user_memcpy_from_chain(buffer, thread->msg.buffer,
|
|
||||||
0, size);
|
|
||||||
if (status < B_OK) {
|
|
||||||
cbuf_free_chain(thread->msg.buffer);
|
|
||||||
release_sem(thread->msg.write_sem);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*_sender = thread->msg.sender;
|
|
||||||
code = thread->msg.code;
|
|
||||||
|
|
||||||
cbuf_free_chain(thread->msg.buffer);
|
|
||||||
release_sem(thread->msg.write_sem);
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
receive_data(thread_id *sender, void *buffer, size_t bufferSize)
|
receive_data(thread_id *sender, void *buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
@@ -1929,39 +1959,6 @@ has_data(thread_id thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Fills the thread_info structure with information from the specified
|
|
||||||
thread.
|
|
||||||
The thread lock must be held when called.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
fill_thread_info(struct thread *thread, thread_info *info, size_t size)
|
|
||||||
{
|
|
||||||
info->thread = thread->id;
|
|
||||||
info->team = thread->team->id;
|
|
||||||
|
|
||||||
strlcpy(info->name, thread->name, B_OS_NAME_LENGTH);
|
|
||||||
|
|
||||||
if (thread->state == B_THREAD_WAITING) {
|
|
||||||
if (thread->sem.blocking == sSnoozeSem)
|
|
||||||
info->state = B_THREAD_ASLEEP;
|
|
||||||
else if (thread->sem.blocking == thread->msg.read_sem)
|
|
||||||
info->state = B_THREAD_RECEIVING;
|
|
||||||
else
|
|
||||||
info->state = B_THREAD_WAITING;
|
|
||||||
} else
|
|
||||||
info->state = (thread_state)thread->state;
|
|
||||||
|
|
||||||
info->priority = thread->priority;
|
|
||||||
info->sem = thread->sem.blocking;
|
|
||||||
info->user_time = thread->user_time;
|
|
||||||
info->kernel_time = thread->kernel_time;
|
|
||||||
info->stack_base = (void *)thread->user_stack_base;
|
|
||||||
info->stack_end = (void *)(thread->user_stack_base
|
|
||||||
+ thread->user_stack_size - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
_get_thread_info(thread_id id, thread_info *info, size_t size)
|
_get_thread_info(thread_id id, thread_info *info, size_t size)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user