From d4fc2b7db779647aed0ff248d21527146e8e2bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 18 Nov 2007 11:59:53 +0000 Subject: [PATCH] * 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 --- src/system/kernel/thread.cpp | 295 +++++++++++++++++------------------ 1 file changed, 146 insertions(+), 149 deletions(-) diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index 8c55c14a72..79b043e782 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -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) {