diff --git a/src/system/kernel/sem.c b/src/system/kernel/sem.c index 5edc2b0400..2dbc0b71a1 100644 --- a/src/system/kernel/sem.c +++ b/src/system/kernel/sem.c @@ -6,7 +6,7 @@ * Distributed under the terms of the NewOS License. */ -/* Semaphore code */ +/*! Semaphore code */ #include @@ -84,8 +84,7 @@ static spinlock sem_spinlock = 0; #define RELEASE_SEM_LOCK(s) release_spinlock(&(s).lock) static int remove_thread_from_sem(struct thread *thread, struct sem_entry *sem, - struct thread_queue *queue, status_t acquireStatus, - bool hasThreadLock); + struct thread_queue *queue, status_t acquireStatus, bool hasThreadLock); struct sem_timeout_args { thread_id blocked_thread; @@ -132,9 +131,9 @@ dump_sem_list(int argc, char **argv) || (owner != -1 && sem->u.used.owner != owner)) continue; - kprintf("%p %6lx %5ld %6lx " + kprintf("%p %6ld %5ld %6ld " #ifdef DEBUG_LAST_ACQUIRER - "%6lx " + "%6ld " #endif " %s\n", sem, sem->id, sem->u.used.count, sem->u.used.owner, @@ -152,16 +151,16 @@ static void dump_sem(struct sem_entry *sem) { kprintf("SEM: %p\n", sem); - kprintf("id: %#lx\n", sem->id); + kprintf("id: %ld (%#lx)\n", sem->id, sem->id); if (sem->id >= 0) { kprintf("name: '%s'\n", sem->u.used.name); - kprintf("owner: 0x%lx\n", sem->u.used.owner); - kprintf("count: 0x%lx\n", sem->u.used.count); + kprintf("owner: %ld\n", sem->u.used.owner); + kprintf("count: %ld\n", sem->u.used.count); kprintf("queue: "); if (sem->u.used.queue.head != NULL) { struct thread *thread = sem->u.used.queue.head; while (thread != NULL) { - kprintf(" %lx", thread->id); + kprintf(" %ld", thread->id); thread = thread->queue_next; } kprintf("\n"); @@ -175,7 +174,7 @@ dump_sem(struct sem_entry *sem) #endif } else { kprintf("next: %p\n", sem->u.unused.next); - kprintf("next_id: %#lx\n", sem->u.unused.next_id); + kprintf("next_id: %ld\n", sem->u.unused.next_id); } } @@ -230,16 +229,15 @@ clear_thread_queue(struct thread_queue *queue) } -/** \brief Appends a semaphore slot to the free list. - * - * The semaphore list must be locked. - * The slot's id field is not changed. It should already be set to -1. - * - * \param slot The index of the semaphore slot. - * \param nextID The ID the slot will get when reused. If < 0 the \a slot - * is used. - */ +/*! \brief Appends a semaphore slot to the free list. + The semaphore list must be locked. + The slot's id field is not changed. It should already be set to -1. + + \param slot The index of the semaphore slot. + \param nextID The ID the slot will get when reused. If < 0 the \a slot + is used. +*/ static void free_sem_slot(int slot, sem_id nextID) { @@ -259,7 +257,7 @@ free_sem_slot(int slot, sem_id nextID) } -static void +static inline void notify_sem_select_events(struct sem_entry* sem, uint16 events) { if (sem->u.used.select_infos) @@ -267,6 +265,80 @@ notify_sem_select_events(struct sem_entry* sem, uint16 events) } +/*! Called from a timer handler. Wakes up a semaphore */ +static int32 +sem_timeout(timer *data) +{ + struct sem_timeout_args *args = (struct sem_timeout_args *)data->entry.prev; + struct thread *thread; + int slot; + int state; + struct thread_queue wakeupQueue; + + thread = thread_get_thread_struct(args->blocked_thread); + if (thread == NULL) + return B_HANDLED_INTERRUPT; + slot = args->blocked_sem_id % sMaxSems; + + state = disable_interrupts(); + GRAB_SEM_LOCK(sSems[slot]); + + TRACE(("sem_timeout: called on %p sem %ld, thread %ld\n", + data, args->blocked_sem_id, args->blocked_thread)); + + if (sSems[slot].id != args->blocked_sem_id) { + // this thread was not waiting on this semaphore + panic("sem_timeout: thread %ld was trying to wait on sem %ld which " + "doesn't exist!\n", args->blocked_thread, args->blocked_sem_id); + + RELEASE_SEM_LOCK(sSems[slot]); + restore_interrupts(state); + return B_HANDLED_INTERRUPT; + } + + clear_thread_queue(&wakeupQueue); + remove_thread_from_sem(thread, &sSems[slot], &wakeupQueue, B_TIMED_OUT, + false); + + RELEASE_SEM_LOCK(sSems[slot]); + + GRAB_THREAD_LOCK(); + // put the threads in the run q here to make sure we dont deadlock in sem_interrupt_thread + while ((thread = thread_dequeue(&wakeupQueue)) != NULL) { + scheduler_enqueue_in_run_queue(thread); + } + RELEASE_THREAD_LOCK(); + + restore_interrupts(state); + + return B_INVOKE_SCHEDULER; +} + + +/*! Fills the thread_info structure with information from the specified + thread. + The thread lock must be held when called. +*/ +static void +fill_sem_info(struct sem_entry *sem, sem_info *info, size_t size) +{ + info->sem = sem->id; + info->team = sem->u.used.owner; + strlcpy(info->name, sem->u.used.name, sizeof(info->name)); + info->count = sem->u.used.count; + + // ToDo: not sure if this is the latest holder, or the next + // holder... + if (sem->u.used.queue.head != NULL) + info->latest_holder = sem->u.used.queue.head->id; + else + info->latest_holder = -1; +} + + +// #pragma mark - Private Kernel API + + status_t sem_init(kernel_args *args) { @@ -308,14 +380,13 @@ sem_init(kernel_args *args) } -/** Creates a semaphore with the given parameters. - * Note, the team_id is not checked, it must be correct, or else - * that semaphore might not be deleted. - * This function is only available from within the kernel, and - * should not be made public - if possible, we should remove it - * completely (and have only create_sem() exported). - */ - +/*! Creates a semaphore with the given parameters. + Note, the team_id is not checked, it must be correct, or else + that semaphore might not be deleted. + This function is only available from within the kernel, and + should not be made public - if possible, we should remove it + completely (and have only create_sem() exported). +*/ sem_id create_sem_etc(int32 count, const char *name, team_id owner) { @@ -387,6 +458,230 @@ create_sem_etc(int32 count, const char *name, team_id owner) } +status_t +select_sem(int32 id, struct select_info* info, bool kernel) +{ + cpu_status state; + int32 slot; + status_t error = B_OK; + + if (id < 0) + return B_BAD_SEM_ID; + + slot = id % sMaxSems; + + state = disable_interrupts(); + GRAB_SEM_LOCK(sSems[slot]); + + if (sSems[slot].id != id) { + // bad sem ID + error = B_BAD_SEM_ID; + } else if (!kernel + && sSems[slot].u.used.owner == team_get_kernel_team_id()) { + // kernel semaphore, but call from userland + error = B_NOT_ALLOWED; + } else { + info->selected_events &= B_EVENT_ACQUIRE_SEMAPHORE | B_EVENT_INVALID; + + if (info->selected_events != 0) { + info->next = sSems[slot].u.used.select_infos; + sSems[slot].u.used.select_infos = info; + + if (sSems[slot].u.used.count > 0) + notify_select_events(info, B_EVENT_ACQUIRE_SEMAPHORE); + } + } + + RELEASE_SEM_LOCK(sSems[slot]); + restore_interrupts(state); + + return error; +} + + +status_t +deselect_sem(int32 id, struct select_info* info, bool kernel) +{ + cpu_status state; + int32 slot; + + if (id < 0) + return B_BAD_SEM_ID; + + if (info->selected_events == 0) + return B_OK; + + slot = id % sMaxSems; + + state = disable_interrupts(); + GRAB_SEM_LOCK(sSems[slot]); + + if (sSems[slot].id == id) { + select_info** infoLocation = &sSems[slot].u.used.select_infos; + while (*infoLocation != NULL && *infoLocation != info) + infoLocation = &(*infoLocation)->next; + + if (*infoLocation == info) + *infoLocation = info->next; + } + + RELEASE_SEM_LOCK(sSems[slot]); + restore_interrupts(state); + + return B_OK; +} + + +/*! Wake up a thread that's blocked on a semaphore + this function must be entered with interrupts disabled and THREADLOCK held +*/ +status_t +sem_interrupt_thread(struct thread *thread) +{ + struct thread_queue wakeupQueue; + int32 slot; + + TRACE(("sem_interrupt_thread: called on thread %p (%ld), blocked on sem %ld\n", + thread, thread->id, thread->sem.blocking)); + + if (thread->state != B_THREAD_WAITING || thread->sem.blocking < 0) + return B_BAD_VALUE; + if ((thread->sem.flags & B_CAN_INTERRUPT) == 0 + && ((thread->sem.flags & B_KILL_CAN_INTERRUPT) == 0 + || (thread->sig_pending & KILL_SIGNALS) == 0)) { + return B_NOT_ALLOWED; + } + + slot = thread->sem.blocking % sMaxSems; + + GRAB_SEM_LOCK(sSems[slot]); + + if (sSems[slot].id != thread->sem.blocking) { + panic("sem_interrupt_thread: thread %ld blocks on sem %ld, but that " + "sem doesn't exist!\n", thread->id, thread->sem.blocking); + } + + clear_thread_queue(&wakeupQueue); + if (remove_thread_from_sem(thread, &sSems[slot], &wakeupQueue, + B_INTERRUPTED, true) != B_OK) { + panic("sem_interrupt_thread: thread %ld not found in sem %ld's wait " + "queue\n", thread->id, thread->sem.blocking); + } + + RELEASE_SEM_LOCK(sSems[slot]); + + while ((thread = thread_dequeue(&wakeupQueue)) != NULL) { + scheduler_enqueue_in_run_queue(thread); + } + + return B_NO_ERROR; +} + + +/*! Forcibly removes a thread from a semaphores wait queue. May have to wake up + other threads in the process. All threads that need to be woken up are added + to the passed in thread_queue. + Must be called with semaphore lock held. +*/ +static int +remove_thread_from_sem(struct thread *thread, struct sem_entry *sem, + struct thread_queue *queue, status_t acquireStatus, bool hasThreadLock) +{ + // remove the thread from the queue and place it in the supplied queue + if (thread_dequeue_id(&sem->u.used.queue, thread->id) != thread) + return B_ENTRY_NOT_FOUND; + + sem->u.used.count += thread->sem.acquire_count; + thread->state = thread->next_state = B_THREAD_READY; + thread->sem.acquire_status = acquireStatus; + thread_enqueue(thread, queue); + + // now see if more threads need to be woken up + while (sem->u.used.count > 0 + && thread_lookat_queue(&sem->u.used.queue) != NULL) { + int32 delta = min(thread->sem.count, sem->u.used.count); + + thread->sem.count -= delta; + if (thread->sem.count <= 0) { + thread = thread_dequeue(&sem->u.used.queue); + thread->state = thread->next_state = B_THREAD_READY; + thread_enqueue(thread, queue); + } + sem->u.used.count -= delta; + } + + if (sem->u.used.count > 0 && sem->u.used.select_infos != NULL) { + if (hasThreadLock) + RELEASE_THREAD_LOCK(); + + notify_sem_select_events(sem, B_EVENT_ACQUIRE_SEMAPHORE); + + if (hasThreadLock) + GRAB_THREAD_LOCK(); + } + + return B_OK; +} + + +/*! This function cycles through the sem table, deleting all the sems + that are owned by the specified team. +*/ +int +sem_delete_owned_sems(team_id owner) +{ + int state; + int i; + int count = 0; + + // ToDo: that looks horribly inefficient - maybe it would be better + // to have them in a list in the team + + if (owner < 0) + return B_BAD_TEAM_ID; + + state = disable_interrupts(); + GRAB_SEM_LIST_LOCK(); + + for (i = 0; i < sMaxSems; i++) { + if (sSems[i].id != -1 && sSems[i].u.used.owner == owner) { + sem_id id = sSems[i].id; + + RELEASE_SEM_LIST_LOCK(); + restore_interrupts(state); + + delete_sem(id); + count++; + + state = disable_interrupts(); + GRAB_SEM_LIST_LOCK(); + } + } + + RELEASE_SEM_LIST_LOCK(); + restore_interrupts(state); + + return count; +} + + +int32 +sem_max_sems(void) +{ + return sMaxSems; +} + + +int32 +sem_used_sems(void) +{ + return sUsedSems; +} + + +// #pragma mark - Public Kernel API + + sem_id create_sem(int32 count, const char *name) { @@ -465,130 +760,6 @@ delete_sem(sem_id id) } -status_t -select_sem(int32 id, struct select_info* info, bool kernel) -{ - cpu_status state; - int32 slot; - status_t error = B_OK; - - if (id < 0) - return B_BAD_SEM_ID; - - slot = id % sMaxSems; - - state = disable_interrupts(); - GRAB_SEM_LOCK(sSems[slot]); - - if (sSems[slot].id != id) { - // bad sem ID - error = B_BAD_SEM_ID; - } else if (!kernel - && sSems[slot].u.used.owner == team_get_kernel_team_id()) { - // kernel semaphore, but call from userland - error = B_NOT_ALLOWED; - } else { - info->selected_events &= B_EVENT_ACQUIRE_SEMAPHORE | B_EVENT_INVALID; - - if (info->selected_events != 0) { - info->next = sSems[slot].u.used.select_infos; - sSems[slot].u.used.select_infos = info; - - if (sSems[slot].u.used.count > 0) - notify_select_events(info, B_EVENT_ACQUIRE_SEMAPHORE); - } - } - - RELEASE_SEM_LOCK(sSems[slot]); - restore_interrupts(state); - - return error; -} - - -status_t -deselect_sem(int32 id, struct select_info* info, bool kernel) -{ - cpu_status state; - int32 slot; - - if (id < 0) - return B_BAD_SEM_ID; - - if (info->selected_events == 0) - return B_OK; - - slot = id % sMaxSems; - - state = disable_interrupts(); - GRAB_SEM_LOCK(sSems[slot]); - - if (sSems[slot].id == id) { - select_info** infoLocation = &sSems[slot].u.used.select_infos; - while (*infoLocation != NULL && *infoLocation != info) - infoLocation = &(*infoLocation)->next; - - if (*infoLocation == info) - *infoLocation = info->next; - } - - RELEASE_SEM_LOCK(sSems[slot]); - restore_interrupts(state); - - return B_OK; -} - - -/** Called from a timer handler. Wakes up a semaphore */ - -static int32 -sem_timeout(timer *data) -{ - struct sem_timeout_args *args = (struct sem_timeout_args *)data->entry.prev; - struct thread *thread; - int slot; - int state; - struct thread_queue wakeupQueue; - - thread = thread_get_thread_struct(args->blocked_thread); - if (thread == NULL) - return B_HANDLED_INTERRUPT; - slot = args->blocked_sem_id % sMaxSems; - - state = disable_interrupts(); - GRAB_SEM_LOCK(sSems[slot]); - - TRACE(("sem_timeout: called on 0x%x sem %ld, tid %ld\n", data, args->blocked_sem_id, args->blocked_thread)); - - if (sSems[slot].id != args->blocked_sem_id) { - // this thread was not waiting on this semaphore - panic("sem_timeout: thid %ld was trying to wait on sem %ld which doesn't exist!\n", - args->blocked_thread, args->blocked_sem_id); - - RELEASE_SEM_LOCK(sSems[slot]); - restore_interrupts(state); - return B_HANDLED_INTERRUPT; - } - - clear_thread_queue(&wakeupQueue); - remove_thread_from_sem(thread, &sSems[slot], &wakeupQueue, B_TIMED_OUT, - false); - - RELEASE_SEM_LOCK(sSems[slot]); - - GRAB_THREAD_LOCK(); - // put the threads in the run q here to make sure we dont deadlock in sem_interrupt_thread - while ((thread = thread_dequeue(&wakeupQueue)) != NULL) { - scheduler_enqueue_in_run_queue(thread); - } - RELEASE_THREAD_LOCK(); - - restore_interrupts(state); - - return B_INVOKE_SCHEDULER; -} - - status_t acquire_sem(sem_id id) { @@ -623,8 +794,10 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, if (sSemsActive == false) return B_NO_MORE_SEMS; - if (!are_interrupts_enabled()) - panic("acquire_sem_etc: called with interrupts disabled for sem %#lx\n", id); + if (!are_interrupts_enabled()) { + panic("switch_sem_etc: called with interrupts disabled for sem %ld\n", + id); + } if (id < 0) return B_BAD_SEM_ID; @@ -637,7 +810,7 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, GRAB_SEM_LOCK(sSems[slot]); if (sSems[slot].id != id) { - TRACE(("acquire_sem_etc: bad sem_id %ld\n", id)); + TRACE(("switch_sem_etc: bad sem %ld\n", id)); status = B_BAD_SEM_ID; goto err; } @@ -665,7 +838,7 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, timer timeout_timer; // stick it on the stack, since we may be blocking here struct sem_timeout_args args; - TRACE(("acquire_sem_etc(id = %ld): block name = %s, thread = %p," + TRACE(("switch_sem_etc(id = %ld): block name = %s, thread = %p," " name = %s\n", id, sSems[slot].u.used.name, thread, thread->name)); // do a quick check to see if the thread has any pending signals @@ -691,7 +864,7 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, thread_enqueue(thread, &sSems[slot].u.used.queue); if (timeout != B_INFINITE_TIMEOUT) { - TRACE(("sem_acquire_etc: setting timeout sem for %Ld usecs, semid %d, tid %d\n", + TRACE(("switch_sem_etc: setting timeout sem for %Ld usecs, sem %ld, thread %ld\n", timeout, id, thread->id)); // set up an event to go off with the thread struct as the data @@ -755,8 +928,8 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, restore_interrupts(state); - TRACE(("acquire_sem_etc(id = %ld): exit block name = %s, " - "thread = %p (%s)\n", id, sSems[slot].u.used.name, thread, + TRACE(("switch_sem_etc(sem %ld): exit block name %s, " + "thread %ld (%s)\n", id, sSems[slot].u.used.name, thread->id, thread->name)); return thread->sem.acquire_status; } else { @@ -898,7 +1071,7 @@ outnolock: status_t -get_sem_count(sem_id id, int32 *thread_count) +get_sem_count(sem_id id, int32 *_count) { int slot; int state; @@ -907,8 +1080,8 @@ get_sem_count(sem_id id, int32 *thread_count) return B_NO_MORE_SEMS; if (id < 0) return B_BAD_SEM_ID; - if (thread_count == NULL) - return EINVAL; + if (_count == NULL) + return B_BAD_VALUE; slot = id % sMaxSems; @@ -922,43 +1095,16 @@ get_sem_count(sem_id id, int32 *thread_count) return B_BAD_SEM_ID; } - *thread_count = sSems[slot].u.used.count; + *_count = sSems[slot].u.used.count; RELEASE_SEM_LOCK(sSems[slot]); restore_interrupts(state); - return B_NO_ERROR; + return B_OK; } -/** Fills the thread_info structure with information from the specified - * thread. - * The thread lock must be held when called. - */ - -static void -fill_sem_info(struct sem_entry *sem, sem_info *info, size_t size) -{ - info->sem = sem->id; - info->team = sem->u.used.owner; - strlcpy(info->name, sem->u.used.name, sizeof(info->name)); - info->count = sem->u.used.count; - - // ToDo: not sure if this is the latest holder, or the next - // holder... - if (sem->u.used.queue.head != NULL) - info->latest_holder = sem->u.used.queue.head->id; - else - info->latest_holder = -1; -} - - -/** The underscore is needed for binary compatibility with BeOS. - * OS.h contains the following macro: - * #define get_sem_info(sem, info) \ - * _get_sem_info((sem), (info), sizeof(*(info))) - */ - +/*! Called by the get_sem_info() macro. */ status_t _get_sem_info(sem_id id, struct sem_info *info, size_t size) { @@ -991,14 +1137,10 @@ _get_sem_info(sem_id id, struct sem_info *info, size_t size) } -/** The underscore is needed for binary compatibility with BeOS. - * OS.h contains the following macro: - * #define get_next_sem_info(team, cookie, info) \ - * _get_next_sem_info((team), (cookie), (info), sizeof(*(info))) - */ - +/*! Called by the get_next_sem_info() macro. */ status_t -_get_next_sem_info(team_id team, int32 *_cookie, struct sem_info *info, size_t size) +_get_next_sem_info(team_id team, int32 *_cookie, struct sem_info *info, + size_t size) { int state; int slot; @@ -1088,156 +1230,7 @@ set_sem_owner(sem_id id, team_id team) } -/** Wake up a thread that's blocked on a semaphore - * this function must be entered with interrupts disabled and THREADLOCK held - */ - -status_t -sem_interrupt_thread(struct thread *thread) -{ - struct thread_queue wakeupQueue; - int32 slot; - - TRACE(("sem_interrupt_thread: called on thread %p (%d), blocked on sem 0x%x\n", - thread, thread->id, thread->sem.blocking)); - - if (thread->state != B_THREAD_WAITING || thread->sem.blocking < 0) - return B_BAD_VALUE; - if ((thread->sem.flags & B_CAN_INTERRUPT) == 0 - && ((thread->sem.flags & B_KILL_CAN_INTERRUPT) == 0 - || (thread->sig_pending & KILL_SIGNALS) == 0)) { - return B_NOT_ALLOWED; - } - - slot = thread->sem.blocking % sMaxSems; - - GRAB_SEM_LOCK(sSems[slot]); - - if (sSems[slot].id != thread->sem.blocking) { - panic("sem_interrupt_thread: thread 0x%lx sez it's blocking on sem 0x%lx, but that sem doesn't exist!\n", thread->id, thread->sem.blocking); - } - - clear_thread_queue(&wakeupQueue); - if (remove_thread_from_sem(thread, &sSems[slot], &wakeupQueue, - B_INTERRUPTED, true) != B_OK) { - panic("sem_interrupt_thread: thread 0x%lx not found in sem 0x%lx's wait queue\n", - thread->id, thread->sem.blocking); - } - - RELEASE_SEM_LOCK(sSems[slot]); - - while ((thread = thread_dequeue(&wakeupQueue)) != NULL) { - scheduler_enqueue_in_run_queue(thread); - } - - return B_NO_ERROR; -} - - -/** Forcibly removes a thread from a semaphores wait queue. May have to wake up - * other threads in the process. All threads that need to be woken up are added - * to the passed in thread_queue. - * Must be called with semaphore lock held. - */ - -static int -remove_thread_from_sem(struct thread *thread, struct sem_entry *sem, - struct thread_queue *queue, status_t acquireStatus, bool hasThreadLock) -{ - // remove the thread from the queue and place it in the supplied queue - if (thread_dequeue_id(&sem->u.used.queue, thread->id) != thread) - return B_ENTRY_NOT_FOUND; - - sem->u.used.count += thread->sem.acquire_count; - thread->state = thread->next_state = B_THREAD_READY; - thread->sem.acquire_status = acquireStatus; - thread_enqueue(thread, queue); - - // now see if more threads need to be woken up - while (sem->u.used.count > 0 - && thread_lookat_queue(&sem->u.used.queue) != NULL) { - int32 delta = min(thread->sem.count, sem->u.used.count); - - thread->sem.count -= delta; - if (thread->sem.count <= 0) { - thread = thread_dequeue(&sem->u.used.queue); - thread->state = thread->next_state = B_THREAD_READY; - thread_enqueue(thread, queue); - } - sem->u.used.count -= delta; - } - - if (sem->u.used.count > 0 && sem->u.used.select_infos != NULL) { - if (hasThreadLock) - RELEASE_THREAD_LOCK(); - - notify_sem_select_events(sem, B_EVENT_ACQUIRE_SEMAPHORE); - - if (hasThreadLock) - GRAB_THREAD_LOCK(); - } - - return B_OK; -} - - -/** this function cycles through the sem table, deleting all the sems that are owned by - * the passed team_id - */ - -int -sem_delete_owned_sems(team_id owner) -{ - int state; - int i; - int count = 0; - - // ToDo: that looks horribly inefficient - maybe it would be better - // to have them in a list in the team - - if (owner < 0) - return B_BAD_TEAM_ID; - - state = disable_interrupts(); - GRAB_SEM_LIST_LOCK(); - - for (i = 0; i < sMaxSems; i++) { - if (sSems[i].id != -1 && sSems[i].u.used.owner == owner) { - sem_id id = sSems[i].id; - - RELEASE_SEM_LIST_LOCK(); - restore_interrupts(state); - - delete_sem(id); - count++; - - state = disable_interrupts(); - GRAB_SEM_LIST_LOCK(); - } - } - - RELEASE_SEM_LIST_LOCK(); - restore_interrupts(state); - - return count; -} - - -int32 -sem_max_sems(void) -{ - return sMaxSems; -} - - -int32 -sem_used_sems(void) -{ - return sUsedSems; -} - - -// #pragma mark - +// #pragma mark - Syscalls sem_id diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index f89ee772b4..28efbac264 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -255,7 +255,7 @@ create_thread_struct(struct thread *inthread, const char *name, list_init(&thread->exit.waiters); thread->select_infos = NULL; - sprintf(temp, "thread_0x%lx_retcode_sem", thread->id); + sprintf(temp, "thread_%lx_retcode_sem", thread->id); thread->exit.sem = create_sem(0, temp); if (thread->exit.sem < B_OK) goto err1; @@ -558,7 +558,7 @@ get_death_stack(void) bit >>= 1; } - TRACE(("get_death_stack: returning 0x%lx\n", sDeathStacks[i].address)); + TRACE(("get_death_stack: returning %#lx\n", sDeathStacks[i].address)); return (uint32)i; } @@ -599,16 +599,16 @@ thread_exit2(void *_args) // we can't let the interrupts disabled at this point enable_interrupts(); - TRACE(("thread_exit2, running on death stack 0x%lx\n", args.death_stack)); + TRACE(("thread_exit2, running on death stack %#lx\n", args.death_stack)); // delete the old kernel stack area - TRACE(("thread_exit2: deleting old kernel stack id 0x%lx for thread 0x%lx\n", + TRACE(("thread_exit2: deleting old kernel stack id %ld for thread %ld\n", args.old_kernel_stack, args.thread->id)); delete_area(args.old_kernel_stack); // remove this thread from all of the global lists - TRACE(("thread_exit2: removing thread 0x%lx from global lists\n", + TRACE(("thread_exit2: removing thread %ld from global lists\n", args.thread->id)); disable_interrupts(); @@ -683,7 +683,7 @@ make_thread_unreal(int argc, char **argv) if (thread->priority > B_DISPLAY_PRIORITY) { thread->priority = thread->next_priority = B_NORMAL_PRIORITY; - kprintf("thread 0x%lx made unreal\n", thread->id); + kprintf("thread %ld made unreal\n", thread->id); } } @@ -722,11 +722,11 @@ set_thread_prio(int argc, char **argv) if (thread->id != id) continue; thread->priority = thread->next_priority = prio; - kprintf("thread 0x%lx set to priority %ld\n", id, prio); + kprintf("thread %ld set to priority %ld\n", id, prio); break; } if (!thread) - kprintf("thread 0x%lx not found\n", id); + kprintf("thread %ld (%#lx) not found\n", id, id); hash_close(sThreadHash, &i, false); return 0; @@ -757,11 +757,11 @@ make_thread_suspended(int argc, char **argv) continue; thread->state = thread->next_state = B_THREAD_SUSPENDED; - kprintf("thread 0x%lx suspended\n", id); + kprintf("thread %ld suspended\n", id); break; } if (!thread) - kprintf("thread 0x%lx not found\n", id); + kprintf("thread %ld (%#lx) not found\n", id, id); hash_close(sThreadHash, &i, false); return 0; @@ -793,12 +793,12 @@ make_thread_resumed(int argc, char **argv) if (thread->state == B_THREAD_SUSPENDED) { thread->state = thread->next_state = B_THREAD_READY; scheduler_enqueue_in_run_queue(thread); - kprintf("thread 0x%lx resumed\n", thread->id); + kprintf("thread %ld resumed\n", thread->id); } break; } if (!thread) - kprintf("thread 0x%lx not found\n", id); + kprintf("thread %ld (%#lx) not found\n", id, id); hash_close(sThreadHash, &i, false); return 0; @@ -825,7 +825,7 @@ drop_into_debugger(int argc, char **argv) if (err) kprintf("drop failed\n"); else - kprintf("thread 0x%lx dropped into user debugger\n", id); + kprintf("thread %ld dropped into user debugger\n", id); return 0; } @@ -867,7 +867,7 @@ _dump_thread_info(struct thread *thread) struct death_entry *death = NULL; kprintf("THREAD: %p\n", thread); - kprintf("id: 0x%lx\n", thread->id); + kprintf("id: %ld (%#lx)\n", thread->id, thread->id); kprintf("name: \"%s\"\n", thread->name); kprintf("all_next: %p\nteam_next: %p\nq_next: %p\n", thread->all_next, thread->team_next, thread->queue_next); @@ -879,12 +879,12 @@ _dump_thread_info(struct thread *thread) kprintf("(%d)\n", thread->cpu->cpu_num); else kprintf("\n"); - kprintf("sig_pending: 0x%lx\n", thread->sig_pending); + kprintf("sig_pending: %#lx\n", thread->sig_pending); kprintf("in_kernel: %d\n", thread->in_kernel); - kprintf(" sem.blocking: 0x%lx\n", thread->sem.blocking); - kprintf(" sem.count: 0x%lx\n", thread->sem.count); - kprintf(" sem.acquire_status: 0x%lx\n", thread->sem.acquire_status); - kprintf(" sem.flags: 0x%lx\n", thread->sem.flags); + kprintf(" sem.blocking: %ld\n", thread->sem.blocking); + kprintf(" sem.count: %ld\n", thread->sem.count); + kprintf(" sem.acquire_status: %#lx\n", thread->sem.acquire_status); + kprintf(" sem.flags: %#lx\n", thread->sem.flags); kprintf("condition variables:"); PrivateConditionVariableEntry* entry = thread->condition_variable_entry; @@ -898,22 +898,23 @@ _dump_thread_info(struct thread *thread) kprintf("args: %p %p\n", thread->args1, thread->args2); kprintf("entry: %p\n", (void *)thread->entry); kprintf("team: %p, \"%s\"\n", thread->team, thread->team->name); - kprintf(" exit.sem: 0x%lx\n", thread->exit.sem); - kprintf(" exit.status: 0x%lx (%s)\n", thread->exit.status, strerror(thread->exit.status)); - kprintf(" exit.reason: 0x%x\n", thread->exit.reason); - kprintf(" exit.signal: 0x%x\n", thread->exit.signal); + kprintf(" exit.sem: %ld\n", thread->exit.sem); + kprintf(" exit.status: %#lx (%s)\n", thread->exit.status, strerror(thread->exit.status)); + kprintf(" exit.reason: %#x\n", thread->exit.reason); + kprintf(" exit.signal: %#x\n", thread->exit.signal); kprintf(" exit.waiters:\n"); while ((death = (struct death_entry*)list_get_next_item( &thread->exit.waiters, death)) != NULL) { - kprintf("\t%p (group 0x%lx, thread 0x%lx)\n", death, death->group_id, death->thread); + kprintf("\t%p (group %ld, thread %ld)\n", death, death->group_id, death->thread); } - kprintf("kernel_stack_area: 0x%lx\n", thread->kernel_stack_area); + kprintf("kernel_stack_area: %ld\n", thread->kernel_stack_area); kprintf("kernel_stack_base: %p\n", (void *)thread->kernel_stack_base); - kprintf("user_stack_area: 0x%lx\n", thread->user_stack_area); + kprintf("user_stack_area: %ld\n", thread->user_stack_area); kprintf("user_stack_base: %p\n", (void *)thread->user_stack_base); kprintf("user_local_storage: %p\n", (void *)thread->user_local_storage); - kprintf("kernel_errno: %d\n", thread->kernel_errno); + kprintf("kernel_errno: %#x (%s)\n", thread->kernel_errno, + strerror(thread->kernel_errno)); kprintf("kernel_time: %Ld\n", thread->kernel_time); kprintf("user_time: %Ld\n", thread->user_time); kprintf("architecture dependant section:\n"); @@ -1010,7 +1011,7 @@ dump_thread_list(int argc, char **argv) || (realTimeOnly && thread->priority < B_REAL_TIME_DISPLAY_PRIORITY)) continue; - kprintf("%p %6lx %-9s", thread, thread->id, state_to_text(thread, + kprintf("%p %6ld %-9s", thread, thread->id, state_to_text(thread, thread->state)); // does it block on a semaphore or a condition variable? @@ -1018,7 +1019,7 @@ dump_thread_list(int argc, char **argv) if (thread->condition_variable_entry) kprintf("%p ", thread->condition_variable_entry->Variable()); else - kprintf("%10lx ", thread->sem.blocking); + kprintf("%10ld ", thread->sem.blocking); } else kprintf(" - "); @@ -1028,7 +1029,7 @@ dump_thread_list(int argc, char **argv) else kprintf(" -"); - kprintf("%4ld %p%5lx %s\n", thread->priority, + kprintf("%4ld %p%5ld %s\n", thread->priority, (void *)thread->kernel_stack_base, thread->team->id, thread->name != NULL ? thread->name : ""); } @@ -1114,9 +1115,9 @@ thread_exit(void) struct thread_debug_info debugInfo; team_id teamID = team->id; - TRACE(("thread 0x%lx exiting %s w/return code 0x%x\n", thread->id, - thread->exit.reason == THREAD_RETURN_INTERRUPTED ? "due to signal" : "normally", - (int)thread->exit.status)); + TRACE(("thread %ld exiting %s w/return code %#lx\n", thread->id, + thread->exit.reason == THREAD_RETURN_INTERRUPTED + ? "due to signal" : "normally", thread->exit.status)); if (!are_interrupts_enabled()) panic("thread_exit() called with interrupts disabled!\n"); @@ -1201,7 +1202,7 @@ thread_exit(void) vm_swap_address_space(vm_kernel_address_space()); restore_interrupts(state); - TRACE(("thread_exit: thread 0x%lx now a kernel thread!\n", thread->id)); + TRACE(("thread_exit: thread %ld now a kernel thread!\n", thread->id)); } // delete the team if we're its main thread @@ -1358,7 +1359,7 @@ thread_at_kernel_entry(void) cpu_status state; bigtime_t now; - TRACE(("thread_atkernel_entry: entry thread 0x%lx\n", thread->id)); + TRACE(("thread_atkernel_entry: entry thread %ld\n", thread->id)); state = disable_interrupts(); @@ -1384,7 +1385,7 @@ thread_at_kernel_exit(void) cpu_status state; bigtime_t now; - TRACE(("thread_atkernel_exit: exit thread 0x%lx\n", thread->id)); + TRACE(("thread_atkernel_exit: exit thread %ld\n", thread->id)); if (handle_signals(thread)) { state = disable_interrupts(); @@ -1603,7 +1604,7 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, if (status == B_OK) { // this should never happen as the thread deletes the semaphore on exit - panic("could acquire exit_sem for thread %lx\n", id); + panic("could acquire exit_sem for thread %ld\n", id); } else if (status == B_BAD_SEM_ID) { // this is the way the thread normally exits status = B_OK;