* 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:
Axel Dörfler
2007-11-18 11:59:53 +00:00
parent 79939c8d1e
commit d4fc2b7db7
+146 -149
View File
@@ -63,9 +63,6 @@ struct thread_key {
thread_id id;
};
static status_t receive_data_etc(thread_id *_sender, void *buffer,
size_t bufferSize, int32 flags);
// global
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
@@ -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
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
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
_get_thread_info(thread_id id, thread_info *info, size_t size)
{